instar 1.3.740 → 1.3.742

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.
@@ -0,0 +1,114 @@
1
+ /**
2
+ * Shared prompt↔parser contract library — the mechanical arm of the
3
+ * "The Prompt and the Parser Are One Contract" standard (defect class 1 closure;
4
+ * docs/specs/prompt-parser-contract-standard.md).
5
+ *
6
+ * WHY THIS EXISTS (earned): on 2026-07-02 the INSTAR-Bench v2 defect-class
7
+ * review found the tone gate's PROMPT taught models the short rule id ("B15")
8
+ * while its production PARSER accepts only the full identifier
9
+ * ("B15_CONTEXT_DEATH_STOP") and fails closed on the short form. Every model
10
+ * through every door obeyed the prompt and "failed" — a 100%-our-fault defect.
11
+ * An LLM callsite whose output is machine-parsed is ONE contract with TWO halves
12
+ * maintained separately: the prompt promises an output vocabulary/shape; the
13
+ * parser accepts one. Nothing held them coherent. This module gives that
14
+ * contract a code artifact — the type of a co-located promise, and a pure
15
+ * generator for the counter-examples a contract test must prove the parser
16
+ * REJECTS — so a taught-but-unparsed vocabulary becomes a CI failure instead of
17
+ * a latent door.
18
+ *
19
+ * SCOPE HONESTY (design §2): the PREFERRED form for an enumerated-verdict
20
+ * callsite is single-sourcing — prompt, parser, and test all consume ONE
21
+ * exported verdict constant, which makes a taught-but-undeclared token
22
+ * structurally impossible. The `PromptContract` manifest below is the FALLBACK
23
+ * form for prose-shaped prompts where single-sourcing is impractical (a reviewed
24
+ * claim per spec §2, not an author's private call). This module ships DARK: it
25
+ * introduces no runtime caller and changes NO live prompt or parser behavior.
26
+ * It is consumed only by the per-callsite CONTRACT TESTS that graduate on the
27
+ * shrink-only schedule (rollout §1/§2) — each of which renders the REAL
28
+ * production prompt through an exported pure render function; that render
29
+ * refactor of the live builders is deferred to its own A/B-gated increments and
30
+ * is NOT part of this dark increment.
31
+ */
32
+ /**
33
+ * The election of a contract's form, recorded per coverage entry (spec §2:
34
+ * "Form election is not self-certified"). A `manifest`-form entry on an
35
+ * enumerated-verdict callsite requires an X1 argued reason in the registry.
36
+ */
37
+ export type ContractForm = 'single-source' | 'manifest';
38
+ /**
39
+ * The co-located machine-readable promise for a prose-shaped (fallback-form)
40
+ * callsite. Co-location is the point (spec §2): a prompt edit lands in the same
41
+ * file/diff as the promise, so review and CI see contract drift as ONE change.
42
+ *
43
+ * The `parser` is a FUNCTION REFERENCE, never a string — refactor-safe (spec §2).
44
+ * A parser returning a non-null/defined value for an input is treated as
45
+ * "accepted"; the contract test decides acceptance semantics per callsite.
46
+ */
47
+ export interface PromptContract<TAccepted = unknown> {
48
+ /**
49
+ * Every terminal token/shape the prompt text tells the model to produce.
50
+ * Prefer the shared verdict constant even here (spec §2).
51
+ */
52
+ readonly promisedOutputs: readonly string[];
53
+ /**
54
+ * Canonical counter-examples the parser must REJECT (fail-closed proof).
55
+ * MECHANICALLY DERIVED from `promisedOutputs` via `deriveRejectedForms`
56
+ * (case-mutation, prefix-truncation, separator-stripping) plus hand-picked
57
+ * extras — a hand-only list invites trivial rejects (spec §2).
58
+ */
59
+ readonly rejectedForms: readonly string[];
60
+ /**
61
+ * Known-hazard shapes that must NOT appear anywhere in the full rendered
62
+ * prompt outside explicitly-declared negative sections (spec §3.1) — the
63
+ * inverse-direction backstop (e.g. bare rule ids the parser rejects).
64
+ */
65
+ readonly hazardPatterns: readonly RegExp[];
66
+ /**
67
+ * The response envelope the prompt promises (JSON shape, field names).
68
+ */
69
+ readonly envelope: {
70
+ readonly shape: 'json' | 'text';
71
+ readonly verdictField?: string;
72
+ };
73
+ /**
74
+ * Compatibility forms the parser DELIBERATELY accepts (documented, tested).
75
+ * "non-promised" for the fail-closed test means outside promised ∪ aliases.
76
+ */
77
+ readonly acceptedAliases: readonly string[];
78
+ /** The REAL production parser, by reference. */
79
+ readonly parser: (raw: string) => TAccepted;
80
+ }
81
+ /**
82
+ * Options for {@link deriveRejectedForms}.
83
+ */
84
+ export interface DeriveRejectedFormsOptions {
85
+ /**
86
+ * The separator characters whose stripping/truncation produces a rejected
87
+ * form. Defaults to `_`, `-`, and a space — the separators that produced the
88
+ * historical B15 defect ("B15_CONTEXT_DEATH_STOP" → "B15").
89
+ */
90
+ readonly separators?: readonly string[];
91
+ }
92
+ /**
93
+ * Mechanically derive the canonical counter-examples a contract test feeds the
94
+ * REAL parser to prove its documented fail-closed behavior (spec §2/§3.3).
95
+ *
96
+ * For each promised token it produces: case-mutations, prefix-truncations at
97
+ * each separator, and separator-stripped forms. `extras` (hand-picked shapes,
98
+ * e.g. the literal short id `B15` and the empty string) are appended. The
99
+ * result EXCLUDES any form that collides with a genuinely-promised token — a
100
+ * mutation that equals a real promised output is NOT a rejected form (that would
101
+ * make the fail-closed assertion contradict the acceptance assertion). The
102
+ * output is de-duplicated and stably ordered.
103
+ *
104
+ * Pure and side-effect-free. It touches no live parser and reads no I/O.
105
+ *
106
+ * @param vocabulary the promised output vocabulary (the taught verdict tokens).
107
+ * @param extras hand-picked additional rejected forms (spec §2: a hand-only
108
+ * list invites trivial rejects, so this AUGMENTS the derived set).
109
+ * @param options separator configuration (defaults to `_ - <space>`).
110
+ * @returns the derived + hand-picked rejected forms, minus any that collide
111
+ * with a promised token, de-duplicated and stably ordered.
112
+ */
113
+ export declare function deriveRejectedForms(vocabulary: readonly string[], extras?: readonly string[], options?: DeriveRejectedFormsOptions): string[];
114
+ //# sourceMappingURL=promptContract.d.ts.map
@@ -0,0 +1 @@
1
+ {"version":3,"file":"promptContract.d.ts","sourceRoot":"","sources":["../../src/core/promptContract.ts"],"names":[],"mappings":"AAAA;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;GA8BG;AAEH;;;;GAIG;AACH,MAAM,MAAM,YAAY,GAAG,eAAe,GAAG,UAAU,CAAC;AAExD;;;;;;;;GAQG;AACH,MAAM,WAAW,cAAc,CAAC,SAAS,GAAG,OAAO;IACjD;;;OAGG;IACH,QAAQ,CAAC,eAAe,EAAE,SAAS,MAAM,EAAE,CAAC;IAC5C;;;;;OAKG;IACH,QAAQ,CAAC,aAAa,EAAE,SAAS,MAAM,EAAE,CAAC;IAC1C;;;;OAIG;IACH,QAAQ,CAAC,cAAc,EAAE,SAAS,MAAM,EAAE,CAAC;IAC3C;;OAEG;IACH,QAAQ,CAAC,QAAQ,EAAE;QAAE,QAAQ,CAAC,KAAK,EAAE,MAAM,GAAG,MAAM,CAAC;QAAC,QAAQ,CAAC,YAAY,CAAC,EAAE,MAAM,CAAA;KAAE,CAAC;IACvF;;;OAGG;IACH,QAAQ,CAAC,eAAe,EAAE,SAAS,MAAM,EAAE,CAAC;IAC5C,gDAAgD;IAChD,QAAQ,CAAC,MAAM,EAAE,CAAC,GAAG,EAAE,MAAM,KAAK,SAAS,CAAC;CAC7C;AAED;;GAEG;AACH,MAAM,WAAW,0BAA0B;IACzC;;;;OAIG;IACH,QAAQ,CAAC,UAAU,CAAC,EAAE,SAAS,MAAM,EAAE,CAAC;CACzC;AAgDD;;;;;;;;;;;;;;;;;;;;GAoBG;AACH,wBAAgB,mBAAmB,CACjC,UAAU,EAAE,SAAS,MAAM,EAAE,EAC7B,MAAM,GAAE,SAAS,MAAM,EAAO,EAC9B,OAAO,GAAE,0BAA+B,GACvC,MAAM,EAAE,CAqBV"}
@@ -0,0 +1,120 @@
1
+ /**
2
+ * Shared prompt↔parser contract library — the mechanical arm of the
3
+ * "The Prompt and the Parser Are One Contract" standard (defect class 1 closure;
4
+ * docs/specs/prompt-parser-contract-standard.md).
5
+ *
6
+ * WHY THIS EXISTS (earned): on 2026-07-02 the INSTAR-Bench v2 defect-class
7
+ * review found the tone gate's PROMPT taught models the short rule id ("B15")
8
+ * while its production PARSER accepts only the full identifier
9
+ * ("B15_CONTEXT_DEATH_STOP") and fails closed on the short form. Every model
10
+ * through every door obeyed the prompt and "failed" — a 100%-our-fault defect.
11
+ * An LLM callsite whose output is machine-parsed is ONE contract with TWO halves
12
+ * maintained separately: the prompt promises an output vocabulary/shape; the
13
+ * parser accepts one. Nothing held them coherent. This module gives that
14
+ * contract a code artifact — the type of a co-located promise, and a pure
15
+ * generator for the counter-examples a contract test must prove the parser
16
+ * REJECTS — so a taught-but-unparsed vocabulary becomes a CI failure instead of
17
+ * a latent door.
18
+ *
19
+ * SCOPE HONESTY (design §2): the PREFERRED form for an enumerated-verdict
20
+ * callsite is single-sourcing — prompt, parser, and test all consume ONE
21
+ * exported verdict constant, which makes a taught-but-undeclared token
22
+ * structurally impossible. The `PromptContract` manifest below is the FALLBACK
23
+ * form for prose-shaped prompts where single-sourcing is impractical (a reviewed
24
+ * claim per spec §2, not an author's private call). This module ships DARK: it
25
+ * introduces no runtime caller and changes NO live prompt or parser behavior.
26
+ * It is consumed only by the per-callsite CONTRACT TESTS that graduate on the
27
+ * shrink-only schedule (rollout §1/§2) — each of which renders the REAL
28
+ * production prompt through an exported pure render function; that render
29
+ * refactor of the live builders is deferred to its own A/B-gated increments and
30
+ * is NOT part of this dark increment.
31
+ */
32
+ /**
33
+ * Toggle a token's letter case in the three ways a lenient model most often
34
+ * mutates a taught identifier: all-upper, all-lower, and first-letter-flipped.
35
+ * Purely mechanical — no locale assumptions beyond JS default casing.
36
+ */
37
+ function caseMutations(token) {
38
+ const out = new Set();
39
+ out.add(token.toUpperCase());
40
+ out.add(token.toLowerCase());
41
+ if (token.length > 0) {
42
+ const first = token[0];
43
+ const flippedFirst = first === first.toUpperCase() ? first.toLowerCase() : first.toUpperCase();
44
+ out.add(flippedFirst + token.slice(1));
45
+ }
46
+ return [...out];
47
+ }
48
+ /**
49
+ * Prefix-truncations at each separator boundary — the exact B15 shape: the
50
+ * model emits the leading segment ("B15") of a compound identifier
51
+ * ("B15_CONTEXT_DEATH_STOP") that the parser rejects.
52
+ */
53
+ function prefixTruncations(token, separators) {
54
+ const out = new Set();
55
+ for (const sep of separators) {
56
+ if (!sep)
57
+ continue;
58
+ const idx = token.indexOf(sep);
59
+ if (idx > 0)
60
+ out.add(token.slice(0, idx));
61
+ }
62
+ return [...out];
63
+ }
64
+ /**
65
+ * Separator-stripped forms — the same token with each separator removed
66
+ * ("B15_CONTEXT_DEATH_STOP" → "B15CONTEXTDEATHSTOP").
67
+ */
68
+ function separatorStripped(token, separators) {
69
+ const out = new Set();
70
+ for (const sep of separators) {
71
+ if (!sep)
72
+ continue;
73
+ if (token.includes(sep))
74
+ out.add(token.split(sep).join(''));
75
+ }
76
+ return [...out];
77
+ }
78
+ /**
79
+ * Mechanically derive the canonical counter-examples a contract test feeds the
80
+ * REAL parser to prove its documented fail-closed behavior (spec §2/§3.3).
81
+ *
82
+ * For each promised token it produces: case-mutations, prefix-truncations at
83
+ * each separator, and separator-stripped forms. `extras` (hand-picked shapes,
84
+ * e.g. the literal short id `B15` and the empty string) are appended. The
85
+ * result EXCLUDES any form that collides with a genuinely-promised token — a
86
+ * mutation that equals a real promised output is NOT a rejected form (that would
87
+ * make the fail-closed assertion contradict the acceptance assertion). The
88
+ * output is de-duplicated and stably ordered.
89
+ *
90
+ * Pure and side-effect-free. It touches no live parser and reads no I/O.
91
+ *
92
+ * @param vocabulary the promised output vocabulary (the taught verdict tokens).
93
+ * @param extras hand-picked additional rejected forms (spec §2: a hand-only
94
+ * list invites trivial rejects, so this AUGMENTS the derived set).
95
+ * @param options separator configuration (defaults to `_ - <space>`).
96
+ * @returns the derived + hand-picked rejected forms, minus any that collide
97
+ * with a promised token, de-duplicated and stably ordered.
98
+ */
99
+ export function deriveRejectedForms(vocabulary, extras = [], options = {}) {
100
+ const separators = options.separators ?? ['_', '-', ' '];
101
+ const promised = new Set(vocabulary);
102
+ const derived = [];
103
+ for (const token of vocabulary) {
104
+ if (typeof token !== 'string' || token.length === 0)
105
+ continue;
106
+ derived.push(...caseMutations(token), ...prefixTruncations(token, separators), ...separatorStripped(token, separators));
107
+ }
108
+ const seen = new Set();
109
+ const out = [];
110
+ for (const form of [...derived, ...extras]) {
111
+ if (promised.has(form))
112
+ continue; // a real promised token is never a "rejected form"
113
+ if (seen.has(form))
114
+ continue;
115
+ seen.add(form);
116
+ out.push(form);
117
+ }
118
+ return out;
119
+ }
120
+ //# sourceMappingURL=promptContract.js.map
@@ -0,0 +1 @@
1
+ {"version":3,"file":"promptContract.js","sourceRoot":"","sources":["../../src/core/promptContract.ts"],"names":[],"mappings":"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"}
@@ -53,4 +53,12 @@ export type JudgesClaimsFlag = {
53
53
  false: string;
54
54
  };
