From 4fda01356f5a54358762bb49d83eb16f1068f328 Mon Sep 17 00:00:00 2001 From: Eve Date: Thu, 23 Apr 2026 08:33:54 +0800 Subject: [PATCH] test: add long-task governor wrapper fixture runner --- scripts/test_long_task_governor_wrapper.mjs | 102 ++++++++++++++++++++ 1 file changed, 102 insertions(+) create mode 100644 scripts/test_long_task_governor_wrapper.mjs diff --git a/scripts/test_long_task_governor_wrapper.mjs b/scripts/test_long_task_governor_wrapper.mjs new file mode 100644 index 0000000..8568456 --- /dev/null +++ b/scripts/test_long_task_governor_wrapper.mjs @@ -0,0 +1,102 @@ +#!/usr/bin/env node +import assert from 'node:assert/strict'; +import { execFileSync } from 'node:child_process'; +import path from 'node:path'; +import { fileURLToPath } from 'node:url'; + +const __filename = fileURLToPath(import.meta.url); +const __dirname = path.dirname(__filename); +const repoRoot = path.resolve(__dirname, '..'); +const wrapperPath = path.join(repoRoot, 'scripts', 'long_task_governor_wrapper.mjs'); + +const fixtures = [ + { + name: 'example', + file: path.join(repoRoot, 'docs', '_artifacts', 'long_task_governor_wrapper_example.json'), + assert(output) { + assert.equal(output.classification, 'long_task'); + }, + }, + { + name: 'invalid silent', + file: path.join(repoRoot, 'docs', '_artifacts', 'long_task_governor_wrapper_invalid_silent_example.json'), + assert(output) { + assert.equal(output.silentLaunchOk, false); + }, + }, + { + name: 'general chat', + file: path.join(repoRoot, 'docs', '_artifacts', 'long_task_governor_wrapper_general_chat_example.json'), + assert(output) { + assert.equal(output.classification, 'general_chat'); + }, + }, + { + name: 'non-silent long task', + file: path.join(repoRoot, 'docs', '_artifacts', 'long_task_governor_wrapper_non_silent_long_task_example.json'), + assert(output) { + assert.equal(output.classification, 'long_task'); + assert.equal(output.silentCandidate, false); + }, + }, + { + name: 'owner decision', + file: path.join(repoRoot, 'docs', '_artifacts', 'long_task_governor_wrapper_silent_owner_decision_example.json'), + assert(output) { + assert.equal(output.handoff.mode, 'button_path'); + }, + }, + { + name: 'subagent wait', + file: path.join(repoRoot, 'docs', '_artifacts', 'long_task_governor_wrapper_subagent_wait_example.json'), + assert(output) { + assert.equal(output.silentCandidate, true); + }, + }, +]; + +function runFixture(fixture) { + const stdout = execFileSync(process.execPath, [wrapperPath, '--compact', '--input', fixture.file], { + cwd: repoRoot, + encoding: 'utf8', + }); + + let output; + try { + output = JSON.parse(stdout); + } catch (error) { + throw new Error(`Fixture \"${fixture.name}\" did not produce valid JSON: ${error.message}\nOutput: ${stdout}`); + } + + assert.ok(output.classification !== undefined, `${fixture.name}: missing classification`); + assert.ok(output.silentCandidate !== undefined, `${fixture.name}: missing silentCandidate`); + assert.ok(output.silentLaunchOk !== undefined, `${fixture.name}: missing silentLaunchOk`); + assert.ok(output.requiredNextAction !== undefined, `${fixture.name}: missing requiredNextAction`); + assert.ok(output.handoff && output.handoff.mode !== undefined, `${fixture.name}: missing handoff.mode`); + + fixture.assert(output); + + return { + name: fixture.name, + output, + }; +} + +function main() { + const results = fixtures.map(runFixture); + const summary = { + passed: results.length, + fixtures: results.map(({ name, output }) => ({ + name, + classification: output.classification, + silentCandidate: output.silentCandidate, + silentLaunchOk: output.silentLaunchOk, + requiredNextAction: output.requiredNextAction, + handoffMode: output.handoff.mode, + })), + }; + + process.stdout.write(JSON.stringify(summary, null, 2) + '\n'); +} + +main();