ruvnet-brain 4.0.90-dev → 4.2.2-dev

This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
@@ -37,6 +37,7 @@ import { verifyPayload } from './release-payload.mjs';
37
37
 
38
38
  const ROOT = path.dirname(path.dirname(fileURLToPath(import.meta.url)));
39
39
  const PUBLISH = process.argv.includes('--publish');
40
+ const CORPUS_SEED = process.argv.includes('--corpus-seed');
40
41
  let protectedCandidate = null;
41
42
  let sealedPackageArtifact = null;
42
43
  let publicationReceiptPath = null;
@@ -56,6 +57,147 @@ function runOrDie(label, cmd, args, opts = {}) {
56
57
  }
57
58
  }
58
59
 
60
+ const cliArg = (argv, name) => {
61
+ const index = argv.indexOf(name);
62
+ return index >= 0 ? argv[index + 1] : undefined;
63
+ };
64
+ const isHex = (value, length) => new RegExp(`^[a-f0-9]{${length}}$`).test(String(value || ''));
65
+ const sha256File = (file) => {
66
+ const hash = crypto.createHash('sha256');
67
+ const fd = fs.openSync(file, 'r');
68
+ const buffer = Buffer.allocUnsafe(1024 * 1024);
69
+ try {
70
+ let bytes;
71
+ while ((bytes = fs.readSync(fd, buffer, 0, buffer.length, null)) > 0) hash.update(buffer.subarray(0, bytes));
72
+ } finally {
73
+ fs.closeSync(fd);
74
+ }
75
+ return hash.digest('hex');
76
+ };
77
+ const exactFileIdentity = (value) => value && typeof value.file === 'string'
78
+ && isHex(value.sha256, 64) && Number.isSafeInteger(value.bytes) && value.bytes >= 0;
79
+
80
+ function corpusFailure(message) {
81
+ throw new Error(`[corpus-seed] ${message}`);
82
+ }
83
+
84
+ export function runProtectedCorpusSeed({
85
+ argv = process.argv.slice(2),
86
+ env = process.env,
87
+ root = ROOT,
88
+ run = (command, args, options) => spawnSync(command, args, { encoding: 'utf8', ...options }),
89
+ } = {}) {
90
+ if (env.GITHUB_ACTIONS !== 'true' || env.GITHUB_WORKFLOW !== 'protected-release'
91
+ || env.GITHUB_REPOSITORY !== 'stuinfla/ruvnet-brain') {
92
+ corpusFailure('publication is allowed only inside the protected-release GitHub workflow for stuinfla/ruvnet-brain');
93
+ }
94
+
95
+ const tag = cliArg(argv, '--corpus-tag');
96
+ const bundleFile = cliArg(argv, '--corpus-bundle');
97
+ const receiptFile = cliArg(argv, '--corpus-receipt');
98
+ const target = cliArg(argv, '--target');
99
+ const repo = cliArg(argv, '--repo') || env.GITHUB_REPOSITORY;
100
+ const digestMatch = String(tag || '').match(/^corpus-sha256-([a-f0-9]{64})$/);
101
+ if (!digestMatch) corpusFailure('corpus tag must be corpus-sha256- followed by 64 lowercase hex characters');
102
+ if (repo !== env.GITHUB_REPOSITORY || repo !== 'stuinfla/ruvnet-brain') corpusFailure('repository does not match the protected workflow');
103
+
104
+ for (const [label, file] of [['bundle', bundleFile], ['receipt', receiptFile]]) {
105
+ if (!file || !path.isAbsolute(file)) corpusFailure(`${label} must be an absolute regular file`);
106
+ try {
107
+ const stat = fs.lstatSync(file);
108
+ if (!stat.isFile() || stat.isSymbolicLink()) corpusFailure(`${label} must be an absolute regular file`);
109
+ } catch (error) {
110
+ if (String(error.message).startsWith('[corpus-seed]')) throw error;
111
+ corpusFailure(`${label} must be an absolute regular file (${error.message})`);
112
+ }
113
+ }
114
+
115
+ const headResult = run('git', ['rev-parse', 'HEAD'], {
116
+ cwd: root, encoding: 'utf8', stdio: ['ignore', 'pipe', 'pipe'],
117
+ });
118
+ if (headResult.error || headResult.status !== 0) corpusFailure('cannot resolve release HEAD');
119
+ const head = String(headResult.stdout || '').trim();
120
+
121
+ let receipt;
122
+ try {
123
+ receipt = JSON.parse(fs.readFileSync(receiptFile, 'utf8'));
124
+ } catch (error) {
125
+ corpusFailure(`corpus receipt is unreadable/corrupt (${error.message})`);
126
+ }
127
+ if (!isHex(target, 40) || target !== head || target !== env.GITHUB_SHA || target !== receipt.builderSourceSha) {
128
+ corpusFailure('target must exactly equal HEAD, GITHUB_SHA, and the corpus receipt builderSourceSha');
129
+ }
130
+
131
+ const boundaryIdentities = [receipt.privateFence, receipt.eligibilityPolicy, receipt.generationLedger];
132
+ const storeBindingsValid = Number.isSafeInteger(receipt.storeCount) && receipt.storeCount > 0
133
+ && Array.isArray(receipt.stores) && receipt.stores.length === receipt.storeCount
134
+ && receipt.stores.every((store) => typeof store?.name === 'string' && store.name.length > 0
135
+ && /^[a-f0-9]{7,64}$/.test(String(store.sourceCommit || ''))
136
+ && typeof store.builtUtc === 'string' && Number.isFinite(Date.parse(store.builtUtc))
137
+ && typeof store.model === 'string' && store.model.length > 0
138
+ && Number.isSafeInteger(store.dimensions) && store.dimensions > 0
139
+ && Array.isArray(store.files) && store.files.length > 0 && store.files.every(exactFileIdentity));
140
+ const emptyFailureArrays = ['duplicateRvfDigests', 'unreceiptedRvfFiles', 'missingSidecars']
141
+ .every((key) => Array.isArray(receipt[key]) && receipt[key].length === 0);
142
+ const privateExclusionsValid = Array.isArray(receipt.excludedPrivateStores)
143
+ && receipt.excludedPrivateStores.every((name) => typeof name === 'string' && name.length > 0);
144
+ const generatorFile = path.join(root, 'scripts/corpus-candidate.mjs');
145
+ const generatorValid = fs.existsSync(generatorFile)
146
+ && receipt.generator?.corpusCandidateSha256 === sha256File(generatorFile);
147
+ if (receipt.schemaVersion !== 1 || receipt.kind !== 'ruvnet-brain-corpus-candidate'
148
+ || !receipt.createdAt || !receipt.coverageGeneration || !storeBindingsValid || !emptyFailureArrays
149
+ || !privateExclusionsValid || !boundaryIdentities.every(exactFileIdentity) || !exactFileIdentity(receipt.archive)
150
+ || !generatorValid
151
+ || receipt.archive.file !== path.basename(bundleFile)) {
152
+ corpusFailure('corpus receipt bindings are incomplete or invalid');
153
+ }
154
+
155
+ const archiveSha256 = sha256File(bundleFile);
156
+ if (archiveSha256 !== receipt.archive.sha256 || fs.statSync(bundleFile).size !== receipt.archive.bytes) {
157
+ corpusFailure('archive bytes do not match the corpus receipt');
158
+ }
159
+ if (digestMatch[1] !== archiveSha256) corpusFailure('corpus tag digest does not match the receipt and archive');
160
+
161
+ const viewArgs = ['release', 'view', tag, '--json', 'tagName', '--repo', repo];
162
+ const view = run('gh', viewArgs, { encoding: 'utf8', stdio: ['ignore', 'pipe', 'pipe'] });
163
+ if (!view.error && view.status === 0) corpusFailure(`release ${tag} already exists; refusing to overwrite immutable corpus seed`);
164
+ const viewError = String(view.error?.message || view.stderr || view.stdout || '');
165
+ if (!/(release not found|no release found)/i.test(viewError)) corpusFailure(`cannot prove ${tag} is absent (${viewError.trim() || `gh exited ${view.status}`})`);
166
+
167
+ const notes = [
168
+ 'Content-addressed RuvNet Brain corpus seed.',
169
+ `Archive SHA-256: ${archiveSha256}`,
170
+ `Receipt SHA-256: ${sha256File(receiptFile)}`,
171
+ `Stores: ${receipt.storeCount}`,
172
+ `Coverage generation: ${receipt.coverageGeneration}`,
173
+ 'This published prerelease is immutable and must never be replaced.',
174
+ ].join('\n');
175
+ const createArgs = [
176
+ 'release', 'create', tag,
177
+ '--prerelease', '--latest=false',
178
+ '--target', target,
179
+ '--repo', repo,
180
+ '--title', `Immutable corpus seed ${archiveSha256.slice(0, 16)}`,
181
+ '--notes', notes,
182
+ bundleFile, receiptFile,
183
+ ];
184
+ const create = run('gh', createArgs, { encoding: 'utf8', stdio: ['ignore', 'pipe', 'pipe'] });
185
+ if (create.error || create.status !== 0) {
186
+ corpusFailure(`protected corpus publication failed (${String(create.error?.message || create.stderr || create.stdout || '').trim()})`);
187
+ }
188
+ return { tag, target, repository: repo, archiveSha256, receiptSha256: sha256File(receiptFile) };
189
+ }
190
+
191
+ if (CORPUS_SEED) {
192
+ try {
193
+ const result = runProtectedCorpusSeed();
194
+ console.log(JSON.stringify({ ok: true, mode: 'corpus-seed', ...result }, null, 2));
195
+ } catch (error) {
196
+ console.error(error.message);
197
+ process.exitCode = 1;
198
+ }
199
+ } else {
200
+
59
201
  console.log(`\n${c.b('RuvNet Brain — release / definition-of-done')} ${c.dim('· ' + (PUBLISH ? 'PUBLISH' : 'check-only') + ' · shipping ' + V())}\n`);
60
202
 
61
203
  // The local CLI remains useful as a read-only preflight, but publication authority lives only in
@@ -195,6 +337,8 @@ if (PUBLISH) {
195
337
  bundleSignaturePath: path.join(payloadRoot, 'ruvnet-brain.zip.sig'),
196
338
  bundleDigestPath: path.join(payloadRoot, 'ruvnet-brain.zip.sha256'),
197
339
  packagePath: byRole.get('npm'),
340
+ corpusSeedPath: byRole.get('corpus-seed'),
341
+ generationLedgerPath: byRole.get('generation-ledger'),
198
342
  };
199
343
  for (const asset of Object.values(assets)) {
200
344
  if (!fs.existsSync(asset)) {
@@ -224,6 +368,8 @@ if (PUBLISH) {
224
368
  bundleSha256,
225
369
  bundleSignatureSha256: crypto.createHash('sha256').update(fs.readFileSync(assets.bundleSignaturePath)).digest('hex'),
226
370
  bundleDigestSha256: crypto.createHash('sha256').update(fs.readFileSync(assets.bundleDigestPath)).digest('hex'),
371
+ corpusSeedSha256: crypto.createHash('sha256').update(fs.readFileSync(assets.corpusSeedPath)).digest('hex'),
372
+ generationLedgerSha256: crypto.createHash('sha256').update(fs.readFileSync(assets.generationLedgerPath)).digest('hex'),
227
373
  };
228
374
  const privatePem = process.env.RUVNET_SIGNING_KEY;
229
375
  if (!privatePem) throw new Error('RUVNET_SIGNING_KEY is required for signed transaction receipts');
@@ -254,3 +400,4 @@ if (PUBLISH) {
254
400
  } else {
255
401
  console.log(`\n${c.g(c.b('✓✓✓ PREFLIGHT PASS — NOT PUBLISHED'))} — the committed candidate passed every check-only gate.\n`);
256
402
  }
403
+ }
@@ -119,3 +119,47 @@ export function verifyRvfGenerations(dir, {
119
119
  }
120
120
  return { manifest, failures };
121
121
  }
122
+
123
+ // Release-time closure check for the exact public roots selected for a bundle. Unlike the
124
+ // source-only verifier above, this rejects every ambiguity in the byte-bearing asset directory.
125
+ export function validateSelectedRvfGenerations(dir, {
126
+ selectedStores = canonicalRvfStores(dir),
127
+ privateStores = [],
128
+ version,
129
+ releaseTag,
130
+ } = {}) {
131
+ const manifest = readRvfGenerations(dir);
132
+ const failures = [];
133
+ const selected = [...new Set(selectedStores)].sort();
134
+ const selectedLower = new Map(selected.map((name) => [name.toLowerCase(), name]));
135
+ const privateLower = new Set(privateStores.map((name) => String(name).toLowerCase()));
136
+ if (version !== undefined && manifest.brainVersion !== version) failures.push(`brainVersion=${manifest.brainVersion}, expected ${version}`);
137
+ if (releaseTag !== undefined && manifest.releaseTag !== releaseTag) failures.push(`releaseTag=${manifest.releaseTag}, expected ${releaseTag}`);
138
+ for (const name of selected) if (privateLower.has(name.toLowerCase())) failures.push(`${name}: private store selected`);
139
+ for (const [store, row] of Object.entries(manifest.stores || {})) {
140
+ const canonical = selectedLower.get(store.toLowerCase());
141
+ if (!canonical) {
142
+ if (!privateLower.has(store.toLowerCase())) failures.push(`${store}: extra generation record`);
143
+ continue;
144
+ }
145
+ if (canonical !== store) failures.push(`${store}: alias differs from selected store ${canonical}`);
146
+ const expectedFile = `${canonical}.big.rvf`;
147
+ if (row?.file !== expectedFile) failures.push(`${store}: file=${row?.file}, expected ${expectedFile}`);
148
+ const file = path.join(dir, expectedFile);
149
+ if (!fs.existsSync(file)) failures.push(`${store}: missing ${expectedFile}`);
150
+ else {
151
+ const stat = fs.statSync(file);
152
+ if (row?.bytes !== stat.size) failures.push(`${store}: bytes=${row?.bytes}, actual ${stat.size}`);
153
+ const digest = sha256File(file);
154
+ if (row?.sha256 !== digest) failures.push(`${store}: sha256=${digest}, recorded ${row?.sha256}`);
155
+ }
156
+ if (typeof row?.model !== 'string' || !row.model.trim()) failures.push(`${store}: invalid model`);
157
+ if (!Number.isInteger(row?.dimensions) || row.dimensions <= 0) failures.push(`${store}: invalid dimensions`);
158
+ if (row?.sourceCommit !== null && (typeof row?.sourceCommit !== 'string' || !/^[a-f0-9]{7,64}$/i.test(row.sourceCommit))) failures.push(`${store}: invalid sourceCommit`);
159
+ if (typeof row?.builtUtc !== 'string' || !Number.isFinite(Date.parse(row.builtUtc))) failures.push(`${store}: invalid builtUtc`);
160
+ }
161
+ for (const name of selected) if (!manifest.stores?.[name]) failures.push(`${name}: no exact generation record`);
162
+ const publicRows = Object.keys(manifest.stores || {}).filter((name) => !privateLower.has(name.toLowerCase()));
163
+ if (publicRows.length !== selected.length) failures.push(`store count=${publicRows.length}, selected ${selected.length}`);
164
+ return { manifest, selectedStores: selected, failures };
165
+ }