@aviaratech/ai-delivery 0.3.24 → 0.3.25

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.
Files changed (61) hide show
  1. package/CONTRIBUTING.md +157 -16
  2. package/README.md +20 -0
  3. package/dist/agentReadiness.test.d.ts +1 -0
  4. package/dist/agentReadiness.test.js +139 -0
  5. package/dist/agentReadiness.test.js.map +1 -0
  6. package/dist/cli.js +16 -5
  7. package/dist/cli.js.map +1 -1
  8. package/dist/contributorChecks.test.d.ts +1 -0
  9. package/dist/contributorChecks.test.js +1010 -0
  10. package/dist/contributorChecks.test.js.map +1 -0
  11. package/dist/currentConsumer.test.d.ts +1 -0
  12. package/dist/currentConsumer.test.js +832 -0
  13. package/dist/currentConsumer.test.js.map +1 -0
  14. package/dist/dependencyCompatibility.test.d.ts +1 -0
  15. package/dist/dependencyCompatibility.test.js +175 -0
  16. package/dist/dependencyCompatibility.test.js.map +1 -0
  17. package/dist/directoryIndependent.test.js +91 -1
  18. package/dist/directoryIndependent.test.js.map +1 -1
  19. package/dist/dispatch.js +6 -0
  20. package/dist/dispatch.js.map +1 -1
  21. package/dist/issue.d.ts +7 -0
  22. package/dist/issue.js +1 -1
  23. package/dist/issue.js.map +1 -1
  24. package/dist/issueJournal.test.js +88 -6
  25. package/dist/issueJournal.test.js.map +1 -1
  26. package/dist/mcp/tools.d.ts +7 -1
  27. package/dist/mcp/tools.js +20 -2
  28. package/dist/mcp/tools.js.map +1 -1
  29. package/dist/pluginInstaller.js +8 -2
  30. package/dist/pluginInstaller.js.map +1 -1
  31. package/dist/pluginInstaller.test.js +213 -2
  32. package/dist/pluginInstaller.test.js.map +1 -1
  33. package/dist/pluginPackaging.test.js +100 -6
  34. package/dist/pluginPackaging.test.js.map +1 -1
  35. package/dist/pr.d.ts +20 -13
  36. package/dist/pr.js +638 -66
  37. package/dist/pr.js.map +1 -1
  38. package/dist/pr.test.js +166 -7
  39. package/dist/pr.test.js.map +1 -1
  40. package/dist/prAssociation.test.d.ts +1 -0
  41. package/dist/prAssociation.test.js +1336 -0
  42. package/dist/prAssociation.test.js.map +1 -0
  43. package/dist/prDispatch.test.d.ts +1 -0
  44. package/dist/prDispatch.test.js +96 -0
  45. package/dist/prDispatch.test.js.map +1 -0
  46. package/dist/releaseReconciliation.test.js +6 -2
  47. package/dist/releaseReconciliation.test.js.map +1 -1
  48. package/dist/releaseWorkflow.test.d.ts +1 -0
  49. package/dist/releaseWorkflow.test.js +447 -0
  50. package/dist/releaseWorkflow.test.js.map +1 -0
  51. package/dist/services/agentReadinessService.js +2 -1
  52. package/dist/services/agentReadinessService.js.map +1 -1
  53. package/dist/stagedChecks.test.d.ts +1 -0
  54. package/dist/stagedChecks.test.js +228 -0
  55. package/dist/stagedChecks.test.js.map +1 -0
  56. package/package.json +9 -6
  57. package/plugins/ai-delivery/.claude-plugin/plugin.json +2 -2
  58. package/plugins/ai-delivery/plugin.json +1 -1
  59. package/plugins/ai-delivery/runtime/dist/THIRD-PARTY-NOTICES.md +1 -1
  60. package/plugins/ai-delivery/runtime/dist/cli.js +40 -40
  61. package/plugins/ai-delivery/runtime/package.json +1 -1
