ReviewOS

also looking at this

stacks/drone

test: retain execution lifetime failure observations

#62
Draft chris wants to merge codex/execution-lifetime-observations into main
10 files +174 -64

Review threads live on the whole diff, not on one commit, so none are shown here - a thread's line means something in the branch's final form, and painting it into an intermediate step would put it on code it is not about.

docs/public-safety-execution.mdmodified+2-1
Changes to docs/public-safety-execution.md
@@ -120,7 +120,8 @@ response. The existing workspace browser scenarios remain required regressions.
120120The native lifetime fixture emits bounded phase observations around setup,
121121authority reads, retention waits and cleanup. Its parent records the observed
122122exit code and signal separately from whether its own watchdog fired or cleanup
123requested a kill. Elapsed time includes process work and output handling, not
123requested a kill. The settled `exited` status is distinct from the raw
124`exitCode` property, which can remain null after a signal. Elapsed time includes process work and output handling, not
124125just a native check. Failed cases retain their private temporary directory,
125126stdout, stderr and lifecycle receipt when storage permits. A fixed warning
126127identifies each unavailable evidence file if its write fails; this does not
tests/unit/public-safety-execution-lifetime.test.tsmodified+10-5
Changes to tests/unit/public-safety-execution-lifetime.test.ts
@@ -8,6 +8,7 @@ for (const mode of ['completed', 'canceled', 'quarantine']) test(`native executi
88 if (evidence) await mkdir(resolve(evidence), { recursive: true, mode: 0o700 })
99 const root = await mkdtemp(join(evidence ? resolve(evidence) : tmpdir(), 'drone-incident-access-execution-lifetime-'))
1010 let child: ReturnType<typeof Bun.spawn> | undefined
11 let settledExitCode: number | null = null
1112 const began = performance.now()
1213 let deadlineFired = false, cleanupKill = false, completed = false
1314 let stdoutWritten = false, stderrWritten = false
@@ -18,15 +19,16 @@ for (const mode of ['completed', 'canceled', 'quarantine']) test(`native executi
1819 try {
1920 const config = join(root, 'bunfig.toml'); await writeFile(config, 'preload=[]\n[install]\nauto="disable"\n')
2021 const running = child = Bun.spawn([process.execPath, '--no-install', `--config=${config}`, '--no-env-file', `${import.meta.dir}/../fixtures/public-safety-access/execution-lifetime.ts`, mode], { cwd: root, env: { APP_ENV: 'test', APP_DEBUG: 'false', NODE_ENV: 'test', DB_CONNECTION: 'sqlite', DB_DATABASE_PATH: join(root, 'access.sqlite') }, stdin: 'ignore', stdout: 'pipe', stderr: 'pipe' })
22 const exited = running.exited.then(code => { settledExitCode = code; return code })
2123 const timeout = setTimeout(() => {
22 if (running.exitCode !== null) return
24 if (settledExitCode !== null) return
2325 deadlineFired = true
2426 running.kill('SIGKILL')
2527 console.error('LIFETIME_FIXTURE_DEADLINE', JSON.stringify({ mode, pid: running.pid, timeoutMs: 90000, elapsedMs: performance.now() - began, requestedSignal: 'SIGKILL' }))
2628 }, 90000)
2729 try {
2830 console.log(JSON.stringify({ oracle: 'lifetime-fixture-start', mode, pid: running.pid, timeoutMs: 90000 }))
29 const [code, stdout, stderr] = await Promise.all([running.exited, new Response(running.stdout).text(), new Response(running.stderr).text()])
31 const [code, stdout, stderr] = await Promise.all([exited, new Response(running.stdout).text(), new Response(running.stderr).text()])
3032 // eslint-disable-next-line no-console
3133 for (const line of stdout.split('\n')) if (line.startsWith('{"oracle":')) console.log(line)
3234 stdoutWritten = await retain('fixture.stdout', stdout)
@@ -35,11 +37,14 @@ for (const mode of ['completed', 'canceled', 'quarantine']) test(`native executi
3537 expect(stdout).toContain(`PASS native execution lifetime ${mode}`)
3638 completed = true
3739 }
38 finally { clearTimeout(timeout); if (running.exitCode === null) { cleanupKill = true; running.kill('SIGKILL') }; await running.exited }
40 finally { clearTimeout(timeout); if (settledExitCode === null) { cleanupKill = true; running.kill('SIGKILL') }; settledExitCode = await exited }
3941 }
4042 finally {
41 if (child?.exitCode === null) { cleanupKill = true; child.kill('SIGKILL'); await child.exited }
42 const lifecycle = { mode, pid: child?.pid ?? null, exitCode: child?.exitCode ?? null, signal: child?.signalCode ?? null, timeoutMs: 90000, deadlineFired, cleanupKill, elapsedMs: performance.now() - began, stdoutWritten, stderrWritten, completed }
43 if (child && settledExitCode === null) {
44 if (child.exitCode === null && !child.signalCode) { cleanupKill = true; child.kill('SIGKILL') }
45 settledExitCode = await child.exited
46 }
47 const lifecycle = { mode, pid: child?.pid ?? null, exitCode: settledExitCode, exitProperty: child?.exitCode ?? null, signal: child?.signalCode ?? null, timeoutMs: 90000, deadlineFired, cleanupKill, elapsedMs: performance.now() - began, stdoutWritten, stderrWritten, completed }
4348 console.log(JSON.stringify({ oracle: 'lifetime-fixture-exit', ...lifecycle }))
4449 await retain('lifecycle.json', JSON.stringify(lifecycle, null, 2))
4550 if (completed) await rm(root, { recursive: true, force: true })