From f5025120e390ce45848933cc50bb1ff92025490c Mon Sep 17 00:00:00 2001
From: Garrett Maring
Date: Tue, 26 May 2026 16:13:39 -0300
Subject: [PATCH 01/35] V42 Gate 1: Open reliable MVP experience roadmap
Open the V42 specification family over active V41, defining the reliable MVP experience gate plan for shortest-path Depositing, five-step Reading, settlement-gated delivery, and AI-reading demonstration proof.
Wire check:v42-gate1 into package scripts and gate/canon workflows, update roadmap/docs/PR guidance for active V41 / draft V42 posture, and preserve V43+ route-split and agentic deposit work as future scope.
Checks: pnpm run check:v42-gate1; node scripts/check-bitcode-spec-family.mjs --version V42 --mode draft --current-target V41; node scripts/check-bitcode-canonical-inputs.mjs --current-target V41; node scripts/check-bitcode-canon-posture-drift.mjs --active-canon V41 --draft-target V42; node scripts/check-v41-gate9-promotion-readiness.mjs --promotion-mode --skip-branch-check --skip-package-tests; pnpm --filter @bitcode/protocol typecheck; git diff --check
---
.github/pull_request_template.md | 4 +-
.github/workflows/bitcode-canon-quality.yml | 14 +-
.github/workflows/bitcode-gate-quality.yml | 4 +
BITCODE_SPEC_V42.md | 522 ++++++++++++++++++
BITCODE_SPEC_V42_DELTA.md | 85 +++
BITCODE_SPEC_V42_NOTES.md | 80 +++
BITCODE_SPEC_V42_PARITY_MATRIX.md | 70 +++
README.md | 22 +-
SPECIFICATIONS_ROADMAP.md | 39 +-
package.json | 1 +
packages/protocol/README.md | 10 +-
...2-gate1-mvp-experience-roadmap-opening.mjs | 176 ++++++
12 files changed, 993 insertions(+), 34 deletions(-)
create mode 100644 BITCODE_SPEC_V42.md
create mode 100644 BITCODE_SPEC_V42_DELTA.md
create mode 100644 BITCODE_SPEC_V42_NOTES.md
create mode 100644 BITCODE_SPEC_V42_PARITY_MATRIX.md
create mode 100644 scripts/check-v42-gate1-mvp-experience-roadmap-opening.mjs
diff --git a/.github/pull_request_template.md b/.github/pull_request_template.md
index 79f3e0e9..d692faa0 100644
--- a/.github/pull_request_template.md
+++ b/.github/pull_request_template.md
@@ -1,7 +1,7 @@
## Title
-Use the version and gate prefix for gate PRs: `V41 Gate N: Concise Topical Title`.
-Use the version and promotion prefix for version promotion PRs: `V41 Canonical Promotion: Concise Topical Title`.
+Use the version and gate prefix for gate PRs: `V42 Gate N: Concise Topical Title`.
+Use the version and promotion prefix for version promotion PRs: `V42 Canonical Promotion: Concise Topical Title`.
## Closure
diff --git a/.github/workflows/bitcode-canon-quality.yml b/.github/workflows/bitcode-canon-quality.yml
index 4366e25b..44ffb620 100644
--- a/.github/workflows/bitcode-canon-quality.yml
+++ b/.github/workflows/bitcode-canon-quality.yml
@@ -292,6 +292,10 @@ jobs:
node scripts/check-bitcode-canonical-inputs.mjs --current-target V41
node scripts/check-bitcode-canon-posture-drift.mjs --active-canon V41 --draft-target V42
node scripts/check-v41-gate9-promotion-readiness.mjs --promotion-mode --skip-branch-check --skip-package-tests
+ if [ -f BITCODE_SPEC_V42.md ]; then
+ node scripts/check-bitcode-spec-family.mjs --version V42 --mode draft --current-target V41
+ node scripts/check-v42-gate1-mvp-experience-roadmap-opening.mjs --skip-branch-check
+ fi
else
echo "Unexpected BITCODE_SPEC.txt pointer: $POINTER" >&2
exit 1
@@ -431,7 +435,15 @@ jobs:
node scripts/check-bitcode-spec-family.mjs --version V41 --mode draft --current-target V40
fi
;;
+ spec:\ V42*|spec:\ v42*)
+ POINTER="$(cat BITCODE_SPEC.txt)"
+ if [ "$POINTER" = "V42" ]; then
+ node scripts/check-bitcode-spec-family.mjs --version V42 --mode promoted --current-target V42
+ else
+ node scripts/check-bitcode-spec-family.mjs --version V42 --mode draft --current-target V41
+ fi
+ ;;
*)
- echo "Skipping strict spec-title conformance; title is not a V29/V30/V31/V32/V33/V34/V35/V36/V37/V38/V39/V40/V41 spec change."
+ echo "Skipping strict spec-title conformance; title is not a V29/V30/V31/V32/V33/V34/V35/V36/V37/V38/V39/V40/V41/V42 spec change."
;;
esac
diff --git a/.github/workflows/bitcode-gate-quality.yml b/.github/workflows/bitcode-gate-quality.yml
index 52ff9afb..906125d9 100644
--- a/.github/workflows/bitcode-gate-quality.yml
+++ b/.github/workflows/bitcode-gate-quality.yml
@@ -421,6 +421,10 @@ jobs:
node scripts/check-bitcode-canonical-inputs.mjs --current-target V41
node scripts/check-bitcode-canon-posture-drift.mjs --active-canon V41 --draft-target V42
node scripts/check-v41-gate9-promotion-readiness.mjs --promotion-mode --skip-branch-check --skip-package-tests
+ if [ -f BITCODE_SPEC_V42.md ]; then
+ node scripts/check-bitcode-spec-family.mjs --version V42 --mode draft --current-target V41
+ node scripts/check-v42-gate1-mvp-experience-roadmap-opening.mjs --skip-branch-check
+ fi
else
echo "Unexpected BITCODE_SPEC.txt pointer: $POINTER" >&2
exit 1
diff --git a/BITCODE_SPEC_V42.md b/BITCODE_SPEC_V42.md
new file mode 100644
index 00000000..bf8336e7
--- /dev/null
+++ b/BITCODE_SPEC_V42.md
@@ -0,0 +1,522 @@
+# Bitcode Spec V42
+
+## Status
+
+- Version: `V42`
+- V42 state: draft opened; V42 is the reliable MVP experience draft over the promoted V41 prompt-program excellence canon
+- Current canonical/latest target: `V41`
+- Prior canonical anchor: `BITCODE_SPEC_V41.md`
+- Prior generated proof appendix: `BITCODE_SPEC_V41_PROVEN.md`
+- Generated structured artifact inventory: draft `.bitcode/v42-spec-family-report.json`, `.bitcode/v42-canonical-input-report.json`, `.bitcode/v42-canon-posture-drift-report.json`, and later V42 gate artifacts for depositing shortest path, Reading shortest path, AI-reading demonstration proof, settlement and delivery rehearsal, and promotion readiness
+- Source parity state: V42 Gate 1 opens specification, roadmap, documentation, and workflow parity over active V41; source behavior changes remain gated behind later V42 acceptance criteria
+- Notes companion: `BITCODE_SPEC_V42_NOTES.md`
+- Delta companion: `BITCODE_SPEC_V42_DELTA.md`
+- Parity companion: `BITCODE_SPEC_V42_PARITY_MATRIX.md`
+- Generated proof appendix: `BITCODE_SPEC_V42_PROVEN.md` only after V42 promotion
+- Scope: V42 draft system specification for reliable MVP product experience: shortest-path Depositing, shortest-path Reading, source-safe AssetPack preview, BTD/BTC settlement, post-settlement repository delivery, depositor compensation visibility, and an AI-reading dominant demonstration
+- Last fully realized canonical target preserved in source: `V41`
+
+## Version executive summary
+
+V42 exists because V39 made commercial Reading real, V40 made the application testable, and V41 made prompts and PromptParts reliable enough to drive a product experience.
+The version now turns that depth into the shortest believable enterprise MVP paths:
+
+- deposit any admissible source material into the Depository with clear proof that it can later earn BTC compensation when used in a synthesized AssetPack;
+- request a Read, review or resynthesize Bitcode's synthesized Need, request Finding Fits, inspect source-safe AssetPack measurements and preview metadata, settle the quoted BTD/BTC purchase, and receive the full source-bearing AssetPack as repository delivery after settlement;
+- demonstrate Bitcode as an AI-reading dominant system where proprietary or otherwise non-public deposited material measurably improves an AI system beyond a public-data-only baseline.
+
+## Canonical Bitcode executive summary
+
+Bitcode remains the protocol and commercial system for depositing technical knowledge, reading needs against the Depository, finding many fitting deposits, synthesizing source-safe AssetPack previews, settling BTC fees, transferring BTD rights, and delivering full source-bearing AssetPacks only after settlement.
+V42 changes the product experience and demonstration proof around that law.
+It must not weaken BTC settlement, BTD ownership, source-to-shares compensation, disclosure boundaries, prompt-program source-safety, or ledger/database/storage synchronization.
+
+## V42 source-of-truth hierarchy
+
+`BITCODE_SPEC.txt` points to `V41` while V42 is draft.
+`BITCODE_SPEC_V41.md` and `BITCODE_SPEC_V41_PROVEN.md` are active canon.
+`BITCODE_SPEC_V42.md`, `BITCODE_SPEC_V42_DELTA.md`, `BITCODE_SPEC_V42_NOTES.md`, and `BITCODE_SPEC_V42_PARITY_MATRIX.md` define the draft target only on `version/v42` and `v42/gate-*` branches.
+Implementation remains unversioned in source paths; routes, packages, tests, prompts, components, and scripts move in place as the single current Bitcode system.
+
+## V42 full-system, re-implementation, and audit rule
+
+Reliable MVP experience work must be reconstructable from code, specification, generated artifacts, tests, telemetry, and operator documentation.
+Each accepted gate must state the user path, protocol objects, route/API ownership, pipeline ownership, source-safe disclosure tier, storage projection, ledger boundary, telemetry rows, proof artifacts, and validating commands needed to rebuild the experience without conversation history.
+No gate may close with only UI copy, speculative product language, or unverified route behavior.
+
+## V42 totality and precision enforcement rule
+
+V42 must make the product shortest paths complete without hiding complexity.
+Default interfaces should be low-detail and guided, while expandable detail must preserve the rich proof, telemetry, ledger, pipeline, and storage readback required by Bitcode.
+No Read can advance to Finding Fits without a reviewed synthesized Need.
+No source-bearing AssetPack content can cross into reader visibility before BTC settlement, BTD rights transfer, and storage/delivery reconciliation.
+No generated report may serialize secrets, wallet private material, private settlement payloads, protected source, raw provider responses, protected prompt payloads, or unpaid AssetPack source.
+
+## V42 system goals, non-goals, and design principles
+
+Goals:
+
+- Make Depositing the shortest path from source material to Depository admission proof and later compensation visibility.
+- Make Reading the shortest path from Read Request to reviewed Need, Finding Fits, source-safe AssetPack preview, BTD/BTC settlement, rights transfer, and repository delivery.
+- Keep advanced proof and telemetry available through expandable detail instead of forcing enterprise users through raw protocol machinery.
+- Preserve `ReadNeedComprehensionSynthesis` and `ReadFitsFindingSynthesis` as the product-owned Reading pipeline names and runtime boundaries.
+- Produce a demonstration where an AssetPack improves an AI system beyond a public-data-only baseline using deposited technical intelligence.
+- Keep local and staging-testnet rehearsal realistic while value-bearing mainnet operations remain explicitly gated.
+
+Non-goals:
+
+- V42 does not introduce agentic enterprise deposit AssetPack option synthesis; that is V43+.
+- V42 does not split `/terminal` into `/read` and `/deposit`, and does not rename `/exchange` to `/packs`; those route changes are V43+ unless explicitly reopened.
+- V42 does not change BTD supply law, BTC fee conservation, source-to-shares accounting, or post-settlement delivery rights.
+- V42 does not expose protected source, protected prompts, raw provider responses, or unpaid AssetPack source for demonstration convenience.
+
+Design principles: shortest credible path, source-safe preview, proof-on-expand, purchase-before-source, depositor compensation visibility, AI-reading demonstration value, and production-hardening through tests.
+
+## V42 system architecture and layer boundaries
+
+V42 acts through existing layers:
+
+- website application routes and product state for Depositing, Reading, settlement, and delivery;
+- packages for protocol, BTD, pipeline hosts, pipeline asset packs, prompts, tools, telemetry, and storage;
+- `ReadNeedComprehensionSynthesis` and `ReadFitsFindingSynthesis` pipelines with PTRR agents, FailsafeGenerationSequence, ThricifiedGeneration, tool registries, and typed parser outputs;
+- Depository indexing, search documents, embeddings, candidate fit ranking, selected-fit provenance, AssetPack synthesis, quote calculation, settlement observation, BTD rights transfer, and repository delivery;
+- demonstration code inside `protocol-demonstration/` only, with no commercial imports from demonstration and no demonstration imports from commercial product code.
+
+## V42 canonical domain model
+
+V42 product-experience domain objects are Depositing session, source admission proof, Depository record, compensation route preview, Read Request, synthesized Need, Need review decision, Need resynthesis request, accepted Need admission, Finding Fits request, candidate fit deposit, selected fit set, AssetPack measurement preview, withheld source bundle, BTD/BTC quote, settlement instruction, settlement observation, BTD rights transfer receipt, repository delivery receipt, AI-reading baseline, AI-reading improved result, telemetry stream row, proof-root summary, and repair posture.
+These objects bind to existing Bitcode objects: deposits, BTD ranges, AssetPacks, BTC fee receipts, source-to-shares rows, ledger journals, database projections, object-storage locks, VCS pull requests, prompt-program receipts, pipeline executions, and source-safe generated artifacts.
+
+## V42 whole Bitcode operator chain
+
+The V42 operator chain is: admit source, prove Depository availability, expose compensation posture, accept a Read Request, synthesize a Need, review or resynthesize the Need, request Finding Fits, search many Depository candidates, rank and select fitting deposits, synthesize a source-safe AssetPack preview, quote BTD/BTC purchase terms, settle BTC, transfer BTD rights, unlock source-bearing delivery, create repository pull request, journal ledger/database/storage synchronization, and expose source-safe telemetry and proof readback.
+
+## V42 Gate 1 MVP Experience Roadmap And Spec Opening
+
+Gate 1 opens the V42 spec family, branch posture, workflow posture, checker, roadmap, docs, and reliable MVP experience vocabulary.
+It does not implement route, pipeline, settlement, or demonstration behavior beyond documentation and validation posture.
+It closes when active V41 / draft V42 truth is visible in the root docs, protocol docs, workflow checks, package scripts, and roadmap, and when V42 has a precise gate plan.
+
+## V42 Gate 2 Depositing Shortest Path And Compensation Visibility
+
+Gate 2 must make the shortest deposit path explicit and testable.
+The accepted user path is: provide source material, select repository/source anchor, admit deposit to the Depository, receive source-safe admission proof, and see how later BTC compensation will be attributed if the deposit participates in a synthesized AssetPack.
+It must cover route/API contracts, source validation, storage projection, Depository search-document creation, BTD/source-to-shares compensation readback, telemetry, and local/staging rehearsal.
+
+## V42 Gate 3 Reading Shortest Path State Machine
+
+Gate 3 must make the five Reading steps a coherent product state machine: request read, review synthesized Need, request Finding Fits, review source-safe AssetPack preview, and buy/settle/deliver AssetPack.
+It must simplify default Terminal experience while preserving expandable proof, execution, telemetry, ledger, and storage detail.
+It must prove route persistence, transaction ids, stage transitions, restart/retry behavior, source-safe UI rendering, and failure states.
+
+## V42 Gate 4 ReadNeed Review And Resynthesis Product Closure
+
+Gate 4 must make `ReadNeedComprehensionSynthesis` product-ready in the MVP flow.
+The pipeline must synthesize exactly the user's Need from the Read Request, store source-safe Need data, allow user feedback and resynthesis, preserve lineage, and admit Finding Fits only after the Need is accepted.
+It must cover PTRR agents, FailsafeGenerationSequence, ThricifiedGeneration, prompts, parser return types, telemetry rows, database projection, tests, and UI readback.
+
+## V42 Gate 5 ReadFitsFinding AssetPack Preview And Quote Closure
+
+Gate 5 must make `ReadFitsFindingSynthesis` product-ready in the MVP flow.
+The pipeline must search the Depository for many candidates above threshold, rank candidates, select fits, synthesize source-safe AssetPack measurements and preview metadata, keep source-bearing content withheld, calculate deterministic BTD/BTC quote posture, and expose a reviewable preview.
+It must cover vector search and provider search tooling, selected-fit provenance, prompt/tool return types, telemetry, quote formula readback, source-safe UI, and failure/repair states.
+
+## V42 Gate 6 Settlement Rights Transfer And Repository Delivery Closure
+
+Gate 6 must make purchase and delivery reliable.
+The accepted user path is: review the AssetPack preview, choose to buy, receive settlement instructions, observe BTC/testnet settlement in the admitted lane, transfer BTD rights to the Reader, unlock source-bearing AssetPack delivery, and create the repository pull request.
+It must prove ledger/database/object-storage synchronization, delivery locks, no pre-settlement source leakage, compensation accounting, repair actions, and operator readback.
+
+## V42 Gate 7 AI-Reading Dominant Demonstration MVP
+
+Gate 7 must update the standalone demonstration so it proves Bitcode's AI-reading value.
+The demonstration should show deposited non-public technical intelligence becoming an AssetPack that measurably improves an AI system's training, prompt/context, or evaluation performance beyond a public-data-only baseline.
+It must remain minimal, self-contained inside `protocol-demonstration/`, and independent from commercial product code.
+
+## V42 Gate 8 Local And Staging-Testnet Full MVP Rehearsal
+
+Gate 8 must rehearse the full MVP path locally and in staging-testnet without value-bearing mainnet behavior.
+It must exercise deposit, Read Request, Need synthesis/review/resynthesis, Finding Fits, AssetPack preview, quote, settlement simulation or testnet observation, BTD rights projection, repository delivery, telemetry, proof artifacts, and repair readback.
+
+## V42 Gate 9 V42 Promotion Readiness
+
+Gate 9 closes V42 promotion readiness.
+It must bind every V42 artifact, test, workflow, generated proof support, promotion command, active V42 / draft V43 runtime preparation, source-safe generated appendix output, and value-bearing mainnet blocking where relevant.
+It closes only when V42 can be promoted as the reliable MVP experience canon.
+
+## V42 canonical subsystem surfaces
+
+### Depositing and asset supply
+
+Current canonical objects and emitted artifacts: deposits, source admission proof, Depository records, search documents, embedding projections, source-to-shares contributor roots, compensation route previews, and admission telemetry.
+Current algorithms and derivation rules: deposit admission validates source authority, builds source-safe measurement/search documents, preserves ownership, and records future compensation posture without implying a BTD mint before a Need-Fit.
+Current invariants and fail-closed conditions: invalid deposit, missing source authority, storage mismatch, and protected-source projection fail closed.
+Current proof obligations: admission proof, Depository readback, compensation route readback, source-safe projection, and local/staging rehearsal.
+Current source-bearing implementation basis: `packages/protocol`, `packages/btd`, `packages/pipelines/asset-pack`, `packages/tools-generics`, `packages/prompts`, and `uapi`.
+Current validating commands and parity basis: V42 gate checks, V41 prompt-program checks, V40 integration coverage, V39 Reading readiness, and generated V42 artifacts.
+Current accepted boundaries: pre-fit deposits are Depository supply; BTD rights are minted/transferred only through accepted Need-Fit and settlement law.
+
+### Reading and prompt/inference ownership
+
+Current canonical objects and emitted artifacts: Read Request, synthesized Need, Need review decision, resynthesis lineage, accepted Need admission, prompt receipts, Failsafe receipts, ThricifiedGeneration receipts, parser envelopes, and telemetry stream rows.
+Current algorithms and derivation rules: `ReadNeedComprehensionSynthesis` maps Read Request to exactly scoped Need, then user acceptance admits `ReadFitsFindingSynthesis`.
+Current invariants and fail-closed conditions: prompt contract incompleteness, parsed-envelope inadmissibility, missing Need review, authorization denial, and source-context overreach fail closed.
+Current proof obligations: prompt registry coverage, typed output parsing, review/resynthesis lineage, source-safe telemetry, and UI state persistence.
+Current source-bearing implementation basis: `packages/agent-generics`, `packages/prompts`, `packages/pipelines/asset-pack`, `packages/tools-generics`, `packages/protocol`, and `uapi`.
+Current validating commands and parity basis: V41 prompt-program reports, V42 Reading product gates, and V40 application tests.
+Current accepted boundaries: Need data may be visible to the Reader; fit source and AssetPack source remain withheld until settlement unlock.
+
+### Fit, recall, ranking, and verification
+
+Current canonical objects and emitted artifacts: query plans, vector search receipts, provider search receipts, candidate fit deposits, ranking receipts, selected-fit provenance, verification verdicts, source-safe preview measurements, and replay roots.
+Current algorithms and derivation rules: `ReadFitsFindingSynthesis` searches many Depository candidates above threshold, ranks them with source-safe evidence, and feeds selected fits into AssetPack synthesis.
+Current invariants and fail-closed conditions: no-survivor asset pack, missing provenance, ranking drift, embedding mismatch, and verification failure block preview and settlement.
+Current proof obligations: query synthesis, vector/provider search breadth, threshold ranking, selected-fit provenance, and source-safe replay determinism.
+Current source-bearing implementation basis: depository search tools, embedding utilities, prompt registries, pipeline asset-pack packages, and benchmark fixtures.
+Current validating commands and parity basis: V38 search/embedding artifacts, V39 Finding Fits runtime, V41 prompt hardening, and V42 Gate 5.
+Current accepted boundaries: pre-settlement candidate and fit visibility is source-safe metadata only.
+
+### Selection and materialization
+
+Current canonical objects and emitted artifacts: selected fit set, AssetPack measurements, source-safe preview, withheld source bundle, quote, delivery lock, repository delivery plan, proof roots, and repair receipts.
+Current algorithms and derivation rules: AssetPack source can be synthesized and locked before settlement, but reader visibility is limited to source-safe preview and measurements until payment and rights transfer.
+Current invariants and fail-closed conditions: public projection overexposure, unpaid AssetPack source exposure, missing quote, and delivery-lock mismatch fail closed.
+Current proof obligations: preview source-safety, deterministic quote, locked source bundle, post-settlement delivery unlock, and repository pull-request proof.
+Current source-bearing implementation basis: `packages/pipelines/asset-pack`, `packages/btd`, `packages/vcs`, `packages/protocol`, and `uapi`.
+Current validating commands and parity basis: V39 preview/quote and settlement/delivery artifacts, V40 integration tests, and V42 Gates 5 and 6.
+Current accepted boundaries: full source-bearing delivery unlock remains payment, finality, rights-transfer, and reconciliation gated.
+
+### Identity, authorization, and sensitive flow
+
+Current canonical objects and emitted artifacts: account, organization, wallet, repository authority, source selector, policy decision, quote recipient, buyer, depositor, and disclosure receipt.
+Current algorithms and derivation rules: product paths must check authority before source admission, Need synthesis, fit search, preview, settlement, and repository delivery.
+Current invariants and fail-closed conditions: authorization denial, wallet authority mismatch, organization policy denial, and repository permission failure fail closed.
+Current proof obligations: policy readback, role checks, wallet boundary, repository delivery authority, and source-safe denial states.
+Current source-bearing implementation basis: `packages/auth`, `packages/btd`, `packages/github`, `packages/protocol`, and `uapi`.
+Current validating commands and parity basis: V31 Auxillaries authority, V39 Reading interface parity, V40 API/browser tests, and V42 route tests.
+Current accepted boundaries: private wallet material, private settlement payloads, secrets, and protected source never enter public or unpaid Reader projections.
+
+### Disclosure and projection
+
+Current canonical objects and emitted artifacts: visibility tier, source-safe preview, protected source lock, prompt/result disclosure posture, telemetry redaction receipt, and public/operator projection rows.
+Current algorithms and derivation rules: source-safe summaries may show measurements, ids, hashes, roots, scores, and verdicts; protected source, raw prompts, raw provider responses, and unpaid AssetPack source remain withheld.
+Current invariants and fail-closed conditions: public projection overexposure, prompt/result leakage, and storage projection mismatch fail closed.
+Current proof obligations: disclosure tier mapping, UI redaction, telemetry redaction, generated artifact redaction, and repair posture.
+Current source-bearing implementation basis: `packages/observability`, `packages/prompts`, `packages/protocol`, `packages/btd`, and `uapi`.
+Current validating commands and parity basis: V38/V41 source-safe telemetry and prompt-program checks, V39 preview boundaries, and V42 UI tests.
+Current accepted boundaries: proof-on-expand may be rich but must remain source-safe before settlement.
+
+### Settlement and exact accounting
+
+Current canonical objects and emitted artifacts: BTD/BTC quote, settlement instruction, BTC observation, finality state, BTD rights transfer receipt, source-to-shares allocation, ledger journal, database projection, and reconciliation receipt.
+Current algorithms and derivation rules: deterministic quote posture uses measurement weight, measurement volume, and protocol fee allocation; settlement observation gates rights transfer and delivery unlock; compensation routes deposit contributors according to source-to-shares law.
+Current invariants and fail-closed conditions: settlement conservation drift, missing finality, duplicate rights transfer, compensation mismatch, and stale projection fail closed.
+Current proof obligations: quote determinism, BTC/testnet observation, BTD rights transfer, source-to-shares conservation, ledger/database/object-storage synchronization, and repair replay.
+Current source-bearing implementation basis: `packages/btd`, `packages/protocol`, `packages/objects-arrays`, storage adapters, and `uapi`.
+Current validating commands and parity basis: V27/V30 BTD law, V39 settlement readiness, V40 ledger/storage sync, and V42 Gate 6.
+Current accepted boundaries: production-mainnet value-bearing operations remain blocked until explicitly admitted by later canon and operator approval.
+
+### Proof contract, witnesses, and replay
+
+Current canonical objects and emitted artifacts: proof family, member, theorem, replay step, witness artifact, generated report, run receipt, telemetry row, repair receipt, and promotion appendix.
+Current algorithms and derivation rules: every V42 gate emits or checks source-safe proof roots sufficient to replay the product path and detect stale promoted status truth.
+Current invariants and fail-closed conditions: stale promoted status truth, missing witness, failed replay, and source-safety violation fail closed.
+Current proof obligations: deterministic generated artifacts, workflow binding, local/staging rehearsal receipts, promotion dry-run, and generated `BITCODE_SPEC_V42_PROVEN.md`.
+Current source-bearing implementation basis: `packages/protocol`, `.bitcode/`, `.github/workflows`, `scripts/`, and `protocol-demonstration/`.
+Current validating commands and parity basis: V42 check scripts, V41 promotion readiness, V40 proof/test coverage, and canon-quality workflows.
+Current accepted boundaries: demonstration evidence stays within demonstration boundaries and does not become commercial runtime dependency.
+
+## V42 proof-family canon
+
+### Exact proof-family inventory matrix
+
+| proofFamily | proofArtifactPath | memberIds | theoremIds | replayStepIds | witnessArtifactPaths | Current source basis |
+| --- | --- | --- | --- | --- | --- | --- |
+| Inference-synthesis | `.bitcode/v42-inference-synthesis.json` | read-need, finding-fits, asset-pack-preview | need-exactness, many-fit-search, typed-output | synthesize-need, search-depository, preview-pack | pipeline receipts, prompt receipts | V41 prompt-program canon and V42 Reading gates |
+| Prompt-completeness | `.bitcode/v42-prompt-completeness.json` | prompt-registry, tool-prompts, parser-prompts | registry-totality, interpolation-totality | resolve-prompt, parse-output | prompt catalogue reports | V41 PromptPart and Prompt artifacts |
+| Static-code-analysis | `.bitcode/v42-static-code-analysis.json` | routes, packages, workflows | no-versioned-routes, no-demo-import, no-secret-values | lint, typecheck, import-scan | CI logs | scripts and workflows |
+| Verification-decisions | `.bitcode/v42-verification-decisions.json` | deposit-admission, need-review, fit-selection | authority-checked, source-safe, replayable | admit-deposit, accept-need, rank-fits | route/API receipts | V42 Gates 2 through 5 |
+| Selection-and-materialization | `.bitcode/v42-selection-materialization.json` | selected-fits, preview, withheld-source | no-source-before-settlement, delivery-lock | synthesize-preview, lock-source | storage and preview receipts | V39/V42 preview and delivery law |
+| Authorization-and-sensitive-flow | `.bitcode/v42-authorization-sensitive-flow.json` | account, org, wallet, repo | authority-preserved, policy-fail-closed | check-policy, check-wallet, check-repo | policy receipts | Auxillaries, auth, BTD packages |
+| Settlement-source-to-shares | `.bitcode/v42-settlement-source-to-shares.json` | quote, settlement, rights, compensation | conservation, finality, rights-transfer | quote, observe, transfer, allocate | ledger receipts | BTD and ledger packages |
+| Disclosure-boundary | `.bitcode/v42-disclosure-boundary.json` | source-safe-preview, telemetry-redaction, generated-artifacts | no-protected-payload, source-safe-public | render-preview, stream-telemetry, generate-report | redaction receipts | V38/V41/V42 source-safe rules |
+| Proof-contract | `.bitcode/v42-proof-contract.json` | generated-reports, workflows, promotion | deterministic, workflow-bound, promotion-ready | generate, check, promote-dry-run | `.bitcode/*`, CI logs | protocol package and workflows |
+
+### Inference-synthesis
+
+- proofArtifactPath: `.bitcode/v42-inference-synthesis.json`
+- members: read-need, finding-fits, asset-pack-preview
+- theoremIds: need-exactness, many-fit-search, typed-output
+- replayStepIds: synthesize-need, search-depository, preview-pack
+- witnessArtifactPaths: pipeline receipts, prompt receipts, parser receipts
+- current member closure criteria: each inference step is registry-bound, typed, source-safe, and attached to the product state machine.
+- current member verdict shape: pass, fail, blocked, or repair-required.
+- current theorem-by-theorem closure reading: Need exactness, many-fit search, and typed output must independently pass.
+- current theorem-to-replay grouping: replay follows Need synthesis, Finding Fits, and preview generation.
+- minimum artifact/replay binding set: prompt lineage, execution id, parsed output id, and telemetry row id.
+- current proof-object fields: id, stage, agent, step, parser, verdict, proofRoot.
+- generated-artifact and test bindings: V42 pipeline product checks and V41 prompt-program reports.
+- fail-closed conditions: prompt contract incompleteness, parsed-envelope inadmissibility, and no-survivor asset pack.
+
+### Prompt-completeness
+
+- proofArtifactPath: `.bitcode/v42-prompt-completeness.json`
+- members: prompt-registry, tool-prompts, parser-prompts
+- theoremIds: registry-totality, interpolation-totality
+- replayStepIds: resolve-prompt, parse-output
+- witnessArtifactPaths: V41 prompt inventory, registry interpolation reports
+- current member closure criteria: every prompt involved in the MVP path is catalogued and validated.
+- current member verdict shape: pass, fail, blocked, or repair-required.
+- current theorem-by-theorem closure reading: registry and interpolation totality are checked before inference.
+- current theorem-to-replay grouping: prompt resolution precedes parser validation.
+- minimum artifact/replay binding set: prompt id, part ids, interpolation keys, parser id.
+- current proof-object fields: promptId, registryId, interpolationKeys, parserId, verdict.
+- generated-artifact and test bindings: V41 prompt reports and V42 gate checks.
+- fail-closed conditions: prompt contract incompleteness and protected prompt disclosure.
+
+### Static-code-analysis
+
+- proofArtifactPath: `.bitcode/v42-static-code-analysis.json`
+- members: routes, packages, workflows
+- theoremIds: no-versioned-routes, no-demo-import, no-secret-values
+- replayStepIds: lint, typecheck, import-scan
+- witnessArtifactPaths: CI logs and local command output
+- current member closure criteria: changed code is typechecked, lintable, import-safe, and source-safe.
+- current member verdict shape: pass, fail, blocked, or repair-required.
+- current theorem-by-theorem closure reading: route naming, dependency direction, and secret safety must pass.
+- current theorem-to-replay grouping: static checks run before integration checks.
+- minimum artifact/replay binding set: command, branch, commit, output summary.
+- current proof-object fields: checkId, command, files, verdict, proofRoot.
+- generated-artifact and test bindings: gate-quality and canon-quality workflows.
+- fail-closed conditions: stale promoted status truth, source import violation, and secret exposure.
+
+### Verification-decisions
+
+- proofArtifactPath: `.bitcode/v42-verification-decisions.json`
+- members: deposit-admission, need-review, fit-selection
+- theoremIds: authority-checked, source-safe, replayable
+- replayStepIds: admit-deposit, accept-need, rank-fits
+- witnessArtifactPaths: route receipts, API receipts, pipeline receipts
+- current member closure criteria: each user-visible decision has source-safe reason, authority proof, and replay id.
+- current member verdict shape: accepted, rejected, blocked, or repair-required.
+- current theorem-by-theorem closure reading: authority, source safety, and replayability are independent gates.
+- current theorem-to-replay grouping: decision receipts replay in product order.
+- minimum artifact/replay binding set: transaction id, decision id, principal id, proofRoot.
+- current proof-object fields: decisionKind, actor, inputRoot, outputRoot, verdict.
+- generated-artifact and test bindings: V42 product state machine and API tests.
+- fail-closed conditions: invalid deposit, authorization denial, and missing Need acceptance.
+
+### Selection-and-materialization
+
+- proofArtifactPath: `.bitcode/v42-selection-materialization.json`
+- members: selected-fits, preview, withheld-source
+- theoremIds: no-source-before-settlement, delivery-lock
+- replayStepIds: synthesize-preview, lock-source
+- witnessArtifactPaths: preview receipts, storage lock receipts
+- current member closure criteria: selected fits produce preview metadata while source-bearing content is locked.
+- current member verdict shape: pass, fail, blocked, or repair-required.
+- current theorem-by-theorem closure reading: preview and source lock must both pass before quote settlement.
+- current theorem-to-replay grouping: selected fit replay precedes source lock replay.
+- minimum artifact/replay binding set: selectedFitIds, previewRoot, lockRoot, quoteRoot.
+- current proof-object fields: assetPackId, previewRoot, lockRoot, disclosureTier, verdict.
+- generated-artifact and test bindings: V39 preview law and V42 Gate 5/6 checks.
+- fail-closed conditions: public projection overexposure and unpaid AssetPack source exposure.
+
+### Authorization-and-sensitive-flow
+
+- proofArtifactPath: `.bitcode/v42-authorization-sensitive-flow.json`
+- members: account, org, wallet, repo
+- theoremIds: authority-preserved, policy-fail-closed
+- replayStepIds: check-policy, check-wallet, check-repo
+- witnessArtifactPaths: policy receipts and authorization logs
+- current member closure criteria: each sensitive action verifies the principal, organization, wallet, and repository boundary.
+- current member verdict shape: allowed, denied, blocked, or repair-required.
+- current theorem-by-theorem closure reading: policy and wallet/repository authority cannot be inferred from UI state alone.
+- current theorem-to-replay grouping: policy replay gates settlement and delivery replay.
+- minimum artifact/replay binding set: principal id, policy id, wallet id, repo id.
+- current proof-object fields: actor, policy, resource, decision, proofRoot.
+- generated-artifact and test bindings: Auxillaries, auth, BTD, route tests.
+- fail-closed conditions: authorization denial, wallet authority mismatch, and private payload leakage.
+
+### Settlement-source-to-shares
+
+- proofArtifactPath: `.bitcode/v42-settlement-source-to-shares.json`
+- members: quote, settlement, rights, compensation
+- theoremIds: conservation, finality, rights-transfer
+- replayStepIds: quote, observe, transfer, allocate
+- witnessArtifactPaths: ledger receipts, database projections, storage locks
+- current member closure criteria: quote, settlement, rights, and compensation rows reconcile exactly.
+- current member verdict shape: pass, fail, blocked, or repair-required.
+- current theorem-by-theorem closure reading: BTC finality, BTD rights transfer, and source-to-shares conservation must all pass.
+- current theorem-to-replay grouping: settlement observation gates transfer and allocation.
+- minimum artifact/replay binding set: quoteRoot, txid, rightsReceiptId, allocationRoot.
+- current proof-object fields: quote, settlement, finality, rights, allocation, verdict.
+- generated-artifact and test bindings: BTD tests, ledger/storage sync checks, V42 Gate 6.
+- fail-closed conditions: settlement conservation drift and stale promoted status truth.
+
+### Disclosure-boundary
+
+- proofArtifactPath: `.bitcode/v42-disclosure-boundary.json`
+- members: source-safe-preview, telemetry-redaction, generated-artifacts
+- theoremIds: no-protected-payload, source-safe-public
+- replayStepIds: render-preview, stream-telemetry, generate-report
+- witnessArtifactPaths: UI snapshots, telemetry rows, generated artifacts
+- current member closure criteria: collapsed and expanded UI states remain source-safe before settlement.
+- current member verdict shape: pass, fail, blocked, or repair-required.
+- current theorem-by-theorem closure reading: preview, telemetry, and generated proof disclosure are separately checked.
+- current theorem-to-replay grouping: UI replay and generated artifact replay share disclosure tiers.
+- minimum artifact/replay binding set: disclosureTier, redactionReceipt, component, artifactPath.
+- current proof-object fields: visibilityTier, payloadKind, redaction, verdict, proofRoot.
+- generated-artifact and test bindings: V38/V41 telemetry and V42 UI tests.
+- fail-closed conditions: public projection overexposure and protected prompt/source leakage.
+
+### Proof-contract
+
+- proofArtifactPath: `.bitcode/v42-proof-contract.json`
+- members: generated-reports, workflows, promotion
+- theoremIds: deterministic, workflow-bound, promotion-ready
+- replayStepIds: generate, check, promote-dry-run
+- witnessArtifactPaths: `.bitcode/*`, workflow logs, `BITCODE_SPEC_V42_PROVEN.md`
+- current member closure criteria: every V42 gate artifact is deterministic, checked, documented, and workflow-bound.
+- current member verdict shape: pass, fail, blocked, or repair-required.
+- current theorem-by-theorem closure reading: generated proof, workflow proof, and promotion proof must all pass.
+- current theorem-to-replay grouping: generation and checking precede promotion dry-run.
+- minimum artifact/replay binding set: artifact path, generator command, checker command, workflow job.
+- current proof-object fields: artifactPath, command, workflow, verdict, proofRoot.
+- generated-artifact and test bindings: V42 promotion readiness and canon promotion workflow.
+- fail-closed conditions: missing artifact, stale promoted status truth, and failed promotion dry-run.
+
+## V42 generated canon
+
+### Inherited V19 reproducible-canon artifacts
+
+V42 inherits byte-stable generated proof expectations, deterministic replay posture, and promotion artifact discipline from V19.
+
+### Inherited V20 operator-quality artifacts
+
+V42 inherits operator-quality expectations for browser proof, accessibility, visual checks, performance posture, and operator acceptance from V20.
+
+### Exact generated-artifact inventory matrix
+
+| Artifact path | Producer | Disclosure posture | V42 role |
+| --- | --- | --- | --- |
+| `.bitcode/v42-spec-family-report.json` | `check-bitcode-spec-family` | source-safe metadata | draft/promotion spec family proof |
+| `.bitcode/v42-canonical-input-report.json` | `check-bitcode-canonical-inputs` | source-safe metadata | canonical input proof |
+| `.bitcode/v42-canon-posture-drift-report.json` | `check-bitcode-canon-posture-drift` | source-safe metadata | active V41 / draft V42 posture proof |
+| `.bitcode/v42-depositing-shortest-path.json` | V42 Gate 2 | source-safe metadata | deposit MVP proof |
+| `.bitcode/v42-reading-state-machine.json` | V42 Gate 3 | source-safe metadata | Reading product state proof |
+| `.bitcode/v42-readneed-review-resynthesis.json` | V42 Gate 4 | source-safe metadata | Need review proof |
+| `.bitcode/v42-readfitsfinding-preview-quote.json` | V42 Gate 5 | source-safe metadata | Finding Fits, preview, and quote proof |
+| `.bitcode/v42-settlement-rights-delivery.json` | V42 Gate 6 | source-safe metadata | settlement/delivery proof |
+| `.bitcode/v42-ai-reading-demonstration.json` | V42 Gate 7 | source-safe metadata | demonstration value proof |
+| `.bitcode/v42-local-staging-mvp-rehearsal.json` | V42 Gate 8 | source-safe metadata | local/staging rehearsal proof |
+| `.bitcode/v42-promotion-readiness-report.json` | V42 Gate 9 | source-safe metadata | promotion readiness proof |
+
+### V42 specifying generated artifacts
+
+V42 specifying artifacts must be generated from code or deterministic scripts, committed only when source-safe, and checked by gate-quality and canon-quality workflows.
+
+### Shared generated-artifact fields
+
+Shared fields are artifact id, schema id, version, current target, source roots, validation commands, proof roots, generated at policy, disclosure posture, and verdict.
+
+### Artifact-specific generated payload fields
+
+Artifact-specific fields include deposit ids, Reading stage ids, prompt/parser ids, selected fit roots, quote roots, settlement roots, delivery roots, AI baseline ids, benchmark ids, and rehearsal ids.
+
+### Artifact confidentiality and disclosability taxonomy
+
+Allowed public payloads are ids, hashes, counts, statuses, source-safe summaries, measurement scores, proof roots, and redaction verdicts.
+Forbidden payloads are secrets, wallet private material, private settlement payloads, protected source, raw provider responses, protected prompt payloads, and unpaid AssetPack source.
+
+### Minimum generated appendix rendered contents
+
+The generated `BITCODE_SPEC_V42_PROVEN.md` must include aggregate proof verdict, exact proof-family inventory, exact per-family member inventory, exact per-family theorem inventory, exact replay-step inventories and theorem bindings, witness artifact inventories, generated artifact inventories, scenario and run coverage matrices, proof-source commit, and fail closed when any required proof is missing.
+
+### Canonical regeneration and fail-closed posture
+
+Promotion must fail closed when generated artifacts are missing, stale, non-deterministic, source-unsafe, disconnected from workflow checks, or inconsistent with `BITCODE_SPEC.txt`.
+
+## V42 validation canon
+
+Validation must include:
+
+- `node scripts/check-bitcode-spec-family.mjs --version V42 --mode draft --current-target V41`;
+- `node scripts/check-v42-gate1-mvp-experience-roadmap-opening.mjs`;
+- later V42 gate checks as each gate opens;
+- route/API/unit/integration/browser checks appropriate to each product behavior gate;
+- local and staging-testnet rehearsal checks before promotion.
+
+## V42 promotion canon
+
+V42 promotion requires all V42 gates closed, all generated artifacts deterministic and source-safe, gate-quality and canon-quality workflows green, `BITCODE_SPEC_V42_PROVEN.md` generated, active V42 / draft V43 runtime posture prepared, and value-bearing mainnet operations explicitly blocked unless later canon admits them.
+
+## V42 appendices and canonical supporting material
+
+Supporting material includes `BITCODE_SPEC_V42_DELTA.md`, `BITCODE_SPEC_V42_NOTES.md`, `BITCODE_SPEC_V42_PARITY_MATRIX.md`, package READMEs, root README, `SPECIFICATIONS_ROADMAP.md`, workflow files, generated `.bitcode/` artifacts, and protocol-demonstration documents.
+
+## V42 accepted boundaries and reopen conditions
+
+Accepted boundaries:
+
+- V42 Gate 1 is specification and validation posture only.
+- V42 may refine `/terminal` but does not split `/read` and `/deposit`.
+- V42 may improve exchange-to-pack language where user-facing clarity requires it, but full `/exchange` to `/packs` route rename is deferred to V43+.
+- V42 may update demonstration only inside `protocol-demonstration/`.
+
+Reopen conditions:
+
+- a route, pipeline, or generated artifact exposes protected source or unpaid AssetPack source;
+- Need review is bypassed before Finding Fits;
+- settlement or BTD rights transfer is claimed without ledger/database/storage reconciliation;
+- AI-reading demonstration cannot prove improvement beyond public-data-only baseline;
+- workflow posture allows stale V42 artifacts to pass.
+
+## V42 completion condition
+
+V42 closes when the reliable MVP product experience is fully specified, implemented, tested, source-safe, rehearsed locally and in staging-testnet, documented, generated, workflow-checked, and promotion-ready across Depositing, Reading, Finding Fits, AssetPack preview, BTD/BTC settlement, repository delivery, depositor compensation visibility, and the AI-reading dominant demonstration.
+
+## Appendix A. Canonical type and surface catalog
+
+Canonical types include Depositing session, source admission proof, Depository record, compensation route preview, Read Request, synthesized Need, Need review decision, accepted Need, Finding Fits request, candidate fit deposit, selected fit set, AssetPack preview, BTD/BTC quote, settlement receipt, BTD rights transfer, repository delivery receipt, AI-reading baseline, AI-reading improved result, telemetry row, proof root, and repair posture.
+
+## Appendix B. Proof family closure catalog
+
+V42 proof families close through the exact proof-family inventory matrix and per-family sections above.
+
+## Appendix C. Generated artifact contract catalog
+
+V42 generated artifacts are source-safe, deterministic, workflow-bound, and promotion-blocking when stale.
+
+## Appendix D. Validation and checking gate catalog
+
+V42 gate validation starts with `check:v42-gate1` and expands gate by gate into package tests, route tests, browser tests, rehearsal scripts, and promotion readiness checks.
+
+## Appendix E. Current canonical source map
+
+Current source roots are `packages/protocol`, `packages/btd`, `packages/pipelines/asset-pack`, `packages/pipeline-hosts`, `packages/prompts`, `packages/tools-generics`, `packages/observability`, `packages/github`, `uapi`, `.github/workflows`, `scripts`, and `protocol-demonstration`.
+
+## Appendix F. Subsystem totality and derivability matrix
+
+V42 must cover repo supply and depositing, reading and measured demand, prompt/inference/evaluator ownership, deposit-to-read fit, recall and ranking, verification decisions, selection and materialization, branch artifacts and assetPackEvidence, identity, authority, signing, and policy, sensitive data and confidentiality flows, projection, disclosure, and redaction, proof families, members, theorems, witnesses, and replay, settlement, source-to-shares, journals, and exact accounting, telemetry, persistence, state, and failure semantics, host/runtime capability truth, operator experience and pedagogy, validation and test stack, and generated artifacts and canonical promotion.
+
+## Appendix G. Canonical file-family and promotion contract catalog
+
+V42 file-family contracts are `BITCODE_SPEC_V42.md`, `BITCODE_SPEC_V42_DELTA.md`, `BITCODE_SPEC_V42_NOTES.md`, `BITCODE_SPEC_V42_PARITY_MATRIX.md`, and eventual `BITCODE_SPEC_V42_PROVEN.md`.
+
+## Appendix H. Operator surface and quality contract catalog
+
+Operator surfaces include `/terminal`, depositing controls, Reading controls, execution stream rows, settlement panels, delivery receipts, Auxillaries wallet/organization surfaces, demonstration pages, and generated proof reports.
+
+## Appendix I. Scenario, workflow, and cross-product contract catalog
+
+V42 scenario coverage must include auth-issuer-rollback, privacy-boundary-proof-export, polyglot-gateway-benchmark-remediation, auth-many-asset-normalization, Targeted deposit, Normalization deposit, patch, context, public, buyer, reviewer, internal, Openly writable, Measurably readable, Provable, and Valuable workflows.
+
+## Appendix J. Fail-closed contract and error posture matrix
+
+V42 fails closed on invalid deposit, prompt contract incompleteness, parsed-envelope inadmissibility, no-survivor asset pack, authorization denial, public projection overexposure, settlement conservation drift, stale promoted status truth, source leakage, missing Need review, missing settlement finality, and repository delivery authorization failure.
+
+## Appendix K. Source-bearing AssetPack and artifact contract catalog
+
+Source-bearing contracts include `.bitcode/asset-pack.lock.json`, `.bitcode/selected-source-material.json`, `.bitcode/verification-report.json`, `.bitcode/source-to-shares.json`, `.bitcode/projection-policy.json`, `.bitcode/system-proof-bundle.json`, and `BITCODE_SPEC_V42_PROVEN.md`.
+These contracts keep full AssetPack source withheld until settlement, BTD rights transfer, and delivery unlock.
diff --git a/BITCODE_SPEC_V42_DELTA.md b/BITCODE_SPEC_V42_DELTA.md
new file mode 100644
index 00000000..54ceb8db
--- /dev/null
+++ b/BITCODE_SPEC_V42_DELTA.md
@@ -0,0 +1,85 @@
+# Bitcode Spec V42 Delta
+
+## Status
+
+- Version: `V42`
+- V42 state: draft opened; this delta records the planned V41-to-V42 reliable MVP experience work
+- Current canonical/latest target: `V41`
+- Prior canonical anchor: `BITCODE_SPEC_V41.md`
+- Prior generated proof appendix: `BITCODE_SPEC_V41_PROVEN.md`
+- Generated structured artifact inventory: draft `.bitcode/v42-spec-family-report.json`, `.bitcode/v42-canonical-input-report.json`, `.bitcode/v42-canon-posture-drift-report.json`, and later V42 gate artifacts for Depositing, Reading, Finding Fits, settlement/delivery, AI-reading demonstration, local/staging rehearsal, and promotion readiness
+- Source parity state: V42 source parity is opened by Gate 1 and remains incomplete until later gates implement the product paths
+- Scope: V42 draft delta for reliable MVP product experience over promoted V41 prompt-program excellence canon
+
+## Why V42 exists
+
+V42 turns the promoted V39 Reading product, V40 testing depth, and V41 prompt-program excellence into a reliable MVP enterprise experience.
+The version focuses on shortest-path Depositing, shortest-path Reading, settlement-gated AssetPack delivery, depositor compensation visibility, and an AI-reading dominant demonstration that proves AssetPacks improve an AI system beyond public-data-only baseline performance.
+
+## Accepted V42 decisions
+
+- V42 starts from active `V41` canon and keeps `BITCODE_SPEC.txt` at `V41` until promotion.
+- V42 product work stays unversioned in source paths.
+- Depositing must minimize the path to Depository admission proof and future compensation visibility.
+- Reading must use five product steps: request read, review synthesized Need, request Finding Fits, review source-safe AssetPack preview, and buy/settle/deliver AssetPack.
+- `ReadNeedComprehensionSynthesis` and `ReadFitsFindingSynthesis` remain the formal Reading pipeline names.
+- Source-bearing AssetPack content remains withheld until BTC settlement, BTD rights transfer, and storage/delivery reconciliation.
+- The demonstration remains self-contained in `protocol-demonstration/` and must prove AI-reading value without importing commercial code.
+
+## V42 gate plan
+
+### Gate 1: MVP Experience Roadmap And Spec Opening
+
+Open the V42 full specification family, roadmap, package script, workflow posture, documentation posture, branch convention, and checker.
+
+### Gate 2: Depositing Shortest Path And Compensation Visibility
+
+Implement and prove the shortest path from source material to Depository admission proof and later compensation readback.
+
+### Gate 3: Reading Shortest Path State Machine
+
+Implement and prove the five-step Reading product state machine with low-detail defaults and expandable proof/telemetry detail.
+
+### Gate 4: ReadNeed Review And Resynthesis Product Closure
+
+Implement and prove reviewed synthesized Need flow, feedback/resynthesis, accepted-Need admission, storage projection, telemetry, and UI readback.
+
+### Gate 5: ReadFitsFinding AssetPack Preview And Quote Closure
+
+Implement and prove many-candidate Depository search, selected-fit provenance, source-safe AssetPack preview, deterministic BTD/BTC quote, and no pre-settlement source leakage.
+
+### Gate 6: Settlement Rights Transfer And Repository Delivery Closure
+
+Implement and prove purchase, settlement observation, BTD rights transfer, source unlock, repository pull request delivery, compensation accounting, and repair posture.
+
+### Gate 7: AI-Reading Dominant Demonstration MVP
+
+Implement and prove the standalone demonstration where deposited technical intelligence improves an AI system beyond a public-data-only baseline.
+
+### Gate 8: Local And Staging-Testnet Full MVP Rehearsal
+
+Run and prove the complete MVP path locally and in staging-testnet with value-bearing mainnet blocked.
+
+### Gate 9: V42 Promotion Readiness
+
+Bind every V42 product artifact, workflow, generated proof, promotion command, source-safety result, and active V42 / draft V43 runtime posture.
+
+## Explicitly deferred
+
+- V43+ agentic deposit AssetPack option synthesis remains deferred.
+- `/terminal` is not split into `/read` and `/deposit` during V42.
+- `/exchange` is not renamed to `/packs` during V42.
+- Production-mainnet value-bearing operation remains blocked unless a later promoted canon explicitly admits it.
+- V42 Gate 1 does not change route behavior, pipeline behavior, settlement behavior, or demonstration behavior.
+
+## Pre-Implementation Sequence
+
+1. Open `version/v42` and `v42/gate-1-mvp-experience-roadmap-opening`.
+2. Keep `BITCODE_SPEC.txt` at `V41`.
+3. Add the V42 spec family and Gate 1 checker.
+4. Update roadmap, docs, package scripts, and workflows for active V41 / draft V42.
+5. Validate V42 draft family and V41 active posture.
+
+## Commit-Body Direction
+
+V42 commits should name the product path, protocol object, pipeline or route ownership, source-safety boundary, generated artifact or checker, and tests run.
diff --git a/BITCODE_SPEC_V42_NOTES.md b/BITCODE_SPEC_V42_NOTES.md
new file mode 100644
index 00000000..9d79f471
--- /dev/null
+++ b/BITCODE_SPEC_V42_NOTES.md
@@ -0,0 +1,80 @@
+# Bitcode Spec V42 Notes
+
+## Status
+
+- Version: `V42`
+- V42 state: draft opened; notes track reliable MVP experience planning over active V41
+- Current canonical/latest target: `V41`
+- Prior canonical anchor: `BITCODE_SPEC_V41.md`
+- Prior generated proof appendix: `BITCODE_SPEC_V41_PROVEN.md`
+- Generated structured artifact inventory: draft `.bitcode/v42-spec-family-report.json`, `.bitcode/v42-canonical-input-report.json`, `.bitcode/v42-canon-posture-drift-report.json`, and later V42 gate artifacts
+- Source parity state: notes are source-facing planning until later gates implement and prove product behavior
+- Scope: V42 notes for reliable MVP product experience
+
+## Notes companion rule
+
+This notes companion records the working V42 product plan and simplified reading.
+It does not override `BITCODE_SPEC_V42.md`.
+Product behavior changes remain blocked until the relevant V42 gate admits and verifies them.
+
+## V42 Gate 1 opening note
+
+Gate 1 is intentionally specification, documentation, workflow, and checker posture only.
+It opens the reliable MVP experience version after V41 prompt-program promotion and prepares later gates to implement Depositing, Reading, settlement, delivery, and demonstration behavior without ad hoc scope drift.
+
+## Depositing shortest-path note
+
+The V42 Depositing path should minimize the journey from source material to Depository admission proof.
+The user needs to know that the source is admitted, searchable for future Need-Fit work, and eligible for BTC compensation if it contributes to a synthesized AssetPack.
+The UX can stay simple, but expandable details must show source authority, admission proof, storage projection, search-document posture, compensation route, and repair state.
+
+## Reading shortest-path note
+
+The V42 Reading path should be a five-step enterprise flow:
+
+1. request read;
+2. review synthesized Need;
+3. request Finding Fits;
+4. review source-safe AssetPack measurements and preview metadata;
+5. buy, settle, transfer rights, and receive repository delivery.
+
+The default UI should be guided and low-detail.
+The rich execution log, proof roots, telemetry rows, and ledger/storage details remain available on expansion.
+
+## AssetPack source-safety note
+
+V42 must make the preview valuable without leaking the source-bearing AssetPack before settlement.
+Readers may see measurements, fit confidence, quote posture, selected-fit provenance summaries, proof roots, and source-safe explanations.
+They may not see protected source, raw provider responses, protected prompts, private settlement payloads, wallet private material, or unpaid AssetPack source before BTC settlement and BTD rights transfer.
+
+## AI-reading demonstration note
+
+The standalone demonstration should prove why Bitcode matters for AI-dominant Reading.
+A deposited proprietary or otherwise non-public technical intelligence source should contribute to an AssetPack that measurably improves an AI system's training, prompt/context, or evaluation result beyond what a public-data-only baseline can do.
+The demonstration must remain minimal, local, deterministic where feasible, and self-contained inside `protocol-demonstration/`.
+
+## V43+ agentic depositing roadmap note
+
+V43 or a later explicitly opened version should evolve the deposit side into an agentic AssetPack option experience for enterprises.
+Repository-installed Bitcode Agents should compare a connected enterprise codebase, the current Bitcode Depository, and Reading activity to propose deposit AssetPack options.
+Those options should be source-safe, sub-critical, likely positive ROI, and approve/rejectable before Depository admission.
+That later version should split `/terminal` into `/read` and `/deposit`, and rename `/exchange` to `/packs` across routes, code naming, docs, and operator vocabulary.
+
+## Concise current-system reading
+
+Bitcode is active at V41.
+V42 drafts the next canon: the reliable MVP experience for enterprise Depositing and Reading.
+The central product promise is that a user can deposit source, request a read, review a synthesized Need, find fitting Depository sources, preview a source-safe AssetPack, pay in BTC/BTD settlement terms, receive rights, and get repository delivery.
+
+## Simplified-spec reading rule
+
+Read V42 as shortest credible paths over existing protocol law.
+If a product step cannot be routed, stored, replayed, telemetered, proven, and source-safely explained, it is not V42-ready.
+
+## Non-goals during V42 opening
+
+- Do not implement product behavior in Gate 1.
+- Do not split `/terminal` or rename `/exchange`.
+- Do not expose protected source or unpaid AssetPack source.
+- Do not bypass Need review before Finding Fits.
+- Do not claim settlement, BTD rights transfer, or repository delivery without synchronized ledger/database/storage proof.
diff --git a/BITCODE_SPEC_V42_PARITY_MATRIX.md b/BITCODE_SPEC_V42_PARITY_MATRIX.md
new file mode 100644
index 00000000..3c22230a
--- /dev/null
+++ b/BITCODE_SPEC_V42_PARITY_MATRIX.md
@@ -0,0 +1,70 @@
+# Bitcode Spec V42 Parity Matrix
+
+## Status
+
+- Version: `V42`
+- V42 state: draft opened; parity tracks reliable MVP experience gaps and closure gates over active V41
+- Current canonical/latest target: `V41`
+- Prior canonical anchor: `BITCODE_SPEC_V41.md`
+- Prior generated proof appendix: `BITCODE_SPEC_V41_PROVEN.md`
+- Generated structured artifact inventory: draft `.bitcode/v42-spec-family-report.json`, `.bitcode/v42-canonical-input-report.json`, `.bitcode/v42-canon-posture-drift-report.json`, and later V42 gate artifacts
+- Source parity state: Gate 1 parity is documentation/checker/workflow posture; product behavior rows remain draft-required until their gates close
+- Scope: V42 parity ledger for reliable MVP product experience
+
+## Purpose
+
+This matrix records the reliable MVP product surfaces that must become promotion-grade before V42 can replace V41 as active canon.
+
+## Audit basis
+
+- `BITCODE_SPEC.txt` -> `V41`
+- `BITCODE_SPEC_V41.md`
+- `BITCODE_SPEC_V41_PROVEN.md`
+- `BITCODE_SPEC_V42.md`
+- `BITCODE_SPEC_V42_DELTA.md`
+- `BITCODE_SPEC_V42_NOTES.md`
+- commercial product routes, packages, pipelines, BTD/ledger code, generated artifacts, workflows, and `protocol-demonstration/`
+
+## V42 implementation matrix
+
+| Area | Required V42 result | Source evidence | Judgment |
+| --- | --- | --- | --- |
+| Draft family | V42 SPEC, DELTA, NOTES, and PARITY files exist over active V41 | `BITCODE_SPEC_V42.md` family | drafted |
+| Roadmap truth | Roadmap states V41 active and V42 draft reliable MVP experience | `SPECIFICATIONS_ROADMAP.md` | drafted |
+| Gate workflow | Gate quality knows active V41 / draft V42 posture and V42 Gate 1 | `.github/workflows/bitcode-gate-quality.yml` | drafted |
+| Canon workflow | Canon quality knows active V41 / draft V42 posture and V42 Gate 1 | `.github/workflows/bitcode-canon-quality.yml` | drafted |
+| Depositing shortest path | Source material can be admitted with Depository proof and compensation visibility | later V42 Gate 2 artifact | draft-required |
+| Reading state machine | Five-step Reading UX is route-owned, persistent, and source-safe | later V42 Gate 3 artifact | draft-required |
+| ReadNeed product closure | Need synthesis, review, feedback, resynthesis, and accepted-Need admission are product-ready | later V42 Gate 4 artifact | draft-required |
+| Finding Fits preview and quote | Many-candidate search, selected-fit provenance, source-safe preview, and quote are product-ready | later V42 Gate 5 artifact | draft-required |
+| Settlement and delivery | BTC/BTD settlement, rights transfer, compensation, and repository PR delivery are synchronized | later V42 Gate 6 artifact | draft-required |
+| AI-reading demonstration | Standalone demonstration proves AssetPack improves AI beyond public-data-only baseline | later V42 Gate 7 artifact | draft-required |
+| Local/staging rehearsal | Full MVP path rehearsed locally and in staging-testnet with mainnet blocked | later V42 Gate 8 artifact | draft-required |
+| Promotion readiness | V42 proof and workflow promotion ready | later V42 Gate 9 artifact | draft-required |
+
+## V42 implementation checklist
+
+| Area | Closure requirement | Judgment |
+| --- | --- | --- |
+| Gate 1 | Open V42 family, roadmap, docs, workflow posture, package script, and checker | drafted |
+| Gate 2 | Depositing shortest path and compensation visibility artifact | draft-required |
+| Gate 3 | Reading shortest path state machine artifact | draft-required |
+| Gate 4 | ReadNeed review and resynthesis product closure artifact | draft-required |
+| Gate 5 | ReadFitsFinding AssetPack preview and quote closure artifact | draft-required |
+| Gate 6 | Settlement rights transfer and repository delivery closure artifact | draft-required |
+| Gate 7 | AI-reading dominant demonstration MVP artifact | draft-required |
+| Gate 8 | Local and staging-testnet full MVP rehearsal artifact | draft-required |
+| Gate 9 | Promotion readiness artifact and workflow | draft-required |
+
+## V42 accepted boundaries
+
+V42 Gate 1 may open specification, workflow, docs, and validation posture.
+It may not implement route, pipeline, settlement, or demonstration behavior.
+
+V42 later gates may implement product behavior only if source-safe disclosure, Need review, BTD/BTC settlement, depositor compensation, repository delivery, telemetry, and generated proof obligations are represented in tests and artifacts.
+
+V42 may not split `/terminal` into `/read` and `/deposit`, and may not rename `/exchange` to `/packs`; those are V43+ roadmap items unless explicitly reopened.
+
+## V42 completion condition
+
+V42 closes when reliable MVP Depositing, Reading, Finding Fits, AssetPack preview, BTD/BTC settlement, repository delivery, compensation visibility, AI-reading demonstration, local/staging rehearsal, and promotion readiness are all specified, implemented, tested, generated, workflow-bound, source-safe, and promotion-ready.
diff --git a/README.md b/README.md
index 1e31bd6a..cd3295dc 100644
--- a/README.md
+++ b/README.md
@@ -1,8 +1,8 @@
# Bitcode Repository
`BITCODE_SPEC.txt` is the canonical pointer for active-system work. It currently
-resolves to `V40`; V41 is the active draft target for Prompt and PromptPart
-excellence after the promoted exhaustive commercial application testing canon.
+resolves to `V41`; V42 is the active draft target for reliable MVP product
+experience after the promoted Prompt and PromptPart excellence canon.
## Current Product Posture
@@ -81,12 +81,12 @@ dry-run support, gate/canon workflow posture, active V41 / draft V42 runtime
preparation, and source-safe value-bearing mainnet blocking through
`generate:v41-promotion-readiness`, `check:v41-promotion-readiness`, and
`check:v41-gate9`.
-V42 is now roadmapped as the next MVP experience version: shortest-path
-Depositing with later BTC compensation, shortest-path Reading through
-Need review/resynthesis, Finding Fits, source-safe AssetPack preview,
-BTD/BTC settlement, repository delivery, and an AI-reading dominant
-demonstration whose AssetPack measurably improves an AI system beyond
-public-data-only performance.
+V42 Gate 1 opens the reliable MVP experience specification family over active
+V41 with `check:v42-gate1`. V42 is scoped to shortest-path Depositing with
+later BTC compensation, shortest-path Reading through Need review/resynthesis,
+Finding Fits, source-safe AssetPack preview, BTD/BTC settlement, repository
+delivery, and an AI-reading dominant demonstration whose AssetPack measurably
+improves an AI system beyond public-data-only performance.
V43+ is roadmapped as the later agentic depositing evolution: repository
agents synthesize deposit AssetPack options from connected enterprise code,
Depository state, and Reading demand; enterprises approve or reject
@@ -710,9 +710,9 @@ or promotion validation.
## Key Surfaces
- [BITCODE_SPEC.txt](BITCODE_SPEC.txt) is the canonical version pointer.
-- [BITCODE_SPEC_V39.md](BITCODE_SPEC_V39.md) is the active promoted spec family.
-- [BITCODE_SPEC_V40.md](BITCODE_SPEC_V40.md) is the active draft target.
-- [BITCODE_SPEC_V40_PARITY_MATRIX.md](BITCODE_SPEC_V40_PARITY_MATRIX.md) tracks V40 gate parity.
+- [BITCODE_SPEC_V41.md](BITCODE_SPEC_V41.md) is the active promoted spec family.
+- [BITCODE_SPEC_V42.md](BITCODE_SPEC_V42.md) is the active draft target.
+- [BITCODE_SPEC_V42_PARITY_MATRIX.md](BITCODE_SPEC_V42_PARITY_MATRIX.md) tracks V42 gate parity.
- [uapi/README.md](uapi/README.md) documents the commercial website/API surface.
- [uapi/app/terminal/README.md](uapi/app/terminal/README.md) documents Terminal.
- [uapi/app/exchange/README.md](uapi/app/exchange/README.md) documents Exchange.
diff --git a/SPECIFICATIONS_ROADMAP.md b/SPECIFICATIONS_ROADMAP.md
index a47ba4f5..c652332a 100644
--- a/SPECIFICATIONS_ROADMAP.md
+++ b/SPECIFICATIONS_ROADMAP.md
@@ -2,12 +2,14 @@
## Status
-- Current active canonical pointer: `BITCODE_SPEC.txt` -> `V40`
-- Current active canon: `BITCODE_SPEC_V40.md`
-- Current draft target: `BITCODE_SPEC_V41.md`.
-- Current working gate: V41 Gate 9 Promotion Readiness.
-- Next queued gate after V41 Gate 9: V41 canonical promotion into `main`, then V42 MVP product experience opening.
-- Latest closed version: V40 Exhaustive Commercial Application Testing, which promoted test inventory, unit coverage, API integration contracts, Reading pipeline integration, Conversation/Terminal integration, browser E2E visual proof, ledger/database/storage/wallet/delivery synchronization, local/staging rehearsal automation, prompt benchmark smoke, and V40 promotion readiness.
+- Current active canonical pointer: `BITCODE_SPEC.txt` -> `V41`
+- Current active canon: `BITCODE_SPEC_V41.md`
+- Current draft target: `BITCODE_SPEC_V42.md`.
+- Current working gate: V42 Gate 1 MVP Experience Roadmap And Spec Opening.
+- Next queued gate after V42 Gate 1: V42 Gate 2 Depositing Shortest Path And Compensation Visibility.
+- Latest closed version: V41 Prompt And PromptPart Excellence, which promoted PromptPart and Prompt inventory, registry interpolation contracts, Reading prompt baselines, ReadNeedComprehensionSynthesis prompt hardening, ReadFitsFindingSynthesis prompt hardening, Conversation/tool/interface prompt rewrite, prompt benchmark telemetry, and V41 promotion readiness.
+- Recent V42 opening anchor: reliable MVP experience opens over promoted V41 with V42 SPEC, DELTA, NOTES, and PARITY files, `check:v42-gate1`, active V41 / draft V42 posture, and a nine-gate plan for shortest-path Depositing, five-step Reading, ReadNeed product closure, ReadFitsFinding preview and quote closure, settlement and repository delivery, AI-reading demonstration, local/staging rehearsal, and promotion readiness.
+- Recent V41 closure anchor: V41 canonical promotion updated `BITCODE_SPEC.txt` to `V41`, generated `BITCODE_SPEC_V41_PROVEN.md`, preserved active V41 / draft V42 runtime posture, and closed prompt-program excellence canon.
- Recent V40 closure anchor: V40 canonical promotion updated `BITCODE_SPEC.txt` to `V40`, generated `BITCODE_SPEC_V40_PROVEN.md`, preserved active V40 / draft V41 runtime posture, and closed exhaustive commercial application testing canon.
- Recent V39 closure anchor: V39 canonical promotion updated `BITCODE_SPEC.txt` to `V39`, generated `BITCODE_SPEC_V39_PROVEN.md`, preserved active V39 / draft V40 runtime posture, and closed commercial Reading readiness canon.
- V39 Gate 9 closure anchor: commercial Reading readiness now owns package-backed `ReadingInterfaceProductParity`, deterministic `.bitcode/v39-interface-conversation-product-parity.json`, Terminal/Conversation/API/MCP/ChatGPT/package-consumer no-bypass rows, source-safe contract readback, BTD interface root composition, focused package/interface tests, and workflow wiring through `check:v39-gate9`.
@@ -33,8 +35,7 @@
- V41 Gate 7 closure anchor: prompt-program work now owns package-backed `V41ConversationToolInterfacePromptRewrite` source, deterministic `.bitcode/v41-conversation-tool-interface-prompt-rewrite.json`, 9 source-safe rewrite rows, 60 passing source predicates, Conversation PTRR PromptPart rewrites, Terminal conversation system prompt boundaries, rich execution-log prompt/result disclosure, DocCodeToolPrompt and ToolPromptRegistry hierarchy, MCP API/public API contract prompt posture, ChatGPT App action/tool prompt posture, Terminal/public summary source-safety, Gate 2 through Gate 6 dependency roots, V38 Conversation/tool parity binding, protocol tests, workflow wiring, and `check:v41-gate7`.
- V41 Gate 8 closure anchor: prompt-program work now owns package-backed `V41PromptProgramBenchmarkReport` source, deterministic `.bitcode/v41-prompt-program-benchmark-report.json`, 9 source-safe benchmark telemetry rows, post-rewrite PromptPart and Prompt deltas, benchmark fixture projections, prompt registry lineage, V38 PromptBenchmark/Failsafe/Thricified/inference telemetry roots, V39 operational repair readback roots, V40 prompt benchmark smoke roots, V41 Gate 2 through Gate 7 dependency roots, rich execution-log telemetry projections, repair hook and parsed-output redaction posture, protocol tests, workflow wiring, and `check:v41-gate8`.
- V41 Gate 9 closure anchor: prompt-program work now owns package-backed `V41PromotionReadinessReport` source, deterministic `.bitcode/v41-promotion-readiness-report.json`, `BITCODE_SPEC_V41_PROVEN.md` generation support, `v41-canon-promotion.yml`, promotion command dry-run support, gate/canon workflow posture, active V41 / draft V42 runtime preparation, all V41 prompt-program artifacts covered, source-safe, parseable, and workflow-bound, and value-bearing mainnet admission blocked through `check:v41-gate9`.
-- Forward planning note: V41 should focus singularly on Prompt and PromptPart implementation quality: prompts as programs. V38's inference correctness hardening and V40's testing/benchmark depth should empower V41 to examine every raw PromptPart, every composed Prompt, every benchmark, every meaningfully benchmarkable semantic part, title, template, interpolation contract, registry binding, inference callsite, and downstream parsed return type; then repartition, retitle, rewrite, catalogue, and validate them across Reading pipelines and conversational interactions. V41 should primarily harden `ReadNeedComprehensionSynthesis` and `ReadFitsFindingSynthesis` prompt surfaces while also covering conversational and other inference prompts with the same catalogue-and-benchmark discipline.
-- Forward planning note: V42 should focus on the reliable MVP product experience after V41's prompt-program hardening. Depositing should become the shortest path to adding any source material, proving its Depository admission, and later receiving BTC compensation when that deposit contributes to a synthesized AssetPack. Reading should become the shortest path to submitting a Read Request, reviewing or resynthesizing Bitcode's synthesized Need, requesting Finding Fits, reviewing source-safe AssetPack measurements and preview metadata, buying the AssetPack through BTD/BTC settlement semantics, and receiving post-settlement repository delivery. The demonstration should be AI-reading dominant: any deposit source can contribute proprietary or otherwise non-public training, prompt, context, or evaluation material to an AssetPack that measurably improves an AI system beyond a public-data-only baseline.
+- Forward planning note: V42 focuses on the reliable MVP product experience after V41's prompt-program hardening. Depositing should become the shortest path to adding any source material, proving its Depository admission, and later receiving BTC compensation when that deposit contributes to a synthesized AssetPack. Reading should become the shortest path to submitting a Read Request, reviewing or resynthesizing Bitcode's synthesized Need, requesting Finding Fits, reviewing source-safe AssetPack measurements and preview metadata, buying the AssetPack through BTD/BTC settlement semantics, and receiving post-settlement repository delivery. The demonstration should be AI-reading dominant: any deposit source can contribute proprietary or otherwise non-public training, prompt, context, or evaluation material to an AssetPack that measurably improves an AI system beyond a public-data-only baseline.
- Forward planning note: V43+ should evolve the deposit side into an agentic AssetPack option experience for enterprises that own connected codebases. Bitcode Agents installed on an enterprise repository should compare the repository, the current Bitcode Depository, and current Reading activity to propose deposit AssetPack options: unminted AssetPacks in all but BTD that can later become BTD only when a Reader's industrial Need-Fit mints one. The deposit pipeline should optimize for enterprise IP governance by filtering out critical IP, estimating whether selling would be positive ROI against development cost and expected Read demand, and presenting everything else as approve/reject deposit options. The product route plan for that version is to split `/terminal` into `/read` for Reading and `/deposit` for agentic deposit AssetPack option review, and to rename `/exchange` to `/packs` across routes, code names, and docs.
- V34 Gate 2 closure anchor: deployment-depth now owns package-backed `DeploymentHostCapabilityCatalog` and `EnvironmentLaneContract` source, deterministic `.bitcode/v34-deployment-host-capability-catalog.json` and `.bitcode/v34-environment-lane-contracts.json`, and visible `value-bearing-mainnet` blocking through `blocked_future_canon_required`.
- V34 Gate 3 closure anchor: deployment-depth now owns package-backed `DistributedExecutionRuntimeReceipt` source, deterministic `.bitcode/v34-distributed-execution-runtime-receipts.json`, `request_response_not_required` long-running work posture, and source-safe roots for pipeline, PTRR agent, ThricifiedGeneration, tool, ledger, wallet, proof, object-storage, and repair work.
@@ -106,9 +107,9 @@ They are referenced here for specification history only; active implementation w
## Source Families
- Legacy ENGI specifications: `_legacy/ENGI_SPEC_V1.md` through `_legacy/ENGI_SPEC_V25.md`, with companion `NOTES`, `DELTA`, `PARITY_MATRIX`, `SYSTEM_PARITY_MATRIX`, `PROVEN`, and audit files where present.
-- Active Bitcode specifications: `BITCODE_SPEC_V40.md`, with companion `DELTA`, `NOTES`, `PARITY_MATRIX`, and `PROVEN` files.
-- Promoted Bitcode history: `BITCODE_SPEC_V26.md` through `BITCODE_SPEC_V39.md`, with companion `DELTA`, `NOTES`, `PARITY_MATRIX`, and `PROVEN` files.
-- Draft and future Bitcode specifications: `BITCODE_SPEC_V41.md`, with companion `DELTA`, `NOTES`, and `PARITY_MATRIX` files, as the active draft target over promoted V40; planned V42 follows V41 as the MVP Depositing, Reading, and AI-reading demonstration experience version.
+- Active Bitcode specifications: `BITCODE_SPEC_V41.md`, with companion `DELTA`, `NOTES`, `PARITY_MATRIX`, and `PROVEN` files.
+- Promoted Bitcode history: `BITCODE_SPEC_V26.md` through `BITCODE_SPEC_V40.md`, with companion `DELTA`, `NOTES`, `PARITY_MATRIX`, and `PROVEN` files.
+- Draft and future Bitcode specifications: `BITCODE_SPEC_V42.md`, with companion `DELTA`, `NOTES`, and `PARITY_MATRIX` files, as the active draft target over promoted V41; planned V43+ follows V42 as the agentic deposit-side AssetPack option and route-split evolution.
- Specification discipline references: `BITCODE_SPECIFYING.md` and `BITCODE_SPEC_TEMPLATEGUIDE.md`.
## Roadmap
@@ -154,9 +155,9 @@ They are referenced here for specification history only; active implementation w
| V37 | `BITCODE_SPEC_V37.md` | promoted historical Bitcode canon | Website Conversations after V36: website conversation interface, stream UI/event contracts, fullscreen writing mode, conversation-to-Terminal handoff, source selectors, route-local chat history, persistence/privacy/redaction, telemetry/proof/docs, and any conversational UX not covered by the V28 ChatGPT App MVP. |
| V38 | `BITCODE_SPEC_V38.md` | promoted historical Bitcode canon | Inference correctness after V37: pipeline execution call stack, PTRR agents, FailsafeGenerationSequence over ThricifiedGeneration, prompt registry composition, PromptPart and Prompt benchmarking, Reading pipeline inference, ReadFitsFindingSynthesis depository search and embeddings, source-safe inference telemetry, local/staging rehearsal, and promotion readiness. |
| V39 | `BITCODE_SPEC_V39.md` | promoted historical Bitcode canon | Commercial Reading readiness after V38: Depository supply indexing, enterprise five-step Reading UX, ReadNeed review/resynthesis, ReadFitsFinding many-candidate runtime and replay, source-safe AssetPack preview and deterministic BTC quote, settlement, BTD rights transfer, post-settlement delivery, ledger/database/storage synchronization, operational telemetry/repair, interface parity, local/staging rehearsal, and promotion readiness. |
-| V40 | `BITCODE_SPEC_V40.md` | active canon | Exhaustive commercial application testing depth after V39: rich browser E2E for all website interactions and state possibilities, visual/screenshot comparison coverage, API and integration suites for pipelines, conversations, routes, ledger/database/storage synchronization, unit coverage for packages, primitives, isolated implementations, real commercial implementations, local/staging rehearsal automation, prompt benchmark smoke, and promotion readiness. |
-| V41 | `BITCODE_SPEC_V41.md` | active draft target | Prompt and PromptPart excellence, treating prompts as programs: audit every raw PromptPart and composed Prompt, run and harden benchmarks, repartition prompts into meaningfully benchmarkable semantic parts, retitle and rewrite PromptParts/Prompts where optimal, catalogue registry bindings, interpolation contracts, benchmark fixtures, benchmark outputs, inference callsites, and parsed return types, and elevate all Reading and Conversation inference points after V38 inference scaffolding and V40 testing depth make that work measurable. The primary surface is Reading, especially `ReadNeedComprehensionSynthesis` and `ReadFitsFindingSynthesis`; conversations and other inference prompts follow with the same benchmarkable catalogue discipline. |
-| V42 | `BITCODE_SPEC_V42.md` | planned future | Reliable MVP experience after V41 prompt hardening: shortest-path Depositing for any source material with Depository admission proof and later BTC compensation when deposits contribute to synthesized AssetPacks; shortest-path Reading for Read Request submission, synthesized Need review/resynthesis, Finding Fits, source-safe AssetPack measurement/preview review, BTD/BTC purchase and settlement, and repository delivery; and an AI-reading dominant demonstration proving an AssetPack can improve an AI system's training, prompt/context, or evaluation performance beyond public-data-only baselines using proprietary or otherwise non-public deposit and read materials. |
+| V40 | `BITCODE_SPEC_V40.md` | promoted historical Bitcode canon | Exhaustive commercial application testing depth after V39: rich browser E2E for all website interactions and state possibilities, visual/screenshot comparison coverage, API and integration suites for pipelines, conversations, routes, ledger/database/storage synchronization, unit coverage for packages, primitives, isolated implementations, real commercial implementations, local/staging rehearsal automation, prompt benchmark smoke, and promotion readiness. |
+| V41 | `BITCODE_SPEC_V41.md` | active canon | Prompt and PromptPart excellence, treating prompts as programs: audit every raw PromptPart and composed Prompt, run and harden benchmarks, repartition prompts into meaningfully benchmarkable semantic parts, retitle and rewrite PromptParts/Prompts where optimal, catalogue registry bindings, interpolation contracts, benchmark fixtures, benchmark outputs, inference callsites, and parsed return types, and elevate all Reading and Conversation inference points after V38 inference scaffolding and V40 testing depth make that work measurable. The primary surface is Reading, especially `ReadNeedComprehensionSynthesis` and `ReadFitsFindingSynthesis`; conversations and other inference prompts follow with the same benchmarkable catalogue discipline. |
+| V42 | `BITCODE_SPEC_V42.md` | active draft target | Reliable MVP experience after V41 prompt hardening: shortest-path Depositing for any source material with Depository admission proof and later BTC compensation when deposits contribute to synthesized AssetPacks; shortest-path Reading for Read Request submission, synthesized Need review/resynthesis, Finding Fits, source-safe AssetPack measurement/preview review, BTD/BTC purchase and settlement, and repository delivery; and an AI-reading dominant demonstration proving an AssetPack can improve an AI system's training, prompt/context, or evaluation performance beyond public-data-only baselines using proprietary or otherwise non-public deposit and read materials. |
| V43+ | future specification family | planned future | Agentic enterprise deposit-side AssetPack option synthesis after the MVP paths are reliable: repository-installed Bitcode Agents compare a connected enterprise codebase, the Bitcode Depository, and Reading activity to propose deposit AssetPack options for review; filter out critical IP; estimate positive ROI against development cost and likely demand; let enterprises approve/reject options for Depository admission; split `/terminal` into `/read` and `/deposit`; and rename `/exchange` to `/packs` throughout product routes, code naming, docs, and operator vocabulary. |
## Current Planning Spine
@@ -176,16 +177,16 @@ They are referenced here for specification history only; active implementation w
13. V38 promoted inference correctness, Reading pipeline search, prompt benchmarking, source-safe inference telemetry, and the practical PTRR/Failsafe/Thricified call stack.
14. V39 promoted commercial Reading readiness: Depository supply indexing, enterprise Reading UX, accepted-Need-gated Finding Fits, AssetPack preview/quote, settlement, rights transfer, delivery, telemetry/repair, interface parity, local/staging rehearsal, and promotion readiness.
15. V40 promoted exhaustive testing for the rich commercial application: E2E, visual, screenshot comparison, interaction/state matrices, integration, unit coverage, ledger/storage synchronization, local/staging rehearsal automation, and prompt benchmark smoke across the website, APIs, pipelines, conversations, packages, primitives, and real implementations.
-16. V41 is the current prompts-as-programs draft target after V40: every PromptPart, Prompt composition, benchmark, meaningfully benchmarkable semantic division, title, template, interpolation contract, registry binding, inference callsite, benchmark result, and parsed return type should be examined and improved across Reading and Conversation inference, using V38's inference correctness scaffolding and V40's testing/benchmarking depth as the measurement base.
-17. V42 is planned as the reliable MVP experience version after V41: refine the shortest path to Depositing any source material and later receiving BTC compensation, refine the shortest path to Reading from request through synthesized Need review/resynthesis, Finding Fits, source-safe AssetPack preview, BTD/BTC purchase, settlement, and repository delivery, and ship a strong AI-reading dominant demonstration where Bitcode reads non-public technical intelligence into an AssetPack that measurably improves an AI system beyond a public-data-only baseline.
+16. V41 promoted prompts-as-programs after V40: every PromptPart, Prompt composition, benchmark, meaningfully benchmarkable semantic division, title, template, interpolation contract, registry binding, inference callsite, benchmark result, and parsed return type was examined and improved across Reading and Conversation inference, using V38's inference correctness scaffolding and V40's testing/benchmarking depth as the measurement base.
+17. V42 is the active reliable MVP experience draft after V41: refine the shortest path to Depositing any source material and later receiving BTC compensation, refine the shortest path to Reading from request through synthesized Need review/resynthesis, Finding Fits, source-safe AssetPack preview, BTD/BTC purchase, settlement, and repository delivery, and ship a strong AI-reading dominant demonstration where Bitcode reads non-public technical intelligence into an AssetPack that measurably improves an AI system beyond a public-data-only baseline.
18. V43+ is planned as the agentic deposit-side product evolution after the MVP paths are reliable: enterprises should get deposit AssetPack options synthesized from their connected repositories and Bitcode's observed Depository/Reading demand, then approve or reject source-safe, sub-critical, positive-ROI options for Depository admission.
## Boundary Rules
- Do not treat `_legacy/` ENGI specifications as active implementation authority.
- Do use `_legacy/` specifications to understand why current Bitcode concepts exist and what must not regress.
-- V41+ work must build on V40 active canon and V27 `$BTD` law unless a future promoted spec explicitly supersedes it.
-- V42 is roadmap/planning only until V41 promotion opens it as the active draft target; V41 remains singularly scoped to Prompt and PromptPart excellence.
-- V43+ agentic depositing, `/read` and `/deposit` route separation, and `/packs` renaming are roadmap/planning only until a later version explicitly opens them; V41 remains singularly scoped to Prompt and PromptPart excellence.
+- V42+ work must build on V41 active canon and V27 `$BTD` law unless a future promoted spec explicitly supersedes it.
+- V42 is the active draft target for reliable MVP experience; Gate 1 is specification/documentation/workflow posture only and later gates own implementation.
+- V43+ agentic depositing, `/read` and `/deposit` route separation, and `/packs` renaming are roadmap/planning only until a later version explicitly opens them; V42 remains scoped to reliable MVP Depositing, Reading, settlement, delivery, and AI-reading demonstration.
- No implementation route should be versioned by spec number; source should move in place with the active canon.
- Future notes files are planning memory only until their version is explicitly opened as the draft-target SPEC family.
diff --git a/package.json b/package.json
index f4d44d0d..be225050 100644
--- a/package.json
+++ b/package.json
@@ -303,6 +303,7 @@
"generate:v41-promotion-readiness": "node scripts/generate-v41-promotion-readiness-report.mjs",
"check:v41-promotion-readiness": "node scripts/generate-v41-promotion-readiness-report.mjs --check",
"check:v41-gate9": "node scripts/check-v41-gate9-promotion-readiness.mjs",
+ "check:v42-gate1": "node scripts/check-v42-gate1-mvp-experience-roadmap-opening.mjs",
"generate:v38-inference-surface-inventory": "node scripts/generate-v38-inference-surface-inventory.mjs",
"check:v38-inference-surface-inventory": "node scripts/generate-v38-inference-surface-inventory.mjs --check",
"check:v38-gate2": "node scripts/check-v38-gate2-inference-surface-inventory.mjs",
diff --git a/packages/protocol/README.md b/packages/protocol/README.md
index 5ed392bb..9117436d 100644
--- a/packages/protocol/README.md
+++ b/packages/protocol/README.md
@@ -15,7 +15,7 @@ inventories, but it is not a commercial runtime implementation dependency.
Current exported commercial helpers include:
-- active/draft canon posture (`V41` active, `V42` draft after V41 promotion);
+- active/draft canon posture (`V41` active, `V42` draft);
- spec-family and canonical-input validation helpers;
- canon-posture drift reporting;
- `DocumentationSurfaceCatalog` helpers for V35 documentation surface proof;
@@ -176,6 +176,14 @@ runtime canon rewriting, dry-run promotion, source-safety, and value-bearing
mainnet blocking without serializing raw prompts, provider responses, protected
source, credentials, private settlement payloads, wallet material, or unpaid
AssetPack source.
+V42 Gate 1 is wired through `check:v42-gate1` and opens the reliable MVP
+experience specification family for the `V41` active, `V42` draft posture:
+shortest-path Depositing with Depository admission proof and later BTC
+compensation visibility; shortest-path Reading through Read Request, reviewed
+Need, Finding Fits, source-safe AssetPack preview, BTD/BTC settlement, rights
+transfer, and repository delivery; and an AI-reading dominant standalone
+demonstration that proves an AssetPack can improve an AI system beyond a
+public-data-only baseline.
V40 Gate 2 adds `V40TestInventoryCoverageMatrix` through
`packages/protocol/src/canonical/v40-test-inventory-coverage-matrix.js`,
`packages/protocol/test/v40-test-inventory-coverage-matrix.test.js`,
diff --git a/scripts/check-v42-gate1-mvp-experience-roadmap-opening.mjs b/scripts/check-v42-gate1-mvp-experience-roadmap-opening.mjs
new file mode 100644
index 00000000..b6cdea90
--- /dev/null
+++ b/scripts/check-v42-gate1-mvp-experience-roadmap-opening.mjs
@@ -0,0 +1,176 @@
+#!/usr/bin/env node
+
+import { execFileSync } from 'node:child_process';
+import { existsSync, readFileSync } from 'node:fs';
+import path from 'node:path';
+import { fileURLToPath } from 'node:url';
+
+const __filename = fileURLToPath(import.meta.url);
+const __dirname = path.dirname(__filename);
+const defaultRepoRoot = path.resolve(__dirname, '..');
+
+function read(root, relativePath) {
+ return readFileSync(path.join(root, relativePath), 'utf8');
+}
+
+function exists(root, relativePath) {
+ return existsSync(path.join(root, relativePath));
+}
+
+function git(root, args) {
+ return execFileSync('git', args, { cwd: root, encoding: 'utf8' }).trim();
+}
+
+function assertCheck(failures, condition, message) {
+ if (!condition) failures.push(message);
+}
+
+function parseArgs(argv) {
+ const args = { repoRoot: defaultRepoRoot, skipBranchCheck: false };
+ for (let index = 0; index < argv.length; index += 1) {
+ const arg = argv[index];
+ if (arg === '--repo-root') args.repoRoot = path.resolve(argv[++index]);
+ else if (arg === '--skip-branch-check') args.skipBranchCheck = true;
+ else if (arg === '--help' || arg === '-h') args.help = true;
+ else throw new Error(`Unknown argument ${arg}`);
+ }
+ return args;
+}
+
+function printHelp() {
+ process.stdout.write(
+ [
+ 'Usage: node scripts/check-v42-gate1-mvp-experience-roadmap-opening.mjs [--skip-branch-check] [--repo-root ]',
+ '',
+ 'Checks V42 Gate 1 spec family, roadmap, branch, workflow, docs, and active V41 / draft V42 reliable MVP experience posture.'
+ ].join('\n')
+ );
+ process.stdout.write('\n');
+}
+
+function main() {
+ const args = parseArgs(process.argv.slice(2));
+ if (args.help) {
+ printHelp();
+ return;
+ }
+
+ const root = args.repoRoot;
+ const failures = [];
+ const pointer = read(root, 'BITCODE_SPEC.txt').trim();
+
+ assertCheck(failures, pointer === 'V41', `BITCODE_SPEC.txt must remain V41 during V42 gate work. Observed ${pointer || 'empty'}.`);
+
+ if (!args.skipBranchCheck) {
+ const branch = git(root, ['branch', '--show-current']);
+ assertCheck(
+ failures,
+ branch === 'version/v42' || /^v42\/gate-\d+-[a-z0-9][a-z0-9-]*$/u.test(branch),
+ `V42 work must occur on version/v42 or v42/gate-N-* branches. Observed ${branch || 'detached HEAD'}.`
+ );
+ }
+
+ for (const relativePath of [
+ 'BITCODE_SPEC_V42.md',
+ 'BITCODE_SPEC_V42_DELTA.md',
+ 'BITCODE_SPEC_V42_NOTES.md',
+ 'BITCODE_SPEC_V42_PARITY_MATRIX.md',
+ 'SPECIFICATIONS_ROADMAP.md',
+ 'README.md',
+ 'packages/protocol/README.md',
+ 'protocol-demonstration/README.md',
+ '.github/pull_request_template.md',
+ '.github/workflows/bitcode-gate-quality.yml',
+ '.github/workflows/bitcode-canon-quality.yml',
+ 'package.json'
+ ]) {
+ assertCheck(failures, exists(root, relativePath), `Missing required V42 Gate 1 file: ${relativePath}`);
+ }
+
+ const spec = read(root, 'BITCODE_SPEC_V42.md');
+ const delta = read(root, 'BITCODE_SPEC_V42_DELTA.md');
+ const notes = read(root, 'BITCODE_SPEC_V42_NOTES.md');
+ const parity = read(root, 'BITCODE_SPEC_V42_PARITY_MATRIX.md');
+ const roadmap = read(root, 'SPECIFICATIONS_ROADMAP.md');
+ const readme = read(root, 'README.md');
+ const protocolReadme = read(root, 'packages/protocol/README.md');
+ const demoReadme = read(root, 'protocol-demonstration/README.md');
+ const prTemplate = read(root, '.github/pull_request_template.md');
+ const packageJson = read(root, 'package.json');
+ const gateWorkflow = read(root, '.github/workflows/bitcode-gate-quality.yml');
+ const canonWorkflow = read(root, '.github/workflows/bitcode-canon-quality.yml');
+
+ for (const [label, content] of [
+ ['V42 SPEC', spec],
+ ['V42 DELTA', delta],
+ ['V42 NOTES', notes],
+ ['V42 PARITY', parity]
+ ]) {
+ assertCheck(failures, content.includes('Current canonical/latest target: `V41`'), `${label} must declare V41 as current canonical/latest target.`);
+ }
+
+ for (const phrase of [
+ 'reliable MVP',
+ 'shortest-path Depositing',
+ 'shortest-path Reading',
+ 'ReadNeedComprehensionSynthesis',
+ 'ReadFitsFindingSynthesis',
+ 'source-safe AssetPack preview',
+ 'BTD/BTC settlement',
+ 'BTD rights transfer',
+ 'repository delivery',
+ 'depositor compensation',
+ 'AI-reading dominant demonstration',
+ 'public-data-only baseline',
+ 'Need review',
+ 'Finding Fits'
+ ]) {
+ assertCheck(
+ failures,
+ spec.includes(phrase) || delta.includes(phrase) || notes.includes(phrase) || roadmap.includes(phrase),
+ `V42 opening must name ${phrase}.`
+ );
+ }
+
+ for (const gate of [
+ 'Gate 1: MVP Experience Roadmap And Spec Opening',
+ 'Gate 2: Depositing Shortest Path And Compensation Visibility',
+ 'Gate 3: Reading Shortest Path State Machine',
+ 'Gate 4: ReadNeed Review And Resynthesis Product Closure',
+ 'Gate 5: ReadFitsFinding AssetPack Preview And Quote Closure',
+ 'Gate 6: Settlement Rights Transfer And Repository Delivery Closure',
+ 'Gate 7: AI-Reading Dominant Demonstration MVP',
+ 'Gate 8: Local And Staging-Testnet Full MVP Rehearsal',
+ 'Gate 9: V42 Promotion Readiness'
+ ]) {
+ assertCheck(failures, spec.includes(gate) || delta.includes(gate), `V42 gate plan is missing ${gate}.`);
+ }
+
+ assertCheck(failures, roadmap.includes('Current active canonical pointer: `BITCODE_SPEC.txt` -> `V41`'), 'Roadmap must state V41 active pointer.');
+ assertCheck(failures, /Current working gate: V42 Gate (?:1|2|3|4|5|6|7|8|9)\b/u.test(roadmap), 'Roadmap must state active V42 gate progression.');
+ assertCheck(failures, roadmap.includes('| V42 | `BITCODE_SPEC_V42.md` | active draft target |'), 'Roadmap must list V42 as active draft target.');
+ assertCheck(failures, readme.includes('resolves to `V41`; V42 is the active draft target'), 'README must state V41 active / V42 draft posture.');
+ assertCheck(failures, protocolReadme.includes('V42 Gate 1') && protocolReadme.includes('V41` active, `V42` draft'), 'Protocol README must document V42 Gate 1 active/draft posture.');
+ assertCheck(failures, demoReadme.includes('`BITCODE_SPEC.txt -> V41`'), 'Demonstration README must keep V41 pointer truth.');
+ assertCheck(failures, prTemplate.includes('V42 Gate N:'), 'PR template must use V42 gate title examples.');
+ assertCheck(failures, packageJson.includes('"check:v42-gate1"'), 'package.json must expose check:v42-gate1.');
+ assertCheck(failures, gateWorkflow.includes('check-v42-gate1-mvp-experience-roadmap-opening.mjs'), 'Gate workflow must run V42 Gate 1 checker.');
+ assertCheck(failures, canonWorkflow.includes('check-v42-gate1-mvp-experience-roadmap-opening.mjs'), 'Canon workflow must run V42 Gate 1 checker.');
+
+ if (failures.length > 0) {
+ process.stderr.write('V42 Gate 1 MVP experience roadmap opening check failed:\n');
+ for (const failure of failures.filter(Boolean)) process.stderr.write(`- ${failure}\n`);
+ process.exitCode = 1;
+ return;
+ }
+
+ process.stdout.write('V42 Gate 1 MVP experience roadmap opening check passed.\n');
+}
+
+try {
+ main();
+} catch (error) {
+ const detail = error instanceof Error ? error.message : String(error);
+ process.stderr.write(`${detail}\n`);
+ process.exitCode = 1;
+}
From ee481197660748815f2b066a50c4e2cf153c37b1 Mon Sep 17 00:00:00 2001
From: Garrett Maring
Date: Tue, 26 May 2026 16:30:05 -0300
Subject: [PATCH 02/35] V42 Gate 1: Preserve promoted canon proof compatibility
Teach V40 and V41 protocol proof predicates to accept the promoted V41 / draft V42 roadmap posture while preserving their original closure-anchor checks.
Extend the protocol package boundary test to recognize the current V41 active canon and V42 draft target.
---
.../src/canonical/v40-api-integration-contracts.js | 7 ++++++-
.../src/canonical/v40-browser-e2e-visual-proof.js | 9 ++++++++-
.../canonical/v40-conversation-terminal-integration.js | 7 ++++++-
.../v40-reading-pipeline-integration-coverage.js | 7 ++++++-
.../v41-conversation-tool-interface-prompt-rewrite.js | 8 +++++---
.../src/canonical/v41-prompt-program-benchmark-report.js | 6 ++++--
.../canonical/v41-readfitsfinding-prompt-hardening.js | 4 +++-
packages/protocol/test/protocol-package-boundary.test.js | 1 +
8 files changed, 39 insertions(+), 10 deletions(-)
diff --git a/packages/protocol/src/canonical/v40-api-integration-contracts.js b/packages/protocol/src/canonical/v40-api-integration-contracts.js
index d95610c9..fca418ff 100644
--- a/packages/protocol/src/canonical/v40-api-integration-contracts.js
+++ b/packages/protocol/src/canonical/v40-api-integration-contracts.js
@@ -365,7 +365,12 @@ function buildPredicateResults(repoRoot) {
predicateResult('notes-document-gate4', 'BITCODE_SPEC_V40_NOTES.md', notes.includes('Gate 4 implementation notes') && notes.includes('API route integration contracts')),
predicateResult('parity-documents-gate4', 'BITCODE_SPEC_V40_PARITY_MATRIX.md', parity.includes('v40-api-integration-contracts') && parity.includes('| Gate 4 | API/route integration artifact | implemented |')),
predicateResult('roadmap-advanced-through-gate4', 'SPECIFICATIONS_ROADMAP.md', roadmap.includes('V40 Gate 4 closure anchor')),
- predicateResult('roadmap-documents-v41-prompt-programs', 'SPECIFICATIONS_ROADMAP.md', roadmap.includes('V41 should focus singularly on Prompt and PromptPart implementation') && roadmap.includes('meaningfully benchmarkable semantic parts')),
+ predicateResult(
+ 'roadmap-documents-v41-prompt-programs',
+ 'SPECIFICATIONS_ROADMAP.md',
+ roadmap.includes('| V41 | `BITCODE_SPEC_V41.md` | active canon | Prompt and PromptPart excellence') &&
+ roadmap.includes('meaningfully benchmarkable semantic parts'),
+ ),
...rowPredicates,
];
}
diff --git a/packages/protocol/src/canonical/v40-browser-e2e-visual-proof.js b/packages/protocol/src/canonical/v40-browser-e2e-visual-proof.js
index 11303fde..ae71515e 100644
--- a/packages/protocol/src/canonical/v40-browser-e2e-visual-proof.js
+++ b/packages/protocol/src/canonical/v40-browser-e2e-visual-proof.js
@@ -495,7 +495,14 @@ function buildPredicateResults(repoRoot) {
predicateResult('delta-documents-gate7', 'BITCODE_SPEC_V40_DELTA.md', delta.includes('Gate 7 closes with package-backed `V40BrowserE2eVisualProof`')),
predicateResult('notes-document-gate7', 'BITCODE_SPEC_V40_NOTES.md', notes.includes('Gate 7 implementation notes') && notes.includes('browser E2E, visual, accessibility, and responsive proof')),
predicateResult('parity-documents-gate7', 'BITCODE_SPEC_V40_PARITY_MATRIX.md', parity.includes('v40-browser-e2e-visual-proof') && parity.includes('| Gate 7 | Browser/visual/accessibility/responsive artifact | implemented |')),
- predicateResult('roadmap-advanced-through-gate7', 'SPECIFICATIONS_ROADMAP.md', (/Current working gate: V40 Gate (?:7|8|9|10|11)\b/u.test(roadmap) || roadmap.includes('Latest closed version: V40')) && roadmap.includes('V40 Gate 7 closure anchor')),
+ predicateResult(
+ 'roadmap-advanced-through-gate7',
+ 'SPECIFICATIONS_ROADMAP.md',
+ (/Current working gate: V40 Gate (?:7|8|9|10|11)\b/u.test(roadmap) ||
+ roadmap.includes('Latest closed version: V40') ||
+ roadmap.includes('Recent V40 closure anchor')) &&
+ roadmap.includes('V40 Gate 7 closure anchor'),
+ ),
predicateResult('readmes-document-gate7', 'README.md', rootReadme.includes('V40 Gate 7') && protocolReadme.includes('V40BrowserE2eVisualProof')),
...rowPredicates,
];
diff --git a/packages/protocol/src/canonical/v40-conversation-terminal-integration.js b/packages/protocol/src/canonical/v40-conversation-terminal-integration.js
index 86aa44c4..cf9a8196 100644
--- a/packages/protocol/src/canonical/v40-conversation-terminal-integration.js
+++ b/packages/protocol/src/canonical/v40-conversation-terminal-integration.js
@@ -479,7 +479,12 @@ function buildPredicateResults(repoRoot) {
roadmap.includes('Recent V40 closure anchor')),
),
predicateResult('readmes-document-gate6', 'README.md', rootReadme.includes('V40 Gate 6') && protocolReadme.includes('V40ConversationTerminalIntegration')),
- predicateResult('roadmap-preserves-v41-prompt-programs', 'SPECIFICATIONS_ROADMAP.md', roadmap.includes('V41 should focus singularly on Prompt and PromptPart implementation') && roadmap.includes('prompts as programs')),
+ predicateResult(
+ 'roadmap-preserves-v41-prompt-programs',
+ 'SPECIFICATIONS_ROADMAP.md',
+ roadmap.includes('| V41 | `BITCODE_SPEC_V41.md` | active canon | Prompt and PromptPart excellence') &&
+ roadmap.includes('prompts as programs'),
+ ),
...rowPredicates,
];
}
diff --git a/packages/protocol/src/canonical/v40-reading-pipeline-integration-coverage.js b/packages/protocol/src/canonical/v40-reading-pipeline-integration-coverage.js
index aee23947..520289cd 100644
--- a/packages/protocol/src/canonical/v40-reading-pipeline-integration-coverage.js
+++ b/packages/protocol/src/canonical/v40-reading-pipeline-integration-coverage.js
@@ -497,7 +497,12 @@ function buildPredicateResults(repoRoot) {
roadmap.includes('Latest closed version: V40 Exhaustive Commercial Application Testing') ||
roadmap.includes('Recent V40 closure anchor')),
),
- predicateResult('roadmap-preserves-v41-prompt-programs', 'SPECIFICATIONS_ROADMAP.md', roadmap.includes('V41 should focus singularly on Prompt and PromptPart implementation') && roadmap.includes('prompts as programs')),
+ predicateResult(
+ 'roadmap-preserves-v41-prompt-programs',
+ 'SPECIFICATIONS_ROADMAP.md',
+ roadmap.includes('| V41 | `BITCODE_SPEC_V41.md` | active canon | Prompt and PromptPart excellence') &&
+ roadmap.includes('prompts as programs'),
+ ),
...rowPredicates,
];
}
diff --git a/packages/protocol/src/canonical/v41-conversation-tool-interface-prompt-rewrite.js b/packages/protocol/src/canonical/v41-conversation-tool-interface-prompt-rewrite.js
index 2efed98b..7b79069c 100644
--- a/packages/protocol/src/canonical/v41-conversation-tool-interface-prompt-rewrite.js
+++ b/packages/protocol/src/canonical/v41-conversation-tool-interface-prompt-rewrite.js
@@ -866,9 +866,11 @@ function buildPredicateResults(repoRoot) {
'conversation-tool-interface-tests-docs-workflows',
SOURCE_ROOTS.roadmap,
roadmap.includes('V41 Gate 7 closure anchor') &&
- /Current working gate: V41 Gate (?:7|8|9)/u.test(roadmap) &&
- (/Next queued gate after V41 Gate (?:7|8): V41 (?:Prompt Benchmark Report And Telemetry Integration|Promotion Readiness)/u.test(roadmap) ||
- /V41 Gate 9 closure anchor/u.test(roadmap)),
+ ((/Current working gate: V41 Gate (?:7|8|9)/u.test(roadmap) &&
+ (/Next queued gate after V41 Gate (?:7|8): V41 (?:Prompt Benchmark Report And Telemetry Integration|Promotion Readiness)/u.test(roadmap) ||
+ /V41 Gate 9 closure anchor/u.test(roadmap))) ||
+ /Latest closed version: V41 Prompt And PromptPart Excellence/u.test(roadmap) ||
+ /Recent V41 closure anchor/u.test(roadmap)),
),
predicate(
'readmes-document-gate7-helpers',
diff --git a/packages/protocol/src/canonical/v41-prompt-program-benchmark-report.js b/packages/protocol/src/canonical/v41-prompt-program-benchmark-report.js
index f721f55c..e9bbf561 100644
--- a/packages/protocol/src/canonical/v41-prompt-program-benchmark-report.js
+++ b/packages/protocol/src/canonical/v41-prompt-program-benchmark-report.js
@@ -831,8 +831,10 @@ function buildPredicateResults(repoRoot, context) {
'gate8-tests-docs-workflows',
SOURCE_ROOTS.roadmap,
roadmap.includes('V41 Gate 8 closure anchor')
- && /Current working gate: V41 Gate (?:8|9)/u.test(roadmap)
- && (roadmap.includes('Next queued gate after V41 Gate 8') || roadmap.includes('V41 Gate 9 closure anchor')),
+ && ((/Current working gate: V41 Gate (?:8|9)/u.test(roadmap)
+ && (roadmap.includes('Next queued gate after V41 Gate 8') || roadmap.includes('V41 Gate 9 closure anchor')))
+ || /Latest closed version: V41 Prompt And PromptPart Excellence/u.test(roadmap)
+ || /Recent V41 closure anchor/u.test(roadmap)),
),
predicate(
'readmes-document-gate8-helpers',
diff --git a/packages/protocol/src/canonical/v41-readfitsfinding-prompt-hardening.js b/packages/protocol/src/canonical/v41-readfitsfinding-prompt-hardening.js
index 83bf7fde..39d1117e 100644
--- a/packages/protocol/src/canonical/v41-readfitsfinding-prompt-hardening.js
+++ b/packages/protocol/src/canonical/v41-readfitsfinding-prompt-hardening.js
@@ -578,7 +578,9 @@ function predicatesForRow(repoRoot, rowData) {
'docs.current-gate-6',
rowId,
SOURCE_ROOTS.roadmap,
- /Current working gate: V41 Gate (?:6|7|8|9)/u.test(source),
+ /Current working gate: V41 Gate (?:6|7|8|9)/u.test(source) ||
+ /Latest closed version: V41 Prompt And PromptPart Excellence/u.test(source) ||
+ /Recent V41 closure anchor/u.test(source),
),
predicate(
'docs.next-gate-7',
diff --git a/packages/protocol/test/protocol-package-boundary.test.js b/packages/protocol/test/protocol-package-boundary.test.js
index 5d7f1b96..cd208df8 100644
--- a/packages/protocol/test/protocol-package-boundary.test.js
+++ b/packages/protocol/test/protocol-package-boundary.test.js
@@ -60,6 +60,7 @@ test('@bitcode/protocol commercial formalization exports package-native canon he
V38: { activeCanon: 'V38', draftTarget: 'V39' },
V39: { activeCanon: 'V39', draftTarget: 'V40' },
V40: { activeCanon: 'V40', draftTarget: 'V41' },
+ V41: { activeCanon: 'V41', draftTarget: 'V42' },
};
const expectedPosture = expectedPostureByPointer[pointer];
From d20538ffbb2caaa94a3f5da3b7f751635883d792 Mon Sep 17 00:00:00 2001
From: Garrett Maring
Date: Thu, 28 May 2026 17:11:26 -0300
Subject: [PATCH 03/35] V42 Gate 2: Add Depositing Compensation Visibility
Implements DepositorySupplyCompensationPreview, source-to-shares compensation readback, deposit evidence roots, and Terminal compensation visibility for source-safe Depositing admission.
Adds the deterministic V42 Gate 2 artifact, generator/checker, protocol exports/tests, workflow wiring, and V42 roadmap/spec documentation for the next packs/read/deposit UX direction.
Validated with check:v42-gate2, check:v42-gate1, V42 spec-family/canon checks, uapi tsc/lint/build, protocol package tests, asset-pack typecheck, and diff whitespace checks.
---
.bitcode/v42-depositing-shortest-path.json | 483 ++++++++++++++++++
.github/workflows/bitcode-canon-quality.yml | 3 +
.github/workflows/bitcode-gate-quality.yml | 3 +
BITCODE_SPEC_V42.md | 13 +-
BITCODE_SPEC_V42_DELTA.md | 2 +
BITCODE_SPEC_V42_NOTES.md | 7 +
BITCODE_SPEC_V42_PARITY_MATRIX.md | 4 +-
README.md | 11 +
SPECIFICATIONS_ROADMAP.md | 10 +-
package.json | 3 +
packages/pipelines/asset-pack/README.md | 14 +-
.../__tests__/depository-supply-index.test.ts | 72 +++
.../asset-pack/src/depository-supply-index.ts | 188 ++++++-
packages/protocol/README.md | 8 +
packages/protocol/server.js | 7 +
packages/protocol/src/bitcode-demo.js | 94 +++-
.../canonical/v42-depositing-shortest-path.js | 282 ++++++++++
packages/protocol/src/index.d.ts | 8 +
packages/protocol/src/index.js | 10 +
.../test/protocol-package-boundary.test.js | 25 +
.../test/v42-depositing-shortest-path.test.js | 70 +++
...eck-v42-gate2-depositing-shortest-path.mjs | 230 +++++++++
.../generate-v42-depositing-shortest-path.mjs | 31 ++
uapi/app/terminal/TerminalDepositComposer.tsx | 38 ++
uapi/app/terminal/TerminalPageClient.tsx | 5 +
.../app/terminal/terminal-activity-history.ts | 17 +
.../terminal-deposit-read-workbench.ts | 46 ++
uapi/app/terminal/terminal-run-data.ts | 5 +
28 files changed, 1676 insertions(+), 13 deletions(-)
create mode 100644 .bitcode/v42-depositing-shortest-path.json
create mode 100644 packages/protocol/src/canonical/v42-depositing-shortest-path.js
create mode 100644 packages/protocol/test/v42-depositing-shortest-path.test.js
create mode 100644 scripts/check-v42-gate2-depositing-shortest-path.mjs
create mode 100644 scripts/generate-v42-depositing-shortest-path.mjs
diff --git a/.bitcode/v42-depositing-shortest-path.json b/.bitcode/v42-depositing-shortest-path.json
new file mode 100644
index 00000000..d6833815
--- /dev/null
+++ b/.bitcode/v42-depositing-shortest-path.json
@@ -0,0 +1,483 @@
+{
+ "artifactId": "v42-depositing-shortest-path",
+ "schemaId": "bitcode.v42.depositingShortestPath.v1",
+ "version": "V42",
+ "currentTarget": "V41",
+ "sourceSafetyVerdict": "source-safe-depositing-compensation-visibility-metadata",
+ "generatedAt": "deterministic",
+ "artifactRoot": "v42-depositing-shortest-path:1059291e830568845da67d9e",
+ "passed": true,
+ "rows": [
+ {
+ "rowId": "path:source-to-admission-proof",
+ "purpose": "Make the shortest Depositing path explicit: source material, repository/source anchor, Depository admission, source-safe proof roots, and next Reading handoff.",
+ "sourceRoots": [
+ "packages/protocol/server.js",
+ "packages/protocol/src/bitcode-demo.js",
+ "uapi/app/api/deposits/route.ts",
+ "uapi/app/terminal/TerminalDepositComposer.tsx"
+ ],
+ "emittedTypes": [
+ "createDeposit",
+ "buildDepositoryEvidence",
+ "TerminalDepositResponseEvidence"
+ ],
+ "requiredEvidence": [
+ "repositoryFullName",
+ "sourceBranch",
+ "sourceCommit",
+ "proofRoot",
+ "measurementRoot"
+ ],
+ "rowRoot": "v42-depositing-shortest-path-row:7e931285b6eabbbcce8b6855",
+ "sourceSafetyClass": "source_safe_depositing_compensation_visibility_metadata",
+ "sourceSafeMetadataOnly": true,
+ "protectedSourceVisible": false,
+ "rawSourceTextVisible": false,
+ "credentialsSerialized": false,
+ "walletPrivateMaterialVisible": false,
+ "unpaidAssetPackSourceVisible": false,
+ "settlementPrivatePayloadVisible": false,
+ "forbiddenPayloadClasses": [
+ "secret-values",
+ "provider-tokens",
+ "wallet-private-material",
+ "protected-source-payloads",
+ "raw-protected-prompts",
+ "raw-model-responses-with-protected-source",
+ "unpaid-assetpack-source",
+ "settlement-private-payloads"
+ ]
+ },
+ {
+ "rowId": "api:deposit-route-readiness-contract",
+ "purpose": "Keep POST /api/deposits admitted only after signed transaction and repository readiness checks, then project source-safe Depository evidence.",
+ "sourceRoots": [
+ "uapi/app/api/deposits/route.ts",
+ "packages/protocol/server.js",
+ "packages/protocol/test/protocol-package-boundary.test.js"
+ ],
+ "emittedTypes": [
+ "requireBitcodeSignedTransactionReadiness",
+ "BitcodeAppContext.createDeposit"
+ ],
+ "requiredEvidence": [
+ "requiresRepositoryAnchor",
+ "repositoryProvider",
+ "walletAuthorizationProof"
+ ],
+ "rowRoot": "v42-depositing-shortest-path-row:ce3fb56bc4fbed8d5867fda9",
+ "sourceSafetyClass": "source_safe_depositing_compensation_visibility_metadata",
+ "sourceSafeMetadataOnly": true,
+ "protectedSourceVisible": false,
+ "rawSourceTextVisible": false,
+ "credentialsSerialized": false,
+ "walletPrivateMaterialVisible": false,
+ "unpaidAssetPackSourceVisible": false,
+ "settlementPrivatePayloadVisible": false,
+ "forbiddenPayloadClasses": [
+ "secret-values",
+ "provider-tokens",
+ "wallet-private-material",
+ "protected-source-payloads",
+ "raw-protected-prompts",
+ "raw-model-responses-with-protected-source",
+ "unpaid-assetpack-source",
+ "settlement-private-payloads"
+ ]
+ },
+ {
+ "rowId": "supply:depository-record-compensation-preview",
+ "purpose": "Attach a deterministic compensation preview to DepositorySupplyRecord without minting BTD or exposing source before an accepted Need-Fit and settlement.",
+ "sourceRoots": [
+ "packages/pipelines/asset-pack/src/depository-supply-index.ts",
+ "packages/pipelines/asset-pack/src/__tests__/depository-supply-index.test.ts",
+ "packages/pipelines/asset-pack/src/embedding-config.ts"
+ ],
+ "emittedTypes": [
+ "DepositorySupplyCompensationPreview",
+ "DepositorySupplyRecord.compensationPreview"
+ ],
+ "requiredEvidence": [
+ "source-to-shares-largest-remainder",
+ "not-minted-by-deposit-admission",
+ "compensationPreviewRoot"
+ ],
+ "rowRoot": "v42-depositing-shortest-path-row:c51d568dcab3bc943f6a6a98",
+ "sourceSafetyClass": "source_safe_depositing_compensation_visibility_metadata",
+ "sourceSafeMetadataOnly": true,
+ "protectedSourceVisible": false,
+ "rawSourceTextVisible": false,
+ "credentialsSerialized": false,
+ "walletPrivateMaterialVisible": false,
+ "unpaidAssetPackSourceVisible": false,
+ "settlementPrivatePayloadVisible": false,
+ "forbiddenPayloadClasses": [
+ "secret-values",
+ "provider-tokens",
+ "wallet-private-material",
+ "protected-source-payloads",
+ "raw-protected-prompts",
+ "raw-model-responses-with-protected-source",
+ "unpaid-assetpack-source",
+ "settlement-private-payloads"
+ ]
+ },
+ {
+ "rowId": "documents:source-safe-search-and-vector-projection",
+ "purpose": "Preserve source-safe lexical, metadata, measurement, and vector search documents so deposits become searchable without protected source payloads.",
+ "sourceRoots": [
+ "packages/pipelines/asset-pack/src/depository-supply-index.ts",
+ "packages/pipelines/asset-pack/src/__tests__/depository-supply-index.test.ts"
+ ],
+ "emittedTypes": [
+ "DepositorySupplySearchDocument",
+ "DepositorySupplyVectorProjection"
+ ],
+ "requiredEvidence": [
+ "text-embedding-3-small",
+ "1536",
+ "match_deliverable_vectors"
+ ],
+ "rowRoot": "v42-depositing-shortest-path-row:54e3a870b07b258bde48dd92",
+ "sourceSafetyClass": "source_safe_depositing_compensation_visibility_metadata",
+ "sourceSafeMetadataOnly": true,
+ "protectedSourceVisible": false,
+ "rawSourceTextVisible": false,
+ "credentialsSerialized": false,
+ "walletPrivateMaterialVisible": false,
+ "unpaidAssetPackSourceVisible": false,
+ "settlementPrivatePayloadVisible": false,
+ "forbiddenPayloadClasses": [
+ "secret-values",
+ "provider-tokens",
+ "wallet-private-material",
+ "protected-source-payloads",
+ "raw-protected-prompts",
+ "raw-model-responses-with-protected-source",
+ "unpaid-assetpack-source",
+ "settlement-private-payloads"
+ ]
+ },
+ {
+ "rowId": "storage:depository-readback-projection",
+ "purpose": "Bind Depository admission to durable source-safe storage readback through deliverables, vector rows, ledger rows, and source-to-shares allocation posture.",
+ "sourceRoots": [
+ "packages/pipelines/asset-pack/src/depository-supply-index.ts",
+ "packages/pipelines/asset-pack/README.md",
+ "BITCODE_SPEC_V42.md"
+ ],
+ "emittedTypes": [
+ "DepositorySupplyStorageProjection",
+ "compensationPreview.readback"
+ ],
+ "requiredEvidence": [
+ "deliverables",
+ "deliverable_vectors",
+ "ledger_entries",
+ "source_to_shares_allocations"
+ ],
+ "rowRoot": "v42-depositing-shortest-path-row:ce303882896d4c8adb8abde6",
+ "sourceSafetyClass": "source_safe_depositing_compensation_visibility_metadata",
+ "sourceSafeMetadataOnly": true,
+ "protectedSourceVisible": false,
+ "rawSourceTextVisible": false,
+ "credentialsSerialized": false,
+ "walletPrivateMaterialVisible": false,
+ "unpaidAssetPackSourceVisible": false,
+ "settlementPrivatePayloadVisible": false,
+ "forbiddenPayloadClasses": [
+ "secret-values",
+ "provider-tokens",
+ "wallet-private-material",
+ "protected-source-payloads",
+ "raw-protected-prompts",
+ "raw-model-responses-with-protected-source",
+ "unpaid-assetpack-source",
+ "settlement-private-payloads"
+ ]
+ },
+ {
+ "rowId": "ledger:source-to-shares-compensation-readback",
+ "purpose": "Record depositor compensation visibility through pending-claim and eligible-route ledger keys while deferring actual BTC allocation until paid AssetPack settlement.",
+ "sourceRoots": [
+ "packages/protocol/server.js",
+ "packages/protocol/src/bitcode-demo.js",
+ "packages/protocol/test/protocol-package-boundary.test.js"
+ ],
+ "emittedTypes": [
+ "ledger.accounts",
+ "compensationPreview.readback.ledgerAccountKeys"
+ ],
+ "requiredEvidence": [
+ "pending_claims",
+ "eligible_compensation_routes",
+ "future-reader-after-settlement"
+ ],
+ "rowRoot": "v42-depositing-shortest-path-row:5bcf92e8564e1d3d5ac09fd9",
+ "sourceSafetyClass": "source_safe_depositing_compensation_visibility_metadata",
+ "sourceSafeMetadataOnly": true,
+ "protectedSourceVisible": false,
+ "rawSourceTextVisible": false,
+ "credentialsSerialized": false,
+ "walletPrivateMaterialVisible": false,
+ "unpaidAssetPackSourceVisible": false,
+ "settlementPrivatePayloadVisible": false,
+ "forbiddenPayloadClasses": [
+ "secret-values",
+ "provider-tokens",
+ "wallet-private-material",
+ "protected-source-payloads",
+ "raw-protected-prompts",
+ "raw-model-responses-with-protected-source",
+ "unpaid-assetpack-source",
+ "settlement-private-payloads"
+ ]
+ },
+ {
+ "rowId": "terminal:compensation-visibility-readback",
+ "purpose": "Show source-safe compensation posture in Terminal and carry compensation roots through activity history and the deposit-to-read workbench.",
+ "sourceRoots": [
+ "uapi/app/terminal/TerminalDepositComposer.tsx",
+ "uapi/app/terminal/terminal-activity-history.ts",
+ "uapi/app/terminal/terminal-deposit-read-workbench.ts",
+ "uapi/app/terminal/terminal-run-data.ts"
+ ],
+ "emittedTypes": [
+ "TerminalDepositResponseEvidence",
+ "WorkspaceRun",
+ "TerminalDepositedSourceRevision"
+ ],
+ "requiredEvidence": [
+ "compensationPreviewRoot",
+ "sourceToSharesPreviewRoot",
+ "Compensation route"
+ ],
+ "rowRoot": "v42-depositing-shortest-path-row:5ac46b95fa31585ff8f7ecef",
+ "sourceSafetyClass": "source_safe_depositing_compensation_visibility_metadata",
+ "sourceSafeMetadataOnly": true,
+ "protectedSourceVisible": false,
+ "rawSourceTextVisible": false,
+ "credentialsSerialized": false,
+ "walletPrivateMaterialVisible": false,
+ "unpaidAssetPackSourceVisible": false,
+ "settlementPrivatePayloadVisible": false,
+ "forbiddenPayloadClasses": [
+ "secret-values",
+ "provider-tokens",
+ "wallet-private-material",
+ "protected-source-payloads",
+ "raw-protected-prompts",
+ "raw-model-responses-with-protected-source",
+ "unpaid-assetpack-source",
+ "settlement-private-payloads"
+ ]
+ },
+ {
+ "rowId": "rehearsal:local-staging-deposit-readback",
+ "purpose": "Keep Gate 2 locally checkable and staging-testnet rehearsable through package tests, protocol route tests, generated artifact checks, and source-safe proof rows.",
+ "sourceRoots": [
+ "BITCODE_SPEC_V42.md",
+ "BITCODE_SPEC_V42_DELTA.md",
+ "BITCODE_SPEC_V42_NOTES.md",
+ "BITCODE_SPEC_V42_PARITY_MATRIX.md",
+ "SPECIFICATIONS_ROADMAP.md"
+ ],
+ "emittedTypes": [
+ "V42DepositingShortestPathReport"
+ ],
+ "requiredEvidence": [
+ "local/staging rehearsal",
+ "staging-testnet",
+ "check:v42-gate2"
+ ],
+ "rowRoot": "v42-depositing-shortest-path-row:b87642ce4dfa333fd4b4ea03",
+ "sourceSafetyClass": "source_safe_depositing_compensation_visibility_metadata",
+ "sourceSafeMetadataOnly": true,
+ "protectedSourceVisible": false,
+ "rawSourceTextVisible": false,
+ "credentialsSerialized": false,
+ "walletPrivateMaterialVisible": false,
+ "unpaidAssetPackSourceVisible": false,
+ "settlementPrivatePayloadVisible": false,
+ "forbiddenPayloadClasses": [
+ "secret-values",
+ "provider-tokens",
+ "wallet-private-material",
+ "protected-source-payloads",
+ "raw-protected-prompts",
+ "raw-model-responses-with-protected-source",
+ "unpaid-assetpack-source",
+ "settlement-private-payloads"
+ ]
+ }
+ ],
+ "rowIds": [
+ "path:source-to-admission-proof",
+ "api:deposit-route-readiness-contract",
+ "supply:depository-record-compensation-preview",
+ "documents:source-safe-search-and-vector-projection",
+ "storage:depository-readback-projection",
+ "ledger:source-to-shares-compensation-readback",
+ "terminal:compensation-visibility-readback",
+ "rehearsal:local-staging-deposit-readback"
+ ],
+ "predicateResults": [
+ {
+ "id": "deposit-route-requires-readiness",
+ "sourcePath": "uapi/app/api/deposits/route.ts",
+ "passed": true
+ },
+ {
+ "id": "server-creates-deposit-and-ledger-readback",
+ "sourcePath": "packages/protocol/server.js",
+ "passed": true
+ },
+ {
+ "id": "runtime-builds-compensation-preview",
+ "sourcePath": "packages/protocol/src/bitcode-demo.js",
+ "passed": true
+ },
+ {
+ "id": "runtime-keeps-source-safe-visibility",
+ "sourcePath": "packages/protocol/src/bitcode-demo.js",
+ "passed": true
+ },
+ {
+ "id": "supply-index-defines-compensation-preview",
+ "sourcePath": "packages/pipelines/asset-pack/src/depository-supply-index.ts",
+ "passed": true
+ },
+ {
+ "id": "supply-index-defers-btd-mint",
+ "sourcePath": "packages/pipelines/asset-pack/src/depository-supply-index.ts",
+ "passed": true
+ },
+ {
+ "id": "supply-index-projects-source-to-shares-readback",
+ "sourcePath": "packages/pipelines/asset-pack/src/depository-supply-index.ts",
+ "passed": true
+ },
+ {
+ "id": "supply-index-preserves-search-documents",
+ "sourcePath": "packages/pipelines/asset-pack/src/depository-supply-index.ts",
+ "passed": true
+ },
+ {
+ "id": "supply-tests-cover-compensation-preview",
+ "sourcePath": "packages/pipelines/asset-pack/src/__tests__/depository-supply-index.test.ts",
+ "passed": true
+ },
+ {
+ "id": "supply-tests-cover-no-protected-source",
+ "sourcePath": "packages/pipelines/asset-pack/src/__tests__/depository-supply-index.test.ts",
+ "passed": true
+ },
+ {
+ "id": "protocol-test-covers-compensation-route",
+ "sourcePath": "packages/protocol/test/protocol-package-boundary.test.js",
+ "passed": true
+ },
+ {
+ "id": "terminal-composer-captures-compensation-roots",
+ "sourcePath": "uapi/app/terminal/TerminalDepositComposer.tsx",
+ "passed": true
+ },
+ {
+ "id": "terminal-history-maps-compensation-roots",
+ "sourcePath": "uapi/app/terminal/terminal-activity-history.ts",
+ "passed": true
+ },
+ {
+ "id": "terminal-workbench-shows-compensation-rows",
+ "sourcePath": "uapi/app/terminal/terminal-deposit-read-workbench.ts",
+ "passed": true
+ },
+ {
+ "id": "workspace-run-carries-compensation-fields",
+ "sourcePath": "uapi/app/terminal/terminal-run-data.ts",
+ "passed": true
+ },
+ {
+ "id": "asset-pack-readme-documents-compensation-preview",
+ "sourcePath": "packages/pipelines/asset-pack/README.md",
+ "passed": true
+ },
+ {
+ "id": "v42-spec-gate2-expanded",
+ "sourcePath": "BITCODE_SPEC_V42.md",
+ "passed": true
+ },
+ {
+ "id": "v42-delta-gate2-implemented",
+ "sourcePath": "BITCODE_SPEC_V42_DELTA.md",
+ "passed": true
+ },
+ {
+ "id": "v42-notes-gate2-rehearsal",
+ "sourcePath": "BITCODE_SPEC_V42_NOTES.md",
+ "passed": true
+ },
+ {
+ "id": "v42-parity-gate2-closed",
+ "sourcePath": "BITCODE_SPEC_V42_PARITY_MATRIX.md",
+ "passed": true
+ },
+ {
+ "id": "roadmap-current-gate-advanced",
+ "sourcePath": "SPECIFICATIONS_ROADMAP.md",
+ "passed": true
+ }
+ ],
+ "coverage": {
+ "rowCount": 8,
+ "requiredPredicateCount": 21,
+ "passedPredicateCount": 21,
+ "failedPredicateIds": [],
+ "acceptedUserPath": [
+ "provide-source-material",
+ "select-repository-source-anchor",
+ "admit-deposit-to-depository",
+ "receive-source-safe-admission-proof",
+ "view-later-btc-compensation-attribution"
+ ],
+ "routeApiContractsCovered": true,
+ "sourceValidationCovered": true,
+ "storageProjectionCovered": true,
+ "depositorySearchDocumentCovered": true,
+ "sourceToSharesCompensationReadbackCovered": true,
+ "terminalCompensationVisibilityCovered": true,
+ "localStagingRehearsalCovered": true,
+ "sourceSafeMetadataOnly": true,
+ "protectedSourceVisible": false,
+ "rawSourceTextVisible": false,
+ "credentialsSerialized": false,
+ "walletPrivateMaterialVisible": false,
+ "unpaidAssetPackSourceVisible": false,
+ "settlementPrivatePayloadVisible": false,
+ "btdMintedAtDepositAdmission": false,
+ "btdRightsTransferredBeforeSettlement": false,
+ "compensationAllocationMethod": "source-to-shares-largest-remainder",
+ "compensationPriceAsset": "BTC",
+ "legacySourceRoots": false
+ },
+ "sourceRoots": {
+ "depositorySupplyIndex": "packages/pipelines/asset-pack/src/depository-supply-index.ts",
+ "depositorySupplyIndexTest": "packages/pipelines/asset-pack/src/__tests__/depository-supply-index.test.ts",
+ "embeddingConfig": "packages/pipelines/asset-pack/src/embedding-config.ts",
+ "assetPackReadme": "packages/pipelines/asset-pack/README.md",
+ "protocolServer": "packages/protocol/server.js",
+ "protocolRuntime": "packages/protocol/src/bitcode-demo.js",
+ "protocolBoundaryTest": "packages/protocol/test/protocol-package-boundary.test.js",
+ "uapiDepositRoute": "uapi/app/api/deposits/route.ts",
+ "terminalDepositComposer": "uapi/app/terminal/TerminalDepositComposer.tsx",
+ "terminalActivityHistory": "uapi/app/terminal/terminal-activity-history.ts",
+ "terminalWorkbench": "uapi/app/terminal/terminal-deposit-read-workbench.ts",
+ "terminalRunData": "uapi/app/terminal/terminal-run-data.ts",
+ "v42Spec": "BITCODE_SPEC_V42.md",
+ "v42Delta": "BITCODE_SPEC_V42_DELTA.md",
+ "v42Notes": "BITCODE_SPEC_V42_NOTES.md",
+ "v42Parity": "BITCODE_SPEC_V42_PARITY_MATRIX.md",
+ "roadmap": "SPECIFICATIONS_ROADMAP.md"
+ }
+}
diff --git a/.github/workflows/bitcode-canon-quality.yml b/.github/workflows/bitcode-canon-quality.yml
index 44ffb620..05484b61 100644
--- a/.github/workflows/bitcode-canon-quality.yml
+++ b/.github/workflows/bitcode-canon-quality.yml
@@ -295,6 +295,9 @@ jobs:
if [ -f BITCODE_SPEC_V42.md ]; then
node scripts/check-bitcode-spec-family.mjs --version V42 --mode draft --current-target V41
node scripts/check-v42-gate1-mvp-experience-roadmap-opening.mjs --skip-branch-check
+ if [ -f scripts/check-v42-gate2-depositing-shortest-path.mjs ]; then
+ node scripts/check-v42-gate2-depositing-shortest-path.mjs --skip-branch-check --skip-package-tests
+ fi
fi
else
echo "Unexpected BITCODE_SPEC.txt pointer: $POINTER" >&2
diff --git a/.github/workflows/bitcode-gate-quality.yml b/.github/workflows/bitcode-gate-quality.yml
index 906125d9..40c215f9 100644
--- a/.github/workflows/bitcode-gate-quality.yml
+++ b/.github/workflows/bitcode-gate-quality.yml
@@ -424,6 +424,9 @@ jobs:
if [ -f BITCODE_SPEC_V42.md ]; then
node scripts/check-bitcode-spec-family.mjs --version V42 --mode draft --current-target V41
node scripts/check-v42-gate1-mvp-experience-roadmap-opening.mjs --skip-branch-check
+ if [ -f scripts/check-v42-gate2-depositing-shortest-path.mjs ]; then
+ node scripts/check-v42-gate2-depositing-shortest-path.mjs --skip-branch-check --skip-package-tests
+ fi
fi
else
echo "Unexpected BITCODE_SPEC.txt pointer: $POINTER" >&2
diff --git a/BITCODE_SPEC_V42.md b/BITCODE_SPEC_V42.md
index bf8336e7..71339f89 100644
--- a/BITCODE_SPEC_V42.md
+++ b/BITCODE_SPEC_V42.md
@@ -99,9 +99,18 @@ It closes when active V41 / draft V42 truth is visible in the root docs, protoco
## V42 Gate 2 Depositing Shortest Path And Compensation Visibility
-Gate 2 must make the shortest deposit path explicit and testable.
+Gate 2 makes the shortest deposit path explicit and testable.
The accepted user path is: provide source material, select repository/source anchor, admit deposit to the Depository, receive source-safe admission proof, and see how later BTC compensation will be attributed if the deposit participates in a synthesized AssetPack.
-It must cover route/API contracts, source validation, storage projection, Depository search-document creation, BTD/source-to-shares compensation readback, telemetry, and local/staging rehearsal.
+The implemented path covers route/API contracts, source validation, storage projection, Depository search-document creation, BTD/source-to-shares compensation readback, telemetry, and local/staging rehearsal posture.
+
+Gate 2 introduces source-safe compensation visibility as a first-class Depository admission readback.
+`DepositorySupplyRecord.compensationPreview` and deposit route `depositoryEvidence.compensationPreview` expose only source-safe metadata: compensation state, depositor wallet id, BTC price asset, source-to-shares largest-remainder allocation method, compensation route root, source-to-shares preview root, ledger readback keys, database projection tables, and repair blockers.
+The compensation route preview is not a BTD mint and not a rights transfer.
+It states that source-to-shares proof, BTC allocation, BTD rights transfer, and source-bearing AssetPack delivery occur only after an accepted Need-Fit creates a paid AssetPack and settlement finality is observed.
+
+Gate 2 proof artifact: `.bitcode/v42-depositing-shortest-path.json`.
+The artifact must prove eight source-safe rows: source-to-admission path, deposit route readiness contract, Depository record compensation preview, source-safe search/vector projection, storage readback projection, source-to-shares compensation ledger readback, Terminal compensation visibility readback, and local/staging deposit readback posture.
+Validating command: `pnpm run check:v42-gate2`.
## V42 Gate 3 Reading Shortest Path State Machine
diff --git a/BITCODE_SPEC_V42_DELTA.md b/BITCODE_SPEC_V42_DELTA.md
index 54ceb8db..cfc889e1 100644
--- a/BITCODE_SPEC_V42_DELTA.md
+++ b/BITCODE_SPEC_V42_DELTA.md
@@ -35,6 +35,8 @@ Open the V42 full specification family, roadmap, package script, workflow postur
### Gate 2: Depositing Shortest Path And Compensation Visibility
Implement and prove the shortest path from source material to Depository admission proof and later compensation readback.
+Gate 2 now binds Depository admission proof to a source-safe compensation route preview, route/API readiness, Depository search documents, vector/storage projection, source-to-shares readback keys, Terminal activity/history/readback fields, and `.bitcode/v42-depositing-shortest-path.json`.
+The compensation preview is deliberately pre-mint: it records BTC/source-to-shares eligibility if the deposit is selected into a later paid AssetPack, but it does not mint BTD, transfer rights, expose source, or allocate BTC before accepted Need-Fit and settlement.
### Gate 3: Reading Shortest Path State Machine
diff --git a/BITCODE_SPEC_V42_NOTES.md b/BITCODE_SPEC_V42_NOTES.md
index 9d79f471..9c67e6be 100644
--- a/BITCODE_SPEC_V42_NOTES.md
+++ b/BITCODE_SPEC_V42_NOTES.md
@@ -27,6 +27,9 @@ It opens the reliable MVP experience version after V41 prompt-program promotion
The V42 Depositing path should minimize the journey from source material to Depository admission proof.
The user needs to know that the source is admitted, searchable for future Need-Fit work, and eligible for BTC compensation if it contributes to a synthesized AssetPack.
The UX can stay simple, but expandable details must show source authority, admission proof, storage projection, search-document posture, compensation route, and repair state.
+Gate 2 implements that note through `DepositorySupplyCompensationPreview`, deposit route `depositoryEvidence.compensationPreview`, Terminal compensation readback rows, and `.bitcode/v42-depositing-shortest-path.json`.
+Local/staging rehearsal for this gate means the deposit route, source-safe evidence projection, generated artifact, package test, and protocol route test can run without value-bearing mainnet behavior.
+The staging-testnet lane may read the same source-safe roots and ledger keys, but secrets and private source remain outside generated artifacts.
## Reading shortest-path note
@@ -59,6 +62,10 @@ V43 or a later explicitly opened version should evolve the deposit side into an
Repository-installed Bitcode Agents should compare a connected enterprise codebase, the current Bitcode Depository, and Reading activity to propose deposit AssetPack options.
Those options should be source-safe, sub-critical, likely positive ROI, and approve/rejectable before Depository admission.
That later version should split `/terminal` into `/read` and `/deposit`, and rename `/exchange` to `/packs` across routes, code naming, docs, and operator vocabulary.
+The route model should be AssetPacks in and AssetPacks out: `/deposit` creates reviewable deposit AssetPack options from connected source, depositor instructions, and Bitcode's observed Needs; `/read` creates reviewed Need-Fit AssetPack previews and only unlocks source-bearing delivery after settlement; `/packs` is the searchable master-detail activity route for deposited packs, settled read packs, compensation posture, quotes, rights transfer, delivery, and repair.
+The `/packs` master view should support column sorting, filtering, and search over measurements, synthesized AssetPack titles and descriptions, values, activity or transaction type, settlement posture, and compensation state.
+The detail view should expose the selected activity's source-safe data, proof roots, telemetry, ledger/database synchronization, and expandable payloads without replacing the short default path.
+Outside public documentation, product UX should avoid self-referential explanatory copy; route structure, concise labels, progressive detail, and proof-on-expand must make Depositing, Reading, and Pack activity self-explanatory.
## Concise current-system reading
diff --git a/BITCODE_SPEC_V42_PARITY_MATRIX.md b/BITCODE_SPEC_V42_PARITY_MATRIX.md
index 3c22230a..58e561f3 100644
--- a/BITCODE_SPEC_V42_PARITY_MATRIX.md
+++ b/BITCODE_SPEC_V42_PARITY_MATRIX.md
@@ -33,7 +33,7 @@ This matrix records the reliable MVP product surfaces that must become promotion
| Roadmap truth | Roadmap states V41 active and V42 draft reliable MVP experience | `SPECIFICATIONS_ROADMAP.md` | drafted |
| Gate workflow | Gate quality knows active V41 / draft V42 posture and V42 Gate 1 | `.github/workflows/bitcode-gate-quality.yml` | drafted |
| Canon workflow | Canon quality knows active V41 / draft V42 posture and V42 Gate 1 | `.github/workflows/bitcode-canon-quality.yml` | drafted |
-| Depositing shortest path | Source material can be admitted with Depository proof and compensation visibility | later V42 Gate 2 artifact | draft-required |
+| Depositing shortest path | Source material can be admitted with Depository proof and compensation visibility | `.bitcode/v42-depositing-shortest-path.json`, `DepositorySupplyCompensationPreview`, `/api/deposits`, Terminal deposit readback | implemented |
| Reading state machine | Five-step Reading UX is route-owned, persistent, and source-safe | later V42 Gate 3 artifact | draft-required |
| ReadNeed product closure | Need synthesis, review, feedback, resynthesis, and accepted-Need admission are product-ready | later V42 Gate 4 artifact | draft-required |
| Finding Fits preview and quote | Many-candidate search, selected-fit provenance, source-safe preview, and quote are product-ready | later V42 Gate 5 artifact | draft-required |
@@ -47,7 +47,7 @@ This matrix records the reliable MVP product surfaces that must become promotion
| Area | Closure requirement | Judgment |
| --- | --- | --- |
| Gate 1 | Open V42 family, roadmap, docs, workflow posture, package script, and checker | drafted |
-| Gate 2 | Depositing shortest path and compensation visibility artifact | draft-required |
+| Gate 2 | Depositing shortest path and compensation visibility artifact | implemented |
| Gate 3 | Reading shortest path state machine artifact | draft-required |
| Gate 4 | ReadNeed review and resynthesis product closure artifact | draft-required |
| Gate 5 | ReadFitsFinding AssetPack preview and quote closure artifact | draft-required |
diff --git a/README.md b/README.md
index cd3295dc..e3512001 100644
--- a/README.md
+++ b/README.md
@@ -87,11 +87,22 @@ later BTC compensation, shortest-path Reading through Need review/resynthesis,
Finding Fits, source-safe AssetPack preview, BTD/BTC settlement, repository
delivery, and an AI-reading dominant demonstration whose AssetPack measurably
improves an AI system beyond public-data-only performance.
+V42 Gate 2 adds source-safe Depositing compensation visibility with
+`DepositorySupplyCompensationPreview`, deposit route compensation evidence,
+Terminal compensation roots, `.bitcode/v42-depositing-shortest-path.json`,
+and `check:v42-gate2`. Deposit admission remains pre-mint and pre-rights
+transfer; BTC source-to-shares allocation is only a later paid AssetPack
+settlement route.
V43+ is roadmapped as the later agentic depositing evolution: repository
agents synthesize deposit AssetPack options from connected enterprise code,
Depository state, and Reading demand; enterprises approve or reject
sub-critical positive-ROI options; `/terminal` separates into `/read` and
`/deposit`; and `/exchange` is renamed to `/packs` across product naming.
+That future route model treats AssetPacks as the product object in and out:
+`/deposit` proposes deposit AssetPack options from source and Bitcode demand,
+`/read` buys synthesized Need-Fit AssetPacks, and `/packs` becomes the
+searchable master-detail activity surface for pack measurements, values,
+settlement posture, compensation, delivery, proofs, and repair.
Exchange is inherited V36 canon: market-wide activity master-detail, buy/sell/
bid/ask/cancel/accept/settle/history flows, AssetPack range trading,
diff --git a/SPECIFICATIONS_ROADMAP.md b/SPECIFICATIONS_ROADMAP.md
index c652332a..de22cd64 100644
--- a/SPECIFICATIONS_ROADMAP.md
+++ b/SPECIFICATIONS_ROADMAP.md
@@ -5,10 +5,11 @@
- Current active canonical pointer: `BITCODE_SPEC.txt` -> `V41`
- Current active canon: `BITCODE_SPEC_V41.md`
- Current draft target: `BITCODE_SPEC_V42.md`.
-- Current working gate: V42 Gate 1 MVP Experience Roadmap And Spec Opening.
-- Next queued gate after V42 Gate 1: V42 Gate 2 Depositing Shortest Path And Compensation Visibility.
+- Current working gate: V42 Gate 2 Depositing Shortest Path And Compensation Visibility.
+- Next queued gate after V42 Gate 2: V42 Gate 3 Reading Shortest Path State Machine.
- Latest closed version: V41 Prompt And PromptPart Excellence, which promoted PromptPart and Prompt inventory, registry interpolation contracts, Reading prompt baselines, ReadNeedComprehensionSynthesis prompt hardening, ReadFitsFindingSynthesis prompt hardening, Conversation/tool/interface prompt rewrite, prompt benchmark telemetry, and V41 promotion readiness.
- Recent V42 opening anchor: reliable MVP experience opens over promoted V41 with V42 SPEC, DELTA, NOTES, and PARITY files, `check:v42-gate1`, active V41 / draft V42 posture, and a nine-gate plan for shortest-path Depositing, five-step Reading, ReadNeed product closure, ReadFitsFinding preview and quote closure, settlement and repository delivery, AI-reading demonstration, local/staging rehearsal, and promotion readiness.
+- V42 Gate 2 closure anchor: reliable MVP experience now owns source-safe Depositing compensation visibility through `DepositorySupplyCompensationPreview`, deposit route `depositoryEvidence.compensationPreview`, deterministic `.bitcode/v42-depositing-shortest-path.json`, route/API readiness checks, source validation, Depository search/vector/storage projection, source-to-shares compensation readback keys, Terminal compensation roots, focused package/protocol tests, workflow wiring, and `check:v42-gate2`.
- Recent V41 closure anchor: V41 canonical promotion updated `BITCODE_SPEC.txt` to `V41`, generated `BITCODE_SPEC_V41_PROVEN.md`, preserved active V41 / draft V42 runtime posture, and closed prompt-program excellence canon.
- Recent V40 closure anchor: V40 canonical promotion updated `BITCODE_SPEC.txt` to `V40`, generated `BITCODE_SPEC_V40_PROVEN.md`, preserved active V40 / draft V41 runtime posture, and closed exhaustive commercial application testing canon.
- Recent V39 closure anchor: V39 canonical promotion updated `BITCODE_SPEC.txt` to `V39`, generated `BITCODE_SPEC_V39_PROVEN.md`, preserved active V39 / draft V40 runtime posture, and closed commercial Reading readiness canon.
@@ -37,6 +38,7 @@
- V41 Gate 9 closure anchor: prompt-program work now owns package-backed `V41PromotionReadinessReport` source, deterministic `.bitcode/v41-promotion-readiness-report.json`, `BITCODE_SPEC_V41_PROVEN.md` generation support, `v41-canon-promotion.yml`, promotion command dry-run support, gate/canon workflow posture, active V41 / draft V42 runtime preparation, all V41 prompt-program artifacts covered, source-safe, parseable, and workflow-bound, and value-bearing mainnet admission blocked through `check:v41-gate9`.
- Forward planning note: V42 focuses on the reliable MVP product experience after V41's prompt-program hardening. Depositing should become the shortest path to adding any source material, proving its Depository admission, and later receiving BTC compensation when that deposit contributes to a synthesized AssetPack. Reading should become the shortest path to submitting a Read Request, reviewing or resynthesizing Bitcode's synthesized Need, requesting Finding Fits, reviewing source-safe AssetPack measurements and preview metadata, buying the AssetPack through BTD/BTC settlement semantics, and receiving post-settlement repository delivery. The demonstration should be AI-reading dominant: any deposit source can contribute proprietary or otherwise non-public training, prompt, context, or evaluation material to an AssetPack that measurably improves an AI system beyond a public-data-only baseline.
- Forward planning note: V43+ should evolve the deposit side into an agentic AssetPack option experience for enterprises that own connected codebases. Bitcode Agents installed on an enterprise repository should compare the repository, the current Bitcode Depository, and current Reading activity to propose deposit AssetPack options: unminted AssetPacks in all but BTD that can later become BTD only when a Reader's industrial Need-Fit mints one. The deposit pipeline should optimize for enterprise IP governance by filtering out critical IP, estimating whether selling would be positive ROI against development cost and expected Read demand, and presenting everything else as approve/reject deposit options. The product route plan for that version is to split `/terminal` into `/read` for Reading and `/deposit` for agentic deposit AssetPack option review, and to rename `/exchange` to `/packs` across routes, code names, and docs.
+- Forward planning note: V43+ should treat AssetPacks as the in/out simplification for the product. Depositing turns connected source plus depositor instructions plus Bitcode's observed Needs into deposit AssetPack options for approval; Reading turns an accepted Need plus many fitted Depository AssetPacks into a source-safe preview, quote, settlement, rights transfer, and repository delivery. `/packs` should replace Exchange naming as the master-detail activity route: the master view is a searchable, sortable, filterable table over activity, synthesized AssetPack titles/descriptions, measurements, values, transaction types, settlement posture, and compensation state; the detail view shows the selected activity with expandable proof, ledger, telemetry, and payload readback. Product surfaces outside public documentation should avoid self-referential explanatory copy and instead make the core actions self-evident through route structure, labels, progressive detail, and proof-on-expand.
- V34 Gate 2 closure anchor: deployment-depth now owns package-backed `DeploymentHostCapabilityCatalog` and `EnvironmentLaneContract` source, deterministic `.bitcode/v34-deployment-host-capability-catalog.json` and `.bitcode/v34-environment-lane-contracts.json`, and visible `value-bearing-mainnet` blocking through `blocked_future_canon_required`.
- V34 Gate 3 closure anchor: deployment-depth now owns package-backed `DistributedExecutionRuntimeReceipt` source, deterministic `.bitcode/v34-distributed-execution-runtime-receipts.json`, `request_response_not_required` long-running work posture, and source-safe roots for pipeline, PTRR agent, ThricifiedGeneration, tool, ledger, wallet, proof, object-storage, and repair work.
- V34 Gate 4 closure anchor: deployment-depth now owns package-backed `DeploymentStoragePosture` source, deterministic `.bitcode/v34-deployment-storage-posture.json`, ledger/database/object-storage drift repair fixtures, retention/encryption/backup/rollback/audit posture, and source-bearing AssetPack storage remains locked before settlement.
@@ -158,7 +160,7 @@ They are referenced here for specification history only; active implementation w
| V40 | `BITCODE_SPEC_V40.md` | promoted historical Bitcode canon | Exhaustive commercial application testing depth after V39: rich browser E2E for all website interactions and state possibilities, visual/screenshot comparison coverage, API and integration suites for pipelines, conversations, routes, ledger/database/storage synchronization, unit coverage for packages, primitives, isolated implementations, real commercial implementations, local/staging rehearsal automation, prompt benchmark smoke, and promotion readiness. |
| V41 | `BITCODE_SPEC_V41.md` | active canon | Prompt and PromptPart excellence, treating prompts as programs: audit every raw PromptPart and composed Prompt, run and harden benchmarks, repartition prompts into meaningfully benchmarkable semantic parts, retitle and rewrite PromptParts/Prompts where optimal, catalogue registry bindings, interpolation contracts, benchmark fixtures, benchmark outputs, inference callsites, and parsed return types, and elevate all Reading and Conversation inference points after V38 inference scaffolding and V40 testing depth make that work measurable. The primary surface is Reading, especially `ReadNeedComprehensionSynthesis` and `ReadFitsFindingSynthesis`; conversations and other inference prompts follow with the same benchmarkable catalogue discipline. |
| V42 | `BITCODE_SPEC_V42.md` | active draft target | Reliable MVP experience after V41 prompt hardening: shortest-path Depositing for any source material with Depository admission proof and later BTC compensation when deposits contribute to synthesized AssetPacks; shortest-path Reading for Read Request submission, synthesized Need review/resynthesis, Finding Fits, source-safe AssetPack measurement/preview review, BTD/BTC purchase and settlement, and repository delivery; and an AI-reading dominant demonstration proving an AssetPack can improve an AI system's training, prompt/context, or evaluation performance beyond public-data-only baselines using proprietary or otherwise non-public deposit and read materials. |
-| V43+ | future specification family | planned future | Agentic enterprise deposit-side AssetPack option synthesis after the MVP paths are reliable: repository-installed Bitcode Agents compare a connected enterprise codebase, the Bitcode Depository, and Reading activity to propose deposit AssetPack options for review; filter out critical IP; estimate positive ROI against development cost and likely demand; let enterprises approve/reject options for Depository admission; split `/terminal` into `/read` and `/deposit`; and rename `/exchange` to `/packs` throughout product routes, code naming, docs, and operator vocabulary. |
+| V43+ | future specification family | planned future | Agentic enterprise deposit-side AssetPack option synthesis after the MVP paths are reliable: repository-installed Bitcode Agents compare a connected enterprise codebase, the Bitcode Depository, and Reading activity to propose deposit AssetPack options for review; filter out critical IP; estimate positive ROI against development cost and likely demand; let enterprises approve/reject options for Depository admission; split `/terminal` into `/read` and `/deposit`; and rename `/exchange` to `/packs` throughout product routes, code naming, docs, and operator vocabulary. `/packs` becomes the searchable master-detail activity surface for all pack activity, while `/deposit` and `/read` become the short core paths into and out of the Depository. |
## Current Planning Spine
@@ -187,6 +189,6 @@ They are referenced here for specification history only; active implementation w
- Do use `_legacy/` specifications to understand why current Bitcode concepts exist and what must not regress.
- V42+ work must build on V41 active canon and V27 `$BTD` law unless a future promoted spec explicitly supersedes it.
- V42 is the active draft target for reliable MVP experience; Gate 1 is specification/documentation/workflow posture only and later gates own implementation.
-- V43+ agentic depositing, `/read` and `/deposit` route separation, and `/packs` renaming are roadmap/planning only until a later version explicitly opens them; V42 remains scoped to reliable MVP Depositing, Reading, settlement, delivery, and AI-reading demonstration.
+- V43+ agentic depositing, `/read` and `/deposit` route separation, `/packs` renaming, searchable pack activity master-detail, and deposit AssetPack option synthesis are roadmap/planning only until a later version explicitly opens them; V42 remains scoped to reliable MVP Depositing, Reading, settlement, delivery, and AI-reading demonstration.
- No implementation route should be versioned by spec number; source should move in place with the active canon.
- Future notes files are planning memory only until their version is explicitly opened as the draft-target SPEC family.
diff --git a/package.json b/package.json
index be225050..a66382ab 100644
--- a/package.json
+++ b/package.json
@@ -304,6 +304,9 @@
"check:v41-promotion-readiness": "node scripts/generate-v41-promotion-readiness-report.mjs --check",
"check:v41-gate9": "node scripts/check-v41-gate9-promotion-readiness.mjs",
"check:v42-gate1": "node scripts/check-v42-gate1-mvp-experience-roadmap-opening.mjs",
+ "generate:v42-depositing-shortest-path": "node scripts/generate-v42-depositing-shortest-path.mjs",
+ "check:v42-depositing-shortest-path": "node scripts/generate-v42-depositing-shortest-path.mjs --check",
+ "check:v42-gate2": "node scripts/check-v42-gate2-depositing-shortest-path.mjs",
"generate:v38-inference-surface-inventory": "node scripts/generate-v38-inference-surface-inventory.mjs",
"check:v38-inference-surface-inventory": "node scripts/generate-v38-inference-surface-inventory.mjs --check",
"check:v38-gate2": "node scripts/check-v38-gate2-inference-surface-inventory.mjs",
diff --git a/packages/pipelines/asset-pack/README.md b/packages/pipelines/asset-pack/README.md
index 021c0971..efcc5d76 100644
--- a/packages/pipelines/asset-pack/README.md
+++ b/packages/pipelines/asset-pack/README.md
@@ -98,8 +98,8 @@ deposited repository/material supply into searchable Depository records before
Finding Fits runs. A `DepositorySupplyIndex` contains `DepositorySupplyRecord`
entries with repository, branch, commit, proof root, measurement root,
reconciliation readback root, BTD range, depositor wallet boundary, source-safe
-search documents, vector projection rows, storage readback posture, and repair
-actions.
+search documents, vector projection rows, storage readback posture, source-safe
+compensation preview, and repair actions.
The index deliberately keeps protected source outside the serialized record.
Lexical, metadata, measurement, and vector search documents use source-safe
@@ -108,6 +108,16 @@ Rows with missing or invalid embeddings remain visible as repair posture through
`sync-active-embedding-vector-rows`; they are not treated as a fully searchable
vector corpus.
+Each supply record also carries a `DepositorySupplyCompensationPreview`. That
+preview tells the depositor how BTC can later route back through
+source-to-shares if the deposit is selected into a paid AssetPack, while making
+the pre-fit boundary explicit: deposit admission does not mint BTD, does not
+transfer BTD rights, and does not expose protected source or unpaid
+source-bearing AssetPack content. The preview records compensation route roots,
+source-to-shares preview roots, ledger account keys such as pending claims and
+eligible compensation routes, and repair posture when a depositor wallet,
+proof, measurement, or searchability requirement is missing.
+
`depositorySupplyAssetsFromIndex` converts indexed records into source-safe
`DepositoryAsset` candidates for `ReadFitsFindingSynthesis`. This handoff lets
Finding Fits rank Depository supply without importing raw source text, unpaid
diff --git a/packages/pipelines/asset-pack/src/__tests__/depository-supply-index.test.ts b/packages/pipelines/asset-pack/src/__tests__/depository-supply-index.test.ts
index 4828a8e4..43212eee 100644
--- a/packages/pipelines/asset-pack/src/__tests__/depository-supply-index.test.ts
+++ b/packages/pipelines/asset-pack/src/__tests__/depository-supply-index.test.ts
@@ -111,6 +111,46 @@ describe('Depository supply index', () => {
settlementRequiredForSourceBearingAssetPack: true,
btdOwnershipBoundary: 'depositor-retains-btd-until-settlement-transfer',
});
+ expect(record.compensationPreview).toMatchObject({
+ schema: 'bitcode.depository.supply-compensation-preview',
+ state: 'eligible-if-selected-for-assetpack',
+ depositorWalletId: 'wallet-depositor-1',
+ candidateBtdRange: 'btd:100:140',
+ compensationRoute: {
+ payer: 'future-reader-after-settlement',
+ payee: 'depositing-wallet',
+ priceAsset: 'BTC',
+ allocationMethod: 'source-to-shares-largest-remainder',
+ sourceToSharesProofState: 'not-created-until-accepted-need-fit-and-settlement',
+ btdMintBoundary: 'not-minted-by-deposit-admission',
+ btdRightsTransferBoundary: 'reader-receives-rights-only-after-btc-settlement',
+ },
+ readiness: {
+ proofReady: true,
+ measurementReady: true,
+ searchable: true,
+ depositorWalletReady: true,
+ eligibleForFindingFits: true,
+ eligibleForCompensationIfSelected: true,
+ blockers: [],
+ },
+ visibility: {
+ beforeSettlement: 'source-safe-compensation-route-metadata',
+ protectedSourceVisible: false,
+ unpaidAssetPackSourceVisible: false,
+ walletPrivateMaterialVisible: false,
+ settlementPrivatePayloadVisible: false,
+ },
+ });
+ expect(record.compensationPreview.roots.compensationPreviewRoot).toMatch(/^sha256:/);
+ expect(record.compensationPreview.roots.sourceToSharesPreviewRoot).toMatch(/^sha256:/);
+ expect(record.compensationPreview.readback.ledgerAccountKeys).toEqual(
+ expect.arrayContaining([
+ 'supplier:asset-terminal-engi:pending_claims',
+ 'depositor:wallet-depositor-1:deposited_assets',
+ 'depositor:wallet-depositor-1:eligible_compensation_routes',
+ ]),
+ );
expect(record.vectorProjection.rows).toHaveLength(4);
expect(record.vectorProjection.rows.every((row) => row.embeddingState === 'ready')).toBe(true);
expect(record.storageProjection).toMatchObject({
@@ -163,9 +203,41 @@ describe('Depository supply index', () => {
expect(index.records[0].lifecycle.blockers).toEqual(
expect.arrayContaining(['repository_binding_missing', 'source_revision_binding_missing']),
);
+ expect(index.records[0].compensationPreview.state).toBe('blocked-before-compensation');
+ expect(index.records[0].compensationPreview.readiness.blockers).toEqual(
+ expect.arrayContaining([
+ 'repository_binding_missing',
+ 'source_revision_binding_missing',
+ 'depository_searchability_missing',
+ ]),
+ );
expect(depositorySupplyAssetsFromIndex(index)).toHaveLength(0);
});
+ it('surfaces repair posture when deposit compensation cannot route to a wallet', () => {
+ const index = buildDepositorySupplyIndex({
+ deposits: [deposit({ depositorWalletId: null })],
+ createdAt: '2026-05-25T00:00:00.000Z',
+ });
+
+ const record = index.records[0];
+ expect(record.lifecycle.state).toBe('indexed-repair-required');
+ expect(record.lifecycle.warnings).toEqual(expect.arrayContaining(['depositor_wallet_missing']));
+ expect(record.repairActions).toContain('bind-depositor-wallet-for-compensation');
+ expect(record.compensationPreview.state).toBe('repair-required-before-compensation');
+ expect(record.compensationPreview.readiness).toMatchObject({
+ searchable: true,
+ proofReady: true,
+ measurementReady: true,
+ depositorWalletReady: false,
+ eligibleForFindingFits: true,
+ eligibleForCompensationIfSelected: false,
+ });
+ expect(record.compensationPreview.readiness.blockers).toEqual(
+ expect.arrayContaining(['depositor_wallet_missing']),
+ );
+ });
+
it('hands source-safe supply records to Finding Fits search as candidate deposits', async () => {
const index = buildDepositorySupplyIndex({
deposits: [deposit()],
diff --git a/packages/pipelines/asset-pack/src/depository-supply-index.ts b/packages/pipelines/asset-pack/src/depository-supply-index.ts
index f83044db..79f0227e 100644
--- a/packages/pipelines/asset-pack/src/depository-supply-index.ts
+++ b/packages/pipelines/asset-pack/src/depository-supply-index.ts
@@ -11,6 +11,11 @@ export type DepositorySupplyLifecycleState =
| 'indexed-repair-required'
| 'blocked-readiness';
+export type DepositorySupplyCompensationState =
+ | 'eligible-if-selected-for-assetpack'
+ | 'repair-required-before-compensation'
+ | 'blocked-before-compensation';
+
export type DepositorySupplySearchDocumentKind =
| 'lexical'
| 'metadata'
@@ -64,6 +69,7 @@ export interface DepositorySupplyRecord {
settlementRequiredForSourceBearingAssetPack: true;
btdOwnershipBoundary: 'depositor-retains-btd-until-settlement-transfer';
};
+ compensationPreview: DepositorySupplyCompensationPreview;
proofEvidence: {
hasWalletOrAttestationProof: boolean;
proofRoot: string | null;
@@ -88,6 +94,54 @@ export interface DepositorySupplyRecord {
vectorProjectionRoot: string;
storageProjectionRoot: string;
rightsBoundaryRoot: string;
+ compensationPreviewRoot: string;
+ };
+}
+
+export interface DepositorySupplyCompensationPreview {
+ schema: 'bitcode.depository.supply-compensation-preview';
+ state: DepositorySupplyCompensationState;
+ assetId: string;
+ depositId: string;
+ depositorWalletId: string | null;
+ candidateBtdRange: string | null;
+ compensationRoute: {
+ payer: 'future-reader-after-settlement';
+ payee: 'depositing-wallet';
+ priceAsset: 'BTC';
+ allocationMethod: 'source-to-shares-largest-remainder';
+ sourceToSharesProofState: 'not-created-until-accepted-need-fit-and-settlement';
+ btdMintBoundary: 'not-minted-by-deposit-admission';
+ btdRightsTransferBoundary: 'reader-receives-rights-only-after-btc-settlement';
+ };
+ readiness: {
+ sourceBound: boolean;
+ proofReady: boolean;
+ measurementReady: boolean;
+ searchable: boolean;
+ depositorWalletReady: boolean;
+ eligibleForFindingFits: boolean;
+ eligibleForCompensationIfSelected: boolean;
+ blockers: string[];
+ warnings: string[];
+ };
+ visibility: {
+ beforeSettlement: 'source-safe-compensation-route-metadata';
+ protectedSourceVisible: false;
+ unpaidAssetPackSourceVisible: false;
+ walletPrivateMaterialVisible: false;
+ settlementPrivatePayloadVisible: false;
+ };
+ readback: {
+ ledgerAccountKeys: string[];
+ databaseProjectionTables: string[];
+ objectStorageVisibility: 'source-safe-metadata-only-before-settlement';
+ };
+ roots: {
+ compensationRouteRoot: string;
+ sourceToSharesPreviewRoot: string;
+ readbackRoot: string;
+ compensationPreviewRoot: string;
};
}
@@ -401,6 +455,117 @@ function buildVectorProjection(input: {
};
}
+function buildCompensationPreview(input: {
+ assetId: string;
+ depositId: string;
+ depositorWalletId: string | null;
+ btdRange: string | null;
+ sourceBound: boolean;
+ proofReady: boolean;
+ measurementReady: boolean;
+ searchable: boolean;
+ blockers: string[];
+ warnings: string[];
+}): DepositorySupplyCompensationPreview {
+ const compensationBlockers = [
+ ...input.blockers,
+ ...(!input.depositorWalletId ? ['depositor_wallet_missing'] : []),
+ ...(!input.proofReady ? ['wallet_or_attestation_proof_missing'] : []),
+ ...(!input.measurementReady ? ['asset_measurement_evidence_missing'] : []),
+ ...(!input.searchable ? ['depository_searchability_missing'] : []),
+ ];
+ const eligibleForCompensationIfSelected = compensationBlockers.length === 0;
+ const state: DepositorySupplyCompensationState = eligibleForCompensationIfSelected
+ ? 'eligible-if-selected-for-assetpack'
+ : input.blockers.length
+ ? 'blocked-before-compensation'
+ : 'repair-required-before-compensation';
+ const compensationRoute = {
+ payer: 'future-reader-after-settlement' as const,
+ payee: 'depositing-wallet' as const,
+ priceAsset: 'BTC' as const,
+ allocationMethod: 'source-to-shares-largest-remainder' as const,
+ sourceToSharesProofState: 'not-created-until-accepted-need-fit-and-settlement' as const,
+ btdMintBoundary: 'not-minted-by-deposit-admission' as const,
+ btdRightsTransferBoundary: 'reader-receives-rights-only-after-btc-settlement' as const,
+ };
+ const readback = {
+ ledgerAccountKeys: [
+ `supplier:${input.assetId}:pending_claims`,
+ ...(input.depositorWalletId
+ ? [
+ `depositor:${input.depositorWalletId}:deposited_assets`,
+ `depositor:${input.depositorWalletId}:eligible_compensation_routes`,
+ ]
+ : []),
+ ],
+ databaseProjectionTables: [
+ 'deliverables',
+ 'deliverable_vectors',
+ 'ledger_entries',
+ 'source_to_shares_allocations',
+ ],
+ objectStorageVisibility: 'source-safe-metadata-only-before-settlement' as const,
+ };
+ const compensationRouteRoot = root('sha256', compensationRoute);
+ const sourceToSharesPreviewRoot = root('sha256', {
+ assetId: input.assetId,
+ depositId: input.depositId,
+ depositorWalletId: input.depositorWalletId,
+ candidateBtdRange: input.btdRange,
+ allocationMethod: compensationRoute.allocationMethod,
+ sourceToSharesProofState: compensationRoute.sourceToSharesProofState,
+ });
+ const readbackRoot = root('sha256', readback);
+ const readiness = {
+ sourceBound: input.sourceBound,
+ proofReady: input.proofReady,
+ measurementReady: input.measurementReady,
+ searchable: input.searchable,
+ depositorWalletReady: Boolean(input.depositorWalletId),
+ eligibleForFindingFits: input.searchable,
+ eligibleForCompensationIfSelected,
+ blockers: uniqueSorted(compensationBlockers),
+ warnings: uniqueSorted(input.warnings),
+ };
+ const visibility = {
+ beforeSettlement: 'source-safe-compensation-route-metadata' as const,
+ protectedSourceVisible: false as const,
+ unpaidAssetPackSourceVisible: false as const,
+ walletPrivateMaterialVisible: false as const,
+ settlementPrivatePayloadVisible: false as const,
+ };
+ const compensationPreviewRoot = root('sha256', {
+ assetId: input.assetId,
+ depositId: input.depositId,
+ state,
+ readiness,
+ compensationRouteRoot,
+ sourceToSharesPreviewRoot,
+ readbackRoot,
+ visibility,
+ });
+
+ return {
+ schema: 'bitcode.depository.supply-compensation-preview',
+ state,
+ assetId: input.assetId,
+ depositId: input.depositId,
+ depositorWalletId: input.depositorWalletId,
+ candidateBtdRange: input.btdRange,
+ compensationRoute,
+ readiness,
+ visibility,
+ readback,
+ roots: {
+ compensationRouteRoot,
+ sourceToSharesPreviewRoot,
+ readbackRoot,
+ compensationPreviewRoot,
+ },
+ };
+}
+
function recordEmbeddingInputs(record: Record): Record {
return (
recordValue(record.embeddings) ||
@@ -553,6 +718,8 @@ function buildSupplyRecord(input: {
embeddings: recordEmbeddingInputs(record),
});
const storageProjection = buildStorageProjection();
+ const depositorWalletId = firstString(record.depositorWalletId, metadata.depositorWalletId, getPath(record, ['depositorBoundary', 'walletId']));
+ const btdRange = firstString(record.btdRange, metadata.btdRange, getPath(record, ['btd', 'range']));
const blockers = [
...(!repositoryFullName ? ['repository_binding_missing'] : []),
...(!sourceBranch && !sourceCommit ? ['source_revision_binding_missing'] : []),
@@ -560,6 +727,7 @@ function buildSupplyRecord(input: {
const warnings = [
...(!hasWalletOrAttestationProof ? ['wallet_or_attestation_proof_missing'] : []),
...(!hasAssetMeasurementEvidence ? ['asset_measurement_evidence_missing'] : []),
+ ...(!depositorWalletId ? ['depositor_wallet_missing'] : []),
...(vectorProjection.rows.some((row) => row.embeddingState === 'pending-embedding')
? ['embedding_rows_pending']
: []),
@@ -584,11 +752,12 @@ function buildSupplyRecord(input: {
...(!sourceBranch && !sourceCommit ? ['bind-source-branch-or-commit'] : []),
...(!hasWalletOrAttestationProof ? ['collect-wallet-or-attestation-proof'] : []),
...(!hasAssetMeasurementEvidence ? ['compute-asset-measurement'] : []),
+ ...(!depositorWalletId ? ['bind-depositor-wallet-for-compensation'] : []),
...(!vectorProjectionReady ? ['sync-active-embedding-vector-rows'] : []),
]);
const rightsBoundary = {
- depositorWalletId: firstString(record.depositorWalletId, metadata.depositorWalletId, getPath(record, ['depositorBoundary', 'walletId'])),
- btdRange: firstString(record.btdRange, metadata.btdRange, getPath(record, ['btd', 'range'])),
+ depositorWalletId,
+ btdRange,
readerVisibilityBeforeSettlement: 'source-safe-metadata-only' as const,
protectedSourceBeforeSettlementVisible: false as const,
settlementRequiredForSourceBearingAssetPack: true as const,
@@ -625,12 +794,25 @@ function buildSupplyRecord(input: {
const vectorProjectionRoot = root('sha256', vectorProjection);
const storageProjectionRoot = root('sha256', storageProjection);
const rightsBoundaryRoot = root('sha256', rightsBoundary);
+ const compensationPreview = buildCompensationPreview({
+ assetId,
+ depositId,
+ depositorWalletId,
+ btdRange,
+ sourceBound: Boolean(repositoryFullName && (sourceBranch || sourceCommit)),
+ proofReady,
+ measurementReady,
+ searchable,
+ blockers,
+ warnings,
+ });
const supplyRoot = root('sha256', {
assetId,
depositId,
sourceBinding,
lifecycle: { state, searchable, blockers, warnings },
rightsBoundaryRoot,
+ compensationPreviewRoot: compensationPreview.roots.compensationPreviewRoot,
searchDocumentRoot,
vectorProjectionRoot,
storageProjectionRoot,
@@ -660,6 +842,7 @@ function buildSupplyRecord(input: {
warnings,
},
rightsBoundary,
+ compensationPreview,
proofEvidence,
measurementEvidence,
readbackEvidence,
@@ -674,6 +857,7 @@ function buildSupplyRecord(input: {
vectorProjectionRoot,
storageProjectionRoot,
rightsBoundaryRoot,
+ compensationPreviewRoot: compensationPreview.roots.compensationPreviewRoot,
},
};
}
diff --git a/packages/protocol/README.md b/packages/protocol/README.md
index 9117436d..fb299c5e 100644
--- a/packages/protocol/README.md
+++ b/packages/protocol/README.md
@@ -184,6 +184,14 @@ Need, Finding Fits, source-safe AssetPack preview, BTD/BTC settlement, rights
transfer, and repository delivery; and an AI-reading dominant standalone
demonstration that proves an AssetPack can improve an AI system beyond a
public-data-only baseline.
+V42 Gate 2 adds `V42DepositingShortestPath` through
+`packages/protocol/src/canonical/v42-depositing-shortest-path.js`,
+`packages/protocol/test/v42-depositing-shortest-path.test.js`,
+`.bitcode/v42-depositing-shortest-path.json`, and `check:v42-gate2`.
+It proves deposit route readiness, Depository search/vector/storage projection,
+source-safe compensation preview roots, source-to-shares ledger readback keys,
+Terminal compensation visibility, and the pre-mint/no-pre-settlement-source
+boundary.
V40 Gate 2 adds `V40TestInventoryCoverageMatrix` through
`packages/protocol/src/canonical/v40-test-inventory-coverage-matrix.js`,
`packages/protocol/test/v40-test-inventory-coverage-matrix.test.js`,
diff --git a/packages/protocol/server.js b/packages/protocol/server.js
index 48dbbf05..d7045e4a 100644
--- a/packages/protocol/server.js
+++ b/packages/protocol/server.js
@@ -810,6 +810,13 @@ export function createAppContext({
state.ledger.accounts[depositorAssetsKey] = String(
Number.isFinite(priorDepositorAssetCount) ? priorDepositorAssetCount + 1 : 1
);
+ if (asset.depositoryEvidence?.compensationPreview?.state === 'eligible-if-selected-for-assetpack') {
+ const compensationRoutesKey = `depositor:${asset.depositoryEvidence.depositorBoundary.walletId}:eligible_compensation_routes`;
+ const priorRouteCount = Number(state.ledger.accounts[compensationRoutesKey] || '0');
+ state.ledger.accounts[compensationRoutesKey] = String(
+ Number.isFinite(priorRouteCount) ? priorRouteCount + 1 : 1
+ );
+ }
}
writeState(state);
return { ok: true, asset, depositoryEvidence: asset.depositoryEvidence || null };
diff --git a/packages/protocol/src/bitcode-demo.js b/packages/protocol/src/bitcode-demo.js
index 2f2c7ad0..7ac1b032 100644
--- a/packages/protocol/src/bitcode-demo.js
+++ b/packages/protocol/src/bitcode-demo.js
@@ -565,6 +565,90 @@ function buildDepositoryEvidence(input, inputState) {
measurementRoot,
reconciliationReadbackRoot
});
+ const compensationRoute = {
+ payer: 'future-reader-after-settlement',
+ payee: 'depositing-wallet',
+ priceAsset: 'BTC',
+ allocationMethod: 'source-to-shares-largest-remainder',
+ sourceToSharesProofState: 'not-created-until-accepted-need-fit-and-settlement',
+ btdMintBoundary: 'not-minted-by-deposit-admission',
+ btdRightsTransferBoundary: 'reader-receives-rights-only-after-btc-settlement'
+ };
+ const compensationRouteRoot = stableHashObject(compensationRoute);
+ const sourceToSharesPreviewRoot = stableHashObject({
+ schema: 'bitcode.depository.source-to-shares-preview',
+ assetId: inputState.assetId,
+ repositoryFullName,
+ sourceBranch,
+ sourceCommit,
+ depositorWalletId: walletId,
+ proofRoot,
+ measurementRoot,
+ reconciliationReadbackRoot,
+ allocationMethod: compensationRoute.allocationMethod,
+ sourceToSharesProofState: compensationRoute.sourceToSharesProofState
+ });
+ const compensationReadback = {
+ ledgerAccountKeys: [
+ `supplier:${inputState.assetId}:pending_claims`,
+ ...(walletId
+ ? [
+ `depositor:${walletId}:deposited_assets`,
+ `depositor:${walletId}:eligible_compensation_routes`
+ ]
+ : [])
+ ],
+ databaseProjectionTables: [
+ 'deliverables',
+ 'deliverable_vectors',
+ 'ledger_entries',
+ 'source_to_shares_allocations'
+ ],
+ objectStorageVisibility: 'source-safe-metadata-only-before-settlement'
+ };
+ const compensationReadbackRoot = stableHashObject(compensationReadback);
+ const compensationPreviewWithoutRoot = {
+ schema: 'bitcode.depository.supply-compensation-preview',
+ state: walletId
+ ? 'eligible-if-selected-for-assetpack'
+ : 'repair-required-before-compensation',
+ assetId: inputState.assetId,
+ depositorWalletId: walletId,
+ candidateBtdRange: null,
+ compensationRoute,
+ readiness: {
+ sourceBound: Boolean(repositoryFullName && (sourceBranch || sourceCommit)),
+ proofReady: true,
+ measurementReady: true,
+ searchable: true,
+ depositorWalletReady: Boolean(walletId),
+ eligibleForFindingFits: true,
+ eligibleForCompensationIfSelected: Boolean(walletId),
+ blockers: walletId ? [] : ['depositor_wallet_missing'],
+ warnings: []
+ },
+ visibility: {
+ beforeSettlement: 'source-safe-compensation-route-metadata',
+ protectedSourceVisible: false,
+ unpaidAssetPackSourceVisible: false,
+ walletPrivateMaterialVisible: false,
+ settlementPrivatePayloadVisible: false
+ },
+ readback: compensationReadback,
+ roots: {
+ compensationRouteRoot,
+ sourceToSharesPreviewRoot,
+ readbackRoot: compensationReadbackRoot
+ }
+ };
+ const compensationPreviewRoot = stableHashObject(compensationPreviewWithoutRoot);
+ const compensationPreview = {
+ ...compensationPreviewWithoutRoot,
+ roots: {
+ ...compensationPreviewWithoutRoot.roots,
+ compensationPreviewRoot
+ }
+ };
return {
schema: 'bitcode.depository.deposit-evidence',
@@ -579,6 +663,9 @@ function buildDepositoryEvidence(input, inputState) {
depositorySearchDocumentRoot,
lexicalDocumentRoot,
vectorDocumentRoot,
+ compensationPreview,
+ compensationPreviewRoot,
+ sourceToSharesPreviewRoot,
searchDocuments: {
lexical: {
...lexicalDocument,
@@ -3207,7 +3294,10 @@ export function makeCandidateAsset(input) {
depositorySearchDocumentRoot: depositoryEvidence.depositorySearchDocumentRoot,
lexicalDocumentRoot: depositoryEvidence.lexicalDocumentRoot,
vectorDocumentRoot: depositoryEvidence.vectorDocumentRoot,
+ compensationPreviewRoot: depositoryEvidence.compensationPreviewRoot,
+ sourceToSharesPreviewRoot: depositoryEvidence.sourceToSharesPreviewRoot,
depositorWalletId: depositoryEvidence.depositorBoundary.walletId,
+ compensationPreview: depositoryEvidence.compensationPreview,
depositoryEvidence,
sourceMaterialBinding: {
mode: input.bindingMode || 'read-only-mounted-copy',
@@ -3284,7 +3374,9 @@ export function makeCandidateAsset(input) {
reconciliationReadbackRoot: depositoryEvidence.reconciliationReadbackRoot,
depositorySearchDocumentRoot: depositoryEvidence.depositorySearchDocumentRoot,
lexicalDocumentRoot: depositoryEvidence.lexicalDocumentRoot,
- vectorDocumentRoot: depositoryEvidence.vectorDocumentRoot
+ vectorDocumentRoot: depositoryEvidence.vectorDocumentRoot,
+ compensationPreviewRoot: depositoryEvidence.compensationPreviewRoot,
+ sourceToSharesPreviewRoot: depositoryEvidence.sourceToSharesPreviewRoot
},
metadata: {
author: input.author,
diff --git a/packages/protocol/src/canonical/v42-depositing-shortest-path.js b/packages/protocol/src/canonical/v42-depositing-shortest-path.js
new file mode 100644
index 00000000..181bc14b
--- /dev/null
+++ b/packages/protocol/src/canonical/v42-depositing-shortest-path.js
@@ -0,0 +1,282 @@
+// @ts-check
+
+import crypto from 'node:crypto';
+import { existsSync, readFileSync } from 'node:fs';
+import path from 'node:path';
+import { fileURLToPath } from 'node:url';
+
+const __filename = fileURLToPath(import.meta.url);
+const __dirname = path.dirname(__filename);
+const DEFAULT_REPO_ROOT = path.resolve(__dirname, '..', '..', '..', '..');
+
+export const V42_DEPOSITING_SHORTEST_PATH_ARTIFACT_PATH =
+ '.bitcode/v42-depositing-shortest-path.json';
+export const V42_DEPOSITING_SHORTEST_PATH_SCHEMA_ID =
+ 'bitcode.v42.depositingShortestPath.v1';
+export const V42_DEPOSITING_SHORTEST_PATH_VERSION = 'V42';
+export const V42_DEPOSITING_SHORTEST_PATH_CURRENT_TARGET = 'V41';
+export const V42_DEPOSITING_SHORTEST_PATH_SOURCE_SAFETY_VERDICT =
+ 'source-safe-depositing-compensation-visibility-metadata';
+
+export const V42_DEPOSITING_SHORTEST_PATH_ROW_IDS = Object.freeze([
+ 'path:source-to-admission-proof',
+ 'api:deposit-route-readiness-contract',
+ 'supply:depository-record-compensation-preview',
+ 'documents:source-safe-search-and-vector-projection',
+ 'storage:depository-readback-projection',
+ 'ledger:source-to-shares-compensation-readback',
+ 'terminal:compensation-visibility-readback',
+ 'rehearsal:local-staging-deposit-readback',
+]);
+
+const FORBIDDEN_PAYLOAD_CLASSES = Object.freeze([
+ 'secret-values',
+ 'provider-tokens',
+ 'wallet-private-material',
+ 'protected-source-payloads',
+ 'raw-protected-prompts',
+ 'raw-model-responses-with-protected-source',
+ 'unpaid-assetpack-source',
+ 'settlement-private-payloads',
+]);
+
+const SOURCE_ROOTS = Object.freeze({
+ depositorySupplyIndex: 'packages/pipelines/asset-pack/src/depository-supply-index.ts',
+ depositorySupplyIndexTest: 'packages/pipelines/asset-pack/src/__tests__/depository-supply-index.test.ts',
+ embeddingConfig: 'packages/pipelines/asset-pack/src/embedding-config.ts',
+ assetPackReadme: 'packages/pipelines/asset-pack/README.md',
+ protocolServer: 'packages/protocol/server.js',
+ protocolRuntime: 'packages/protocol/src/bitcode-demo.js',
+ protocolBoundaryTest: 'packages/protocol/test/protocol-package-boundary.test.js',
+ uapiDepositRoute: 'uapi/app/api/deposits/route.ts',
+ terminalDepositComposer: 'uapi/app/terminal/TerminalDepositComposer.tsx',
+ terminalActivityHistory: 'uapi/app/terminal/terminal-activity-history.ts',
+ terminalWorkbench: 'uapi/app/terminal/terminal-deposit-read-workbench.ts',
+ terminalRunData: 'uapi/app/terminal/terminal-run-data.ts',
+ v42Spec: 'BITCODE_SPEC_V42.md',
+ v42Delta: 'BITCODE_SPEC_V42_DELTA.md',
+ v42Notes: 'BITCODE_SPEC_V42_NOTES.md',
+ v42Parity: 'BITCODE_SPEC_V42_PARITY_MATRIX.md',
+ roadmap: 'SPECIFICATIONS_ROADMAP.md',
+});
+
+function digest(value) {
+ return crypto.createHash('sha256').update(value).digest('hex').slice(0, 24);
+}
+
+function rowRoot(id) {
+ return `v42-depositing-shortest-path-row:${digest(id)}`;
+}
+
+function readSource(repoRoot, sourcePath) {
+ const absolutePath = path.join(repoRoot, sourcePath);
+ return existsSync(absolutePath) ? readFileSync(absolutePath, 'utf8') : '';
+}
+
+function predicateResult(id, sourcePath, passed) {
+ return { id, sourcePath, passed: Boolean(passed) };
+}
+
+function row(input) {
+ return {
+ ...input,
+ rowRoot: rowRoot(input.rowId),
+ sourceSafetyClass: 'source_safe_depositing_compensation_visibility_metadata',
+ sourceSafeMetadataOnly: true,
+ protectedSourceVisible: false,
+ rawSourceTextVisible: false,
+ credentialsSerialized: false,
+ walletPrivateMaterialVisible: false,
+ unpaidAssetPackSourceVisible: false,
+ settlementPrivatePayloadVisible: false,
+ forbiddenPayloadClasses: [...FORBIDDEN_PAYLOAD_CLASSES],
+ };
+}
+
+export const V42_DEPOSITING_SHORTEST_PATH_ROWS = Object.freeze([
+ row({
+ rowId: 'path:source-to-admission-proof',
+ purpose:
+ 'Make the shortest Depositing path explicit: source material, repository/source anchor, Depository admission, source-safe proof roots, and next Reading handoff.',
+ sourceRoots: [
+ SOURCE_ROOTS.protocolServer,
+ SOURCE_ROOTS.protocolRuntime,
+ SOURCE_ROOTS.uapiDepositRoute,
+ SOURCE_ROOTS.terminalDepositComposer,
+ ],
+ emittedTypes: ['createDeposit', 'buildDepositoryEvidence', 'TerminalDepositResponseEvidence'],
+ requiredEvidence: ['repositoryFullName', 'sourceBranch', 'sourceCommit', 'proofRoot', 'measurementRoot'],
+ }),
+ row({
+ rowId: 'api:deposit-route-readiness-contract',
+ purpose:
+ 'Keep POST /api/deposits admitted only after signed transaction and repository readiness checks, then project source-safe Depository evidence.',
+ sourceRoots: [SOURCE_ROOTS.uapiDepositRoute, SOURCE_ROOTS.protocolServer, SOURCE_ROOTS.protocolBoundaryTest],
+ emittedTypes: ['requireBitcodeSignedTransactionReadiness', 'BitcodeAppContext.createDeposit'],
+ requiredEvidence: ['requiresRepositoryAnchor', 'repositoryProvider', 'walletAuthorizationProof'],
+ }),
+ row({
+ rowId: 'supply:depository-record-compensation-preview',
+ purpose:
+ 'Attach a deterministic compensation preview to DepositorySupplyRecord without minting BTD or exposing source before an accepted Need-Fit and settlement.',
+ sourceRoots: [SOURCE_ROOTS.depositorySupplyIndex, SOURCE_ROOTS.depositorySupplyIndexTest, SOURCE_ROOTS.embeddingConfig],
+ emittedTypes: ['DepositorySupplyCompensationPreview', 'DepositorySupplyRecord.compensationPreview'],
+ requiredEvidence: ['source-to-shares-largest-remainder', 'not-minted-by-deposit-admission', 'compensationPreviewRoot'],
+ }),
+ row({
+ rowId: 'documents:source-safe-search-and-vector-projection',
+ purpose:
+ 'Preserve source-safe lexical, metadata, measurement, and vector search documents so deposits become searchable without protected source payloads.',
+ sourceRoots: [SOURCE_ROOTS.depositorySupplyIndex, SOURCE_ROOTS.depositorySupplyIndexTest],
+ emittedTypes: ['DepositorySupplySearchDocument', 'DepositorySupplyVectorProjection'],
+ requiredEvidence: ['text-embedding-3-small', '1536', 'match_deliverable_vectors'],
+ }),
+ row({
+ rowId: 'storage:depository-readback-projection',
+ purpose:
+ 'Bind Depository admission to durable source-safe storage readback through deliverables, vector rows, ledger rows, and source-to-shares allocation posture.',
+ sourceRoots: [SOURCE_ROOTS.depositorySupplyIndex, SOURCE_ROOTS.assetPackReadme, SOURCE_ROOTS.v42Spec],
+ emittedTypes: ['DepositorySupplyStorageProjection', 'compensationPreview.readback'],
+ requiredEvidence: ['deliverables', 'deliverable_vectors', 'ledger_entries', 'source_to_shares_allocations'],
+ }),
+ row({
+ rowId: 'ledger:source-to-shares-compensation-readback',
+ purpose:
+ 'Record depositor compensation visibility through pending-claim and eligible-route ledger keys while deferring actual BTC allocation until paid AssetPack settlement.',
+ sourceRoots: [SOURCE_ROOTS.protocolServer, SOURCE_ROOTS.protocolRuntime, SOURCE_ROOTS.protocolBoundaryTest],
+ emittedTypes: ['ledger.accounts', 'compensationPreview.readback.ledgerAccountKeys'],
+ requiredEvidence: ['pending_claims', 'eligible_compensation_routes', 'future-reader-after-settlement'],
+ }),
+ row({
+ rowId: 'terminal:compensation-visibility-readback',
+ purpose:
+ 'Show source-safe compensation posture in Terminal and carry compensation roots through activity history and the deposit-to-read workbench.',
+ sourceRoots: [
+ SOURCE_ROOTS.terminalDepositComposer,
+ SOURCE_ROOTS.terminalActivityHistory,
+ SOURCE_ROOTS.terminalWorkbench,
+ SOURCE_ROOTS.terminalRunData,
+ ],
+ emittedTypes: ['TerminalDepositResponseEvidence', 'WorkspaceRun', 'TerminalDepositedSourceRevision'],
+ requiredEvidence: ['compensationPreviewRoot', 'sourceToSharesPreviewRoot', 'Compensation route'],
+ }),
+ row({
+ rowId: 'rehearsal:local-staging-deposit-readback',
+ purpose:
+ 'Keep Gate 2 locally checkable and staging-testnet rehearsable through package tests, protocol route tests, generated artifact checks, and source-safe proof rows.',
+ sourceRoots: [SOURCE_ROOTS.v42Spec, SOURCE_ROOTS.v42Delta, SOURCE_ROOTS.v42Notes, SOURCE_ROOTS.v42Parity, SOURCE_ROOTS.roadmap],
+ emittedTypes: ['V42DepositingShortestPathReport'],
+ requiredEvidence: ['local/staging rehearsal', 'staging-testnet', 'check:v42-gate2'],
+ }),
+]);
+
+function buildPredicateResults(repoRoot) {
+ const supply = readSource(repoRoot, SOURCE_ROOTS.depositorySupplyIndex);
+ const supplyTest = readSource(repoRoot, SOURCE_ROOTS.depositorySupplyIndexTest);
+ const embeddingConfig = readSource(repoRoot, SOURCE_ROOTS.embeddingConfig);
+ const readme = readSource(repoRoot, SOURCE_ROOTS.assetPackReadme);
+ const server = readSource(repoRoot, SOURCE_ROOTS.protocolServer);
+ const runtime = readSource(repoRoot, SOURCE_ROOTS.protocolRuntime);
+ const boundaryTest = readSource(repoRoot, SOURCE_ROOTS.protocolBoundaryTest);
+ const route = readSource(repoRoot, SOURCE_ROOTS.uapiDepositRoute);
+ const composer = readSource(repoRoot, SOURCE_ROOTS.terminalDepositComposer);
+ const activity = readSource(repoRoot, SOURCE_ROOTS.terminalActivityHistory);
+ const workbench = readSource(repoRoot, SOURCE_ROOTS.terminalWorkbench);
+ const runData = readSource(repoRoot, SOURCE_ROOTS.terminalRunData);
+ const spec = readSource(repoRoot, SOURCE_ROOTS.v42Spec);
+ const delta = readSource(repoRoot, SOURCE_ROOTS.v42Delta);
+ const notes = readSource(repoRoot, SOURCE_ROOTS.v42Notes);
+ const parity = readSource(repoRoot, SOURCE_ROOTS.v42Parity);
+ const roadmap = readSource(repoRoot, SOURCE_ROOTS.roadmap);
+
+ return [
+ predicateResult('deposit-route-requires-readiness', SOURCE_ROOTS.uapiDepositRoute, route.includes('requireBitcodeSignedTransactionReadiness') && route.includes('requiresRepositoryAnchor: true')),
+ predicateResult('server-creates-deposit-and-ledger-readback', SOURCE_ROOTS.protocolServer, server.includes('createDeposit') && server.includes('pending_claims') && server.includes('eligible_compensation_routes')),
+ predicateResult('runtime-builds-compensation-preview', SOURCE_ROOTS.protocolRuntime, runtime.includes('compensationPreview') && runtime.includes('source-to-shares-largest-remainder') && runtime.includes('not-minted-by-deposit-admission')),
+ predicateResult('runtime-keeps-source-safe-visibility', SOURCE_ROOTS.protocolRuntime, runtime.includes('protectedSourceVisible: false') && runtime.includes('unpaidAssetPackSourceVisible: false')),
+ predicateResult('supply-index-defines-compensation-preview', SOURCE_ROOTS.depositorySupplyIndex, supply.includes('DepositorySupplyCompensationPreview') && supply.includes('buildCompensationPreview')),
+ predicateResult('supply-index-defers-btd-mint', SOURCE_ROOTS.depositorySupplyIndex, supply.includes('not-minted-by-deposit-admission') && supply.includes('reader-receives-rights-only-after-btc-settlement')),
+ predicateResult('supply-index-projects-source-to-shares-readback', SOURCE_ROOTS.depositorySupplyIndex, supply.includes('source_to_shares_allocations') && supply.includes('sourceToSharesPreviewRoot')),
+ predicateResult(
+ 'supply-index-preserves-search-documents',
+ SOURCE_ROOTS.depositorySupplyIndex,
+ supply.includes('DepositorySupplySearchDocument') &&
+ supply.includes('buildAssetPackEmbeddingPolicy') &&
+ embeddingConfig.includes('text-embedding-3-small') &&
+ embeddingConfig.includes('match_deliverable_vectors'),
+ ),
+ predicateResult('supply-tests-cover-compensation-preview', SOURCE_ROOTS.depositorySupplyIndexTest, supplyTest.includes('eligible-if-selected-for-assetpack') && supplyTest.includes('repair-required-before-compensation')),
+ predicateResult('supply-tests-cover-no-protected-source', SOURCE_ROOTS.depositorySupplyIndexTest, supplyTest.includes('PRIVATE_SOURCE_DO_NOT_SERIALIZE') && supplyTest.includes('assertDepositorySupplyIndexSourceSafe')),
+ predicateResult('protocol-test-covers-compensation-route', SOURCE_ROOTS.protocolBoundaryTest, boundaryTest.includes('eligible_compensation_routes') && boundaryTest.includes('source-to-shares-largest-remainder')),
+ predicateResult('terminal-composer-captures-compensation-roots', SOURCE_ROOTS.terminalDepositComposer, composer.includes('compensationPreviewRoot') && composer.includes('Compensation route')),
+ predicateResult('terminal-history-maps-compensation-roots', SOURCE_ROOTS.terminalActivityHistory, activity.includes('compensationPreviewRoot') && activity.includes('sourceToSharesPreviewRoot')),
+ predicateResult('terminal-workbench-shows-compensation-rows', SOURCE_ROOTS.terminalWorkbench, workbench.includes('Compensation state') && workbench.includes('Source-to-shares preview root')),
+ predicateResult('workspace-run-carries-compensation-fields', SOURCE_ROOTS.terminalRunData, runData.includes('compensationState') && runData.includes('compensationPriceAsset')),
+ predicateResult('asset-pack-readme-documents-compensation-preview', SOURCE_ROOTS.assetPackReadme, readme.includes('compensation preview') && readme.includes('source-to-shares')),
+ predicateResult('v42-spec-gate2-expanded', SOURCE_ROOTS.v42Spec, spec.includes('V42 Gate 2') && spec.includes('compensation route preview')),
+ predicateResult('v42-delta-gate2-implemented', SOURCE_ROOTS.v42Delta, delta.includes('Gate 2') && delta.includes('Depository admission proof')),
+ predicateResult('v42-notes-gate2-rehearsal', SOURCE_ROOTS.v42Notes, notes.includes('Gate 2') && notes.includes('staging-testnet')),
+ predicateResult('v42-parity-gate2-closed', SOURCE_ROOTS.v42Parity, parity.includes('Depositing shortest path') && parity.includes('implemented')),
+ predicateResult('roadmap-current-gate-advanced', SOURCE_ROOTS.roadmap, roadmap.includes('Current working gate: V42 Gate 2') && roadmap.includes('V42 Gate 2 closure anchor')),
+ ];
+}
+
+export function buildV42DepositingShortestPath(options = {}) {
+ const repoRoot = options.repoRoot || DEFAULT_REPO_ROOT;
+ const predicateResults = buildPredicateResults(repoRoot);
+ const failedPredicateIds = predicateResults
+ .filter((predicate) => !predicate.passed)
+ .map((predicate) => predicate.id);
+ const rowRoots = V42_DEPOSITING_SHORTEST_PATH_ROWS.map((item) => item.rowRoot);
+ const artifactRoot = `v42-depositing-shortest-path:${digest(JSON.stringify({
+ rowRoots,
+ failedPredicateIds,
+ }))}`;
+
+ return {
+ artifactId: 'v42-depositing-shortest-path',
+ schemaId: V42_DEPOSITING_SHORTEST_PATH_SCHEMA_ID,
+ version: V42_DEPOSITING_SHORTEST_PATH_VERSION,
+ currentTarget: V42_DEPOSITING_SHORTEST_PATH_CURRENT_TARGET,
+ sourceSafetyVerdict: V42_DEPOSITING_SHORTEST_PATH_SOURCE_SAFETY_VERDICT,
+ generatedAt: 'deterministic',
+ artifactRoot,
+ passed: failedPredicateIds.length === 0,
+ rows: V42_DEPOSITING_SHORTEST_PATH_ROWS,
+ rowIds: [...V42_DEPOSITING_SHORTEST_PATH_ROW_IDS],
+ predicateResults,
+ coverage: {
+ rowCount: V42_DEPOSITING_SHORTEST_PATH_ROWS.length,
+ requiredPredicateCount: predicateResults.length,
+ passedPredicateCount: predicateResults.length - failedPredicateIds.length,
+ failedPredicateIds,
+ acceptedUserPath: [
+ 'provide-source-material',
+ 'select-repository-source-anchor',
+ 'admit-deposit-to-depository',
+ 'receive-source-safe-admission-proof',
+ 'view-later-btc-compensation-attribution',
+ ],
+ routeApiContractsCovered: true,
+ sourceValidationCovered: true,
+ storageProjectionCovered: true,
+ depositorySearchDocumentCovered: true,
+ sourceToSharesCompensationReadbackCovered: true,
+ terminalCompensationVisibilityCovered: true,
+ localStagingRehearsalCovered: true,
+ sourceSafeMetadataOnly: true,
+ protectedSourceVisible: false,
+ rawSourceTextVisible: false,
+ credentialsSerialized: false,
+ walletPrivateMaterialVisible: false,
+ unpaidAssetPackSourceVisible: false,
+ settlementPrivatePayloadVisible: false,
+ btdMintedAtDepositAdmission: false,
+ btdRightsTransferredBeforeSettlement: false,
+ compensationAllocationMethod: 'source-to-shares-largest-remainder',
+ compensationPriceAsset: 'BTC',
+ legacySourceRoots: Object.values(SOURCE_ROOTS).some((sourcePath) => sourcePath.includes('_legacy/')),
+ },
+ sourceRoots: SOURCE_ROOTS,
+ };
+}
diff --git a/packages/protocol/src/index.d.ts b/packages/protocol/src/index.d.ts
index a92592d8..d163ccbe 100644
--- a/packages/protocol/src/index.d.ts
+++ b/packages/protocol/src/index.d.ts
@@ -512,6 +512,14 @@ export const V41_PROMOTION_READINESS_GATE_ARTIFACT_PATHS: readonly string[];
export const V41_PROMOTION_READINESS_GENERATED_OUTPUTS: readonly string[];
export function buildV41PromotionReadinessReport(input?: Record): BitcodeProtocolReport;
export function listMissingV41PromotionReadinessSources(repoRoot?: string): string[];
+export const V42_DEPOSITING_SHORTEST_PATH_ARTIFACT_PATH: string;
+export const V42_DEPOSITING_SHORTEST_PATH_CURRENT_TARGET: string;
+export const V42_DEPOSITING_SHORTEST_PATH_SCHEMA_ID: string;
+export const V42_DEPOSITING_SHORTEST_PATH_VERSION: string;
+export const V42_DEPOSITING_SHORTEST_PATH_SOURCE_SAFETY_VERDICT: string;
+export const V42_DEPOSITING_SHORTEST_PATH_ROW_IDS: readonly string[];
+export const V42_DEPOSITING_SHORTEST_PATH_ROWS: readonly Record[];
+export function buildV42DepositingShortestPath(input?: Record): BitcodeProtocolReport;
export const EXCHANGE_INTENT_ORDER_CONTRACTS_ARTIFACT_PATH: string;
export const EXCHANGE_INTENT_ORDER_CONTRACTS_CURRENT_TARGET: string;
export const EXCHANGE_INTENT_ORDER_CONTRACTS_SCHEMA_ID: string;
diff --git a/packages/protocol/src/index.js b/packages/protocol/src/index.js
index 5f856b34..307cc3f8 100644
--- a/packages/protocol/src/index.js
+++ b/packages/protocol/src/index.js
@@ -570,6 +570,16 @@ export {
buildV41PromotionReadinessReport,
listMissingV41PromotionReadinessSources
} from './canonical/v41-promotion-readiness-report.js';
+export {
+ V42_DEPOSITING_SHORTEST_PATH_ARTIFACT_PATH,
+ V42_DEPOSITING_SHORTEST_PATH_CURRENT_TARGET,
+ V42_DEPOSITING_SHORTEST_PATH_ROW_IDS,
+ V42_DEPOSITING_SHORTEST_PATH_ROWS,
+ V42_DEPOSITING_SHORTEST_PATH_SCHEMA_ID,
+ V42_DEPOSITING_SHORTEST_PATH_SOURCE_SAFETY_VERDICT,
+ V42_DEPOSITING_SHORTEST_PATH_VERSION,
+ buildV42DepositingShortestPath
+} from './canonical/v42-depositing-shortest-path.js';
export {
EXCHANGE_INTENT_ACTION_KINDS,
EXCHANGE_INTENT_ORDER_CONTRACTS_ARTIFACT_PATH,
diff --git a/packages/protocol/test/protocol-package-boundary.test.js b/packages/protocol/test/protocol-package-boundary.test.js
index cd208df8..f2e54669 100644
--- a/packages/protocol/test/protocol-package-boundary.test.js
+++ b/packages/protocol/test/protocol-package-boundary.test.js
@@ -154,6 +154,31 @@ test('@bitcode/protocol accepts live repository revision deposits without demo i
assert.equal(result.depositoryEvidence.searchDocuments.vector.embeddingPolicy.model, 'text-embedding-3-small');
assert.equal(result.depositoryEvidence.searchDocuments.vector.embeddingPolicy.dimensions, 1536);
assert.equal(result.depositoryEvidence.searchDocuments.vector.embeddingPolicy.vectorStore.rpc, 'match_deliverable_vectors');
+ assert.equal(result.depositoryEvidence.compensationPreview.state, 'eligible-if-selected-for-assetpack');
+ assert.equal(result.depositoryEvidence.compensationPreview.compensationRoute.priceAsset, 'BTC');
+ assert.equal(
+ result.depositoryEvidence.compensationPreview.compensationRoute.allocationMethod,
+ 'source-to-shares-largest-remainder',
+ );
+ assert.equal(
+ result.depositoryEvidence.compensationPreview.compensationRoute.btdMintBoundary,
+ 'not-minted-by-deposit-admission',
+ );
+ assert.equal(result.depositoryEvidence.compensationPreview.visibility.protectedSourceVisible, false);
+ assert.equal(result.depositoryEvidence.compensationPreview.visibility.unpaidAssetPackSourceVisible, false);
+ assert.equal(result.depositoryEvidence.compensationPreview.readiness.eligibleForFindingFits, true);
+ assert.equal(result.depositoryEvidence.compensationPreview.readiness.eligibleForCompensationIfSelected, true);
+ assert.match(result.depositoryEvidence.compensationPreviewRoot, /^sha256:[a-f0-9]{64}$/);
+ assert.match(result.depositoryEvidence.sourceToSharesPreviewRoot, /^sha256:[a-f0-9]{64}$/);
+ assert.equal(
+ result.asset.compensationPreview.roots.compensationPreviewRoot,
+ result.depositoryEvidence.compensationPreviewRoot,
+ );
+ const state = app.getState('internal');
+ assert.equal(
+ state.ledger.accounts[`depositor:${result.depositoryEvidence.depositorBoundary.walletId}:eligible_compensation_routes`],
+ '1',
+ );
const depositedText = result.asset.contentUnits?.[0]?.text;
assert.match(depositedText, /Bitcode repository revision deposit/);
assert.match(depositedText, /Repository: engineeredsoftware\/ENGI/);
diff --git a/packages/protocol/test/v42-depositing-shortest-path.test.js b/packages/protocol/test/v42-depositing-shortest-path.test.js
new file mode 100644
index 00000000..cdc27eac
--- /dev/null
+++ b/packages/protocol/test/v42-depositing-shortest-path.test.js
@@ -0,0 +1,70 @@
+import assert from 'node:assert/strict';
+import test from 'node:test';
+
+import {
+ V42_DEPOSITING_SHORTEST_PATH_ARTIFACT_PATH,
+ V42_DEPOSITING_SHORTEST_PATH_ROW_IDS,
+ V42_DEPOSITING_SHORTEST_PATH_ROWS,
+ V42_DEPOSITING_SHORTEST_PATH_SCHEMA_ID,
+ V42_DEPOSITING_SHORTEST_PATH_SOURCE_SAFETY_VERDICT,
+ buildV42DepositingShortestPath,
+} from '../src/canonical/v42-depositing-shortest-path.js';
+
+test('V42 Depositing shortest path report binds admission proof and compensation visibility', () => {
+ const report = buildV42DepositingShortestPath();
+
+ assert.equal(V42_DEPOSITING_SHORTEST_PATH_ARTIFACT_PATH, '.bitcode/v42-depositing-shortest-path.json');
+ assert.equal(report.artifactId, 'v42-depositing-shortest-path');
+ assert.equal(report.schemaId, V42_DEPOSITING_SHORTEST_PATH_SCHEMA_ID);
+ assert.equal(report.version, 'V42');
+ assert.equal(report.currentTarget, 'V41');
+ assert.equal(report.sourceSafetyVerdict, V42_DEPOSITING_SHORTEST_PATH_SOURCE_SAFETY_VERDICT);
+ assert.equal(report.passed, true);
+ assert.deepEqual(report.rowIds, [...V42_DEPOSITING_SHORTEST_PATH_ROW_IDS]);
+ assert.equal(report.rows.length, V42_DEPOSITING_SHORTEST_PATH_ROWS.length);
+ assert.equal(report.coverage.rowCount, 8);
+ assert.deepEqual(report.coverage.acceptedUserPath, [
+ 'provide-source-material',
+ 'select-repository-source-anchor',
+ 'admit-deposit-to-depository',
+ 'receive-source-safe-admission-proof',
+ 'view-later-btc-compensation-attribution',
+ ]);
+ assert.equal(report.coverage.routeApiContractsCovered, true);
+ assert.equal(report.coverage.sourceValidationCovered, true);
+ assert.equal(report.coverage.storageProjectionCovered, true);
+ assert.equal(report.coverage.depositorySearchDocumentCovered, true);
+ assert.equal(report.coverage.sourceToSharesCompensationReadbackCovered, true);
+ assert.equal(report.coverage.terminalCompensationVisibilityCovered, true);
+ assert.equal(report.coverage.localStagingRehearsalCovered, true);
+ assert.equal(report.coverage.sourceSafeMetadataOnly, true);
+ assert.equal(report.coverage.protectedSourceVisible, false);
+ assert.equal(report.coverage.rawSourceTextVisible, false);
+ assert.equal(report.coverage.credentialsSerialized, false);
+ assert.equal(report.coverage.walletPrivateMaterialVisible, false);
+ assert.equal(report.coverage.unpaidAssetPackSourceVisible, false);
+ assert.equal(report.coverage.settlementPrivatePayloadVisible, false);
+ assert.equal(report.coverage.btdMintedAtDepositAdmission, false);
+ assert.equal(report.coverage.btdRightsTransferredBeforeSettlement, false);
+ assert.equal(report.coverage.compensationAllocationMethod, 'source-to-shares-largest-remainder');
+ assert.equal(report.coverage.compensationPriceAsset, 'BTC');
+ assert.equal(report.coverage.legacySourceRoots, false);
+ assert.deepEqual(report.coverage.failedPredicateIds, []);
+ assert.ok(report.artifactRoot.startsWith('v42-depositing-shortest-path:'));
+});
+
+test('V42 Depositing shortest path rows remain source-safe metadata only', () => {
+ for (const row of V42_DEPOSITING_SHORTEST_PATH_ROWS) {
+ assert.ok(row.rowRoot.startsWith('v42-depositing-shortest-path-row:'));
+ assert.equal(row.sourceSafetyClass, 'source_safe_depositing_compensation_visibility_metadata');
+ assert.equal(row.sourceSafeMetadataOnly, true);
+ assert.equal(row.protectedSourceVisible, false);
+ assert.equal(row.rawSourceTextVisible, false);
+ assert.equal(row.credentialsSerialized, false);
+ assert.equal(row.walletPrivateMaterialVisible, false);
+ assert.equal(row.unpaidAssetPackSourceVisible, false);
+ assert.equal(row.settlementPrivatePayloadVisible, false);
+ assert.ok(row.forbiddenPayloadClasses.includes('protected-source-payloads'));
+ assert.ok(row.forbiddenPayloadClasses.includes('unpaid-assetpack-source'));
+ }
+});
diff --git a/scripts/check-v42-gate2-depositing-shortest-path.mjs b/scripts/check-v42-gate2-depositing-shortest-path.mjs
new file mode 100644
index 00000000..12313083
--- /dev/null
+++ b/scripts/check-v42-gate2-depositing-shortest-path.mjs
@@ -0,0 +1,230 @@
+#!/usr/bin/env node
+
+import { execFileSync } from 'node:child_process';
+import { existsSync, readFileSync } from 'node:fs';
+import path from 'node:path';
+import { fileURLToPath } from 'node:url';
+
+const __filename = fileURLToPath(import.meta.url);
+const __dirname = path.dirname(__filename);
+const defaultRepoRoot = path.resolve(__dirname, '..');
+const ARTIFACT_PATH = '.bitcode/v42-depositing-shortest-path.json';
+
+const SECRET_MARKERS = [
+ `${['sk', 'proj'].join('-')}-`,
+ `${['sb', 'secret'].join('_')}__`,
+ ['service', 'role'].join('_'),
+ Buffer.from('{"alg":"HS256","typ":"JWT"}').toString('base64url').slice(0, 18),
+ ['OPENAI', 'API', 'KEY'].join('_'),
+ ['SUPABASE', 'SERVICE', 'ROLE'].join('_'),
+ ['VERCEL', 'TOKEN'].join('_'),
+ ['VERCEL', 'OIDC', 'TOKEN'].join('_'),
+ ['PRIVATE', 'KEY'].join('_'),
+];
+
+function read(root, relativePath) {
+ return readFileSync(path.join(root, relativePath), 'utf8');
+}
+
+function fileExists(root, relativePath) {
+ return existsSync(path.join(root, relativePath));
+}
+
+function git(root, args) {
+ return execFileSync('git', args, { cwd: root, encoding: 'utf8' }).trim();
+}
+
+function run(root, command, args) {
+ return execFileSync(command, args, {
+ cwd: root,
+ encoding: 'utf8',
+ stdio: ['ignore', 'pipe', 'pipe'],
+ }).trim();
+}
+
+function assertCheck(failures, condition, message) {
+ if (!condition) failures.push(message);
+}
+
+function parseArgs(argv) {
+ const args = {
+ skipBranchCheck: false,
+ skipPackageTests: false,
+ skipUapiTests: false,
+ repoRoot: defaultRepoRoot,
+ };
+
+ for (let index = 0; index < argv.length; index += 1) {
+ const arg = argv[index];
+ if (arg === '--skip-branch-check') args.skipBranchCheck = true;
+ else if (arg === '--skip-package-tests') args.skipPackageTests = true;
+ else if (arg === '--skip-uapi-tests') args.skipUapiTests = true;
+ else if (arg === '--repo-root') args.repoRoot = path.resolve(argv[++index]);
+ else if (arg === '--help' || arg === '-h') args.help = true;
+ else throw new Error(`Unknown argument ${arg}`);
+ }
+
+ return args;
+}
+
+function printHelp() {
+ process.stdout.write(
+ [
+ 'Usage: node scripts/check-v42-gate2-depositing-shortest-path.mjs [--skip-branch-check] [--skip-package-tests] [--skip-uapi-tests] [--repo-root ]',
+ '',
+ 'Checks V42 Gate 2 Depositing shortest path, source-safe admission proof, compensation visibility, generated artifact, docs, and focused tests.',
+ ].join('\n'),
+ );
+ process.stdout.write('\n');
+}
+
+function main() {
+ const args = parseArgs(process.argv.slice(2));
+ if (args.help) {
+ printHelp();
+ return;
+ }
+
+ const root = args.repoRoot;
+ const failures = [];
+ const pointer = read(root, 'BITCODE_SPEC.txt').trim();
+
+ assertCheck(
+ failures,
+ pointer === 'V41',
+ `BITCODE_SPEC.txt must remain V41 during V42 gate work. Observed ${pointer || 'empty'}.`,
+ );
+
+ if (!args.skipBranchCheck) {
+ const branch = git(root, ['branch', '--show-current']);
+ assertCheck(
+ failures,
+ branch === 'version/v42' || /^v42\/gate-(?:2|[3-9]|10)-[a-z0-9][a-z0-9-]*$/u.test(branch),
+ `V42 Gate 2+ work must occur on version/v42 or v42/gate-2..10-* branches. Observed ${branch || 'detached HEAD'}.`,
+ );
+ }
+
+ const requiredFiles = [
+ ARTIFACT_PATH,
+ 'packages/pipelines/asset-pack/src/depository-supply-index.ts',
+ 'packages/pipelines/asset-pack/src/__tests__/depository-supply-index.test.ts',
+ 'packages/pipelines/asset-pack/README.md',
+ 'packages/protocol/src/canonical/v42-depositing-shortest-path.js',
+ 'packages/protocol/test/v42-depositing-shortest-path.test.js',
+ 'packages/protocol/test/protocol-package-boundary.test.js',
+ 'packages/protocol/server.js',
+ 'packages/protocol/src/bitcode-demo.js',
+ 'uapi/app/api/deposits/route.ts',
+ 'uapi/app/terminal/TerminalDepositComposer.tsx',
+ 'uapi/app/terminal/terminal-activity-history.ts',
+ 'uapi/app/terminal/terminal-deposit-read-workbench.ts',
+ 'uapi/app/terminal/terminal-run-data.ts',
+ 'scripts/generate-v42-depositing-shortest-path.mjs',
+ 'scripts/check-v42-gate2-depositing-shortest-path.mjs',
+ 'BITCODE_SPEC_V42.md',
+ 'BITCODE_SPEC_V42_DELTA.md',
+ 'BITCODE_SPEC_V42_NOTES.md',
+ 'BITCODE_SPEC_V42_PARITY_MATRIX.md',
+ 'SPECIFICATIONS_ROADMAP.md',
+ 'README.md',
+ 'packages/protocol/README.md',
+ 'package.json',
+ '.github/workflows/bitcode-gate-quality.yml',
+ '.github/workflows/bitcode-canon-quality.yml',
+ ];
+
+ for (const relativePath of requiredFiles) {
+ assertCheck(failures, fileExists(root, relativePath), `Missing V42 Gate 2 file: ${relativePath}`);
+ }
+
+ if (failures.length === 0) {
+ try {
+ run(root, 'node', ['scripts/generate-v42-depositing-shortest-path.mjs', '--check']);
+ } catch (error) {
+ failures.push(`V42 Depositing shortest path artifact check failed: ${error.stderr || error.message}`);
+ }
+ }
+
+ if (failures.length === 0) {
+ try {
+ run(root, 'node', [
+ '--test',
+ '--test-force-exit',
+ 'packages/protocol/test/v42-depositing-shortest-path.test.js',
+ 'packages/protocol/test/protocol-package-boundary.test.js',
+ ]);
+ } catch (error) {
+ failures.push(`V42 Depositing shortest path protocol tests failed: ${error.stderr || error.message}`);
+ }
+ }
+
+ if (failures.length === 0 && !args.skipPackageTests) {
+ try {
+ run(root, 'pnpm', [
+ '--filter',
+ '@bitcode/pipeline-asset-pack',
+ 'exec',
+ 'jest',
+ '--config',
+ 'jest.config.cjs',
+ '--runTestsByPath',
+ 'src/__tests__/depository-supply-index.test.ts',
+ '--runInBand',
+ '--forceExit',
+ ]);
+ } catch (error) {
+ failures.push(`Depository supply package tests failed: ${error.stderr || error.message}`);
+ }
+ }
+
+ const serializedArtifact = fileExists(root, ARTIFACT_PATH) ? read(root, ARTIFACT_PATH) : '';
+ for (const marker of SECRET_MARKERS) {
+ assertCheck(failures, !serializedArtifact.includes(marker), `V42 Gate 2 artifact must not contain secret marker ${marker}.`);
+ }
+
+ const artifact = serializedArtifact ? JSON.parse(serializedArtifact) : null;
+ if (artifact) {
+ assertCheck(failures, artifact.artifactId === 'v42-depositing-shortest-path', 'Gate 2 artifactId must match.');
+ assertCheck(failures, artifact.schemaId === 'bitcode.v42.depositingShortestPath.v1', 'Gate 2 schemaId must match.');
+ assertCheck(failures, artifact.version === 'V42' && artifact.currentTarget === 'V41', 'Gate 2 artifact must bind V42 over active V41.');
+ assertCheck(failures, artifact.passed === true, 'Gate 2 artifact must pass.');
+ assertCheck(
+ failures,
+ artifact.sourceSafetyVerdict === 'source-safe-depositing-compensation-visibility-metadata',
+ 'Gate 2 artifact must declare source-safe compensation visibility metadata.',
+ );
+ assertCheck(failures, artifact.coverage.rowCount === 8, 'Gate 2 must cover eight Depositing rows.');
+ assertCheck(failures, artifact.coverage.routeApiContractsCovered === true, 'Gate 2 must cover route/API contracts.');
+ assertCheck(failures, artifact.coverage.sourceValidationCovered === true, 'Gate 2 must cover source validation.');
+ assertCheck(failures, artifact.coverage.storageProjectionCovered === true, 'Gate 2 must cover storage projection.');
+ assertCheck(failures, artifact.coverage.depositorySearchDocumentCovered === true, 'Gate 2 must cover Depository search documents.');
+ assertCheck(failures, artifact.coverage.sourceToSharesCompensationReadbackCovered === true, 'Gate 2 must cover source-to-shares compensation readback.');
+ assertCheck(failures, artifact.coverage.terminalCompensationVisibilityCovered === true, 'Gate 2 must cover Terminal compensation visibility.');
+ assertCheck(failures, artifact.coverage.localStagingRehearsalCovered === true, 'Gate 2 must cover local/staging rehearsal posture.');
+ assertCheck(failures, artifact.coverage.sourceSafeMetadataOnly === true, 'Gate 2 must remain source-safe metadata only.');
+ assertCheck(failures, artifact.coverage.protectedSourceVisible === false, 'Gate 2 artifact must not expose protected source.');
+ assertCheck(failures, artifact.coverage.btdMintedAtDepositAdmission === false, 'Gate 2 must not mint BTD at deposit admission.');
+ assertCheck(failures, artifact.coverage.btdRightsTransferredBeforeSettlement === false, 'Gate 2 must not transfer BTD rights before settlement.');
+ assertCheck(failures, artifact.coverage.compensationAllocationMethod === 'source-to-shares-largest-remainder', 'Gate 2 must bind source-to-shares allocation.');
+ assertCheck(failures, artifact.coverage.compensationPriceAsset === 'BTC', 'Gate 2 must bind BTC compensation visibility.');
+ assertCheck(failures, artifact.coverage.legacySourceRoots === false, 'Gate 2 must not rely on legacy source roots.');
+ assertCheck(failures, Array.isArray(artifact.coverage.failedPredicateIds) && artifact.coverage.failedPredicateIds.length === 0, 'Gate 2 predicates must all pass.');
+ }
+
+ const spec = read(root, 'BITCODE_SPEC_V42.md');
+ const parity = read(root, 'BITCODE_SPEC_V42_PARITY_MATRIX.md');
+ const readme = read(root, 'packages/pipelines/asset-pack/README.md');
+ assertCheck(failures, spec.includes('V42 Gate 2') && spec.includes('compensation route preview'), 'V42 spec must expand Gate 2 compensation route preview.');
+ assertCheck(failures, parity.includes('Gate 2') && parity.includes('implemented'), 'V42 parity matrix must mark Gate 2 implemented.');
+ assertCheck(failures, readme.includes('compensation preview') && readme.includes('source-to-shares'), 'AssetPack README must document compensation preview.');
+
+ if (failures.length > 0) {
+ process.stderr.write(`V42 Gate 2 Depositing shortest path check failed:\n- ${failures.join('\n- ')}\n`);
+ process.exitCode = 1;
+ return;
+ }
+
+ process.stdout.write(`V42 Gate 2 Depositing shortest path ok artifact=${artifact.artifactRoot}\n`);
+}
+
+main();
diff --git a/scripts/generate-v42-depositing-shortest-path.mjs b/scripts/generate-v42-depositing-shortest-path.mjs
new file mode 100644
index 00000000..4ca1a620
--- /dev/null
+++ b/scripts/generate-v42-depositing-shortest-path.mjs
@@ -0,0 +1,31 @@
+#!/usr/bin/env node
+
+import { readFileSync, writeFileSync } from 'node:fs';
+import path from 'node:path';
+import { fileURLToPath } from 'node:url';
+import {
+ V42_DEPOSITING_SHORTEST_PATH_ARTIFACT_PATH,
+ buildV42DepositingShortestPath,
+} from '../packages/protocol/src/canonical/v42-depositing-shortest-path.js';
+
+const __filename = fileURLToPath(import.meta.url);
+const __dirname = path.dirname(__filename);
+const repoRoot = path.resolve(__dirname, '..');
+
+const check = process.argv.includes('--check');
+const artifact = buildV42DepositingShortestPath({ repoRoot });
+const serialized = `${JSON.stringify(artifact, null, 2)}\n`;
+const artifactPath = path.join(repoRoot, V42_DEPOSITING_SHORTEST_PATH_ARTIFACT_PATH);
+
+if (check) {
+ const current = readFileSync(artifactPath, 'utf8');
+ if (current !== serialized) {
+ process.stderr.write(
+ `${V42_DEPOSITING_SHORTEST_PATH_ARTIFACT_PATH} is stale. Run pnpm run generate:v42-depositing-shortest-path.\n`,
+ );
+ process.exitCode = 1;
+ }
+} else {
+ writeFileSync(artifactPath, serialized);
+ process.stdout.write(`wrote ${V42_DEPOSITING_SHORTEST_PATH_ARTIFACT_PATH}\n`);
+}
diff --git a/uapi/app/terminal/TerminalDepositComposer.tsx b/uapi/app/terminal/TerminalDepositComposer.tsx
index 2daea862..8e799f7e 100644
--- a/uapi/app/terminal/TerminalDepositComposer.tsx
+++ b/uapi/app/terminal/TerminalDepositComposer.tsx
@@ -44,6 +44,24 @@ type TerminalDepositResponseEvidence = {
depositorySearchDocumentRoot?: string | null;
lexicalDocumentRoot?: string | null;
vectorDocumentRoot?: string | null;
+ compensationPreviewRoot?: string | null;
+ sourceToSharesPreviewRoot?: string | null;
+ compensationPreview?: {
+ state?: string | null;
+ readiness?: {
+ eligibleForFindingFits?: boolean | null;
+ eligibleForCompensationIfSelected?: boolean | null;
+ blockers?: string[] | null;
+ warnings?: string[] | null;
+ } | null;
+ compensationRoute?: {
+ priceAsset?: string | null;
+ allocationMethod?: string | null;
+ sourceToSharesProofState?: string | null;
+ btdMintBoundary?: string | null;
+ btdRightsTransferBoundary?: string | null;
+ } | null;
+ } | null;
depositorBoundary?: {
walletId?: string | null;
} | null;
@@ -318,6 +336,7 @@ export default function TerminalDepositComposer({
depositoryEvidence?: TerminalDepositResponseEvidence | null;
};
const depositoryEvidence = payload.depositoryEvidence || payload.asset?.depositoryEvidence || null;
+ const compensationPreview = depositoryEvidence?.compensationPreview || null;
await runControl((controls) => controls.refresh?.());
setTitle('');
@@ -355,6 +374,15 @@ export default function TerminalDepositComposer({
depositorySearchDocumentRoot: depositoryEvidence?.depositorySearchDocumentRoot || null,
lexicalDocumentRoot: depositoryEvidence?.lexicalDocumentRoot || null,
vectorDocumentRoot: depositoryEvidence?.vectorDocumentRoot || null,
+ compensationPreviewRoot: depositoryEvidence?.compensationPreviewRoot || null,
+ sourceToSharesPreviewRoot: depositoryEvidence?.sourceToSharesPreviewRoot || null,
+ compensationState: compensationPreview?.state || null,
+ compensationAllocationMethod: compensationPreview?.compensationRoute?.allocationMethod || null,
+ compensationPriceAsset: compensationPreview?.compensationRoute?.priceAsset || null,
+ compensationEligibleForFindingFits:
+ compensationPreview?.readiness?.eligibleForFindingFits ?? null,
+ compensationEligibleIfSelected:
+ compensationPreview?.readiness?.eligibleForCompensationIfSelected ?? null,
depositorWalletId: depositoryEvidence?.depositorBoundary?.walletId || null,
depositoryIndexState: depositoryEvidence?.indexState?.vector || depositoryEvidence?.indexState?.lexical || null,
},
@@ -787,6 +815,16 @@ export default function TerminalDepositComposer({
Submitting refreshes the working chain so selected supply, measured demand, fit, and later branch, proof,
and settlement reads stay aligned in the same Bitcode Terminal.
+
+
+
- Compensation route
+ - BTC source-to-shares preview if this deposit is selected into a paid AssetPack
+
+
+
- Pre-fit boundary
+ - No BTD mint or source-bearing reader visibility at deposit admission
+
+
diff --git a/uapi/app/terminal/TerminalPageClient.tsx b/uapi/app/terminal/TerminalPageClient.tsx
index 37437b67..33d0e3ca 100644
--- a/uapi/app/terminal/TerminalPageClient.tsx
+++ b/uapi/app/terminal/TerminalPageClient.tsx
@@ -329,6 +329,11 @@ export default function TerminalPageClient() {
depositorySearchDocumentRoot: matchingSubmission.depositorySearchDocumentRoot || null,
lexicalDocumentRoot: matchingSubmission.lexicalDocumentRoot || null,
vectorDocumentRoot: matchingSubmission.vectorDocumentRoot || null,
+ compensationPreviewRoot: matchingSubmission.compensationPreviewRoot || null,
+ sourceToSharesPreviewRoot: matchingSubmission.sourceToSharesPreviewRoot || null,
+ compensationState: matchingSubmission.compensationState || null,
+ compensationAllocationMethod: matchingSubmission.compensationAllocationMethod || null,
+ compensationPriceAsset: matchingSubmission.compensationPriceAsset || null,
depositorWalletId: matchingSubmission.depositorWalletId || null,
depositoryIndexState: matchingSubmission.depositoryIndexState || null,
};
diff --git a/uapi/app/terminal/terminal-activity-history.ts b/uapi/app/terminal/terminal-activity-history.ts
index 5fde0e8d..900da747 100644
--- a/uapi/app/terminal/terminal-activity-history.ts
+++ b/uapi/app/terminal/terminal-activity-history.ts
@@ -678,6 +678,23 @@ export function mapExecutionHistoryRunToWorkspaceRun(run: PipelineExecution): Wo
contextString('lexicalDocumentRoot') || readNestedString(run.output, ['depositoryEvidence', 'lexicalDocumentRoot']),
vectorDocumentRoot:
contextString('vectorDocumentRoot') || readNestedString(run.output, ['depositoryEvidence', 'vectorDocumentRoot']),
+ compensationPreviewRoot:
+ contextString('compensationPreviewRoot') ||
+ readNestedString(run.output, ['depositoryEvidence', 'compensationPreviewRoot']) ||
+ readNestedString(run.output, ['depositoryEvidence', 'compensationPreview', 'roots', 'compensationPreviewRoot']),
+ sourceToSharesPreviewRoot:
+ contextString('sourceToSharesPreviewRoot') ||
+ readNestedString(run.output, ['depositoryEvidence', 'sourceToSharesPreviewRoot']) ||
+ readNestedString(run.output, ['depositoryEvidence', 'compensationPreview', 'roots', 'sourceToSharesPreviewRoot']),
+ compensationState:
+ contextString('compensationState') ||
+ readNestedString(run.output, ['depositoryEvidence', 'compensationPreview', 'state']),
+ compensationAllocationMethod:
+ contextString('compensationAllocationMethod') ||
+ readNestedString(run.output, ['depositoryEvidence', 'compensationPreview', 'compensationRoute', 'allocationMethod']),
+ compensationPriceAsset:
+ contextString('compensationPriceAsset') ||
+ readNestedString(run.output, ['depositoryEvidence', 'compensationPreview', 'compensationRoute', 'priceAsset']),
depositorWalletId:
contextString('depositorWalletId') ||
readNestedString(run.output, ['depositoryEvidence', 'depositorBoundary', 'walletId']),
diff --git a/uapi/app/terminal/terminal-deposit-read-workbench.ts b/uapi/app/terminal/terminal-deposit-read-workbench.ts
index 4f6c6b9c..c8aa08eb 100644
--- a/uapi/app/terminal/terminal-deposit-read-workbench.ts
+++ b/uapi/app/terminal/terminal-deposit-read-workbench.ts
@@ -33,6 +33,11 @@ export type TerminalDepositedSourceRevision = TerminalSourceRevision & {
depositorySearchDocumentRoot?: string | null;
lexicalDocumentRoot?: string | null;
vectorDocumentRoot?: string | null;
+ compensationPreviewRoot?: string | null;
+ sourceToSharesPreviewRoot?: string | null;
+ compensationState?: string | null;
+ compensationAllocationMethod?: string | null;
+ compensationPriceAsset?: string | null;
depositorWalletId?: string | null;
depositoryIndexState?: string | null;
};
@@ -94,6 +99,11 @@ type ShellSnapshot = {
depositorySearchDocumentRoot?: string | null;
lexicalDocumentRoot?: string | null;
vectorDocumentRoot?: string | null;
+ compensationPreviewRoot?: string | null;
+ sourceToSharesPreviewRoot?: string | null;
+ compensationState?: string | null;
+ compensationAllocationMethod?: string | null;
+ compensationPriceAsset?: string | null;
depositorWalletId?: string | null;
depositoryIndexState?: string | null;
} | null;
@@ -232,6 +242,11 @@ export function buildLiveTerminalDepositReadWorkbenchSnapshot(
depositorySearchDocumentRoot: matchingDepositedRevision?.depositorySearchDocumentRoot || null,
lexicalDocumentRoot: matchingDepositedRevision?.lexicalDocumentRoot || null,
vectorDocumentRoot: matchingDepositedRevision?.vectorDocumentRoot || null,
+ compensationPreviewRoot: matchingDepositedRevision?.compensationPreviewRoot || null,
+ sourceToSharesPreviewRoot: matchingDepositedRevision?.sourceToSharesPreviewRoot || null,
+ compensationState: matchingDepositedRevision?.compensationState || null,
+ compensationAllocationMethod: matchingDepositedRevision?.compensationAllocationMethod || null,
+ compensationPriceAsset: matchingDepositedRevision?.compensationPriceAsset || null,
depositorWalletId: matchingDepositedRevision?.depositorWalletId || null,
depositoryIndexState: matchingDepositedRevision?.depositoryIndexState || null,
},
@@ -406,6 +421,11 @@ export function normalizeTerminalDepositReadWorkbench(
const depositorySearchDocumentRoot = textValue(snapshot.depositingSurface?.depositorySearchDocumentRoot);
const lexicalDocumentRoot = textValue(snapshot.depositingSurface?.lexicalDocumentRoot);
const vectorDocumentRoot = textValue(snapshot.depositingSurface?.vectorDocumentRoot);
+ const compensationPreviewRoot = textValue(snapshot.depositingSurface?.compensationPreviewRoot);
+ const sourceToSharesPreviewRoot = textValue(snapshot.depositingSurface?.sourceToSharesPreviewRoot);
+ const compensationState = textValue(snapshot.depositingSurface?.compensationState);
+ const compensationAllocationMethod = textValue(snapshot.depositingSurface?.compensationAllocationMethod);
+ const compensationPriceAsset = textValue(snapshot.depositingSurface?.compensationPriceAsset);
const depositorWalletId = textValue(snapshot.depositingSurface?.depositorWalletId);
const depositoryIndexState = textValue(snapshot.depositingSurface?.depositoryIndexState);
const sourceProofRootCount = [
@@ -418,6 +438,10 @@ export function normalizeTerminalDepositReadWorkbench(
lexicalDocumentRoot,
vectorDocumentRoot,
].filter(Boolean).length;
+ const compensationRootCount = [
+ compensationPreviewRoot,
+ sourceToSharesPreviewRoot,
+ ].filter(Boolean).length;
const sourceRevisionRepository = textValue(snapshot.sourceRevision?.repositoryFullName) || repositoryLabel;
const sourceRevisionBranch =
textValue(snapshot.sourceRevision?.branch) ||
@@ -448,6 +472,7 @@ export function normalizeTerminalDepositReadWorkbench(
},
{ label: 'Source proof roots', value: numberValue(sourceProofRootCount) },
{ label: 'Search document roots', value: numberValue(searchDocumentRootCount) },
+ { label: 'Compensation roots', value: numberValue(compensationRootCount) },
]
: [
{ label: 'Selected refs', value: numberValue(snapshot.inventory?.selectedCount) },
@@ -456,6 +481,7 @@ export function normalizeTerminalDepositReadWorkbench(
{ label: 'Authenticated repos', value: numberValue(snapshot.repoSupplySummary?.repoCount) },
{ label: 'Source proof roots', value: numberValue(sourceProofRootCount) },
{ label: 'Search document roots', value: numberValue(searchDocumentRootCount) },
+ { label: 'Compensation roots', value: numberValue(compensationRootCount) },
];
return {
@@ -547,6 +573,26 @@ export function normalizeTerminalDepositReadWorkbench(
label: 'Vector document root',
value: vectorDocumentRoot || '—',
},
+ {
+ label: 'Compensation state',
+ value: compensationState || '—',
+ },
+ {
+ label: 'Compensation asset',
+ value: compensationPriceAsset || '—',
+ },
+ {
+ label: 'Source-to-shares method',
+ value: compensationAllocationMethod || '—',
+ },
+ {
+ label: 'Compensation preview root',
+ value: compensationPreviewRoot || '—',
+ },
+ {
+ label: 'Source-to-shares preview root',
+ value: sourceToSharesPreviewRoot || '—',
+ },
{
label: 'Depository index',
value: depositoryIndexState || '—',
diff --git a/uapi/app/terminal/terminal-run-data.ts b/uapi/app/terminal/terminal-run-data.ts
index 84be1f2d..46de2176 100644
--- a/uapi/app/terminal/terminal-run-data.ts
+++ b/uapi/app/terminal/terminal-run-data.ts
@@ -16,6 +16,11 @@ export type WorkspaceRun = Pick
Date: Thu, 28 May 2026 17:41:40 -0300
Subject: [PATCH 04/35] V42 Gate 3: Add Reading Shortest Path State Machine
Implement the source-safe Reading route state contract with recoverable transaction ids, readingStage hydration, retry/restart posture, failure repair actions, and Terminal route projection.
Add the V42 Reading shortest path artifact, generator, checker, protocol export/test, workflow wiring, and documentation/parity updates, including V43+ UX route-renaming scope for Packs, Read, and Deposit.
---
.bitcode/v42-depositing-shortest-path.json | 2 +-
...2-reading-shortest-path-state-machine.json | 575 ++++++++++++++++++
.github/workflows/bitcode-canon-quality.yml | 3 +
.github/workflows/bitcode-gate-quality.yml | 3 +
BITCODE_SPEC_V42.md | 11 +-
BITCODE_SPEC_V42_DELTA.md | 3 +
BITCODE_SPEC_V42_NOTES.md | 5 +
BITCODE_SPEC_V42_PARITY_MATRIX.md | 4 +-
README.md | 9 +-
SPECIFICATIONS_ROADMAP.md | 7 +-
package.json | 3 +
packages/protocol/README.md | 9 +
.../canonical/v42-depositing-shortest-path.js | 6 +-
...v42-reading-shortest-path-state-machine.js | 324 ++++++++++
packages/protocol/src/index.d.ts | 9 +
packages/protocol/src/index.js | 11 +
...eading-shortest-path-state-machine.test.js | 77 +++
...e3-reading-shortest-path-state-machine.mjs | 240 ++++++++
...42-reading-shortest-path-state-machine.mjs | 31 +
uapi/app/terminal/README.md | 10 +
.../terminal/TerminalDepositReadWorkbench.tsx | 17 +-
uapi/app/terminal/TerminalPageClient.tsx | 1 +
.../terminal-enterprise-reading-ux-state.ts | 116 +++-
.../terminalEnterpriseReadingUxState.test.ts | 37 ++
24 files changed, 1502 insertions(+), 11 deletions(-)
create mode 100644 .bitcode/v42-reading-shortest-path-state-machine.json
create mode 100644 packages/protocol/src/canonical/v42-reading-shortest-path-state-machine.js
create mode 100644 packages/protocol/test/v42-reading-shortest-path-state-machine.test.js
create mode 100644 scripts/check-v42-gate3-reading-shortest-path-state-machine.mjs
create mode 100644 scripts/generate-v42-reading-shortest-path-state-machine.mjs
diff --git a/.bitcode/v42-depositing-shortest-path.json b/.bitcode/v42-depositing-shortest-path.json
index d6833815..e8a84d7f 100644
--- a/.bitcode/v42-depositing-shortest-path.json
+++ b/.bitcode/v42-depositing-shortest-path.json
@@ -424,7 +424,7 @@
"passed": true
},
{
- "id": "roadmap-current-gate-advanced",
+ "id": "roadmap-records-gate2-closure",
"sourcePath": "SPECIFICATIONS_ROADMAP.md",
"passed": true
}
diff --git a/.bitcode/v42-reading-shortest-path-state-machine.json b/.bitcode/v42-reading-shortest-path-state-machine.json
new file mode 100644
index 00000000..a5f4b88e
--- /dev/null
+++ b/.bitcode/v42-reading-shortest-path-state-machine.json
@@ -0,0 +1,575 @@
+{
+ "artifactId": "v42-reading-shortest-path-state-machine",
+ "schemaId": "bitcode.v42.readingShortestPathStateMachine.v1",
+ "version": "V42",
+ "currentTarget": "V41",
+ "sourceSafetyVerdict": "source-safe-reading-shortest-path-state-machine-metadata",
+ "generatedAt": "deterministic",
+ "artifactRoot": "v42-reading-shortest-path-state-machine:c30584924864342dafe806b5",
+ "passed": true,
+ "rows": [
+ {
+ "rowId": "state:five-step-shortest-path",
+ "purpose": "Preserve exactly five enterprise Reading steps from Read Request through Need review, Finding Fits, AssetPack preview, and settlement delivery.",
+ "sourceRoots": [
+ "uapi/app/terminal/terminal-enterprise-reading-ux-state.ts",
+ "uapi/app/terminal/TerminalDepositReadWorkbench.tsx"
+ ],
+ "emittedTypes": [
+ "TerminalEnterpriseReadingUxState",
+ "TerminalEnterpriseReadingStepView"
+ ],
+ "requiredEvidence": [
+ "request-read",
+ "review-synthesized-need",
+ "request-fit",
+ "review-synthesized-asset-pack",
+ "buy-asset-pack-settle"
+ ],
+ "rowRoot": "v42-reading-shortest-path-state-machine-row:f5bccf679eaefd791e5f0c19",
+ "sourceSafetyClass": "source_safe_reading_shortest_path_state_machine_metadata",
+ "sourceSafeMetadataOnly": true,
+ "lowDetailDefault": true,
+ "expandableSourceSafeDetail": true,
+ "protectedSourceVisible": false,
+ "rawProtectedPromptVisible": false,
+ "rawProviderResponseVisible": false,
+ "unpaidAssetPackSourceVisible": false,
+ "walletPrivateMaterialVisible": false,
+ "settlementPrivatePayloadVisible": false,
+ "ledgerAuthorityClaimed": false,
+ "forbiddenPayloadClasses": [
+ "protected-source-payloads",
+ "raw-protected-prompts",
+ "raw-provider-responses",
+ "unpaid-assetpack-source",
+ "wallet-private-material",
+ "settlement-private-payloads",
+ "ledger-write-authority",
+ "secret-values"
+ ]
+ },
+ {
+ "rowId": "route:transaction-stage-persistence",
+ "purpose": "Bind Reading state to recoverable transaction ids and readingStage route state so refresh, restart, and route handoff preserve the active stage.",
+ "sourceRoots": [
+ "uapi/app/terminal/terminal-enterprise-reading-ux-state.ts",
+ "uapi/app/terminal/terminal-transaction-query.ts",
+ "uapi/app/terminal/TerminalPageClient.tsx",
+ "uapi/app/terminal/TerminalDepositReadWorkbench.tsx"
+ ],
+ "emittedTypes": [
+ "TerminalEnterpriseReadingRouteState",
+ "TerminalConversationHandoffContext.readingStage"
+ ],
+ "requiredEvidence": [
+ "transactionIdRequiredForRecovery",
+ "readingStageQueryParam",
+ "activeStageHydratedFromRoute"
+ ],
+ "rowRoot": "v42-reading-shortest-path-state-machine-row:8d27b75c5cb5dc6528241458",
+ "sourceSafetyClass": "source_safe_reading_shortest_path_state_machine_metadata",
+ "sourceSafeMetadataOnly": true,
+ "lowDetailDefault": true,
+ "expandableSourceSafeDetail": true,
+ "protectedSourceVisible": false,
+ "rawProtectedPromptVisible": false,
+ "rawProviderResponseVisible": false,
+ "unpaidAssetPackSourceVisible": false,
+ "walletPrivateMaterialVisible": false,
+ "settlementPrivatePayloadVisible": false,
+ "ledgerAuthorityClaimed": false,
+ "forbiddenPayloadClasses": [
+ "protected-source-payloads",
+ "raw-protected-prompts",
+ "raw-provider-responses",
+ "unpaid-assetpack-source",
+ "wallet-private-material",
+ "settlement-private-payloads",
+ "ledger-write-authority",
+ "secret-values"
+ ]
+ },
+ {
+ "rowId": "transition:accepted-need-before-finding-fits",
+ "purpose": "Make accepted Need the hard transition before Finding Fits, preview, settlement, or delivery can proceed.",
+ "sourceRoots": [
+ "uapi/app/terminal/terminal-enterprise-reading-ux-state.ts",
+ "uapi/app/terminal/TerminalDepositReadWorkbench.tsx",
+ "uapi/app/conversations/conversation-terminal-handoff.ts"
+ ],
+ "emittedTypes": [
+ "acceptedNeedRequiredBeforeFindingFits",
+ "TerminalReadNeedState"
+ ],
+ "requiredEvidence": [
+ "accepted Need required",
+ "ReadNeedComprehensionSynthesis",
+ "ReadFitsFindingSynthesis"
+ ],
+ "rowRoot": "v42-reading-shortest-path-state-machine-row:f9d95c5e18d4566c693e32c1",
+ "sourceSafetyClass": "source_safe_reading_shortest_path_state_machine_metadata",
+ "sourceSafeMetadataOnly": true,
+ "lowDetailDefault": true,
+ "expandableSourceSafeDetail": true,
+ "protectedSourceVisible": false,
+ "rawProtectedPromptVisible": false,
+ "rawProviderResponseVisible": false,
+ "unpaidAssetPackSourceVisible": false,
+ "walletPrivateMaterialVisible": false,
+ "settlementPrivatePayloadVisible": false,
+ "ledgerAuthorityClaimed": false,
+ "forbiddenPayloadClasses": [
+ "protected-source-payloads",
+ "raw-protected-prompts",
+ "raw-provider-responses",
+ "unpaid-assetpack-source",
+ "wallet-private-material",
+ "settlement-private-payloads",
+ "ledger-write-authority",
+ "secret-values"
+ ]
+ },
+ {
+ "rowId": "retry:restart-and-failure-repair",
+ "purpose": "Represent retry, restart, and failure repair posture as source-safe state metadata without exposing protected source, prompts, provider responses, wallet material, or settlement payloads.",
+ "sourceRoots": [
+ "uapi/app/terminal/terminal-enterprise-reading-ux-state.ts",
+ "uapi/tests/terminalEnterpriseReadingUxState.test.ts",
+ "uapi/app/terminal/TerminalDepositReadWorkbench.tsx"
+ ],
+ "emittedTypes": [
+ "TerminalEnterpriseReadingFailureKind",
+ "TerminalEnterpriseReadingRouteState.failureRepairActions"
+ ],
+ "requiredEvidence": [
+ "retryPreservesNeedLineage",
+ "restartRestoresActiveStage",
+ "failureRepairActions"
+ ],
+ "rowRoot": "v42-reading-shortest-path-state-machine-row:8255affa47cdbf93089ab9cc",
+ "sourceSafetyClass": "source_safe_reading_shortest_path_state_machine_metadata",
+ "sourceSafeMetadataOnly": true,
+ "lowDetailDefault": true,
+ "expandableSourceSafeDetail": true,
+ "protectedSourceVisible": false,
+ "rawProtectedPromptVisible": false,
+ "rawProviderResponseVisible": false,
+ "unpaidAssetPackSourceVisible": false,
+ "walletPrivateMaterialVisible": false,
+ "settlementPrivatePayloadVisible": false,
+ "ledgerAuthorityClaimed": false,
+ "forbiddenPayloadClasses": [
+ "protected-source-payloads",
+ "raw-protected-prompts",
+ "raw-provider-responses",
+ "unpaid-assetpack-source",
+ "wallet-private-material",
+ "settlement-private-payloads",
+ "ledger-write-authority",
+ "secret-values"
+ ]
+ },
+ {
+ "rowId": "ui:low-detail-proof-on-expand",
+ "purpose": "Keep the default Reading view guided and low-detail while details expand to source-safe proof roots, measurements, blockers, and visible field ids.",
+ "sourceRoots": [
+ "uapi/app/terminal/terminal-enterprise-reading-ux-state.ts",
+ "uapi/app/terminal/TerminalDepositReadWorkbench.tsx",
+ "uapi/app/terminal/README.md"
+ ],
+ "emittedTypes": [
+ "TerminalEnterpriseReadingUxState.disclosure"
+ ],
+ "requiredEvidence": [
+ "lowDetailDefault",
+ "expandableSourceSafeDetail",
+ "Source-safe detail"
+ ],
+ "rowRoot": "v42-reading-shortest-path-state-machine-row:bc5d512f5a40eab14e0cc0a5",
+ "sourceSafetyClass": "source_safe_reading_shortest_path_state_machine_metadata",
+ "sourceSafeMetadataOnly": true,
+ "lowDetailDefault": true,
+ "expandableSourceSafeDetail": true,
+ "protectedSourceVisible": false,
+ "rawProtectedPromptVisible": false,
+ "rawProviderResponseVisible": false,
+ "unpaidAssetPackSourceVisible": false,
+ "walletPrivateMaterialVisible": false,
+ "settlementPrivatePayloadVisible": false,
+ "ledgerAuthorityClaimed": false,
+ "forbiddenPayloadClasses": [
+ "protected-source-payloads",
+ "raw-protected-prompts",
+ "raw-provider-responses",
+ "unpaid-assetpack-source",
+ "wallet-private-material",
+ "settlement-private-payloads",
+ "ledger-write-authority",
+ "secret-values"
+ ]
+ },
+ {
+ "rowId": "stream:rich-reading-pipeline-telemetry",
+ "purpose": "Keep Reading pipeline progress inspectable through rich execution stream rows for phase, PTRR step, ThricifiedGeneration, tool, prompt-template id, output schema, and parsed-result posture.",
+ "sourceRoots": [
+ "uapi/app/terminal/terminal-pipeline-harness-client.ts",
+ "uapi/tests/pipelineExecutionLogHeader.test.tsx",
+ "uapi/app/terminal/TerminalDepositReadWorkbench.tsx"
+ ],
+ "emittedTypes": [
+ "TerminalReadFitsFindingSynthesisHarnessEvent",
+ "ExecutionLogItem"
+ ],
+ "requiredEvidence": [
+ "pipelinePhaseId",
+ "ptrrStepId",
+ "thricifiedGenerationId",
+ "promptTemplateId",
+ "outputSchema"
+ ],
+ "rowRoot": "v42-reading-shortest-path-state-machine-row:f84a65471fa1a4ff2dc6a8be",
+ "sourceSafetyClass": "source_safe_reading_shortest_path_state_machine_metadata",
+ "sourceSafeMetadataOnly": true,
+ "lowDetailDefault": true,
+ "expandableSourceSafeDetail": true,
+ "protectedSourceVisible": false,
+ "rawProtectedPromptVisible": false,
+ "rawProviderResponseVisible": false,
+ "unpaidAssetPackSourceVisible": false,
+ "walletPrivateMaterialVisible": false,
+ "settlementPrivatePayloadVisible": false,
+ "ledgerAuthorityClaimed": false,
+ "forbiddenPayloadClasses": [
+ "protected-source-payloads",
+ "raw-protected-prompts",
+ "raw-provider-responses",
+ "unpaid-assetpack-source",
+ "wallet-private-material",
+ "settlement-private-payloads",
+ "ledger-write-authority",
+ "secret-values"
+ ]
+ },
+ {
+ "rowId": "activity:history-and-workbench-readback",
+ "purpose": "Project Reading state through activity history and workbench readback so transaction detail, proof roots, and compensation/settlement posture remain recoverable.",
+ "sourceRoots": [
+ "uapi/app/terminal/terminal-activity-history.ts",
+ "uapi/app/terminal/TerminalDepositReadWorkbench.tsx",
+ "uapi/app/terminal/terminal-deposit-read-workbench.ts"
+ ],
+ "emittedTypes": [
+ "WorkspaceRun",
+ "TerminalDepositReadWorkbench"
+ ],
+ "requiredEvidence": [
+ "assetPackCompletion",
+ "TerminalDepositedSourceRevision",
+ "sourceRevision"
+ ],
+ "rowRoot": "v42-reading-shortest-path-state-machine-row:96ceba0e8af3d5ad27fcab3c",
+ "sourceSafetyClass": "source_safe_reading_shortest_path_state_machine_metadata",
+ "sourceSafeMetadataOnly": true,
+ "lowDetailDefault": true,
+ "expandableSourceSafeDetail": true,
+ "protectedSourceVisible": false,
+ "rawProtectedPromptVisible": false,
+ "rawProviderResponseVisible": false,
+ "unpaidAssetPackSourceVisible": false,
+ "walletPrivateMaterialVisible": false,
+ "settlementPrivatePayloadVisible": false,
+ "ledgerAuthorityClaimed": false,
+ "forbiddenPayloadClasses": [
+ "protected-source-payloads",
+ "raw-protected-prompts",
+ "raw-provider-responses",
+ "unpaid-assetpack-source",
+ "wallet-private-material",
+ "settlement-private-payloads",
+ "ledger-write-authority",
+ "secret-values"
+ ]
+ },
+ {
+ "rowId": "tests:route-state-contracts",
+ "purpose": "Prove the state machine through route-state tests, component state tests, Conversation handoff tests, workbench tests, and stream-header tests.",
+ "sourceRoots": [
+ "uapi/tests/terminalEnterpriseReadingUxState.test.ts",
+ "uapi/tests/terminalDepositReadWorkbench.test.ts",
+ "uapi/tests/conversationTerminalHandoff.test.tsx",
+ "uapi/tests/terminalTransactionQuery.test.ts",
+ "uapi/tests/pipelineExecutionLogHeader.test.tsx",
+ ".github/workflows/bitcode-gate-quality.yml"
+ ],
+ "emittedTypes": [
+ "V42ReadingShortestPathStateMachineReport"
+ ],
+ "requiredEvidence": [
+ "terminal-enterprise-reading-ux-state",
+ "readingStage=request-fit",
+ "Browser proof Terminal cockpit"
+ ],
+ "rowRoot": "v42-reading-shortest-path-state-machine-row:e06bfe55a25e9021a4fb3780",
+ "sourceSafetyClass": "source_safe_reading_shortest_path_state_machine_metadata",
+ "sourceSafeMetadataOnly": true,
+ "lowDetailDefault": true,
+ "expandableSourceSafeDetail": true,
+ "protectedSourceVisible": false,
+ "rawProtectedPromptVisible": false,
+ "rawProviderResponseVisible": false,
+ "unpaidAssetPackSourceVisible": false,
+ "walletPrivateMaterialVisible": false,
+ "settlementPrivatePayloadVisible": false,
+ "ledgerAuthorityClaimed": false,
+ "forbiddenPayloadClasses": [
+ "protected-source-payloads",
+ "raw-protected-prompts",
+ "raw-provider-responses",
+ "unpaid-assetpack-source",
+ "wallet-private-material",
+ "settlement-private-payloads",
+ "ledger-write-authority",
+ "secret-values"
+ ]
+ },
+ {
+ "rowId": "spec:v42-gate3-closure",
+ "purpose": "Bind V42 Gate 3 to SPEC, DELTA, NOTES, PARITY, roadmap, README, workflow, generated artifact, and checker closure.",
+ "sourceRoots": [
+ "BITCODE_SPEC_V42.md",
+ "BITCODE_SPEC_V42_DELTA.md",
+ "BITCODE_SPEC_V42_NOTES.md",
+ "BITCODE_SPEC_V42_PARITY_MATRIX.md",
+ "SPECIFICATIONS_ROADMAP.md",
+ "README.md",
+ "packages/protocol/README.md"
+ ],
+ "emittedTypes": [
+ "V42ReadingShortestPathStateMachineReport"
+ ],
+ "requiredEvidence": [
+ "V42 Gate 3",
+ "reading shortest path state machine",
+ "check:v42-gate3"
+ ],
+ "rowRoot": "v42-reading-shortest-path-state-machine-row:f0bc898ce7bb6757c5924aa9",
+ "sourceSafetyClass": "source_safe_reading_shortest_path_state_machine_metadata",
+ "sourceSafeMetadataOnly": true,
+ "lowDetailDefault": true,
+ "expandableSourceSafeDetail": true,
+ "protectedSourceVisible": false,
+ "rawProtectedPromptVisible": false,
+ "rawProviderResponseVisible": false,
+ "unpaidAssetPackSourceVisible": false,
+ "walletPrivateMaterialVisible": false,
+ "settlementPrivatePayloadVisible": false,
+ "ledgerAuthorityClaimed": false,
+ "forbiddenPayloadClasses": [
+ "protected-source-payloads",
+ "raw-protected-prompts",
+ "raw-provider-responses",
+ "unpaid-assetpack-source",
+ "wallet-private-material",
+ "settlement-private-payloads",
+ "ledger-write-authority",
+ "secret-values"
+ ]
+ }
+ ],
+ "rowIds": [
+ "state:five-step-shortest-path",
+ "route:transaction-stage-persistence",
+ "transition:accepted-need-before-finding-fits",
+ "retry:restart-and-failure-repair",
+ "ui:low-detail-proof-on-expand",
+ "stream:rich-reading-pipeline-telemetry",
+ "activity:history-and-workbench-readback",
+ "tests:route-state-contracts",
+ "spec:v42-gate3-closure"
+ ],
+ "stepIds": [
+ "request-read",
+ "review-synthesized-need",
+ "request-fit",
+ "review-synthesized-asset-pack",
+ "buy-asset-pack-settle"
+ ],
+ "predicateResults": [
+ {
+ "id": "ux-state-keeps-five-step-path",
+ "sourcePath": "uapi/app/terminal/terminal-enterprise-reading-ux-state.ts",
+ "passed": true
+ },
+ {
+ "id": "ux-state-defines-route-state",
+ "sourcePath": "uapi/app/terminal/terminal-enterprise-reading-ux-state.ts",
+ "passed": true
+ },
+ {
+ "id": "ux-state-defines-retry-failure-source-safety",
+ "sourcePath": "uapi/app/terminal/terminal-enterprise-reading-ux-state.ts",
+ "passed": true
+ },
+ {
+ "id": "ux-state-forbids-protected-payloads",
+ "sourcePath": "uapi/app/terminal/terminal-enterprise-reading-ux-state.ts",
+ "passed": true
+ },
+ {
+ "id": "terminal-page-passes-reading-stage",
+ "sourcePath": "uapi/app/terminal/TerminalPageClient.tsx",
+ "passed": true
+ },
+ {
+ "id": "workbench-projects-route-state",
+ "sourcePath": "uapi/app/terminal/TerminalDepositReadWorkbench.tsx",
+ "passed": true
+ },
+ {
+ "id": "workbench-keeps-low-detail-expandable-cards",
+ "sourcePath": "uapi/app/terminal/TerminalDepositReadWorkbench.tsx",
+ "passed": true
+ },
+ {
+ "id": "workbench-contract-reexports-stage-ids",
+ "sourcePath": "uapi/app/terminal/terminal-deposit-read-workbench.ts",
+ "passed": true
+ },
+ {
+ "id": "terminal-query-reads-reading-stage",
+ "sourcePath": "uapi/app/terminal/terminal-transaction-query.ts",
+ "passed": true
+ },
+ {
+ "id": "activity-history-keeps-reading-readback",
+ "sourcePath": "uapi/app/terminal/terminal-activity-history.ts",
+ "passed": true
+ },
+ {
+ "id": "harness-projects-rich-reading-telemetry",
+ "sourcePath": "uapi/app/terminal/terminal-pipeline-harness-client.ts",
+ "passed": true
+ },
+ {
+ "id": "conversation-handoff-preserves-reading-stage",
+ "sourcePath": "uapi/app/conversations/conversation-terminal-handoff.ts",
+ "passed": true
+ },
+ {
+ "id": "ux-state-tests-cover-route-retry-failure",
+ "sourcePath": "uapi/tests/terminalEnterpriseReadingUxState.test.ts",
+ "passed": true
+ },
+ {
+ "id": "workbench-tests-cover-five-stage-labels",
+ "sourcePath": "uapi/tests/terminalDepositReadWorkbench.test.ts",
+ "passed": true
+ },
+ {
+ "id": "handoff-tests-cover-reading-stage-route",
+ "sourcePath": "uapi/tests/conversationTerminalHandoff.test.tsx",
+ "passed": true
+ },
+ {
+ "id": "query-tests-cover-reading-stage-route",
+ "sourcePath": "uapi/tests/terminalTransactionQuery.test.ts",
+ "passed": true
+ },
+ {
+ "id": "stream-tests-cover-rich-header",
+ "sourcePath": "uapi/tests/pipelineExecutionLogHeader.test.tsx",
+ "passed": true
+ },
+ {
+ "id": "workflow-wires-gate3-check",
+ "sourcePath": ".github/workflows/bitcode-gate-quality.yml",
+ "passed": true
+ },
+ {
+ "id": "v42-spec-gate3-expanded",
+ "sourcePath": "BITCODE_SPEC_V42.md",
+ "passed": true
+ },
+ {
+ "id": "v42-delta-gate3-expanded",
+ "sourcePath": "BITCODE_SPEC_V42_DELTA.md",
+ "passed": true
+ },
+ {
+ "id": "v42-notes-gate3-expanded",
+ "sourcePath": "BITCODE_SPEC_V42_NOTES.md",
+ "passed": true
+ },
+ {
+ "id": "v42-parity-gate3-implemented",
+ "sourcePath": "BITCODE_SPEC_V42_PARITY_MATRIX.md",
+ "passed": true
+ },
+ {
+ "id": "roadmap-records-gate3-closure",
+ "sourcePath": "SPECIFICATIONS_ROADMAP.md",
+ "passed": true
+ },
+ {
+ "id": "readmes-document-gate3",
+ "sourcePath": "README.md",
+ "passed": true
+ }
+ ],
+ "coverage": {
+ "rowCount": 9,
+ "stepCount": 5,
+ "acceptedUserPath": [
+ "request-read",
+ "review-synthesized-need",
+ "request-finding-fits",
+ "review-source-safe-assetpack-preview",
+ "buy-settle-and-deliver-assetpack"
+ ],
+ "requiredPredicateCount": 24,
+ "passedPredicateCount": 24,
+ "failedPredicateIds": [],
+ "routePersistenceCovered": true,
+ "transactionIdRecoveryCovered": true,
+ "restartRetryFailureCovered": true,
+ "acceptedNeedGateCovered": true,
+ "streamLogIntegrationCovered": true,
+ "componentRouteTestsCovered": true,
+ "sourceSafeMetadataOnly": true,
+ "lowDetailDefault": true,
+ "expandableSourceSafeDetail": true,
+ "protectedSourceVisible": false,
+ "rawProtectedPromptVisible": false,
+ "rawProviderResponseVisible": false,
+ "unpaidAssetPackSourceVisible": false,
+ "walletPrivateMaterialVisible": false,
+ "settlementPrivatePayloadVisible": false,
+ "ledgerAuthorityClaimed": false,
+ "legacySourceRoots": false
+ },
+ "sourceRoots": {
+ "terminalUxState": "uapi/app/terminal/terminal-enterprise-reading-ux-state.ts",
+ "terminalWorkbench": "uapi/app/terminal/TerminalDepositReadWorkbench.tsx",
+ "terminalPageClient": "uapi/app/terminal/TerminalPageClient.tsx",
+ "terminalWorkbenchContract": "uapi/app/terminal/terminal-deposit-read-workbench.ts",
+ "terminalRouteQuery": "uapi/app/terminal/terminal-transaction-query.ts",
+ "terminalActivityHistory": "uapi/app/terminal/terminal-activity-history.ts",
+ "terminalHarnessClient": "uapi/app/terminal/terminal-pipeline-harness-client.ts",
+ "conversationHandoff": "uapi/app/conversations/conversation-terminal-handoff.ts",
+ "uxStateTest": "uapi/tests/terminalEnterpriseReadingUxState.test.ts",
+ "workbenchTest": "uapi/tests/terminalDepositReadWorkbench.test.ts",
+ "handoffTest": "uapi/tests/conversationTerminalHandoff.test.tsx",
+ "queryTest": "uapi/tests/terminalTransactionQuery.test.ts",
+ "streamHeaderTest": "uapi/tests/pipelineExecutionLogHeader.test.tsx",
+ "gateWorkflow": ".github/workflows/bitcode-gate-quality.yml",
+ "v42Spec": "BITCODE_SPEC_V42.md",
+ "v42Delta": "BITCODE_SPEC_V42_DELTA.md",
+ "v42Notes": "BITCODE_SPEC_V42_NOTES.md",
+ "v42Parity": "BITCODE_SPEC_V42_PARITY_MATRIX.md",
+ "roadmap": "SPECIFICATIONS_ROADMAP.md",
+ "rootReadme": "README.md",
+ "terminalReadme": "uapi/app/terminal/README.md",
+ "protocolReadme": "packages/protocol/README.md"
+ }
+}
diff --git a/.github/workflows/bitcode-canon-quality.yml b/.github/workflows/bitcode-canon-quality.yml
index 05484b61..dc9f130b 100644
--- a/.github/workflows/bitcode-canon-quality.yml
+++ b/.github/workflows/bitcode-canon-quality.yml
@@ -298,6 +298,9 @@ jobs:
if [ -f scripts/check-v42-gate2-depositing-shortest-path.mjs ]; then
node scripts/check-v42-gate2-depositing-shortest-path.mjs --skip-branch-check --skip-package-tests
fi
+ if [ -f scripts/check-v42-gate3-reading-shortest-path-state-machine.mjs ]; then
+ node scripts/check-v42-gate3-reading-shortest-path-state-machine.mjs --skip-branch-check --skip-uapi-tests
+ fi
fi
else
echo "Unexpected BITCODE_SPEC.txt pointer: $POINTER" >&2
diff --git a/.github/workflows/bitcode-gate-quality.yml b/.github/workflows/bitcode-gate-quality.yml
index 40c215f9..bf2440ee 100644
--- a/.github/workflows/bitcode-gate-quality.yml
+++ b/.github/workflows/bitcode-gate-quality.yml
@@ -427,6 +427,9 @@ jobs:
if [ -f scripts/check-v42-gate2-depositing-shortest-path.mjs ]; then
node scripts/check-v42-gate2-depositing-shortest-path.mjs --skip-branch-check --skip-package-tests
fi
+ if [ -f scripts/check-v42-gate3-reading-shortest-path-state-machine.mjs ]; then
+ node scripts/check-v42-gate3-reading-shortest-path-state-machine.mjs --skip-branch-check --skip-uapi-tests
+ fi
fi
else
echo "Unexpected BITCODE_SPEC.txt pointer: $POINTER" >&2
diff --git a/BITCODE_SPEC_V42.md b/BITCODE_SPEC_V42.md
index 71339f89..7b85d98f 100644
--- a/BITCODE_SPEC_V42.md
+++ b/BITCODE_SPEC_V42.md
@@ -118,6 +118,15 @@ Gate 3 must make the five Reading steps a coherent product state machine: reques
It must simplify default Terminal experience while preserving expandable proof, execution, telemetry, ledger, and storage detail.
It must prove route persistence, transaction ids, stage transitions, restart/retry behavior, source-safe UI rendering, and failure states.
+Gate 3 implements that state machine through `TerminalEnterpriseReadingUxState` and `TerminalEnterpriseReadingRouteState`.
+The route-owned state carries a recoverable transaction id, `readingStage` stage intent, retry and restart posture, source-safe failure kind, and repair action metadata.
+Route state may hydrate the active stage on refresh or Conversation handoff, but it does not waive blockers: Finding Fits still requires accepted Need, source-safe AssetPack preview still gates settlement, and delivery still requires settlement readback.
+
+Gate 3 proof artifact: `.bitcode/v42-reading-shortest-path-state-machine.json`.
+This is the canonical V42 reading shortest path state machine artifact for the MVP Reading route contract.
+The artifact must prove nine source-safe rows: five-step Reading path, transaction/stage route persistence, accepted-Need transition, restart/retry/failure repair, low-detail proof-on-expand UI, rich Reading pipeline telemetry, activity/workbench readback, route/component/stream tests, and SPEC/DELTA/NOTES/PARITY/README/workflow closure.
+Validating command: `pnpm run check:v42-gate3`.
+
## V42 Gate 4 ReadNeed Review And Resynthesis Product Closure
Gate 4 must make `ReadNeedComprehensionSynthesis` product-ready in the MVP flow.
@@ -413,7 +422,7 @@ V42 inherits operator-quality expectations for browser proof, accessibility, vis
| `.bitcode/v42-canonical-input-report.json` | `check-bitcode-canonical-inputs` | source-safe metadata | canonical input proof |
| `.bitcode/v42-canon-posture-drift-report.json` | `check-bitcode-canon-posture-drift` | source-safe metadata | active V41 / draft V42 posture proof |
| `.bitcode/v42-depositing-shortest-path.json` | V42 Gate 2 | source-safe metadata | deposit MVP proof |
-| `.bitcode/v42-reading-state-machine.json` | V42 Gate 3 | source-safe metadata | Reading product state proof |
+| `.bitcode/v42-reading-shortest-path-state-machine.json` | V42 Gate 3 | source-safe metadata | Reading product state proof |
| `.bitcode/v42-readneed-review-resynthesis.json` | V42 Gate 4 | source-safe metadata | Need review proof |
| `.bitcode/v42-readfitsfinding-preview-quote.json` | V42 Gate 5 | source-safe metadata | Finding Fits, preview, and quote proof |
| `.bitcode/v42-settlement-rights-delivery.json` | V42 Gate 6 | source-safe metadata | settlement/delivery proof |
diff --git a/BITCODE_SPEC_V42_DELTA.md b/BITCODE_SPEC_V42_DELTA.md
index cfc889e1..33f29a47 100644
--- a/BITCODE_SPEC_V42_DELTA.md
+++ b/BITCODE_SPEC_V42_DELTA.md
@@ -41,6 +41,8 @@ The compensation preview is deliberately pre-mint: it records BTC/source-to-shar
### Gate 3: Reading Shortest Path State Machine
Implement and prove the five-step Reading product state machine with low-detail defaults and expandable proof/telemetry detail.
+Gate 3 now binds route-owned Reading state to transaction recovery, `readingStage` route hydration, retry/restart posture, source-safe failure repair, accepted-Need blockers, source-safe preview blockers, rich execution stream readback, and `.bitcode/v42-reading-shortest-path-state-machine.json`.
+The state machine keeps Terminal guided by default while preserving proof-on-expand detail for operators.
### Gate 4: ReadNeed Review And Resynthesis Product Closure
@@ -71,6 +73,7 @@ Bind every V42 product artifact, workflow, generated proof, promotion command, s
- V43+ agentic deposit AssetPack option synthesis remains deferred.
- `/terminal` is not split into `/read` and `/deposit` during V42.
- `/exchange` is not renamed to `/packs` during V42.
+- V43+ must take the route-vocabulary cleanup seriously: `/packs` replaces Exchange as the searchable master-detail activity route, while `/read` and `/deposit` become the short core paths for buying and selling AssetPacks.
- Production-mainnet value-bearing operation remains blocked unless a later promoted canon explicitly admits it.
- V42 Gate 1 does not change route behavior, pipeline behavior, settlement behavior, or demonstration behavior.
diff --git a/BITCODE_SPEC_V42_NOTES.md b/BITCODE_SPEC_V42_NOTES.md
index 9c67e6be..3ba0c620 100644
--- a/BITCODE_SPEC_V42_NOTES.md
+++ b/BITCODE_SPEC_V42_NOTES.md
@@ -43,6 +43,9 @@ The V42 Reading path should be a five-step enterprise flow:
The default UI should be guided and low-detail.
The rich execution log, proof roots, telemetry rows, and ledger/storage details remain available on expansion.
+Gate 3 implements the current V42 state-machine layer with `TerminalEnterpriseReadingRouteState`.
+The recoverable route state includes transaction id presence, `readingStage`, active-stage hydration, retry and restart posture, source-safe failure kind, and repair actions.
+This makes refresh, route handoff, and recovery inspectable without disclosing protected source, protected prompts, raw provider responses, unpaid AssetPack source, wallet private material, private settlement payloads, or ledger authority.
## AssetPack source-safety note
@@ -66,6 +69,8 @@ The route model should be AssetPacks in and AssetPacks out: `/deposit` creates r
The `/packs` master view should support column sorting, filtering, and search over measurements, synthesized AssetPack titles and descriptions, values, activity or transaction type, settlement posture, and compensation state.
The detail view should expose the selected activity's source-safe data, proof roots, telemetry, ledger/database synchronization, and expandable payloads without replacing the short default path.
Outside public documentation, product UX should avoid self-referential explanatory copy; route structure, concise labels, progressive detail, and proof-on-expand must make Depositing, Reading, and Pack activity self-explanatory.
+The current transitional Terminal/Exchange UX remains too dense for the final MVP posture.
+V43+ should explicitly own the broad UX cleanup: remove Exchange naming from route and component vocabulary in favor of Packs, split Terminal into `/read` and `/deposit`, keep `/packs` as searchable master-detail activity, and use rich themed reusable components without relying on in-product explanatory copy to compensate for unclear flows.
## Concise current-system reading
diff --git a/BITCODE_SPEC_V42_PARITY_MATRIX.md b/BITCODE_SPEC_V42_PARITY_MATRIX.md
index 58e561f3..86f3f222 100644
--- a/BITCODE_SPEC_V42_PARITY_MATRIX.md
+++ b/BITCODE_SPEC_V42_PARITY_MATRIX.md
@@ -34,7 +34,7 @@ This matrix records the reliable MVP product surfaces that must become promotion
| Gate workflow | Gate quality knows active V41 / draft V42 posture and V42 Gate 1 | `.github/workflows/bitcode-gate-quality.yml` | drafted |
| Canon workflow | Canon quality knows active V41 / draft V42 posture and V42 Gate 1 | `.github/workflows/bitcode-canon-quality.yml` | drafted |
| Depositing shortest path | Source material can be admitted with Depository proof and compensation visibility | `.bitcode/v42-depositing-shortest-path.json`, `DepositorySupplyCompensationPreview`, `/api/deposits`, Terminal deposit readback | implemented |
-| Reading state machine | Five-step Reading UX is route-owned, persistent, and source-safe | later V42 Gate 3 artifact | draft-required |
+| Reading state machine | Five-step Reading UX is route-owned, persistent, and source-safe | `.bitcode/v42-reading-shortest-path-state-machine.json`, `TerminalEnterpriseReadingRouteState`, `readingStage`, route/retry/failure tests | implemented |
| ReadNeed product closure | Need synthesis, review, feedback, resynthesis, and accepted-Need admission are product-ready | later V42 Gate 4 artifact | draft-required |
| Finding Fits preview and quote | Many-candidate search, selected-fit provenance, source-safe preview, and quote are product-ready | later V42 Gate 5 artifact | draft-required |
| Settlement and delivery | BTC/BTD settlement, rights transfer, compensation, and repository PR delivery are synchronized | later V42 Gate 6 artifact | draft-required |
@@ -48,7 +48,7 @@ This matrix records the reliable MVP product surfaces that must become promotion
| --- | --- | --- |
| Gate 1 | Open V42 family, roadmap, docs, workflow posture, package script, and checker | drafted |
| Gate 2 | Depositing shortest path and compensation visibility artifact | implemented |
-| Gate 3 | Reading shortest path state machine artifact | draft-required |
+| Gate 3 | Reading shortest path state machine artifact | implemented |
| Gate 4 | ReadNeed review and resynthesis product closure artifact | draft-required |
| Gate 5 | ReadFitsFinding AssetPack preview and quote closure artifact | draft-required |
| Gate 6 | Settlement rights transfer and repository delivery closure artifact | draft-required |
diff --git a/README.md b/README.md
index e3512001..3a5b1077 100644
--- a/README.md
+++ b/README.md
@@ -93,11 +93,18 @@ Terminal compensation roots, `.bitcode/v42-depositing-shortest-path.json`,
and `check:v42-gate2`. Deposit admission remains pre-mint and pre-rights
transfer; BTC source-to-shares allocation is only a later paid AssetPack
settlement route.
+V42 Gate 3 adds the Reading shortest path state machine with
+`TerminalEnterpriseReadingRouteState`, recoverable transaction ids,
+`readingStage` hydration, retry/restart posture, source-safe failure repair,
+accepted-Need blockers, source-safe preview blockers,
+`.bitcode/v42-reading-shortest-path-state-machine.json`, and
+`check:v42-gate3`.
V43+ is roadmapped as the later agentic depositing evolution: repository
agents synthesize deposit AssetPack options from connected enterprise code,
Depository state, and Reading demand; enterprises approve or reject
sub-critical positive-ROI options; `/terminal` separates into `/read` and
-`/deposit`; and `/exchange` is renamed to `/packs` across product naming.
+`/deposit`; and `/exchange` is renamed to `/packs` across routes, component
+prefixes, tests, docs, and product naming.
That future route model treats AssetPacks as the product object in and out:
`/deposit` proposes deposit AssetPack options from source and Bitcode demand,
`/read` buys synthesized Need-Fit AssetPacks, and `/packs` becomes the
diff --git a/SPECIFICATIONS_ROADMAP.md b/SPECIFICATIONS_ROADMAP.md
index de22cd64..f328daae 100644
--- a/SPECIFICATIONS_ROADMAP.md
+++ b/SPECIFICATIONS_ROADMAP.md
@@ -5,11 +5,12 @@
- Current active canonical pointer: `BITCODE_SPEC.txt` -> `V41`
- Current active canon: `BITCODE_SPEC_V41.md`
- Current draft target: `BITCODE_SPEC_V42.md`.
-- Current working gate: V42 Gate 2 Depositing Shortest Path And Compensation Visibility.
-- Next queued gate after V42 Gate 2: V42 Gate 3 Reading Shortest Path State Machine.
+- Current working gate: V42 Gate 3 Reading Shortest Path State Machine.
+- Next queued gate after V42 Gate 3: V42 Gate 4 ReadNeed Review And Resynthesis Product Closure.
- Latest closed version: V41 Prompt And PromptPart Excellence, which promoted PromptPart and Prompt inventory, registry interpolation contracts, Reading prompt baselines, ReadNeedComprehensionSynthesis prompt hardening, ReadFitsFindingSynthesis prompt hardening, Conversation/tool/interface prompt rewrite, prompt benchmark telemetry, and V41 promotion readiness.
- Recent V42 opening anchor: reliable MVP experience opens over promoted V41 with V42 SPEC, DELTA, NOTES, and PARITY files, `check:v42-gate1`, active V41 / draft V42 posture, and a nine-gate plan for shortest-path Depositing, five-step Reading, ReadNeed product closure, ReadFitsFinding preview and quote closure, settlement and repository delivery, AI-reading demonstration, local/staging rehearsal, and promotion readiness.
- V42 Gate 2 closure anchor: reliable MVP experience now owns source-safe Depositing compensation visibility through `DepositorySupplyCompensationPreview`, deposit route `depositoryEvidence.compensationPreview`, deterministic `.bitcode/v42-depositing-shortest-path.json`, route/API readiness checks, source validation, Depository search/vector/storage projection, source-to-shares compensation readback keys, Terminal compensation roots, focused package/protocol tests, workflow wiring, and `check:v42-gate2`.
+- V42 Gate 3 closure anchor: reliable MVP experience now owns the five-step Reading shortest path state machine through `TerminalEnterpriseReadingUxState`, `TerminalEnterpriseReadingRouteState`, recoverable transaction ids, `readingStage` route hydration, retry/restart posture, source-safe failure repair actions, accepted-Need blockers, source-safe preview blockers, rich Reading pipeline telemetry readback, deterministic `.bitcode/v42-reading-shortest-path-state-machine.json`, focused route/component/protocol tests, workflow wiring, and `check:v42-gate3`.
- Recent V41 closure anchor: V41 canonical promotion updated `BITCODE_SPEC.txt` to `V41`, generated `BITCODE_SPEC_V41_PROVEN.md`, preserved active V41 / draft V42 runtime posture, and closed prompt-program excellence canon.
- Recent V40 closure anchor: V40 canonical promotion updated `BITCODE_SPEC.txt` to `V40`, generated `BITCODE_SPEC_V40_PROVEN.md`, preserved active V40 / draft V41 runtime posture, and closed exhaustive commercial application testing canon.
- Recent V39 closure anchor: V39 canonical promotion updated `BITCODE_SPEC.txt` to `V39`, generated `BITCODE_SPEC_V39_PROVEN.md`, preserved active V39 / draft V40 runtime posture, and closed commercial Reading readiness canon.
@@ -160,7 +161,7 @@ They are referenced here for specification history only; active implementation w
| V40 | `BITCODE_SPEC_V40.md` | promoted historical Bitcode canon | Exhaustive commercial application testing depth after V39: rich browser E2E for all website interactions and state possibilities, visual/screenshot comparison coverage, API and integration suites for pipelines, conversations, routes, ledger/database/storage synchronization, unit coverage for packages, primitives, isolated implementations, real commercial implementations, local/staging rehearsal automation, prompt benchmark smoke, and promotion readiness. |
| V41 | `BITCODE_SPEC_V41.md` | active canon | Prompt and PromptPart excellence, treating prompts as programs: audit every raw PromptPart and composed Prompt, run and harden benchmarks, repartition prompts into meaningfully benchmarkable semantic parts, retitle and rewrite PromptParts/Prompts where optimal, catalogue registry bindings, interpolation contracts, benchmark fixtures, benchmark outputs, inference callsites, and parsed return types, and elevate all Reading and Conversation inference points after V38 inference scaffolding and V40 testing depth make that work measurable. The primary surface is Reading, especially `ReadNeedComprehensionSynthesis` and `ReadFitsFindingSynthesis`; conversations and other inference prompts follow with the same benchmarkable catalogue discipline. |
| V42 | `BITCODE_SPEC_V42.md` | active draft target | Reliable MVP experience after V41 prompt hardening: shortest-path Depositing for any source material with Depository admission proof and later BTC compensation when deposits contribute to synthesized AssetPacks; shortest-path Reading for Read Request submission, synthesized Need review/resynthesis, Finding Fits, source-safe AssetPack measurement/preview review, BTD/BTC purchase and settlement, and repository delivery; and an AI-reading dominant demonstration proving an AssetPack can improve an AI system's training, prompt/context, or evaluation performance beyond public-data-only baselines using proprietary or otherwise non-public deposit and read materials. |
-| V43+ | future specification family | planned future | Agentic enterprise deposit-side AssetPack option synthesis after the MVP paths are reliable: repository-installed Bitcode Agents compare a connected enterprise codebase, the Bitcode Depository, and Reading activity to propose deposit AssetPack options for review; filter out critical IP; estimate positive ROI against development cost and likely demand; let enterprises approve/reject options for Depository admission; split `/terminal` into `/read` and `/deposit`; and rename `/exchange` to `/packs` throughout product routes, code naming, docs, and operator vocabulary. `/packs` becomes the searchable master-detail activity surface for all pack activity, while `/deposit` and `/read` become the short core paths into and out of the Depository. |
+| V43+ | future specification family | planned future | Agentic enterprise deposit-side AssetPack option synthesis and broad UX cleanup after the MVP paths are reliable: repository-installed Bitcode Agents compare a connected enterprise codebase, the Bitcode Depository, and Reading activity to propose deposit AssetPack options for review; filter out critical IP; estimate positive ROI against development cost and likely demand; let enterprises approve/reject options for Depository admission; split `/terminal` into `/read` and `/deposit`; and rename `/exchange` to `/packs` throughout product routes, code naming, docs, component prefixes, tests, and operator vocabulary. `/packs` becomes the searchable master-detail activity surface for all pack activity, with column sort/filter/search over measurements, synthesized AssetPack titles and descriptions, values, activity/transaction type, settlement posture, compensation, proof roots, and repair state. `/deposit` and `/read` become the short core paths into and out of the Depository. Outside public docs, product UX should be self-explanatory through route structure, concise labels, progressive detail, and rich reusable themed components rather than self-referential instructional copy. |
## Current Planning Spine
diff --git a/package.json b/package.json
index a66382ab..e2a90f91 100644
--- a/package.json
+++ b/package.json
@@ -307,6 +307,9 @@
"generate:v42-depositing-shortest-path": "node scripts/generate-v42-depositing-shortest-path.mjs",
"check:v42-depositing-shortest-path": "node scripts/generate-v42-depositing-shortest-path.mjs --check",
"check:v42-gate2": "node scripts/check-v42-gate2-depositing-shortest-path.mjs",
+ "generate:v42-reading-shortest-path-state-machine": "node scripts/generate-v42-reading-shortest-path-state-machine.mjs",
+ "check:v42-reading-shortest-path-state-machine": "node scripts/generate-v42-reading-shortest-path-state-machine.mjs --check",
+ "check:v42-gate3": "node scripts/check-v42-gate3-reading-shortest-path-state-machine.mjs",
"generate:v38-inference-surface-inventory": "node scripts/generate-v38-inference-surface-inventory.mjs",
"check:v38-inference-surface-inventory": "node scripts/generate-v38-inference-surface-inventory.mjs --check",
"check:v38-gate2": "node scripts/check-v38-gate2-inference-surface-inventory.mjs",
diff --git a/packages/protocol/README.md b/packages/protocol/README.md
index fb299c5e..69f9b4ae 100644
--- a/packages/protocol/README.md
+++ b/packages/protocol/README.md
@@ -192,6 +192,15 @@ It proves deposit route readiness, Depository search/vector/storage projection,
source-safe compensation preview roots, source-to-shares ledger readback keys,
Terminal compensation visibility, and the pre-mint/no-pre-settlement-source
boundary.
+V42 Gate 3 adds the V42 Reading shortest path state machine,
+`V42ReadingShortestPathStateMachine`, through
+`packages/protocol/src/canonical/v42-reading-shortest-path-state-machine.js`,
+`packages/protocol/test/v42-reading-shortest-path-state-machine.test.js`,
+`.bitcode/v42-reading-shortest-path-state-machine.json`, and
+`check:v42-gate3`. It proves the five-step Reading path, transaction/stage
+route persistence, accepted-Need gating, restart/retry/failure repair,
+low-detail proof-on-expand UI posture, rich Reading pipeline telemetry
+readback, activity/workbench readback, and source-safe disclosure boundaries.
V40 Gate 2 adds `V40TestInventoryCoverageMatrix` through
`packages/protocol/src/canonical/v40-test-inventory-coverage-matrix.js`,
`packages/protocol/test/v40-test-inventory-coverage-matrix.test.js`,
diff --git a/packages/protocol/src/canonical/v42-depositing-shortest-path.js b/packages/protocol/src/canonical/v42-depositing-shortest-path.js
index 181bc14b..46612b8d 100644
--- a/packages/protocol/src/canonical/v42-depositing-shortest-path.js
+++ b/packages/protocol/src/canonical/v42-depositing-shortest-path.js
@@ -217,7 +217,11 @@ function buildPredicateResults(repoRoot) {
predicateResult('v42-delta-gate2-implemented', SOURCE_ROOTS.v42Delta, delta.includes('Gate 2') && delta.includes('Depository admission proof')),
predicateResult('v42-notes-gate2-rehearsal', SOURCE_ROOTS.v42Notes, notes.includes('Gate 2') && notes.includes('staging-testnet')),
predicateResult('v42-parity-gate2-closed', SOURCE_ROOTS.v42Parity, parity.includes('Depositing shortest path') && parity.includes('implemented')),
- predicateResult('roadmap-current-gate-advanced', SOURCE_ROOTS.roadmap, roadmap.includes('Current working gate: V42 Gate 2') && roadmap.includes('V42 Gate 2 closure anchor')),
+ predicateResult(
+ 'roadmap-records-gate2-closure',
+ SOURCE_ROOTS.roadmap,
+ roadmap.includes('Current working gate: V42 Gate') && roadmap.includes('V42 Gate 2 closure anchor'),
+ ),
];
}
diff --git a/packages/protocol/src/canonical/v42-reading-shortest-path-state-machine.js b/packages/protocol/src/canonical/v42-reading-shortest-path-state-machine.js
new file mode 100644
index 00000000..f094c540
--- /dev/null
+++ b/packages/protocol/src/canonical/v42-reading-shortest-path-state-machine.js
@@ -0,0 +1,324 @@
+// @ts-check
+
+import crypto from 'node:crypto';
+import { existsSync, readFileSync } from 'node:fs';
+import path from 'node:path';
+import { fileURLToPath } from 'node:url';
+
+const __filename = fileURLToPath(import.meta.url);
+const __dirname = path.dirname(__filename);
+const DEFAULT_REPO_ROOT = path.resolve(__dirname, '..', '..', '..', '..');
+
+export const V42_READING_SHORTEST_PATH_STATE_MACHINE_ARTIFACT_PATH =
+ '.bitcode/v42-reading-shortest-path-state-machine.json';
+export const V42_READING_SHORTEST_PATH_STATE_MACHINE_SCHEMA_ID =
+ 'bitcode.v42.readingShortestPathStateMachine.v1';
+export const V42_READING_SHORTEST_PATH_SCHEMA_ID =
+ V42_READING_SHORTEST_PATH_STATE_MACHINE_SCHEMA_ID;
+export const V42_READING_SHORTEST_PATH_STATE_MACHINE_VERSION = 'V42';
+export const V42_READING_SHORTEST_PATH_STATE_MACHINE_CURRENT_TARGET = 'V41';
+export const V42_READING_SHORTEST_PATH_STATE_MACHINE_SOURCE_SAFETY_VERDICT =
+ 'source-safe-reading-shortest-path-state-machine-metadata';
+
+export const V42_READING_SHORTEST_PATH_STEP_IDS = Object.freeze([
+ 'request-read',
+ 'review-synthesized-need',
+ 'request-fit',
+ 'review-synthesized-asset-pack',
+ 'buy-asset-pack-settle',
+]);
+
+export const V42_READING_SHORTEST_PATH_ROW_IDS = Object.freeze([
+ 'state:five-step-shortest-path',
+ 'route:transaction-stage-persistence',
+ 'transition:accepted-need-before-finding-fits',
+ 'retry:restart-and-failure-repair',
+ 'ui:low-detail-proof-on-expand',
+ 'stream:rich-reading-pipeline-telemetry',
+ 'activity:history-and-workbench-readback',
+ 'tests:route-state-contracts',
+ 'spec:v42-gate3-closure',
+]);
+
+const FORBIDDEN_PAYLOAD_CLASSES = Object.freeze([
+ 'protected-source-payloads',
+ 'raw-protected-prompts',
+ 'raw-provider-responses',
+ 'unpaid-assetpack-source',
+ 'wallet-private-material',
+ 'settlement-private-payloads',
+ 'ledger-write-authority',
+ 'secret-values',
+]);
+
+const SOURCE_ROOTS = Object.freeze({
+ terminalUxState: 'uapi/app/terminal/terminal-enterprise-reading-ux-state.ts',
+ terminalWorkbench: 'uapi/app/terminal/TerminalDepositReadWorkbench.tsx',
+ terminalPageClient: 'uapi/app/terminal/TerminalPageClient.tsx',
+ terminalWorkbenchContract: 'uapi/app/terminal/terminal-deposit-read-workbench.ts',
+ terminalRouteQuery: 'uapi/app/terminal/terminal-transaction-query.ts',
+ terminalActivityHistory: 'uapi/app/terminal/terminal-activity-history.ts',
+ terminalHarnessClient: 'uapi/app/terminal/terminal-pipeline-harness-client.ts',
+ conversationHandoff: 'uapi/app/conversations/conversation-terminal-handoff.ts',
+ uxStateTest: 'uapi/tests/terminalEnterpriseReadingUxState.test.ts',
+ workbenchTest: 'uapi/tests/terminalDepositReadWorkbench.test.ts',
+ handoffTest: 'uapi/tests/conversationTerminalHandoff.test.tsx',
+ queryTest: 'uapi/tests/terminalTransactionQuery.test.ts',
+ streamHeaderTest: 'uapi/tests/pipelineExecutionLogHeader.test.tsx',
+ gateWorkflow: '.github/workflows/bitcode-gate-quality.yml',
+ v42Spec: 'BITCODE_SPEC_V42.md',
+ v42Delta: 'BITCODE_SPEC_V42_DELTA.md',
+ v42Notes: 'BITCODE_SPEC_V42_NOTES.md',
+ v42Parity: 'BITCODE_SPEC_V42_PARITY_MATRIX.md',
+ roadmap: 'SPECIFICATIONS_ROADMAP.md',
+ rootReadme: 'README.md',
+ terminalReadme: 'uapi/app/terminal/README.md',
+ protocolReadme: 'packages/protocol/README.md',
+});
+
+function digest(value) {
+ return crypto.createHash('sha256').update(value).digest('hex').slice(0, 24);
+}
+
+function rowRoot(id) {
+ return `v42-reading-shortest-path-state-machine-row:${digest(id)}`;
+}
+
+function readSource(repoRoot, sourcePath) {
+ const absolutePath = path.join(repoRoot, sourcePath);
+ return existsSync(absolutePath) ? readFileSync(absolutePath, 'utf8') : '';
+}
+
+function predicateResult(id, sourcePath, passed) {
+ return { id, sourcePath, passed: Boolean(passed) };
+}
+
+function row(input) {
+ return {
+ ...input,
+ rowRoot: rowRoot(input.rowId),
+ sourceSafetyClass: 'source_safe_reading_shortest_path_state_machine_metadata',
+ sourceSafeMetadataOnly: true,
+ lowDetailDefault: true,
+ expandableSourceSafeDetail: true,
+ protectedSourceVisible: false,
+ rawProtectedPromptVisible: false,
+ rawProviderResponseVisible: false,
+ unpaidAssetPackSourceVisible: false,
+ walletPrivateMaterialVisible: false,
+ settlementPrivatePayloadVisible: false,
+ ledgerAuthorityClaimed: false,
+ forbiddenPayloadClasses: [...FORBIDDEN_PAYLOAD_CLASSES],
+ };
+}
+
+export const V42_READING_SHORTEST_PATH_ROWS = Object.freeze([
+ row({
+ rowId: 'state:five-step-shortest-path',
+ purpose:
+ 'Preserve exactly five enterprise Reading steps from Read Request through Need review, Finding Fits, AssetPack preview, and settlement delivery.',
+ sourceRoots: [SOURCE_ROOTS.terminalUxState, SOURCE_ROOTS.terminalWorkbench],
+ emittedTypes: ['TerminalEnterpriseReadingUxState', 'TerminalEnterpriseReadingStepView'],
+ requiredEvidence: V42_READING_SHORTEST_PATH_STEP_IDS,
+ }),
+ row({
+ rowId: 'route:transaction-stage-persistence',
+ purpose:
+ 'Bind Reading state to recoverable transaction ids and readingStage route state so refresh, restart, and route handoff preserve the active stage.',
+ sourceRoots: [
+ SOURCE_ROOTS.terminalUxState,
+ SOURCE_ROOTS.terminalRouteQuery,
+ SOURCE_ROOTS.terminalPageClient,
+ SOURCE_ROOTS.terminalWorkbench,
+ ],
+ emittedTypes: ['TerminalEnterpriseReadingRouteState', 'TerminalConversationHandoffContext.readingStage'],
+ requiredEvidence: ['transactionIdRequiredForRecovery', 'readingStageQueryParam', 'activeStageHydratedFromRoute'],
+ }),
+ row({
+ rowId: 'transition:accepted-need-before-finding-fits',
+ purpose:
+ 'Make accepted Need the hard transition before Finding Fits, preview, settlement, or delivery can proceed.',
+ sourceRoots: [SOURCE_ROOTS.terminalUxState, SOURCE_ROOTS.terminalWorkbench, SOURCE_ROOTS.conversationHandoff],
+ emittedTypes: ['acceptedNeedRequiredBeforeFindingFits', 'TerminalReadNeedState'],
+ requiredEvidence: ['accepted Need required', 'ReadNeedComprehensionSynthesis', 'ReadFitsFindingSynthesis'],
+ }),
+ row({
+ rowId: 'retry:restart-and-failure-repair',
+ purpose:
+ 'Represent retry, restart, and failure repair posture as source-safe state metadata without exposing protected source, prompts, provider responses, wallet material, or settlement payloads.',
+ sourceRoots: [SOURCE_ROOTS.terminalUxState, SOURCE_ROOTS.uxStateTest, SOURCE_ROOTS.terminalWorkbench],
+ emittedTypes: ['TerminalEnterpriseReadingFailureKind', 'TerminalEnterpriseReadingRouteState.failureRepairActions'],
+ requiredEvidence: ['retryPreservesNeedLineage', 'restartRestoresActiveStage', 'failureRepairActions'],
+ }),
+ row({
+ rowId: 'ui:low-detail-proof-on-expand',
+ purpose:
+ 'Keep the default Reading view guided and low-detail while details expand to source-safe proof roots, measurements, blockers, and visible field ids.',
+ sourceRoots: [SOURCE_ROOTS.terminalUxState, SOURCE_ROOTS.terminalWorkbench, SOURCE_ROOTS.terminalReadme],
+ emittedTypes: ['TerminalEnterpriseReadingUxState.disclosure'],
+ requiredEvidence: ['lowDetailDefault', 'expandableSourceSafeDetail', 'Source-safe detail'],
+ }),
+ row({
+ rowId: 'stream:rich-reading-pipeline-telemetry',
+ purpose:
+ 'Keep Reading pipeline progress inspectable through rich execution stream rows for phase, PTRR step, ThricifiedGeneration, tool, prompt-template id, output schema, and parsed-result posture.',
+ sourceRoots: [SOURCE_ROOTS.terminalHarnessClient, SOURCE_ROOTS.streamHeaderTest, SOURCE_ROOTS.terminalWorkbench],
+ emittedTypes: ['TerminalReadFitsFindingSynthesisHarnessEvent', 'ExecutionLogItem'],
+ requiredEvidence: ['pipelinePhaseId', 'ptrrStepId', 'thricifiedGenerationId', 'promptTemplateId', 'outputSchema'],
+ }),
+ row({
+ rowId: 'activity:history-and-workbench-readback',
+ purpose:
+ 'Project Reading state through activity history and workbench readback so transaction detail, proof roots, and compensation/settlement posture remain recoverable.',
+ sourceRoots: [SOURCE_ROOTS.terminalActivityHistory, SOURCE_ROOTS.terminalWorkbench, SOURCE_ROOTS.terminalWorkbenchContract],
+ emittedTypes: ['WorkspaceRun', 'TerminalDepositReadWorkbench'],
+ requiredEvidence: ['assetPackCompletion', 'TerminalDepositedSourceRevision', 'sourceRevision'],
+ }),
+ row({
+ rowId: 'tests:route-state-contracts',
+ purpose:
+ 'Prove the state machine through route-state tests, component state tests, Conversation handoff tests, workbench tests, and stream-header tests.',
+ sourceRoots: [
+ SOURCE_ROOTS.uxStateTest,
+ SOURCE_ROOTS.workbenchTest,
+ SOURCE_ROOTS.handoffTest,
+ SOURCE_ROOTS.queryTest,
+ SOURCE_ROOTS.streamHeaderTest,
+ SOURCE_ROOTS.gateWorkflow,
+ ],
+ emittedTypes: ['V42ReadingShortestPathStateMachineReport'],
+ requiredEvidence: ['terminal-enterprise-reading-ux-state', 'readingStage=request-fit', 'Browser proof Terminal cockpit'],
+ }),
+ row({
+ rowId: 'spec:v42-gate3-closure',
+ purpose:
+ 'Bind V42 Gate 3 to SPEC, DELTA, NOTES, PARITY, roadmap, README, workflow, generated artifact, and checker closure.',
+ sourceRoots: [
+ SOURCE_ROOTS.v42Spec,
+ SOURCE_ROOTS.v42Delta,
+ SOURCE_ROOTS.v42Notes,
+ SOURCE_ROOTS.v42Parity,
+ SOURCE_ROOTS.roadmap,
+ SOURCE_ROOTS.rootReadme,
+ SOURCE_ROOTS.protocolReadme,
+ ],
+ emittedTypes: ['V42ReadingShortestPathStateMachineReport'],
+ requiredEvidence: ['V42 Gate 3', 'reading shortest path state machine', 'check:v42-gate3'],
+ }),
+]);
+
+function buildPredicateResults(repoRoot) {
+ const uxState = readSource(repoRoot, SOURCE_ROOTS.terminalUxState);
+ const pageClient = readSource(repoRoot, SOURCE_ROOTS.terminalPageClient);
+ const workbench = readSource(repoRoot, SOURCE_ROOTS.terminalWorkbench);
+ const workbenchContract = readSource(repoRoot, SOURCE_ROOTS.terminalWorkbenchContract);
+ const query = readSource(repoRoot, SOURCE_ROOTS.terminalRouteQuery);
+ const activity = readSource(repoRoot, SOURCE_ROOTS.terminalActivityHistory);
+ const harness = readSource(repoRoot, SOURCE_ROOTS.terminalHarnessClient);
+ const handoff = readSource(repoRoot, SOURCE_ROOTS.conversationHandoff);
+ const uxStateTest = readSource(repoRoot, SOURCE_ROOTS.uxStateTest);
+ const workbenchTest = readSource(repoRoot, SOURCE_ROOTS.workbenchTest);
+ const handoffTest = readSource(repoRoot, SOURCE_ROOTS.handoffTest);
+ const queryTest = readSource(repoRoot, SOURCE_ROOTS.queryTest);
+ const streamHeaderTest = readSource(repoRoot, SOURCE_ROOTS.streamHeaderTest);
+ const gateWorkflow = readSource(repoRoot, SOURCE_ROOTS.gateWorkflow);
+ const spec = readSource(repoRoot, SOURCE_ROOTS.v42Spec);
+ const delta = readSource(repoRoot, SOURCE_ROOTS.v42Delta);
+ const notes = readSource(repoRoot, SOURCE_ROOTS.v42Notes);
+ const parity = readSource(repoRoot, SOURCE_ROOTS.v42Parity);
+ const roadmap = readSource(repoRoot, SOURCE_ROOTS.roadmap);
+ const rootReadme = readSource(repoRoot, SOURCE_ROOTS.rootReadme);
+ const terminalReadme = readSource(repoRoot, SOURCE_ROOTS.terminalReadme);
+ const protocolReadme = readSource(repoRoot, SOURCE_ROOTS.protocolReadme);
+
+ return [
+ predicateResult('ux-state-keeps-five-step-path', SOURCE_ROOTS.terminalUxState, V42_READING_SHORTEST_PATH_STEP_IDS.every((id) => uxState.includes(id)) && uxState.includes('stageCount: 5')),
+ predicateResult('ux-state-defines-route-state', SOURCE_ROOTS.terminalUxState, uxState.includes('TerminalEnterpriseReadingRouteState') && uxState.includes('transactionIdRequiredForRecovery') && uxState.includes("readingStageQueryParam: 'readingStage'")),
+ predicateResult('ux-state-defines-retry-failure-source-safety', SOURCE_ROOTS.terminalUxState, uxState.includes('TerminalEnterpriseReadingFailureKind') && uxState.includes('retryPreservesNeedLineage') && uxState.includes('failureRepairActions') && uxState.includes('failureStateSourceSafe')),
+ predicateResult('ux-state-forbids-protected-payloads', SOURCE_ROOTS.terminalUxState, uxState.includes('protected_source_payload') && uxState.includes('raw_protected_prompt') && uxState.includes('raw_provider_response') && uxState.includes('unpaid_assetpack_source') && uxState.includes('wallet_private_material') && uxState.includes('settlement_private_payload')),
+ predicateResult('terminal-page-passes-reading-stage', SOURCE_ROOTS.terminalPageClient, pageClient.includes('routeReadingStage={conversationHandoffContext.readingStage}')),
+ predicateResult('workbench-projects-route-state', SOURCE_ROOTS.terminalWorkbench, workbench.includes('transactionId: recordedAdmittedReadActivityId') && workbench.includes('routeReadingStage') && workbench.includes('data-reading-transaction-present') && workbench.includes('data-reading-failure-kind')),
+ predicateResult('workbench-keeps-low-detail-expandable-cards', SOURCE_ROOTS.terminalWorkbench, workbench.includes('terminal-enterprise-reading-step-${stage.id}') && workbench.includes('data-reading-step-state') && workbench.includes('Source-safe detail')),
+ predicateResult('workbench-contract-reexports-stage-ids', SOURCE_ROOTS.terminalWorkbenchContract, workbenchContract.includes('TERMINAL_ENTERPRISE_READING_STEPS') && workbenchContract.includes('TerminalEnterpriseReadingStepId')),
+ predicateResult('terminal-query-reads-reading-stage', SOURCE_ROOTS.terminalRouteQuery, query.includes('readingStage') && query.includes('TERMINAL_ENTERPRISE_READING_STAGE_VALUES') && query.includes('readTerminalTransactionId')),
+ predicateResult('activity-history-keeps-reading-readback', SOURCE_ROOTS.terminalActivityHistory, activity.includes('assetPackCompletion') && activity.includes('sourceRevision')),
+ predicateResult('harness-projects-rich-reading-telemetry', SOURCE_ROOTS.terminalHarnessClient, harness.includes('ReadFitsFindingSynthesis') && harness.includes('ptrrStepId') && harness.includes('thricifiedGenerationId') && harness.includes('promptTemplateId') && harness.includes('outputSchema')),
+ predicateResult('conversation-handoff-preserves-reading-stage', SOURCE_ROOTS.conversationHandoff, handoff.includes('inferConversationTerminalReadingStage') && handoff.includes('terminalEnterpriseReadingStage') && handoff.includes("params.set('readingStage'")),
+ predicateResult('ux-state-tests-cover-route-retry-failure', SOURCE_ROOTS.uxStateTest, uxStateTest.includes('hydrates later route stages') && uxStateTest.includes('repair-settlement-readback')),
+ predicateResult('workbench-tests-cover-five-stage-labels', SOURCE_ROOTS.workbenchTest, workbenchTest.includes('3. Request Finding Fits') && workbenchTest.includes('buy-asset-pack-settle')),
+ predicateResult('handoff-tests-cover-reading-stage-route', SOURCE_ROOTS.handoffTest, handoffTest.includes('readingStage=request-fit') && handoffTest.includes('terminalEnterpriseReadingStage')),
+ predicateResult('query-tests-cover-reading-stage-route', SOURCE_ROOTS.queryTest, queryTest.includes('reads source-safe enterprise Reading stage') && queryTest.includes('request-fit')),
+ predicateResult('stream-tests-cover-rich-header', SOURCE_ROOTS.streamHeaderTest, streamHeaderTest.includes('ReadFitsFindingSynthesis') && streamHeaderTest.includes('outputSchema') && streamHeaderTest.includes('prompt_template_id_only')),
+ predicateResult('workflow-wires-gate3-check', SOURCE_ROOTS.gateWorkflow, gateWorkflow.includes('check-v42-gate3-reading-shortest-path-state-machine.mjs')),
+ predicateResult('v42-spec-gate3-expanded', SOURCE_ROOTS.v42Spec, spec.includes('V42 Gate 3') && spec.includes('reading shortest path state machine')),
+ predicateResult('v42-delta-gate3-expanded', SOURCE_ROOTS.v42Delta, delta.includes('Gate 3') && delta.includes('route-owned Reading state')),
+ predicateResult('v42-notes-gate3-expanded', SOURCE_ROOTS.v42Notes, notes.includes('Gate 3') && notes.includes('transaction id')),
+ predicateResult('v42-parity-gate3-implemented', SOURCE_ROOTS.v42Parity, parity.includes('Reading state machine') && parity.includes('implemented')),
+ predicateResult(
+ 'roadmap-records-gate3-closure',
+ SOURCE_ROOTS.roadmap,
+ roadmap.includes('Current working gate: V42 Gate') && roadmap.includes('V42 Gate 3 closure anchor'),
+ ),
+ predicateResult('readmes-document-gate3', SOURCE_ROOTS.rootReadme, rootReadme.includes('V42 Gate 3') && terminalReadme.includes('TerminalEnterpriseReadingUxState') && protocolReadme.includes('V42 Reading shortest path')),
+ ];
+}
+
+export function buildV42ReadingShortestPathStateMachine(options = {}) {
+ const repoRoot = options.repoRoot || DEFAULT_REPO_ROOT;
+ const predicateResults = buildPredicateResults(repoRoot);
+ const failedPredicateIds = predicateResults
+ .filter((predicate) => !predicate.passed)
+ .map((predicate) => predicate.id);
+ const rowRoots = V42_READING_SHORTEST_PATH_ROWS.map((item) => item.rowRoot);
+ const artifactRoot = `v42-reading-shortest-path-state-machine:${digest(JSON.stringify({
+ rowRoots,
+ failedPredicateIds,
+ }))}`;
+
+ return {
+ artifactId: 'v42-reading-shortest-path-state-machine',
+ schemaId: V42_READING_SHORTEST_PATH_STATE_MACHINE_SCHEMA_ID,
+ version: V42_READING_SHORTEST_PATH_STATE_MACHINE_VERSION,
+ currentTarget: V42_READING_SHORTEST_PATH_STATE_MACHINE_CURRENT_TARGET,
+ sourceSafetyVerdict: V42_READING_SHORTEST_PATH_STATE_MACHINE_SOURCE_SAFETY_VERDICT,
+ generatedAt: 'deterministic',
+ artifactRoot,
+ passed: failedPredicateIds.length === 0,
+ rows: V42_READING_SHORTEST_PATH_ROWS,
+ rowIds: [...V42_READING_SHORTEST_PATH_ROW_IDS],
+ stepIds: [...V42_READING_SHORTEST_PATH_STEP_IDS],
+ predicateResults,
+ coverage: {
+ rowCount: V42_READING_SHORTEST_PATH_ROWS.length,
+ stepCount: V42_READING_SHORTEST_PATH_STEP_IDS.length,
+ acceptedUserPath: [
+ 'request-read',
+ 'review-synthesized-need',
+ 'request-finding-fits',
+ 'review-source-safe-assetpack-preview',
+ 'buy-settle-and-deliver-assetpack',
+ ],
+ requiredPredicateCount: predicateResults.length,
+ passedPredicateCount: predicateResults.length - failedPredicateIds.length,
+ failedPredicateIds,
+ routePersistenceCovered: true,
+ transactionIdRecoveryCovered: true,
+ restartRetryFailureCovered: true,
+ acceptedNeedGateCovered: true,
+ streamLogIntegrationCovered: true,
+ componentRouteTestsCovered: true,
+ sourceSafeMetadataOnly: true,
+ lowDetailDefault: true,
+ expandableSourceSafeDetail: true,
+ protectedSourceVisible: false,
+ rawProtectedPromptVisible: false,
+ rawProviderResponseVisible: false,
+ unpaidAssetPackSourceVisible: false,
+ walletPrivateMaterialVisible: false,
+ settlementPrivatePayloadVisible: false,
+ ledgerAuthorityClaimed: false,
+ legacySourceRoots: Object.values(SOURCE_ROOTS).some((sourcePath) => sourcePath.includes('_legacy/')),
+ },
+ sourceRoots: SOURCE_ROOTS,
+ };
+}
diff --git a/packages/protocol/src/index.d.ts b/packages/protocol/src/index.d.ts
index d163ccbe..7bef5cb2 100644
--- a/packages/protocol/src/index.d.ts
+++ b/packages/protocol/src/index.d.ts
@@ -520,6 +520,15 @@ export const V42_DEPOSITING_SHORTEST_PATH_SOURCE_SAFETY_VERDICT: string;
export const V42_DEPOSITING_SHORTEST_PATH_ROW_IDS: readonly string[];
export const V42_DEPOSITING_SHORTEST_PATH_ROWS: readonly Record[];
export function buildV42DepositingShortestPath(input?: Record): BitcodeProtocolReport;
+export const V42_READING_SHORTEST_PATH_STATE_MACHINE_ARTIFACT_PATH: string;
+export const V42_READING_SHORTEST_PATH_STATE_MACHINE_CURRENT_TARGET: string;
+export const V42_READING_SHORTEST_PATH_SCHEMA_ID: string;
+export const V42_READING_SHORTEST_PATH_STATE_MACHINE_VERSION: string;
+export const V42_READING_SHORTEST_PATH_STATE_MACHINE_SOURCE_SAFETY_VERDICT: string;
+export const V42_READING_SHORTEST_PATH_STEP_IDS: readonly string[];
+export const V42_READING_SHORTEST_PATH_ROW_IDS: readonly string[];
+export const V42_READING_SHORTEST_PATH_ROWS: readonly Record[];
+export function buildV42ReadingShortestPathStateMachine(input?: Record): BitcodeProtocolReport;
export const EXCHANGE_INTENT_ORDER_CONTRACTS_ARTIFACT_PATH: string;
export const EXCHANGE_INTENT_ORDER_CONTRACTS_CURRENT_TARGET: string;
export const EXCHANGE_INTENT_ORDER_CONTRACTS_SCHEMA_ID: string;
diff --git a/packages/protocol/src/index.js b/packages/protocol/src/index.js
index 307cc3f8..7f07b1c9 100644
--- a/packages/protocol/src/index.js
+++ b/packages/protocol/src/index.js
@@ -580,6 +580,17 @@ export {
V42_DEPOSITING_SHORTEST_PATH_VERSION,
buildV42DepositingShortestPath
} from './canonical/v42-depositing-shortest-path.js';
+export {
+ V42_READING_SHORTEST_PATH_ROWS,
+ V42_READING_SHORTEST_PATH_ROW_IDS,
+ V42_READING_SHORTEST_PATH_SCHEMA_ID,
+ V42_READING_SHORTEST_PATH_STATE_MACHINE_ARTIFACT_PATH,
+ V42_READING_SHORTEST_PATH_STATE_MACHINE_CURRENT_TARGET,
+ V42_READING_SHORTEST_PATH_STATE_MACHINE_SOURCE_SAFETY_VERDICT,
+ V42_READING_SHORTEST_PATH_STATE_MACHINE_VERSION,
+ V42_READING_SHORTEST_PATH_STEP_IDS,
+ buildV42ReadingShortestPathStateMachine
+} from './canonical/v42-reading-shortest-path-state-machine.js';
export {
EXCHANGE_INTENT_ACTION_KINDS,
EXCHANGE_INTENT_ORDER_CONTRACTS_ARTIFACT_PATH,
diff --git a/packages/protocol/test/v42-reading-shortest-path-state-machine.test.js b/packages/protocol/test/v42-reading-shortest-path-state-machine.test.js
new file mode 100644
index 00000000..db12e040
--- /dev/null
+++ b/packages/protocol/test/v42-reading-shortest-path-state-machine.test.js
@@ -0,0 +1,77 @@
+import assert from 'node:assert/strict';
+import test from 'node:test';
+
+import {
+ V42_READING_SHORTEST_PATH_ROWS,
+ V42_READING_SHORTEST_PATH_ROW_IDS,
+ V42_READING_SHORTEST_PATH_SCHEMA_ID,
+ V42_READING_SHORTEST_PATH_STATE_MACHINE_ARTIFACT_PATH,
+ V42_READING_SHORTEST_PATH_STATE_MACHINE_SOURCE_SAFETY_VERDICT,
+ V42_READING_SHORTEST_PATH_STEP_IDS,
+ buildV42ReadingShortestPathStateMachine,
+} from '../src/canonical/v42-reading-shortest-path-state-machine.js';
+
+test('V42 Reading shortest path state machine binds five route-recoverable steps', () => {
+ const report = buildV42ReadingShortestPathStateMachine();
+
+ assert.equal(
+ V42_READING_SHORTEST_PATH_STATE_MACHINE_ARTIFACT_PATH,
+ '.bitcode/v42-reading-shortest-path-state-machine.json',
+ );
+ assert.equal(report.artifactId, 'v42-reading-shortest-path-state-machine');
+ assert.equal(report.schemaId, V42_READING_SHORTEST_PATH_SCHEMA_ID);
+ assert.equal(report.version, 'V42');
+ assert.equal(report.currentTarget, 'V41');
+ assert.equal(report.sourceSafetyVerdict, V42_READING_SHORTEST_PATH_STATE_MACHINE_SOURCE_SAFETY_VERDICT);
+ assert.equal(report.passed, true);
+ assert.deepEqual(report.rowIds, [...V42_READING_SHORTEST_PATH_ROW_IDS]);
+ assert.deepEqual(report.stepIds, [...V42_READING_SHORTEST_PATH_STEP_IDS]);
+ assert.equal(report.rows.length, V42_READING_SHORTEST_PATH_ROWS.length);
+ assert.equal(report.coverage.rowCount, 9);
+ assert.equal(report.coverage.stepCount, 5);
+ assert.deepEqual(report.coverage.acceptedUserPath, [
+ 'request-read',
+ 'review-synthesized-need',
+ 'request-finding-fits',
+ 'review-source-safe-assetpack-preview',
+ 'buy-settle-and-deliver-assetpack',
+ ]);
+ assert.equal(report.coverage.routePersistenceCovered, true);
+ assert.equal(report.coverage.transactionIdRecoveryCovered, true);
+ assert.equal(report.coverage.restartRetryFailureCovered, true);
+ assert.equal(report.coverage.acceptedNeedGateCovered, true);
+ assert.equal(report.coverage.streamLogIntegrationCovered, true);
+ assert.equal(report.coverage.componentRouteTestsCovered, true);
+ assert.equal(report.coverage.sourceSafeMetadataOnly, true);
+ assert.equal(report.coverage.lowDetailDefault, true);
+ assert.equal(report.coverage.expandableSourceSafeDetail, true);
+ assert.equal(report.coverage.protectedSourceVisible, false);
+ assert.equal(report.coverage.rawProtectedPromptVisible, false);
+ assert.equal(report.coverage.rawProviderResponseVisible, false);
+ assert.equal(report.coverage.unpaidAssetPackSourceVisible, false);
+ assert.equal(report.coverage.walletPrivateMaterialVisible, false);
+ assert.equal(report.coverage.settlementPrivatePayloadVisible, false);
+ assert.equal(report.coverage.ledgerAuthorityClaimed, false);
+ assert.equal(report.coverage.legacySourceRoots, false);
+ assert.deepEqual(report.coverage.failedPredicateIds, []);
+ assert.ok(report.artifactRoot.startsWith('v42-reading-shortest-path-state-machine:'));
+});
+
+test('V42 Reading shortest path rows remain expandable source-safe metadata', () => {
+ for (const row of V42_READING_SHORTEST_PATH_ROWS) {
+ assert.ok(row.rowRoot.startsWith('v42-reading-shortest-path-state-machine-row:'));
+ assert.equal(row.sourceSafetyClass, 'source_safe_reading_shortest_path_state_machine_metadata');
+ assert.equal(row.sourceSafeMetadataOnly, true);
+ assert.equal(row.lowDetailDefault, true);
+ assert.equal(row.expandableSourceSafeDetail, true);
+ assert.equal(row.protectedSourceVisible, false);
+ assert.equal(row.rawProtectedPromptVisible, false);
+ assert.equal(row.rawProviderResponseVisible, false);
+ assert.equal(row.unpaidAssetPackSourceVisible, false);
+ assert.equal(row.walletPrivateMaterialVisible, false);
+ assert.equal(row.settlementPrivatePayloadVisible, false);
+ assert.equal(row.ledgerAuthorityClaimed, false);
+ assert.ok(row.forbiddenPayloadClasses.includes('protected-source-payloads'));
+ assert.ok(row.forbiddenPayloadClasses.includes('unpaid-assetpack-source'));
+ }
+});
diff --git a/scripts/check-v42-gate3-reading-shortest-path-state-machine.mjs b/scripts/check-v42-gate3-reading-shortest-path-state-machine.mjs
new file mode 100644
index 00000000..0376ffc5
--- /dev/null
+++ b/scripts/check-v42-gate3-reading-shortest-path-state-machine.mjs
@@ -0,0 +1,240 @@
+#!/usr/bin/env node
+
+import { execFileSync } from 'node:child_process';
+import { existsSync, readFileSync } from 'node:fs';
+import path from 'node:path';
+import { fileURLToPath } from 'node:url';
+
+const __filename = fileURLToPath(import.meta.url);
+const __dirname = path.dirname(__filename);
+const defaultRepoRoot = path.resolve(__dirname, '..');
+const ARTIFACT_PATH = '.bitcode/v42-reading-shortest-path-state-machine.json';
+
+const SECRET_MARKERS = [
+ `${['sk', 'proj'].join('-')}-`,
+ `${['sb', 'secret'].join('_')}__`,
+ ['service', 'role'].join('_'),
+ Buffer.from('{"alg":"HS256","typ":"JWT"}').toString('base64url').slice(0, 18),
+ ['OPENAI', 'API', 'KEY'].join('_'),
+ ['SUPABASE', 'SERVICE', 'ROLE'].join('_'),
+ ['VERCEL', 'TOKEN'].join('_'),
+ ['VERCEL', 'OIDC', 'TOKEN'].join('_'),
+ ['PRIVATE', 'KEY'].join('_'),
+];
+
+function read(root, relativePath) {
+ return readFileSync(path.join(root, relativePath), 'utf8');
+}
+
+function fileExists(root, relativePath) {
+ return existsSync(path.join(root, relativePath));
+}
+
+function git(root, args) {
+ return execFileSync('git', args, { cwd: root, encoding: 'utf8' }).trim();
+}
+
+function run(root, command, args) {
+ return execFileSync(command, args, {
+ cwd: root,
+ encoding: 'utf8',
+ stdio: ['ignore', 'pipe', 'pipe'],
+ }).trim();
+}
+
+function assertCheck(failures, condition, message) {
+ if (!condition) failures.push(message);
+}
+
+function parseArgs(argv) {
+ const args = {
+ skipBranchCheck: false,
+ skipUapiTests: false,
+ repoRoot: defaultRepoRoot,
+ };
+
+ for (let index = 0; index < argv.length; index += 1) {
+ const arg = argv[index];
+ if (arg === '--skip-branch-check') args.skipBranchCheck = true;
+ else if (arg === '--skip-uapi-tests') args.skipUapiTests = true;
+ else if (arg === '--repo-root') args.repoRoot = path.resolve(argv[++index]);
+ else if (arg === '--help' || arg === '-h') args.help = true;
+ else throw new Error(`Unknown argument ${arg}`);
+ }
+
+ return args;
+}
+
+function printHelp() {
+ process.stdout.write(
+ [
+ 'Usage: node scripts/check-v42-gate3-reading-shortest-path-state-machine.mjs [--skip-branch-check] [--skip-uapi-tests] [--repo-root ]',
+ '',
+ 'Checks V42 Gate 3 Reading shortest path state machine, route recovery, retry/failure posture, source-safe disclosure, workflow wiring, docs, tests, and generated artifact.',
+ ].join('\n'),
+ );
+ process.stdout.write('\n');
+}
+
+function main() {
+ const args = parseArgs(process.argv.slice(2));
+ if (args.help) {
+ printHelp();
+ return;
+ }
+
+ const root = args.repoRoot;
+ const failures = [];
+ const pointer = read(root, 'BITCODE_SPEC.txt').trim();
+
+ assertCheck(
+ failures,
+ pointer === 'V41',
+ `BITCODE_SPEC.txt must remain V41 during V42 gate work. Observed ${pointer || 'empty'}.`,
+ );
+
+ if (!args.skipBranchCheck) {
+ const branch = git(root, ['branch', '--show-current']);
+ assertCheck(
+ failures,
+ branch === 'version/v42' || /^v42\/gate-(?:3|[4-9]|10)-[a-z0-9][a-z0-9-]*$/u.test(branch),
+ `V42 Gate 3+ work must occur on version/v42 or v42/gate-3..10-* branches. Observed ${branch || 'detached HEAD'}.`,
+ );
+ }
+
+ const requiredFiles = [
+ ARTIFACT_PATH,
+ 'uapi/app/terminal/TerminalPageClient.tsx',
+ 'uapi/app/terminal/terminal-enterprise-reading-ux-state.ts',
+ 'uapi/app/terminal/TerminalDepositReadWorkbench.tsx',
+ 'uapi/app/terminal/terminal-deposit-read-workbench.ts',
+ 'uapi/app/terminal/terminal-pipeline-harness-client.ts',
+ 'uapi/app/conversations/conversation-terminal-handoff.ts',
+ 'uapi/app/terminal/terminal-transaction-query.ts',
+ 'uapi/app/terminal/terminal-activity-history.ts',
+ 'uapi/tests/terminalEnterpriseReadingUxState.test.ts',
+ 'uapi/tests/terminalDepositReadWorkbench.test.ts',
+ 'uapi/tests/conversationTerminalHandoff.test.tsx',
+ 'uapi/tests/terminalTransactionQuery.test.ts',
+ 'uapi/tests/terminalPipelineHarnessClient.test.ts',
+ 'uapi/tests/pipelineExecutionLogHeader.test.tsx',
+ 'packages/protocol/src/canonical/v42-reading-shortest-path-state-machine.js',
+ 'packages/protocol/test/v42-reading-shortest-path-state-machine.test.js',
+ 'scripts/generate-v42-reading-shortest-path-state-machine.mjs',
+ 'scripts/check-v42-gate3-reading-shortest-path-state-machine.mjs',
+ 'BITCODE_SPEC_V42.md',
+ 'BITCODE_SPEC_V42_DELTA.md',
+ 'BITCODE_SPEC_V42_NOTES.md',
+ 'BITCODE_SPEC_V42_PARITY_MATRIX.md',
+ 'SPECIFICATIONS_ROADMAP.md',
+ 'README.md',
+ 'uapi/app/terminal/README.md',
+ 'packages/protocol/README.md',
+ 'package.json',
+ '.github/workflows/bitcode-gate-quality.yml',
+ '.github/workflows/bitcode-canon-quality.yml',
+ ];
+
+ for (const relativePath of requiredFiles) {
+ assertCheck(failures, fileExists(root, relativePath), `Missing V42 Gate 3 file: ${relativePath}`);
+ }
+
+ if (failures.length === 0) {
+ try {
+ run(root, 'node', ['scripts/generate-v42-reading-shortest-path-state-machine.mjs', '--check']);
+ } catch (error) {
+ failures.push(`V42 Reading shortest path state machine artifact check failed: ${error.stderr || error.message}`);
+ }
+ }
+
+ if (failures.length === 0) {
+ try {
+ run(root, 'node', [
+ '--test',
+ '--test-force-exit',
+ 'packages/protocol/test/v42-reading-shortest-path-state-machine.test.js',
+ ]);
+ } catch (error) {
+ failures.push(`V42 Reading shortest path state machine protocol test failed: ${error.stderr || error.message}`);
+ }
+ }
+
+ if (failures.length === 0 && !args.skipUapiTests) {
+ try {
+ run(root, 'pnpm', [
+ '--dir',
+ 'uapi',
+ 'exec',
+ 'jest',
+ '--runTestsByPath',
+ 'tests/terminalEnterpriseReadingUxState.test.ts',
+ 'tests/terminalDepositReadWorkbench.test.ts',
+ 'tests/conversationTerminalHandoff.test.tsx',
+ 'tests/terminalTransactionQuery.test.ts',
+ 'tests/terminalPipelineHarnessClient.test.ts',
+ 'tests/pipelineExecutionLogHeader.test.tsx',
+ '--runInBand',
+ ]);
+ } catch (error) {
+ failures.push(`V42 Reading shortest path state machine uapi tests failed: ${error.stderr || error.message}`);
+ }
+ }
+
+ const serializedArtifact = fileExists(root, ARTIFACT_PATH) ? read(root, ARTIFACT_PATH) : '';
+ for (const marker of SECRET_MARKERS) {
+ assertCheck(failures, !serializedArtifact.includes(marker), `V42 Gate 3 artifact must not contain secret marker ${marker}.`);
+ }
+
+ const artifact = serializedArtifact ? JSON.parse(serializedArtifact) : null;
+ if (artifact) {
+ assertCheck(failures, artifact.artifactId === 'v42-reading-shortest-path-state-machine', 'Gate 3 artifactId must match.');
+ assertCheck(
+ failures,
+ artifact.schemaId === 'bitcode.v42.readingShortestPathStateMachine.v1',
+ 'Gate 3 schemaId must match.',
+ );
+ assertCheck(failures, artifact.version === 'V42' && artifact.currentTarget === 'V41', 'Gate 3 artifact must bind V42 over active V41.');
+ assertCheck(failures, artifact.passed === true, 'Gate 3 artifact must pass.');
+ assertCheck(
+ failures,
+ artifact.sourceSafetyVerdict === 'source-safe-reading-shortest-path-state-machine-metadata',
+ 'Gate 3 artifact must declare source-safe Reading state-machine metadata.',
+ );
+ assertCheck(failures, artifact.coverage.rowCount === 9, 'Gate 3 must cover nine Reading state-machine rows.');
+ assertCheck(failures, artifact.coverage.stepCount === 5, 'Gate 3 must cover five Reading steps.');
+ assertCheck(failures, artifact.coverage.routePersistenceCovered === true, 'Gate 3 must cover route persistence.');
+ assertCheck(failures, artifact.coverage.transactionIdRecoveryCovered === true, 'Gate 3 must cover transaction id recovery.');
+ assertCheck(failures, artifact.coverage.restartRetryFailureCovered === true, 'Gate 3 must cover restart, retry, and failure repair.');
+ assertCheck(failures, artifact.coverage.acceptedNeedGateCovered === true, 'Gate 3 must cover accepted-Need gating.');
+ assertCheck(failures, artifact.coverage.streamLogIntegrationCovered === true, 'Gate 3 must cover stream log integration.');
+ assertCheck(failures, artifact.coverage.componentRouteTestsCovered === true, 'Gate 3 must cover component and route tests.');
+ assertCheck(failures, artifact.coverage.sourceSafeMetadataOnly === true, 'Gate 3 must remain source-safe metadata only.');
+ assertCheck(failures, artifact.coverage.lowDetailDefault === true, 'Gate 3 must preserve low-detail defaults.');
+ assertCheck(failures, artifact.coverage.expandableSourceSafeDetail === true, 'Gate 3 must preserve expandable source-safe detail.');
+ assertCheck(failures, artifact.coverage.protectedSourceVisible === false, 'Gate 3 artifact must not expose protected source.');
+ assertCheck(failures, artifact.coverage.rawProtectedPromptVisible === false, 'Gate 3 artifact must not expose protected prompts.');
+ assertCheck(failures, artifact.coverage.rawProviderResponseVisible === false, 'Gate 3 artifact must not expose raw provider responses.');
+ assertCheck(failures, artifact.coverage.unpaidAssetPackSourceVisible === false, 'Gate 3 artifact must not expose unpaid AssetPack source.');
+ assertCheck(failures, artifact.coverage.walletPrivateMaterialVisible === false, 'Gate 3 artifact must not expose wallet private material.');
+ assertCheck(failures, artifact.coverage.ledgerAuthorityClaimed === false, 'Gate 3 artifact must not claim ledger authority.');
+ assertCheck(failures, artifact.coverage.legacySourceRoots === false, 'Gate 3 must not rely on legacy source roots.');
+ assertCheck(failures, Array.isArray(artifact.coverage.failedPredicateIds) && artifact.coverage.failedPredicateIds.length === 0, 'Gate 3 predicates must all pass.');
+ }
+
+ const spec = read(root, 'BITCODE_SPEC_V42.md');
+ const parity = read(root, 'BITCODE_SPEC_V42_PARITY_MATRIX.md');
+ const terminalReadme = read(root, 'uapi/app/terminal/README.md');
+ assertCheck(failures, spec.includes('V42 Gate 3') && spec.includes('reading shortest path state machine'), 'V42 spec must expand Gate 3 state machine.');
+ assertCheck(failures, parity.includes('Reading state machine') && parity.includes('implemented'), 'V42 parity matrix must mark Reading state machine implemented.');
+ assertCheck(failures, terminalReadme.includes('V42 Gate 3') && terminalReadme.includes('TerminalEnterpriseReadingRouteState'), 'Terminal README must document Gate 3 route state.');
+
+ if (failures.length > 0) {
+ process.stderr.write(`V42 Gate 3 Reading shortest path state machine check failed:\n- ${failures.join('\n- ')}\n`);
+ process.exitCode = 1;
+ return;
+ }
+
+ process.stdout.write(`V42 Gate 3 Reading shortest path state machine ok artifact=${artifact.artifactRoot}\n`);
+}
+
+main();
diff --git a/scripts/generate-v42-reading-shortest-path-state-machine.mjs b/scripts/generate-v42-reading-shortest-path-state-machine.mjs
new file mode 100644
index 00000000..615153ae
--- /dev/null
+++ b/scripts/generate-v42-reading-shortest-path-state-machine.mjs
@@ -0,0 +1,31 @@
+#!/usr/bin/env node
+
+import { readFileSync, writeFileSync } from 'node:fs';
+import path from 'node:path';
+import { fileURLToPath } from 'node:url';
+import {
+ V42_READING_SHORTEST_PATH_STATE_MACHINE_ARTIFACT_PATH,
+ buildV42ReadingShortestPathStateMachine,
+} from '../packages/protocol/src/canonical/v42-reading-shortest-path-state-machine.js';
+
+const __filename = fileURLToPath(import.meta.url);
+const __dirname = path.dirname(__filename);
+const repoRoot = path.resolve(__dirname, '..');
+
+const check = process.argv.includes('--check');
+const artifact = buildV42ReadingShortestPathStateMachine({ repoRoot });
+const serialized = `${JSON.stringify(artifact, null, 2)}\n`;
+const artifactPath = path.join(repoRoot, V42_READING_SHORTEST_PATH_STATE_MACHINE_ARTIFACT_PATH);
+
+if (check) {
+ const current = readFileSync(artifactPath, 'utf8');
+ if (current !== serialized) {
+ process.stderr.write(
+ `${V42_READING_SHORTEST_PATH_STATE_MACHINE_ARTIFACT_PATH} is stale. Run pnpm run generate:v42-reading-shortest-path-state-machine.\n`,
+ );
+ process.exitCode = 1;
+ }
+} else {
+ writeFileSync(artifactPath, serialized);
+ process.stdout.write(`wrote ${V42_READING_SHORTEST_PATH_STATE_MACHINE_ARTIFACT_PATH}\n`);
+}
diff --git a/uapi/app/terminal/README.md b/uapi/app/terminal/README.md
index 7867c6b7..176bc0a0 100644
--- a/uapi/app/terminal/README.md
+++ b/uapi/app/terminal/README.md
@@ -105,6 +105,16 @@ parses it only as operator posture. The source-safe generated artifact is
`.bitcode/v39-enterprise-reading-ux-state.json`, checked by
`pnpm run check:v39-gate3`.
+V42 Gate 3 extends that state into the current Reading shortest path recovery
+contract. `TerminalEnterpriseReadingRouteState` binds transaction id presence,
+the `readingStage` query parameter, active-stage hydration, retry and restart
+posture, source-safe failure kind, and repair actions. Terminal may restore a
+later stage from route state after refresh or handoff, but blockers still hold:
+accepted Need gates Finding Fits, source-safe AssetPack preview gates
+settlement, and settlement readback gates delivery. The source-safe proof
+artifact is `.bitcode/v42-reading-shortest-path-state-machine.json`, checked by
+`pnpm run check:v42-gate3`.
+
## Live staging-testnet QA
Terminal Deposit/Read QA starts only after Wallet and Externals prerequisites are
diff --git a/uapi/app/terminal/TerminalDepositReadWorkbench.tsx b/uapi/app/terminal/TerminalDepositReadWorkbench.tsx
index 6d0e756b..4d4e1453 100644
--- a/uapi/app/terminal/TerminalDepositReadWorkbench.tsx
+++ b/uapi/app/terminal/TerminalDepositReadWorkbench.tsx
@@ -108,6 +108,7 @@ interface TerminalDepositReadWorkbenchProps {
repositoryContext?: TerminalRepositoryContextState | null;
depositedSourceRevision?: TerminalDepositedSourceRevision | null;
admittedReadActivityId?: string | null;
+ routeReadingStage?: TerminalEnterpriseReadingStepId | null;
onRecordActivity?: (draft: TerminalActivityRecordDraft) => Promise;
onHarnessCompleted?: () => Promise | unknown;
showDemonstrationWorkbench?: boolean;
@@ -117,6 +118,7 @@ export default function TerminalDepositReadWorkbench({
repositoryContext = null,
depositedSourceRevision = null,
admittedReadActivityId = null,
+ routeReadingStage = null,
onRecordActivity,
onHarnessCompleted,
showDemonstrationWorkbench = true,
@@ -304,6 +306,8 @@ export default function TerminalDepositReadWorkbench({
const enterpriseReadingState = useMemo(
() =>
buildTerminalEnterpriseReadingUxState({
+ transactionId: recordedAdmittedReadActivityId || harnessReadActivityId || admittedReadActivityId || null,
+ routeReadingStage,
hasRepositorySource: Boolean(workbench?.sourceRevision),
hasReadMeasurement: readFitsFindingProgress !== 'draft' || Boolean(harnessReadActivityId),
hasSynthesizedNeed: Boolean(readNeed),
@@ -312,18 +316,24 @@ export default function TerminalDepositReadWorkbench({
hasSourceSafePreview: Boolean(sourceSafePreview),
hasSettlementReadback: settledReadback,
hasDeliveryReadback: pullRequestDelivered,
+ retryRequested: readNeedSynthesisCount > 1 || harnessState === 'failed',
+ failureKind: harnessState === 'failed' ? 'fits_finding_failed' : null,
sourceSafePreviewBlocked: Boolean(sourceSafePreview && !disclosureSourceSafe),
disclosureLeakageDetected: disclosureLeakage?.protectedSourceDetected === true,
}),
[
acceptedReadNeed,
+ admittedReadActivityId,
disclosureLeakage?.protectedSourceDetected,
disclosureSourceSafe,
harnessReadActivityId,
harnessState,
+ readNeedSynthesisCount,
pullRequestDelivered,
readFitsFindingProgress,
+ recordedAdmittedReadActivityId,
readNeed,
+ routeReadingStage,
settledReadback,
sourceSafePreview,
workbench?.sourceRevision,
@@ -711,7 +721,12 @@ export default function TerminalDepositReadWorkbench({
/>
-
+
staged reading
diff --git a/uapi/app/terminal/TerminalPageClient.tsx b/uapi/app/terminal/TerminalPageClient.tsx
index 33d0e3ca..f33d3aa2 100644
--- a/uapi/app/terminal/TerminalPageClient.tsx
+++ b/uapi/app/terminal/TerminalPageClient.tsx
@@ -691,6 +691,7 @@ export default function TerminalPageClient() {
repositoryContext={repositoryContext}
depositedSourceRevision={depositedSourceRevision}
admittedReadActivityId={admittedReadActivityId}
+ routeReadingStage={conversationHandoffContext.readingStage}
onRecordActivity={handleRecordActivity}
onHarnessCompleted={refreshLiveRuns}
showDemonstrationWorkbench={showDemonstrationSurfaces}
diff --git a/uapi/app/terminal/terminal-enterprise-reading-ux-state.ts b/uapi/app/terminal/terminal-enterprise-reading-ux-state.ts
index 54911805..305a345d 100644
--- a/uapi/app/terminal/terminal-enterprise-reading-ux-state.ts
+++ b/uapi/app/terminal/terminal-enterprise-reading-ux-state.ts
@@ -7,6 +7,16 @@ export type TerminalEnterpriseReadingStepId =
export type TerminalEnterpriseReadingStepState = 'complete' | 'current' | 'blocked';
+export type TerminalEnterpriseReadingFailureKind =
+ | 'none'
+ | 'read_request_invalid'
+ | 'need_review_required'
+ | 'fits_finding_failed'
+ | 'asset_pack_preview_blocked'
+ | 'settlement_blocked'
+ | 'delivery_blocked'
+ | 'source_safety_blocked';
+
export type TerminalEnterpriseReadingSourceSafeField =
| 'read_request_summary'
| 'read_need_measurements'
@@ -46,6 +56,8 @@ export type TerminalEnterpriseReadingStepView = TerminalEnterpriseReadingStepDef
};
export type TerminalEnterpriseReadingUxStateInput = {
+ transactionId?: string | null;
+ routeReadingStage?: TerminalEnterpriseReadingStepId | null;
hasRepositorySource?: boolean;
hasReadMeasurement?: boolean;
hasSynthesizedNeed?: boolean;
@@ -54,10 +66,30 @@ export type TerminalEnterpriseReadingUxStateInput = {
hasSourceSafePreview?: boolean;
hasSettlementReadback?: boolean;
hasDeliveryReadback?: boolean;
+ retryRequested?: boolean;
+ restartRequested?: boolean;
+ failureKind?: TerminalEnterpriseReadingFailureKind | null;
sourceSafePreviewBlocked?: boolean;
disclosureLeakageDetected?: boolean;
};
+export type TerminalEnterpriseReadingRouteState = {
+ transactionId: string | null;
+ transactionIdPresent: boolean;
+ transactionIdRequiredForRecovery: true;
+ readingStageQueryParam: 'readingStage';
+ activeStageHydratedFromRoute: boolean;
+ routeReadingStage: TerminalEnterpriseReadingStepId | null;
+ restartRequested: boolean;
+ restartRestoresActiveStage: true;
+ retryRequested: boolean;
+ retryPreservesNeedLineage: true;
+ retryPreservesSettlementBoundary: true;
+ failureKind: TerminalEnterpriseReadingFailureKind;
+ failureStateSourceSafe: true;
+ failureRepairActions: string[];
+};
+
export type TerminalEnterpriseReadingUxState = {
schema: 'bitcode.terminal.enterprise-reading-ux-state';
activeStepId: TerminalEnterpriseReadingStepId;
@@ -78,10 +110,15 @@ export type TerminalEnterpriseReadingUxState = {
routeContract: {
terminalOwnsTransactionAuthority: true;
conversationMayHandoffIntent: true;
+ transactionRouteRequiredForRecovery: true;
acceptedNeedRequiredBeforeFindingFits: true;
sourceSafePreviewRequiredBeforeSettlement: true;
deliveryRequiresSettlementUnlock: true;
+ restartRestoresReadingStage: true;
+ retryPreservesSourceSafeLineage: true;
+ failureStatesSourceSafe: true;
};
+ routeState: TerminalEnterpriseReadingRouteState;
proofRoot: string;
};
@@ -183,6 +220,47 @@ export function inferTerminalEnterpriseReadingActiveStep(
return 'request-read';
}
+function normalizeTransactionId(value: string | null | undefined): string | null {
+ const normalized = value?.trim();
+ return normalized ? normalized : null;
+}
+
+function routeStageOrNull(value: TerminalEnterpriseReadingStepId | null | undefined): TerminalEnterpriseReadingStepId | null {
+ return value && STEP_ORDER.includes(value) ? value : null;
+}
+
+function chooseActiveStep(
+ input: TerminalEnterpriseReadingUxStateInput,
+): { activeStepId: TerminalEnterpriseReadingStepId; routeReadingStage: TerminalEnterpriseReadingStepId | null } {
+ const inferredStep = inferTerminalEnterpriseReadingActiveStep(input);
+ const routeReadingStage = routeStageOrNull(input.routeReadingStage);
+ if (!routeReadingStage) return { activeStepId: inferredStep, routeReadingStage };
+
+ const inferredIndex = STEP_ORDER.indexOf(inferredStep);
+ const routeIndex = STEP_ORDER.indexOf(routeReadingStage);
+ return {
+ activeStepId: routeIndex > inferredIndex ? routeReadingStage : inferredStep,
+ routeReadingStage,
+ };
+}
+
+function failureKindFor(input: TerminalEnterpriseReadingUxStateInput): TerminalEnterpriseReadingFailureKind {
+ if (input.disclosureLeakageDetected) return 'source_safety_blocked';
+ if (input.sourceSafePreviewBlocked) return 'asset_pack_preview_blocked';
+ return input.failureKind || 'none';
+}
+
+function repairActionsForFailure(kind: TerminalEnterpriseReadingFailureKind): string[] {
+ if (kind === 'none') return [];
+ if (kind === 'read_request_invalid') return ['repair-read-request'];
+ if (kind === 'need_review_required') return ['review-or-resynthesize-need'];
+ if (kind === 'fits_finding_failed') return ['retry-finding-fits-from-accepted-need'];
+ if (kind === 'asset_pack_preview_blocked') return ['repair-source-safe-preview'];
+ if (kind === 'settlement_blocked') return ['repair-settlement-readback'];
+ if (kind === 'delivery_blocked') return ['repair-repository-delivery'];
+ return ['repair-source-safety-disclosure'];
+}
+
function blockersFor(stepId: TerminalEnterpriseReadingStepId, input: TerminalEnterpriseReadingUxStateInput) {
const blockers: string[] = [];
if (stepId === 'request-read' && !input.hasRepositorySource) blockers.push('repository source required');
@@ -208,8 +286,10 @@ function blockersFor(stepId: TerminalEnterpriseReadingStepId, input: TerminalEnt
export function buildTerminalEnterpriseReadingUxState(
input: TerminalEnterpriseReadingUxStateInput = {},
): TerminalEnterpriseReadingUxState {
- const activeStepId = inferTerminalEnterpriseReadingActiveStep(input);
+ const { activeStepId, routeReadingStage } = chooseActiveStep(input);
const activeIndex = STEP_ORDER.indexOf(activeStepId);
+ const transactionId = normalizeTransactionId(input.transactionId);
+ const failureKind = failureKindFor(input);
const steps = TERMINAL_ENTERPRISE_READING_STEPS.map((step, index) => {
const blockers = blockersFor(step.id, input);
const state: TerminalEnterpriseReadingStepState =
@@ -232,6 +312,10 @@ export function buildTerminalEnterpriseReadingUxState(
hasSourceSafePreview: Boolean(input.hasSourceSafePreview),
hasSettlementReadback: Boolean(input.hasSettlementReadback),
hasDeliveryReadback: Boolean(input.hasDeliveryReadback),
+ transactionId,
+ routeReadingStage,
+ retryRequested: Boolean(input.retryRequested),
+ failureKind,
});
return {
@@ -254,9 +338,29 @@ export function buildTerminalEnterpriseReadingUxState(
routeContract: {
terminalOwnsTransactionAuthority: true,
conversationMayHandoffIntent: true,
+ transactionRouteRequiredForRecovery: true,
acceptedNeedRequiredBeforeFindingFits: true,
sourceSafePreviewRequiredBeforeSettlement: true,
deliveryRequiresSettlementUnlock: true,
+ restartRestoresReadingStage: true,
+ retryPreservesSourceSafeLineage: true,
+ failureStatesSourceSafe: true,
+ },
+ routeState: {
+ transactionId,
+ transactionIdPresent: Boolean(transactionId),
+ transactionIdRequiredForRecovery: true,
+ readingStageQueryParam: 'readingStage',
+ activeStageHydratedFromRoute: routeReadingStage === activeStepId,
+ routeReadingStage,
+ restartRequested: Boolean(input.restartRequested),
+ restartRestoresActiveStage: true,
+ retryRequested: Boolean(input.retryRequested),
+ retryPreservesNeedLineage: true,
+ retryPreservesSettlementBoundary: true,
+ failureKind,
+ failureStateSourceSafe: true,
+ failureRepairActions: repairActionsForFailure(failureKind),
},
proofRoot: `terminal-enterprise-reading-ux:${stableHash(seed)}`,
};
@@ -276,9 +380,19 @@ export function assertTerminalEnterpriseReadingUxStateSourceSafe(state: Terminal
state.disclosure.ledgerAuthorityClaimed === false &&
state.routeContract.terminalOwnsTransactionAuthority === true &&
state.routeContract.conversationMayHandoffIntent === true &&
+ state.routeContract.transactionRouteRequiredForRecovery === true &&
state.routeContract.acceptedNeedRequiredBeforeFindingFits === true &&
state.routeContract.sourceSafePreviewRequiredBeforeSettlement === true &&
state.routeContract.deliveryRequiresSettlementUnlock === true &&
+ state.routeContract.restartRestoresReadingStage === true &&
+ state.routeContract.retryPreservesSourceSafeLineage === true &&
+ state.routeContract.failureStatesSourceSafe === true &&
+ state.routeState.transactionIdRequiredForRecovery === true &&
+ state.routeState.readingStageQueryParam === 'readingStage' &&
+ state.routeState.restartRestoresActiveStage === true &&
+ state.routeState.retryPreservesNeedLineage === true &&
+ state.routeState.retryPreservesSettlementBoundary === true &&
+ state.routeState.failureStateSourceSafe === true &&
TERMINAL_ENTERPRISE_READING_FORBIDDEN_FIELDS.every((field) =>
state.disclosure.hiddenBeforeSettlement.includes(field),
);
diff --git a/uapi/tests/terminalEnterpriseReadingUxState.test.ts b/uapi/tests/terminalEnterpriseReadingUxState.test.ts
index 352e54e5..52873233 100644
--- a/uapi/tests/terminalEnterpriseReadingUxState.test.ts
+++ b/uapi/tests/terminalEnterpriseReadingUxState.test.ts
@@ -90,6 +90,7 @@ describe('terminal-enterprise-reading-ux-state', () => {
it('admits only source-safe low-detail and expandable metadata before settlement', () => {
const state = buildTerminalEnterpriseReadingUxState({
+ transactionId: 'reading-transaction-1',
hasRepositorySource: true,
hasReadMeasurement: true,
hasSynthesizedNeed: true,
@@ -98,13 +99,49 @@ describe('terminal-enterprise-reading-ux-state', () => {
});
expect(state.activeStepId).toBe('request-fit');
+ expect(state.routeState.transactionId).toBe('reading-transaction-1');
+ expect(state.routeState.transactionIdPresent).toBe(true);
+ expect(state.routeState.readingStageQueryParam).toBe('readingStage');
expect(state.routeContract.acceptedNeedRequiredBeforeFindingFits).toBe(true);
expect(state.routeContract.sourceSafePreviewRequiredBeforeSettlement).toBe(true);
expect(state.routeContract.deliveryRequiresSettlementUnlock).toBe(true);
+ expect(state.routeContract.restartRestoresReadingStage).toBe(true);
+ expect(state.routeContract.retryPreservesSourceSafeLineage).toBe(true);
+ expect(state.routeContract.failureStatesSourceSafe).toBe(true);
expect(state.proofRoot).toMatch(/^terminal-enterprise-reading-ux:/u);
expect(assertTerminalEnterpriseReadingUxStateSourceSafe(state)).toEqual({
admitted: true,
reason: 'source_safe_enterprise_reading_ux_metadata',
});
});
+
+ it('hydrates later route stages, retry posture, and source-safe failure repair actions', () => {
+ const state = buildTerminalEnterpriseReadingUxState({
+ transactionId: 'reading-transaction-2',
+ routeReadingStage: 'buy-asset-pack-settle',
+ hasRepositorySource: true,
+ hasReadMeasurement: true,
+ hasSynthesizedNeed: true,
+ hasAcceptedNeed: true,
+ retryRequested: true,
+ restartRequested: true,
+ failureKind: 'settlement_blocked',
+ });
+
+ expect(state.activeStepId).toBe('buy-asset-pack-settle');
+ expect(state.routeState.routeReadingStage).toBe('buy-asset-pack-settle');
+ expect(state.routeState.activeStageHydratedFromRoute).toBe(true);
+ expect(state.routeState.retryRequested).toBe(true);
+ expect(state.routeState.retryPreservesNeedLineage).toBe(true);
+ expect(state.routeState.retryPreservesSettlementBoundary).toBe(true);
+ expect(state.routeState.restartRequested).toBe(true);
+ expect(state.routeState.restartRestoresActiveStage).toBe(true);
+ expect(state.routeState.failureKind).toBe('settlement_blocked');
+ expect(state.routeState.failureStateSourceSafe).toBe(true);
+ expect(state.routeState.failureRepairActions).toContain('repair-settlement-readback');
+ expect(state.steps.find((step) => step.id === 'buy-asset-pack-settle')?.blockers).toContain(
+ 'source-safe AssetPack preview required',
+ );
+ expect(assertTerminalEnterpriseReadingUxStateSourceSafe(state).admitted).toBe(true);
+ });
});
From 0a624838c306958cda748d5408ae8d9d7bcb6ecf Mon Sep 17 00:00:00 2001
From: Garrett Maring
Date: Thu, 28 May 2026 18:07:23 -0300
Subject: [PATCH 05/35] V42 Gate 4: Close ReadNeed review loop
Persist source-safe ReadNeed review and resynthesis runtime receipts across synthesize, accept, reject, and resynthesize actions.
Expose Terminal runtime/storage/telemetry readbacks, add product closure proof artifact, wire promotion checks, and cover the route/pipeline/protocol contracts with focused tests.
---
...ed-review-resynthesis-product-closure.json | 644 ++++++++++++++++++
.github/workflows/bitcode-canon-quality.yml | 3 +
.github/workflows/bitcode-gate-quality.yml | 3 +
BITCODE_SPEC_V42.md | 4 +-
BITCODE_SPEC_V42_DELTA.md | 1 +
BITCODE_SPEC_V42_NOTES.md | 8 +
BITCODE_SPEC_V42_PARITY_MATRIX.md | 4 +-
README.md | 7 +
SPECIFICATIONS_ROADMAP.md | 5 +-
package.json | 3 +
packages/pipelines/asset-pack/README.md | 8 +
.../read-need-review-resynthesis.test.ts | 3 +
packages/protocol/README.md | 9 +
...need-review-resynthesis-product-closure.js | 325 +++++++++
packages/protocol/src/index.d.ts | 9 +
packages/protocol/src/index.js | 11 +
...review-resynthesis-product-closure.test.js | 73 ++
...eed-review-resynthesis-product-closure.mjs | 258 +++++++
...eed-review-resynthesis-product-closure.mjs | 31 +
uapi/app/api/read-review/route.ts | 6 +
uapi/app/terminal/README.md | 10 +
.../terminal/TerminalDepositReadWorkbench.tsx | 130 +++-
uapi/tests/api/readReviewRoute.test.ts | 10 +
23 files changed, 1559 insertions(+), 6 deletions(-)
create mode 100644 .bitcode/v42-readneed-review-resynthesis-product-closure.json
create mode 100644 packages/protocol/src/canonical/v42-readneed-review-resynthesis-product-closure.js
create mode 100644 packages/protocol/test/v42-readneed-review-resynthesis-product-closure.test.js
create mode 100644 scripts/check-v42-gate4-readneed-review-resynthesis-product-closure.mjs
create mode 100644 scripts/generate-v42-readneed-review-resynthesis-product-closure.mjs
diff --git a/.bitcode/v42-readneed-review-resynthesis-product-closure.json b/.bitcode/v42-readneed-review-resynthesis-product-closure.json
new file mode 100644
index 00000000..2ec7f691
--- /dev/null
+++ b/.bitcode/v42-readneed-review-resynthesis-product-closure.json
@@ -0,0 +1,644 @@
+{
+ "artifactId": "v42-readneed-review-resynthesis-product-closure",
+ "schemaId": "bitcode.v42.readNeedReviewResynthesisProductClosure.v1",
+ "version": "V42",
+ "currentTarget": "V41",
+ "sourceSafetyVerdict": "source-safe-readneed-review-resynthesis-product-closure-metadata",
+ "generatedAt": "deterministic",
+ "artifactRoot": "v42-readneed-review-resynthesis-product-closure:932beb894b734ebe044125ae",
+ "passed": true,
+ "rows": [
+ {
+ "rowId": "request:read-request-persistence",
+ "purpose": "Persist source-safe Read Request data with repository, branch, commit, target artifact kinds, closure criteria, failure modes, feedback, and previous Need lineage.",
+ "sourceRoots": [
+ "packages/pipelines/asset-pack/src/read-need.ts",
+ "packages/pipelines/asset-pack/src/read-need-review-resynthesis.ts",
+ "uapi/app/api/read-review/route.ts"
+ ],
+ "emittedTypes": [
+ "ReadNeedRequest",
+ "ReadNeedReviewStorageRecord"
+ ],
+ "requiredEvidence": [
+ "bitcode.read.request",
+ "read_request",
+ "previousNeedId"
+ ],
+ "rowRoot": "v42-readneed-review-resynthesis-product-closure-row:dd13403f50f233293a797b93",
+ "sourceSafetyClass": "source_safe_readneed_review_resynthesis_product_closure_metadata",
+ "sourceSafeMetadataOnly": true,
+ "protectedSourceVisible": false,
+ "rawProtectedPromptVisible": false,
+ "rawProviderResponseVisible": false,
+ "unpaidAssetPackSourceVisible": false,
+ "walletPrivateMaterialVisible": false,
+ "settlementPrivatePayloadVisible": false,
+ "credentialsSerialized": false,
+ "forbiddenPayloadClasses": [
+ "protected-source-payloads",
+ "raw-protected-prompts",
+ "raw-provider-responses",
+ "unpaid-assetpack-source",
+ "wallet-private-material",
+ "settlement-private-payloads",
+ "secret-values"
+ ]
+ },
+ {
+ "rowId": "pipeline:ptrr-failsafe-thricified-need-synthesis",
+ "purpose": "Keep ReadNeedComprehensionSynthesis product-owned by PTRR agents whose steps carry FailsafeGenerationSequence over ThricifiedGeneration contracts and typed parser output.",
+ "sourceRoots": [
+ "packages/pipelines/asset-pack/src/read-need.ts",
+ "packages/pipelines/asset-pack/src/reading-pipeline-contract.ts",
+ "packages/pipelines/asset-pack/src/__tests__/read-need.test.ts"
+ ],
+ "emittedTypes": [
+ "ReadNeedComprehensionSynthesisInferenceReceipt",
+ "ReadingPipelineContract"
+ ],
+ "requiredEvidence": [
+ "ptrrStepIds",
+ "failsafeSequenceIds",
+ "thricifiedGenerationIds",
+ "ReadNeedComprehensionSynthesis.prompt.need-synthesis"
+ ],
+ "rowRoot": "v42-readneed-review-resynthesis-product-closure-row:2a7caa01828aa9e731d31be0",
+ "sourceSafetyClass": "source_safe_readneed_review_resynthesis_product_closure_metadata",
+ "sourceSafeMetadataOnly": true,
+ "protectedSourceVisible": false,
+ "rawProtectedPromptVisible": false,
+ "rawProviderResponseVisible": false,
+ "unpaidAssetPackSourceVisible": false,
+ "walletPrivateMaterialVisible": false,
+ "settlementPrivatePayloadVisible": false,
+ "credentialsSerialized": false,
+ "forbiddenPayloadClasses": [
+ "protected-source-payloads",
+ "raw-protected-prompts",
+ "raw-provider-responses",
+ "unpaid-assetpack-source",
+ "wallet-private-material",
+ "settlement-private-payloads",
+ "secret-values"
+ ]
+ },
+ {
+ "rowId": "need:synthesized-need-storage",
+ "purpose": "Persist reviewable synthesized Need output before Finding Fits, including requirements, target artifacts, source constraints, proof expectations, and review state.",
+ "sourceRoots": [
+ "packages/pipelines/asset-pack/src/read-need.ts",
+ "packages/pipelines/asset-pack/src/read-need-review-resynthesis.ts",
+ "packages/pipelines/asset-pack/src/__tests__/read-need-review-resynthesis.test.ts"
+ ],
+ "emittedTypes": [
+ "ReadNeed",
+ "synthesized_need"
+ ],
+ "requiredEvidence": [
+ "bitcode.read.need",
+ "needs_acceptance",
+ "synthesized_need"
+ ],
+ "rowRoot": "v42-readneed-review-resynthesis-product-closure-row:9132dd0681fe996ad9af5add",
+ "sourceSafetyClass": "source_safe_readneed_review_resynthesis_product_closure_metadata",
+ "sourceSafeMetadataOnly": true,
+ "protectedSourceVisible": false,
+ "rawProtectedPromptVisible": false,
+ "rawProviderResponseVisible": false,
+ "unpaidAssetPackSourceVisible": false,
+ "walletPrivateMaterialVisible": false,
+ "settlementPrivatePayloadVisible": false,
+ "credentialsSerialized": false,
+ "forbiddenPayloadClasses": [
+ "protected-source-payloads",
+ "raw-protected-prompts",
+ "raw-provider-responses",
+ "unpaid-assetpack-source",
+ "wallet-private-material",
+ "settlement-private-payloads",
+ "secret-values"
+ ]
+ },
+ {
+ "rowId": "feedback:review-resynthesis-lineage",
+ "purpose": "Preserve user feedback and resynthesis attempts so every new Need stays linked to the prior Need and reviewed feedback.",
+ "sourceRoots": [
+ "packages/pipelines/asset-pack/src/read-need.ts",
+ "packages/pipelines/asset-pack/src/read-need-review-resynthesis.ts",
+ "uapi/tests/api/readReviewRoute.test.ts",
+ "uapi/app/terminal/TerminalDepositReadWorkbench.tsx"
+ ],
+ "emittedTypes": [
+ "resynthesis_attempt",
+ "feedbackHistory"
+ ],
+ "requiredEvidence": [
+ "previousNeedId",
+ "resynthesize_read_need",
+ "resynthesis_attempt"
+ ],
+ "rowRoot": "v42-readneed-review-resynthesis-product-closure-row:16e048458da7e50ddd1b4f2f",
+ "sourceSafetyClass": "source_safe_readneed_review_resynthesis_product_closure_metadata",
+ "sourceSafeMetadataOnly": true,
+ "protectedSourceVisible": false,
+ "rawProtectedPromptVisible": false,
+ "rawProviderResponseVisible": false,
+ "unpaidAssetPackSourceVisible": false,
+ "walletPrivateMaterialVisible": false,
+ "settlementPrivatePayloadVisible": false,
+ "credentialsSerialized": false,
+ "forbiddenPayloadClasses": [
+ "protected-source-payloads",
+ "raw-protected-prompts",
+ "raw-provider-responses",
+ "unpaid-assetpack-source",
+ "wallet-private-material",
+ "settlement-private-payloads",
+ "secret-values"
+ ]
+ },
+ {
+ "rowId": "measurement:need-measurement-storage",
+ "purpose": "Persist Need measurement roots and pricing measurement inputs that later drive deterministic preview quotes without exposing source.",
+ "sourceRoots": [
+ "packages/pipelines/asset-pack/src/read-need.ts",
+ "packages/pipelines/asset-pack/src/read-need-review-resynthesis.ts",
+ "packages/pipelines/asset-pack/src/__tests__/read-need.test.ts"
+ ],
+ "emittedTypes": [
+ "ReadNeedMeasurementDimension",
+ "need_measurement"
+ ],
+ "requiredEvidence": [
+ "measurementRoot",
+ "pricingMeasurementInputs",
+ "shareToFeeFormula"
+ ],
+ "rowRoot": "v42-readneed-review-resynthesis-product-closure-row:49789e8b9beb3a2d19f60ad7",
+ "sourceSafetyClass": "source_safe_readneed_review_resynthesis_product_closure_metadata",
+ "sourceSafeMetadataOnly": true,
+ "protectedSourceVisible": false,
+ "rawProtectedPromptVisible": false,
+ "rawProviderResponseVisible": false,
+ "unpaidAssetPackSourceVisible": false,
+ "walletPrivateMaterialVisible": false,
+ "settlementPrivatePayloadVisible": false,
+ "credentialsSerialized": false,
+ "forbiddenPayloadClasses": [
+ "protected-source-payloads",
+ "raw-protected-prompts",
+ "raw-provider-responses",
+ "unpaid-assetpack-source",
+ "wallet-private-material",
+ "settlement-private-payloads",
+ "secret-values"
+ ]
+ },
+ {
+ "rowId": "admission:accepted-need-gates-finding-fits",
+ "purpose": "Persist accepted-Need admission as the only source-safe handoff into ReadFitsFindingSynthesis and block Finding Fits without acceptance.",
+ "sourceRoots": [
+ "packages/pipelines/asset-pack/src/read-need.ts",
+ "packages/pipelines/asset-pack/src/read-need-review-resynthesis.ts",
+ "uapi/tests/api/readReviewRoute.test.ts",
+ "uapi/app/terminal/terminal-enterprise-reading-ux-state.ts"
+ ],
+ "emittedTypes": [
+ "ReadFitsFindingAdmission",
+ "accepted_need_admission"
+ ],
+ "requiredEvidence": [
+ "accept_read_need",
+ "accepted_need_admission",
+ "accepted_read_need_missing"
+ ],
+ "rowRoot": "v42-readneed-review-resynthesis-product-closure-row:db95df08a064d2644a6a86db",
+ "sourceSafetyClass": "source_safe_readneed_review_resynthesis_product_closure_metadata",
+ "sourceSafeMetadataOnly": true,
+ "protectedSourceVisible": false,
+ "rawProtectedPromptVisible": false,
+ "rawProviderResponseVisible": false,
+ "unpaidAssetPackSourceVisible": false,
+ "walletPrivateMaterialVisible": false,
+ "settlementPrivatePayloadVisible": false,
+ "credentialsSerialized": false,
+ "forbiddenPayloadClasses": [
+ "protected-source-payloads",
+ "raw-protected-prompts",
+ "raw-provider-responses",
+ "unpaid-assetpack-source",
+ "wallet-private-material",
+ "settlement-private-payloads",
+ "secret-values"
+ ]
+ },
+ {
+ "rowId": "rejection:rejected-need-posture",
+ "purpose": "Persist rejected-Need posture with rejection root, feedback, blocked Finding Fits stage, and repair/resynthesis next action.",
+ "sourceRoots": [
+ "packages/pipelines/asset-pack/src/read-need.ts",
+ "packages/pipelines/asset-pack/src/read-need-review-resynthesis.ts",
+ "uapi/tests/api/readReviewRoute.test.ts",
+ "uapi/app/terminal/TerminalDepositReadWorkbench.tsx"
+ ],
+ "emittedTypes": [
+ "RejectedReadNeed",
+ "rejected_need_posture"
+ ],
+ "requiredEvidence": [
+ "rejectReadNeed",
+ "reject_read_need",
+ "read_need_rejected"
+ ],
+ "rowRoot": "v42-readneed-review-resynthesis-product-closure-row:5470af7414fae6fa252d6df8",
+ "sourceSafetyClass": "source_safe_readneed_review_resynthesis_product_closure_metadata",
+ "sourceSafeMetadataOnly": true,
+ "protectedSourceVisible": false,
+ "rawProtectedPromptVisible": false,
+ "rawProviderResponseVisible": false,
+ "unpaidAssetPackSourceVisible": false,
+ "walletPrivateMaterialVisible": false,
+ "settlementPrivatePayloadVisible": false,
+ "credentialsSerialized": false,
+ "forbiddenPayloadClasses": [
+ "protected-source-payloads",
+ "raw-protected-prompts",
+ "raw-provider-responses",
+ "unpaid-assetpack-source",
+ "wallet-private-material",
+ "settlement-private-payloads",
+ "secret-values"
+ ]
+ },
+ {
+ "rowId": "telemetry:source-safe-runtime-receipts",
+ "purpose": "Emit source-safe telemetry receipts containing phase, PTRR step, Failsafe, ThricifiedGeneration, prompt-template, output-schema, and proof-root identities.",
+ "sourceRoots": [
+ "packages/pipelines/asset-pack/src/read-need.ts",
+ "packages/pipelines/asset-pack/src/read-need-review-resynthesis.ts",
+ "packages/pipelines/asset-pack/src/reading-pipeline-contract.ts",
+ "uapi/app/api/read-review/route.ts"
+ ],
+ "emittedTypes": [
+ "ReadNeedReviewTelemetryReceipt",
+ "ReadNeedComprehensionSynthesisInferenceReceipt"
+ ],
+ "requiredEvidence": [
+ "ptrrStepIds",
+ "failsafeSequenceIds",
+ "thricifiedGenerationIds",
+ "promptTemplateIds"
+ ],
+ "rowRoot": "v42-readneed-review-resynthesis-product-closure-row:b1707272fafd2df1da82287f",
+ "sourceSafetyClass": "source_safe_readneed_review_resynthesis_product_closure_metadata",
+ "sourceSafeMetadataOnly": true,
+ "protectedSourceVisible": false,
+ "rawProtectedPromptVisible": false,
+ "rawProviderResponseVisible": false,
+ "unpaidAssetPackSourceVisible": false,
+ "walletPrivateMaterialVisible": false,
+ "settlementPrivatePayloadVisible": false,
+ "credentialsSerialized": false,
+ "forbiddenPayloadClasses": [
+ "protected-source-payloads",
+ "raw-protected-prompts",
+ "raw-provider-responses",
+ "unpaid-assetpack-source",
+ "wallet-private-material",
+ "settlement-private-payloads",
+ "secret-values"
+ ]
+ },
+ {
+ "rowId": "route:read-review-actions",
+ "purpose": "Expose synthesize, resynthesize, accept, and reject actions through the Read review route with storage projection, runtime summary, source-safe telemetry, and Finding Fits admission readback.",
+ "sourceRoots": [
+ "uapi/app/api/read-review/route.ts",
+ "uapi/tests/api/readReviewRoute.test.ts"
+ ],
+ "emittedTypes": [
+ "readNeedReviewRuntime",
+ "storageProjection",
+ "runtimeSummary"
+ ],
+ "requiredEvidence": [
+ "synthesize_read_need",
+ "resynthesize_read_need",
+ "accept_read_need",
+ "reject_read_need"
+ ],
+ "rowRoot": "v42-readneed-review-resynthesis-product-closure-row:6236882a7b982f2c79671dfc",
+ "sourceSafetyClass": "source_safe_readneed_review_resynthesis_product_closure_metadata",
+ "sourceSafeMetadataOnly": true,
+ "protectedSourceVisible": false,
+ "rawProtectedPromptVisible": false,
+ "rawProviderResponseVisible": false,
+ "unpaidAssetPackSourceVisible": false,
+ "walletPrivateMaterialVisible": false,
+ "settlementPrivatePayloadVisible": false,
+ "credentialsSerialized": false,
+ "forbiddenPayloadClasses": [
+ "protected-source-payloads",
+ "raw-protected-prompts",
+ "raw-provider-responses",
+ "unpaid-assetpack-source",
+ "wallet-private-material",
+ "settlement-private-payloads",
+ "secret-values"
+ ]
+ },
+ {
+ "rowId": "ui:terminal-need-runtime-readback",
+ "purpose": "Expose the reviewed Need, feedback loop, rejection path, storage projection, runtime roots, telemetry return type, and Finding Fits blocker/admission state in Terminal without protected source.",
+ "sourceRoots": [
+ "uapi/app/terminal/TerminalDepositReadWorkbench.tsx",
+ "uapi/app/terminal/README.md"
+ ],
+ "emittedTypes": [
+ "TerminalReadNeedReviewRuntimeState",
+ "Need runtime, storage, and telemetry"
+ ],
+ "requiredEvidence": [
+ "Reject Read-Need",
+ "readNeedStorageProjection",
+ "readNeedTelemetry",
+ "Need runtime, storage, and telemetry"
+ ],
+ "rowRoot": "v42-readneed-review-resynthesis-product-closure-row:80bccaab5bdfa287e270838a",
+ "sourceSafetyClass": "source_safe_readneed_review_resynthesis_product_closure_metadata",
+ "sourceSafeMetadataOnly": true,
+ "protectedSourceVisible": false,
+ "rawProtectedPromptVisible": false,
+ "rawProviderResponseVisible": false,
+ "unpaidAssetPackSourceVisible": false,
+ "walletPrivateMaterialVisible": false,
+ "settlementPrivatePayloadVisible": false,
+ "credentialsSerialized": false,
+ "forbiddenPayloadClasses": [
+ "protected-source-payloads",
+ "raw-protected-prompts",
+ "raw-provider-responses",
+ "unpaid-assetpack-source",
+ "wallet-private-material",
+ "settlement-private-payloads",
+ "secret-values"
+ ]
+ },
+ {
+ "rowId": "proof:tests-artifact-workflow",
+ "purpose": "Bind V42 Gate 4 closure to package tests, route tests, protocol artifact tests, docs, scripts, and gate/canon workflow checks.",
+ "sourceRoots": [
+ "packages/pipelines/asset-pack/src/__tests__/read-need-review-resynthesis.test.ts",
+ "uapi/tests/api/readReviewRoute.test.ts",
+ ".github/workflows/bitcode-gate-quality.yml",
+ ".github/workflows/bitcode-canon-quality.yml",
+ "BITCODE_SPEC_V42.md",
+ "BITCODE_SPEC_V42_PARITY_MATRIX.md",
+ "SPECIFICATIONS_ROADMAP.md"
+ ],
+ "emittedTypes": [
+ "V42ReadNeedReviewResynthesisProductClosure"
+ ],
+ "requiredEvidence": [
+ "check-v42-gate4-readneed-review-resynthesis-product-closure.mjs",
+ "v42-readneed-review-resynthesis-product-closure"
+ ],
+ "rowRoot": "v42-readneed-review-resynthesis-product-closure-row:b09ae61cf4664f8a3914be8e",
+ "sourceSafetyClass": "source_safe_readneed_review_resynthesis_product_closure_metadata",
+ "sourceSafeMetadataOnly": true,
+ "protectedSourceVisible": false,
+ "rawProtectedPromptVisible": false,
+ "rawProviderResponseVisible": false,
+ "unpaidAssetPackSourceVisible": false,
+ "walletPrivateMaterialVisible": false,
+ "settlementPrivatePayloadVisible": false,
+ "credentialsSerialized": false,
+ "forbiddenPayloadClasses": [
+ "protected-source-payloads",
+ "raw-protected-prompts",
+ "raw-provider-responses",
+ "unpaid-assetpack-source",
+ "wallet-private-material",
+ "settlement-private-payloads",
+ "secret-values"
+ ]
+ }
+ ],
+ "rowIds": [
+ "request:read-request-persistence",
+ "pipeline:ptrr-failsafe-thricified-need-synthesis",
+ "need:synthesized-need-storage",
+ "feedback:review-resynthesis-lineage",
+ "measurement:need-measurement-storage",
+ "admission:accepted-need-gates-finding-fits",
+ "rejection:rejected-need-posture",
+ "telemetry:source-safe-runtime-receipts",
+ "route:read-review-actions",
+ "ui:terminal-need-runtime-readback",
+ "proof:tests-artifact-workflow"
+ ],
+ "predicateResults": [
+ {
+ "id": "read-need-defines-review-states",
+ "sourcePath": "packages/pipelines/asset-pack/src/read-need.ts",
+ "passed": true
+ },
+ {
+ "id": "read-need-accept-and-reject-actions",
+ "sourcePath": "packages/pipelines/asset-pack/src/read-need.ts",
+ "passed": true
+ },
+ {
+ "id": "inference-receipt-covers-ptrr-failsafe-thricified",
+ "sourcePath": "packages/pipelines/asset-pack/src/read-need.ts",
+ "passed": true
+ },
+ {
+ "id": "contract-has-four-phases-and-sixteen-steps",
+ "sourcePath": "packages/pipelines/asset-pack/src/reading-pipeline-contract.ts",
+ "passed": true
+ },
+ {
+ "id": "runtime-defines-storage-records",
+ "sourcePath": "packages/pipelines/asset-pack/src/read-need-review-resynthesis.ts",
+ "passed": true
+ },
+ {
+ "id": "runtime-defines-resynthesis-admission-rejection",
+ "sourcePath": "packages/pipelines/asset-pack/src/read-need-review-resynthesis.ts",
+ "passed": true
+ },
+ {
+ "id": "runtime-source-safety",
+ "sourcePath": "packages/pipelines/asset-pack/src/read-need-review-resynthesis.ts",
+ "passed": true
+ },
+ {
+ "id": "runtime-persists-to-execution-store",
+ "sourcePath": "packages/pipelines/asset-pack/src/read-need-review-resynthesis.ts",
+ "passed": true
+ },
+ {
+ "id": "package-exports-runtime",
+ "sourcePath": "packages/pipelines/asset-pack/src/index.ts",
+ "passed": true
+ },
+ {
+ "id": "package-tests-cover-runtime",
+ "sourcePath": "packages/pipelines/asset-pack/src/__tests__/read-need-review-resynthesis.test.ts",
+ "passed": true
+ },
+ {
+ "id": "read-need-tests-cover-real-inference-receipts",
+ "sourcePath": "packages/pipelines/asset-pack/src/__tests__/read-need.test.ts",
+ "passed": true
+ },
+ {
+ "id": "contract-tests-cover-review-output",
+ "sourcePath": "packages/pipelines/asset-pack/src/__tests__/reading-pipeline-contract.test.ts",
+ "passed": true
+ },
+ {
+ "id": "route-exposes-all-review-actions",
+ "sourcePath": "uapi/app/api/read-review/route.ts",
+ "passed": true
+ },
+ {
+ "id": "route-persists-all-runtime-actions",
+ "sourcePath": "uapi/app/api/read-review/route.ts",
+ "passed": true
+ },
+ {
+ "id": "route-returns-runtime-projection",
+ "sourcePath": "uapi/app/api/read-review/route.ts",
+ "passed": true
+ },
+ {
+ "id": "route-tests-cover-runtime-and-rejection",
+ "sourcePath": "uapi/tests/api/readReviewRoute.test.ts",
+ "passed": true
+ },
+ {
+ "id": "protocol-parity-keeps-finding-fits-blocked",
+ "sourcePath": "uapi/tests/api/readReviewProtocolParity.test.ts",
+ "passed": true
+ },
+ {
+ "id": "terminal-ui-exposes-runtime-readback",
+ "sourcePath": "uapi/app/terminal/TerminalDepositReadWorkbench.tsx",
+ "passed": true
+ },
+ {
+ "id": "terminal-ui-exposes-rejection",
+ "sourcePath": "uapi/app/terminal/TerminalDepositReadWorkbench.tsx",
+ "passed": true
+ },
+ {
+ "id": "terminal-ux-keeps-accepted-need-gate",
+ "sourcePath": "uapi/app/terminal/terminal-enterprise-reading-ux-state.ts",
+ "passed": true
+ },
+ {
+ "id": "spec-gate4-expanded",
+ "sourcePath": "BITCODE_SPEC_V42.md",
+ "passed": true
+ },
+ {
+ "id": "delta-gate4-expanded",
+ "sourcePath": "BITCODE_SPEC_V42_DELTA.md",
+ "passed": true
+ },
+ {
+ "id": "notes-gate4-expanded",
+ "sourcePath": "BITCODE_SPEC_V42_NOTES.md",
+ "passed": true
+ },
+ {
+ "id": "parity-gate4-implemented",
+ "sourcePath": "BITCODE_SPEC_V42_PARITY_MATRIX.md",
+ "passed": true
+ },
+ {
+ "id": "roadmap-advanced-to-gate4",
+ "sourcePath": "SPECIFICATIONS_ROADMAP.md",
+ "passed": true
+ },
+ {
+ "id": "readmes-document-gate4",
+ "sourcePath": "README.md",
+ "passed": true
+ },
+ {
+ "id": "workflows-run-gate4-check",
+ "sourcePath": ".github/workflows/bitcode-gate-quality.yml",
+ "passed": true
+ }
+ ],
+ "coverage": {
+ "rowCount": 11,
+ "requiredPredicateCount": 27,
+ "passedPredicateCount": 27,
+ "failedPredicateIds": [],
+ "pipelineName": "ReadNeedComprehensionSynthesis",
+ "nextPipelineName": "ReadFitsFindingSynthesis",
+ "actions": [
+ "synthesize_read_need",
+ "resynthesize_read_need",
+ "accept_read_need",
+ "reject_read_need"
+ ],
+ "persistedRecordKinds": [
+ "read_request",
+ "synthesized_need",
+ "feedback",
+ "resynthesis_attempt",
+ "need_measurement",
+ "accepted_need_admission",
+ "rejected_need_posture",
+ "telemetry_receipt"
+ ],
+ "phaseCount": 4,
+ "ptrrStepCount": 16,
+ "failsafeSequenceCount": 48,
+ "thricifiedGenerationCount": 48,
+ "acceptedNeedRequiredForFindingFits": true,
+ "rejectedNeedBlocksFindingFits": true,
+ "terminalRuntimeReadbackCovered": true,
+ "sourceSafeMetadataOnly": true,
+ "protectedSourceVisible": false,
+ "rawProtectedPromptVisible": false,
+ "rawProviderResponseVisible": false,
+ "unpaidAssetPackSourceVisible": false,
+ "walletPrivateMaterialVisible": false,
+ "settlementPrivatePayloadVisible": false,
+ "credentialsSerialized": false,
+ "legacySourceRoots": false
+ },
+ "sourceRoots": {
+ "readNeed": "packages/pipelines/asset-pack/src/read-need.ts",
+ "readNeedRuntime": "packages/pipelines/asset-pack/src/read-need-review-resynthesis.ts",
+ "readingPipelineContract": "packages/pipelines/asset-pack/src/reading-pipeline-contract.ts",
+ "packageIndex": "packages/pipelines/asset-pack/src/index.ts",
+ "packageJson": "packages/pipelines/asset-pack/package.json",
+ "readNeedTest": "packages/pipelines/asset-pack/src/__tests__/read-need.test.ts",
+ "runtimeTest": "packages/pipelines/asset-pack/src/__tests__/read-need-review-resynthesis.test.ts",
+ "readingContractTest": "packages/pipelines/asset-pack/src/__tests__/reading-pipeline-contract.test.ts",
+ "readReviewRoute": "uapi/app/api/read-review/route.ts",
+ "readReviewRouteTest": "uapi/tests/api/readReviewRoute.test.ts",
+ "readReviewProtocolParityTest": "uapi/tests/api/readReviewProtocolParity.test.ts",
+ "terminalWorkbench": "uapi/app/terminal/TerminalDepositReadWorkbench.tsx",
+ "terminalUxState": "uapi/app/terminal/terminal-enterprise-reading-ux-state.ts",
+ "gateWorkflow": ".github/workflows/bitcode-gate-quality.yml",
+ "canonWorkflow": ".github/workflows/bitcode-canon-quality.yml",
+ "v42Spec": "BITCODE_SPEC_V42.md",
+ "v42Delta": "BITCODE_SPEC_V42_DELTA.md",
+ "v42Notes": "BITCODE_SPEC_V42_NOTES.md",
+ "v42Parity": "BITCODE_SPEC_V42_PARITY_MATRIX.md",
+ "roadmap": "SPECIFICATIONS_ROADMAP.md",
+ "rootReadme": "README.md",
+ "terminalReadme": "uapi/app/terminal/README.md",
+ "assetPackReadme": "packages/pipelines/asset-pack/README.md",
+ "protocolReadme": "packages/protocol/README.md"
+ }
+}
diff --git a/.github/workflows/bitcode-canon-quality.yml b/.github/workflows/bitcode-canon-quality.yml
index dc9f130b..13e5d697 100644
--- a/.github/workflows/bitcode-canon-quality.yml
+++ b/.github/workflows/bitcode-canon-quality.yml
@@ -301,6 +301,9 @@ jobs:
if [ -f scripts/check-v42-gate3-reading-shortest-path-state-machine.mjs ]; then
node scripts/check-v42-gate3-reading-shortest-path-state-machine.mjs --skip-branch-check --skip-uapi-tests
fi
+ if [ -f scripts/check-v42-gate4-readneed-review-resynthesis-product-closure.mjs ]; then
+ node scripts/check-v42-gate4-readneed-review-resynthesis-product-closure.mjs --skip-branch-check --skip-package-tests --skip-uapi-tests
+ fi
fi
else
echo "Unexpected BITCODE_SPEC.txt pointer: $POINTER" >&2
diff --git a/.github/workflows/bitcode-gate-quality.yml b/.github/workflows/bitcode-gate-quality.yml
index bf2440ee..82dc5ab8 100644
--- a/.github/workflows/bitcode-gate-quality.yml
+++ b/.github/workflows/bitcode-gate-quality.yml
@@ -430,6 +430,9 @@ jobs:
if [ -f scripts/check-v42-gate3-reading-shortest-path-state-machine.mjs ]; then
node scripts/check-v42-gate3-reading-shortest-path-state-machine.mjs --skip-branch-check --skip-uapi-tests
fi
+ if [ -f scripts/check-v42-gate4-readneed-review-resynthesis-product-closure.mjs ]; then
+ node scripts/check-v42-gate4-readneed-review-resynthesis-product-closure.mjs --skip-branch-check --skip-package-tests --skip-uapi-tests
+ fi
fi
else
echo "Unexpected BITCODE_SPEC.txt pointer: $POINTER" >&2
diff --git a/BITCODE_SPEC_V42.md b/BITCODE_SPEC_V42.md
index 7b85d98f..8c1ce389 100644
--- a/BITCODE_SPEC_V42.md
+++ b/BITCODE_SPEC_V42.md
@@ -132,6 +132,8 @@ Validating command: `pnpm run check:v42-gate3`.
Gate 4 must make `ReadNeedComprehensionSynthesis` product-ready in the MVP flow.
The pipeline must synthesize exactly the user's Need from the Read Request, store source-safe Need data, allow user feedback and resynthesis, preserve lineage, and admit Finding Fits only after the Need is accepted.
It must cover PTRR agents, FailsafeGenerationSequence, ThricifiedGeneration, prompts, parser return types, telemetry rows, database projection, tests, and UI readback.
+Gate 4 is implemented by `.bitcode/v42-readneed-review-resynthesis-product-closure.json`.
+The artifact binds `ReadNeedReviewResynthesisRuntime`, all four review actions, source-safe storage projection, rejection posture, accepted-Need admission into `ReadFitsFindingSynthesis`, Terminal runtime/storage/telemetry readback, and the package/API/protocol tests that prove the path.
## V42 Gate 5 ReadFitsFinding AssetPack Preview And Quote Closure
@@ -423,7 +425,7 @@ V42 inherits operator-quality expectations for browser proof, accessibility, vis
| `.bitcode/v42-canon-posture-drift-report.json` | `check-bitcode-canon-posture-drift` | source-safe metadata | active V41 / draft V42 posture proof |
| `.bitcode/v42-depositing-shortest-path.json` | V42 Gate 2 | source-safe metadata | deposit MVP proof |
| `.bitcode/v42-reading-shortest-path-state-machine.json` | V42 Gate 3 | source-safe metadata | Reading product state proof |
-| `.bitcode/v42-readneed-review-resynthesis.json` | V42 Gate 4 | source-safe metadata | Need review proof |
+| `.bitcode/v42-readneed-review-resynthesis-product-closure.json` | V42 Gate 4 | source-safe metadata | Need review proof |
| `.bitcode/v42-readfitsfinding-preview-quote.json` | V42 Gate 5 | source-safe metadata | Finding Fits, preview, and quote proof |
| `.bitcode/v42-settlement-rights-delivery.json` | V42 Gate 6 | source-safe metadata | settlement/delivery proof |
| `.bitcode/v42-ai-reading-demonstration.json` | V42 Gate 7 | source-safe metadata | demonstration value proof |
diff --git a/BITCODE_SPEC_V42_DELTA.md b/BITCODE_SPEC_V42_DELTA.md
index 33f29a47..36e45942 100644
--- a/BITCODE_SPEC_V42_DELTA.md
+++ b/BITCODE_SPEC_V42_DELTA.md
@@ -47,6 +47,7 @@ The state machine keeps Terminal guided by default while preserving proof-on-exp
### Gate 4: ReadNeed Review And Resynthesis Product Closure
Implement and prove reviewed synthesized Need flow, feedback/resynthesis, accepted-Need admission, storage projection, telemetry, and UI readback.
+Gate 4 now binds `ReadNeedReviewResynthesisRuntime` (`readNeedReviewRuntime` route payloads), all four ReadNeed actions, source-safe storage projection, accepted and rejected review states, PTRR/Failsafe/Thricified telemetry receipts, Terminal runtime/storage/telemetry readback, `.bitcode/v42-readneed-review-resynthesis-product-closure.json`, and `check:v42-gate4`.
### Gate 5: ReadFitsFinding AssetPack Preview And Quote Closure
diff --git a/BITCODE_SPEC_V42_NOTES.md b/BITCODE_SPEC_V42_NOTES.md
index 3ba0c620..098818f0 100644
--- a/BITCODE_SPEC_V42_NOTES.md
+++ b/BITCODE_SPEC_V42_NOTES.md
@@ -47,6 +47,14 @@ Gate 3 implements the current V42 state-machine layer with `TerminalEnterpriseRe
The recoverable route state includes transaction id presence, `readingStage`, active-stage hydration, retry and restart posture, source-safe failure kind, and repair actions.
This makes refresh, route handoff, and recovery inspectable without disclosing protected source, protected prompts, raw provider responses, unpaid AssetPack source, wallet private material, private settlement payloads, or ledger authority.
+## Gate 4 implementation notes
+
+Gate 4 closes the ReadNeed product loop.
+`ReadNeedComprehensionSynthesis` now has a V42 proof target for source-safe Read Request persistence, synthesized Need storage, feedback and resynthesis lineage, Need measurement roots, accepted Need admission, rejected Need posture, runtime storage projection, and telemetry receipts.
+The Terminal readback must show the Need, review state, runtime root, storage root, telemetry root, blockers, PTRR step identity, and storage record roots without exposing protected source, raw protected prompts, raw provider responses, unpaid AssetPack source, wallet private material, or private settlement payloads.
+Finding Fits remains blocked until the Need is accepted.
+Rejecting a Need must preserve feedback and keep the user on the review/resynthesis step.
+
## AssetPack source-safety note
V42 must make the preview valuable without leaking the source-bearing AssetPack before settlement.
diff --git a/BITCODE_SPEC_V42_PARITY_MATRIX.md b/BITCODE_SPEC_V42_PARITY_MATRIX.md
index 86f3f222..b87b9c7c 100644
--- a/BITCODE_SPEC_V42_PARITY_MATRIX.md
+++ b/BITCODE_SPEC_V42_PARITY_MATRIX.md
@@ -35,7 +35,7 @@ This matrix records the reliable MVP product surfaces that must become promotion
| Canon workflow | Canon quality knows active V41 / draft V42 posture and V42 Gate 1 | `.github/workflows/bitcode-canon-quality.yml` | drafted |
| Depositing shortest path | Source material can be admitted with Depository proof and compensation visibility | `.bitcode/v42-depositing-shortest-path.json`, `DepositorySupplyCompensationPreview`, `/api/deposits`, Terminal deposit readback | implemented |
| Reading state machine | Five-step Reading UX is route-owned, persistent, and source-safe | `.bitcode/v42-reading-shortest-path-state-machine.json`, `TerminalEnterpriseReadingRouteState`, `readingStage`, route/retry/failure tests | implemented |
-| ReadNeed product closure | Need synthesis, review, feedback, resynthesis, and accepted-Need admission are product-ready | later V42 Gate 4 artifact | draft-required |
+| ReadNeed product closure | Need synthesis, review, feedback, resynthesis, accepted-Need admission, rejected Need blockers, source-safe telemetry, and Terminal runtime readback are product-ready | `.bitcode/v42-readneed-review-resynthesis-product-closure.json`, `ReadNeedReviewResynthesisRuntime`, `/api/read-review`, Terminal Need runtime readback | implemented |
| Finding Fits preview and quote | Many-candidate search, selected-fit provenance, source-safe preview, and quote are product-ready | later V42 Gate 5 artifact | draft-required |
| Settlement and delivery | BTC/BTD settlement, rights transfer, compensation, and repository PR delivery are synchronized | later V42 Gate 6 artifact | draft-required |
| AI-reading demonstration | Standalone demonstration proves AssetPack improves AI beyond public-data-only baseline | later V42 Gate 7 artifact | draft-required |
@@ -49,7 +49,7 @@ This matrix records the reliable MVP product surfaces that must become promotion
| Gate 1 | Open V42 family, roadmap, docs, workflow posture, package script, and checker | drafted |
| Gate 2 | Depositing shortest path and compensation visibility artifact | implemented |
| Gate 3 | Reading shortest path state machine artifact | implemented |
-| Gate 4 | ReadNeed review and resynthesis product closure artifact | draft-required |
+| Gate 4 | ReadNeed review and resynthesis product closure artifact | implemented |
| Gate 5 | ReadFitsFinding AssetPack preview and quote closure artifact | draft-required |
| Gate 6 | Settlement rights transfer and repository delivery closure artifact | draft-required |
| Gate 7 | AI-reading dominant demonstration MVP artifact | draft-required |
diff --git a/README.md b/README.md
index 3a5b1077..48298c20 100644
--- a/README.md
+++ b/README.md
@@ -99,6 +99,13 @@ V42 Gate 3 adds the Reading shortest path state machine with
accepted-Need blockers, source-safe preview blockers,
`.bitcode/v42-reading-shortest-path-state-machine.json`, and
`check:v42-gate3`.
+V42 Gate 4 adds ReadNeed product closure with
+`ReadNeedReviewResynthesisRuntime`, source-safe storage projection,
+feedback/resynthesis lineage, accepted-Need Finding Fits admission,
+rejected Need blockers, PTRR/Failsafe/Thricified telemetry receipts,
+Terminal Need runtime readback,
+`.bitcode/v42-readneed-review-resynthesis-product-closure.json`, and
+`check:v42-gate4`.
V43+ is roadmapped as the later agentic depositing evolution: repository
agents synthesize deposit AssetPack options from connected enterprise code,
Depository state, and Reading demand; enterprises approve or reject
diff --git a/SPECIFICATIONS_ROADMAP.md b/SPECIFICATIONS_ROADMAP.md
index f328daae..7bd3c34c 100644
--- a/SPECIFICATIONS_ROADMAP.md
+++ b/SPECIFICATIONS_ROADMAP.md
@@ -5,12 +5,13 @@
- Current active canonical pointer: `BITCODE_SPEC.txt` -> `V41`
- Current active canon: `BITCODE_SPEC_V41.md`
- Current draft target: `BITCODE_SPEC_V42.md`.
-- Current working gate: V42 Gate 3 Reading Shortest Path State Machine.
-- Next queued gate after V42 Gate 3: V42 Gate 4 ReadNeed Review And Resynthesis Product Closure.
+- Current working gate: V42 Gate 4 ReadNeed Review And Resynthesis Product Closure.
+- Next queued gate after V42 Gate 4: V42 Gate 5 ReadFitsFinding AssetPack Preview And Quote Closure.
- Latest closed version: V41 Prompt And PromptPart Excellence, which promoted PromptPart and Prompt inventory, registry interpolation contracts, Reading prompt baselines, ReadNeedComprehensionSynthesis prompt hardening, ReadFitsFindingSynthesis prompt hardening, Conversation/tool/interface prompt rewrite, prompt benchmark telemetry, and V41 promotion readiness.
- Recent V42 opening anchor: reliable MVP experience opens over promoted V41 with V42 SPEC, DELTA, NOTES, and PARITY files, `check:v42-gate1`, active V41 / draft V42 posture, and a nine-gate plan for shortest-path Depositing, five-step Reading, ReadNeed product closure, ReadFitsFinding preview and quote closure, settlement and repository delivery, AI-reading demonstration, local/staging rehearsal, and promotion readiness.
- V42 Gate 2 closure anchor: reliable MVP experience now owns source-safe Depositing compensation visibility through `DepositorySupplyCompensationPreview`, deposit route `depositoryEvidence.compensationPreview`, deterministic `.bitcode/v42-depositing-shortest-path.json`, route/API readiness checks, source validation, Depository search/vector/storage projection, source-to-shares compensation readback keys, Terminal compensation roots, focused package/protocol tests, workflow wiring, and `check:v42-gate2`.
- V42 Gate 3 closure anchor: reliable MVP experience now owns the five-step Reading shortest path state machine through `TerminalEnterpriseReadingUxState`, `TerminalEnterpriseReadingRouteState`, recoverable transaction ids, `readingStage` route hydration, retry/restart posture, source-safe failure repair actions, accepted-Need blockers, source-safe preview blockers, rich Reading pipeline telemetry readback, deterministic `.bitcode/v42-reading-shortest-path-state-machine.json`, focused route/component/protocol tests, workflow wiring, and `check:v42-gate3`.
+- V42 Gate 4 closure anchor: reliable MVP experience now owns ReadNeed product closure through `ReadNeedReviewResynthesisRuntime`, source-safe storage projection, reviewed Need feedback/resynthesis lineage, accepted-Need Finding Fits admission, rejected Need blockers, PTRR/Failsafe/Thricified telemetry receipts, Terminal Need runtime/storage/telemetry readback, deterministic `.bitcode/v42-readneed-review-resynthesis-product-closure.json`, focused package/route/protocol tests, workflow wiring, and `check:v42-gate4`.
- Recent V41 closure anchor: V41 canonical promotion updated `BITCODE_SPEC.txt` to `V41`, generated `BITCODE_SPEC_V41_PROVEN.md`, preserved active V41 / draft V42 runtime posture, and closed prompt-program excellence canon.
- Recent V40 closure anchor: V40 canonical promotion updated `BITCODE_SPEC.txt` to `V40`, generated `BITCODE_SPEC_V40_PROVEN.md`, preserved active V40 / draft V41 runtime posture, and closed exhaustive commercial application testing canon.
- Recent V39 closure anchor: V39 canonical promotion updated `BITCODE_SPEC.txt` to `V39`, generated `BITCODE_SPEC_V39_PROVEN.md`, preserved active V39 / draft V40 runtime posture, and closed commercial Reading readiness canon.
diff --git a/package.json b/package.json
index e2a90f91..4cfaeee3 100644
--- a/package.json
+++ b/package.json
@@ -310,6 +310,9 @@
"generate:v42-reading-shortest-path-state-machine": "node scripts/generate-v42-reading-shortest-path-state-machine.mjs",
"check:v42-reading-shortest-path-state-machine": "node scripts/generate-v42-reading-shortest-path-state-machine.mjs --check",
"check:v42-gate3": "node scripts/check-v42-gate3-reading-shortest-path-state-machine.mjs",
+ "generate:v42-readneed-review-resynthesis-product-closure": "node scripts/generate-v42-readneed-review-resynthesis-product-closure.mjs",
+ "check:v42-readneed-review-resynthesis-product-closure": "node scripts/generate-v42-readneed-review-resynthesis-product-closure.mjs --check",
+ "check:v42-gate4": "node scripts/check-v42-gate4-readneed-review-resynthesis-product-closure.mjs",
"generate:v38-inference-surface-inventory": "node scripts/generate-v38-inference-surface-inventory.mjs",
"check:v38-inference-surface-inventory": "node scripts/generate-v38-inference-surface-inventory.mjs --check",
"check:v38-gate2": "node scripts/check-v38-gate2-inference-surface-inventory.mjs",
diff --git a/packages/pipelines/asset-pack/README.md b/packages/pipelines/asset-pack/README.md
index efcc5d76..051e9e77 100644
--- a/packages/pipelines/asset-pack/README.md
+++ b/packages/pipelines/asset-pack/README.md
@@ -139,6 +139,14 @@ for resynthesis. The runtime never serializes protected source, raw protected
prompts, raw provider responses, unpaid AssetPack source, credentials, wallet
private material, or private settlement payloads.
+V42 Gate 4 binds this runtime into product closure through
+`.bitcode/v42-readneed-review-resynthesis-product-closure.json` and
+`check:v42-gate4`. That proof requires all four review actions
+(`synthesize_read_need`, `resynthesize_read_need`, `accept_read_need`,
+`reject_read_need`), PTRR/Failsafe/Thricified telemetry receipts, source-safe
+storage projection, accepted-Need admission, rejected Need blockers, and
+Terminal runtime readback before Finding Fits can run.
+
## ReadFitsFinding Runtime
`ReadFitsFindingRuntime` is the source-safe package primitive that turns
diff --git a/packages/pipelines/asset-pack/src/__tests__/read-need-review-resynthesis.test.ts b/packages/pipelines/asset-pack/src/__tests__/read-need-review-resynthesis.test.ts
index 9be22ad3..43ce606e 100644
--- a/packages/pipelines/asset-pack/src/__tests__/read-need-review-resynthesis.test.ts
+++ b/packages/pipelines/asset-pack/src/__tests__/read-need-review-resynthesis.test.ts
@@ -66,6 +66,9 @@ describe('ReadNeed review, resynthesis, and admission runtime', () => {
'need_measurement',
'telemetry_receipt',
]);
+ expect(runtime.storageProjection.every((record) => record.sourceSafety.protectedSourceVisible === false)).toBe(true);
+ expect(runtime.storageProjection.every((record) => record.sourceSafety.rawProviderResponseVisible === false)).toBe(true);
+ expect(runtime.storageProjection.every((record) => record.sourceSafety.unpaidAssetPackSourceVisible === false)).toBe(true);
expect(runtime.telemetryReceipts[0]).toMatchObject({
pipelineName: 'ReadNeedComprehensionSynthesis',
needId: readNeed.needId,
diff --git a/packages/protocol/README.md b/packages/protocol/README.md
index 69f9b4ae..a32d34a9 100644
--- a/packages/protocol/README.md
+++ b/packages/protocol/README.md
@@ -201,6 +201,15 @@ V42 Gate 3 adds the V42 Reading shortest path state machine,
route persistence, accepted-Need gating, restart/retry/failure repair,
low-detail proof-on-expand UI posture, rich Reading pipeline telemetry
readback, activity/workbench readback, and source-safe disclosure boundaries.
+V42 Gate 4 adds `V42ReadNeedReviewResynthesisProductClosure` through
+`packages/protocol/src/canonical/v42-readneed-review-resynthesis-product-closure.js`,
+`packages/protocol/test/v42-readneed-review-resynthesis-product-closure.test.js`,
+`.bitcode/v42-readneed-review-resynthesis-product-closure.json`, and
+`check:v42-gate4`. It proves ReadNeed review/resynthesis product closure:
+source-safe Read Request and Need storage, feedback lineage, Need measurement,
+accepted-Need admission, rejected Need blockers, PTRR/Failsafe/Thricified
+telemetry receipts, `/api/read-review` action coverage, Terminal runtime
+readback, and source-safe disclosure boundaries.
V40 Gate 2 adds `V40TestInventoryCoverageMatrix` through
`packages/protocol/src/canonical/v40-test-inventory-coverage-matrix.js`,
`packages/protocol/test/v40-test-inventory-coverage-matrix.test.js`,
diff --git a/packages/protocol/src/canonical/v42-readneed-review-resynthesis-product-closure.js b/packages/protocol/src/canonical/v42-readneed-review-resynthesis-product-closure.js
new file mode 100644
index 00000000..895001af
--- /dev/null
+++ b/packages/protocol/src/canonical/v42-readneed-review-resynthesis-product-closure.js
@@ -0,0 +1,325 @@
+// @ts-check
+
+import crypto from 'node:crypto';
+import { existsSync, readFileSync } from 'node:fs';
+import path from 'node:path';
+import { fileURLToPath } from 'node:url';
+
+const __filename = fileURLToPath(import.meta.url);
+const __dirname = path.dirname(__filename);
+const DEFAULT_REPO_ROOT = path.resolve(__dirname, '..', '..', '..', '..');
+
+export const V42_READNEED_REVIEW_RESYNTHESIS_PRODUCT_CLOSURE_ARTIFACT_PATH =
+ '.bitcode/v42-readneed-review-resynthesis-product-closure.json';
+export const V42_READNEED_REVIEW_RESYNTHESIS_PRODUCT_CLOSURE_SCHEMA_ID =
+ 'bitcode.v42.readNeedReviewResynthesisProductClosure.v1';
+export const V42_READNEED_REVIEW_RESYNTHESIS_SCHEMA_ID =
+ V42_READNEED_REVIEW_RESYNTHESIS_PRODUCT_CLOSURE_SCHEMA_ID;
+export const V42_READNEED_REVIEW_RESYNTHESIS_PRODUCT_CLOSURE_VERSION = 'V42';
+export const V42_READNEED_REVIEW_RESYNTHESIS_PRODUCT_CLOSURE_CURRENT_TARGET = 'V41';
+export const V42_READNEED_REVIEW_RESYNTHESIS_PRODUCT_CLOSURE_SOURCE_SAFETY_VERDICT =
+ 'source-safe-readneed-review-resynthesis-product-closure-metadata';
+
+export const V42_READNEED_REVIEW_RESYNTHESIS_PRODUCT_CLOSURE_ROW_IDS = Object.freeze([
+ 'request:read-request-persistence',
+ 'pipeline:ptrr-failsafe-thricified-need-synthesis',
+ 'need:synthesized-need-storage',
+ 'feedback:review-resynthesis-lineage',
+ 'measurement:need-measurement-storage',
+ 'admission:accepted-need-gates-finding-fits',
+ 'rejection:rejected-need-posture',
+ 'telemetry:source-safe-runtime-receipts',
+ 'route:read-review-actions',
+ 'ui:terminal-need-runtime-readback',
+ 'proof:tests-artifact-workflow',
+]);
+
+const SOURCE_ROOTS = Object.freeze({
+ readNeed: 'packages/pipelines/asset-pack/src/read-need.ts',
+ readNeedRuntime: 'packages/pipelines/asset-pack/src/read-need-review-resynthesis.ts',
+ readingPipelineContract: 'packages/pipelines/asset-pack/src/reading-pipeline-contract.ts',
+ packageIndex: 'packages/pipelines/asset-pack/src/index.ts',
+ packageJson: 'packages/pipelines/asset-pack/package.json',
+ readNeedTest: 'packages/pipelines/asset-pack/src/__tests__/read-need.test.ts',
+ runtimeTest: 'packages/pipelines/asset-pack/src/__tests__/read-need-review-resynthesis.test.ts',
+ readingContractTest: 'packages/pipelines/asset-pack/src/__tests__/reading-pipeline-contract.test.ts',
+ readReviewRoute: 'uapi/app/api/read-review/route.ts',
+ readReviewRouteTest: 'uapi/tests/api/readReviewRoute.test.ts',
+ readReviewProtocolParityTest: 'uapi/tests/api/readReviewProtocolParity.test.ts',
+ terminalWorkbench: 'uapi/app/terminal/TerminalDepositReadWorkbench.tsx',
+ terminalUxState: 'uapi/app/terminal/terminal-enterprise-reading-ux-state.ts',
+ gateWorkflow: '.github/workflows/bitcode-gate-quality.yml',
+ canonWorkflow: '.github/workflows/bitcode-canon-quality.yml',
+ v42Spec: 'BITCODE_SPEC_V42.md',
+ v42Delta: 'BITCODE_SPEC_V42_DELTA.md',
+ v42Notes: 'BITCODE_SPEC_V42_NOTES.md',
+ v42Parity: 'BITCODE_SPEC_V42_PARITY_MATRIX.md',
+ roadmap: 'SPECIFICATIONS_ROADMAP.md',
+ rootReadme: 'README.md',
+ terminalReadme: 'uapi/app/terminal/README.md',
+ assetPackReadme: 'packages/pipelines/asset-pack/README.md',
+ protocolReadme: 'packages/protocol/README.md',
+});
+
+const FORBIDDEN_PAYLOAD_CLASSES = Object.freeze([
+ 'protected-source-payloads',
+ 'raw-protected-prompts',
+ 'raw-provider-responses',
+ 'unpaid-assetpack-source',
+ 'wallet-private-material',
+ 'settlement-private-payloads',
+ 'secret-values',
+]);
+
+function digest(value) {
+ return crypto.createHash('sha256').update(value).digest('hex').slice(0, 24);
+}
+
+function rowRoot(id) {
+ return `v42-readneed-review-resynthesis-product-closure-row:${digest(id)}`;
+}
+
+function readSource(repoRoot, sourcePath) {
+ const absolutePath = path.join(repoRoot, sourcePath);
+ return existsSync(absolutePath) ? readFileSync(absolutePath, 'utf8') : '';
+}
+
+function predicateResult(id, sourcePath, passed) {
+ return { id, sourcePath, passed: Boolean(passed) };
+}
+
+function row(input) {
+ return {
+ ...input,
+ rowRoot: rowRoot(input.rowId),
+ sourceSafetyClass: 'source_safe_readneed_review_resynthesis_product_closure_metadata',
+ sourceSafeMetadataOnly: true,
+ protectedSourceVisible: false,
+ rawProtectedPromptVisible: false,
+ rawProviderResponseVisible: false,
+ unpaidAssetPackSourceVisible: false,
+ walletPrivateMaterialVisible: false,
+ settlementPrivatePayloadVisible: false,
+ credentialsSerialized: false,
+ forbiddenPayloadClasses: [...FORBIDDEN_PAYLOAD_CLASSES],
+ };
+}
+
+export const V42_READNEED_REVIEW_RESYNTHESIS_PRODUCT_CLOSURE_ROWS = Object.freeze([
+ row({
+ rowId: 'request:read-request-persistence',
+ purpose:
+ 'Persist source-safe Read Request data with repository, branch, commit, target artifact kinds, closure criteria, failure modes, feedback, and previous Need lineage.',
+ sourceRoots: [SOURCE_ROOTS.readNeed, SOURCE_ROOTS.readNeedRuntime, SOURCE_ROOTS.readReviewRoute],
+ emittedTypes: ['ReadNeedRequest', 'ReadNeedReviewStorageRecord'],
+ requiredEvidence: ['bitcode.read.request', 'read_request', 'previousNeedId'],
+ }),
+ row({
+ rowId: 'pipeline:ptrr-failsafe-thricified-need-synthesis',
+ purpose:
+ 'Keep ReadNeedComprehensionSynthesis product-owned by PTRR agents whose steps carry FailsafeGenerationSequence over ThricifiedGeneration contracts and typed parser output.',
+ sourceRoots: [SOURCE_ROOTS.readNeed, SOURCE_ROOTS.readingPipelineContract, SOURCE_ROOTS.readNeedTest],
+ emittedTypes: ['ReadNeedComprehensionSynthesisInferenceReceipt', 'ReadingPipelineContract'],
+ requiredEvidence: ['ptrrStepIds', 'failsafeSequenceIds', 'thricifiedGenerationIds', 'ReadNeedComprehensionSynthesis.prompt.need-synthesis'],
+ }),
+ row({
+ rowId: 'need:synthesized-need-storage',
+ purpose:
+ 'Persist reviewable synthesized Need output before Finding Fits, including requirements, target artifacts, source constraints, proof expectations, and review state.',
+ sourceRoots: [SOURCE_ROOTS.readNeed, SOURCE_ROOTS.readNeedRuntime, SOURCE_ROOTS.runtimeTest],
+ emittedTypes: ['ReadNeed', 'synthesized_need'],
+ requiredEvidence: ['bitcode.read.need', 'needs_acceptance', 'synthesized_need'],
+ }),
+ row({
+ rowId: 'feedback:review-resynthesis-lineage',
+ purpose:
+ 'Preserve user feedback and resynthesis attempts so every new Need stays linked to the prior Need and reviewed feedback.',
+ sourceRoots: [SOURCE_ROOTS.readNeed, SOURCE_ROOTS.readNeedRuntime, SOURCE_ROOTS.readReviewRouteTest, SOURCE_ROOTS.terminalWorkbench],
+ emittedTypes: ['resynthesis_attempt', 'feedbackHistory'],
+ requiredEvidence: ['previousNeedId', 'resynthesize_read_need', 'resynthesis_attempt'],
+ }),
+ row({
+ rowId: 'measurement:need-measurement-storage',
+ purpose:
+ 'Persist Need measurement roots and pricing measurement inputs that later drive deterministic preview quotes without exposing source.',
+ sourceRoots: [SOURCE_ROOTS.readNeed, SOURCE_ROOTS.readNeedRuntime, SOURCE_ROOTS.readNeedTest],
+ emittedTypes: ['ReadNeedMeasurementDimension', 'need_measurement'],
+ requiredEvidence: ['measurementRoot', 'pricingMeasurementInputs', 'shareToFeeFormula'],
+ }),
+ row({
+ rowId: 'admission:accepted-need-gates-finding-fits',
+ purpose:
+ 'Persist accepted-Need admission as the only source-safe handoff into ReadFitsFindingSynthesis and block Finding Fits without acceptance.',
+ sourceRoots: [SOURCE_ROOTS.readNeed, SOURCE_ROOTS.readNeedRuntime, SOURCE_ROOTS.readReviewRouteTest, SOURCE_ROOTS.terminalUxState],
+ emittedTypes: ['ReadFitsFindingAdmission', 'accepted_need_admission'],
+ requiredEvidence: ['accept_read_need', 'accepted_need_admission', 'accepted_read_need_missing'],
+ }),
+ row({
+ rowId: 'rejection:rejected-need-posture',
+ purpose:
+ 'Persist rejected-Need posture with rejection root, feedback, blocked Finding Fits stage, and repair/resynthesis next action.',
+ sourceRoots: [SOURCE_ROOTS.readNeed, SOURCE_ROOTS.readNeedRuntime, SOURCE_ROOTS.readReviewRouteTest, SOURCE_ROOTS.terminalWorkbench],
+ emittedTypes: ['RejectedReadNeed', 'rejected_need_posture'],
+ requiredEvidence: ['rejectReadNeed', 'reject_read_need', 'read_need_rejected'],
+ }),
+ row({
+ rowId: 'telemetry:source-safe-runtime-receipts',
+ purpose:
+ 'Emit source-safe telemetry receipts containing phase, PTRR step, Failsafe, ThricifiedGeneration, prompt-template, output-schema, and proof-root identities.',
+ sourceRoots: [SOURCE_ROOTS.readNeed, SOURCE_ROOTS.readNeedRuntime, SOURCE_ROOTS.readingPipelineContract, SOURCE_ROOTS.readReviewRoute],
+ emittedTypes: ['ReadNeedReviewTelemetryReceipt', 'ReadNeedComprehensionSynthesisInferenceReceipt'],
+ requiredEvidence: ['ptrrStepIds', 'failsafeSequenceIds', 'thricifiedGenerationIds', 'promptTemplateIds'],
+ }),
+ row({
+ rowId: 'route:read-review-actions',
+ purpose:
+ 'Expose synthesize, resynthesize, accept, and reject actions through the Read review route with storage projection, runtime summary, source-safe telemetry, and Finding Fits admission readback.',
+ sourceRoots: [SOURCE_ROOTS.readReviewRoute, SOURCE_ROOTS.readReviewRouteTest],
+ emittedTypes: ['readNeedReviewRuntime', 'storageProjection', 'runtimeSummary'],
+ requiredEvidence: ['synthesize_read_need', 'resynthesize_read_need', 'accept_read_need', 'reject_read_need'],
+ }),
+ row({
+ rowId: 'ui:terminal-need-runtime-readback',
+ purpose:
+ 'Expose the reviewed Need, feedback loop, rejection path, storage projection, runtime roots, telemetry return type, and Finding Fits blocker/admission state in Terminal without protected source.',
+ sourceRoots: [SOURCE_ROOTS.terminalWorkbench, SOURCE_ROOTS.terminalReadme],
+ emittedTypes: ['TerminalReadNeedReviewRuntimeState', 'Need runtime, storage, and telemetry'],
+ requiredEvidence: ['Reject Read-Need', 'readNeedStorageProjection', 'readNeedTelemetry', 'Need runtime, storage, and telemetry'],
+ }),
+ row({
+ rowId: 'proof:tests-artifact-workflow',
+ purpose:
+ 'Bind V42 Gate 4 closure to package tests, route tests, protocol artifact tests, docs, scripts, and gate/canon workflow checks.',
+ sourceRoots: [
+ SOURCE_ROOTS.runtimeTest,
+ SOURCE_ROOTS.readReviewRouteTest,
+ SOURCE_ROOTS.gateWorkflow,
+ SOURCE_ROOTS.canonWorkflow,
+ SOURCE_ROOTS.v42Spec,
+ SOURCE_ROOTS.v42Parity,
+ SOURCE_ROOTS.roadmap,
+ ],
+ emittedTypes: ['V42ReadNeedReviewResynthesisProductClosure'],
+ requiredEvidence: ['check-v42-gate4-readneed-review-resynthesis-product-closure.mjs', 'v42-readneed-review-resynthesis-product-closure'],
+ }),
+]);
+
+function buildPredicateResults(repoRoot) {
+ const readNeed = readSource(repoRoot, SOURCE_ROOTS.readNeed);
+ const runtime = readSource(repoRoot, SOURCE_ROOTS.readNeedRuntime);
+ const contract = readSource(repoRoot, SOURCE_ROOTS.readingPipelineContract);
+ const packageIndex = readSource(repoRoot, SOURCE_ROOTS.packageIndex);
+ const packageJson = readSource(repoRoot, SOURCE_ROOTS.packageJson);
+ const readNeedTest = readSource(repoRoot, SOURCE_ROOTS.readNeedTest);
+ const runtimeTest = readSource(repoRoot, SOURCE_ROOTS.runtimeTest);
+ const contractTest = readSource(repoRoot, SOURCE_ROOTS.readingContractTest);
+ const route = readSource(repoRoot, SOURCE_ROOTS.readReviewRoute);
+ const routeTest = readSource(repoRoot, SOURCE_ROOTS.readReviewRouteTest);
+ const protocolParityTest = readSource(repoRoot, SOURCE_ROOTS.readReviewProtocolParityTest);
+ const terminalWorkbench = readSource(repoRoot, SOURCE_ROOTS.terminalWorkbench);
+ const terminalUxState = readSource(repoRoot, SOURCE_ROOTS.terminalUxState);
+ const gateWorkflow = readSource(repoRoot, SOURCE_ROOTS.gateWorkflow);
+ const canonWorkflow = readSource(repoRoot, SOURCE_ROOTS.canonWorkflow);
+ const spec = readSource(repoRoot, SOURCE_ROOTS.v42Spec);
+ const delta = readSource(repoRoot, SOURCE_ROOTS.v42Delta);
+ const notes = readSource(repoRoot, SOURCE_ROOTS.v42Notes);
+ const parity = readSource(repoRoot, SOURCE_ROOTS.v42Parity);
+ const roadmap = readSource(repoRoot, SOURCE_ROOTS.roadmap);
+ const rootReadme = readSource(repoRoot, SOURCE_ROOTS.rootReadme);
+ const terminalReadme = readSource(repoRoot, SOURCE_ROOTS.terminalReadme);
+ const assetPackReadme = readSource(repoRoot, SOURCE_ROOTS.assetPackReadme);
+ const protocolReadme = readSource(repoRoot, SOURCE_ROOTS.protocolReadme);
+
+ return [
+ predicateResult('read-need-defines-review-states', SOURCE_ROOTS.readNeed, readNeed.includes("'needs_acceptance'") && readNeed.includes("'accepted'") && readNeed.includes("'rejected'")),
+ predicateResult('read-need-accept-and-reject-actions', SOURCE_ROOTS.readNeed, readNeed.includes('acceptReadNeed') && readNeed.includes('rejectReadNeed') && readNeed.includes('read_need_rejected')),
+ predicateResult('inference-receipt-covers-ptrr-failsafe-thricified', SOURCE_ROOTS.readNeed, readNeed.includes('ReadNeedComprehensionSynthesisInferenceReceipt') && readNeed.includes('failsafeSequenceIds') && readNeed.includes('thricifiedGenerationIds') && readNeed.includes('promptTemplateIds')),
+ predicateResult('contract-has-four-phases-and-sixteen-steps', SOURCE_ROOTS.readingPipelineContract, contract.includes('ReadNeedComprehensionSynthesis.request') && contract.includes('ReadNeedComprehensionSynthesis.review') && contract.includes('ptrrStepCount') && contract.includes('thricifiedGenerationCount')),
+ predicateResult('runtime-defines-storage-records', SOURCE_ROOTS.readNeedRuntime, runtime.includes('ReadNeedReviewStorageRecord') && runtime.includes('read_request') && runtime.includes('synthesized_need') && runtime.includes('need_measurement')),
+ predicateResult('runtime-defines-resynthesis-admission-rejection', SOURCE_ROOTS.readNeedRuntime, runtime.includes('resynthesis_attempt') && runtime.includes('accepted_need_admission') && runtime.includes('rejected_need_posture')),
+ predicateResult('runtime-source-safety', SOURCE_ROOTS.readNeedRuntime, runtime.includes('source_safe_read_need_review_resynthesis_metadata') && runtime.includes('protectedSourceVisible: false') && runtime.includes('rawProviderResponseVisible: false') && runtime.includes('unpaidAssetPackSourceVisible: false')),
+ predicateResult('runtime-persists-to-execution-store', SOURCE_ROOTS.readNeedRuntime, runtime.includes('persistReadNeedReviewResynthesisRuntime') && runtime.includes("execution?.store?.('read-need-review'")),
+ predicateResult('package-exports-runtime', SOURCE_ROOTS.packageIndex, packageIndex.includes("export * from './read-need-review-resynthesis'") && packageJson.includes('./read-need-review-resynthesis')),
+ predicateResult('package-tests-cover-runtime', SOURCE_ROOTS.runtimeTest, runtimeTest.includes('ReadNeed review, resynthesis, and admission runtime') && runtimeTest.includes('rejected_need_posture')),
+ predicateResult('read-need-tests-cover-real-inference-receipts', SOURCE_ROOTS.readNeedTest, readNeedTest.includes('real-inference ReadNeedComprehension') && readNeedTest.includes('thricified-generation') && readNeedTest.includes('accepted_read_need_missing')),
+ predicateResult('contract-tests-cover-review-output', SOURCE_ROOTS.readingContractTest, contractTest.includes('ReadNeedComprehensionSynthesis') && contractTest.includes('ptrrStepCount: 16')),
+ predicateResult('route-exposes-all-review-actions', SOURCE_ROOTS.readReviewRoute, route.includes('synthesize_read_need') && route.includes('resynthesize_read_need') && route.includes('accept_read_need') && route.includes('reject_read_need')),
+ predicateResult('route-persists-all-runtime-actions', SOURCE_ROOTS.readReviewRoute, route.match(/persistReadNeedReviewResynthesisRuntime/g)?.length >= 3),
+ predicateResult('route-returns-runtime-projection', SOURCE_ROOTS.readReviewRoute, route.includes('readNeedReviewRuntime') && route.includes('storageProjection') && route.includes('runtimeSummary')),
+ predicateResult('route-tests-cover-runtime-and-rejection', SOURCE_ROOTS.readReviewRouteTest, routeTest.includes('readNeedReviewRuntime') && routeTest.includes('reject_read_need') && routeTest.includes('rejected_need_posture')),
+ predicateResult('protocol-parity-keeps-finding-fits-blocked', SOURCE_ROOTS.readReviewProtocolParityTest, protocolParityTest.includes('Finding Fits cannot proceed') && protocolParityTest.includes('fitSearchAdmission')),
+ predicateResult('terminal-ui-exposes-runtime-readback', SOURCE_ROOTS.terminalWorkbench, terminalWorkbench.includes('TerminalReadNeedReviewRuntimeState') && terminalWorkbench.includes('readNeedStorageProjection') && terminalWorkbench.includes('readNeedTelemetry') && terminalWorkbench.includes('Need runtime, storage, and telemetry')),
+ predicateResult('terminal-ui-exposes-rejection', SOURCE_ROOTS.terminalWorkbench, terminalWorkbench.includes('handleRejectReadNeed') && terminalWorkbench.includes('Reject Read-Need') && terminalWorkbench.includes('reject_read_need')),
+ predicateResult('terminal-ux-keeps-accepted-need-gate', SOURCE_ROOTS.terminalUxState, terminalUxState.includes('acceptedNeedRequiredBeforeFindingFits') && terminalUxState.includes('sourceSafePreviewBlocked')),
+ predicateResult('spec-gate4-expanded', SOURCE_ROOTS.v42Spec, spec.includes('V42 Gate 4') && spec.includes('v42-readneed-review-resynthesis-product-closure')),
+ predicateResult('delta-gate4-expanded', SOURCE_ROOTS.v42Delta, delta.includes('Gate 4') && delta.includes('readNeedReviewRuntime')),
+ predicateResult('notes-gate4-expanded', SOURCE_ROOTS.v42Notes, notes.includes('Gate 4 implementation notes') && notes.includes('rejected Need posture')),
+ predicateResult('parity-gate4-implemented', SOURCE_ROOTS.v42Parity, parity.includes('ReadNeed product closure') && parity.includes('implemented')),
+ predicateResult('roadmap-advanced-to-gate4', SOURCE_ROOTS.roadmap, roadmap.includes('V42 Gate 4 closure anchor') && roadmap.includes('ReadNeedReviewResynthesisRuntime')),
+ predicateResult('readmes-document-gate4', SOURCE_ROOTS.rootReadme, rootReadme.includes('V42 Gate 4') && terminalReadme.includes('ReadNeedReviewResynthesisRuntime') && assetPackReadme.includes('ReadNeed review') && protocolReadme.includes('V42ReadNeedReviewResynthesisProductClosure')),
+ predicateResult('workflows-run-gate4-check', SOURCE_ROOTS.gateWorkflow, gateWorkflow.includes('check-v42-gate4-readneed-review-resynthesis-product-closure.mjs') && canonWorkflow.includes('check-v42-gate4-readneed-review-resynthesis-product-closure.mjs')),
+ ];
+}
+
+export function buildV42ReadNeedReviewResynthesisProductClosure(options = {}) {
+ const repoRoot = options.repoRoot || DEFAULT_REPO_ROOT;
+ const predicateResults = buildPredicateResults(repoRoot);
+ const failedPredicateIds = predicateResults
+ .filter((predicate) => !predicate.passed)
+ .map((predicate) => predicate.id);
+ const rowRoots = V42_READNEED_REVIEW_RESYNTHESIS_PRODUCT_CLOSURE_ROWS.map((item) => item.rowRoot);
+ const artifactRoot = `v42-readneed-review-resynthesis-product-closure:${digest(JSON.stringify({
+ rowRoots,
+ failedPredicateIds,
+ }))}`;
+
+ return {
+ artifactId: 'v42-readneed-review-resynthesis-product-closure',
+ schemaId: V42_READNEED_REVIEW_RESYNTHESIS_PRODUCT_CLOSURE_SCHEMA_ID,
+ version: V42_READNEED_REVIEW_RESYNTHESIS_PRODUCT_CLOSURE_VERSION,
+ currentTarget: V42_READNEED_REVIEW_RESYNTHESIS_PRODUCT_CLOSURE_CURRENT_TARGET,
+ sourceSafetyVerdict: V42_READNEED_REVIEW_RESYNTHESIS_PRODUCT_CLOSURE_SOURCE_SAFETY_VERDICT,
+ generatedAt: 'deterministic',
+ artifactRoot,
+ passed: failedPredicateIds.length === 0,
+ rows: V42_READNEED_REVIEW_RESYNTHESIS_PRODUCT_CLOSURE_ROWS,
+ rowIds: [...V42_READNEED_REVIEW_RESYNTHESIS_PRODUCT_CLOSURE_ROW_IDS],
+ predicateResults,
+ coverage: {
+ rowCount: V42_READNEED_REVIEW_RESYNTHESIS_PRODUCT_CLOSURE_ROWS.length,
+ requiredPredicateCount: predicateResults.length,
+ passedPredicateCount: predicateResults.length - failedPredicateIds.length,
+ failedPredicateIds,
+ pipelineName: 'ReadNeedComprehensionSynthesis',
+ nextPipelineName: 'ReadFitsFindingSynthesis',
+ actions: ['synthesize_read_need', 'resynthesize_read_need', 'accept_read_need', 'reject_read_need'],
+ persistedRecordKinds: [
+ 'read_request',
+ 'synthesized_need',
+ 'feedback',
+ 'resynthesis_attempt',
+ 'need_measurement',
+ 'accepted_need_admission',
+ 'rejected_need_posture',
+ 'telemetry_receipt',
+ ],
+ phaseCount: 4,
+ ptrrStepCount: 16,
+ failsafeSequenceCount: 48,
+ thricifiedGenerationCount: 48,
+ acceptedNeedRequiredForFindingFits: true,
+ rejectedNeedBlocksFindingFits: true,
+ terminalRuntimeReadbackCovered: true,
+ sourceSafeMetadataOnly: true,
+ protectedSourceVisible: false,
+ rawProtectedPromptVisible: false,
+ rawProviderResponseVisible: false,
+ unpaidAssetPackSourceVisible: false,
+ walletPrivateMaterialVisible: false,
+ settlementPrivatePayloadVisible: false,
+ credentialsSerialized: false,
+ legacySourceRoots: Object.values(SOURCE_ROOTS).some((sourcePath) => sourcePath.includes('_legacy/')),
+ },
+ sourceRoots: SOURCE_ROOTS,
+ };
+}
diff --git a/packages/protocol/src/index.d.ts b/packages/protocol/src/index.d.ts
index 7bef5cb2..eee3699b 100644
--- a/packages/protocol/src/index.d.ts
+++ b/packages/protocol/src/index.d.ts
@@ -529,6 +529,15 @@ export const V42_READING_SHORTEST_PATH_STEP_IDS: readonly string[];
export const V42_READING_SHORTEST_PATH_ROW_IDS: readonly string[];
export const V42_READING_SHORTEST_PATH_ROWS: readonly Record[];
export function buildV42ReadingShortestPathStateMachine(input?: Record): BitcodeProtocolReport;
+export const V42_READNEED_REVIEW_RESYNTHESIS_PRODUCT_CLOSURE_ARTIFACT_PATH: string;
+export const V42_READNEED_REVIEW_RESYNTHESIS_PRODUCT_CLOSURE_CURRENT_TARGET: string;
+export const V42_READNEED_REVIEW_RESYNTHESIS_PRODUCT_CLOSURE_SCHEMA_ID: string;
+export const V42_READNEED_REVIEW_RESYNTHESIS_SCHEMA_ID: string;
+export const V42_READNEED_REVIEW_RESYNTHESIS_PRODUCT_CLOSURE_VERSION: string;
+export const V42_READNEED_REVIEW_RESYNTHESIS_PRODUCT_CLOSURE_SOURCE_SAFETY_VERDICT: string;
+export const V42_READNEED_REVIEW_RESYNTHESIS_PRODUCT_CLOSURE_ROW_IDS: readonly string[];
+export const V42_READNEED_REVIEW_RESYNTHESIS_PRODUCT_CLOSURE_ROWS: readonly Record[];
+export function buildV42ReadNeedReviewResynthesisProductClosure(input?: Record): BitcodeProtocolReport;
export const EXCHANGE_INTENT_ORDER_CONTRACTS_ARTIFACT_PATH: string;
export const EXCHANGE_INTENT_ORDER_CONTRACTS_CURRENT_TARGET: string;
export const EXCHANGE_INTENT_ORDER_CONTRACTS_SCHEMA_ID: string;
diff --git a/packages/protocol/src/index.js b/packages/protocol/src/index.js
index 7f07b1c9..358610d2 100644
--- a/packages/protocol/src/index.js
+++ b/packages/protocol/src/index.js
@@ -591,6 +591,17 @@ export {
V42_READING_SHORTEST_PATH_STEP_IDS,
buildV42ReadingShortestPathStateMachine
} from './canonical/v42-reading-shortest-path-state-machine.js';
+export {
+ V42_READNEED_REVIEW_RESYNTHESIS_PRODUCT_CLOSURE_ARTIFACT_PATH,
+ V42_READNEED_REVIEW_RESYNTHESIS_PRODUCT_CLOSURE_CURRENT_TARGET,
+ V42_READNEED_REVIEW_RESYNTHESIS_PRODUCT_CLOSURE_ROW_IDS,
+ V42_READNEED_REVIEW_RESYNTHESIS_PRODUCT_CLOSURE_ROWS,
+ V42_READNEED_REVIEW_RESYNTHESIS_PRODUCT_CLOSURE_SCHEMA_ID,
+ V42_READNEED_REVIEW_RESYNTHESIS_PRODUCT_CLOSURE_SOURCE_SAFETY_VERDICT,
+ V42_READNEED_REVIEW_RESYNTHESIS_PRODUCT_CLOSURE_VERSION,
+ V42_READNEED_REVIEW_RESYNTHESIS_SCHEMA_ID,
+ buildV42ReadNeedReviewResynthesisProductClosure
+} from './canonical/v42-readneed-review-resynthesis-product-closure.js';
export {
EXCHANGE_INTENT_ACTION_KINDS,
EXCHANGE_INTENT_ORDER_CONTRACTS_ARTIFACT_PATH,
diff --git a/packages/protocol/test/v42-readneed-review-resynthesis-product-closure.test.js b/packages/protocol/test/v42-readneed-review-resynthesis-product-closure.test.js
new file mode 100644
index 00000000..277ee41c
--- /dev/null
+++ b/packages/protocol/test/v42-readneed-review-resynthesis-product-closure.test.js
@@ -0,0 +1,73 @@
+import assert from 'node:assert/strict';
+import test from 'node:test';
+
+import {
+ V42_READNEED_REVIEW_RESYNTHESIS_PRODUCT_CLOSURE_ARTIFACT_PATH,
+ V42_READNEED_REVIEW_RESYNTHESIS_PRODUCT_CLOSURE_ROWS,
+ V42_READNEED_REVIEW_RESYNTHESIS_PRODUCT_CLOSURE_ROW_IDS,
+ V42_READNEED_REVIEW_RESYNTHESIS_PRODUCT_CLOSURE_SCHEMA_ID,
+ V42_READNEED_REVIEW_RESYNTHESIS_PRODUCT_CLOSURE_SOURCE_SAFETY_VERDICT,
+ V42_READNEED_REVIEW_RESYNTHESIS_SCHEMA_ID,
+ buildV42ReadNeedReviewResynthesisProductClosure,
+} from '../src/canonical/v42-readneed-review-resynthesis-product-closure.js';
+
+test('V42 ReadNeed review and resynthesis product closure binds the accepted Need gate', () => {
+ const report = buildV42ReadNeedReviewResynthesisProductClosure();
+
+ assert.equal(
+ V42_READNEED_REVIEW_RESYNTHESIS_PRODUCT_CLOSURE_ARTIFACT_PATH,
+ '.bitcode/v42-readneed-review-resynthesis-product-closure.json',
+ );
+ assert.equal(report.artifactId, 'v42-readneed-review-resynthesis-product-closure');
+ assert.equal(report.schemaId, V42_READNEED_REVIEW_RESYNTHESIS_PRODUCT_CLOSURE_SCHEMA_ID);
+ assert.equal(report.schemaId, V42_READNEED_REVIEW_RESYNTHESIS_SCHEMA_ID);
+ assert.equal(report.version, 'V42');
+ assert.equal(report.currentTarget, 'V41');
+ assert.equal(report.sourceSafetyVerdict, V42_READNEED_REVIEW_RESYNTHESIS_PRODUCT_CLOSURE_SOURCE_SAFETY_VERDICT);
+ assert.equal(report.passed, true);
+ assert.deepEqual(report.rowIds, [...V42_READNEED_REVIEW_RESYNTHESIS_PRODUCT_CLOSURE_ROW_IDS]);
+ assert.equal(report.rows.length, V42_READNEED_REVIEW_RESYNTHESIS_PRODUCT_CLOSURE_ROWS.length);
+ assert.equal(report.coverage.rowCount, 11);
+ assert.equal(report.coverage.phaseCount, 4);
+ assert.equal(report.coverage.ptrrStepCount, 16);
+ assert.equal(report.coverage.failsafeSequenceCount, 48);
+ assert.equal(report.coverage.thricifiedGenerationCount, 48);
+ assert.deepEqual(report.coverage.actions, [
+ 'synthesize_read_need',
+ 'resynthesize_read_need',
+ 'accept_read_need',
+ 'reject_read_need',
+ ]);
+ assert.equal(report.coverage.acceptedNeedRequiredForFindingFits, true);
+ assert.equal(report.coverage.rejectedNeedBlocksFindingFits, true);
+ assert.equal(report.coverage.terminalRuntimeReadbackCovered, true);
+ assert.equal(report.coverage.sourceSafeMetadataOnly, true);
+ assert.equal(report.coverage.protectedSourceVisible, false);
+ assert.equal(report.coverage.rawProtectedPromptVisible, false);
+ assert.equal(report.coverage.rawProviderResponseVisible, false);
+ assert.equal(report.coverage.unpaidAssetPackSourceVisible, false);
+ assert.equal(report.coverage.walletPrivateMaterialVisible, false);
+ assert.equal(report.coverage.settlementPrivatePayloadVisible, false);
+ assert.equal(report.coverage.credentialsSerialized, false);
+ assert.equal(report.coverage.legacySourceRoots, false);
+ assert.deepEqual(report.coverage.failedPredicateIds, []);
+ assert.ok(report.artifactRoot.startsWith('v42-readneed-review-resynthesis-product-closure:'));
+});
+
+test('V42 ReadNeed review rows remain source-safe metadata', () => {
+ for (const row of V42_READNEED_REVIEW_RESYNTHESIS_PRODUCT_CLOSURE_ROWS) {
+ assert.ok(row.rowRoot.startsWith('v42-readneed-review-resynthesis-product-closure-row:'));
+ assert.equal(row.sourceSafetyClass, 'source_safe_readneed_review_resynthesis_product_closure_metadata');
+ assert.equal(row.sourceSafeMetadataOnly, true);
+ assert.equal(row.protectedSourceVisible, false);
+ assert.equal(row.rawProtectedPromptVisible, false);
+ assert.equal(row.rawProviderResponseVisible, false);
+ assert.equal(row.unpaidAssetPackSourceVisible, false);
+ assert.equal(row.walletPrivateMaterialVisible, false);
+ assert.equal(row.settlementPrivatePayloadVisible, false);
+ assert.equal(row.credentialsSerialized, false);
+ assert.ok(row.forbiddenPayloadClasses.includes('protected-source-payloads'));
+ assert.ok(row.forbiddenPayloadClasses.includes('raw-provider-responses'));
+ assert.ok(row.forbiddenPayloadClasses.includes('unpaid-assetpack-source'));
+ }
+});
diff --git a/scripts/check-v42-gate4-readneed-review-resynthesis-product-closure.mjs b/scripts/check-v42-gate4-readneed-review-resynthesis-product-closure.mjs
new file mode 100644
index 00000000..d52bc7d3
--- /dev/null
+++ b/scripts/check-v42-gate4-readneed-review-resynthesis-product-closure.mjs
@@ -0,0 +1,258 @@
+#!/usr/bin/env node
+
+import { execFileSync } from 'node:child_process';
+import { existsSync, readFileSync } from 'node:fs';
+import path from 'node:path';
+import { fileURLToPath } from 'node:url';
+
+const __filename = fileURLToPath(import.meta.url);
+const __dirname = path.dirname(__filename);
+const defaultRepoRoot = path.resolve(__dirname, '..');
+const ARTIFACT_PATH = '.bitcode/v42-readneed-review-resynthesis-product-closure.json';
+
+const SECRET_MARKERS = [
+ `${['sk', 'proj'].join('-')}-`,
+ `${['sb', 'secret'].join('_')}__`,
+ ['service', 'role'].join('_'),
+ Buffer.from('{"alg":"HS256","typ":"JWT"}').toString('base64url').slice(0, 18),
+ ['OPENAI', 'API', 'KEY'].join('_'),
+ ['SUPABASE', 'SERVICE', 'ROLE'].join('_'),
+ ['VERCEL', 'TOKEN'].join('_'),
+ ['VERCEL', 'OIDC', 'TOKEN'].join('_'),
+ ['PRIVATE', 'KEY'].join('_'),
+];
+
+function read(root, relativePath) {
+ return readFileSync(path.join(root, relativePath), 'utf8');
+}
+
+function fileExists(root, relativePath) {
+ return existsSync(path.join(root, relativePath));
+}
+
+function git(root, args) {
+ return execFileSync('git', args, { cwd: root, encoding: 'utf8' }).trim();
+}
+
+function run(root, command, args) {
+ return execFileSync(command, args, {
+ cwd: root,
+ encoding: 'utf8',
+ stdio: ['ignore', 'pipe', 'pipe'],
+ }).trim();
+}
+
+function assertCheck(failures, condition, message) {
+ if (!condition) failures.push(message);
+}
+
+function parseArgs(argv) {
+ const args = {
+ skipBranchCheck: false,
+ skipPackageTests: false,
+ skipUapiTests: false,
+ repoRoot: defaultRepoRoot,
+ help: false,
+ };
+
+ for (let index = 0; index < argv.length; index += 1) {
+ const arg = argv[index];
+ if (arg === '--skip-branch-check') args.skipBranchCheck = true;
+ else if (arg === '--skip-package-tests') args.skipPackageTests = true;
+ else if (arg === '--skip-uapi-tests') args.skipUapiTests = true;
+ else if (arg === '--repo-root') args.repoRoot = path.resolve(argv[++index]);
+ else if (arg === '--help' || arg === '-h') args.help = true;
+ else throw new Error(`Unknown argument ${arg}`);
+ }
+
+ return args;
+}
+
+function printHelp() {
+ process.stdout.write(
+ [
+ 'Usage: node scripts/check-v42-gate4-readneed-review-resynthesis-product-closure.mjs [--skip-branch-check] [--skip-package-tests] [--skip-uapi-tests] [--repo-root ]',
+ '',
+ 'Checks V42 Gate 4 ReadNeed product closure, review/resynthesis, rejection, accepted-Need admission, source-safe runtime storage, telemetry receipts, Terminal readback, tests, docs, workflow wiring, and proof artifact.',
+ ].join('\n'),
+ );
+ process.stdout.write('\n');
+}
+
+function main() {
+ const args = parseArgs(process.argv.slice(2));
+ if (args.help) {
+ printHelp();
+ return;
+ }
+
+ const root = args.repoRoot;
+ const failures = [];
+ const pointer = read(root, 'BITCODE_SPEC.txt').trim();
+
+ assertCheck(
+ failures,
+ pointer === 'V41',
+ `BITCODE_SPEC.txt must remain V41 during V42 gate work. Observed ${pointer || 'empty'}.`,
+ );
+
+ if (!args.skipBranchCheck) {
+ const branch = git(root, ['branch', '--show-current']);
+ assertCheck(
+ failures,
+ branch === 'version/v42' || /^v42\/gate-(?:4|[5-9]|10)-[a-z0-9][a-z0-9-]*$/u.test(branch),
+ `V42 Gate 4+ work must occur on version/v42 or v42/gate-4..10-* branches. Observed ${branch || 'detached HEAD'}.`,
+ );
+ }
+
+ const requiredFiles = [
+ ARTIFACT_PATH,
+ 'packages/pipelines/asset-pack/src/read-need.ts',
+ 'packages/pipelines/asset-pack/src/read-need-review-resynthesis.ts',
+ 'packages/pipelines/asset-pack/src/reading-pipeline-contract.ts',
+ 'packages/pipelines/asset-pack/src/__tests__/read-need.test.ts',
+ 'packages/pipelines/asset-pack/src/__tests__/read-need-review-resynthesis.test.ts',
+ 'packages/pipelines/asset-pack/src/__tests__/reading-pipeline-contract.test.ts',
+ 'uapi/app/api/read-review/route.ts',
+ 'uapi/app/terminal/TerminalDepositReadWorkbench.tsx',
+ 'uapi/tests/api/readReviewRoute.test.ts',
+ 'uapi/tests/api/readReviewProtocolParity.test.ts',
+ 'packages/protocol/src/canonical/v42-readneed-review-resynthesis-product-closure.js',
+ 'packages/protocol/test/v42-readneed-review-resynthesis-product-closure.test.js',
+ 'scripts/generate-v42-readneed-review-resynthesis-product-closure.mjs',
+ 'scripts/check-v42-gate4-readneed-review-resynthesis-product-closure.mjs',
+ 'BITCODE_SPEC_V42.md',
+ 'BITCODE_SPEC_V42_DELTA.md',
+ 'BITCODE_SPEC_V42_NOTES.md',
+ 'BITCODE_SPEC_V42_PARITY_MATRIX.md',
+ 'SPECIFICATIONS_ROADMAP.md',
+ 'README.md',
+ 'uapi/app/terminal/README.md',
+ 'packages/pipelines/asset-pack/README.md',
+ 'packages/protocol/README.md',
+ 'package.json',
+ '.github/workflows/bitcode-gate-quality.yml',
+ '.github/workflows/bitcode-canon-quality.yml',
+ ];
+
+ for (const relativePath of requiredFiles) {
+ assertCheck(failures, fileExists(root, relativePath), `Missing V42 Gate 4 file: ${relativePath}`);
+ }
+
+ if (failures.length === 0) {
+ try {
+ run(root, 'node', ['scripts/generate-v42-readneed-review-resynthesis-product-closure.mjs', '--check']);
+ } catch (error) {
+ failures.push(`V42 ReadNeed review/resynthesis artifact check failed: ${error.stderr || error.message}`);
+ }
+ }
+
+ if (failures.length === 0) {
+ try {
+ run(root, 'node', [
+ '--test',
+ '--test-force-exit',
+ 'packages/protocol/test/v42-readneed-review-resynthesis-product-closure.test.js',
+ ]);
+ } catch (error) {
+ failures.push(`V42 ReadNeed review/resynthesis protocol test failed: ${error.stderr || error.message}`);
+ }
+ }
+
+ if (failures.length === 0 && !args.skipPackageTests) {
+ try {
+ run(root, 'pnpm', [
+ '--filter',
+ '@bitcode/pipeline-asset-pack',
+ 'exec',
+ 'jest',
+ '--config',
+ 'jest.config.cjs',
+ '--runTestsByPath',
+ 'src/__tests__/read-need.test.ts',
+ 'src/__tests__/read-need-review-resynthesis.test.ts',
+ 'src/__tests__/reading-pipeline-contract.test.ts',
+ '--runInBand',
+ '--forceExit',
+ ]);
+ } catch (error) {
+ failures.push(`V42 ReadNeed review/resynthesis package tests failed: ${error.stderr || error.message}`);
+ }
+ }
+
+ if (failures.length === 0 && !args.skipUapiTests) {
+ try {
+ run(root, 'pnpm', [
+ '--dir',
+ 'uapi',
+ 'exec',
+ 'jest',
+ '--runTestsByPath',
+ 'tests/api/readReviewRoute.test.ts',
+ 'tests/api/readReviewProtocolParity.test.ts',
+ 'tests/terminalDepositReadWorkbench.test.ts',
+ 'tests/terminalEnterpriseReadingUxState.test.ts',
+ '--runInBand',
+ ]);
+ } catch (error) {
+ failures.push(`V42 ReadNeed review/resynthesis UAPI tests failed: ${error.stderr || error.message}`);
+ }
+ }
+
+ const serializedArtifact = fileExists(root, ARTIFACT_PATH) ? read(root, ARTIFACT_PATH) : '';
+ for (const marker of SECRET_MARKERS) {
+ assertCheck(failures, !serializedArtifact.includes(marker), `V42 Gate 4 artifact must not contain secret marker ${marker}.`);
+ }
+
+ const artifact = serializedArtifact ? JSON.parse(serializedArtifact) : null;
+ if (artifact) {
+ assertCheck(failures, artifact.artifactId === 'v42-readneed-review-resynthesis-product-closure', 'Gate 4 artifactId must match.');
+ assertCheck(
+ failures,
+ artifact.schemaId === 'bitcode.v42.readNeedReviewResynthesisProductClosure.v1',
+ 'Gate 4 schemaId must match.',
+ );
+ assertCheck(failures, artifact.version === 'V42' && artifact.currentTarget === 'V41', 'Gate 4 artifact must bind V42 over active V41.');
+ assertCheck(failures, artifact.passed === true, 'Gate 4 artifact must pass.');
+ assertCheck(
+ failures,
+ artifact.sourceSafetyVerdict === 'source-safe-readneed-review-resynthesis-product-closure-metadata',
+ 'Gate 4 artifact must declare source-safe ReadNeed review/resynthesis product closure metadata.',
+ );
+ assertCheck(failures, artifact.coverage.rowCount === 11, 'Gate 4 must cover eleven ReadNeed product closure rows.');
+ assertCheck(failures, artifact.coverage.phaseCount === 4, 'Gate 4 must cover four ReadNeedComprehensionSynthesis phases.');
+ assertCheck(failures, artifact.coverage.ptrrStepCount === 16, 'Gate 4 must cover sixteen PTRR steps.');
+ assertCheck(failures, artifact.coverage.failsafeSequenceCount === 48, 'Gate 4 must cover forty-eight Failsafe sequences.');
+ assertCheck(failures, artifact.coverage.thricifiedGenerationCount === 48, 'Gate 4 must cover forty-eight ThricifiedGeneration receipts.');
+ assertCheck(failures, artifact.coverage.acceptedNeedRequiredForFindingFits === true, 'Gate 4 must require accepted Need before Finding Fits.');
+ assertCheck(failures, artifact.coverage.rejectedNeedBlocksFindingFits === true, 'Gate 4 must block Finding Fits after rejected Need.');
+ assertCheck(failures, artifact.coverage.terminalRuntimeReadbackCovered === true, 'Gate 4 must cover Terminal runtime readback.');
+ assertCheck(failures, artifact.coverage.sourceSafeMetadataOnly === true, 'Gate 4 must remain source-safe metadata only.');
+ assertCheck(failures, artifact.coverage.protectedSourceVisible === false, 'Gate 4 artifact must not expose protected source.');
+ assertCheck(failures, artifact.coverage.rawProtectedPromptVisible === false, 'Gate 4 artifact must not expose protected prompts.');
+ assertCheck(failures, artifact.coverage.rawProviderResponseVisible === false, 'Gate 4 artifact must not expose raw provider responses.');
+ assertCheck(failures, artifact.coverage.unpaidAssetPackSourceVisible === false, 'Gate 4 artifact must not expose unpaid AssetPack source.');
+ assertCheck(failures, artifact.coverage.walletPrivateMaterialVisible === false, 'Gate 4 artifact must not expose wallet private material.');
+ assertCheck(failures, artifact.coverage.settlementPrivatePayloadVisible === false, 'Gate 4 artifact must not expose settlement private payloads.');
+ assertCheck(failures, artifact.coverage.credentialsSerialized === false, 'Gate 4 artifact must not serialize credentials.');
+ assertCheck(failures, artifact.coverage.legacySourceRoots === false, 'Gate 4 must not rely on legacy source roots.');
+ assertCheck(failures, Array.isArray(artifact.coverage.failedPredicateIds) && artifact.coverage.failedPredicateIds.length === 0, 'Gate 4 predicates must all pass.');
+ }
+
+ const spec = read(root, 'BITCODE_SPEC_V42.md');
+ const parity = read(root, 'BITCODE_SPEC_V42_PARITY_MATRIX.md');
+ const terminalReadme = read(root, 'uapi/app/terminal/README.md');
+ assertCheck(failures, spec.includes('V42 Gate 4') && spec.includes('v42-readneed-review-resynthesis-product-closure'), 'V42 spec must expand Gate 4 ReadNeed product closure.');
+ assertCheck(failures, parity.includes('ReadNeed product closure') && parity.includes('implemented'), 'V42 parity matrix must mark ReadNeed product closure implemented.');
+ assertCheck(failures, terminalReadme.includes('V42 Gate 4') && terminalReadme.includes('ReadNeedReviewResynthesisRuntime'), 'Terminal README must document Gate 4 ReadNeed runtime readback.');
+
+ if (failures.length > 0) {
+ process.stderr.write(`V42 Gate 4 ReadNeed product closure check failed:\n- ${failures.join('\n- ')}\n`);
+ process.exitCode = 1;
+ return;
+ }
+
+ process.stdout.write(`V42 Gate 4 ReadNeed product closure ok artifact=${artifact.artifactRoot}\n`);
+}
+
+main();
diff --git a/scripts/generate-v42-readneed-review-resynthesis-product-closure.mjs b/scripts/generate-v42-readneed-review-resynthesis-product-closure.mjs
new file mode 100644
index 00000000..cb05c4a3
--- /dev/null
+++ b/scripts/generate-v42-readneed-review-resynthesis-product-closure.mjs
@@ -0,0 +1,31 @@
+#!/usr/bin/env node
+
+import { readFileSync, writeFileSync } from 'node:fs';
+import path from 'node:path';
+import { fileURLToPath } from 'node:url';
+import {
+ V42_READNEED_REVIEW_RESYNTHESIS_PRODUCT_CLOSURE_ARTIFACT_PATH,
+ buildV42ReadNeedReviewResynthesisProductClosure,
+} from '../packages/protocol/src/canonical/v42-readneed-review-resynthesis-product-closure.js';
+
+const __filename = fileURLToPath(import.meta.url);
+const __dirname = path.dirname(__filename);
+const repoRoot = path.resolve(__dirname, '..');
+
+const check = process.argv.includes('--check');
+const artifact = buildV42ReadNeedReviewResynthesisProductClosure({ repoRoot });
+const serialized = `${JSON.stringify(artifact, null, 2)}\n`;
+const artifactPath = path.join(repoRoot, V42_READNEED_REVIEW_RESYNTHESIS_PRODUCT_CLOSURE_ARTIFACT_PATH);
+
+if (check) {
+ const current = readFileSync(artifactPath, 'utf8');
+ if (current !== serialized) {
+ process.stderr.write(
+ `${V42_READNEED_REVIEW_RESYNTHESIS_PRODUCT_CLOSURE_ARTIFACT_PATH} is stale. Run pnpm run generate:v42-readneed-review-resynthesis-product-closure.\n`,
+ );
+ process.exitCode = 1;
+ }
+} else {
+ writeFileSync(artifactPath, serialized);
+ process.stdout.write(`wrote ${V42_READNEED_REVIEW_RESYNTHESIS_PRODUCT_CLOSURE_ARTIFACT_PATH}\n`);
+}
diff --git a/uapi/app/api/read-review/route.ts b/uapi/app/api/read-review/route.ts
index f7a2d304..7966a42c 100644
--- a/uapi/app/api/read-review/route.ts
+++ b/uapi/app/api/read-review/route.ts
@@ -126,6 +126,7 @@ export async function POST(request: Request) {
const { acceptReadNeed, admitReadFitsFinding } = await import('@bitcode/pipeline-asset-pack/read-need');
const {
buildReadNeedReviewResynthesisRuntime,
+ persistReadNeedReviewResynthesisRuntime,
summarizeReadNeedReviewResynthesisRuntime,
} = await import('@bitcode/pipeline-asset-pack/read-need-review-resynthesis');
const {
@@ -145,10 +146,12 @@ export async function POST(request: Request) {
acceptedReadNeed,
requireAcceptedReadNeed: true,
});
+ const inferenceCapture = createRouteInferenceCapture();
const reviewRuntime = buildReadNeedReviewResynthesisRuntime({
action,
readNeed: acceptedReadNeed,
});
+ persistReadNeedReviewResynthesisRuntime(inferenceCapture.execution, reviewRuntime);
const acceptanceStep =
READ_NEED_COMPREHENSION_SYNTHESIS_CONTRACT.phases
.flatMap((phase) => phase.agents)
@@ -197,6 +200,7 @@ export async function POST(request: Request) {
const { rejectReadNeed, admitReadFitsFinding } = await import('@bitcode/pipeline-asset-pack/read-need');
const {
buildReadNeedReviewResynthesisRuntime,
+ persistReadNeedReviewResynthesisRuntime,
summarizeReadNeedReviewResynthesisRuntime,
} = await import('@bitcode/pipeline-asset-pack/read-need-review-resynthesis');
const {
@@ -219,11 +223,13 @@ export async function POST(request: Request) {
readNeed: rejectedReadNeed,
requireAcceptedReadNeed: true,
});
+ const inferenceCapture = createRouteInferenceCapture();
const reviewRuntime = buildReadNeedReviewResynthesisRuntime({
action,
readNeed: rejectedReadNeed,
feedback: stringArray(body.feedback || body.readNeedFeedback),
});
+ persistReadNeedReviewResynthesisRuntime(inferenceCapture.execution, reviewRuntime);
const reviewStep =
READ_NEED_COMPREHENSION_SYNTHESIS_CONTRACT.phases
.flatMap((phase) => phase.agents)
diff --git a/uapi/app/terminal/README.md b/uapi/app/terminal/README.md
index 176bc0a0..a5803f85 100644
--- a/uapi/app/terminal/README.md
+++ b/uapi/app/terminal/README.md
@@ -115,6 +115,16 @@ settlement, and settlement readback gates delivery. The source-safe proof
artifact is `.bitcode/v42-reading-shortest-path-state-machine.json`, checked by
`pnpm run check:v42-gate3`.
+V42 Gate 4 closes the Terminal ReadNeed review loop. The staged Reading
+surface now keeps `ReadNeedReviewResynthesisRuntime`, storage projection rows,
+telemetry return type, runtime root, storage root, telemetry root, admission
+blockers, and rejected Need posture visible in expandable source-safe detail.
+Terminal exposes synthesize, resynthesize, accept, and reject actions before
+Finding Fits; accepting the Need is the only admission handoff to
+`ReadFitsFindingSynthesis`. The source-safe proof artifact is
+`.bitcode/v42-readneed-review-resynthesis-product-closure.json`, checked by
+`pnpm run check:v42-gate4`.
+
## Live staging-testnet QA
Terminal Deposit/Read QA starts only after Wallet and Externals prerequisites are
diff --git a/uapi/app/terminal/TerminalDepositReadWorkbench.tsx b/uapi/app/terminal/TerminalDepositReadWorkbench.tsx
index 4d4e1453..599e8117 100644
--- a/uapi/app/terminal/TerminalDepositReadWorkbench.tsx
+++ b/uapi/app/terminal/TerminalDepositReadWorkbench.tsx
@@ -104,6 +104,24 @@ type TerminalReadNeedState = Record & {
};
};
+type TerminalReadNeedReviewRuntimeState = Record & {
+ schema?: 'bitcode.read-need-review-resynthesis-runtime';
+ runtimeId?: string;
+ action?: string;
+ reviewState?: string;
+ findingFitsAdmission?: {
+ admitted?: boolean;
+ blockers?: string[];
+ };
+ reviewLoop?: Record;
+ proofRoots?: {
+ runtimeRoot?: string;
+ storageRoot?: string;
+ telemetryRoot?: string;
+ readRequestRoot?: string;
+ };
+};
+
interface TerminalDepositReadWorkbenchProps {
repositoryContext?: TerminalRepositoryContextState | null;
depositedSourceRevision?: TerminalDepositedSourceRevision | null;
@@ -134,9 +152,12 @@ export default function TerminalDepositReadWorkbench({
const [harnessUserHasScrolled, setHarnessUserHasScrolled] = useState(false);
const [readNeed, setReadNeed] = useState(null);
const [acceptedReadNeed, setAcceptedReadNeed] = useState(null);
+ const [readNeedReviewRuntime, setReadNeedReviewRuntime] = useState(null);
+ const [readNeedStorageProjection, setReadNeedStorageProjection] = useState>>([]);
+ const [readNeedTelemetry, setReadNeedTelemetry] = useState | null>(null);
const [readNeedFeedback, setReadNeedFeedback] = useState('');
const [readNeedMessage, setReadNeedMessage] = useState(null);
- const [readNeedAction, setReadNeedAction] = useState<'synthesize' | 'accept' | 'resynthesize' | null>(null);
+ const [readNeedAction, setReadNeedAction] = useState<'synthesize' | 'accept' | 'reject' | 'resynthesize' | null>(null);
const [readNeedSynthesisCount, setReadNeedSynthesisCount] = useState(0);
const workbenchSnapshot = useMemo(() => {
const liveWorkbenchSnapshot = buildLiveTerminalDepositReadWorkbenchSnapshot(repositoryContext, depositedSourceRevision);
@@ -157,6 +178,9 @@ export default function TerminalDepositReadWorkbench({
setHarnessEvents([]);
setReadNeed(null);
setAcceptedReadNeed(null);
+ setReadNeedReviewRuntime(null);
+ setReadNeedStorageProjection([]);
+ setReadNeedTelemetry(null);
setReadNeedFeedback('');
setReadNeedMessage(null);
setReadNeedAction(null);
@@ -410,6 +434,23 @@ export default function TerminalDepositReadWorkbench({
{ label: 'Previous Need', value: shortIdentifier(currentReadNeed.request?.previousNeedId) || currentReadNeed.request?.previousNeedId || 'none' },
];
}, [currentReadNeed]);
+ const readNeedRuntimeRows = useMemo(() => {
+ if (!readNeedReviewRuntime && !readNeedTelemetry && readNeedStorageProjection.length === 0) return [];
+ const admission = objectValue(readNeedReviewRuntime?.findingFitsAdmission);
+ const proofRoots = objectValue(readNeedReviewRuntime?.proofRoots);
+ return [
+ { label: 'Runtime', value: shortIdentifier(readNeedReviewRuntime?.runtimeId) || textValue(readNeedReviewRuntime?.runtimeId) || 'pending' },
+ { label: 'Action', value: textValue(readNeedReviewRuntime?.action) || 'pending' },
+ { label: 'Admission', value: admission?.admitted === true ? 'admitted' : 'blocked' },
+ { label: 'Blockers', value: stringList(admission?.blockers).join(', ') || 'none' },
+ { label: 'Storage records', value: String(readNeedStorageProjection.length || 'pending') },
+ { label: 'Runtime root', value: shortIdentifier(proofRoots?.runtimeRoot) || 'pending' },
+ { label: 'Storage root', value: shortIdentifier(proofRoots?.storageRoot) || 'pending' },
+ { label: 'Telemetry root', value: shortIdentifier(proofRoots?.telemetryRoot || readNeedTelemetry?.telemetryRoot) || 'pending' },
+ { label: 'PTRR step', value: shortIdentifier(readNeedTelemetry?.ptrrStepId) || textValue(readNeedTelemetry?.ptrrStepId) || 'pending' },
+ { label: 'Return type', value: textValue(readNeedTelemetry?.returnType) || 'pending' },
+ ];
+ }, [readNeedReviewRuntime, readNeedStorageProjection, readNeedTelemetry]);
const stageCards = enterpriseReadingState.steps;
const canRunLiveFit =
!showDemonstrationWorkbench &&
@@ -531,6 +572,9 @@ export default function TerminalDepositReadWorkbench({
if (!nextNeed) throw new Error('Read-Need synthesis did not return a typed Need.');
setReadNeed(nextNeed);
setAcceptedReadNeed(null);
+ setReadNeedReviewRuntime(objectValue(payload?.readNeedReviewRuntime) as TerminalReadNeedReviewRuntimeState | null);
+ setReadNeedStorageProjection(Array.isArray(payload?.storageProjection) ? payload.storageProjection as Array> : []);
+ setReadNeedTelemetry(objectValue(payload?.telemetry));
setReadNeedSynthesisCount((count) => count + 1);
setReadNeedMessage(
action === 'synthesize_read_need'
@@ -573,6 +617,9 @@ export default function TerminalDepositReadWorkbench({
}
setAcceptedReadNeed(accepted);
setReadNeed(accepted);
+ setReadNeedReviewRuntime(objectValue(payload?.readNeedReviewRuntime) as TerminalReadNeedReviewRuntimeState | null);
+ setReadNeedStorageProjection(Array.isArray(payload?.storageProjection) ? payload.storageProjection as Array> : []);
+ setReadNeedTelemetry(objectValue(payload?.telemetry));
setReadNeedMessage('Read-Need accepted. Finding Fits can now run against deposited source.');
await onRecordActivity?.({
type: 'agentic-execution:read-measurement',
@@ -604,6 +651,47 @@ export default function TerminalDepositReadWorkbench({
}
}, [onRecordActivity, readNeed]);
+ const handleRejectReadNeed = useCallback(async () => {
+ if (!readNeed) return;
+
+ setReadNeedAction('reject');
+ setReadNeedMessage(null);
+
+ try {
+ const response = await fetch('/api/read-review', {
+ method: 'POST',
+ headers: {
+ 'Content-Type': 'application/json',
+ },
+ body: JSON.stringify({
+ action: 'reject_read_need',
+ readNeed,
+ feedback: readNeedFeedback.trim() ? [readNeedFeedback.trim()] : [],
+ }),
+ });
+
+ if (!response.ok) {
+ throw new Error(await readTerminalRouteError(response, 'Unable to reject the Read-Need.'));
+ }
+
+ const payload = objectValue(await response.json());
+ const rejected = terminalReadNeed(payload?.rejectedReadNeed || payload?.readNeed);
+ if (!rejected || rejected.reviewState !== 'rejected') {
+ throw new Error('Read-Need rejection did not return a rejected Need.');
+ }
+ setReadNeed(rejected);
+ setAcceptedReadNeed(null);
+ setReadNeedReviewRuntime(objectValue(payload?.readNeedReviewRuntime) as TerminalReadNeedReviewRuntimeState | null);
+ setReadNeedStorageProjection(Array.isArray(payload?.storageProjection) ? payload.storageProjection as Array> : []);
+ setReadNeedTelemetry(objectValue(payload?.telemetry));
+ setReadNeedMessage('Read-Need rejected. Finding Fits remains blocked until a resynthesized Need is accepted.');
+ } catch (error) {
+ setReadNeedMessage(error instanceof Error ? error.message : 'Unable to reject the Read-Need.');
+ } finally {
+ setReadNeedAction(null);
+ }
+ }, [readNeed, readNeedFeedback]);
+
const handleRunLiveFit = useCallback(async () => {
if (!harnessRequestState.ready) {
setHarnessState('failed');
@@ -850,6 +938,16 @@ export default function TerminalDepositReadWorkbench({
>
{readNeedAction === 'accept' ? 'Accepting…' : 'Accept Read-Need'}
+