feat(harness): F6/F7 close on their last approval — no echo phase gate
Where completeness is machine-detectable, the reviewer's last substantive approval now closes the phase itself (same pattern as F3/F4/F8): - F6: approving the LAST CTE of the plan (kind:"cte_result" with next_cte now empty) advances the phase; a non-final CTE keeps the phase open and names the next one. - F7: kind:"sql" records sql_approved — which IS F7's only advance prerequisite — and advances immediately. Two reviewer interactions per session removed, both pure echoes. The summary phase gate remains only where completeness is a human judgment (F1, F2 with recorded memories, F5). SKILL.md states the rule and the five self-closing gates; L1 tests cover last/non-last CTE and sql close. Co-Authored-By: Claude Fable 5 <noreply@anthropic.com>
This commit is contained in:
@@ -1299,7 +1299,28 @@ export default function (pi) {
|
||||
"",
|
||||
);
|
||||
if (err) return err;
|
||||
return textResult(`CTE '${cteName}' approvato (sessione ${session}).`);
|
||||
// Deterministic completeness: when no CTE remains in the plan the reviewer
|
||||
// has approved everything F6 can ask — close the phase here instead of
|
||||
// echoing a reviewer_confirm kind:"phase" that decides nothing new.
|
||||
const remaining = tht(ctx, ["cte", "next", "--session", session]).trim();
|
||||
if (remaining) {
|
||||
return textResult(
|
||||
`CTE '${cteName}' approvato (sessione ${session}). Prossimo CTE del piano: '${remaining}'.`,
|
||||
);
|
||||
}
|
||||
const closed = advancePhaseAndFinalize(ctx, session, curNum);
|
||||
if (closed.err) return closed.err;
|
||||
if (closed.finalized) {
|
||||
lockActive = false;
|
||||
lastSteered = false;
|
||||
return textResult(
|
||||
`CTE '${cteName}' approvato — era l'ultimo del piano: fase chiusa e sessione finalizzata (${session}).`,
|
||||
);
|
||||
}
|
||||
return textResult(
|
||||
`CTE '${cteName}' approvato — era l'ultimo del piano: Fase ${curNum} chiusa automaticamente. ` +
|
||||
'NON presentare reviewer_confirm kind:"phase" per questa fase; prosegui con la successiva.',
|
||||
);
|
||||
}
|
||||
if (kind === "sql") {
|
||||
const err = relayIfThtFails(
|
||||
@@ -1317,7 +1338,19 @@ export default function (pi) {
|
||||
"",
|
||||
);
|
||||
if (err) return err;
|
||||
return textResult(`SQL approvato (sessione ${session}).`);
|
||||
// F7's only prerequisite IS sql_approved (workflow.yaml): the phase gate
|
||||
// after it decides nothing new — close the phase here.
|
||||
const closed = advancePhaseAndFinalize(ctx, session, curNum);
|
||||
if (closed.err) return closed.err;
|
||||
if (closed.finalized) {
|
||||
lockActive = false;
|
||||
lastSteered = false;
|
||||
return textResult(`SQL approvato — fase chiusa e sessione finalizzata (${session}).`);
|
||||
}
|
||||
return textResult(
|
||||
`SQL approvato — Fase ${curNum} chiusa automaticamente. ` +
|
||||
'NON presentare reviewer_confirm kind:"phase" per questa fase; prosegui con la successiva (datamart/memorie).',
|
||||
);
|
||||
}
|
||||
return textResult(`Approvato (kind=${kind}, sessione ${session}).`);
|
||||
} catch (fatal) {
|
||||
|
||||
Reference in New Issue
Block a user