Files
ThothII/harness/.pi/extensions/gate/__tests__/archive_repair.test.js
T
Codex d8a29bfbdd Add full shell, replaceable Omics adapter and bilingual interaction
Implement approved specification #32 and tickets #33-#37. Keep host authentication server-verified and pin session interaction language. Compile scoped base selectors for browser compatibility and retain full gutters during CSS pruning.
2026-09-13 14:26:39 +02:00

65 lines
3.1 KiB
JavaScript

const test = require("node:test");
const assert = require("node:assert/strict");
const { installRepairGate } = require("../memory/repair.js");
const { gateText } = require("../core/locale.js");
function gate({ answers, fail = false, resume = false }) {
let tool;
const calls = [], widgets = [];
const repair = { repair_id: "receipt", choice: null, status: "proposed", can_apply: true,
saved: false, indexed: false, options: [{ id: "fix", content: { detail: "Correction" } }] };
installRepairGate({ registerTool: def => { tool = def; } }, {
languageFor: () => "en",
gateText,
workflow: { activate() {}, phase: () => ({ id: "F4" }) },
memory: { execute: (_ctx, args) => {
calls.push(args);
if (args[0] === "repair-apply") {
const choice = args[args.indexOf("--choice") + 1];
if (choice === "reject") Object.assign(repair, { choice, status: "rejected" });
else Object.assign(repair, { choice, saved: true, indexed: !fail,
status: fail ? "pending_activation" : "active" });
fail = false;
}
return JSON.stringify(repair);
} },
waitForReviewer: async (_ctx, descriptor) => {
widgets.push(descriptor);
assert.ok(answers.length, "gate must not ask an unbounded extra question");
return answers.shift();
},
toTextResult: text => text,
});
return { calls, widgets, run: () => tool.execute("id", {
session: "s", ...(resume ? { repair_id: "receipt" } : { proposal: { reason: "conflict", options: [] } }),
}, null, null, {}) };
}
test("human choice applies once and the next widget reports activation", async () => {
const g = gate({ answers: [{ choices: ["fix"] }, { choices: ["continue"] }] });
assert.equal(JSON.parse(await g.run()).indexed, true);
assert.deepEqual(g.calls.map(args => args[0]), ["repair-prepare", "repair-apply"]);
assert.equal(g.widgets[0].repair.saved, false);
assert.equal(g.widgets[1].repair.status, "active");
});
test("rejection asks for reformulation without a normal workflow decision", async () => {
const g = gate({ answers: [{ choices: ["reject"] }] });
assert.match(await g.run(), /rejected as inadequate/);
assert.equal(g.calls.length, 2);
});
test("retry keeps the receipt and selected choice, then reports true activation", async () => {
const g = gate({ resume: true, fail: true,
answers: [{ choices: ["fix"] }, { choices: ["fix"] }, { choices: ["continue"] }] });
assert.equal(JSON.parse(await g.run()).indexed, true);
assert.equal(g.widgets[1].repair.status, "pending_activation");
assert.equal(g.calls[0][0], "repair-show");
assert.deepEqual(g.calls[1], g.calls[2]);
});
test("free text and forged choices never apply a correction", async () => {
for (const response of [{ control: "freetext", text: "Explain the conflict" }, { choices: ["forged"] }]) {
const g = gate({ answers: [response] });
await g.run();
assert.equal(g.calls.length, 1);
}
});