@dsh-cc/context-crusher 0.7.1 → 0.8.0-rc.2

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 (53) hide show
  1. package/README.i18n.yaml +2 -2
  2. package/README.md +4 -0
  3. package/README.zh.md +4 -0
  4. package/lib/config.d.ts +9 -1
  5. package/lib/config.d.ts.map +1 -1
  6. package/lib/config.js +114 -1
  7. package/lib/config.js.map +1 -1
  8. package/lib/defer/counter.d.ts +44 -0
  9. package/lib/defer/counter.d.ts.map +1 -0
  10. package/lib/defer/counter.js +81 -0
  11. package/lib/defer/counter.js.map +1 -0
  12. package/lib/defer/gate.d.ts +41 -0
  13. package/lib/defer/gate.d.ts.map +1 -0
  14. package/lib/defer/gate.js +32 -0
  15. package/lib/defer/gate.js.map +1 -0
  16. package/lib/defer/pass.d.ts +70 -0
  17. package/lib/defer/pass.d.ts.map +1 -0
  18. package/lib/defer/pass.js +288 -0
  19. package/lib/defer/pass.js.map +1 -0
  20. package/lib/defer/residents.d.ts +126 -0
  21. package/lib/defer/residents.d.ts.map +1 -0
  22. package/lib/defer/residents.js +171 -0
  23. package/lib/defer/residents.js.map +1 -0
  24. package/lib/defer/swap.d.ts +57 -0
  25. package/lib/defer/swap.d.ts.map +1 -0
  26. package/lib/defer/swap.js +120 -0
  27. package/lib/defer/swap.js.map +1 -0
  28. package/lib/fold-counters.d.ts +29 -0
  29. package/lib/fold-counters.d.ts.map +1 -0
  30. package/lib/fold-counters.js +62 -0
  31. package/lib/fold-counters.js.map +1 -0
  32. package/lib/index.d.ts +20 -0
  33. package/lib/index.d.ts.map +1 -1
  34. package/lib/index.js +86 -15
  35. package/lib/index.js.map +1 -1
  36. package/lib/receipt.d.ts +45 -0
  37. package/lib/receipt.d.ts.map +1 -0
  38. package/lib/receipt.js +73 -0
  39. package/lib/receipt.js.map +1 -0
  40. package/lib/reducer.d.ts +52 -0
  41. package/lib/reducer.d.ts.map +1 -0
  42. package/lib/reducer.js +202 -0
  43. package/lib/reducer.js.map +1 -0
  44. package/lib/settings.d.ts.map +1 -1
  45. package/lib/settings.js +6 -3
  46. package/lib/settings.js.map +1 -1
  47. package/lib/types.d.ts +52 -1
  48. package/lib/types.d.ts.map +1 -1
  49. package/lib/verifier.d.ts +29 -0
  50. package/lib/verifier.d.ts.map +1 -0
  51. package/lib/verifier.js +57 -0
  52. package/lib/verifier.js.map +1 -0
  53. package/package.json +26 -13