@@ -0,0 +1,1010 @@
1
+ import assert from 'node:assert/strict';
2
+ import { execFileSync, spawn, spawnSync } from 'node:child_process';
3
+ import { chmodSync, existsSync, mkdirSync, mkdtempSync, readFileSync, realpathSync, renameSync, rmSync, symlinkSync, writeFileSync, } from 'node:fs';
4
+ import { tmpdir } from 'node:os';
5
+ import { dirname, join } from 'node:path';
6
+ import { fileURLToPath } from 'node:url';
7
+ import { test } from 'vitest';
8
+ const checks = (await import(new URL('../scripts/checks.mjs', import.meta.url).href));
9
+ const repository = fileURLToPath(new URL('../', import.meta.url));
10
+ function fixture() {
11
+ const base = mkdtempSync(join(tmpdir(), 'contributor-check-fixture-'));
12
+ const cwd = join(base, 'repo');
13
+ mkdirSync(join(cwd, 'src'), { recursive: true });
14
+ writeFileSync(join(cwd, '.gitignore'), '/dist/\n/node_modules/\n/plugins/ai-delivery/runtime/dist/\n/plugins/ai-delivery/dist/\n');
15
+ writeFileSync(join(cwd, 'src/original.test.ts'), '// synthetic original test\n');
16
+ writeFileSync(join(cwd, 'package.json'), JSON.stringify({
17
+ name: '@example/fixture',
18
+ version: '1.0.0',
19
+ bin: { fixture: './dist/cli.js' },
20
+ exports: { '.': { default: './dist/index.js' } },
21
+ }));
22
+ execFileSync('git', ['init', '-q', cwd]);
23
+ execFileSync('git', ['add', '.'], { cwd });
24
+ const toolchain = {
25
+ controller: { version: 'v24.21.0', executable: process.execPath },
26
+ npm: { version: '11.19.0', executable: 'synthetic-npm' },
27
+ libraryConsumer: { version: 'v26.2.0', executable: 'synthetic-node26' },
28
+ };
29
+ const cleanup = () => rmSync(base, { recursive: true, force: true });
30
+ return { base, cwd, toolchain, cleanup };
31
+ }
32
+ function passingReport(cwd, names) {
33
+ return {
34
+ success: true,
35
+ numTotalTests: names.length,
36
+ numPassedTests: names.length,
37
+ testResults: names.map((name) => ({
38
+ name: join(cwd, name),
39
+ status: 'passed',
40
+ assertionResults: [{ fullName: 'synthetic assertion', status: 'passed' }],
41
+ })),
42
+ };
43
+ }
44
+ function executor(f, failStage = '') {
45
+ return async (command, options) => {
46
+ mkdirSync(options.directory, { recursive: true });
47
+ const stdoutPath = join(options.directory, 'stdout.txt');
48
+ const stderrPath = join(options.directory, 'stderr.txt');
49
+ writeFileSync(stdoutPath, '');
50
+ writeFileSync(stderrPath, '');
51
+ const stage = options.directory.split('/').at(-1);
52
+ if (stage === 'build') {
53
+ assert.equal(existsSync(join(f.cwd, 'dist/stale.test.js')), false, 'clean before build, rather than after selection');
54
+ mkdirSync(join(f.cwd, 'dist'), { recursive: true });
55
+ const source = existsSync(join(f.cwd, 'src/renamed.test.ts')) ? 'renamed' : 'original';
56
+ writeFileSync(join(f.cwd, `dist/${source}.test.js`), '// compiled synthetic test\n');
57
+ for (const path of [
58
+ 'dist/cli.js',
59
+ 'dist/index.js',
60
+ 'plugins/ai-delivery/runtime/dist/cli.js',
61
+ 'plugins/ai-delivery/dist/mcp-launcher.js',
62
+ ]) {
63
+ mkdirSync(dirname(join(f.cwd, path)), { recursive: true });
64
+ writeFileSync(join(f.cwd, path), '// fictional packaged output\n');
65
+ chmodSync(join(f.cwd, path), 0o755);
66
+ }
67
+ }
68
+ if (stage === 'tests') {
69
+ const names = command.filter((arg) => arg.startsWith('dist/') && arg.endsWith('.test.js'));
70
+ assert.equal(names.length, 1);
71
+ const path = command
72
+ .find((arg) => arg.startsWith('--outputFile.json='))
73
+ .split('=')
74
+ .slice(1)
75
+ .join('=');
76
+ writeFileSync(path, JSON.stringify(passingReport(f.cwd, names)));
77
+ }
78
+ if (stage === 'inventory') {
79
+ writeFileSync(stdoutPath, JSON.stringify([
80
+ {
81
+ name: '@example/fixture',
82
+ version: '1.0.0',
83
+ files: [
84
+ 'dist/cli.js',
85
+ 'dist/index.js',
86
+ 'plugins/ai-delivery/runtime/dist/cli.js',
87
+ 'plugins/ai-delivery/dist/mcp-launcher.js',
88
+ ].map((path) => ({ path, mode: 0o755, size: readFileSync(join(f.cwd, path)).length })),
89
+ },
90
+ ]));
91
+ const coverage = options.env.NODE_V8_COVERAGE;
92
+ mkdirSync(coverage, { recursive: true });
93
+ writeFileSync(join(coverage, 'synthetic.json'), JSON.stringify({
94
+ result: [
95
+ {
96
+ url: new URL(`file://${join(f.cwd, 'dist/index.js')}`).href,
97
+ functions: [{ ranges: [{ startOffset: 0, endOffset: 1, count: 1 }] }],
98
+ },
99
+ ],
100
+ }));
101
+ }
102
+ const result = {
103
+ status: stage === failStage ? 'failed' : 'passed',
104
+ exitCode: stage === failStage ? 7 : 0,
105
+ stdoutPath,
106
+ stderrPath,
107
+ };
108
+ options.progress?.(result);
109
+ return result;
110
+ };
111
+ }
112
+ test('local and CI share full entry; fast explicitly omits gates and no CI duplicate build', () => {
113
+ const manifest = JSON.parse(readFileSync(join(repository, 'package.json'), 'utf8'));
114
+ assert.equal(manifest.scripts.checks, 'node scripts/current-qualification.mjs');
115
+ assert.equal(manifest.scripts['checks:producer'], 'node scripts/current-qualification.mjs --producer-only');
116
+ assert.equal(manifest.scripts['checks:fast'], 'node scripts/checks.mjs --fast');
117
+ const ci = readFileSync(join(repository, '.github/workflows/ci.yml'), 'utf8');
118
+ assert.match(ci, /npm run checks -- --results-dir/u);
119
+ assert.doesNotMatch(ci, /npm run build|npm pack/u);
120
+ assert.match(ci, /if: always\(\)/u);
121
+ assert.deepEqual(checks.FULL_GATES, ['format', 'lint', 'types', 'build', 'tests', 'inventory']);
122
+ });
123
+ test('clean full graph removes deleted/renamed compiled tests and retains exact command evidence', async () => {
124
+ const f = fixture();
125
+ try {
126
+ mkdirSync(join(f.cwd, 'dist'));
127
+ writeFileSync(join(f.cwd, 'dist/stale.test.js'), '// deleted source output\n');
128
+ renameSync(join(f.cwd, 'src/original.test.ts'), join(f.cwd, 'src/renamed.test.ts'));
129
+ const resultsDir = join(f.base, 'results');
130
+ const report = await checks.runChecks({
131
+ cwd: f.cwd,
132
+ resultsDir,
133
+ toolchain: () => f.toolchain,
134
+ execute: executor(f),
135
+ });
136
+ assert.equal(report.fullSuccess, true, report.error);
137
+ assert.deepEqual(report.commands.map((entry) => entry.stage), checks.FULL_GATES);
138
+ assert.deepEqual(report.selectedTestFiles, ['dist/renamed.test.js']);
139
+ assert.match(readFileSync(join(resultsDir, 'result.txt'), 'utf8'), /FULL contributor checks: passed/u);
140
+ assert.equal(existsSync(join(f.cwd, 'dist/stale.test.js')), false);
141
+ await assert.rejects(checks.runChecks({ cwd: f.cwd, resultsDir }), /Existing result/u);
142
+ writeFileSync(join(f.cwd, 'dist/stale.test.js'), '// unexpected survivor\n');
143
+ assert.throws(() => checks.assertCleanSelection(f.cwd), /stale, deleted, renamed/u);
144
+ }
145
+ finally {
146
+ f.cleanup();
147
+ }
148
+ });
149
+ test('fast success and command failure remain partial and preserve omitted/remaining proof', async () => {
150
+ const f = fixture();
151
+ try {
152
+ const fast = await checks.runChecks({
153
+ cwd: f.cwd,
154
+ resultsDir: join(f.base, 'fast'),
155
+ fast: true,
156
+ toolchain: () => f.toolchain,
157
+ execute: executor(f),
158
+ });
159
+ assert.equal(fast.status, 'partial-passed');
160
+ assert.equal(fast.fullSuccess, false);
161
+ assert.deepEqual(fast.omitted, ['build', 'tests', 'inventory']);
162
+ const failed = await checks.runChecks({
163
+ cwd: f.cwd,
164
+ resultsDir: join(f.base, 'failed'),
165
+ toolchain: () => f.toolchain,
166
+ execute: executor(f, 'lint'),
167
+ });
168
+ assert.equal(failed.exitCode, 1);
169
+ assert.equal(failed.fullSuccess, false);
170
+ assert.deepEqual(failed.commands.map((entry) => entry.stage), ['format', 'lint']);
171
+ assert.match(failed.error, /lint: failed/u);
172
+ const testFailure = await checks.runChecks({
173
+ cwd: f.cwd,
174
+ resultsDir: join(f.base, 'failed-tests'),
175
+ toolchain: () => f.toolchain,
176
+ execute: executor(f, 'tests'),
177
+ });
178
+ assert.equal(testFailure.fullSuccess, false);
179
+ assert.equal(testFailure.observedTests?.total, 1);
180
+ assert.match(readFileSync(join(f.base, 'failed-tests/result.txt'), 'utf8'), /Observed test results/u);
181
+ assert.equal(testFailure.commands.at(-1).status, 'failed');
182
+ }
183
+ finally {
184
+ f.cleanup();
185
+ }
186
+ });
187
+ test('toolchain preflight rejects absent/inaccessible/wrong consumer before gates; environment excludes credentials and ambient preloads', async () => {
188
+ const env = checks.safeEnvironment({
189
+ PATH: process.env.PATH,
190
+ HOME: process.env.HOME,
191
+ GH_TOKEN: 'fictional-do-not-forward',
192
+ GH_PRIVATE_KEY_GPT_REVIEWER: 'fictional-ref',
193
+ NODE_OPTIONS: '--require fictional',
194
+ NODE_PATH: 'checkout-only',
195
+ NPM_TOKEN: 'fictional-token',
196
+ AI_DELIVERY_REAL_PACKAGE_ARCHIVE: '/synthetic/explicit-historical.tgz',
197
+ });
198
+ assert.equal(env.GH_TOKEN, undefined);
199
+ assert.equal(env.NODE_OPTIONS, undefined);
200
+ assert.equal(env.NODE_PATH, undefined);
201
+ assert.equal(env.NPM_TOKEN, undefined);
202
+ assert.equal(env.AI_DELIVERY_REAL_PACKAGE_ARCHIVE, '/synthetic/explicit-historical.tgz');
203
+ assert.throws(() => checks.validateToolchain(repository, env), /AI_DELIVERY_NODE26_EXECUTABLE/u);
204
+ assert.throws(() => checks.validateToolchain(repository, { ...env, AI_DELIVERY_NODE26_EXECUTABLE: '/nonexistent/synthetic-node' }), /ENOENT/u);
205
+ assert.throws(() => checks.validateToolchain(repository, { ...env, AI_DELIVERY_NODE26_EXECUTABLE: process.execPath }), /Node 26\.2\.0/u);
206
+ const f = fixture();
207
+ try {
208
+ const report = await checks.runChecks({
209
+ cwd: f.cwd,
210
+ resultsDir: join(f.base, 'missing'),
211
+ toolchain: () => {
212
+ throw new Error('missing runtime');
213
+ },
214
+ });
215
+ assert.equal(report.fullSuccess, false);
216
+ assert.deepEqual(report.commands, []);
217
+ }
218
+ finally {
219
+ f.cleanup();
220
+ }
221
+ });
222
+ test('selection, counts and explicit skip reasons reject unexpected/zero/excluded or unproved results', () => {
223
+ const cwd = '/synthetic/repo';
224
+ const report = passingReport(cwd, ['dist/setup.test.js']);
225
+ const file = report.testResults[0];
226
+ file.assertionResults = [
227
+ {
228
+ fullName: 'stopped setup owners stay busy and orphan recovery confirms cleanup before retrying the incomplete install',
229
+ status: 'passed',
230
+ },
231
+ {
232
+ fullName: 'native stopped setup owners stay busy and orphan recovery confirms cleanup before retrying the incomplete install',
233
+ status: 'passed',
234
+ },
235
+ { fullName: 'setup interruption child', status: 'pending' },
236
+ {
237
+ fullName: 'actual reviewed 0.3.4 archive qualifies with real npm production installation in a temporary synthetic consumer',
238
+ status: 'pending',
239
+ },
240
+ ];
241
+ report.numTotalTests = 4;
242
+ report.numPassedTests = 2;
243
+ const result = checks.analyzeTests(report, ['dist/setup.test.js'], cwd, 'SETUP_INTERRUPTION_RECEIPT');
244
+ assert.equal(result.skips.length, 2);
245
+ assert.throws(() => checks.analyzeTests(report, ['dist/setup.test.js'], cwd, 'SETUP_INTERRUPTION_RECEIPT', {
246
+ AI_DELIVERY_REAL_PACKAGE_ARCHIVE: '/synthetic/explicit.tgz',
247
+ }), /skipped despite explicit/u);
248
+ assert.match(JSON.stringify(result.skips), /qualification is unexecuted/u);
249
+ assert.throws(() => checks.analyzeTests(report, ['dist/setup.test.js'], cwd, ''), /proof is missing/u);
250
+ assert.throws(() => checks.analyzeTests(report, ['dist/other.test.js'], cwd, ''), /unexpected file/u);
251
+ file.assertionResults[2].fullName = 'unexpected conditional skip';
252
+ assert.throws(() => checks.analyzeTests(report, ['dist/setup.test.js'], cwd, ''), /Unexpected skip/u);
253
+ assert.throws(() => checks.analyzeTests({ success: true, numTotalTests: 0, numPassedTests: 0, testResults: [] }, [], cwd, ''), /Zero tests/u);
254
+ });
255
+ test('real failed and explicitly timed-out commands preserve logs and prove owned cleanup', async () => {
256
+ const f = fixture();
257
+ try {
258
+ const env = checks.safeEnvironment(process.env);
259
+ const failed = await checks.executeCommand([process.execPath, '-e', "console.log('partial failure evidence');process.exit(7)"], { cwd: f.cwd, env, directory: join(f.base, 'failure') });
260
+ assert.equal(failed.status, 'failed');
261
+ assert.equal(failed.exitCode, 7);
262
+ assert.match(readFileSync(failed.stdoutPath, 'utf8'), /partial failure evidence/u);
263
+ const timed = await checks.executeCommand([process.execPath, '-e', "console.log('started');setInterval(()=>{},1000)"], { cwd: f.cwd, env, directory: join(f.base, 'timeout'), timeoutMs: 200 });
264
+ assert.equal(timed.status, 'command-timeout');
265
+ assert.equal(timed.cleanupConfirmed, true);
266
+ assert.ok(timed.observedProcesses.length > 0);
267
+ assert.ok(timed.observedProcesses.every((row) => row.birth.length > 0));
268
+ }
269
+ finally {
270
+ f.cleanup();
271
+ }
272
+ });
273
+ test('cancellation reaps observed detached descendants and preserves an unrelated peer', async () => {
274
+ const f = fixture();
275
+ const peer = spawn(process.execPath, ['-e', 'setInterval(()=>{},1000)'], { stdio: 'ignore' });
276
+ try {
277
+ const controller = new AbortController();
278
+ const marker = join(f.base, 'owned-child');
279
+ const script = `const cp=require('node:child_process'),fs=require('node:fs');const c=cp.spawn(process.execPath,['-e','setInterval(()=>{},1000)'],{detached:true,stdio:'ignore'});fs.writeFileSync(${JSON.stringify(marker)},String(c.pid));setInterval(()=>{},1000);`;
280
+ const timer = setInterval(() => {
281
+ if (existsSync(marker)) {
282
+ clearInterval(timer);
283
+ setTimeout(() => controller.abort(), 250);
284
+ }
285
+ }, 20);
286
+ const result = await checks.executeCommand([process.execPath, '-e', script], {
287
+ cwd: f.cwd,
288
+ env: checks.safeEnvironment(process.env),
289
+ directory: join(f.base, 'cancelled'),
290
+ signal: controller.signal,
291
+ });
292
+ clearInterval(timer);
293
+ assert.equal(result.status, 'cancelled');
294
+ assert.equal(result.cleanupConfirmed, true);
295
+ const ownedPid = readFileSync(marker, 'utf8');
296
+ const state = execFileSync('/bin/ps', ['-p', ownedPid, '-o', 'stat='], { encoding: 'utf8' }).trim();
297
+ assert.ok(state.startsWith('Z'));
298
+ process.kill(peer.pid, 0);
299
+ }
300
+ catch (error) {
301
+ // ps exits1 for an absent child, which is also confirmed cleanup.
302
+ if (!(error instanceof Error && 'status' in error && error.status === 1))
303
+ throw error;
304
+ process.kill(peer.pid, 0);
305
+ }
306
+ finally {
307
+ peer.kill('SIGKILL');
308
+ await new Promise((done) => {
309
+ if (peer.exitCode !== null || peer.signalCode !== null)
310
+ done();
311
+ else
312
+ peer.once('close', () => done());
313
+ });
314
+ f.cleanup();
315
+ }
316
+ });
317
+ test('existing temporary aliases resolve to the same physical directory without creating a new destination', () => {
318
+ const f = fixture();
319
+ try {
320
+ const target = join(f.base, 'existing-temp');
321
+ const alias = join(f.base, 'temp-alias');
322
+ mkdirSync(target);
323
+ symlinkSync(target, alias);
324
+ const env = checks.safeEnvironment({ TMPDIR: alias, TEMP: alias, TMP: alias });
325
+ assert.equal(env.TMPDIR, realpathSync(target));
326
+ assert.equal(env.TEMP, realpathSync(target));
327
+ assert.equal(env.TMP, realpathSync(target));
328
+ assert.equal(readFileSync(join(f.cwd, 'src/original.test.ts'), 'utf8'), '// synthetic original test\n');
329
+ }
330
+ finally {
331
+ f.cleanup();
332
+ }
333
+ });
334
+ test('source identity preserves leading filename whitespace and refuses dangling tracked symlinks', () => {
335
+ const f = fixture();
336
+ try {
337
+ const path = join(f.cwd, ' leading.txt');
338
+ writeFileSync(path, 'first source bytes');
339
+ execFileSync('git', ['add', '--', ' leading.txt'], { cwd: f.cwd });
340
+ const before = checks.treeIdentity(f.cwd).sha256;
341
+ writeFileSync(path, 'changed source bytes');
342
+ assert.notEqual(checks.treeIdentity(f.cwd).sha256, before);
343
+ symlinkSync('nonexistent-target', join(f.cwd, 'dangling-link'));
344
+ execFileSync('git', ['add', '--', 'dangling-link'], { cwd: f.cwd });
345
+ assert.throws(() => checks.treeIdentity(f.cwd), /regular tracked\/source files/u);
346
+ }
347
+ finally {
348
+ f.cleanup();
349
+ }
350
+ });
351
+ test('cancellation discovers children born from a detached owner after the root exits and preserves a peer', async () => {
352
+ const f = fixture();
353
+ const peer = spawn(process.execPath, ['-e', 'setInterval(()=>{},1000)'], { stdio: 'ignore' });
354
+ const marker = join(f.base, 'late-children.json');
355
+ const controller = new AbortController();
356
+ const identity = (pid) => {
357
+ const result = spawnSync('/bin/ps', ['-p', String(pid), '-o', 'stat=,lstart='], { encoding: 'utf8' });
358
+ assert.ok(!result.error, result.error?.message);
359
+ assert.ok(result.status === 0 || result.status === 1, result.stderr);
360
+ return result.status === 1 ? undefined : result.stdout.trim();
361
+ };
362
+ let timer;
363
+ try {
364
+ const descendant = `const cp=require('node:child_process'),fs=require('node:fs');
365
+ const id=(pid)=>cp.execFileSync('/bin/ps',['-p',String(pid),'-o','stat=,lstart='],{encoding:'utf8'}).trim().split(/\\s+/).slice(1).join(' ');
366
+ const record={a:process.pid,aBirth:id(process.pid)};fs.writeFileSync(${JSON.stringify(marker)},JSON.stringify(record));
367
+ process.once('SIGTERM',()=>setTimeout(()=>{
368
+ const root=cp.spawnSync('/bin/ps',['-p',process.argv[1],'-o','stat='],{encoding:'utf8'});
369
+ record.rootExited=root.status===1||root.stdout.trim().startsWith('Z');
370
+ const b=cp.spawn(process.execPath,['-e','setInterval(()=>{},1000)'],{detached:true,stdio:'ignore'});
371
+ record.b=b.pid;record.bBirth=id(b.pid);fs.writeFileSync(${JSON.stringify(marker)},JSON.stringify(record));
372
+ },200));setInterval(()=>{},1000);`;
373
+ // The root exits on TERM. Its detached child ignores TERM and births B later.
374
+ const script = `const cp=require('node:child_process');cp.spawn(process.execPath,['-e',${JSON.stringify(descendant)},String(process.pid)],{detached:true,stdio:'ignore'});setInterval(()=>{},1000);`;
375
+ timer = setInterval(() => {
376
+ if (existsSync(marker)) {
377
+ clearInterval(timer);
378
+ setTimeout(() => controller.abort(), 250);
379
+ }
380
+ }, 20);
381
+ const result = await checks.executeCommand([process.execPath, '-e', script], {
382
+ cwd: f.cwd,
383
+ env: checks.safeEnvironment(process.env),
384
+ directory: join(f.base, 'late-cancellation'),
385
+ signal: controller.signal,
386
+ });
387
+ const children = JSON.parse(readFileSync(marker, 'utf8'));
388
+ assert.ok(children.b, 'The TERM-resistant owner must create a late descendant.');
389
+ assert.equal(children.rootExited, true, 'The late descendant must be born after the root exits.');
390
+ assert.equal(result.status, 'cancelled');
391
+ assert.equal(result.cleanupConfirmed, true);
392
+ assert.ok(result.observedProcesses?.some((row) => row.pid === children.b && row.birth === children.bBirth));
393
+ for (const pid of [children.a, children.b])
394
+ assert.ok(identity(pid)?.startsWith('Z') ?? true);
395
+ process.kill(peer.pid, 0);
396
+ }
397
+ finally {
398
+ clearInterval(timer);
399
+ // On a failing assertion, signal only the synthetic identities this fixture recorded.
400
+ if (existsSync(marker)) {
401
+ const children = JSON.parse(readFileSync(marker, 'utf8'));
402
+ for (const [pid, birth] of [
403
+ [children.a, children.aBirth],
404
+ [children.b, children.bBirth],
405
+ ]) {
406
+ if (pid && birth) {
407
+ const state = identity(pid);
408
+ if (state && !state.startsWith('Z') && state.split(/\s+/u).slice(1).join(' ') === birth)
409
+ process.kill(pid, 'SIGKILL');
410
+ }
411
+ }
412
+ }
413
+ peer.kill('SIGKILL');
414
+ await new Promise((done) => {
415
+ if (peer.exitCode !== null || peer.signalCode !== null)
416
+ done();
417
+ else
418
+ peer.once('close', () => done());
419
+ });
420
+ f.cleanup();
421
+ }
422
+ });
423
+ test('coverage labels unobserved contributor scripts without synthesizing measured ranges or floors', () => {
424
+ const f = fixture();
425
+ try {
426
+ const directory = join(f.base, 'unit-coverage');
427
+ mkdirSync(directory);
428
+ writeFileSync(join(directory, 'fixture.json'), JSON.stringify({
429
+ result: [
430
+ {
431
+ url: new URL('scripts/build-plugin.mjs', `file://${f.cwd}/`).href,
432
+ functions: [{ ranges: [{ startOffset: 0, endOffset: 1, count: 1 }] }],
433
+ },
434
+ ],
435
+ }));
436
+ const baseline = checks.coverageBaseline(directory, f.cwd);
437
+ assert.deepEqual(baseline.files.map((file) => file.path), ['scripts/build-plugin.mjs']);
438
+ assert.deepEqual(baseline.unmeasuredContributorScripts.map((file) => file.path), [
439
+ 'scripts/checks.mjs',
440
+ 'scripts/pre-commit.mjs',
441
+ 'scripts/current-qualification.mjs',
442
+ 'scripts/current-consumer.mjs',
443
+ ]);
444
+ assert.ok(baseline.unmeasuredContributorScripts.every((file) => file.threshold === null && file.reason.length > 0));
445
+ assert.match(baseline.thresholdProposal, /no derived floor until actual instrumentation/u);
446
+ // This controlled parser fixture is not the measured canonical graph baseline.
447
+ }
448
+ finally {
449
+ f.cleanup();
450
+ }
451
+ });
452
+ const qualification = (await import(new URL('../scripts/current-qualification.mjs', import.meta.url).href));
453
+ const consumerProof = (await import(new URL('../scripts/current-consumer.mjs', import.meta.url).href));
454
+ function qualificationFixture() {
455
+ const f = fixture();
456
+ mkdirSync(join(f.cwd, 'dist'));
457
+ writeFileSync(join(f.cwd, 'dist/generated.js'), 'original');
458
+ writeFileSync(join(f.cwd, 'package-lock.json'), '{}\n');
459
+ execFileSync('git', ['add', '.'], { cwd: f.cwd });
460
+ execFileSync('git', [
461
+ '-c',
462
+ 'user.name=Fictional fixture',
463
+ '-c',
464
+ 'user.email=fixture@example.invalid',
465
+ '-c',
466
+ 'core.hooksPath=/dev/null',
467
+ 'commit',
468
+ '-qm',
469
+ 'fictional clean source',
470
+ ], { cwd: f.cwd });
471
+ let producers = 0;
472
+ let packs = 0;
473
+ let consumers = 0;
474
+ let packStatus = 'passed';
475
+ let cleanup = true;
476
+ let mutateProducer = () => { };
477
+ const members = [
478
+ { path: 'dist/generated.js', size: 8, mode: 0o644 },
479
+ { path: 'package.json', size: readFileSync(join(f.cwd, 'package.json')).length, mode: 0o644 },
480
+ ];
481
+ const inspect = (contract) => {
482
+ assert.equal(consumerProof.sha256(readFileSync(contract.archivePath)), contract.archiveSha256);
483
+ assert.deepEqual(contract.dryInventory, members);
484
+ const inventory = members.map((item) => ({
485
+ ...item,
486
+ sha256: consumerProof.sha256(readFileSync(join(f.cwd, item.path))),
487
+ }));
488
+ return {
489
+ archiveSha256: contract.archiveSha256,
490
+ sourceManifestSha256: contract.sourceManifestSha256,
491
+ sourceLockSha256: contract.sourceLockSha256,
492
+ archiveManifestSha256: contract.sourceManifestSha256,
493
+ packageVersion: contract.packageVersion,
494
+ inventorySha256: consumerProof.sha256(JSON.stringify(inventory)),
495
+ inventory,
496
+ skills: ['intake-create', 'worktree-lifecycle', 'pr-handoff'].map((path) => ({ path, sha256: 'a'.repeat(64) })),
497
+ };
498
+ };
499
+ const produce = async ({ resultsDir }) => {
500
+ producers++;
501
+ mkdirSync(resultsDir);
502
+ const report = {
503
+ schemaVersion: 'contributor-checks@1',
504
+ runId: 'fictional-one-producer',
505
+ scope: 'full',
506
+ status: 'passed',
507
+ fullSuccess: true,
508
+ exitCode: 0,
509
+ gates: checks.FULL_GATES,
510
+ omitted: [],
511
+ tree: qualification.sourceIdentity(f.cwd).fingerprint,
512
+ commands: checks.FULL_GATES.map((stage) => ({
513
+ stage,
514
+ status: 'passed',
515
+ exitCode: 0,
516
+ signal: null,
517
+ cleanupConfirmed: true,
518
+ })),
519
+ tests: { files: 1, total: 1, passed: 1, skips: [] },
520
+ selectedTestFiles: ['dist/original.test.js'],
521
+ toolchain: f.toolchain,
522
+ inventory: {
523
+ kind: 'dry-inventory-only',
524
+ name: '@aviaratech/ai-delivery',
525
+ version: '1.0.0',
526
+ fileCount: members.length,
527
+ files: members.map((item) => ({ ...item, sha256: consumerProof.sha256(readFileSync(join(f.cwd, item.path))) })),
528
+ },
529
+ };
530
+ mutateProducer(report);
531
+ writeFileSync(join(resultsDir, 'result.json'), JSON.stringify(report));
532
+ return report;
533
+ };
534
+ const execute = async (command, options) => {
535
+ if (command.at(-1) === '--authorize-install') {
536
+ const contractPath = command[2];
537
+ const resultPath = command[3];
538
+ assert.ok(contractPath && resultPath, 'Synthetic consumer requires contract and result paths.');
539
+ const contract = JSON.parse(readFileSync(contractPath, 'utf8'));
540
+ const receipt = await consume(contract, { authorizeInstall: true });
541
+ mkdirSync(options.directory);
542
+ const stdoutPath = join(options.directory, 'stdout.txt');
543
+ const stderrPath = join(options.directory, 'stderr.txt');
544
+ writeFileSync(stdoutPath, 'fictional supervised consumer');
545
+ writeFileSync(stderrPath, '');
546
+ writeFileSync(resultPath, JSON.stringify(receipt));
547
+ const result = {
548
+ command,
549
+ status: 'passed',
550
+ exitCode: 0,
551
+ signal: null,
552
+ stdoutPath,
553
+ stderrPath,
554
+ cleanupConfirmed: true,
555
+ };
556
+ options.progress?.(result);
557
+ return result;
558
+ }
559
+ packs++;
560
+ assert.deepEqual(command.slice(2, 5), ['pack', '--ignore-scripts', '--json']);
561
+ mkdirSync(options.directory);
562
+ const destination = command.at(-1);
563
+ writeFileSync(join(destination, 'fictional.tgz'), 'fictional archive boundary');
564
+ const stdoutPath = join(options.directory, 'stdout.txt');
565
+ const stderrPath = join(options.directory, 'stderr.txt');
566
+ writeFileSync(stdoutPath, JSON.stringify([{ filename: 'fictional.tgz', files: members }]));
567
+ writeFileSync(stderrPath, '');
568
+ return {
569
+ command,
570
+ startedAt: 'fictional',
571
+ status: packStatus,
572
+ exitCode: packStatus === 'passed' ? 0 : 9,
573
+ signal: null,
574
+ stdoutPath,
575
+ stderrPath,
576
+ cleanupConfirmed: cleanup,
577
+ };
578
+ };
579
+ const consume = async (contract, options) => {
580
+ consumers++;
581
+ assert.equal(options.authorizeInstall, true);
582
+ const candidate = inspect(contract);
583
+ return {
584
+ schemaVersion: 'ai-delivery.current-consumer@1',
585
+ boundary: 'current-artifact',
586
+ status: 'passed',
587
+ qualified: true,
588
+ sourceIdentityVerified: true,
589
+ scriptsDisabled: true,
590
+ sourceCommit: contract.sourceCommit,
591
+ sourceTree: contract.sourceTree,
592
+ sourceManifestSha256: contract.sourceManifestSha256,
593
+ sourceLockSha256: contract.sourceLockSha256,
594
+ archiveManifestSha256: contract.sourceManifestSha256,
595
+ archiveSha256: contract.archiveSha256,
596
+ packageVersion: contract.packageVersion,
597
+ inventorySha256: candidate.inventorySha256,
598
+ inventory: candidate.inventory,
599
+ producerJoin: consumerProof.verifyProducerJoin(contract, candidate),
600
+ cleanup: { quiescent: true, removed: true },
601
+ productionClosure: {},
602
+ mcp: {},
603
+ skills: candidate.skills,
604
+ resolutions: ['fictional owned resolution'],
605
+ phases: [
606
+ 'node24',
607
+ 'node26',
608
+ 'npm',
609
+ 'production-install',
610
+ 'production-closure',
611
+ 'cli-version',
612
+ 'cli-json',
613
+ 'exports-node24',
614
+ 'library-node26',
615
+ 'packaged-mcp',
616
+ ].map((phase) => ({ phase, code: 0, signal: null, quiescent: true })),
617
+ };
618
+ };
619
+ const options = {
620
+ cwd: f.cwd,
621
+ resultsDir: join(f.base, 'qualification'),
622
+ checks: produce,
623
+ execute,
624
+ inspect,
625
+ };
626
+ return {
627
+ ...f,
628
+ options,
629
+ inspect,
630
+ consume,
631
+ counts: () => ({ producers, packs, consumers }),
632
+ mutate: (fn) => {
633
+ mutateProducer = fn;
634
+ },
635
+ packFailure: (status, quiescent = true) => {
636
+ packStatus = status;
637
+ cleanup = quiescent;
638
+ },
639
+ };
640
+ }
641
+ test('qualification checkpoints one producer and pack, resumes without replay, and retains immutable digests', async () => {
642
+ const f = qualificationFixture();
643
+ try {
644
+ const report = await qualification.runQualification({ ...f.options, producerOnly: true });
645
+ assert.equal(report.status, 'incomplete');
646
+ assert.equal(report.qualified, false);
647
+ assert.equal(report.exitCode, 2);
648
+ assert.deepEqual(f.counts(), { producers: 1, packs: 1, consumers: 0 });
649
+ const checkpoint = join(f.options.resultsDir, 'checkpoint.json');
650
+ const producer = readFileSync(join(f.options.resultsDir, 'producer/result.json'));
651
+ const resumed = await qualification.runQualification({
652
+ ...f.options,
653
+ resume: checkpoint,
654
+ resultsDir: join(f.base, 'resumed'),
655
+ });
656
+ assert.equal(resumed.qualified, true);
657
+ assert.equal(resumed.exitCode, 0);
658
+ assert.deepEqual(f.counts(), { producers: 1, packs: 1, consumers: 1 });
659
+ assert.deepEqual(readFileSync(join(f.options.resultsDir, 'producer/result.json')), producer);
660
+ await assert.rejects(qualification.runQualification({ ...f.options, resume: checkpoint, resultsDir: join(f.base, 'resumed') }), /Existing overall result/u);
661
+ }
662
+ finally {
663
+ f.cleanup();
664
+ }
665
+ });
666
+ test('full qualification executes one producer, actual pack and consumer in order', async () => {
667
+ const f = qualificationFixture();
668
+ try {
669
+ const report = await qualification.runQualification(f.options);
670
+ assert.equal(report.qualified, true);
671
+ assert.deepEqual(f.counts(), { producers: 1, packs: 1, consumers: 1 });
672
+ }
673
+ finally {
674
+ f.cleanup();
675
+ }
676
+ });
677
+ test('producer byte inventory rejects a same-length ignored build change before consumer launch', async () => {
678
+ const f = qualificationFixture();
679
+ try {
680
+ const before = qualification.sourceIdentity(f.cwd).fingerprint;
681
+ f.mutate(() => writeFileSync(join(f.cwd, 'dist/generated.js'), 'replaced'));
682
+ const report = await qualification.runQualification(f.options);
683
+ assert.deepEqual(qualification.sourceIdentity(f.cwd).fingerprint, before);
684
+ assert.equal(report.qualified, false);
685
+ assert.match(report.error, /Archive bytes differ from the successful producer/u);
686
+ assert.deepEqual(f.counts(), { producers: 1, packs: 1, consumers: 0 });
687
+ assert.equal(existsSync(join(f.options.resultsDir, 'checkpoint.json')), false);
688
+ }
689
+ finally {
690
+ f.cleanup();
691
+ }
692
+ });
693
+ test('resume rejects changed generated bytes and missing retained producer member hashes', async () => {
694
+ for (const change of ['bytes', 'missing-digest']) {
695
+ const f = qualificationFixture();
696
+ try {
697
+ if (change === 'missing-digest')
698
+ f.mutate((report) => {
699
+ const inventory = report.inventory;
700
+ const first = inventory.files[0];
701
+ assert.ok(first, 'Synthetic producer inventory must contain a member.');
702
+ delete first.sha256;
703
+ });
704
+ const produced = await qualification.runQualification({ ...f.options, producerOnly: true });
705
+ if (change === 'bytes') {
706
+ assert.equal(produced.status, 'incomplete');
707
+ writeFileSync(join(f.cwd, 'dist/generated.js'), 'replaced');
708
+ const resumed = await qualification.runQualification({
709
+ ...f.options,
710
+ resume: join(f.options.resultsDir, 'checkpoint.json'),
711
+ resultsDir: join(f.base, 'changed-bytes'),
712
+ });
713
+ assert.match(resumed.error, /Archive bytes differ|freshness join is incomplete/u);
714
+ }
715
+ else
716
+ assert.equal(produced.status, 'failed');
717
+ assert.deepEqual(f.counts(), { producers: 1, packs: 1, consumers: 0 });
718
+ }
719
+ finally {
720
+ f.cleanup();
721
+ }
722
+ }
723
+ });
724
+ test('consumer cancellation retains actual PID/birth and logs, and resume cannot duplicate it', async () => {
725
+ const f = qualificationFixture();
726
+ try {
727
+ await qualification.runQualification({ ...f.options, producerOnly: true });
728
+ const controller = new AbortController();
729
+ let launches = 0;
730
+ const execute = async (_command, options) => {
731
+ launches++;
732
+ return checks.executeCommand([process.execPath, '-e', "console.log('fictional consumer started');setInterval(()=>{},1000)"], {
733
+ ...options,
734
+ progress: (partial) => {
735
+ options.progress?.(partial);
736
+ if (partial.observedProcesses?.length)
737
+ controller.abort();
738
+ },
739
+ });
740
+ };
741
+ const resume = join(f.options.resultsDir, 'checkpoint.json');
742
+ const report = await qualification.runQualification({
743
+ ...f.options,
744
+ execute,
745
+ resume,
746
+ signal: controller.signal,
747
+ resultsDir: join(f.base, 'cancelled-consumer'),
748
+ });
749
+ assert.equal(report.status, 'cancelled');
750
+ const attempt = JSON.parse(readFileSync(join(f.options.resultsDir, 'consumer-attempt.json'), 'utf8'));
751
+ assert.equal(attempt.status, 'completed');
752
+ assert.equal(attempt.command.status, 'cancelled');
753
+ assert.equal(attempt.command.cleanupConfirmed, true);
754
+ assert.ok(attempt.command.observedProcesses.every((row) => row.birth.length > 0));
755
+ assert.ok(existsSync(attempt.tempRoot));
756
+ const retried = await qualification.runQualification({
757
+ ...f.options,
758
+ execute,
759
+ resume,
760
+ resultsDir: join(f.base, 'blocked-retry'),
761
+ });
762
+ assert.equal(retried.qualified, false);
763
+ assert.equal(launches, 1);
764
+ assert.deepEqual(f.counts(), { producers: 1, packs: 1, consumers: 0 });
765
+ }
766
+ finally {
767
+ f.cleanup();
768
+ }
769
+ });
770
+ test('lost consumer completion retains a reservation, blocks duplicate launch and reconciles without producer or pack replay', async () => {
771
+ const f = qualificationFixture();
772
+ try {
773
+ await qualification.runQualification({ ...f.options, producerOnly: true });
774
+ const resume = join(f.options.resultsDir, 'checkpoint.json');
775
+ const contract = JSON.parse(readFileSync(join(f.options.resultsDir, 'contract.json'), 'utf8'));
776
+ const fictionalReceipt = await f.consume(contract, { authorizeInstall: true });
777
+ let launches = 0;
778
+ const execute = async (command, options) => {
779
+ launches++;
780
+ const resultPath = command[3];
781
+ assert.ok(resultPath, 'Synthetic consumer requires a result path.');
782
+ // A real credential-free child writes fictional application evidence.
783
+ // Withhold terminal supervisor transport after its actual quiescent exit.
784
+ const code = "const fs=require('node:fs');setTimeout(()=>fs.writeFileSync(process.argv[1],process.argv[2]),200)";
785
+ const completed = await checks.executeCommand([process.execPath, '-e', code, resultPath, JSON.stringify(fictionalReceipt)], {
786
+ ...options,
787
+ progress: (partial) => {
788
+ if (!partial.completedAt)
789
+ options.progress?.(partial);
790
+ },
791
+ });
792
+ assert.equal(completed.cleanupConfirmed, true);
793
+ throw new Error('fictional controller lost terminal consumer response');
794
+ };
795
+ const lost = await qualification.runQualification({
796
+ ...f.options,
797
+ execute,
798
+ resume,
799
+ resultsDir: join(f.base, 'lost-response'),
800
+ });
801
+ assert.equal(lost.qualified, false);
802
+ const attemptPath = join(f.options.resultsDir, 'consumer-attempt.json');
803
+ const attempt = JSON.parse(readFileSync(attemptPath, 'utf8'));
804
+ assert.equal(attempt.status, 'running');
805
+ assert.ok(attempt.command.observedProcesses.length > 0);
806
+ const blocked = await qualification.runQualification({
807
+ ...f.options,
808
+ execute,
809
+ resume,
810
+ resultsDir: join(f.base, 'unreconciled'),
811
+ });
812
+ assert.match(blocked.error, /Unresolved consumer attempt/u);
813
+ const reconciled = await qualification.runQualification({
814
+ ...f.options,
815
+ execute,
816
+ resume,
817
+ reconcileConsumer: true,
818
+ resultsDir: join(f.base, 'reconciled'),
819
+ });
820
+ assert.equal(reconciled.qualified, true);
821
+ assert.equal(launches, 1);
822
+ assert.deepEqual(f.counts(), { producers: 1, packs: 1, consumers: 1 });
823
+ assert.equal(JSON.parse(readFileSync(attemptPath, 'utf8')).status, 'reconciled');
824
+ }
825
+ finally {
826
+ f.cleanup();
827
+ }
828
+ });
829
+ test('reservation before launch survives an uncertain spawn and refuses automatic retry', async () => {
830
+ const f = qualificationFixture();
831
+ try {
832
+ await qualification.runQualification({ ...f.options, producerOnly: true });
833
+ let launches = 0;
834
+ const execute = async () => {
835
+ launches++;
836
+ throw new Error('fictional spawn response unknown');
837
+ };
838
+ const resume = join(f.options.resultsDir, 'checkpoint.json');
839
+ await qualification.runQualification({
840
+ ...f.options,
841
+ execute,
842
+ resume,
843
+ resultsDir: join(f.base, 'uncertain-launch'),
844
+ });
845
+ const blocked = await qualification.runQualification({
846
+ ...f.options,
847
+ execute,
848
+ resume,
849
+ reconcileConsumer: true,
850
+ resultsDir: join(f.base, 'uncertain-retry'),
851
+ });
852
+ assert.match(blocked.error, /launch identity is unavailable/u);
853
+ assert.equal(launches, 1);
854
+ assert.deepEqual(f.counts(), { producers: 1, packs: 1, consumers: 0 });
855
+ }
856
+ finally {
857
+ f.cleanup();
858
+ }
859
+ });
860
+ for (const mutation of ['zero-selection', 'counts', 'skip', 'inventory', 'command-cleanup', 'ordered-gates']) {
861
+ test(`qualification rejects ${mutation} producer proof without installation`, async () => {
862
+ const f = qualificationFixture();
863
+ try {
864
+ f.mutate((report) => {
865
+ if (mutation === 'zero-selection')
866
+ report.selectedTestFiles = [];
867
+ if (mutation === 'counts')
868
+ report.tests = { files: 1, total: 99, passed: 1, skips: [] };
869
+ if (mutation === 'skip')
870
+ report.tests = {
871
+ files: 1,
872
+ total: 2,
873
+ passed: 1,
874
+ skips: [{ file: 'dist/original.test.js', title: 'unreviewed', kind: 'arbitrary' }],
875
+ };
876
+ if (mutation === 'inventory')
877
+ report.inventory = {
878
+ kind: 'dry-inventory-only',
879
+ name: '@aviaratech/ai-delivery',
880
+ version: '1.0.0',
881
+ fileCount: 0,
882
+ files: [],
883
+ };
884
+ if (mutation === 'command-cleanup')
885
+ report.commands = checks.FULL_GATES.map((stage) => ({
886
+ stage,
887
+ status: 'passed',
888
+ exitCode: 0,
889
+ signal: null,
890
+ cleanupConfirmed: false,
891
+ }));
892
+ if (mutation === 'ordered-gates')
893
+ report.gates = [...checks.FULL_GATES].reverse();
894
+ });
895
+ const report = await qualification.runQualification(f.options);
896
+ assert.equal(report.qualified, false);
897
+ assert.equal(report.status, 'failed');
898
+ assert.equal(f.counts().consumers, 0);
899
+ }
900
+ finally {
901
+ f.cleanup();
902
+ }
903
+ });
904
+ }
905
+ for (const mutation of ['wrong-head', 'producer-digest', 'archive-digest', 'contract-digest']) {
906
+ test(`resume rejects ${mutation} without replaying any process`, async () => {
907
+ const f = qualificationFixture();
908
+ try {
909
+ await qualification.runQualification({ ...f.options, producerOnly: true });
910
+ const checkpoint = join(f.options.resultsDir, 'checkpoint.json');
911
+ if (mutation === 'wrong-head')
912
+ execFileSync('git', [
913
+ '-c',
914
+ 'user.name=Fictional fixture',
915
+ '-c',
916
+ 'user.email=fixture@example.invalid',
917
+ '-c',
918
+ 'core.hooksPath=/dev/null',
919
+ 'commit',
920
+ '--allow-empty',
921
+ '-qm',
922
+ 'different head same tree',
923
+ ], { cwd: f.cwd });
924
+ if (mutation === 'producer-digest')
925
+ writeFileSync(join(f.options.resultsDir, 'producer/result.json'), '{}');
926
+ if (mutation === 'archive-digest')
927
+ writeFileSync(join(f.options.resultsDir, 'pack/fictional.tgz'), 'changed');
928
+ if (mutation === 'contract-digest') {
929
+ const value = JSON.parse(readFileSync(checkpoint, 'utf8'));
930
+ value.contractSha256 = '0'.repeat(64);
931
+ writeFileSync(checkpoint, JSON.stringify(value));
932
+ }
933
+ const resumed = await qualification.runQualification({
934
+ ...f.options,
935
+ resume: checkpoint,
936
+ resultsDir: join(f.base, 'resume-bad'),
937
+ });
938
+ assert.equal(resumed.status, 'failed');
939
+ assert.equal(resumed.qualified, false);
940
+ assert.deepEqual(f.counts(), { producers: 1, packs: 1, consumers: 0 });
941
+ }
942
+ finally {
943
+ f.cleanup();
944
+ }
945
+ });
946
+ }
947
+ test('external consumer join never installs twice and rejects unconfirmed owned removal', async () => {
948
+ const f = qualificationFixture();
949
+ try {
950
+ await qualification.runQualification({ ...f.options, producerOnly: true });
951
+ const contract = JSON.parse(readFileSync(join(f.options.resultsDir, 'contract.json'), 'utf8'));
952
+ const receipt = await f.consume(contract, { authorizeInstall: true });
953
+ const consumerResult = join(f.base, 'external-consumer.json');
954
+ writeFileSync(consumerResult, JSON.stringify(receipt));
955
+ const resume = join(f.options.resultsDir, 'checkpoint.json');
956
+ const joined = await qualification.runQualification({
957
+ ...f.options,
958
+ resume,
959
+ consumerResult,
960
+ resultsDir: join(f.base, 'join'),
961
+ });
962
+ assert.equal(joined.qualified, true);
963
+ assert.deepEqual(f.counts(), { producers: 1, packs: 1, consumers: 1 });
964
+ receipt.cleanup = { quiescent: true, removed: false };
965
+ writeFileSync(consumerResult, JSON.stringify(receipt));
966
+ const bad = await qualification.runQualification({
967
+ ...f.options,
968
+ resume,
969
+ consumerResult,
970
+ resultsDir: join(f.base, 'bad-join'),
971
+ });
972
+ assert.equal(bad.qualified, false);
973
+ assert.match(bad.error, /removal/u);
974
+ }
975
+ finally {
976
+ f.cleanup();
977
+ }
978
+ });
979
+ for (const status of ['failed', 'timed-out', 'cancelled', 'cleanup-unconfirmed']) {
980
+ test(`actual pack ${status} cannot produce a successful checkpoint`, async () => {
981
+ const f = qualificationFixture();
982
+ try {
983
+ f.packFailure(status === 'cleanup-unconfirmed' ? 'passed' : status, status !== 'cleanup-unconfirmed');
984
+ const report = await qualification.runQualification(f.options);
985
+ assert.equal(report.qualified, false);
986
+ assert.equal(existsSync(join(f.options.resultsDir, 'checkpoint.json')), false);
987
+ assert.equal(f.counts().consumers, 0);
988
+ }
989
+ finally {
990
+ f.cleanup();
991
+ }
992
+ });
993
+ }
994
+ test('pre-start cancellation and inside-source evidence refuse all graph launches', async () => {
995
+ const f = qualificationFixture();
996
+ try {
997
+ const controller = new AbortController();
998
+ controller.abort();
999
+ const report = await qualification.runQualification({ ...f.options, signal: controller.signal });
1000
+ assert.equal(report.status, 'cancelled');
1001
+ assert.equal(report.exitCode, 130);
1002
+ assert.deepEqual(f.counts(), { producers: 0, packs: 0, consumers: 0 });
1003
+ await assert.rejects(qualification.runQualification({ ...f.options, resultsDir: join(f.cwd, '..looks-outside') }), /outside source/u);
1004
+ assert.deepEqual(f.counts(), { producers: 0, packs: 0, consumers: 0 });
1005
+ }
1006
+ finally {
1007
+ f.cleanup();
1008
+ }
1009
+ });
1010
+ //# sourceMappingURL=contributorChecks.test.js.map