← Về thư mục
📄 / / profiles / r-and-d / raw_evidence / OpenAI4S / docs / auto-mode.md

Auto Mode product and terminal-state contract

Status: Stage 0 contract plus Stages 1–12 implemented as independent, default-off rollout opt-ins.

This document freezes the product truth implemented by Stages 1–12. Each stage is an independent, default-off rollout opt-in: enabling a later stage never implicitly enables an earlier one. Stage 1 consumes only stage1_trusted_delivery. Stage 2 consumes only stage2_auto_run_storage. Stage 3 consumes only stage3_scientific_review_shadow and records a shadow judgment without gating completion. Stage 4 consumes only stage4_review_completion_gate and does gate completion: with it on and result_review_mode not off, the candidate is streamed provisional and its exact canonical assistant row is committed with review_status=candidate before the verdict. It cannot look Verified until exact CAS promotion succeeds. The gate calls Stage 5 when result_review_mode=auto_fix and stage5_auto_repair is on: a repaired candidate is returned as the answer to deliver, not merely as a reason to withhold Verified. A repaired answer without a newly persisted independent pass remains explicitly unverified. Stages 6–12 likewise consume only their own flags and are described in their own sections; the configuration guide lists the behavior behind every flag.

The existing review:auto:<frame> setting remains the old single-call, post-completion Reviewer. It records an ordinary review step after the final answer and does not gate completion. It must not be described as the Auto Mode defined here.

Stage 1 delivery boundary

OPENAI4S_STAGE1_TRUSTED_DELIVERY=1 enables three prerequisites without enabling Auto Mode:

The flag remains off by default. It does not select review_only, auto_fix, or auto_review; create a candidate, finding, or permission decision; or alter the non-negotiable Reviewer/Repair/Guardian safety invariants below.

Product modes

Result review and permission review are separate control planes:

Setting Closed vocabulary Stage 0 default Contract
result_review_mode off, review_only, auto_fix off Whether a candidate is scientifically reviewed and whether findings may start a repair loop.
approvals_reviewer user, auto_review user Who resolves actions that the deterministic permission policy classified as ask. It cannot override a hard deny.
Auto Mode preset off, on/autonomous off The autonomous preset always normalizes to auto_fix + auto_review and the bounded budget ceiling below. It is not a third independent switch, is not full access, and never weakens another safety layer.

Config.auto_mode parses and normalizes these values. Runtime consumption remains behind the corresponding independent rollout flags: Stage 2 resolves and persists the selection, Stages 3–5 apply result-review behavior, Stage 6 records shadow advice on deterministic ask decisions, and Stage 7 consumes the approval reviewer for unattended enforcement. A selection alone does not enable one of those stages. Unknown boolean spellings and unknown enum values reject configuration; an explicitly empty value also rejects rather than meaning off. When the preset is on, contradictory explicit sub-mode values are normalized to auto_fix and auto_review. When it is off, the two sub-modes remain independently selectable.

Scope and precedence

The Stage 2 durable resolver applies one selection source, in this order:

  1. An imported/quarantined session forces the preset off, result_review_mode=off, and approvals_reviewer=user until an explicit fresh continuation is created. Historical labels remain read-only facts.
  2. An explicit frame selection overrides its project's selection.
  3. An explicit project selection overrides an explicitly configured deployment default.
  4. An explicitly configured deployment value overrides legacy compatibility.
  5. Only when no new selection exists, the old review:auto:{root_frame_id} boolean maps to result_review_mode=review_only. It can never select auto_fix, approvals_reviewer=auto_review, or the Auto Mode preset.
  6. With no source, the built-in values are preset off, result review off, and user approval.

An unset deployment value is not an explicit off; this distinction prevents the built-in default from erasing a legacy frame preference during migration. Sandbox, egress, biosecurity, secret/credential, cost, and deterministic permission policy are outside this selection order and always take precedence.

Frozen bounded budgets

These are hard ceilings for the autonomous preset. A deployment default and, later, project/frame policy may tighten the monotonic limits but cannot loosen them. The rolling circuit window stays fixed at 50 so changing its denominator cannot ambiguously weaken the rate threshold. A component consumes its budget only when that component's rollout stage is enabled.

