zelari-code 2.55.0 → 2.57.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 (106) hide show
  1. package/README.md +1 -1
  2. package/dist/cli/app.js +2 -2
  3. package/dist/cli/app.js.map +1 -1
  4. package/dist/cli/budget/modelContextBuilder.js +4 -1
  5. package/dist/cli/budget/modelContextBuilder.js.map +1 -1
  6. package/dist/cli/commands/evolve.js +247 -0
  7. package/dist/cli/commands/evolve.js.map +1 -0
  8. package/dist/cli/commands/replay.js +202 -0
  9. package/dist/cli/commands/replay.js.map +1 -0
  10. package/dist/cli/commands/session.js +264 -0
  11. package/dist/cli/commands/session.js.map +1 -0
  12. package/dist/cli/commands/spineSession.js +77 -0
  13. package/dist/cli/commands/spineSession.js.map +1 -0
  14. package/dist/cli/components/StatusBar.js +6 -2
  15. package/dist/cli/components/StatusBar.js.map +1 -1
  16. package/dist/cli/components/statusChips.js +43 -0
  17. package/dist/cli/components/statusChips.js.map +1 -1
  18. package/dist/cli/councilDispatcher.js +12 -0
  19. package/dist/cli/councilDispatcher.js.map +1 -1
  20. package/dist/cli/evolution/controller.js +107 -0
  21. package/dist/cli/evolution/controller.js.map +1 -0
  22. package/dist/cli/evolution/ledger.js +127 -0
  23. package/dist/cli/evolution/ledger.js.map +1 -1
  24. package/dist/cli/evolution/patternLedger.js +165 -0
  25. package/dist/cli/evolution/patternLedger.js.map +1 -0
  26. package/dist/cli/headless/runOneTurn.js +31 -1
  27. package/dist/cli/headless/runOneTurn.js.map +1 -1
  28. package/dist/cli/hooks/useChatTurn.js +60 -2
  29. package/dist/cli/hooks/useChatTurn.js.map +1 -1
  30. package/dist/cli/hooks/useSlashDispatch.js +8 -0
  31. package/dist/cli/hooks/useSlashDispatch.js.map +1 -1
  32. package/dist/cli/inbox.js +63 -10
  33. package/dist/cli/inbox.js.map +1 -1
  34. package/dist/cli/inboxSources.js +173 -0
  35. package/dist/cli/inboxSources.js.map +1 -0
  36. package/dist/cli/main.bundled.js +11889 -8078
  37. package/dist/cli/main.bundled.js.map +4 -4
  38. package/dist/cli/main.js +80 -0
  39. package/dist/cli/main.js.map +1 -1
  40. package/dist/cli/memory/mcpAdapter.js +3 -1
  41. package/dist/cli/memory/mcpAdapter.js.map +1 -1
  42. package/dist/cli/memory/onePager.js +93 -0
  43. package/dist/cli/memory/onePager.js.map +1 -0
  44. package/dist/cli/memory/serviceFactory.js +5 -0
  45. package/dist/cli/memory/serviceFactory.js.map +1 -1
  46. package/dist/cli/memory/sqliteBackend.js +40 -3
  47. package/dist/cli/memory/sqliteBackend.js.map +1 -1
  48. package/dist/cli/memory/sqliteCodec.js +2 -0
  49. package/dist/cli/memory/sqliteCodec.js.map +1 -1
  50. package/dist/cli/memory/sqliteSchema.js +11 -1
  51. package/dist/cli/memory/sqliteSchema.js.map +1 -1
  52. package/dist/cli/plugins/bundleCommand.js +238 -0
  53. package/dist/cli/plugins/bundleCommand.js.map +1 -0
  54. package/dist/cli/plugins/bundleDiscover.js +74 -0
  55. package/dist/cli/plugins/bundleDiscover.js.map +1 -0
  56. package/dist/cli/plugins/bundleFs.js +57 -0
  57. package/dist/cli/plugins/bundleFs.js.map +1 -0
  58. package/dist/cli/plugins/bundleHookDef.js +70 -0
  59. package/dist/cli/plugins/bundleHookDef.js.map +1 -0
  60. package/dist/cli/plugins/bundleLoad.js +180 -0
  61. package/dist/cli/plugins/bundleLoad.js.map +1 -0
  62. package/dist/cli/plugins/bundleManifest.js +233 -0
  63. package/dist/cli/plugins/bundleManifest.js.map +1 -0
  64. package/dist/cli/plugins/bundleMcp.js +41 -0
  65. package/dist/cli/plugins/bundleMcp.js.map +1 -0
  66. package/dist/cli/plugins/bundleState.js +142 -0
  67. package/dist/cli/plugins/bundleState.js.map +1 -0
  68. package/dist/cli/runHeadless.js +102 -12
  69. package/dist/cli/runHeadless.js.map +1 -1
  70. package/dist/cli/safety/decisionEmit.js +43 -0
  71. package/dist/cli/safety/decisionEmit.js.map +1 -0
  72. package/dist/cli/safety/permissionGate.js +239 -0
  73. package/dist/cli/safety/permissionGate.js.map +1 -0
  74. package/dist/cli/safety/permissionPolicy.js +279 -0
  75. package/dist/cli/safety/permissionPolicy.js.map +1 -0
  76. package/dist/cli/safety/permissionRules.js +145 -0
  77. package/dist/cli/safety/permissionRules.js.map +1 -0
  78. package/dist/cli/safety/sessionSink.js +169 -0
  79. package/dist/cli/safety/sessionSink.js.map +1 -0
  80. package/dist/cli/slashCommands.js +29 -3
  81. package/dist/cli/slashCommands.js.map +1 -1
  82. package/dist/cli/slashHandlers/evolve.js +41 -0
  83. package/dist/cli/slashHandlers/evolve.js.map +1 -0
  84. package/dist/cli/slashHandlers/memory.js +21 -0
  85. package/dist/cli/slashHandlers/memory.js.map +1 -1
  86. package/dist/cli/slashHandlers/permissions.js +170 -0
  87. package/dist/cli/slashHandlers/permissions.js.map +1 -0
  88. package/dist/cli/statusline/inboxFeed.js +76 -0
  89. package/dist/cli/statusline/inboxFeed.js.map +1 -0
  90. package/dist/cli/statusline/statuslineItems.js +15 -0
  91. package/dist/cli/statusline/statuslineItems.js.map +1 -1
  92. package/dist/cli/toolRegistry.js +161 -7
  93. package/dist/cli/toolRegistry.js.map +1 -1
  94. package/dist/cli/toolResultCache.js +4 -22
  95. package/dist/cli/toolResultCache.js.map +1 -1
  96. package/dist/cli/tools/askUser.js +17 -2
  97. package/dist/cli/tools/askUser.js.map +1 -1
  98. package/dist/cli/tools/execProcess.js +15 -1
  99. package/dist/cli/tools/execProcess.js.map +1 -1
  100. package/dist/cli/tools/krakenWorktree.js +334 -43
  101. package/dist/cli/tools/krakenWorktree.js.map +1 -1
  102. package/dist/cli/tools/taskTool.js +179 -43
  103. package/dist/cli/tools/taskTool.js.map +1 -1
  104. package/dist/cli/tools/verifyDebtSpine.js +41 -0
  105. package/dist/cli/tools/verifyDebtSpine.js.map +1 -1
  106. package/package.json +6 -2
