agentfootprint 9.94.3 → 9.96.1

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 (156) hide show
  1. package/CHANGELOG.md +48 -0
  2. package/CLAUDE.md +4 -1
  3. package/dist/answer-validation/evidence.js +121 -0
  4. package/dist/answer-validation/evidence.js.map +1 -0
  5. package/dist/answer-validation/index.js +10 -0
  6. package/dist/answer-validation/index.js.map +1 -0
  7. package/dist/answer-validation/types.js +24 -0
  8. package/dist/answer-validation/types.js.map +1 -0
  9. package/dist/answer-validation/validate.js +326 -0
  10. package/dist/answer-validation/validate.js.map +1 -0
  11. package/dist/core/Agent.js +93 -3
  12. package/dist/core/Agent.js.map +1 -1
  13. package/dist/core/agent/AgentBuilder.js +27 -1
  14. package/dist/core/agent/AgentBuilder.js.map +1 -1
  15. package/dist/core/agent/buildAgentChart.js +17 -2
  16. package/dist/core/agent/buildAgentChart.js.map +1 -1
  17. package/dist/core/agent/buildDynamicAgentChart.js +27 -2
  18. package/dist/core/agent/buildDynamicAgentChart.js.map +1 -1
  19. package/dist/core/agent/evidence/gate.js +13 -1
  20. package/dist/core/agent/evidence/gate.js.map +1 -1
  21. package/dist/core/agent/evidence/recovery.js +75 -0
  22. package/dist/core/agent/evidence/recovery.js.map +1 -0
  23. package/dist/core/agent/outputEnforcement.js.map +1 -1
  24. package/dist/core/agent/stages/answerValidation.js +57 -0
  25. package/dist/core/agent/stages/answerValidation.js.map +1 -0
  26. package/dist/core/agent/stages/breakFinal.js +11 -1
  27. package/dist/core/agent/stages/breakFinal.js.map +1 -1
  28. package/dist/core/agent/stages/callLLM.js +31 -8
  29. package/dist/core/agent/stages/callLLM.js.map +1 -1
  30. package/dist/core/agent/stages/evidenceRecheck.js +12 -22
  31. package/dist/core/agent/stages/evidenceRecheck.js.map +1 -1
  32. package/dist/core/agent/stages/prepareFinal.js +35 -2
  33. package/dist/core/agent/stages/prepareFinal.js.map +1 -1
  34. package/dist/core/agent/stages/route.js +9 -5
  35. package/dist/core/agent/stages/route.js.map +1 -1
  36. package/dist/core/agent/stages/seed.js +6 -1
  37. package/dist/core/agent/stages/seed.js.map +1 -1
  38. package/dist/core/runCheckpoint.js +22 -1
  39. package/dist/core/runCheckpoint.js.map +1 -1
  40. package/dist/esm/answer-validation/evidence.d.ts +12 -0
  41. package/dist/esm/answer-validation/evidence.js +117 -0
  42. package/dist/esm/answer-validation/evidence.js.map +1 -0
  43. package/dist/esm/answer-validation/index.d.ts +3 -0
  44. package/dist/esm/answer-validation/index.js +4 -0
  45. package/dist/esm/answer-validation/index.js.map +1 -0
  46. package/dist/esm/answer-validation/types.d.ts +94 -0
  47. package/dist/esm/answer-validation/types.js +20 -0
  48. package/dist/esm/answer-validation/types.js.map +1 -0
  49. package/dist/esm/answer-validation/validate.d.ts +15 -0
  50. package/dist/esm/answer-validation/validate.js +321 -0
  51. package/dist/esm/answer-validation/validate.js.map +1 -0
  52. package/dist/esm/core/Agent.d.ts +10 -1
  53. package/dist/esm/core/Agent.js +93 -3
  54. package/dist/esm/core/Agent.js.map +1 -1
  55. package/dist/esm/core/agent/AgentBuilder.d.ts +11 -0
  56. package/dist/esm/core/agent/AgentBuilder.js +27 -1
  57. package/dist/esm/core/agent/AgentBuilder.js.map +1 -1
  58. package/dist/esm/core/agent/buildAgentChart.d.ts +2 -0
  59. package/dist/esm/core/agent/buildAgentChart.js +19 -4
  60. package/dist/esm/core/agent/buildAgentChart.js.map +1 -1
  61. package/dist/esm/core/agent/buildDynamicAgentChart.js +29 -4
  62. package/dist/esm/core/agent/buildDynamicAgentChart.js.map +1 -1
  63. package/dist/esm/core/agent/evidence/gate.js +13 -1
  64. package/dist/esm/core/agent/evidence/gate.js.map +1 -1
  65. package/dist/esm/core/agent/evidence/index.d.ts +1 -1
  66. package/dist/esm/core/agent/evidence/recovery.d.ts +21 -0
  67. package/dist/esm/core/agent/evidence/recovery.js +69 -0
  68. package/dist/esm/core/agent/evidence/recovery.js.map +1 -0
  69. package/dist/esm/core/agent/evidence/types.d.ts +30 -0
  70. package/dist/esm/core/agent/outputEnforcement.d.ts +2 -0
  71. package/dist/esm/core/agent/outputEnforcement.js.map +1 -1
  72. package/dist/esm/core/agent/stages/answerValidation.d.ts +10 -0
  73. package/dist/esm/core/agent/stages/answerValidation.js +53 -0
  74. package/dist/esm/core/agent/stages/answerValidation.js.map +1 -0
  75. package/dist/esm/core/agent/stages/breakFinal.d.ts +6 -0
  76. package/dist/esm/core/agent/stages/breakFinal.js +9 -0
  77. package/dist/esm/core/agent/stages/breakFinal.js.map +1 -1
  78. package/dist/esm/core/agent/stages/callLLM.d.ts +4 -0
  79. package/dist/esm/core/agent/stages/callLLM.js +31 -8
  80. package/dist/esm/core/agent/stages/callLLM.js.map +1 -1
  81. package/dist/esm/core/agent/stages/evidenceRecheck.d.ts +3 -6
  82. package/dist/esm/core/agent/stages/evidenceRecheck.js +13 -23
  83. package/dist/esm/core/agent/stages/evidenceRecheck.js.map +1 -1
  84. package/dist/esm/core/agent/stages/prepareFinal.d.ts +7 -0
  85. package/dist/esm/core/agent/stages/prepareFinal.js +33 -1
  86. package/dist/esm/core/agent/stages/prepareFinal.js.map +1 -1
  87. package/dist/esm/core/agent/stages/route.js +9 -5
  88. package/dist/esm/core/agent/stages/route.js.map +1 -1
  89. package/dist/esm/core/agent/stages/seed.d.ts +3 -0
  90. package/dist/esm/core/agent/stages/seed.js +6 -1
  91. package/dist/esm/core/agent/stages/seed.js.map +1 -1
  92. package/dist/esm/core/agent/types.d.ts +12 -1
  93. package/dist/esm/core/runCheckpoint.d.ts +17 -1
  94. package/dist/esm/core/runCheckpoint.js +22 -1
  95. package/dist/esm/core/runCheckpoint.js.map +1 -1
  96. package/dist/esm/events/types.d.ts +1 -1
  97. package/dist/esm/index.d.ts +2 -1
  98. package/dist/esm/index.js +2 -0
  99. package/dist/esm/index.js.map +1 -1
  100. package/dist/esm/lib/time-travel/servedView.js +5 -2
  101. package/dist/esm/lib/time-travel/servedView.js.map +1 -1
  102. package/dist/esm/recorders/core/contextEngineering.js +1 -0
  103. package/dist/esm/recorders/core/contextEngineering.js.map +1 -1
  104. package/dist/index.js +4 -1
  105. package/dist/index.js.map +1 -1
  106. package/dist/lib/time-travel/servedView.js +5 -2
  107. package/dist/lib/time-travel/servedView.js.map +1 -1
  108. package/dist/recorders/core/contextEngineering.js +1 -0
  109. package/dist/recorders/core/contextEngineering.js.map +1 -1
  110. package/dist/types/answer-validation/evidence.d.ts +13 -0
  111. package/dist/types/answer-validation/evidence.d.ts.map +1 -0
  112. package/dist/types/answer-validation/index.d.ts +4 -0
  113. package/dist/types/answer-validation/index.d.ts.map +1 -0
  114. package/dist/types/answer-validation/types.d.ts +95 -0
  115. package/dist/types/answer-validation/types.d.ts.map +1 -0
  116. package/dist/types/answer-validation/validate.d.ts +16 -0
  117. package/dist/types/answer-validation/validate.d.ts.map +1 -0
  118. package/dist/types/core/Agent.d.ts +10 -1
  119. package/dist/types/core/Agent.d.ts.map +1 -1
  120. package/dist/types/core/agent/AgentBuilder.d.ts +11 -0
  121. package/dist/types/core/agent/AgentBuilder.d.ts.map +1 -1
  122. package/dist/types/core/agent/buildAgentChart.d.ts +2 -0
  123. package/dist/types/core/agent/buildAgentChart.d.ts.map +1 -1
  124. package/dist/types/core/agent/buildDynamicAgentChart.d.ts.map +1 -1
  125. package/dist/types/core/agent/evidence/gate.d.ts.map +1 -1
  126. package/dist/types/core/agent/evidence/index.d.ts +1 -1
  127. package/dist/types/core/agent/evidence/index.d.ts.map +1 -1
  128. package/dist/types/core/agent/evidence/recovery.d.ts +22 -0
  129. package/dist/types/core/agent/evidence/recovery.d.ts.map +1 -0
  130. package/dist/types/core/agent/evidence/types.d.ts +30 -0
  131. package/dist/types/core/agent/evidence/types.d.ts.map +1 -1
  132. package/dist/types/core/agent/outputEnforcement.d.ts +2 -0
  133. package/dist/types/core/agent/outputEnforcement.d.ts.map +1 -1
  134. package/dist/types/core/agent/stages/answerValidation.d.ts +11 -0
  135. package/dist/types/core/agent/stages/answerValidation.d.ts.map +1 -0
  136. package/dist/types/core/agent/stages/breakFinal.d.ts +6 -0
  137. package/dist/types/core/agent/stages/breakFinal.d.ts.map +1 -1
  138. package/dist/types/core/agent/stages/callLLM.d.ts +4 -0
  139. package/dist/types/core/agent/stages/callLLM.d.ts.map +1 -1
  140. package/dist/types/core/agent/stages/evidenceRecheck.d.ts +3 -6
  141. package/dist/types/core/agent/stages/evidenceRecheck.d.ts.map +1 -1
  142. package/dist/types/core/agent/stages/prepareFinal.d.ts +7 -0
  143. package/dist/types/core/agent/stages/prepareFinal.d.ts.map +1 -1
  144. package/dist/types/core/agent/stages/seed.d.ts +3 -0
  145. package/dist/types/core/agent/stages/seed.d.ts.map +1 -1
  146. package/dist/types/core/agent/types.d.ts +12 -1
  147. package/dist/types/core/agent/types.d.ts.map +1 -1
  148. package/dist/types/core/runCheckpoint.d.ts +17 -1
  149. package/dist/types/core/runCheckpoint.d.ts.map +1 -1
  150. package/dist/types/events/types.d.ts +1 -1
  151. package/dist/types/events/types.d.ts.map +1 -1
  152. package/dist/types/index.d.ts +2 -1
  153. package/dist/types/index.d.ts.map +1 -1
  154. package/dist/types/lib/time-travel/servedView.d.ts.map +1 -1
  155. package/dist/types/recorders/core/contextEngineering.d.ts.map +1 -1
  156. package/package.json +1 -1
