@aviaratech/ai-delivery 0.3.10 → 0.3.12

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.
package/README.md CHANGED
@@ -10,6 +10,15 @@ Install the versioned package from npm or a reviewed package archive. The
10
10
  consuming repository must run its own configuration and runtime-admission
11
11
  procedure before any lifecycle write.
12
12
 
13
+ The selected CLI, MCP server and verification controller use Node 24.21.0 and
14
+ npm 11.19.0. The public library exports also support Node 26.2.0 consumers.
15
+ Package checks run the Node 24 controller against actual npm-packed Node 26
16
+ consumers, including filesystem fixture contention, reader and link rejection,
17
+ success/failure teardown, cancellation, leaked fixtures and positive byte limits.
18
+ For package development, set `AI_DELIVERY_NODE26_EXECUTABLE` to the absolute
19
+ Node 26.2.0 executable before `npm run checks`; CI retains that executable while
20
+ selecting Node 24 for the canonical commands.
21
+
13
22
  ```sh
14
23
  node --version # 24.21.0
15
24
  npm --version # 11.19.0
@@ -327,7 +336,7 @@ The `--admit` flag explicitly admits additional resource classes for execution.
327
336
 
328
337
  For a bounded run, pass `--max-aggregate-rss-bytes`, `--min-free-disk-bytes`, and optionally `--max-new-output-bytes` with one or more `--output-root` paths to `verify`. `issue_verify` accepts the same values in `resourceBounds`. RSS is sampled across the observed child process tree, including observed detached descendants; free disk is checked before commands and during execution on the worktree and declared output filesystems. Positive file-size growth is sampled under the declared roots, with previously measured completed stages carried across a resume. The caller must declare every output root relevant to its allowance; aliases must resolve within those roots. The roots are relative to the issue worktree unless absolute. Output growth is separate from the 8 MiB captured stdout/stderr limit. Resource limits are opt in and do not impose a total runtime deadline.
329
338
 
330
- During a running command, an `ENOENT` from symlink resolution can reflect ordinary tree removal. The observer reports the first path and errno and retries complete scans for at most one second; it never accepts a partial scan or resets that observation-stall window. Cancellation interrupts the wait, and RSS and disk checks continue. Baseline and final scans remain strict; persistent broken links, cycles and escaping aliases fail closed. Failed commands retain captured stdout/stderr in the existing private content-addressed command-output store, with its digest and the actual exit status in the failure diagnostic. Output still buffered inside a killed child is unavailable to the runner.
339
+ During a running command, a previously validated, unchanged alias may temporarily lose its physical target during a rebuild. The observer checks its current identity and target ancestry, reports the path and errno, and still completes a fresh scan of all physical files in every declared root. It never substitutes an incomplete scan or an earlier byte count. A missing target does not impose a build deadline when complete output accounting remains available. Unvalidated aliases that prevent a complete scan retain the one-second observation-stall window, starting after the first failed scan rather than before it. Cancellation, RSS and disk checks continue. Baseline and final scans remain strict; permanent broken links, cycles, escaping aliases and changed identities fail closed. Failed commands retain captured stdout/stderr in the existing private content-addressed command-output store, with its digest, actual exit status and first/last filesystem observation in the failure diagnostic. Output still buffered inside a killed child is unavailable to the runner.
331
340
 
332
341
  Real filesystem-negative tests can use `withVerificationFilesystemFixture` from `@aviaratech/ai-delivery` (or its `agent` export):
333
342
 
@@ -1,10 +1,12 @@
1
1
  import assert from 'node:assert/strict';
2
2
  import { execFileSync, spawn, spawnSync } from 'node:child_process';
3
3
  import { createHash } from 'node:crypto';
4
+ import { syncBuiltinESMExports } from 'node:module';
4
5
  import { cpSync, chmodSync, existsSync, mkdirSync, mkdtempSync, readFileSync, readlinkSync, readdirSync, realpathSync, rmSync, symlinkSync, unlinkSync, utimesSync, writeFileSync, } from 'node:fs';
5
6
  import { tmpdir } from 'node:os';
6
7
  import { dirname, join } from 'node:path';
7
- import { test, vi } from 'vitest';
8
+ import { fileURLToPath } from 'node:url';
9
+ import { afterAll, test, vi } from 'vitest';
8
10
  import { syntheticDiscoveryClients, syntheticOverrides } from './fixtures/discovery.js';
9
11
  import { Octokit } from '@octokit/rest';
10
12
  import { Client } from '@modelcontextprotocol/sdk/client/index.js';
@@ -4021,7 +4023,196 @@ test.each([
4021
4023
  test('an unrelated consumer uses public MCP setup through verified configured-author publication, counted review readback, merge and cleanup', { timeout: 0 }, async () => {
4022
4024
  await syntheticLifecycle({ remote: 'origin', divergentOrigin: false, producerOnboarding: true });
4023
4025
  });
4024
- test.each(['pass', 'command-error', 'cancel', 'persistent', 'limit'])('ordinary owned symlink teardown preserves observation and %s command evidence', async (mode) => {
4026
+ function ordinaryCliRebuildScript(output, mode = 'pass', target = join(output, 'cli.js')) {
4027
+ return `(async () => {
4028
+ const fs = require('node:fs');
4029
+ const trace = event => fs.appendFileSync(${JSON.stringify(join(output, 'events'))}, event + '\\n');
4030
+ trace('command-started'); fs.unlinkSync(${JSON.stringify(target)}); trace('target-removed');
4031
+ if (${JSON.stringify(dirname(target))} !== ${JSON.stringify(output)}) fs.rmdirSync(${JSON.stringify(dirname(target))});
4032
+ if (${JSON.stringify(mode)} === 'limit') fs.writeFileSync(${JSON.stringify(join(output, 'oversized'))}, 'x'.repeat(4096));
4033
+ for (let unit = 0; unit < 32; unit++) {
4034
+ fs.appendFileSync(${JSON.stringify(join(output, 'compiled'))}, 'build-unit\\n');
4035
+ trace('build-unit-' + unit);
4036
+ await new Promise(resolve => setTimeout(resolve, 100));
4037
+ }
4038
+ if (${JSON.stringify(mode)} !== 'absent') {
4039
+ fs.mkdirSync(${JSON.stringify(dirname(target))}, { recursive: true });
4040
+ fs.writeFileSync(${JSON.stringify(target)}, 'rebuilt CLI'); trace('target-restored');
4041
+ }
4042
+ })().catch(error => { console.error(error); process.exitCode = 1; });`;
4043
+ }
4044
+ test.each(['direct', 'chain', 'directory'])('ordinary bounded rebuild restores its %s CLI target after observable build work', async (shape) => {
4045
+ const output = realpathSync(mkdtempSync(join(tmpdir(), 'ai-delivery-cli-rebuild-')));
4046
+ const { root } = await fixture();
4047
+ const target = shape === 'directory' ? join(output, 'dist', 'cli.js') : join(output, 'cli.js');
4048
+ const alias = join(output, 'cli');
4049
+ const events = join(output, 'events');
4050
+ mkdirSync(dirname(target), { recursive: true });
4051
+ writeFileSync(target, 'original CLI');
4052
+ writeFileSync(join(output, 'unrelated'), 'preserved');
4053
+ if (shape === 'direct')
4054
+ symlinkSync('./cli.js', alias);
4055
+ else {
4056
+ symlinkSync(shape === 'chain' ? './cli.js' : './dist', join(output, 'intermediate'));
4057
+ symlinkSync(shape === 'chain' ? './intermediate' : './intermediate/cli.js', alias);
4058
+ }
4059
+ const observations = [];
4060
+ const duringAbsence = [];
4061
+ const progress = vi.spyOn(process.stderr, 'write').mockImplementation((line) => {
4062
+ observations.push(String(line));
4063
+ if (!existsSync(target) && String(line).includes('sampledNewOutputBytes'))
4064
+ duringAbsence.push(JSON.parse(String(line).slice(String(line).indexOf('{'))));
4065
+ return true;
4066
+ });
4067
+ const script = ordinaryCliRebuildScript(output, 'pass', target);
4068
+ try {
4069
+ const { withRuntimeSetupWriter } = await import('./verification.js');
4070
+ await withRuntimeSetupWriter(root, (runner) => runner.run([process.execPath, '-e', script], {
4071
+ maxAggregateRssBytes: 1_000_000_000,
4072
+ minFreeDiskBytes: 1,
4073
+ maxNewOutputBytes: 8192,
4074
+ outputRoots: [output],
4075
+ }));
4076
+ assert.equal(readFileSync(target, 'utf8'), 'rebuilt CLI');
4077
+ assert.equal(readFileSync(join(output, 'compiled'), 'utf8').split('\n').length, 33);
4078
+ assert.equal(readFileSync(join(output, 'unrelated'), 'utf8'), 'preserved');
4079
+ assert.ok(duringAbsence.some((sample) => (sample.sampledNewOutputBytes ?? 0) > 0));
4080
+ assert.ok(duringAbsence.every((sample) => (sample.sampledAggregateRssBytes ?? 0) > 0));
4081
+ }
4082
+ finally {
4083
+ console.log(JSON.stringify({
4084
+ scenario: 'ordinary-cli-rebuild',
4085
+ shape,
4086
+ firstObservation: observations.find((line) => line.includes('ENOENT')),
4087
+ events: readFileSync(events, 'utf8').trim().split('\n'),
4088
+ targetRestored: existsSync(target),
4089
+ unrelatedPreserved: readFileSync(join(output, 'unrelated'), 'utf8') === 'preserved',
4090
+ }));
4091
+ progress.mockRestore();
4092
+ rmSync(root, { recursive: true, force: true });
4093
+ rmSync(output, { recursive: true, force: true });
4094
+ }
4095
+ });
4096
+ test.each([
4097
+ 'bytes',
4098
+ 'rss',
4099
+ 'disk',
4100
+ 'fifo',
4101
+ 'permission',
4102
+ 'identity',
4103
+ 'ancestor',
4104
+ 'cycle',
4105
+ 'chain-identity',
4106
+ 'directory-identity',
4107
+ 'chain-cycle',
4108
+ ])('a missing validated target retains complete scan and %s rejection across roots', async (mode) => {
4109
+ const output = realpathSync(mkdtempSync(join(tmpdir(), 'ai-delivery-rebuild-boundary-')));
4110
+ const { root } = await fixture();
4111
+ const first = join(output, 'first'), second = join(output, 'second');
4112
+ mkdirSync(first);
4113
+ mkdirSync(second);
4114
+ const directory = join(first, 'dist'), target = join(directory, 'cli.js'), alias = join(first, 'cli');
4115
+ mkdirSync(directory);
4116
+ writeFileSync(target, 'CLI');
4117
+ const intermediate = join(first, 'intermediate');
4118
+ if (mode === 'chain-identity' || mode === 'chain-cycle') {
4119
+ symlinkSync('./dist/cli.js', intermediate);
4120
+ symlinkSync('./intermediate', alias);
4121
+ }
4122
+ else if (mode === 'directory-identity') {
4123
+ symlinkSync('./dist', intermediate);
4124
+ symlinkSync('./intermediate/cli.js', alias);
4125
+ }
4126
+ else
4127
+ symlinkSync('./dist/cli.js', alias);
4128
+ writeFileSync(join(second, 'unrelated'), 'preserved');
4129
+ const released = join(second, 'released');
4130
+ const observations = [];
4131
+ const progress = vi.spyOn(process.stderr, 'write').mockImplementation((line) => {
4132
+ observations.push(String(line));
4133
+ if (String(line).includes('ENOENT'))
4134
+ writeFileSync(released, 'observed');
4135
+ return true;
4136
+ });
4137
+ const script = `(async () => {
4138
+ const fs = require('node:fs'), cp = require('node:child_process');
4139
+ fs.unlinkSync(${JSON.stringify(target)});
4140
+ while (!fs.existsSync(${JSON.stringify(released)})) await new Promise(resolve => setTimeout(resolve, 10));
4141
+ if (${JSON.stringify(mode)} === 'bytes') fs.writeFileSync(${JSON.stringify(join(second, 'oversized'))}, 'x'.repeat(4096));
4142
+ if (${JSON.stringify(mode)} === 'rss') globalThis.retainedBuildMemory = Buffer.alloc(200 * 1024 * 1024, 1);
4143
+ if (${JSON.stringify(mode)} === 'disk') fs.writeFileSync(${JSON.stringify(join(second, 'disk-output'))}, Buffer.alloc(64 * 1024 * 1024, 1));
4144
+ if (${JSON.stringify(mode)} === 'fifo') cp.execFileSync('mkfifo', [${JSON.stringify(join(second, 'unsupported'))}]);
4145
+ if (${JSON.stringify(mode)} === 'permission') {
4146
+ fs.mkdirSync(${JSON.stringify(join(second, 'denied'))});
4147
+ fs.chmodSync(${JSON.stringify(join(second, 'denied'))}, 0);
4148
+ }
4149
+ if (${JSON.stringify(mode)} === 'identity') {
4150
+ fs.unlinkSync(${JSON.stringify(alias)}); fs.writeFileSync(${JSON.stringify(join(first, 'other'))}, 'other');
4151
+ fs.symlinkSync('./other', ${JSON.stringify(alias)});
4152
+ }
4153
+ if (${JSON.stringify(mode)} === 'ancestor') {
4154
+ fs.rmdirSync(${JSON.stringify(directory)}); fs.symlinkSync(${JSON.stringify(second)}, ${JSON.stringify(directory)});
4155
+ }
4156
+ if (${JSON.stringify(mode)} === 'cycle') fs.symlinkSync('./cli.js', ${JSON.stringify(target)});
4157
+ if (${JSON.stringify(mode)} === 'chain-identity') {
4158
+ fs.unlinkSync(${JSON.stringify(intermediate)}); fs.writeFileSync(${JSON.stringify(join(first, 'other'))}, 'other');
4159
+ fs.symlinkSync('./other', ${JSON.stringify(intermediate)});
4160
+ }
4161
+ if (${JSON.stringify(mode)} === 'directory-identity') {
4162
+ fs.unlinkSync(${JSON.stringify(intermediate)}); fs.mkdirSync(${JSON.stringify(join(first, 'other'))});
4163
+ fs.writeFileSync(${JSON.stringify(join(first, 'other', 'cli.js'))}, 'other');
4164
+ fs.symlinkSync('./other', ${JSON.stringify(intermediate)});
4165
+ }
4166
+ if (${JSON.stringify(mode)} === 'chain-cycle') {
4167
+ fs.unlinkSync(${JSON.stringify(intermediate)}); fs.symlinkSync('./cli', ${JSON.stringify(intermediate)});
4168
+ }
4169
+ for (let unit = 0; unit < 32; unit++) {
4170
+ fs.appendFileSync(${JSON.stringify(join(second, 'work'))}, 'unit\\n');
4171
+ await new Promise(resolve => setTimeout(resolve, 100));
4172
+ }
4173
+ fs.writeFileSync(${JSON.stringify(target)}, 'rebuilt CLI');
4174
+ })().catch(error => { console.error(error); process.exitCode = 1; });`;
4175
+ try {
4176
+ const { withRuntimeSetupWriter } = await import('./verification.js');
4177
+ const disk = (await import('node:fs')).statfsSync(output);
4178
+ await assert.rejects(withRuntimeSetupWriter(root, (runner) => runner.run([process.execPath, '-e', script], {
4179
+ maxAggregateRssBytes: mode === 'rss' ? 128 * 1024 * 1024 : 1_000_000_000,
4180
+ minFreeDiskBytes: mode === 'disk' ? disk.bavail * disk.bsize - 32 * 1024 * 1024 : 1,
4181
+ maxNewOutputBytes: mode === 'disk' ? 128 * 1024 * 1024 : 1024,
4182
+ outputRoots: [first, second],
4183
+ })), (error) => {
4184
+ const message = String(error);
4185
+ assert.match(message, mode === 'bytes'
4186
+ ? /filesystem output.*exceeded/u
4187
+ : mode === 'rss'
4188
+ ? /aggregate RSS.*exceeded/u
4189
+ : mode === 'disk'
4190
+ ? /Free disk fell below/u
4191
+ : mode === 'fifo'
4192
+ ? /unsupported file/u
4193
+ : mode === 'permission'
4194
+ ? /readdir failed.*EACCES/u
4195
+ : mode === 'cycle' || mode === 'chain-cycle'
4196
+ ? /ELOOP/u
4197
+ : /identity changed/u);
4198
+ assert.match(message, /First filesystem observation:.*ENOENT.*Last filesystem observation:/u);
4199
+ assert.doesNotMatch(message, /cleanup failed/u);
4200
+ return true;
4201
+ });
4202
+ assert.ok(observations.some((line) => line.includes('ENOENT')));
4203
+ assert.equal(observations.some((line) => line.includes('"state":"completed"')), false);
4204
+ assert.equal(readFileSync(join(second, 'unrelated'), 'utf8'), 'preserved');
4205
+ }
4206
+ finally {
4207
+ const denied = join(second, 'denied');
4208
+ if (existsSync(denied))
4209
+ chmodSync(denied, 0o700);
4210
+ progress.mockRestore();
4211
+ rmSync(root, { recursive: true, force: true });
4212
+ rmSync(output, { recursive: true, force: true });
4213
+ }
4214
+ });
4215
+ test.each(['pass', 'chain-pass', 'command-error', 'cancel', 'persistent', 'limit'])('ordinary owned symlink teardown preserves observation and %s command evidence', async (mode) => {
4025
4216
  const output = realpathSync(mkdtempSync(join(tmpdir(), 'ai-delivery-ordinary-teardown-')));
4026
4217
  const { root } = await fixture();
4027
4218
  const controller = new AbortController();
@@ -4030,7 +4221,9 @@ test.each(['pass', 'command-error', 'cancel', 'persistent', 'limit'])('ordinary
4030
4221
  const release = join(output, 'release');
4031
4222
  writeFileSync(join(output, 'unrelated'), 'preserved');
4032
4223
  writeFileSync(join(output, 'target'), 'x'.repeat(128));
4033
- symlinkSync('./target', join(output, 'alias'));
4224
+ if (mode === 'chain-pass')
4225
+ symlinkSync('./target', join(output, 'intermediate'));
4226
+ symlinkSync(mode === 'chain-pass' ? './intermediate' : './target', join(output, 'alias'));
4034
4227
  let observedGap = false;
4035
4228
  const observations = [];
4036
4229
  let releaseTimer;
@@ -4043,7 +4236,7 @@ test.each(['pass', 'command-error', 'cancel', 'persistent', 'limit'])('ordinary
4043
4236
  releaseTimer = setTimeout(() => {
4044
4237
  if (mode === 'cancel')
4045
4238
  controller.abort();
4046
- else if (mode !== 'persistent')
4239
+ else
4047
4240
  writeFileSync(release, 'continue');
4048
4241
  }, 100);
4049
4242
  }
@@ -4059,7 +4252,10 @@ test.each(['pass', 'command-error', 'cancel', 'persistent', 'limit'])('ordinary
4059
4252
  trace('target-removed'); fs.writeFileSync(${JSON.stringify(ready)}, 'ready');
4060
4253
  if (${JSON.stringify(mode)} === 'limit') fs.writeFileSync(${JSON.stringify(join(output, 'retained'))}, 'x'.repeat(512));
4061
4254
  while (!fs.existsSync(${JSON.stringify(release)})) await new Promise(resolve => setTimeout(resolve, 10));
4062
- fs.unlinkSync(${JSON.stringify(join(output, 'alias'))}); trace('alias-removed');
4255
+ if (${JSON.stringify(mode)} !== 'persistent') {
4256
+ fs.unlinkSync(${JSON.stringify(join(output, 'alias'))}); trace('alias-removed');
4257
+ if (${JSON.stringify(mode)} === 'chain-pass') fs.unlinkSync(${JSON.stringify(join(output, 'intermediate'))});
4258
+ }
4063
4259
  process.exitCode = ${mode === 'command-error' ? 7 : 0};
4064
4260
  })().catch(error => { console.error(error); process.exitCode = 1; });`;