@@ -0,0 +1,107 @@
1
+ /**
2
+ * evolution/controller — Evolution Controller v0: SHADOW ONLY (ADR-0036).
3
+ *
4
+ * The controller is the piece that was missing between the WS7 slices: the
5
+ * operator (tools/eval/operators/fuseEditVerify.ts) PROPOSES, the eval gate
6
+ * JUDGES, and this module turns proposals into controller verdicts. In v0 the
7
+ * only reachable actions are:
8
+ *
9
+ * shadow — "report it": the proposal is valid evidence, nothing runs;
10
+ * hold — "do not even report": unparsable, duplicate, under-evidenced,
11
+ * or the evolution surface is off (ZELARI_EVOLUTION != shadow).
12
+ *
13
+ * `canary` and `promote` DO NOT EXIST here on purpose. A promotion is a claim
14
+ * on the future that only a signed PromotionReceipt (tools/eval/
15
+ * promotionReceipt.ts, slice 1) can back; wiring that path is a later slice
16
+ * and will arrive with its own gate. Fail-closed: anything the controller
17
+ * cannot prove becomes `hold` with the reason spelled out — never a silent
18
+ * pass (ADR-0023: unknown ≠ pass).
19
+ *
20
+ * Pure: no I/O, no clock, no env reads (the caller builds the policy — the
21
+ * command layer reads ZELARI_EVOLUTION through evolution/ledger.ts so the
22
+ * flag has exactly one spelling in the codebase).
23
+ */
24
+ import { z } from 'zod';
25
+ /** The actions v0 can emit. Deliberately narrow: no canary, no promote. */
26
+ export const CONTROLLER_V0_ACTIONS = ['hold', 'shadow'];
27
+ /**
28
+ * Structural mirror of the operator's FuseProposal (tools/eval/operators/
29
+ * fuseEditVerify.ts). NOT imported from there on purpose: tools/eval is the
30
+ * judge surface (ADR-0036 JUDGE_PATHS) written for `node --experimental-strip-
31
+ * types` (`.ts` import specifiers) — importing it from src/cli would break the
32
+ * tsc build. The mirror is validated with zod at the boundary, so a drifting
33
+ * operator shape degrades to `hold: unparsable`, never to a wrong verdict.
34
+ */
35
+ export const ControllerProposalSchema = z.object({
36
+ kind: z.string().min(1),
37
+ /** Spine identities of the calls the fused form would replace. */
38
+ callIds: z.array(z.string().min(1)).min(1),
39
+ /** Tool calls the fused form removes from the spine (counted, not modelled). */
40
+ estSavedCalls: z.number().int().nonnegative(),
41
+ /** Verifiable spine pointers (`{kind, ref}` — same shape the operator emits). */
42
+ evidence: z.array(z.object({ kind: z.string().min(1), ref: z.string().min(1) })).min(1),
43
+ /** The seq the proposal is anchored on (deterministic order + dedupe key). */
44
+ decisiveSeq: z.number().int().positive(),
45
+ path: z.string().optional(),
46
+ tool: z.string().optional(),
47
+ note: z.string().optional(),
48
+ });
49
+ /** Conservative defaults: report nothing unless evolution is opted in. */
50
+ export const DEFAULT_CONTROLLER_POLICY = {
51
+ evolutionMode: '0',
52
+ minEvidence: 3,
53
+ maxVerdicts: 50,
54
+ };
55
+ /** One proposal → one verdict. `seenKeys` carries the dedupe set across calls. */
56
+ export function evaluateProposal(raw, policy, seenKeys) {
57
+ const parsed = ControllerProposalSchema.safeParse(raw);
58
+ if (!parsed.success) {
59
+ const where = parsed.error.issues[0]?.path.join('.') ?? 'root';
60
+ return { action: 'hold', reason: `unparsable proposal (${where}) — operator/controller shape drift` };
61
+ }
62
+ const proposal = parsed.data;
63
+ if (policy.evolutionMode !== 'shadow') {
64
+ return {
65
+ action: 'hold',
66
+ reason: 'ZELARI_EVOLUTION is not "shadow" — evolution surface off (ADR-0036 default-off)',
67
+ proposal,
68
+ };
69
+ }
70
+ const key = `${proposal.kind}:${proposal.decisiveSeq}`;
71
+ if (seenKeys.has(key)) {
72
+ return { action: 'hold', reason: `duplicate proposal (kind+decisiveSeq already verdicted)`, proposal };
73
+ }
74
+ if (proposal.evidence.length < policy.minEvidence) {
75
+ return {
76
+ action: 'hold',
77
+ reason: `insufficient evidence (${proposal.evidence.length} < ${policy.minEvidence}) — a fusion claim needs the calls AND the boundary`,
78
+ proposal,
79
+ };
80
+ }
81
+ seenKeys.add(key);
82
+ return { action: 'shadow', reason: 'v0 shadow: report-only, no runtime effect (apply is a later, gated slice)', proposal };
83
+ }
84
+ /** A batch of proposals → verdicts, capped by `policy.maxVerdicts`. */
85
+ export function evaluateProposals(proposals, policy = DEFAULT_CONTROLLER_POLICY) {
86
+ const seenKeys = new Set();
87
+ const verdicts = [];
88
+ for (const raw of proposals) {
89
+ if (verdicts.length >= policy.maxVerdicts)
90
+ break;
91
+ verdicts.push(evaluateProposal(raw, policy, seenKeys));
92
+ }
93
+ return verdicts;
94
+ }
95
+ /** Deterministic summary for the report footer (and its tests). */
96
+ export function summarizeVerdicts(verdicts) {
97
+ let shadow = 0;
98
+ let estSavedCalls = 0;
99
+ for (const v of verdicts) {
100
+ if (v.action === 'shadow') {
101
+ shadow += 1;
102
+ estSavedCalls += v.proposal?.estSavedCalls ?? 0;
103
+ }
104
+ }
105
+ return { total: verdicts.length, shadow, hold: verdicts.length - shadow, estSavedCalls };
106
+ }
107
+ //# sourceMappingURL=controller.js.map
@@ -0,0 +1 @@
1
+ {"version":3,"file":"controller.js","sourceRoot":"","sources":["../../../src/cli/evolution/controller.ts"],"names":[],"mappings":"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"}
@@ -19,6 +19,99 @@ import path from 'node:path';
19
19
  export const EVOLUTION_ENV = 'ZELARI_EVOLUTION';
