40 lines
2.4 KiB
JavaScript
40 lines
2.4 KiB
JavaScript
import assert from "node:assert/strict";
|
|
import fs from "node:fs";
|
|
import path from "node:path";
|
|
import { buildTaskContext, contextSizeReport, CONTEXT_LIMITS, root, verifyTaskIndex } from "./task-context-lib.mjs";
|
|
import { validateContextBundle } from "./context-governance.mjs";
|
|
|
|
const taskArg = process.argv.indexOf("--task");
|
|
const task = taskArg >= 0 ? process.argv[taskArg + 1] : undefined;
|
|
const write = process.argv.includes("--write");
|
|
verifyTaskIndex();
|
|
const bundle = buildTaskContext(task);
|
|
const report = contextSizeReport(bundle);
|
|
const { context } = bundle;
|
|
const governance = validateContextBundle(bundle);
|
|
assert.equal(report.withinBudget, true, `task context exceeds budget: ${JSON.stringify(report)}`);
|
|
assert.deepEqual(governance.violations, [], `task context governance failed: ${JSON.stringify(governance.violations)}`);
|
|
if (task) assert.equal(context.task, task);
|
|
assert.ok(context.parentTask);
|
|
assert.ok(context.commands.length > 0, "task must expose at least one focused command");
|
|
assert.ok(context.sourceDocuments.parentManifest.endsWith("manifest.json"));
|
|
assert.ok(!context.sourceDocuments.taskCard.includes("CURRENT_EXECUTION_PLAN"));
|
|
if (bundle.sources.taskSource && context.task === bundle.sources.queue.currentTask) {
|
|
for (const heading of ["## 目标", "## 输入与范围", "## 验收", "## 交付与回滚"]) {
|
|
assert.ok(bundle.sources.taskSource.includes(heading), `current task card must include ${heading}`);
|
|
}
|
|
assert.match(bundle.sources.taskSource, /malformed|unsupported|取消|超限|负例|失败/iu, "current task card must name one failure boundary");
|
|
}
|
|
if (context.task === bundle.sources.queue.currentTask) {
|
|
assert.ok(bundle.sources.taskSource, "current task must have a compact task card; do not fall back to the full plan");
|
|
assert.ok(bundle.sources.taskSource.length <= CONTEXT_LIMITS.taskBytes, "current task card exceeds the 8 KiB context budget");
|
|
}
|
|
|
|
const outputDir = path.join(root, "tests/golden", context.task);
|
|
const outputPath = path.join(outputDir, "task-context.json");
|
|
if (write) {
|
|
fs.mkdirSync(outputDir, { recursive: true });
|
|
fs.writeFileSync(outputPath, `${JSON.stringify({ ...context, size: report }, null, 2)}\n`);
|
|
}
|
|
process.stdout.write(`task-context-ok task=${context.task} parent=${context.parentTask} totalTokens=${report.totalTokens} taskBytes=${context.budgets.taskBytes} next=${context.nextTask ?? "NONE"}${write ? ` output=${path.relative(root, outputPath)}` : ""}\n`);
|