@@ -0,0 +1,57 @@
1
+ /**
2
+ * The deferred swap pass (design §3.3): one non-awaiting critical section
3
+ * per eligible entry, executed at the `agent/pre-step` boundary. Mirrors the
4
+ * microcompact replacement shape exactly (compaction-micro index.ts
5
+ * 270-295): a `compaction/prune` shadow-price row debiting the token meter,
6
+ * immediately followed by the `tool/result` replacement carrying
7
+ * `surfaceOp: replace` + `sourceEventSeqs`, with every non-content field of
8
+ * the original block preserved.
9
+ *
10
+ * Staleness is re-checked against the live surface inside the same section
11
+ * (locate by callId — the sole locator — then byte-equality of the body), so
12
+ * an in-flight request or a microcompact pass cannot interleave with a swap.
13
+ *
14
+ * @module @dsh-cc/context-crusher/defer/swap
15
+ */
16
+ import type { Message } from '@deepseek-ai/dsh-llm';
17
+ import type { Session, SessionEvent, SessionSeq } from '@deepseek-ai/dsh-session';
18
+ import type { DeferGateFacts, ResidentEntry } from './residents.ts';
19
+ export interface SwapInput {
20
+ readonly session: Session;
21
+ readonly entry: ResidentEntry;
22
+ /** Stored original full text (fetched BEFORE the critical section). */
23
+ readonly fullText: string;
24
+ /** Standard compressed body + `buildMarker(...)` trailer. */
25
+ readonly stubText: string;
26
+ /** `false` in dry-run: evaluate everything, append nothing (§3.6). */
27
+ readonly apply: boolean;
28
+ readonly margin: number;
29
+ readonly remainingRequestsEstimate: number;
30
+ readonly urgencyTokens?: number;
31
+ readonly sessionTokens?: number;
32
+ readonly contextWindow?: number;
33
+ readonly estimateMessage: (message: Message) => number;
34
+ }
35
+ export type SwapResult = {
36
+ readonly outcome: 'applied' | 'dry-run' | 'gate-failed';
37
+ readonly gate: DeferGateFacts;
38
+ } | {
39
+ readonly outcome: 'stale';
40
+ };
41
+ /** Locate the current surface `tool/result` event by callId (sole locator). */
42
+ export declare function locateResultEvent(session: Session, callId: ResidentEntry['callId']): {
43
+ seq: SessionSeq;
44
+ event: SessionEvent<'tool/result'>;
45
+ } | undefined;
46
+ /**
47
+ * Σ estimateMessage over surface nodes AFTER `seq` — the suffix the prompt
48
+ * cache would reprice if the entry were swapped now (§3.4).
49
+ */
50
+ export declare function suffixTokensAfter(session: Session, seq: SessionSeq, estimateMessage: (message: Message) => number): number;
51
+ /**
52
+ * Evaluate and (when `apply`) commit one entry's swap. Synchronous: callers
53
+ * must fetch the stored text and build the stub BEFORE calling, so the
54
+ * staleness re-check and the two appends happen without yielding.
55
+ */
56
+ export declare function attemptSwap(input: SwapInput): SwapResult;
57
+ //# sourceMappingURL=swap.d.ts.map
@@ -0,0 +1 @@
1
+ {"version":3,"file":"swap.d.ts","sourceRoot":"","sources":["../../src/defer/swap.ts"],"names":[],"mappings":"AAAA;;;;;;;;;;;;;;GAcG;AAGH,OAAO,KAAK,EAAE,OAAO,EAAmB,MAAM,sBAAsB,CAAA;AAEpE,OAAO,KAAK,EAAE,OAAO,EAAE,YAAY,EAAE,UAAU,EAAqB,MAAM,0BAA0B,CAAA;AAKpG,OAAO,KAAK,EAAE,cAAc,EAAE,aAAa,EAAE,MAAM,gBAAgB,CAAA;AAEnE,MAAM,WAAW,SAAS;IACxB,QAAQ,CAAC,OAAO,EAAE,OAAO,CAAA;IACzB,QAAQ,CAAC,KAAK,EAAE,aAAa,CAAA;IAC7B,uEAAuE;IACvE,QAAQ,CAAC,QAAQ,EAAE,MAAM,CAAA;IACzB,6DAA6D;IAC7D,QAAQ,CAAC,QAAQ,EAAE,MAAM,CAAA;IACzB,sEAAsE;IACtE,QAAQ,CAAC,KAAK,EAAE,OAAO,CAAA;IACvB,QAAQ,CAAC,MAAM,EAAE,MAAM,CAAA;IACvB,QAAQ,CAAC,yBAAyB,EAAE,MAAM,CAAA;IAC1C,QAAQ,CAAC,aAAa,CAAC,EAAE,MAAM,CAAA;IAC/B,QAAQ,CAAC,aAAa,CAAC,EAAE,MAAM,CAAA;IAC/B,QAAQ,CAAC,aAAa,CAAC,EAAE,MAAM,CAAA;IAC/B,QAAQ,CAAC,eAAe,EAAE,CAAC,OAAO,EAAE,OAAO,KAAK,MAAM,CAAA;CACvD;AAED,MAAM,MAAM,UAAU,GAClB;IAAE,QAAQ,CAAC,OAAO,EAAE,SAAS,GAAG,SAAS,GAAG,aAAa,CAAC;IAAC,QAAQ,CAAC,IAAI,EAAE,cAAc,CAAA;CAAE,GAC1F;IAAE,QAAQ,CAAC,OAAO,EAAE,OAAO,CAAA;CAAE,CAAA;AAEjC,+EAA+E;AAC/E,wBAAgB,iBAAiB,CAC/B,OAAO,EAAE,OAAO,EAChB,MAAM,EAAE,aAAa,CAAC,QAAQ,CAAC,GAC9B;IAAE,GAAG,EAAE,UAAU,CAAC;IAAC,KAAK,EAAE,YAAY,CAAC,aAAa,CAAC,CAAA;CAAE,GAAG,SAAS,CAOrE;AAED;;;GAGG;AACH,wBAAgB,iBAAiB,CAC/B,OAAO,EAAE,OAAO,EAChB,GAAG,EAAE,UAAU,EACf,eAAe,EAAE,CAAC,OAAO,EAAE,OAAO,KAAK,MAAM,GAC5C,MAAM,CAeR;AAED;;;;GAIG;AACH,wBAAgB,WAAW,CAAC,KAAK,EAAE,SAAS,GAAG,UAAU,CA0DxD"}
@@ -0,0 +1,120 @@
1
+ /**
2
+ * The deferred swap pass (design §3.3): one non-awaiting critical section
3
+ * per eligible entry, executed at the `agent/pre-step` boundary. Mirrors the
4
+ * microcompact replacement shape exactly (compaction-micro index.ts
5
+ * 270-295): a `compaction/prune` shadow-price row debiting the token meter,
6
+ * immediately followed by the `tool/result` replacement carrying
7
+ * `surfaceOp: replace` + `sourceEventSeqs`, with every non-content field of
8
+ * the original block preserved.
9
+ *
10
+ * Staleness is re-checked against the live surface inside the same section
11
+ * (locate by callId — the sole locator — then byte-equality of the body), so
12
+ * an in-flight request or a microcompact pass cannot interleave with a swap.
13
+ *
14
+ * @module @dsh-cc/context-crusher/defer/swap
15
+ */
16
+ import { freezeMessage } from '@deepseek-ai/dsh-llm';
17
+ import { deriveEventMessage } from '@deepseek-ai/dsh-session';
18
+ import { joinTextBlocks } from "./counter.js";
19
+ import { evaluateDeferGate } from "./gate.js";
20
+ /** Locate the current surface `tool/result` event by callId (sole locator). */
21
+ export function locateResultEvent(session, callId) {
22
+ for (const seq of session.surface.nodes) {
23
+ const event = session.eventAt(seq);
24
+ if (event?.type !== 'tool/result')
25
+ continue;
26
+ if (String(event.data.message.source.callId) === String(callId))
27
+ return { seq, event };
28
+ }
29
+ return undefined;
30
+ }
31
+ /**
32
+ * Σ estimateMessage over surface nodes AFTER `seq` — the suffix the prompt
33
+ * cache would reprice if the entry were swapped now (§3.4).
34
+ */
35
+ export function suffixTokensAfter(session, seq, estimateMessage) {
36
+ let sum = 0;
37
+ let seen = false;
38
+ for (const node of session.surface.nodes) {
39
+ if (node === seq) {
40
+ seen = true;
41
+ continue;
42
+ }
43
+ if (!seen)
44
+ continue;
45
+ const event = session.eventAt(node);
46
+ if (event === undefined)
47
+ continue;
48
+ const message = deriveEventMessage(event);
49
+ if (message !== null)
50
+ sum += estimateMessage(message);
51
+ }
52
+ return sum;
53
+ }
54
+ /**
55
+ * Evaluate and (when `apply`) commit one entry's swap. Synchronous: callers
56
+ * must fetch the stored text and build the stub BEFORE calling, so the
57
+ * staleness re-check and the two appends happen without yielding.
58
+ */
59
+ export function attemptSwap(input) {
60
+ const { session, entry } = input;
61
+ const located = locateResultEvent(session, entry.callId);
62
+ if (located === undefined)
63
+ return { outcome: 'stale' };
64
+ const { seq, event } = located;
65
+ const message = event.data.message;
66
+ const first = message.content[0];
67
+ const resultBlock = first?.type === 'tool-result' ? first : undefined;
68
+ const body = resultBlock === undefined ? undefined : joinTextBlocks(resultBlock.content);
69
+ if (body !== input.fullText)
70
+ return { outcome: 'stale' };
71
+ const suffixTokens = suffixTokensAfter(session, seq, input.estimateMessage);
72
+ const gate = evaluateDeferGate({
73
+ tokensSaved: entry.tokensSaved,
74
+ remainingRequestsEstimate: input.remainingRequestsEstimate,
75
+ margin: input.margin,
76
+ suffixTokens,
77
+ ...(input.urgencyTokens !== undefined ? { urgencyTokens: input.urgencyTokens } : {}),
78
+ ...(input.sessionTokens !== undefined ? { sessionTokens: input.sessionTokens } : {}),
79
+ ...(input.contextWindow !== undefined ? { contextWindow: input.contextWindow } : {}),
80
+ });
81
+ const facts = {
82
+ sentCount: entry.sentCount,
83
+ suffixTokens,
84
+ projectedSavings: gate.projectedSavings,
85
+ margin: input.margin,
86
+ remainingRequestsEstimate: Math.max(1, input.remainingRequestsEstimate),
87
+ urgencyOverride: gate.urgencyOverride,
88
+ };
89
+ if (!gate.pass)
90
+ return { outcome: 'gate-failed', gate: facts };
91
+ if (!input.apply)
92
+ return { outcome: 'dry-run', gate: facts };
93
+ // Preserve every non-content field of the original tool-result block (type,
94
+ // toolCallId, isError, plus future additions) — the "may change only
95
+ // content" surface invariant.
96
+ const replacementBlock = resultBlock === undefined
97
+ ? { type: 'tool-result', toolCallId: message.source.callId, content: [{ type: 'text', text: input.stubText }] }
98
+ : { ...resultBlock, content: [{ type: 'text', text: input.stubText }] };
99
+ const replacementMessage = freezeMessage({
100
+ ...message,
101
+ content: [replacementBlock],
102
+ });
103
+ // Shadow-price protocol: the metering event and its replacement are
104
+ // appended synchronously adjacent so the token meter subtracts the
105
+ // shadowed node's heuristic price exactly once.
106
+ session.append('compaction/prune', {
107
+ shadowedRange: { start: seq, end: seq },
108
+ shadowedSeqs: [seq],
109
+ shadowedTokenCount: input.estimateMessage(message),
110
+ });
111
+ session.append('tool/result', {
112
+ ...event.data,
113
+ message: replacementMessage,
114
+ }, {
115
+ surfaceOp: { op: 'replace', startSeq: seq, endSeq: seq },
116
+ sourceEventSeqs: [seq],
117
+ });
118
+ return { outcome: 'applied', gate: facts };
119
+ }
120
+ //# sourceMappingURL=swap.js.map
@@ -0,0 +1 @@
1
+ {"version":3,"file":"swap.js","sourceRoot":"","sources":["../../src/defer/swap.ts"],"names":[],"mappings":"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"}
@@ -0,0 +1,29 @@
1
+ /**
2
+ * foldCounters seam for @dsh-cc/token-efficiency (design
3
+ * docs/plans/2026-09-20-token-efficiency-eval-harness.md §3.4).
4
+ *
5
+ * The marker/ledger shape knowledge lives HERE (the feature owns it): if the
6
+ * marker contract or tool-result extraction drifts, this fold and its tests
7
+ * must change in the same PR — never a silently-wrong foreign regex.
8
+ *
9
+ * @module @dsh-cc/context-crusher/fold-counters
10
+ */
11
+ /**
12
+ * Structural materials contract shared by every efficiency-feature fold.
13
+ * Declared locally (no cross-package import); the loose event shape
14
+ * intentionally mirrors SessionLogEvent without depending on dsh-session.
15
+ */
16
+ export interface FoldCounterMaterials {
17
+ readonly events: readonly {
18
+ readonly type: string;
19
+ readonly time?: number;
20
+ readonly data?: Record<string, unknown> | undefined;
21
+ }[];
22
+ readonly dshHome: string;
23
+ }
24
+ /**
25
+ * Fold CCR evidence in session streams: `ccr.applied` (marker count),
26
+ * `ccr.tokensBefore` (ΣN), `ccr.tokensAfter` (ΣM).
27
+ */
28
+ export declare function foldCounters(materials: FoldCounterMaterials): Record<string, number>;
29
+ //# sourceMappingURL=fold-counters.d.ts.map
@@ -0,0 +1 @@
1
+ {"version":3,"file":"fold-counters.d.ts","sourceRoot":"","sources":["../src/fold-counters.ts"],"names":[],"mappings":"AAAA;;;;;;;;;GASG;AAIH;;;;GAIG;AACH,MAAM,WAAW,oBAAoB;IACnC,QAAQ,CAAC,MAAM,EAAE,SAAS;QACxB,QAAQ,CAAC,IAAI,EAAE,MAAM,CAAA;QACrB,QAAQ,CAAC,IAAI,CAAC,EAAE,MAAM,CAAA;QACtB,QAAQ,CAAC,IAAI,CAAC,EAAE,MAAM,CAAC,MAAM,EAAE,OAAO,CAAC,GAAG,SAAS,CAAA;KACpD,EAAE,CAAA;IACH,QAAQ,CAAC,OAAO,EAAE,MAAM,CAAA;CACzB;AAyBD;;;GAGG;AACH,wBAAgB,YAAY,CAAC,SAAS,EAAE,oBAAoB,GAAG,MAAM,CAAC,MAAM,EAAE,MAAM,CAAC,CAiBpF"}
@@ -0,0 +1,62 @@
1
+ /**
2
+ * foldCounters seam for @dsh-cc/token-efficiency (design
3
+ * docs/plans/2026-09-20-token-efficiency-eval-harness.md §3.4).
4
+ *
5
+ * The marker/ledger shape knowledge lives HERE (the feature owns it): if the
6
+ * marker contract or tool-result extraction drifts, this fold and its tests
7
+ * must change in the same PR — never a silently-wrong foreign regex.
8
+ *
9
+ * @module @dsh-cc/context-crusher/fold-counters
10
+ */
11
+ import { parseMarker } from "./marker.js";
12
+ /**
13
+ * Extract every text fragment from a tool/result event's message content.
14
+ * Handles the real dsh-llm shapes: string content, text blocks, and
15
+ * nested tool-result blocks (content: ContentBlock[]).
16
+ */
17
+ function resultTexts(data) {
18
+ const content = data?.message?.content;
19
+ const texts = [];
20
+ if (typeof content === 'string')
21
+ return [content];
22
+ if (!Array.isArray(content))
23
+ return texts;
24
+ for (const block of content) {
25
+ const b = block;
26
+ if (b.type === 'tool-result') {
27
+ for (const inner of (Array.isArray(b.content) ? b.content : [])) {
28
+ if (typeof inner?.text === 'string')
29
+ texts.push(inner.text);
30
+ }
31
+ }
32
+ else if (typeof b?.text === 'string') {
33
+ texts.push(b.text);
34
+ }
35
+ }
36
+ return texts;
37
+ }
38
+ /**
39
+ * Fold CCR evidence in session streams: `ccr.applied` (marker count),
40
+ * `ccr.tokensBefore` (ΣN), `ccr.tokensAfter` (ΣM).
41
+ */
42
+ export function foldCounters(materials) {
43
+ let applied = 0;
44
+ let tokensBefore = 0;
45
+ let tokensAfter = 0;
46
+ for (const event of materials.events) {
47
+ if (event.type !== 'tool/result')
48
+ continue;
49
+ for (const text of resultTexts(event.data)) {
50
+ for (const line of text.split('\n')) {
51
+ const marker = parseMarker(line.trim());
52
+ if (marker === null)
53
+ continue;
54
+ applied += 1;
55
+ tokensBefore += marker.tokensBefore;
56
+ tokensAfter += marker.tokensAfter;
57
+ }
58
+ }
59
+ }
60
+ return { 'ccr.applied': applied, 'ccr.tokensBefore': tokensBefore, 'ccr.tokensAfter': tokensAfter };
61
+ }
62
+ //# sourceMappingURL=fold-counters.js.map
@@ -0,0 +1 @@
1
+ {"version":3,"file":"fold-counters.js","sourceRoot":"","sources":["../src/fold-counters.ts"],"names":[],"mappings":"AAAA;;;;;;;;;GASG;AAEH,OAAO,EAAE,WAAW,EAAE,MAAM,aAAa,CAAA;AAgBzC;;;;GAIG;AACH,SAAS,WAAW,CAAC,IAAa;IAChC,MAAM,OAAO,GAAI,IAAwD,EAAE,OAAO,EAAE,OAAO,CAAA;IAC3F,MAAM,KAAK,GAAa,EAAE,CAAA;IAC1B,IAAI,OAAO,OAAO,KAAK,QAAQ;QAAE,OAAO,CAAC,OAAO,CAAC,CAAA;IACjD,IAAI,CAAC,KAAK,CAAC,OAAO,CAAC,OAAO,CAAC;QAAE,OAAO,KAAK,CAAA;IACzC,KAAK,MAAM,KAAK,IAAI,OAAO,EAAE,CAAC;QAC5B,MAAM,CAAC,GAAG,KAA6D,CAAA;QACvE,IAAI,CAAC,CAAC,IAAI,KAAK,aAAa,EAAE,CAAC;YAC7B,KAAK,MAAM,KAAK,IAAI,CAAC,KAAK,CAAC,OAAO,CAAC,CAAC,CAAC,OAAO,CAAC,CAAC,CAAC,CAAC,CAAC,CAAC,OAAO,CAAC,CAAC,CAAC,EAAE,CAAyB,EAAE,CAAC;gBACxF,IAAI,OAAO,KAAK,EAAE,IAAI,KAAK,QAAQ;oBAAE,KAAK,CAAC,IAAI,CAAC,KAAK,CAAC,IAAI,CAAC,CAAA;YAC7D,CAAC;QACH,CAAC;aAAM,IAAI,OAAO,CAAC,EAAE,IAAI,KAAK,QAAQ,EAAE,CAAC;YACvC,KAAK,CAAC,IAAI,CAAC,CAAC,CAAC,IAAI,CAAC,CAAA;QACpB,CAAC;IACH,CAAC;IACD,OAAO,KAAK,CAAA;AACd,CAAC;AAED;;;GAGG;AACH,MAAM,UAAU,YAAY,CAAC,SAA+B;IAC1D,IAAI,OAAO,GAAG,CAAC,CAAA;IACf,IAAI,YAAY,GAAG,CAAC,CAAA;IACpB,IAAI,WAAW,GAAG,CAAC,CAAA;IACnB,KAAK,MAAM,KAAK,IAAI,SAAS,CAAC,MAAM,EAAE,CAAC;QACrC,IAAI,KAAK,CAAC,IAAI,KAAK,aAAa;YAAE,SAAQ;QAC1C,KAAK,MAAM,IAAI,IAAI,WAAW,CAAC,KAAK,CAAC,IAAI,CAAC,EAAE,CAAC;YAC3C,KAAK,MAAM,IAAI,IAAI,IAAI,CAAC,KAAK,CAAC,IAAI,CAAC,EAAE,CAAC;gBACpC,MAAM,MAAM,GAAG,WAAW,CAAC,IAAI,CAAC,IAAI,EAAE,CAAC,CAAA;gBACvC,IAAI,MAAM,KAAK,IAAI;oBAAE,SAAQ;gBAC7B,OAAO,IAAI,CAAC,CAAA;gBACZ,YAAY,IAAI,MAAM,CAAC,YAAY,CAAA;gBACnC,WAAW,IAAI,MAAM,CAAC,WAAW,CAAA;YACnC,CAAC;QACH,CAAC;IACH,CAAC;IACD,OAAO,EAAE,aAAa,EAAE,OAAO,EAAE,kBAAkB,EAAE,YAAY,EAAE,iBAAiB,EAAE,WAAW,EAAE,CAAA;AACrG,CAAC"}
package/lib/index.d.ts CHANGED
@@ -20,9 +20,19 @@ import type { CrusherConfig, RetrieveError, ResolvedConfig } from './types.ts';
20
20
  export { resolveConfig, overlaySettings, DEFAULTS, DEFAULT_PROTECTED_TOOLS, Config } from './config.ts';
