diff --git a/.github/workflows/verify.yml b/.github/workflows/verify.yml index 628e439a..0eba96b0 100644 --- a/.github/workflows/verify.yml +++ b/.github/workflows/verify.yml @@ -51,7 +51,7 @@ jobs: - name: Execute coded golden component scenes uses: treeseed-ai/reviewer/.github/actions/run-scenes@013d38165f0430278ac944592d3b20618736c2d5 env: - NODE_OPTIONS: --import=${{ github.workspace }}/tests/support/os-custody.mjs + NODE_OPTIONS: --import=${{ github.workspace }}/tests/support/os-custody.ts with: ids: guarantee.cli.golden.component-boundaries diff --git a/guarantees/agent/golden/scenes/component-boundaries.scene.yaml b/guarantees/agent/golden/scenes/component-boundaries.scene.yaml index 90fc01b6..4ac52079 100644 --- a/guarantees/agent/golden/scenes/component-boundaries.scene.yaml +++ b/guarantees/agent/golden/scenes/component-boundaries.scene.yaml @@ -498,3 +498,12 @@ workflow: - id: provider-handoff-selection-native action: { verifier: cli.golden.provider-handoff-selection-native } expect: { status: passed } + - id: installed-assets-unit + action: { verifier: cli.golden.installed-assets-unit } + expect: { status: passed } + - id: installed-assets-native + action: { verifier: cli.golden.installed-assets-native } + expect: { status: passed } + - id: installed-event-command + action: { verifier: cli.golden.installed-event-command } + expect: { status: passed } diff --git a/guarantees/verifiers/golden.verifiers.yaml b/guarantees/verifiers/golden.verifiers.yaml index 5f99ec9a..9ecfff57 100644 --- a/guarantees/verifiers/golden.verifiers.yaml +++ b/guarantees/verifiers/golden.verifiers.yaml @@ -9,7 +9,7 @@ verifiers: cli.golden.execution-diagnostics-read-native: kind: nodeTestCase ownerPackage: "@treeseed/cli" - testFile: tests/unit/command-boundary/observation/workday-events.test.ts + testFile: tests/acceptance/workday-events.test.ts testName: "packaged native workday diagnostic readback preserves exact clock bytes and denied history through unchanged retry without execution requests" cli.golden.execution-library-lookup-unit-1: kind: nodeTestCase @@ -104,7 +104,7 @@ verifiers: cli.golden.architecture-workday-event-native: kind: nodeTestCase ownerPackage: "@treeseed/cli" - testFile: tests/unit/command-boundary/observation/workday-events.test.ts + testFile: tests/acceptance/workday-events.test.ts testName: "retrieves a later exact event page through independent native CLI and real HTTP transport" cli.golden.schema-canonical: kind: nodeTestCase @@ -826,3 +826,18 @@ verifiers: ownerPackage: "@treeseed/cli" testFile: tests/integration/development-rebuild.test.ts testName: native restart refreshes changed caller recipe and retains one exact build and endpoint through retry + cli.golden.installed-assets-unit: + kind: nodeTestCase + ownerPackage: "@treeseed/cli" + testFile: tests/contract/package/installed-assets.test.ts + testName: "ships the selected CLI native observation assets without checkout source execution or private imports" + cli.golden.installed-assets-native: + kind: nodeTestCase + ownerPackage: "@treeseed/cli" + testFile: tests/contract/package/installed-assets.test.ts + testName: "native production CLI archive retains exact observation assets and executes its public binary without source or development dependencies" + cli.golden.installed-event-command: + kind: nodeTestCase + ownerPackage: "@treeseed/cli" + testFile: tests/contract/package/installed-assets.test.ts + testName: "native workday event cases never execute checkout source or substitute an unbound command" diff --git a/package.json b/package.json index b7e42c0d..74b90c8d 100644 --- a/package.json +++ b/package.json @@ -22,7 +22,11 @@ "completions", "dist", "docs/command-reference.md", - "schemas" + "schemas", + "treeseed.package.yaml", + "guarantees", + "tests/acceptance/workday-events.test.ts", + "tests/support/os-custody.ts" ], "publishConfig": { "access": "public" diff --git a/scripts/testing/run-tests.ts b/scripts/testing/run-tests.ts index 2884955c..8f192dcd 100644 --- a/scripts/testing/run-tests.ts +++ b/scripts/testing/run-tests.ts @@ -39,7 +39,7 @@ function main(): void { ...tests, ], { cwd: process.cwd(), - env: {...process.env,NODE_OPTIONS:`${process.env.NODE_OPTIONS ?? ''} --import=${resolve(process.cwd(),'tests/support/os-custody.mjs')}`.trim()}, + env: {...process.env,NODE_OPTIONS:`${process.env.NODE_OPTIONS ?? ''} --import=${resolve(process.cwd(),'tests/support/os-custody.ts')}`.trim()}, stdio: 'inherit', }); diff --git a/tests/acceptance/workday-events.test.ts b/tests/acceptance/workday-events.test.ts new file mode 100644 index 00000000..d186ed6e --- /dev/null +++ b/tests/acceptance/workday-events.test.ts @@ -0,0 +1,143 @@ +import '../support/os-custody.ts'; +import assert from 'node:assert/strict'; +import { spawn } from 'node:child_process'; +import { existsSync, mkdtempSync, readFileSync, rmSync } from 'node:fs'; +import { createServer } from 'node:http'; +import { tmpdir } from 'node:os'; +import { resolve } from 'node:path'; +import test from 'node:test'; +import { encodeCapacityPageCursor } from '@treeseed/sdk/capacity-pagination'; +import type { CommandExecutionBinding } from '@treeseed/sdk/operator-contracts'; + +const packageRoot = resolve(import.meta.dirname, '../..'); +const { commandSpecs }: { commandSpecs: Array<{ path: string[]; execution: CommandExecutionBinding }> } = + await import(new URL('../../dist/cli/registry.js', import.meta.url).href); +const { saveServerSession } = await import(new URL('../../dist/cli/support/server-custody.js', import.meta.url).href); +const loader = import.meta.resolve('tsx'); +const custody = new URL('../support/os-custody.ts', import.meta.url).href; +test('packaged native workday diagnostic readback preserves exact clock bytes and denied history through unchanged retry without execution requests', { timeout: 30_000 }, async context => { + const packageBytes = readFileSync(resolve(packageRoot, 'package.json')), manifest = JSON.parse(packageBytes.toString('utf8')); + assert.equal(manifest.bin.trsd, './dist/cli/main.js'); const entrypoint = resolve(packageRoot, manifest.bin.trsd), entryBytes = readFileSync(entrypoint); + const root = mkdtempSync(resolve(tmpdir(), 'treeseed-cli-clock-diagnostics-')); + const teamId = '11111111-1111-4111-8111-111111111111', runId = 'workday-fixture'; + const cursor = encodeCapacityPageCursor({ id: 'event-049', createdAt: '2026-10-07T12:00:00.000Z' }); + // Controlled raw diagnostic bytes, not native model clocks, API authorization or provider charges. + const clock = { observedAt: '2026-10-07T12:00:01.250Z', startedAt: '2026-10-07T12:00:00.000Z', + endsAt: '2026-10-07T12:01:00.000Z', remainingSeconds: 59 }; + const event = { id: 'event-050', runId, teamId, assignmentId: 'assignment-fixture', eventIndex: 50, + eventType: 'provider.execution.completed', status: 'completed', createdAt: '2026-10-07T12:00:02.000Z', + payload: { protection: { protected: true } }, protectedPayload: { providerEvents: [ + { type: 'model.tool.result', callId: 'clock-original', tool: 'provider.assignment.clock', output: JSON.stringify(clock) }, + ] } }; + const page = { items: [event], page: { limit: 50, hasMore: false, nextCursor: null } }, held = structuredClone(page); + const requests: Array<{ method: string | undefined; url: string; body: string }> = []; + let mode: 'accept' | 'denied' | 'unavailable' = 'accept', child: ReturnType | undefined; + const server = createServer((request, response) => { + let body = ''; request.setEncoding('utf8'); request.on('data', value => { body += String(value); }); + request.on('end', () => { + requests.push({ method: request.method, url: request.url ?? '', body }); + response.setHeader('content-type', 'application/json'); + if (mode !== 'accept') { + response.statusCode = mode === 'denied' ? 403 : 503; + response.end(JSON.stringify({ status: response.statusCode, code: mode === 'denied' ? 'diagnostics_access_denied' : 'diagnostics_unavailable', title: 'Original diagnostic read failure.' })); return; + } + const detail = new URL(request.url ?? '', 'http://isolated.test').searchParams.get('diagnostics'); + const { protectedPayload: _protected, ...metadata } = event; + response.end(JSON.stringify({ data: detail === 'full' ? page : { ...page, items: [metadata] } })); + }); + }); + try { + await new Promise(accept => server.listen(0, '127.0.0.1', accept)); + const address = server.address(); assert.ok(address && typeof address !== 'string'); const url = `http://127.0.0.1:${address.port}`; + const env: NodeJS.ProcessEnv = { ...process.env, TREESEED_CONFIG_HOME: root, TREESEED_API_BASE_URL: url }; + delete env.NODE_OPTIONS; delete env.NODE_TEST_CONTEXT; + await saveServerSession({ identity: { issuer: 'https://isolated.example.test', subject: 'reader' }, clientId: 'trsd', + scopes: ['treeseed:read'], serverId: 'local', audience: url, accessToken: 'isolated-fixture-token' }, env); + const execute = async (options: string[]) => { + const command = commandSpecs.filter(value => value.execution.kind === 'operation' && value.execution.operationId === 'workdays.events.list'); + assert.equal(command.length, 1); + const argv = [...command[0]!.path, runId, '--team', teamId, '--cursor', cursor, '--limit', '50', ...options, '--server', 'local', '--json']; + const before = structuredClone(argv); + child = spawn(process.execPath, ['--import', loader, '--import', custody, entrypoint, ...argv], { cwd: packageRoot, env, signal: context.signal, stdio: ['ignore', 'pipe', 'pipe'] }); + let stdout = '', stderr = ''; child.stdout!.on('data', bytes => { stdout += String(bytes); }); child.stderr!.on('data', bytes => { stderr += String(bytes); }); + const code = await new Promise((accept, reject) => { child!.once('error', reject); child!.once('close', accept); }); + assert.deepEqual(argv, before); assert.equal(child.signalCode, null); + const text = (code === 0 ? stdout : stderr).trim(); assert.ok(text, JSON.stringify({ code, stdout, stderr })); + assert.equal((code === 0 ? stderr : stdout).trim(), ''); + return { code, envelope: JSON.parse(text) }; + }; + for (const detail of [undefined, 'metadata', 'full']) { + const start = requests.length, result = await execute(detail === undefined ? [] : ['--diagnostics', detail]); + assert.equal(result.code, 0); assert.equal(result.envelope.ok, true); assert.deepEqual(result.envelope.warnings, []); + const { protectedPayload: _protected, ...metadata } = event; + assert.deepEqual(result.envelope.result, detail === 'full' ? page : { ...page, items: [metadata] }); + assert.equal(requests.length, start + 1); const requested = new URL(requests.at(-1)!.url, url); + assert.equal(requested.pathname, `/v1/teams/${teamId}/workday-runs/${runId}/events`); + assert.equal(requested.searchParams.get('diagnostics'), detail ?? null); assert.equal(requested.searchParams.get('cursor'), cursor); + assert.equal(requested.searchParams.get('limit'), '50'); assert.equal(requests.at(-1)!.method, 'GET'); assert.equal(requests.at(-1)!.body, ''); + } + for (const failure of ['denied', 'unavailable'] as const) { + mode = failure; const start = requests.length, failed = await execute(['--diagnostics', 'full']); + assert.equal(failed.code, 1); assert.equal(failed.envelope.ok, false); assert.equal(failed.envelope.result, null); + assert.equal(failed.envelope.error.code, failure === 'denied' ? 'diagnostics_access_denied' : 'diagnostics_unavailable'); + assert.deepEqual(failed.envelope.warnings, []); assert.equal(requests.length, start + 1); const deniedRequest = structuredClone(requests.at(-1)!); + mode = 'accept'; const retried = await execute(['--diagnostics', 'full']); + assert.equal(retried.code, 0); assert.deepEqual(retried.envelope.result, page); assert.equal(requests.length, start + 2); + assert.deepEqual(requests.at(-1), deniedRequest); assert.deepEqual(requests[start], deniedRequest); + } + const start = requests.length, malformed = await execute(['--diagnostics']); + assert.equal(malformed.code, 1); assert.equal(malformed.envelope.ok, false); assert.equal(malformed.envelope.result, null); + assert.equal(malformed.envelope.error.category, 'invalid_input'); assert.equal(requests.length, start); + assert.deepEqual(page, held); assert.deepEqual(readFileSync(entrypoint), entryBytes); assert.deepEqual(readFileSync(resolve(packageRoot, 'package.json')), packageBytes); + } finally { + if (child && child.exitCode === null && child.signalCode === null) { child.kill(); await new Promise(accept => child!.once('close', () => accept())); } + server.closeAllConnections(); await new Promise((accept, reject) => server.close(error => error ? reject(error) : accept())); + rmSync(root, { recursive: true, force: true }); assert.equal(server.listening, false); assert.equal(existsSync(root), false); + } +}); + +test('retrieves a later exact event page through independent native CLI and real HTTP transport', { timeout: 30_000 }, async context => { + const root = mkdtempSync(resolve(tmpdir(), 'treeseed-cli-event-observation-')); + const teamId = '11111111-1111-4111-8111-111111111111', runId = 'workday-fixture'; + const cursor = encodeCapacityPageCursor({ id: 'event-049', createdAt: '2026-10-02T21:00:00Z' }); + const requests: string[] = []; + // Isolated response input, not an authenticated production API or genuine event receipt. + const result = { items: [{ id: 'event-050', runId, teamId, eventIndex: 50, eventType: 'assignment.failed', + status: 'failed', createdAt: '2026-10-02T21:00:01Z' }], page: { limit: 50, hasMore: false, nextCursor: null } }; + const server = createServer((request, response) => { + requests.push(request.url ?? ''); response.writeHead(200, { 'content-type': 'application/json' }); + response.end(JSON.stringify({ data: result })); + }); + let child: ReturnType | undefined; + try { + await new Promise(resolve => server.listen(0, '127.0.0.1', resolve)); + const address = server.address(); assert.ok(address && typeof address !== 'string'); + const url = `http://127.0.0.1:${address.port}`; + const env: NodeJS.ProcessEnv = { ...process.env, TREESEED_CONFIG_HOME: root, TREESEED_API_BASE_URL: url, TSX_DISABLE_CACHE: '1' }; + delete env.NODE_OPTIONS; delete env.NODE_TEST_CONTEXT; + await saveServerSession({ identity: { issuer: 'https://isolated.example.test', subject: 'reader' }, clientId: 'trsd', + scopes: ['treeseed:read'], serverId: 'local', audience: url, accessToken: 'isolated-fixture-token' }, env); + const bound = commandSpecs.find(command => command.execution.kind === 'operation' && command.execution.operationId === 'workdays.events.list'); + assert.ok(bound, 'The existing public event command must be bound.'); + const manifest = JSON.parse(readFileSync(resolve(packageRoot, 'package.json'), 'utf8')); + assert.equal(manifest.bin.trsd, './dist/cli/main.js'); const entrypoint = resolve(packageRoot, manifest.bin.trsd), bytes = readFileSync(entrypoint); + child = spawn(process.execPath, ['--import', loader, '--import', custody, entrypoint, ...bound.path, runId, + '--team', teamId, '--cursor', cursor, '--limit', '50', '--json'], { cwd: packageRoot, env, signal: context.signal, stdio: ['ignore', 'pipe', 'pipe'] }); + let stdout = '', stderr = ''; + child.stdout!.on('data', chunk => { stdout += String(chunk); }); child.stderr!.on('data', chunk => { stderr += String(chunk); }); + const code = await new Promise((resolve, reject) => { child!.once('error', reject); child!.once('close', resolve); }); + assert.equal(code, 0, JSON.stringify({ requests, stdout, stderr })); + assert.equal(requests.length, 1); + const requested = new URL(requests[0]!, url); + assert.equal(requested.pathname, `/v1/teams/${teamId}/workday-runs/${runId}/events`); + assert.equal(requested.searchParams.get('cursor'), cursor); assert.equal(requested.searchParams.get('limit'), '50'); + assert.deepEqual(JSON.parse(stdout).result, result); assert.equal(stderr, ''); + assert.deepEqual(readFileSync(entrypoint), bytes); + } finally { + if (child && child.exitCode === null && child.signalCode === null) { + child.kill(); await new Promise(resolve => child!.once('close', () => resolve())); + } + await new Promise((resolve, reject) => server.close(error => error ? reject(error) : resolve())); + rmSync(root, { recursive: true, force: true }); + } +}); diff --git a/tests/contract/package/installed-assets.test.ts b/tests/contract/package/installed-assets.test.ts new file mode 100644 index 00000000..598b9abf --- /dev/null +++ b/tests/contract/package/installed-assets.test.ts @@ -0,0 +1,68 @@ +import assert from 'node:assert/strict'; +import { execFile } from 'node:child_process'; +import { createHash } from 'node:crypto'; +import { existsSync, lstatSync, mkdtempSync, readFileSync, realpathSync, rmSync, writeFileSync } from 'node:fs'; +import { tmpdir } from 'node:os'; +import { resolve } from 'node:path'; +import test from 'node:test'; +import { promisify } from 'node:util'; +import ts from 'typescript'; + +const assets = ['treeseed.package.yaml', 'guarantees/verifiers/golden.verifiers.yaml', + 'tests/acceptance/workday-events.test.ts', 'tests/support/os-custody.ts']; +type Packed = { filename: string; integrity: string; files: Array<{ path: string }> }; +const execute = async (command: string, args: string[], cwd = process.cwd()) => + (await promisify(execFile)(command, args, { cwd, encoding: 'utf8', maxBuffer: 8 * 1024 * 1024 })).stdout; + +test('ships the selected CLI native observation assets without checkout source execution or private imports', async () => { + const [packed] = JSON.parse(await execute('npm', ['pack', '--dry-run', '--ignore-scripts', '--json'])) as Packed[]; + assert.ok(packed); const paths = new Set(packed.files.map(file => file.path)); + assert.deepEqual(assets.filter(path => !paths.has(path)), []); + const source = ts.createSourceFile(assets[2]!, readFileSync(assets[2]!, 'utf8'), ts.ScriptTarget.Latest, true); + const privatePaths: string[] = []; + const visit = (node: ts.Node) => { + if (ts.isStringLiteral(node) && /(?:^|\/)src\//u.test(node.text)) privatePaths.push(node.text); + ts.forEachChild(node, visit); + }; + visit(source); assert.deepEqual(privatePaths, []); + assert.equal(existsSync('tests/support/os-custody.mjs'), false); +}); + +test('native production CLI archive retains exact observation assets and executes its public binary without source or development dependencies', { timeout: 30_000 }, async () => { + const root = mkdtempSync(resolve(tmpdir(), 'cli-installed-assets-')); + try { + const packed: Packed[] = []; + for (const owner of ['./node_modules/@treeseed/sdk', './node_modules/@treeseed/identity', '.']) { + const [archive] = JSON.parse(await execute('npm', ['pack', owner, '--ignore-scripts', '--json', '--pack-destination', root])) as Packed[]; + assert.ok(archive); packed.push(archive); + assert.equal(`sha512-${createHash('sha512').update(readFileSync(resolve(root, archive.filename))).digest('base64')}`, archive.integrity); + } + const names = ['@treeseed/sdk', '@treeseed/identity', '@treeseed/cli']; + const dependencies = Object.fromEntries(packed.map((archive, index) => [names[index]!, `file:${resolve(root, archive.filename)}`])); + writeFileSync(resolve(root, 'package.json'), JSON.stringify({ private: true, type: 'module', dependencies, + overrides: { '@treeseed/sdk': '$@treeseed/sdk', '@treeseed/identity': '$@treeseed/identity' } })); + await execute('npm', ['install', '--prefix', root, '--omit=dev', '--ignore-scripts', '--package-lock=false', '--no-save', '--no-audit', '--no-fund', + ...packed.map(archive => resolve(root, archive.filename))], root); + await execute('npm', ['ls', '--all', '--omit=dev', '--json'], root); + const installed = resolve(root, 'node_modules/@treeseed/cli'); + assert.equal(realpathSync(installed), installed); assert.equal(lstatSync(installed).isSymbolicLink(), false); + for (const path of ['src', 'node_modules/@treeseed/sdk', 'node_modules/@treeseed/identity']) assert.equal(existsSync(resolve(installed, path)), false, path); + for (const dependency of ['tsx', 'vitest', '@treeseed/deployment', '@treeseed/ui']) assert.equal(existsSync(resolve(root, 'node_modules', dependency)), false, dependency); + for (const path of assets) assert.deepEqual(readFileSync(resolve(installed, path)), readFileSync(path), path); + const manifest = JSON.parse(readFileSync(resolve(installed, 'package.json'), 'utf8')); + assert.equal(manifest.bin.trsd, './dist/cli/main.js'); const binary = resolve(installed, manifest.bin.trsd), bytes = readFileSync(binary); + const env: NodeJS.ProcessEnv = { ...process.env, TREESEED_CONFIG_HOME: resolve(root, 'config') }; delete env.NODE_OPTIONS; delete env.NODE_TEST_CONTEXT; + const result = await promisify(execFile)(process.execPath, [binary, '--help'], { cwd: root, env, encoding: 'utf8' }); + assert.equal(result.stderr, ''); assert.match(result.stdout, /trsd/u); assert.deepEqual(readFileSync(binary), bytes); + for (const archive of packed) assert.equal(`sha512-${createHash('sha512').update(readFileSync(resolve(root, archive.filename))).digest('base64')}`, archive.integrity); + console.log(JSON.stringify({ archives: packed.map(archive => ({ filename: archive.filename, + sha256: createHash('sha256').update(readFileSync(resolve(root, archive.filename))).digest('hex') })), installedPublicBinary: 'passed' })); + } finally { rmSync(root, { recursive: true, force: true }); assert.equal(existsSync(root), false); } +}); + +test('native workday event cases never execute checkout source or substitute an unbound command', () => { + const selected = existsSync(assets[2]!) ? assets[2]! : 'tests/unit/command-boundary/observation/workday-events.test.ts'; + const source = readFileSync(selected, 'utf8'); + assert.doesNotMatch(source, /['"]src\/cli\/main\.ts['"]/u); + assert.doesNotMatch(source, /bound\?\.path\s*\?\?/u); +}); diff --git a/tests/contract/package/thin-package.test.ts b/tests/contract/package/thin-package.test.ts index e4c759ad..d3d6b699 100644 --- a/tests/contract/package/thin-package.test.ts +++ b/tests/contract/package/thin-package.test.ts @@ -189,6 +189,11 @@ test('guarantee metadata binds owner tests without adding a second CLI implement 'cli.golden.reporting-unit': {testFile:'tests/unit/native-suite-reporting.test.ts',testName:'native reporting accepts only a complete nonempty reporting pair without test selection'}, 'cli.golden.component-scene-os-boundary': {testFile:'tests/unit/native-suite-reporting.test.ts',testName:'component scene case execution inherits the same declared test-only OS boundary as complete suites without changing runtime or host acceptance'}, }; + reporting['cli.golden.installed-assets-unit'] = {testFile:'tests/contract/package/installed-assets.test.ts',testName:'ships the selected CLI native observation assets without checkout source execution or private imports'}; + reporting['cli.golden.installed-assets-native'] = {testFile:'tests/contract/package/installed-assets.test.ts',testName:'native production CLI archive retains exact observation assets and executes its public binary without source or development dependencies'}; + reporting['cli.golden.installed-event-command'] = {testFile:'tests/contract/package/installed-assets.test.ts',testName:'native workday event cases never execute checkout source or substitute an unbound command'}; + reporting['cli.golden.execution-diagnostics-read-native'] = {testFile:'tests/acceptance/workday-events.test.ts',testName:'packaged native workday diagnostic readback preserves exact clock bytes and denied history through unchanged retry without execution requests'}; + reporting['cli.golden.architecture-workday-event-native'] = {testFile:'tests/acceptance/workday-events.test.ts',testName:'retrieves a later exact event page through independent native CLI and real HTTP transport'}; const observedReporting = new Set(); const files = readdirSync('guarantees', { recursive: true, withFileTypes: true }).filter(entry => entry.isFile()); assert.equal(files.length, 3); diff --git a/tests/integration/native-suite-reporting.test.ts b/tests/integration/native-suite-reporting.test.ts index b21f06d5..f476adc1 100644 --- a/tests/integration/native-suite-reporting.test.ts +++ b/tests/integration/native-suite-reporting.test.ts @@ -15,7 +15,7 @@ function fixture() { symlinkSync(resolve(import.meta.dirname,'../../node_modules'),resolve(root,'node_modules')); writeFileSync(resolve(root,'package.json'),JSON.stringify({type:'module',scripts:{test:`node --import tsx build.ts && node --import tsx ${runner}`}})); writeFileSync(resolve(root,'build.ts'),"import {writeFileSync} from 'node:fs'; writeFileSync('built','yes');"); - writeFileSync(resolve(root,'tests/support/os-custody.mjs'),"globalThis.custodyLoaded=true;"); + writeFileSync(resolve(root,'tests/support/os-custody.ts'),"globalThis.custodyLoaded=true;"); writeFileSync(resolve(root,'tests/unit.test.ts'),"import test from 'node:test'; import assert from 'node:assert/strict'; import {appendFileSync,existsSync} from 'node:fs'; test('unit boundary',()=>{assert.equal(existsSync('built'),true); assert.equal(globalThis.custodyLoaded,true); appendFileSync('order','unit\\n');});"); writeFileSync(resolve(root,'outside/child.ts'),"import test from 'node:test'; test('child boundary',()=>{});"); writeFileSync(resolve(root,'tests/nested/integration.test.ts'),"import {suite,test} from 'node:test'; import assert from 'node:assert/strict'; import {appendFileSync} from 'node:fs'; import {spawnSync} from 'node:child_process'; suite('integration suite',()=>{test('integration boundary',()=>{const env={...process.env}; delete env.NODE_TEST_CONTEXT; const child=spawnSync(process.execPath,['--import','tsx','--test','outside/child.ts'],{encoding:'utf8',env}); assert.equal(child.status,0); assert.match(child.stdout,/child boundary/); appendFileSync('order','integration\\n');});});"); diff --git a/tests/support/os-custody.mjs b/tests/support/os-custody.ts similarity index 64% rename from tests/support/os-custody.mjs rename to tests/support/os-custody.ts index 2b7d0fe2..74ec8011 100644 --- a/tests/support/os-custody.mjs +++ b/tests/support/os-custody.ts @@ -1,12 +1,14 @@ // Unit-test OS boundary. Real systemd user sealing is accepted separately on the supported host. -import childProcess from 'node:child_process'; +import childProcess, { type ExecFileSyncOptions } from 'node:child_process'; import { syncBuiltinESMExports } from 'node:module'; import { createCipheriv, createDecipheriv, randomBytes, createHash } from 'node:crypto'; const actual=childProcess.execFileSync; const key=createHash('sha256').update('synthetic-unit-test-os-boundary').digest(); -childProcess.execFileSync=function(file,args,options){ - if(file!=='/usr/bin/systemd-creds')return actual.call(this,file,args,options); - const input=Buffer.from(options.input); +childProcess.execFileSync=((file: string, args: readonly string[], options: ExecFileSyncOptions) => { + if(file!=='/usr/bin/systemd-creds')return actual(file,[...args],options); + const raw=options.input; + if(raw===undefined)throw new TypeError('OS credential test input is required'); + const input=typeof raw==='string'?Buffer.from(raw):Buffer.from(raw.buffer,raw.byteOffset,raw.byteLength); if(args[0]==='encrypt'){ const iv=randomBytes(12),cipher=createCipheriv('aes-256-gcm',key,iv); const bytes=Buffer.concat([cipher.update(input),cipher.final()]); @@ -17,5 +19,5 @@ childProcess.execFileSync=function(file,args,options){ return Buffer.concat([cipher.update(input.subarray(28)),cipher.final()]); } throw new Error('Unexpected OS credential test operation'); -}; +}) as typeof actual; syncBuiltinESMExports(); diff --git a/tests/unit/command-boundary/observation/workday-events.test.ts b/tests/unit/command-boundary/observation/workday-events.test.ts index 8de3bbb1..031f3ccf 100644 --- a/tests/unit/command-boundary/observation/workday-events.test.ts +++ b/tests/unit/command-boundary/observation/workday-events.test.ts @@ -1,15 +1,8 @@ import assert from 'node:assert/strict'; -import { spawn } from 'node:child_process'; -import { existsSync, mkdtempSync, readFileSync, rmSync } from 'node:fs'; -import { createServer } from 'node:http'; -import { tmpdir } from 'node:os'; -import { resolve } from 'node:path'; import test from 'node:test'; -import { encodeCapacityPageCursor } from '@treeseed/sdk/capacity-pagination'; import { commandSpecs } from '../../../../src/cli/registry.ts'; import { parseInvocation } from '../../../../src/cli/parser.ts'; import { runCommandLine } from '../../../../src/cli/runtime.ts'; -import { saveServerSession } from '../../../../src/cli/support/server-custody.ts'; test('requires one generated read command for exact workday events with cursor and page limit', () => { const commands = commandSpecs.filter(command => command.execution.kind === 'operation' @@ -58,127 +51,3 @@ test('binds optional workday diagnostic detail to the sole generated read operat assert.equal(error.ok, false); assert.equal(error.result, null); assert.equal(error.error.category, 'invalid_input'); assert.deepEqual(error.warnings, []); assert.deepEqual(argv, before); assert.deepEqual(commandSpecs, held); }); - -test('packaged native workday diagnostic readback preserves exact clock bytes and denied history through unchanged retry without execution requests', { timeout: 30_000 }, async context => { - const packageBytes = readFileSync(resolve('package.json')), manifest = JSON.parse(packageBytes.toString('utf8')); - assert.equal(manifest.bin.trsd, './dist/cli/main.js'); const entrypoint = resolve(manifest.bin.trsd), entryBytes = readFileSync(entrypoint); - const root = mkdtempSync(resolve(tmpdir(), 'treeseed-cli-clock-diagnostics-')); - const teamId = '11111111-1111-4111-8111-111111111111', runId = 'workday-fixture'; - const cursor = encodeCapacityPageCursor({ id: 'event-049', createdAt: '2026-10-07T12:00:00.000Z' }); - // Controlled raw diagnostic bytes, not native model clocks, API authorization or provider charges. - const clock = { observedAt: '2026-10-07T12:00:01.250Z', startedAt: '2026-10-07T12:00:00.000Z', - endsAt: '2026-10-07T12:01:00.000Z', remainingSeconds: 59 }; - const event = { id: 'event-050', runId, teamId, assignmentId: 'assignment-fixture', eventIndex: 50, - eventType: 'provider.execution.completed', status: 'completed', createdAt: '2026-10-07T12:00:02.000Z', - payload: { protection: { protected: true } }, protectedPayload: { providerEvents: [ - { type: 'model.tool.result', callId: 'clock-original', tool: 'provider.assignment.clock', output: JSON.stringify(clock) }, - ] } }; - const page = { items: [event], page: { limit: 50, hasMore: false, nextCursor: null } }, held = structuredClone(page); - const requests: Array<{ method: string | undefined; url: string; body: string }> = []; - let mode: 'accept' | 'denied' | 'unavailable' = 'accept', child: ReturnType | undefined; - const server = createServer((request, response) => { - let body = ''; request.setEncoding('utf8'); request.on('data', value => { body += String(value); }); - request.on('end', () => { - requests.push({ method: request.method, url: request.url ?? '', body }); - response.setHeader('content-type', 'application/json'); - if (mode !== 'accept') { - response.statusCode = mode === 'denied' ? 403 : 503; - response.end(JSON.stringify({ status: response.statusCode, code: mode === 'denied' ? 'diagnostics_access_denied' : 'diagnostics_unavailable', title: 'Original diagnostic read failure.' })); return; - } - const detail = new URL(request.url ?? '', 'http://isolated.test').searchParams.get('diagnostics'); - const { protectedPayload: _protected, ...metadata } = event; - response.end(JSON.stringify({ data: detail === 'full' ? page : { ...page, items: [metadata] } })); - }); - }); - try { - await new Promise(accept => server.listen(0, '127.0.0.1', accept)); - const address = server.address(); assert.ok(address && typeof address !== 'string'); const url = `http://127.0.0.1:${address.port}`; - const env = { ...process.env, TREESEED_CONFIG_HOME: root, TREESEED_API_BASE_URL: url }; - await saveServerSession({ identity: { issuer: 'https://isolated.example.test', subject: 'reader' }, clientId: 'trsd', - scopes: ['treeseed:read'], serverId: 'local', audience: url, accessToken: 'isolated-fixture-token' }, env); - const execute = async (options: string[]) => { - const command = commandSpecs.filter(value => value.execution.kind === 'operation' && value.execution.operationId === 'workdays.events.list'); - assert.equal(command.length, 1); - const argv = [...command[0]!.path, runId, '--team', teamId, '--cursor', cursor, '--limit', '50', ...options, '--server', 'local', '--json']; - const before = structuredClone(argv); - child = spawn(process.execPath, [entrypoint, ...argv], { cwd: process.cwd(), env, signal: context.signal, stdio: ['ignore', 'pipe', 'pipe'] }); - let stdout = '', stderr = ''; child.stdout!.on('data', bytes => { stdout += String(bytes); }); child.stderr!.on('data', bytes => { stderr += String(bytes); }); - const code = await new Promise((accept, reject) => { child!.once('error', reject); child!.once('close', accept); }); - assert.deepEqual(argv, before); assert.equal(child.signalCode, null); - const text = (code === 0 ? stdout : stderr).trim(); assert.ok(text, JSON.stringify({ code, stdout, stderr })); - assert.equal((code === 0 ? stderr : stdout).trim(), ''); - return { code, envelope: JSON.parse(text) }; - }; - for (const detail of [undefined, 'metadata', 'full']) { - const start = requests.length, result = await execute(detail === undefined ? [] : ['--diagnostics', detail]); - assert.equal(result.code, 0); assert.equal(result.envelope.ok, true); assert.deepEqual(result.envelope.warnings, []); - const { protectedPayload: _protected, ...metadata } = event; - assert.deepEqual(result.envelope.result, detail === 'full' ? page : { ...page, items: [metadata] }); - assert.equal(requests.length, start + 1); const requested = new URL(requests.at(-1)!.url, url); - assert.equal(requested.pathname, `/v1/teams/${teamId}/workday-runs/${runId}/events`); - assert.equal(requested.searchParams.get('diagnostics'), detail ?? null); assert.equal(requested.searchParams.get('cursor'), cursor); - assert.equal(requested.searchParams.get('limit'), '50'); assert.equal(requests.at(-1)!.method, 'GET'); assert.equal(requests.at(-1)!.body, ''); - } - for (const failure of ['denied', 'unavailable'] as const) { - mode = failure; const start = requests.length, failed = await execute(['--diagnostics', 'full']); - assert.equal(failed.code, 1); assert.equal(failed.envelope.ok, false); assert.equal(failed.envelope.result, null); - assert.equal(failed.envelope.error.code, failure === 'denied' ? 'diagnostics_access_denied' : 'diagnostics_unavailable'); - assert.deepEqual(failed.envelope.warnings, []); assert.equal(requests.length, start + 1); const deniedRequest = structuredClone(requests.at(-1)!); - mode = 'accept'; const retried = await execute(['--diagnostics', 'full']); - assert.equal(retried.code, 0); assert.deepEqual(retried.envelope.result, page); assert.equal(requests.length, start + 2); - assert.deepEqual(requests.at(-1), deniedRequest); assert.deepEqual(requests[start], deniedRequest); - } - const start = requests.length, malformed = await execute(['--diagnostics']); - assert.equal(malformed.code, 1); assert.equal(malformed.envelope.ok, false); assert.equal(malformed.envelope.result, null); - assert.equal(malformed.envelope.error.category, 'invalid_input'); assert.equal(requests.length, start); - assert.deepEqual(page, held); assert.deepEqual(readFileSync(entrypoint), entryBytes); assert.deepEqual(readFileSync(resolve('package.json')), packageBytes); - } finally { - if (child && child.exitCode === null && child.signalCode === null) { child.kill(); await new Promise(accept => child!.once('close', () => accept())); } - server.closeAllConnections(); await new Promise((accept, reject) => server.close(error => error ? reject(error) : accept())); - rmSync(root, { recursive: true, force: true }); assert.equal(server.listening, false); assert.equal(existsSync(root), false); - } -}); - -test('retrieves a later exact event page through independent native CLI and real HTTP transport', { timeout: 30_000 }, async () => { - const root = mkdtempSync(resolve(tmpdir(), 'treeseed-cli-event-observation-')); - const teamId = '11111111-1111-4111-8111-111111111111', runId = 'workday-fixture'; - const cursor = encodeCapacityPageCursor({ id: 'event-049', createdAt: '2026-10-02T21:00:00Z' }); - const requests: string[] = []; - // Isolated response input, not an authenticated production API or genuine event receipt. - const result = { items: [{ id: 'event-050', runId, teamId, eventIndex: 50, eventType: 'assignment.failed', - status: 'failed', createdAt: '2026-10-02T21:00:01Z' }], page: { limit: 50, hasMore: false, nextCursor: null } }; - const server = createServer((request, response) => { - requests.push(request.url ?? ''); response.writeHead(200, { 'content-type': 'application/json' }); - response.end(JSON.stringify({ data: result })); - }); - let child: ReturnType | undefined; - try { - await new Promise(resolve => server.listen(0, '127.0.0.1', resolve)); - const address = server.address(); assert.ok(address && typeof address !== 'string'); - const url = `http://127.0.0.1:${address.port}`; - const env = { ...process.env, TREESEED_CONFIG_HOME: root, TREESEED_API_BASE_URL: url, TSX_DISABLE_CACHE: '1' }; - await saveServerSession({ identity: { issuer: 'https://isolated.example.test', subject: 'reader' }, clientId: 'trsd', - scopes: ['treeseed:read'], serverId: 'local', audience: url, accessToken: 'isolated-fixture-token' }, env); - const bound = commandSpecs.find(command => command.execution.kind === 'operation' && command.execution.operationId === 'workdays.events.list'); - // Do not prescribe a new command name. Exercise a future bound catalog route; - // until it exists, the current observation leaf itself must not count as proof. - const path = bound?.path ?? ['workdays', 'watch']; - child = spawn(process.execPath, ['--import', 'tsx', 'src/cli/main.ts', ...path, runId, - '--team', teamId, '--cursor', cursor, '--limit', '50', '--json'], { cwd: process.cwd(), env, stdio: ['ignore', 'pipe', 'pipe'] }); - let stdout = '', stderr = ''; - child.stdout!.on('data', chunk => { stdout += String(chunk); }); child.stderr!.on('data', chunk => { stderr += String(chunk); }); - const code = await new Promise((resolve, reject) => { child!.once('error', reject); child!.once('close', resolve); }); - assert.equal(code, 0, JSON.stringify({ requests, stdout, stderr })); - assert.equal(requests.length, 1); - const requested = new URL(requests[0]!, url); - assert.equal(requested.pathname, `/v1/teams/${teamId}/workday-runs/${runId}/events`); - assert.equal(requested.searchParams.get('cursor'), cursor); assert.equal(requested.searchParams.get('limit'), '50'); - assert.deepEqual(JSON.parse(stdout).result, result); - } finally { - if (child && child.exitCode === null && child.signalCode === null) { - child.kill(); await new Promise(resolve => child!.once('close', () => resolve())); - } - await new Promise((resolve, reject) => server.close(error => error ? reject(error) : resolve())); - rmSync(root, { recursive: true, force: true }); - } -}); diff --git a/tests/unit/native-suite-reporting.test.ts b/tests/unit/native-suite-reporting.test.ts index ca091e81..d60cc720 100644 --- a/tests/unit/native-suite-reporting.test.ts +++ b/tests/unit/native-suite-reporting.test.ts @@ -10,9 +10,9 @@ test('component scene case execution inherits the same declared test-only OS bou const scenes = job.steps.filter((step: { uses?: string }) => step.uses?.includes('reviewer/.github/actions/run-scenes@')); assert.equal(scenes.length, 1); assert.equal(scenes[0].with.ids, 'guarantee.cli.golden.component-boundaries'); - assert.equal(scenes[0].env?.NODE_OPTIONS, '--import=${{ github.workspace }}/tests/support/os-custody.mjs'); + assert.equal(scenes[0].env?.NODE_OPTIONS, '--import=${{ github.workspace }}/tests/support/os-custody.ts'); assert.equal(Object.hasOwn(job.env, 'NODE_OPTIONS'), false); - assert.match(readFileSync('scripts/testing/run-tests.ts', 'utf8'), /tests\/support\/os-custody\.mjs/u); + assert.match(readFileSync('scripts/testing/run-tests.ts', 'utf8'), /tests\/support\/os-custody\.ts/u); }); test('native reporting accepts only a complete nonempty reporting pair without test selection',()=>{