55
55
  export declare const LLM_JUDGES_CLAIMS: Readonly<Record<string, JudgesClaimsFlag>>;
56
+ export type ParserContractFlag = {
57
+ contractTest: string;
58
+ } | {
59
+ pending: 'contract-wave-1' | 'contract-wave-2';
60
+ } | {
61
+ false: string;
62
+ };
63
+ export declare const LLM_PARSER_CONTRACT: Readonly<Record<string, ParserContractFlag>>;
56
64
  //# sourceMappingURL=llmBenchCoverage.d.ts.map
@@ -1 +1 @@
1
- {"version":3,"file":"llmBenchCoverage.d.ts","sourceRoot":"","sources":["../../src/data/llmBenchCoverage.ts"],"names":[],"mappings":"AAAA;;;;;;;;;;;;;;;;;;;;;;;;GAwBG;AAEH,MAAM,MAAM,aAAa,GACrB;IAAE,IAAI,EAAE,MAAM,CAAA;CAAE,GAChB;IAAE,OAAO,EAAE,QAAQ,GAAG,QAAQ,CAAA;CAAE,GAChC;IAAE,MAAM,EAAE,MAAM,CAAA;CAAE,CAAC;AAEvB,eAAO,MAAM,kBAAkB,EAAE,QAAQ,CAAC,MAAM,CAAC,MAAM,EAAE,aAAa,CAAC,CAqFtE,CAAC;AA4BF,MAAM,MAAM,kBAAkB,GAAG,IAAI,GAAG;IAAE,KAAK,EAAE,MAAM,CAAA;CAAE,CAAC;AAE1D,eAAO,MAAM,mBAAmB,EAAE,QAAQ,CAAC,MAAM,CAAC,MAAM,EAAE,kBAAkB,CAAC,CAiF5E,CAAC;AA+CF;;;;6EAI6E;AAC7E,MAAM,MAAM,SAAS,GAAG,iBAAiB,GAAG,aAAa,GAAG,cAAc,CAAC;AAE3E,eAAO,MAAM,WAAW,EAAE,aAAa,CAAC,SAAS,CAIhD,CAAC;AAEF;;;;oFAIoF;AACpF,MAAM,MAAM,gBAAgB,GAAG;IAAE,SAAS,EAAE,SAAS,CAAA;CAAE,GAAG,KAAK,GAAG;IAAE,KAAK,EAAE,MAAM,CAAA;CAAE,CAAC;AAEpF,eAAO,MAAM,iBAAiB,EAAE,QAAQ,CAAC,MAAM,CAAC,MAAM,EAAE,gBAAgB,CAAC,CAmExE,CAAC"}
1
+ {"version":3,"file":"llmBenchCoverage.d.ts","sourceRoot":"","sources":["../../src/data/llmBenchCoverage.ts"],"names":[],"mappings":"AAAA;;;;;;;;;;;;;;;;;;;;;;;;GAwBG;AAEH,MAAM,MAAM,aAAa,GACrB;IAAE,IAAI,EAAE,MAAM,CAAA;CAAE,GAChB;IAAE,OAAO,EAAE,QAAQ,GAAG,QAAQ,CAAA;CAAE,GAChC;IAAE,MAAM,EAAE,MAAM,CAAA;CAAE,CAAC;AAEvB,eAAO,MAAM,kBAAkB,EAAE,QAAQ,CAAC,MAAM,CAAC,MAAM,EAAE,aAAa,CAAC,CAqFtE,CAAC;AA4BF,MAAM,MAAM,kBAAkB,GAAG,IAAI,GAAG;IAAE,KAAK,EAAE,MAAM,CAAA;CAAE,CAAC;AAE1D,eAAO,MAAM,mBAAmB,EAAE,QAAQ,CAAC,MAAM,CAAC,MAAM,EAAE,kBAAkB,CAAC,CAiF5E,CAAC;AA+CF;;;;6EAI6E;AAC7E,MAAM,MAAM,SAAS,GAAG,iBAAiB,GAAG,aAAa,GAAG,cAAc,CAAC;AAE3E,eAAO,MAAM,WAAW,EAAE,aAAa,CAAC,SAAS,CAIhD,CAAC;AAEF;;;;oFAIoF;AACpF,MAAM,MAAM,gBAAgB,GAAG;IAAE,SAAS,EAAE,SAAS,CAAA;CAAE,GAAG,KAAK,GAAG;IAAE,KAAK,EAAE,MAAM,CAAA;CAAE,CAAC;AAEpF,eAAO,MAAM,iBAAiB,EAAE,QAAQ,CAAC,MAAM,CAAC,MAAM,EAAE,gBAAgB,CAAC,CAmExE,CAAC;AAgDF,MAAM,MAAM,kBAAkB,GAC1B;IAAE,YAAY,EAAE,MAAM,CAAA;CAAE,GACxB;IAAE,OAAO,EAAE,iBAAiB,GAAG,iBAAiB,CAAA;CAAE,GAClD;IAAE,KAAK,EAAE,MAAM,CAAA;CAAE,CAAC;AAEtB,eAAO,MAAM,mBAAmB,EAAE,QAAQ,CAAC,MAAM,CAAC,MAAM,EAAE,kBAAkB,CAAC,CAmJ5E,CAAC"}
@@ -239,4 +239,121 @@ export const LLM_JUDGES_CLAIMS = {
239
239
  CartographerSweep: false, // authors doc-tree summaries over code
240
240
  StandardsCoverageEnrichment: false, // enriches standards-coverage rows
241
241
  };