21
21
  export { SETTINGS_NAMESPACE } from './settings.ts';
22
22
  export { route } from './router.ts';
23
+ export { REDUCER_COMMAND_TOOLS, invocationCommand, isReducerEligible, reduceToolOutput, truncateView } from './reducer.ts';
24
+ export { parseReceipt, renderReceipt, ReceiptSchema } from './receipt.ts';
25
+ export { verifyReceipt } from './verifier.ts';
23
26
  export { CrusherStore, shortHash, STORE_MAX_ENTRIES, STORE_TTL_MS } from './store.ts';
24
27
  export { SavingsLedger } from './ledger.ts';
25
28
  export { buildMarker, parseMarker } from './marker.ts';
29
+ export { foldCounters } from './fold-counters.ts';
30
+ export type { FoldCounterMaterials } from './fold-counters.ts';
31
+ export { Deferral } from './defer/pass.ts';
32
+ export { evaluateDeferGate } from './defer/gate.ts';
33
+ export { attemptSwap } from './defer/swap.ts';
34
+ export { DeferLedger, ResidentTable, foldDeferRows, parseTodoCounts, readDeferLedger, rebuildResidents, } from './defer/residents.ts';
35
+ export type { DeferLedgerRow, ResidentEntry } from './defer/residents.ts';
26
36
  export type { CrusherConfig, CrusherMode, ResolvedConfig, LedgerRow, RetrieveError } from './types.ts';
