Преглед на файлове

docs(compact): correct pruning surface contracts

Tianyi Cui преди 1 месец
родител
ревизия
7aee299bda

+ 2 - 0
docs/cordis-catalog/services.md

@@ -1147,6 +1147,8 @@ pruneContent(blocks: readonly ContentBlock[]): ContentBlock[] | null
  * and points at the shadowed node for durable provenance and replay.
  * @param session - session whose current surface is rewritten.
  * @returns landed replacements and aggregate Unicode-code-point savings.
+ * @throws when the session rejects a replacement; replacements committed
+ * earlier in the pass remain durable.
  */
 pruneSession(session: Session): PruneResult
 ```

+ 1 - 1
docs/core-data-structures/compaction.md

@@ -6,7 +6,7 @@ Source: [`packages/compact/compact/src/types.ts`](../../packages/compact/compact
 
 ## The `compact/*` session events
 
-Compaction extends [`SessionEventMap`](session.md) with three event types via declaration merging. All three are **log-only** — they record the compaction lock and its provenance, and never join the surface. `SurfaceEventType` is deliberately NOT extended (only message-producing events reach the model), so the summary itself rides on a separate `user/message` with `surfaceOp: { op: 'replace', start, end }` — the only surface mutation. See the Agent Note for why reusing `user/message` is honest rather than a workaround.
+Compaction extends [`SessionEventMap`](session.md) with three event types via declaration merging. All three are **log-only** — they record the compaction lock and its provenance, and never join the surface. `SurfaceEventType` is deliberately NOT extended (only message-producing events reach the model), so the summary itself rides on a separate `user/message` with `surfaceOp: { op: 'replace', start, end }` — the only surface mutation performed by summary compaction. See the Agent Note for why reusing `user/message` is honest rather than a workaround.
 
 | Event | Payload | Role |
 |---|---|---|

+ 2 - 0
packages/compact/compact-tool-result-prune/README.md

@@ -8,6 +8,8 @@ This is a concrete companion to [`dsh-compact-basic`](../compact-basic/README.md
 
 `pruneSession(session)` scans one stable snapshot of the current surface. Every over-budget tool result is replaced by one newly appended `tool/result` carrying `{ surfaceOp: { op: 'replace', start: originalSeq, end: originalSeq }, sourceEventSeqs: [originalSeq] }`. The replacement spreads the complete original data and changes only `content`, preserving `turn`, `step`, `callId`, error fields, `meta`, and later data additions. The original event remains available for persistence, replay, and exact-log inspection.
 
+The method throws synchronously when the session rejects a replacement. Replacements committed earlier in the pass remain durable.
+
 `measureContent(blocks)` counts Unicode code points in `text` blocks. `pruneContent(blocks)` returns the bounded replacement or `null` when content is already within the threshold. Non-text blocks are retained at their original relative positions; text slicing never splits a UTF-16 surrogate pair, though it can split a multi-code-point grapheme cluster.
 
 Every emitted result has exactly the configured head budget, fixed marker, and tail budget in text code points, is no larger than `thresholdChars`, and is strictly smaller than the triggering input. A second pass therefore emits no replacement.

+ 2 - 0
packages/compact/compact-tool-result-prune/src/index.ts

@@ -118,6 +118,8 @@ export class ToolResultPruneService extends Service {
    * and points at the shadowed node for durable provenance and replay.
    * @param session - session whose current surface is rewritten.
    * @returns landed replacements and aggregate Unicode-code-point savings.
+   * @throws when the session rejects a replacement; replacements committed
+   * earlier in the pass remain durable.
    */
   pruneSession(session: Session): PruneResult {
     const candidates: SnapshotCandidate[] = []

+ 1 - 1
packages/compact/compact/README.md

@@ -38,7 +38,7 @@ The private per-session cache is keyed by `session.surface.replaceGeneration` an
 1. appends `compact/start` (log-only) — acquires the lock,
 2. summarizes the range,
 3. appends `compact/summary` (log-only) — provenance: summary, range, shadowed seqs, token count, and provider/model call envelope,
-4. appends a single `user/message` with `surfaceOp: { op: 'replace', start, end }` carrying the summary — **the only surface mutation**,
+4. appends a single `user/message` with `surfaceOp: { op: 'replace', start, end }` carrying the summary — **the only surface mutation in this operation**,
 5. appends `compact/end` (log-only) — releases the lock.
 
 The surface mutation (step 4) sits **inside** the lock bracket: `compact/end` is the last event, so the lock is never released before the mutation lands. A crash between `compact/start` and `compact/end` therefore leaves a detectable orphaned lock (a `compact/start` with no matching `compact/end`) rather than a `compact/end` that falsely claims compaction finished while the surface was never shadowed.

+ 1 - 1
packages/cordis/tool-cordis/src/api-catalog.ts

@@ -541,7 +541,7 @@ export const SERVICE_API: readonly ServiceApiEntry[] = [
       },
       {
         signature: 'pruneSession(session: Session): PruneResult',
-        jsDoc: '/**\n * Prune every over-budget tool result from one stable current-surface snapshot.\n * Each replacement preserves the complete event data except for `content`,\n * and points at the shadowed node for durable provenance and replay.\n * @param session - session whose current surface is rewritten.\n * @returns landed replacements and aggregate Unicode-code-point savings.\n */',
+        jsDoc: '/**\n * Prune every over-budget tool result from one stable current-surface snapshot.\n * Each replacement preserves the complete event data except for `content`,\n * and points at the shadowed node for durable provenance and replay.\n * @param session - session whose current surface is rewritten.\n * @returns landed replacements and aggregate Unicode-code-point savings.\n * @throws when the session rejects a replacement; replacements committed\n * earlier in the pass remain durable.\n */',
       },
     ],
   },

+ 3 - 1
website/zh-CN/api/harness/tool-result-prune.md

@@ -68,6 +68,8 @@ Replace an over-budget text middle while retaining rich-block order. Text slicin
  * and points at the shadowed node for durable provenance and replay.
  * @param session - session whose current surface is rewritten.
  * @returns landed replacements and aggregate Unicode-code-point savings.
+ * @throws when the session rejects a replacement; replacements committed
+ * earlier in the pass remain durable.
  */
 pruneSession(session: Session): PruneResult
 ```
@@ -78,4 +80,4 @@ Prune every over-budget tool result from one stable current-surface snapshot. Ea
 
 **Returns** landed replacements and aggregate Unicode-code-point savings.
 
-[Source](https://github.com/deepseek-harness/deepseek-harness/blob/master/packages/compact/compact-tool-result-prune/src/index.ts#L122)
+[Source](https://github.com/deepseek-harness/deepseek-harness/blob/master/packages/compact/compact-tool-result-prune/src/index.ts#L124)