refactor(harness): route workflow persistence through repositories

This commit is contained in:
User
2026-07-16 18:01:29 +02:00
parent 259f021313
commit c1cddaa667
30 changed files with 925 additions and 348 deletions
@@ -0,0 +1,41 @@
const test = require("node:test");
const assert = require("node:assert");
const cp = require("node:child_process");
const { createRequire } = require("node:module");
const path = require("node:path");
const GATE = path.join(__dirname, "..", "..", "tht-gate.js");
if (typeof globalThis.require === "undefined") globalThis.require = createRequire(GATE);
test("repository write tools persist CTE and final SQL through deterministic tht commands", async () => {
const calls = [];
const original = cp.execFileSync;
cp.execFileSync = (file, args, options) => {
calls.push({ args, input: options?.input });
return "";
};
try {
const gate = require(GATE);
const { createFakePi } = require("./fake_pi_runtime.js");
const { pi, ctx, tools } = createFakePi();
ctx.cwd = "/nonexistent-thothii-test-cwd";
gate.default(pi);
const cte = tools.get("write_cte_sql");
const final = tools.get("write_final_sql");
assert.ok(cte, "write_cte_sql must be registered");
assert.ok(final, "write_final_sql must be registered");
await cte.def.execute("cte", { session: "s1", name: "base", sql: "WITH base AS (SELECT 1)" }, null, null, ctx);
await final.def.execute("sql", { session: "s1", sql: "SELECT * FROM base" }, null, null, ctx);
assert.deepEqual(calls.map((call) => call.args), [
["cte", "save", "--session", "s1", "--name", "base", "--file", "-"],
["sql", "set-final", "--session", "s1", "--file", "-"],
]);
assert.deepEqual(calls.map((call) => call.input), ["WITH base AS (SELECT 1)", "SELECT * FROM base"]);
assert.equal(JSON.stringify(calls).includes("sessions/s1"), false);
} finally {
cp.execFileSync = original;
}
});
+32
View File
@@ -1401,6 +1401,38 @@ export default function (pi) {
},
});
pi.registerTool({
name: "write_cte_sql",
label: "Scrittura CTE SQL",
description: "Persiste un blocco CTE tramite tht cte save; non scrivere mai file di sessione direttamente.",
parameters: Type.Object({ session: Type.String(), name: Type.String(), sql: Type.String() }),
async execute(_id, params, _signal, _onUpdate, ctx) {
const err = relayIfThtFails(
ctx,
["cte", "save", "--session", params.session, "--name", params.name, "--file", "-"],
"Correggi il blocco CTE e riprova.",
params.sql,
);
return err || textResult(`CTE ${params.name} salvato per la sessione ${params.session}.`);
},
});
pi.registerTool({
name: "write_final_sql",
label: "Scrittura SQL finale",
description: "Persiste il SQL finale tramite tht sql set-final; non scrivere mai file di sessione direttamente.",
parameters: Type.Object({ session: Type.String(), sql: Type.String() }),
async execute(_id, params, _signal, _onUpdate, ctx) {
const err = relayIfThtFails(
ctx,
["sql", "set-final", "--session", params.session, "--file", "-"],
"Correggi il SQL finale e riprova.",
params.sql,
);
return err || textResult(`SQL finale salvato per la sessione ${params.session}.`);
},
});
// --- slash command: /torna [session_id] [N] (rollback to a previous phase) --
pi.registerCommand("torna", {
description: