@wrongstack/core 0.281.3 → 0.282.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.
Files changed (55) hide show
  1. package/dist/{agent-subagent-runner-DyOSK2Wy.d.ts → agent-subagent-runner-Dksf0QVU.d.ts} +15 -4
  2. package/dist/{config-CN-vdDEI.d.ts → config-BCAEJicb.d.ts} +33 -1
  3. package/dist/coordination/index.d.ts +147 -48
  4. package/dist/coordination/index.js +1244 -274
  5. package/dist/coordination/index.js.map +1 -1
  6. package/dist/defaults/index.d.ts +18 -18
  7. package/dist/defaults/index.js +980 -166
  8. package/dist/defaults/index.js.map +1 -1
  9. package/dist/{director-state-BfeCUbmk.d.ts → director-state-B_GPa78Q.d.ts} +14 -0
  10. package/dist/{events-C5hLU0AT.d.ts → events-CovDylaH.d.ts} +2 -1
  11. package/dist/execution/index.d.ts +10 -10
  12. package/dist/execution/index.js +69 -3
  13. package/dist/execution/index.js.map +1 -1
  14. package/dist/extension/index.d.ts +4 -4
  15. package/dist/{global-mailbox-CHM1QkCi.d.ts → global-mailbox-CNfgvRw3.d.ts} +1 -1
  16. package/dist/{goal-store-BLGZq16t.d.ts → goal-store-CBd749M4.d.ts} +1 -1
  17. package/dist/hq/index.d.ts +4 -4
  18. package/dist/{index-C1E-_71T.d.ts → index-D5HB7WkV.d.ts} +4 -3
  19. package/dist/index.d.ts +3005 -2704
  20. package/dist/index.js +51862 -49927
  21. package/dist/index.js.map +1 -1
  22. package/dist/infrastructure/index.d.ts +3 -3
  23. package/dist/kernel/index.d.ts +7 -7
  24. package/dist/kernel/index.js.map +1 -1
  25. package/dist/{mcp-servers-EKRAcJDi.d.ts → mcp-servers-DJYwZXyH.d.ts} +1 -1
  26. package/dist/models/index.d.ts +2 -2
  27. package/dist/models/index.js +100 -14
  28. package/dist/models/index.js.map +1 -1
  29. package/dist/{multi-agent-coordinator-IpHCuHUa.d.ts → multi-agent-coordinator-4DC31QWu.d.ts} +1 -1
  30. package/dist/{null-fleet-bus-ZBkKGR9j.d.ts → null-fleet-bus-DuvA8PIR.d.ts} +74 -6
  31. package/dist/observability/index.d.ts +1 -1
  32. package/dist/{parallel-eternal-engine-Cc2CNgmv.d.ts → parallel-eternal-engine-BwcA0bAt.d.ts} +4 -4
  33. package/dist/{pipeline-E7_jqGyV.d.ts → pipeline-DM-CPTUs.d.ts} +1 -1
  34. package/dist/{provider-model-resolve-KgIdiEQ6.d.ts → provider-model-resolve-hNUbewMd.d.ts} +1 -1
  35. package/dist/{provider-runner-DxWXNHL1.d.ts → provider-runner-Bz4GyUqo.d.ts} +1 -1
  36. package/dist/sdd/index.d.ts +6 -6
  37. package/dist/sdd/index.js +76 -2
  38. package/dist/sdd/index.js.map +1 -1
  39. package/dist/{session-event-bridge-vA2fLV58.d.ts → session-event-bridge-Bkp7ORfc.d.ts} +2 -2
  40. package/dist/skills/index.d.ts +84 -84
  41. package/dist/storage/index.d.ts +168 -168
  42. package/dist/storage/index.js +19 -7
  43. package/dist/storage/index.js.map +1 -1
  44. package/dist/{todos-checkpoint-B1QVkoa8.d.ts → todos-checkpoint-addCdQ9f.d.ts} +2 -2
  45. package/dist/{tool-executor-BWtYwuPI.d.ts → tool-executor-B3spV_Q6.d.ts} +7 -7
  46. package/dist/tools/index.d.ts +1 -1
  47. package/dist/types/index.d.ts +33 -33
  48. package/dist/types/index.js.map +1 -1
  49. package/dist/utils/index.d.ts +113 -113
  50. package/dist/{worktree-manager-C6CIilTT.d.ts → worktree-manager-BBXdJq-Y.d.ts} +1 -1
  51. package/instructions/agents/reviewer.md +25 -0
  52. package/instructions/agents/verifier.md +24 -0
  53. package/instructions/coordination/director-preamble.md +24 -2
  54. package/instructions/coordination/subagent-baseline.md +8 -1
  55. package/package.json +1 -1
@@ -46,12 +46,12 @@ interface SessionEventBridge {
46
46
  allows(type: SessionEvent['type']): boolean;
47
47
  }
48
48
  /** Core events that are always written regardless of auditLevel. */
49
- declare const CORE_RECONSTRUCT_EVENTS: Set<"error" | "tool_use" | "tool_result" | "session_start" | "session_resumed" | "user_input" | "llm_request" | "llm_response" | "compaction" | "session_end" | "mode_changed" | "task_created" | "task_updated" | "task_completed" | "task_failed" | "agent_spawned" | "agent_stopped" | "agent_error" | "spec_parsed" | "spec_analyzed" | "skill_activated" | "skill_deactivated" | "tool_call_start" | "tool_call_end" | "tool_progress" | "message_truncated" | "provider_retry" | "provider_error" | "checkpoint" | "file_snapshot" | "rewound" | "in_flight_start" | "in_flight_end" | "side_effect">;
49
+ declare const CORE_RECONSTRUCT_EVENTS: Set<"tool_use" | "tool_result" | "error" | "session_start" | "session_resumed" | "user_input" | "llm_request" | "llm_response" | "compaction" | "session_end" | "mode_changed" | "task_created" | "task_updated" | "task_completed" | "task_failed" | "agent_spawned" | "agent_stopped" | "agent_error" | "spec_parsed" | "spec_analyzed" | "skill_activated" | "skill_deactivated" | "tool_call_start" | "tool_call_end" | "tool_progress" | "message_truncated" | "provider_retry" | "provider_error" | "checkpoint" | "file_snapshot" | "rewound" | "in_flight_start" | "in_flight_end" | "side_effect">;
50
50
  /**
51
51
  * Events that are considered "standard" audit detail.
52
52
  * These are lightweight and high-value for forensics.
53
53
  */
54
- declare const STANDARD_AUDIT_EVENTS: Set<"error" | "tool_use" | "tool_result" | "session_start" | "session_resumed" | "user_input" | "llm_request" | "llm_response" | "compaction" | "session_end" | "mode_changed" | "task_created" | "task_updated" | "task_completed" | "task_failed" | "agent_spawned" | "agent_stopped" | "agent_error" | "spec_parsed" | "spec_analyzed" | "skill_activated" | "skill_deactivated" | "tool_call_start" | "tool_call_end" | "tool_progress" | "message_truncated" | "provider_retry" | "provider_error" | "checkpoint" | "file_snapshot" | "rewound" | "in_flight_start" | "in_flight_end" | "side_effect">;
54
+ declare const STANDARD_AUDIT_EVENTS: Set<"tool_use" | "tool_result" | "error" | "session_start" | "session_resumed" | "user_input" | "llm_request" | "llm_response" | "compaction" | "session_end" | "mode_changed" | "task_created" | "task_updated" | "task_completed" | "task_failed" | "agent_spawned" | "agent_stopped" | "agent_error" | "spec_parsed" | "spec_analyzed" | "skill_activated" | "skill_deactivated" | "tool_call_start" | "tool_call_end" | "tool_progress" | "message_truncated" | "provider_retry" | "provider_error" | "checkpoint" | "file_snapshot" | "rewound" | "in_flight_start" | "in_flight_end" | "side_effect">;
55
55
  /**
56
56
  * Create a safe, audit-level-aware bridge around a SessionWriter.
57
57
  *
@@ -1,5 +1,89 @@
1
1
  import { b as SkillEntry, S as SkillLoader } from '../skill-DHniprNl.js';
2
2
 
3
+ /**
4
+ * Skill registry adapter contract.
5
+ *
6
+ * A registry is a searchable catalog of skills that resolves to a concrete
7
+ * install target (a GitHub `user/repo[@ref]`). Two adapters ship out of the
8
+ * box:
9
+ *
10
+ * - `githubDirectAdapter` — no search; `user/repo` is typed directly. This
11
+ * is the original pre-registry install path.
12
+ * - `skillsShAdapter` — searches the skills.sh marketplace
13
+ * (https://skills.sh/api/skills), which indexes
14
+ * 34k+ skills from 2.8k+ repos and computes a
15
+ * per-skill security score (0–100).
16
+ *
17
+ * The adapter layer keeps the installer registry-agnostic: it asks each
18
+ * adapter to resolve a `<adapterId>:<registryId>` ref to a `user/repo@ref`
19
+ * and reuses the existing GitHub tarball path. New registries (an internal
20
+ * company hub, ags, …) are added by implementing this interface and passing
21
+ * them to the `SkillInstaller`.
22
+ */
23
+ /**
24
+ * One hit from a registry search. Fields are optional where the underlying
25
+ * registry doesn't guarantee them — every adapter normalizes to this shape.
26
+ */
27
+ interface RegistrySkillSummary {
28
+ /** Registry-native id (used as `<adapterId>:<id>` in `/skill-install`). */
29
+ id: string;
30
+ /** Skill name (kebab-case, as it will appear once installed). */
31
+ name: string;
32
+ /** Short description / trigger line. */
33
+ description: string;
34
+ /** Author / owner (often the GitHub owner). */
35
+ author?: string | undefined;
36
+ /** Install count, if the registry reports it. */
37
+ installs?: number | undefined;
38
+ /** Star count, if the registry reports it. */
39
+ stars?: number | undefined;
40
+ /**
41
+ * Security score 0–100 (skills.sh computes this; ags uses the same scale).
42
+ * Lower = riskier. Below 30 the install command prompts for confirmation.
43
+ */
44
+ securityScore?: number | undefined;
45
+ /** ISO timestamp of the skill's last update, if known. */
46
+ updatedAt?: string | undefined;
47
+ /**
48
+ * The `user/repo[@ref]` the installer passes to `downloadGitHubTarball`.
49
+ * Always present for real registry hits — it's the whole point of resolving.
50
+ */
51
+ installRef: string;
52
+ }
53
+ interface RegistrySearchOptions {
54
+ /** 1-indexed page (default 1). */
55
+ page?: number | undefined;
56
+ /** Page size (default 20; registries may cap this). */
57
+ pageSize?: number | undefined;
58
+ }
59
+ interface RegistrySearchResult {
60
+ /** Which adapter produced these results. */
61
+ adapterId: string;
62
+ results: RegistrySkillSummary[];
63
+ /** True when the registry indicates more pages exist. */
64
+ hasMore?: boolean | undefined;
65
+ }
66
+ /**
67
+ * A searchable skill catalog that resolves to a GitHub install target.
68
+ *
69
+ * `search` is optional in spirit (the github-direct adapter doesn't search),
70
+ * but the interface requires it so callers can fan out uniformly — adapters
71
+ * that can't search simply return `[]`.
72
+ */
73
+ interface SkillRegistryAdapter {
74
+ /** Stable id used in `<adapterId>:<registryId>` refs (e.g. `'skills.sh'`). */
75
+ readonly id: string;
76
+ /** Human label for UI (e.g. `'skills.sh'`). */
77
+ readonly displayName: string;
78
+ /** Search the catalog. Return `[]` if the adapter doesn't support search. */
79
+ search(query: string, opts?: RegistrySearchOptions): Promise<RegistrySearchResult>;
80
+ /**
81
+ * Resolve a registry-native id to a `user/repo[@ref]` install ref. Should
82
+ * validate the id shape and throw on an id this adapter can't resolve.
83
+ */
84
+ resolveInstallRef(registryId: string): string;
85
+ }
86
+
3
87
  /**
4
88
  * Well-known foreign coding-agent skill directories. All follow the
5
89
  * agentskills.io `SKILL.md` format, so the same loader reads them — this just
@@ -264,90 +348,6 @@ declare class SkillManifestStore {
264
348
  invalidateCache(): void;
265
349
  }
266
350
 
267
- /**
268
- * Skill registry adapter contract.
269
- *
270
- * A registry is a searchable catalog of skills that resolves to a concrete
271
- * install target (a GitHub `user/repo[@ref]`). Two adapters ship out of the
272
- * box:
273
- *
274
- * - `githubDirectAdapter` — no search; `user/repo` is typed directly. This
275
- * is the original pre-registry install path.
276
- * - `skillsShAdapter` — searches the skills.sh marketplace
277
- * (https://skills.sh/api/skills), which indexes
278
- * 34k+ skills from 2.8k+ repos and computes a
279
- * per-skill security score (0–100).
280
- *
281
- * The adapter layer keeps the installer registry-agnostic: it asks each
282
- * adapter to resolve a `<adapterId>:<registryId>` ref to a `user/repo@ref`
283
- * and reuses the existing GitHub tarball path. New registries (an internal
284
- * company hub, ags, …) are added by implementing this interface and passing
285
- * them to the `SkillInstaller`.
286
- */
287
- /**
288
- * One hit from a registry search. Fields are optional where the underlying
289
- * registry doesn't guarantee them — every adapter normalizes to this shape.
290
- */
291
- interface RegistrySkillSummary {
292
- /** Registry-native id (used as `<adapterId>:<id>` in `/skill-install`). */
293
- id: string;
294
- /** Skill name (kebab-case, as it will appear once installed). */
295
- name: string;
296
- /** Short description / trigger line. */
297
- description: string;
298
- /** Author / owner (often the GitHub owner). */
299
- author?: string | undefined;
300
- /** Install count, if the registry reports it. */
301
- installs?: number | undefined;
302
- /** Star count, if the registry reports it. */
303
- stars?: number | undefined;
304
- /**
305
- * Security score 0–100 (skills.sh computes this; ags uses the same scale).
306
- * Lower = riskier. Below 30 the install command prompts for confirmation.
307
- */
308
- securityScore?: number | undefined;
309
- /** ISO timestamp of the skill's last update, if known. */
310
- updatedAt?: string | undefined;
311
- /**
312
- * The `user/repo[@ref]` the installer passes to `downloadGitHubTarball`.
313
- * Always present for real registry hits — it's the whole point of resolving.
314
- */
315
- installRef: string;
316
- }
317
- interface RegistrySearchOptions {
318
- /** 1-indexed page (default 1). */
319
- page?: number | undefined;
320
- /** Page size (default 20; registries may cap this). */
321
- pageSize?: number | undefined;
322
- }
323
- interface RegistrySearchResult {
324
- /** Which adapter produced these results. */
325
- adapterId: string;
326
- results: RegistrySkillSummary[];
327
- /** True when the registry indicates more pages exist. */
328
- hasMore?: boolean | undefined;
329
- }
330
- /**
331
- * A searchable skill catalog that resolves to a GitHub install target.
332
- *
333
- * `search` is optional in spirit (the github-direct adapter doesn't search),
334
- * but the interface requires it so callers can fan out uniformly — adapters
335
- * that can't search simply return `[]`.
336
- */
337
- interface SkillRegistryAdapter {
338
- /** Stable id used in `<adapterId>:<registryId>` refs (e.g. `'skills.sh'`). */
339
- readonly id: string;
340
- /** Human label for UI (e.g. `'skills.sh'`). */
341
- readonly displayName: string;
342
- /** Search the catalog. Return `[]` if the adapter doesn't support search. */
343
- search(query: string, opts?: RegistrySearchOptions): Promise<RegistrySearchResult>;
344
- /**
345
- * Resolve a registry-native id to a `user/repo[@ref]` install ref. Should
346
- * validate the id shape and throw on an id this adapter can't resolve.
347
- */
348
- resolveInstallRef(registryId: string): string;
349
- }
350
-
351
351
  /**
352
352
  * GitHub-direct registry adapter.
353
353
  *
@@ -1,28 +1,186 @@
1
- import { M as MemoryBackend, j as FileMemoryBackendOptions } from '../todos-checkpoint-B1QVkoa8.js';
2
- export { A as AbandonedSession, a as AttachmentStoreOptions, C as ConfigLoaderOptions, b as ConfigMigration, c as ConfigMigrationError, d as ConfigSource, D as DEFAULT_CONFIG_MIGRATIONS, e as DefaultAttachmentStore, f as DefaultConfigLoader, g as DefaultConfigStore, h as DefaultMemoryStore, i as DefaultSessionStore, F as FileMemoryBackend, k as MemoryStoreOptions, l as MigrationContext, m as MigrationResult, P as PersistedQueueItem, n as PlanFile, o as PlanItem, p as PlanTemplate, Q as QueueStore, R as RecoveryLock, q as RecoveryLockOptions, S as SessionAnalyzer, r as SessionStoreOptions, T as TodosCheckpointFile, s as addPlanItem, t as attachPlanCheckpoint, u as attachTodosCheckpoint, v as clearPlan, w as deriveTodosFromPlanItem, x as emptyPlan, y as formatPlan, z as formatPlanTemplates, B as getPlanTemplate, E as listPlanTemplates, G as loadPlan, H as loadTodosCheckpoint, I as mutatePlan, J as parseEntries, K as removePlanItem, L as runConfigMigrations, N as savePlan, O as saveTodosCheckpoint, U as setPlanItemStatus } from '../todos-checkpoint-B1QVkoa8.js';
3
- import { M as MemoryScope, b as MemoryEntry, c as MemoryStore, E as EventBus } from '../events-C5hLU0AT.js';
4
- import { i as AgentExtension, k as AfterRunHook } from '../index-C1E-_71T.js';
5
- import { P as Provider, c as Request, e as Response, S as SessionEvent, D as CompletedWorkEvidence } from '../tool-LVSLiE1s.js';
6
- import { P as ProviderConfig, a2 as SyncCategory, j as SyncConfig } from '../config-CN-vdDEI.js';
1
+ import { M as MemoryBackend, j as FileMemoryBackendOptions } from '../todos-checkpoint-addCdQ9f.js';
2
+ export { A as AbandonedSession, a as AttachmentStoreOptions, C as ConfigLoaderOptions, b as ConfigMigration, c as ConfigMigrationError, d as ConfigSource, D as DEFAULT_CONFIG_MIGRATIONS, e as DefaultAttachmentStore, f as DefaultConfigLoader, g as DefaultConfigStore, h as DefaultMemoryStore, i as DefaultSessionStore, F as FileMemoryBackend, k as MemoryStoreOptions, l as MigrationContext, m as MigrationResult, P as PersistedQueueItem, n as PlanFile, o as PlanItem, p as PlanTemplate, Q as QueueStore, R as RecoveryLock, q as RecoveryLockOptions, S as SessionAnalyzer, r as SessionStoreOptions, T as TodosCheckpointFile, s as addPlanItem, t as attachPlanCheckpoint, u as attachTodosCheckpoint, v as clearPlan, w as deriveTodosFromPlanItem, x as emptyPlan, y as formatPlan, z as formatPlanTemplates, B as getPlanTemplate, E as listPlanTemplates, G as loadPlan, H as loadTodosCheckpoint, I as mutatePlan, J as parseEntries, K as removePlanItem, L as runConfigMigrations, N as savePlan, O as saveTodosCheckpoint, U as setPlanItemStatus } from '../todos-checkpoint-addCdQ9f.js';
3
+ import { E as EventBus, M as MemoryScope, b as MemoryEntry, c as MemoryStore } from '../events-CovDylaH.js';
4
+ import { i as AgentExtension, k as AfterRunHook } from '../index-D5HB7WkV.js';
5
+ import { c as Request, e as Response, P as Provider, S as SessionEvent, D as CompletedWorkEvidence } from '../tool-LVSLiE1s.js';
6
+ import { P as ProviderConfig, a2 as SyncCategory, j as SyncConfig } from '../config-BCAEJicb.js';
7
7
  import { S as SecretVault } from '../secret-vault-BAKpgFw_.js';
8
8
  export { D as DefaultSessionReader, f as DefaultSessionReaderOptions, S as SessionReader } from '../session-reader-B-Fi9L6I.js';
9
9
  import { b as SessionRegistry, A as AgentEntry } from '../session-registry-Dvg7i_IA.js';
10
10
  export { a as AgentLiveStatus, S as SessionLiveStatus, c as SessionRegistryEntry, g as getSessionRegistry, h as hasSessionRegistry } from '../session-registry-Dvg7i_IA.js';
11
11
  import { S as SessionRewinder, C as CheckpointInfo, a as RewindResultExtended } from '../session-rewinder-C9HnMkhP.js';
12
12
  import { T as TaskItem } from '../task-format-vGOIftmK.js';
13
- export { a as DirectorStateCheckpoint, D as DirectorStateSnapshot, b as DirectorSubagentState, c as DirectorTaskState, l as loadDirectorState } from '../director-state-BfeCUbmk.js';
14
- export { G as GoalFile, J as JournalEntry, M as MAX_JOURNAL_ENTRIES, a as MAX_PROGRESS_HISTORY, P as ProgressSnapshot, b as appendJournal, e as emptyGoal, f as formatGoal, g as goalFilePath, l as loadGoal, p as parseProgressFromText, r as recordProgress, s as saveGoal, c as setProgress, d as summarizeUsage } from '../goal-store-BLGZq16t.js';
13
+ export { a as DirectorStateCheckpoint, D as DirectorStateSnapshot, b as DirectorSubagentState, c as DirectorTaskState, l as loadDirectorState } from '../director-state-B_GPa78Q.js';
14
+ export { G as GoalFile, J as JournalEntry, M as MAX_JOURNAL_ENTRIES, a as MAX_PROGRESS_HISTORY, P as ProgressSnapshot, b as appendJournal, e as emptyGoal, f as formatGoal, g as goalFilePath, l as loadGoal, p as parseProgressFromText, r as recordProgress, s as saveGoal, c as setProgress, d as summarizeUsage } from '../goal-store-CBd749M4.js';
15
15
  import { a as PromptEntry } from '../prompt-DLd35n4Q.js';
16
16
  import { W as WstackPaths } from '../wstack-paths-C3K40Qst.js';
17
17
  import { S as SecretScrubber } from '../secret-scrubber-3MHDDAtm.js';
18
- export { A as AuditLevel, C as CORE_RECONSTRUCT_EVENTS, a as STANDARD_AUDIT_EVENTS, S as SessionEventBridge, b as SessionEventBridgeOptions, c as SessionSamplingOptions, T as ToolProgressSamplingOptions, d as createSessionEventBridge, r as resolveAuditLevel, e as resolveSessionLoggingConfig } from '../session-event-bridge-vA2fLV58.js';
18
+ export { A as AuditLevel, C as CORE_RECONSTRUCT_EVENTS, a as STANDARD_AUDIT_EVENTS, S as SessionEventBridge, b as SessionEventBridgeOptions, c as SessionSamplingOptions, T as ToolProgressSamplingOptions, d as createSessionEventBridge, r as resolveAuditLevel, e as resolveSessionLoggingConfig } from '../session-event-bridge-Bkp7ORfc.js';
19
19
  import '../permission-B6YAtNFz.js';
20
20
  import '../logger-B63L5bTg.js';
21
- import '../pipeline-E7_jqGyV.js';
21
+ import '../pipeline-DM-CPTUs.js';
22
22
  import '../mailbox-types-BGZWrYTJ.js';
23
23
  import '../observability-D-HZN_mF.js';
24
24
  import '../task-graph-u1q9Jkyk.js';
25
25
 
26
+ interface PromptStore {
27
+ list(): Promise<PromptEntry[]>;
28
+ get(id: string): Promise<PromptEntry | null>;
29
+ save(entry: PromptEntry): Promise<void>;
30
+ delete(id: string): Promise<boolean>;
31
+ find(query: string): Promise<PromptEntry[]>;
32
+ }
33
+ /** sha256 of a prompt's content — used for builtin/synced integrity checks. */
34
+ declare function promptChecksum(content: string): string;
35
+ /**
36
+ * Upgrade any persisted prompt record (v1 or v2) to a fully-populated v2
37
+ * `PromptEntry`. Pure — does not touch disk. v1 records (only
38
+ * `id/title/content/tags/createdAt/updatedAt`) get sensible defaults:
39
+ * slug from title, empty description, `uncategorized` category, `user` source.
40
+ */
41
+ declare function migratePromptEntry(raw: unknown): PromptEntry | null;
42
+ /**
43
+ * DefaultPromptStore — file-per-prompt JSON in a single directory (the global
44
+ * `~/.wrongstack/prompts` by default, or a layer dir the loader passes in).
45
+ * Reads tolerate legacy v1 files via `migratePromptEntry`; writes always emit
46
+ * the current v2 schema.
47
+ */
48
+ declare class DefaultPromptStore implements PromptStore {
49
+ private readonly dir;
50
+ constructor(pathsOrDir: WstackPaths | string);
51
+ list(): Promise<PromptEntry[]>;
52
+ get(id: string): Promise<PromptEntry | null>;
53
+ save(entry: PromptEntry): Promise<void>;
54
+ delete(id: string): Promise<boolean>;
55
+ find(query: string): Promise<PromptEntry[]>;
56
+ /** Create a new v2 entry and return it. Does NOT persist — call save() afterwards. */
57
+ createNew(title: string, content: string, tags?: string[], extra?: Partial<Omit<PromptEntry, 'id' | 'title' | 'content' | 'tags' | 'createdAt' | 'updatedAt'>>): PromptEntry;
58
+ }
59
+
60
+ interface PromptUsage {
61
+ count: number;
62
+ lastUsedAt: string;
63
+ }
64
+ /**
65
+ * Tracks how often each prompt is inserted, keyed by slug, in a single JSON
66
+ * file (`~/.wrongstack/prompt-usage.json`). Kept SEPARATE from the prompt
67
+ * entries so usage can be recorded for read-only builtin prompts without
68
+ * copy-on-writing them into the user layer. Surfaces "recent / most-used"
69
+ * views and a gentle search-ranking boost.
70
+ */
71
+ declare class PromptUsageStore {
72
+ private readonly file;
73
+ constructor(file: string);
74
+ load(): Promise<Record<string, PromptUsage>>;
75
+ record(slug: string, at?: string): Promise<PromptUsage>;
76
+ get(slug: string): Promise<PromptUsage | undefined>;
77
+ /** Slugs ordered by most-recently-used (then by count), capped at `limit`. */
78
+ recent(limit?: number): Promise<{
79
+ slug: string;
80
+ usage: PromptUsage;
81
+ }[]>;
82
+ /** Slugs ordered by usage count (then recency), capped at `limit`. */
83
+ top(limit?: number): Promise<{
84
+ slug: string;
85
+ usage: PromptUsage;
86
+ }[]>;
87
+ }
88
+
89
+ /**
90
+ * ReplayLogStore — sidecar store for deterministic-replay support
91
+ * (idea #2 from IDEAS.md). One JSONL file per session, recording
92
+ * every provider request/response pair so the same agent loop can
93
+ * be re-run later with frozen API responses.
94
+ *
95
+ * Why a sidecar (not the session JSONL)?
96
+ *
97
+ * Same reason as `AnnotationsStore` — the session log is
98
+ * event-sourced and append-only; a provider request payload can be
99
+ * tens of kilobytes (especially with long conversation history),
100
+ * and we want replay to be opt-in (recorded only when the user
101
+ * runs with `--replay` or a future equivalent). Mixing it into
102
+ * the event log would inflate every read for replay-irrelevant
103
+ * paths.
104
+ *
105
+ * File layout: `sessionScopedPath(dir, sessionId, '.replay.jsonl')`,
106
+ * one entry per line.
107
+ * Each entry: `{ hash, ts, request, response }`. The `hash` is
108
+ * computed via `hashRequest` so lookups are O(1) by hash.
109
+ *
110
+ * Concurrency: per-session write queue (same pattern as
111
+ * `AnnotationsStore`). Reads are lock-free; the write chain makes
112
+ * the append + rehash sequence atomic.
113
+ */
114
+ interface ReplayEntry {
115
+ hash: string;
116
+ ts: string;
117
+ request: Request;
118
+ response: Response;
119
+ }
120
+ interface ReplayLogStoreOptions {
121
+ /** Root sessions directory used with `sessionScopedPath(..., '.replay.jsonl')`. */
122
+ dir: string;
123
+ /**
124
+ * Cap on the number of entries per session. When a `record` would
125
+ * push the file beyond this, the oldest entries are evicted (LRU
126
+ * by insertion order). Set to `Infinity` to disable rotation.
127
+ * Defaults to 1000 — a single LLM call averages ~5KB serialized
128
+ * (messages + tools + response), so 1000 entries is ~5MB per
129
+ * session which is a reasonable upper bound.
130
+ */
131
+ maxEntries?: number | undefined;
132
+ events?: EventBus;
133
+ traceId?: string;
134
+ }
135
+ declare class ReplayLogStore {
136
+ private readonly dir;
137
+ private readonly events;
138
+ private readonly traceId;
139
+ private readonly writeChains;
140
+ /** Per-session hash → on-disk location, with lazy entry hydration. */
141
+ private readonly cache;
142
+ /** Per-session entry count on disk, to detect when compaction is needed. */
143
+ private readonly diskCount;
144
+ private readonly maxEntries;
145
+ constructor(opts: ReplayLogStoreOptions);
146
+ /**
147
+ * Record a request/response pair. Idempotent on hash: a second
148
+ * `record` for the same hash is a no-op (the existing entry wins).
149
+ * Returns the hash.
150
+ */
151
+ record(input: {
152
+ sessionId: string;
153
+ request: Request;
154
+ response: Response;
155
+ }): Promise<string>;
156
+ /**
157
+ * Look up an entry by hash. Returns `null` when the request has
158
+ * not been recorded for this session. O(1) after the first call
159
+ * per session (in-memory cache).
160
+ */
161
+ lookup(sessionId: string, hash: string): Promise<ReplayEntry | null>;
162
+ /** All recorded entries for a session, in insertion order. */
163
+ load(sessionId: string): Promise<ReplayEntry[]>;
164
+ /**
165
+ * List every session id that has a replay log in the store dir.
166
+ * Returns an array of `{ sessionId, entryCount, path }` sorted
167
+ * by sessionId for stable output. Used by `wstack replay --list`.
168
+ */
169
+ list(): Promise<Array<{
170
+ sessionId: string;
171
+ entryCount: number;
172
+ path: string;
173
+ }>>;
174
+ private filePath;
175
+ private countEntries;
176
+ private parseReplayLine;
177
+ private readAll;
178
+ private writeAll;
179
+ private ensureCache;
180
+ private hydrateEntry;
181
+ private enqueue;
182
+ }
183
+
26
184
  /**
27
185
  * @deprecated Legacy helper kept for callers that still need filename-safe
28
186
  * labels. New session ids are opaque and do not include model/provider names.
@@ -344,101 +502,6 @@ declare class AnnotationsStore {
344
502
  private enqueue;
345
503
  }
346
504
 
347
- /**
348
- * ReplayLogStore — sidecar store for deterministic-replay support
349
- * (idea #2 from IDEAS.md). One JSONL file per session, recording
350
- * every provider request/response pair so the same agent loop can
351
- * be re-run later with frozen API responses.
352
- *
353
- * Why a sidecar (not the session JSONL)?
354
- *
355
- * Same reason as `AnnotationsStore` — the session log is
356
- * event-sourced and append-only; a provider request payload can be
357
- * tens of kilobytes (especially with long conversation history),
358
- * and we want replay to be opt-in (recorded only when the user
359
- * runs with `--replay` or a future equivalent). Mixing it into
360
- * the event log would inflate every read for replay-irrelevant
361
- * paths.
362
- *
363
- * File layout: `sessionScopedPath(dir, sessionId, '.replay.jsonl')`,
364
- * one entry per line.
365
- * Each entry: `{ hash, ts, request, response }`. The `hash` is
366
- * computed via `hashRequest` so lookups are O(1) by hash.
367
- *
368
- * Concurrency: per-session write queue (same pattern as
369
- * `AnnotationsStore`). Reads are lock-free; the write chain makes
370
- * the append + rehash sequence atomic.
371
- */
372
- interface ReplayEntry {
373
- hash: string;
374
- ts: string;
375
- request: Request;
376
- response: Response;
377
- }
378
- interface ReplayLogStoreOptions {
379
- /** Root sessions directory used with `sessionScopedPath(..., '.replay.jsonl')`. */
380
- dir: string;
381
- /**
382
- * Cap on the number of entries per session. When a `record` would
383
- * push the file beyond this, the oldest entries are evicted (LRU
384
- * by insertion order). Set to `Infinity` to disable rotation.
385
- * Defaults to 1000 — a single LLM call averages ~5KB serialized
386
- * (messages + tools + response), so 1000 entries is ~5MB per
387
- * session which is a reasonable upper bound.
388
- */
389
- maxEntries?: number | undefined;
390
- events?: EventBus;
391
- traceId?: string;
392
- }
393
- declare class ReplayLogStore {
394
- private readonly dir;
395
- private readonly events;
396
- private readonly traceId;
397
- private readonly writeChains;
398
- /** Per-session hash → on-disk location, with lazy entry hydration. */
399
- private readonly cache;
400
- /** Per-session entry count on disk, to detect when compaction is needed. */
401
- private readonly diskCount;
402
- private readonly maxEntries;
403
- constructor(opts: ReplayLogStoreOptions);
404
- /**
405
- * Record a request/response pair. Idempotent on hash: a second
406
- * `record` for the same hash is a no-op (the existing entry wins).
407
- * Returns the hash.
408
- */
409
- record(input: {
410
- sessionId: string;
411
- request: Request;
412
- response: Response;
413
- }): Promise<string>;
414
- /**
415
- * Look up an entry by hash. Returns `null` when the request has
416
- * not been recorded for this session. O(1) after the first call
417
- * per session (in-memory cache).
418
- */
419
- lookup(sessionId: string, hash: string): Promise<ReplayEntry | null>;
420
- /** All recorded entries for a session, in insertion order. */
421
- load(sessionId: string): Promise<ReplayEntry[]>;
422
- /**
423
- * List every session id that has a replay log in the store dir.
424
- * Returns an array of `{ sessionId, entryCount, path }` sorted
425
- * by sessionId for stable output. Used by `wstack replay --list`.
426
- */
427
- list(): Promise<Array<{
428
- sessionId: string;
429
- entryCount: number;
430
- path: string;
431
- }>>;
432
- private filePath;
433
- private countEntries;
434
- private parseReplayLine;
435
- private readAll;
436
- private writeAll;
437
- private ensureCache;
438
- private hydrateEntry;
439
- private enqueue;
440
- }
441
-
442
505
  /**
443
506
  * Idea #1 from IDEAS.md — Stateful Session Recovery.
444
507
  *
@@ -830,69 +893,6 @@ declare function saveTasks(filePath: string, tasks: TaskFile, events?: EventBus,
830
893
  */
831
894
  declare function mutateTasks(filePath: string, sessionId: string, fn: (file: TaskFile) => TaskFile | Promise<TaskFile>, events?: EventBus, traceId?: string): Promise<TaskFile>;
832
895
 
833
- interface PromptStore {
834
- list(): Promise<PromptEntry[]>;
835
- get(id: string): Promise<PromptEntry | null>;
836
- save(entry: PromptEntry): Promise<void>;
837
- delete(id: string): Promise<boolean>;
838
- find(query: string): Promise<PromptEntry[]>;
839
- }
840
- /** sha256 of a prompt's content — used for builtin/synced integrity checks. */
841
- declare function promptChecksum(content: string): string;
842
- /**
843
- * Upgrade any persisted prompt record (v1 or v2) to a fully-populated v2
844
- * `PromptEntry`. Pure — does not touch disk. v1 records (only
845
- * `id/title/content/tags/createdAt/updatedAt`) get sensible defaults:
846
- * slug from title, empty description, `uncategorized` category, `user` source.
847
- */
848
- declare function migratePromptEntry(raw: unknown): PromptEntry | null;
849
- /**
850
- * DefaultPromptStore — file-per-prompt JSON in a single directory (the global
851
- * `~/.wrongstack/prompts` by default, or a layer dir the loader passes in).
852
- * Reads tolerate legacy v1 files via `migratePromptEntry`; writes always emit
853
- * the current v2 schema.
854
- */
855
- declare class DefaultPromptStore implements PromptStore {
856
- private readonly dir;
857
- constructor(pathsOrDir: WstackPaths | string);
858
- list(): Promise<PromptEntry[]>;
859
- get(id: string): Promise<PromptEntry | null>;
860
- save(entry: PromptEntry): Promise<void>;
861
- delete(id: string): Promise<boolean>;
862
- find(query: string): Promise<PromptEntry[]>;
863
- /** Create a new v2 entry and return it. Does NOT persist — call save() afterwards. */
864
- createNew(title: string, content: string, tags?: string[], extra?: Partial<Omit<PromptEntry, 'id' | 'title' | 'content' | 'tags' | 'createdAt' | 'updatedAt'>>): PromptEntry;
865
- }
866
-
867
- interface PromptUsage {
868
- count: number;
869
- lastUsedAt: string;
870
- }
871
- /**
872
- * Tracks how often each prompt is inserted, keyed by slug, in a single JSON
873
- * file (`~/.wrongstack/prompt-usage.json`). Kept SEPARATE from the prompt
874
- * entries so usage can be recorded for read-only builtin prompts without
875
- * copy-on-writing them into the user layer. Surfaces "recent / most-used"
876
- * views and a gentle search-ranking boost.
877
- */
878
- declare class PromptUsageStore {
879
- private readonly file;
880
- constructor(file: string);
881
- load(): Promise<Record<string, PromptUsage>>;
882
- record(slug: string, at?: string): Promise<PromptUsage>;
883
- get(slug: string): Promise<PromptUsage | undefined>;
884
- /** Slugs ordered by most-recently-used (then by count), capped at `limit`. */
885
- recent(limit?: number): Promise<{
886
- slug: string;
887
- usage: PromptUsage;
888
- }[]>;
889
- /** Slugs ordered by usage count (then recency), capped at `limit`. */
890
- top(limit?: number): Promise<{
891
- slug: string;
892
- usage: PromptUsage;
893
- }[]>;
894
- }
895
-
896
896
  declare const INPUT_HISTORY_DEFAULT_MAX = 100;
