Preparing your workspace...

assistant-chat.tsx2.5k
utils.ts850
button.tsx720
Quick Actions
codmir
Docs
Discord
Get started
API
  • Introduction
  • Installation
  • Your First Project
  • Your First Agent
  • Overview
    • Cortex Protocol
    • CortexIO
    • DNAManager
    • Timeline
    • SwarmProtocol

Append-only reasoning ledger — every decision, discovery, fix, and failure recorded.

Timeline

The Timeline is an append-only reasoning ledger. Every decision, discovery, failure, and learning is recorded as a TimelineEntry with reasoning, confidence, context, and outcome. Entries are buffered in memory and flushed to disk periodically or on demand. This is what prevents thousands of agents from repeating the same mistakes.

import { Timeline, CortexIO } from '@codmir/cortex';

Constructor

new Timeline(io: CortexIO)
ParameterTypeDescription
ioCortexIOThe CortexIO instance for file operations
const io = new CortexIO('/home/dev/my-project');
await io.init();
const timeline = new Timeline(io);

Recording

record()

Creates a new timeline entry and adds it to the in-memory buffer. The entry is not written to disk until flush() is called (or auto-flush triggers).

async record(opts: {
  agentId: string;
  type: TimelineEntryType;
  action: string;
  reasoning: string;
  confidence?: number;
  context?: Partial<TimelineContext>;
  refs?: string[];
  parent?: string;
  outcome?: 'success' | 'failure' | 'pending' | 'abandoned';
}): Promise<TimelineEntry>
ParameterTypeDescription
opts.agentIdstringThe agent recording this entry
opts.typeTimelineEntryTypeEntry type (decision, failure, learning, etc.)
opts.actionstringWhat was done
opts.reasoningstringWhy it was done
opts.confidencenumber (optional)Confidence score 0-1 (default: 0.8)
opts.contextPartial<TimelineContext> (optional)Files, branch, trigger, state
opts.refsstring[] (optional)Reference IDs (other entries, tasks, etc.)
opts.parentstring (optional)Parent entry ID for nested reasoning
opts.outcomestring (optional)Initial outcome (default: 'pending')

Returns the created TimelineEntry with a generated id and timestamp.

const entry = await timeline.record({
  agentId: 'agent_alpha',
  type: 'decision',
  action: 'Chose NestJS over Express for API migration',
  reasoning: 'NestJS provides DI, decorators, and module system needed for the server architecture',
  confidence: 0.9,
  context: {
    files: ['apps/server/src/main.ts'],
    branch: 'feat/api-migration',
    state: { migratedRoutes: 42 },
  },
});

resolve()

Updates the outcome of an existing entry, both in the buffer and on disk.

async resolve(
  entryId: string,
  outcome: 'success' | 'failure' | 'pending' | 'abandoned',
  detail?: string
): Promise<void>
ParameterTypeDescription
entryIdstringThe entry ID to resolve
outcomestringNew outcome value
detailstring (optional)Additional detail about the outcome
await timeline.resolve(entry.id, 'success', 'Migration completed, all tests pass');

flush()

Writes all buffered entries to disk via CortexIO.appendTimeline() and clears the buffer. Returns the number of entries flushed.

async flush(): Promise<number>
const flushed = await timeline.flush();
console.log(`Flushed ${flushed} entries to disk`);

Auto-Flush

startAutoFlush()

Starts a periodic flush interval.

startAutoFlush(intervalMs?: number): void
ParameterTypeDescription
intervalMsnumber (optional)Flush interval in ms (default: 5000)
timeline.startAutoFlush(3000); // flush every 3 seconds

stopAutoFlush()

Stops the periodic flush interval.

stopAutoFlush(): void

Querying

query()

Queries timeline entries from both disk and the in-memory buffer. Results are sorted by timestamp descending (newest first).

async query(opts: {
  agentId?: string;
  type?: TimelineEntryType;
  since?: number;
  limit?: number;
  outcome?: 'success' | 'failure' | 'pending' | 'abandoned';
}): Promise<TimelineEntry[]>
ParameterTypeDescription
opts.agentIdstring (optional)Filter by agent ID
opts.typeTimelineEntryType (optional)Filter by entry type
opts.sincenumber (optional)Minimum timestamp
opts.limitnumber (optional)Maximum entries to return
opts.outcomestring (optional)Filter by outcome
const recentDecisions = await timeline.query({
  type: 'decision',
  since: Date.now() - 3600_000,
  limit: 10,
});

failures()

Shorthand for querying all failure entries.

async failures(since?: number): Promise<TimelineEntry[]>
const recentFailures = await timeline.failures(Date.now() - 86400_000);

learnings()

Shorthand for querying all learning entries.

async learnings(since?: number): Promise<TimelineEntry[]>

