Skip to content

Commit ba357d1

Browse files
Merge pull request #206 from engineeredsoftware/v45/gate-3-assetpack-lifecycle-state-machine
V45 Gate 3: AssetPack Lifecycle State Machine
2 parents 85e4f9e + cf73fed commit ba357d1

3 files changed

Lines changed: 226 additions & 0 deletions

File tree

BITCODE_SPEC_V45_NOTES.md

Lines changed: 65 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -200,6 +200,71 @@ Need-relative, source-safety before settlement, repository delivery after rights
200200
proof, and proof/ledger/journal observability as Bitcode's market-infrastructure
201201
rails.
202202

203+
## V45 protocol atom 2: AssetPack lifecycle state machine
204+
205+
Audit classification: V43/V44 correctly establish AssetPacks in and
206+
AssetPacks out, but the canon still spreads lifecycle law across `/deposit`,
207+
`/read`, `/packs`, BTD accounting, preview, settlement, and delivery sections.
208+
V45 consolidates the lifecycle into one source-safe state machine before it
209+
specifies BTD calculation and BTC settlement state in later atoms.
210+
211+
Protocol-law statement:
212+
213+
Every AssetPack-like object must occupy exactly one lifecycle state at every
214+
protocol boundary, and every transition must state whether the object is source
215+
safe only, source-bearing but withheld, quoteable, settled, deliverable,
216+
compensable, or in repair. No interface, API, pipeline, proof artifact, or
217+
operator tool may collapse lifecycle states to make a deposit option look like
218+
settled BTD, a preview look like source disclosure, a quote look like payment
219+
finality, or an admitted Depository AssetPack look like a delivered Need-Fit
220+
AssetPack.
221+
222+
The canonical AssetPack lifecycle states are:
223+
224+
| State | Owner boundary | Source visibility | BTD posture | Required proof |
225+
| --- | --- | --- | --- | --- |
226+
| `deposit-option-synthesized` | Depositor-connected source and deposit pipeline | Source-safe measurements and metadata only; protected source remains outside visible Bitcode surfaces | Deposit-time BTD-relevant measurements may show potential, coverage, likely utility, criticality, and search posture; no final BTD size | option synthesis root, source-safety root, measurement root |
227+
| `deposit-option-reviewed` | Depositor review | Same source-safe view; depositor may approve, reject, or request resynthesis | Still no final BTD size and no minted BTD | review decision root and policy root |
228+
| `depository-assetpack-admitted` | Depository supply | Searchable source-safe metadata, measurements, embeddings, and external protected-source pointer roots only | Admitted supply may carry BTD potential, not final BTD, because no reviewed Need has selected it yet | admission receipt, Depository index root, storage projection root |
229+
| `fit-candidates-recalled` | Reading Finding Fits search | Candidate identity, ranking, measurements, and provenance are source-safe to the Reader; candidate source remains withheld | Candidate BTD contribution is only provisional until selected against the reviewed Need | query root, search-channel roots, ranking root |
230+
| `fit-set-selected` | Reading Finding Fits selection | Selected Fit set provenance is source-safe; protected source remains withheld from the Reader | Need-relative contribution can be measured for quote preparation, but rights-bearing BTD is not minted or transferred | selected-fit root, threshold root, verification root |
231+
| `need-fit-assetpack-synthesized` | AssetPack synthesis pipeline | Source-bearing pack material may exist internally, but Reader-visible output is only a source-safe preview | Need-relative BTD scalar volume may be computed for quote; it is not settled BTD | synthesis root, withheld-source bundle root, preview boundary root |
232+
| `need-fit-assetpack-quoted` | Reading procurement and quote authority | Source-safe measurements, metadata, quality posture, BTD volume/range, BTC quote, expiration, and proof roots only | Quoteable BTD volume exists because a reviewed Need and selected Fit set exist; rights are still unpaid and untransferred | quote root, budget approval root when required, expiry root |
233+
| `settlement-observed` | BTC observation and ledger/database journal | Still source-safe to the Reader until settlement finality and BTD transfer are proven | BTC payment is observed but not final; BTD rights are not yet authoritative | BTC observation root, journal root, reconciliation root |
234+
| `btd-settled-rights-transferred` | BTD and settlement authority | Source unlock is authorized for the paying Reader and still withheld from other parties | Rights-bearing BTD is minted/mined/assigned for the Need-Fit AssetPack according to the later BTD state machine | final settlement root, BTD rights receipt, source-to-shares root |
235+
| `source-unlocked-delivery` | Repository delivery authority | Full source-bearing AssetPack delivery is visible only to the entitled Reader boundary, such as the target repository pull request | BTD rights authorize delivery and future ownership/read/use boundaries | source unlock root, repository delivery receipt, pull request root |
236+
| `compensated-and-reconciled` | Contributor compensation and Packs accounting | `/packs` shows source-safe settlement, delivery, and compensation readback; protected source remains boundary-scoped | Source-to-shares allocation and BTC compensation statements reconcile to settlement truth | compensation statement root, ledger/database/storage reconciliation root |
237+
| `repair-required` | Operator repair | Only source-safe failure class, blocker, repair command, and proof roots are visible | No state may advance until the failed transition is repaired and replayed | repair case root, replay root, operator action root |
238+
239+
Transition law:
240+
241+
- A deposit option may transition to `depository-assetpack-admitted` only after
242+
depositor approval, policy eligibility, source-safety verification, and
243+
storage/index projection.
244+
- A Depository AssetPack may transition into Reading only through Finding Fits;
245+
the search may recall many candidates above threshold, and the selected Fit
246+
set may contain one or many admitted Depository AssetPacks.
247+
- The Need-Fit AssetPack is synthesized from the reviewed Need plus the selected
248+
Fit set. It is a new Need-relative AssetPack state, not a disclosure of the
249+
underlying admitted Depository AssetPacks.
250+
- The Reader may review the Need-Fit preview and quote, but may not see source
251+
before BTC settlement finality and BTD rights transfer.
252+
- BTD final scalar knowledge-volume is Need-relative. It may be calculated for
253+
quote only after the reviewed Need, selected Fit set, and synthesized
254+
Need-Fit AssetPack exist; it becomes rights-bearing only after settlement.
255+
- BTC payment observation, BTC finality, BTD rights transfer, source unlock,
256+
repository delivery, source-to-shares compensation, and reconciliation are
257+
distinct states and must not be represented as synonyms.
258+
- Any missing proof root, stale storage projection, failed source-safety check,
259+
failed payment finality, failed rights transfer, failed delivery, or failed
260+
compensation reconciliation moves the object to `repair-required`.
261+
262+
Acceptance for this atom: later V45 specification may refine field names and
263+
proof root schemas, but it must preserve this lifecycle ordering, exact state
264+
separation, source visibility boundaries, Need-relative BTD calculation
265+
condition, one-to-many Finding Fits input set, BTC settlement-before-source law,
266+
and repair-required fail-closed posture.
267+
203268
## Non-goals during V45 opening
204269

