Skip to content

Commit 3ce77ec

Browse files
Close Gate 12 settlement rights delivery
Adds the settlement-unlock primitive for protected AssetPack source visibility, wires settlement/read-license/readback evidence into the sandbox harness and Terminal stream surfaces, and documents the Gate 12 closure contract. Extends V28 gate quality checks to cover the new settlement closure script plus BTD primitive typecheck/test coverage.
1 parent d2ed02c commit 3ce77ec

16 files changed

Lines changed: 556 additions & 7 deletions

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

Lines changed: 3 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -48,6 +48,7 @@ jobs:
4848
node scripts/check-v28-gate9-depository-evidence.mjs
4949
node scripts/check-v28-gate10-read-need-comprehension.mjs
5050
node scripts/check-v28-gate11-read-fits-finding-preview.mjs
51+
node scripts/check-v28-gate12-settlement-rights-delivery.mjs
5152
node scripts/promote-bitcode-canon.mjs --version V28 --commit HEAD --dry-run
5253
5354
- name: Validate source casing and imports
@@ -57,11 +58,13 @@ jobs:
5758
5859
- name: Type-check gate packages
5960
run: |
61+
pnpm --filter @bitcode/btd typecheck
6062
pnpm --filter @bitcode/pipeline-asset-pack typecheck
6163
pnpm --filter @bitcode/pipeline-hosts typecheck
6264
6365
- name: Test gate packages
6466
run: |
67+
pnpm --filter @bitcode/btd test
6568
pnpm --filter @bitcode/pipeline-asset-pack exec jest --config jest.config.cjs --passWithNoTests --forceExit
6669
pnpm --filter @bitcode/pipeline-hosts exec jest --config jest.config.cjs --passWithNoTests --forceExit
6770

BITCODE_SPEC_V28.md

Lines changed: 25 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -881,6 +881,31 @@ Gate 12 owns BTC settlement, depositor/reader ownership boundaries, read-license
881881
rows, ledger/database synchronization, protected-source unlock, and PR delivery
882882
of the purchased AssetPack into the Reading repository.
883883

884+
Gate 12 acceptance requires:
885+
886+
- settlement is represented as a typed unlock decision, not as UI inference:
887+
the `bitcode.asset-pack.settlement-unlock` envelope keeps source-bearing
888+
AssetPack material unavailable unless ledger settlement status is `settled`,
889+
settlement is admissible, required readback rows are all present, and
890+
pull-request delivery readback exists when delivery is required;
891+
- BTC payment posture is reader-paid and server-noncustodial. The fee receipt,
892+
wallet authorization/session, network, sats, finality state, and receipt id
893+
remain visible before unlock and must not imply server custody of private
894+
keys;
895+
- depositor/reader boundaries stay separate: the depositor owns the minted BTD
896+
range for the deposited source evidence, while the reader receives a
897+
policy-matching read license only after payment/readback;
898+
- required readback covers semantic measurement, measure-mint receipt,
899+
AssetPack range, BTD cell, ownership event, read license, mint receipt, BTC
900+
fee transaction, ledger anchor, Terminal journal rows, and crypto telemetry;
901+
- source-safe preview is upgraded only by settlement readback. After settlement,
902+
the preview access state becomes `licensed_read`, unlock reports
903+
`sourceAvailable=true`, and delivery points at the pull request. Before that,
904+
the preview stays `pending_settlement` or `denied`;
905+
- Terminal exposes ledger status, unlock state, read-license id, BTC fee receipt
906+
id, and PR target in the five-step Reading flow, while expandable stream
907+
metadata retains full settlement and readback evidence.
908+
884909
### Gate 13: Commercial Product Closure And Promotion Readiness
885910

886911
Gate 13 owns final commercial-product closure: website application UX, package

BITCODE_SPEC_V28_PARITY_MATRIX.md

Lines changed: 10 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -196,6 +196,16 @@ boundary, settlement boundary, and BTC quote before settlement. Gate 12 remains
196196
responsible for paid unlock, rights transfer, ledger reconciliation, and PR
197197
delivery.
198198

