diff --git a/AGENTS.md b/AGENTS.md index 41fe3f6..1d9dd5d 100644 --- a/AGENTS.md +++ b/AGENTS.md @@ -44,6 +44,10 @@ consult faculties; faculties read their sensor organ; a conductor never consults another conductor — if it wants one's opinion, that opinion should be a faculty. The Build Agent is the reusable template for this pattern. +How much human checkpointing a workflow run needs is defined once in +[`AUTONOMY.md`](AUTONOMY.md) — the autonomy contract mapping each Mind-prompt +`Autonomy:` level to behaviour at every checkpoint. + ## Specialist reasoning agents Agents live in **two tiers** under `agents/`, distinguished by one question — diff --git a/AUTONOMY.md b/AUTONOMY.md new file mode 100644 index 0000000..b4e944a --- /dev/null +++ b/AUTONOMY.md @@ -0,0 +1,118 @@ +# The autonomy contract + +The **one canonical page** for how much human checkpointing a workflow run +needs. Mind prompts carry `Autonomy: safe | supervised | human-required` in +their header (written at conception by the Intake Agent via the sizing +faculty — `PyAutoMind/README.md` "Prompt file format"); this page defines what +those levels *do* at each checkpoint. Every workflow skill links here instead +of restating checkpoint rules — if you are editing autonomy prose anywhere +else, stop and edit this file. + +Levels are consumed **only as defined here**. A level is an input to a gate, +never a bypass of one. + +## The checkpoints + +Where the dev workflow stops for a human today: + +| # | Checkpoint | Lives in | +|---|------------|----------| +| 1 | **Plan approval** — present the plan, wait for explicit approval before any edit | `start_dev` (Plan Mode) | +| 2 | **Ship PR sign-off** — review of `## API Changes` / `## Scripts Changed` before commit/push/PR | `ship_library` / `ship_workspace` | +| 3 | **Heart YELLOW acknowledgement** — warnings surfaced, proceed only on explicit go-ahead | ship gate (`skills/WORKFLOW.md` "Heart readiness gate") | +| 4 | **Merge / issue close** — offered after shipping, never automatic | post-ship | +| 5 | **Version ask** — the minor-version choice | `pre_build` | +| 6 | **Post-merge cleanup confirmation** — worktree removal, branch deletion, registry moves | `ship_*` cleanup | + +## Levels × checkpoints + +| Checkpoint | `safe` | `supervised` | `human-required` | +|------------|--------|--------------|------------------| +| Plan approval | write plan to the issue, proceed | write plan to the issue, proceed | present + wait | +| Ship PR sign-off | proceed through the autonomous-ship gate; end at PR-open | park (`awaiting-input`), question to the issue, continue elsewhere | present + wait | +| Heart YELLOW | park — human checkpoint at **every** level | park | present + wait | +| Heart RED | stop, report | stop, report | stop, report | +| Merge / close | human, always | human, always | human, always | +| Version ask | n/a — release is always `human-required` | n/a | ask | +| Cleanup | proceed + log | proceed + log | confirm | + +The difference between `safe` and `supervised` is the ship step and judgment +gates: `safe` runs end-to-end to an open PR; `supervised` proceeds wherever the +path is mechanical but converts each judgment gate into a batched question on +the issue and moves on (**checkpoint-and-continue** — the question is written +with enough context to answer cold, the task parks as `awaiting-input` in +`active.md`, and the session advances to the next independent step or task +rather than blocking). + +## Per-work-type caps + +A prompt's header never exceeds its work-type cap. The **effective level** is +`min(header, cap)`; a missing header means `human-required`. + +| Work-type | Cap | Why | +|-----------|-----|-----| +| `refactor`, `test`, `maintenance` | `safe` | behaviour-preserving by definition; tests + review are a near-complete gate | +| `feature`, `bug`, `docs` | `supervised` | until the calibration log justifies raising | +| `research`, `experiment` | `supervised` | output is judgment-shaped | +| `release` | `human-required` | always; no autonomy level ships a release | + +Raising a cap is a doctrine edit to this page and must cite calibration-log +evidence. + +## Activation + +- Levels bind **only** when the human launches with an explicit `--auto`. + Default invocations behave exactly as before this page existed — + present-and-wait at every checkpoint. +- Opt-in per invocation, never ambient: no config flag, no environment + variable, no "remembered" mode. + +## The autonomous-ship gate + +An unattended ship (checkpoint 2 at `safe`) requires **all four**, no +substitutions: + +1. worktree pytest on the affected repos (full suite), +2. the curated smoke-test subset, +3. review-faculty verdict **CLEAN**, +4. Heart **GREEN**. + +The gate's audit and precise composition are `PyAutoMind/feature/autonomy/` +task 3; the review faculty is task 2. **Until both land, no run ships +unattended** — `--auto` ends at ship sign-off regardless of level. A failed +gate downgrades the run to a human checkpoint: state written to the issue, +nothing force-shipped. + +## Calibration log + +`PyAutoMind/autonomy_log.md` — append-only. Every `--auto` run appends a row +at PR-open (or on parking): + +```markdown +| date | task | effective level | gates (tests/smoke/review/heart) | outcome | +``` + +Outcome ∈ `merged-unchanged` / `amended` / `rejected` / `parked`. This is the +evidence base for raising or lowering caps — autonomy grows by demonstrated +calibration, not by optimism. + +## Hard invariants (every level, no exceptions) + +- **Merge and issue-close are human acts.** An explicit future flag may extend + autonomy to merge; it does not exist and must not be assumed. +- **Autonomous runs end at PR-open**, with the PR body carrying the plan, the + review verdict, test/smoke counts, and a validation checklist. +- **Never modify code to make tests or smoke tests pass.** +- **Heart YELLOW/RED is never acknowledged autonomously.** +- **Never rewrite history** (`AGENTS.md` rules apply verbatim to autonomous + runs). +- The `Autonomy:` header is a model's own estimate. The caps, the explicit + `--auto` launch, and the calibration log are what make consuming it + defensible — none of the three is optional. + +## Consumers + +Today: **none** — this page is doctrine ahead of implementation, by design. +Consumption lands with the `PyAutoMind/feature/autonomy/` series: task 4 +(`--auto` through `start_dev → ship_*`), task 5 (checkpoint-and-continue), +task 7 (queue runner). Skills must link here rather than copying the tables. diff --git a/skills/WORKFLOW.md b/skills/WORKFLOW.md index 0a951b7..db5a713 100644 --- a/skills/WORKFLOW.md +++ b/skills/WORKFLOW.md @@ -40,6 +40,18 @@ directly; it asks the vitals faculty, and only the vitals faculty talks to the H organ. The same applies when the dev workflow consults the vitals faculty for its ship gate. +## Autonomy (how much human checkpointing) + +The human checkpoints across these skills — plan approval, ship PR sign-off, +Heart YELLOW acknowledgement, merge/close, the `pre_build` version ask, +post-merge cleanup — are governed by **the autonomy contract**, +[`../AUTONOMY.md`](../AUTONOMY.md): what each Mind-prompt `Autonomy:` level +(`safe`/`supervised`/`human-required`) does at each checkpoint, the +per-work-type caps, and the hard invariants (merge is always human; autonomous +runs end at PR-open). Levels bind **only** under an explicit `--auto` launch; +default runs present-and-wait at every checkpoint, exactly as the steps below +describe. Do not restate checkpoint rules in a skill body — link the contract. + ## Brain agent entry points Reasoning is delegated to PyAutoBrain agents (`PyAutoBrain/AGENTS.md` is authoritative): @@ -59,13 +71,20 @@ When `pyauto-brain` is not on `PATH` and no PyAutoBrain checkout is present (e.g. a GitHub-only session), perform the same reasoning inline following this file and `PyAutoBrain/AGENTS.md`, and note that the agent was emulated. -## Model delegation (Opus plans, Sonnet executes) +## Model delegation (judgment tier plans, execution tier ships) + +The workflow skills split work across **model tiers**, not named models — the +doctrine survives model access changing: + +- **Judgment tier** — the strongest model available to the session (currently + **Fable 5**; previously, and as fallback, **Opus**). Planning, orchestration, + risk judgment, anything user-facing. +- **Execution tier** — a fast, cheap model (currently **Sonnet**) for + mechanical shell/git phases, delegated as subagents (`Agent` tool, + `model: "sonnet"`). -The workflow skills follow a **"plan in Opus, execute in Sonnet"** split: the main -session stays on Opus for planning, judgment and orchestration; mechanical -shell/git phases are delegated to Sonnet subagents (`Agent` tool, -`model: "sonnet"`). This keeps judgement in the stronger model while moving bulk -execution to the faster, cheaper one — no manual model toggling. +The main session stays on the judgment tier; bulk execution moves to the +execution tier — no manual model toggling. **Delegated (mechanical phase only):** @@ -74,7 +93,7 @@ execution to the faster, cheaper one — no manual model toggling. - `pre_build` — step 2 (format, generate, version bump, stage, commit, push, dispatch workflow). -**Stays in Opus:** planning (`start_dev`), environment setup +**Stays in the judgment tier:** planning (`start_dev`), environment setup (`start_library`/`start_workspace`), release triage (`review_release`); identifying affected repos, drafting the commit message and full PR body (`## API Changes` / `## Scripts Changed`), workspace-impact analysis, the @@ -84,9 +103,9 @@ asking for the minor version, printing the summary. **Subagent prompt contract (all delegated calls):** -- **Inputs Opus passes:** worktree path / `$WT_ROOT`, repo list, pre-drafted - commit message, pre-drafted PR body (paste verbatim via HEREDOC — never - rewrite), relevant URLs (library PR, issue), target branch, labels. +- **Inputs the judgment tier passes:** worktree path / `$WT_ROOT`, repo list, + pre-drafted commit message, pre-drafted PR body (paste verbatim via HEREDOC — + never rewrite), relevant URLs (library PR, issue), target branch, labels. - **Subagent's job:** run the named shell steps exactly. `source activate.sh` before `pytest` / `smoke_test`. Verify the branch is `feature/` before committing — never auto-switch branches. **Never modify code to make @@ -94,21 +113,22 @@ asking for the minor version, printing the summary. (failing test names + traceback tail, or the shell error). - **Subagent returns:** one line per repo — test/smoke pass-fail counts, commit SHA, PR URL, cross-reference/dispatch confirmations. -- **Opus after return:** interpret failures, decide routing, update registries, - talk to the user. +- **Judgment tier after return:** interpret failures, decide routing, update + registries, talk to the user. **Tutorial-prose split** (separate from skill delegation — depends on what the reader is there to learn): -- **Opus** for narrative science-teaching scripts where the docstrings/comments - are the product: tutorials in `autofit_workspace`, `autogalaxy_workspace`, - `autolens_workspace` (`overview_*`, `start_here.py`, `howto*`). Sonnet drifts - to generic textbook phrasing and misses domain framing here. -- **Sonnet** for code-heavy, doc-light scripts where comments are short +- **Judgment tier** for narrative science-teaching scripts where the + docstrings/comments are the product: tutorials in `autofit_workspace`, + `autogalaxy_workspace`, `autolens_workspace` (`overview_*`, `start_here.py`, + `howto*`). Execution-tier models drift to generic textbook phrasing and miss + domain framing here. +- **Execution tier** for code-heavy, doc-light scripts where comments are short API-usage notes: `*_workspace_test`, `euclid_strong_lens_modeling_pipeline` glue, and developer/regression/smoke/parity scripts. - Heuristic: *"is the reader here to learn science, or to exercise code?"* - Science → Opus. Code → Sonnet. + Science → judgment tier. Code → execution tier. ## Consult Memory before substantial planning @@ -127,7 +147,9 @@ pyauto-heart readiness --json # authoritative GREEN / YELLOW / RED verdict ``` - **GREEN** → proceed to execution. -- **YELLOW** → surface the warnings; proceed only with explicit user acknowledgement. +- **YELLOW** → surface the warnings; proceed only with explicit user + acknowledgement (a human checkpoint at **every** autonomy level — + [`../AUTONOMY.md`](../AUTONOMY.md)). - **RED** → stop; report what failed. Do not ship. Tests/smoke runs that feed the verdict are Heart's domain — invoke them through @@ -138,11 +160,12 @@ the vitals faculty rather than re-deriving pass/fail criteria in the skill. - `/name` references mean "use that skill"; a harness without slash commands follows the same body file directly. - "Plan Mode" means: present the plan and wait for explicit user approval - before any file edit. + before any file edit (checkpoint 1 of [`../AUTONOMY.md`](../AUTONOMY.md); + under an explicit `--auto` launch the contract's level table applies). - If the user gives a development task with **no** PyAutoMind prompt path, first write a concise prompt under the right `//` folder (original request verbatim), then continue with that path. -- Where a body delegates mechanical execution to a Sonnet subagent, a harness +- Where a body delegates mechanical execution to an execution-tier subagent, a harness without subagents performs the same steps directly, preserving the judgment/mechanical split above.