20
20
  /** Ledger location, relative to the project root (project-scoped by design). */
21
21
  export const LEDGER_REL = path.join('.zelari', 'evolution', 'ledger.jsonl');
22
+ /** Findings ledger location (S1) — instance-level failure findings, append-only. */
23
+ export const FINDINGS_REL = path.join('.zelari', 'evolution', 'findings.jsonl');
24
+ /**
25
+ * S1 — every project-scoped evolution artifact, relative to the root. Kept in
26
+ * one place so runners (tools/eval) and the CLI agree on disk layout. Adding a
27
+ * path here is additive; existing paths never move (append-only culture).
28
+ */
29
+ export const EVOLUTION_PATHS = {
30
+ /** Outcome ledger (ADR-0036) — one JSON object per run. */
31
+ ledger: LEDGER_REL,
32
+ /** Instance-level findings ledger — the input to the pattern ledger (S1). */
33
+ findings: FINDINGS_REL,
34
+ /** Proposals store — owned by tools/eval evolvePropose (read-only here). */
35
+ proposals: path.join('.zelari', 'evolution', 'proposals.jsonl'),
36
+ /** Failure-pattern clusters — derived, append-only (S1). */
37
+ patternLedger: path.join('.zelari', 'evolution', 'pattern-ledger.jsonl'),
38
+ };
39
+ /**
40
+ * Stable fingerprint of a finding's KIND — identity, not instance. taskKey,
41
+ * count and timestamps are excluded so the same mechanism merges as evidence
42
+ * accumulates (mirrors the proposal fingerprint contract).
43
+ */
44
+ export function findingFingerprint(f) {
45
+ return [f.kind || 'unknown', f.operator || '-', f.surface || '-', f.signal || '-'].join('|');
46
+ }
47
+ export function findingsPath(cwd) {
48
+ return path.join(cwd, FINDINGS_REL);
49
+ }
50
+ /**
51
+ * Append instance findings. No-op (not an error) when evolution is off — same
52
+ * gate as the outcome ledger (default-off, ADR-0036). Never throws: fs failures
53
+ * come back as `{ written: false, reason }` (fail-open telemetry).
54
+ */
55
+ export function appendFindings(cwd, findings) {
56
+ if (evolutionMode() === '0') {
57
+ return { written: false, reason: `${EVOLUTION_ENV} != shadow — findings write skipped` };
58
+ }
59
+ if (findings.length === 0) {
60
+ return { written: false, reason: 'no findings' };
61
+ }
62
+ try {
63
+ const file = findingsPath(cwd);
64
+ mkdirSync(path.dirname(file), { recursive: true });
65
+ appendFileSync(file, `${findings.map((f) => JSON.stringify(f)).join('\n')}\n`, 'utf8');
66
+ return { written: true, path: file };
67
+ }
68
+ catch (err) {
69
+ return {
70
+ written: false,
71
+ reason: `findings append failed (fail-open): ${err instanceof Error ? err.message : String(err)}`,
72
+ };
73
+ }
74
+ }
75
+ /**
76
+ * Tolerant replay for the findings ledger: parse every line, skip corrupt ones
77
+ * silently, require a string `kind` (the one mandatory field). Never throws.
78
+ */
79
+ export function readFindings(cwd) {
80
+ const file = findingsPath(cwd);
81
+ if (!existsSync(file))
82
+ return [];
83
+ let raw;
84
+ try {
85
+ raw = readFileSync(file, 'utf8');
86
+ }
87
+ catch {
88
+ return [];
89
+ }
90
+ const out = [];
91
+ for (const line of raw.split('\n')) {
92
+ const trimmed = line.trim();
93
+ if (!trimmed)
94
+ continue;
95
+ try {
96
+ const parsed = JSON.parse(trimmed);
97
+ if (parsed && typeof parsed === 'object' && typeof parsed.kind === 'string') {
98
+ out.push(parsed);
99
+ }
100
+ }
101
+ catch {
102
+ // corrupt line — skip (tolerant replay)
103
+ }
104
+ }
105
+ return out;
106
+ }
107
+ /**
108
+ * Check-id prefix of the honesty FAMILY in the verification report vocabulary
109
+ * (packages/core .../council/verification/types.ts): `synthesis.honesty`,
110
+ * `synthesis.tier-inflation`, `synthesis.cite-invalid`,
111
+ * `synthesis.degraded-banner`. They all grade the chairman's CLAIMS against
112
+ * traceable evidence — exactly what "honesty" means in this codebase.
113
+ */
114
+ export const HONESTY_CHECK_PREFIX = 'synthesis.';
22
115
  /** Resolve the active evolution mode (default off, ADR-0036). */
