Restart recovery and Goal design for the complete session runtime
Design question: after an App or worker restart, how do previously running sessions and Goals automatically continue, restoring subtasks, approvals, context, and usage without repeating unknown writes or resuming work the user explicitly stopped?
For framework development and product acceptance. This page defines the target design; implementation status is collected at the end. Scope includes Web, TUI, ACP, background Jobs, and authorized subtasks. Goals use the same chat execution layer. Retain the Python Workflow API without duplicating the execution engine, introducing a general scheduler, or promising exactly-once execution for arbitrary external operations.
Core contract:Resuming a session does not mean retrying its tools. An old turn may end as interrupted while its operations remain outcome_unknown; a new turn first checks actual state. Goal, Todo, chat history, and incurred usage remain preserved.
1. Save the objectiveOriginal objective, completion conditions, permission scope, and explicit budget.
2. Work through ordinary chatThe agent maintains Todo and uses existing tools and approvals.
3. Check at turn completionSettle usage and decide whether to continue, wait, pause, or verify acceptance.
4. Accept completionSubmit achieved once evidence supports every condition; otherwise continue working.
There is no default round cap. Round count is diagnostic information, not a substitute for progress or stopping conditions. Retain the short state tools create_goal/get_goal/update_goal; they only read and write objectives, rather than executing the entire task within one function call.
Five harnesses: what to adopt and what not to duplicate
Tools interrupted by a crash are not automatically rerun; an independent small model evaluates the Goal from conversational evidence. Only official contracts were verified, not internal source.
Adopt recovery without blind reruns and independent completion review; do not add evaluation after every work turn, avoiding unnecessary latency and cost.
Append repairs after exclusive write access; distinguish not-started from unknown outcomes; close old turns and require explicit authorization to continue recovered Goals.
Adopt layered state and idempotent repair; do not copy its default round cap or the product policy requiring manual reactivation after restart.
The following are OpenProgram design choices based on these implementations, not claims that the five projects provide identical safety, acceptance, or cost guarantees. Reference source is pinned to inspected versions; external project tests were not run.
Verifiable Codex boundaries:Official App Server documentationdistinguishes thread/resume, turn/start, and persistent Goals;public extension sourceloads active Goals when resuming threads and attempts continuation while idle. This does not establish that arbitrary desktop exits, system restarts, or tool-process deaths can restore original memory or continue original tools. OpenProgram defines automatic continuation while prior run intent remains valid as its own explicit product contract, without relying on that unverified stronger assumption.
Current state: persistence exists, but consistent recovery decisions are missing
Owner checks, canonical recovery, wait-receipt recovery, and projection redelivery already exist; this is not a blank implementation.
Unconfirmed effects can place an entire execution in reconciliation_required; separate operation reconciliation from whether the session can continue.
execution/restart.py
Restart pause intent, deduplicated continuation commands, and resource admission exist. Recovery has no default expiry; explicit disabling and finite deadlines remain, and unresolved effects are disallowed.
Complete state recovery still needs acceptance. Existing finite deadlines in old records are not automatically extended, and removing the default expiry does not authorize replay of unresolved effects.
workflow/goal/chat.py, _webui/_exec_dag.py
Chat Goals do not pause because of downtime or display-projection repair. Persist completion notifications before execution finishes, then continue under the original policy after restart. Old records without recovery provenance retain explicit Resume.
Completion notifications and checkpoint recovery have focused tests; unknown effects, new-turn recovery, and complete subtask paths still require implementation and acceptance.
Job recovery, deferred inbox, durable answers, and deduplicated continue exist; some ordinary-chat restart paths exclude spawn/merge.
Unify parent/child recovery decisions and result delivery. A saved Job does not imply a fully recovered child agent.
execution/waits.py
Durable waits differ from live producer waits; live waits are cancelled when their producer disappears.
Recoverable approvals and questions cannot depend solely on process callbacks. Preserve expired question records and reconfirm rather than assuming approval.
usage/context.py, usage/event.py
Session, agent, and Job attribution and a ledger exist; context does not directly retain Goal/revision/request-attempt identity.
Fix attribution and unique keys before requests to support late receipts after restart; missing usage must not become zero.
browser_resources.py, terminal_resources.py, Web session store
Resource identity, recovery state, and session projections exist; this does not mean every process, page state, or environment can be reconstructed.
Accept real reconnection, invalidation reporting, and new identity separately for each resource; frontend reconnection must not trigger duplicate execution.
Inspection covers the shared entry points above, not individual failure tests for every adapter. A paused UI does not prove history was deleted, and existing records do not prove automatic continuation is possible.
Automatic recovery contract: run intent survives the process
Complete durable run_intent on top of existing admission / command / restart intent rather than adding a parallel scheduler. It records work_id, original input and unconsumed messages, desired_state (run / paused / cancelled / done), latest valid control version, permission scope, objective revision, execution host identity, parent/child relationships, last committed progress, and recovery policy. Acknowledge acceptance to the client only after reliably saving the original user request.
By default, automatically recover previously authorized work whose state remains run, consistently for ordinary sessions and Goals and without requiring the user to reopen the session. Preserve pauses, stops, completion, outstanding approval, and exhausted budgets. Ordinary requests without a Goal continue only until that request finishes, not as indefinite Goals. Background work retains its prior authorization and concurrency quota; restart does not authorize additional subtasks.
Closing a window or reloading the frontend only disconnects the client; “quit and stop all tasks” must persist user stop intent. Ordinary App exit, upgrades, worker crashes, and machine restarts do not implicitly mean user Pause. Graceful shutdown first stops new admission and saves accepted controls and checkpoints, then exits the worker; forced shutdown recovers from the last committed records. Client-only drafts without server acknowledgment must not be represented as submitted requests.
Remove the hidden two-hour recovery expiry. Long downtime preserves run intent, but continuation rechecks directory, host, model/tool availability, credentials, current permissions, and budget. Missing resources or revoked permissions show precise waiting reasons, without switching project, account, or model or expanding permissions automatically. Explicit automatic-recovery disabling remains effective; old paused records with unknown reasons stay paused with an explanation rather than being guessed to have been running.
Load facts:Read run intent, user controls, messages, checkpoints, effects, waits, resources, usage, and projection cursors. Read/migration failures show recovery failure without clearing old state.
Confirm ownership:Reconnect live executors; exclude dead executors through generation fencing. Only one host recovers each work item. Single-host recovery must not silently become cross-host takeover.
Repair context:Merge real results, supply missing tool outputs, and record interruption. Resume from a complete safe checkpoint when available; otherwise start a new turn with the same work_id without re-appending user input.
Decide:User stops take priority, followed by approval, permissions, budget, resources, and unknown effects. Runnable work becomes queued; dependency waits become waiting; faults expose retryable reasons. Persist all decisions in the same control service.
Admit and continue:Use existing fair scheduling and resource quotas; derive a stable continuation key from work_id + control version + predecessor commit point. Admission persistence and recovery-intent consumption must leave no duplication window; converge cross-database steps through a retryable outbox.
Restore the interface:App/Web/TUI reconstruct from canonical snapshots and monotonic event sequences, showing recovery, queueing, working, waiting, or failure; display is not a second control implementation.
Recovery coordination belongs to existing execution control. The server and JobRunner may call the same idempotent entry point but cannot make independent recovery decisions. UI orphan cleanup repairs only derived projections; Goal.after_terminal submits continuation requests only for the current version. Temporary faults use durable retry times and bounded backoff instead of idle model calls. Persistent faults retain pending-recovery records and show the error plus Retry / Pause / End without deleting tasks.
Complete recovery-state matrix
Before restart
Default behavior after restart
Restrictions that must persist
Accepted ordinary request not yet scheduled
Requeue with original input order and admit once.
Deduplicate by client request ID; late retries must not override Stop.
Interrupted model stream
Preserve committed text and tool results; label incomplete output and request the remaining work again.
Do not fabricate a complete response by concatenation; a new provider attempt can incur additional cost.
An active Goal working or between turns
Load objective, Todo, evidence, budget, and original run intent; automatically continue work or acceptance.
Do not omit idle active Goals because no execution currently exists; 5/5 only triggers acceptance.
User Pause / End / Stop
Remain paused or terminated; completion notifications and automatic recovery cannot release it.
Persist stop commands when accepted; separate visible execution-stopping progress from business intent.
Pending approval or user answer
Restore the question, request summary, and scope; consume a committed durable answer only once.
Restart is not approval; old approval does not authorize a new action after changes to implementation, arguments, or permissions.
Parent agent waiting for subtasks
Restore existing subtask identities, outputs, inbox cursors, and wait relationships; after receiving terminal state, the parent continues under its original intent.
Reconnect live subtasks and do not recreate finished ones. Propagate user pause policy to child executions within the same task scope without stopping independent tasks.
External process, terminal, or remote job running
Query using host, process-start identity, or job handle; keep observing if alive.
PID alone is insufficient; preserve unknown when completion is uncertain and do not resubmit.
Browser / MCP / temporary resource
Preserve stable resource references and verify identity on reconnection; report actual invalidation and create new resources only as authorized.
Page forms, login state, JS memory, and REPL variables are not guaranteed to recover; a new tab or session must not impersonate the original object.
Context compaction or message persistence in progress
Use the last committed history and summary; an uncommitted summary cannot replace original history.
Partial tool arguments are not executable. Use currently effective permissions and display durable work configuration and unavailable dependencies explicitly.
Result written but completion notification undelivered
Replay terminal projections and inbox delivery without rerunning the task.
Canonical terminal state and projection versions prevent UI rollback; parent aggregation must not double-charge.
Usage receipt absent or seen only in a stream
Reconcile obtainable receipts by provider attempt and deduplicate existing records.
Unobtainable consumption remains unknown; downtime does not count as active time.
Recovery promises confirmed saved work state, run intent, and reconstructable execution, not arbitrary process-memory snapshots. Unpersisted stream fragments, interactive memory in a dead shell, and receipts lost by external services must be reported accurately, not hidden by clearing tasks or fabricated success.
One chat execution layer, five durable data categories
Data and sole owner
Preserved content
Responsibilities it must not assume
Goal / objective state service
goal_id, revision, original objective, acceptance conditions, status, explicit budget, and blocking reasons.
Does not hold provider streams or restore function-call stacks.
Todo / existing plan store
Stable item_id, goal_id, revision, status, and evidence references; UI reads the same source.
Deleting unfinished items must not reduce the objective; plan edits alone are insufficient evidence of progress.
Do not infer Goal costs from session totals or present estimates as actual settlement.
Continue using existing session, execution, effect, todo, and usage stores without building a second event platform. Cross-database updates use existing retryable notifications and unique operation keys; do not assume cross-database atomic transactions. Derived UI and statistics can be reconstructed and must not overwrite original records.
Goal states remain active / paused / blocked / achieved / cancelled / budget_exhausted. Execution, waiting, and acceptance belong in phase or existing wait records instead of a redundant combined state machine. Retain compatibility reads for paused_recoverable. Revision or permission changes invalidate old acceptance and automatic-continuation reservations; old usage retains its original objective attribution.
Interruption recovery: confirm execution ownership before restoring context
Confirm the old executor:Use the existing owner lease / generation; do not write repairs when the lease is uncertain or storage unreadable. A disconnected connection alone does not prove process death. Reject subsequent writes from the old generation.
Verify child processes:Reconnect trackable live processes and wait or explicitly cancel; do not treat a running shell as stopped. Preserve unknown-effect records for unreachable remote operations.
Choose exactly one recovery mode:Only reconnect a live owner. If death is confirmed and a verifiable safe checkpoint exists, create a new attempt under the same execution. Only when no reliable checkpoint exists, acquire exclusive recovery ownership, fill missing outputs using a stable repair key, end the old turn as interrupted, and admit a new turn. These choices are mutually exclusive and bind to the same durable recovery decision, control version, and continuation key; never resume a checkpoint and start a new turn together. Checkpoints must cover committed effects and satisfy current permission, wait, and safe-point contracts, without replaying unknown writes. Repeating repairs has no side effects; real results take priority and no usage is fabricated. Append late verifiable receipts as reconciliation events that replace synthetic placeholders in subsequent context.
Restore run intent:Previously running ordinary requests and active Goals automatically enter unified admission; user-paused work does not resume automatically. Only specific permission, budget, resource, or unknown-operation issues need human intervention; restart itself is not a reason to require manual Resume.
Decide tool behavior:New turns know which calls never started and which outcomes are unknown. Old unknown results do not globally block investigation or independent work; related writes retain original approval and recovery restrictions.
State before interruption
Facts after recovery
Permitted next action
Intent saved, dispatch not yet recorded
not_started; every dispatch must be recorded durably first, otherwise this conclusion is invalid.
Invoke again under current permissions if still needed.
Dispatch recorded, result missing
outcome_unknown; includes a crash between recording the start and making the actual call.
Trusted read-only tools may reread; use the original idempotency key when the service supports deduplication; reconcile other writes first.
Result persisted
completed / error with the actual return value preserved.
Reuse the result; do not rerun because of restart.
External task still alive
running_external + verifiable handle.
Reconnect, wait, or cancel; do not resubmit.
Non-idempotent write outcome cannot be queried
outcome_unknown + pending-operation details.
Allow reads and investigation; retry or explicitly abandon the operation only after the user confirms the risk.
Safety boundary: read_only / idempotent / state_probe capabilities come from trusted tool registration and implementation identity saved at execution. Do not accept model claims of read-only behavior or infer them from a name containing read. General shell, third-party MCP, and custom tools default to unknown. Recovery turns related to unknown writes initially allow only trusted reads and state queries. Without reliable relevance determination, do not automatically allow writes; reconcile first or obtain explicit user authorization.
Request-history repair first matches the nearest call by original call ID, then converts provider IDs. Existing real outputs take priority; duplicate outputs use the last saved real record. Missing results get deterministic unknown placeholders. Calls and results are adjacent in the request projection while user-message order remains intact; original history is unchanged. Results without corresponding calls are not sent as valid tool-protocol items. Interrupted responses retain partial text and an interruption marker without reusing incomplete reasoning signatures. Ambiguous duplicate call IDs within one response produce an explicit error rather than guessed execution facts. This conversion grants no execution permission and cannot replace recovery decisions.
Recovery permission checks use the same conversation provenance to scope old executions and invoked Jobs, without expanding to all executions in the invoked session. Only actual built-in read, grep, glob, and list execution functions qualify for read-only investigation; names, acceptEdits flags, and plugin declarations cannot replace implementation identity. For uncertain effects within the applicable execution scope described below, all other operations require one-time approval; bypass, automatic classification, and existing allow rules cannot waive it. Durable approval binds to the new tool call and unknown-effect set; changes to that set require fresh approval and do not erase old effects. Reject execution if recovery state cannot be read. This check is a prerequisite for restricted new-turn recovery; it does not independently change old execution state or enable Resume.
This is neither an exception for one session nor a repair restricted to allowlisted files. Ordinary chat and Goals share the recovery entry point. Old effect audits may remain unresolved while their chat turns end as interrupted; adjust the old constraint that any unresolved effect prevents turn termination accordingly.
Only an explicitly activated Goal produces Goal UI. Starting, running, pausing and verifying do not add transcript cards. At termination, one compact record remains at the ending transcript position. It uses the existing attachment-card styling and opens the existing Goal details dialog in read-only historical mode. Each record carries its own Goal snapshot and transcript anchor; a later Goal cannot replace its contents. The composer continues to show the current Goal only. Canonically identified verifier messages are internal records, not assistant chat prose; ordinary agent replies remain unchanged. No assessment text, evidence identifiers or raw report is appended to chat. Terminal history is saved with the Goal state under optimistic concurrency. The implementation passes independent specification and quality review. Coverage includes terminal snapshot persistence, stable historical anchors, read-only reuse of the Goal dialog, keyboard focus restoration and preservation of ordinary JSON replies. Full verification and installed-App acceptance remain separate release gates.
Todo manages the plan; acceptance manages the objective
At creation, preserve the original objective and extract verifiable requirements; ask the user only when ambiguity would change scope. The working agent maintains Todo for multi-step tasks; simple tasks may omit it. Every necessary requirement has an evidence checkpoint; adding or removing Todo must not implicitly remove original requirements.
Ordinary work turns do not run a second judge. Enter verifying when the worker submits a complete candidate or all required Todo items finish without verification. First check current revision, required Todo, unfinished subtasks, and relevant unknown effects, then run one independent read-only acceptance review. The worker's completion text is not an acceptance fact.
Acceptance returns met / unmet / unknown and evidence references for each requirement. Deterministic requirements inspect actual test receipts, file versions, and runtime state; semantic requirements use independent model review. Tests retain ordinary tool approval and budget rules: calling shell verification does not make it read-only. Missing evidence returns to another work turn rather than fabricated acceptance.
Only the current goal_id + revision + verified result version may submit achieved. Recheck evidence versions and compare the Goal control version before committing. Controlled artifacts use version numbers or content digests; external facts retain verification time and query receipts without claiming atomic verification across all external systems. Completion means conditions held at that verification; it does not automatically monitor files or reopen the Goal afterward. Later edits, new requests, or explicit monitoring require separate acceptance. Human waivers must be explicit objective revisions with reasons; the agent cannot reduce scope itself. Independent acceptance can also err and does not guarantee absolute correctness.
Judge lack of progress by changes in results and evidence, not tool invocation count. Enter blocked only when the same real blocker recurs consecutively and no independent work is available. Waiting with a live handle enters waiting without idle model turns. A fixed total round count is not evidence of blocking or completion.
Waiting uses existing durable waits and execution-terminal notifications, saving work_id / Goal revision, handle, observed version, and unique consumption key. Completion, failure, or timeout notifications admit exactly once only if intent remains run, versions match, and no other current execution exists. Existing reconciliation polls for missing notifications with backoff. Save results arriving during restart, then automatically continue under the same rules. Pause, cancel, or revision invalidates old wakeups without discarding results; query timeout does not imply the external operation stopped.
Cost: attribute per request, settle per receipt
Fix goal_id / revision / turn_id / request_id before dispatch. Ordinary chat after pausing has no old Goal attribution. Subagent and acceptance requests explicitly inherit attribution; count each receipt once rather than adding both parent totals and child details. Retries are new provider attempts and count separately when they incur actual consumption.
Streaming cumulative usage updates a watermark for the same attempt; do not sum cumulative snapshots. Update Goal projections only after durable receipt writes succeed. Temporary failures retry with the same idempotency key, and restart can reconstruct statistics. Late receipts remain attributed to the original Goal even if paused, ended, or edited.
Store known tokens and known prices separately. Pricing-table changes do not rewrite historical quotes. Display estimates, known values, and partial unknowns separately, such as “Known $0.42; usage unknown for 1 additional request.” Preserve historical cursor data without inventing attribution. Accumulate active time from durable start/stop records, excluding pauses and downtime and without resetting on recovery. When an executor disappears, preserve its last heartbeat; crash-discovery time is not stop time. Show the known duration lower bound and unknown interruption interval. Late usage does not restart paused timers. If an explicit time limit cannot be verified, stop new admission without adding a default limit.
Budgets are unlimited by default. With a user-set hard cost budget, unknown prices or unverifiable consumption cannot be treated as available balance; pause new paid admission and explain why. Reserve a maximum request amount when calculable; otherwise do not promise absolute prevention of overspend. Recheck explicit budgets after ledger reload and before execution recovery or acceptance.
Background Jobs save Goal identity at the real active caller's admission boundary, restore it at startup, and clear unrelated temporary attribution. Cross-session calls preserve original caller provenance without creating a cross-session canonical parent. Goal and Job share start/settlement transactions in usage.db; receipts save Job reservation identity so metering can be reconstructed without an in-memory governor after restart. Unknown tokens and unknown costs retain separate reservations; partial cumulative data records only lower bounds. Expired unstarted reservations cannot dispatch; started requests are not automatically released. Hard budgets accept only audited input/output limits, explicit prices, and service tiers and add no default restriction to Goals without budgets.
Controls and interface: show state, reason, and action together
No Resume click required; specific obstacles show reasons, relevant actions, and Retry. Resume appears only for user-paused work.
Restore intent without blindly resending old tools; admit only one turn per work item.
Todo 5/5 → begin acceptance → verifying
“5/5 · Verifying,” not “Complete.”
Missing evidence returns to work; show “Goal completed” only after acceptance.
active → Pause → paused
Stop automatic continuation immediately; separately show whether current execution is still stopping.
Block new admission and cancel current execution without pretending to undo existing effects.
Any unfinished Goal → End → cancelled
“Goal ended”; still show unfinished processes or unknown operations.
Ending objective intent does not depend on reconciling every effect; old executions no longer trigger automatic continuation.
Pending operation → inspect / query / human confirmation → reconciled or still unknown
Identify the exact call, input summary, original time, and available checks, rather than only linking to the entire Activity list.
Risk-bearing retries require the current user's explicit authorization; models or page content cannot answer for them.
An empty Todo shows no progress placeholder or separator. Backend can_resume / can_verify / can_end and reason_code determine button permissions; the frontend must not infer them from status strings. UI read failures show “State temporarily unavailable” with refresh, not permanently disabled unexplained controls.
User input takes priority over automatic continuation using existing steer/queue semantics. Continuation keys bind goal_id, revision, and the previous committed turn; state checking and admission share version comparisons. Durable state and generation checks block stale actions when pause, edit, explicit cancellation, and admission race.
Ordinary requests, active Goals, and existing subtasks recover automatically after restart; user-paused work does not. Remove the hidden time window and projection-layer business-state rewrites while preserving unique admission and current permissions.
Terminate real child processes before dispatch, after start, and after result persistence. Restart appends repair once, preserves real results, and allows ordinary chat to continue. Late old-owner writes, live shells, and unknown non-idempotent writes must not be retried incorrectly.
3. Goal continuation and control: workflow/goal, HTTP/WS/TUI/ACP entry points
Resume does not replay tools. Double clicks, repeated completion events, and edit/pause races do not produce duplicate executions. Old revisions cannot complete new objectives. No Todo means no placeholder; 5/5 does not directly show achieved.
Reject completion separately for unfinished required items, missing evidence, failing tests, stale results, and relevant unknown effects; commit achieved once when actual evidence satisfies requirements. Verification cannot elevate tool permissions.
5. Request attribution and statistics: usage/recorder, ledger, Goal projections
Handle duplicate/out-of-order usage, concurrent subtasks, streaming cumulative values, retries, ledger faults, and late post-pause receipts correctly. Unknown is not zero; exceeded budgets stop further paid requests.
6. Compatibility and local acceptance
Old Goals remain readable; unknown effects migrate without guessing; chat recovery policies do not break Python Workflow. After full regression and independent specification/quality reviews, update the single default App and verify actual controls, restart continuation, and cost display.
Each stage begins with a public-entry failure reproduction, followed by minimal implementation and regression. Recovery tests cover ordinary chat, not just one specific session. Acceptance distinguishes source, automated tests, local App, and remote release; designs without test or deployment evidence are not marked implemented.
Restart failure acceptance: more than testing Resume once
Create work through public chat, Goal, Job, approval, and control entry points; perform real termination using isolated test storage and non-user-visible process tests. Do not terminate the user's current work to demonstrate recovery. Final visible App acceptance uses only the default instance and first confirms that updating will not overwrite unrelated work.
Cover frontend reload, normal App exit, graceful worker restart, forced worker termination, downtime beyond the old two-hour window, and another crash during recovery. Test host-restart semantics through process-identity changes; list actual OS reboot separately as unverified and do not reboot the user's machine yourself.
Interruption points include before/after input acceptance, provider requests, before/after tool dispatch, before/after result commit, parent/child delivery, all Todo complete before acceptance, after completion commit before projection delivery, and before/after usage persistence.
Recover multiple sessions together to prove fair queueing, shared quotas, one owner per work item, and no duplicate execution from repeated notifications. User Pause / End, permission changes, and new input take priority during recovery; old versions cannot continue.
Live child processes only reconnect; unknown non-idempotent writes only undergo investigation. Consume accepted approvals once and never approve unaccepted requests automatically. Late results and usage retain their original identity.
Unavailable databases, broken migrations, missing credentials/directories, changed tool versions, and lost projection events all need explicit states and recoverable actions, without clearing history or leaving unexplained disabled controls.
Python Workflow compatibility path and existing detailed diagrams (do not define the chat Goal contract above)
Implementation Survey · Design Reference
Agent Goal capability: implementation comparison
This document compares actual Goal runtime responsibilities: where objectives reside, who triggers the next turn, who determines completion, how resources are limited, how waiting and human intervention work, and whether recovery survives process restart. The focus is control flow and state ownership, not feature names.
4 native Goal implementations2 adjacent mechanismsCompatibility reference, not proof of chat Goal implementation5 Archify SVGs embedded in the document
Already availableIndependent completion judgment with inspection toolsThe working agent produces results; an inspection judge checks evidence and decides to continue or complete.
Main current gapExternal-event wakeup is not implementedwaiting_external Explicit resume remains required; live Goals sharing a directory on one machine are protected by an exclusive controller lock.
Current designDurable snapshots, asynchronous questions, an independent judge, and hard budgets share one controllerRestart becomes recoverable pause; waiting consumes neither rounds nor active-time budget.
1. Scope and comparison criteria
A system counts as a native Goal here only if it stores objective state and uses that state after ordinary agent turns to decide whether to automatically start another turn. Todo, Plan, Task, and Cron may participate in Goals but are not Goals on their own.
Compared systems
OpenProgram, Codex, Claude Code, and Hermes Agent; OpenCode and OpenClaw as adjacent implementations; OpenAI Agents SDK, LangGraph, AutoGen, and CrewAI as general-framework baselines.
Fixed dimensions
Entry points, state structure, loop triggers, completion decisions, budgets, waiting, human intervention, persistence, recovery, concurrency control, events, and UI.
Evidence priority
Public and repository source take priority; official runtime documentation covers closed-source implementations. Product behavior illustrates interfaces, not inferred internal data structures.
Claude Code implementation source is not public. This document records only control contracts explicitly stated in official documentation:/goal is a session-scoped prompt Stop hook, including evaluator input, three verdicts, recovery, and background-task wait rules, without inferring tables or internal class names.
Control flow for compatible Python Workflow
This section describes the retained Python goal() Workflow. Ordinary chat uses the chat Goal contract at the top, not the refine/work/judge loop below.
All four native implementations decide whether to start another turn after work. Their differences center on who owns state, who determines completion, and whether waiting pauses execution.
Minimal complete Goal flow from input to terminationSolid lines are the current work path; dashed lines indicate re-execution after incomplete work or external changes.
WorkDecisionWaitStop
A complete Goal implementation must genuinely pause on its yellow waiting branch, distinguish reasons on its red stopping branch, and recover control state across turns and processes. Implementing only the central work–judgment loop is insufficient.
Five implementation models
Level
Input
Progress
Termination
Across turns
Representative systems
Task input
User messageAs this turn's task
No requirement
Model stops
No
Ordinary agent turn
Progress ledger
Task + items
Todo / TaskFor prompting and UI
Does not determine overall termination
No automatic continuation
OpenCode Todo
Graph termination
graph state
Application-defined
edge / condition
Implemented by the application
LangGraph · AutoGen
Persisted controller
objective
usage / status
Agent declaration
Automatic continuation when idle
Codex
Evaluator loop
Goal spec
evidence
Independent evaluator
Continue if incomplete
OpenProgram · Claude · Hermes
D and E can combine. Codex lets the working agent declare completion while its control plane manages lifecycle and budget; the other three implementations delegate completion to an independent evaluator.
Four native Goal architectures in one diagram
Each row is a complete implementation. Read horizontally to see where each places state, work, judgment, and continuation.
State ownership and judgment paths of native GoalsCyan denotes independent evaluators, blue working agents, and yellow waiting or restricted states.
Implementation comparison matrix
The diagram explains control structure; the table preserves exact fields and boundaries for design review.
View the complete comparison matrix
System
Goal representation
Next-turn trigger
Completion decision
Budget
Waiting / human intervention
Persistence and recovery
Key property
OpenProgram Python Workflow compatibility path
session extra_meta.goal Versioned snapshot with goal/run ID, spec, checklist, question queue, and checkpoint
goal() Controller commits state at the boundary before starting the next agent()
Independent judge with read-only inspection tools; typed verdict and can_continue
No default round limit; optional total round/token/active-time/cost budgets accumulate after resume
Questions accumulate asynchronously; independent work continues; enter the following state only when remaining work requires answers: waiting_user
CAS writes to session; page reload retains state; worker restart converts active execution to paused_recoverable
Completion, stopping, recovery, and UI are unified; automatic external wakeup and multi-worker leases remain absent
Codex
SQLite ThreadGoal; includes goal_id and typed status
Thread-idle lifecycle reads the active Goal and starts a turn
The working agent calls update_goal(complete|blocked) for self-reporting; no independent judge
Optional token budget; cumulative tokens and elapsed time
User/system controls pause/resume/usage-limit; blocked requires a three-turn audit
SQLite persistence; resume restores the active controller
Most complete control plane and data model
Claude Code
One completion condition per session
Prompt-based Stop hook prevents stopping and supplies its reason as next-turn guidance
Small fast model: not met / met / impossible; no tools
No structured Goal budget; conditions may include stop clauses; outer limits separately support max turns / USD
Defer judgment while background tasks run; idle check-ins use backoff and a finite count
Resume restores the active condition but resets round, time, and token baselines
Reuses the general Hook protocol with the smallest surface
CLI/gateway queues an ordinary user-role continuation after a turn
Run deterministic gates first, then an auxiliary judge returns done/blocked/continue/wait
20 Goal turns by default; per-gate timeout/retry
Can wait for PID, process session, or duration; user messages take priority
SessionDB.state_meta; resume and compression-session migration
Most complete combination of completion contracts, deterministic gates, and asynchronous waits
OpenCode
User task + SQLite Todo rows
Continue within the same turn based on tool-call finish reason
Ends when the model stops calling tools; Todo completion does not control the overall loop
agent steps limit; unlimited by default
Question/permission belongs to the turn; no Goal pause/resume
Sessions, messages, and todos persist; no active Goal controller
Reliable progress ledger, not a Goal
OpenClaw
Automation jobs, heartbeat scratch, commitments, and background tasks are modeled separately
Scheduler, events, or task completion wake the session
Run success/failure, script exit code, or model stopping for this turn; no open-ended Goal evaluator
Timeout/tool budget per automation run, not a total Goal budget
Naturally supports scheduled waiting, event wakeup, delivery, and backoff
Schedule definitions, run state, and history persist across gateway restarts
Suited to long-term scheduling, not open-ended objective convergence
How controllers stop when tasks cannot be completed
Native Goals automatically decide whether to continue after ordinary agent turns, so they must distinguish incomplete work, missing external conditions, impossible objectives, and persistent lack of meaningful progress. Round limits alone cannot distinguish these causes; they only bound worst-case execution length.
State machine for difficult tasksGreen denotes success. Yellow states must stop automatic work until an explicit event. Red states require changes to the objective, budget, or environment before continuation.
DecisionPauseTermination
View difficult-task stopping mechanisms by framework
Compatible Workflow has no default round limit; optional token/active-time/cost budgets; 3 consecutive judge failures; 3 checklist stalls; 2 consecutive incomplete turns without tools
No fixed round cap without a budget; current stall evidence mainly uses checklist increments and tool use
No general deterministic gate executor yet;waiting_external no automatic event wakeup
Codex
Working agent can declare blocked; the control plane can enter paused, usage_limited, budget_limited or complete
Optional token budget; blocked requires three consecutive audits of the same blocker; user/system can pause
Yes. Without a token budget and without an agent declaration of blocked/complete, the Goal controller continues turns
Completion and blocking rely on worker self-report, without an independent evaluator verifying actual lack of progress
Claude Code
When the evaluator returns impossible , clear the Goal; consecutive absence of tool progress stops continuation but retains the Goal
The general Stop hook forces termination after 8 consecutive stop prevention events; background idle check-ins cap at 3; outer max-turn and USD budgets are configurable
Yes. Goals have no structured hard budget; if tool actions continue and the evaluator keeps returning not met , stopping depends on outer limits
The evaluator has no tools and cannot directly inspect files, tests, or external state; Goal and runner budgets are separate
Hermes Agent
The judge may return blocked or wait; continuation stops at the Goal-turn limit
20 Goal turns by default; gates have timeout/retry; the same failed gate is not rerun under the same workspace fingerprint; waiting consumes no work turns
No infinite continuation, but low-value work may repeat within 20 turns
No confirmed Goal-level total token/cost budget; the semantic judge can keep returning continue
OpenCode
The current turn ends when the model stops invoking tools; unfinished Todo does not start another turn automatically
Configurable agent steps limit
A single turn may be long because steps can default to unlimited, but Todo does not form a cross-turn Goal loop
No cross-turn stalled, blocked, budget, or recovery contract
OpenClaw
An automation run succeeds, fails, or times out; explicit schedules determine subsequent runs
Per-run timeout/tool budget, schedule backoff, and durable run state
No indefinite automatic continuation merely because an objective is unfinished; Cron can repeat forever as configured by the user
No open-ended Goal evaluator to determine whether a long-term objective is achieved or impossible
Why invoking a tool is not progress
Tool calls prove actions, not movement toward acceptance conditions. Stall detection should compare newly added evidence refs, passed deterministic gates, unfinished checklist items, and external-state changes across consecutive turns. Repeated identical evidence should enter stalledrather than reset the stall counter.
Waiting must not consume work turns
Questions first enter a durable asynchronous queue; the controller continues while safe independent work remains. Enter the following state only when all remaining work requires answers: waiting_user. CI, background processes, time, or external events enter waiting_external; explicit resume is currently required.
Conclusion:Semantic evaluators alone cannot guarantee convergence in any of these implementations. Reliable controllers need hard budgets, evidence-based stall detection, explicit blocked/impossible/waiting categories, and waiting states released only by external events.
Native Goal implementation details
OpenProgram
One public Workflow handles Goal execution, judgment loops, and session-state projections.
Native Goal · Open source
Entrygoal(prompt, ...)
State ownersession extra_meta.goal
Completiontool-capable judge
ResumePreserve checkpoints; continue in a new execution
Write activePersist minimal GoalState first so status/clear can see it immediately
refineAn independent inspection turn creates the spec and fixed checklist
workPublic agent() executes one complete tool loop
collectRecord tool-use signals and this turn's result, then update turns
judgeAn independent subagent reads evidence and may inspect with bash/read/grep
transitionTyped verdict, asynchronous questions, budget, and stall checks
repeatContinue independent work or write waiting / achieved / stopped state
Data and judgment
The entry accepts only a single prompt; the same text goes to the worker, while refinement produces a completion specification and checklist.
Schema v3 snapshots include goal/run ID, revision/version, typed status, budget/usage, checkpoint, question queue, and unconsumed answers.
Session entry points run refinement and judgment as independent agent turns that do not advance the main conversation; sessionless programs run goal also executes independent refinement/judge turns with read-only tool constraints in the current runtime.
The judge reads more than worker claims: it can inspect files, command outputs, and checklist items. Strict JSON parse failure retries once; 3 consecutive judgment-failure rounds enter failed.
Stopping and recovery
Compatible Workflow has no default work-round cap and supports total token, active-time, and cost budgets; checklist stalls and consecutive tool-free turns enter stalled.
/goal clear writes cancelledand cancels old execution; CAS version prevents old controllers from overwriting new controls.
needs_user + can_continue adds questions to the queue while independent work continues; only no independent work produces actual waiting_user.
Worker restart moves executing Goals into paused_recoverable; objective, checklist, usage, questions, and checkpoint remain; resume creates a new run.
Implementation assessment: OpenProgram has an independent tool-capable judge, typed states, versioned durable snapshots, asynchronous questions, hard budgets, and explicit post-restart recovery. General deterministic gate execution, automatic external-event wakeup, and an independent evidence repository remain unimplemented. OS file locks provide exclusive ownership for multiple workers on one machine.
Goal is a durable thread-level control entity; the working agent declares completion or blocking through tools.
Native Goal · Open source
EntryUI/API + create_goal
State ownerSQLite ThreadGoal
Completionagent self-report tool
ResumeIdle-lifecycle recovery
create/setValidate objective and optional token budget; only one unfinished Goal per thread
persistwrites goal_id, status, usage, and time fields
start turnInject continuation steering when the Goal is active and the thread idle
workAn ordinary Codex turn uses existing tools, plans, and context
accountAt turn completion, accumulate tokens and elapsed seconds relative to the baseline
declareThe agent may only call update_goal(complete|blocked)
idle againContinue while active; external controls may pause/resume/clear
Separate data and permissions
ThreadGoal is a typed record:thread_id, goal_id, objective, status, token budget, tokens used, time used, created/updated.
Status is active, paused, blocked, usage_limited, budget_limited, or complete.
Model tools may only create, read, or set complete/blocked; user/system controls pause, resume, and budget/usage limited.
External app-server provides thread/goal/set|get|clear and updated/cleared notifications.
Concurrency and completion semantics
Goal mutation and idle continuation share a semaphore; writes use expected_goal_id to prevent an old turn from updating a new Goal.
Resume reads the durable Goal and registers idle continuation again only when active.
The continuation prompt contains the completion audit; the same worker uses actual evidence to decide whether to call update_goal, without independent model review.
Blocked requires the same blocker in at least 3 consecutive Goal turns; token exhaustion moves to budget_limited through system control.
Implementation assessment: Codex has first-class state, permission boundaries, CAS-style updates, resource accounting, and resume. Its risk is that the executor also judges completion, largely relying on prompt constraints and disciplined tool use. It accumulates elapsed time but currently has neither a time budget nor a dedicated external-process wait state.
/goal is a session-scoped prompt-evaluator configuration on the general Stop-hook mechanism.
Native Goal · Official runtime contract
Entry/goal <condition>
State ownersession-scoped condition
Completionsmall fast model
ResumeRestore condition; reset metering baselines
setOne condition per session; a new value replaces the old one and immediately starts a turn
workOrdinary Claude Code turn; Goal does not change permission mode
Stop eventThe session-scoped prompt hook triggers when the main agent is about to finish
deferSkip the evaluator this turn if a background task is still running
evaluateSend condition + conversation to a small fast model without tool access
verdictnot met / met / impossible, each with a reason
continue/clearnot met supplies its reason to the next turn; the other two clear the active Goal
Reuses the Hook protocol
An ordinary Stop hook may return decision:"block" and reason; the reason enters Claude's next-turn context.
A prompt hook may return model-generated ok, reason, impossible./goal adds condition, status display, and recovery to this general mechanism.
stop_hook_active prevents unconditional recursion by extension scripts; the runtime forces termination after 8 consecutive Stop-hook stop prevention events.
The Goal evaluator only sees evidence already in the conversation; it does not read files or run tests.
Waiting, errors, and budgets
Do not evaluate while background shells/subagents run; completion results trigger new turns. Long waits use backoff check-ins, with at most 3 automatic idle check-ins between user inputs in interactive sessions.
Several consecutive turns without tool progress stop automatic looping but retain the Goal for evaluation after the next user prompt.
Unrecoverable auth, balance, uncompactable context overflow, or model-unavailability errors clear the Goal; transient errors retain it.
Goal has no independent typed budget; turn/time termination conditions can be included in the condition. Outer print mode separately provides --max-turns and --max-budget-usd.
Implementation assessment: Claude Code demonstrates that Goal can specialize a general stop interceptor without a separate executor. Its background-work defer/check-in handling is complete, but the tool-free evaluator relies on the worker placing verification evidence in the transcript.
GoalManager Unifies free-text objectives, structured completion contracts, deterministic gates, and asynchronous waits at turn boundaries.
Native Goal · Open source
Entry/goal / /subgoal
State ownerGoalState in SessionDB
Completiongate → auxiliary judge
Resumesession resume + wait release
set/draftFree text or completion contract; subgoals may be appended
workUse ordinary run_conversation to complete a turn
gateRun shell quality gates with timeout/retry first
judgeAn auxiliary model returns done/blocked/continue/wait
waitMay bind PID, process session, or deadline; waiting consumes no Goal turns
enqueueQueue continue as an ordinary user-role message in CLI/gateway
persistWrite on every transition: state_meta[goal:session]
Completion contract and gates
GoalContract stores outcome, verification, constraints, boundaries, and stop_when separately and injects them into both worker and judge prompts.
GoalGate runs before the LLM judge; failures skip judgment, bound the output tail, and provide failure evidence as continuation.
Gates record attempts, exit code, output tail, and workspace fingerprint; reuse failed results when the workspace is unchanged to avoid repeating identical checks.
A subgoal is an additional user-specified acceptance condition; it neither restarts the main Goal nor resets the original objective.
The judge returns done, blocked, continue, or wait; wait may specify PID, process session, or seconds.
CLI and gateway share GoalManagerbut separately queue continuation in their existing message queues, without changing system prompts or toolsets.
Goal state restores on session resume; when context compression rotates session ids, migrate the Goal and remove its old record.
Implementation assessment: Hermes separates verifiable completion from unfinished external work. Deterministic gates handle verification results, the judge handles open-ended semantics, and wait barriers handle asynchronous dependencies. The default remains one Goal per session with a turn budget; total token/cost budgets are not part of the confirmed GoalState contract.
These systems provide some Goal components but lack the complete contract in which one open-ended completion condition controls multiple turns until independently judged complete.
OpenCode
Durable Todo + single-turn agent loop; Todo records progress rather than terminating the loop.
Adjacent mechanism · Open source
Task sourcelatest user message
Progress stateSQLite Todo rows
Loop stopprovider finish reason
Boundagent.steps
Implementation
SessionPrompt.run The loop reads latest messages and exits when the assistant has a non-tool-call finish reason with no unhandled tool calls.
Each round resolves the agent profile and tools, handles compaction/subtasks, then invokes the provider.agent.steps Unlimited by default; the last step injects a max-steps hint into model messages.
Plan is a primary agent profile that mainly prohibits edits through permissions while allowing specific plan files; it is not Goal state.
Todo boundaries
Todo items contain only content, status, and priority; stored in SQLite by session ID, with publication of todo.updated.
todowrite replaces the entire list each time; UI shows completed/total; disabled for subagents by default.
Whether all Todo items are completed does not affect SessionPrompt.run the exit decision or automatically start a new turn after session idle.
It can therefore serve as a Goal progress projection, but not independently as its controller.
Models durable work as schedulers, background tasks, heartbeats, standing instructions, and commitments rather than providing a general Goal evaluator.
Adjacent mechanism · Open source
Persistent intentautomation / standing order
Wake ownerGateway scheduler
Executionagent turn / command / script
Completionper-run outcome
Scheduling and state
Automation jobs store id, name, enabled, schedule, session target, wake mode, typed payload, delivery, failure alert, and run state.
Payloads include system event, agent turn, command, and script; session targets may be main, current, isolated, or named sessions.
Run results distinguish execution from delivery; jobs, run state, and history persist, and scheduling continues after gateway restart.
Scripts and commands can use exit codes for deterministic success, but that judges one run rather than an open-ended objective.
Heartbeat and commitment
Heartbeat is a system-owned monitor automation; it reads scratch or HEARTBEAT.mdand skips model calls when nothing is due.
Structured heartbeat tasks contain only name, interval, and prompt and enter subsequent monitor turns on their own schedules.
Commitments record agent promises or follow-ups inferred from user context, with due window, confidence, status, attempts, and delivery scope.
These mechanisms determine when to run or notify again but provide no met/unmet evaluator and do not constrain multiple runs to one completion condition.
Implementation assessment: OpenClaw is most useful as a reference for external Goal waiting and scheduling. Calling it Goal directly loses completion semantics. A better combination is for a Goal controller to create/bind automation when future time or an external event is needed, then resume the Goal on the event.
Independent judgment and compatibility constraints for Python Workflow
The independent work/judge contract below applies only to Python Workflow. Chat uses the design above: no judge during ordinary work turns, with independent acceptance only on a completion candidate.
Already adopted
Codex control-plane data model
Current snapshots already have stable goal_id, a separate per-execution run_id, typed status, budget/usage, time fields, and CAS version. User controls handle pause/resume/edit/answer/limit/clear; the judge only proposes candidate verdicts.
Adopt directly
Hermes three-stage judgment
The completion contract explicitly defines outcome/verification/constraints/boundaries/stop_when. Deterministic gates run first; semantic judgment runs only after they pass. Asynchronous dependencies enter a wait barrier instead of repeatedly starting work turns.
Adopt directly
Claude Code background-task deferral
If background tasks remain when a work turn ends, neither accept completion nor immediately continue. Completion events resume work; long waits use bounded backoff check-ins and supply the controller with the running-task list.
Already retained
OpenProgram tool-capable judge
An independent judge uses read-only inspection tools to verify files and command results directly and returns typed verdicts. The deterministic gate executor remains future work.
Use in combination
OpenCode Todo as progress projection
Goal checklists should have independent typed-item tables and events for stable UI display. Completed checklist status is only evidence, not equivalent to overall Goal completion, and UI state must not drive the controller.
Combine as needed
OpenClaw scheduling as wait adapter
Future times, CI, external events, and background jobs should not consume Goal turns. GoalRun stores wait handles; scheduler/task subsystems wake it; the controller re-evaluates or continues on the event.
Not adopted
Relying only on worker completion declarations
Codex self-report suits a low-cost general control plane, but OpenProgram already has an independent judge and should not regress to relying only on update_goal(complete). That tool may signal a candidate, while evaluator/controller commits final state.
Current boundary
Versioned session snapshot
extra_meta.goal Schema version, entity IDs, CAS writes, and migration reads already support the current single-session controller. This is not an append-only evidence repository; separate storage is needed only when audit-grade evidence history is required.
Not adopted
Naming Todo, Plan, or Cron as Goal
These address decomposition, change permissions, and timed triggers respectively, without the full semantics of completion conditions + judgment + automatic continuation. APIs and UI should retain those distinctions.
Compatible Python Workflow contract and remaining extensions
Independent judges, role configuration, and recovery checkpoints in this section belong to Python Workflow. Chat entry points share state storage and budget controls but do not invoke this controller.
Goal adds no second agent loop. The controller sits above existing session/dispatcher code, and work still executes through public agent() ; in the diagram, implemented denotes current code, andtarget denotes unimplemented extensions.
Archify architecture · Showcase structure validation 9/9, 0 errors, 0 warnings. Zoomable SVG is embedded directly; typed source is stored beside this document. Purple dashed lines indicate waiting and recovery paths.
Spec and run share a versioned snapshot.goal_id remains stable across resume, whilerun_id identifies one execution. Editing creates a new revision and refines the spec/checklist again. Refinement only restates user requirements and necessary correctness checks, preserving approximate constraints such as “about” without adding format ratios, benchmark names, numeric thresholds, or reference-work comparisons. Significant ambiguity remains a pending question.
Stop policy checks accumulated budgets at phase boundaries.Rounds, tokens, active elapsed time, and cost accumulate across resume; waiting and pause consume no active-time budget. Work turns default to 300 seconds, and silent provider streams remain subject to the whole-call deadline; cumulative budgets are not precise preemptive limits on the current phase.
The controller commits state transitions.Each phase saves a checkpoint; pause/edit/answer/cancel compete with old controllers through CAS versions, preventing stale execution from overwriting new state.
The evaluator is an independent inspection agent.It returns met, unmet, blocked, impossible, waiting_external, needs_user, and can_continue. Besides local inspection it provides web_fetch, web_searchwith existing URL and network-permission checks; web-tool failures propagate as structured is_error receipts. If a judgment includes a failed tool-inspection receipt, the controller rejects metand re-evaluates first; persistent failure reports judge failure. This conservatively requires one acceptance evaluation free of inspection errors; successful receipts alone do not prove all semantic requirements. The general deterministic gate executor remains unimplemented.
The asynchronous question queue does not block unrelated work.Questions accumulate and can be answered individually. Active execution consumes answers at the next boundary and enters the following state only when all remaining work requires answers: waiting_user. Questions occupy only the Goal detail panel without replacing or disabling the ordinary composer.
Restart recovery uses an explicit new execution.Startup reconciliation converts leftover execution state to paused_recoverable; recovery reuses the snapshot rather than resurrecting an old call stack.
External scheduling is a target extension.waiting_external State exists, but automatic job/timer/event wake handles are not implemented. Goal controllers sharing a session store on one machine use a separate OS file lock; startup recovery takes the same lock to avoid rewriting live siblings.
View the complete objective-state transition table
One controller starts work turns and judgment sequentially and saves state at every boundary.
waiting_user
evaluator/controller
Any new answer triggers resume, or edit/cancel
No
Only means all remaining work requires answers; partial answers may release some dependencies while other questions remain.
waiting_external
evaluator
Explicit resume / edit / cancel
No
No automatic wake handle currently exists; the user resumes after external dependencies change.
paused / paused_recoverable
User / startup reconciliation
resume / edit / cancel
No
Preserve budget, questions, checklist, and checkpoint; waiting time is excluded from active time.
blocked
evaluator
Resume after dependency changes, edit, or cancel
No
Not success; reason records the current blocking facts.
impossible
evaluator
Read-only terminal state; may create a new Goal
No
The current objective and fixed constraints cannot both be satisfied.
stalled
controller
resume / edit / cancel
No
Consecutive checklist non-growth or tool-free work reaches the threshold.
achieved
Controller accepts evaluator result
Read-only; new objectives create a new run
No
Save evidence refs, gate results, and final usage.
budget_exhausted / failed
controller / runtime
Resume after adjusting budget, or edit/cancel
No
Budget exhaustion is recorded separately from execution/judgment errors.
Goal controls and Workflow compatibility fields
Starting and resuming in Web/TUI both submit ordinary chat. Role fields below apply only to compatible Workflow records; chat Goals hide role configuration and use the current session model.
The bottom Goal status bar opens details rather than acting as a static label. After page reload or worker restart, it restores objective text, status, checklist, usage, and last reason from durable projection. If the previous execution was lost, it shows paused_recoverableinstead of appearing to still run.
Web panels and TUI commands call the versioned Goal Action API; the interface does not duplicate state transitions, concurrency checks, or recovery rules.
Web · Composer Goal PanelInteraction design
◎ Goal · Paused after restart · 4/9
Research and complete a survey of large-model knowledgegoal_7f2a · run 2 · version 18
StateRecoverable pause: worker restart interrupted the previous turn
Recovery pointCreate a new execution from saved spec, checklist, and session evidence
Pending questions2 items; answer individually later without affecting independent source verification
ContinueEdit objectiveAdjust budgetTermination
TUI · /goalSame contract
$ /goal status
Goal [paused_recoverable]
Research and complete a survey of large-model knowledge
progress 4/9
usage 7 rounds · 38k tokens
reason worker restarted during round 8
$ /goal resume
Goal resumed as execution goal-exec-02.
$ /goal edit Narrow scope to knowledge editing and continual learning
Goal revision 3 saved; prior evidence retained.
$ /goal pause
Goal paused.
$ /goal
pending questions: 2
[?] scope: Include knowledge editing?
[?] date: What is the literature cutoff date?
$ /goal answer scope Include it
Goal answer saved; resuming from the latest checkpoint.
Editing a Goal increments revision and regenerates the current spec/checklist; old unanswered questions remain as superseded audit records and no longer block the new revision. Continue retains goal_id, cumulative usage, and question history while creating a new run_id. Pause, waiting, and restart recovery do not reset consumed budgets; waiting is excluded from active-time limits.
Implementation and acceptance contract
Independent specification review requires two contracts: genuine human dependencies enter waiting without being overridden by ordinary no-progress counters; successful Web actions immediately update visible state and shared cache from HTTP snapshots, and old events cannot roll back newer state. Repairs stay within Goal transitions and frontend projections without changing other workflows. Acceptance uses public Goal → answer-command regression plus action-response/remount tests without WebSocket broadcasts. The original reviewer must re-review repairs before independent quality review.
Genuine human dependencies are not overridden by no-progress counters; budget checks remain independent. The frontend uses shared updateSessionGoal to apply HTTP, WebSocket, and hydration snapshots by session version. Four component tests cover pause without broadcasts, remounting, out-of-order messages, background sessions, and late loading. All 229 Web tests, TypeScript, static checks, and the 32-page production build passed; independent specification re-reviews passed for waiting-state and frontend repairs. The build retains an existing Next SWC lockfile-repair warning; dependency lockfiles were unchanged.
Controller saves use CAS. Concurrent updates within the same run merge the latest confirmed snapshot, current-round state, and latest disk state under the session write lock, without unbounded retries. Merging permits only the same goal_id/run_id while the latest state is still executing; preserve budgets, new answers, current progress, and consumed answers. Pause, cancel, or run replacement still rejects stale-controller writes. Terminal saves use the same path; new answers invalidate an old terminal decision and save as paused_recoverable / answer_receivedso the user can continue handling them, without falsely reporting achieved. Answers consumed in batches all enter later work prompts. On subsequent resume, rebuild confirmed decisions from durable questions for the current revision and restore a bounded evidence window. Objective edits isolate old-revision decisions and evidence.
Independent quality re-review of the concurrency repair returned PASSand covered the original reproduction where budget edits caused controller exit while the UI still showed running. The reviewer independently passed 9 focused regressions: budget/answer races during evaluating/terminal, pause/cancel/run replacement, new answers during consumption, and old CAS rejection. Integrated Goal, storage, and Web API tests passed; full counts are below. This conclusion is limited to the reviewed repair and does not replace full post-repair verification, unimplemented design capabilities, or default-App visual acceptance.
The following ties requirements to public entry points and observable results. Local source, tests, and independent repair reviews do not imply full acceptance. Final integrated full tests passed, while default-App refresh and visual acceptance are recorded separately. Implementation descriptions below refer only to existing worktree code, not publication or fulfillment of every requirement.
Requirement
Public entry / evidence
Observable result
Current status
Single-prompt Goal with separate work and judgment
goal(prompt, ...); judge_goal()
Working Agent executes; inspection judge independently verifies and returns a typed verdict
Implemented with unit coverage
Difficult tasks do not continue indefinitely
round/token/active-time/cost budget; active-run usage cursor; stall and judge-failure guards
Enter respectively budget_exhausted, stalled, failed, blocked or impossible; other sessions' usage during waiting is excluded from the Goal
Implemented with boundary tests
Unattended operation continues independent work without interruption
Reload restores the complete projection; restart-interrupted state becomes paused_recoverable; resume creates a new run
Component tests passed; default App verified restart-recovery state, edit/reload, and actual Resume execution
Consistent Web and TUI controls
Goal dialog; /goal commands; the same Action API
Inspect objective, checklist, usage, and questions; edit, pause, answer, adjust budget, continue, and terminate
Type checks and automated tests passed; default App verified editing, budget, pause, resume, and completion judgment; the full asynchronous-answer interface flow is not yet accepted
Automatic external-event wakeup
Target: durable wait handle + scheduler event
Idempotent recovery after CI/job/timer completion without user resume
Not implemented
Multi-worker ownership of a shared state directory
ownership.goal_owner(); independent nonblocking OS file lock
Exclusive controller per same-machine store; startup reconciliation skips live siblings; crashes release the lock
Cross-process and abnormal-exit tests cover this; no cross-host distributed lease
Deterministic gates and independent evidence repository
Target: gate runner + evidence refs/repository
Reusable command checks precede the judge; complete evidence does not depend on session snapshots
python -m scripts.docs_site.build, followed by python -m scripts.docs_site.checklinks
Web verification: the judge has web-reading and search tools; failed receipts are marked is_error=true. Existing real-model checks were limited by arXiv's NON_GLOBAL_ADDRESS rejection and missing Tavily credentials. Network policy was not bypassed, and that research output cannot be treated as a source-verified survey.
Integrated code ran python -m pytest -q -n 4: 7015 passed, 18 skipped, 1 expected failure, including paused-execution identity and in-Runtime inspection fixes. The full run exposed and fixed Goal wrapper source-location problems; execution databases for two agent-contract suites were isolated per test so startup recovery would not read other tests' records. TUI tests: 148 passed, 2 skipped; type checks passed. Actual default-App evidence is recorded separately from automated tests.
Real-model verification: through the public programs run goal entry point, MiniMax-M3 wrote an approximately 300-character Chinese article, read the file for verification, and judged it; the command exited normally and the artifact was independently read and checked. This example used supplied facts without networking and cannot replace source verification. The earlier survey attempt remained limited by source access and search credentials and still cannot be delivered as a verified survey. Failed-receipt protection blocks metwhen inspection receipts contain errors, but does not prove all semantic judgments reliable.
The default App verified restart-recovery state, edit/save, reload, budget change, pause, and resume for a test Goal. Pause moved the corresponding canonical execution into cancellingand then stopped it as cancelled / cancel.user while the Goal remained recoverably paused. After resuming, judgment first rejected excess output and then accepted corrected output; the final Goal showed achieved, checklist 4/4, and 0 judgment-parse errors. This is actual acceptance for a short-text task, not verification of external research or every task type.
Within an existing Runtime, Goal refiner/judge use public agent(): each retains its tools, model, and phase label while sharing the current execution owner and creating no separate Job, avoiding global startup recovery on initial JobRunner creation misclassifying the outer live execution. Standalone session helpers without Runtime retain their original path. This local repair does not resolve other processes invoking global recovery. Execution-tree summaries still have a field-mapping defect: persisted LLM replies reside in raw_replybut summaries read output; empty input parameters do not imply lost responses. A separate display inconsistency shows Completed on a function-result row while canonical execution is cancelled; that summary label cannot prove successful execution.
Completion acceptance also found that generic execution-end recording did not consistently converge: the Goal was achievedbut repeated completed-write retries for its canonical execution left finish_repair_stalledand state remained running. This unresolved issue does not invalidate generated work or Goal judgment, but prevents claiming full execution-lifecycle acceptance.
Implementation status and evidence boundaries
Chat Goals use existing ordinary chat execution and durable completion notifications for continuation; display projections do not rewrite run intent. There are no default round or recovery-expiry limits, while explicit user limits remain. Shared history pairing, unknown-effect approval, durable deduplicated new turns, restricted Resume, incompatible-checkpoint handling, background Job continuation with original resource authorization, independent read-only completion acceptance, durable request attribution, late/partially unknown usage, concurrent hard-budget reservations, and joint settlement passed independent specification and quality reviews. Unified backend action conditions, explicit Verify, exact execution checks, crash-time lower bounds, and related-background-work completion restrictions also passed review. Complete Python, Web, CLI, Desktop, documentation checks and browser regressions after an independent build passed; skipped tests do not prove capabilities. Isolated-process interruption matrices for ordinary chat and Goals and macOS live-background-process reconnection have actual process evidence. This does not extend to Windows process survival, OS restart, cross-host takeover, or general external-event scheduling. Installed version, default-App visual acceptance, and remote commits require separate checks against the implementation ledger and actual source markers; source tests do not prove the local App was updated.
Evidence boundaries: unknown outcomes always remain in effect records; new side effects require one-time approval for the current operation, and ordinary chat recovery never reruns old tool calls. All Todo complete produces only an acceptance candidate. Independent ordinary chat checks actual reads or session evidence against the original objective and fixed requirements; before commit, recheck control version, evidence digest, related background processes, and execution state. The same inspected plan is not automatically accepted repeatedly. Request statistics retain Goal/revision/execution identity and prices; the durable ledger restores cumulative usage watermarks, child attribution, reservations, and joint settlement. Missing receipts remain unknown; old session statistics are not inferred into new attribution. Sudden executor loss counts only verifiable duration lower bounds and excludes downtime. Completion acceptance remains evidence-constrained model judgment, not a guarantee of absolute correctness.
Compatibility-path records, not evidence for the new design
Python Workflow work/refine/judge controllers and budget policies remain.
Versioned Goal snapshots, goal/run ID, CAS writes, and legacy reads exist.
Web/TUI controls and restart-pause state exist, with the recovery gaps described above.
Existing detailed diagrams remain as compatibility references and do not establish that chat uses a separate Workflow.
Extensions outside this design
Cross-host distributed execution leases, a general workflow engine, and an independent audit repository.
Automatic bulk rewriting of historical Goal costs or tool effects.
Exactly-once execution guarantees for arbitrary non-idempotent external operations.
Rerunning Python Workflow's independent judge on every ordinary chat turn.
Version boundaries:Local reference repositories provide reproducible code paths; official online documentation and public main branches establish later contracts. The local Hermes snapshot's basic GoalManager lacks upstream completion contracts, quality gates, and wait barriers, so those sections rely on public upstream source. Claude Code relies on official documentation.
Authoritative engineering design and implementation comparison for OpenProgram Goals. Product instructions are in Goal Workflow; unaccepted items here are not evidence of release or deployment.
Goal completion presentation
A terminal historical Goal stays at its existing conversation anchor as a compact, clickable status row. A successful Goal shows an animated Lucide check icon and Goal achieved in 9m 42s using that Goal's active elapsed time. Missing time does not become zero; interrupted time retains its lower-bound label. Other terminal states keep their actual status and never appear successful. The row opens the existing read-only historical Goal details. Canonical completion, acceptance and accounting remain authoritative; presentation does not infer completion from the assistant text or Todo counts.
Implementation status
The compact completion row uses recorded Goal status and active duration and opens the original read-only details. Component and browser checks cover this presentation; installed-App acceptance is part of the release verification record.
A new interactive owner turn in Auto or bypass evaluates uncertain effects only in its current execution subtree. A nested Runtime uses this same boundary only when immutable admission proves a chat from that owner: the stored actor is interactive owner, the integrity-checked chat payload has the same source, and current execution, session and principal match. Executor-thread submission carries the existing ContextVars so scope capture checks the same current execution before spawning. Runtime stays non-interactive and cannot grant approval. Missing or mismatched evidence retains the existing restriction; unreadable or corrupt recovery state fails closed. Unknown effects in the current subtree still require exact one-time approval. Old receipts are never resolved or replayed by this filter. Explicit ask/deny, source constraints, plan mode and exact Page binding continue to apply.
Acceptance: reproduce an old interrupted effect followed by a new owner activation through permission_decision and real nested Runtime gates; check Auto classification and bypass, exact current/descendant uncertainty, mismatched provenance, rules, and real subprocess Page access. The nested-scope correction is implemented. Independent specification and quality reviews, actual subprocess Page access, browser components, and the final combined verification pass. Skipped environment-dependent cases do not establish those capabilities. Installed-App acceptance is recorded separately in release evidence.