242
+ export const LLM_PARSER_CONTRACT = {
243
+ // ── WAVE-1: the four spec-named highest-stakes parsed callsites (rollout §0) ──
244
+ MessagingToneGate: { pending: 'contract-wave-1' }, // THE motivating defect: prompt taught "B15", parser accepts only "B15_CONTEXT_DEATH_STOP"
245
+ ExternalOperationGate: { pending: 'contract-wave-1' }, // parses a closed mutability/reversibility classification
246
+ CompletionEvaluator: { pending: 'contract-wave-1' }, // the stop-judge surface parses a closed done/blocked/continue verdict
247
+ InputClassifier: { pending: 'contract-wave-1' }, // parses a closed auto-approve vs relay decision
248
+ // ── WAVE-2: every other enumerated-verdict / decision callsite (rollout §2) ──
249
+ MessageSentinel: { pending: 'contract-wave-2' }, // closed intent set (pause / emergency / normal)
250
+ LLMSanitizer: { pending: 'contract-wave-2' }, // parses a closed sanitize verdict/decision
251
+ WarrantsReplyGate: { pending: 'contract-wave-2' }, // closed should-reply yes/no verdict
252
+ InputGuard: { pending: 'contract-wave-2' }, // closed input-coherence verdict
253
+ StallTriageNurse: { pending: 'contract-wave-2' }, // closed stall-triage diagnosis label
254
+ CommitmentSentinel: { pending: 'contract-wave-2' }, // closed commitment-detected verdict + structured envelope
255
+ PresenceProxy: { pending: 'contract-wave-2' }, // closed tier-3 stall verdict
256
+ ProjectDriftChecker: { pending: 'contract-wave-2' }, // closed on-project verdict
257
+ TemporalCoherenceChecker: { pending: 'contract-wave-2' }, // closed temporal-coherence verdict
258
+ SessionWatchdog: { pending: 'contract-wave-2' }, // closed stuck verdict
259
+ ResumeQueueDrainer: { pending: 'contract-wave-2' }, // closed resume-sanity verdict
260
+ TopicIntentArcCheck: { pending: 'contract-wave-2' }, // closed arc-check classification label
261
+ TelegramAdapter: { pending: 'contract-wave-2' }, // stall-confirm — closed genuinely-stalled verdict
262
+ SlackAdapter: { pending: 'contract-wave-2' }, // stall-confirm (byte-identical prompt to Telegram's; parity)
263
+ PromptGate: { pending: 'contract-wave-2' }, // closed injection-detected verdict
264
+ UnjustifiedStopGate: { pending: 'contract-wave-2' }, // closed stop-justified verdict
265
+ OverrideDetector: { pending: 'contract-wave-2' }, // closed override-intent verdict
266
+ TaskClassifier: { pending: 'contract-wave-2' }, // closed task-type label set
267
+ ResumeValidator: { pending: 'contract-wave-2' }, // closed resume-UUID match yes/no verdict
268
+ CoherenceReviewer: { pending: 'contract-wave-2' }, // gate-triage — closed coherence verdict
269
+ // ── Argued false (pinned shrink-only) — no closed-vocabulary verdict parse ──
270
+ // No live LLM callsite, a fixed canary, or free-text / open-set content.
271
+ InputDetector: {
272
+ false: 'attribution-manifest alias only (a legacy prompt-pattern matcher); the live matcher calls with attribution PromptGate, contracted there',
273
+ },
274
+ SessionActivitySentinel: {
275
+ false: 'authors a free-text activity DIGEST — the product is prose, not a closed verdict vocabulary a prompt teaches and a parser gates on',
276
+ },
277
+ PromiseBeacon: {
278
+ false: 'no live LLM prompt — generateStatusLine/classifyProgress hooks are unwired at the construction site; nothing parses a taught vocabulary (matches its bench-coverage exemption)',
279
+ },
280
+ InteractivePoolCanaryJudge: {
281
+ false: 'judges a FIXED known-answer canary probe — the expected output is a constant, so the canary is its own contract; a prompt↔parser contract test would re-test the same constant',
282
+ },
283
+ SessionSummarySentinel: {
284
+ false: 'extracts task/phase/files as open-set free-text FIELDS — there is no closed taught verdict vocabulary, so the B15 prompt↔parser drift cannot arise here',
285
+ },
286
+ AutoApprover: {
287
+ false: 'mechanical key injection + audit logging, no LLM prompt of its own; the upstream parsed decision is InputClassifier.classify(), contracted there',
288
+ },
289
+ IntegrationGate: {
290
+ false: 'no LLM prompt of its own — delegates to JobReflector.reflect(); zero LLM-provider callsites of its own that parse a taught vocabulary',
291
+ },
292
+ CoherenceGate: {
293
+ false: 'no callsite carries attribution CoherenceGate — all LLM calls flow through CoherenceReviewer.callApi(), contracted there',
294
+ },
295
+ JobReflector: {
296
+ false: 'reflection produces free-text content over a job — no closed taught verdict vocabulary a parser gates on (its own bench coverage is wave-3)',
297
+ },
298
+ crossModelReviewer: {
299
+ false: 'produces a free-text review of a SPEC document — no closed output vocabulary the prompt teaches and a parser must accept',
300
+ },
301
+ SelfKnowledgeTree: {
302
+ false: 'extracts self-knowledge tree fragments as content that is stored/merged — no closed verdict token gates a branch on a taught vocabulary',
303
+ },
304
+ TreeTriage: {
305
+ false: 'triages knowledge-tree fragments into content — no closed taught output vocabulary a parser must accept or reject',
306
+ },
307
+ TopicSummarizer: {
308
+ false: 'produces a free-text topic summary — the prose is the product; there is no closed vocabulary the prompt teaches and a parser gates on',
309
+ },
310
+ ContextualEvaluator: {
311
+ false: 'evaluates context relevance into content — no closed taught verdict vocabulary that a parser accepts a promised form of',
312
+ },
313
+ RelationshipManager: {
314
+ false: 'extracts relationship facts as open-set structured content — no closed taught vocabulary a prompt promises and a parser gates on',
315
+ },
316
+ StandardsConformanceReviewer: {
317
+ false: 'reviews artifact-vs-standard conformance as content — no closed output vocabulary the prompt teaches and a parser must accept',
318
+ },
319
+ DiscoveryEvaluator: {
320
+ false: 'evaluates serendipity discoveries into content — no closed taught verdict vocabulary a parser accepts a promised form of',
321
+ },
322
+ Usher: {
323
+ false: 'routes a turn to candidate TOPIC IDS — an OPEN, machine-supplied set, not a closed taught vocabulary the prompt fixes and a parser gates on',
324
+ },
325
+ TopicIntentExtractor: {
326
+ false: 'extracts a topic-intent description from a turn — free-text content, not a closed taught verdict vocabulary a parser accepts',
327
+ },
328
+ PreCompactionFlush: {
329
+ false: 'extracts durable facts before compaction as free-text content — no closed taught output vocabulary a parser gates on',
330
+ },
331
+ TreeSynthesis: {
332
+ false: 'synthesizes knowledge fragments into a free-text answer — the prose is the product, no closed taught verdict vocabulary a parser accepts',
333
+ },
334
+ LLMConflictResolver: {
335
+ false: 'resolves divergent multi-machine state into a merged value/content — no closed taught verdict vocabulary a prompt promises and a parser gates on',
336
+ },
337
+ openConversationBrief: {
338
+ false: 'generates a free-text A2A conversation brief — the prose is the product, no closed output vocabulary the prompt teaches and a parser must accept',
339
+ },
340
+ 'a2a-checkin': {
341
+ false: 'summarizes A2A check-in threads into free-text content — no closed taught verdict vocabulary a parser accepts a promised form of',
342
+ },
343
+ 'correction-learning': {
344
+ false: 'distills recurring corrections into a preference (content) — no closed taught output vocabulary a parser gates on',
345
+ },
346
+ 'mentor-stage-b': {
347
+ false: 'classifies mentor signals over mentee output into differential content — no closed taught verdict vocabulary a parser gates on (its own bench coverage is wave-3)',
348
+ },
349
+ PipeSessionSpawner: {
350
+ false: 'spawns sessions from task descriptions — no LLM output parsed into a closed taught verdict vocabulary',
351
+ },
352
+ CartographerSweep: {
353
+ false: 'authors doc-tree summaries over code as free text — the prose is the product, no closed taught output vocabulary a parser gates on',
354
+ },
355
+ StandardsCoverageEnrichment: {
356
+ false: 'enriches standards-coverage rows with content — no closed taught verdict vocabulary a prompt promises and a parser accepts',
357
+ },
358
+ };
242
359
  //# sourceMappingURL=llmBenchCoverage.js.map