23
116
  export function evolutionMode(env = process.env) {
24
117
  return env[EVOLUTION_ENV] === 'shadow' ? 'shadow' : '0';
@@ -26,6 +119,21 @@ export function evolutionMode(env = process.env) {
26
119
  export function ledgerPath(cwd) {
27
120
  return path.join(cwd, LEDGER_REL);
28
121
  }
122
+ /**
123
+ * Derive the ledger honesty signal from a verification report's `results`.
124
+ * Pure and total: `undefined` when the run produced NO report (unknown — the
125
+ * caller then omits the field), and `flagged` counts only FAILED checks of the
126
+ * honesty family. A missing check is never read as a violation, and a passing
127
+ * one never as evidence that the lint ran.
128
+ */
129
+ export function honestyFromVerificationResults(results) {
130
+ if (!results)
131
+ return undefined;
132
+ return {
133
+ linted: true,
134
+ flagged: results.filter((r) => !r.ok && r.id.startsWith(HONESTY_CHECK_PREFIX)).length,
135
+ };
136
+ }
29
137
  /**
30
138
  * Append one outcome entry. No-op (not an error) when evolution is off.
31
139
  * Never throws: fs failures come back as `{ written: false, reason }`.
@@ -116,6 +224,21 @@ function mean(nums) {
116
224
  return undefined;
117
225
  return nums.reduce((a, b) => a + b, 0) / nums.length;
118
226
  }
227
+ /**
228
+ * Token-weighted provider cache hit rate over the entries that actually carry
229
+ * both numbers. Entries without a provider cache report contribute nothing —
230
+ * the result is `undefined` rather than a flattering 0.
231
+ */
232
+ function cacheHitRate(entries) {
233
+ const withCache = entries.filter((e) => typeof e.cacheHitTokens === 'number' &&
234
+ typeof e.inputTokens === 'number' &&
235
+ e.inputTokens > 0);
236
+ if (withCache.length === 0)
237
+ return undefined;
238
+ const hit = withCache.reduce((acc, e) => acc + (e.cacheHitTokens ?? 0), 0);
239
+ const prompt = withCache.reduce((acc, e) => acc + (e.inputTokens ?? 0), 0);
240
+ return prompt > 0 ? hit / prompt : undefined;
241
+ }
119
242
  function classFitness(entries) {
120
243
  const rated = entries.filter((e) => isRated(e.verdict));
121
244
  const passRate = rated.length === 0 ? 0 : rated.filter((e) => e.verdict === 'PASS').length / rated.length;
@@ -131,6 +254,8 @@ function classFitness(entries) {
131
254
  avgLatencyMs: mean(entries.map((e) => e.latencyMs).filter((c) => typeof c === 'number')),
132
255
  avgSteerCount: mean(entries.map((e) => e.steerCount).filter((c) => typeof c === 'number')),
133
256
  rollbackRate: entries.length === 0 ? 0 : entries.filter((e) => e.rollbackUsed === true).length / entries.length,
257
+ avgHonestyFlags: mean(entries.map((e) => e.honesty?.flagged).filter((c) => typeof c === 'number')),
258
+ cacheHitRate: cacheHitRate(entries),
134
259
  };
135
260
  }
136
261
  /** Aggregate stats + deterministic fitness for `--evolve-status` / `/evolve`. */
@@ -167,6 +292,8 @@ export function ledgerStats(entries) {
167
292
  ...(entries.length > 0 ? { rollbackRate: global.rollbackRate } : {}),
168
293
  ...(global.avgCostUsd !== undefined ? { avgCostUsd: global.avgCostUsd } : {}),
169
294
  ...(global.avgLatencyMs !== undefined ? { avgLatencyMs: global.avgLatencyMs } : {}),
295
+ ...(global.avgHonestyFlags !== undefined ? { avgHonestyFlags: global.avgHonestyFlags } : {}),
296
+ ...(global.cacheHitRate !== undefined ? { cacheHitRate: global.cacheHitRate } : {}),
170
297
  byClassFitness,
171
298
  };
172
299
  }
@@ -1 +1 @@
1
- {"version":3,"file":"ledger.js","sourceRoot":"","sources":["../../../src/cli/evolution/ledger.ts"],"names":[],"mappings":"AAAA;;;;;;;;;;;;;;GAcG;AACH,OAAO,EAAE,cAAc,EAAE,UAAU,EAAE,SAAS,EAAE,YAAY,EAAE,MAAM,SAAS,CAAC;AAC9E,OAAO,IAAI,MAAM,WAAW,CAAC;AAE7B,8EAA8E;AAC9E,MAAM,CAAC,MAAM,aAAa,GAAG,kBAAkB,CAAC;AAIhD,gFAAgF;AAChF,MAAM,CAAC,MAAM,UAAU,GAAG,IAAI,CAAC,IAAI,CAAC,SAAS,EAAE,WAAW,EAAE,cAAc,CAAC,CAAC;AAqC5E,iEAAiE;AACjE,MAAM,UAAU,aAAa,CAAC,MAA0C,OAAO,CAAC,GAAG;IACjF,OAAO,GAAG,CAAC,aAAa,CAAC,KAAK,QAAQ,CAAC,CAAC,CAAC,QAAQ,CAAC,CAAC,CAAC,GAAG,CAAC;AAC1D,CAAC;AAED,MAAM,UAAU,UAAU,CAAC,GAAW;IACpC,OAAO,IAAI,CAAC,IAAI,CAAC,GAAG,EAAE,UAAU,CAAC,CAAC;AACpC,CAAC;AAQD;;;GAGG;AACH,MAAM,UAAU,iBAAiB,CAAC,GAAW,EAAE,KAAkB;IAC/D,IAAI,aAAa,EAAE,KAAK,GAAG,EAAE,CAAC;QAC5B,OAAO,EAAE,OAAO,EAAE,KAAK,EAAE,MAAM,EAAE,GAAG,aAAa,mCAAmC,EAAE,CAAC;IACzF,CAAC;IACD,IAAI,CAAC;QACH,MAAM,IAAI,GAAG,UAAU,CAAC,GAAG,CAAC,CAAC;QAC7B,SAAS,CAAC,IAAI,CAAC,OAAO,CAAC,IAAI,CAAC,EAAE,EAAE,SAAS,EAAE,IAAI,EAAE,CAAC,CAAC;QACnD,cAAc,CAAC,IAAI,EAAE,GAAG,IAAI,CAAC,SAAS,CAAC,KAAK,CAAC,IAAI,EAAE,MAAM,CAAC,CAAC;QAC3D,OAAO,EAAE,OAAO,EAAE,IAAI,EAAE,IAAI,EAAE,IAAI,EAAE,CAAC;IACvC,CAAC;IAAC,OAAO,GAAG,EAAE,CAAC;QACb,OAAO;YACL,OAAO,EAAE,KAAK;YACd,MAAM,EAAE,qCAAqC,GAAG,YAAY,KAAK,CAAC,CAAC,CAAC,GAAG,CAAC,OAAO,CAAC,CAAC,CAAC,MAAM,CAAC,GAAG,CAAC,EAAE;SAChG,CAAC;IACJ,CAAC;AACH,CAAC;AAED;;;GAGG;AACH,MAAM,UAAU,UAAU,CAAC,GAAW;IACpC,MAAM,IAAI,GAAG,UAAU,CAAC,GAAG,CAAC,CAAC;IAC7B,IAAI,CAAC,UAAU,CAAC,IAAI,CAAC;QAAE,OAAO,EAAE,CAAC;IACjC,IAAI,GAAW,CAAC;IAChB,IAAI,CAAC;QACH,GAAG,GAAG,YAAY,CAAC,IAAI,EAAE,MAAM,CAAC,CAAC;IACnC,CAAC;IAAC,MAAM,CAAC;QACP,OAAO,EAAE,CAAC;IACZ,CAAC;IACD,MAAM,GAAG,GAAkB,EAAE,CAAC;IAC9B,KAAK,MAAM,IAAI,IAAI,GAAG,CAAC,KAAK,CAAC,IAAI,CAAC,EAAE,CAAC;QACnC,MAAM,OAAO,GAAG,IAAI,CAAC,IAAI,EAAE,CAAC;QAC5B,IAAI,CAAC,OAAO;YAAE,SAAS;QACvB,IAAI,CAAC;YACH,MAAM,MAAM,GAAG,IAAI,CAAC,KAAK,CAAC,OAAO,CAAgB,CAAC;YAClD,IAAI,OAAO,MAAM,EAAE,KAAK,KAAK,QAAQ,IAAI,OAAO,MAAM,EAAE,EAAE,KAAK,QAAQ,EAAE,CAAC;gBACxE,GAAG,CAAC,IAAI,CAAC,MAAM,CAAC,CAAC;YACnB,CAAC;QACH,CAAC;QAAC,MAAM,CAAC;YACP,wCAAwC;QAC1C,CAAC;IACH,CAAC;IACD,OAAO,GAAG,CAAC;AACb,CAAC;AAED,6EAA6E;AAC7E,EAAE;AACF,wEAAwE;AACxE,0EAA0E;AAC1E,gEAAgE;AAChE,EAAE;AACF,6EAA6E;AAC7E,sDAAsD;AACtD,0EAA0E;AAC1E,+EAA+E;AAC/E,gFAAgF;AAChF,4EAA4E;AAC5E,4EAA4E;AAE5E,MAAM,YAAY,GAA2B;IAC3C,KAAK,EAAE,CAAC;IACR,aAAa,EAAE,CAAC;IAChB,gBAAgB,EAAE,CAAC;IACnB,IAAI,EAAE,CAAC;IACP,OAAO,EAAE,CAAC;IACV,gBAAgB,EAAE,GAAG;IACrB,EAAE,EAAE,GAAG;CACR,CAAC;AACF,MAAM,eAAe,GAAG,IAAI,CAAC;AAE7B,SAAS,UAAU,CAAC,IAAwB;IAC1C,IAAI,CAAC,IAAI;QAAE,OAAO,eAAe,CAAC;IAClC,OAAO,YAAY,CAAC,IAAI,CAAC,IAAI,eAAe,CAAC;AAC/C,CAAC;AAED,0EAA0E;AAC1E,SAAS,OAAO,CAAC,OAAe;IAC9B,OAAO,OAAO,KAAK,MAAM,IAAI,OAAO,KAAK,MAAM,CAAC;AAClD,CAAC;AAkCD,SAAS,IAAI,CAAC,IAAuB;IACnC,IAAI,IAAI,CAAC,MAAM,KAAK,CAAC;QAAE,OAAO,SAAS,CAAC;IACxC,OAAO,IAAI,CAAC,MAAM,CAAC,CAAC,CAAC,EAAE,CAAC,EAAE,EAAE,CAAC,CAAC,GAAG,CAAC,EAAE,CAAC,CAAC,GAAG,IAAI,CAAC,MAAM,CAAC;AACvD,CAAC;AAED,SAAS,YAAY,CAAC,OAA+B;IACnD,MAAM,KAAK,GAAG,OAAO,CAAC,MAAM,CAAC,CAAC,CAAC,EAAE,EAAE,CAAC,OAAO,CAAC,CAAC,CAAC,OAAO,CAAC,CAAC,CAAC;IACxD,MAAM,QAAQ,GACZ,KAAK,CAAC,MAAM,KAAK,CAAC,CAAC,CAAC,CAAC,CAAC,CAAC,CAAC,CAAC,KAAK,CAAC,MAAM,CAAC,CAAC,CAAC,EAAE,EAAE,CAAC,CAAC,CAAC,OAAO,KAAK,MAAM,CAAC,CAAC,MAAM,GAAG,KAAK,CAAC,MAAM,CAAC;IAC3F,MAAM,IAAI,GAAG,KAAK,CAAC,MAAM,CAAC,CAAC,GAAG,EAAE,CAAC,EAAE,EAAE,CAAC,GAAG,GAAG,UAAU,CAAC,CAAC,CAAC,YAAY,CAAC,EAAE,CAAC,CAAC,CAAC;IAC3E,MAAM,KAAK,GAAG,KAAK;SAChB,MAAM,CAAC,CAAC,CAAC,EAAE,EAAE,CAAC,CAAC,CAAC,OAAO,KAAK,MAAM,CAAC;SACnC,MAAM,CAAC,CAAC,GAAG,EAAE,CAAC,EAAE,EAAE,CAAC,GAAG,GAAG,UAAU,CAAC,CAAC,CAAC,YAAY,CAAC,EAAE,CAAC,CAAC,CAAC;IAC3D,OAAO;QACL,IAAI,EAAE,OAAO,CAAC,MAAM;QACpB,QAAQ;QACR,gBAAgB,EAAE,IAAI,KAAK,CAAC,CAAC,CAAC,CAAC,CAAC,CAAC,CAAC,CAAC,KAAK,GAAG,IAAI;QAC/C,UAAU,EAAE,IAAI,CAAC,OAAO,CAAC,GAAG,CAAC,CAAC,CAAC,EAAE,EAAE,CAAC,CAAC,CAAC,OAAO,CAAC,CAAC,MAAM,CAAC,CAAC,CAAC,EAAe,EAAE,CAAC,OAAO,CAAC,KAAK,QAAQ,CAAC,CAAC;QACjG,YAAY,EAAE,IAAI,CAChB,OAAO,CAAC,GAAG,CAAC,CAAC,CAAC,EAAE,EAAE,CAAC,CAAC,CAAC,SAAS,CAAC,CAAC,MAAM,CAAC,CAAC,CAAC,EAAe,EAAE,CAAC,OAAO,CAAC,KAAK,QAAQ,CAAC,CAClF;QACD,aAAa,EAAE,IAAI,CACjB,OAAO,CAAC,GAAG,CAAC,CAAC,CAAC,EAAE,EAAE,CAAC,CAAC,CAAC,UAAU,CAAC,CAAC,MAAM,CAAC,CAAC,CAAC,EAAe,EAAE,CAAC,OAAO,CAAC,KAAK,QAAQ,CAAC,CACnF;QACD,YAAY,EACV,OAAO,CAAC,MAAM,KAAK,CAAC,CAAC,CAAC,CAAC,CAAC,CAAC,CAAC,CAAC,OAAO,CAAC,MAAM,CAAC,CAAC,CAAC,EAAE,EAAE,CAAC,CAAC,CAAC,YAAY,KAAK,IAAI,CAAC,CAAC,MAAM,GAAG,OAAO,CAAC,MAAM;KACpG,CAAC;AACJ,CAAC;AAED,iFAAiF;AACjF,MAAM,UAAU,WAAW,CAAC,OAA+B;IACzD,MAAM,SAAS,GAA2B,EAAE,CAAC;IAC7C,MAAM,OAAO,GAA2B,EAAE,CAAC;IAC3C,MAAM,cAAc,GAAkC,EAAE,CAAC;IACzD,IAAI,OAA2B,CAAC;IAChC,IAAI,MAA0B,CAAC;IAC/B,KAAK,MAAM,CAAC,IAAI,OAAO,EAAE,CAAC;QACxB,SAAS,CAAC,CAAC,CAAC,OAAO,CAAC,GAAG,CAAC,SAAS,CAAC,CAAC,CAAC,OAAO,CAAC,IAAI,CAAC,CAAC,GAAG,CAAC,CAAC;QACvD,OAAO,CAAC,CAAC,CAAC,SAAS,CAAC,GAAG,CAAC,OAAO,CAAC,CAAC,CAAC,SAAS,CAAC,IAAI,CAAC,CAAC,GAAG,CAAC,CAAC;QACvD,CAAC,cAAc,CAAC,CAAC,CAAC,SAAS,CAAC,KAAK,EAAE,CAAC,CAAC,IAAI,CAAC,CAAC,CAAC,CAAC;QAC7C,IAAI,CAAC,OAAO,IAAI,CAAC,CAAC,EAAE,GAAG,OAAO;YAAE,OAAO,GAAG,CAAC,CAAC,EAAE,CAAC;QAC/C,IAAI,CAAC,MAAM,IAAI,CAAC,CAAC,EAAE,GAAG,MAAM;YAAE,MAAM,GAAG,CAAC,CAAC,EAAE,CAAC;IAC9C,CAAC;IACD,MAAM,cAAc,GAAiC,EAAE,CAAC;IACxD,KAAK,MAAM,CAAC,GAAG,EAAE,IAAI,CAAC,IAAI,MAAM,CAAC,OAAO,CAAC,cAAc,CAAC,EAAE,CAAC;QACzD,cAAc,CAAC,GAAG,CAAC,GAAG,YAAY,CAAC,IAAI,CAAC,CAAC;IAC3C,CAAC;IACD,MAAM,MAAM,GAAG,YAAY,CAAC,OAAO,CAAC,CAAC;IACrC,OAAO;QACL,IAAI,EAAE,OAAO,CAAC,MAAM;QACpB,SAAS;QACT,OAAO;QACP,GAAG,CAAC,OAAO,CAAC,CAAC,CAAC,EAAE,OAAO,EAAE,CAAC,CAAC,CAAC,EAAE,CAAC;QAC/B,GAAG,CAAC,MAAM,CAAC,CAAC,CAAC,EAAE,MAAM,EAAE,CAAC,CAAC,CAAC,EAAE,CAAC;QAC7B,GAAG,CAAC,MAAM,CAAC,gBAAgB,KAAK,SAAS,IAAI,OAAO,CAAC,IAAI,CAAC,CAAC,CAAC,EAAE,EAAE,CAAC,OAAO,CAAC,CAAC,CAAC,OAAO,CAAC,CAAC;YAClF,CAAC,CAAC,EAAE,gBAAgB,EAAE,MAAM,CAAC,gBAAgB,EAAE;YAC/C,CAAC,CAAC,EAAE,CAAC;QACP,GAAG,CAAC,MAAM,CAAC,aAAa,KAAK,SAAS,CAAC,CAAC,CAAC,EAAE,aAAa,EAAE,MAAM,CAAC,aAAa,EAAE,CAAC,CAAC,CAAC,EAAE,CAAC;QACtF,GAAG,CAAC,OAAO,CAAC,MAAM,GAAG,CAAC,CAAC,CAAC,CAAC,EAAE,YAAY,EAAE,MAAM,CAAC,YAAY,EAAE,CAAC,CAAC,CAAC,EAAE,CAAC;QACpE,GAAG,CAAC,MAAM,CAAC,UAAU,KAAK,SAAS,CAAC,CAAC,CAAC,EAAE,UAAU,EAAE,MAAM,CAAC,UAAU,EAAE,CAAC,CAAC,CAAC,EAAE,CAAC;QAC7E,GAAG,CAAC,MAAM,CAAC,YAAY,KAAK,SAAS,CAAC,CAAC,CAAC,EAAE,YAAY,EAAE,MAAM,CAAC,YAAY,EAAE,CAAC,CAAC,CAAC,EAAE,CAAC;QACnF,cAAc;KACf,CAAC;AACJ,CAAC"}
1
+ {"version":3,"file":"ledger.js","sourceRoot":"","sources":["../../../src/cli/evolution/ledger.ts"],"names":[],"mappings":"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"}
@@ -0,0 +1,165 @@
1
+ /**
2
+ * patternLedger — S1 failure-pattern ledger (ADR-0036). Clusters findings by
3
+ * failure mechanism (tool|errorClass|termination) and emits a cluster ONLY when
4
+ * the same mechanism repeats across ≥2 DISTINCT tasks — never one task retried
5
+ * N times. P1: this clusters, it never promotes/applies. taskKey is INSTANCE
6
+ * data, not identity. Empty input ⇒ honest zero, never a throw. Runners under
7
+ * tools/eval READ src/cli/evolution — never the reverse.
8
+ */
9
+ import { createHash } from 'node:crypto';
10
+ import { appendFileSync, existsSync, mkdirSync, readFileSync } from 'node:fs';
11
+ import path from 'node:path';
12
+ /** Mirror of EVOLUTION_PATHS.patternLedger (kept local: a runtime ledger.js
13
+ * import breaks `node --experimental-strip-types`; a test keeps it in sync). */
14
+ export const PATTERN_LEDGER_REL = path.join('.zelari', 'evolution', 'pattern-ledger.jsonl');
15
+ export const DEFAULT_MIN_DISTINCT_TASKS = 2;
16
+ function nonEmpty(v) {
17
+ return typeof v === 'string' && v.trim() !== '' ? v : undefined;
18
+ }
19
+ /** missionTaskId → sha256(normalized taskText) → sessionId. Stable across sessions. */
20
+ export function makeTaskKey(input) {
21
+ const mission = input.missionTaskId?.trim();
22
+ if (mission)
23
+ return mission;
24
+ const normalized = (input.taskText ?? '').trim().replace(/\s+/g, ' ').toLowerCase();
25
+ if (normalized)
26
+ return createHash('sha256').update(normalized).digest('hex').slice(0, 12);
27
+ return input.sessionId;
28
+ }
29
+ /** `tool|errorClass|termination` with 'unknown' fallbacks (kind backs termination). */
30
+ export function clusterKeyFor(input) {
31
+ const tool = nonEmpty(input.tool) ?? 'unknown';
32
+ const errorClass = nonEmpty(input.errorClass) ?? 'unknown';
33
+ const termination = nonEmpty(input.termination) ?? nonEmpty(input.kind) ?? 'unknown';
34
+ return `${tool}|${errorClass}|${termination}`;
35
+ }
36
+ /** harness-repair (DEFAULT) vs model-accommodation. Accommodation requires a
37
+ * skill/prompt change touching NEITHER tool, verification nor observation. */
38
+ export function categorizeCluster(input) {
39
+ const operator = nonEmpty(input.operator) ?? '';
40
+ const haystack = `${input.kind ?? ''} ${operator} ${input.patchHint ?? ''}`.toLowerCase();
41
+ const touchesHarness = /tool|verif|observ|compact|resource|budget|boundary|interrupt|loop|context/.test(haystack);
42
+ if (operator === 'revise_skill' && !touchesHarness)
43
+ return 'model-accommodation';
44
+ return 'harness-repair';
45
+ }
46
+ function deriveTool(f) {
47
+ const ev = f.evidence ?? {};
48
+ const explicit = nonEmpty(ev.toolName) ?? nonEmpty(ev.tool);
49
+ if (explicit)
50
+ return explicit;
51
+ const signal = nonEmpty(f.signal);
52
+ return signal && signal.includes(':') ? signal.slice(0, signal.indexOf(':')) : 'unknown';
53
+ }
54
+ /**
55
+ * Group findings by mechanism; keep only clusters spanning ≥minDistinctTasks
56
+ * distinct tasks. `unmapped` counts findings that produced no cluster (missing
57
+ * taskKey, or a below-threshold cluster). Deterministic: sorted by mechanism
58
+ * key; ids 'c-0001'… in that order.
59
+ */
60
+ export function clusterFailures(findings, opts) {
61
+ const minDistinct = Math.max(1, Math.floor(opts?.minDistinctTasks ?? DEFAULT_MIN_DISTINCT_TASKS));
62
+ const buckets = new Map();
63
+ let unmapped = 0;
64
+ for (const f of findings) {
65
+ const sessions = f.sessions ?? [];
66
+ const taskKey = nonEmpty(f.taskKey) ?? nonEmpty(sessions[0]);
67
+ if (!taskKey) {
68
+ unmapped += 1; // no instance origin → not attributable to a task
69
+ continue;
70
+ }
71
+ const tool = deriveTool(f);
72
+ const errorClass = nonEmpty(f.evidence?.errorClass) ?? 'unknown';
73
+ const termination = nonEmpty(f.evidence?.termination) ?? nonEmpty(f.kind) ?? 'unknown';
74
+ const key = clusterKeyFor({ tool, errorClass, termination, kind: f.kind });
75
+ let b = buckets.get(key);
76
+ if (!b) {
77
+ b = { tool, errorClass, termination, count: 0, findings: 0, sessions: new Set(), taskKeys: new Set(), taskClasses: new Set() };
78
+ buckets.set(key, b);
79
+ }
80
+ b.findings += 1;
81
+ b.count += typeof f.count === 'number' ? f.count : 1;
82
+ for (const s of sessions)
83
+ b.sessions.add(s);
84
+ b.taskKeys.add(taskKey);
85
+ if (!b.operator)
86
+ b.operator = nonEmpty(f.operator);
87
+ if (!b.patchHint)
88
+ b.patchHint = nonEmpty(f.surface);
89
+ const taskClass = nonEmpty(f.taskClass);
90
+ if (taskClass)
91
+ b.taskClasses.add(taskClass);
92
+ if (f.firstAt && (!b.firstAt || f.firstAt < b.firstAt))
93
+ b.firstAt = f.firstAt;
94
+ if (f.lastAt && (!b.lastAt || f.lastAt > b.lastAt))
95
+ b.lastAt = f.lastAt;
96
+ }
97
+ const clusters = [];
98
+ for (const [key, b] of [...buckets.entries()].sort(([a], [c]) => (a < c ? -1 : a > c ? 1 : 0))) {
99
+ if (b.taskKeys.size < minDistinct) {
100
+ unmapped += b.findings; // below threshold — honest zero cluster
101
+ continue;
102
+ }
103
+ clusters.push({
104
+ id: `c-${String(clusters.length + 1).padStart(4, '0')}`,
105
+ key,
106
+ category: categorizeCluster({ kind: b.termination, operator: b.operator, patchHint: b.patchHint ?? key }),
107
+ tool: b.tool,
108
+ errorClass: b.errorClass,
109
+ termination: b.termination,
110
+ count: b.count,
111
+ sessions: [...b.sessions].sort(),
112
+ taskKeys: [...b.taskKeys].sort(),
113
+ distinctTasks: b.taskKeys.size,
114
+ taskClasses: [...b.taskClasses].sort(),
115
+ firstAt: b.firstAt ?? '',
116
+ lastAt: b.lastAt ?? '',
117
+ });
118
+ }
119
+ return { clusters, unmapped };
120
+ }
121
+ export function patternLedgerPath(cwd = process.cwd()) {
122
+ return path.join(cwd, PATTERN_LEDGER_REL);
123
+ }
124
+ /** Append clusters as JSONL (mkdir -p; empty batch is a no-op). Never throws. */
125
+ export async function appendClusters(clusters, cwd = process.cwd()) {
126
+ if (clusters.length === 0)
127
+ return;
128
+ try {
129
+ const file = patternLedgerPath(cwd);
130
+ mkdirSync(path.dirname(file), { recursive: true });
131
+ appendFileSync(file, `${clusters.map((c) => JSON.stringify(c)).join('\n')}\n`, 'utf8');
132
+ }
133
+ catch {
134
+ // fail-open telemetry — a ledger write must never break a run
135
+ }
136
+ }
137
+ /** Tolerant replay: parse every line, skip corrupt ones. Missing file ⇒ []. */
138
+ export async function readClusters(cwd = process.cwd()) {
139
+ const file = patternLedgerPath(cwd);
140
+ if (!existsSync(file))
141
+ return [];
142
+ let raw;
143
+ try {
144
+ raw = readFileSync(file, 'utf8');
145
+ }
146
+ catch {
147
+ return [];
148
+ }
149
+ const out = [];
150
+ for (const line of raw.split('\n')) {
151
+ const trimmed = line.trim();
152
+ if (!trimmed)
153
+ continue;
154
+ try {
155
+ const parsed = JSON.parse(trimmed);
156
+ if (parsed && typeof parsed === 'object' && typeof parsed.key === 'string')
157
+ out.push(parsed);
158
+ }
159
+ catch {
160
+ // corrupt line — skip (tolerant replay)
161
+ }
162
+ }
163
+ return out;
164
+ }
165
+ //# sourceMappingURL=patternLedger.js.map
@@ -0,0 +1 @@
1
+ {"version":3,"file":"patternLedger.js","sourceRoot":"","sources":["../../../src/cli/evolution/patternLedger.ts"],"names":[],"mappings":"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"}
@@ -38,6 +38,10 @@ import { honestUnevaluatedPayload } from '../kraken/verifyHonestVerdict.js';
38
38
  // t78 (ADR-0033 slice): runtime general⇒verify obligation on the task tool path.
39
39
  import { hydrateTaskVerifyDebtFromSpine, outcomeMemoryAllowed, taskVerifyObligation } from '../tools/taskTool.js';
40
40
  import { bindVerifyDebtSpineEmit, flushVerifyDebtSpine, formatHeadlessVerifyDebtNotice } from '../tools/verifyDebtSpine.js';
41
+ // WS7 slice 4b (t139): the tool-side session sink (ToolContext.emitSessionEvent)
42
+ // bound to THIS run's spine, so file.* telemetry and the permission/decision
43
+ // events stop being dormant on the headless host path.
44
+ import { lateSessionSink, spineSessionSink } from '../safety/sessionSink.js';
41
45
  import { writeCompletionProofDetailed } from '../kraken/completionProof.js';
42
46
  import { enforceRequiredProofPersistence } from '../kraken/completionProofPersist.js';
43
47
  import { promoteOpsKnowledgeSafe, skippedOpsKnowledgeResult } from '../memory/opsKnowledge.js';
@@ -45,6 +49,7 @@ import { formatCheckProposalNotice } from '../memory/repeatCheck.js';
45
49
  import { nativePackEnabled } from '../kraken/nativeVerification.js';
46
50
  import { runAdvisoryVerifierReview } from '../kraken/verifierLifecycle.js';
47
51
  import { buildModelContext, resourceStatusTail } from '../budget/modelContextBuilder.js';
52
+ import { buildOnePager } from '../memory/onePager.js';
48
53
  import { recordCompactionMetrics } from '../metrics.js';
49
54
  import { flushMessageUsage, recordMessageUsage } from '../budget/messageUsage.js';
50
55
  import { openHeadlessSpine, seedHeadlessModelHistory, sessionStartedEvent } from '../headlessSpine.js';
@@ -263,8 +268,18 @@ export async function runOneTurn(opts, provider, model, providerStream, extras)
263
268
  // --permissions yolo (full allow), ZELARI_AUTO=1 (auto-allow ask rules),
264
269
  // ZELARI_PERMISSION_EXECUTE=deny (hard lockdown).
265
270
  const { defaultPermissionPolicy } = await import('../safety/toolPermissions.js');
271
+ // WS7 slice 4b (t139): this turn's tool-side session sink. The spine writer is
272
+ // opened a few lines BELOW (`openHeadlessSpine`) while the registry — and the
273
+ // tools the harness will dispatch through it — are built HERE, so the sink is
274
+ // late-bound through a holder (same pattern as `spineHolder` for memory
275
+ // telemetry). Before the binding runs, tools see no sink and emit nothing;
276
+ // after it, file.* telemetry and the decision events (permission.denied /
277
+ // permission.asked / auto_approve.granted / jail.blocked) land on THIS run's
278
+ // spine, where replay and `buildProjection` can see them.
279
+ const toolSpineSink = {};
266
280
  const { registry: toolRegistry } = createBuiltinToolRegistry({
267
281
  root: cwd,
282
+ sessionEventSink: lateSessionSink(toolSpineSink),
268
283
  onTentacleEvent: (ev) => emitEvent(ev),
269
284
  planMode: planModeFromOpts(opts),
270
285
  gauntletParent: Boolean(opts.gauntlet) && !planModeFromOpts(opts),
@@ -318,6 +333,10 @@ export async function runOneTurn(opts, provider, model, providerStream, extras)
318
333
  // K1.5 / F5: bind debt emit to this turn's spine, then merge un-cleared
319
334
  // opens from the log (do not wipe — callers/tests may have seeded debt).
320
335
  bindVerifyDebtSpineEmit(async (input) => ({ seq: await spine.appendEvent(input) }));
336
+ // WS7 slice 4b (t139): now that the spine exists, make the tool-side sink live
337
+ // for the rest of the turn. Same writer as the debt emit above — one spine, one
338
+ // seq sequence, no second log.
339
+ toolSpineSink.current = spineSessionSink(spine);
321
340
  // Fresh sessions have no prior debt; only `--resume` must replay the log
322
341
  // (and must not race the just-opened writer on win32).
323
342
  if (opts.resumeSessionId) {
@@ -501,10 +520,18 @@ export async function runOneTurn(opts, provider, model, providerStream, extras)
501
520
  // multi-turn binding. The legacy --history JSON is only the one-shot
502
521
  // import source (or the declared fallback when the spine is degraded).
503
522
  await spine.beginResourceTurn();
523
+ // S4: volatile working set — one build per turn (no compact recap live; the
524
+ // budget already lands compactSummary in history when a compaction happens).
525
+ const onePager = await buildOnePager({
526
+ cwd,
527
+ memory: nativeMemory ?? null,
528
+ skipCompactRecap: true,
529
+ });
504
530
  const modelContext = await buildModelContext({
505
531
  fallbackHistory: seededHistory.history,
506
532
  session: spine.spine,
507
533
  resourceSnapshot: spine.spine.latestResourceSnapshot(),
534
+ volatileOnePager: onePager,
508
535
  phase: opts.phase ?? 'build',
509
536
  model,
510
537
  provider,
@@ -556,7 +583,10 @@ export async function runOneTurn(opts, provider, model, providerStream, extras)
556
583
  cwd,
557
584
  providerStream,
558
585
  buildLiveness: { mutationRequired: wantWrites, maxRecoveries: 2 },
559
- requestTail: () => resourceStatusTail(spine.spine.latestResourceSnapshot()),
586
+ requestTail: () => [
587
+ ...resourceStatusTail(spine.spine.latestResourceSnapshot()),
588
+ ...onePager,
589
+ ],
560
590
  // 2.6 Phase 3: host-owned pre-dispatch resource gate (doc section 11.3).
561
591
  // Advisory by default; ZELARI_RESOURCE_ENFORCEMENT=protected enables the
562
592
  // protected verification reserve. Degrade-and-stop (null gate = allow).