Skip to content
Merged
Show file tree
Hide file tree
Changes from all commits
Commits
File filter

Filter by extension

Filter by extension

Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
3 changes: 3 additions & 0 deletions CHANGELOG.md
Original file line number Diff line number Diff line change
Expand Up @@ -13,6 +13,9 @@ project adheres to [Semantic Versioning](https://semver.org/).
- Playwright setup note in the Quick start section of `README.md`.

### Fixed
- The integrator example now removes its scratch directory when decide fails
or policy refuses the response. `process.exit` skipped the cleanup, so each
failed run left an `aas-integrator-` directory behind.
- `aas inspect --root` now rejects a blank path, matching the other saved-case
commands. A whitespace root used to be treated as a directory and failed
with a filesystem error.
Expand Down
21 changes: 18 additions & 3 deletions examples/review-handoff.mjs
Original file line number Diff line number Diff line change
Expand Up @@ -45,9 +45,16 @@ const DOMAIN_FIXTURES = {
},
};

class HandoffExit extends Error {
constructor(code) {
super("handoff exit");
this.exitCode = code;
}
}

function fail(reason) {
process.stderr.write(`integrator example failed: ${reason}\n`);
process.exit(1);
throw new HandoffExit(1);
}

function parseArgs(argv) {
Expand Down Expand Up @@ -111,7 +118,7 @@ function main() {
const evaluation = readJson("decide", decided);
if (evaluation.passed !== true) {
note("decide: policy refused the response; act and prove are skipped (fail-closed)");
process.exit(1);
throw new HandoffExit(1);
}
note(`decide: policy ${evaluation.policy_id} passed (${evaluation.rule_results.length} rules)`);

Expand Down Expand Up @@ -218,4 +225,12 @@ function main() {
}
}

main();
try {
main();
} catch (error) {
if (error instanceof HandoffExit) {
process.exitCode = error.exitCode;
} else {
throw error;
}
}
27 changes: 27 additions & 0 deletions test/stack.test.mjs
Original file line number Diff line number Diff line change
Expand Up @@ -2075,6 +2075,33 @@ test('filtered case pages preserve scan bounds and continuation across nonmatche
for(const args of [['--domain','real'],['--outcome','paid'],['--search',''],['--search','x'.repeat(201)],['--domain','refund','--domain','inventory']]) assert.equal((await captureMain(['cases',...args,'--json'])).exitCode,2);
});

test("review handoff removes its scratch directory when decide cannot start", () => {
const dir = mkdtempSync(join(tmpdir(), "aas-handoff-scratch-"));
const preload = join(dir, "preload.cjs");
writeFileSync(preload, [
"if (typeof process.argv[1] === 'string' && process.argv[1].includes('sys.version_info')) {",
" process.stdout.write('3.13\\n');",
" process.exit(0);",
"}",
"",
].join("\n"));
const result = spawnSync(process.execPath, [join(ROOT, "examples/review-handoff.mjs"), "--response", "fail"], {
cwd: ROOT,
encoding: "utf8",
timeout: 15000,
env: {
...process.env,
TMPDIR: dir,
TMP: dir,
TEMP: dir,
AAS_PYTHON: process.execPath,
NODE_OPTIONS: `--require ${JSON.stringify(preload)}`,
},
});
assert.equal(result.status, 1, `${result.stderr}\n${result.stdout}`);
assert.deepEqual(readdirSync(dir).filter((name) => name.startsWith("aas-integrator-")), []);
});

test('review handoff example honors the explicit interpreter override', () => {
const child=spawnSync(process.execPath,[join(ROOT,'examples/review-handoff.mjs')],{cwd:ROOT,encoding:'utf8',timeout:5000,env:{...process.env,AAS_PYTHON:'aas-synthetic-missing-python'}});
assert.equal(child.status,1);assert.match(child.stderr,/AAS_PYTHON/);assert.match(child.stderr,/did not report a usable Python version/);
Expand Down
Loading