feat: plan-done и арбитраж gate3 — только терминальный грант (consent forgery B4)

Снятие печати плана (plan-done) и арбитраж gate3 (gate3-arb:accept/continue) — тело-агностичные
согласия, обходящие/снимающие стену — теперь открываются ТОЛЬКО терминальным грантом владельца
(Поза 1, HOLE-4). supreme-gate: новый параметр terminalGrants в decideMode/runGate, PLAN_FINISH_ACTION
проверяется против него (лёгкий escape остаётся на chat-грантах); main грузит loadTerminalGrants.
gate3-loop: арбитраж-гранты грузятся через loadTerminalGrants (loader-swap; resolveOwnerArbitration
агностична). Ядро стены: 138/138, gate3 44/44, полный свод 4346. Спека §B/§DEC.

Co-Authored-By: Claude Opus 4.8 <noreply@anthropic.com>
This commit is contained in:
Дмитрий
2026-06-18 19:03:10 +03:00
parent 29287d73c9
commit 5bcf229e4f
4 changed files with 63 additions and 13 deletions
+3 -2
View File
@@ -241,7 +241,7 @@ async function main() {
const { resolveJudgeLlmKey } = await import('./judge-gate-config.mjs');
const { callJudgeModel } = await import('./enforce-judge-gate.mjs');
const { requiredLensesFor, runJudge } = await import('./judge-engine.mjs');
const { loadFloorEscapes, loadConsumed } = await import('./escape-grant.mjs');
const { loadTerminalGrants, loadConsumed } = await import('./escape-grant.mjs');
try {
const event = parseEventJson(await readStdin());
const dir = runtimeDir();
@@ -267,7 +267,8 @@ async function main() {
const v = runJudge({ functionName: 'gate3card', requiredLenses, subRunsRequired: [], subRuns: [], llmCall: () => raw, promptArgs });
return { wired: true, decision: v.decision, verdict: v };
};
const r = await runGate3Stop(event, { runtimeDir: dir, sess, key, judgeKey, loadGreens, loadArtifact, callJudge, callCardJudge, grants: loadFloorEscapes(sess), consumed: loadConsumed(sess), now: Date.now() });
// Поза 1 (#B4): арбитраж gate3 (accept/continue) — ТЯЖЁЛОЕ → ТОЛЬКО терминальный грант владельца.
const r = await runGate3Stop(event, { runtimeDir: dir, sess, key, judgeKey, loadGreens, loadArtifact, callJudge, callCardJudge, grants: loadTerminalGrants(sess), consumed: loadConsumed(sess), now: Date.now() });
exitDecision({ block: !!r.block, message: r.block ? `[gate3-loop] ${r.message || 'петля открыта — цель не подтверждена'}` : undefined });
} catch {
exitDecision({ block: false }); // Stop fail-OPEN: внутренняя ошибка хука НЕ кирпичит конец хода