@@ -1 +1 @@
1
- {"version":3,"file":"llmBenchCoverage.js","sourceRoot":"","sources":["../../src/data/llmBenchCoverage.ts"],"names":[],"mappings":"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"}
1
+ {"version":3,"file":"llmBenchCoverage.js","sourceRoot":"","sources":["../../src/data/llmBenchCoverage.ts"],"names":[],"mappings":"AAAA;;;;;;;;;;;;;;;;;;;;;;;;GAwBG;AAOH,MAAM,CAAC,MAAM,kBAAkB,GAA4C;IACzE,mEAAmE;IACnE,eAAe,EAAE,EAAE,IAAI,EAAE,mBAAmB,EAAE;IAC9C,iBAAiB,EAAE,EAAE,IAAI,EAAE,WAAW,EAAE;IACxC,6DAA6D;IAC7D,mBAAmB,EAAE,EAAE,IAAI,EAAE,iCAAiC,EAAE;IAChE,qBAAqB,EAAE,EAAE,IAAI,EAAE,kBAAkB,EAAE;IACnD,YAAY,EAAE,EAAE,IAAI,EAAE,qBAAqB,EAAE;IAC7C,iBAAiB,EAAE,EAAE,IAAI,EAAE,gBAAgB,EAAE;IAC7C,eAAe,EAAE,EAAE,IAAI,EAAE,kBAAkB,EAAE;IAC7C,KAAK,EAAE,EAAE,IAAI,EAAE,OAAO,EAAE;IACxB,qBAAqB,EAAE,EAAE,IAAI,EAAE,sBAAsB,EAAE;IACvD,iBAAiB,EAAE,EAAE,IAAI,EAAE,aAAa,EAAE;IAE1C,kEAAkE;IAClE,0BAA0B,EAAE;QAC1B,MAAM,EACJ,0HAA0H;KAC7H;IAED,mFAAmF;IACnF,UAAU,EAAE,EAAE,IAAI,EAAE,uBAAuB,EAAE;IAC7C,uBAAuB,EAAE,EAAE,IAAI,EAAE,iBAAiB,EAAE;IACpD,gBAAgB,EAAE,EAAE,IAAI,EAAE,wBAAwB,EAAE;IACpD,kBAAkB,EAAE,EAAE,IAAI,EAAE,qBAAqB,EAAE;IACnD,aAAa,EAAE,EAAE,IAAI,EAAE,sBAAsB,EAAE;IAC/C,mBAAmB,EAAE,EAAE,IAAI,EAAE,qBAAqB,EAAE;IACpD,wBAAwB,EAAE,EAAE,IAAI,EAAE,oBAAoB,EAAE;IACxD,eAAe,EAAE,EAAE,IAAI,EAAE,sBAAsB,EAAE;IACjD,kBAAkB,EAAE,EAAE,IAAI,EAAE,qBAAqB,EAAE;IACnD,mBAAmB,EAAE,EAAE,IAAI,EAAE,oBAAoB,EAAE;IACnD,eAAe,EAAE,EAAE,IAAI,EAAE,wBAAwB,EAAE;IACnD,mEAAmE;IACnE,sEAAsE;IACtE,iEAAiE;IACjE,YAAY,EAAE,EAAE,IAAI,EAAE,wBAAwB,EAAE;IAChD,UAAU,EAAE,EAAE,IAAI,EAAE,oBAAoB,EAAE;IAC1C,mBAAmB,EAAE,EAAE,IAAI,EAAE,uBAAuB,EAAE;IACtD,gBAAgB,EAAE,EAAE,IAAI,EAAE,mBAAmB,EAAE;IAC/C,cAAc,EAAE,EAAE,IAAI,EAAE,iBAAiB,EAAE;IAC3C,eAAe,EAAE,EAAE,IAAI,EAAE,kBAAkB,EAAE;IAC7C,sBAAsB,EAAE,EAAE,IAAI,EAAE,0BAA0B,EAAE;IAC5D,oBAAoB,EAAE,EAAE,IAAI,EAAE,wBAAwB,EAAE;IAExD,yFAAyF;IACzF,eAAe,EAAE;QACf,MAAM,EACJ,yKAAyK;KAC5K;IACD,aAAa,EAAE;QACb,MAAM,EACJ,qKAAqK;KACxK;IACD,YAAY,EAAE;QACZ,MAAM,EACJ,6IAA6I;KAChJ;IACD,aAAa,EAAE;QACb,MAAM,EACJ,mLAAmL;KACtL;IACD,aAAa,EAAE;QACb,MAAM,EACJ,+LAA+L;KAClM;IAED,mDAAmD;IACnD,YAAY,EAAE,EAAE,OAAO,EAAE,QAAQ,EAAE;IACnC,kBAAkB,EAAE,EAAE,OAAO,EAAE,QAAQ,EAAE;IACzC,iBAAiB,EAAE,EAAE,OAAO,EAAE,QAAQ,EAAE;IACxC,UAAU,EAAE,EAAE,OAAO,EAAE,QAAQ,EAAE;IACjC,eAAe,EAAE,EAAE,OAAO,EAAE,QAAQ,EAAE;IACtC,mBAAmB,EAAE,EAAE,OAAO,EAAE,QAAQ,EAAE;IAC1C,mBAAmB,EAAE,EAAE,OAAO,EAAE,QAAQ,EAAE;IAC1C,4BAA4B,EAAE,EAAE,OAAO,EAAE,QAAQ,EAAE;IACnD,kBAAkB,EAAE,EAAE,OAAO,EAAE,QAAQ,EAAE;IACzC,kBAAkB,EAAE,EAAE,OAAO,EAAE,QAAQ,EAAE;IACzC,iBAAiB,EAAE,EAAE,OAAO,EAAE,QAAQ,EAAE;IACxC,2BAA2B,EAAE,EAAE,OAAO,EAAE,QAAQ,EAAE;IAClD,kBAAkB,EAAE,EAAE,OAAO,EAAE,QAAQ,EAAE;IACzC,aAAa,EAAE,EAAE,OAAO,EAAE,QAAQ,EAAE;IACpC,mBAAmB,EAAE,EAAE,OAAO,EAAE,QAAQ,EAAE;IAC1C,qBAAqB,EAAE,EAAE,OAAO,EAAE,QAAQ,EAAE;IAC5C,aAAa,EAAE,EAAE,OAAO,EAAE,QAAQ,EAAE;IACpC,gBAAgB,EAAE,EAAE,OAAO,EAAE,QAAQ,EAAE;CACxC,CAAC;AA8BF,MAAM,CAAC,MAAM,mBAAmB,GAAiD;IAC/E,yEAAyE;IACzE,UAAU,EAAE,IAAI;IAChB,uBAAuB,EAAE,IAAI;IAC7B,gBAAgB,EAAE,IAAI;IACtB,kBAAkB,EAAE,IAAI;IACxB,aAAa,EAAE,IAAI;IACnB,eAAe,EAAE,IAAI;IACrB,mBAAmB,EAAE,IAAI;IACzB,wBAAwB,EAAE,IAAI;IAC9B,mBAAmB,EAAE,IAAI;IACzB,eAAe,EAAE,IAAI;IACrB,kBAAkB,EAAE,IAAI;IACxB,mBAAmB,EAAE,IAAI;IACzB,YAAY,EAAE,IAAI;IAClB,eAAe,EAAE,IAAI;IACrB,sBAAsB,EAAE,IAAI;IAC5B,eAAe,EAAE,IAAI;IAErB,4DAA4D;IAC5D,UAAU,EAAE,IAAI;IAChB,qBAAqB,EAAE,IAAI,EAAE,uEAAuE;IACpG,iBAAiB,EAAE,IAAI;IACvB,mBAAmB,EAAE,IAAI;IACzB,iBAAiB,EAAE,IAAI,EAAE,oEAAoE;IAC7F,iBAAiB,EAAE,IAAI;IACvB,YAAY,EAAE,IAAI,EAAE,kDAAkD;IACtE,gBAAgB,EAAE,IAAI;IACtB,cAAc,EAAE,IAAI;IACpB,eAAe,EAAE,IAAI,EAAE,wEAAwE;IAE/F,oFAAoF;IACpF,YAAY,EAAE,IAAI;IAClB,kBAAkB,EAAE,IAAI;IACxB,iBAAiB,EAAE,IAAI;IACvB,UAAU,EAAE,IAAI;IAChB,eAAe,EAAE,IAAI;IACrB,mBAAmB,EAAE,IAAI;IACzB,mBAAmB,EAAE,IAAI;IACzB,4BAA4B,EAAE,IAAI;IAClC,kBAAkB,EAAE,IAAI;IACxB,KAAK,EAAE,IAAI;IACX,oBAAoB,EAAE,IAAI;IAC1B,kBAAkB,EAAE,IAAI;IACxB,aAAa,EAAE,IAAI;IACnB,mBAAmB,EAAE,IAAI,EAAE,sDAAsD;IACjF,qBAAqB,EAAE,IAAI;IAC3B,aAAa,EAAE,IAAI,EAAE,4BAA4B;IACjD,qBAAqB,EAAE,IAAI;IAC3B,gBAAgB,EAAE,IAAI;IAEtB,+DAA+D;IAC/D,kBAAkB,EAAE,IAAI,EAAE,0DAA0D;IACpF,iBAAiB,EAAE,IAAI,EAAE,gGAAgG;IACzH,2BAA2B,EAAE,IAAI;IAEjC,0FAA0F;IAC1F,aAAa,EAAE;QACb,KAAK,EACH,8KAA8K;KACjL;IACD,0BAA0B,EAAE;QAC1B,KAAK,EACH,iIAAiI;KACpI;IACD,YAAY,EAAE;QACZ,KAAK,EACH,2IAA2I;KAC9I;IACD,eAAe,EAAE;QACf,KAAK,EACH,mIAAmI;KACtI;IACD,aAAa,EAAE;QACb,KAAK,EACH,+HAA+H;KAClI;IACD,aAAa,EAAE;QACb,KAAK,EACH,8IAA8I;KACjJ;CACF,CAAC;AAsDF,MAAM,CAAC,MAAM,WAAW,GAA6B;IACnD,iBAAiB;IACjB,aAAa;IACb,cAAc;CACf,CAAC;AASF,MAAM,CAAC,MAAM,iBAAiB,GAA+C;IAC3E,8EAA8E;IAC9E,kEAAkE;IAClE,mBAAmB,EAAE,EAAE,SAAS,EAAE,iBAAiB,EAAE,EAAE,wDAAwD;IAC/G,mBAAmB,EAAE,EAAE,SAAS,EAAE,iBAAiB,EAAE,EAAE,iFAAiF;IACxI,YAAY,EAAE,EAAE,SAAS,EAAE,iBAAiB,EAAE,EAAE,yHAAyH;IAEzK,iFAAiF;IACjF,eAAe,EAAE,EAAE,SAAS,EAAE,aAAa,EAAE,EAAE,cAAc;IAC7D,aAAa,EAAE,EAAE,SAAS,EAAE,aAAa,EAAE,EAAE,qBAAqB;IAClE,gBAAgB,EAAE,EAAE,SAAS,EAAE,aAAa,EAAE,EAAE,yBAAyB;IACzE,eAAe,EAAE,EAAE,SAAS,EAAE,aAAa,EAAE,EAAE,kIAAkI;IACjL,YAAY,EAAE,EAAE,SAAS,EAAE,aAAa,EAAE,EAAE,kEAAkE;IAE9G,qDAAqD;IACrD,gBAAgB,EAAE,EAAE,SAAS,EAAE,cAAc,EAAE,EAAE,4EAA4E;IAE7H,+EAA+E;IAC/E,iFAAiF;IACjF,aAAa,EAAE,KAAK,EAAE,sCAAsC;IAC5D,UAAU,EAAE,KAAK,EAAE,iDAAiD;IACpE,uBAAuB,EAAE,KAAK,EAAE,8FAA8F;IAC9H,kBAAkB,EAAE,KAAK,EAAE,8BAA8B;IACzD,aAAa,EAAE,KAAK,EAAE,+EAA+E;IACrG,eAAe,EAAE,KAAK,EAAE,sEAAsE;IAC9F,mBAAmB,EAAE,KAAK,EAAE,8EAA8E;IAC1G,eAAe,EAAE,KAAK,EAAE,6CAA6C;IACrE,sBAAsB,EAAE,KAAK,EAAE,yEAAyE;IACxG,mBAAmB,EAAE,KAAK,EAAE,8DAA8D;IAC1F,wBAAwB,EAAE,KAAK,EAAE,oCAAoC;IACrE,kBAAkB,EAAE,KAAK,EAAE,uFAAuF;IAClH,0BAA0B,EAAE,KAAK,EAAE,kEAAkE;IAErG,qFAAqF;IACrF,UAAU,EAAE,KAAK,EAAE,sCAAsC;IACzD,YAAY,EAAE,KAAK,EAAE,qDAAqD;IAC1E,eAAe,EAAE,KAAK,EAAE,uDAAuD;IAC/E,qBAAqB,EAAE,KAAK,EAAE,wEAAwE;IACtG,iBAAiB,EAAE,KAAK,EAAE,oDAAoD;IAC9E,aAAa,EAAE,KAAK,EAAE,oDAAoD;IAC1E,iBAAiB,EAAE,KAAK,EAAE,8BAA8B;IACxD,iBAAiB,EAAE,KAAK,EAAE,6BAA6B;IACvD,YAAY,EAAE,KAAK,EAAE,sCAAsC;IAC3D,gBAAgB,EAAE,KAAK,EAAE,oCAAoC;IAC7D,cAAc,EAAE,KAAK,EAAE,uBAAuB;IAC9C,eAAe,EAAE,KAAK,EAAE,qEAAqE;IAE7F,4FAA4F;IAC5F,kBAAkB,EAAE,KAAK,EAAE,4DAA4D;IACvF,iBAAiB,EAAE,KAAK,EAAE,0BAA0B;IACpD,UAAU,EAAE,KAAK,EAAE,yBAAyB;IAC5C,eAAe,EAAE,KAAK,EAAE,qBAAqB;IAC7C,mBAAmB,EAAE,KAAK,EAAE,8BAA8B;IAC1D,mBAAmB,EAAE,KAAK,EAAE,8BAA8B;IAC1D,4BAA4B,EAAE,KAAK,EAAE,2EAA2E;IAChH,kBAAkB,EAAE,KAAK,EAAE,oCAAoC;IAC/D,KAAK,EAAE,KAAK,EAAE,oCAAoC;IAClD,oBAAoB,EAAE,KAAK,EAAE,oCAAoC;IACjE,kBAAkB,EAAE,KAAK,EAAE,2CAA2C;IACtE,aAAa,EAAE,KAAK,EAAE,2CAA2C;IACjE,mBAAmB,EAAE,KAAK,EAAE,yCAAyC;IACrE,qBAAqB,EAAE,KAAK,EAAE,sCAAsC;IACpE,aAAa,EAAE,KAAK,EAAE,kCAAkC;IACxD,qBAAqB,EAAE,KAAK,EAAE,8CAA8C;IAC5E,kBAAkB,EAAE,KAAK,EAAE,gCAAgC;IAC3D,iBAAiB,EAAE,KAAK,EAAE,uCAAuC;IACjE,2BAA2B,EAAE,KAAK,EAAE,mCAAmC;CACxE,CAAC;AAqDF,MAAM,CAAC,MAAM,mBAAmB,GAAiD;IAC/E,iFAAiF;IACjF,iBAAiB,EAAE,EAAE,OAAO,EAAE,iBAAiB,EAAE,EAAE,2FAA2F;IAC9I,qBAAqB,EAAE,EAAE,OAAO,EAAE,iBAAiB,EAAE,EAAE,0DAA0D;IACjH,mBAAmB,EAAE,EAAE,OAAO,EAAE,iBAAiB,EAAE,EAAE,uEAAuE;IAC5H,eAAe,EAAE,EAAE,OAAO,EAAE,iBAAiB,EAAE,EAAE,iDAAiD;IAElG,gFAAgF;IAChF,eAAe,EAAE,EAAE,OAAO,EAAE,iBAAiB,EAAE,EAAE,iDAAiD;IAClG,YAAY,EAAE,EAAE,OAAO,EAAE,iBAAiB,EAAE,EAAE,4CAA4C;IAC1F,iBAAiB,EAAE,EAAE,OAAO,EAAE,iBAAiB,EAAE,EAAE,qCAAqC;IACxF,UAAU,EAAE,EAAE,OAAO,EAAE,iBAAiB,EAAE,EAAE,iCAAiC;IAC7E,gBAAgB,EAAE,EAAE,OAAO,EAAE,iBAAiB,EAAE,EAAE,sCAAsC;IACxF,kBAAkB,EAAE,EAAE,OAAO,EAAE,iBAAiB,EAAE,EAAE,2DAA2D;IAC/G,aAAa,EAAE,EAAE,OAAO,EAAE,iBAAiB,EAAE,EAAE,8BAA8B;IAC7E,mBAAmB,EAAE,EAAE,OAAO,EAAE,iBAAiB,EAAE,EAAE,4BAA4B;IACjF,wBAAwB,EAAE,EAAE,OAAO,EAAE,iBAAiB,EAAE,EAAE,oCAAoC;IAC9F,eAAe,EAAE,EAAE,OAAO,EAAE,iBAAiB,EAAE,EAAE,uBAAuB;IACxE,kBAAkB,EAAE,EAAE,OAAO,EAAE,iBAAiB,EAAE,EAAE,+BAA+B;IACnF,mBAAmB,EAAE,EAAE,OAAO,EAAE,iBAAiB,EAAE,EAAE,wCAAwC;IAC7F,eAAe,EAAE,EAAE,OAAO,EAAE,iBAAiB,EAAE,EAAE,mDAAmD;IACpG,YAAY,EAAE,EAAE,OAAO,EAAE,iBAAiB,EAAE,EAAE,8DAA8D;IAC5G,UAAU,EAAE,EAAE,OAAO,EAAE,iBAAiB,EAAE,EAAE,oCAAoC;IAChF,mBAAmB,EAAE,EAAE,OAAO,EAAE,iBAAiB,EAAE,EAAE,gCAAgC;IACrF,gBAAgB,EAAE,EAAE,OAAO,EAAE,iBAAiB,EAAE,EAAE,iCAAiC;IACnF,cAAc,EAAE,EAAE,OAAO,EAAE,iBAAiB,EAAE,EAAE,6BAA6B;IAC7E,eAAe,EAAE,EAAE,OAAO,EAAE,iBAAiB,EAAE,EAAE,0CAA0C;IAC3F,iBAAiB,EAAE,EAAE,OAAO,EAAE,iBAAiB,EAAE,EAAE,yCAAyC;IAE5F,+EAA+E;IAC/E,yEAAyE;IACzE,aAAa,EAAE;QACb,KAAK,EACH,yIAAyI;KAC5I;IACD,uBAAuB,EAAE;QACvB,KAAK,EACH,oIAAoI;KACvI;IACD,aAAa,EAAE;QACb,KAAK,EACH,gLAAgL;KACnL;IACD,0BAA0B,EAAE;QAC1B,KAAK,EACH,gLAAgL;KACnL;IACD,sBAAsB,EAAE;QACtB,KAAK,EACH,yJAAyJ;KAC5J;IACD,YAAY,EAAE;QACZ,KAAK,EACH,kJAAkJ;KACrJ;IACD,eAAe,EAAE;QACf,KAAK,EACH,uIAAuI;KAC1I;IACD,aAAa,EAAE;QACb,KAAK,EACH,0HAA0H;KAC7H;IACD,YAAY,EAAE;QACZ,KAAK,EACH,6IAA6I;KAChJ;IACD,kBAAkB,EAAE;QAClB,KAAK,EACH,0HAA0H;KAC7H;IACD,iBAAiB,EAAE;QACjB,KAAK,EACH,yIAAyI;KAC5I;IACD,UAAU,EAAE;QACV,KAAK,EACH,mHAAmH;KACtH;IACD,eAAe,EAAE;QACf,KAAK,EACH,uIAAuI;KAC1I;IACD,mBAAmB,EAAE;QACnB,KAAK,EACH,yHAAyH;KAC5H;IACD,mBAAmB,EAAE;QACnB,KAAK,EACH,kIAAkI;KACrI;IACD,4BAA4B,EAAE;QAC5B,KAAK,EACH,+HAA+H;KAClI;IACD,kBAAkB,EAAE;QAClB,KAAK,EACH,0HAA0H;KAC7H;IACD,KAAK,EAAE;QACL,KAAK,EACH,6IAA6I;KAChJ;IACD,oBAAoB,EAAE;QACpB,KAAK,EACH,8HAA8H;KACjI;IACD,kBAAkB,EAAE;QAClB,KAAK,EACH,sHAAsH;KACzH;IACD,aAAa,EAAE;QACb,KAAK,EACH,0IAA0I;KAC7I;IACD,mBAAmB,EAAE;QACnB,KAAK,EACH,kJAAkJ;KACrJ;IACD,qBAAqB,EAAE;QACrB,KAAK,EACH,kJAAkJ;KACrJ;IACD,aAAa,EAAE;QACb,KAAK,EACH,kIAAkI;KACrI;IACD,qBAAqB,EAAE;QACrB,KAAK,EACH,mHAAmH;KACtH;IACD,gBAAgB,EAAE;QAChB,KAAK,EACH,mKAAmK;KACtK;IACD,kBAAkB,EAAE;QAClB,KAAK,EACH,uGAAuG;KAC1G;IACD,iBAAiB,EAAE;QACjB,KAAK,EACH,oIAAoI;KACvI;IACD,2BAA2B,EAAE;QAC3B,KAAK,EACH,4HAA4H;KAC/H;CACF,CAAC"}
@@ -35,6 +35,11 @@ export interface OutboundContentDedupConfig {
35
35
  minLength?: number;
36
36
  /** Cap on remembered fingerprints per topic (ring). Default 50. */
37
37
  maxPerTopic?: number;
38
+ /** How long an in-flight `tryReserve` claim stays live before it auto-expires,
39
+ * so a leaked reservation (a send that neither recorded nor released — e.g. a
40
+ * crash mid-send) can never permanently suppress a fingerprint. Must comfortably
41
+ * exceed the outbound route's own send budget. Default 3min. */
42
+ reserveTtlMs?: number;
38
43
  }
