@sema-agent/core 7.14.0 → 7.16.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 (136) hide show
  1. package/CHANGELOG.md +59 -0
  2. package/dist/core/ask-origin.d.ts +2 -2
  3. package/dist/core/checkpoint-store.d.ts +14 -15
  4. package/dist/core/governance-codes.js +2 -0
  5. package/dist/core/hooks.d.ts +4 -3
  6. package/dist/core/memory-engine/delegation-settlement.d.ts +37 -12
  7. package/dist/core/memory-engine/delegation-settlement.js +128 -39
  8. package/dist/core/memory-engine/engine.d.ts +9 -8
  9. package/dist/core/memory-engine/engine.js +115 -120
  10. package/dist/core/memory-engine/file-backend.d.ts +17 -5
  11. package/dist/core/memory-engine/file-backend.js +78 -34
  12. package/dist/core/memory-engine/index.d.ts +2 -2
  13. package/dist/core/memory-engine/index.js +2 -2
  14. package/dist/core/memory-engine/layout.d.ts +152 -54
  15. package/dist/core/memory-engine/layout.js +441 -104
  16. package/dist/core/memory-engine/types.d.ts +8 -3
  17. package/dist/core/memory-engine/types.js +5 -0
  18. package/dist/core/runner/abort-race.d.ts +3 -3
  19. package/dist/core/runner/active-skill-scope.d.ts +2 -2
  20. package/dist/core/runner/assemble-result.d.ts +29 -29
  21. package/dist/core/runner/checkpoint-scope.d.ts +4 -4
  22. package/dist/core/runner/clock-and-limits.d.ts +3 -3
  23. package/dist/core/runner/compaction-call-options.d.ts +11 -11
  24. package/dist/core/runner/compaction-knobs.d.ts +4 -4
  25. package/dist/core/runner/compaction-seams.d.ts +5 -5
  26. package/dist/core/runner/contracts.d.ts +224 -226
  27. package/dist/core/runner/decide-continuation.d.ts +6 -6
  28. package/dist/core/runner/denial-limit-arms.d.ts +8 -8
  29. package/dist/core/runner/derived-route-fallback.d.ts +2 -2
  30. package/dist/core/runner/gate-exit.d.ts +6 -6
  31. package/dist/core/runner/git-status-frame.d.ts +7 -7
  32. package/dist/core/runner/inherited-ask-grants.d.ts +6 -6
  33. package/dist/core/runner/memory-capture-optout.d.ts +1 -1
  34. package/dist/core/runner/memory-consolidation-driver.d.ts +4 -4
  35. package/dist/core/runner/memory-consolidation.d.ts +6 -6
  36. package/dist/core/runner/park-commit.d.ts +6 -6
  37. package/dist/core/runner/permission-rule-lanes.d.ts +22 -20
  38. package/dist/core/runner/permission-rule-lanes.js +1 -1
  39. package/dist/core/runner/prepare-acquire-reconcile.d.ts +4 -4
  40. package/dist/core/runner/prepare-ask-lane.d.ts +3 -3
  41. package/dist/core/runner/prepare-boundary-parks.d.ts +3 -3
  42. package/dist/core/runner/prepare-caps-and-workflow.d.ts +5 -5
  43. package/dist/core/runner/prepare-config-doors.d.ts +21 -21
  44. package/dist/core/runner/prepare-context-lane.d.ts +6 -6
  45. package/dist/core/runner/prepare-defer-classify.d.ts +3 -3
  46. package/dist/core/runner/prepare-defer-classify.js +12 -10
  47. package/dist/core/runner/prepare-delegation-surface.d.ts +1 -1
  48. package/dist/core/runner/prepare-file-history.d.ts +2 -2
  49. package/dist/core/runner/prepare-gate-stations.d.ts +8 -9
  50. package/dist/core/runner/prepare-gate-stations.js +2 -2
  51. package/dist/core/runner/prepare-hands-readface.d.ts +41 -41
  52. package/dist/core/runner/prepare-hands-readface.js +27 -29
  53. package/dist/core/runner/prepare-inherited-gate.d.ts +6 -6
  54. package/dist/core/runner/prepare-listings.d.ts +3 -3
  55. package/dist/core/runner/prepare-lsp.d.ts +3 -3
  56. package/dist/core/runner/prepare-memory-engine-session.d.ts +5 -5
  57. package/dist/core/runner/prepare-memory.js +6 -7
  58. package/dist/core/runner/prepare-offload-wrappers.d.ts +2 -2
  59. package/dist/core/runner/prepare-park-ask.d.ts +11 -12
  60. package/dist/core/runner/prepare-park-ask.js +3 -3
  61. package/dist/core/runner/prepare-policy-chain.d.ts +6 -6
  62. package/dist/core/runner/prepare-policy-chain.js +2 -2
  63. package/dist/core/runner/prepare-prompt-inputs.d.ts +5 -5
  64. package/dist/core/runner/prepare-protocol-tools.d.ts +1 -1
  65. package/dist/core/runner/prepare-question-face.d.ts +4 -4
  66. package/dist/core/runner/prepare-run-refs.d.ts +11 -11
  67. package/dist/core/runner/prepare-safety-scan.d.ts +1 -1
  68. package/dist/core/runner/prepare-suspend-saga.d.ts +4 -4
  69. package/dist/core/runner/prepare-task.d.ts +12 -12
  70. package/dist/core/runner/prepare-task.js +5 -7
  71. package/dist/core/runner/prepare-tool-disclosure-mount.d.ts +2 -3
  72. package/dist/core/runner/prepare-wiring-manifest.d.ts +4 -4
  73. package/dist/core/runner/prepare-workspace-restore.d.ts +1 -1
  74. package/dist/core/runner/remote-env-retry.d.ts +3 -3
  75. package/dist/core/runner/resume-admission.d.ts +1 -1
  76. package/dist/core/runner/resume-claim.d.ts +1 -1
  77. package/dist/core/runner/resume-internals-and-config.d.ts +1 -1
  78. package/dist/core/runner/resume-policy-outcome.d.ts +1 -1
  79. package/dist/core/runner/resume-preflight.d.ts +1 -1
  80. package/dist/core/runner/resume-review-outcome.d.ts +1 -1
  81. package/dist/core/runner/run-brain-sinks.d.ts +1 -1
  82. package/dist/core/runner/run-clock-and-content.d.ts +4 -4
  83. package/dist/core/runner/run-compaction-machinery.d.ts +3 -3
  84. package/dist/core/runner/run-git-lane.d.ts +1 -1
  85. package/dist/core/runner/run-harness-handlers.d.ts +2 -2
  86. package/dist/core/runner/run-identity-wiring.d.ts +4 -4
  87. package/dist/core/runner/run-leg.d.ts +3 -3
  88. package/dist/core/runner/run-notification-lane.d.ts +2 -2
  89. package/dist/core/runner/run-reasoning-seat.d.ts +2 -2
  90. package/dist/core/runner/run-settle-and-teardown.d.ts +4 -4
  91. package/dist/core/runner/run-telemetry-and-budget-seats.d.ts +2 -2
  92. package/dist/core/runner/run-terminal-adoption.d.ts +5 -5
  93. package/dist/core/runner/runtask.d.ts +14 -14
  94. package/dist/core/runner/session-file-state-replay.d.ts +3 -3
  95. package/dist/core/runner/session-rule-policy.d.ts +2 -2
  96. package/dist/core/runner/steer-admission.d.ts +2 -2
  97. package/dist/core/runner/stream-halt-verbs.d.ts +1 -1
  98. package/dist/core/runner/stream-reap.d.ts +1 -1
  99. package/dist/core/runner/synthetic-tools.d.ts +8 -8
  100. package/dist/core/runner/teardown-bounded.d.ts +2 -2
  101. package/dist/core/runner/tool-defer-gate.d.ts +86 -0
  102. package/dist/core/runner/tool-defer-gate.js +57 -0
  103. package/dist/core/runner/tool-disclosure.d.ts +33 -69
  104. package/dist/core/runner/tool-disclosure.js +0 -43
  105. package/dist/core/runner/tool-end-body.d.ts +3 -3
  106. package/dist/core/runner/tool-face-overlay.d.ts +2 -2
  107. package/dist/core/runner/tool-output-projection.d.ts +2 -2
  108. package/dist/core/runner/turn-attachments.d.ts +53 -53
  109. package/dist/core/runner/usage-accounting.d.ts +4 -4
  110. package/dist/core/runner/workspace-path.d.ts +1 -1
  111. package/dist/core/runner-deps.d.ts +16 -9
  112. package/dist/core/task-spec.d.ts +8 -2
  113. package/dist/core/tool-spec.d.ts +7 -4
  114. package/dist/core/types.d.ts +1 -1
  115. package/dist/engine/llm/types.d.ts +1 -1
  116. package/dist/index.d.ts +4 -4
  117. package/dist/index.js +3 -3
  118. package/dist/tools/fs/bash-readonly-classifier.d.ts +40 -40
  119. package/dist/tools/fs/encoding.d.ts +31 -40
  120. package/dist/tools/fs/fs-bash.d.ts +76 -35
  121. package/dist/tools/fs/fs-bash.js +86 -29
  122. package/dist/tools/fs/fs-pdf.d.ts +8 -8
  123. package/dist/tools/fs/fs-search-tools.d.ts +4 -4
  124. package/dist/tools/fs/fs-shared.d.ts +144 -158
  125. package/dist/tools/fs/fs-write.d.ts +8 -8
  126. package/dist/tools/fs/gh-rate-limit.d.ts +13 -14
  127. package/dist/tools/fs/index.d.ts +74 -78
  128. package/dist/tools/fs/notebook.d.ts +24 -25
  129. package/dist/tools/fs/pdf.d.ts +3 -3
  130. package/dist/tools/fs/read-deny.d.ts +22 -22
  131. package/dist/tools/fs/read-face.d.ts +21 -24
  132. package/dist/tools/fs/repo-map.d.ts +8 -8
  133. package/dist/tools/fs/safety.d.ts +116 -129
  134. package/dist/tools/fs/search.d.ts +63 -71
  135. package/package.json +5 -2
  136. package/test/export-surface.snapshot.json +9 -1