Limit Default ceiling Environment variable
Reviewer attempts per candidate, including at most one transient retry 2 OPENAI4S_AUTO_MAX_REVIEW_ROUNDS
Repair rounds 2 OPENAI4S_AUTO_MAX_REPAIR_ROUNDS
Repair Agent turns per round 12 OPENAI4S_AUTO_REPAIR_TURNS_PER_ROUND
Additional Cells 30 OPENAI4S_AUTO_MAX_EXTRA_CELLS
Auto Run wall time 900 seconds OPENAI4S_AUTO_WALL_TIME_S
Additional token budget relative to the initial turn 1.5× OPENAI4S_AUTO_EXTRA_TOKEN_MULTIPLIER
Repeated unchanged finding 2 OPENAI4S_AUTO_REPEATED_FINDING_LIMIT
Same action digest without a durable delta 3 OPENAI4S_AUTO_SAME_ACTION_NO_DELTA_LIMIT
Turns without Artifact/Plan/Evidence progress 5 OPENAI4S_AUTO_NO_PROGRESS_TURN_LIMIT
Guardian decision timeout 90 seconds OPENAI4S_AUTO_GUARDIAN_TIMEOUT_S
Consecutive Guardian denials before circuit-open 3 OPENAI4S_AUTO_GUARDIAN_CONSECUTIVE_DENIAL_LIMIT
Guardian rolling circuit window 50 decisions OPENAI4S_AUTO_GUARDIAN_WINDOW_SIZE
Denials in that window before circuit-open 10 OPENAI4S_AUTO_GUARDIAN_WINDOW_DENIAL_LIMIT

A limit is checked before admitting the next action and is recorded in the Auto Run. Reaching a token, cost, time, turn, cell, review, or repair hard limit forbids new autonomous actions. With a durable issues verdict and unresolved findings, a review/repair limit stops as completed_with_issues(stop_reason=budget_exhausted); exhausted Reviewer availability attempts stop as review_unavailable; a Guardian timeout stops as blocked_by_guardian. A limit outside those state-specific terminals commits terminal_reason=budget_exhausted with Paused · Budget exhausted user truth. No limit silently replenishes itself on reopen. Repeated-finding, same-action/no-delta, and no-progress limits open a durable no-progress circuit. With unresolved review findings this stops as completed_with_issues(stop_reason=loop_detected); a Guardian-denial loop stops as blocked_by_guardian(stop_reason=loop_detected); a loop before either domain has a terminal fact uses the existing terminal_reason=loop_detected. Every projection names Loop detected, and none silently resubmits the same finding or action. Guardian timeout fails the proposed action closed. Either Guardian denial threshold opens its durable denial circuit. Cancellation remains separate and Auto Mode never resumes it.

Finding identity

A finding has two keys and they answer different questions. Its fingerprint is content only -- severity, category, claim and evidence refs -- because Stage 5 compares fingerprints across repair rounds to notice that a finding did not go away. Its identity (finding_id) is that content within one review run, so two sessions that reach the same conclusion record two findings rather than colliding on one row. review_findings.finding_id is globally unique, and must stay so: session import resolves a finding's owner by id alone.

Deriving the identity from content alone made the two keys the same key. The second session to reach a given conclusion failed its complete_review insert on the primary key, its Auto Run stayed in reviewing, and the branch refused every later turn -- and a recurring wrong claim is precisely the finding most likely to recur.

State vocabulary and sole entry conditions

These names belong to one Auto Run. A run is identified by root_frame_id + branch_id + turn_id + execution_id; a candidate additionally has an immutable candidate/snapshot identity. Terminal state is a committed fact, not text inferred from an assistant message or a transient WebSocket event.

candidate

verified

completed_with_issues

review_unavailable

blocked_by_guardian

Deterministic controls always run before Guardian, but the subsystem that stopped an action does not by itself choose the terminal label. The committed reason does. These non-Guardian terminal truths remain outside the five Auto Mode states:

Stage 7's credential-shaped file fence is one such deterministic control. It may promote a permissive file rule to ask, but a headless refusal and its audit remain attributed to policy rather than being relabelled as a Guardian verdict. With an attached channel, the same ask can be reviewed by a human.