897
897
  /**
898
898
  * Per-project TUI prompt input history.
@@ -8820,9 +8820,24 @@ var DirectorStateCheckpoint = class {
8820
8820
  recordTaskStatus(taskId, patch) {
8821
8821
  this.snapshot = {
8822
8822
  ...this.snapshot,
8823
- tasks: this.snapshot.tasks.map(
8824
- (t) => t.taskId === taskId ? { ...t, ...patch } : t
8825
- )
8823
+ tasks: this.snapshot.tasks.map((t) => t.taskId === taskId ? { ...t, ...patch } : t)
8824
+ };
8825
+ this.bumpUpdatedAt();
8826
+ this.schedule();
8827
+ }
8828
+ recordTaskWorktree(taskId, worktree) {
8829
+ const exists = this.snapshot.tasks.some((t) => t.taskId === taskId);
8830
+ this.snapshot = {
8831
+ ...this.snapshot,
8832
+ tasks: exists ? this.snapshot.tasks.map((t) => t.taskId === taskId ? { ...t, worktree } : t) : [
8833
+ ...this.snapshot.tasks,
8834
+ {
8835
+ taskId,
8836
+ subagentId: worktree.subagentId,
8837
+ status: "running",
8838
+ worktree
8839
+ }
8840
+ ]
8826
8841
  };
8827
8842
  this.bumpUpdatedAt();
8828
8843
  this.schedule();
@@ -8865,10 +8880,7 @@ var DirectorStateCheckpoint = class {
8865
8880
  mode: 384
8866
8881
  });
8867
8882
  } catch (err) {
8868
- console.warn(
8869
- "[director-state] checkpoint write failed:",
8870
- toErrorMessage(err)
8871
- );
8883
+ console.warn("[director-state] checkpoint write failed:", toErrorMessage(err));
8872
8884
  } finally {
8873
8885
  this.writing = false;
8874
8886
  if (this.rewriteRequested) {