feat(gate): write_schema_linking tool (validated F4 artifact via CLI)

tht() gains an optional stdin arg; the tool pipes the schema-linking
object to 'tht session set-schema-linking --file -', which validates
against SchemaLinking and returns the exact error on failure — so the
model stops hand-writing the artifact and validating with ad-hoc python.

Co-Authored-By: Claude Opus 4.8 <noreply@anthropic.com>
This commit is contained in:
2026-07-01 16:49:18 +02:00
co-authored by Claude Opus 4.8
parent 00777922d8
commit 20bc3de950
+34 -2
View File
@@ -144,9 +144,9 @@ function loadEnvFromDotenv(ctx) {
}
// Single chokepoint for all CLI calls. cwd is the Pi project root (harness/).
function tht(ctx, args) {
function tht(ctx, args, input) {
loadEnvFromDotenv(ctx);
return execFileSync("tht", args, { cwd: ctx.cwd, encoding: "utf8" });
return execFileSync("tht", args, { cwd: ctx.cwd, encoding: "utf8", input });
}
// Runs a privileged tht call; converts any failure into an actionable textResult
@@ -701,6 +701,38 @@ export default function (pi) {
},
});
pi.registerTool({
name: "write_schema_linking",
label: "Scrittura schema_linking.json (validata)",
description:
"Scrive deterministicamente schema_linking.json validandolo contro il modello " +
"SchemaLinking via tht session set-schema-linking (evita edit a mano e la " +
"validazione manuale). schema_linking e' l'oggetto JSON completo: {question, " +
"candidates:[{kind:'table'|'column', name, evidence?, decision?}], joins:[{from, " +
"to, source?}], excluded:[{kind, name}], open_questions:[], concept_formulas:[]}.",
parameters: Type.Object({
session: Type.String(),
schema_linking: Type.Any(),
}),
async execute(_id, params, _signal, _onUpdate, ctx) {
lockActive = true;
const { session, schema_linking } = params;
try {
tht(
ctx,
["session", "set-schema-linking", session, "--file", "-"],
JSON.stringify(schema_linking),
);
return textResult(
`schema_linking.json scritto e validato per la sessione ${session}.`,
);
} catch (e) {
const cliMsg = (e.stderr || e.message || String(e)).toString().trim();
return textResult(`${cliMsg} Correggi schema_linking e riprova.`);
}
},
});
// --- slash command: /torna [session_id] [N] (rollback to a previous phase) --
pi.registerCommand("torna", {
description: