Skip to content

Commit 8b1651a

Browse files
Merge pull request #14 from engineeredsoftware/v28/gate-9-depository-evidence
Gate 9 project depository evidence through Reading
2 parents e59b5fe + d0e8787 commit 8b1651a

23 files changed

Lines changed: 675 additions & 4 deletions

.github/workflows/bitcode-gate-quality.yml

Lines changed: 1 addition & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -45,6 +45,7 @@ jobs:
4545
node scripts/check-bitcode-canon-posture-drift.mjs --active-canon V27 --draft-target V28
4646
node scripts/check-bitcode-canonical-inputs.mjs --current-target V27
4747
node scripts/check-v28-metadevelopment-readiness.mjs --skip-branch-check
48+
node scripts/check-v28-gate9-depository-evidence.mjs
4849
node scripts/promote-bitcode-canon.mjs --version V28 --commit HEAD --dry-run
4950
5051
- name: Validate source casing and imports

BITCODE_SPEC_V28.md

Lines changed: 25 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -794,6 +794,31 @@ repository inventory, deposit admission, depository evidence storage,
794794
measurement vectors, wallet/depositor boundaries, search-index population, and
795795
Terminal visibility for deposited source materials.
796796

797+
Gate 9 acceptance closes only when a deposited repository revision produces a
798+
single evidence spine usable by later Reading gates:
799+
800+
- the deposit route returns and persists a source-bound depository evidence
801+
envelope containing repository, branch, commit, asset id, content root, proof
802+
root, measurement root, reconciliation readback root, lexical search document
803+
root, vector search document root, and aggregate depository search document
804+
root;
805+
- the depositor boundary is explicit as a wallet/signer ownership boundary,
806+
with the deposited asset owned by the depositor before any Reader settlement
807+
or read-license transfer;
808+
- the vector document contract names the embedding policy
809+
`text-embedding-3-small`, 1536 dimensions, and the `deliverable_vectors` /
810+
`match_deliverable_vectors` store/RPC boundary, while lexical search remains
811+
deterministic and source-rooted;
812+
- Terminal execution-history rows retain the deposit evidence roots and replay
813+
them into the latest deposited source revision so the Read/Fit harness can
814+
pass proof, measurement, and readback roots into Finding Fits;
815+
- Terminal Deposit + Read surfaces show the deposit asset id, depositor wallet,
816+
source proof roots, search document roots, and index state without requiring
817+
operators to inspect raw JSON;
818+
- the Gate 9 SQL/readback query checks recent deposit rows for repository
819+
alignment, candidate asset id, source proof roots, depository search document
820+
roots, depositor boundary, and vector embedding policy posture.
821+
797822
### Gate 10: Read Request To Read-Need Comprehension
798823

799824
Gate 10 owns the enterprise Reading start: request Read, synthesize a

BITCODE_SPEC_V28_DELTA.md

Lines changed: 8 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -190,6 +190,14 @@ Read Request, Read-Need synthesis/review/resynthesis, Finding Fits, AssetPack
190190
preview, BTC settlement, read-license/right transfer, protected-source unlock,
191191
PR delivery, Terminal UX, documentation, proof coverage, and live validation.
192192

193+
Gate 9 introduces the deposited-source evidence spine that later gates consume.
194+
Depositing now produces proof, measurement, reconciliation readback, lexical
195+
document, vector document, and aggregate depository search roots; projects those
196+
roots through Terminal execution history; and carries them into the Read/Fit
197+
harness deposit reference. The vector document policy is explicit:
198+
`text-embedding-3-small`, 1536 dimensions, `deliverable_vectors`, and
199+
`match_deliverable_vectors`.
200+
193201
## Later Version Handoff
194202

195203
- V29: deeper Terminal workflows and transaction operation beyond V28 MVP QA.

BITCODE_SPEC_V28_NOTES.md

Lines changed: 17 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -553,6 +553,23 @@ Need synthesis/review/resynthesis, Finding Fits over the depository, source-safe
553553
AssetPack preview, BTC settlement, read-license/right transfer, pull-request
554554
delivery, Terminal usability, proof coverage, and local/live validation.
555555

556+
## Gate 9 depository evidence closure notes
557+
558+
Gate 9 closes the first product gate after metadevelopment by making Deposit
559+
evidence reusable by later Reading gates. A deposited repository revision must
560+
emit proof, measurement, reconciliation readback, lexical document, vector
561+
document, and aggregate depository search roots. Terminal activity history must
562+
persist those roots and project them back into the latest deposited source
563+
revision. The Read/Fit harness must receive the same roots in its deposit
564+
reference so Finding Fits can distinguish real proof-bearing deposited supply
565+
from local placeholders.
566+
567+
The vector search document policy for V28 Gate 9 is `text-embedding-3-small`,
568+
1536 dimensions, `deliverable_vectors`, `match_deliverable_vectors`, and cosine
569+
distance. Gate 9 records the vector document as ready for embedding generation;
570+
later Finding Fits and live validation gates own provider execution, ranking,
571+
settlement, and protected-source disclosure boundaries.
572+
556573
## Non-Goals For V28
557574

558575
- V28 does not implement or QA Exchange product behavior, broad order-book depth, external market routing, wrapper liquidity, or third-party marketplace integration.

BITCODE_SPEC_V28_PARITY_MATRIX.md

Lines changed: 1 addition & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -172,7 +172,7 @@ by a later V28 gate before `version/v28` can be promoted to `main`.
172172

173173
| Carryforward surface | Next gate | Required commercial implementation | Required proof/test coverage | Carryforward closure requirement |
174174
| --- | --- | --- | --- | --- |
175-
| Source Depositing and depository evidence | Gate 9 | Repository inventory, deposit admission, source measurement, depository asset rows, vector/lexical search documents, depositor wallet boundary, source proof roots, and Terminal deposit history. | Deposit API/ORM tests, depository-search tests, staging-testnet SQL/readback queries, Terminal UX tests, and no demonstration runtime imports. | A user can deposit real source material and see source-bound evidence persisted, searchable, journaled, and owned by the depositor boundary. |
175+
| Source Depositing and depository evidence | Gate 9 | Repository inventory, deposit admission, source measurement, depository asset rows, lexical/vector search documents, depositor wallet boundary, source proof roots, execution-history projection, and Terminal deposit history. | Protocol deposit evidence tests, depository-search tests, pipeline harness deposit-root propagation tests, staging-testnet SQL/readback queries, Terminal UX tests, and no demonstration runtime imports. | A user can deposit real source material and see source-bound evidence persisted, searchable, journaled, root-projected into Finding Fits, and owned by the depositor boundary. |
176176
| Read Request capture | Gate 10 | Enterprise Read Request form/state, repository target, source branch/commit context, constraints, non-goals, desired artifact types, and feedback history. | UAPI route tests, Terminal form tests, typed Read Request schema tests, prompt/context interpolation tests. | Raw requests are persisted as requests only; they do not directly trigger Finding Fits until a reviewed Need exists. |
177177
| Read-Need synthesis, review, and resynthesis | Gate 10 | `ReadNeedComprehensionSynthesis` execution over PTRR agents and ThricifiedGenerations, reviewable Need object, operator feedback, resynthesis attempts, acceptance root, and blocked-readiness reasons. | Pipeline contract tests, prompt/return audits, mocked typed-envelope tests, live local OpenAI validation, Terminal stream/accordion tests. | A Reader can accept or resynthesize the Need; accepted Need truth becomes the only input admitted to Finding Fits. |
178178
| Finding Fits over the depository | Gate 11 | `ReadFindingFitsSynthesis.discovery` searches lexical/vector deposits, ranks all threshold-passing fits, records fit deposits, query/ranking roots, blockers, and no-worthy-fit outcomes. | Depository search tests, embedding policy tests, tool telemetry tests, staging-testnet readback verifier, mock/live parity tests. | Discovery returns all fit deposits above threshold and never invents source outside the depository. |

package.json

Lines changed: 1 addition & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -39,6 +39,7 @@
3939
"check:canon-posture-drift": "node scripts/check-bitcode-canon-posture-drift.mjs",
4040
"check:spec-family": "node scripts/check-bitcode-spec-family.mjs",
4141
"check:v28-metadevelopment": "node scripts/check-v28-metadevelopment-readiness.mjs",
42+
"check:v28-gate9": "node scripts/check-v28-gate9-depository-evidence.mjs",
4243
"check:spec-quality": "node scripts/run-bitcode-spec-quality.mjs --mode basic",
4344
"check:spec-quality:title": "node scripts/run-bitcode-spec-quality.mjs --mode strict-from-title",
4445
"check:spec-quality:v24": "node scripts/run-bitcode-spec-quality.mjs --mode strict-version --version V24",

packages/pipelines/asset-pack/src/__tests__/depository-search.test.ts

Lines changed: 8 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -249,13 +249,21 @@ describe('AssetPack depository search', () => {
249249
assetId: 'asset-1',
250250
hasWalletOrAttestationProof: true,
251251
hasAssetMeasurementEvidence: true,
252+
proofRoot: 'sha256:manifest-proof',
253+
measurementRoot: 'sha256:manifest-measurement',
254+
reconciliationReadbackRoot: 'sha256:manifest-readback',
252255
},
253256
});
254257

255258
expect(normalized).toHaveLength(1);
256259
expect(normalized[0].assetId).toBe('asset-1');
257260
expect(normalized[0].repositoryFullName).toBe('engineeredsoftware/ENGI');
258261
expect(normalized[0].hasWalletOrAttestationProof).toBe(true);
262+
expect(normalized[0].verificationEvidence).toMatchObject({
263+
proofRoot: 'sha256:manifest-proof',
264+
measurementRoot: 'sha256:manifest-measurement',
265+
reconciliationReadbackRoot: 'sha256:manifest-readback',
266+
});
259267
});
260268

261269
it('stores depository search and fit result evidence during pipeline preprocess', async () => {

packages/pipelines/asset-pack/src/depository-search.ts

Lines changed: 5 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -1258,6 +1258,11 @@ export function normalizePipelineDepositoryAssets(input: unknown): DepositoryAss
12581258
mutableInBranch: false,
12591259
materializationRoot: `.bitcode/source-material/${assetId}`,
12601260
},
1261+
verificationEvidence: {
1262+
proofRoot: firstString(depositRecord.proofRoot),
1263+
measurementRoot: firstString(depositRecord.measurementRoot),
1264+
reconciliationReadbackRoot: firstString(depositRecord.reconciliationReadbackRoot),
1265+
},
12611266
hasWalletOrAttestationProof: depositRecord.hasWalletOrAttestationProof === true,
12621267
hasAssetMeasurementEvidence: depositRecord.hasAssetMeasurementEvidence === true,
12631268
},

packages/protocol/server.js