39
44
  /** Normalize for fingerprinting: trim, collapse internal whitespace runs. Two
40
45
  * sends that differ only in trailing/whitespace are the same message. */
@@ -45,6 +50,15 @@ export declare class OutboundContentDedup {
45
50
  private readonly cfg;
46
51
  /** topicId -> (fingerprint -> last-sent epoch ms) */
47
52
  private readonly seen;
53
+ /** topicId -> (fingerprint -> reserved-at epoch ms). An IN-FLIGHT claim taken
54
+ * by `tryReserve` BEFORE a send starts and cleared by `record` (success) or
55
+ * `releaseReservation` (failure). This closes the check-then-send race that
56
+ * `isDuplicate` + record-after-success left open: under a server stall a send
57
+ * can be in flight for tens of seconds, and a second identical request that
58
+ * arrives in that window used to pass the duplicate check (nothing recorded
59
+ * yet) and send a second copy. Reservations auto-expire after `reserveTtlMs`
60
+ * so a leaked claim can never permanently suppress a fingerprint. */
61
+ private readonly reserved;
48
62
  private readonly now;
49
63
  /** Optional durable backing so a duplicate is caught ACROSS a restart / across
50
64
  * overlapping processes (the in-memory `seen` Map resets on restart — the exact
@@ -57,10 +71,29 @@ export declare class OutboundContentDedup {
57
71
  * window? Pure read — does NOT record. Returns false when disabled or the
58
72
  * text is below the length floor. */
59
73
  isDuplicate(topicId: number, text: string): boolean;
74
+ /** Atomically decide whether `text` may be sent to `topicId`, AND — if so —
75
+ * reserve it in-flight so a concurrent/rapid identical send is caught before
76
+ * the first one has recorded. Returns:
77
+ * - false ⇒ suppress: an identical text was sent within the window OR is
78
+ * currently in flight (a live reservation). The caller must NOT
79
+ * send and must NOT release (it doesn't own the reservation).
80
+ * - true ⇒ proceed: the caller now OWNS a reservation and MUST resolve it
81
+ * with `record` (on success) or `releaseReservation` (on failure).
82
+ * Below-floor text is never deduped → always returns true with no reservation
83
+ * (brief acks legitimately repeat). This supersedes the plain `isDuplicate`
84
+ * check at the send callsite to close the check-then-send race. */
85
+ tryReserve(topicId: number, text: string): boolean;
86
+ /** Release an in-flight reservation taken by `tryReserve` — call when the send
87
+ * FAILED, so the legitimate retry of the same text isn't wrongly suppressed. */
88
+ releaseReservation(topicId: number, text: string): void;
60
89
  /** Record that `text` was sent to `topicId` now. Call AFTER a successful send.
61
- * No-op for below-floor text (it can never be a dedup target anyway). */
90
+ * No-op for below-floor text (it can never be a dedup target anyway). Also
91
+ * clears any in-flight reservation for this fingerprint (the send resolved). */
62
92
  record(topicId: number, text: string): void;
63
93
  /** Drop expired entries, then enforce the per-topic ring cap (oldest-first). */
64
94
  private pruneTopic;
95
+ /** Drop expired reservations (past `reserveTtlMs`), then cap the ring. Keeps a
96
+ * leaked reservation from lingering and bounds memory the same way `seen` is. */
97
+ private pruneReserved;
65
98
  }
