fix(ui): stream phase progress without gates

This commit is contained in:
2026-08-24 12:10:56 +02:00
parent 36a7a0ab33
commit fa2298653b
10 changed files with 186 additions and 5 deletions
@@ -0,0 +1,59 @@
const test = require("node:test");
const assert = require("node:assert");
const cp = require("node:child_process");
const path = require("node:path");
const { createRequire } = require("node:module");
const { createFakePi } = require("./fake_pi_runtime.js");
const GATE = path.join(__dirname, "..", "..", "tht-gate.js");
globalThis.require = createRequire(GATE);
let phase = 2;
cp.execFileSync = (_file, args) => {
if (args.join(" ") === "phase meta --json") {
return JSON.stringify({
max_phase: 8,
phases: Array.from({ length: 8 }, (_, index) => ({
num: index + 1,
id: `F${index + 1}`,
name: `phase-${index + 1}`,
emits: [],
})),
});
}
if (args.slice(0, 4).join(" ") === "phase show --session session-1") {
return `Fase corrente: ${phase}\n`;
}
return "";
};
const installGate = require(GATE).default ?? require(GATE);
test("tool completion announces each newly active phase even without a reviewer gate", async () => {
const { pi, ctx } = createFakePi();
ctx.mode = "rpc";
installGate(pi);
await pi.emit("session_start", {});
await pi.emit("tool_result", {
toolName: "reviewer_select",
input: { session: "session-1" },
isError: false,
});
phase = 3;
await pi.emit("tool_result", {
toolName: "reviewer_decide",
input: { session: "session-1" },
isError: false,
});
await pi.emit("tool_result", {
toolName: "reviewer_decide",
input: { session: "session-1" },
isError: false,
});
assert.deepEqual(ctx.notifications, [
{ message: "__tht_phase_started__:F2", level: "info" },
{ message: "__tht_phase_started__:F3", level: "info" },
]);
});