@@ -5,18 +5,18 @@ import { type DecodedTextFile } from "./encoding.js";
5
5
  import { type ImageDownsampler } from "../../core/mcp.js";
6
6
  import { type EngineNotice } from "../../core/types.js";
7
7
  /**
8
- * The "hand" tool band (design/44 §3) — built per task over an injected {@link ExecutionEnv} and a
9
- * per-task {@link ReadFileState}, closure-captured (design/44 §11 ruling A: the codebase tool idiom; no
10
- * `ToolExecuteContext` growth). Every edit/write enforces the CC-ported safety invariants (read-before-
11
- * edit, content-hash staleness, edit uniqueness, write-back) + rootPath containment (§4). The band is
12
- * the file tools read/edit/write/grep/glob plus a shell: `bash` (effect:write, full shell) for normal
13
- * tasks, or `bash_readonly` (effect:read, allowlisted) under the verifier read-only boundary (§6).
8
+ * The "hand" tool band — built per task over an injected {@link ExecutionEnv} and a per-task
9
+ * {@link ReadFileState}, closure-captured (the codebase tool idiom; no `ToolExecuteContext` growth).
10
+ * Every edit/write enforces the CC-ported safety invariants (read-before-edit, content-hash staleness,
11
+ * edit uniqueness, write-back) plus rootPath containment. The band is the file tools
12
+ * read/edit/write/grep/glob plus a shell: `bash` (effect:write, full shell) for normal tasks, or
13
+ * `bash_readonly` (effect:read, allowlisted) under the verifier read-only boundary.
14
14
  */
15
- /** Byte cap on a single read (design/64 §7.2(3), CC `MAX_OUTPUT_SIZE = 0.25*1024*1024`). A DEFAULT
16
- * whole-file read over this is refused with guidance; an explicit offset/limit slice is served
17
- * (fidelity-sweep F3 — keeps read-before-edit satisfiable on large files). */
15
+ /** Byte cap on a single read (CC `MAX_OUTPUT_SIZE = 0.25*1024*1024`). A DEFAULT whole-file read over
16
+ * this is refused with guidance; an explicit offset/limit slice is served, which keeps
17
+ * read-before-edit satisfiable on large files. */
18
18
  export declare const MAX_READ_BYTES: number;
19
- /** Hard MEMORY upper bound on a sliced (explicit offset/limit) read (fidelity R3-1). The offset/limit
19
+ /** Hard MEMORY upper bound on a sliced (explicit offset/limit) read. The offset/limit
20
20
  * escape hatch bypasses the whole-file byte cap above, but the reader still loads the ENTIRE file into
21
21
  * memory (`readBinaryFile`) before slicing by line — so without this cap, an explicit `offset:1,limit:1`
22
22
  * on a multi-GB file is an OOM lever the model can pull. This bounds the bytes loaded into MEMORY, not
@@ -24,30 +24,27 @@ export declare const MAX_READ_BYTES: number;
24
24
  * explicit slice, with guidance to stream a portion via bash (`sed -n` / `head -c`) instead, which
25
25
  * never loads the whole file. */
26
26
  export declare const SLICED_READ_MAX_BYTES: number;
27
- /** RB-200 F7 (form-one audit, CC 220 @367140-367150, `ned` verbatim): the byte cap Edit refuses ABOVE.
28
- * CC stats the target before touching it and refuses with a formatted-size message when it exceeds
29
- * this; sema's Edit had no equivalent — it goes straight to a whole-file `readBinaryFile` (twice: the
30
- * `old_string:""` full-overwrite branch and the normal find/replace branch), so a multi-GB target was
31
- * an unguarded OOM lever the model could pull with an ordinary Edit call. Read solved the identical
32
- * problem for its own tool via a pre-read `env.fileInfo` stat + a post-read TOCTOU recheck
33
- * ({@link SLICED_READ_MAX_BYTES} above) — same pattern, reused here rather than invented fresh. */
27
+ /** The byte cap Edit refuses ABOVE (CC's own constant, verbatim). CC stats the target before touching
28
+ * it and refuses with a formatted-size message when it exceeds this. Without the gate, Edit goes
29
+ * straight to a whole-file `readBinaryFile` (twice: the `old_string:""` full-overwrite branch and the
30
+ * normal find/replace branch), so a multi-GB target is an unguarded OOM lever an ordinary Edit call
31
+ * can pull. The shape is Read's: a pre-read `env.fileInfo` stat plus a post-read TOCTOU recheck
32
+ * ({@link SLICED_READ_MAX_BYTES} above). */
34
33
  export declare const MAX_EDIT_BYTES: number;
35
- /** RB-200 F7: `Edit`'s human-readable byte-count formatter (CC `pl()` verbatim: bytes below 1KB, else
34
+ /** `Edit`'s human-readable byte-count formatter (CC `pl()` verbatim: bytes below 1KB, else
36
35
  * KB/MB/GB with one decimal, trailing ".0" stripped). */
37
36
  export declare function formatByteSize(n: number): string;