4065
4261
  try {
@@ -4070,7 +4266,7 @@ test.each(['pass', 'command-error', 'cancel', 'persistent', 'limit'])('ordinary
4070
4266
  maxNewOutputBytes: mode === 'limit' ? 256 : 4096,
4071
4267
  outputRoots: [output],
4072
4268
  }, controller.signal));
4073
- if (mode === 'pass')
4269
+ if (mode === 'pass' || mode === 'chain-pass')
4074
4270
  await run;
4075
4271
  else
4076
4272
  await assert.rejects(run, (error) => {
@@ -4078,7 +4274,7 @@ test.each(['pass', 'command-error', 'cancel', 'persistent', 'limit'])('ordinary
4078
4274
  assert.match(message, mode === 'cancel'
4079
4275
  ? /cancelled/u
4080
4276
  : mode === 'persistent'
4081
- ? /remained unavailable.*First observation:.*ENOENT/u
4277
+ ? /broken or cyclic symbolic link.*ENOENT/u
4082
4278
  : mode === 'limit'
4083
4279
  ? /filesystem output.*exceeded/u
4084
4280
  : /exit 7/u);
@@ -4107,7 +4303,7 @@ test.each(['pass', 'command-error', 'cancel', 'persistent', 'limit'])('ordinary
4107
4303
  unrelatedPreserved: true,
4108
4304
  aliasRetained: readdirSync(output).includes('alias'),
4109
4305
  }));
4110
- assert.deepEqual(readFileSync(events, 'utf8').trim().split('\n'), mode === 'cancel' || mode === 'persistent'
4306
+ assert.deepEqual(readFileSync(events, 'utf8').trim().split('\n'), mode === 'cancel' || mode === 'persistent' || mode === 'limit'
4111
4307
  ? ['command-started', 'target-removed']
4112
4308
  : ['command-started', 'target-removed', 'alias-removed']);
4113
4309
  if (mode === 'cancel' || mode === 'persistent') {
@@ -4132,12 +4328,68 @@ test.each(['pass', 'command-error', 'cancel', 'persistent', 'limit'])('ordinary
4132
4328
  rmSync(output, { recursive: true, force: true });
4133
4329
  }
4134
4330
  });
4135
- test('injected observation deadline rejects a late complete real filesystem retry', async () => {
4331
+ test('injected first failed scan duration does not consume the subsequent observation stall window', async () => {
4332
+ const output = realpathSync(mkdtempSync(join(tmpdir(), 'ai-delivery-scan-duration-')));
4333
+ const { root } = await fixture();
4334
+ const target = join(output, 'target'), alias = join(output, 'alias'), release = join(output, 'release');
4335
+ writeFileSync(target, 'target');
4336
+ const fs = (await import('node:fs')).default;
4337
+ const actualRealpath = fs.realpathSync;
4338
+ const now = Date.now.bind(Date);
4339
+ let offset = 0, delayed = false, firstObservation;
4340
+ const clock = vi.spyOn(Date, 'now').mockImplementation(() => now() + offset);
4341
+ const scan = vi.spyOn(fs, 'realpathSync').mockImplementation((path, options) => {
4342
+ try {
4343
+ return actualRealpath(path, options);
4344
+ }
4345
+ catch (error) {
4346
+ if (path === alias && !delayed) {
4347
+ delayed = true;
4348
+ offset = 1500;
4349
+ }
4350
+ throw error;
4351
+ }
4352
+ });
4353
+ syncBuiltinESMExports();
4354
+ const progress = vi.spyOn(process.stderr, 'write').mockImplementation((line) => {
4355
+ if (firstObservation === undefined && String(line).includes('ENOENT')) {
4356
+ firstObservation = String(line);
4357
+ unlinkSync(alias);
4358
+ writeFileSync(release, 'finish');
4359
+ }
4360
+ return true;
4361
+ });
4362
+ const script = `(async () => {
4363
+ const fs = require('node:fs'); fs.unlinkSync(${JSON.stringify(target)});
4364
+ fs.symlinkSync('./target', ${JSON.stringify(alias)});
4365
+ while (!fs.existsSync(${JSON.stringify(release)})) await new Promise(resolve => setTimeout(resolve, 10));
4366
+ })().catch(error => { console.error(error); process.exitCode = 1; });`;
4367
+ try {
4368
+ const { withRuntimeSetupWriter } = await import('./verification.js');
4369
+ await withRuntimeSetupWriter(root, (runner) => runner.run([process.execPath, '-e', script], {
4370
+ maxAggregateRssBytes: 1_000_000_000,
4371
+ minFreeDiskBytes: 1,
4372
+ maxNewOutputBytes: 4096,
4373
+ outputRoots: [output],
4374
+ }));
4375
+ assert.ok(delayed);
4376
+ assert.ok(firstObservation);
4377
+ assert.equal(existsSync(alias), false);
4378
+ }
4379
+ finally {
4380
+ progress.mockRestore();
4381
+ scan.mockRestore();
4382
+ syncBuiltinESMExports();
4383
+ clock.mockRestore();
4384
+ rmSync(root, { recursive: true, force: true });
4385
+ rmSync(output, { recursive: true, force: true });
4386
+ }
4387
+ });
4388
+ test('injected observation stall rejects a late complete retry for an unvalidated alias', async () => {
4136
4389
  const output = realpathSync(mkdtempSync(join(tmpdir(), 'ai-delivery-observation-deadline-')));
4137
4390
  const { root } = await fixture();
4138
4391
  const target = join(output, 'target'), alias = join(output, 'alias'), release = join(output, 'release');
4139
4392
  writeFileSync(target, 'target');
4140
- symlinkSync('./target', alias);
4141
4393
  const now = Date.now.bind(Date);
4142
4394
  let offset = 0;
4143
4395
  let firstObservation;
@@ -4157,6 +4409,7 @@ test('injected observation deadline rejects a late complete real filesystem retr
4157
4409
  });
4158
4410
  const script = `(async () => {
4159
4411
  const fs = require('node:fs'); fs.unlinkSync(${JSON.stringify(target)});
4412
+ fs.symlinkSync('./target', ${JSON.stringify(alias)});
4160
4413
  while (!fs.existsSync(${JSON.stringify(release)})) await new Promise(resolve => setTimeout(resolve, 10));
4161
4414
  })().catch(error => { console.error(error); process.exitCode = 1; });`;
4162
4415
  try {
@@ -4251,13 +4504,155 @@ test('fully cached bounded verification still rejects a newly leaked FIFO', asyn
4251
4504
  rmSync(root, { recursive: true, force: true });
4252
4505
  }
4253
4506
  });
4254
- function filesystemFixtureScript(output, mode) {
4507
+ let node26Package;
4508
+ function packedNode26Consumer() {
4509
+ if (node26Package !== undefined)
4510
+ return node26Package;
4511
+ assert.equal(process.version, 'v24.21.0', 'canonical verification controller must remain Node 24.21.0');
4512
+ const executable = process.env['AI_DELIVERY_NODE26_EXECUTABLE'];
4513
+ assert.ok(executable, 'set AI_DELIVERY_NODE26_EXECUTABLE to the actual Node 26.2.0 executable');
4514
+ assert.equal(execFileSync(executable, ['--version'], { encoding: 'utf8' }).trim(), 'v26.2.0');
4515
+ const temporary = realpathSync(mkdtempSync(join(tmpdir(), 'ai-delivery-node26-')));
4516
+ try {
4517
+ const source = fileURLToPath(new URL('../', import.meta.url));
4518
+ const pack = JSON.parse(execFileSync('npm', ['pack', '--json', '--pack-destination', temporary], {
4519
+ cwd: source,
4520
+ encoding: 'utf8',
4521
+ maxBuffer: 4 * 1024 * 1024,
4522
+ }));
4523
+ execFileSync('tar', ['-xzf', join(temporary, pack[0].filename), '-C', temporary]);
4524
+ const root = join(temporary, 'package');
4525
+ symlinkSync(join(source, 'node_modules'), join(root, 'node_modules'), 'dir');
4526
+ process.stderr.write(`ai-delivery.node26-consumer ${JSON.stringify({
4527
+ controller: process.version,
4528
+ consumer: 'v26.2.0',
4529
+ archiveSha256: createHash('sha256')
4530
+ .update(readFileSync(join(temporary, pack[0].filename)))
4531
+ .digest('hex'),
4532
+ manifestSha256: createHash('sha256')
4533
+ .update(readFileSync(join(root, 'package.json')))
4534
+ .digest('hex'),
4535
+ })}\n`);
4536
+ node26Package = { executable: realpathSync(executable), root, temporary };
4537
+ return node26Package;
4538
+ }
4539
+ catch (error) {
4540
+ rmSync(temporary, { recursive: true, force: true });
4541
+ throw error;
4542
+ }
4543
+ }
4544
+ afterAll(() => {
4545
+ if (node26Package !== undefined)
4546
+ rmSync(node26Package.temporary, { recursive: true, force: true });
4547
+ });
4548
+ function node26ConsumerScript(script) {
4549
+ const consumer = packedNode26Consumer();
4255
4550
  return `
4551
+ require('node:assert/strict').equal(process.version, 'v24.21.0');
4552
+ const child = require('node:child_process').spawnSync(${JSON.stringify(consumer.executable)}, ['-e', ${JSON.stringify(script)}], { cwd: ${JSON.stringify(consumer.root)}, stdio: 'inherit' });
4553
+ if (child.error) throw child.error;
4554
+ process.exit(child.status ?? 1);`;
4555
+ }
4556
+ test.each(['pass', 'absent', 'limit', 'cancel'])('Node 26 packed public verification preserves CLI rebuild %s behavior', async (mode) => {
4557
+ const output = realpathSync(mkdtempSync(join(tmpdir(), 'ai-delivery-packed-rebuild-')));
4558
+ const target = join(output, 'cli.js');
4559
+ writeFileSync(target, 'original CLI');
4560
+ symlinkSync('./cli.js', join(output, 'cli'));
4561
+ writeFileSync(join(output, 'unrelated'), 'preserved');
4562
+ const { root } = await fixture({ personalAuthor: true, firstStageScript: ordinaryCliRebuildScript(output, mode) });
4563
+ try {
4564
+ const row = await prepareIssueWorktree({
4565
+ baseRef: 'main',
4566
+ identity: 'host-author',
4567
+ issueNumber: 17,
4568
+ repoRoot: root,
4569
+ });
4570
+ const clients = syntheticDiscoveryClients();
4571
+ const replies = [];
4572
+ for (const fragment of [
4573
+ 'query DeliveryRepository',
4574
+ 'query ProjectDeliveryConfiguration',
4575
+ 'issueFields(first:',
4576
+ 'issueTypes(first:',
4577
+ ])
4578
+ replies.push({ fragment, data: await clients.graphql(fragment) });
4579
+ const consumer = packedNode26Consumer();
4580
+ const result = execFileSync(consumer.executable, [
4581
+ '-e',
4582
+ `(async () => {
4583
+ const assert = require('node:assert/strict'), fs = require('node:fs');
4584
+ assert.equal(process.version, 'v26.2.0');
4585
+ const replies = ${JSON.stringify(replies)};
4586
+ // Only GitHub discovery transport is synthetic; package, writer, scanner and child filesystem are real.
4587
+ globalThis.fetch = async (url, options) => {
4588
+ assert.equal(String(url), 'https://api.github.com/graphql');
4589
+ const query = JSON.parse(options.body).query;
4590
+ const reply = replies.find(reply => query.includes(reply.fragment));
4591
+ assert.ok(reply, 'unexpected synthetic discovery query');
4592
+ return new Response(JSON.stringify({ data: reply.data }), { status: 200, headers: { 'content-type': 'application/json' } });
4593
+ };
4594
+ process.env.AUTHOR_TOKEN = 'synthetic-author-token';
4595
+ const { verifyIssue } = await import('@aviaratech/ai-delivery/agent');
4596
+ const controller = new AbortController();
4597
+ const observations = []; const write = process.stderr.write.bind(process.stderr);
4598
+ process.stderr.write = line => {
4599
+ observations.push(String(line));
4600
+ if (${JSON.stringify(mode)} === 'cancel' && String(line).includes('ENOENT')) controller.abort();
4601
+ return true;
4602
+ };
4603
+ try {
4604
+ const running = verifyIssue({ issueNumber: 17, repoRoot: ${JSON.stringify(row.path)}, signal: controller.signal,
4605
+ resourceBounds: { maxAggregateRssBytes: 1000000000, minFreeDiskBytes: 1,
4606
+ maxNewOutputBytes: ${mode === 'limit' ? 1024 : 8192}, outputRoots: [${JSON.stringify(output)}] } });
4607
+ if (${JSON.stringify(mode)} === 'pass') {
4608
+ const run = await running;
4609
+ assert.ok(run.resources.sampleCount > 0); assert.ok(run.resources.maxSampledNewOutputBytes > 0);
4610
+ assert.equal(fs.readFileSync(${JSON.stringify(target)}, 'utf8'), 'rebuilt CLI');
4611
+ // Compatible completed proof is reused, but the current final filesystem is still strictly scanned.
4612
+ fs.unlinkSync(${JSON.stringify(target)});
4613
+ await assert.rejects(verifyIssue({ issueNumber: 17, repoRoot: ${JSON.stringify(row.path)},
4614
+ resourceBounds: { maxAggregateRssBytes: 1000000000, minFreeDiskBytes: 1, maxNewOutputBytes: 8192,
4615
+ outputRoots: [${JSON.stringify(output)}] } }), /broken or cyclic symbolic link/);
4616
+ } else {
4617
+ await assert.rejects(running, error => {
4618
+ assert.match(String(error), ${mode === 'cancel' ? '/cancelled/' : mode === 'limit' ? '/filesystem output.*exceeded/' : '/broken or cyclic symbolic link/'});
4619
+ assert.doesNotMatch(String(error), /cleanup failed/); return true;
4620
+ });
4621
+ }
4622
+ assert.ok(observations.some(line => line.includes('ENOENT')));
4623
+ assert.equal(fs.readFileSync(${JSON.stringify(join(output, 'unrelated'))}, 'utf8'), 'preserved');
4624
+ console.log(JSON.stringify({ scenario: 'packed-node26-cli-rebuild', mode: ${JSON.stringify(mode)},
4625
+ firstObservation: observations.find(line => line.includes('ENOENT')), events: fs.readFileSync(${JSON.stringify(join(output, 'events'))}, 'utf8').trim().split('\\n') }));
4626
+ } finally { controller.abort(); process.stderr.write = write; }
4627
+ })().catch(error => { console.error(error); process.exitCode = 1; });`,
4628
+ ], {
4629
+ cwd: consumer.root,
4630
+ encoding: 'utf8',
4631
+ maxBuffer: 1024 * 1024,
4632
+ });
4633
+ console.log(result.trim());
4634
+ }
4635
+ finally {
4636
+ rmSync(root, { recursive: true, force: true });
4637
+ rmSync(output, { recursive: true, force: true });
4638
+ }
4639
+ });
4640
+ function filesystemFixtureScript(output, mode, runtime = 'node24') {
4641
+ const script = `
4256
4642
  (async () => {
4257
4643
  const fs = require('node:fs'), cp = require('node:child_process'), path = require('node:path'), assert = require('node:assert/strict');
4258
- const { withVerificationFilesystemFixture } = await import(${JSON.stringify(new URL('./agent.js', import.meta.url).href)});
4259
- const { assertPrivateFile } = await import(${JSON.stringify(new URL('./delivery/common.js', import.meta.url).href)});
4644
+ assert.equal(process.version, ${JSON.stringify(runtime === 'node26' ? 'v26.2.0' : 'v24.21.0')});
4645
+ const { withVerificationFilesystemFixture } = await import(${JSON.stringify(runtime === 'node26' ? '@aviaratech/ai-delivery/agent' : new URL('./agent.js', import.meta.url).href)});
4646
+ const { loadValidRepositoryDeliveryEvidence } = await import(${JSON.stringify(runtime === 'node26' ? '@aviaratech/ai-delivery/delivery' : new URL('./delivery/index.js', import.meta.url).href)});
4260
4647
  const output = ${JSON.stringify(output)}, fifo = path.join(output, 'fifo'), events = path.join(output, 'events');
4648
+ const evidenceId = 'sha256:' + 'a'.repeat(64), currentHead = { sha: 'b'.repeat(40), tree: 'c'.repeat(40) };
4649
+ const evidence = path.join(output, 'ai-delivery', 'receipts', 'delivery@1', currentHead.sha, evidenceId.slice(7) + '.json');
4650
+ fs.mkdirSync(path.dirname(evidence), { recursive: true });
4651
+ const rejectPrivateFile = file => {
4652
+ fs.renameSync(file, evidence);
4653
+ try { assert.throws(() => loadValidRepositoryDeliveryEvidence({ createInput: { gitCommonDir: output, currentHead }, evidenceId }), /private regular file/); }
4654
+ finally { fs.renameSync(evidence, file); }
4655
+ };
4261
4656
  const gate = JSON.parse(process.env.AI_DELIVERY_OUTPUT_OBSERVATION_GATE);
4262
4657
  const trace = value => fs.appendFileSync(events, value + '\\n');
4263
4658
  await withVerificationFilesystemFixture(async () => {
@@ -4270,20 +4665,26 @@ function filesystemFixtureScript(output, mode) {
4270
4665
  if (${JSON.stringify(mode)} === 'block') fs.readFileSync(fifo);
4271
4666
  while (fs.readdirSync(path.join(gate.directory, 'requests')).length === 0) await new Promise(resolve => setTimeout(resolve, 10));
4272
4667
  assert.ok(fs.existsSync(fifo)); trace('scan-queued');
4273
- assert.throws(() => assertPrivateFile(fifo), /private regular file/); trace('reader-rejected');
4668
+ rejectPrivateFile(fifo); trace('reader-rejected');
4274
4669
  const regular = path.join(output, 'regular'), hard = path.join(output, 'hard'), alias = path.join(output, 'alias');
4275
4670
  fs.writeFileSync(regular, 'x'.repeat(128), { mode: 0o600 });
4276
- fs.linkSync(regular, hard); assert.throws(() => assertPrivateFile(hard), /private regular file/); fs.unlinkSync(hard);
4277
- fs.symlinkSync('./regular', alias); assert.throws(() => assertPrivateFile(alias), /private regular file/); fs.unlinkSync(alias);
4671
+ fs.linkSync(regular, hard); rejectPrivateFile(hard); fs.unlinkSync(hard);
4672
+ fs.symlinkSync('./regular', alias); rejectPrivateFile(alias); fs.unlinkSync(alias);
4278
4673
  if (${JSON.stringify(mode)} === 'assertion') throw new Error('synthetic reader assertion failure');
4279
4674
  } finally { fs.unlinkSync(fifo); trace('cleaned'); }
4280
4675
  });
4281
4676
  trace('released');
4282
4677
  })().catch(error => { console.error(error.message); process.exitCode = 1; });`;
4678
+ return runtime === 'node26' ? node26ConsumerScript(script) : script;
4283
4679
  }
4284
- test.each(['pass', 'assertion'])('filesystem fixture gate deterministically queues a scan through reader rejection and %s teardown', async (mode) => {
4680
+ test.each([
4681
+ ['pass', 'node24'],
4682
+ ['assertion', 'node24'],
4683
+ ['pass', 'node26'],
4684
+ ['assertion', 'node26'],
4685
+ ])('filesystem fixture gate deterministically queues a scan through reader rejection and %s teardown on %s', async (mode, runtime) => {
4285
4686
  const output = realpathSync(mkdtempSync(join(tmpdir(), 'ai-delivery-fixture-gate-')));
4286
- const { root } = await fixture({ firstStageScript: filesystemFixtureScript(output, mode) });
4687
+ const { root } = await fixture({ firstStageScript: filesystemFixtureScript(output, mode, runtime) });
4287
4688
  try {
4288
4689
  const row = await prepareIssueWorktree({
4289
4690
  baseRef: 'main',
@@ -4319,10 +4720,17 @@ test.each(['pass', 'assertion'])('filesystem fixture gate deterministically queu
4319
4720
  rmSync(output, { recursive: true, force: true });
4320
4721
  }
4321
4722
  });
4322
- test.each(['abrupt', 'block', 'cancel'])('filesystem fixture gate preserves leaked FIFO and unrelated files after %s', async (mode) => {
4723
+ test.each([
4724
+ ['abrupt', 'node24'],
4725
+ ['block', 'node24'],
4726
+ ['cancel', 'node24'],
4727
+ ['abrupt', 'node26'],
4728
+ ['block', 'node26'],
4729
+ ['cancel', 'node26'],
4730
+ ])('filesystem fixture gate preserves leaked FIFO and unrelated files after %s on %s', async (mode, runtime) => {
4323
4731
  const output = realpathSync(mkdtempSync(join(tmpdir(), 'ai-delivery-fixture-failure-')));
4324
4732
  writeFileSync(join(output, 'unrelated'), 'preserved');
4325
- const { root } = await fixture({ firstStageScript: filesystemFixtureScript(output, mode) });
4733
+ const { root } = await fixture({ firstStageScript: filesystemFixtureScript(output, mode, runtime) });
4326
4734
  const controller = new AbortController();
4327
4735
  let running;
4328
4736
  const progress = vi.spyOn(process.stderr, 'write');
@@ -4374,9 +4782,9 @@ test.each(['abrupt', 'block', 'cancel'])('filesystem fixture gate preserves leak
4374
4782
  rmSync(output, { recursive: true, force: true });
4375
4783
  }
4376
4784
  });
4377
- test('filesystem fixture gate still enforces positive byte limits after deterministic contention', async () => {
4785
+ test.each(['node24', 'node26'])('filesystem fixture gate still enforces positive byte limits after deterministic contention on %s', async (runtime) => {
4378
4786
  const output = realpathSync(mkdtempSync(join(tmpdir(), 'ai-delivery-fixture-limit-')));
4379
- const { root } = await fixture({ firstStageScript: filesystemFixtureScript(output, 'pass') });
4787
+ const { root } = await fixture({ firstStageScript: filesystemFixtureScript(output, 'pass', runtime) });
4380
4788
  try {
4381
4789
  const row = await prepareIssueWorktree({
4382
4790
  baseRef: 'main',
@@ -4478,6 +4886,37 @@ test.each(['verification', 'runtime'])('filesystem fixture gate preserves observ
4478
4886
  rmSync(output, { recursive: true, force: true });
4479
4887
  }
4480
4888
  });
4889
+ test('Node 26 packed public exports preserve standalone and malformed-capability behavior', () => {
4890
+ const consumer = packedNode26Consumer();
4891
+ execFileSync(consumer.executable, [
4892
+ '-e',
4893
+ `
4894
+ (async () => {
4895
+ const assert = require('node:assert/strict');
4896
+ assert.equal(process.version, 'v26.2.0');
4897
+ const [root, agent, delivery, mcp] = await Promise.all([
4898
+ import('@aviaratech/ai-delivery'), import('@aviaratech/ai-delivery/agent'),
4899
+ import('@aviaratech/ai-delivery/delivery'), import('@aviaratech/ai-delivery/mcp'),
4900
+ ]);
4901
+ assert.equal(root.withVerificationFilesystemFixture, agent.withVerificationFilesystemFixture);
4902
+ assert.equal(typeof agent.verifyIssue, 'function');
4903
+ assert.equal(typeof delivery.loadValidRepositoryDeliveryEvidence, 'function');
4904
+ assert.equal(typeof mcp.createAiDeliveryMcpServer, 'function');
4905
+ const manifest = JSON.parse(require('node:fs').readFileSync('package.json', 'utf8'));
4906
+ assert.deepEqual(Object.keys(manifest.exports).sort(), ['.', './agent', './delivery', './mcp']);
4907
+ const prior = process.env.AI_DELIVERY_OUTPUT_OBSERVATION_GATE;
4908
+ delete process.env.AI_DELIVERY_OUTPUT_OBSERVATION_GATE;
4909
+ assert.equal(await agent.withVerificationFilesystemFixture(() => 'standalone'), 'standalone');
4910
+ process.env.AI_DELIVERY_OUTPUT_OBSERVATION_GATE = '{}';
4911
+ let executed = false;
4912
+ await assert.rejects(agent.withVerificationFilesystemFixture(() => { executed = true; }), /invalid or stale/);
4913
+ assert.equal(executed, false);
4914
+ if (prior === undefined) delete process.env.AI_DELIVERY_OUTPUT_OBSERVATION_GATE;
4915
+ else process.env.AI_DELIVERY_OUTPUT_OBSERVATION_GATE = prior;
4916
+ })().catch(error => { console.error(error); process.exitCode = 1; });
4917
+ `,
4918
+ ], { cwd: consumer.root, stdio: 'pipe' });
4919
+ });
4481
4920
  test('filesystem fixture helper runs standalone and fails closed on malformed capability', async () => {
4482
4921
  const { withVerificationFilesystemFixture } = await import('./agent.js');
4483
4922
  assert.equal(await withVerificationFilesystemFixture(() => 'standalone'), 'standalone');