199+
Gate 12 closure narrows the two Gate 12 carryforward rows to paid-unlock
200+
readiness: settlement must produce a typed
201+
`bitcode.asset-pack.settlement-unlock` decision from ledger settlement evidence,
202+
readback booleans, and delivery posture. Protected source can become available
203+
only when BTC fee, BTD range, ownership event, read-license row, mint receipt,
204+
ledger anchor, Terminal journal, crypto telemetry, and pull-request delivery
205+
read back together. Terminal must show the unlock state, read-license id, BTC
206+
fee receipt id, ledger status, and PR target without treating unpaid preview
207+
metadata as source access.
208+
199209
## V28 implementation matrix
200210

201211
| Area | Current source evidence | Judgment | Gate owner |

BITCODE_V28_QA.md

Lines changed: 36 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -2144,3 +2144,39 @@ Expected evidence:
21442144
- The preview must not expose protected source content, full patches,
21452145
source-bearing manifest entries, licensed read payloads, or PR source changes
21462146
before settlement. Gate 12 owns paid unlock, rights transfer, and delivery.
2147+
2148+
### Gate 12 Settlement, Rights, Delivery, And Reconciliation QA
2149+
2150+
Gate 12 local closure proves that paid AssetPack unlock is derived from typed
2151+
settlement/readback evidence and never from source-safe preview metadata alone.
2152+
2153+
Required local checks:
2154+
2155+
```bash
2156+
pnpm run check:v28-gate12
2157+
pnpm --filter @bitcode/btd typecheck
2158+
pnpm --filter @bitcode/btd test
2159+
pnpm --filter @bitcode/pipeline-hosts typecheck
2160+
pnpm --filter @bitcode/pipeline-hosts exec jest --config jest.config.cjs --passWithNoTests --forceExit
2161+
pnpm --dir uapi exec jest --runTestsByPath \
2162+
tests/api/pipelineHarnessRoute.test.ts \
2163+
tests/terminalPipelineHarnessClient.test.ts \
2164+
tests/terminalDepositReadWorkbench.test.ts \
2165+
--runInBand
2166+
```
2167+
2168+
Expected evidence:
2169+
2170+
- `packages/btd` exports `bitcode.asset-pack.settlement-unlock` construction
2171+
and preview application helpers. They return `licensed_read` and
2172+
`sourceAvailable=true` only after settlement is settled/admissible, all
2173+
required readback keys are true, and required pull-request delivery exists.
2174+
- The sandbox harness applies settlement unlock after ledger settlement
2175+
readback, stores `asset-pack/settlement.unlock`, and embeds
2176+
`ledgerSettlement.protectedSourceUnlock` plus the updated source-safe preview
2177+
in evidence.
2178+
- Route and Terminal stream summaries surface ledger status, fee quote,
2179+
source-unlock state, read-license id, BTC fee receipt id, and PR target.
2180+
- Missing read-license, BTC fee, ownership, journal, ledger anchor, telemetry,
2181+
or delivery readback leaves protected source withheld and records the blocking
2182+
readback key.

package.json

Lines changed: 1 addition & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -42,6 +42,7 @@
4242
"check:v28-gate9": "node scripts/check-v28-gate9-depository-evidence.mjs",
4343
"check:v28-gate10": "node scripts/check-v28-gate10-read-need-comprehension.mjs",
4444
"check:v28-gate11": "node scripts/check-v28-gate11-read-fits-finding-preview.mjs",
45+
"check:v28-gate12": "node scripts/check-v28-gate12-settlement-rights-delivery.mjs",
4546
"check:spec-quality": "node scripts/run-bitcode-spec-quality.mjs --mode basic",
4647
"check:spec-quality:title": "node scripts/run-bitcode-spec-quality.mjs --mode strict-from-title",
4748
"check:spec-quality:v24": "node scripts/run-bitcode-spec-quality.mjs --mode strict-version --version V24",

packages/btd/__tests__/btd.test.ts

Lines changed: 93 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -9,8 +9,10 @@ import {
99
BtdFungibleMutationRejectedError,
1010
BTD_MAX_MINTABLE_SUPPLY,
1111
BITCODE_FEE_ASSET,
12+
applyAssetPackSettlementUnlockToPreview,
1213
assertBtdAccessPolicyTemplateCoverage,
1314
assertBtdMintableSupplyLimit,
15+
buildAssetPackSettlementUnlock,
1416
buildBtdReadAccessProjectionFromRegistryRows,
1517
calculateLlmBtcFeeEstimate,
1618
calculateMeasuredBtdFromTokens,
@@ -44,6 +46,97 @@ describe('calculateLlmBtcFeeEstimate', () => {
4446
});
4547
});
4648