38
- /** RB-200 F7 (independent-review CONFIRMED bug): Node's own string-length ceiling
39
- * (`buffer.constants.MAX_STRING_LENGTH` ~512MiB on V8/Node 24, verified on this host) sits BELOW
40
- * `MAX_EDIT_BYTES` (1GiB, copied from CC's own `ned` constant 220:367009 with no cross-check
41
- * against the host engine's actual limit). A file whose size lands between the two thresholds passes
42
- * Edit's byte-count gate (both the pre-read `fileInfo` stat and the post-read TOCTOU recheck) but
43
- * still crashes `decodeTextBytes`'s `Buffer#toString` with an uncaught `RangeError` reproduced with
44
- * a real ~700MB file and NO race, via the `old_string:""` branch's own documented "no read-before-edit
45
- * gate" path (no Read call needed first). The model would see a bare, unactionable
46
- * "Cannot create a string longer than…" instead of the intended "too large to edit" guidance the byte
47
- * gate exists to provide. A numeric threshold pinned to today's engine constant would be fragile
48
- * across Node/V8 versions (and does nothing for the ALREADY-shipped Read tool's own decode call if a
49
- * future engine ever lowers the ceiling further) — this instead catches ANY decode failure, at
50
- * whatever byte count actually broke, and reports it exactly like the byte-count gate would have. */
37
+ /** Node's own string-length ceiling (`buffer.constants.MAX_STRING_LENGTH` — ~512MiB on V8/Node 24)
38
+ * sits BELOW `MAX_EDIT_BYTES` (1GiB, CC's constant, which was never cross-checked against a host
39
+ * engine's actual limit). A file whose size lands between the two thresholds passes Edit's byte-count
40
+ * gate (both the pre-read `fileInfo` stat and the post-read TOCTOU recheck) and still crashes
41
+ * `decodeTextBytes`'s `Buffer#toString` with an uncaught `RangeError` no race needed, reachable
42
+ * through the `old_string:""` branch's documented "no read-before-edit gate" path. The model would
43
+ * then see a bare, unactionable "Cannot create a string longer than…" instead of the "too large to
44
+ * edit" guidance the byte gate exists to provide. A numeric threshold pinned to today's engine
45
+ * constant would be fragile across Node/V8 versions (and would do nothing for Read's own decode call
46
+ * if a future engine lowered the ceiling further), so this catches ANY decode failure, at whatever
47
+ * byte count actually broke, and reports it exactly like the byte-count gate would have. */
51
48
  export declare function decodeEditBytes(bytes: Uint8Array, path: string): {
52
49
  ok: true;
53
50
  value: DecodedTextFile;
@@ -65,7 +62,7 @@ export declare function truncatedUtf16BodyMessage(tool: string, path: string): s
65
62
  /** Why a bash_readonly refusal is terminal rather than escalated. Appended by every arm of that refusal
66
63
  * family; the arms differ in what they found, never in what the model can do about it. */
67
64
  export declare const BASH_READONLY_CONFINEMENT_NOTE = "bash_readonly is confined to the workspace roots; it has no approval path, so the call is refused rather than escalated.";
68
- /** RB-222 r3 — the readFileState hash coordinate for a file that was JUST WRITTEN via
65
+ /** The readFileState hash coordinate for a file that was JUST WRITTEN via
69
66
  * `encodeTextForFile`: decode the EXACT payload handed to `env.writeFile`, i.e. what the next
70
67
  * re-read's `decodeTextBytes` will produce. A blanket `normalizeFileText` is WRONG on the
71
68
  * encode-preserving Edit lanes: a leading U+FEFF in the new text is stripped by the next read only
@@ -75,7 +72,7 @@ export declare const BASH_READONLY_CONFINEMENT_NOTE = "bash_readonly is confined
75
72
  * and stays correct if the encoding rules ever change. */
76
73
  export declare function persistedTextOf(encoded: string | Uint8Array): string;
77
74
  /**
78
- * #483 — one APPLIED edit as the Edit tool's `details` card records it: the RESOLVED old/new strings
75
+ * One APPLIED edit as the Edit tool's `details` card records it: the RESOLVED old/new strings
79
76
  * (post quote/escape resolution, post deletion-newline widening) in the normalized originalFile
80
77
  * coordinate. This is the card shape a transcript replay must re-apply, so the application step is a
81
78
  * single source shared by the Edit tool's own apply loop and the replay — two spellings of "apply"
@@ -88,14 +85,14 @@ export interface RecordedEdit {
88
85
  replaceAll: boolean;
89
86
  }
90
87
  /**
91
- * #483 — apply ONE recorded edit mechanically (no matching layers, no validation: the recording site
88
+ * Apply ONE recorded edit mechanically (no matching layers, no validation: the recording site
92
89
  * already resolved and validated the strings; a replay consumer that cannot prove `oldString` is
93
90
  * present must fall back to retracting its record, never guess here).
94
91
  *
95
92
  * Two load-bearing details, both shared with the Edit tool's historical inline apply:
96
93
  * - Function-form replacement: the callback's return value is NOT interpreted as a replacement
97
- * pattern, so `$&`/`$$`/`` $` ``/`$'` in `newString` are written literally (S-1; the replaceAll
98
- * split/join path was always literal).
94
+ * pattern, so `$&`/`$$`/`` $` ``/`$'` in `newString` are written literally (the replaceAll
95
+ * split/join path is literal by construction).
99
96
  * - `oldString === ""` is the whole-content OVERWRITE shape: the Edit tool's whitespace-only-file
100
97
  * overwrite lane records `{oldString: "", newString: <full new text>}` after REPLACING the file's
101
98
  * content wholesale (fs-write.ts, the `old_string:""` existing-file branch). The tool's own apply
@@ -103,32 +100,30 @@ export interface RecordedEdit {
103
100
  * it exists for the replay consumer alone — a plain `replace("", ...)` would PREPEND instead.
104
101
  */
105
102
  export declare function applyRecordedEdit(text: string, edit: RecordedEdit): string;
106
- /** fidelity-sweep F3 (stopgap wording): render the read-before-edit refusal, appending the slice/bash
107
- * escape hatch when the target is over the Read byte cap — a bare "read it first" is un-followable
108
- * there (a default whole-file Read refuses such files). Best-effort: an un-stattable file keeps the
109
- * bare CC-verbatim refusal.
103
+ /** Render the read-before-edit refusal, appending the slice/bash escape hatch when the target is over
104
+ * the Read byte cap — a bare "read it first" is un-followable there (a default whole-file Read
105
+ * refuses such files). Best-effort: an un-stattable file keeps the bare CC-verbatim refusal.
110
106
  *
111
- * RB-264 ⑥W1: `fallbackHint` is a caller-supplied parenthetical for the case NO branch below
112
- * diagnosed anything (all three writing tools pass {@link READ_REFUSED_ESCAPE_HINT} — the
113
- * Read-refuses-this-file deadlock, which by construction leaves nothing to stat). It is NOT appended
114
- * beside a sharper hint: both sharper shapes describe files Read handled successfully, so the
115
- * encoding-deadlock sentence would be false there — and stacking two escape routes on one refusal
116
- * buries the one that applies. */
107
+ * `fallbackHint` is a caller-supplied parenthetical for the case NO branch below diagnosed anything
108
+ * (all three writing tools pass {@link READ_REFUSED_ESCAPE_HINT} — the Read-refuses-this-file
109
+ * deadlock, which by construction leaves nothing to stat). It is NOT appended beside a sharper hint:
110
+ * both sharper shapes describe files Read handled successfully, so the encoding-deadlock sentence
111
+ * would be false there — and stacking two escape routes on one refusal buries the one that applies. */
117
112
  export declare function notReadRefusalText(env: ExecutionEnv, toolName: string, key: string, v: Pick<FsViolation, "code" | "message" | "partialView">, signal?: AbortSignal, fallbackHint?: string): Promise<string>;
118
- /** Byte cap on a Read-image WITHOUT a downsampler (batch-C / design/64 §13.4): an image file is returned AS
119
- * a visual `ImageContent` block (base64) rather than refused. Bounded so a huge image can't blow the request.
120
- * 批③: this stat-time cap only bounds the READ; the accept/refuse decision is the base64 gate below (the
121
- * Anthropic limit is on base64 LENGTH, so the effective no-sharp accept bound is raw ≤ 3.75MB). */
113
+ /** Byte cap on a Read-image WITHOUT a downsampler: an image file is returned AS a visual
114
+ * `ImageContent` block (base64) rather than refused. Bounded so a huge image cannot blow the request.
115
+ * This stat-time cap only bounds the READ; the accept/refuse decision is the base64 gate below (the
116
+ * provider limit is on base64 LENGTH, so the effective no-sharp accept bound is raw ≤ 3.75MB). */
122
117
  export declare const MAX_IMAGE_READ_BYTES: number;
123
- /** Byte cap on a Read-image WITH a downsampler (批③): sharp can shrink a big photo to the 2000×2000/3.75MB
124
- * CC target, so the old 5MB hard refusal is replaced by downsampling (CC readImageWithTokenBudget reads the
125
- * file unbounded; we keep an OOM sanity bound — deliberate delta, camera photos fit comfortably). */
118
+ /** Byte cap on a Read-image WITH a downsampler: sharp can shrink a big photo to CC's 2000×2000/3.75MB
119
+ * target, so the smaller hard refusal does not apply (CC readImageWithTokenBudget reads the file
120
+ * unbounded; we keep an OOM sanity bound — deliberate delta, camera photos fit comfortably). */
126
121
  export declare const MAX_IMAGE_DOWNSAMPLE_INPUT_BYTES: number;
127
- /** A4-2 (external black-box audit, ruled 2026-08-03): the no-downsampler cap above is a DELIBERATE bound
128
- * and does not move — what was wrong is that its refusal read like a hard ceiling. Whether the higher cap
129
- * is reachable depends on an OPTIONAL dependency the caller can install, and only this package knew that,
130
- * so the refusal now names the move instead of leaving the caller to guess that the limit is negotiable.
131
- * Appended ONLY on the no-downsampler branch: with sharp already resolved the hint would be false advice. */
122
+ /** The no-downsampler cap above is a DELIBERATE bound and does not move — but its refusal must not
123
+ * read like a hard ceiling. Whether the higher cap is reachable depends on an OPTIONAL dependency the
124
+ * caller can install, and only this package knows that, so the refusal names the move instead of
125
+ * leaving the caller to guess that the limit is negotiable. Appended ONLY on the no-downsampler
126
+ * branch: with sharp already resolved the hint would be false advice. */
132
127
  export declare const NO_DOWNSAMPLER_IMAGE_CAP_HINT = "Install the optional \"sharp\" dependency (declared in this package's optionalDependencies) to read images up to 67108864 bytes \u2014 it downsamples them to fit the API image limit.";
133
128
  /** Read-image downsampler seam: `undefined` → auto-detect sharp; `false` → force-disabled (deterministic
134
129
  * no-sharp path, used by tests + envs that must not touch native deps); a function → injected. */
@@ -136,28 +131,25 @@ export type ReadImageDownsamplerOption = ImageDownsampler | false | undefined;
136
131
  /** Resolve (and memoize) the auto-detected sharp downsampler, process-wide. Shared accessor for the two
137
132
  * consumers of the module-private {@link autoDownsampler} cache. */
138
133
  export declare function resolveAutoDownsampler(): Promise<ImageDownsampler | undefined>;
139
- /** Output-token cap as a char proxy (design/64 §7.2(3), CC `Py_ = 25000` @335039; ~4 chars/token).
140
- * Caps the shown body so 2000 very long lines can't blow the context budget.
134
+ /** Output-token cap as a char proxy (CC's 25000, at ~4 chars/token). Caps the shown body so 2000 very
135
+ * long lines cannot blow the context budget.
141
136
  *
142
- * RB-285 M5 (归因收窄, CC 220 亲核): only the 25000 NUMBER is CC's. CC does NOT use a flat chars/4
143
- * proxy — `KMu` @279761 pre-filters with a PER-EXTENSION chars-per-token coefficient (json/jsonl = 2,
144
- * i.e. half of the 4 assumed here) and then confirms with a REAL tokenizer (`BLd` @518589); the
145
- * budget itself is also overridable per call (`fileReadingLimits`) and by the `tengu_amber_wren` gate
146
- * (`eze` @335063 (cli250.js:39563)), neither of which has a sema lane. Consequence, stated rather than hidden: on
147
- * token-dense text (JSON/CJK/base64) this proxy UNDER-counts, so sema serves a page CC would have cut
148
- * further; on token-sparse text it over-counts and paginates earlier than CC. A real tokenizer here
149
- * would need a provider-neutral counting seam (BYOM no single vocabulary), which is why the proxy
150
- * stands; the divergence is a fidelity delta, not a correctness one (the partial-view marker always
151
- * states the served window truthfully). */
137
+ * Only the 25000 NUMBER is CC's. CC does NOT use a flat chars/4 proxy — it pre-filters with a
138
+ * PER-EXTENSION chars-per-token coefficient (json/jsonl = 2, half the 4 assumed here) and then
139
+ * confirms with a REAL tokenizer; its budget is also overridable per call and by a feature gate,
140
+ * neither of which has a sema lane. Consequence, stated rather than hidden: on token-dense text
141
+ * (JSON/CJK/base64) this proxy UNDER-counts, so sema serves a page CC would have cut further; on
142
+ * token-sparse text it over-counts and paginates earlier than CC. A real tokenizer here would need a
143
+ * provider-neutral counting seam (BYOM no single vocabulary), which is why the proxy stands; the
144
+ * divergence is a fidelity delta, not a correctness one (the partial-view marker always states the
145
+ * served window truthfully). */
152
146
  export declare const MAX_READ_OUTPUT_CHARS = 100000;
153
- /** Per-read content-safety reminder appended after a text read (design/64 §7.2(7)).
147
+ /** Per-read content-safety reminder appended after a text read.
154
148
  *
155
- * Attribution, stated precisely because it was previously stated twice and wrongly in both directions.
156
- * The upstream 88 source DOES carry the same mechanism — `FileReadTool.ts`'s
157
- * `CYBER_RISK_MITIGATION_REMINDER`, appended after every text read, behind a PER-MODEL exemption gate.
158
- * The 220 baseline does NOT: the text is gone (`grep -c malware pretty220.js` = 0), retired once the
159
- * mitigation moved inside the serving model. So "not an upstream port" is false against 88 and true
160
- * against 220, and neither reading alone describes the situation.
149
+ * Attribution, stated precisely because either half alone is wrong. The upstream 88 source DOES carry
150
+ * the same mechanism — `FileReadTool`'s `CYBER_RISK_MITIGATION_REMINDER`, appended after every text
151
+ * read, behind a PER-MODEL exemption gate. The 220 baseline does NOT: the text is gone, retired once
152
+ * the mitigation moved inside the serving model.
161
153
  *
162
154
  * This engine keeps it because a BYOM deployment cannot assume its serving model carries the
163
155
  * mitigation, and adjacency is the whole mechanism (a reminder in a system prompt hundreds of turns
@@ -169,16 +161,15 @@ export declare const MAX_READ_OUTPUT_CHARS = 100000;
169
161
  * COVERAGE, stated because the switch is easy to over-read: the reminder rides the plain-text read and
170
162
  * the notebook projection. PDF text extraction returns through its own result builder and has never
171
163
  * carried it, so extracted PDF text reaches the model without this mitigation whatever the switch says.
172
- * That gap predates the switch; its IMPERSONATION half is now closed — design/319 (B ticket) gave the
173
- * PDF text legs the same detect-and-disclose trailer as this lane (reminder-shaped bytes in extracted
174
- * PDF text are disclosed at the outlet, fs-pdf.ts), and their bodies were already fenced. The CYBER
175
- * half (this malware-alertness sentence) still does not ride PDF text and stays an open item rather
176
- * than closed silently — widening it to a third surface is a change to what every PDF read costs,
177
- * not a wiring fix.
164
+ * That gap predates the switch; its IMPERSONATION half is closed — the PDF text legs carry the same
165
+ * detect-and-disclose trailer as this lane (reminder-shaped bytes in extracted PDF text are disclosed
166
+ * at the outlet, fs-pdf.ts), and their bodies are fenced. The CYBER half (this malware-alertness
167
+ * sentence) still does not ride PDF text and stays an open item rather than closed silently —
168
+ * widening it to a third surface is a change to what every PDF read costs, not a wiring fix.
178
169
  *
179
- * design/319 (A ticket): a FUNCTION over the session mark (formerly the `READ_CYBER_REMINDER`
180
- * constant) the open tag is rendered by the mint home so it carries the run's provenance mark;
181
- * the sentence bytes are unchanged, and a markless call renders the historic bare form verbatim. */
170
+ * A FUNCTION over the session mark, not a constant: the open tag is rendered by the mint home so it
171
+ * carries the run's provenance mark; the sentence bytes are unchanged, and a markless call renders
172
+ * the bare form verbatim. */
182
173
  export declare function readCyberReminderText(mark: string | undefined): string;
183
174
  export declare const BASH_DEFAULT_TIMEOUT_SEC = 120;
184
175
  export declare const BASH_MAX_TIMEOUT_SEC = 600;
@@ -238,10 +229,9 @@ export declare function bashTimeoutArgRefusal(timeoutMs: number | undefined, cap
238
229
  maxMs: number;
239
230
  }): string | undefined;
