test: add force-recall long-task preflight smoke test
This commit is contained in:
70
scripts/test_force_recall_long_task_preflight.mjs
Normal file
70
scripts/test_force_recall_long_task_preflight.mjs
Normal file
@@ -0,0 +1,70 @@
|
||||
#!/usr/bin/env node
|
||||
import assert from 'node:assert/strict';
|
||||
import fs from 'node:fs/promises';
|
||||
import path from 'node:path';
|
||||
import { pathToFileURL } from 'node:url';
|
||||
import { stripTypeScriptTypes } from 'node:module';
|
||||
|
||||
const __dirname = path.dirname(new URL(import.meta.url).pathname);
|
||||
const repoRoot = path.resolve(__dirname, '..');
|
||||
const handlerPath = path.join(repoRoot, 'hooks', 'force-recall', 'handler.ts');
|
||||
const wrapperPath = path.join(repoRoot, 'scripts', 'long_task_governor_wrapper.mjs');
|
||||
|
||||
async function importTsModule(tsPath) {
|
||||
const source = await fs.readFile(tsPath, 'utf8');
|
||||
const jsSource = stripTypeScriptTypes(source, { mode: 'strip' });
|
||||
const dataUrl = `data:text/javascript;charset=utf-8,${encodeURIComponent(jsSource)}\n//# sourceURL=${encodeURIComponent(pathToFileURL(tsPath).href)}`;
|
||||
return import(dataUrl);
|
||||
}
|
||||
|
||||
async function main() {
|
||||
await fs.access(wrapperPath);
|
||||
const { default: forceRecall } = await importTsModule(handlerPath);
|
||||
assert.equal(typeof forceRecall, 'function', 'force-recall handler should export default function');
|
||||
|
||||
const requestText = [
|
||||
'Please inspect the workspace files and verify the hook injection path.',
|
||||
'I need you to review the behavior, choose the final accept/reject decision,',
|
||||
'and continue in background with a follow-up later.',
|
||||
].join(' ');
|
||||
|
||||
const event = {
|
||||
type: 'message',
|
||||
action: 'preprocessed',
|
||||
context: {
|
||||
workspaceDir: repoRoot,
|
||||
body: requestText,
|
||||
bodyForAgent: requestText,
|
||||
},
|
||||
};
|
||||
|
||||
await forceRecall(event);
|
||||
|
||||
const injected = event.context?.bodyForAgent;
|
||||
assert.equal(typeof injected, 'string', 'event.context.bodyForAgent should be a string after handler runs');
|
||||
|
||||
const expectedSnippets = [
|
||||
'[LONG_TASK_GOVERNOR_PREFLIGHT]',
|
||||
'classification=long_task',
|
||||
'silentLaunchOk=false',
|
||||
'handoff.mode=button_path',
|
||||
'HARD_GATE:',
|
||||
];
|
||||
|
||||
for (const snippet of expectedSnippets) {
|
||||
assert.match(injected, new RegExp(snippet.replace(/[.*+?^${}()|[\]\\]/g, '\\$&')), `missing snippet: ${snippet}`);
|
||||
}
|
||||
|
||||
const summary = {
|
||||
ok: true,
|
||||
checked: expectedSnippets,
|
||||
bodyPreview: injected.split('\n').slice(0, 20),
|
||||
};
|
||||
|
||||
process.stdout.write(JSON.stringify(summary, null, 2) + '\n');
|
||||
}
|
||||
|
||||
main().catch((error) => {
|
||||
console.error(error);
|
||||
process.exitCode = 1;
|
||||
});
|
||||
Reference in New Issue
Block a user