refactor(disambiguation): extract F3 rewrite path (#26)
This commit is contained in:
@@ -45,6 +45,7 @@ import {
|
||||
appendLedgerSection,
|
||||
} from "./gate/enrich.js";
|
||||
import { createMemoryGate } from "./gate/memory/index.js";
|
||||
import { createDisambiguationGate } from "./gate/disambiguation/index.js";
|
||||
import { isReserved } from "./reserved-labels.mjs";
|
||||
|
||||
// Load the workflow contract once when Pi loads the extension. Asking the model to
|
||||
@@ -619,6 +620,26 @@ export default function (pi) {
|
||||
waitForReviewer: emitAndWait,
|
||||
toTextResult: textResult,
|
||||
});
|
||||
const disambiguationGate = createDisambiguationGate({
|
||||
workflow: {
|
||||
activate: () => {
|
||||
lockActive = true;
|
||||
},
|
||||
phase: (ctx, session) => ({ number: currentPhase(ctx, session) }),
|
||||
advance: advancePhaseAndFinalize,
|
||||
},
|
||||
session: {
|
||||
mutate: (ctx, args, recovery) => relayIfThtFails(
|
||||
ctx, ["session", ...args], recovery,
|
||||
),
|
||||
},
|
||||
ledger: {
|
||||
record: (ctx, session, decision, recovery) => relayIfThtFails(
|
||||
ctx, decisionAddArgs(session, decision), recovery,
|
||||
),
|
||||
},
|
||||
toTextResult: textResult,
|
||||
});
|
||||
|
||||
// 1) ANTI-BYPASS tool_call hook (spec D4, verbatim). Blocks direct phase/decision
|
||||
// calls and writes to protected files so the reviewer cannot bypass the gate.
|
||||
@@ -1580,63 +1601,7 @@ export default function (pi) {
|
||||
}
|
||||
|
||||
memoryGate.install(pi);
|
||||
|
||||
pi.registerTool({
|
||||
name: "rewrite_question",
|
||||
label: "Riscrittura domanda e chiusura F3 (deterministica)",
|
||||
description:
|
||||
"In Fase 3 scrive deterministicamente question.md, registra question_rewritten e " +
|
||||
"chiude la fase senza chiedere conferma al reviewer. assumptions puo' essere array " +
|
||||
"o stringa JSON.",
|
||||
parameters: Type.Object({
|
||||
session: Type.String(),
|
||||
question: Type.String(),
|
||||
assumptions: Type.Optional(Type.Any()),
|
||||
}),
|
||||
async execute(_id, params, _signal, _onUpdate, ctx) {
|
||||
lockActive = true;
|
||||
try {
|
||||
const { session, question, assumptions } = params;
|
||||
const curNum = currentPhase(ctx, session);
|
||||
if (curNum !== 3) {
|
||||
return textResult("La riscrittura automatica e' disponibile solo in Fase 3.");
|
||||
}
|
||||
let assumps = assumptions;
|
||||
if (typeof assumps === "string") {
|
||||
try {
|
||||
assumps = JSON.parse(assumps);
|
||||
} catch {
|
||||
assumps = [assumps];
|
||||
}
|
||||
}
|
||||
// `tht session set-question` takes the session id as a positional argument
|
||||
// (the `session` command group uses positional ids, unlike phase/cte/decision
|
||||
// which use --session).
|
||||
const args = ["session", "set-question", session, "--question", question];
|
||||
if (Array.isArray(assumps)) {
|
||||
for (const a of assumps) args.push("--assumption", String(a));
|
||||
}
|
||||
const err = relayIfThtFails(ctx, args, "");
|
||||
if (err) return err;
|
||||
const decisionErr = relayIfThtFails(
|
||||
ctx,
|
||||
decisionAddArgs(session, {
|
||||
type: "question_rewritten",
|
||||
subject: "domanda",
|
||||
detail: question,
|
||||
}),
|
||||
"",
|
||||
);
|
||||
if (decisionErr) return decisionErr;
|
||||
const advanced = advancePhaseAndFinalize(ctx, session, curNum);
|
||||
if (advanced.err) return advanced.err;
|
||||
return textResult(`Domanda riscritta e Fase 3 completata (sessione ${session}).`);
|
||||
} catch (fatal) {
|
||||
const msg = (fatal.stderr || fatal.message || String(fatal)).toString().trim();
|
||||
return textResult(`[rewrite_question ERRORE INTERNO] ${msg}. Riprova o usa un approccio diverso.`);
|
||||
}
|
||||
},
|
||||
});
|
||||
disambiguationGate.install(pi);
|
||||
|
||||
pi.registerTool({
|
||||
name: "write_schema_linking",
|
||||
|
||||
Reference in New Issue
Block a user