66
99
  //# sourceMappingURL=OutboundContentDedup.d.ts.map
@@ -1 +1 @@
1
- {"version":3,"file":"OutboundContentDedup.d.ts","sourceRoot":"","sources":["../../src/messaging/OutboundContentDedup.ts"],"names":[],"mappings":"AAAA;;;;;;;;;;;;;;;;;;;;;;;;;;;;GA4BG;AAEH,MAAM,WAAW,0BAA0B;IACzC,OAAO,CAAC,EAAE,OAAO,CAAC;IAClB,kFAAkF;IAClF,QAAQ,CAAC,EAAE,MAAM,CAAC;IAClB,iGAAiG;IACjG,SAAS,CAAC,EAAE,MAAM,CAAC;IACnB,mEAAmE;IACnE,WAAW,CAAC,EAAE,MAAM,CAAC;CACtB;AASD;0EAC0E;AAC1E,wBAAgB,iBAAiB,CAAC,IAAI,EAAE,MAAM,GAAG,MAAM,CAEtD;AAED,oEAAoE;AACpE,wBAAgB,WAAW,CAAC,IAAI,EAAE,MAAM,GAAG,MAAM,CAQhD;AAED,qBAAa,oBAAoB;IAC/B,OAAO,CAAC,QAAQ,CAAC,GAAG,CAAuC;IAC3D,qDAAqD;IACrD,OAAO,CAAC,QAAQ,CAAC,IAAI,CAA0C;IAC/D,OAAO,CAAC,QAAQ,CAAC,GAAG,CAAe;IACnC;;;;gFAI4E;IAC5E,OAAO,CAAC,QAAQ,CAAC,KAAK,CAA8D;gBAGlF,GAAG,GAAE,0BAA+B,EACpC,GAAG,GAAE,MAAM,MAAiB,EAC5B,KAAK,GAAE,OAAO,yBAAyB,EAAE,kBAAkB,GAAG,IAAW;IAO3E;;0CAEsC;IACtC,WAAW,CAAC,OAAO,EAAE,MAAM,EAAE,IAAI,EAAE,MAAM,GAAG,OAAO;IAiBnD;8EAC0E;IAC1E,MAAM,CAAC,OAAO,EAAE,MAAM,EAAE,IAAI,EAAE,MAAM,GAAG,IAAI;IAiB3C,gFAAgF;IAChF,OAAO,CAAC,UAAU;CAWnB"}
1
+ {"version":3,"file":"OutboundContentDedup.d.ts","sourceRoot":"","sources":["../../src/messaging/OutboundContentDedup.ts"],"names":[],"mappings":"AAAA;;;;;;;;;;;;;;;;;;;;;;;;;;;;GA4BG;AAEH,MAAM,WAAW,0BAA0B;IACzC,OAAO,CAAC,EAAE,OAAO,CAAC;IAClB,kFAAkF;IAClF,QAAQ,CAAC,EAAE,MAAM,CAAC;IAClB,iGAAiG;IACjG,SAAS,CAAC,EAAE,MAAM,CAAC;IACnB,mEAAmE;IACnE,WAAW,CAAC,EAAE,MAAM,CAAC;IACrB;;;qEAGiE;IACjE,YAAY,CAAC,EAAE,MAAM,CAAC;CACvB;AAUD;0EAC0E;AAC1E,wBAAgB,iBAAiB,CAAC,IAAI,EAAE,MAAM,GAAG,MAAM,CAEtD;AAED,oEAAoE;AACpE,wBAAgB,WAAW,CAAC,IAAI,EAAE,MAAM,GAAG,MAAM,CAQhD;AAED,qBAAa,oBAAoB;IAC/B,OAAO,CAAC,QAAQ,CAAC,GAAG,CAAuC;IAC3D,qDAAqD;IACrD,OAAO,CAAC,QAAQ,CAAC,IAAI,CAA0C;IAC/D;;;;;;;0EAOsE;IACtE,OAAO,CAAC,QAAQ,CAAC,QAAQ,CAA0C;IACnE,OAAO,CAAC,QAAQ,CAAC,GAAG,CAAe;IACnC;;;;gFAI4E;IAC5E,OAAO,CAAC,QAAQ,CAAC,KAAK,CAA8D;gBAGlF,GAAG,GAAE,0BAA+B,EACpC,GAAG,GAAE,MAAM,MAAiB,EAC5B,KAAK,GAAE,OAAO,yBAAyB,EAAE,kBAAkB,GAAG,IAAW;IAO3E;;0CAEsC;IACtC,WAAW,CAAC,OAAO,EAAE,MAAM,EAAE,IAAI,EAAE,MAAM,GAAG,OAAO;IAiBnD;;;;;;;;;;wEAUoE;IACpE,UAAU,CAAC,OAAO,EAAE,MAAM,EAAE,IAAI,EAAE,MAAM,GAAG,OAAO;IAuBlD;qFACiF;IACjF,kBAAkB,CAAC,OAAO,EAAE,MAAM,EAAE,IAAI,EAAE,MAAM,GAAG,IAAI;IAMvD;;qFAEiF;IACjF,MAAM,CAAC,OAAO,EAAE,MAAM,EAAE,IAAI,EAAE,MAAM,GAAG,IAAI;IAoB3C,gFAAgF;IAChF,OAAO,CAAC,UAAU;IAYlB;sFACkF;IAClF,OAAO,CAAC,aAAa;CAWtB"}
@@ -32,6 +32,7 @@ const DEFAULTS = {
32
32
  windowMs: 15 * 60 * 1000,
33
33
  minLength: 40,
34
34
  maxPerTopic: 50,
35
+ reserveTtlMs: 3 * 60 * 1000,
35
36
  };
