feat(harness): gate uses externally-provided THT_SESSION id (BE-5)

When THT_SESSION env var is set, /nuova-domanda injects a kickoff that
tells the model to use the pre-created session id instead of running
`tht session new`. /riprendi-sessione and no-env-var paths unchanged.

Co-Authored-By: Claude Sonnet 4.6 <noreply@anthropic.com>
This commit is contained in:
2026-06-27 20:07:25 +02:00
co-authored by Claude Sonnet 4.6
parent 8c4a1798da
commit 0240242f5c
2 changed files with 43 additions and 1 deletions
@@ -0,0 +1,30 @@
const test = require("node:test");
const assert = require("node:assert");
const { createFakePi } = require("./fake_pi_runtime.js");
const installGate = require("../../tht-gate.js").default ?? require("../../tht-gate.js");
test("con THT_SESSION il kickoff usa l'id fornito e NON crea la sessione", async () => {
process.env.THT_SESSION = "2026-06-27-100000-test";
try {
const { pi, ctx } = createFakePi();
installGate(pi);
await pi.emit("input", { source: "rpc", text: '/nuova-domanda "x"' });
const injected = await pi.emit("before_agent_start", { systemPrompt: "" });
// before_agent_start returns { systemPrompt: "<original>\n\n<kickoff>" }
const text = injected?.systemPrompt ?? "";
assert.match(text, /2026-06-27-100000-test/);
assert.doesNotMatch(text, /tht session new/);
} finally {
delete process.env.THT_SESSION;
}
});
test("senza THT_SESSION il kickoff contiene tht session new (comportamento attuale)", async () => {
delete process.env.THT_SESSION;
const { pi, ctx } = createFakePi();
installGate(pi);
await pi.emit("input", { source: "rpc", text: '/nuova-domanda "x"' });
const injected = await pi.emit("before_agent_start", { systemPrompt: "" });
const text = injected?.systemPrompt ?? "";
assert.match(text, /tht session new/);
});
+13 -1
View File
@@ -60,6 +60,16 @@ const NUOVA_DOMANDA_KICKOFF =
"NON eseguire mai `tht phase advance|reopen` ne' `tht decision add` da shell.\n" + "NON eseguire mai `tht phase advance|reopen` ne' `tht decision add` da shell.\n" +
"- Procedi una fase alla volta: a fine fase cedi il turno al reviewer, non incatenare le fasi."; "- Procedi una fase alla volta: a fine fase cedi il turno al reviewer, non incatenare le fasi.";
const NUOVA_DOMANDA_KICKOFF_PROVIDED = (sessionId) =>
"Istruzioni operative — sessione ThothII (workflow human-in-the-middle). " +
`La sessione è GIÀ creata con id \`${sessionId}\`: usalo in OGNI comando \`tht\`. ` +
"NON creare una nuova sessione.\n" +
"1. Carica la skill leggendo `.pi/skills/tht-sessione/SKILL.md` con il tool `read`, " +
`poi segui il workflow dalla Fase 1 usando l'id \`${sessionId}\`.\n` +
"Regole non negoziabili: una domanda al reviewer per volta; mai promuovere/escludere/" +
"correggere senza conferma; le interazioni passano dai tool reviewer_*; testo libero col prefisso '!'. " +
"MAI `tht phase advance|reopen` né `tht decision add` da shell.";
const RIPRENDI_KICKOFF = const RIPRENDI_KICKOFF =
"Istruzioni operative — ripresa di una sessione ThothII esistente (id nel messaggio sopra).\n" + "Istruzioni operative — ripresa di una sessione ThothII esistente (id nel messaggio sopra).\n" +
"1. Esegui `tht session show <id>` e leggi: stato, domanda, decisioni registrate, presenza " + "1. Esegui `tht session show <id>` e leggi: stato, domanda, decisioni registrate, presenza " +
@@ -208,7 +218,9 @@ export default function (pi) {
lockActive = true; lockActive = true;
lastSteered = false; lastSteered = false;
pendingKickoff = /^\/nuova-domanda\b/.test(raw) pendingKickoff = /^\/nuova-domanda\b/.test(raw)
? NUOVA_DOMANDA_KICKOFF ? (process.env.THT_SESSION
? NUOVA_DOMANDA_KICKOFF_PROVIDED(process.env.THT_SESSION)
: NUOVA_DOMANDA_KICKOFF)
: RIPRENDI_KICKOFF; : RIPRENDI_KICKOFF;
} }
// free-input block: attivo quando il lock è su, per qualsiasi input utente (non solo interattivo). // free-input block: attivo quando il lock è su, per qualsiasi input utente (non solo interattivo).