Lines changed: 8 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -804,8 +804,15 @@ export function createAppContext({
804804

805805
state.assets.unshift(asset);
806806
state.ledger.accounts[`supplier:${asset.assetId}:pending_claims`] = '0';
807+
if (asset.depositoryEvidence?.depositorBoundary?.walletId) {
808+
const depositorAssetsKey = `depositor:${asset.depositoryEvidence.depositorBoundary.walletId}:deposited_assets`;
809+
const priorDepositorAssetCount = Number(state.ledger.accounts[depositorAssetsKey] || '0');
810+
state.ledger.accounts[depositorAssetsKey] = String(
811+
Number.isFinite(priorDepositorAssetCount) ? priorDepositorAssetCount + 1 : 1
812+
);
813+
}
807814
writeState(state);
808-
return { ok: true, asset };
815+
return { ok: true, asset, depositoryEvidence: asset.depositoryEvidence || null };
809816
}
810817

811818
/**

packages/protocol/src/bitcode-demo.js

Lines changed: 184 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -460,6 +460,156 @@ function stableHashObject(value) {
460460
return `sha256:${sha256(canonicalJson(value))}`;
461461
}
462462

463+
/**
464+
* @param {any} input
465+
* @param {{
466+
* assetId: string,
467+
* title: string,
468+
* artifactKind: string,
469+
* artifactType: string,
470+
* contentRoot: string,
471+
* contentUnits: any[],
472+
* addressingSurface: any,
473+
* artifactSelectionSurface: any,
474+
* signingSurface: any,
475+
* githubAppAuthSurface: any,
476+
* assetMeasurement: any,
477+
* measurementProvenance: any[]
478+
* }} inputState
479+
* @returns {any}
480+
*/
481+
function buildDepositoryEvidence(input, inputState) {
482+
const repositoryFullName = inputState.addressingSurface.repo || input.sourceRepo || input.authSession?.repo || null;
483+
const sourceBranch = inputState.addressingSurface.ref || input.sourceRef || input.sourceBranch || input.authSession?.defaultRef || null;
484+
const sourceCommit = inputState.addressingSurface.commit || input.sourceCommit || null;
485+
const signerAddress = inputState.signingSurface.signerAddress || input.signerAddress || null;
486+
const walletId = signerAddress ? `wallet:${signerAddress}` : null;
487+
const proofRoot = stableHashObject({
488+
kind: 'deposit-proof',
489+
assetId: inputState.assetId,
490+
contentRoot: inputState.contentRoot,
491+
signerAddress,
492+
signatureChecksPass: inputState.signingSurface.signatureChecksPass,
493+
attestationHash: inputState.signingSurface.attestationHash,
494+
authPayloadHash: inputState.githubAppAuthSurface.authPayloadHash
495+
});
496+
const measurementRoot = stableHashObject({
497+
kind: 'deposit-measurement',
498+
assetId: inputState.assetId,
499+
contentRoot: inputState.contentRoot,
500+
staticReceiptIds: (inputState.assetMeasurement.staticExecutionReceipts || []).map((receipt) => receipt.receiptId),
501+
contentUnitHashes: inputState.contentUnits.map((unit) => unit.unitHash)
502+
});
503+
const reconciliationReadbackRoot = stableHashObject({
504+
kind: 'deposit-reconciliation-readback',
505+
assetId: inputState.assetId,
506+
repositoryFullName,
507+
sourceBranch,
508+
sourceCommit,
509+
proofRoot,
510+
measurementRoot,
511+
addressingRoot: inputState.addressingSurface.addressingRoot,
512+
selectedInventoryRoot: inputState.artifactSelectionSurface.selectedInventoryRoot
513+
});
514+
const lexicalDocument = {
515+
schema: 'bitcode.depository.lexical-document',
516+
documentId: `lexical:${inputState.assetId}`,
517+
assetId: inputState.assetId,
518+
title: inputState.title,
519+
artifactKind: inputState.artifactKind,
520+
artifactType: inputState.artifactType,
521+
repositoryFullName,
522+
sourceBranch,
523+
sourceCommit,
524+
contentRoot: inputState.contentRoot,
525+
contentUnitIds: inputState.contentUnits.map((unit) => unit.unitId),
526+
contentUnitRoots: inputState.contentUnits.map((unit) => unit.unitHash),
527+
searchableTermsRoot: stableHashObject({
528+
title: inputState.title,
529+
artifactKind: inputState.artifactKind,
530+
repositoryFullName,
531+
sourceBranch,
532+
sourceCommit,
533+
paths: inputState.addressingSurface.sourcePaths || []
534+
})
535+
};
536+
const vectorDocument = {
537+
schema: 'bitcode.depository.vector-document',
538+
documentId: `vector:${inputState.assetId}`,
539+
assetId: inputState.assetId,
540+
sourceTextRoot: stableHashObject({
541+
assetId: inputState.assetId,
542+
contentRoot: inputState.contentRoot,
543+
contentUnitRoots: inputState.contentUnits.map((unit) => unit.unitHash)
544+
}),
545+
embeddingPolicy: {
546+
model: 'text-embedding-3-small',
547+
dimensions: 1536,
548+
inputKind: 'source-bound-depository-document',
549+
vectorStore: {
550+
table: 'deliverable_vectors',
551+
rpc: 'match_deliverable_vectors',
552+
distanceMetric: 'cosine'
553+
}
554+
},
555+
indexState: 'ready_for_embedding_generation'
556+
};
557+
const lexicalDocumentRoot = stableHashObject(lexicalDocument);
558+
const vectorDocumentRoot = stableHashObject(vectorDocument);
559+
const depositorySearchDocumentRoot = stableHashObject({
560+
schema: 'bitcode.depository.search-document-set',
561+
assetId: inputState.assetId,
562+
lexicalDocumentRoot,
563+
vectorDocumentRoot,
564+
proofRoot,
565+
measurementRoot,
566+
reconciliationReadbackRoot
567+
});
568+
569+
return {
570+
schema: 'bitcode.depository.deposit-evidence',
571+
assetId: inputState.assetId,
572+
repositoryFullName,
573+
sourceBranch,
574+
sourceCommit,
575+
contentRoot: inputState.contentRoot,
576+
proofRoot,
577+
measurementRoot,
578+
reconciliationReadbackRoot,
579+
depositorySearchDocumentRoot,
580+
lexicalDocumentRoot,
581+
vectorDocumentRoot,
582+
searchDocuments: {
583+
lexical: {
584+
...lexicalDocument,
585+
documentRoot: lexicalDocumentRoot
586+
},
587+
vector: {
588+
...vectorDocument,
589+
documentRoot: vectorDocumentRoot
590+
}
591+
},
592+
depositorBoundary: {
593+
walletId,
594+
signerAddress,
595+
signerClass: 'depositor',
596+
ownershipState: 'depositor-owned-before-read-settlement',
597+
readerVisibilityBeforeSettlement: 'measurements-and-non-source-metadata-only'
598+
},
599+
indexState: {
600+
lexical: 'ready',
601+
vector: vectorDocument.indexState,
602+
table: 'deliverable_vectors',
603+
rpc: 'match_deliverable_vectors'
604+
},
605+
sourceProofRoots: {
606+
addressingRoot: inputState.addressingSurface.addressingRoot,
607+
selectedInventoryRoot: inputState.artifactSelectionSurface.selectedInventoryRoot,
608+
authPayloadHash: inputState.githubAppAuthSurface.authPayloadHash
609+
}
610+
};
611+
}
612+
463613
/**
464614
* @param {string} surfaceId
465615
* @param {readonly unknown[]} [values=[]]
@@ -3025,13 +3175,40 @@ export function makeCandidateAsset(input) {
30253175
],
30263176
staticExecutionReceipts: [assetCodeAnalysisReceipt, ...collectStaticExecutionReceipts(contentUnits)]
30273177
};
3178+
const depositoryEvidence = buildDepositoryEvidence(input, {
3179+
assetId,
3180+
title: input.title,
3181+
artifactKind,
3182+
artifactType,
3183+
contentRoot,
3184+
contentUnits,
3185+
addressingSurface,
3186+
artifactSelectionSurface,
3187+
signingSurface,
3188+
githubAppAuthSurface,
3189+
assetMeasurement,
3190+
measurementProvenance: assetMeasurement.provenance
3191+
});
30283192

30293193
return {
30303194
assetId,
30313195
depositedAt: input.depositedAt || nowIso(),
30323196
title: input.title,
30333197
artifactKind,
30343198
artifactType,
3199+
repositoryFullName: depositoryEvidence.repositoryFullName,
3200+
sourceBranch: depositoryEvidence.sourceBranch,
3201+
sourceCommit: depositoryEvidence.sourceCommit,
3202+
hasWalletOrAttestationProof: true,
3203+
hasAssetMeasurementEvidence: true,
3204+
proofRoot: depositoryEvidence.proofRoot,
3205+
measurementRoot: depositoryEvidence.measurementRoot,
3206+
reconciliationReadbackRoot: depositoryEvidence.reconciliationReadbackRoot,
3207+
depositorySearchDocumentRoot: depositoryEvidence.depositorySearchDocumentRoot,
3208+
lexicalDocumentRoot: depositoryEvidence.lexicalDocumentRoot,
3209+
vectorDocumentRoot: depositoryEvidence.vectorDocumentRoot,
3210+
depositorWalletId: depositoryEvidence.depositorBoundary.walletId,
3211+
depositoryEvidence,
30353212
sourceMaterialBinding: {
30363213
mode: input.bindingMode || 'read-only-mounted-copy',
30373214
confidentiality: 'private-required',
@@ -3101,7 +3278,13 @@ export function makeCandidateAsset(input) {
31013278
benchmarkRunId: input.benchmarkRunId || 'gha_run_auth_001',
31023279
reproSteps: input.reproSteps || ['rerun benchmark workflow', 'inspect issuer compatibility logs'],
31033280
pinnedEnvironment: input.pinnedEnvironment || 'ubuntu-24.04 + node 22 + rust stable',
3104-
proofLogs: input.proofLogs || []
3281+
proofLogs: input.proofLogs || [],
3282+
proofRoot: depositoryEvidence.proofRoot,
3283+
measurementRoot: depositoryEvidence.measurementRoot,
3284+
reconciliationReadbackRoot: depositoryEvidence.reconciliationReadbackRoot,
3285+
depositorySearchDocumentRoot: depositoryEvidence.depositorySearchDocumentRoot,
3286+
lexicalDocumentRoot: depositoryEvidence.lexicalDocumentRoot,
3287+
vectorDocumentRoot: depositoryEvidence.vectorDocumentRoot
31053288
},
31063289
metadata: {
31073290
author: input.author,

0 commit comments

Comments
 (0)