36
37
  /** Normalize for fingerprinting: trim, collapse internal whitespace runs. Two
37
38
  * sends that differ only in trailing/whitespace are the same message. */
@@ -52,6 +53,15 @@ export class OutboundContentDedup {
52
53
  cfg;
53
54
  /** topicId -> (fingerprint -> last-sent epoch ms) */
54
55
  seen = new Map();
56
+ /** topicId -> (fingerprint -> reserved-at epoch ms). An IN-FLIGHT claim taken
57
+ * by `tryReserve` BEFORE a send starts and cleared by `record` (success) or
58
+ * `releaseReservation` (failure). This closes the check-then-send race that
59
+ * `isDuplicate` + record-after-success left open: under a server stall a send
60
+ * can be in flight for tens of seconds, and a second identical request that
61
+ * arrives in that window used to pass the duplicate check (nothing recorded
62
+ * yet) and send a second copy. Reservations auto-expire after `reserveTtlMs`
63
+ * so a leaked claim can never permanently suppress a fingerprint. */
64
+ reserved = new Map();
55
65
  now;
56
66
  /** Optional durable backing so a duplicate is caught ACROSS a restart / across
57
67
  * overlapping processes (the in-memory `seen` Map resets on restart — the exact
@@ -86,8 +96,54 @@ export class OutboundContentDedup {
86
96
  }
87
97
  return false;
88
98
  }
99
+ /** Atomically decide whether `text` may be sent to `topicId`, AND — if so —
100
+ * reserve it in-flight so a concurrent/rapid identical send is caught before
101
+ * the first one has recorded. Returns:
102
+ * - false ⇒ suppress: an identical text was sent within the window OR is
103
+ * currently in flight (a live reservation). The caller must NOT
104
+ * send and must NOT release (it doesn't own the reservation).
105
+ * - true ⇒ proceed: the caller now OWNS a reservation and MUST resolve it
106
+ * with `record` (on success) or `releaseReservation` (on failure).
107
+ * Below-floor text is never deduped → always returns true with no reservation
108
+ * (brief acks legitimately repeat). This supersedes the plain `isDuplicate`
109
+ * check at the send callsite to close the check-then-send race. */
110
+ tryReserve(topicId, text) {
111
+ if (!this.cfg.enabled)
112
+ return true;
113
+ const norm = normalizeForDedup(text);
114
+ if (norm.length < this.cfg.minLength)
115
+ return true;
116
+ const fp = fingerprint(norm);
117
+ // Already sent within the window (in-memory or durable) → duplicate.
118
+ if (this.isDuplicate(topicId, text))
119
+ return false;
120
+ // Currently in flight (a live, non-expired reservation) → duplicate.
121
+ const now = this.now();
122
+ const resMap = this.reserved.get(topicId);
123
+ const reservedAt = resMap?.get(fp);
124
+ if (reservedAt !== undefined && now - reservedAt < this.cfg.reserveTtlMs)
125
+ return false;
126
+ // Claim it.
127
+ let topicRes = this.reserved.get(topicId);
128
+ if (!topicRes) {
129
+ topicRes = new Map();
130
+ this.reserved.set(topicId, topicRes);
131
+ }
132
+ topicRes.set(fp, now);
133
+ this.pruneReserved(topicRes);
134
+ return true;
135
+ }
136
+ /** Release an in-flight reservation taken by `tryReserve` — call when the send
137
+ * FAILED, so the legitimate retry of the same text isn't wrongly suppressed. */
138
+ releaseReservation(topicId, text) {
139
+ const norm = normalizeForDedup(text);
140
+ if (norm.length < this.cfg.minLength)
141
+ return;
142
+ this.reserved.get(topicId)?.delete(fingerprint(norm));
143
+ }
89
144
  /** Record that `text` was sent to `topicId` now. Call AFTER a successful send.
90
- * No-op for below-floor text (it can never be a dedup target anyway). */
145
+ * No-op for below-floor text (it can never be a dedup target anyway). Also
146
+ * clears any in-flight reservation for this fingerprint (the send resolved). */
91
147
  record(topicId, text) {
92
148
  if (!this.cfg.enabled)
93
149
  return;
@@ -103,6 +159,9 @@ export class OutboundContentDedup {
103
159
  const fp = fingerprint(norm);
104
160
  topicMap.set(fp, now);
105
161
  this.pruneTopic(topicMap);
162
+ // The send resolved → drop the in-flight reservation; the `seen` record now
163
+ // carries the (longer) window suppression.
164
+ this.reserved.get(topicId)?.delete(fp);
106
165
  // Mirror to the durable store so a post-restart process sees it. Fail-open.
107
166
  this.store?.record(topicId, fp, now);
108
167
  }
@@ -120,5 +179,20 @@ export class OutboundContentDedup {
120
179
  topicMap.delete(oldest);
121
180
  }
122
181
  }
182
+ /** Drop expired reservations (past `reserveTtlMs`), then cap the ring. Keeps a
183
+ * leaked reservation from lingering and bounds memory the same way `seen` is. */
184
+ pruneReserved(resMap) {
185
+ const cutoff = this.now() - this.cfg.reserveTtlMs;
186
+ for (const [fp, at] of resMap) {
187
+ if (at < cutoff)
188
+ resMap.delete(fp);
189
+ }
190
+ while (resMap.size > this.cfg.maxPerTopic) {
191
+ const oldest = resMap.keys().next().value; // insertion-ordered
192
+ if (oldest === undefined)
193
+ break;
194
+ resMap.delete(oldest);
195
+ }
196
+ }
123
197
  }
124
198
  //# sourceMappingURL=OutboundContentDedup.js.map
@@ -1 +1 @@
1
- {"version":3,"file":"OutboundContentDedup.js","sourceRoot":"","sources":["../../src/messaging/OutboundContentDedup.ts"],"names":[],"mappings":"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"}
1
+ {"version":3,"file":"OutboundContentDedup.js","sourceRoot":"","sources":["../../src/messaging/OutboundContentDedup.ts"],"names":[],"mappings":"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"}