205270
- Do not implement V45 gate behavior before the V45 intent discussion is

package.json

Lines changed: 1 addition & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -388,6 +388,7 @@
388388
"check:v44-promotion-readiness": "node scripts/generate-v44-promotion-readiness-report.mjs --check",
389389
"check:v44-gate10": "node scripts/check-v44-gate10-promotion-readiness.mjs",
390390
"check:v45-gate2": "node scripts/check-v45-gate2-knowledge-commoditization-law.mjs",
391+
"check:v45-gate3": "node scripts/check-v45-gate3-assetpack-lifecycle-state-machine.mjs",
391392
"generate:v38-inference-surface-inventory": "node scripts/generate-v38-inference-surface-inventory.mjs",
392393
"check:v38-inference-surface-inventory": "node scripts/generate-v38-inference-surface-inventory.mjs --check",
393394
"check:v38-gate2": "node scripts/check-v38-gate2-inference-surface-inventory.mjs",
Lines changed: 160 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,160 @@
1+
#!/usr/bin/env node
2+
3+
import { execFileSync } from 'node:child_process';
4+
import { existsSync, readFileSync } from 'node:fs';
5+
import path from 'node:path';
6+
import { fileURLToPath } from 'node:url';
7+
8+
const __filename = fileURLToPath(import.meta.url);
9+
const __dirname = path.dirname(__filename);
10+
const defaultRepoRoot = path.resolve(__dirname, '..');
11+
12+
function read(root, relativePath) {
13+
return readFileSync(path.join(root, relativePath), 'utf8');
14+
}
15+
16+
function exists(root, relativePath) {
17+
return existsSync(path.join(root, relativePath));
18+
}
19+
20+
function git(root, args) {
21+
return execFileSync('git', args, { cwd: root, encoding: 'utf8' }).trim();
22+
}
23+
24+
function assertCheck(failures, condition, message) {
25+
if (!condition) failures.push(message);
26+
}
27+
28+
function normalize(content) {
29+
return content.replace(/\s+/gu, ' ').trim();
30+
}
31+
32+
function parseArgs(argv) {
33+
const args = { repoRoot: defaultRepoRoot, skipBranchCheck: false };
34+
for (let index = 0; index < argv.length; index += 1) {
35+
const arg = argv[index];
36+
if (arg === '--repo-root') args.repoRoot = path.resolve(argv[++index]);
37+
else if (arg === '--skip-branch-check') args.skipBranchCheck = true;
38+
else if (arg === '--help' || arg === '-h') args.help = true;
39+
else throw new Error(`Unknown argument ${arg}`);
40+
}
41+
return args;
42+
}
43+
44+
function printHelp() {
45+
process.stdout.write(
46+
[
47+
'Usage: node scripts/check-v45-gate3-assetpack-lifecycle-state-machine.mjs [--skip-branch-check] [--repo-root <path>]',
48+
'',
49+
'Checks the V45 AssetPack lifecycle state machine specification atom.',
50+
].join('\n'),
51+
);
52+
process.stdout.write('\n');
53+
}
54+
55+
function main() {
56+
const args = parseArgs(process.argv.slice(2));
57+
if (args.help) {
58+
printHelp();
59+
return;
60+
}
61+
62+
const root = args.repoRoot;
63+
const failures = [];
64+
const pointer = read(root, 'BITCODE_SPEC.txt').trim();
65+
66+
assertCheck(failures, pointer === 'V44', `BITCODE_SPEC.txt must remain V44 during V45 atom work. Observed ${pointer || 'empty'}.`);
67+
68+
if (!args.skipBranchCheck) {
69+
const branch = git(root, ['branch', '--show-current']);
70+
assertCheck(
71+
failures,
72+
branch === 'version/v45' || /^v45\/gate-\d+-[a-z0-9][a-z0-9-]*$/u.test(branch),
73+
`V45 work must occur on version/v45 or v45/gate-N-* branches. Observed ${branch || 'detached HEAD'}.`,
74+
);
75+
}
76+
77+
for (const relativePath of [
78+
'BITCODE_SPEC_V45_NOTES.md',
79+
'BITCODE_SPEC_V44.md',
80+
'package.json',
81+
'scripts/check-v45-gate2-knowledge-commoditization-law.mjs',
82+
]) {
83+
assertCheck(failures, exists(root, relativePath), `Missing required V45 Gate 3 file: ${relativePath}`);
84+
}
85+
86+
const notes = read(root, 'BITCODE_SPEC_V45_NOTES.md');
87+
const normalizedNotes = normalize(notes);
88+
const packageJson = read(root, 'package.json');
89+
90+
for (const phrase of [
91+
'V45 protocol atom 2: AssetPack lifecycle state machine',
92+
'V43/V44 correctly establish AssetPacks in and AssetPacks out',
93+
'Every AssetPack-like object must occupy exactly one lifecycle state at every protocol boundary',
94+
'source safe only, source-bearing but withheld, quoteable, settled, deliverable, compensable, or in repair',
95+
'No interface, API, pipeline, proof artifact, or operator tool may collapse lifecycle states',
96+
'deposit option look like settled BTD',
97+
'preview look like source disclosure',
98+
'quote look like payment finality',
99+
'admitted Depository AssetPack look like a delivered Need-Fit AssetPack',
100+
'deposit-option-synthesized',
101+
'deposit-option-reviewed',
102+
'depository-assetpack-admitted',
103+
'fit-candidates-recalled',
104+
'fit-set-selected',
105+
'need-fit-assetpack-synthesized',
106+
'need-fit-assetpack-quoted',
107+
'settlement-observed',
108+
'btd-settled-rights-transferred',
109+
'source-unlocked-delivery',
110+
'compensated-and-reconciled',
111+
'repair-required',
112+
'Deposit-time BTD-relevant measurements may show potential',
113+
'no final BTD size',
114+
'Admitted supply may carry BTD potential, not final BTD',
115+
'Candidate BTD contribution is only provisional until selected against the reviewed Need',
116+
'Need-relative BTD scalar volume may be computed for quote',
117+
'rights-bearing BTD is not minted or transferred',
118+
'Quoteable BTD volume exists because a reviewed Need and selected Fit set exist',
119+
'BTC payment is observed but not final',
120+
'Rights-bearing BTD is minted/mined/assigned for the Need-Fit AssetPack',
121+
'A deposit option may transition to `depository-assetpack-admitted` only after depositor approval',
122+
'the search may recall many candidates above threshold',
123+
'selected Fit set may contain one or many admitted Depository AssetPacks',
124+
'The Need-Fit AssetPack is synthesized from the reviewed Need plus the selected Fit set',
125+
'may not see source before BTC settlement finality and BTD rights transfer',
126+
'BTD final scalar knowledge-volume is Need-relative',
127+
'becomes rights-bearing only after settlement',
128+
'BTC payment observation, BTC finality, BTD rights transfer, source unlock, repository delivery, source-to-shares compensation, and reconciliation are distinct states',
129+
'moves the object to `repair-required`',
130+
'Acceptance for this atom',
131+
'Need-relative BTD calculation condition',
132+
'one-to-many Finding Fits input set',
133+
'BTC settlement-before-source law',
134+
]) {
135+
assertCheck(failures, normalizedNotes.includes(phrase), `V45 Gate 3 notes must include phrase: ${phrase}`);
136+
}
137+
138+
assertCheck(
139+
failures,
140+
packageJson.includes('"check:v45-gate3": "node scripts/check-v45-gate3-assetpack-lifecycle-state-machine.mjs"'),
141+
'package.json must expose check:v45-gate3.',
142+
);
143+
144+
if (failures.length > 0) {
145+
process.stderr.write('V45 Gate 3 AssetPack lifecycle state machine check failed:\n');
146+
for (const failure of failures) process.stderr.write(`- ${failure}\n`);
147+
process.exitCode = 1;
148+
return;
149+
}
150+
151+
process.stdout.write('V45 Gate 3 AssetPack lifecycle state machine check passed.\n');
152+
}
153+
154+
try {
155+
main();
156+
} catch (error) {
157+
const detail = error instanceof Error ? error.message : String(error);
158+
process.stderr.write(`${detail}\n`);
159+
process.exitCode = 1;
160+
}

0 commit comments

Comments
 (0)