Goal completion is a claim, not a decision: the independent audit

Adopted from studying Claude Code's /goal (completion judged by a fresh
model, never the one doing the work) and pi-goal-x's auditor (isolated
session, read-only tools, explicit approval marker, rejects scaffold-only
and proxy-metric completions).

complete_goal no longer closes a goal on the caller's word:
- It now takes a required `evidence` claim, and permission/argument gates
  run before any audit spend.
- The audit is an isolated tool-turn loop: fresh conversation (the auditor
  never sees the executor's transcript), read-only workspace tools (no
  run_command), strict auditor instructions, at most 6 iterations.
- Only an explicit <approved/> closes the goal (recorded with the audit
  verdict). <disapproved/>, no marker, or an exhausted budget all leave the
  goal active and hand the decisive gap back to the caller as the tool
  result.
- The handler moved from the sync dispatcher into the run loop's async
  routing because it needs provider access; the goal-review prompt warns
  that substanceless claims will bounce.

AGENTS.md documents both this and the web-access contract.
This commit is contained in:
ZacharyZhang-NY committed 2026-07-09 20:46:53 -04:00
1 parent 80e70649c3
commit 34ea33cb8d
5 files changed
+273 -67

No files matched your search

+1 -3
View File
@@ -8,7 +8,7 @@ import { readMessagesTool } from "./agent-read-messages";
import { grantConnectorTool, listConnectorsTool } from "./agent-connector-tools";
import { bindSkillSlugs, grantSkillTool, listSkillsTool } from "./agent-skill-tools";
import { createDocumentTool, writeDeliverableTool } from "./agent-deliverable-tools";
import { completeGoalTool, GOAL_TOOLS } from "./agent-goal-tools";
import { GOAL_TOOLS } from "./agent-goal-tools";
import { describeSend } from "./agent-message-presence";
import { optionalString, optionalStringArray, requireString } from "./agent-tool-args";
import type { JsonRecord } from "./provider-http";
@@ -234,8 +234,6 @@ export function dispatchAgentTool(
return createTask(deps, ctx, call.arguments, options);
case "update_task_status":
return updateTaskStatus(deps, ctx, call.arguments);
case "complete_goal":
return completeGoalTool(deps, ctx);
case "write_deliverable":
return writeDeliverableTool(deps, ctx, call.arguments);
case "send_message":