Durable terminal reason Sole trigger and user truth
policy_requires_explicit_setup A dangerous/unknown tool, non-canonicalizable target, or deterministic policy conflict refused the unexecuted action and its refusal audit committed. UI: Blocked · Policy requires explicit setup. A plain egress allowlist refusal may use this reason; it is not a Guardian verdict.
budget_exhausted A token, cost, time, turn, cell, or other hard budget denied admission of the next action outside a state-specific result-review or Guardian terminal. UI: Paused · Budget exhausted, naming the exhausted counter without silently replenishing it. An open-finding review/repair stop instead uses completed_with_issues(stop_reason=budget_exhausted).
safe_rollback_unavailable Auto Repair could not commit its pre-repair checkpoint, encountered a branch conflict, or could not prove that the proposed repair remains inside its authorized mutation set. Repair never starts. UI: Blocked · Safe rollback unavailable. A real sandbox/path escape is the higher-priority safety boundary below.
outcome_unknown An external write or remote side effect may have committed, bounded readback/reconciliation still cannot determine output_committed, and the action therefore cannot be safely retried. UI: Needs review · Outcome unknown.
loop_detected Repeated finding/action/no-delta behavior reached its durable circuit outside a result-review or Guardian terminal. UI: Paused/Blocked · Loop detected. When a review finding or Guardian denial owns the loop, the corresponding five-state terminal carries stop_reason=loop_detected instead.
safety_boundary A secret/credential probe or sensitive exfiltration, sandbox/path escape, failure to persist a required audit, immutable snapshot/reference integrity failure, or exact-action/review digest mismatch occurred. UI: Failed · Safety boundary.

Egress, biosecurity, credential, cost, and sandbox controls all retain priority over model decisions, but their durable reason must select the truthful row above instead of being labelled from the subsystem name. In particular, permission/action audit failure and exact-action mismatch are never Guardian decisions; result-review audit or immutable-evidence integrity failure is never review unavailability. User cancellation and ordinary Agent failure also keep their existing meanings. None of these terminals may be remapped to one of the five states merely to make an Auto Run look complete.

Durable sources and projection truth

Stages 2–7 make the following records authoritative when their corresponding rollout flag is enabled. A disabled stage projects no claim from its rows.

Fact Durable source required before the fact may be shown
Candidate identity and phase auto_mode_runs candidate pointer plus immutable Evidence Snapshot and committed candidate_ready event.
Verified / issues / unavailable result review_runs, review_findings, snapshot/evidence hashes, and the committed auto_run_terminal transition.
Repair claim repair_runs, exact before/after Artifact versions, execution ledger, and a later independent review; a repair row alone never proves success.
Guardian decision permission_review_assessments bound to the existing ask decision, exact action digest, policy/prompt/model versions, and the permission/action audit transaction. If that audit cannot commit, no Guardian fact is projected; the action fails closed as a safety-boundary failure.
Final Auto Run status auto_mode_runs plus its idempotent terminal event, tied to the same run and branch identities.

SQLite is the source of truth. WebSocket events are notification hints. An assistant message, step title, badge cached in browser memory, or model-produced JSON is never enough to reconstruct a status.

Provider/session timeout and parse/schema failures may project Unavailable only when their required failure records and terminal transition committed. If a required audit row is missing, references a different candidate/version, fails immutable-hash validation, or cannot be reconciled after restart, projections fail closed to the separate safety-boundary failure, never Unavailable or Verified.

Failure to provision a Reviewer/session that satisfies the run's frozen independence policy follows the same durable Unavailable projection with reason=reviewer_independence_unavailable; it is a pre-inference availability failure, so retrying a model response cannot cure it. By contrast, a review row whose actor produced, repaired, or may promote the candidate, or whose frozen identity/fingerprint binding has drifted, is identity-integrity evidence of an invalid transition and projects the separate safety-boundary failure.

A complete, hash-valid snapshot whose read-only evidence adapter still cannot cover required material after its bounded attempts projects Unavailable with reason=evidence_incomplete. Every attempt durably names the missing coverage; neither the model nor the projector may fill the gap from prose. Failure to construct/freeze the snapshot itself, or any structural, hash, or immutable-ref integrity failure, instead projects the separate safety-boundary failure.

Projection also validates the review/findings set as one fact. A durable pass with any open, claimed, or unaddressed material finding is contradictory integrity evidence and projects the separate safety-boundary failure. It is not repaired by trusting one row over another, coercing the verdict, or hiding the finding.

Canonical API and event names

Stage 0 originally reserved exactly these versioned routes. Subsequent opt-in stages implement them, and these remain their only canonical route names:

There is no unversioned or alternate route alias. The new event types are auto_run_started, candidate_ready, auto_audit_started, auto_audit_completed, repair_started, repair_completed, and auto_run_terminal. Result and permission audits use the same two canonical auto_audit_* types with subject_kind=result_review or subject_kind=permission_review; review/Guardian-specific phrases are not additional wire or storage event names. The existing permission_resolved event remains the sole permission-resolution type and carries resolution_actor and audit_id after the durable transaction commits.

The audit subject has two orthogonal, closed-vocabulary fields. subject_kind names the control plane (result_review or permission_review), while subject_entity_kind names the exact entity under assessment. Their only valid pairings are result_review + candidate_evidence_snapshot and permission_review + approval_action. Entity names never appear in subject_kind, and neither field creates another event alias.

Every auto_audit_started and matching auto_audit_completed event carries the same audit_id, subject fields, and audit_request_digest. That digest is the canonical digest of the immutable audit request and its subject bindings only; it never incorporates or stands in for the result. Completion separately carries the canonical assessment plus assessment_digest. The assessment digest binds the request digest, subject fields, attempt, verdict/decision, findings, risk, authorization, outcome, rationale, failure, and completion bookkeeping such as durability and retry state. The two digests have different meanings and must never be reused, substituted, or mixed; a completion whose assessment does not rehash to its assessment_digest fails closed.

Every durable transition has one event id. WebSocket delivery is a projection of that committed fact, never a second event and never the authority for recovery.

Reopen, share, export, and import

Recovery contract

Last durable state Allowed recovery Forbidden recovery
candidate Resume/retry review from the same immutable Evidence Snapshot, or explicitly start a new candidate from a safe checkpoint. Re-run already committed side effects merely because a response was lost; infer pass from old prose.
verified Rebuild the projection from durable review evidence. Any requested change starts a new candidate/review identity. Mutate the reviewed versions in place; let recovery or the Repair Agent self-certify the change.
completed_with_issues Preserve findings and best versions; an explicit continuation may create a new Repair Run from a verified checkpoint and must be independently re-reviewed. Hide findings, silently spend a fresh budget on reopen, or relabel user acceptance as Verified.
review_unavailable Explicitly retry review against the unchanged snapshot under the bounded retry/restart policy; configure an eligible independent Reviewer before a fresh continuation for reviewer_independence_unavailable; provide the missing read-only adapter coverage without mutating the snapshot for evidence_incomplete; or create a fresh run. Treat provider/timeout/parse/independence/coverage failure as pass; publish a Verified badge without a later admissible verdict; invent or silently omit missing coverage; use this state to conceal an audit-persistence, snapshot-construction/hash/ref, self-review, or frozen-identity integrity failure.
blocked_by_guardian Show the denial and require a fresh continuation. A user/administrator may establish an exact, narrow policy before that continuation. Replay the refused action; reuse an old one-shot grant; let Guardian create a standing allow; weaken sandbox/egress/secret/biosecurity/cost policy.
policy_requires_explicit_setup A user/administrator may establish an exact, narrow policy or supported canonical target, then create a fresh continuation whose action is newly reviewed and hashed. Rename, split, or otherwise work around the refusal; attribute it to Guardian; execute the refused action under an old decision.
budget_exhausted Preserve the run and its exact counters. Only an explicit fresh continuation under an authorized budget may admit more work. Refill a budget on restart/reopen, hide the exhausted counter, or continue in the same run.
safe_rollback_unavailable Establish a valid checkpoint, resolve the branch conflict, and start a new Repair Run from that proven state. Let Repair touch the formal workspace without rollback, widen its mutation set, or treat a path escape as an ordinary conflict.
outcome_unknown Continue bounded readback/reconciliation or hand the durable evidence to a user/operator; a later confirmed outcome is appended, never guessed. Blindly retry, claim success/failure without readback, or reuse the prior one-shot authorization for a second effect.
loop_detected Require an explicit materially different continuation; preserve the repeated finding/action fingerprints and counters. Resubmit the same finding/action, reset the circuit on reopen, or fragment a denied action to evade the fingerprint.
Existing failure with terminal_reason=safety_boundary Repair audit persistence, immutable-evidence construction, Reviewer identity binding, or the violated hard boundary, then explicitly create a fresh continuation from a verified checkpoint. Any proposed action is newly authorized and hashed. Attribute the integrity/hard-boundary failure to Guardian/Reviewer unavailability; replay a refused/mismatched action; infer an audit record that never committed; reuse an evidence snapshot whose immutable hash failed, a self-review whose actor was ineligible, or a pass that still has an unresolved material finding.

All recovery transitions are idempotent. After daemon restart, committed external effects are reconciled/read back rather than blindly retried. A one-shot action capability is atomically consumed and bound to its exact action digest, run context, generation, expiry, and max_uses=1.

Non-negotiable invariants

See Architecture, Configuration, and the Web App API contract for the Stage 1 implementation boundary.