@sema-agent/core 7.15.0 → 7.17.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 (287) hide show
  1. package/CHANGELOG.md +202 -0
  2. package/dist/agents/builtin-agents.d.ts +3 -3
  3. package/dist/agents/cross-session-envelope.d.ts +0 -1
  4. package/dist/agents/cross-session-envelope.js +0 -1
  5. package/dist/agents/peer-notices.d.ts +0 -9
  6. package/dist/agents/peer-notices.js +0 -63
  7. package/dist/agents/subagent.js +7 -15
  8. package/dist/brain/request-params.d.ts +2 -2
  9. package/dist/config/defaults.d.ts +0 -7
  10. package/dist/config/defaults.js +0 -2
  11. package/dist/core/artifact-host.d.ts +218 -0
  12. package/dist/core/artifact-host.js +92 -0
  13. package/dist/core/ask-origin.d.ts +29 -3
  14. package/dist/core/ask-origin.js +17 -9
  15. package/dist/core/ask-question.d.ts +25 -0
  16. package/dist/core/ask-question.js +4 -0
  17. package/dist/core/ask-unresolvable-notice.d.ts +30 -21
  18. package/dist/core/ask-unresolvable-notice.js +16 -8
  19. package/dist/core/auto-compaction.d.ts +10 -10
  20. package/dist/core/auto-mode-arming.d.ts +2 -2
  21. package/dist/core/background-agent-store.d.ts +5 -5
  22. package/dist/core/background-shell.d.ts +1 -1
  23. package/dist/core/checkpoint-execution-record.d.ts +0 -3
  24. package/dist/core/checkpoint-execution-record.js +0 -4
  25. package/dist/core/checkpoint-store.d.ts +71 -99
  26. package/dist/core/checkpoint-store.js +9 -16
  27. package/dist/core/context-edit.d.ts +36 -104
  28. package/dist/core/context-edit.js +37 -60
  29. package/dist/core/effective-path-target.d.ts +68 -8
  30. package/dist/core/effective-path-target.js +42 -30
  31. package/dist/core/engine-notice.d.ts +46 -32
  32. package/dist/core/env-budget.d.ts +31 -0
  33. package/dist/core/env-budget.js +39 -0
  34. package/dist/core/exec-output-tail.d.ts +5 -5
  35. package/dist/core/file-history-store.js +3 -6
  36. package/dist/core/fs-write-gate-policy.d.ts +1 -1
  37. package/dist/core/fs-write-gate-policy.js +3 -3
  38. package/dist/core/gate-lanes.js +9 -15
  39. package/dist/core/governance-codes.d.ts +1 -1
  40. package/dist/core/governance-codes.js +4 -0
  41. package/dist/core/hands-band.d.ts +1 -1
  42. package/dist/core/hooks.d.ts +18 -17
  43. package/dist/core/lsp-session.d.ts +1 -1
  44. package/dist/core/lsp.d.ts +1 -1
  45. package/dist/core/lsp.js +5 -4
  46. package/dist/core/mcp.d.ts +5 -5
  47. package/dist/core/mcp.js +4 -48
  48. package/dist/core/memory-engine/delegation-settlement.d.ts +37 -12
  49. package/dist/core/memory-engine/delegation-settlement.js +128 -39
  50. package/dist/core/memory-engine/engine.d.ts +9 -8
  51. package/dist/core/memory-engine/engine.js +115 -120
  52. package/dist/core/memory-engine/file-backend.d.ts +17 -5
  53. package/dist/core/memory-engine/file-backend.js +78 -34
  54. package/dist/core/memory-engine/index.d.ts +2 -2
  55. package/dist/core/memory-engine/index.js +2 -2
  56. package/dist/core/memory-engine/layout.d.ts +152 -54
  57. package/dist/core/memory-engine/layout.js +441 -104
  58. package/dist/core/memory-engine/types.d.ts +8 -3
  59. package/dist/core/memory-engine/types.js +5 -0
  60. package/dist/core/memory-recall.d.ts +0 -8
  61. package/dist/core/memory.d.ts +1 -1
  62. package/dist/core/oracle-isolation.js +2 -2
  63. package/dist/core/parent-spec-seat.d.ts +66 -0
  64. package/dist/core/parent-spec-seat.js +47 -0
  65. package/dist/core/permission-rule-model.d.ts +11 -6
  66. package/dist/core/permission-rule-model.js +53 -37
  67. package/dist/core/permission-rules.js +8 -3
  68. package/dist/core/protocol-naming.d.ts +2 -2
  69. package/dist/core/remote-env.d.ts +1 -1
  70. package/dist/core/retired-keys.d.ts +19 -0
  71. package/dist/core/retired-keys.js +15 -0
  72. package/dist/core/runner/abort-race.d.ts +3 -3
  73. package/dist/core/runner/active-skill-scope.d.ts +2 -2
  74. package/dist/core/runner/active-skill-scope.js +3 -3
  75. package/dist/core/runner/assemble-result.d.ts +42 -40
  76. package/dist/core/runner/assemble-result.js +5 -4
  77. package/dist/core/runner/checkpoint-scope.d.ts +4 -4
  78. package/dist/core/runner/clock-and-limits.d.ts +3 -3
  79. package/dist/core/runner/compaction-call-options.d.ts +35 -99
  80. package/dist/core/runner/compaction-knobs.d.ts +4 -4
  81. package/dist/core/runner/compaction-seams.d.ts +5 -5
  82. package/dist/core/runner/contracts.d.ts +232 -233
  83. package/dist/core/runner/decide-continuation.d.ts +6 -6
  84. package/dist/core/runner/denial-limit-arms.d.ts +8 -8
  85. package/dist/core/runner/derived-route-fallback.d.ts +2 -2
  86. package/dist/core/runner/gate-exit.d.ts +6 -6
  87. package/dist/core/runner/gate-exit.js +15 -1
  88. package/dist/core/runner/git-status-frame.d.ts +7 -7
  89. package/dist/core/runner/halt-attribution.d.ts +35 -0
  90. package/dist/core/runner/halt-attribution.js +16 -0
  91. package/dist/core/runner/inherited-ask-grants.d.ts +6 -6
  92. package/dist/core/runner/memory-capture-optout.d.ts +1 -1
  93. package/dist/core/runner/memory-consolidation-driver.d.ts +4 -4
  94. package/dist/core/runner/memory-consolidation.d.ts +6 -8
  95. package/dist/core/runner/memory-consolidation.js +0 -1
  96. package/dist/core/runner/park-commit.d.ts +6 -6
  97. package/dist/core/runner/permission-rule-lanes.d.ts +19 -19
  98. package/dist/core/runner/prepare-acquire-reconcile.d.ts +4 -4
  99. package/dist/core/runner/prepare-artifact.d.ts +53 -0
  100. package/dist/core/runner/prepare-artifact.js +77 -0
  101. package/dist/core/runner/prepare-ask-lane.d.ts +3 -3
  102. package/dist/core/runner/prepare-boundary-parks.d.ts +3 -3
  103. package/dist/core/runner/prepare-caps-and-workflow.d.ts +9 -7
  104. package/dist/core/runner/prepare-caps-and-workflow.js +2 -3
  105. package/dist/core/runner/prepare-config-doors.d.ts +24 -24
  106. package/dist/core/runner/prepare-config-doors.js +5 -2
  107. package/dist/core/runner/prepare-context-lane.d.ts +8 -8
  108. package/dist/core/runner/prepare-context-lane.js +2 -13
  109. package/dist/core/runner/prepare-defer-classify.d.ts +2 -2
  110. package/dist/core/runner/prepare-delegation-surface.d.ts +1 -1
  111. package/dist/core/runner/prepare-file-history.d.ts +3 -3
  112. package/dist/core/runner/prepare-file-history.js +3 -52
  113. package/dist/core/runner/prepare-gate-stations.d.ts +5 -5
  114. package/dist/core/runner/prepare-hands-readface.d.ts +35 -38
  115. package/dist/core/runner/prepare-hands-readface.js +3 -2
  116. package/dist/core/runner/prepare-inherited-gate.d.ts +9 -6
  117. package/dist/core/runner/prepare-inherited-gate.js +7 -8
  118. package/dist/core/runner/prepare-listings.d.ts +3 -3
  119. package/dist/core/runner/prepare-lsp.d.ts +3 -3
  120. package/dist/core/runner/prepare-memory-engine-session.d.ts +5 -5
  121. package/dist/core/runner/prepare-memory.d.ts +4 -6
  122. package/dist/core/runner/prepare-memory.js +10 -9
  123. package/dist/core/runner/prepare-offload-wrappers.d.ts +2 -2
  124. package/dist/core/runner/prepare-park-ask.d.ts +6 -6
  125. package/dist/core/runner/prepare-policy-chain.d.ts +7 -7
  126. package/dist/core/runner/prepare-policy-chain.js +15 -30
  127. package/dist/core/runner/prepare-prompt-assembly.js +1 -1
  128. package/dist/core/runner/prepare-prompt-inputs.d.ts +5 -5
  129. package/dist/core/runner/prepare-protocol-tools.d.ts +1 -1
  130. package/dist/core/runner/prepare-question-face.d.ts +4 -4
  131. package/dist/core/runner/prepare-run-refs.d.ts +11 -11
  132. package/dist/core/runner/prepare-safety-scan.d.ts +2 -2
  133. package/dist/core/runner/prepare-suspend-saga.d.ts +4 -4
  134. package/dist/core/runner/prepare-suspend-saga.js +0 -2
  135. package/dist/core/runner/prepare-task.d.ts +12 -12
  136. package/dist/core/runner/prepare-task.js +10 -9
  137. package/dist/core/runner/prepare-tool-disclosure-mount.d.ts +2 -3
  138. package/dist/core/runner/prepare-wiring-manifest.d.ts +4 -4
  139. package/dist/core/runner/prepare-wiring-manifest.js +9 -7
  140. package/dist/core/runner/prepare-workspace-restore.d.ts +1 -1
  141. package/dist/core/runner/remote-env-retry.d.ts +3 -3
  142. package/dist/core/runner/resume-admission.d.ts +1 -1
  143. package/dist/core/runner/resume-admission.js +2 -1
  144. package/dist/core/runner/resume-claim.d.ts +1 -1
  145. package/dist/core/runner/resume-internals-and-config.d.ts +1 -1
  146. package/dist/core/runner/resume-internals-and-config.js +4 -0
  147. package/dist/core/runner/resume-policy-outcome.d.ts +1 -1
  148. package/dist/core/runner/resume-preflight.d.ts +1 -1
  149. package/dist/core/runner/resume-review-outcome.d.ts +1 -1
  150. package/dist/core/runner/retired-runner-deps.d.ts +3 -0
  151. package/dist/core/runner/retired-runner-deps.js +7 -0
  152. package/dist/core/runner/run-brain-sinks.d.ts +1 -1
  153. package/dist/core/runner/run-clock-and-content.d.ts +4 -4
  154. package/dist/core/runner/run-compaction-machinery.d.ts +3 -3
  155. package/dist/core/runner/run-git-lane.d.ts +1 -1
  156. package/dist/core/runner/run-harness-handlers.d.ts +2 -2
  157. package/dist/core/runner/run-harness-handlers.js +2 -3
  158. package/dist/core/runner/run-identity-wiring.d.ts +4 -4
  159. package/dist/core/runner/run-leg.d.ts +3 -3
  160. package/dist/core/runner/run-notification-lane.d.ts +2 -2
  161. package/dist/core/runner/run-reasoning-seat.d.ts +2 -2
  162. package/dist/core/runner/run-settle-and-teardown.d.ts +5 -5
  163. package/dist/core/runner/run-settle-and-teardown.js +3 -1
  164. package/dist/core/runner/run-telemetry-and-budget-seats.d.ts +2 -2
  165. package/dist/core/runner/run-terminal-adoption.d.ts +5 -5
  166. package/dist/core/runner/runtask.d.ts +14 -14
  167. package/dist/core/runner/session-file-state-replay.d.ts +3 -3
  168. package/dist/core/runner/session-file-state-replay.js +3 -3
  169. package/dist/core/runner/session-rule-policy.d.ts +2 -2
  170. package/dist/core/runner/session-rule-policy.js +3 -4
  171. package/dist/core/runner/steer-admission.d.ts +2 -2
  172. package/dist/core/runner/stream-halt-verbs.d.ts +1 -1
  173. package/dist/core/runner/stream-halt-verbs.js +1 -1
  174. package/dist/core/runner/stream-reap.d.ts +1 -1
  175. package/dist/core/runner/stream-steer-verb.js +1 -4
  176. package/dist/core/runner/synthetic-tools.d.ts +8 -8
  177. package/dist/core/runner/teardown-bounded.d.ts +2 -2
  178. package/dist/core/runner/tool-defer-gate.d.ts +1 -1
  179. package/dist/core/runner/tool-disclosure.d.ts +33 -33
  180. package/dist/core/runner/tool-end-body.d.ts +3 -3
  181. package/dist/core/runner/tool-face-overlay.d.ts +2 -2
  182. package/dist/core/runner/tool-output-projection.d.ts +2 -2
  183. package/dist/core/runner/turn-attachments.d.ts +53 -53
  184. package/dist/core/runner/usage-accounting.d.ts +4 -4
  185. package/dist/core/runner/workspace-path.d.ts +1 -1
  186. package/dist/core/runner/workspace-path.js +3 -0
  187. package/dist/core/runner-deps.d.ts +30 -49
  188. package/dist/core/safe-notify.d.ts +1 -1
  189. package/dist/core/sensitive-path-policy.d.ts +1 -1
  190. package/dist/core/sensitive-path-policy.js +4 -4
  191. package/dist/core/session.d.ts +2 -2
  192. package/dist/core/skill-tool-specifier.d.ts +1 -1
  193. package/dist/core/skills-directory.d.ts +1 -1
  194. package/dist/core/store-contracts/checkpoint-store-contract.js +1 -1
  195. package/dist/core/strategy-store.d.ts +8 -11
  196. package/dist/core/task-event.d.ts +20 -17
  197. package/dist/core/task-limits.d.ts +1 -1
  198. package/dist/core/task-notification.d.ts +5 -5
  199. package/dist/core/task-registry-agent.d.ts +5 -5
  200. package/dist/core/task-registry-monitor.d.ts +2 -2
  201. package/dist/core/task-registry-shared.d.ts +27 -27
  202. package/dist/core/task-registry-shared.js +3 -13
  203. package/dist/core/task-registry.d.ts +8 -8
  204. package/dist/core/task-result.d.ts +37 -37
  205. package/dist/core/task-spec.d.ts +5 -5
  206. package/dist/core/task-stream.d.ts +16 -11
  207. package/dist/core/tool-catalog-entries.d.ts +1 -0
  208. package/dist/core/tool-catalog-entries.js +5 -0
  209. package/dist/core/tool-conformance.d.ts +0 -2
  210. package/dist/core/tool-conformance.js +1 -3
  211. package/dist/core/tool-errors.d.ts +5 -0
  212. package/dist/core/tool-errors.js +1 -0
  213. package/dist/core/tool-policy.d.ts +51 -22
  214. package/dist/core/tool-policy.js +28 -5
  215. package/dist/core/tool-result-budget.d.ts +1 -1
  216. package/dist/core/tool-result-store.d.ts +11 -11
  217. package/dist/core/tool-spec.d.ts +34 -38
  218. package/dist/core/tools.d.ts +2 -2
  219. package/dist/core/trace.d.ts +12 -15
  220. package/dist/core/untrusted-text.d.ts +1 -1
  221. package/dist/core/wiring-manifest.d.ts +4 -3
  222. package/dist/core/workflow-journal-store.d.ts +11 -11
  223. package/dist/engine/execution-env/node-execution-env.d.ts +3 -2
  224. package/dist/engine/execution-env/node-execution-env.js +4 -2
  225. package/dist/engine/harness/agent-harness.d.ts +47 -4
  226. package/dist/engine/harness/agent-harness.js +52 -9
  227. package/dist/engine/llm/types.d.ts +1 -1
  228. package/dist/engine/loop/agent-loop.js +15 -8
  229. package/dist/engine/loop/types.d.ts +5 -0
  230. package/dist/index.d.ts +21 -16
  231. package/dist/index.js +17 -12
  232. package/dist/internal/harness.d.ts +1 -0
  233. package/dist/orchestration/run-spec.d.ts +3 -0
  234. package/dist/orchestration/run-spec.js +3 -3
  235. package/dist/orchestration/run-workflow-tool.d.ts +12 -6
  236. package/dist/orchestration/run-workflow-tool.js +23 -5
  237. package/dist/orchestration/workflow-primitives.d.ts +4 -2
  238. package/dist/orchestration/workflow-primitives.js +1 -4
  239. package/dist/orchestration/workflow-types.d.ts +34 -4
  240. package/dist/orchestration/workflow-types.js +2 -0
  241. package/dist/orchestration/workflow.d.ts +39 -7
  242. package/dist/orchestration/workflow.js +234 -113
  243. package/dist/prompt-assembly/assemble.d.ts +2 -2
  244. package/dist/prompt-assembly/assemble.js +9 -9
  245. package/dist/prompt-assembly/composer.d.ts +6 -7
  246. package/dist/prompt-assembly/composer.js +10 -10
  247. package/dist/prompt-assembly/epoch.js +1 -1
  248. package/dist/prompt-assembly/event-registry.d.ts +0 -21
  249. package/dist/prompt-assembly/packs/sema-default.js +30 -30
  250. package/dist/prompt-assembly/types.d.ts +14 -14
  251. package/dist/prompts/coordinator.d.ts +0 -13
  252. package/dist/prompts/coordinator.js +0 -3
  253. package/dist/stores/file/checkpoint-store.js +1 -5
  254. package/dist/stores/file/file-history-store.js +2 -2
  255. package/dist/stores/file/permission-rule-store.d.ts +4 -35
  256. package/dist/stores/file/permission-rule-store.js +4 -148
  257. package/dist/tools/artifact/artifact-text.d.ts +62 -0
  258. package/dist/tools/artifact/artifact-text.js +68 -0
  259. package/dist/tools/artifact/artifact-tool.d.ts +52 -0
  260. package/dist/tools/artifact/artifact-tool.js +351 -0
  261. package/dist/tools/artifact/local-stub.d.ts +26 -0
  262. package/dist/tools/artifact/local-stub.js +296 -0
  263. package/dist/tools/fs/bash-readonly-classifier.d.ts +114 -48
  264. package/dist/tools/fs/bash-readonly-classifier.js +171 -60
  265. package/dist/tools/fs/encoding.d.ts +31 -40
  266. package/dist/tools/fs/fs-bash.d.ts +49 -45
  267. package/dist/tools/fs/fs-bash.js +19 -27
  268. package/dist/tools/fs/fs-pdf.d.ts +8 -8
  269. package/dist/tools/fs/fs-search-tools.d.ts +4 -4
  270. package/dist/tools/fs/fs-search-tools.js +5 -2
  271. package/dist/tools/fs/fs-shared.d.ts +146 -158
  272. package/dist/tools/fs/fs-shared.js +3 -11
  273. package/dist/tools/fs/fs-write.d.ts +8 -8
  274. package/dist/tools/fs/gh-rate-limit.d.ts +13 -14
  275. package/dist/tools/fs/index.d.ts +78 -78
  276. package/dist/tools/fs/index.js +4 -1
  277. package/dist/tools/fs/notebook.d.ts +24 -25
  278. package/dist/tools/fs/pdf.d.ts +3 -3
  279. package/dist/tools/fs/read-deny.d.ts +22 -22
  280. package/dist/tools/fs/read-face.d.ts +21 -24
  281. package/dist/tools/fs/repo-map.d.ts +8 -8
  282. package/dist/tools/fs/safety.d.ts +233 -130
  283. package/dist/tools/fs/safety.js +131 -31
  284. package/dist/tools/fs/search.d.ts +63 -71
  285. package/dist/tools/fs/search.js +8 -6
  286. package/package.json +6 -2
  287. package/test/export-surface.snapshot.json +119 -39