240
231
  /**
241
- * RB-370 ②/③ — the SINGLE authority for the Bash `timeout` parameter's two numbers:
242
- * the default budget applied when the model omits `timeout`, and the engine ceiling requests are
243
- * clamped to. The 120s/600s constants themselves are CC 220-same; what CC additionally has and this
244
- * resolver adds — is configurability.
232
+ * The SINGLE authority for the Bash `timeout` parameter's two numbers: the default budget applied
233
+ * when the model omits `timeout`, and the engine ceiling requests are clamped to. The 120s/600s
234
+ * constants themselves are CC-same; what this resolver adds on top is configurability.
245
235
  *
246
236
  * Resolution, per leg (options over env over constant — the standing sema discipline: "deployments
247
237
  * configure the tool, not the process"; env stays as the CC-shaped fallback for process-level tuning):
@@ -252,7 +242,7 @@ export declare function bashTimeoutArgRefusal(timeoutMs: number | undefined, cap
252
242
  * default floors the cap. Invalid values (non-finite / <= 0) are discarded at every leg, options
253
243
  * included, exactly like CC's env read.
254
244
  *
255
- * Readable seam: a shell/host rendering its OWN copy of the Bash tool description MUST
245
+ * Readable seam: a shell/host rendering its OWN copy of the Bash tool description MUST
256
246
  * read the true values from here instead of holding a sibling constant — the engine's description/param
257
247
  * text and its runtime clamp both interpolate this function's output (resolved once per tool instance),
258
248
  * so a self-held "600s" only matches by coincidence and forks silently the moment a deployment
@@ -273,8 +263,8 @@ export declare function resolveBashTimeoutCaps(opts?: {
273
263
  * the line must be able to re-arm the ledger. Re-arms BOTH arms (a WeakMap has no clear — it is
274
264
  * re-minted). Never called by production code. */
