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

+12
View File
@@ -1,5 +1,6 @@
import type { ProviderService } from "./provider-service";
import { AGENT_TOOLS, dispatchAgentTool, type AgentToolContext, type AgentToolDeps } from "./agent-tools";
import { completeGoalTool } from "./agent-goal-tools";
import { executeWebTool, isWebTool, WEB_TOOLS } from "./agent-web-tools";
import { executeWorkspaceTool, isWorkspaceTool, WORKSPACE_TOOLS } from "./agent-workspace-tools";
import { canonicalMentionHandle } from "../../shared/mention-handles";
@@ -76,6 +77,17 @@ export async function runAgentLoop(deps: AgentRunLoopDeps, input: AgentRunLoopIn
output = await executeWorkspaceTool(input.toolContext, call);
} else if (isWebTool(call.name)) {
output = await executeWebTool(call);
} else if (call.name === "complete_goal") {
// Runs an independent audit turn against the provider, so it needs
// the loop's provider access rather than the sync dispatcher.
output = await completeGoalTool({
deps: deps.tools,
ctx: input.toolContext,
providers: deps.providers,
providerId: input.providerId,
workspaceId: input.workspaceId,
call,
});
} else {
output = dispatchAgentTool(deps.tools, input.toolContext, call, {
announceTaskAssignments: shouldAnnounceTaskAssignment(call, turn.toolCalls),