27
37
  export declare const RETRIEVE_TOOL_NAME = "context_retrieve";
28
38
  /** The pinned marker contract, mirrored verbatim in the retrieve tool's description. */
@@ -45,11 +55,21 @@ export declare class ContextCrusher extends Service {
45
55
  private readonly readSettings;
46
56
  private readonly store;
47
57
  private readonly ledger;
58
+ private readonly home;
59
+ /** Deferred-mode orchestration (counting, swap pass, resume, ledger). */
60
+ private readonly deferral;
48
61
  constructor(ctx: Context, config?: CrusherConfig);
49
62
  /** Effective configuration for one use: config defaults overlaid by live settings. */
50
63
  effectiveConfig(): ResolvedConfig;
51
64
  private registerListener;
52
65
  private crush;
66
+ /**
67
+ * Reducer escalation stage (§3.1): after the deterministic route declined
68
+ * (null) or its savings fell below `minSavingsRatio`. Any reducer failure —
69
+ * eligibility, lane, timeout, verification — passes the ORIGINAL bytes
70
+ * through (fail-soft inside `reduceToolOutput` too).
71
+ */
72
+ private reduceOrPassthrough;
53
73
  /** Token-based sizing (D3): the same estimator gates, markers, and ledger rows. */
54
74
  private estimate;
55
75
  /** `sha256(sessionCwd)` first 16 hex — the store's project bucket. */
@@ -1 +1 @@
1
- {"version":3,"file":"index.d.ts","sourceRoot":"","sources":["../src/index.ts"],"names":[],"mappings":"AAAA;;;;;;;;;;;;;;GAcG;AAEH,OAAO,EAAE,OAAO,EAAE,MAAM,qBAAqB,CAAA;AAC7C,OAAO,KAAK,EAAE,OAAO,EAAE,MAAM,qBAAqB,CAAA;AAIlD,OAAO,KAAK,EAAwD,cAAc,EAAE,MAAM,eAAe,CAAA;AASzG,OAAO,KAAK,EAAE,aAAa,EAAa,aAAa,EAAE,cAAc,EAAE,MAAM,YAAY,CAAA;AAEzF,OAAO,EAAE,aAAa,EAAE,eAAe,EAAE,QAAQ,EAAE,uBAAuB,EAAE,MAAM,EAAE,MAAM,aAAa,CAAA;AACvG,OAAO,EAAE,kBAAkB,EAAE,MAAM,eAAe,CAAA;AAClD,OAAO,EAAE,KAAK,EAAE,MAAM,aAAa,CAAA;AACnC,OAAO,EAAE,YAAY,EAAE,SAAS,EAAE,iBAAiB,EAAE,YAAY,EAAE,MAAM,YAAY,CAAA;AACrF,OAAO,EAAE,aAAa,EAAE,MAAM,aAAa,CAAA;AAC3C,OAAO,EAAE,WAAW,EAAE,WAAW,EAAE,MAAM,aAAa,CAAA;AACtD,YAAY,EAAE,aAAa,EAAE,WAAW,EAAE,cAAc,EAAE,SAAS,EAAE,aAAa,EAAE,MAAM,YAAY,CAAA;AAEtG,eAAO,MAAM,kBAAkB,qBAAqB,CAAA;AAEpD,wFAAwF;AACxF,eAAO,MAAM,yBAAyB,QAK8C,CAAA;AAKpF,OAAO,QAAQ,qBAAqB,CAAC;IACnC,UAAU,OAAO;QACf,oGAAoG;QACpG,WAAW,CAAC,EAAE,CAAC,GAAG,QAAQ,EAAE,MAAM,EAAE,KAAK,MAAM,CAAA;KAChD;CACF;AAyBD;;;GAGG;AACH,qBAAa,cAAe,SAAQ,OAAO;IACzC,MAAM,CAAC,MAAM,WAAiB;IAE9B,MAAM,CAAC,MAAM,4DAAS;IAEtB,6EAA6E;IAC7E,OAAO,CAAC,QAAQ,CAAC,IAAI,CAAgB;IACrC,OAAO,CAAC,QAAQ,CAAC,YAAY,CAAiC;IAC9D,OAAO,CAAC,QAAQ,CAAC,KAAK,CAA0B;IAChD,OAAO,CAAC,QAAQ,CAAC,MAAM,CAA2B;gBAEtC,GAAG,EAAE,OAAO,EAAE,MAAM,GAAE,aAAkB;IAgBpD,sFAAsF;IACtF,eAAe,IAAI,cAAc;IAIjC,OAAO,CAAC,gBAAgB;YAmBV,KAAK;IAgEnB,mFAAmF;IACnF,OAAO,CAAC,QAAQ;IAOhB,sEAAsE;IACtE,OAAO,CAAC,UAAU;IAYlB,+EAA+E;IACzE,QAAQ,CAAC,IAAI,EAAE,cAAc,EAAE,IAAI,EAAE,MAAM,GAAG,OAAO,CACzD;QAAE,EAAE,EAAE,IAAI,CAAC;QAAC,IAAI,EAAE,MAAM,CAAA;KAAE,GAAG;QAAE,EAAE,EAAE,KAAK,CAAC;QAAC,KAAK,EAAE,aAAa,GAAG,aAAa,GAAG,cAAc,CAAA;KAAE,CAClG;IAcD,OAAO,CAAC,oBAAoB;CAK7B;AA2BD,eAAe,cAAc,CAAA"}
1
+ {"version":3,"file":"index.d.ts","sourceRoot":"","sources":["../src/index.ts"],"names":[],"mappings":"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"}
package/lib/index.js CHANGED
@@ -19,15 +19,26 @@ import { getSessionCwd } from '@dsh-cc/session-cwd';
19
19
  import { resolveConfig, overlaySettings, Config } from "./config.js";
20
20
  import { registerSettings } from "./settings.js";
21
21
  import { route } from "./router.js";
22
+ import { reduceToolOutput } from "./reducer.js";
22
23
  import { CrusherStore, shortHash } from "./store.js";
23
24
  import { SavingsLedger } from "./ledger.js";
24
25
  import { buildMarker, CCR_HASH_RE } from "./marker.js";
26
+ import { joinTextBlocks } from "./defer/counter.js";
27
+ import { Deferral } from "./defer/pass.js";
25
28
  export { resolveConfig, overlaySettings, DEFAULTS, DEFAULT_PROTECTED_TOOLS, Config } from "./config.js";
26
29
  export { SETTINGS_NAMESPACE } from "./settings.js";
27
30
  export { route } from "./router.js";
31
+ export { REDUCER_COMMAND_TOOLS, invocationCommand, isReducerEligible, reduceToolOutput, truncateView } from "./reducer.js";
32
+ export { parseReceipt, renderReceipt, ReceiptSchema } from "./receipt.js";
33
+ export { verifyReceipt } from "./verifier.js";
28
34
  export { CrusherStore, shortHash, STORE_MAX_ENTRIES, STORE_TTL_MS } from "./store.js";
29
35
  export { SavingsLedger } from "./ledger.js";
30
36
  export { buildMarker, parseMarker } from "./marker.js";
37
+ export { foldCounters } from "./fold-counters.js";
38
+ export { Deferral } from "./defer/pass.js";
39
+ export { evaluateDeferGate } from "./defer/gate.js";
40
+ export { attemptSwap } from "./defer/swap.js";
41
+ export { DeferLedger, ResidentTable, foldDeferRows, parseTodoCounts, readDeferLedger, rebuildResidents, } from "./defer/residents.js";
31
42
  export const RETRIEVE_TOOL_NAME = 'context_retrieve';
32
43
  /** The pinned marker contract, mirrored verbatim in the retrieve tool's description. */
33
44
  export const RETRIEVE_TOOL_DESCRIPTION = 'Retrieve the ORIGINAL text of a tool result that dsh-cc compressed. When a tool result '
@@ -49,32 +60,30 @@ function dshHomeFn(ctx) {
49
60
  }
50
61
  }