275
265
  export declare function __resetBashTimeoutAnnouncements(): void;
276
- /** RB-370 ②: the seconds view of a resolved {@link resolveBashTimeoutCaps} pair — the shell's INTERNAL
277
- * unit stays seconds while every model-facing surface stays ms (design/64 §8.1C posture). One rounding
266
+ /** The seconds view of a resolved {@link resolveBashTimeoutCaps} pair — the shell's INTERNAL unit
267
+ * stays seconds while every model-facing surface stays ms. One rounding
278
268
  * point, same Math.round form as the model-supplied timeout's own ms→s conversion, floored at 1s. */
279
269
  export declare function bashTimeoutCapsSec(caps: {
280
270
  defaultMs: number;
@@ -287,22 +277,21 @@ export declare function bashMaxOutputChars(): number;
287
277
  export declare const FILE_PATH_PARAMS: {
288
278
  file_path: Type.TString;
289
279
  };
290
- /** Honest head+tail truncation to {@link bashMaxOutputChars} (the middle is dropped with a real-total marker —
291
- * the head AND tail both matter for a shell deliberately KEPT as the inline shape even after RB-198 F4 added
292
- * file-backed recovery below: unlike a background task's poll-for-the-latest-tail interaction, a foreground
293
- * command's head can carry status a bare tail-keep would drop, and this shape is already tested/relied on).
294
- * Shared by runShell (foreground) and TaskOutput (background poll). Delegates its arithmetic to the shared
295
- * {@link clipWithFilePointer} (RB-85/RB-112/RB-122-hardened) but never exercises its pointer arm — no caller
296
- * here passes a path. */
280
+ /** Honest head+tail truncation to {@link bashMaxOutputChars}: the middle is dropped with a real-total
281
+ * marker, because the head AND tail both matter for a shell. Kept as the inline shape even beside the
282
+ * file-backed recovery below unlike a background task's poll-for-the-latest-tail interaction, a
283
+ * foreground command's head can carry status a bare tail-keep would drop. Shared by runShell
284
+ * (foreground) and TaskOutput (background poll). Delegates its arithmetic to the shared
285
+ * {@link clipWithFilePointer} but never exercises its pointer arm — no caller here passes a path. */
297
286
  export declare function clipShellOutput(s: string): string;
298
287
  /**
299
- * RB-198 F4 (form-one audit, "前台大输出落盘回读"): a foreground command's captured stdout/stderr are
300
- * ALREADY fully in memory here (the env delivered them whole — only `clipShellOutput` above decides how
301
- * much of that the model's turn actually sees) the gap this closes is that the omitted middle was
302
- * simply discarded, forcing a blind full re-run to recover output that was, in fact, captured. "Whole"
303
- * means whatever THIS layer received, not a guarantee about what the process originally wrote (
304
- * review P1): the env's own rolling-tail cap (`MAX_EXEC_OUTPUT_BYTES`, exec-output-tail.ts) can already
305
- * have dropped the head before delivery on a truly enormous single command — this file is a faithful copy
288
+ * A foreground command's captured stdout/stderr are ALREADY fully in memory here (the env delivered
289
+ * them whole — only `clipShellOutput` above decides how much of that the model's turn actually sees).
290
+ * What this closes is that the omitted middle would otherwise be discarded, forcing a blind full
291
+ * re-run to recover output that was, in fact, captured. "Whole" means whatever THIS layer received,
292
+ * not a guarantee about what the process originally wrote: the env's own rolling-tail cap
293
+ * (`MAX_EXEC_OUTPUT_BYTES`, exec-output-tail.ts) can already have dropped the head before delivery on
294
+ * a truly enormous single command — this file is a faithful copy
306
295
  * of the received bytes either way, and still carries that cap's own `markTruncated()` marker when it
307
296
  * fired, so nothing here overclaims completeness beyond what the text itself already discloses. Purely
308
297
  * ADDITIVE: the inline head+tail framing above is untouched; this only gives the model a second, explicit
@@ -320,20 +309,20 @@ export declare function clipShellOutput(s: string): string;
320
309
  * containment on their explicit path arguments), so the model already has a direct route to the file: a
321
310
  * later `bash` call — the message text says so explicitly rather than implying Read will work, and picks
322
311
  * an example command the CALLING tool variant can actually run (see {@link shellRecoveryHint}: `sed -n`
323
- * for full `bash`, an allowlisted `tail -c` for `bash_readonly`, independent-review finding B). Creation/
324
- * write failure degrades silently to no file (the inline clip is unaffected either way), matching A5's
325
- * own degrade posture.
312
+ * for full `bash`, an allowlisted `tail -c` for `bash_readonly`). Creation/write failure degrades
313
+ * silently to no file (the inline clip is unaffected either way), matching the background lane's own
314
+ * degrade posture.
326
315
  */
327
316
  export declare function writeShellOverflowFile(env: ExecutionEnv, stdout: string, stderr: string): Promise<string | undefined>;
328
317
  /**
329
- * RB-421 (BB-5) — recognise the engine's OWN shell overflow recovery files, so `bash_readonly` can keep
330
- * honouring the `tail -c … <file>` command its result trailer advertises.
318
+ * Recognise the engine's OWN shell overflow recovery files, so `bash_readonly` can keep honouring the
319
+ * `tail -c … <file>` command its result trailer advertises.
331
320
  *
332
- * The first cut of that exemption was a `Set` of the exact paths ONE tool instance had minted. But the
333
- * trailer lives in the transcript, not in the instance: the hands toolkit is rebuilt on every task
334
- * preparation, so a later run replaying the advertised command met a tool with no memory of it and was
335
- * refused — the engine refusing its own advice, and (in the read-only band, whose Read tool is fenced by
336
- * the same roots) the only route to the truncated output.
321
+ * NOT a `Set` of the exact paths one tool instance minted: the trailer lives in the transcript, not in
322
+ * the instance, and the hands toolkit is rebuilt on every task preparation — a later run replaying the
323
+ * advertised command would meet a tool with no memory of it and be refused, i.e. the engine refusing
324
+ * its own advice, and (in the read-only band, whose Read tool is fenced by the same roots) the only
325
+ * route to the truncated output.
337
326
  *
338
327
  * Judged by SHAPE instead, which survives any rebuild, with the grant kept pinned to the engine's own
339
328
  * temp area on three counts that must ALL hold:
@@ -358,7 +347,7 @@ export declare function writeShellOverflowFile(env: ExecutionEnv, stdout: string
358
347
  */
359
348
  export declare function createShellOverflowSpoolFence(env: ExecutionEnv): (path: string) => Promise<boolean>;
360
349
  /**
361
- * RB-198 F4 (independent-review finding B): the recovery-file trailer's example command must be one the
350
+ * The recovery-file trailer's example command must be one the
362
351
  * CALLING tool can actually run. `sed` is not in {@link import("./bash-readonly-classifier.js").BASH_READONLY_DEFAULT_ALLOW} and `bash_readonly`
363
352
  * forbids the operators a pipe/redirect would need, so a `bash_readonly` command that overflows gets a
364
353
  * single-command, allowlisted alternative instead (`tail -c`, byte-bounded so it doesn't depend on line
@@ -366,17 +355,17 @@ export declare function createShellOverflowSpoolFence(env: ExecutionEnv): (path:
366
355
  * executable. Full `bash` keeps the precise form.
367
356
  */
368
357
  export declare function shellRecoveryHint(path: string, readOnly: boolean | undefined): string;
369
- /** CC 2.1.198 live-verbatim Edit/Write success trailer (all-tools-live-probe 2026-07-08 §2.1/§3.1)
370
- * appended to every Edit/Write success message (NOT NotebookEdit — CC ships it without the trailer). */
358
+ /** CC 2.1.198 live-verbatim Edit/Write success trailer appended to every Edit/Write success message
359
+ * (NOT NotebookEdit — CC ships it without the trailer). */
371
360
  export declare const FILE_STATE_TRAILER = " (file state is current in your context \u2014 no need to Read it back)";
372
361
  export declare const CWD_SENTINEL = "__cc_cwd_9f2c1b__";
373
- /** Convert a model-supplied millisecond timeout to our internal seconds, clamped (design/64 §8.1C). Exported
374
- * for the cc-parity TC-8.2 unit (model sees ms, internal stays seconds — no ×1000 error).
375
- * ⚠️ RB-370: this returns the EFFECTIVE budget, not the request — capping at a call site destroys the
376
- * caller's number before it can be disclosed. The Bash legs deliberately do NOT use this anymore (they
377
- * pass the uncapped conversion into runShell, which caps once and reports the true request); use this
378
- * only where the post-ceiling value is what you mean.
379
- * RB-370 ②: the clamp bounds are no longer the bare constants — pass the caller's resolved caps
362
+ /** Convert a model-supplied millisecond timeout to our internal seconds, clamped. Exported for the
363
+ * cc-parity unit (model sees ms, internal stays seconds — no ×1000 error).
364
+ * ⚠️ This returns the EFFECTIVE budget, not the request — capping at a call site destroys the
365
+ * caller's number before it can be disclosed. The Bash legs deliberately do NOT use it (they pass the
366
+ * uncapped conversion into runShell, which caps once and reports the true request); use this only
367
+ * where the post-ceiling value is what you mean.
368
+ * The clamp bounds are not the bare constants — pass the caller's resolved caps
380
369
  * ({@link resolveBashTimeoutCaps}) to clamp against a configured deployment; omitted ⇒ resolve fresh
381
370
  * (zero-config = the historical 120s/600s, byte-compat).
382
371
  * ⚠️ This is the RAW converter and NOT the authority on what the tool accepts: it still folds the whole
@@ -388,7 +377,7 @@ export declare function msTimeoutToSec(timeoutMs: number | undefined, caps?: {
388
377
  defaultMs: number;
389
378
  maxMs: number;
390
379
  }): number;
391
- /** `.ipynb` redirect (design/64 §7.2(5), CC `FileEditTool:266-270`): a raw text edit/overwrite corrupts the
380
+ /** `.ipynb` redirect (CC FileEditTool parity): a raw text edit/overwrite corrupts the
392
381
  * notebook JSON, so the text-edit face refuses and redirects to the NotebookEdit tool (built in
393
382
  * src/tools/fs/fs-write.ts, mounted with the rest of the hands band). */
394
383
  export declare function ipynbRedirect(toolName: string, path: string): string | undefined;
@@ -397,32 +386,29 @@ export declare function ipynbRedirect(toolName: string, path: string): string |
397
386
  * ends in "\n". Behavior is identical for content WITHOUT a trailing newline. Shared by read_file's
398
387
  * `total`, edit_file/write_file's "N lines" report, and the persisted ReadFileState.totalLines. */
399
388
  export declare function countLines(s: string): number;
400
- /** parity-204 — CC 2.1.204 VERBATIM (constants `qfc`+`Wfc`, cc204-bundle @9438179/@9440917; 198 zero
401
- * hits): the reminder served when a DEFAULT whole-file Read hits a startup-seeded, unchanged file.
402
- * CC: ``Wfc(e) = `${qfc} (see "Contents of ${e}" above) and has not changed on disk. Use that content
403
- * instead of re-reading.</system-reminder>``` with `qfc = '<system-reminder>This file is already in
404
- * your context'`. `filePath` is the CANONICAL key (CC passes the resolved full path `f`, matching the
389
+ /** CC 2.1.204 VERBATIM: the reminder served when a DEFAULT whole-file Read hits a startup-seeded,
390
+ * unchanged file. `filePath` is the CANONICAL key (CC passes the resolved full path, matching the
405
391
  * `Contents of <path>` header its context seeding emits — deployments seeding files should title the
406
- * injected block the same way so the back-reference lands). Locked verbatim by test (逐字常量锁)
407
- * design/319: the BODY and close tag stay CC-verbatim; the open tag alone is rendered by the mint
408
- * home and carries the session mark when one is threaded (the recorded wire-form divergence). */
392
+ * injected block the same way so the back-reference lands). Locked verbatim by test: the BODY and
393
+ * close tag stay CC-verbatim; the open tag alone is rendered by the mint home and carries the session
394
+ * mark when one is threaded (the recorded wire-form divergence). */
409
395
  export declare function seededFileUnchangedReminder(filePath: string, mark?: string): string;
410
396
  /**
411
- * RB-197②(交叉复审命中,已修) — true when `resultText` is one of the Read tool's TWO dedup
412
- * markers (the ordinary unchanged-since-last-read stub below, or {@link seededFileUnchangedReminder})
413
- * rather than a genuine content transmission. A consumer deciding "is this file's real content
414
- * present in THIS message" (e.g. auto-compaction's kept-tail visibility scan) must treat a stub hit
415
- * as absence — the marker POINTS AT an earlier read that may itself no longer be in context.
397
+ * True when `resultText` is one of the Read tool's TWO dedup markers (the ordinary
398
+ * unchanged-since-last-read stub below, or {@link seededFileUnchangedReminder}) rather than a genuine
399
+ * content transmission. A consumer deciding "is this file's real content present in THIS message"
400
+ * (e.g. auto-compaction's kept-tail visibility scan) must treat a stub hit as absence — the marker
401
+ * POINTS AT an earlier read that may itself no longer be in context.
416
402
  *
417
- * RB-373: both emitters now ALSO carry a structured marker (`details.type === "file_unchanged"`,
403
+ * Both emitters ALSO carry a structured marker (`details.type === "file_unchanged"`,
418
404
  * fs-read.ts `fileUnchangedResult`) — consumers with access to the tool result's `details` should
419
405
  * branch on that instead of this prose match (which can false-positive on file CONTENT that quotes
420
406
  * either sentence). This predicate stays for text-only surfaces (compaction sees rendered text).
421
407
  */
422
408
  export declare function isReadDedupStubResult(resultText: string): boolean;
423
- /** parity-204 — pre-seed the hands' read state for a file whose FULL, disk-verbatim text was injected
424
- * into the model's context at startup (CC 2.1.204 `seededFromContext:!0` seeding, cc204-bundle
425
- * @17917159: CLAUDE.md/nested-memory preload; sema: ProjectMemoryLoad.seededFiles → prepare-task).
409
+ /** Pre-seed the hands' read state for a file whose FULL, disk-verbatim text was injected into the
410
+ * model's context at startup (CC 2.1.204 `seededFromContext` seeding of the memory preload; sema:
411
+ * ProjectMemoryLoad.seededFiles → prepare-task).
426
412
  * `content` MUST be the file's exact disk text at load time — the Read tool's seeded dedup treats a
427
413
  * hash match as "unchanged"; a truncated/annotated variant must NOT be seeded (CC exempts those via
428
414
  * `isPartialView`; sema's contract is simply "don't seed partials"). `key` is the CANONICAL path
@@ -431,7 +417,7 @@ export declare function isReadDedupStubResult(resultText: string): boolean;
431
417
  export declare function seedReadFileStateFromContext(state: ReadFileState, key: string, content: string): void;
432
418
  /**
433
419
  * Seed the hands' read state from a WHOLE-file content the session transcript recorded on an earlier
434
- * turn (ruled 2026-08-05; the selection rules live in core/runner/session-file-state-replay.ts).
420
+ * turn (the selection rules live in core/runner/session-file-state-replay.ts).
435
421
  *
436
422
  * Same minting as {@link seedReadFileStateFromContext} and the same normalization reason, with three
437
423
  * deliberate differences, each of which is a claim this seed cannot honestly make:
@@ -446,7 +432,7 @@ export declare function seedReadFileStateFromContext(state: ReadFileState, key:
446
432
  */
447
433
  export declare function seedReadFileStateFromTranscript(state: ReadFileState, key: string, content: string, lastReadAt: number): void;
448
434
  /**
449
- * #483 rung-1 — copy a SESSION-inherited read-file state into a new task's map, under the new task's
435
+ * Copy a SESSION-inherited read-file state into a new task's map, under the new task's
450
436
  * own containment judgment (CC parity: readFileState is session-scoped — minted once per REPL session,
451
437
  * mutated across turns, with no turn-boundary or abort clear site; sema's per-task map inherits the
452
438
  * previous turn's live state instead).
@@ -458,7 +444,7 @@ export declare function seedReadFileStateFromTranscript(state: ReadFileState, ke
458
444
  * replay leg already judges — an unjudged copy would smuggle out-of-face entries into the task
459
445
  * (and into its checkpoints).
460
446
  * - **`seededFromContext` entries do not inherit.** That flag claims the file's text lives in the
461
- * system-prompt lane OF THIS TASK — a claim only this task's own startup seeding (T10) can make.
447
+ * system-prompt lane OF THIS TASK — a claim only this task's own startup seeding can make.
462
448
  * A still-declared file is re-seeded the same turn (no loss); a no-longer-declared one must not
463
449
  * keep answering reads with an "already in your context" reminder that is no longer true.
464
450
  *
@@ -468,8 +454,8 @@ export declare function seedReadFileStateFromTranscript(state: ReadFileState, ke
468
454
  */
469
455
  export declare function inheritSessionReadFileState(target: ReadFileState, inherited: ReadFileState, judgeKey: (recordedKey: string) => Promise<string | undefined>): Promise<void>;
470
456
  /**
471
- * RB-197 (form-one audit, CC 2.1.220 @388663-388664): a landed compaction summarizes old Read results OUT
472
- * of the context, so every non-seeded read-state entry must be dropped — CC snapshots then
457
+ * CC parity: a landed compaction summarizes old Read results OUT of the context, so every non-seeded
458
+ * read-state entry must be dropped — CC snapshots then
473
459
  * `readFileState.clear()`s at the same spot. Without this, the Read dedup stub above answers a re-read of
474
460
  * an unchanged file with "content omitted to save context" pointing at content that no longer exists
475
461
  * anywhere in the context (the model works from hallucinated memory or has to vary offset/limit to escape).
@@ -482,14 +468,14 @@ export declare function inheritSessionReadFileState(target: ReadFileState, inher
482
468
  * The read-before-edit gate tightens as a consequence, matching CC: after a compaction the model must
483
469
  * re-Read a summarized-away file before editing it, instead of blind-editing from a stale recollection.
484
470
  *
485
- * RB-197②(独立复审 + 命中,已修): a THIRD category besides seeded/re-attached a file whose most
486
- * recent Read is still visible verbatim in the compaction's KEPT tail is deliberately left OUT of
471
+ * A THIRD category besides seeded/re-attached: a file whose most recent Read is still visible
472
+ * verbatim in the compaction's KEPT tail is deliberately left OUT of
487
473
  * `attachedComplete` (re-attaching it would just duplicate content already in context), but its
488
474
  * existing read-state entry must survive unmodified for the SAME reason a seeded entry does: the
489
- * model's view of it did not change. Wiping it (the pre-fix behavior) broke two things for exactly
490
- * these files — the read-before-edit gate would reject an Edit the model could visibly justify from
491
- * its own kept-tail Read, and a next Read would miss the dedup stub and retransmit the whole file,
492
- * recreating the exact waste RB-197①/② exist to remove. `preserveKeys` is the caller's kept-tail set
475
+ * model's view of it did not change. Wiping it breaks two things for exactly these files — the
476
+ * read-before-edit gate would reject an Edit the model could visibly justify from its own kept-tail
477
+ * Read, and a next Read would miss the dedup stub and retransmit the whole file, recreating the exact
478
+ * waste this dedup exists to remove. `preserveKeys` is the caller's kept-tail set
493
479
  * (see `maybeCompact`'s `candidateFiles` computation) — passed as keys already in `state`'s own
494
480
  * coordinate (canonicalized the same way the Read/Edit/Write tools populate it), so a plain lookup
495
481
  * suffices; no re-hash/re-register needed since the entry's content genuinely has not changed.
@@ -498,7 +484,7 @@ export declare function applyCompactionToReadFileState(state: ReadFileState, att
498
484
  path: string;
499
485
  content: string;
500
486
  }>, preserveKeys?: ReadonlyArray<string>): void;
501
- /** 批④ #1 (CC 2.1.198 verbatim skeleton, bundle :48196/:335883/:478419): the ENOENT error body for a
487
+ /** CC 2.1.198 verbatim skeleton: the ENOENT error body for a
502
488
  * missing Read/Edit target — `File does not exist. Note: your current working directory is <cwd>.`
503
489
  * plus a `Did you mean <sibling>?` correction when the parent directory holds a near-name (case
504
490
  * variant / same stem different extension — the high-frequency self-heal path). Best-effort: a
@@ -508,7 +494,7 @@ export declare function enoentMessage(env: ExecutionEnv, key: string, cwd: strin
508
494
  pattern: string;
509
495
  } | null;
510
496
  }): Promise<string>;
511
- /** Per-task mutable working directory shared by the shell and the path-taking fs tools (design/64 §16.3).
497
+ /** Per-task mutable working directory shared by the shell and the path-taking fs tools.
512
498
  * Holds the RAW path (never canonicalized): bash `cd` updates `current`, and the fs tools resolve relative
513
499
  * paths against it. Containment is still enforced per-op by resolveKey (canonicalize + within), so a `cd`
514
500
  * through a symlink out of root cannot carry across a relative fs path outside. */
@@ -3,13 +3,13 @@ import type { BeforeWriteHook, FileEditedHook, TrackFileEditHook } from "../../c
3
3
  import { type ReadFileState } from "./safety.js";
4
4
  import { type CwdRef } from "./fs-shared.js";
5
5
  /**
6
- * design/138 S2-C — the `beforeWrite` CONTENT hook (C-F2: mounted here, not in ToolPolicy, because
7
- * only this band sees the FINAL text an Edit/NotebookEdit produces — the applied old→new full text
8
- * is what actually lands on disk). Called before EVERY `env.writeFile` in Write/Edit/NotebookEdit
9
- * with the resolved containment key and the exact text about to be written. Returning `{ ok:false }`
10
- * makes the tool fail with a structured error and NOTHING is written. The Runner wires this to the
11
- * MemoryEngine's write gate (`MemoryEngine.gateWrite`) a non-memory path passes with one string
12
- * prefix comparison there (零开销直通). Absent hook ⇒ byte-identical behavior.
6
+ * The `beforeWrite` CONTENT hook, mounted here rather than in ToolPolicy because only this band sees
7
+ * the FINAL text an Edit/NotebookEdit produces — the applied old→new full text is what actually lands
8
+ * on disk. Called before EVERY `env.writeFile` in Write/Edit/NotebookEdit with the resolved
9
+ * containment key and the exact text about to be written. Returning `{ ok:false }` makes the tool fail
10
+ * with a structured error and NOTHING is written. The Runner wires this to the MemoryEngine's write
11
+ * gate (`MemoryEngine.gateWrite`), where a non-memory path passes on one string prefix comparison.
12
+ * Absent hook ⇒ byte-identical behavior.
13
13
  */
14
14
  export type { BeforeWriteRequest, BeforeWriteResult, BeforeWriteHook, TrackEditRequest, TrackEditResult, TrackFileEditHook } from "../../core/types.js";
15
15
  export declare function createEditFileTool(env: ExecutionEnv, state: ReadFileState, rootCanonical: string, cwdRef?: CwdRef, additionalRoots?: readonly string[], beforeWrite?: BeforeWriteHook, trackEdit?: TrackFileEditHook, onEdited?: FileEditedHook): AgentTool;
@@ -18,7 +18,7 @@ export declare function createWriteFileTool(env: ExecutionEnv, state: ReadFileSt
18
18
  * design v1.163 — NotebookEdit: replace/insert/delete a single cell in a .ipynb. CC-parity tool over the SAME hand-band
19
19
  * safety skeleton as Edit/Write (resolveKey containment → requireRead read-before-edit → checkStale content-hash
20
20
  * freshness → mutate → writeFile → state.set), with object ops swapped for ipynb-JSON cell mutation. Read serves
21
- * .ipynb as the RB-227 cell projection but records read state (hash/totalLines) in the RAW notebook-text
21
+ * .ipynb as the cell projection but records read state (hash/totalLines) in the RAW notebook-text
22
22
  * coordinate — that raw-coordinate read record is what this tool's freshness check depends on.
23
23
  */
24
24
  export declare function createNotebookEditTool(env: ExecutionEnv, state: ReadFileState, rootCanonical: string, cwdRef?: CwdRef, additionalRoots?: readonly string[], beforeWrite?: BeforeWriteHook, trackEdit?: TrackFileEditHook, onEdited?: FileEditedHook): AgentTool;
@@ -1,27 +1,26 @@
1
1
  /**
2
- * gh rate-limit hint (CC 2.1.198 parity — PARITY-SPOT-REMINDERS SR-2).
2
+ * gh rate-limit hint (CC 2.1.198 parity).
3
3
  *
4
4
  * CC appends a one-shot <system-reminder> to a FOREGROUND Bash result when a `gh` invocation hits the
5
- * GitHub API rate limit, so the model sleeps/schedules instead of hammering retries. Anchors:
6
- * pretty.js:281399-281404 (`Bxa` the reminder text), :281472-281473 (`m0p` command gate + `f0p`
7
- * output gate, both ported verbatim), :281426 (`h0p` = 60s throttle), :335536 (attach point — background
8
- * tasks are never hinted). sema delta (recorded): CC's closing clause names its ScheduleWakeup tool;
9
- * sema's wait primitive is the Monitor tool, so the clause is adapted — everything else is verbatim.
5
+ * GitHub API rate limit, so the model sleeps/schedules instead of hammering retries. The command gate,
6
+ * output gate and 60s throttle below are ported verbatim; a detached/background task is never hinted.
7
+ * Registered delta: CC's closing clause names its ScheduleWakeup tool; sema's wait primitive is the
8
+ * Monitor tool, so that clause is adapted everything else is verbatim.
10
9
  */
11
- /** Test seam: reset the process-wide throttle window (mirrors CC's module-level `Mxa`). */
10
+ /** Test seam: reset the process-wide throttle window (mirrors CC's module-level timestamp). */
12
11
  export declare function resetGhRateLimitHintThrottleForTests(): void;
13
12
  /**
14
13
  * Returns the rate-limit reminder when `command` is a real gh call AND `output` shows a rate-limit
15
14
  * error AND the 60s throttle window is open; otherwise undefined. Callers attach it to FOREGROUND
16
15
  * Bash results only (CC gates on `backgroundTaskId` — a detached/background task is never hinted).
17
16
  *
18
- * `monitorToolActive` (#181-F6): the closing clause teaches the Monitor tool, but Monitor is mounted
19
- * by the Runner (`backgroundTaskToolsActive`), not by the Bash tool — under handsReadOnly or a
20
- * background-less env the taught tool is not on the roster. `false` drops exactly that clause (the
21
- * sleep-until-reset advice stays); absent/`true` keeps the historic full wording (RB-374① posture:
22
- * an uninformed caller gets the byte-identical sentence, never a silent rewrite).
17
+ * `monitorToolActive`: the closing clause teaches the Monitor tool, but Monitor is mounted by the
18
+ * Runner (`backgroundTaskToolsActive`), not by the Bash tool — under handsReadOnly or a background-less
19
+ * env the taught tool is not on the roster. `false` drops exactly that clause (the sleep-until-reset
20
+ * advice stays); absent/`true` keeps the full wording, so an uninformed caller gets the byte-identical
21
+ * sentence rather than a silent rewrite.
23
22
  *
24
- * design/319 (A ticket): `mark` the session's reminder provenance mark, stamped on the open tag
25
- * by the mint home (body bytes unchanged; absent ⇒ historic bare tag).
23
+ * `mark`: the session's reminder provenance mark, stamped on the open tag by the mint home (body bytes
24
+ * unchanged; absent ⇒ bare tag).
26
25
  */
27
26
  export declare function ghRateLimitHint(command: string, output: string, now?: number, monitorToolActive?: boolean, mark?: string): string | undefined;