decisions()

Shorthand for querying all decision entries.

async decisions(since?: number): Promise<TimelineEntry[]>

forTask()

Reads per-task reasoning entries from reasoning/<taskId>.crtx.

async forTask(taskId: string): Promise<TimelineEntry[]>
ParameterTypeDescription
taskIdstringThe task identifier
const reasoning = await timeline.forTask('task_abc');
for (const entry of reasoning) {
  console.log(`[${entry.type}] ${entry.action}: ${entry.reasoning}`);
}

recordForTask()

Records an entry and immediately appends it to the per-task reasoning file (in addition to the buffer).

async recordForTask(
  taskId: string,
  opts: Parameters<Timeline['record']>[0]
): Promise<TimelineEntry>
const entry = await timeline.recordForTask('task_abc', {
  agentId: 'agent_beta',
  type: 'experiment',
  action: 'Tried parallel file processing',
  reasoning: 'Sequential was too slow for 200 files',
  confidence: 0.6,
});

getBufferSize()

Returns the number of entries currently in the in-memory buffer (not yet flushed to disk).

getBufferSize(): number

Types

TimelineEntry

interface TimelineEntry {
  id: string;
  timestamp: number;
  agentId: string;
  type: TimelineEntryType;
  action: string;
  reasoning: string;
  confidence: number;
  context: TimelineContext;
  refs: string[];
  outcome: 'success' | 'failure' | 'pending' | 'abandoned';
  outcomeDetail?: string;
  parent?: string;
  children?: string[];
}

TimelineEntryType

type TimelineEntryType =
  | 'decision'
  | 'discovery'
  | 'fix'
  | 'refactor'
  | 'experiment'
  | 'failure'
  | 'learning'
  | 'delegation'
  | 'escalation'
  | 'merge'
  | 'conflict';

TimelineContext

interface TimelineContext {
  files: string[];
  task?: string;
  branch?: string;
  trigger?: string;
  dependencies?: string[];
  state: Record<string, unknown>;
}

Example

import { CortexIO, Timeline } from '@codmir/cortex';

const io = new CortexIO('/home/dev/my-project');
await io.init();

const timeline = new Timeline(io);
timeline.startAutoFlush(5000);

// Record agent reasoning
const decision = await timeline.record({
  agentId: 'coordinator',
  type: 'delegation',
  action: 'Assigned auth migration to agent_alpha',
  reasoning: 'Agent has expertise in edge-auth and JWT patterns',
  confidence: 0.85,
  context: {
    files: ['apps/web/src/app/api/auth'],
    branch: 'feat/cortex-auth',
    state: { totalRoutes: 12, assignedRoutes: 4 },
  },
});

// Agent completes work
await timeline.resolve(decision.id, 'success', 'All 4 auth routes migrated');

// Record a task-specific entry
await timeline.recordForTask('auth-migration', {
  agentId: 'agent_alpha',
  type: 'learning',
  action: 'CLI tokens require DB lookup fallback',
  reasoning: 'Opaque 32-char tokens are not JWTs — validateToken must try JWT first, then cli_tokens table',
  confidence: 1.0,
  context: {
    files: ['apps/web/src/lib/auth.ts'],
    state: {},
  },
  outcome: 'success',
});

// Query recent failures to avoid repeating mistakes
const failures = await timeline.failures(Date.now() - 86400_000);
console.log(`${failures.length} failures in the last 24 hours`);

// Force flush before shutdown
await timeline.flush();
timeline.stopAutoFlush();
Open in ChatGPTOpen in ClaudeConnect MCP on CursorConnect MCP on WindsurfEdit on GitHub
codmir
Products
Desktop AppMobile AppIDE ExtensionAI AgentsOverseerVoice ModeCortex ProtocolHive MindGame Dev (Godat)PricingDownload
Solutions
AI Code AgentsCode ReviewError TrackingSelf-HealingDeploy TrackingAI Tracking SDKWorkflow AutomationTesting FrameworkTime TrackingVoice Control
Platform
ProjectsTickets & BoardsAgent MarketplaceIntegrationsTemplatesApp HubAdmin PanelAnalytics
Integrations
GitHubSlackDiscordVercelSentryRailwayLinearAll Integrations
Developers
DocumentationAPI ReferenceSDKCLIDeveloper PortalMarketplaceMCP ConnectorsWebhooksExamplesnpm Packages
Resources
BlogChangelogCommunityTutorialsGet StartedSupportStatusFeedback
Company
AboutCareersContact SalesKickstarterReferral Program
Legal
Terms of UsePrivacy PolicyEULATrademarkSecurity
Download on the App StoreGet it on Google Play

Codmir™ 2026. All rights reserved.

Free & open source SDK — Apache 2.0 License