@wrongstack/core 0.287.0 → 0.291.0
This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
- package/dist/agent-status-tracker.d.ts +13 -0
- package/dist/agent-status-tracker.d.ts.map +1 -1
- package/dist/boot.d.ts.map +1 -1
- package/dist/chronicle/context.d.ts +13 -0
- package/dist/chronicle/context.d.ts.map +1 -0
- package/dist/chronicle/decision-adapter.d.ts +13 -0
- package/dist/chronicle/decision-adapter.d.ts.map +1 -0
- package/dist/chronicle/domain-adapter.d.ts +13 -0
- package/dist/chronicle/domain-adapter.d.ts.map +1 -0
- package/dist/chronicle/file-observer.d.ts +20 -0
- package/dist/chronicle/file-observer.d.ts.map +1 -0
- package/dist/chronicle/health-monitor.d.ts +11 -0
- package/dist/chronicle/health-monitor.d.ts.map +1 -0
- package/dist/chronicle/identity.d.ts +18 -0
- package/dist/chronicle/identity.d.ts.map +1 -0
- package/dist/chronicle/index.d.ts +16 -0
- package/dist/chronicle/index.d.ts.map +1 -0
- package/dist/chronicle/index.js +2555 -0
- package/dist/chronicle/index.js.map +7 -0
- package/dist/chronicle/journal.d.ts +81 -0
- package/dist/chronicle/journal.d.ts.map +1 -0
- package/dist/chronicle/process-adapter.d.ts +14 -0
- package/dist/chronicle/process-adapter.d.ts.map +1 -0
- package/dist/chronicle/prompt-manifest.d.ts +34 -0
- package/dist/chronicle/prompt-manifest.d.ts.map +1 -0
- package/dist/chronicle/provider-adapter.d.ts +13 -0
- package/dist/chronicle/provider-adapter.d.ts.map +1 -0
- package/dist/chronicle/query.d.ts +108 -0
- package/dist/chronicle/query.d.ts.map +1 -0
- package/dist/chronicle/rollup-adapter.d.ts +14 -0
- package/dist/chronicle/rollup-adapter.d.ts.map +1 -0
- package/dist/chronicle/stream-adapter.d.ts +13 -0
- package/dist/chronicle/stream-adapter.d.ts.map +1 -0
- package/dist/chronicle/tool-adapter.d.ts +15 -0
- package/dist/chronicle/tool-adapter.d.ts.map +1 -0
- package/dist/chronicle/types.d.ts +82 -0
- package/dist/chronicle/types.d.ts.map +1 -0
- package/dist/coordination/agent-monitor.d.ts +40 -0
- package/dist/coordination/agent-monitor.d.ts.map +1 -1
- package/dist/coordination/agent-subagent-runner.d.ts +7 -1
- package/dist/coordination/agent-subagent-runner.d.ts.map +1 -1
- package/dist/coordination/agents/phase6-domain.d.ts.map +1 -1
- package/dist/coordination/autonomous-coordinator.d.ts +2 -0
- package/dist/coordination/autonomous-coordinator.d.ts.map +1 -1
- package/dist/coordination/brain-monitor.d.ts +1 -1
- package/dist/coordination/brain.d.ts +3 -2
- package/dist/coordination/brain.d.ts.map +1 -1
- package/dist/coordination/collab-debug.d.ts +0 -9
- package/dist/coordination/collab-debug.d.ts.map +1 -1
- package/dist/coordination/coordinator/error-classifier.d.ts.map +1 -1
- package/dist/coordination/dep-watcher.d.ts +2 -1
- package/dist/coordination/dep-watcher.d.ts.map +1 -1
- package/dist/coordination/director/director-collab.d.ts +1 -1
- package/dist/coordination/director/director-collab.d.ts.map +1 -1
- package/dist/coordination/director-tools.d.ts.map +1 -1
- package/dist/coordination/director.d.ts +10 -1
- package/dist/coordination/director.d.ts.map +1 -1
- package/dist/coordination/file-author-tracker.d.ts.map +1 -1
- package/dist/coordination/fleet-bus.d.ts.map +1 -1
- package/dist/coordination/fleet-event-validation.d.ts +0 -7
- package/dist/coordination/fleet-event-validation.d.ts.map +1 -1
- package/dist/coordination/fleet-spawn.d.ts.map +1 -1
- package/dist/coordination/fleet-supervisor.d.ts +1 -1
- package/dist/coordination/fleet-supervisor.d.ts.map +1 -1
- package/dist/coordination/fleet.d.ts +0 -44
- package/dist/coordination/fleet.d.ts.map +1 -1
- package/dist/coordination/global-mailbox.d.ts +7 -1
- package/dist/coordination/global-mailbox.d.ts.map +1 -1
- package/dist/coordination/index.d.ts +5 -3
- package/dist/coordination/index.d.ts.map +1 -1
- package/dist/coordination/index.js +2426 -299
- package/dist/coordination/index.js.map +4 -4
- package/dist/coordination/knowledge-graph.d.ts +2 -1
- package/dist/coordination/knowledge-graph.d.ts.map +1 -1
- package/dist/coordination/large-answer-store.d.ts +0 -6
- package/dist/coordination/large-answer-store.d.ts.map +1 -1
- package/dist/coordination/mail-tools.d.ts +2 -2
- package/dist/coordination/mail-tools.d.ts.map +1 -1
- package/dist/coordination/mailbox-hooks.d.ts +2 -0
- package/dist/coordination/mailbox-hooks.d.ts.map +1 -1
- package/dist/coordination/mailbox-http-router.d.ts +43 -0
- package/dist/coordination/mailbox-http-router.d.ts.map +1 -0
- package/dist/coordination/mailbox-message-codec.d.ts +35 -0
- package/dist/coordination/mailbox-message-codec.d.ts.map +1 -1
- package/dist/coordination/mailbox-tool.d.ts +1 -1
- package/dist/coordination/mailbox-tool.d.ts.map +1 -1
- package/dist/coordination/mailbox-types.d.ts +170 -10
- package/dist/coordination/mailbox-types.d.ts.map +1 -1
- package/dist/coordination/mailbox.d.ts +1 -1
- package/dist/coordination/mailbox.d.ts.map +1 -1
- package/dist/coordination/package-author-tracker.d.ts.map +1 -1
- package/dist/coordination/provider-status-tracker.d.ts +236 -0
- package/dist/coordination/provider-status-tracker.d.ts.map +1 -0
- package/dist/coordination/subagent-budget.d.ts +2 -1
- package/dist/coordination/subagent-budget.d.ts.map +1 -1
- package/dist/core/agent-loop.d.ts +8 -3
- package/dist/core/agent-loop.d.ts.map +1 -1
- package/dist/core/agent-response.d.ts +5 -4
- package/dist/core/agent-response.d.ts.map +1 -1
- package/dist/core/agent-tools.d.ts +1 -1
- package/dist/core/agent-tools.d.ts.map +1 -1
- package/dist/core/agent.d.ts +4 -2
- package/dist/core/agent.d.ts.map +1 -1
- package/dist/core/context.d.ts +55 -1
- package/dist/core/context.d.ts.map +1 -1
- package/dist/core/fallback-model.d.ts +14 -8
- package/dist/core/fallback-model.d.ts.map +1 -1
- package/dist/core/fallback-profile-manager.d.ts +118 -0
- package/dist/core/fallback-profile-manager.d.ts.map +1 -0
- package/dist/core/fleet-pulse.d.ts +2 -1
- package/dist/core/fleet-pulse.d.ts.map +1 -1
- package/dist/core/iteration-limit.d.ts +2 -1
- package/dist/core/iteration-limit.d.ts.map +1 -1
- package/dist/core/mailbox-loop.d.ts +16 -1
- package/dist/core/mailbox-loop.d.ts.map +1 -1
- package/dist/core/model-availability-calendar.d.ts +27 -0
- package/dist/core/model-availability-calendar.d.ts.map +1 -0
- package/dist/core/provider-runner.d.ts.map +1 -1
- package/dist/core/system-prompt-builder.d.ts +2 -1
- package/dist/core/system-prompt-builder.d.ts.map +1 -1
- package/dist/defaults/index.js +1920 -598
- package/dist/defaults/index.js.map +4 -4
- package/dist/execution/auto-compaction-middleware.d.ts +3 -2
- package/dist/execution/auto-compaction-middleware.d.ts.map +1 -1
- package/dist/execution/compaction-core.d.ts.map +1 -1
- package/dist/execution/council-brain.d.ts +28 -49
- package/dist/execution/council-brain.d.ts.map +1 -1
- package/dist/execution/council-orchestrator.d.ts +30 -0
- package/dist/execution/council-orchestrator.d.ts.map +1 -1
- package/dist/execution/enhance-recovery.d.ts +8 -0
- package/dist/execution/enhance-recovery.d.ts.map +1 -1
- package/dist/execution/error-handler.d.ts +2 -2
- package/dist/execution/error-handler.d.ts.map +1 -1
- package/dist/execution/eternal-autonomy.d.ts.map +1 -1
- package/dist/execution/index.js +2600 -1903
- package/dist/execution/index.js.map +4 -4
- package/dist/execution/intelligent-compactor.d.ts +0 -16
- package/dist/execution/intelligent-compactor.d.ts.map +1 -1
- package/dist/execution/model-runtime.d.ts.map +1 -1
- package/dist/execution/one-shot-llm.d.ts +9 -1
- package/dist/execution/one-shot-llm.d.ts.map +1 -1
- package/dist/execution/prompt-enhancer.d.ts +36 -0
- package/dist/execution/prompt-enhancer.d.ts.map +1 -1
- package/dist/execution/prompt-enhancer.js +158 -10
- package/dist/execution/prompt-enhancer.js.map +2 -2
- package/dist/execution/retry-policy.d.ts +0 -13
- package/dist/execution/retry-policy.d.ts.map +1 -1
- package/dist/execution/skill-loader.d.ts.map +1 -1
- package/dist/execution/tool-executor.d.ts.map +1 -1
- package/dist/goal/checkpoint.d.ts.map +1 -0
- package/dist/{autophase/auto-phase-planner.d.ts → goal/goal-planner.d.ts} +8 -8
- package/dist/goal/goal-planner.d.ts.map +1 -0
- package/dist/{autophase/auto-phase-runner.d.ts → goal/goal-runner.d.ts} +10 -10
- package/dist/goal/goal-runner.d.ts.map +1 -0
- package/dist/{autophase → goal}/index.d.ts +3 -3
- package/dist/goal/index.d.ts.map +1 -0
- package/dist/goal/phase-graph-builder.d.ts.map +1 -0
- package/dist/{autophase → goal}/phase-orchestrator.d.ts +2 -2
- package/dist/goal/phase-orchestrator.d.ts.map +1 -0
- package/dist/goal/phase-store.d.ts.map +1 -0
- package/dist/{autophase → goal}/types.d.ts +2 -2
- package/dist/goal/types.d.ts.map +1 -0
- package/dist/hq/auth-store.d.ts.map +1 -1
- package/dist/hq/commands.d.ts +2 -1
- package/dist/hq/commands.d.ts.map +1 -1
- package/dist/hq/exposure.d.ts +66 -0
- package/dist/hq/exposure.d.ts.map +1 -0
- package/dist/hq/index.d.ts +1 -0
- package/dist/hq/index.d.ts.map +1 -1
- package/dist/hq/index.js +190 -21
- package/dist/hq/index.js.map +4 -4
- package/dist/hq/mailbox-mapper.d.ts +13 -1
- package/dist/hq/mailbox-mapper.d.ts.map +1 -1
- package/dist/hq/protocol/browser.d.ts +9 -1
- package/dist/hq/protocol/browser.d.ts.map +1 -1
- package/dist/hq/protocol/client.d.ts +2 -2
- package/dist/hq/protocol/client.d.ts.map +1 -1
- package/dist/hq/protocol/core.d.ts.map +1 -1
- package/dist/hq/protocol/mailbox.d.ts +6 -0
- package/dist/hq/protocol/mailbox.d.ts.map +1 -1
- package/dist/hq/protocol/session.d.ts +4 -0
- package/dist/hq/protocol/session.d.ts.map +1 -1
- package/dist/hq/publisher.d.ts.map +1 -1
- package/dist/index.d.ts +34 -25
- package/dist/index.d.ts.map +1 -1
- package/dist/index.js +30287 -22214
- package/dist/index.js.map +4 -4
- package/dist/infrastructure/index.js +60 -5
- package/dist/infrastructure/index.js.map +2 -2
- package/dist/kernel/events/agent-events.d.ts +33 -1
- package/dist/kernel/events/agent-events.d.ts.map +1 -1
- package/dist/kernel/events/file-events.d.ts +65 -0
- package/dist/kernel/events/file-events.d.ts.map +1 -0
- package/dist/kernel/events/memory-events.d.ts +36 -0
- package/dist/kernel/events/memory-events.d.ts.map +1 -1
- package/dist/kernel/events/network-events.d.ts +60 -0
- package/dist/kernel/events/network-events.d.ts.map +1 -0
- package/dist/kernel/events/process-events.d.ts +44 -0
- package/dist/kernel/events/process-events.d.ts.map +1 -0
- package/dist/kernel/events/provider-events.d.ts +89 -0
- package/dist/kernel/events/provider-events.d.ts.map +1 -1
- package/dist/kernel/events/tool-events.d.ts +10 -0
- package/dist/kernel/events/tool-events.d.ts.map +1 -1
- package/dist/kernel/events/worktree-events.d.ts +1 -1
- package/dist/kernel/events.d.ts +14 -1
- package/dist/kernel/events.d.ts.map +1 -1
- package/dist/kernel/index.js +2 -1
- package/dist/kernel/index.js.map +2 -2
- package/dist/kernel/tokens.d.ts +3 -1
- package/dist/kernel/tokens.d.ts.map +1 -1
- package/dist/mailbox-attach.d.ts.map +1 -1
- package/dist/models/index.js.map +2 -2
- package/dist/observability/index.d.ts +3 -0
- package/dist/observability/index.d.ts.map +1 -1
- package/dist/observability/index.js +278 -0
- package/dist/observability/index.js.map +4 -4
- package/dist/observability/network-telemetry.d.ts +15 -0
- package/dist/observability/network-telemetry.d.ts.map +1 -0
- package/dist/observability/process-telemetry.d.ts +18 -0
- package/dist/observability/process-telemetry.d.ts.map +1 -0
- package/dist/observability/redact-command.d.ts +20 -0
- package/dist/observability/redact-command.d.ts.map +1 -0
- package/dist/plugins/auto-review-plugin.d.ts +56 -3
- package/dist/plugins/auto-review-plugin.d.ts.map +1 -1
- package/dist/plugins/chimera-plugin.d.ts +164 -5
- package/dist/plugins/chimera-plugin.d.ts.map +1 -1
- package/dist/plugins/review-context-builder.d.ts +52 -0
- package/dist/plugins/review-context-builder.d.ts.map +1 -0
- package/dist/security/index.d.ts +1 -0
- package/dist/security/index.d.ts.map +1 -1
- package/dist/security/index.js +186 -9
- package/dist/security/index.js.map +4 -4
- package/dist/security/kanban-boundary.d.ts +10 -0
- package/dist/security/kanban-boundary.d.ts.map +1 -0
- package/dist/security/permission-policy.d.ts +1 -0
- package/dist/security/permission-policy.d.ts.map +1 -1
- package/dist/session-registry.d.ts +80 -0
- package/dist/session-registry.d.ts.map +1 -1
- package/dist/skills/index.js.map +2 -2
- package/dist/storage/config-loader.d.ts +7 -0
- package/dist/storage/config-loader.d.ts.map +1 -1
- package/dist/storage/file-session-writer.d.ts +20 -7
- package/dist/storage/file-session-writer.d.ts.map +1 -1
- package/dist/storage/goal-coordination.d.ts +40 -0
- package/dist/storage/goal-coordination.d.ts.map +1 -0
- package/dist/storage/goal-store.d.ts +9 -5
- package/dist/storage/goal-store.d.ts.map +1 -1
- package/dist/storage/index.d.ts +4 -2
- package/dist/storage/index.d.ts.map +1 -1
- package/dist/storage/index.js +1066 -226
- package/dist/storage/index.js.map +4 -4
- package/dist/storage/memory-consolidator.d.ts +49 -4
- package/dist/storage/memory-consolidator.d.ts.map +1 -1
- package/dist/storage/memory-graph-backend.d.ts +11 -0
- package/dist/storage/memory-graph-backend.d.ts.map +1 -1
- package/dist/storage/provider-config-watcher.d.ts +19 -0
- package/dist/storage/provider-config-watcher.d.ts.map +1 -1
- package/dist/storage/session-event-bridge.d.ts +2 -2
- package/dist/storage/session-event-bridge.d.ts.map +1 -1
- package/dist/storage/session-resume-validation.d.ts +10 -0
- package/dist/storage/session-resume-validation.d.ts.map +1 -1
- package/dist/storage/session-rewind-apply.d.ts +53 -0
- package/dist/storage/session-rewind-apply.d.ts.map +1 -0
- package/dist/storage/session-rewinder.d.ts.map +1 -1
- package/dist/storage/session-store.d.ts.map +1 -1
- package/dist/tasking/index.js.map +1 -1
- package/dist/tasking/task-store.d.ts +1 -1
- package/dist/tools/council-tool.d.ts +3 -0
- package/dist/tools/council-tool.d.ts.map +1 -1
- package/dist/tools/fallback-manage-tools.d.ts +82 -0
- package/dist/tools/fallback-manage-tools.d.ts.map +1 -0
- package/dist/tools/index.d.ts +1 -0
- package/dist/tools/index.d.ts.map +1 -1
- package/dist/tools/index.js +3423 -192
- package/dist/tools/index.js.map +4 -4
- package/dist/tools/one-shot-llm-tool.d.ts +2 -0
- package/dist/tools/one-shot-llm-tool.d.ts.map +1 -1
- package/dist/types/config.d.ts +76 -7
- package/dist/types/config.d.ts.map +1 -1
- package/dist/types/file-event-record.d.ts +68 -0
- package/dist/types/file-event-record.d.ts.map +1 -0
- package/dist/types/index.d.ts +1 -0
- package/dist/types/index.d.ts.map +1 -1
- package/dist/types/index.js +13 -8
- package/dist/types/index.js.map +3 -3
- package/dist/types/memory.d.ts +12 -0
- package/dist/types/memory.d.ts.map +1 -1
- package/dist/types/multi-agent.d.ts +12 -1
- package/dist/types/multi-agent.d.ts.map +1 -1
- package/dist/types/one-shot-llm.d.ts +16 -7
- package/dist/types/one-shot-llm.d.ts.map +1 -1
- package/dist/types/provider.d.ts +1 -1
- package/dist/types/provider.d.ts.map +1 -1
- package/dist/types/session.d.ts +68 -2
- package/dist/types/session.d.ts.map +1 -1
- package/dist/types/tool-executor.d.ts +2 -0
- package/dist/types/tool-executor.d.ts.map +1 -1
- package/dist/types/tool.d.ts +5 -0
- package/dist/types/tool.d.ts.map +1 -1
- package/dist/utils/atomic-write.d.ts.map +1 -1
- package/dist/utils/index.d.ts +10 -10
- package/dist/utils/index.d.ts.map +1 -1
- package/dist/utils/index.js +497 -254
- package/dist/utils/index.js.map +4 -4
- package/dist/utils/message-invariants.d.ts +9 -0
- package/dist/utils/message-invariants.d.ts.map +1 -1
- package/dist/utils/safe-json.d.ts +1 -1
- package/dist/utils/safe-json.d.ts.map +1 -1
- package/dist/utils/term.d.ts +279 -0
- package/dist/utils/term.d.ts.map +1 -1
- package/dist/utils/tool-wire-compact.d.ts +9 -0
- package/dist/utils/tool-wire-compact.d.ts.map +1 -1
- package/dist/utils/wstack-paths.d.ts +12 -2
- package/dist/utils/wstack-paths.d.ts.map +1 -1
- package/dist/worktree/worktree-manager.d.ts +1 -1
- package/dist/worktree/worktree-manager.d.ts.map +1 -1
- package/instructions/agents/ios.md +113 -0
- package/instructions/agents/search.md +1 -1
- package/instructions/llm/chimera-review.md +66 -9
- package/instructions/llm/memory-consolidator.md +4 -12
- package/instructions/llm/prompt-enhancer.md +3 -1
- package/instructions/sections/tool/common-patterns.md +3 -3
- package/instructions/system.md +40 -5
- package/package.json +7 -3
- package/skills/auto-review/SKILL.md +176 -0
- package/skills/mnemosyne/SKILL.md +156 -0
- package/skills/mnemosyne/instructions/agent-prompt.md +200 -0
- package/dist/autophase/auto-phase-planner.d.ts.map +0 -1
- package/dist/autophase/auto-phase-runner.d.ts.map +0 -1
- package/dist/autophase/checkpoint.d.ts.map +0 -1
- package/dist/autophase/index.d.ts.map +0 -1
- package/dist/autophase/phase-graph-builder.d.ts.map +0 -1
- package/dist/autophase/phase-orchestrator.d.ts.map +0 -1
- package/dist/autophase/phase-store.d.ts.map +0 -1
- package/dist/autophase/types.d.ts.map +0 -1
- /package/dist/{autophase → goal}/checkpoint.d.ts +0 -0
- /package/dist/{autophase → goal}/phase-graph-builder.d.ts +0 -0
- /package/dist/{autophase → goal}/phase-store.d.ts +0 -0
- /package/instructions/{autophase → goal}/phase-planner.md +0 -0
|
@@ -2,12 +2,47 @@ import type { AfterRunHook, AgentExtension } from '../extension/extension-points
|
|
|
2
2
|
import type { MemoryStore } from '../types/memory.js';
|
|
3
3
|
import type { Provider } from '../types/provider.js';
|
|
4
4
|
import type { OneShotOrchestrator } from '../execution/one-shot-llm.js';
|
|
5
|
+
/**
|
|
6
|
+
* Minimal interface for writing to Super Memory without importing
|
|
7
|
+
* @wrongstack/super-memory (core cannot depend on super-memory).
|
|
8
|
+
* Tools like the consolidator use this to route adds through
|
|
9
|
+
* rememberSuper rather than the legacy MemoryStore.remember(),
|
|
10
|
+
* making them visible to searchSuper/turn-middleware.
|
|
11
|
+
*/
|
|
12
|
+
type ConsolidatorSuperMemoryKind = 'fact' | 'decision' | 'convention' | 'preference' | 'anti_pattern' | 'file_note';
|
|
13
|
+
export interface ConsolidatorSuperMemory {
|
|
14
|
+
rememberSuper(input: {
|
|
15
|
+
text: string;
|
|
16
|
+
scope?: string | undefined;
|
|
17
|
+
kind?: ConsolidatorSuperMemoryKind | undefined;
|
|
18
|
+
tags?: string[] | undefined;
|
|
19
|
+
priority?: string | undefined;
|
|
20
|
+
importance?: number | undefined;
|
|
21
|
+
confidence?: number | undefined;
|
|
22
|
+
sources?: Array<{
|
|
23
|
+
type: string;
|
|
24
|
+
sessionId?: string | undefined;
|
|
25
|
+
}> | undefined;
|
|
26
|
+
}): Promise<unknown>;
|
|
27
|
+
listSuper?(statuses?: Array<'active'>): Promise<unknown[]>;
|
|
28
|
+
searchSuper?(query: string, opts?: {
|
|
29
|
+
limit?: number;
|
|
30
|
+
scope?: 'project';
|
|
31
|
+
includeStatuses?: Array<'active'>;
|
|
32
|
+
}): Promise<unknown[]>;
|
|
33
|
+
}
|
|
5
34
|
export interface ConsolidationOp {
|
|
6
|
-
|
|
7
|
-
|
|
35
|
+
/**
|
|
36
|
+
* Add-only by design. The consolidator runs unattended after every
|
|
37
|
+
* successful session, so LLM-issued delete/edit ops used to give an
|
|
38
|
+
* unsupervised model a substring-matched deletion path over the whole
|
|
39
|
+
* memory store (see the 2026-07 mass-deletion postmortem). Removals and
|
|
40
|
+
* corrections belong to explicit review flows (memory_delete /
|
|
41
|
+
* memory_update / ReviewQueue), never to this hook.
|
|
42
|
+
*/
|
|
43
|
+
action: 'add';
|
|
44
|
+
/** The fact to remember. */
|
|
8
45
|
text?: string | undefined;
|
|
9
|
-
/** For edit/delete: the query to match existing entries. */
|
|
10
|
-
query?: string | undefined;
|
|
11
46
|
/** Memory type for categorization. */
|
|
12
47
|
type?: string | undefined;
|
|
13
48
|
/** Tags for grouping. */
|
|
@@ -17,6 +52,14 @@ export interface ConsolidationOp {
|
|
|
17
52
|
}
|
|
18
53
|
export interface MemoryConsolidatorOptions {
|
|
19
54
|
memoryStore: MemoryStore;
|
|
55
|
+
/**
|
|
56
|
+
* Optional Super Memory writer. When provided, the consolidator routes
|
|
57
|
+
* adds through `rememberSuper()` and reads existing entries for dedup
|
|
58
|
+
* context via `searchSuper()` instead of the legacy `MemoryStore`.
|
|
59
|
+
* This makes consolidator-sourced memories visible to the turn-middleware
|
|
60
|
+
* (searchSuper, retrieveForPath) which only queries Super Memory.
|
|
61
|
+
*/
|
|
62
|
+
superMemory?: ConsolidatorSuperMemory | undefined;
|
|
20
63
|
/**
|
|
21
64
|
* Provider used for the consolidation LLM call. Uses the session's
|
|
22
65
|
* provider by default.
|
|
@@ -47,6 +90,7 @@ export declare class SessionMemoryConsolidator implements AgentExtension {
|
|
|
47
90
|
name: string;
|
|
48
91
|
owner: string;
|
|
49
92
|
private readonly memoryStore;
|
|
93
|
+
private readonly superMemory?;
|
|
50
94
|
private readonly provider?;
|
|
51
95
|
private readonly model?;
|
|
52
96
|
private readonly minIterations;
|
|
@@ -55,4 +99,5 @@ export declare class SessionMemoryConsolidator implements AgentExtension {
|
|
|
55
99
|
constructor(opts: MemoryConsolidatorOptions);
|
|
56
100
|
afterRun: AfterRunHook;
|
|
57
101
|
}
|
|
102
|
+
export {};
|
|
58
103
|
//# sourceMappingURL=memory-consolidator.d.ts.map
|
|
@@ -1 +1 @@
|
|
|
1
|
-
{"version":3,"file":"memory-consolidator.d.ts","sourceRoot":"","sources":["../../src/storage/memory-consolidator.ts"],"names":[],"mappings":"AAEA,OAAO,KAAK,EAAE,YAAY,EAAE,cAAc,EAAE,MAAM,kCAAkC,CAAC;AACrF,OAAO,KAAK,EAAe,WAAW,EAAE,MAAM,oBAAoB,CAAC;AACnE,OAAO,KAAK,EAAE,QAAQ,EAAE,MAAM,sBAAsB,CAAC;AACrD,OAAO,KAAK,EAAE,mBAAmB,EAAE,MAAM,8BAA8B,CAAC;AAQxE,MAAM,WAAW,
|
|
1
|
+
{"version":3,"file":"memory-consolidator.d.ts","sourceRoot":"","sources":["../../src/storage/memory-consolidator.ts"],"names":[],"mappings":"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"}
|
|
@@ -27,6 +27,17 @@ export interface GraphMemoryBackendOptions extends FileMemoryBackendOptions {
|
|
|
27
27
|
graphPath?: string | undefined;
|
|
28
28
|
}
|
|
29
29
|
/**
|
|
30
|
+
* @deprecated Migrate to `SuperMemoryStore` from the Super Memory package,
|
|
31
|
+
* which provides the same `MemoryBackend` operations (remember, forget, search,
|
|
32
|
+
* consolidate, list, clear) plus graph support via its integrated
|
|
33
|
+
* `SuperMemoryGraph` implementation.
|
|
34
|
+
* This legacy backend stores entries as markdown bullets in a flat file with a
|
|
35
|
+
* separate graph.json; SuperMemoryStore stores structured records in JSONL (or
|
|
36
|
+
* SQLite) with a dedicated edges.jsonl supporting 12 relation types (supersedes,
|
|
37
|
+
* contradicts, about_file, etc.) and mutation-locked append.
|
|
38
|
+
* Migration is NOT drop-in — migrate to SuperMemoryStore and use its
|
|
39
|
+
* integrated graph features instead.
|
|
40
|
+
*
|
|
30
41
|
* Graph-based memory backend that tracks relationships between entries.
|
|
31
42
|
* Builds on top of FileMemoryBackend — entries are still persisted as
|
|
32
43
|
* markdown bullets, but the graph layer adds:
|
|
@@ -1 +1 @@
|
|
|
1
|
-
{"version":3,"file":"memory-graph-backend.d.ts","sourceRoot":"","sources":["../../src/storage/memory-graph-backend.ts"],"names":[],"mappings":"AACA,OAAO,KAAK,EAAE,WAAW,EAAE,WAAW,EAAE,MAAM,oBAAoB,CAAC;AACnE,OAAO,EAAE,KAAK,wBAAwB,EAAqB,MAAM,qBAAqB,CAAC;AACvF,OAAO,KAAK,EAAE,aAAa,EAAE,MAAM,qBAAqB,CAAC;AAIzD,UAAU,SAAS;IACjB,EAAE,EAAE,MAAM,CAAC;IACX,KAAK,EAAE,WAAW,CAAC;IACnB,SAAS,EAAE,MAAM,CAAC;IAClB,KAAK,EAAE,MAAM,CAAC;IACd,0CAA0C;IAC1C,IAAI,CAAC,EAAE,WAAW,CAAC,MAAM,CAAC,GAAG,SAAS,CAAC;IACvC,IAAI,CAAC,EAAE,MAAM,EAAE,GAAG,SAAS,CAAC;IAC5B,QAAQ,CAAC,EAAE,WAAW,CAAC,UAAU,CAAC,GAAG,SAAS,CAAC;CAChD;AAED,UAAU,SAAS;IACjB,IAAI,EAAE,MAAM,CAAC;IACb,EAAE,EAAE,MAAM,CAAC;IACX,mCAAmC;IACnC,QAAQ,EAAE,cAAc,GAAG,SAAS,GAAG,WAAW,GAAG,UAAU,CAAC;IAChE,MAAM,EAAE,MAAM,CAAC;IACf,EAAE,EAAE,MAAM,CAAC;CACZ;AAID,MAAM,WAAW,yBAA0B,SAAQ,wBAAwB;IACzE;;;OAGG;IACH,SAAS,CAAC,EAAE,MAAM,GAAG,SAAS,CAAC;CAChC;AAED
|
|
1
|
+
{"version":3,"file":"memory-graph-backend.d.ts","sourceRoot":"","sources":["../../src/storage/memory-graph-backend.ts"],"names":[],"mappings":"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"}
|
|
@@ -13,6 +13,15 @@ export interface ProviderConfigSnapshot {
|
|
|
13
13
|
/** Display language (Config.uiLocale), surfaced so a cross-process change
|
|
14
14
|
* (e.g. the desktop shell) propagates to running webui instances. */
|
|
15
15
|
uiLocale?: string;
|
|
16
|
+
/** Live routing fields — surfaced so a cross-process WebUI /setmodel or
|
|
17
|
+
* profile-reorder propagates to running workers without restart. */
|
|
18
|
+
fallbackModels?: string[];
|
|
19
|
+
fallbackProfiles?: Record<string, string[]>;
|
|
20
|
+
favoriteModels?: string[];
|
|
21
|
+
favoriteModelsOnly?: boolean;
|
|
22
|
+
modelMatrix?: Record<string, unknown>;
|
|
23
|
+
fallbackAuto?: boolean;
|
|
24
|
+
modelAvailabilitySchedule?: import('../core/model-availability-calendar.js').ModelBlackoutRule[];
|
|
16
25
|
}
|
|
17
26
|
export interface WatchProviderConfigOptions {
|
|
18
27
|
/** Surface non-fatal read/parse/decrypt issues. */
|
|
@@ -20,6 +29,16 @@ export interface WatchProviderConfigOptions {
|
|
|
20
29
|
/** Coalesce bursts of fs events (default 200ms). */
|
|
21
30
|
debounceMs?: number;
|
|
22
31
|
}
|
|
32
|
+
/**
|
|
33
|
+
* Read and decrypt the credential slice of a config file. Returns `undefined`
|
|
34
|
+
* when the file is missing or unparseable (the `warn` callback carries the
|
|
35
|
+
* detail); never throws for routine I/O.
|
|
36
|
+
*
|
|
37
|
+
* Exported so multi-layer watchers (e.g. `provider-runtime-setup.ts`) can
|
|
38
|
+
* re-read every active config layer when any layer changes, then merge them
|
|
39
|
+
* with correct precedence before applying.
|
|
40
|
+
*/
|
|
41
|
+
export declare function readProviderSnapshot(configPath: string, vault: SecretVault, warn?: (msg: string) => void): Promise<ProviderConfigSnapshot | undefined>;
|
|
23
42
|
/**
|
|
24
43
|
* Watch `configPath` for credential changes and invoke `onChange` with a
|
|
25
44
|
* freshly-decrypted snapshot whenever the `providers`/`apiKey`/`baseUrl` slice
|
|
@@ -1 +1 @@
|
|
|
1
|
-
{"version":3,"file":"provider-config-watcher.d.ts","sourceRoot":"","sources":["../../src/storage/provider-config-watcher.ts"],"names":[],"mappings":"AAmCA,OAAO,KAAK,EAAE,cAAc,EAAE,MAAM,oBAAoB,CAAC;AACzD,OAAO,KAAK,EAAE,WAAW,EAAE,MAAM,0BAA0B,CAAC;AAE5D;;;;;GAKG;AACH,MAAM,WAAW,sBAAsB;IACrC,SAAS,EAAE,MAAM,CAAC,MAAM,EAAE,cAAc,CAAC,CAAC;IAC1C,MAAM,CAAC,EAAE,MAAM,CAAC;IAChB,OAAO,CAAC,EAAE,MAAM,CAAC;IACjB;0EACsE;IACtE,QAAQ,CAAC,EAAE,MAAM,CAAC;
|
|
1
|
+
{"version":3,"file":"provider-config-watcher.d.ts","sourceRoot":"","sources":["../../src/storage/provider-config-watcher.ts"],"names":[],"mappings":"AAmCA,OAAO,KAAK,EAAE,cAAc,EAAE,MAAM,oBAAoB,CAAC;AACzD,OAAO,KAAK,EAAE,WAAW,EAAE,MAAM,0BAA0B,CAAC;AAE5D;;;;;GAKG;AACH,MAAM,WAAW,sBAAsB;IACrC,SAAS,EAAE,MAAM,CAAC,MAAM,EAAE,cAAc,CAAC,CAAC;IAC1C,MAAM,CAAC,EAAE,MAAM,CAAC;IAChB,OAAO,CAAC,EAAE,MAAM,CAAC;IACjB;0EACsE;IACtE,QAAQ,CAAC,EAAE,MAAM,CAAC;IAClB;yEACqE;IACrE,cAAc,CAAC,EAAE,MAAM,EAAE,CAAC;IAC1B,gBAAgB,CAAC,EAAE,MAAM,CAAC,MAAM,EAAE,MAAM,EAAE,CAAC,CAAC;IAC5C,cAAc,CAAC,EAAE,MAAM,EAAE,CAAC;IAC1B,kBAAkB,CAAC,EAAE,OAAO,CAAC;IAC7B,WAAW,CAAC,EAAE,MAAM,CAAC,MAAM,EAAE,OAAO,CAAC,CAAC;IACtC,YAAY,CAAC,EAAE,OAAO,CAAC;IACvB,yBAAyB,CAAC,EAAE,OAAO,wCAAwC,EAAE,iBAAiB,EAAE,CAAC;CAClG;AAED,MAAM,WAAW,0BAA0B;IACzC,mDAAmD;IACnD,IAAI,CAAC,EAAE,CAAC,GAAG,EAAE,MAAM,KAAK,IAAI,CAAC;IAC7B,oDAAoD;IACpD,UAAU,CAAC,EAAE,MAAM,CAAC;CACrB;AAED;;;;;;;;GAQG;AACH,wBAAsB,oBAAoB,CACxC,UAAU,EAAE,MAAM,EAClB,KAAK,EAAE,WAAW,EAClB,IAAI,CAAC,EAAE,CAAC,GAAG,EAAE,MAAM,KAAK,IAAI,GAC3B,OAAO,CAAC,sBAAsB,GAAG,SAAS,CAAC,CAgD7C;AAmBD;;;;;;;GAOG;AACH,wBAAgB,mBAAmB,CACjC,UAAU,EAAE,MAAM,EAClB,KAAK,EAAE,WAAW,EAClB,QAAQ,EAAE,CAAC,QAAQ,EAAE,sBAAsB,KAAK,IAAI,EACpD,IAAI,GAAE,0BAA+B,GACpC;IAAE,KAAK,EAAE,MAAM,IAAI,CAAA;CAAE,CAgEvB"}
|
|
@@ -45,12 +45,12 @@ export interface SessionEventBridge {
|
|
|
45
45
|
allows(type: SessionEvent['type']): boolean;
|
|
46
46
|
}
|
|
47
47
|
/** Core events that are always written regardless of auditLevel. */
|
|
48
|
-
declare const CORE_RECONSTRUCT_EVENTS: Set<"agent_error" | "agent_spawned" | "agent_stopped" | "checkpoint" | "compaction" | "context_snapshot" | "error" | "file_observation" | "file_snapshot" | "in_flight_end" | "in_flight_start" | "llm_request" | "llm_response" | "message_truncated" | "mode_changed" | "provider_error" | "provider_retry" | "rewound" | "session_end" | "session_forked" | "session_resumed" | "session_start" | "side_effect" | "skill_activated" | "skill_deactivated" | "spec_analyzed" | "spec_parsed" | "task_completed" | "task_created" | "task_failed" | "task_updated" | "tool_call_end" | "tool_call_start" | "tool_progress" | "tool_result" | "tool_use" | "user_input">;
|
|
48
|
+
declare const CORE_RECONSTRUCT_EVENTS: Set<"agent_error" | "agent_spawned" | "agent_stopped" | "checkpoint" | "compaction" | "context_snapshot" | "error" | "file_event" | "file_observation" | "file_snapshot" | "in_flight_end" | "in_flight_start" | "llm_request" | "llm_response" | "message_appended" | "message_truncated" | "message_updated" | "messages_replaced" | "mode_changed" | "provider_error" | "provider_retry" | "rewound" | "session_end" | "session_forked" | "session_resumed" | "session_start" | "side_effect" | "skill_activated" | "skill_deactivated" | "spec_analyzed" | "spec_parsed" | "task_completed" | "task_created" | "task_failed" | "task_updated" | "tool_call_end" | "tool_call_start" | "tool_progress" | "tool_result" | "tool_use" | "user_input">;
|
|
49
49
|
/**
|
|
50
50
|
* Events that are considered "standard" audit detail.
|
|
51
51
|
* These are lightweight and high-value for forensics.
|
|
52
52
|
*/
|
|
53
|
-
declare const STANDARD_AUDIT_EVENTS: Set<"agent_error" | "agent_spawned" | "agent_stopped" | "checkpoint" | "compaction" | "context_snapshot" | "error" | "file_observation" | "file_snapshot" | "in_flight_end" | "in_flight_start" | "llm_request" | "llm_response" | "message_truncated" | "mode_changed" | "provider_error" | "provider_retry" | "rewound" | "session_end" | "session_forked" | "session_resumed" | "session_start" | "side_effect" | "skill_activated" | "skill_deactivated" | "spec_analyzed" | "spec_parsed" | "task_completed" | "task_created" | "task_failed" | "task_updated" | "tool_call_end" | "tool_call_start" | "tool_progress" | "tool_result" | "tool_use" | "user_input">;
|
|
53
|
+
declare const STANDARD_AUDIT_EVENTS: Set<"agent_error" | "agent_spawned" | "agent_stopped" | "checkpoint" | "compaction" | "context_snapshot" | "error" | "file_event" | "file_observation" | "file_snapshot" | "in_flight_end" | "in_flight_start" | "llm_request" | "llm_response" | "message_appended" | "message_truncated" | "message_updated" | "messages_replaced" | "mode_changed" | "provider_error" | "provider_retry" | "rewound" | "session_end" | "session_forked" | "session_resumed" | "session_start" | "side_effect" | "skill_activated" | "skill_deactivated" | "spec_analyzed" | "spec_parsed" | "task_completed" | "task_created" | "task_failed" | "task_updated" | "tool_call_end" | "tool_call_start" | "tool_progress" | "tool_result" | "tool_use" | "user_input">;
|
|
54
54
|
/**
|
|
55
55
|
* Create a safe, audit-level-aware bridge around a SessionWriter.
|
|
56
56
|
*
|
|
@@ -1 +1 @@
|
|
|
1
|
-
{"version":3,"file":"session-event-bridge.d.ts","sourceRoot":"","sources":["../../src/storage/session-event-bridge.ts"],"names":[],"mappings":"AAAA,OAAO,KAAK,EAAE,YAAY,EAAE,aAAa,EAAE,MAAM,qBAAqB,CAAC;AAEvE,MAAM,MAAM,UAAU,GAAG,SAAS,GAAG,UAAU,GAAG,MAAM,CAAC;AAEzD;;;;GAIG;AACH,MAAM,WAAW,2BAA2B;IAC1C;;;;OAIG;IACH,UAAU,CAAC,EAAE,MAAM,GAAG,SAAS,CAAC;CACjC;AAED,MAAM,WAAW,sBAAsB;IACrC,kGAAkG;IAClG,YAAY,CAAC,EAAE,2BAA2B,GAAG,SAAS,CAAC;CACxD;AAED,MAAM,WAAW,yBAAyB;IACxC,mDAAmD;IACnD,QAAQ,CAAC,EAAE,sBAAsB,GAAG,SAAS,CAAC;CAC/C;AAED;;;;;;GAMG;AACH,MAAM,WAAW,kBAAkB;IACjC,6DAA6D;IAC7D,MAAM,CAAC,KAAK,EAAE,YAAY,GAAG,OAAO,CAAC,IAAI,CAAC,CAAC;IAC3C,8DAA8D;IAC9D,WAAW,CAAC,MAAM,EAAE,YAAY,EAAE,GAAG,OAAO,CAAC,IAAI,CAAC,CAAC;IAEnD,4EAA4E;IAC5E,QAAQ,CAAC,KAAK,EAAE,UAAU,CAAC;IAE3B;;;;OAIG;IACH,aAAa,CAAC,KAAK,EAAE,UAAU,GAAG,IAAI,CAAC;IAEvC,oFAAoF;IACpF,MAAM,CAAC,IAAI,EAAE,YAAY,CAAC,MAAM,CAAC,GAAG,OAAO,CAAC;CAC7C;AAED,oEAAoE;AACpE,QAAA,MAAM,uBAAuB,
|
|
1
|
+
{"version":3,"file":"session-event-bridge.d.ts","sourceRoot":"","sources":["../../src/storage/session-event-bridge.ts"],"names":[],"mappings":"AAAA,OAAO,KAAK,EAAE,YAAY,EAAE,aAAa,EAAE,MAAM,qBAAqB,CAAC;AAEvE,MAAM,MAAM,UAAU,GAAG,SAAS,GAAG,UAAU,GAAG,MAAM,CAAC;AAEzD;;;;GAIG;AACH,MAAM,WAAW,2BAA2B;IAC1C;;;;OAIG;IACH,UAAU,CAAC,EAAE,MAAM,GAAG,SAAS,CAAC;CACjC;AAED,MAAM,WAAW,sBAAsB;IACrC,kGAAkG;IAClG,YAAY,CAAC,EAAE,2BAA2B,GAAG,SAAS,CAAC;CACxD;AAED,MAAM,WAAW,yBAAyB;IACxC,mDAAmD;IACnD,QAAQ,CAAC,EAAE,sBAAsB,GAAG,SAAS,CAAC;CAC/C;AAED;;;;;;GAMG;AACH,MAAM,WAAW,kBAAkB;IACjC,6DAA6D;IAC7D,MAAM,CAAC,KAAK,EAAE,YAAY,GAAG,OAAO,CAAC,IAAI,CAAC,CAAC;IAC3C,8DAA8D;IAC9D,WAAW,CAAC,MAAM,EAAE,YAAY,EAAE,GAAG,OAAO,CAAC,IAAI,CAAC,CAAC;IAEnD,4EAA4E;IAC5E,QAAQ,CAAC,KAAK,EAAE,UAAU,CAAC;IAE3B;;;;OAIG;IACH,aAAa,CAAC,KAAK,EAAE,UAAU,GAAG,IAAI,CAAC;IAEvC,oFAAoF;IACpF,MAAM,CAAC,IAAI,EAAE,YAAY,CAAC,MAAM,CAAC,GAAG,OAAO,CAAC;CAC7C;AAED,oEAAoE;AACpE,QAAA,MAAM,uBAAuB,wtBAkB3B,CAAC;AAEH;;;GAGG;AACH,QAAA,MAAM,qBAAqB,wtBAyBzB,CAAC;AA4BH;;;;;;;;;;;;GAYG;AACH,wBAAgB,wBAAwB,CACtC,MAAM,EAAE,aAAa,GAAG,CAAC,MAAM,aAAa,GAAG,SAAS,GAAG,IAAI,CAAC,GAAG,SAAS,GAAG,IAAI,EACnF,KAAK,GAAE,UAAuB,EAC9B,OAAO,GAAE,yBAA8B,GACtC,kBAAkB,CAyFpB;AAED,oEAAoE;AACpE,OAAO,EAAE,uBAAuB,EAAE,qBAAqB,EAAE,CAAC;AAE1D;;;GAGG;AACH,wBAAgB,iBAAiB,CAC/B,GAAG,CAAC,EAAE;IAAE,OAAO,CAAC,EAAE;QAAE,UAAU,CAAC,EAAE,UAAU,GAAG,SAAS,CAAA;KAAE,GAAG,SAAS,CAAA;CAAE,GAAG,IAAI,GAC7E,UAAU,CAMZ;AAED;;;GAGG;AACH,wBAAgB,2BAA2B,CACzC,GAAG,CAAC,EAAE;IACJ,OAAO,CAAC,EAAE;QACR,UAAU,CAAC,EAAE,UAAU,GAAG,SAAS,CAAC;QACpC,QAAQ,CAAC,EAAE;YACT,YAAY,CAAC,EAAE;gBAAE,UAAU,CAAC,EAAE,MAAM,GAAG,SAAS,CAAA;aAAE,CAAC;SACpD,CAAC;KACH,CAAC;CACH,GAAG,IAAI,GACP;IACD,UAAU,EAAE,UAAU,CAAC;IACvB,QAAQ,EAAE;QACR,YAAY,EAAE;YAAE,UAAU,EAAE,MAAM,CAAA;SAAE,CAAC;KACtC,CAAC;CACH,CAeA"}
|
|
@@ -3,4 +3,14 @@ import type { ResumeValidation, SessionEvent } from '../types/session.js';
|
|
|
3
3
|
export declare function validateResumeFileObservations(events: readonly SessionEvent[], projectRoot: string): Promise<ResumeValidation>;
|
|
4
4
|
/** Build the ephemeral system message injected into the first resumed turn. */
|
|
5
5
|
export declare function formatResumeValidationNotice(validation: ResumeValidation, projectRoot: string): string | null;
|
|
6
|
+
/**
|
|
7
|
+
* Build the ephemeral system message injected when the resumed session had
|
|
8
|
+
* tool calls still in flight (the previous run crashed or was interrupted
|
|
9
|
+
* before their results were recorded). The interrupted `tool_use` blocks are
|
|
10
|
+
* stripped from the reconstructed conversation by adjacency repair and are NOT
|
|
11
|
+
* re-executed on resume — this notice simply makes the interruption visible so
|
|
12
|
+
* the model can decide whether to retry the work. Returns null when nothing
|
|
13
|
+
* was in flight.
|
|
14
|
+
*/
|
|
15
|
+
export declare function formatInterruptedToolNotice(pendingToolUseCount: number): string | null;
|
|
6
16
|
//# sourceMappingURL=session-resume-validation.d.ts.map
|
|
@@ -1 +1 @@
|
|
|
1
|
-
{"version":3,"file":"session-resume-validation.d.ts","sourceRoot":"","sources":["../../src/storage/session-resume-validation.ts"],"names":[],"mappings":"AAGA,OAAO,KAAK,EAEV,gBAAgB,EAChB,YAAY,EACb,MAAM,qBAAqB,CAAC;AA0G7B,6EAA6E;AAC7E,wBAAsB,8BAA8B,CAClD,MAAM,EAAE,SAAS,YAAY,EAAE,EAC/B,WAAW,EAAE,MAAM,GAClB,OAAO,CAAC,gBAAgB,CAAC,CAc3B;AAED,+EAA+E;AAC/E,wBAAgB,4BAA4B,CAC1C,UAAU,EAAE,gBAAgB,EAC5B,WAAW,EAAE,MAAM,GAClB,MAAM,GAAG,IAAI,CAiBf"}
|
|
1
|
+
{"version":3,"file":"session-resume-validation.d.ts","sourceRoot":"","sources":["../../src/storage/session-resume-validation.ts"],"names":[],"mappings":"AAGA,OAAO,KAAK,EAEV,gBAAgB,EAChB,YAAY,EACb,MAAM,qBAAqB,CAAC;AA0G7B,6EAA6E;AAC7E,wBAAsB,8BAA8B,CAClD,MAAM,EAAE,SAAS,YAAY,EAAE,EAC/B,WAAW,EAAE,MAAM,GAClB,OAAO,CAAC,gBAAgB,CAAC,CAc3B;AAED,+EAA+E;AAC/E,wBAAgB,4BAA4B,CAC1C,UAAU,EAAE,gBAAgB,EAC5B,WAAW,EAAE,MAAM,GAClB,MAAM,GAAG,IAAI,CAiBf;AAED;;;;;;;;GAQG;AACH,wBAAgB,2BAA2B,CAAC,mBAAmB,EAAE,MAAM,GAAG,MAAM,GAAG,IAAI,CAQtF"}
|
|
@@ -0,0 +1,53 @@
|
|
|
1
|
+
import type { Message } from '../types/messages.js';
|
|
2
|
+
import type { SessionWriter } from '../types/session.js';
|
|
3
|
+
/**
|
|
4
|
+
* The slice of ConversationState this module needs. Kept structural so callers
|
|
5
|
+
* can pass `ctx.state` without this module depending on the core layer.
|
|
6
|
+
*/
|
|
7
|
+
export interface RewindableConversation {
|
|
8
|
+
replaceMessages(messages: Message[]): void;
|
|
9
|
+
}
|
|
10
|
+
export interface ApplyRewindOptions {
|
|
11
|
+
/** The live writer for the session being rewound. */
|
|
12
|
+
session: SessionWriter;
|
|
13
|
+
/** The live conversation to cut back. */
|
|
14
|
+
state: RewindableConversation;
|
|
15
|
+
/** Directory holding the session JSONL files. */
|
|
16
|
+
sessionsDir: string;
|
|
17
|
+
/** Checkpoint promptIndex to rewind to. */
|
|
18
|
+
promptIndex: number;
|
|
19
|
+
/**
|
|
20
|
+
* Files the SessionRewinder just reverted, recorded on the `rewound` event.
|
|
21
|
+
* Only this caller knows them: the file_snapshot events that prove what
|
|
22
|
+
* changed are truncated away by this very call.
|
|
23
|
+
*/
|
|
24
|
+
revertedFiles?: readonly string[] | undefined;
|
|
25
|
+
}
|
|
26
|
+
export interface ApplyRewindResult {
|
|
27
|
+
/** Events dropped from the JSONL by the truncation. */
|
|
28
|
+
removedEvents: number;
|
|
29
|
+
/** Message count the live conversation was cut back to. */
|
|
30
|
+
messageCount: number;
|
|
31
|
+
}
|
|
32
|
+
/**
|
|
33
|
+
* Truncate the session JSONL to a checkpoint AND cut the live conversation
|
|
34
|
+
* back to match.
|
|
35
|
+
*
|
|
36
|
+
* Truncating the log alone is not a rewind: the model keeps the rewound turns
|
|
37
|
+
* in its working set, so the next prompt is answered against a history the log
|
|
38
|
+
* no longer contains. Worse, the conversation journal records `message_updated`
|
|
39
|
+
* by absolute index, so once the log is shorter than the live array those
|
|
40
|
+
* updates fail the `index < messages.length` guard on reload and are dropped as
|
|
41
|
+
* damage — the file diverges from the session permanently.
|
|
42
|
+
*
|
|
43
|
+
* The truncated log is the source of truth for what survives, so this reloads
|
|
44
|
+
* it and replays the result into the live state rather than trying to compute
|
|
45
|
+
* the cut point twice. `replaceMessages` emits `messages_replaced`, which
|
|
46
|
+
* re-anchors the journal at the new length and makes the cut explicit to any
|
|
47
|
+
* later reader.
|
|
48
|
+
*
|
|
49
|
+
* The caller is responsible for reverting files (see `SessionRewinder`); this
|
|
50
|
+
* only reconciles the log with the live conversation.
|
|
51
|
+
*/
|
|
52
|
+
export declare function applyRewindToConversation(opts: ApplyRewindOptions): Promise<ApplyRewindResult>;
|
|
53
|
+
//# sourceMappingURL=session-rewind-apply.d.ts.map
|
|
@@ -0,0 +1 @@
|
|
|
1
|
+
{"version":3,"file":"session-rewind-apply.d.ts","sourceRoot":"","sources":["../../src/storage/session-rewind-apply.ts"],"names":[],"mappings":"AAAA,OAAO,KAAK,EAAE,OAAO,EAAE,MAAM,sBAAsB,CAAC;AACpD,OAAO,KAAK,EAAE,aAAa,EAAE,MAAM,qBAAqB,CAAC;AAGzD;;;GAGG;AACH,MAAM,WAAW,sBAAsB;IACrC,eAAe,CAAC,QAAQ,EAAE,OAAO,EAAE,GAAG,IAAI,CAAC;CAC5C;AAED,MAAM,WAAW,kBAAkB;IACjC,qDAAqD;IACrD,OAAO,EAAE,aAAa,CAAC;IACvB,yCAAyC;IACzC,KAAK,EAAE,sBAAsB,CAAC;IAC9B,iDAAiD;IACjD,WAAW,EAAE,MAAM,CAAC;IACpB,2CAA2C;IAC3C,WAAW,EAAE,MAAM,CAAC;IACpB;;;;OAIG;IACH,aAAa,CAAC,EAAE,SAAS,MAAM,EAAE,GAAG,SAAS,CAAC;CAC/C;AAED,MAAM,WAAW,iBAAiB;IAChC,uDAAuD;IACvD,aAAa,EAAE,MAAM,CAAC;IACtB,2DAA2D;IAC3D,YAAY,EAAE,MAAM,CAAC;CACtB;AAED;;;;;;;;;;;;;;;;;;;GAmBG;AACH,wBAAsB,yBAAyB,CAC7C,IAAI,EAAE,kBAAkB,GACvB,OAAO,CAAC,iBAAiB,CAAC,CAY5B"}
|
|
@@ -1 +1 @@
|
|
|
1
|
-
{"version":3,"file":"session-rewinder.d.ts","sourceRoot":"","sources":["../../src/storage/session-rewinder.ts"],"names":[],"mappings":"AAIA,OAAO,KAAK,EAAE,cAAc,EAAgB,oBAAoB,EAAE,eAAe,EAAE,MAAM,8BAA8B,CAAC;AAMxH,MAAM,WAAW,sBAAsB;IACrC,WAAW,EAAE,MAAM,CAAC;IACpB,kFAAkF;IAClF,WAAW,EAAE,MAAM,CAAC;CACrB;AAED;;;GAGG;AACH,qBAAa,sBAAuB,YAAW,eAAe;IAChD,OAAO,CAAC,QAAQ,CAAC,WAAW;IAAU,OAAO,CAAC,QAAQ,CAAC,WAAW;IAA9E,YAA6B,WAAW,EAAE,MAAM,EAAmB,WAAW,EAAE,MAAM,EAAI;IAE1F,OAAO,CAAC,WAAW;IAIb,eAAe,CAAC,SAAS,EAAE,MAAM,GAAG,OAAO,CAAC,cAAc,EAAE,CAAC,CA4BlE;IAEK,kBAAkB,CACtB,SAAS,EAAE,MAAM,EACjB,eAAe,EAAE,MAAM,GACtB,OAAO,CAAC,oBAAoB,CAAC,
|
|
1
|
+
{"version":3,"file":"session-rewinder.d.ts","sourceRoot":"","sources":["../../src/storage/session-rewinder.ts"],"names":[],"mappings":"AAIA,OAAO,KAAK,EAAE,cAAc,EAAgB,oBAAoB,EAAE,eAAe,EAAE,MAAM,8BAA8B,CAAC;AAMxH,MAAM,WAAW,sBAAsB;IACrC,WAAW,EAAE,MAAM,CAAC;IACpB,kFAAkF;IAClF,WAAW,EAAE,MAAM,CAAC;CACrB;AAED;;;GAGG;AACH,qBAAa,sBAAuB,YAAW,eAAe;IAChD,OAAO,CAAC,QAAQ,CAAC,WAAW;IAAU,OAAO,CAAC,QAAQ,CAAC,WAAW;IAA9E,YAA6B,WAAW,EAAE,MAAM,EAAmB,WAAW,EAAE,MAAM,EAAI;IAE1F,OAAO,CAAC,WAAW;IAIb,eAAe,CAAC,SAAS,EAAE,MAAM,GAAG,OAAO,CAAC,cAAc,EAAE,CAAC,CA4BlE;IAEK,kBAAkB,CACtB,SAAS,EAAE,MAAM,EACjB,eAAe,EAAE,MAAM,GACtB,OAAO,CAAC,oBAAoB,CAAC,CA8C/B;IAEK,WAAW,CAAC,SAAS,EAAE,MAAM,EAAE,CAAC,EAAE,MAAM,GAAG,OAAO,CAAC,oBAAoB,CAAC,CAsC7E;IAEK,aAAa,CAAC,SAAS,EAAE,MAAM,GAAG,OAAO,CAAC,oBAAoB,CAAC,CAkBpE;CACF"}
|
|
@@ -1 +1 @@
|
|
|
1
|
-
{"version":3,"file":"session-store.d.ts","sourceRoot":"","sources":["../../src/storage/session-store.ts"],"names":[],"mappings":"AAKA,OAAO,KAAK,EAAE,QAAQ,EAAE,MAAM,qBAAqB,CAAC;
|
|
1
|
+
{"version":3,"file":"session-store.d.ts","sourceRoot":"","sources":["../../src/storage/session-store.ts"],"names":[],"mappings":"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"}
|
|
@@ -1,7 +1,7 @@
|
|
|
1
1
|
{
|
|
2
2
|
"version": 3,
|
|
3
3
|
"sources": ["../../src/tasking/task-store.ts", "../../src/types/task-graph.ts", "../../src/utils/error.ts", "../../src/types/errors.ts", "../../src/tasking/task-tracker.ts"],
|
|
4
|
-
"sourcesContent": ["import type { TaskGraph } from '../types/task-graph.js';\nimport type { TaskStore } from './task-tracker.js';\n\n/**\n * In-memory task-graph store used by AutoPhase and tests.\n *\n * The store clones the graph container on read/write so callers cannot replace\n * its Maps/arrays behind the store's back. Task nodes themselves intentionally\n * remain shared: TaskTracker owns node mutation and persists after each change.\n */\nexport class DefaultTaskStore implements TaskStore {\n private readonly graphs = new Map<string, TaskGraph>();\n\n async saveGraph(graph: TaskGraph): Promise<void> {\n this.graphs.set(graph.id, this.cloneGraph(graph));\n }\n\n async loadGraph(id: string): Promise<TaskGraph | null> {\n const graph = this.graphs.get(id);\n return graph ? this.cloneGraph(graph) : null;\n }\n\n async listGraphs(): Promise<Array<{ id: string; title: string; updatedAt: number }>> {\n return Array.from(this.graphs.values()).map((graph) => ({\n id: graph.id,\n title: graph.title,\n updatedAt: graph.updatedAt,\n }));\n }\n\n async deleteGraph(id: string): Promise<void> {\n this.graphs.delete(id);\n }\n\n private cloneGraph(graph: TaskGraph): TaskGraph {\n return {\n ...graph,\n nodes: new Map(graph.nodes),\n edges: [...graph.edges],\n rootNodes: [...graph.rootNodes],\n };\n }\n}\n", "export type TaskStatus = 'pending' | 'in_progress' | 'blocked' | 'failed' | 'review' | 'completed';\nexport type TaskPriority = 'critical' | 'high' | 'medium' | 'low';\nexport type TaskType = 'feature' | 'bugfix' | 'refactor' | 'docs' | 'test' | 'chore';\n\nexport interface TaskNode {\n id: string;\n title: string;\n description: string;\n type: TaskType;\n priority: TaskPriority;\n status: TaskStatus;\n assignee?: string | undefined;\n estimateHours?: number | undefined;\n actualHours?: number | undefined;\n tags?: string[] | undefined;\n specRequirementId?: string | undefined;\n parentId?: string | undefined;\n children?: string[] | undefined;\n createdAt: number;\n updatedAt: number;\n startedAt?: number | undefined; // set when status \u2192 in_progress\n completedAt?: number | undefined;\n metadata?: Record<string, unknown>;\n}\n\nexport interface TaskEdge {\n id: string;\n from: string;\n to: string;\n type: 'blocks' | 'depends_on' | 'relates_to' | 'implements';\n weight?: number | undefined;\n}\n\nexport interface TaskGraph {\n id: string;\n specId: string;\n title: string;\n nodes: Map<string, TaskNode>;\n edges: TaskEdge[];\n rootNodes: string[];\n createdAt: number;\n updatedAt: number;\n}\n\nexport interface TaskDependency {\n taskId: string;\n blockedBy: string[];\n blocking: string[];\n}\n\nexport interface TaskAssignment {\n taskId: string;\n assignee: string;\n assignedAt: number;\n}\n\nexport interface TaskProgress {\n total: number;\n pending: number;\n inProgress: number;\n blocked: number;\n failed: number;\n review: number;\n completed: number;\n percentComplete: number;\n estimatedHours: number;\n actualHours: number;\n}\n\nexport interface TaskFilter {\n status?: TaskStatus[] | undefined;\n priority?: TaskPriority[] | undefined;\n type?: TaskType[] | undefined;\n assignee?: string[] | undefined;\n tags?: string[] | undefined;\n specRequirementId?: string | undefined;\n}\n\nexport interface TaskSort {\n field: 'priority' | 'createdAt' | 'updatedAt' | 'status';\n direction: 'asc' | 'desc';\n}\n\nexport interface CriticalPathResult {\n taskIds: string[];\n totalEstimateHours: number;\n bottleneckTasks: string[];\n}\n\nexport function computeTaskProgress(graph: TaskGraph): TaskProgress {\n let completed = 0;\n let pending = 0;\n let inProgress = 0;\n let blocked = 0;\n let failed = 0;\n let review = 0;\n let estimatedHours = 0;\n let actualHours = 0;\n for (const n of graph.nodes.values()) {\n switch (n.status) {\n case 'completed':\n completed++;\n break;\n case 'pending':\n pending++;\n break;\n case 'in_progress':\n inProgress++;\n break;\n case 'blocked':\n blocked++;\n break;\n case 'failed':\n failed++;\n break;\n case 'review':\n review++;\n break;\n }\n estimatedHours += n.estimateHours ?? 0;\n actualHours += n.actualHours ?? 0;\n }\n const total = graph.nodes.size;\n\n return {\n total,\n pending,\n inProgress,\n blocked,\n failed,\n review,\n completed,\n percentComplete: total > 0 ? Math.round((completed / total) * 100) : 0,\n estimatedHours,\n actualHours,\n };\n}\n\nexport function findCriticalPath(graph: TaskGraph): CriticalPathResult {\n const nodes = Array.from(graph.nodes.values());\n const criticalNodes = nodes.filter((n) => n.priority === 'critical');\n const bottleneckTasks = criticalNodes\n .filter((n) => graph.edges.some((e) => e.to === n.id && e.type === 'depends_on'))\n .map((n) => n.id);\n\n const totalEstimateHours = criticalNodes.reduce((sum, n) => sum + (n.estimateHours ?? 0), 0);\n\n return {\n taskIds: criticalNodes.map((n) => n.id),\n totalEstimateHours,\n bottleneckTasks,\n };\n}\n\nexport function topologicalSort(graph: TaskGraph): string[] {\n const visited = new Set<string>();\n const inStack = new Set<string>();\n const result: string[] = [];\n\n function visit(id: string): void {\n // Cycle: callers must detect cycles up-front if they care; we just stop recursing.\n if (inStack.has(id)) return;\n if (visited.has(id)) return;\n if (!graph.nodes.has(id)) return;\n\n visited.add(id);\n inStack.add(id);\n\n for (const edge of graph.edges) {\n if (edge.from === id) visit(edge.to);\n }\n\n inStack.delete(id);\n result.push(id);\n }\n\n for (const rootId of graph.rootNodes) {\n visit(rootId);\n }\n\n return result;\n}\n\nexport type SerializableTaskGraphNodes =\n | TaskNode[]\n | Array<[string, TaskNode]>\n | Record<string, TaskNode>;\n\nexport type SerializableTaskGraph = Omit<TaskGraph, 'nodes'> & {\n nodes: SerializableTaskGraphNodes;\n};\n\nexport type SerializedTaskGraph = Omit<TaskGraph, 'nodes'> & {\n nodes: TaskNode[];\n};\n\nexport function serializeTaskGraph(graph: TaskGraph): SerializedTaskGraph {\n return {\n ...graph,\n nodes: Array.from(graph.nodes.values()),\n };\n}\n\nexport function deserializeTaskGraph(input: SerializableTaskGraph): TaskGraph {\n const nodes = new Map<string, TaskNode>();\n if (Array.isArray(input.nodes)) {\n for (const entry of input.nodes) {\n if (Array.isArray(entry)) nodes.set(entry[0], { ...entry[1], id: entry[1].id || entry[0] });\n else nodes.set(entry.id, entry);\n }\n } else {\n for (const [id, node] of Object.entries(input.nodes)) {\n nodes.set(id, { ...node, id: node.id || id });\n }\n }\n return { ...input, nodes };\n}\n", "/**\n * Converts an unknown error value to a human-readable string.\n * Used in 40+ files across the codebase to normalize error messaging.\n */\nexport function toErrorMessage(err: unknown): string {\n return err instanceof Error ? err.message : String(err);\n}\n", "import { toErrorMessage } from '../utils/index.js';\n\n/**\n * WrongStack error hierarchy.\n *\n * Every error thrown by the framework is a `WrongStackError` with a\n * machine-readable `code`, a `subsystem` tag, and a `severity` level.\n * This lets consumers (CLI, TUI, plugins, tests) branch on structured\n * data instead of parsing error messages.\n */\n\n// \u2500\u2500 Error codes \u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\n\n/**\n * Machine-readable error codes as frozen constants.\n *\n * Use `ERROR_CODES.X` instead of raw string literals for:\n * - IDE autocomplete and compile-time validation\n * - Safe refactoring (rename updates all usages)\n * - Plugin extensibility (extend the object to add custom codes)\n *\n * The `ErrorCode` type is derived from this object, so adding a new\n * code here automatically updates the type without extra changes.\n */\nexport const ERROR_CODES = {\n // Provider\n PROVIDER_RATE_LIMITED: 'PROVIDER_RATE_LIMITED',\n PROVIDER_AUTH_FAILED: 'PROVIDER_AUTH_FAILED',\n PROVIDER_OVERLOADED: 'PROVIDER_OVERLOADED',\n PROVIDER_INVALID_REQUEST: 'PROVIDER_INVALID_REQUEST',\n PROVIDER_SERVER_ERROR: 'PROVIDER_SERVER_ERROR',\n PROVIDER_NETWORK_ERROR: 'PROVIDER_NETWORK_ERROR',\n PROVIDER_CONTEXT_OVERFLOW: 'PROVIDER_CONTEXT_OVERFLOW',\n // Tool\n TOOL_NOT_FOUND: 'TOOL_NOT_FOUND',\n TOOL_PERMISSION_DENIED: 'TOOL_PERMISSION_DENIED',\n TOOL_EXECUTION_FAILED: 'TOOL_EXECUTION_FAILED',\n TOOL_TIMEOUT: 'TOOL_TIMEOUT',\n TOOL_INPUT_INVALID: 'TOOL_INPUT_INVALID',\n // Config\n CONFIG_INVALID: 'CONFIG_INVALID',\n CONFIG_NOT_FOUND: 'CONFIG_NOT_FOUND',\n CONFIG_PARSE_FAILED: 'CONFIG_PARSE_FAILED',\n CONFIG_MIGRATION_NEEDED: 'CONFIG_MIGRATION_NEEDED',\n // Plugin\n PLUGIN_LOAD_FAILED: 'PLUGIN_LOAD_FAILED',\n PLUGIN_API_MISMATCH: 'PLUGIN_API_MISMATCH',\n PLUGIN_MISSING_DEPENDENCY: 'PLUGIN_MISSING_DEPENDENCY',\n // Agent\n AGENT_ITERATION_LIMIT: 'AGENT_ITERATION_LIMIT',\n AGENT_CONTEXT_OVERFLOW: 'AGENT_CONTEXT_OVERFLOW',\n AGENT_ABORTED: 'AGENT_ABORTED',\n AGENT_RUN_FAILED: 'AGENT_RUN_FAILED',\n // Session\n SESSION_NOT_FOUND: 'SESSION_NOT_FOUND',\n SESSION_CORRUPTED: 'SESSION_CORRUPTED',\n SESSION_WRITE_FAILED: 'SESSION_WRITE_FAILED',\n // Container / Registry\n CONTAINER_TOKEN_ALREADY_BOUND: 'CONTAINER_TOKEN_ALREADY_BOUND',\n CONTAINER_TOKEN_NOT_BOUND: 'CONTAINER_TOKEN_NOT_BOUND',\n CONTAINER_CIRCULAR_DEPENDENCY: 'CONTAINER_CIRCULAR_DEPENDENCY',\n REGISTRY_DUPLICATE: 'REGISTRY_DUPLICATE',\n REGISTRY_NOT_FOUND: 'REGISTRY_NOT_FOUND',\n REGISTRY_INVALID: 'REGISTRY_INVALID',\n // File system\n FS_READ_FAILED: 'FS_READ_FAILED',\n FS_WRITE_FAILED: 'FS_WRITE_FAILED',\n FS_MKDIR_FAILED: 'FS_MKDIR_FAILED',\n FS_DELETE_FAILED: 'FS_DELETE_FAILED',\n FS_ATOMIC_WRITE_FAILED: 'FS_ATOMIC_WRITE_FAILED',\n // SDD (Spec-Driven Development)\n SDD_VALIDATION_FAILED: 'SDD_VALIDATION_FAILED',\n SDD_PARSE_FAILED: 'SDD_PARSE_FAILED',\n SDD_INVALID_STATE: 'SDD_INVALID_STATE',\n SDD_NOT_READY: 'SDD_NOT_READY',\n // General\n VALIDATION_ERROR: 'VALIDATION_ERROR',\n PARSE_FAILED: 'PARSE_FAILED',\n UNKNOWN: 'UNKNOWN',\n} as const;\n\n/**\n * Union type derived from `ERROR_CODES`. Using `typeof ERROR_CODES[keyof typeof ERROR_CODES]`\n * instead of a string literal union means TypeScript auto-updates the type whenever\n * a new code is added to `ERROR_CODES` \u2014 no need to keep two lists in sync.\n */\nexport type ErrorCode = (typeof ERROR_CODES)[keyof typeof ERROR_CODES];\n\nexport type ErrorSubsystem =\n | 'provider'\n | 'tool'\n | 'config'\n | 'plugin'\n | 'agent'\n | 'session'\n | 'sdd'\n | 'container'\n | 'fs'\n | 'general';\nexport type ErrorSeverity = 'fatal' | 'error' | 'warning';\n\n// \u2500\u2500 Base error class \u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\n\nexport class WrongStackError extends Error {\n readonly code: ErrorCode;\n readonly subsystem: ErrorSubsystem;\n readonly severity: ErrorSeverity;\n readonly recoverable: boolean;\n readonly context?: Record<string, unknown> | undefined;\n\n constructor(opts: {\n message: string;\n code: ErrorCode;\n subsystem: ErrorSubsystem;\n severity?: ErrorSeverity | undefined;\n recoverable?: boolean | undefined;\n context?: Record<string, unknown> | undefined;\n cause?: unknown | undefined;\n }) {\n super(opts.message, { cause: opts.cause });\n this.name = 'WrongStackError';\n this.code = opts.code;\n this.subsystem = opts.subsystem;\n this.severity = opts.severity ?? 'error';\n this.recoverable = opts.recoverable ?? false;\n this.context = opts.context;\n }\n\n /**\n * Render a one-line user-facing description.\n * Subclasses should override for domain-specific formatting.\n */\n describe(): string {\n const ctx = this.context ? ` ${formatContext(this.context)}` : '';\n return `${this.code}: ${this.message}${ctx}`;\n }\n}\n\nfunction formatContext(ctx: Record<string, unknown>): string {\n const parts = Object.entries(ctx)\n .filter(([, v]) => v !== undefined)\n .slice(0, 3)\n .map(([k, v]) => `${k}=${String(v)}`);\n return parts.length > 0 ? `[${parts.join(' ')}]` : '';\n}\n\n// \u2500\u2500 Specific error classes \u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\n\n/**\n * Tool execution errors \u2014 thrown by ToolExecutor and individual tools.\n */\nexport class ToolError extends WrongStackError {\n readonly toolName: string;\n\n constructor(opts: {\n message: string;\n code: Extract<\n ErrorCode,\n | 'TOOL_NOT_FOUND'\n | 'TOOL_PERMISSION_DENIED'\n | 'TOOL_EXECUTION_FAILED'\n | 'TOOL_TIMEOUT'\n | 'TOOL_INPUT_INVALID'\n >;\n toolName: string;\n recoverable?: boolean | undefined;\n context?: Record<string, unknown> | undefined;\n cause?: unknown | undefined;\n }) {\n super({\n message: opts.message,\n code: opts.code,\n subsystem: 'tool',\n recoverable: opts.recoverable,\n context: { tool: opts.toolName, ...opts.context },\n cause: opts.cause,\n });\n this.name = 'ToolError';\n this.toolName = opts.toolName;\n }\n}\n\n/**\n * Config loading / validation errors.\n */\nexport class ConfigError extends WrongStackError {\n constructor(opts: {\n message: string;\n code: Extract<\n ErrorCode,\n 'CONFIG_INVALID' | 'CONFIG_NOT_FOUND' | 'CONFIG_PARSE_FAILED' | 'CONFIG_MIGRATION_NEEDED'\n >;\n context?: Record<string, unknown> | undefined;\n cause?: unknown | undefined;\n }) {\n super({\n message: opts.message,\n code: opts.code,\n subsystem: 'config',\n severity: 'fatal',\n recoverable: false,\n context: opts.context,\n cause: opts.cause,\n });\n this.name = 'ConfigError';\n }\n}\n\n/**\n * Plugin loading / lifecycle errors.\n */\nexport class PluginError extends WrongStackError {\n readonly pluginName: string;\n\n constructor(opts: {\n message: string;\n code: Extract<\n ErrorCode,\n 'PLUGIN_LOAD_FAILED' | 'PLUGIN_API_MISMATCH' | 'PLUGIN_MISSING_DEPENDENCY'\n >;\n pluginName: string;\n context?: Record<string, unknown> | undefined;\n cause?: unknown | undefined;\n }) {\n super({\n message: opts.message,\n code: opts.code,\n subsystem: 'plugin',\n severity: 'error',\n recoverable: opts.code === ERROR_CODES.PLUGIN_MISSING_DEPENDENCY,\n context: { plugin: opts.pluginName, ...opts.context },\n cause: opts.cause,\n });\n this.name = 'PluginError';\n this.pluginName = opts.pluginName;\n }\n}\n\n/**\n * Agent runtime errors \u2014 thrown by Agent.run when a non-WrongStackError\n * escapes the inner loop, so callers always see a structured error.\n */\nexport class AgentError extends WrongStackError {\n constructor(opts: {\n message: string;\n code: Extract<\n ErrorCode,\n 'AGENT_ITERATION_LIMIT' | 'AGENT_CONTEXT_OVERFLOW' | 'AGENT_ABORTED' | 'AGENT_RUN_FAILED'\n >;\n recoverable?: boolean | undefined;\n context?: Record<string, unknown> | undefined;\n cause?: unknown | undefined;\n }) {\n super({\n message: opts.message,\n code: opts.code,\n subsystem: 'agent',\n severity: opts.code === ERROR_CODES.AGENT_ABORTED ? 'warning' : 'error',\n recoverable: opts.recoverable ?? opts.code === ERROR_CODES.AGENT_ITERATION_LIMIT,\n context: opts.context,\n cause: opts.cause,\n });\n this.name = 'AgentError';\n }\n}\n\n/**\n * Wrap an arbitrary thrown value into a `WrongStackError` so the caller\n * always gets a structured error. Pass-throughs WrongStackError instances\n * unchanged; raw `Error`s and primitives get an `AGENT_RUN_FAILED` wrapper\n * with the original preserved as `cause`.\n */\nexport function toWrongStackError(\n err: unknown,\n code: Extract<ErrorCode, 'AGENT_RUN_FAILED' | 'AGENT_ABORTED' | 'UNKNOWN'> = ERROR_CODES.AGENT_RUN_FAILED,\n): WrongStackError {\n if (err instanceof WrongStackError) return err;\n const message = toErrorMessage(err);\n return new AgentError({\n message,\n code: code === 'UNKNOWN' ? ERROR_CODES.AGENT_RUN_FAILED : code,\n cause: err,\n });\n}\n\n/**\n * Session storage errors.\n */\nexport class SessionError extends WrongStackError {\n readonly sessionId?: string | undefined;\n\n constructor(opts: {\n message: string;\n code: Extract<ErrorCode, 'SESSION_NOT_FOUND' | 'SESSION_CORRUPTED' | 'SESSION_WRITE_FAILED'>;\n sessionId?: string | undefined;\n context?: Record<string, unknown> | undefined;\n cause?: unknown | undefined;\n }) {\n super({\n message: opts.message,\n code: opts.code,\n subsystem: 'session',\n severity: opts.code === ERROR_CODES.SESSION_WRITE_FAILED ? 'error' : 'warning',\n recoverable: opts.code !== ERROR_CODES.SESSION_CORRUPTED,\n context: { sessionId: opts.sessionId, ...opts.context },\n cause: opts.cause,\n });\n this.name = 'SessionError';\n this.sessionId = opts.sessionId;\n }\n}\n\n/**\n * SDD (Spec-Driven Development) errors \u2014 spec validation, parsing, and\n * state machine violations in the AISpecBuilder, TaskFlow, and TaskTracker.\n */\nexport class SddError extends WrongStackError {\n constructor(opts: {\n message: string;\n code: Extract<\n ErrorCode,\n 'SDD_VALIDATION_FAILED' | 'SDD_PARSE_FAILED' | 'SDD_INVALID_STATE' | 'SDD_NOT_READY'\n >;\n context?: Record<string, unknown> | undefined;\n cause?: unknown | undefined;\n }) {\n super({\n message: opts.message,\n code: opts.code,\n subsystem: 'sdd',\n severity: opts.code === ERROR_CODES.SDD_PARSE_FAILED ? 'warning' : 'error',\n recoverable: opts.code === ERROR_CODES.SDD_NOT_READY,\n context: opts.context,\n cause: opts.cause,\n });\n this.name = 'SddError';\n }\n}\n\n/**\n * File system operation errors.\n */\nexport class FsError extends WrongStackError {\n readonly path?: string | undefined;\n\n constructor(opts: {\n message: string;\n code: Extract<\n ErrorCode,\n 'FS_READ_FAILED' | 'FS_WRITE_FAILED' | 'FS_MKDIR_FAILED' | 'FS_DELETE_FAILED' | 'FS_ATOMIC_WRITE_FAILED'\n >;\n path?: string | undefined;\n context?: Record<string, unknown> | undefined;\n cause?: unknown | undefined;\n }) {\n super({\n message: opts.message,\n code: opts.code,\n subsystem: 'fs',\n severity: 'error',\n recoverable: opts.code !== ERROR_CODES.FS_READ_FAILED,\n context: { path: opts.path, ...opts.context },\n cause: opts.cause,\n });\n this.name = 'FsError';\n this.path = opts.path;\n }\n}\n\n/**\n * HTTP fetch error \u2014 thrown when a network request returns a non-OK status.\n * Carries the response status so {@link classifyToolError} can branch on it\n * (429 \u2192 transient, 404 \u2192 not_found, 401 \u2192 permission) without duck-typing\n * the error via `'response' in err`.\n *\n * P3 #18 (before-release.md): the previous `'response' in err` check caught\n * any Error with a `response` property, including custom errors, proxy\n * objects, or mocked errors in tests. `instanceof FetchError` is reliable.\n *\n * Tools and providers that make HTTP requests and need the executor to\n * classify their failures should throw `new FetchError({ status, message })`\n * instead of a bare `Error` with an ad-hoc `response` field.\n */\nexport class FetchError extends WrongStackError {\n readonly status: number;\n\n constructor(opts: {\n message: string;\n status: number;\n context?: Record<string, unknown> | undefined;\n cause?: unknown | undefined;\n }) {\n super({\n message: opts.message,\n code: ERROR_CODES.VALIDATION_ERROR,\n subsystem: 'general',\n severity: 'error',\n recoverable: opts.status === 429 || opts.status >= 500,\n context: { status: opts.status, ...opts.context },\n cause: opts.cause,\n });\n this.name = 'FetchError';\n this.status = opts.status;\n }\n}\n\n/**\n * Tool input validation error \u2014 thrown when a tool's input fails a validation\n * check that the JSON Schema cannot express (e.g. `old_string === new_string`\n * in edit, or a cross-field invariant). Use this instead of a bare\n * `throw new Error('...validation...')` so {@link classifyToolError} can\n * match on `instanceof` rather than a locale-dependent message substring.\n *\n * P2 #6 (before-release.md): the previous `err.message.includes('validation')`\n * check misclassified any error whose message happened to contain \"validation\"\n * (e.g. a third-party \"input validation timeout\") as a VALIDATION error.\n *\n * Named `ToolValidationError` (not `ValidationError`) to avoid colliding with\n * the existing `ValidationError` interface exported by json-schema-validate.ts\n * (a validation-result shape, not an Error subclass).\n */\nexport class ToolValidationError extends WrongStackError {\n constructor(opts: {\n message: string;\n /** Field path or tool name that failed validation, for diagnostics. */\n field?: string | undefined;\n context?: Record<string, unknown> | undefined;\n cause?: unknown | undefined;\n }) {\n super({\n message: opts.message,\n code: ERROR_CODES.VALIDATION_ERROR,\n subsystem: 'general',\n severity: 'error',\n recoverable: false,\n context: { field: opts.field, ...opts.context },\n cause: opts.cause,\n });\n this.name = 'ToolValidationError';\n }\n}\n\n/**\n * Response / payload parse error \u2014 thrown when an upstream HTTP response,\n * file, or data structure is well-formed at the transport layer (HTTP 200,\n * valid JSON) but is missing required fields or has an unexpected shape.\n *\n * Distinct from `ConfigError(CONFIG_PARSE_FAILED)` (which is specifically\n * for config-file parsing) and `FetchError` (which covers HTTP non-OK\n * responses). `ParseError` fills the gap: the request succeeded but the\n * response body couldn't be interpreted.\n *\n * Common sites: OAuth token responses missing `access_token`, device-code\n * responses missing `device_code`, registry responses with unexpected\n * schemas.\n */\nexport class ParseError extends WrongStackError {\n readonly source?: string | undefined;\n\n constructor(opts: {\n message: string;\n /**\n * What was being parsed \u2014 e.g. `'oauth-token-response'`,\n * `'device-code-response'`. Lets consumers distinguish parse failures\n * from different upstream APIs without parsing the message.\n */\n source?: string | undefined;\n context?: Record<string, unknown> | undefined;\n cause?: unknown | undefined;\n }) {\n super({\n message: opts.message,\n code: ERROR_CODES.PARSE_FAILED,\n subsystem: 'general',\n severity: 'error',\n recoverable: false,\n context: { source: opts.source, ...opts.context },\n cause: opts.cause,\n });\n this.name = 'ParseError';\n this.source = opts.source;\n }\n}\n\n// \u2500\u2500 Type guards \u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\n\nexport function isWrongStackError(err: unknown): err is WrongStackError {\n return err instanceof WrongStackError;\n}\n\nexport function isToolError(err: unknown): err is ToolError {\n return err instanceof ToolError;\n}\n\nexport function isConfigError(err: unknown): err is ConfigError {\n return err instanceof ConfigError;\n}\n\nexport function isPluginError(err: unknown): err is PluginError {\n return err instanceof PluginError;\n}\n\nexport function isSessionError(err: unknown): err is SessionError {\n return err instanceof SessionError;\n}\n\nexport function isAgentError(err: unknown): err is AgentError {\n return err instanceof AgentError;\n}\n\nexport function isFsError(err: unknown): err is FsError {\n return err instanceof FsError;\n}\n\nexport function isToolValidationError(err: unknown): err is ToolValidationError {\n return err instanceof ToolValidationError;\n}\n\nexport function isFetchError(err: unknown): err is FetchError {\n return err instanceof FetchError;\n}\n\nexport function isParseError(err: unknown): err is ParseError {\n return err instanceof ParseError;\n}\n\nexport function isSddError(err: unknown): err is SddError {\n return err instanceof SddError;\n}\n", "import type {\n TaskFilter,\n TaskGraph,\n TaskNode,\n TaskProgress,\n TaskSort,\n} from '../types/task-graph.js';\nimport { computeTaskProgress } from '../types/task-graph.js';\nimport { ERROR_CODES, SddError } from '../types/errors.js';\nimport { toErrorMessage } from '../utils/error.js';\n\nexport interface TaskStore {\n saveGraph(graph: TaskGraph): Promise<void>;\n loadGraph(id: string): Promise<TaskGraph | null>;\n listGraphs(): Promise<{ id: string; title: string; updatedAt: number }[]>;\n deleteGraph(id: string): Promise<void>;\n}\n\nexport interface TaskTrackerOptions {\n store: TaskStore;\n /**\n * Called when an in-the-background persistence (`saveGraph`) rejects.\n * The synchronous TaskTracker methods (addNode/addEdge/updateNodeStatus)\n * fire-and-forget their writes; without this, a failing store silently\n * loses graph mutations. Defaults to a console.warn.\n */\n onPersistError?: (((err: unknown) => void)) | undefined;\n}\n\nexport interface TaskTransition {\n from: TaskNode['status'];\n to: TaskNode['status'];\n timestamp: number;\n reason?: string | undefined;\n}\n\n/** A change notification emitted to `TaskTracker.subscribe` listeners. */\nexport interface TaskTrackerChange {\n type: 'node_added' | 'node_updated' | 'status_changed' | 'node_removed';\n nodeId: string;\n /** For `node_removed` this is the node as it was just before deletion. */\n node: TaskNode;\n transition?: TaskTransition | undefined;\n}\n\nexport type TaskTrackerListener = (change: TaskTrackerChange) => void;\n\nexport class TaskTracker {\n private graph: TaskGraph | null = null;\n private transitions: TaskTransition[] = [];\n private listeners: TaskTrackerListener[] = [];\n\n constructor(private readonly opts: TaskTrackerOptions) {}\n\n /**\n * Subscribe to live task mutations (add / update / status change). Returns an\n * unsubscribe fn. This is the hook the board projector uses to stream a live\n * snapshot \u2014 the tracker was previously fire-and-forget with no observability.\n */\n subscribe(listener: TaskTrackerListener): () => void {\n this.listeners.push(listener);\n return () => {\n const i = this.listeners.indexOf(listener);\n if (i >= 0) this.listeners.splice(i, 1);\n };\n }\n\n private notifyChange(change: TaskTrackerChange): void {\n for (const l of this.listeners) {\n try {\n l(change);\n } catch {\n // A faulty listener must never break a tracker mutation.\n }\n }\n }\n\n /**\n * Attach an existing graph (used by PhaseOrchestrator to associate a tracker\n * with a phase's pre-built task graph without re-creating it).\n */\n setGraph(graph: TaskGraph): void {\n this.graph = graph;\n }\n\n async createGraph(specId: string, title: string): Promise<TaskGraph> {\n this.graph = {\n id: crypto.randomUUID(),\n specId,\n title,\n nodes: new Map(),\n edges: [],\n rootNodes: [],\n createdAt: Date.now(),\n updatedAt: Date.now(),\n };\n await this.opts.store.saveGraph(this.graph);\n return this.graph;\n }\n\n async loadGraph(id: string): Promise<TaskGraph | null> {\n this.graph = await this.opts.store.loadGraph(id);\n return this.graph;\n }\n\n addNode(node: Omit<TaskNode, 'id' | 'createdAt' | 'updatedAt'>): TaskNode {\n if (!this.graph) throw new SddError({\n message: 'No graph loaded',\n code: ERROR_CODES.SDD_INVALID_STATE,\n });\n\n const now = Date.now();\n const newNode: TaskNode = {\n ...node,\n id: crypto.randomUUID(),\n status: node.status ?? 'pending',\n createdAt: now,\n updatedAt: now,\n };\n\n this.graph.nodes.set(newNode.id, newNode);\n\n if (!node.parentId) {\n this.graph.rootNodes.push(newNode.id);\n }\n\n this.graph.updatedAt = now;\n this.persist();\n this.notifyChange({ type: 'node_added', nodeId: newNode.id, node: newNode });\n\n return newNode;\n }\n\n addEdge(from: string, to: string, type: TaskGraph['edges'][0]['type'] = 'depends_on'): void {\n if (!this.graph) throw new SddError({\n message: 'No graph loaded',\n code: ERROR_CODES.SDD_INVALID_STATE,\n });\n\n this.graph.edges.push({\n id: crypto.randomUUID(),\n from,\n to,\n type,\n });\n this.graph.updatedAt = Date.now();\n this.persist();\n }\n\n /**\n * Declare that `taskId` depends on `depId` (a `depends_on` edge `depId \u2192 taskId`),\n * guarding against self-loops, duplicates, missing nodes, and cycles. Returns\n * true if the dependency now holds (added or already present), false if it was\n * rejected (would create a cycle / unknown node). This is the safe entry point\n * for wiring agent-declared `dependsOn` references into the graph.\n */\n addDependency(depId: string, taskId: string): boolean {\n if (!this.graph) return false;\n if (depId === taskId) return false;\n if (!this.graph.nodes.has(depId) || !this.graph.nodes.has(taskId)) return false;\n // Already a blocker \u2014 idempotent success.\n if (this.getBlockers(taskId).includes(depId)) return true;\n // Cycle guard: if `depId` already (transitively) depends on `taskId`, adding\n // `taskId \u2192 depId` would close a loop. Reject rather than deadlock the run.\n if (this.dependsOnTransitively(depId, taskId, new Set())) return false;\n this.addEdge(depId, taskId, 'depends_on');\n return true;\n }\n\n /** True when `taskId` transitively depends on `targetId` (follows depends_on blockers). */\n private dependsOnTransitively(taskId: string, targetId: string, seen: Set<string>): boolean {\n if (taskId === targetId) return true;\n if (seen.has(taskId)) return false;\n seen.add(taskId);\n for (const blocker of this.getBlockers(taskId)) {\n if (this.dependsOnTransitively(blocker, targetId, seen)) return true;\n }\n return false;\n }\n\n /**\n * Merge `patch` into a node's `metadata` (used for per-task model/provider/\n * fallback assignment and the cancel marker). Persists + notifies as a node\n * update. No-op if the node is missing.\n */\n patchMetadata(id: string, patch: Record<string, unknown>): void {\n if (!this.graph) return;\n const node = this.graph.nodes.get(id);\n if (!node) return;\n node.metadata = { ...node.metadata, ...patch };\n node.updatedAt = Date.now();\n this.graph.updatedAt = node.updatedAt;\n this.persist();\n this.notifyChange({ type: 'node_updated', nodeId: id, node });\n }\n\n /**\n * Remove a node and every edge touching it. Intended for deleting a task that\n * has not started yet \u2014 callers must gate on status (do not remove a running\n * task). Dependents simply lose this blocker (re-evaluated by `canStart`).\n * Returns true if a node was removed.\n */\n removeNode(id: string): boolean {\n if (!this.graph) return false;\n const node = this.graph.nodes.get(id);\n if (!node) return false;\n this.graph.nodes.delete(id);\n this.graph.edges = this.graph.edges.filter((e) => e.from !== id && e.to !== id);\n this.graph.rootNodes = this.graph.rootNodes.filter((r) => r !== id);\n // Detach from any parent's children list.\n for (const n of this.graph.nodes.values()) {\n if (n.children?.includes(id)) n.children = n.children.filter((c) => c !== id);\n }\n this.graph.updatedAt = Date.now();\n this.persist();\n this.notifyChange({ type: 'node_removed', nodeId: id, node });\n return true;\n }\n\n updateNodeStatus(id: string, status: TaskNode['status'], reason?: string): void {\n if (!this.graph) throw new SddError({\n message: 'No graph loaded',\n code: ERROR_CODES.SDD_INVALID_STATE,\n });\n\n const node = this.graph.nodes.get(id);\n if (!node) throw new SddError({\n message: `Node ${id} not found`,\n code: ERROR_CODES.SDD_NOT_READY,\n context: { nodeId: id },\n });\n\n const from = node.status;\n const now = Date.now();\n node.status = status;\n node.updatedAt = now;\n\n if (status === 'completed') {\n node.completedAt = now;\n node.startedAt = node.startedAt ?? now; // ensure startedAt is set\n }\n if (status === 'in_progress') {\n node.startedAt = now;\n }\n\n this.transitions.push({ from, to: status, timestamp: now, reason });\n\n // Auto-unblock dependents\n if (status === 'completed') {\n this.unblockDependents(id);\n }\n\n // Auto-block blockers\n if (status === 'in_progress') {\n this.checkAndBlockIfNeeded(id);\n }\n\n this.graph.updatedAt = now;\n this.persist();\n this.notifyChange({\n type: 'status_changed',\n nodeId: id,\n node,\n transition: { from, to: status, timestamp: now, reason },\n });\n }\n\n updateNode(id: string, patch: Partial<Pick<TaskNode, 'title' | 'description' | 'priority' | 'estimateHours' | 'tags' | 'assignee'>>): void {\n if (!this.graph) throw new SddError({\n message: 'No graph loaded',\n code: ERROR_CODES.SDD_INVALID_STATE,\n });\n\n const node = this.graph.nodes.get(id);\n if (!node) throw new SddError({\n message: `Node ${id} not found`,\n code: ERROR_CODES.SDD_NOT_READY,\n context: { nodeId: id },\n });\n\n if (patch.title !== undefined) node.title = patch.title;\n if (patch.description !== undefined) node.description = patch.description;\n if (patch.priority !== undefined) node.priority = patch.priority;\n if (patch.estimateHours !== undefined) node.estimateHours = patch.estimateHours;\n if (patch.tags !== undefined) node.tags = patch.tags;\n if (patch.assignee !== undefined) node.assignee = patch.assignee;\n node.updatedAt = Date.now();\n this.graph.updatedAt = node.updatedAt;\n this.persist();\n this.notifyChange({ type: 'node_updated', nodeId: id, node });\n }\n\n getNode(id: string): TaskNode | undefined {\n return this.graph?.nodes.get(id);\n }\n\n getAllNodes(filter?: TaskFilter, sort?: TaskSort): TaskNode[] {\n if (!this.graph) return [];\n\n let nodes = Array.from(this.graph.nodes.values());\n\n if (filter) {\n nodes = nodes.filter((n) => {\n if (filter.status?.length && !filter.status.includes(n.status)) return false;\n if (filter.priority?.length && !filter.priority.includes(n.priority)) return false;\n if (filter.type?.length && !filter.type.includes(n.type)) return false;\n if (filter.assignee?.length && n.assignee && !filter.assignee.includes(n.assignee))\n return false;\n if (filter.tags?.length && n.tags && !n.tags.some((t) => filter.tags?.includes(t)))\n return false;\n if (filter.specRequirementId && n.specRequirementId !== filter.specRequirementId)\n return false;\n return true;\n });\n }\n\n if (sort) {\n nodes.sort((a, b) => {\n const cmp = compareByField(a, b, sort.field);\n return sort.direction === 'asc' ? cmp : -cmp;\n });\n }\n\n return nodes;\n }\n\n getChildren(parentId: string): TaskNode[] {\n if (!this.graph) return [];\n return Array.from(this.graph.nodes.values()).filter((n) => n.parentId === parentId);\n }\n\n getDependents(taskId: string): string[] {\n if (!this.graph) return [];\n return this.graph.edges\n .filter((e) => e.from === taskId && e.type === 'depends_on')\n .map((e) => e.to);\n }\n\n getBlockers(taskId: string): string[] {\n if (!this.graph) return [];\n return this.graph.edges\n .filter((e) => e.to === taskId && e.type === 'depends_on')\n .map((e) => e.from);\n }\n\n canStart(taskId: string): boolean {\n const blockers = this.getBlockers(taskId);\n return blockers.every((id) => {\n const node = this.graph?.nodes.get(id);\n // A task can start when all blockers are either completed or failed.\n // Failed blockers should not permanently deadlock dependent tasks.\n return node?.status === 'completed' || node?.status === 'failed';\n });\n }\n\n getProgress(): TaskProgress {\n if (!this.graph) {\n return {\n total: 0,\n pending: 0,\n inProgress: 0,\n blocked: 0,\n failed: 0,\n review: 0,\n completed: 0,\n percentComplete: 0,\n estimatedHours: 0,\n actualHours: 0,\n };\n }\n return computeTaskProgress(this.graph);\n }\n\n getTransitions(_taskId?: string): TaskTransition[] {\n return [...this.transitions];\n }\n\n private unblockDependents(completedId: string): void {\n if (!this.graph) return;\n const dependents = this.getDependents(completedId);\n for (const depId of dependents) {\n const dep = this.graph.nodes.get(depId);\n if (dep?.status === 'blocked') {\n // Check if all blockers are now completed\n const remainingBlockers = this.getBlockers(depId);\n const allUnblocked = remainingBlockers.every((id) => {\n const blocker = this.graph?.nodes.get(id);\n return blocker?.status === 'completed' || blocker?.status === 'failed';\n });\n if (allUnblocked) {\n dep.status = 'pending';\n dep.updatedAt = Date.now();\n }\n }\n }\n }\n\n private checkAndBlockIfNeeded(taskId: string): void {\n if (!this.graph) return;\n const blockers = this.getBlockers(taskId);\n const someBlocked = blockers.some((id) => {\n const blocker = this.graph?.nodes.get(id);\n // A task is only blocked by incomplete blockers that haven't failed.\n // Failed tasks should not block their dependents.\n return blocker?.status !== 'completed' && blocker?.status !== 'failed';\n });\n if (someBlocked) {\n const node = this.graph.nodes.get(taskId);\n if (node) {\n node.status = 'blocked';\n node.updatedAt = Date.now();\n }\n }\n }\n\n /**\n * Fire-and-forget persistence with attached error handler.\n * Synchronous mutators (addNode/addEdge/updateNodeStatus) use this to\n * avoid forcing an async cascade through every caller; if the store\n * is missing or throwing, the error is surfaced via onPersistError.\n */\n private persist(): void {\n if (!this.graph) return;\n this.opts.store.saveGraph(this.graph).catch((err) => {\n this.opts.onPersistError\n ? this.opts.onPersistError(err)\n : console.warn(JSON.stringify({\n level: 'warn',\n event: 'task_tracker.save_graph_failed',\n message: toErrorMessage(err),\n timestamp: new Date().toISOString(),\n }));\n });\n }\n}\n\n// Sort comparison helpers\nconst PRIORITY_RANK: Record<TaskNode['priority'], number> = {\n critical: 0,\n high: 1,\n medium: 2,\n low: 3,\n};\nconst STATUS_RANK: Record<TaskNode['status'], number> = {\n in_progress: 0,\n pending: 1,\n review: 2,\n blocked: 3,\n failed: 4,\n completed: 5,\n};\n\nfunction compareByField(a: TaskNode, b: TaskNode, field: TaskSort['field']): number {\n switch (field) {\n case 'priority': return PRIORITY_RANK[a.priority] - PRIORITY_RANK[b.priority];\n case 'status': return STATUS_RANK[a.status] - STATUS_RANK[b.status];\n case 'createdAt': return a.createdAt - b.createdAt;\n case 'updatedAt': return a.updatedAt - b.updatedAt;\n }\n}\n"],
|
|
4
|
+
"sourcesContent": ["import type { TaskGraph } from '../types/task-graph.js';\nimport type { TaskStore } from './task-tracker.js';\n\n/**\n * In-memory task-graph store used by Goal and tests.\n *\n * The store clones the graph container on read/write so callers cannot replace\n * its Maps/arrays behind the store's back. Task nodes themselves intentionally\n * remain shared: TaskTracker owns node mutation and persists after each change.\n */\nexport class DefaultTaskStore implements TaskStore {\n private readonly graphs = new Map<string, TaskGraph>();\n\n async saveGraph(graph: TaskGraph): Promise<void> {\n this.graphs.set(graph.id, this.cloneGraph(graph));\n }\n\n async loadGraph(id: string): Promise<TaskGraph | null> {\n const graph = this.graphs.get(id);\n return graph ? this.cloneGraph(graph) : null;\n }\n\n async listGraphs(): Promise<Array<{ id: string; title: string; updatedAt: number }>> {\n return Array.from(this.graphs.values()).map((graph) => ({\n id: graph.id,\n title: graph.title,\n updatedAt: graph.updatedAt,\n }));\n }\n\n async deleteGraph(id: string): Promise<void> {\n this.graphs.delete(id);\n }\n\n private cloneGraph(graph: TaskGraph): TaskGraph {\n return {\n ...graph,\n nodes: new Map(graph.nodes),\n edges: [...graph.edges],\n rootNodes: [...graph.rootNodes],\n };\n }\n}\n", "export type TaskStatus = 'pending' | 'in_progress' | 'blocked' | 'failed' | 'review' | 'completed';\nexport type TaskPriority = 'critical' | 'high' | 'medium' | 'low';\nexport type TaskType = 'feature' | 'bugfix' | 'refactor' | 'docs' | 'test' | 'chore';\n\nexport interface TaskNode {\n id: string;\n title: string;\n description: string;\n type: TaskType;\n priority: TaskPriority;\n status: TaskStatus;\n assignee?: string | undefined;\n estimateHours?: number | undefined;\n actualHours?: number | undefined;\n tags?: string[] | undefined;\n specRequirementId?: string | undefined;\n parentId?: string | undefined;\n children?: string[] | undefined;\n createdAt: number;\n updatedAt: number;\n startedAt?: number | undefined; // set when status \u2192 in_progress\n completedAt?: number | undefined;\n metadata?: Record<string, unknown>;\n}\n\nexport interface TaskEdge {\n id: string;\n from: string;\n to: string;\n type: 'blocks' | 'depends_on' | 'relates_to' | 'implements';\n weight?: number | undefined;\n}\n\nexport interface TaskGraph {\n id: string;\n specId: string;\n title: string;\n nodes: Map<string, TaskNode>;\n edges: TaskEdge[];\n rootNodes: string[];\n createdAt: number;\n updatedAt: number;\n}\n\nexport interface TaskDependency {\n taskId: string;\n blockedBy: string[];\n blocking: string[];\n}\n\nexport interface TaskAssignment {\n taskId: string;\n assignee: string;\n assignedAt: number;\n}\n\nexport interface TaskProgress {\n total: number;\n pending: number;\n inProgress: number;\n blocked: number;\n failed: number;\n review: number;\n completed: number;\n percentComplete: number;\n estimatedHours: number;\n actualHours: number;\n}\n\nexport interface TaskFilter {\n status?: TaskStatus[] | undefined;\n priority?: TaskPriority[] | undefined;\n type?: TaskType[] | undefined;\n assignee?: string[] | undefined;\n tags?: string[] | undefined;\n specRequirementId?: string | undefined;\n}\n\nexport interface TaskSort {\n field: 'priority' | 'createdAt' | 'updatedAt' | 'status';\n direction: 'asc' | 'desc';\n}\n\nexport interface CriticalPathResult {\n taskIds: string[];\n totalEstimateHours: number;\n bottleneckTasks: string[];\n}\n\nexport function computeTaskProgress(graph: TaskGraph): TaskProgress {\n let completed = 0;\n let pending = 0;\n let inProgress = 0;\n let blocked = 0;\n let failed = 0;\n let review = 0;\n let estimatedHours = 0;\n let actualHours = 0;\n for (const n of graph.nodes.values()) {\n switch (n.status) {\n case 'completed':\n completed++;\n break;\n case 'pending':\n pending++;\n break;\n case 'in_progress':\n inProgress++;\n break;\n case 'blocked':\n blocked++;\n break;\n case 'failed':\n failed++;\n break;\n case 'review':\n review++;\n break;\n }\n estimatedHours += n.estimateHours ?? 0;\n actualHours += n.actualHours ?? 0;\n }\n const total = graph.nodes.size;\n\n return {\n total,\n pending,\n inProgress,\n blocked,\n failed,\n review,\n completed,\n percentComplete: total > 0 ? Math.round((completed / total) * 100) : 0,\n estimatedHours,\n actualHours,\n };\n}\n\nexport function findCriticalPath(graph: TaskGraph): CriticalPathResult {\n const nodes = Array.from(graph.nodes.values());\n const criticalNodes = nodes.filter((n) => n.priority === 'critical');\n const bottleneckTasks = criticalNodes\n .filter((n) => graph.edges.some((e) => e.to === n.id && e.type === 'depends_on'))\n .map((n) => n.id);\n\n const totalEstimateHours = criticalNodes.reduce((sum, n) => sum + (n.estimateHours ?? 0), 0);\n\n return {\n taskIds: criticalNodes.map((n) => n.id),\n totalEstimateHours,\n bottleneckTasks,\n };\n}\n\nexport function topologicalSort(graph: TaskGraph): string[] {\n const visited = new Set<string>();\n const inStack = new Set<string>();\n const result: string[] = [];\n\n function visit(id: string): void {\n // Cycle: callers must detect cycles up-front if they care; we just stop recursing.\n if (inStack.has(id)) return;\n if (visited.has(id)) return;\n if (!graph.nodes.has(id)) return;\n\n visited.add(id);\n inStack.add(id);\n\n for (const edge of graph.edges) {\n if (edge.from === id) visit(edge.to);\n }\n\n inStack.delete(id);\n result.push(id);\n }\n\n for (const rootId of graph.rootNodes) {\n visit(rootId);\n }\n\n return result;\n}\n\nexport type SerializableTaskGraphNodes =\n | TaskNode[]\n | Array<[string, TaskNode]>\n | Record<string, TaskNode>;\n\nexport type SerializableTaskGraph = Omit<TaskGraph, 'nodes'> & {\n nodes: SerializableTaskGraphNodes;\n};\n\nexport type SerializedTaskGraph = Omit<TaskGraph, 'nodes'> & {\n nodes: TaskNode[];\n};\n\nexport function serializeTaskGraph(graph: TaskGraph): SerializedTaskGraph {\n return {\n ...graph,\n nodes: Array.from(graph.nodes.values()),\n };\n}\n\nexport function deserializeTaskGraph(input: SerializableTaskGraph): TaskGraph {\n const nodes = new Map<string, TaskNode>();\n if (Array.isArray(input.nodes)) {\n for (const entry of input.nodes) {\n if (Array.isArray(entry)) nodes.set(entry[0], { ...entry[1], id: entry[1].id || entry[0] });\n else nodes.set(entry.id, entry);\n }\n } else {\n for (const [id, node] of Object.entries(input.nodes)) {\n nodes.set(id, { ...node, id: node.id || id });\n }\n }\n return { ...input, nodes };\n}\n", "/**\n * Converts an unknown error value to a human-readable string.\n * Used in 40+ files across the codebase to normalize error messaging.\n */\nexport function toErrorMessage(err: unknown): string {\n return err instanceof Error ? err.message : String(err);\n}\n", "import { toErrorMessage } from '../utils/index.js';\n\n/**\n * WrongStack error hierarchy.\n *\n * Every error thrown by the framework is a `WrongStackError` with a\n * machine-readable `code`, a `subsystem` tag, and a `severity` level.\n * This lets consumers (CLI, TUI, plugins, tests) branch on structured\n * data instead of parsing error messages.\n */\n\n// \u2500\u2500 Error codes \u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\n\n/**\n * Machine-readable error codes as frozen constants.\n *\n * Use `ERROR_CODES.X` instead of raw string literals for:\n * - IDE autocomplete and compile-time validation\n * - Safe refactoring (rename updates all usages)\n * - Plugin extensibility (extend the object to add custom codes)\n *\n * The `ErrorCode` type is derived from this object, so adding a new\n * code here automatically updates the type without extra changes.\n */\nexport const ERROR_CODES = {\n // Provider\n PROVIDER_RATE_LIMITED: 'PROVIDER_RATE_LIMITED',\n PROVIDER_AUTH_FAILED: 'PROVIDER_AUTH_FAILED',\n PROVIDER_OVERLOADED: 'PROVIDER_OVERLOADED',\n PROVIDER_INVALID_REQUEST: 'PROVIDER_INVALID_REQUEST',\n PROVIDER_SERVER_ERROR: 'PROVIDER_SERVER_ERROR',\n PROVIDER_NETWORK_ERROR: 'PROVIDER_NETWORK_ERROR',\n PROVIDER_CONTEXT_OVERFLOW: 'PROVIDER_CONTEXT_OVERFLOW',\n // Tool\n TOOL_NOT_FOUND: 'TOOL_NOT_FOUND',\n TOOL_PERMISSION_DENIED: 'TOOL_PERMISSION_DENIED',\n TOOL_EXECUTION_FAILED: 'TOOL_EXECUTION_FAILED',\n TOOL_TIMEOUT: 'TOOL_TIMEOUT',\n TOOL_INPUT_INVALID: 'TOOL_INPUT_INVALID',\n // Config\n CONFIG_INVALID: 'CONFIG_INVALID',\n CONFIG_NOT_FOUND: 'CONFIG_NOT_FOUND',\n CONFIG_PARSE_FAILED: 'CONFIG_PARSE_FAILED',\n CONFIG_MIGRATION_NEEDED: 'CONFIG_MIGRATION_NEEDED',\n // Plugin\n PLUGIN_LOAD_FAILED: 'PLUGIN_LOAD_FAILED',\n PLUGIN_API_MISMATCH: 'PLUGIN_API_MISMATCH',\n PLUGIN_MISSING_DEPENDENCY: 'PLUGIN_MISSING_DEPENDENCY',\n // Agent\n AGENT_ITERATION_LIMIT: 'AGENT_ITERATION_LIMIT',\n AGENT_CONTEXT_OVERFLOW: 'AGENT_CONTEXT_OVERFLOW',\n AGENT_ABORTED: 'AGENT_ABORTED',\n AGENT_RUN_FAILED: 'AGENT_RUN_FAILED',\n // Session\n SESSION_NOT_FOUND: 'SESSION_NOT_FOUND',\n SESSION_CORRUPTED: 'SESSION_CORRUPTED',\n SESSION_WRITE_FAILED: 'SESSION_WRITE_FAILED',\n // Container / Registry\n CONTAINER_TOKEN_ALREADY_BOUND: 'CONTAINER_TOKEN_ALREADY_BOUND',\n CONTAINER_TOKEN_NOT_BOUND: 'CONTAINER_TOKEN_NOT_BOUND',\n CONTAINER_CIRCULAR_DEPENDENCY: 'CONTAINER_CIRCULAR_DEPENDENCY',\n REGISTRY_DUPLICATE: 'REGISTRY_DUPLICATE',\n REGISTRY_NOT_FOUND: 'REGISTRY_NOT_FOUND',\n REGISTRY_INVALID: 'REGISTRY_INVALID',\n // File system\n FS_READ_FAILED: 'FS_READ_FAILED',\n FS_WRITE_FAILED: 'FS_WRITE_FAILED',\n FS_MKDIR_FAILED: 'FS_MKDIR_FAILED',\n FS_DELETE_FAILED: 'FS_DELETE_FAILED',\n FS_ATOMIC_WRITE_FAILED: 'FS_ATOMIC_WRITE_FAILED',\n // SDD (Spec-Driven Development)\n SDD_VALIDATION_FAILED: 'SDD_VALIDATION_FAILED',\n SDD_PARSE_FAILED: 'SDD_PARSE_FAILED',\n SDD_INVALID_STATE: 'SDD_INVALID_STATE',\n SDD_NOT_READY: 'SDD_NOT_READY',\n // General\n VALIDATION_ERROR: 'VALIDATION_ERROR',\n PARSE_FAILED: 'PARSE_FAILED',\n UNKNOWN: 'UNKNOWN',\n} as const;\n\n/**\n * Union type derived from `ERROR_CODES`. Using `typeof ERROR_CODES[keyof typeof ERROR_CODES]`\n * instead of a string literal union means TypeScript auto-updates the type whenever\n * a new code is added to `ERROR_CODES` \u2014 no need to keep two lists in sync.\n */\nexport type ErrorCode = (typeof ERROR_CODES)[keyof typeof ERROR_CODES];\n\nexport type ErrorSubsystem =\n | 'provider'\n | 'tool'\n | 'config'\n | 'plugin'\n | 'agent'\n | 'session'\n | 'sdd'\n | 'container'\n | 'fs'\n | 'general';\nexport type ErrorSeverity = 'fatal' | 'error' | 'warning';\n\n// \u2500\u2500 Base error class \u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\n\nexport class WrongStackError extends Error {\n readonly code: ErrorCode;\n readonly subsystem: ErrorSubsystem;\n readonly severity: ErrorSeverity;\n readonly recoverable: boolean;\n readonly context?: Record<string, unknown> | undefined;\n\n constructor(opts: {\n message: string;\n code: ErrorCode;\n subsystem: ErrorSubsystem;\n severity?: ErrorSeverity | undefined;\n recoverable?: boolean | undefined;\n context?: Record<string, unknown> | undefined;\n cause?: unknown | undefined;\n }) {\n super(opts.message, { cause: opts.cause });\n this.name = 'WrongStackError';\n this.code = opts.code;\n this.subsystem = opts.subsystem;\n this.severity = opts.severity ?? 'error';\n this.recoverable = opts.recoverable ?? false;\n this.context = opts.context;\n }\n\n /**\n * Render a one-line user-facing description.\n * Subclasses should override for domain-specific formatting.\n */\n describe(): string {\n const ctx = this.context ? ` ${formatContext(this.context)}` : '';\n return `${this.code}: ${this.message}${ctx}`;\n }\n}\n\nfunction formatContext(ctx: Record<string, unknown>): string {\n const parts = Object.entries(ctx)\n .filter(([, v]) => v !== undefined)\n .slice(0, 3)\n .map(([k, v]) => `${k}=${String(v)}`);\n return parts.length > 0 ? `[${parts.join(' ')}]` : '';\n}\n\n// \u2500\u2500 Specific error classes \u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\n\n/**\n * Tool execution errors \u2014 thrown by ToolExecutor and individual tools.\n */\nexport class ToolError extends WrongStackError {\n readonly toolName: string;\n\n constructor(opts: {\n message: string;\n code: Extract<\n ErrorCode,\n | 'TOOL_NOT_FOUND'\n | 'TOOL_PERMISSION_DENIED'\n | 'TOOL_EXECUTION_FAILED'\n | 'TOOL_TIMEOUT'\n | 'TOOL_INPUT_INVALID'\n >;\n toolName: string;\n recoverable?: boolean | undefined;\n context?: Record<string, unknown> | undefined;\n cause?: unknown | undefined;\n }) {\n super({\n message: opts.message,\n code: opts.code,\n subsystem: 'tool',\n recoverable: opts.recoverable,\n context: { tool: opts.toolName, ...opts.context },\n cause: opts.cause,\n });\n this.name = 'ToolError';\n this.toolName = opts.toolName;\n }\n}\n\n/**\n * Config loading / validation errors.\n */\nexport class ConfigError extends WrongStackError {\n constructor(opts: {\n message: string;\n code: Extract<\n ErrorCode,\n 'CONFIG_INVALID' | 'CONFIG_NOT_FOUND' | 'CONFIG_PARSE_FAILED' | 'CONFIG_MIGRATION_NEEDED'\n >;\n context?: Record<string, unknown> | undefined;\n cause?: unknown | undefined;\n }) {\n super({\n message: opts.message,\n code: opts.code,\n subsystem: 'config',\n severity: 'fatal',\n recoverable: false,\n context: opts.context,\n cause: opts.cause,\n });\n this.name = 'ConfigError';\n }\n}\n\n/**\n * Plugin loading / lifecycle errors.\n */\nexport class PluginError extends WrongStackError {\n readonly pluginName: string;\n\n constructor(opts: {\n message: string;\n code: Extract<\n ErrorCode,\n 'PLUGIN_LOAD_FAILED' | 'PLUGIN_API_MISMATCH' | 'PLUGIN_MISSING_DEPENDENCY'\n >;\n pluginName: string;\n context?: Record<string, unknown> | undefined;\n cause?: unknown | undefined;\n }) {\n super({\n message: opts.message,\n code: opts.code,\n subsystem: 'plugin',\n severity: 'error',\n recoverable: opts.code === ERROR_CODES.PLUGIN_MISSING_DEPENDENCY,\n context: { plugin: opts.pluginName, ...opts.context },\n cause: opts.cause,\n });\n this.name = 'PluginError';\n this.pluginName = opts.pluginName;\n }\n}\n\n/**\n * Agent runtime errors \u2014 thrown by Agent.run when a non-WrongStackError\n * escapes the inner loop, so callers always see a structured error.\n */\nexport class AgentError extends WrongStackError {\n constructor(opts: {\n message: string;\n code: Extract<\n ErrorCode,\n 'AGENT_ITERATION_LIMIT' | 'AGENT_CONTEXT_OVERFLOW' | 'AGENT_ABORTED' | 'AGENT_RUN_FAILED'\n >;\n recoverable?: boolean | undefined;\n context?: Record<string, unknown> | undefined;\n cause?: unknown | undefined;\n }) {\n super({\n message: opts.message,\n code: opts.code,\n subsystem: 'agent',\n severity: opts.code === ERROR_CODES.AGENT_ABORTED ? 'warning' : 'error',\n recoverable: opts.recoverable ?? opts.code === ERROR_CODES.AGENT_ITERATION_LIMIT,\n context: opts.context,\n cause: opts.cause,\n });\n this.name = 'AgentError';\n }\n}\n\n/**\n * Wrap an arbitrary thrown value into a `WrongStackError` so the caller\n * always gets a structured error. Pass-throughs WrongStackError instances\n * unchanged; raw `Error`s and primitives get an `AGENT_RUN_FAILED` wrapper\n * with the original preserved as `cause`.\n */\nexport function toWrongStackError(\n err: unknown,\n code: Extract<ErrorCode, 'AGENT_RUN_FAILED' | 'AGENT_ABORTED' | 'UNKNOWN'> = ERROR_CODES.AGENT_RUN_FAILED,\n): WrongStackError {\n if (err instanceof WrongStackError) return err;\n const message = toErrorMessage(err);\n return new AgentError({\n message,\n code: code === 'UNKNOWN' ? ERROR_CODES.AGENT_RUN_FAILED : code,\n cause: err,\n });\n}\n\n/**\n * Session storage errors.\n */\nexport class SessionError extends WrongStackError {\n readonly sessionId?: string | undefined;\n\n constructor(opts: {\n message: string;\n code: Extract<ErrorCode, 'SESSION_NOT_FOUND' | 'SESSION_CORRUPTED' | 'SESSION_WRITE_FAILED'>;\n sessionId?: string | undefined;\n context?: Record<string, unknown> | undefined;\n cause?: unknown | undefined;\n }) {\n super({\n message: opts.message,\n code: opts.code,\n subsystem: 'session',\n severity: opts.code === ERROR_CODES.SESSION_WRITE_FAILED ? 'error' : 'warning',\n recoverable: opts.code !== ERROR_CODES.SESSION_CORRUPTED,\n context: { sessionId: opts.sessionId, ...opts.context },\n cause: opts.cause,\n });\n this.name = 'SessionError';\n this.sessionId = opts.sessionId;\n }\n}\n\n/**\n * SDD (Spec-Driven Development) errors \u2014 spec validation, parsing, and\n * state machine violations in the AISpecBuilder, TaskFlow, and TaskTracker.\n */\nexport class SddError extends WrongStackError {\n constructor(opts: {\n message: string;\n code: Extract<\n ErrorCode,\n 'SDD_VALIDATION_FAILED' | 'SDD_PARSE_FAILED' | 'SDD_INVALID_STATE' | 'SDD_NOT_READY'\n >;\n context?: Record<string, unknown> | undefined;\n cause?: unknown | undefined;\n }) {\n super({\n message: opts.message,\n code: opts.code,\n subsystem: 'sdd',\n severity: opts.code === ERROR_CODES.SDD_PARSE_FAILED ? 'warning' : 'error',\n recoverable: opts.code === ERROR_CODES.SDD_NOT_READY,\n context: opts.context,\n cause: opts.cause,\n });\n this.name = 'SddError';\n }\n}\n\n/**\n * File system operation errors.\n */\nexport class FsError extends WrongStackError {\n readonly path?: string | undefined;\n\n constructor(opts: {\n message: string;\n code: Extract<\n ErrorCode,\n 'FS_READ_FAILED' | 'FS_WRITE_FAILED' | 'FS_MKDIR_FAILED' | 'FS_DELETE_FAILED' | 'FS_ATOMIC_WRITE_FAILED'\n >;\n path?: string | undefined;\n context?: Record<string, unknown> | undefined;\n cause?: unknown | undefined;\n }) {\n super({\n message: opts.message,\n code: opts.code,\n subsystem: 'fs',\n severity: 'error',\n recoverable: opts.code !== ERROR_CODES.FS_READ_FAILED,\n context: { path: opts.path, ...opts.context },\n cause: opts.cause,\n });\n this.name = 'FsError';\n this.path = opts.path;\n }\n}\n\n/**\n * HTTP fetch error \u2014 thrown when a network request returns a non-OK status.\n * Carries the response status so {@link classifyToolError} can branch on it\n * (429 \u2192 transient, 404 \u2192 not_found, 401 \u2192 permission) without duck-typing\n * the error via `'response' in err`.\n *\n * P3 #18 (before-release.md): the previous `'response' in err` check caught\n * any Error with a `response` property, including custom errors, proxy\n * objects, or mocked errors in tests. `instanceof FetchError` is reliable.\n *\n * Tools and providers that make HTTP requests and need the executor to\n * classify their failures should throw `new FetchError({ status, message })`\n * instead of a bare `Error` with an ad-hoc `response` field.\n */\nexport class FetchError extends WrongStackError {\n readonly status: number;\n\n constructor(opts: {\n message: string;\n status: number;\n context?: Record<string, unknown> | undefined;\n cause?: unknown | undefined;\n }) {\n super({\n message: opts.message,\n code: ERROR_CODES.VALIDATION_ERROR,\n subsystem: 'general',\n severity: 'error',\n recoverable: opts.status === 429 || opts.status >= 500,\n context: { status: opts.status, ...opts.context },\n cause: opts.cause,\n });\n this.name = 'FetchError';\n this.status = opts.status;\n }\n}\n\n/**\n * Tool input validation error \u2014 thrown when a tool's input fails a validation\n * check that the JSON Schema cannot express (e.g. `old_string === new_string`\n * in edit, or a cross-field invariant). Use this instead of a bare\n * `throw new Error('...validation...')` so {@link classifyToolError} can\n * match on `instanceof` rather than a locale-dependent message substring.\n *\n * P2 #6 (before-release.md): the previous `err.message.includes('validation')`\n * check misclassified any error whose message happened to contain \"validation\"\n * (e.g. a third-party \"input validation timeout\") as a VALIDATION error.\n *\n * Named `ToolValidationError` (not `ValidationError`) to avoid colliding with\n * the existing `ValidationError` interface exported by json-schema-validate.ts\n * (a validation-result shape, not an Error subclass).\n */\nexport class ToolValidationError extends WrongStackError {\n constructor(opts: {\n message: string;\n /** Field path or tool name that failed validation, for diagnostics. */\n field?: string | undefined;\n context?: Record<string, unknown> | undefined;\n cause?: unknown | undefined;\n }) {\n super({\n message: opts.message,\n code: ERROR_CODES.VALIDATION_ERROR,\n subsystem: 'general',\n severity: 'error',\n recoverable: false,\n context: { field: opts.field, ...opts.context },\n cause: opts.cause,\n });\n this.name = 'ToolValidationError';\n }\n}\n\n/**\n * Response / payload parse error \u2014 thrown when an upstream HTTP response,\n * file, or data structure is well-formed at the transport layer (HTTP 200,\n * valid JSON) but is missing required fields or has an unexpected shape.\n *\n * Distinct from `ConfigError(CONFIG_PARSE_FAILED)` (which is specifically\n * for config-file parsing) and `FetchError` (which covers HTTP non-OK\n * responses). `ParseError` fills the gap: the request succeeded but the\n * response body couldn't be interpreted.\n *\n * Common sites: OAuth token responses missing `access_token`, device-code\n * responses missing `device_code`, registry responses with unexpected\n * schemas.\n */\nexport class ParseError extends WrongStackError {\n readonly source?: string | undefined;\n\n constructor(opts: {\n message: string;\n /**\n * What was being parsed \u2014 e.g. `'oauth-token-response'`,\n * `'device-code-response'`. Lets consumers distinguish parse failures\n * from different upstream APIs without parsing the message.\n */\n source?: string | undefined;\n context?: Record<string, unknown> | undefined;\n cause?: unknown | undefined;\n }) {\n super({\n message: opts.message,\n code: ERROR_CODES.PARSE_FAILED,\n subsystem: 'general',\n severity: 'error',\n recoverable: false,\n context: { source: opts.source, ...opts.context },\n cause: opts.cause,\n });\n this.name = 'ParseError';\n this.source = opts.source;\n }\n}\n\n// \u2500\u2500 Type guards \u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\n\nexport function isWrongStackError(err: unknown): err is WrongStackError {\n return err instanceof WrongStackError;\n}\n\nexport function isToolError(err: unknown): err is ToolError {\n return err instanceof ToolError;\n}\n\nexport function isConfigError(err: unknown): err is ConfigError {\n return err instanceof ConfigError;\n}\n\nexport function isPluginError(err: unknown): err is PluginError {\n return err instanceof PluginError;\n}\n\nexport function isSessionError(err: unknown): err is SessionError {\n return err instanceof SessionError;\n}\n\nexport function isAgentError(err: unknown): err is AgentError {\n return err instanceof AgentError;\n}\n\nexport function isFsError(err: unknown): err is FsError {\n return err instanceof FsError;\n}\n\nexport function isToolValidationError(err: unknown): err is ToolValidationError {\n return err instanceof ToolValidationError;\n}\n\nexport function isFetchError(err: unknown): err is FetchError {\n return err instanceof FetchError;\n}\n\nexport function isParseError(err: unknown): err is ParseError {\n return err instanceof ParseError;\n}\n\nexport function isSddError(err: unknown): err is SddError {\n return err instanceof SddError;\n}\n", "import type {\n TaskFilter,\n TaskGraph,\n TaskNode,\n TaskProgress,\n TaskSort,\n} from '../types/task-graph.js';\nimport { computeTaskProgress } from '../types/task-graph.js';\nimport { ERROR_CODES, SddError } from '../types/errors.js';\nimport { toErrorMessage } from '../utils/error.js';\n\nexport interface TaskStore {\n saveGraph(graph: TaskGraph): Promise<void>;\n loadGraph(id: string): Promise<TaskGraph | null>;\n listGraphs(): Promise<{ id: string; title: string; updatedAt: number }[]>;\n deleteGraph(id: string): Promise<void>;\n}\n\nexport interface TaskTrackerOptions {\n store: TaskStore;\n /**\n * Called when an in-the-background persistence (`saveGraph`) rejects.\n * The synchronous TaskTracker methods (addNode/addEdge/updateNodeStatus)\n * fire-and-forget their writes; without this, a failing store silently\n * loses graph mutations. Defaults to a console.warn.\n */\n onPersistError?: (((err: unknown) => void)) | undefined;\n}\n\nexport interface TaskTransition {\n from: TaskNode['status'];\n to: TaskNode['status'];\n timestamp: number;\n reason?: string | undefined;\n}\n\n/** A change notification emitted to `TaskTracker.subscribe` listeners. */\nexport interface TaskTrackerChange {\n type: 'node_added' | 'node_updated' | 'status_changed' | 'node_removed';\n nodeId: string;\n /** For `node_removed` this is the node as it was just before deletion. */\n node: TaskNode;\n transition?: TaskTransition | undefined;\n}\n\nexport type TaskTrackerListener = (change: TaskTrackerChange) => void;\n\nexport class TaskTracker {\n private graph: TaskGraph | null = null;\n private transitions: TaskTransition[] = [];\n private listeners: TaskTrackerListener[] = [];\n\n constructor(private readonly opts: TaskTrackerOptions) {}\n\n /**\n * Subscribe to live task mutations (add / update / status change). Returns an\n * unsubscribe fn. This is the hook the board projector uses to stream a live\n * snapshot \u2014 the tracker was previously fire-and-forget with no observability.\n */\n subscribe(listener: TaskTrackerListener): () => void {\n this.listeners.push(listener);\n return () => {\n const i = this.listeners.indexOf(listener);\n if (i >= 0) this.listeners.splice(i, 1);\n };\n }\n\n private notifyChange(change: TaskTrackerChange): void {\n for (const l of this.listeners) {\n try {\n l(change);\n } catch {\n // A faulty listener must never break a tracker mutation.\n }\n }\n }\n\n /**\n * Attach an existing graph (used by PhaseOrchestrator to associate a tracker\n * with a phase's pre-built task graph without re-creating it).\n */\n setGraph(graph: TaskGraph): void {\n this.graph = graph;\n }\n\n async createGraph(specId: string, title: string): Promise<TaskGraph> {\n this.graph = {\n id: crypto.randomUUID(),\n specId,\n title,\n nodes: new Map(),\n edges: [],\n rootNodes: [],\n createdAt: Date.now(),\n updatedAt: Date.now(),\n };\n await this.opts.store.saveGraph(this.graph);\n return this.graph;\n }\n\n async loadGraph(id: string): Promise<TaskGraph | null> {\n this.graph = await this.opts.store.loadGraph(id);\n return this.graph;\n }\n\n addNode(node: Omit<TaskNode, 'id' | 'createdAt' | 'updatedAt'>): TaskNode {\n if (!this.graph) throw new SddError({\n message: 'No graph loaded',\n code: ERROR_CODES.SDD_INVALID_STATE,\n });\n\n const now = Date.now();\n const newNode: TaskNode = {\n ...node,\n id: crypto.randomUUID(),\n status: node.status ?? 'pending',\n createdAt: now,\n updatedAt: now,\n };\n\n this.graph.nodes.set(newNode.id, newNode);\n\n if (!node.parentId) {\n this.graph.rootNodes.push(newNode.id);\n }\n\n this.graph.updatedAt = now;\n this.persist();\n this.notifyChange({ type: 'node_added', nodeId: newNode.id, node: newNode });\n\n return newNode;\n }\n\n addEdge(from: string, to: string, type: TaskGraph['edges'][0]['type'] = 'depends_on'): void {\n if (!this.graph) throw new SddError({\n message: 'No graph loaded',\n code: ERROR_CODES.SDD_INVALID_STATE,\n });\n\n this.graph.edges.push({\n id: crypto.randomUUID(),\n from,\n to,\n type,\n });\n this.graph.updatedAt = Date.now();\n this.persist();\n }\n\n /**\n * Declare that `taskId` depends on `depId` (a `depends_on` edge `depId \u2192 taskId`),\n * guarding against self-loops, duplicates, missing nodes, and cycles. Returns\n * true if the dependency now holds (added or already present), false if it was\n * rejected (would create a cycle / unknown node). This is the safe entry point\n * for wiring agent-declared `dependsOn` references into the graph.\n */\n addDependency(depId: string, taskId: string): boolean {\n if (!this.graph) return false;\n if (depId === taskId) return false;\n if (!this.graph.nodes.has(depId) || !this.graph.nodes.has(taskId)) return false;\n // Already a blocker \u2014 idempotent success.\n if (this.getBlockers(taskId).includes(depId)) return true;\n // Cycle guard: if `depId` already (transitively) depends on `taskId`, adding\n // `taskId \u2192 depId` would close a loop. Reject rather than deadlock the run.\n if (this.dependsOnTransitively(depId, taskId, new Set())) return false;\n this.addEdge(depId, taskId, 'depends_on');\n return true;\n }\n\n /** True when `taskId` transitively depends on `targetId` (follows depends_on blockers). */\n private dependsOnTransitively(taskId: string, targetId: string, seen: Set<string>): boolean {\n if (taskId === targetId) return true;\n if (seen.has(taskId)) return false;\n seen.add(taskId);\n for (const blocker of this.getBlockers(taskId)) {\n if (this.dependsOnTransitively(blocker, targetId, seen)) return true;\n }\n return false;\n }\n\n /**\n * Merge `patch` into a node's `metadata` (used for per-task model/provider/\n * fallback assignment and the cancel marker). Persists + notifies as a node\n * update. No-op if the node is missing.\n */\n patchMetadata(id: string, patch: Record<string, unknown>): void {\n if (!this.graph) return;\n const node = this.graph.nodes.get(id);\n if (!node) return;\n node.metadata = { ...node.metadata, ...patch };\n node.updatedAt = Date.now();\n this.graph.updatedAt = node.updatedAt;\n this.persist();\n this.notifyChange({ type: 'node_updated', nodeId: id, node });\n }\n\n /**\n * Remove a node and every edge touching it. Intended for deleting a task that\n * has not started yet \u2014 callers must gate on status (do not remove a running\n * task). Dependents simply lose this blocker (re-evaluated by `canStart`).\n * Returns true if a node was removed.\n */\n removeNode(id: string): boolean {\n if (!this.graph) return false;\n const node = this.graph.nodes.get(id);\n if (!node) return false;\n this.graph.nodes.delete(id);\n this.graph.edges = this.graph.edges.filter((e) => e.from !== id && e.to !== id);\n this.graph.rootNodes = this.graph.rootNodes.filter((r) => r !== id);\n // Detach from any parent's children list.\n for (const n of this.graph.nodes.values()) {\n if (n.children?.includes(id)) n.children = n.children.filter((c) => c !== id);\n }\n this.graph.updatedAt = Date.now();\n this.persist();\n this.notifyChange({ type: 'node_removed', nodeId: id, node });\n return true;\n }\n\n updateNodeStatus(id: string, status: TaskNode['status'], reason?: string): void {\n if (!this.graph) throw new SddError({\n message: 'No graph loaded',\n code: ERROR_CODES.SDD_INVALID_STATE,\n });\n\n const node = this.graph.nodes.get(id);\n if (!node) throw new SddError({\n message: `Node ${id} not found`,\n code: ERROR_CODES.SDD_NOT_READY,\n context: { nodeId: id },\n });\n\n const from = node.status;\n const now = Date.now();\n node.status = status;\n node.updatedAt = now;\n\n if (status === 'completed') {\n node.completedAt = now;\n node.startedAt = node.startedAt ?? now; // ensure startedAt is set\n }\n if (status === 'in_progress') {\n node.startedAt = now;\n }\n\n this.transitions.push({ from, to: status, timestamp: now, reason });\n\n // Auto-unblock dependents\n if (status === 'completed') {\n this.unblockDependents(id);\n }\n\n // Auto-block blockers\n if (status === 'in_progress') {\n this.checkAndBlockIfNeeded(id);\n }\n\n this.graph.updatedAt = now;\n this.persist();\n this.notifyChange({\n type: 'status_changed',\n nodeId: id,\n node,\n transition: { from, to: status, timestamp: now, reason },\n });\n }\n\n updateNode(id: string, patch: Partial<Pick<TaskNode, 'title' | 'description' | 'priority' | 'estimateHours' | 'tags' | 'assignee'>>): void {\n if (!this.graph) throw new SddError({\n message: 'No graph loaded',\n code: ERROR_CODES.SDD_INVALID_STATE,\n });\n\n const node = this.graph.nodes.get(id);\n if (!node) throw new SddError({\n message: `Node ${id} not found`,\n code: ERROR_CODES.SDD_NOT_READY,\n context: { nodeId: id },\n });\n\n if (patch.title !== undefined) node.title = patch.title;\n if (patch.description !== undefined) node.description = patch.description;\n if (patch.priority !== undefined) node.priority = patch.priority;\n if (patch.estimateHours !== undefined) node.estimateHours = patch.estimateHours;\n if (patch.tags !== undefined) node.tags = patch.tags;\n if (patch.assignee !== undefined) node.assignee = patch.assignee;\n node.updatedAt = Date.now();\n this.graph.updatedAt = node.updatedAt;\n this.persist();\n this.notifyChange({ type: 'node_updated', nodeId: id, node });\n }\n\n getNode(id: string): TaskNode | undefined {\n return this.graph?.nodes.get(id);\n }\n\n getAllNodes(filter?: TaskFilter, sort?: TaskSort): TaskNode[] {\n if (!this.graph) return [];\n\n let nodes = Array.from(this.graph.nodes.values());\n\n if (filter) {\n nodes = nodes.filter((n) => {\n if (filter.status?.length && !filter.status.includes(n.status)) return false;\n if (filter.priority?.length && !filter.priority.includes(n.priority)) return false;\n if (filter.type?.length && !filter.type.includes(n.type)) return false;\n if (filter.assignee?.length && n.assignee && !filter.assignee.includes(n.assignee))\n return false;\n if (filter.tags?.length && n.tags && !n.tags.some((t) => filter.tags?.includes(t)))\n return false;\n if (filter.specRequirementId && n.specRequirementId !== filter.specRequirementId)\n return false;\n return true;\n });\n }\n\n if (sort) {\n nodes.sort((a, b) => {\n const cmp = compareByField(a, b, sort.field);\n return sort.direction === 'asc' ? cmp : -cmp;\n });\n }\n\n return nodes;\n }\n\n getChildren(parentId: string): TaskNode[] {\n if (!this.graph) return [];\n return Array.from(this.graph.nodes.values()).filter((n) => n.parentId === parentId);\n }\n\n getDependents(taskId: string): string[] {\n if (!this.graph) return [];\n return this.graph.edges\n .filter((e) => e.from === taskId && e.type === 'depends_on')\n .map((e) => e.to);\n }\n\n getBlockers(taskId: string): string[] {\n if (!this.graph) return [];\n return this.graph.edges\n .filter((e) => e.to === taskId && e.type === 'depends_on')\n .map((e) => e.from);\n }\n\n canStart(taskId: string): boolean {\n const blockers = this.getBlockers(taskId);\n return blockers.every((id) => {\n const node = this.graph?.nodes.get(id);\n // A task can start when all blockers are either completed or failed.\n // Failed blockers should not permanently deadlock dependent tasks.\n return node?.status === 'completed' || node?.status === 'failed';\n });\n }\n\n getProgress(): TaskProgress {\n if (!this.graph) {\n return {\n total: 0,\n pending: 0,\n inProgress: 0,\n blocked: 0,\n failed: 0,\n review: 0,\n completed: 0,\n percentComplete: 0,\n estimatedHours: 0,\n actualHours: 0,\n };\n }\n return computeTaskProgress(this.graph);\n }\n\n getTransitions(_taskId?: string): TaskTransition[] {\n return [...this.transitions];\n }\n\n private unblockDependents(completedId: string): void {\n if (!this.graph) return;\n const dependents = this.getDependents(completedId);\n for (const depId of dependents) {\n const dep = this.graph.nodes.get(depId);\n if (dep?.status === 'blocked') {\n // Check if all blockers are now completed\n const remainingBlockers = this.getBlockers(depId);\n const allUnblocked = remainingBlockers.every((id) => {\n const blocker = this.graph?.nodes.get(id);\n return blocker?.status === 'completed' || blocker?.status === 'failed';\n });\n if (allUnblocked) {\n dep.status = 'pending';\n dep.updatedAt = Date.now();\n }\n }\n }\n }\n\n private checkAndBlockIfNeeded(taskId: string): void {\n if (!this.graph) return;\n const blockers = this.getBlockers(taskId);\n const someBlocked = blockers.some((id) => {\n const blocker = this.graph?.nodes.get(id);\n // A task is only blocked by incomplete blockers that haven't failed.\n // Failed tasks should not block their dependents.\n return blocker?.status !== 'completed' && blocker?.status !== 'failed';\n });\n if (someBlocked) {\n const node = this.graph.nodes.get(taskId);\n if (node) {\n node.status = 'blocked';\n node.updatedAt = Date.now();\n }\n }\n }\n\n /**\n * Fire-and-forget persistence with attached error handler.\n * Synchronous mutators (addNode/addEdge/updateNodeStatus) use this to\n * avoid forcing an async cascade through every caller; if the store\n * is missing or throwing, the error is surfaced via onPersistError.\n */\n private persist(): void {\n if (!this.graph) return;\n this.opts.store.saveGraph(this.graph).catch((err) => {\n this.opts.onPersistError\n ? this.opts.onPersistError(err)\n : console.warn(JSON.stringify({\n level: 'warn',\n event: 'task_tracker.save_graph_failed',\n message: toErrorMessage(err),\n timestamp: new Date().toISOString(),\n }));\n });\n }\n}\n\n// Sort comparison helpers\nconst PRIORITY_RANK: Record<TaskNode['priority'], number> = {\n critical: 0,\n high: 1,\n medium: 2,\n low: 3,\n};\nconst STATUS_RANK: Record<TaskNode['status'], number> = {\n in_progress: 0,\n pending: 1,\n review: 2,\n blocked: 3,\n failed: 4,\n completed: 5,\n};\n\nfunction compareByField(a: TaskNode, b: TaskNode, field: TaskSort['field']): number {\n switch (field) {\n case 'priority': return PRIORITY_RANK[a.priority] - PRIORITY_RANK[b.priority];\n case 'status': return STATUS_RANK[a.status] - STATUS_RANK[b.status];\n case 'createdAt': return a.createdAt - b.createdAt;\n case 'updatedAt': return a.updatedAt - b.updatedAt;\n }\n}\n"],
|
|
5
5
|
"mappings": "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",
|
|
6
6
|
"names": []
|
|
7
7
|
}
|
|
@@ -1,7 +1,7 @@
|
|
|
1
1
|
import type { TaskGraph } from '../types/task-graph.js';
|
|
2
2
|
import type { TaskStore } from './task-tracker.js';
|
|
3
3
|
/**
|
|
4
|
-
* In-memory task-graph store used by
|
|
4
|
+
* In-memory task-graph store used by Goal and tests.
|
|
5
5
|
*
|
|
6
6
|
* The store clones the graph container on read/write so callers cannot replace
|
|
7
7
|
* its Maps/arrays behind the store's back. Task nodes themselves intentionally
|
|
@@ -1,3 +1,4 @@
|
|
|
1
|
+
import type { FallbackProfileManager } from '../core/fallback-profile-manager.js';
|
|
1
2
|
import type { CouncilLLMCaller, CouncilOption, CouncilProfileConfig, CouncilResult } from '../types/council.js';
|
|
2
3
|
import type { Tool } from '../types/tool.js';
|
|
3
4
|
import type { CouncilPersonaRegistry } from '../execution/council-personas.js';
|
|
@@ -19,6 +20,8 @@ export interface CreateCouncilToolOptions {
|
|
|
19
20
|
defaultProfile?: string | undefined;
|
|
20
21
|
maxConcurrency?: number | undefined;
|
|
21
22
|
refusalOptionId?: string | undefined;
|
|
23
|
+
/** Shared live FallbackProfileManager. */
|
|
24
|
+
fallbackProfileManager?: FallbackProfileManager | undefined;
|
|
22
25
|
}
|
|
23
26
|
/** Create a read-only, bounded agent-callable Council tool. */
|
|
24
27
|
export declare function createCouncilTool(opts: CreateCouncilToolOptions): Tool<CouncilToolInput, CouncilResult>;
|
|
@@ -1 +1 @@
|
|
|
1
|
-
{"version":3,"file":"council-tool.d.ts","sourceRoot":"","sources":["../../src/tools/council-tool.ts"],"names":[],"mappings":"AACA,OAAO,KAAK,EACV,gBAAgB,EAChB,aAAa,EACb,oBAAoB,EAEpB,aAAa,EACd,MAAM,qBAAqB,CAAC;AAC7B,OAAO,KAAK,EAAc,IAAI,EAAE,MAAM,kBAAkB,CAAC;AACzD,OAAO,KAAK,EAAE,sBAAsB,EAAE,MAAM,kCAAkC,CAAC;AAC/E,OAAO,KAAK,EAAE,sBAAsB,EAAE,MAAM,kCAAkC,CAAC;AAE/E,eAAO,MAAM,iBAAiB,YAAY,CAAC;AAC3C,eAAO,MAAM,wBAAwB,KAAK,CAAC;AAC3C,eAAO,MAAM,0BAA0B,QAAS,CAAC;AACjD,eAAO,MAAM,yBAAyB,QAAS,CAAC;AAEhD,MAAM,WAAW,gBAAgB;IAC/B,QAAQ,EAAE,MAAM,CAAC;IACjB,OAAO,CAAC,EAAE,MAAM,GAAG,SAAS,CAAC;IAC7B,OAAO,CAAC,EAAE,aAAa,EAAE,GAAG,SAAS,CAAC;IACtC,OAAO,CAAC,EAAE,MAAM,GAAG,oBAAoB,GAAG,SAAS,CAAC;CACrD;AAED,MAAM,WAAW,wBAAwB;IACvC,MAAM,EAAE,gBAAgB,CAAC;IACzB,QAAQ,CAAC,EAAE,sBAAsB,GAAG,SAAS,CAAC;IAC9C,QAAQ,CAAC,EAAE,sBAAsB,GAAG,SAAS,CAAC;IAC9C,cAAc,CAAC,EAAE,MAAM,GAAG,SAAS,CAAC;IACpC,cAAc,CAAC,EAAE,MAAM,GAAG,SAAS,CAAC;IACpC,eAAe,CAAC,EAAE,MAAM,GAAG,SAAS,CAAC;
|
|
1
|
+
{"version":3,"file":"council-tool.d.ts","sourceRoot":"","sources":["../../src/tools/council-tool.ts"],"names":[],"mappings":"AACA,OAAO,KAAK,EAAE,sBAAsB,EAAE,MAAM,qCAAqC,CAAC;AAClF,OAAO,KAAK,EACV,gBAAgB,EAChB,aAAa,EACb,oBAAoB,EAEpB,aAAa,EACd,MAAM,qBAAqB,CAAC;AAC7B,OAAO,KAAK,EAAc,IAAI,EAAE,MAAM,kBAAkB,CAAC;AACzD,OAAO,KAAK,EAAE,sBAAsB,EAAE,MAAM,kCAAkC,CAAC;AAC/E,OAAO,KAAK,EAAE,sBAAsB,EAAE,MAAM,kCAAkC,CAAC;AAE/E,eAAO,MAAM,iBAAiB,YAAY,CAAC;AAC3C,eAAO,MAAM,wBAAwB,KAAK,CAAC;AAC3C,eAAO,MAAM,0BAA0B,QAAS,CAAC;AACjD,eAAO,MAAM,yBAAyB,QAAS,CAAC;AAEhD,MAAM,WAAW,gBAAgB;IAC/B,QAAQ,EAAE,MAAM,CAAC;IACjB,OAAO,CAAC,EAAE,MAAM,GAAG,SAAS,CAAC;IAC7B,OAAO,CAAC,EAAE,aAAa,EAAE,GAAG,SAAS,CAAC;IACtC,OAAO,CAAC,EAAE,MAAM,GAAG,oBAAoB,GAAG,SAAS,CAAC;CACrD;AAED,MAAM,WAAW,wBAAwB;IACvC,MAAM,EAAE,gBAAgB,CAAC;IACzB,QAAQ,CAAC,EAAE,sBAAsB,GAAG,SAAS,CAAC;IAC9C,QAAQ,CAAC,EAAE,sBAAsB,GAAG,SAAS,CAAC;IAC9C,cAAc,CAAC,EAAE,MAAM,GAAG,SAAS,CAAC;IACpC,cAAc,CAAC,EAAE,MAAM,GAAG,SAAS,CAAC;IACpC,eAAe,CAAC,EAAE,MAAM,GAAG,SAAS,CAAC;IACrC,0CAA0C;IAC1C,sBAAsB,CAAC,EAAE,sBAAsB,GAAG,SAAS,CAAC;CAC7D;AAuCD,+DAA+D;AAC/D,wBAAgB,iBAAiB,CAC/B,IAAI,EAAE,wBAAwB,GAC7B,IAAI,CAAC,gBAAgB,EAAE,aAAa,CAAC,CAiCvC"}
|