package/CHANGELOG.md CHANGED
@@ -5,6 +5,54 @@ All notable changes to this project will be documented in this file.
5
5
  The format is based on [Keep a Changelog](https://keepachangelog.com/en/1.1.0/),
6
6
  and this project adheres to [Semantic Versioning](https://semver.org/spec/v2.0.0.html).
7
7
 
8
+ ## [9.96.1] - 2026-09-13
9
+
10
+ ### Fixed
11
+
12
+ - Restore publication within the existing documentation site budget: keep image
13
+ originals outside the static export and prune duplicate internal error pages
14
+ only when both public 404 copies match. Public documentation remains available.
15
+ - Includes the evidence recovery option and request-only correction behavior from
16
+ 9.96.0, whose npm publication was blocked by that site budget.
17
+
18
+ ## [9.96.0] - 2026-09-13
19
+
20
+ ### Added
21
+
22
+ - Optional `recoveryInstruction` on `.namesAndNumbersFromEvidence()` supplies
23
+ bounded text or a synchronous callback for the existing evidence repair.
24
+ Applications can ask for missing context without suggesting invented values.
25
+
26
+ ### Changed
27
+
28
+ - Evidence repair is delivered as request-only system context, with the rejected
29
+ draft quoted as untrusted data, instead of synthetic conversation turns.
30
+ Token checks, postures and the one-revision limit remain unchanged. This is
31
+ lexical checking, not proof of question interpretation or claim semantics.
32
+
33
+ ## [9.95.0] - 2026-09-12
34
+
35
+ ### Added
36
+
37
+ - Opt-in `.answerValidation()` checks schema-parsed JSON against host-owned
38
+ evidence before final answer delivery. Enforce mode refuses failed or
39
+ unverified checks; observe mode records them without refusing. Scoped,
40
+ read-only artifact resolution has per-validation read, byte and time limits.
41
+ Reports separate actual checks from unavailable evidence and artifact reads.
42
+ - Configured agents withhold draft tokens and deliver the checked canonical
43
+ value consistently through `run`, `runTyped`, final events and memory.
44
+ Output fallback and coverage suffix combinations are explicitly refused in
45
+ this version; automatic repair and free-text entailment are outside scope.
46
+
47
+ ## [9.94.4] - 2026-09-12
48
+
49
+ ### Documentation
50
+
51
+ - Propose optional answer validation against referenced evidence in
52
+ [proposal 013](docs/proposals/013-answer-validation.md), with executable tests
53
+ of current claim-checking and output-enforcement boundaries. This is a
54
+ feature request; it introduces no runtime API or validation guarantee.
55
+
8
56
  ## [9.94.3] - 2026-09-12
9
57
 
10
58
  ### Fixed — two behaviours that moved with footprintjs 9.22.0+ and 9.24.0, found by running the suite on them
package/CLAUDE.md CHANGED
@@ -17,6 +17,8 @@ not in this table, search `src/index.ts` for the nearest noun before writing cod
17
17
 
18
18
  | If you are about to build… | It is | Where | Since |
19
19
  |---|---|---|---|
20
+ | guiding an evidence repair to ask for missing context without inventing values | `recoveryInstruction` + `EvidenceRecoveryContext` | `src/core/agent/evidence/` | 9.96.0 |
21
+ | checking a typed final answer against scoped evidence before streaming or memory delivery — optional host-authored checks with enforce/observe modes, canonical JSON and bounded read-only artifacts | `answerValidation` + `AnswerValidationError` | `src/answer-validation/` | 9.95.0 |
20
22
  | turning a written operational procedure (a runbook, a triage playbook) into ONE agent tool whose every answer is EVIDENCE — coverage folded up from the inner tools it calls, rule name+version, verdict rows with GENERATED meanings, and the recorded walk as an artifact ticket, never bytes | `runbookAsTool` — dials: `procedure` (factory, invoked per call with `ctx.tools`) + `resultKind` (`'verdict/*'` arms the rowset projection; anything else ships spine + the chart's `report`) + `rules {name, version}` (default absent ⇒ `rule_version: 'undeclared'`) + `verdicts {decider, maxRows}` (default 50; `verdict_meanings` = statically declared branches + this run's rule labels + the DEFAULT branch's label, which reaches evidence only when the chart calls `decide(s, rules, {branch, label})` — fp ≥9.16.1, the default is chosen by NO rule so nothing else can name it, and inside a generated fan-out branch the static walk is blind too; an undeclared or blank label stays ABSENT from the map, never invented from a branch id, and there is deliberately NO caller-supplied meanings map) + `presentation` (`'prose'` default = ship `table` + `VERDICT_RENDER_NOTE` "output it VERBATIM"; `'panel'` = the HOST renders the rowset, so NO `table` key at all + `PANEL_RENDER_NOTE` "the rows are already on the reader's screen — do not reproduce them"; the rowset half is byte-identical across modes, `table` stays RESERVED in both, an unknown value THROWS at definition) + `walk {cap, recording}` (cap default 500; over-cap ⇒ control-flow projection, declared · `recording: true` or `{label, maxBytes}`, default OFF — ALSO files the inner chart's own `{snapshot, events, structure}` under `recording/run` and puts its ref on the spine as `walk.recording_ref`, because the ROW projection cannot be drawn; snapshot read from the REDACTED mirror so one `redact` means the same for both; over `maxBytes` (`DEFAULT_RECORDING_MAX_BYTES` = 5,000,000) it is REFUSED not truncated; every absence — no store / over size / unserializable / store threw — is STATED in `walk.recording_note`, and the four `recording_*` fields are absent entirely when the dial is off) + `composedOf` (drift-checked at agent BUILD) + kept `recorders`/`keepRecord`/`keepRecordLimit`/`redact`; reserved state keys `verdicts`/`coverage`/`report` (the `report` bag lands BESIDE the spine, never over it — a report field spelling `af_coverage`/`af_provenance`/`rule_version`/`walk`/`report_note` or a live projection key is discarded and NAMED in `result.report_note`; precedence is explicit in `report.ts`, never spread order); inner `absent()` passes through VERBATIM unless the call said `allowAbsent`; walk kind `recording/chart-walk` + `walk_segment` discriminant | `src/core/runbook/` | 9.76.0, recording 9.79.0 |
21
23
  | speaking MCP from a BROWSER — the SDK is browser-clean (its client + streamableHttp bundle at `platform:'browser'` with zero `node:` edges and never pull in `client/stdio.js`); the one barrier was that `lazyRequire` gets CALLED there, so the fix is to let the caller supply what the loader would have found | `mcpClient({ sdk })` (`McpSdk` = the two SDK modules you imported statically; the library STILL builds the transport, so headers/fetch/gateway vending/`retryOnThrottle`/`_meta` all keep working) · `mcpClient({ connection })` (`McpConnection` = listTools/callTool/close, deliberately NO `connect` — you already did; the only arm that reaches the SDK's `jsonSchemaValidator`, i.e. CSP) + `McpConnectionOptions`; `refuseConflictingOptions` REFUSES at construction every option a transport would have consumed, naming where it moved (a knob naming a behaviour that no longer happens is the defect class); `transportUrl` resolves a relative `url` against `globalThis.location.href` (absolute takes the identical branch, Node refuses by name); `sdkLoadFailure` classifies the seven load sites so a browser is never told to install a package it has (resolution failure ⇒ byte-identical historical message); `retryingFetch` + `ThrottleFetch` promoted out of `@internal` so the connection arm keeps its 429 handling. stdio keeps `lazyRequire` FOREVER — it spawns a subprocess. ZERO packaging change: no subpath, no `browser` condition (TypeScript is blind to it), peer stays optional (no literal dynamic `import()`). Fenced by `test/lib/mcp/browserGraph.test.ts` | `src/lib/mcp/` | 9.81.0 |
22
24
  | calling ANOTHER registered tool from inside a tool's `execute` — composition over the agent's own dispatch map instead of importing the module and building a second query stack | `agentToolDispatch` + `ctx.tools` (ToolDispatch has/call) — sees static and skill-carried tools, NEVER ToolProvider-delivered ones (no build-time list, the 9.72.0 caveat); inner calls get the outer facts with hasArtifacts false and a derived toolCallId, `needs` resolved fail-closed non-interactively, `checkIn` and `wants` tools refused by name, no nested dispatch; declare ingredients via `composedOf` (and `gates` for a pausing procedure) — both travel MCP `_meta` | `src/core/agent/toolDispatch.ts` | 9.76.0 |
@@ -85,6 +87,7 @@ Entry points — FIFTEEN doors, and `package.json` `exports` is exhaustive, so a
85
87
 
86
88
  | src/ | one job |
87
89
  |---|---|
90
+ | answer-validation/ | optional final-answer contract, scoped bounded artifact reads, canonical JSON and explicit check dispositions; the Agent route owns invocation and final capture owns delivery |
88
91
  | core/ | primitives: Agent.ts (ReAct runner), LLMCall.ts, RunnerBase.ts (dispatcher + attach + enable.*), tools.ts (defineTool), pause.ts, runCheckpoint.ts |
89
92
  | core/agent/evidence/ | (9.35.0) the evidence gate — `.namesAndNumbersFromEvidence()`. Pure + deterministic BY LAW (no model, no embedding: a guard that needed a bigger model to police a smaller one inverts the library's thesis). normalize (one spelling per value, both sides) → extract (which tokens are DATA — conservative, justified clause by clause) → evidenceIndex (STRUCTURAL walk of `role:'tool'` results; the exempt corpus is user message + user/system turns + `systemPromptInjections`, MINUS the library's own frames — see frames.ts, the laundering bug) → gate (resolve/judge/sentences) → errors (`UnsupportedValuesError`). Fabrication detector, NOT a correctness judge: a false claim built from real values passes |
90
93
  | core/agent/coverage/ | the two FIELD-INVENTED result primitives. `absent()` = an absence that names its own coverage (checked / not checked / cannot cover) and says a retry returns the same; `coverage(result, …)` = the ledger of what a clean verdict does NOT rule out. Both RECOGNIZED (reserved `af_absent`/`af_coverage` keys, the effects-envelope strictness law), not conventions. Pure; the moving parts are `declareCoverage` in stages/toolCalls.ts, the whitelist in evidence/evidenceIndex.ts, and `prepareFinalWithLimitsStage` |
@@ -142,7 +145,7 @@ Traps: `src/observability/` holds the finder IMPLEMENTATIONS (canonical home; `d
142
145
  - **Recordings as artifacts (9.26.0)**: `artifacts: { store, recordings: true | { label } }`. `Agent.startRunRecording()` calls the SAME `recordRun` (before `createExecutor` — `attach()` collects for the executor not yet built); `fileRunRecording` mints AFTER `finalizeResult`, awaited, every failure contained to `artifacts.refused`. Pure half in artifacts/recordingArtifact.ts; payload is the recording's JSON TEXT (a live snapshot handed to an in-process store would be a live view into a finished run). No new wire op — `artifact-get` serves it.
143
146
  - **Code staging-in (9.26.0)**: `CodeSession.stageInputs?(inputs) → StagedCodeInput[]` — OPTIONAL, feature-detected via `canStageCodeInputs`, and its contract is TWO promises: the payloads are readable at the returned paths, AND every later `execute` exposes the manifest as `STAGED_INPUTS_ENV` (`AF_STAGED_INPUTS`, `name → path`). `CodeInput.name` is the MANIFEST KEY (the wants arg name, so a static description can name it) and `fileName` is the on-disk name — separate fields so the two cannot drift. `codeRunnerTool({ wants })` composes the schema properties + the description clause and refuses BY NAME on a non-staging runner. Implemented by localCodeRunner only.
144
147
  - **Repeated-call nudge (9.26.0)**: `core/agent/repeatedCall.ts` (pure `noteRepeatedCall` + `repeatedCallLedgers()`) + the ONE batch-loop hook in toolCalls. Fingerprints (FNV-1a) of stable-stringified args and the tool's OWN delivered result — never values. **The counters are NOT tracked state**: they live in a bounded run-keyed map held by `buildToolCallsHandler` and keyed by `deps.currentRun().runId`, so a turn that repeats nothing is byte-identical in state, commit log, narrative and recordings (a scope key would have changed all four for every agent that merely upgraded); the repeat itself rides `agentfootprint.tools.repeated_call`, the emit channel per-attempt facts belong on. A resume mints a new runId ⇒ counting restarts. Fires at the SECOND identical landing, once. `AgentOptions.repeatedCallNudge: false` disables (threaded value-conditionally; ON is the default). Deliberately NOT applied on the pause-resume dispatch paths.
145
- - **Evidence gate (9.35.0)** — `.namesAndNumbersFromEvidence({ posture, shapes, exempt, minDigits })`: every name/number in the final answer must appear in a `role:'tool'` result. Postures reuse the routing VOCABULARY (`assist`|`guard`|`rails`) as a SEPARATE option — routing authority ≠ evidence discipline, and overloading `skillGraphCascade.strictness` would deny "strict routing, loose evidence". Wiring is the stepNudge blast radius verbatim: `ResolvedEvidenceGate` (builder-resolved, refusals at the CALL SITE) → Agent ctor trailing param → `buildRouteDeciderStage`'s 4th arg (`judgeEvidence` runs LAST of the three judges — schema > steps > evidence — and NOT on a denied or schema-exhausted answer) → `evidenceRecheckStage` branch (`{loopTo}`, mounted only for a revising posture) → `STAGE_IDS.EVIDENCE_RECHECK` + BOUNDARY_LOCAL_IDS + milestoneFor. TWO deps flags, and the second is the one a reader misses: `evidenceRecheckStage` (branch) AND `hasEvidenceGate` (bubbles `systemPromptInjections` out of sf-llm-call in the GROUPED chart — without it the gate flags the app's own prompt). Per-check facts ride `agentfootprint.agent.evidence_checked` (emit channel); only the terminal verdict is committed (`unsupportedValues`), because the boundary raises off it. `UnsupportedValuesError` joins the TERMINAL-typed-error list in `run()`'s catch (a verdict is not a crash — no retry handle for a wall). **Grounded numbers (9.75.0)** rides the SAME dial: `nudge: true` arms the staged-refs nudge — `toolWantsOf` harvests `Tool.wants` beside the `toolGrounding` harvest in `Agent.buildChart` (same ToolProvider blindness), callLLM appends ONE request-only late line when a placed ticket's kind matches a SERVED `wants` tool (judged on `registeredToolSchemas`, so wrap-up's withheld surface arms nothing; history untouched ⇒ never in the exempt corpus), recorded as `agent.grounding_nudged`; and the recheck correction names the same refs+spender via `buildEvidenceCorrection`'s third arg — threaded whenever a `wants` tool exists, NOT gated on `nudge`, clause INSIDE the authored frame so `isLibraryAuthoredTurn`'s prefix match and values-last both hold.
148
+ - **Evidence gate (9.35.0)** — `.namesAndNumbersFromEvidence({ posture, shapes, exempt, minDigits })`: every name/number in the final answer must appear in a `role:'tool'` result. Postures reuse the routing VOCABULARY (`assist`|`guard`|`rails`) as a SEPARATE option — routing authority ≠ evidence discipline, and overloading `skillGraphCascade.strictness` would deny "strict routing, loose evidence". Wiring is the stepNudge blast radius verbatim: `ResolvedEvidenceGate` (builder-resolved, refusals at the CALL SITE) → Agent ctor trailing param → `buildRouteDeciderStage`'s 4th arg (`judgeEvidence` runs LAST of the three judges — schema > steps > evidence — and NOT on a denied or schema-exhausted answer) → `evidenceRecheckStage` branch (`{loopTo}`, mounted only for a revising posture) → `STAGE_IDS.EVIDENCE_RECHECK` + BOUNDARY_LOCAL_IDS + milestoneFor. TWO deps flags, and the second is the one a reader misses: `evidenceRecheckStage` (branch) AND `hasEvidenceGate` (bubbles `systemPromptInjections` out of sf-llm-call in the GROUPED chart — without it the gate flags the app's own prompt). Per-check facts ride `agentfootprint.agent.evidence_checked` (emit channel); only the terminal verdict is committed (`unsupportedValues`), because the boundary raises off it. `UnsupportedValuesError` joins the TERMINAL-typed-error list in `run()`'s catch (a verdict is not a crash — no retry handle for a wall). **Grounded numbers (9.75.0)** rides the SAME dial: `nudge: true` arms the staged-refs nudge — `toolWantsOf` harvests `Tool.wants` beside the `toolGrounding` harvest in `Agent.buildChart` (same ToolProvider blindness), callLLM appends ONE request-only late line when a placed ticket's kind matches a SERVED `wants` tool (judged on `registeredToolSchemas`, so wrap-up's withheld surface arms nothing; history untouched ⇒ never in the exempt corpus), recorded as `agent.grounding_nudged`; and the recheck names the same refs+spender whenever a `wants` tool exists, NOT gated on `nudge`. Since 9.96.0 `evidence/recovery.ts` · `buildEvidenceRecovery` composes request-only system guidance; `evidenceRecoveryPiece` carries it into the next request without synthetic conversation turns. Optional `recoveryInstruction` adds bounded synchronous guidance; `buildEvidenceCorrection` remains a legacy compatibility helper. Token extraction, exemptions and the single-revision budget are unchanged; this is not semantic validation or streaming draft suppression.
146
149
  - **Coverage primitives (this release)** — `absent()` / `coverage()`, both copied from FIELD USE. THE argument is the direction of the error: a *nothing-found* misread as an *outage* costs an investigation, an *outage* misread as *nothing-found* declares a system healthy that was never checked — so the two must not share a shape. Blast radius, and it is the `resultCeiling` radius verbatim: `readCoverageResult` called by `declareCoverage` at BOTH execute boundaries in toolCalls.ts (batch loop + `resolveCredentialAndExecute`), on the UNWRAPPED content and BEFORE the ceiling. FOUR downstream changes and no more: (1) `ToolResultStatus` gained a SEVENTH word `'absent'` — routable by `onToolStatus`, because folding it into `'failure'` is the confusion itself and into `'success'` leaves nothing to route on; (2) two events (`tools.absent`, `tools.coverage_declared`); (3) tracked `AgentState.coverageDeclared` — a limit is a fact about the ANSWER, not about an attempt, which is why it is state and the repeated-call counters are not; (4) the evidence corpus indexes an absence's COVERAGE ONLY (`coverage/evidence.ts` — a failed lookup is the cheapest laundering machine, and `absent()` would have made it cheaper: this is frames.ts's argument on the tool side). Deliberately UNCHANGED: no `error: true`, no retry, no refusal, no gate flag. Survival into the answer is `.limitsTravelWithTheAnswer()` → `attachCoverageLimits` dep → BOTH builders swap the final branch's first stage for `prepareFinalWithLimitsStage` (same id, same position). It APPENDS rather than judges: a check for "did the model state its limits?" needs a second model to decide what counts, which is what evidence/README.md forbids.
147
150
  - **Out-of-budget wrap-up (9.56.0)** — `wrapUpAtMaxIterations` (AgentOptions, default ON, `repeatedCallNudge`'s opt-out grammar): the FOURTH Route branch, and the SchemaRetry mechanism verbatim — `STAGE_IDS.WRAP_UP` + same `{loopTo}`, so the last call is one ordinary turn with its own `iteration_start`/`llm_start`/`cost.tick`. Two things are its own: (1) the tools are WITHHELD at REQUEST ASSEMBLY in callLLM (`scope.wrapUpAsked`, the `schemaTool` seam's mirror — the schema tool still rides, so an output contract survives), which is what makes the call terminal BY CONSTRUCTION rather than by a rule, and is why it is exempt from `maxIterations`; (2) the CONDITIONAL MOUNT is on the agent having a TOOL SURFACE (`registryByName.size > 0 || externalToolProvider`) — a limit only cuts a turn short when tool calls were pending, so a toolless agent's chart must not grow a box that can never run. `decideBranch` treats a spent wrap-up as cut-short for every downstream judge (`toolCalls.length > 0 || scope.wrapUpAsked`), or a step nudge / evidence revision would loop past the limit that fired. `wrapUpAsked` is deliberately NOT seeded — a turn that finishes inside its budget commits the exact key set it always did. The record is FOUR channels: `stoppedEarly` (now with `wrappedUp`, corrected on the pass after so `answerWasEmpty` describes the answer the caller GOT), `cost.limit_hit` (unchanged), the new `agent.budget_exhausted {action: 'wrapped-up'|'cut-short'}`, and an optional `turn_end.stoppedEarly` projection.
148
151
  - **Closed seams**: Agent chart internals (AgentChartDeps not exported — extend via injections/tools/memory/thinking, never by adding a ReAct stage); ContextSlot (3 slots fixed); ProviderKind factory; dormant ports with no consumer (ContextSourceAdapter, EmbeddingProvider, RiskDetector — adapters/types.ts only); reserved tool names under selfExplain — 8.16.0 made the list DERIVED: `TRACE_TOOL_NAMES` (traceToolpack.ts, 11 names since 9.61.0: run_overview/find_context_errors/find_in_trace/trace_node/trace_slice/backtrack/who_wrote/get_value/inspect_tool_call/inspect_tool_run/read_narrative) is what AgentBuilder.ts:~1560 reserves in inline mode (`explain_run` in delegate mode), so a NEW toolpack tool joins ONE list and the reservation follows — but it must ALSO join the lazy template's mounted set (lazyToolpack builds over `{narrative: [], events: []}` so the catalog shape is fixed at build time) and the count assertion in test/lib/trace-toolpack/selfExplainAgent.test.ts. **8.17.0 `inspect_tool_run`** is the descent THROUGH the tool boundary: `flowchartAsTool({ keepRecord: true })` files each invocation's record in a bounded LRU store (lib/trace-toolpack/innerRunRecords.ts) keyed by the executing `ctx.toolCallId`, riding the `Tool` under the `INNER_RUN_RECORDS` registry symbol; `AgentBuilder.build()` → `collectInnerRuns(registry, injections)` → `SelfExplainSource.getInnerRuns` → `TraceToolpackArtifacts.innerRuns`. The inner views are the pack ITSELF re-run over `openRecording(record.recording)` — do not add a second query implementation. Provider-delivered tools are NOT collected (no build-time list); inner runtimeStageIds are a SEPARATE namespace and only `inspect_tool_run` accepts them. **9.61.0 `find_context_errors`** is the Context Integrity read-out: it reads `agentfootprint.integrity.context_error` + `…disposition` off the artifacts' EVENT TAIL (never re-running a check), joins each finding to the step it was filed at, and mounts UNCONDITIONALLY — a tool that vanished with the tail could not say the evidence channel is ABSENT, which is the one sentence this family forbids collapsing into "no errors found".
@@ -0,0 +1,121 @@
1
+ "use strict";
2
+ Object.defineProperty(exports, "__esModule", { value: true });
3
+ exports.createAnswerEvidenceResolver = void 0;
4
+ /** Bounded reads over the existing store. No new store, scope, or ref grammar. */
5
+ const naming_js_1 = require("../artifacts/naming.js");
6
+ const payload_js_1 = require("../artifacts/payload.js");
7
+ const types_js_1 = require("../artifacts/types.js");
8
+ /** @internal Run-local read session. Closing invalidates even retained readers. */
9
+ function createAnswerEvidenceResolver(store, scope, limits, signal) {
10
+ const boundScope = Object.freeze({ ...scope });
11
+ const cache = new Map();
12
+ const resolved = new Set();
13
+ let reads = 0;
14
+ let pendingReads = 0;
15
+ let reservedBytes = 0;
16
+ let closed = false;
17
+ let failure;
18
+ const unavailable = (reason) => {
19
+ failure ??= reason;
20
+ return { ok: false, reason };
21
+ };
22
+ const isClosed = () => closed || signal.aborted;
23
+ const load = async (ref, kind) => {
24
+ if (!store)
25
+ return unavailable('no-store');
26
+ try {
27
+ const described = await store.head(boundScope, ref);
28
+ if (isClosed())
29
+ return unavailable('closed');
30
+ if (described === null)
31
+ return unavailable('missing-or-expired');
32
+ // Memory stores may return their own metadata object: snapshot before the
33
+ // next await, and never hand that live value to an author callback.
34
+ const head = structuredClone(described);
35
+ if (head.ref !== ref || !Number.isSafeInteger(head.bytes) || head.bytes < 0)
36
+ return unavailable('invalid-record');
37
+ if (head.kind !== kind)
38
+ return unavailable('kind-mismatch');
39
+ if (head.bytes > limits.maxBytes - reservedBytes)
40
+ return unavailable('max-bytes');
41
+ reservedBytes += head.bytes; // Reserve before await: parallel reads share this budget.
42
+ const record = await store.get(boundScope, ref);
43
+ if (isClosed())
44
+ return unavailable('closed');
45
+ if (record === null)
46
+ return unavailable('missing-or-expired');
47
+ const meta = structuredClone(record.meta);
48
+ if (meta.ref !== ref ||
49
+ meta.kind !== kind ||
50
+ meta.bytes !== head.bytes ||
51
+ meta.digest !== head.digest ||
52
+ meta.createdAt !== head.createdAt ||
53
+ meta.expiresAt !== head.expiresAt ||
54
+ meta.mediaType !== head.mediaType)
55
+ return unavailable('invalid-record');
56
+ // get is the store's verifying read, including its own expiry clock.
57
+ // A nonconforming adapter may allocate too much inside get; the port has
58
+ // no bounded-read verb. Never deliver an understated parcel as accepted.
59
+ const bytes = (0, payload_js_1.canonicalPayloadBytes)(record.data);
60
+ if (bytes.byteLength !== meta.bytes)
61
+ return unavailable('invalid-record');
62
+ if (bytes.byteLength > limits.maxBytes)
63
+ return unavailable('max-bytes');
64
+ const data = (0, payload_js_1.decodeCanonicalPayload)((0, payload_js_1.payloadShapeOf)(record.data), bytes.slice());
65
+ if (isClosed())
66
+ return unavailable('closed');
67
+ resolved.add(ref);
68
+ return { ok: true, record: { meta, data } };
69
+ }
70
+ catch (error) {
71
+ if (isClosed())
72
+ return unavailable('closed');
73
+ return unavailable(error instanceof types_js_1.ArtifactIntegrityError ? 'digest-mismatch' : 'store-error');
74
+ }
75
+ };
76
+ const resolver = Object.freeze({
77
+ async resolve(ref, options) {
78
+ if (isClosed())
79
+ return unavailable('closed');
80
+ if (!(0, naming_js_1.isArtifactRef)(ref) || options === null || typeof options !== 'object')
81
+ return unavailable('invalid-input');
82
+ const descriptor = Object.getOwnPropertyDescriptor(options, 'kind');
83
+ if (!descriptor ||
84
+ !('value' in descriptor) ||
85
+ typeof descriptor.value !== 'string' ||
86
+ descriptor.value.trim() === '' ||
87
+ descriptor.value.length > 256)
88
+ return unavailable('invalid-input');
89
+ const kind = descriptor.value;
90
+ const key = JSON.stringify([ref, kind]);
91
+ let pending = cache.get(key);
92
+ if (!pending) {
93
+ if (reads >= limits.maxReads)
94
+ return unavailable('max-reads');
95
+ reads++;
96
+ pendingReads++;
97
+ pending = load(ref, kind).finally(() => {
98
+ pendingReads--;
99
+ });
100
+ cache.set(key, pending);
101
+ }
102
+ const result = await pending;
103
+ if (isClosed())
104
+ return unavailable('closed');
105
+ // One callback cannot mutate a cached parcel subsequently used by another
106
+ // check. Metadata and data are detached on every successful delivery.
107
+ return result.ok ? { ok: true, record: structuredClone(result.record) } : { ...result };
108
+ },
109
+ });
110
+ return {
111
+ resolver,
112
+ resolvedRefs: () => [...resolved],
113
+ failureReason: () => failure ?? (pendingReads > 0 ? 'closed' : undefined),
114
+ close() {
115
+ closed = true;
116
+ cache.clear();
117
+ },
118
+ };
119
+ }
120
+ exports.createAnswerEvidenceResolver = createAnswerEvidenceResolver;
121
+ //# sourceMappingURL=evidence.js.map
@@ -0,0 +1 @@
1
+ {"version":3,"file":"evidence.js","sourceRoot":"","sources":["../../src/answer-validation/evidence.ts"],"names":[],"mappings":"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"}
@@ -0,0 +1,10 @@
1
+ "use strict";
2
+ Object.defineProperty(exports, "__esModule", { value: true });
3
+ exports.executeAnswerValidation = exports.resolveAnswerValidation = exports.AnswerValidationError = void 0;
4
+ /** Explicit, bounded validation of schema-accepted JSON answers. */
5
+ var types_js_1 = require("./types.js");
6
+ Object.defineProperty(exports, "AnswerValidationError", { enumerable: true, get: function () { return types_js_1.AnswerValidationError; } });
7
+ var validate_js_1 = require("./validate.js");
8
+ Object.defineProperty(exports, "resolveAnswerValidation", { enumerable: true, get: function () { return validate_js_1.resolveAnswerValidation; } });
9
+ Object.defineProperty(exports, "executeAnswerValidation", { enumerable: true, get: function () { return validate_js_1.executeAnswerValidation; } });
10
+ //# sourceMappingURL=index.js.map
@@ -0,0 +1 @@
1
+ {"version":3,"file":"index.js","sourceRoot":"","sources":["../../src/answer-validation/index.ts"],"names":[],"mappings":";;;AAAA,oEAAoE;AACpE,uCAYoB;AAXlB,iHAAA,qBAAqB,OAAA;AAYvB,6CAAiF;AAAxE,sHAAA,uBAAuB,OAAA;AAAE,sHAAA,uBAAuB,OAAA"}
@@ -0,0 +1,24 @@
1
+ "use strict";
2
+ Object.defineProperty(exports, "__esModule", { value: true });
3
+ exports.AnswerValidationError = void 0;
4
+ /** An enforcing host refused delivery; diagnostic metadata only, never content. */
5
+ class AnswerValidationError extends Error {
6
+ code = 'ERR_ANSWER_VALIDATION';
7
+ report;
8
+ constructor(report) {
9
+ super(`Answer validation '${report.validatorId}' did not pass (${report.status}).`);
10
+ this.name = 'AnswerValidationError';
11
+ this.report = Object.freeze({
12
+ ...report,
13
+ checks: Object.freeze(report.checks.map((check) => Object.freeze({
14
+ ...check,
15
+ ...(check.evidenceRefs !== undefined && {
16
+ evidenceRefs: Object.freeze([...check.evidenceRefs]),
17
+ }),
18
+ }))),
19
+ resolvedRefs: Object.freeze([...report.resolvedRefs]),
20
+ });
21
+ }
22
+ }
23
+ exports.AnswerValidationError = AnswerValidationError;
24
+ //# sourceMappingURL=types.js.map
@@ -0,0 +1 @@
1
+ {"version":3,"file":"types.js","sourceRoot":"","sources":["../../src/answer-validation/types.ts"],"names":[],"mappings":";;;AA6GA,mFAAmF;AACnF,MAAa,qBAAsB,SAAQ,KAAK;IACrC,IAAI,GAAG,uBAAgC,CAAC;IACxC,MAAM,CAAyB;IAExC,YAAY,MAA8B;QACxC,KAAK,CAAC,sBAAsB,MAAM,CAAC,WAAW,mBAAmB,MAAM,CAAC,MAAM,IAAI,CAAC,CAAC;QACpF,IAAI,CAAC,IAAI,GAAG,uBAAuB,CAAC;QACpC,IAAI,CAAC,MAAM,GAAG,MAAM,CAAC,MAAM,CAAC;YAC1B,GAAG,MAAM;YACT,MAAM,EAAE,MAAM,CAAC,MAAM,CACnB,MAAM,CAAC,MAAM,CAAC,GAAG,CAAC,CAAC,KAAK,EAAE,EAAE,CAC1B,MAAM,CAAC,MAAM,CAAC;gBACZ,GAAG,KAAK;gBACR,GAAG,CAAC,KAAK,CAAC,YAAY,KAAK,SAAS,IAAI;oBACtC,YAAY,EAAE,MAAM,CAAC,MAAM,CAAC,CAAC,GAAG,KAAK,CAAC,YAAY,CAAC,CAAC;iBACrD,CAAC;aACH,CAAC,CACH,CACF;YACD,YAAY,EAAE,MAAM,CAAC,MAAM,CAAC,CAAC,GAAG,MAAM,CAAC,YAAY,CAAC,CAAC;SACtD,CAAC,CAAC;IACL,CAAC;CACF;AAtBD,sDAsBC"}
@@ -0,0 +1,326 @@
1
+ "use strict";
2
+ Object.defineProperty(exports, "__esModule", { value: true });
3
+ exports.executeAnswerValidation = exports.resolveAnswerValidation = void 0;
4
+ /** One explicit JSON-answer validation; the runner owns when to invoke it. */
5
+ const outputSchema_js_1 = require("../core/outputSchema.js");
6
+ const payload_js_1 = require("../artifacts/payload.js");
7
+ const evidence_js_1 = require("./evidence.js");
8
+ const DEFAULT_LIMITS = Object.freeze({
9
+ maxReads: 16,
10
+ maxBytes: 4 * 1024 * 1024,
11
+ maxChecks: 100,
12
+ maxCandidateBytes: 1024 * 1024,
13
+ timeoutMs: 5000,
14
+ });
15
+ const encoder = new TextEncoder();
16
+ const dispositions = new Set(['checked-pass', 'checked-fail', 'not-applicable', 'unreachable']);
17
+ function ownData(value, allowed) {
18
+ if (value === null ||
19
+ typeof value !== 'object' ||
20
+ Array.isArray(value) ||
21
+ ![Object.prototype, null].includes(Object.getPrototypeOf(value)))
22
+ throw new Error('Expected a plain data object.');
23
+ const result = Object.create(null);
24
+ for (const key of Reflect.ownKeys(value)) {
25
+ if (typeof key !== 'string' || (allowed && !allowed.includes(key)))
26
+ throw new Error('Unknown property.');
27
+ const descriptor = Object.getOwnPropertyDescriptor(value, key);
28
+ if (!descriptor?.enumerable || !('value' in descriptor))
29
+ throw new Error('Expected an enumerable data property.');
30
+ Object.defineProperty(result, key, { value: descriptor.value, enumerable: true });
31
+ }
32
+ return result;
33
+ }
34
+ function text(value, max) {
35
+ if (typeof value !== 'string' || value.trim() === '' || value.length > max)
36
+ throw new Error('Expected bounded non-empty text.');
37
+ return value;
38
+ }
39
+ /** Validate and snapshot an authored contract once, before running an agent. */
40
+ function resolveAnswerValidation(options) {
41
+ const source = ownData(options, ['id', 'version', 'mode', 'limits', 'validate']);
42
+ const id = text(source.id, 128);
43
+ const version = text(source.version, 128);
44
+ const mode = source.mode === undefined ? 'enforce' : source.mode;
45
+ if (mode !== 'enforce' && mode !== 'observe')
46
+ throw new Error('answerValidation.mode must be enforce or observe.');
47
+ if (typeof source.validate !== 'function')
48
+ throw new Error('answerValidation.validate must be a function.');
49
+ const validate = source.validate;
50
+ const supplied = source.limits === undefined ? {} : ownData(source.limits, Object.keys(DEFAULT_LIMITS));
51
+ const limits = { ...DEFAULT_LIMITS };
52
+ for (const key of Object.keys(DEFAULT_LIMITS)) {
53
+ if (Object.hasOwn(supplied, key)) {
54
+ const value = supplied[key];
55
+ if (typeof value !== 'number' ||
56
+ !Number.isSafeInteger(value) ||
57
+ value <= 0 ||
58
+ (key === 'timeoutMs' && value > 2147483647))
59
+ throw new Error(`answerValidation.limits.${key} must be a positive bounded integer.`);
60
+ limits[key] = value;
61
+ }
62
+ }
63
+ return Object.freeze({
64
+ id,
65
+ version,
66
+ mode,
67
+ limits: Object.freeze(limits),
68
+ validate: (candidate, context) => validate(candidate, context),
69
+ });
70
+ }
71
+ exports.resolveAnswerValidation = resolveAnswerValidation;
72
+ /** JSON copy without invoking toJSON/getters or silently dropping data. */
73
+ function jsonCopy(value, maxBytes, freeze) {
74
+ let budget = maxBytes;
75
+ const ancestors = new Set();
76
+ const spend = (bytes) => {
77
+ budget -= bytes;
78
+ if (budget < 0)
79
+ throw new Error('JSON byte limit.');
80
+ };
81
+ const string = (item) => {
82
+ if (item.length > budget)
83
+ throw new Error('JSON byte limit.');
84
+ spend(encoder.encode(JSON.stringify(item)).byteLength);
85
+ };
86
+ const copy = (item, depth) => {
87
+ if (depth > 100)
88
+ throw new Error('JSON nesting limit.');
89
+ if (item === null) {
90
+ spend(4);
91
+ return null;
92
+ }
93
+ if (typeof item === 'string') {
94
+ string(item);
95
+ return item;
96
+ }
97
+ if (typeof item === 'boolean') {
98
+ spend(item ? 4 : 5);
99
+ return item;
100
+ }
101
+ if (typeof item === 'number') {
102
+ if (!Number.isFinite(item) || Object.is(item, -0))
103
+ throw new Error('Non-lossless JSON number.');
104
+ spend(JSON.stringify(item).length);
105
+ return item;
106
+ }
107
+ if (typeof item !== 'object')
108
+ throw new Error('Non-JSON value.');
109
+ if (ancestors.has(item))
110
+ throw new Error('Cyclic JSON value.');
111
+ ancestors.add(item);
112
+ spend(2);
113
+ let output;
114
+ if (Array.isArray(item)) {
115
+ if (Object.getPrototypeOf(item) !== Array.prototype)
116
+ throw new Error('Non-JSON array prototype.');
117
+ if (item.length > budget + 1)
118
+ throw new Error('JSON byte limit.');
119
+ const keys = Reflect.ownKeys(item);
120
+ if (keys.length !== item.length + 1)
121
+ throw new Error('Sparse or decorated array.');
122
+ const result = [];
123
+ for (let index = 0; index < item.length; index++) {
124
+ const descriptor = Object.getOwnPropertyDescriptor(item, String(index));
125
+ if (!descriptor?.enumerable || !('value' in descriptor))
126
+ throw new Error('Sparse or accessor array.');
127
+ if (index)
128
+ spend(1);
129
+ result.push(copy(descriptor.value, depth + 1));
130
+ }
131
+ output = result;
132
+ }
133
+ else {
134
+ const fields = ownData(item);
135
+ const result = {};
136
+ let index = 0;
137
+ for (const key of Object.keys(fields)) {
138
+ if (index++)
139
+ spend(1);
140
+ string(key);
141
+ spend(1);
142
+ Object.defineProperty(result, key, {
143
+ value: copy(fields[key], depth + 1),
144
+ enumerable: true,
145
+ writable: true,
146
+ configurable: true,
147
+ });
148
+ }
149
+ output = result;
150
+ }
151
+ ancestors.delete(item);
152
+ return freeze ? Object.freeze(output) : output;
153
+ };
154
+ return copy(value, 0);
155
+ }
156
+ function readChecks(value, config, resolved) {
157
+ // Bound before copying. The copy rejects getters, class instances, cycles,
158
+ // decorated arrays and values JSON would otherwise silently discard.
159
+ const source = ownData(value, ['checks']);
160
+ if (!Array.isArray(source.checks) || source.checks.length > config.limits.maxChecks)
161
+ throw new Error('Invalid checks.');
162
+ const detached = jsonCopy(source.checks, config.limits.maxChecks * 4096, false);
163
+ const ids = new Set();
164
+ const refs = new Set(resolved);
165
+ return detached.map((raw) => {
166
+ const check = ownData(raw, ['id', 'disposition', 'reason', 'path', 'evidenceRefs']);
167
+ const id = text(check.id, 128);
168
+ if (ids.has(id) ||
169
+ typeof check.disposition !== 'string' ||
170
+ !dispositions.has(check.disposition))
171
+ throw new Error('Invalid check identity or disposition.');
172
+ ids.add(id);
173
+ const reason = check.reason === undefined ? undefined : text(check.reason, 1024);
174
+ const path = check.path;
175
+ if (path !== undefined && (typeof path !== 'string' || path.length > 256))
176
+ throw new Error('Invalid check path.');
177
+ let evidenceRefs;
178
+ if (check.evidenceRefs !== undefined) {
179
+ if (!Array.isArray(check.evidenceRefs) || check.evidenceRefs.length > config.limits.maxReads)
180
+ throw new Error('Invalid evidence references.');
181
+ evidenceRefs = check.evidenceRefs.map((ref) => {
182
+ if (typeof ref !== 'string' || !refs.has(ref))
183
+ throw new Error('Unresolved evidence reference.');
184
+ return ref;
185
+ });
186
+ if (new Set(evidenceRefs).size !== evidenceRefs.length)
187
+ throw new Error('Duplicate evidence reference.');
188
+ }
189
+ return Object.freeze({
190
+ id,
191
+ disposition: check.disposition,
192
+ ...(reason !== undefined && { reason }),
193
+ ...(path !== undefined && { path }),
194
+ ...(evidenceRefs !== undefined && { evidenceRefs: Object.freeze(evidenceRefs) }),
195
+ });
196
+ });
197
+ }
198
+ /**
199
+ * Validate once. Content is present only when delivery is permitted by this
200
+ * contract. It is the exact JSON string whose detached value was checked;
201
+ * callers must not reparse through a transforming schema or rewrite afterward.
202
+ */
203
+ async function executeAnswerValidation(raw, parser, config, store, scope, signal) {
204
+ const controller = new AbortController();
205
+ const evidence = (0, evidence_js_1.createAnswerEvidenceResolver)(store, scope, config.limits, controller.signal);
206
+ let reason;
207
+ let schemaAccepted = false;
208
+ let canonical;
209
+ let candidateDigest;
210
+ let checks = [];
211
+ let active = true;
212
+ let stop;
213
+ const abort = () => {
214
+ reason = 'aborted';
215
+ controller.abort();
216
+ stop?.();
217
+ };
218
+ const timedOut = () => {
219
+ reason = 'timeout';
220
+ controller.abort();
221
+ stop?.();
222
+ };
223
+ const deadline = Date.now() + config.limits.timeoutMs;
224
+ const timer = setTimeout(timedOut, config.limits.timeoutMs);
225
+ signal?.addEventListener('abort', abort, { once: true });
226
+ if (signal?.aborted)
227
+ abort();
228
+ try {
229
+ const interrupted = new Promise((resolve) => {
230
+ stop = resolve;
231
+ if (controller.signal.aborted)
232
+ resolve();
233
+ });
234
+ const work = async () => {
235
+ if (controller.signal.aborted)
236
+ return;
237
+ let candidate;
238
+ try {
239
+ if (raw.length > config.limits.maxCandidateBytes ||
240
+ encoder.encode(raw).byteLength > config.limits.maxCandidateBytes) {
241
+ reason = 'candidate-limit';
242
+ return;
243
+ }
244
+ candidate = (0, outputSchema_js_1.applyOutputSchema)(raw, parser);
245
+ }
246
+ catch {
247
+ reason = 'schema-rejected';
248
+ return;
249
+ }
250
+ try {
251
+ candidate = jsonCopy(candidate, config.limits.maxCandidateBytes, true);
252
+ canonical = JSON.stringify(candidate);
253
+ schemaAccepted = true;
254
+ }
255
+ catch {
256
+ reason = 'non-json-candidate';
257
+ return;
258
+ }
259
+ if (Date.now() >= deadline) {
260
+ timedOut();
261
+ return;
262
+ }
263
+ try {
264
+ const digest = await (0, payload_js_1.computeArtifactDigest)(canonical);
265
+ if (!active || controller.signal.aborted)
266
+ return;
267
+ candidateDigest = digest;
268
+ const returned = await config.validate(candidate, Object.freeze({ signal: controller.signal, artifacts: evidence.resolver }));
269
+ if (!active || controller.signal.aborted)
270
+ return;
271
+ if (Date.now() >= deadline) {
272
+ timedOut();
273
+ return;
274
+ }
275
+ try {
276
+ checks = readChecks(returned, config, evidence.resolvedRefs());
277
+ }
278
+ catch {
279
+ reason = 'invalid-validator-result';
280
+ }
281
+ }
282
+ catch {
283
+ if (active && !controller.signal.aborted)
284
+ reason = 'validator-error';
285
+ }
286
+ };
287
+ await Promise.race([work(), interrupted]);
288
+ }
289
+ finally {
290
+ active = false;
291
+ clearTimeout(timer);
292
+ signal?.removeEventListener('abort', abort);
293
+ evidence.close();
294
+ controller.abort();
295
+ }
296
+ const failed = checks.filter((check) => check.disposition === 'checked-fail').length;
297
+ const checked = failed + checks.filter((check) => check.disposition === 'checked-pass').length;
298
+ const unreachable = checks.filter((check) => check.disposition === 'unreachable').length;
299
+ const notApplicable = checks.filter((check) => check.disposition === 'not-applicable').length;
300
+ if (!reason && evidence.failureReason())
301
+ reason = `evidence-${evidence.failureReason()}`;
302
+ if (!reason && checked === 0)
303
+ reason = 'no-comparable-checks';
304
+ if (!reason && unreachable > 0)
305
+ reason = 'unreachable-checks';
306
+ const status = reason ? 'unverified' : failed > 0 ? 'failed' : 'passed';
307
+ const report = Object.freeze({
308
+ validatorId: config.id,
309
+ validatorVersion: config.version,
310
+ mode: config.mode,
311
+ status,
312
+ checked,
313
+ failed,
314
+ unreachable,
315
+ notApplicable,
316
+ checks: Object.freeze(checks),
317
+ schemaAccepted,
318
+ ...(reason !== undefined && { reason }),
319
+ ...(candidateDigest !== undefined && { candidateDigest }),
320
+ resolvedRefs: Object.freeze(evidence.resolvedRefs()),
321
+ });
322
+ const content = status === 'passed' || config.mode === 'observe' ? canonical ?? raw : undefined;
323
+ return { report, ...(content !== undefined && { content }) };
324
+ }
325
+ exports.executeAnswerValidation = executeAnswerValidation;
326
+ //# sourceMappingURL=validate.js.map
@@ -0,0 +1 @@
1
+ {"version":3,"file":"validate.js","sourceRoot":"","sources":["../../src/answer-validation/validate.ts"],"names":[],"mappings":"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"}