51
62
  /** Join text blocks; returns undefined when any block is non-text. */
52
- function allTextBlocks(blocks) {
53
- const parts = [];
54
- for (const block of blocks) {
55
- if (block.type !== 'text')
56
- return undefined;
57
- parts.push(block.text);
58
- }
59
- return parts.join('\n');
60
- }
63
+ const allTextBlocks = joinTextBlocks;
61
64
  /**
62
65
  * The context-crusher service: registers the post-execute tripwire listener
63
66
  * and the `context_retrieve` agent tool.
64
67
  */
65
68
  export class ContextCrusher extends Service {
66
- static inject = ['tokenMeter'];
69
+ // `llm` backs the reducer's cheap-lane side query (runSideQuery reads it
70
+ // through the context; cordis requires a declared injection to read it).
71
+ static inject = ['tokenMeter', 'llm'];
67
72
  static Config = Config;
68
73
  /** Resolved config-layer defaults; the settings overlay re-reads per use. */
69
74
  base;
70
75
  readSettings;
71
76
  store;
72
77
  ledger;
78
+ home;
79
+ /** Deferred-mode orchestration (counting, swap pass, resume, ledger). */
80
+ deferral;
73
81
  constructor(ctx, config = {}) {
74
82
  super(ctx, 'contextCrusher');
75
83
  this.base = resolveConfig(config);
76
84
  this.readSettings = registerSettings(ctx, this.base);
77
85
  const home = dshHomeFn(ctx);
86
+ this.home = home;
78
87
  if (home === undefined) {
79
88
  // D6 fail-closed: without a durable home the store/ledger cannot exist.
80
89
  ctx.logger.warn('context-crusher: no dshHomePath on the host context; force-disabled');
@@ -83,7 +92,14 @@ export class ContextCrusher extends Service {
83
92
  this.store = new CrusherStore(home('ccr'));
84
93
  this.ledger = new SavingsLedger(home('ccr', 'savings.jsonl'));
85
94
  }
95
+ this.deferral = new Deferral({
96
+ ctx,
97
+ store: () => this.store,
98
+ home: () => this.home,
99
+ effectiveConfig: () => this.effectiveConfig(),
100
+ });
86
101
  this.registerListener();
102
+ this.deferral.registerListeners();
87
103
  this.registerRetrieveTool();
88
104
  }
89
105
  /** Effective configuration for one use: config defaults overlaid by live settings. */
@@ -119,6 +135,10 @@ export class ContextCrusher extends Service {
119
135
  };
120
136
  if (!cfg.enabled || this.store === undefined)
121
137
  return d;
138
+ // Observe-only todo snapshot for the defer gate's remaining-requests
139
+ // estimate (compaction cost-gate doc); the decision is untouched.
140
+ if (exec.name === 'todo_write' && cfg.deferRequests > 0)
141
+ this.deferral.observeTodoSnapshot(exec);
122
142
  // D7: protected tools REPLACE the default list when explicitly set.
123
143
  if (cfg.protectedTools.includes(exec.name))
124
144
  return d;
@@ -142,21 +162,40 @@ export class ContextCrusher extends Service {
142
162
  return d;
143
163
  const candidate = route(originalText);
144
164
  if (candidate === null)
145
- return d;
165
+ return this.reduceOrPassthrough(exec, result, d, originalText, tokensBefore, cfg, ledgerRow);
146
166
  const compressedBody = candidate.text;
147
167
  const tokensAfter = this.estimate(compressedBody);
148
168
  const savings = 1 - tokensAfter / tokensBefore;
149
- if (savings < cfg.minSavingsRatio)
150
- return d;
151
- if (cfg.mode !== 'on') {
169
+ if (savings < cfg.minSavingsRatio) {
170
+ // Escalation (§3.1): sub-threshold deterministic savings go to the
171
+ // reducer, never mixing partial compressions.
172
+ return this.reduceOrPassthrough(exec, result, d, originalText, tokensBefore, cfg, ledgerRow);
173
+ }
174
+ if (cfg.mode !== 'on' && cfg.deferRequests <= 0) {
152
175
  // Dry-run: measure only; the committed result stays original.
153
176
  await ledgerRow({ kind: candidate.kind, charsBefore: originalText.length, charsAfter: compressedBody.length, tokensBefore, tokensAfter, applied: false });
154
177
  return d;
155
178
  }
156
179
  const projectKey = this.projectKey(exec);
157
- if (projectKey === undefined)
180
+ if (projectKey === undefined) {
181
+ // Preserve the dry-run ledger row even when deferral wanted a store.
182
+ if (cfg.mode !== 'on') {
183
+ await ledgerRow({ kind: candidate.kind, charsBefore: originalText.length, charsAfter: compressedBody.length, tokensBefore, tokensAfter, applied: false });
184
+ }
158
185
  return d;
186
+ }
159
187
  const hash = await this.store.put(projectKey, originalText);
188
+ if (cfg.deferRequests > 0) {
189
+ // Deferred mode (§3.1): the store put happened (evidence is durable),
190
+ // the resident entry is recorded, and the downstream decision returns
191
+ // UNMODIFIED — the full text enters the session. §3.6: this applies to
192
+ // dry-run too (deferred dry-run writes store files and ledger rows; it
193
+ // only never appends to the session).
194
+ await this.deferral.recordResident(exec, hash, tokensBefore - tokensAfter);
195
+ await ledgerRow({ kind: candidate.kind, charsBefore: originalText.length, charsAfter: compressedBody.length, tokensBefore, tokensAfter, applied: false, hash });
196
+ void this.store.sweep();
197
+ return d;
198
+ }
160
199
  const replacement = {
161
200
  type: 'text',
162
201
  text: `${compressedBody}\n${buildMarker(tokensBefore, tokensAfter, hash)}`,
@@ -170,6 +209,38 @@ export class ContextCrusher extends Service {
170
209
  // here (checked above), so this is the content-carrying accept variant.
171
210
  return { kind: 'accept', ...('additionalContexts' in d && d.additionalContexts !== undefined ? { additionalContexts: d.additionalContexts } : {}), content: [replacement] };
172
211
  }
212
+ /**
213
+ * Reducer escalation stage (§3.1): after the deterministic route declined
214
+ * (null) or its savings fell below `minSavingsRatio`. Any reducer failure —
215
+ * eligibility, lane, timeout, verification — passes the ORIGINAL bytes
216
+ * through (fail-soft inside `reduceToolOutput` too).
217
+ */
218
+ async reduceOrPassthrough(exec, result, d, originalText, tokensBefore, cfg, ledgerRow) {
219
+ const replacementText = await reduceToolOutput({
220
+ ctx: this.ctx,
221
+ cfg,
222
+ exec,
223
+ originalText,
224
+ tokensBefore,
225
+ isError: result.isError,
226
+ estimate: (text) => this.estimate(text),
227
+ projectKey: this.projectKey(exec),
228
+ mode: cfg.mode,
229
+ put: (projectKey, text) => {
230
+ // The `store === undefined` gate above guarantees the store exists.
231
+ return this.store.put(projectKey, text);
232
+ },
233
+ ledgerRow,
234
+ });
235
+ if (replacementText === undefined)
236
+ return d;
237
+ const replacement = { type: 'text', text: replacementText };
238
+ // Fire-and-forget sweep AFTER the decision is formed (D6), matching the
239
+ // deterministic replacement path.
240
+ void this.store?.sweep();
241
+ // D11: spread the downstream decision so its additionalContexts survive.
242
+ return { kind: 'accept', ...('additionalContexts' in d && d.additionalContexts !== undefined ? { additionalContexts: d.additionalContexts } : {}), content: [replacement] };
243
+ }
173
244
  /** Token-based sizing (D3): the same estimator gates, markers, and ledger rows. */
174
245
  estimate(text) {
175
246
  return this.ctx.tokenMeter.estimateMessage({
package/lib/index.js.map CHANGED
@@ -1 +1 @@
1
- {"version":3,"file":"index.js","sourceRoot":"","sources":["../src/index.ts"],"names":[],"mappings":"AAAA;;;;;;;;;;;;;;GAcG;AAEH,OAAO,EAAE,OAAO,EAAE,MAAM,qBAAqB,CAAA;AAM7C,OAAO,EAAE,UAAU,EAAE,MAAM,eAAe,CAAA;AAC1C,OAAO,EAAE,aAAa,EAAE,MAAM,qBAAqB,CAAA;AACnD,OAAO,EAAE,aAAa,EAAE,eAAe,EAAE,MAAM,EAAE,MAAM,aAAa,CAAA;AACpE,OAAO,EAAE,gBAAgB,EAAE,MAAM,eAAe,CAAA;AAChD,OAAO,EAAE,KAAK,EAAE,MAAM,aAAa,CAAA;AACnC,OAAO,EAAE,YAAY,EAAE,SAAS,EAAE,MAAM,YAAY,CAAA;AACpD,OAAO,EAAE,aAAa,EAAE,MAAM,aAAa,CAAA;AAC3C,OAAO,EAAE,WAAW,EAAE,WAAW,EAAE,MAAM,aAAa,CAAA;AAGtD,OAAO,EAAE,aAAa,EAAE,eAAe,EAAE,QAAQ,EAAE,uBAAuB,EAAE,MAAM,EAAE,MAAM,aAAa,CAAA;AACvG,OAAO,EAAE,kBAAkB,EAAE,MAAM,eAAe,CAAA;AAClD,OAAO,EAAE,KAAK,EAAE,MAAM,aAAa,CAAA;AACnC,OAAO,EAAE,YAAY,EAAE,SAAS,EAAE,iBAAiB,EAAE,YAAY,EAAE,MAAM,YAAY,CAAA;AACrF,OAAO,EAAE,aAAa,EAAE,MAAM,aAAa,CAAA;AAC3C,OAAO,EAAE,WAAW,EAAE,WAAW,EAAE,MAAM,aAAa,CAAA;AAGtD,MAAM,CAAC,MAAM,kBAAkB,GAAG,kBAAkB,CAAA;AAEpD,wFAAwF;AACxF,MAAM,CAAC,MAAM,yBAAyB,GACpC,yFAAyF;MACvF,qGAAqG;MACrG,6FAA6F;MAC7F,8FAA8F;MAC9F,gFAAgF,CAAA;AAYpF;;;;GAIG;AACH,SAAS,SAAS,CAAC,GAAY;IAC7B,IAAI,CAAC;QACH,OAAO,GAAG,CAAC,WAAW,CAAA;IACxB,CAAC;IAAC,MAAM,CAAC;QACP,OAAO,SAAS,CAAA;IAClB,CAAC;AACH,CAAC;AAED,sEAAsE;AACtE,SAAS,aAAa,CAAC,MAA+B;IACpD,MAAM,KAAK,GAAa,EAAE,CAAA;IAC1B,KAAK,MAAM,KAAK,IAAI,MAAM,EAAE,CAAC;QAC3B,IAAI,KAAK,CAAC,IAAI,KAAK,MAAM;YAAE,OAAO,SAAS,CAAA;QAC3C,KAAK,CAAC,IAAI,CAAC,KAAK,CAAC,IAAI,CAAC,CAAA;IACxB,CAAC;IACD,OAAO,KAAK,CAAC,IAAI,CAAC,IAAI,CAAC,CAAA;AACzB,CAAC;AAED;;;GAGG;AACH,MAAM,OAAO,cAAe,SAAQ,OAAO;IACzC,MAAM,CAAC,MAAM,GAAG,CAAC,YAAY,CAAC,CAAA;IAE9B,MAAM,CAAC,MAAM,GAAG,MAAM,CAAA;IAEtB,6EAA6E;IAC5D,IAAI,CAAgB;IACpB,YAAY,CAAiC;IAC7C,KAAK,CAA0B;IAC/B,MAAM,CAA2B;IAElD,YAAY,GAAY,EAAE,SAAwB,EAAE;QAClD,KAAK,CAAC,GAAG,EAAE,gBAAgB,CAAC,CAAA;QAC5B,IAAI,CAAC,IAAI,GAAG,aAAa,CAAC,MAAM,CAAC,CAAA;QACjC,IAAI,CAAC,YAAY,GAAG,gBAAgB,CAAC,GAAG,EAAE,IAAI,CAAC,IAAI,CAAC,CAAA;QACpD,MAAM,IAAI,GAAG,SAAS,CAAC,GAAG,CAAC,CAAA;QAC3B,IAAI,IAAI,KAAK,SAAS,EAAE,CAAC;YACvB,wEAAwE;YACxE,GAAG,CAAC,MAAM,CAAC,IAAI,CAAC,qEAAqE,CAAC,CAAA;QACxF,CAAC;aAAM,CAAC;YACN,IAAI,CAAC,KAAK,GAAG,IAAI,YAAY,CAAC,IAAI,CAAC,KAAK,CAAC,CAAC,CAAA;YAC1C,IAAI,CAAC,MAAM,GAAG,IAAI,aAAa,CAAC,IAAI,CAAC,KAAK,EAAE,eAAe,CAAC,CAAC,CAAA;QAC/D,CAAC;QACD,IAAI,CAAC,gBAAgB,EAAE,CAAA;QACvB,IAAI,CAAC,oBAAoB,EAAE,CAAA;IAC7B,CAAC;IAED,sFAAsF;IACtF,eAAe;QACb,OAAO,eAAe,CAAC,IAAI,CAAC,IAAI,EAAE,IAAI,CAAC,YAAY,EAAE,CAAC,CAAA;IACxD,CAAC;IAEO,gBAAgB;QACtB,IAAI,CAAC,GAAG,CAAC,EAAE,CAAC,oBAAoB,EAAE,KAAK,EACrC,IAAmB,EACnB,MAAqC,EACrC,IAAI,EACuB,EAAE;YAC7B,MAAM,CAAC,GAAG,MAAM,IAAI,EAAE,CAAA;YACtB,IAAI,CAAC,CAAC,IAAI,KAAK,QAAQ;gBAAE,OAAO,CAAC,CAAA;YACjC,IAAI,CAAC;gBACH,OAAO,MAAM,IAAI,CAAC,KAAK,CAAC,IAAI,EAAE,MAAM,EAAE,CAAC,CAAC,CAAA;YAC1C,CAAC;YAAC,OAAO,KAAc,EAAE,CAAC;gBACxB,uEAAuE;gBACvE,iEAAiE;gBACjE,IAAI,CAAC,GAAG,CAAC,MAAM,CAAC,IAAI,CAAC,6CAA6C,MAAM,CAAC,KAAK,CAAC,EAAE,CAAC,CAAA;gBAClF,OAAO,CAAC,CAAA;YACV,CAAC;QACH,CAAC,EAAE,EAAE,OAAO,EAAE,IAAI,EAAE,CAAC,CAAA;IACvB,CAAC;IAEO,KAAK,CAAC,KAAK,CACjB,IAAmB,EACnB,MAAqC,EACrC,CAAgD;QAEhD,MAAM,GAAG,GAAG,IAAI,CAAC,eAAe,EAAE,CAAA;QAClC,MAAM,SAAS,GAAG,IAAI,CAAC,KAAK,KAAK,SAAS,CAAC,CAAC,CAAC,EAAE,CAAC,CAAC,CAAC,MAAM,CAAC,IAAI,CAAC,KAAK,CAAC,OAAO,CAAC,EAAE,CAAC,CAAA;QAC/E,MAAM,SAAS,GAAG,KAAK,EAAE,GAAiD,EAAiB,EAAE;YAC3F,MAAM,IAAI,CAAC,MAAM,EAAE,MAAM,CAAC;gBACxB,EAAE,EAAE,IAAI,IAAI,EAAE,CAAC,WAAW,EAAE;gBAC5B,SAAS;gBACT,IAAI,EAAE,IAAI,CAAC,IAAI;gBACf,GAAG,GAAG;aACP,CAAC,CAAA;QACJ,CAAC,CAAA;QACD,IAAI,CAAC,GAAG,CAAC,OAAO,IAAI,IAAI,CAAC,KAAK,KAAK,SAAS;YAAE,OAAO,CAAC,CAAA;QACtD,oEAAoE;QACpE,IAAK,GAAG,CAAC,cAAoC,CAAC,QAAQ,CAAC,IAAI,CAAC,IAAI,CAAC;YAAE,OAAO,CAAC,CAAA;QAC3E,qEAAqE;QACrE,2EAA2E;QAC3E,IAAI,IAAI,CAAC,IAAI,KAAK,kBAAkB;YAAE,OAAO,CAAC,CAAA;QAE9C,4DAA4D;QAC5D,IAAI,MAAM,CAAC,MAAM,CAAC,CAAC,EAAE,OAAO,CAAC;YAAE,OAAO,CAAC,CAAA;QACvC,MAAM,MAAM,GAAG,CAAC,CAAC,OAAO,IAAI,MAAM,CAAC,OAAO,CAAA;QAC1C,IAAI,MAAM,KAAK,SAAS;YAAE,OAAO,CAAC,CAAA;QAClC,MAAM,YAAY,GAAG,aAAa,CAAC,MAAM,CAAC,CAAA;QAC1C,IAAI,YAAY,KAAK,SAAS;YAAE,OAAO,CAAC,CAAA,CAAC,gCAAgC;QAEzE,MAAM,YAAY,GAAG,IAAI,CAAC,QAAQ,CAAC,YAAY,CAAC,CAAA;QAChD,IAAI,MAAM,CAAC,OAAO,IAAI,YAAY,GAAG,CAAC,GAAG,GAAG,CAAC,QAAQ;YAAE,OAAO,CAAC,CAAA;QAC/D,IAAI,YAAY,GAAG,GAAG,CAAC,QAAQ;YAAE,OAAO,CAAC,CAAA;QAEzC,MAAM,SAAS,GAAG,KAAK,CAAC,YAAY,CAAC,CAAA;QACrC,IAAI,SAAS,KAAK,IAAI;YAAE,OAAO,CAAC,CAAA;QAEhC,MAAM,cAAc,GAAG,SAAS,CAAC,IAAI,CAAA;QACrC,MAAM,WAAW,GAAG,IAAI,CAAC,QAAQ,CAAC,cAAc,CAAC,CAAA;QACjD,MAAM,OAAO,GAAG,CAAC,GAAG,WAAW,GAAG,YAAY,CAAA;QAC9C,IAAI,OAAO,GAAG,GAAG,CAAC,eAAe;YAAE,OAAO,CAAC,CAAA;QAE3C,IAAI,GAAG,CAAC,IAAI,KAAK,IAAI,EAAE,CAAC;YACtB,8DAA8D;YAC9D,MAAM,SAAS,CAAC,EAAE,IAAI,EAAE,SAAS,CAAC,IAAI,EAAE,WAAW,EAAE,YAAY,CAAC,MAAM,EAAE,UAAU,EAAE,cAAc,CAAC,MAAM,EAAE,YAAY,EAAE,WAAW,EAAE,OAAO,EAAE,KAAK,EAAE,CAAC,CAAA;YACzJ,OAAO,CAAC,CAAA;QACV,CAAC;QAED,MAAM,UAAU,GAAG,IAAI,CAAC,UAAU,CAAC,IAAI,CAAC,CAAA;QACxC,IAAI,UAAU,KAAK,SAAS;YAAE,OAAO,CAAC,CAAA;QACtC,MAAM,IAAI,GAAG,MAAM,IAAI,CAAC,KAAK,CAAC,GAAG,CAAC,UAAU,EAAE,YAAY,CAAC,CAAA;QAC3D,MAAM,WAAW,GAAiB;YAChC,IAAI,EAAE,MAAM;YACZ,IAAI,EAAE,GAAG,cAAc,KAAK,WAAW,CAAC,YAAY,EAAE,WAAW,EAAE,IAAI,CAAC,EAAE;SAC3E,CAAA;QACD,MAAM,SAAS,CAAC,EAAE,IAAI,EAAE,SAAS,CAAC,IAAI,EAAE,WAAW,EAAE,YAAY,CAAC,MAAM,EAAE,UAAU,EAAE,WAAW,CAAC,IAAI,CAAC,MAAM,EAAE,YAAY,EAAE,WAAW,EAAE,OAAO,EAAE,IAAI,EAAE,IAAI,EAAE,CAAC,CAAA;QAChK,yEAAyE;QACzE,2DAA2D;QAC3D,KAAK,IAAI,CAAC,KAAK,CAAC,KAAK,EAAE,CAAA;QACvB,yEAAyE;QACzE,4EAA4E;QAC5E,wEAAwE;QACxE,OAAO,EAAE,IAAI,EAAE,QAAQ,EAAE,GAAG,CAAC,oBAAoB,IAAI,CAAC,IAAI,CAAC,CAAC,kBAAkB,KAAK,SAAS,CAAC,CAAC,CAAC,EAAE,kBAAkB,EAAE,CAAC,CAAC,kBAAkB,EAAE,CAAC,CAAC,CAAC,EAAE,CAAC,EAAE,OAAO,EAAE,CAAC,WAAW,CAAC,EAAE,CAAA;IAC7K,CAAC;IAED,mFAAmF;IAC3E,QAAQ,CAAC,IAAY;QAC3B,OAAO,IAAI,CAAC,GAAG,CAAC,UAAU,CAAC,eAAe,CAAC;YACzC,IAAI,EAAE,MAAM;YACZ,OAAO,EAAE,CAAC,EAAE,IAAI,EAAE,MAAM,EAAE,IAAI,EAAE,CAAC;SACZ,CAAC,CAAA;IAC1B,CAAC;IAED,sEAAsE;IAC9D,UAAU,CAAC,IAAmB;QACpC,IAAI,IAAI,CAAC,KAAK,KAAK,SAAS;YAAE,OAAO,SAAS,CAAA;QAC9C,IAAI,CAAC;YACH,mEAAmE;YACnE,oEAAoE;YACpE,iCAAiC;YACjC,OAAO,SAAS,CAAC,aAAa,CAAC,IAAI,CAAC,KAAK,CAAC,CAAC,CAAA;QAC7C,CAAC;QAAC,MAAM,CAAC;YACP,OAAO,SAAS,CAAA;QAClB,CAAC;IACH,CAAC;IAED,+EAA+E;IAC/E,KAAK,CAAC,QAAQ,CAAC,IAAoB,EAAE,IAAY;QAG/C,IAAI,IAAI,CAAC,KAAK,KAAK,SAAS;YAAE,OAAO,EAAE,EAAE,EAAE,KAAK,EAAE,KAAK,EAAE,aAAa,EAAE,CAAA;QACxE,IAAI,CAAC,WAAW,CAAC,IAAI,CAAC,IAAI,CAAC;YAAE,OAAO,EAAE,EAAE,EAAE,KAAK,EAAE,KAAK,EAAE,cAAc,EAAE,CAAA;QACxE,MAAM,KAAK,GAAG,IAAI,CAAC,KAAK,CAAA;QACxB,IAAI,KAAK,KAAK,SAAS;YAAE,OAAO,EAAE,EAAE,EAAE,KAAK,EAAE,KAAK,EAAE,aAAa,EAAE,CAAA;QACnE,IAAI,UAAkB,CAAA;QACtB,IAAI,CAAC;YACH,UAAU,GAAG,SAAS,CAAC,aAAa,CAAC,KAAK,CAAC,CAAC,CAAA;QAC9C,CAAC;QAAC,MAAM,CAAC;YACP,OAAO,EAAE,EAAE,EAAE,KAAK,EAAE,KAAK,EAAE,aAAa,EAAE,CAAA;QAC5C,CAAC;QACD,OAAO,MAAM,IAAI,CAAC,KAAK,CAAC,GAAG,CAAC,UAAU,EAAE,IAAI,CAAC,CAAA;IAC/C,CAAC;IAEO,oBAAoB;QAC1B,MAAM,KAAK,GAAG,IAAI,CAAC,GAAG,CAAC,GAAG,CAAC,OAAO,CAAuD,CAAA;QACzF,IAAI,KAAK,KAAK,SAAS;YAAE,OAAM;QAC/B,KAAK,CAAC,QAAQ,CAAC,kBAAkB,CAAC,IAAI,CAAC,CAAC,CAAA;IAC1C,CAAC;;AAGH,SAAS,kBAAkB,CAAC,OAAuB;IACjD,OAAO,UAAU,CAAC;QAChB,IAAI,EAAE,kBAAkB;QACxB,WAAW,EAAE,yBAAyB;QACtC,UAAU,EAAE;YACV,IAAI,EAAE;gBACJ,IAAI,EAAE,QAAQ;gBACd,QAAQ,EAAE,IAAI;gBACd,WAAW,EAAE,yDAAyD;aACvE;SACF;QACD,MAAM,EAAE;YACN,MAAM,EAAE,EAAE,IAAI,EAAE,QAAQ,EAAE,oBAAoB,EAAE,KAAK,EAAE,UAAU,EAAE,EAAE,IAAI,EAAE,EAAE,IAAI,EAAE,QAAQ,EAAE,QAAQ,EAAE,IAAI,EAAE,EAAE,EAAE;YACjH,MAAM,EAAE,CAAC,KAAK,EAAE,KAAuB,EAAE,EAAE,CAAC,CAAC,EAAE,IAAI,EAAE,MAAM,EAAE,IAAI,EAAE,KAAK,CAAC,IAAI,EAAE,CAAC;SACjF;QACD,KAAK,CAAC,OAAO,CAAC,IAAsB,EAAE,IAAoB;YACxD,MAAM,OAAO,GAAG,MAAM,OAAO,CAAC,QAAQ,CAAC,IAAI,EAAE,IAAI,CAAC,IAAI,CAAC,CAAA;YACvD,IAAI,CAAC,OAAO,CAAC,EAAE,EAAE,CAAC;gBAChB,MAAM,IAAI,KAAK,CAAC,4BAA4B,OAAO,CAAC,KAAK,EAAE,CAAC,CAAA;YAC9D,CAAC;YACD,OAAO,EAAE,IAAI,EAAE,OAAO,CAAC,IAAI,EAAE,CAAA;QAC/B,CAAC;KACF,CAAC,CAAA;AACJ,CAAC;AAED,eAAe,cAAc,CAAA"}
1
+ {"version":3,"file":"index.js","sourceRoot":"","sources":["../src/index.ts"],"names":[],"mappings":"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"}
@@ -0,0 +1,45 @@
1
+ /**
2
+ * Receipt schema and canonical renderer for the evidence-preserving reducer.
3
+ * @module @dsh-cc/context-crusher/receipt
4
+ */
5
+ import z from '@deepseek-ai/schemastery';
6
+ /** One failing test entry: identifier plus a verbatim evidence quote. */
7
+ export interface ReceiptFailure {
8
+ readonly name: string;
9
+ readonly evidence: string;
10
+ }
11
+ /**
12
+ * The cheap-lane extraction receipt (plan §3.3). Every `evidence` /
13
+ * `key_output` string must be a verbatim substring of the (possibly
14
+ * truncated) source view; `verifyReceipt` enforces that.
15
+ */
16
+ export interface Receipt {
17
+ readonly v: 1;
18
+ readonly cmd: string;
19
+ readonly exit: {
20
+ readonly ok: boolean;
21
+ readonly code?: number | undefined;
22
+ };
23
+ readonly failures: ReceiptFailure[];
24
+ readonly key_output: string[];
25
+ readonly counts?: {
26
+ readonly pass: number;
27
+ readonly fail: number;
28
+ readonly skip: number;
29
+ } | undefined;
30
+ }
31
+ /** schemastery schema for the receipt shape (types only; see parseReceipt for key-set checks). */
32
+ export declare const ReceiptSchema: z<Receipt>;
33
+ /**
34
+ * Parse and validate a raw receipt. Returns the receipt, or `null` when any
35
+ * check fails: schema types, the 8-entry `key_output` cap, or the explicit
36
+ * exact-key-set check at every object level (schemastery `z.object` keeps
37
+ * unknown keys rather than stripping them, so rejection is explicit here).
38
+ */
39
+ export declare function parseReceipt(raw: unknown): Receipt | null;
40
+ /**
41
+ * Canonical few-line rendering (plan §3.5): deterministic, receipt body only.
42
+ * The caller appends the pinned `buildMarker(...)` line — never included here.
43
+ */
44
+ export declare function renderReceipt(r: Receipt): string;
45
+ //# sourceMappingURL=receipt.d.ts.map
@@ -0,0 +1 @@
1
+ {"version":3,"file":"receipt.d.ts","sourceRoot":"","sources":["../src/receipt.ts"],"names":[],"mappings":"AAAA;;;GAGG;AAEH,OAAO,CAAC,MAAM,0BAA0B,CAAA;AAExC,yEAAyE;AACzE,MAAM,WAAW,cAAc;IAC7B,QAAQ,CAAC,IAAI,EAAE,MAAM,CAAA;IACrB,QAAQ,CAAC,QAAQ,EAAE,MAAM,CAAA;CAC1B;AAED;;;;GAIG;AACH,MAAM,WAAW,OAAO;IACtB,QAAQ,CAAC,CAAC,EAAE,CAAC,CAAA;IACb,QAAQ,CAAC,GAAG,EAAE,MAAM,CAAA;IACpB,QAAQ,CAAC,IAAI,EAAE;QAAE,QAAQ,CAAC,EAAE,EAAE,OAAO,CAAC;QAAC,QAAQ,CAAC,IAAI,CAAC,EAAE,MAAM,GAAG,SAAS,CAAA;KAAE,CAAA;IAC3E,QAAQ,CAAC,QAAQ,EAAE,cAAc,EAAE,CAAA;IACnC,QAAQ,CAAC,UAAU,EAAE,MAAM,EAAE,CAAA;IAC7B,QAAQ,CAAC,MAAM,CAAC,EAAE;QAAE,QAAQ,CAAC,IAAI,EAAE,MAAM,CAAC;QAAC,QAAQ,CAAC,IAAI,EAAE,MAAM,CAAC;QAAC,QAAQ,CAAC,IAAI,EAAE,MAAM,CAAA;KAAE,GAAG,SAAS,CAAA;CACtG;AAKD,kGAAkG;AAClG,eAAO,MAAM,aAAa,EAAE,CAAC,CAAC,OAAO,CAOnC,CAAA;AAeF;;;;;GAKG;AACH,wBAAgB,YAAY,CAAC,GAAG,EAAE,OAAO,GAAG,OAAO,GAAG,IAAI,CAgBzD;AAED;;;GAGG;AACH,wBAAgB,aAAa,CAAC,CAAC,EAAE,OAAO,GAAG,MAAM,CAQhD"}