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:
1 parent
80e70649c3
commit
34ea33cb8d
5 files changed
+273
-67
No files matched your search
@@ -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),
|
||||
|
||||
Reference in new issue
Block a user