49+
describe('AssetPack settlement unlock', () => {
50+
const completeReadback = {
51+
semanticMeasurement: true,
52+
measureMintReceipt: true,
53+
assetPackRange: true,
54+
btdCell: true,
55+
ownershipEvent: true,
56+
readLicense: true,
57+
mintReceipt: true,
58+
btcFeeTransaction: true,
59+
ledgerAnchor: true,
60+
terminalJournal: true,
61+
cryptoTelemetry: true,
62+
};
63+
64+
it('unlocks protected source only after settlement, readback, license, and delivery agree', () => {
65+
const unlock = buildAssetPackSettlementUnlock({
66+
ledgerSettlement: {
67+
status: 'settled',
68+
settlementAdmissible: true,
69+
assetPackId: 'asset-pack-1',
70+
ledgerAnchorId: 'ledger-anchor-1',
71+
btcFeeReceiptId: 'btc-fee-1',
72+
ownershipEventId: 'ownership-1',
73+
readLicenseId: 'license-1',
74+
depositorWalletId: 'wallet-depositor',
75+
readerWalletId: 'wallet-reader',
76+
readback: completeReadback,
77+
},
78+
pullRequestTarget: 'https://github.com/engineeredsoftware/ENGI/pull/42',
79+
});
80+
81+
expect(unlock).toMatchObject({
82+
schema: 'bitcode.asset-pack.settlement-unlock',
83+
state: 'licensed_read',
84+
sourceAvailable: true,
85+
settlementAdmissible: true,
86+
deliveryAvailable: true,
87+
assetPackId: 'asset-pack-1',
88+
readLicenseId: 'license-1',
89+
btcFeeReceiptId: 'btc-fee-1',
90+
missingReadbackKeys: [],
91+
});
92+
93+
const preview = applyAssetPackSettlementUnlockToPreview(
94+
{
95+
accessPolicy: { readRightState: 'pending_settlement' },
96+
unlock: { state: 'pending_settlement', sourceAvailable: false },
97+
delivery: { pullRequestTarget: null, availableAfterSettlement: true },
98+
},
99+
unlock,
100+
);
101+
102+
expect(preview).toMatchObject({
103+
accessPolicy: { readRightState: 'licensed_read' },
104+
unlock: {
105+
state: 'licensed_read',
106+
sourceAvailable: true,
107+
},
108+
delivery: {
109+
pullRequestTarget: 'https://github.com/engineeredsoftware/ENGI/pull/42',
110+
},
111+
settlementUnlock: unlock,
112+
});
113+
});
114+
115+
it('keeps protected source withheld when any settlement readback key is missing', () => {
116+
const unlock = buildAssetPackSettlementUnlock({
117+
ledgerSettlement: {
118+
status: 'settled',
119+
settlementAdmissible: true,
120+
assetPackId: 'asset-pack-1',
121+
readLicenseId: 'license-1',
122+
readback: {
123+
...completeReadback,
124+
readLicense: false,
125+
},
126+
},
127+
pullRequestTarget: 'https://github.com/engineeredsoftware/ENGI/pull/42',
128+
});
129+
130+
expect(unlock).toMatchObject({
131+
state: 'pending_settlement',
132+
sourceAvailable: false,
133+
settlementAdmissible: false,
134+
missingReadbackKeys: ['readLicense'],
135+
});
136+
expect(unlock.reason).toContain('readLicense');
137+
});
138+
});
139+
47140
describe('calculateMeasuredBtdFromTokens', () => {
48141
it('measures content amount without implying spend', () => {
49142
expect(calculateMeasuredBtdFromTokens({ inputTokens: 1200, outputTokens: 50 })).toBe(2);

packages/btd/src/index.ts

Lines changed: 1 addition & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -171,6 +171,7 @@ export * from './reconciliation';
171171
export * from './replay';
172172
export * from './revenue';
173173
export * from './semantic-volume';
174+
export * from './settlement';
174175
export * from './supply';
175176
export * from './telemetry';
176177
export * from './terminal-journal';

0 commit comments

Comments
 (0)