@@ -1,37 +1,38 @@
1
1
  import type { AssistantMessage } from "../../internal/llm.js";
2
2
  import type { NestedUsage, PausedCause, TaskResult, TaskSpec, TerminalCause } from "../types.js";
3
+ import type { HaltConsumption } from "../../internal/harness.js";
3
4
  /** Per-task usage/cost accumulator (filled across the run loop, surfaced as `TaskResult.stats`). */
4
5
  export interface Stats {
5
6
  turns: number;
6
7
  tokens: number;
7
- /** design/97 CORE-8 (②): total tool calls executed (one per `tool_start`). Spread into `TaskResult.stats`. */
8
+ /** Total tool calls executed (one per `tool_start`). Spread into `TaskResult.stats`. */
8
9
  toolCalls: number;
9
- /** RB-457-a: prompt tokens that MISSED the cache (Anthropic-protocol `input_tokens` shape). */
10
+ /** Prompt tokens that MISSED the cache (Anthropic-protocol `input_tokens` shape). */
10
11
  promptTokens: number;
11
12
  cachedTokens: number;
12
13
  cacheWriteTokens: number;
13
14
  cacheWriteTokensLong: number;
14
15
  outputTokens: number;
15
16
  cacheHitRate?: number;
16
- /** RB-457-a: cache-INCLUSIVE prompt total (`promptTokens + cachedTokens + cacheWriteTokens*`) — the
17
+ /** Cache-INCLUSIVE prompt total (`promptTokens + cachedTokens + cacheWriteTokens*`) — the
17
18
  * billing/window/hit-rate denominator. Required (not derived) so a new accumulation site that forgets
18
19
  * it fails the type check instead of silently reporting a total short by its own leg. */
19
20
  totalInputTokens: number;
20
21
  costMicroUsd: number;
21
- /** #692 C-b — present (`true`) when at least one model round of this leg reported NO usage frame (the brain's
22
+ /** Present (`true`) when at least one model round of this leg reported NO usage frame (the brain's
22
23
  * own `usageMissing` mark on the assistant message: an aborted / errored / usage-less provider reply). The
23
24
  * numeric fields stay required and stay what was COUNTED — with this key present they are a LOWER BOUND,
24
25
  * not a measurement ("0 is unknown, not free"). Absent ⇔ every round reported usage. */
25
26
  usageMissing?: true;
26
27
  nested?: NestedUsage;
27
- /** Post-task memory-consolidation usage (design/41); set after the result is assembled. Kept out of
28
+ /** Post-task memory-consolidation usage; set after the result is assembled. Kept out of
28
29
  * the budget gate (`overBudget` reads `costMicroUsd`/`tokens`, never this). */
29
30
  memory?: {
30
31
  tokens: number;
31
32
  costMicroUsd: number;
32
33
  applied: number;
33
34
  };
34
- /** design/91: human-review burden (design/89 §2.4 C2). Wall-clock approval-gate wait + count, bucketed by
35
+ /** Human-review burden. Wall-clock approval-gate wait + count, bucketed by
35
36
  * `gate.kind`, accumulated across resume legs. Set by the run loop from the per-task human-review
36
37
  * accumulator (synchronous `resolveAsk` timing + durable resume latency). **NOT an LLM cost** — never
37
38
  * folded into `costMicroUsd`/`costBreakdown`/the budget gate (same budget-excluded treatment as `memory`).
@@ -65,21 +66,21 @@ export interface Stats {
65
66
  segment: string;
66
67
  }>;
67
68
  };
68
- /** design/80 D-E-core (Part B): within-task compaction LLM cost (micro-USD), accumulated by
69
+ /** Within-task compaction LLM cost (micro-USD), accumulated by
69
70
  * `recordCompactionUsage` as a SEPARATE running total because that cost IS folded into `costMicroUsd`
70
71
  * (so it can't be re-derived from `costMicroUsd` alone). The {@link costBreakdown.compactionMicroUsd}
71
72
  * source. Run-loop internal — not a public `TaskResult.stats` field. */
72
73
  compactionMicroUsd?: number;
73
74
  /**
74
- * design/80 D-E-core (Part B): a thin FINANCE TAXONOMY of the LLM-derived costs the engine actually
75
+ * A thin FINANCE TAXONOMY of the LLM-derived costs the engine actually
75
76
  * prices, decomposing the task's spend into report categories (no new persisted structure — derived from
76
77
  * the cost sources that already exist). CORE = LLM-token-derived ONLY; the SERVICE adds the infra axes it
77
78
  * owns (tool-call / sandbox-walltime / egress — it has the k8s cost data) and composes them with this.
78
79
  * Each category is ≥ 0 and the parts reconcile to the independently-summed LLM total
79
80
  * (`llmRoot + nestedSubagent + compaction` — `memory` is a separate, budget-excluded line, see its doc).
80
81
  * Filled in assembleResult for `llmRoot`/`nestedSubagent`/`compaction`; the `memoryConsolidation` line is
81
- * permanently 0 since design/157 B19 retired the runner-integrated consolidation pass (field kept — it is
82
- * public stats contract; an engine-plane re-mount per design/138 §7 would fill it again).
82
+ * permanently 0 since B19 retired the runner-integrated consolidation pass (field kept — it is
83
+ * public stats contract; an engine-plane re-mount would fill it again).
83
84
  */
84
85
  costBreakdown?: {
85
86
  /** Root-agent LLM cost (micro-USD): `costMicroUsd` MINUS the sub-categories already folded into it
@@ -97,29 +98,29 @@ export interface Stats {
97
98
  compactionMicroUsd: number;
98
99
  };
99
100
  }
100
- /** design/164 — the two cumulative budget ceilings a task can trip. Tokens outrank cost when both are
101
+ /** The two cumulative budget ceilings a task can trip. Tokens outrank cost when both are
101
102
  * over at the same boundary. */
102
103
  export type BudgetAxis = "tokens" | "cost";
103
104
  /**
104
105
  * The terminal-state flags the run loop hands {@link assembleResult} — the typed contract between the
105
- * loop and result assembly (council design/34 ⑤: exported so it's grep-able and tests can construct it).
106
+ * loop and result assembly (exported so it's grep-able and tests can construct it).
106
107
  */
107
108
  export interface ResultFlags {
108
109
  threw: unknown;
109
- /** #499 — the run's ENGINE-minted identity (`Prepared.runId`), echoed verbatim on
110
+ /** The run's ENGINE-minted identity (`Prepared.runId`), echoed verbatim on
110
111
  * `TaskResult.runId`. Pure pass-through on every terminal: assembly neither mints nor derives it
111
112
  * (a caller reaching assembly at all has completed prepare, so the value exists), and a
112
113
  * hand-constructed flags bag without one simply produces a result without one. */
113
114
  runId?: string;
114
- /** design/99 MF-25: the EFFECTIVE (resolved) model id that served the task — echoed on `TaskResult.model`. */
115
+ /** The EFFECTIVE (resolved) model id that served the task — echoed on `TaskResult.model`. */
115
116
  model?: string;
116
- /** RB-368: some spend was accounted while the serving model had NO configured price table
117
+ /** Some spend was accounted while the serving model had NO configured price table
117
118
  * (no `RunnerDeps.pricing` entry, no `Model.cost`). The numeric total is then a fabricated
118
119
  * undercount — `stats.costMicroUsd`/`costBreakdown` are OMITTED from the public result instead of
119
120
  * reporting a 0 indistinguishable from "declared free". The internal accumulator (budget gate's
120
121
  * coordinate) is untouched. */
121
122
  unpricedSpend?: boolean;
122
- /** RB-430-a (design/101 §E19): prepare-time rewind disclosures to echo on `TaskResult.rewindNotes`.
123
+ /** Prepare-time rewind disclosures to echo on `TaskResult.rewindNotes`.
123
124
  * Pure pass-through — assembly neither adds nor filters (a rewind that FAILED never reaches here; it
124
125
  * throws at prepare and lands in the `threw` slot as a terminal errorCode). */
125
126
  rewindNotes?: TaskResult["rewindNotes"];
@@ -134,37 +135,36 @@ export interface ResultFlags {
134
135
  * path the terminal is `completed`, and this is what tells that completion apart from a natural
135
136
  * one — the model did not finish; the person stopped it and the run awaits their direction). */
136
137
  haltedOnUserRejection?: boolean;
137
- /** design/373 (#504) a `TaskStream.halt` (the bare user interrupt, CC Esc form) was accepted
138
- * while the run was live; echoed on `TaskResult.haltedByUser`. Pure pass-through on every
139
- * terminal (the sibling `haltedOnUserRejection` law: the fact is about the leg that ran) PLUS
140
- * one status decision it owns (slot 9.7 below): a run whose ONLY stop was this halt reads
141
- * `"completed"`, never the `!final` failure and never the aborted terminal whether the halt
142
- * landed before the model said anything (empty result) or cut a turn whose partial text the
143
- * brain kept (that text IS the result). The person stopped the run, which is the verb working,
144
- * not a defect. A REAL abort/limit that also fired still owns the terminal above it. */
145
- userHalted?: boolean;
146
- /** design/174 final-round: call ids of answered-but-never-collected questions, echoed on
138
+ /** the harness's STATEMENT of what the run's halt did (see `HaltConsumption`):
139
+ * the loop's report that the halt's cut settled the final turn, and/or the boundary consult that
140
+ * stopped the loop for the halt's request. This is the ONLY input to `TaskResult.haltedByUser`
141
+ * (`haltConsumed`, halt-attribution.ts) and to slot 9.7 the assembly never infers causation from the
142
+ * final's shape or from the verb's acceptance. A halt that was accepted but consumed nothing (the run
143
+ * ended for its own reason first) leaves this empty: the original terminal stands and the seat is
144
+ * NOT signed (the settle lane mints `task.halt_unconsumed` for it). */
145
+ haltConsumption?: HaltConsumption;
146
+ /** Call ids of answered-but-never-collected questions, echoed on
147
147
  * `TaskResult.strandedHumanAnswers`. Pure pass-through; empty/absent ⇒ the field is omitted. The
148
148
  * optional `onError` alert is NOT the disclosure — this mandatory result face is. */
149
149
  strandedHumanAnswers?: TaskResult["strandedHumanAnswers"];
150
- /** RB-439-a: the run's remote-workspace lifecycle failures, echoed on `TaskResult.remoteEnvFailures`.
150
+ /** The run's remote-workspace lifecycle failures, echoed on `TaskResult.remoteEnvFailures`.
151
151
  * Pure pass-through (assembly neither adds nor filters) and INDEPENDENT of the status/errorCode chain:
152
152
  * a refused `suspendVM` still ends the task exactly the way it did before — this only stops the eleven
153
153
  * distinct codes from arriving as one anonymous `limits.max_turns_exceeded`. Empty/absent ⇒ the field is omitted. */
154
154
  remoteEnvFailures?: TaskResult["remoteEnvFailures"];
155
- /** #240 (design/199 v1.1) — the run's effective read posture (resolved face + normalized deny
155
+ /** The run's effective read posture (resolved face + normalized deny
156
156
  * additions), echoed on `TaskResult.effectiveReadFace` / `.effectiveReadDenyPatterns`. Pure
157
157
  * pass-through (assembly neither adds nor filters) and INDEPENDENT of the status/errorCode chain:
158
158
  * the posture is a fact about the leg that ran, whatever terminal it reached — a post-completion
159
159
  * spawner folds it stricter-wins into follow-on legs; every other consumer may ignore it. */
160
160
  effectiveReadFace?: TaskResult["effectiveReadFace"];
161
161
  effectiveReadDenyPatterns?: TaskResult["effectiveReadDenyPatterns"];
162
- /** design/178 v2 §2.3 (件①) — the memory-visibility observation, echoed on
162
+ /** The memory-visibility observation, echoed on
163
163
  * `TaskResult.effectiveMemoryScopes`. Pure pass-through on every terminal, same law as the
164
164
  * read-posture seats above: present iff prepare completed (the memory-less states are their own
165
165
  * values — absence means only "prepare never ran to completion"). */
166
166
  effectiveMemoryScopes?: TaskResult["effectiveMemoryScopes"];
167
- /** #327 — the leg's effective reasoning resolution, echoed on `TaskResult.effectiveReasoning`.
167
+ /** The leg's effective reasoning resolution, echoed on `TaskResult.effectiveReasoning`.
168
168
  * Pure pass-through on every terminal (same law as the read-posture seats): the SAME object the
169
169
  * `reasoning.resolved` trace frame carried (runtask resolves once per leg — two faces, one mint);
170
170
  * absent when thinking was off/unset for the leg, so the key is omitted. */
@@ -188,7 +188,7 @@ export interface ResultFlags {
188
188
  * and the run takes the completed floor. Absent/false = the abort's ordinary reading. */
189
189
  answerSettled?: boolean;
190
190
  budgetHit?: "exceeded" | "precall";
191
- /** design/164 — which budget ceiling the hit belongs to. Set together with {@link budgetHit} at every
191
+ /** Which budget ceiling the hit belongs to. Set together with {@link budgetHit} at every
192
192
  * site that records one; it picks the terminal code (`limits.max_tokens_exceeded` vs
193
193
  * `limits.max_cost_exceeded`), so a hit without an axis would be an unattributable terminal. */
194
194
  budgetAxis?: BudgetAxis;
@@ -198,7 +198,7 @@ export interface ResultFlags {
198
198
  * the loop folded it into a text-only failure message, so the typed code rides this flag. */
199
199
  gitCoreOverBudget?: boolean;
200
200
  outputInvalid?: boolean;
201
- /** design/72 §2.2 (B): a re-suspend was refused because the task already suspended `maxSuspends` times
201
+ /** A re-suspend was refused because the task already suspended `maxSuspends` times
202
202
  * (a resume/restart loop). It aborted the run (no `threw`) but must read as `failed`/`suspend.loop`,
203
203
  * NOT `suspended` — slotted ABOVE `suspendRef` and the aborted branches (this suspend never minted a
204
204
  * checkpoint, so `suspendRef` is unset anyway; the ordering makes the intent explicit). */
@@ -278,13 +278,13 @@ export declare function terminalCauseOf(final: AssistantMessage | undefined, sta
278
278
  /**
279
279
  * Build the final {@link TaskResult} from the run's terminal state. **The errorCode priority chain is a
280
280
  * public contract** (callers `switch` on these strings) — first match wins, in this exact order
281
- * (council design/34 red-line #3, do not reorder):
281
+ * (red-line #3, do not reorder):
282
282
  * 1. `outputInvalid` → `"output.invalid"`
283
- * 2. degenerate → `"output.degenerate"` + `salvagedOutput` (design/39; wins over budget/timeout)
283
+ * 2. degenerate → `"output.degenerate"` + `salvagedOutput` (wins over budget/timeout)
284
284
  * 3. `budgetHit` → `"limits.max_tokens_exceeded"` | `"limits.max_cost_exceeded"` (by `budgetAxis`;
285
285
  * the pre-call estimate rejection and the after-spend crossing share the code — the distinction
286
286
  * lives in `errorMessage`, not in a second code)
287
- * 3.5 `suspendLoop` → `"suspend.loop"` (design/72 §2.2 B — the re-suspend cap; deterministic root
287
+ * 3.5 `suspendLoop` → `"suspend.loop"` (the re-suspend cap; deterministic root
288
288
  * cause, above `threw` because it owns the abort)
289
289
  * 4. `threw` + walltime → `"limits.max_walltime_exceeded"`
290
290
  * 5. `threw` + turns → `"limits.max_turns_exceeded"`
@@ -293,18 +293,20 @@ export declare function terminalCauseOf(final: AssistantMessage | undefined, sta
293
293
  * 8. `blockedReason` → status `"blocked"` (no errorCode)
294
294
  * 8.5 `paused` → status by the pause's registry row (`suspended` for an approval / resource
295
295
  * slice / platform pause, `needs_review` + `"review.pending"` for a plan or dry-run review) +
296
- * checkpointToken/gate (design/45 B4 — a deliberate durable pause beats the abort it used, but
296
+ * checkpointToken/gate (a deliberate durable pause beats the abort it used, but
297
297
  * yields to a real budget/threw failure above)
298
298
  * 9. `abortedLive` | stopReason aborted → `"limits.max_walltime_exceeded"` | `"limits.max_turns_exceeded"` | undefined
299
299
  * (audit A-1: hoisted ABOVE no-final — the loop exits cleanly on abort, so `final` may be a
300
300
  * normal message or absent; a plain user interrupt carries NO errorCode — switch on `status`),
301
- * EXCEPT when the aborted `final` is the bare halt's OWN cut artifact (`haltOwnsAbortedFinal`),
301
+ * EXCEPT when the aborted `final` is the bare halt's OWN cut artifact (`haltOwnsAbortedFinal`: the
302
+ * loop reported the halt's cut settled the final turn — never shape inference),
302
303
  * and EXCEPT when the answer had already settled (`answerSettled`: a clean `"stop"` final, not
303
304
  * partial) — a stop landing on the run's tail cuts no work, so the run falls through to 12
304
305
  * (`completed`, the answer as `result`, no `limits.*` code for the axis; three axes, one law)
305
- * 9.7 `userHalted` + (no `final` | the halt's own aborted `final`) → status `"completed"` (#504: a
306
- * bare user halt — the verb working, not a defect; below the aborts on purpose, a real
307
- * abort/limit that also fired owns the terminal and the halt rides as the pass-through seat)
306
+ * 9.7 halt CONSUMED (`haltConsumed(flags.haltConsumption)`) + (no `final` | the halt's own aborted
307
+ * `final`) → status `"completed"` (a bare user halt — the verb working, not a defect; below the
308
+ * aborts on purpose, a real abort/limit that also fired owns the terminal and the halt rides as
309
+ * the pass-through seat; an accepted-but-unconsumed halt never reaches this slot)
308
310
  * 10. no `final` → status `"failed"`
309
311
  * 11. stopReason error → brain `[code]` prefix (or `"conflict"` from the storage-layer flag)
310
312
  * 12. else → `"completed"`
@@ -1,6 +1,7 @@
1
1
  import { isDegenerateCutMessage } from "../../brain/terminal-cause.js";
2
2
  import { extractErrorCode, stripErrorCodePrefix } from "../../brain/errors.js";
3
3
  import { terminalProjection } from "./terminal-projection.js";
4
+ import { haltConsumed } from "./halt-attribution.js";
4
5
  const SALVAGE_ELIGIBLE_TERMINALS = new Set([
5
6
  "output.degenerate",
6
7
  "limits.max_tokens_exceeded",
@@ -47,7 +48,7 @@ export function answerSettled(final, continuationCut = false) {
47
48
  export function terminalCauseOf(final, stats, flags) {
48
49
  let terminal;
49
50
  let apiFailure;
50
- const haltOwnsAbortedFinal = flags.userHalted === true &&
51
+ const haltOwnsAbortedFinal = flags.haltConsumption?.turnCut === "halt" &&
51
52
  final?.stopReason === "aborted" &&
52
53
  !flags.abortedLive &&
53
54
  flags.abortedForTimeout !== true &&
@@ -103,7 +104,7 @@ export function terminalCauseOf(final, stats, flags) {
103
104
  const code = flags.abortedForTimeout ? "limits.max_walltime_exceeded" : flags.abortedForTurns ? "limits.max_turns_exceeded" : undefined;
104
105
  terminal = { kind: "failed", ...(code !== undefined ? { code } : {}), message: final?.errorMessage ?? (flags.abortedForTurns ? "max turns exceeded" : "run aborted") };
105
106
  }
106
- else if (flags.userHalted === true && (!final || haltOwnsAbortedFinal)) {
107
+ else if (haltConsumed(flags.haltConsumption) && (!final || haltOwnsAbortedFinal)) {
107
108
  terminal = { kind: "completed" };
108
109
  }
109
110
  else if (!final) {
@@ -155,7 +156,7 @@ export function assembleResult(spec, sessionId, final, stats, flags) {
155
156
  const result = text;
156
157
  let salvagedOutput;
157
158
  const { terminal, apiFailure } = terminalCauseOf(final, stats, flags);
158
- const { status, errorCode } = terminalProjection(terminal);
159
+ const { errorCode } = terminalProjection(terminal);
159
160
  if (errorCode !== undefined && SALVAGE_ELIGIBLE_TERMINALS.has(errorCode)) {
160
161
  salvagedOutput = text.trim() || undefined;
161
162
  }
@@ -164,6 +165,6 @@ export function assembleResult(spec, sessionId, final, stats, flags) {
164
165
  void _internalCompaction;
165
166
  if (flags.unpricedSpend)
166
167
  delete publicStats.costMicroUsd;
167
- const stampHaltedByUser = flags.userHalted === true && status !== "suspended" && status !== "needs_review";
168
+ const stampHaltedByUser = haltConsumed(flags.haltConsumption);
168
169
  return { taskId, ...(flags.runId !== undefined ? { runId: flags.runId } : {}), sessionId, terminal, ...(flags.model !== undefined ? { model: flags.model } : {}), result: result.trim(), salvagedOutput, ...(apiFailure !== undefined ? { apiFailure } : {}), ...(retryAfterMs !== undefined ? { retryAfterMs } : {}), ...(flags.rewindNotes !== undefined && flags.rewindNotes.length > 0 ? { rewindNotes: flags.rewindNotes } : {}), ...(flags.editedFiles !== undefined && flags.editedFiles.length > 0 ? { editedFiles: flags.editedFiles } : {}), ...(flags.haltedOnUserRejection === true ? { haltedOnUserRejection: true } : {}), ...(stampHaltedByUser ? { haltedByUser: true } : {}), ...(flags.remoteEnvFailures !== undefined && flags.remoteEnvFailures.length > 0 ? { remoteEnvFailures: [...flags.remoteEnvFailures] } : {}), ...(flags.strandedHumanAnswers !== undefined && flags.strandedHumanAnswers.length > 0 ? { strandedHumanAnswers: flags.strandedHumanAnswers } : {}), ...(flags.effectiveReadFace !== undefined ? { effectiveReadFace: flags.effectiveReadFace } : {}), ...(flags.effectiveReadDenyPatterns !== undefined && flags.effectiveReadDenyPatterns.length > 0 ? { effectiveReadDenyPatterns: flags.effectiveReadDenyPatterns } : {}), ...(flags.effectiveMemoryScopes !== undefined ? { effectiveMemoryScopes: flags.effectiveMemoryScopes } : {}), ...(flags.effectiveReasoning !== undefined ? { effectiveReasoning: flags.effectiveReasoning } : {}), stats: publicStats };
169
170
  }
@@ -5,19 +5,19 @@
5
5
  * the driver (the restore fold) and runtask (the resume rung) reach DOWN for the same names. Pure: a constant and two
6
6
  * string functions.
7
7
  */
8
- /** design/77 §4.4: the multi-tenant scope used when a durable suspend fires for an IRREVERSIBLE tool in an
8
+ /** The multi-tenant scope used when a durable suspend fires for an IRREVERSIBLE tool in an
9
9
  * unattended deployment that did NOT opt into `durableApproval` (so there is no caller-supplied scope). The
10
10
  * checkpoint carries this scope; resume reads it back from the checkpoint (`cp.scope`), so it is
11
11
  * self-consistent without needing the original `TaskSpec`. Kept distinct from any tenant key to make an
12
12
  * unattended irreversible suspend auditable as such. */
13
13
  export declare const DEFAULT_IRREVERSIBLE_SCOPE = "irreversible";
14
14
  /**
15
- * design/153 §7.1 — the SINGLE derivation of a durable-suspend checkpoint's scope (both gate mint
15
+ * The SINGLE derivation of a durable-suspend checkpoint's scope (both gate mint
16
16
  * sites + the bg-watcher park lane's expire compensation/arbitration consume THIS; a re-derived copy
17
17
  * that drifted was the exact bug the park tests caught — expire against the wrong scope silently
18
18
  * no-ops). `|| DEFAULT` (not `??`): an EMPTY-string principal must not become a shared scope bucket.
19
19
  *
20
- * RB-75 (2026-07-25, red probe): that rule is stated twice in this file and was enforced on ONE of the two
20
+ * That rule is stated twice in this file and was enforced on ONE of the two
21
21
  * inputs — the principal half used `||`, the `durableApproval.scope` half used `??`, so an empty string
22
22
  * arriving through the scope field (a config-centre / env lookup that came back blank is the realistic
23
23
  * source) sailed through as the literal scope `""`. Two different tenants both landed in that one bucket,
@@ -33,7 +33,7 @@ export declare function checkpointScopeOf(spec: {
33
33
  principal?: string;
34
34
  }): string;
35
35
  /**
36
- * rescan C5 — the ONE spelling of the placement fields' empty-string discipline: `""` is absence
36
+ * The ONE spelling of the placement fields' empty-string discipline: `""` is absence
37
37
  * wearing clothes (the resume entry's principal-rung posture), and every placement read that must
38
38
  * treat it so — the resume rung's two sides (runtask), the restore fold's seed and the suspend
39
39
  * stamp — goes through THIS helper, so three sites cannot drift into three readings. Deliberately
@@ -18,7 +18,7 @@ import type { PlatformLimitReason } from "../checkpoint-store.js";
18
18
  import type { TaskSpec } from "../types.js";
19
19
  import type { Prepared } from "./contracts.js";
20
20
  /**
21
- * design/164 — the LIMIT-APPROACH frames, the successor to the retired deadline-nudge family. Two facts
21
+ * The LIMIT-APPROACH frames, the successor to the retired deadline-nudge family. Two facts
22
22
  * make them a different mechanism, not a rename:
23
23
  * - they are measured in BUDGET (the tightest armed axis's fill ratio), not in wall-clock, so they need
24
24
  * no throughput estimate and cannot mis-fire on a starved event loop;
@@ -36,7 +36,7 @@ export declare function limitApproachFrames(index: 0 | 1, axis: string, percent:
36
36
  /**
37
37
  * Resolve the effective turn cap. `undefined` = no turn cap; `0` (explicit) = unbounded.
38
38
  *
39
- * design/164: this is now a pure read of what the caller wrote. The two clauses it used to carry —
39
+ * This is now a pure read of what the caller wrote. The two clauses it used to carry —
40
40
  * "a wall-clock bound was set, so drop the turn cap" and "neither was set, so apply the engine's
41
41
  * safety net" — are both gone: the axes no longer interact (each binds on its own), and there is no
42
42
  * engine-side net to apply. A task with no `maxTurns` has no turn ceiling.
@@ -88,7 +88,7 @@ export declare function awaitChargeWithSlowDisclosure<T>(charge: Promise<T>, onS
88
88
  */
89
89
  export declare function raceUntilDeadline<T>(p: Promise<T>, deadline: number): Promise<T | typeof GOVERNANCE_READ_STALLED>;
90
90
  /**
91
- * design/164 件四/件五 — the TYPED terminal for an external stop cause that could NOT be suspended durably.
91
+ * The TYPED terminal for an external stop cause that could NOT be suspended durably.
92
92
  * Carried on `rs.limits.platformTerminal` and adopted as the run's `threw`, so the caller reads the cause
93
93
  * on `TaskResult.errorCode` (`errorCodeOf` lifts `.code`) instead of the anonymous error an abort produces.
94
94
  * `retryAfterMs` rides the error object because a wait hint has no `TaskResult` seat — a host reads it from
@@ -5,7 +5,7 @@ import type { Context } from "../../internal/llm.js";
5
5
  import { type ToolResultStore } from "../tool-result-store.js";
6
6
  import type { Prepared } from "./contracts.js";
7
7
  /**
8
- * REF-A2 (car R11) — the maybeCompact call arguments that MUST be assembled identically on all three
8
+ * The maybeCompact call arguments that MUST be assembled identically on all three
9
9
  * of runtask's compaction lanes (turn boundary / prompt-too-long recovery / end-of-task).
10
10
  *
11
11
  * Those lanes carried three hand-copied assemblies whose own comments said "must not silently
@@ -30,100 +30,36 @@ import type { Prepared } from "./contracts.js";
30
30
  */
31
31
  export declare function buildWorkingFileAttachments(spec: TaskSpec, prepared: Prepared): MaybeCompactOptions["workingFileAttachments"];
32
32
  /**
33
- * #500 — `MaybeCompactOptions.contextInstructionFiles`: the seat that delivers the deployment's own
34
- * instruction-file content (the CLAUDE.md family) to the SUMMARIZER, assembled once here and spread
35
- * on all three lanes. Without it the compaction boundary is the one place a long task loses the
36
- * standing instructions every other turn has been reading — and it loses them exactly where the
37
- * summary REPLACES the transcript that carried them, so the loss is durable.
33
+ * `MaybeCompactOptions.contextInstructionFiles`: the deployment's instruction-file content (the CLAUDE.md
34
+ * family) delivered to the SUMMARIZER, assembled once here and spread on all three lanes — the compaction
35
+ * boundary is where the summary REPLACES the transcript that carried those instructions.
38
36
  *
39
- * WHICH BYTES, and why the neighbours are not candidates. `Prepared.projectInstructionContent` =
40
- * the RAW loader text (`ProjectMemoryLoad.content`, exactly the string prepare-task feeds
41
- * `composeMemoryBlock(projectMem, "project")`), captured beside the existing `instructionSources`
42
- * capture under the SAME non-blank predicate that composes the project layer:
43
- * · the assembled `memoryBlock` is NOT a candidate. It is the memory ENGINE's composed layers —
44
- * bytes the model itself authored in-band this session through the memory tools — with the
45
- * project layer appended at the tail. The seat's contract is host/systemPrompt tier and says in
46
- * terms: never from tool output, model text, or any other in-band channel. Handing
47
- * model-authored bytes an envelope whose preamble tells the summarizer they may instruct it is
48
- * the laundering shape, not a purity nit. (Mechanically moot too — `memoryBlock` is a
49
- * prepare-task local and never reaches `Prepared`.)
50
- * · the COMPOSED project block is not it either, and this one is checkable rather than a
51
- * judgement: `contextInstructionFilesSection` neutralizes the whole authority family
52
- * (ENGINE_AUTHORITY_ENVELOPE_TAGS) over its payload, and `user_memory`/`scope` ARE in that
53
- * family so feeding a composed block would have the engine rewrite the tags of its own
54
- * composition. Raw text in, one fence at the mint.
55
- * · `prepared.instructionSources` carries path + contentHash only, by design (core never learns a
56
- * file-name policy), so it cannot serve this seat at all.
57
- *
58
- * PROVENANCE, stated plainly because "the host supplies it" is the easy half of the truth. On this
59
- * engine the value is REPOSITORY-CONTROLLED text: the loading block one file over calls a CLAUDE.md
60
- * of unknown authorship untrusted in so many words, the MAIN lane's own framing tells the model it is
61
- * "repository-controlled DATA, not instructions to obey", and this seat hands the same bytes to the
62
- * summarizer with instruction standing for the summarization task. Delivery THROUGH a host callback
63
- * is not host AUTHORSHIP: a prior agent, or anyone who can land a commit, can write a
64
- * "## Compact Instructions" section, and the mint's neutralization stops tag breakout — not a
65
- * sentence asking for a fact to be left out of the summary that replaces the transcript.
66
- * Why it is nevertheless this value: the seat's own contract names this path ("hosts pass the same
67
- * instruction-file content their prompt assembly mounts... on the runner path"), the parity form this
68
- * channel exists to reach reads the user's and the project's instruction files at every boundary with
69
- * exactly this standing, and the two alternatives are worse for reasons above rather than better.
70
- * The standing is also narrower than the framing gap suggests — the section's preamble scopes it to
71
- * guidance about HOW to summarize and classifies the rest as background — and a deployment that does
72
- * not want it has two exits that need no code: do not wire the loader, or return content it vouches
73
- * for. Recorded as an open design candidate rather than built here, because it is a contract change
74
- * and not a wiring one: a SEPARATE deployment-vouched summarization-instructions seat, leaving
75
- * repository-derived context at data tier.
76
- *
77
- * RULING ① — BOTH summary forms, no per-form split. Fork eligibility is decided per pass INSIDE
78
- * maybeCompact (main-model-only, recorded-request-present, not lossy), so a call site cannot say
79
- * "independent form only"; the closest approximation — pass the seat only when `prepared.compModel`
80
- * is set, since an independent compaction model has no main prefix to fork — leaves the hole the
81
- * wrong way round: the configuration it does NOT cover (no compaction model) is precisely the one
82
- * where a fork degrades mid-pass to the independent form, which would then run WITHOUT the files.
83
- * Feeding both forms closes that case by construction, and the library face already handles the fork
84
- * half (the section rides the APPENDED instruction message, never the cached prefix, so the fork's
85
- * whole economic point is untouched).
86
- *
87
- * RULING ② — no new size knob. The bound is the library's own `fitContextInstructionFilesSection`
88
- * (independent form: cap against the compaction model's window, disclosed elision, and a complete
89
- * yield when not even the framing fits). Its three KNOWN LIMITS are accepted here KNOWINGLY, as the
90
- * pre-condition of this wiring rather than something it discovered: a token-dense payload (CJK,
91
- * emoji) can pass a chars-domain fit and still overflow the gateway's tokenizer; an unknown
92
- * `contextWindow` leaves the section unbounded (the conversation clamp declines to guess there too);
93
- * and the FORK form cannot fit at all — its bound is a prompt-too-long that degrades ONCE to the
94
- * independent form, which the engine's own note records as real but NOT total (an oversize rejection
95
- * the classifier cannot read as prompt-too-long returns terminally instead).
96
- *
97
- * HOW BIG THAT ACCEPTANCE ACTUALLY IS — measured, because the sentence above is easy to read more
98
- * comfortably than it deserves. The fitted form is NOT the default path: when a fork is eligible and
99
- * the model answers in its envelope, the fork IS the pass, and its section is delivered WHOLE at any
100
- * size. The independent form — the only one that fits — runs when there is no fork to take or the
101
- * fork's answer did not conform. Both facts are pinned in the REF-A2 suite (a 55 KB payload: whole on
102
- * the fork, elided on the independent fallback). And when a limit does bite, the failure is not a
103
- * quiet degradation: the section is a FIXED part of the request, the reactive retry loop may drop
104
- * only CONVERSATION groups, so a request the SECTION overflowed cannot converge and the boundary
105
- * fails — the task loses that compaction (or that prompt-too-long recovery, or its end-of-task
106
- * summary) rather than sending a shorter one. The exposure is what the wiring widened: this was
107
- * previously reachable only by hosts calling the library directly, and is now reachable by every
108
- * deployment that wires `loadProjectMemory` with a large instruction file and an unknown or small
109
- * window. Making the section participate in the retry loop is the structural answer; it is a change
110
- * to that loop's contract, tracked at the library face, and a runner-side knob would only move the
111
- * decision to a place with less information.
112
- *
113
- * WHAT IT COSTS, measured rather than rounded: every deployment that wires `loadProjectMemory` now
114
- * sends its instruction-file content plus EXACTLY 716 chars of framing (the preamble and the fence)
115
- * on EVERY summarization request, both forms, once per pass — where a real project instruction file
116
- * in this family runs to tens of KB, so the payload, not the framing, is the bill. The number is
117
- * pinned in the REF-A2 suite against the engine's own renderer, so a preamble edit shows up as a
118
- * changed assertion rather than as prose drifting away from the code it describes.
119
- * Deployments that never wired the loader pay nothing: the key is absent, not
120
- * `undefined`, so their requests are byte-identical to the pre-wiring shape on the independent and
121
- * UPDATE passes (the FORK form appends its ~860-char authority clause with or without the seat, and
122
- * always did).
37
+ * Contract:
38
+ * - Bytes = `Prepared.projectInstructionContent`, the RAW loader text captured under the same non-blank
39
+ * predicate that composes the project layer. Not the assembled `memoryBlock` (model-authored in-band
40
+ * bytes would gain an instructing envelope), not the COMPOSED project block (`contextInstructionFilesSection`
41
+ * neutralizes the whole authority family, `user_memory`/`scope` included), not `instructionSources`
42
+ * (path + hash only). Raw text in, one fence at the mint.
43
+ * - Provenance: REPOSITORY-CONTROLLED text delivered through a host callback delivery is not authorship;
44
+ * the mint's neutralization stops tag breakout, not a sentence asking for an omission. Two no-code exits
45
+ * for a deployment that does not want it: do not wire the loader, or return vouched content. A separate
46
+ * deployment-vouched summarization-instructions seat is an open design candidate, not built here.
47
+ * - Both summary forms, no per-form split: fork eligibility is decided per pass inside maybeCompact, and the
48
+ * form NOT covered by a `compModel`-gated split is exactly the fork that degrades mid-pass to the
49
+ * independent form; the section rides the APPENDED instruction message, never the cached prefix.
50
+ * - No new size knob: the bound is `fitContextInstructionFilesSection` (independent form only). Its three
51
+ * known limits are accepted knowingly: a token-dense payload can pass a chars-domain fit and still overflow;
52
+ * an unknown `contextWindow` leaves the section unbounded; the FORK form cannot fit and degrades ONCE. When
53
+ * a limit bites the boundary FAILS (the section is a fixed request part the retry loop cannot drop) — the
54
+ * task loses that compaction rather than sending a shorter one; making the section participate in the
55
+ * retry loop is a library-face contract change, tracked there.
56
+ * - Cost: instruction-file content + exactly 716 chars of framing on every summarization request, both
57
+ * forms, once per pass (pinned in the REF-A2 suite). Deployments that never wired the loader pay nothing:
58
+ * the key is ABSENT, so their requests are byte-identical to the pre-wiring shape.
123
59
  */
124
60
  export declare function contextInstructionFilesOption(prepared: Prepared): Partial<Pick<MaybeCompactOptions, "contextInstructionFiles">>;
125
61
  /**
126
- * design/169-A — the CC-form fork seam, assembled identically on all three lanes (REF-A2): the
62
+ * The CC-form fork seam, assembled identically on all three lanes (REF-A2): the
127
63
  * summary request forks the main lane's latest real request (recorded by prepare-task's provider
128
64
  * shim) instead of re-serializing the conversation into an independent full-price request.
129
65
  * `maybeCompact` consults the accessor per pass and only when the summary model IS the main model;
@@ -135,7 +71,7 @@ export declare function contextInstructionFilesOption(prepared: Prepared): Parti
135
71
  * clearStale content blanking, the aggregate tool-result/media caps, the orphan sweep), that
136
72
  * projection is missing history the summary would PERMANENTLY replace — measured live: a fork of a
137
73
  * trimmed request loses the fact-survival suite's fact; a fork of a clearStale'd request summarizes
138
- * `[tool result cleared …]` markers (独立复审 HIGH,已修). That guard lives at the RECORDING side
74
+ * `[tool result cleared …]` markers. That guard lives at the RECORDING side
139
75
  * (prepare-task arms `requestLossyRef` per request build; a lossy request records `undefined`), so
140
76
  * every lane degrades to the independent form — which reads the FULL session — automatically.
141
77
  *
@@ -145,12 +81,12 @@ export declare function contextInstructionFilesOption(prepared: Prepared): Parti
145
81
  */
146
82
  export declare function forkContextOption(prepared: Prepared, disable: boolean): Pick<MaybeCompactOptions, "forkContext">;
147
83
  /**
148
- * RB-31 — compaction-boundary center-candidate adoption. Absent (an empty object, NOT a
84
+ * Compaction-boundary center-candidate adoption. Absent (an empty object, NOT a
149
85
  * `centerAdoption: undefined` key) = restate as before; a boundary re-pin hashes the same artifact
150
86
  * identity on every lane.
151
87
  */
152
88
  export declare function centerAdoptionOption(prepared: Prepared): Partial<Pick<MaybeCompactOptions, "centerAdoption">>;
153
- /** design/169-F defaults (object-present, field-absent). Named per the magic-number rule. */
89
+ /** Defaults (object-present, field-absent). Named per the magic-number rule. */
154
90
  export declare const STALE_OFFLOAD_DEFAULT_KEEP_RECENT_PER_TOOL = 3;
155
91
  export declare const STALE_OFFLOAD_DEFAULT_MIN_SAVINGS_CHARS = 2000;
156
92
  /** Resolved (validated, defaulted) knob — see {@link resolveStaleToolResultOffload}. */
@@ -159,7 +95,7 @@ export interface ResolvedStaleToolResultOffload {
159
95
  minSavingsChars: number;
160
96
  }
161
97
  /**
162
- * design/169-F — validate + default the spec knob. Fail-loud on non-finite/negative/fractional
98
+ * Validate + default the spec knob. Fail-loud on non-finite/negative/fractional
163
99
  * values (a computed NaN silently re-defaulting is the ||0-fold this repo's engineering code bans);
164
100
  * `undefined` knob ⇒ `undefined` (feature completely off).
165
101
  */
@@ -171,14 +107,14 @@ export declare function resolveStaleToolResultOffload(knob: StaleToolResultOfflo
171
107
  * crossing the staleness line as newer same-tool results arrive) rewrites that message's bytes
172
108
  * once, invalidating the provider cache from that position for one request — a bounded,
173
109
  * once-per-result break the `minSavingsChars` floor is there to amortize.
174
- * Deliberately NOT `offloadPagebackHint` (the design/30 preview's hint): that hint's wording is a
110
+ * Deliberately NOT `offloadPagebackHint` (the preview's hint): that hint's wording is a
175
111
  * function of the LIVE reachable-tool set, and this pointer is re-derived per request — a mid-run
176
112
  * ToolSearch activation would flip its bytes and break the very prefix stability this file pins.
177
- * The reader is named by its real mounted name (独立复审 MED,已修: `read_tool_result` is a
113
+ * The reader is named by its real mounted name (`read_tool_result` is a
178
114
  * retired alias — a model following it burned a rejected call first). */
179
115
  export declare function buildStaleOffloadPointer(toolName: string, ref: string, chars: number): string;
180
116
  /**
181
- * design/169-F — the request-side projection: replace STALE same-tool results with byte-stable
117
+ * The request-side projection: replace STALE same-tool results with byte-stable
182
118
  * pointers. "Stale" = has ≥ `keepRecentPerTool` NEWER results of the same tool name in this request
183
119
  * — a monotone predicate (a result never gains "recency" back), so a replacement decision made on
184
120
  * one request holds on every later one and re-derivation is deterministic: no run-scoped mutable
@@ -194,7 +130,7 @@ export declare function buildStaleOffloadPointer(toolName: string, ref: string,
194
130
  * tool-call ids carry no cross-turn uniqueness contract), readable back via `read_tool_result`.
195
131
  */
196
132
  export declare function projectStaleToolResults(context: Context, cfg: ResolvedStaleToolResultOffload, store: ToolResultStore, sessionId: string,
197
- /** Run-scoped cache of refs already persisted by THIS run (独立复审 MED,已修): without it the
133
+ /** Run-scoped cache of refs already persisted by THIS run: without it the
198
134
  * write-once `put` is still re-issued every request — on the file backend that is a
199
135
  * write-then-discard round-trip per stale result per turn. Caller owns the Set's lifetime. */
200
136
  writtenRefs: Set<string>): Promise<Context>;
@@ -1,5 +1,5 @@
1
1
  /**
2
- * The run loop's three compaction knobs (design/393 S5): the consecutive-failure breaker trip, the anti-thrash
2
+ * The run loop's three compaction knobs: the consecutive-failure breaker trip, the anti-thrash
3
3
  * regrowth factor and the effective-compaction epsilon. They were declared at the turn-boundary lane and the driver
4
4
  * reached DOWN for them; the recovery lane (the forced-compaction pass the prompt-too-long and guard-chain arms
5
5
  * share) reads the same three, and a lane may not name a sibling lane — so the three values sank to the machinery
@@ -9,12 +9,12 @@
9
9
  * lane, and the prefix would put it under the phase-api gate and the run-lanes glob.
10
10
  */
11
11
  /**
12
- * §17.4 (design/64 GAP-25): stop attempting within-task compaction after this many CONSECUTIVE
12
+ * §17.4: stop attempting within-task compaction after this many CONSECUTIVE
13
13
  * failures in one task — a never-recovering summary gateway must not burn an API call at every turn
14
14
  * boundary (CC: MAX_CONSECUTIVE_AUTOCOMPACT_FAILURES = 3). Reset on any success; an open breaker also
15
15
  * skips the end-of-task attempt in `finish()` (teardown unaffected). Per-task scope.
16
16
  *
17
- * RB-190 — this used to say "a flaky/never-recovering gateway", and the word `flaky` was not true. Because
17
+ * This used to say "a flaky/never-recovering gateway", and the word `flaky` was not true. Because
18
18
  * any success zeroes the counter, a gateway that alternates never reaches three CONSECUTIVE failures and
19
19
  * the breaker never opens; it keeps paying for a call at every failed boundary, indefinitely.
20
20
  *
@@ -37,7 +37,7 @@ export declare const MAX_CONSECUTIVE_COMPACTION_FAILURES = 3;
37
37
  */
38
38
  export declare const COMPACTION_REGROWTH_FACTOR = 1.5;
39
39
  /**
40
- * design/84 Seam C reuse guard (b): a compaction that frees fewer than this many (structural) tokens is
40
+ * A compaction that frees fewer than this many (structural) tokens is
41
41
  * treated as NO-EFFECTIVE-COMPACTION and does NOT raise the anti-thrash floor. Guards against a reused
42
42
  * provider summary (or a pathological LLM summary) that reclaims no headroom yet suppresses the next real
43
43
  * summary by inflating the floor to trigger×factor.
@@ -2,17 +2,17 @@ import type { MaybeCompactOptions } from "../auto-compaction.js";
2
2
  import type { TaskSpec } from "../types.js";
3
3
  import type { Prepared, RunnerDepsSeat } from "./contracts.js";
4
4
  /**
5
- * design/84 Seam C — the cost-optimization compaction options threaded into BOTH `maybeCompact` call
5
+ * The cost-optimization compaction options threaded into BOTH `maybeCompact` call
6
6
  * sites (within-task turn boundary + `finish()`). All three fields come from `RunnerDeps` (a trusted
7
7
  * FUNCTION seam — never `TaskSpec`, which is serializable/durable-resumable/untrusted-caller). The
8
8
  * Runner OWNS the consecutive-reuse counter (`prepared.compactionReuseRef`) so the
9
9
  * `maxConsecutiveProviderReuse` drift guard spans the whole task across both sites: it FEEDS the current
10
10
  * count in as `consecutiveProviderReuse`, and {@link recordCompactionReuse} updates it from the result.
11
11
  * Returns `undefined` when no provider is wired (so the call site spreads nothing → byte-identical to
12
- * the pre-design/84 behavior).
12
+ * the prior behavior).
13
13
  */
14
14
  export declare function seamCCompactionOptions(runner: RunnerDepsSeat, prepared: Prepared): Pick<MaybeCompactOptions, "summaryProvider" | "onCompaction" | "maxConsecutiveProviderReuse" | "consecutiveProviderReuse"> | undefined;
15
- /** design/134 §3.2 — resolve the pre/postCompact lifecycle callbacks (whole-slot `spec.hooks ??
15
+ /** Resolve the pre/postCompact lifecycle callbacks (whole-slot `spec.hooks ??
16
16
  * deps.hooks`, same resolution as the stop hook) and wrap each in a SWALLOW+TRACE shell before
17
17
  * threading them into maybeCompact. The wrapper owns the observability half of the R3 MED contract
18
18
  * (maybeCompact swallows defensively too, but has no sink): a throwing callback is reported via
@@ -20,7 +20,7 @@ export declare function seamCCompactionOptions(runner: RunnerDepsSeat, prepared:
20
20
  * reported as ignored (maybeCompact enforces the ignore — blocking a compaction the provider/trim
21
21
  * layer already demanded would kill the run). */
22
22
  export declare function compactionHookOptions(runner: RunnerDepsSeat, spec: TaskSpec, sessionId: string, trigger: "auto" | "manual" | "forced",
23
- /** #281 件A — the leg's identity envelope, spread onto both compaction contexts by the wrappers
23
+ /** The leg's identity envelope, spread onto both compaction contexts by the wrappers
24
24
  * below (the compaction module builds its contexts below the runner and cannot know the leg;
25
25
  * the wrapper is the runner's seam). Every runner call site supplies `prepared.hookIdentity`;
26
26
  * optional only so a context built without a leg stays honestly identity-less. */
@@ -33,7 +33,7 @@ seatBound?: {
33
33
  timeoutMs: number;
34
34
  signal?: AbortSignal;
35
35
  }): Pick<MaybeCompactOptions, "trigger" | "preCompact" | "postCompact">;
36
- /** design/84 Seam C — fold a finished compaction's `reused` flag into the run-scoped consecutive-reuse
36
+ /** Fold a finished compaction's `reused` flag into the run-scoped consecutive-reuse
37
37
  * counter: a reused (provider) summary increments it, a real (LLM) summary resets it to 0. A no-op
38
38
  * compaction (`compacted:false`) leaves the counter untouched. No-op when no provider is wired. */
39
39
  export declare function recordCompactionReuse(runner: RunnerDepsSeat, prepared: Prepared, comp: {