ax:retro - guided experiment-loop session
Closes the self-improvement loop. Claude orchestrates ax improve …
commands; the user decides each row.
Assumes ax (axctl) is on PATH. If ax improve list fails, tell the user
to check docs/development.md#setup (DuckDB dylib setup - no daemon
required) and stop.
When to fire
ONLY fire on explicit triggers:
- "let's do an ax retro" / "ax retrospective" / "retro time"
- "review my ax proposals" / "triage proposals"
- "what's my experiment loop status" / "lock pending verdicts"
- "hook effectiveness review" / "intervention review"
- "self-improvement session"
/ax:retro slash command (if the plugin marketplace publishes one)
Do NOT fire on a generic "look at my recent work" - that risks dragging
unrelated context into the loop.
Defaults
- Window for hook signals: last 7 days. Widen to 30 if evidence is sparse.
- Don't apply changes silently. Every accept/reject/verdict gets the
user's explicit yes per row.
- The retro is read-mostly. Its side-effects are the Step 1 checkpoint
measurements, the task briefs
accept emits, and verdict locks.
Workflow
Step 0 - Drain pending session retros
Before the proposal queue, check whether prior sessions still owe a
retro. This is the "quota arbitrage" path - idle Opus budget chews
through the backlog so the experiment loop has signal next time.
Run:
ax retro pending --since=7 --idle-min=30 --json
Returns sessions in the last 7 days that have no reviewed graph
edge yet AND look finished (explicit ended_at, or last turn is
30min idle). If the list is empty, skip to Step 1.
Show the list to the user as 1 line per session (project · turns ·
model · reason). Ask:
N session(s) pending retro. Want me to dispatch the
retro-reviewer subagent for all of them in parallel, or pick a
subset?
On all or <subset>: for each chosen session, write a brief:
ax retro brief --session=<session_id>
This writes .ax/tasks/retro/<key>.md with frontmatter (transcript
path, suggested model, turn count, etc.) and a body that tells the
reviewer what to do.
Dispatch one retro-reviewer subagent per brief, in parallel. Pass
each brief path in the prompt; let the subagent's frontmatter pin
model: opus (override per session if suggested_model differs and
the user asked you to economize).
If the retro-reviewer subagent type doesn't resolve (not installed,
or the active harness is not Claude Code), read and review the brief INLINE
using its required-output instructions instead of abandoning the backlog.
Wait for all subagents. Aggregate results: counts of retros emitted,
proposals recommended, model-fit suggestions. Render as a short
summary. The user does not approve retro emissions per row - the
subagent already wrote them. The user DOES decide on resulting
proposals in Step 2.
The reviewed edge now exists for each drained session, so a
re-run of ax retro pending should show fewer rows.
If the user declines Step 0, move on. The backlog stays - next retro
picks it up.
Step 1 - Snapshot
Measure first, then read. The checkpoint pass is what turns due windows
into current ones; a verdict read taken before it reports whatever the
last run happened to leave behind.
Run the prerequisite ALONE and wait for it:
AX_NO_AUTO_INGEST=1 ax improve checkpoint --json
It reads the published snapshot and writes checkpoint judgments only -
no transcript parsing, no guidance edits, no verdict locks. Leave
--force out of an ordinary retro; it rewrites unreviewed windows that
are already current.
On success, run the reads (parallel is fine). Prefix EVERY command -
a prefix on the first one leaves the freshness drive on for the rest:
AX_NO_AUTO_INGEST=1 ax improve list --status=open --json
AX_NO_AUTO_INGEST=1 ax improve list --status=accepted --json
AX_NO_AUTO_INGEST=1 ax improve verdict --json
AX_NO_AUTO_INGEST=1 ax retro list --since=7 --json # cluster-derived friction summary
AX_NO_AUTO_INGEST=1 ax hooks summary --since=7 --tail=20 # optional; tolerate failure
If the checkpoint run fails, tell the user measurement is unavailable
and continue with proposal review only. Any suggestion already stored
belongs to an earlier run - report it as that, and skip the verdict
step.
If the checkpoint result reports cacheRefreshRequired above zero, the
opportunity evidence needs deriving; say so, and treat those
experiments as unmeasured. When the user asks for current evidence, run
three operations in order, each awaited on its own: ax ingest (wait
for successful publication), the checkpoint prerequisite, then the
reads.
ax retro list reflects three pattern types now:
- tool failures (skill form) ->
Pre-<Tool> guard proposals
- correction pressure (guidance form) -> "Reduce recurring user
corrections" proposals targeting
CLAUDE.md
- friction kinds (skill form, one per kind) ->
Address recurring <kind> friction proposals
If any of those surfaced, mention them so the user knows to triage in
Step 2.
Compute counts: open proposals (by form), accepted experiments with
locked_verdict IS NONE, and - separately - experiments whose current
view carries a current_reason (insufficient data or a lifecycle state).
Then render to the user as 2-4 lines, e.g.:
7 open proposals (3 skill, 4 guidance). 2 accepted experiments are
waiting on a verdict. Hook activity last 7d: 142 invocations, 3
blocking errors. Want to triage proposals first, lock the pending
verdicts, or skim hook signals?
If both proposal/verdict queues are empty: tell the user nothing's due
and offer ax ingest --derive-only to refresh evidence.
Step 2 - Triage open proposals
Order open proposals by frequency desc. For each, in turn:
Run ax improve show <dedupe_sig> --json (or reuse the row from
step 1).
Render as 3-5 lines. Example for a skill proposal:
Schema change guardrail (skill · freq=9 · confidence=high)
Hypothesis: schema edits often surface in fix-chains within ~14d.
Trigger: fix commits overlap schema files.
Behavior: run schema lint + one read/write smoke before edit.
Ask the user: accept, reject, or skip.
Branch:
- accept → run
ax improve accept <dedupe_sig>.
By default this emits a TASK BRIEF and returns its task_path; it
does not install the artifact. Report that path.
Offer: "Want me to implement the brief now?"
If yes: implement it, then run ax improve lint so ax reconciles the
marker it finds on disk and records the installed artifact. Until
lint records one, the experiment has no measurable installation.
- reject → ask for a short reason (≤80 chars).
Run
ax improve reject <dedupe_sig> --reason "<reason>".
- skip → no command. Move on; the proposal stays open for the
next retro.
After the loop, summarize: "Accepted 3, rejected 1, skipped 2."
Step 3 - Verdict review
For each experiment whose latest checkpoint is unlocked
(locked_verdict IS NONE), in age order:
Run AX_NO_AUTO_INGEST=1 ax improve verdict <dedupe_sig> to fetch the
experiment + checkpoint history.
When the current view carries a current_reason, there is no
suggestion to confirm. Report the reason as it is - no opportunities in the window, no detector for this form, retired - and move to
the next experiment. A suggestion in the checkpoints history is
history, not a recommendation.
Otherwise render the current checkpoint as 2-3 lines:
Schema change guardrail - +30s checkpoint
12 opportunities in window, 8 addressed (66%) - observed use.
Suggested: adopted.
Ask the user to confirm the suggested verdict OR override:
adopted (artifact is doing real work)
ignored (user wrote it but never invoked it)
regressed (it made things worse)
partial (mixed signal)
no_longer_needed (pattern self-resolved; trigger stopped firing)
Run ax improve verdict <dedupe_sig> --set <verdict> to lock it. All
five values stay available to the user by hand, including
no_longer_needed, which the algorithm never suggests on its own.
Step 4 - Hook effectiveness pass (optional)
Only run if the user asked for hook review OR if step-1 found ≥3
blocking errors. Light touch - this section is read-only.
Show top hooks from ax hooks summary --since=7 --tail=20 if not
already shown.
If a hook keeps blocking, ask: "Want to inspect a recent
invocation?" Then run
ax hooks invocations --command="<hook>" --tail=5 and render.
Backtest known feedback cases:
ax hooks cases enforce-worktree --tail=50 --window=3
Treat each backtest result as one case type. Report pass/fail/
inconclusive counts.
Interpretation:
- A blocking hook error is not automatically bad. If the next few
agent actions show corrected behavior, it's a useful corrective
signal.
- A successful hook is not automatically useful. Look for downstream
behavior change.
hook_progress without a terminal success/blocking event is a
telemetry gap unless correlated with visible behavior.
- Prefer deterministic backtests over model judgment.
- To author a NEW guard from a recurring failure:
ax hooks init, write a defineHook hook in ~/.ax/hooks/, ax hooks backtest it against history, then ax hooks install --providers=claude,codex.
Step 5 - Close out
Output a one-paragraph summary:
- Counts: accepted / rejected / skipped / verdicts locked.
- Any scaffolded SKILL.md files that still need refinement.
- When the next retro is recommended. Compute: earliest
experiment.created_at + 7d among accepted-but-unlocked
experiments, formatted as "next retro suggested around YYYY-MM-DD".
Then ask whether the user wants to commit the scaffolded skill files +
proposal-status changes (DB is local, but SKILL.md files are on disk
and may belong in version control).
How to track feedback
The retro itself produces durable signal that the experiment loop
already captures:
Acceptance rate by form - after the session, derive from
proposal.status. If skill-form gets accepted 80% but guidance gets
rejected 80%, the derive-proposals stage is over-eager on the wrong
form. Surface as an observation.
Reject reasons - proposal.reject_reason is a free-text corpus.
After the session run:
ax improve list --status=rejected --json | jq '.[].reject_reason'
Look for repeated phrases ("duplicate of existing hook"). When a
pattern emerges, the derive-proposals stage should dedupe against it
Verdict surprises - when the user overrides a suggested verdict,
note it. Repeated overrides mean the verdict math is biased.
These are observations, not actions. Report in the close-out; don't
write to insight tables.
CLI reference Claude calls
ax improve list [--form=skill|subagent|hook|guidance|automation] \
[--status=open|accepted|rejected|superseded|all] [--json]
ax improve show <dedupe_sig> [--json]
ax improve accept <dedupe_sig> [--force]
ax improve reject <dedupe_sig> --reason "<text>"
ax improve verdict [<dedupe_sig>] [--set <verdict>] [--json]
ax improve checkpoint [--force] # Step 1 prerequisite; --force only on request
ax improve reset --yes # destructive; only when user requests
ax retro pending [--since=N] [--idle-min=N] [--json] # Step 0 backlog
ax retro brief --session=<id> [--out-dir=<path>] [--json]
ax retro emit --session=<id> [--source=<src>] [--from-file=<json>]
ax retro list [--since=N] [--limit=N] [--json]
ax hooks summary [--since=N] [--tail=N]
ax hooks invocations [--command="<name>"] [--tail=N]
ax hooks cases <case-name> [--tail=N] [--window=N]
--force on accept overwrites an existing SKILL.md scaffold. Only use
when the user explicitly says so.
reset --yes wipes ALL proposal/experiment/checkpoint state. NEVER run
without explicit user confirmation in this session.
Failure modes
ax improve list returns empty → run ax ingest --derive-only once,
retry. If still empty, evidence is genuinely thin; tell the user.
ax improve accept reports scaffold_exists → ask the user if they
want --force or to abandon.
ax improve verdict --set reports verdict_locked → that experiment
is already finalized; show the locked value and move on.
ax improve checkpoint fails → measurement is unavailable for this
retro. Say so, skip Step 3, and keep Step 2 going.
ax hooks summary returns nothing → retry with --since=30; if
still empty, the hook telemetry pipeline is idle, surface as a TODO.
- Read/query error → tell the user to check
docs/development.md#setup
(AX_DUCKDB_DYLIB).
Anti-patterns
- Don't dump raw JSON. Render summaries.
- Don't run
ax improve accept for every open proposal in a batch; the
user must say yes per row.
- Don't write to
~/.claude/skills/ directly. The CLI handles that.
- Don't propose deleting a scaffolded SKILL.md mid-retro; that's a
separate cleanup task.
- Don't auto-implement experiments from the hook pass. Recommendations
only; the user decides + commits.
1---2name: retro3description: Guided experiment-loop retrospective over the ax agent-experience graph. Walks the user through their open proposals (accept-with-scaffold or reject), pending verdicts (confirm the suggested verdict or override), and recent harness-hook effectiveness signal. Triggers when the user says "let's do an ax retro", "ax retrospective", "review my ax proposals", "triage proposals", "experiment loop status", "lock pending verdicts", "hook effectiveness review", "intervention review", "self-improvement session", or invokes /ax:retro. Reads/writes via the local `ax improve` and `ax hooks` CLIs. Do NOT auto-trigger on unrelated work.4---56# ax:retro - guided experiment-loop session78Closes the self-improvement loop. Claude orchestrates `ax improve …`9commands; the user decides each row.1011Assumes `ax` (axctl) is on PATH. If `ax improve list` fails, tell the user12to check `docs/development.md#setup` (DuckDB dylib setup - no daemon13required) and stop.1415## When to fire1617ONLY fire on explicit triggers:18- "let's do an ax retro" / "ax retrospective" / "retro time"19- "review my ax proposals" / "triage proposals"20- "what's my experiment loop status" / "lock pending verdicts"21- "hook effectiveness review" / "intervention review"22- "self-improvement session"23- `/ax:retro` slash command (if the plugin marketplace publishes one)2425Do NOT fire on a generic "look at my recent work" - that risks dragging26unrelated context into the loop.2728## Defaults2930- Window for hook signals: last 7 days. Widen to 30 if evidence is sparse.31- Don't apply changes silently. Every accept/reject/verdict gets the32 user's explicit yes per row.33- The retro is read-mostly. Its side-effects are the Step 1 checkpoint34 measurements, the task briefs `accept` emits, and verdict locks.3536## Workflow3738### Step 0 - Drain pending session retros3940Before the proposal queue, check whether prior sessions still owe a41retro. This is the "quota arbitrage" path - idle Opus budget chews42through the backlog so the experiment loop has signal next time.43441. Run:4546 ```bash47 ax retro pending --since=7 --idle-min=30 --json48 ```4950 Returns sessions in the last 7 days that have no `reviewed` graph51 edge yet AND look finished (explicit `ended_at`, or last turn is52 >30min idle). If the list is empty, skip to Step 1.53542. Show the list to the user as 1 line per session (project · turns ·55 model · reason). Ask:5657 > N session(s) pending retro. Want me to dispatch the58 > retro-reviewer subagent for all of them in parallel, or pick a59 > subset?60613. On `all` or `<subset>`: for each chosen session, write a brief:6263 ```bash64 ax retro brief --session=<session_id>65 ```6667 This writes `.ax/tasks/retro/<key>.md` with frontmatter (transcript68 path, suggested model, turn count, etc.) and a body that tells the69 reviewer what to do.70714. Dispatch one `retro-reviewer` subagent per brief, in parallel. Pass72 each brief path in the prompt; let the subagent's frontmatter pin73 `model: opus` (override per session if `suggested_model` differs and74 the user asked you to economize).7576 If the `retro-reviewer` subagent type doesn't resolve (not installed,77 or the active harness is not Claude Code), read and review the brief INLINE78 using its required-output instructions instead of abandoning the backlog.79805. Wait for all subagents. Aggregate results: counts of retros emitted,81 proposals recommended, model-fit suggestions. Render as a short82 summary. The user does not approve retro emissions per row - the83 subagent already wrote them. The user DOES decide on resulting84 proposals in Step 2.85866. The `reviewed` edge now exists for each drained session, so a87 re-run of `ax retro pending` should show fewer rows.8889If the user declines Step 0, move on. The backlog stays - next retro90picks it up.9192### Step 1 - Snapshot9394Measure first, then read. The checkpoint pass is what turns due windows95into current ones; a verdict read taken before it reports whatever the96last run happened to leave behind.97981. Run the prerequisite ALONE and wait for it:99100 ```bash101 AX_NO_AUTO_INGEST=1 ax improve checkpoint --json102 ```103104 It reads the published snapshot and writes checkpoint judgments only -105 no transcript parsing, no guidance edits, no verdict locks. Leave106 `--force` out of an ordinary retro; it rewrites unreviewed windows that107 are already current.1081092. On success, run the reads (parallel is fine). Prefix EVERY command -110 a prefix on the first one leaves the freshness drive on for the rest:111112 ```bash113 AX_NO_AUTO_INGEST=1 ax improve list --status=open --json114 AX_NO_AUTO_INGEST=1 ax improve list --status=accepted --json115 AX_NO_AUTO_INGEST=1 ax improve verdict --json116 AX_NO_AUTO_INGEST=1 ax retro list --since=7 --json # cluster-derived friction summary117 AX_NO_AUTO_INGEST=1 ax hooks summary --since=7 --tail=20 # optional; tolerate failure118 ```1191203. If the checkpoint run fails, tell the user measurement is unavailable121 and continue with proposal review only. Any suggestion already stored122 belongs to an earlier run - report it as that, and skip the verdict123 step.1241254. If the checkpoint result reports `cacheRefreshRequired` above zero, the126 opportunity evidence needs deriving; say so, and treat those127 experiments as unmeasured. When the user asks for current evidence, run128 three operations in order, each awaited on its own: `ax ingest` (wait129 for successful publication), the checkpoint prerequisite, then the130 reads.131132`ax retro list` reflects three pattern types now:133- **tool failures** (skill form) -> `Pre-<Tool> guard` proposals134- **correction pressure** (guidance form) -> "Reduce recurring user135 corrections" proposals targeting `CLAUDE.md`136- **friction kinds** (skill form, one per kind) -> `Address recurring137 <kind> friction` proposals138139If any of those surfaced, mention them so the user knows to triage in140Step 2.141142Compute counts: open proposals (by form), accepted experiments with143`locked_verdict IS NONE`, and - separately - experiments whose current144view carries a `current_reason` (insufficient data or a lifecycle state).145Then render to the user as 2-4 lines, e.g.:146147> 7 open proposals (3 skill, 4 guidance). 2 accepted experiments are148> waiting on a verdict. Hook activity last 7d: 142 invocations, 3149> blocking errors. Want to triage proposals first, lock the pending150> verdicts, or skim hook signals?151152If both proposal/verdict queues are empty: tell the user nothing's due153and offer `ax ingest --derive-only` to refresh evidence.154155### Step 2 - Triage open proposals156157Order open proposals by `frequency` desc. For each, in turn:1581591. Run `ax improve show <dedupe_sig> --json` (or reuse the row from160 step 1).1612. Render as 3-5 lines. Example for a skill proposal:162163 > **Schema change guardrail** (skill · freq=9 · confidence=high)164 > Hypothesis: schema edits often surface in fix-chains within ~14d.165 > Trigger: fix commits overlap schema files.166 > Behavior: run schema lint + one read/write smoke before edit.1671683. Ask the user: **accept**, **reject**, or **skip**.1691704. Branch:171 - **accept** → run `ax improve accept <dedupe_sig>`.172 By default this emits a TASK BRIEF and returns its `task_path`; it173 does not install the artifact. Report that path.174 Offer: *"Want me to implement the brief now?"*175 If yes: implement it, then run `ax improve lint` so ax reconciles the176 marker it finds on disk and records the installed artifact. Until177 lint records one, the experiment has no measurable installation.178 - **reject** → ask for a short reason (≤80 chars).179 Run `ax improve reject <dedupe_sig> --reason "<reason>"`.180 - **skip** → no command. Move on; the proposal stays open for the181 next retro.182183After the loop, summarize: *"Accepted 3, rejected 1, skipped 2."*184185### Step 3 - Verdict review186187For each experiment whose latest checkpoint is unlocked188(`locked_verdict IS NONE`), in age order:1891901. Run `AX_NO_AUTO_INGEST=1 ax improve verdict <dedupe_sig>` to fetch the191 experiment + checkpoint history.1921932. When the current view carries a `current_reason`, there is no194 suggestion to confirm. Report the reason as it is - `no opportunities195 in the window`, `no detector for this form`, `retired` - and move to196 the next experiment. A suggestion in the `checkpoints` history is197 history, not a recommendation.1981993. Otherwise render the current checkpoint as 2-3 lines:200201 > **Schema change guardrail** - +30s checkpoint202 > 12 opportunities in window, 8 addressed (66%) - observed use.203 > Suggested: **adopted**.2042054. Ask the user to confirm the suggested verdict OR override:206 - `adopted` (artifact is doing real work)207 - `ignored` (user wrote it but never invoked it)208 - `regressed` (it made things worse)209 - `partial` (mixed signal)210 - `no_longer_needed` (pattern self-resolved; trigger stopped firing)2112125. Run `ax improve verdict <dedupe_sig> --set <verdict>` to lock it. All213 five values stay available to the user by hand, including214 `no_longer_needed`, which the algorithm never suggests on its own.215216### Step 4 - Hook effectiveness pass (optional)217218Only run if the user asked for hook review OR if step-1 found ≥3219blocking errors. Light touch - this section is read-only.2202211. Show top hooks from `ax hooks summary --since=7 --tail=20` if not222 already shown.2232242. If a hook keeps blocking, ask: *"Want to inspect a recent225 invocation?"* Then run226 `ax hooks invocations --command="<hook>" --tail=5` and render.2272283. Backtest known feedback cases:229230 ```bash231 ax hooks cases enforce-worktree --tail=50 --window=3232 ```233234 Treat each backtest result as one case type. Report pass/fail/235 inconclusive counts.2362374. Interpretation:238 - A blocking hook error is not automatically bad. If the next few239 agent actions show corrected behavior, it's a useful corrective240 signal.241 - A successful hook is not automatically useful. Look for downstream242 behavior change.243 - `hook_progress` without a terminal success/blocking event is a244 telemetry gap unless correlated with visible behavior.245 - Prefer deterministic backtests over model judgment.246 - To author a NEW guard from a recurring failure: `ax hooks init`, write a `defineHook` hook in `~/.ax/hooks/`, `ax hooks backtest` it against history, then `ax hooks install --providers=claude,codex`.247248### Step 5 - Close out249250Output a one-paragraph summary:251- Counts: accepted / rejected / skipped / verdicts locked.252- Any scaffolded SKILL.md files that still need refinement.253- When the next retro is recommended. Compute: earliest254 `experiment.created_at + 7d` among accepted-but-unlocked255 experiments, formatted as "next retro suggested around YYYY-MM-DD".256257Then ask whether the user wants to commit the scaffolded skill files +258proposal-status changes (DB is local, but SKILL.md files are on disk259and may belong in version control).260261## How to track feedback262263The retro itself produces durable signal that the experiment loop264already captures:265266- **Acceptance rate by form** - after the session, derive from267 `proposal.status`. If skill-form gets accepted 80% but guidance gets268 rejected 80%, the derive-proposals stage is over-eager on the wrong269 form. Surface as an observation.270- **Reject reasons** - `proposal.reject_reason` is a free-text corpus.271 After the session run:272273 ```bash274 ax improve list --status=rejected --json | jq '.[].reject_reason'275 ```276277 Look for repeated phrases ("duplicate of existing hook"). When a278 pattern emerges, the derive-proposals stage should dedupe against it279 - tell the user.280- **Verdict surprises** - when the user overrides a suggested verdict,281 note it. Repeated overrides mean the verdict math is biased.282283These are observations, not actions. Report in the close-out; don't284write to insight tables.285286## CLI reference Claude calls287288```bash289ax improve list [--form=skill|subagent|hook|guidance|automation] \290 [--status=open|accepted|rejected|superseded|all] [--json]291ax improve show <dedupe_sig> [--json]292ax improve accept <dedupe_sig> [--force]293ax improve reject <dedupe_sig> --reason "<text>"294ax improve verdict [<dedupe_sig>] [--set <verdict>] [--json]295ax improve checkpoint [--force] # Step 1 prerequisite; --force only on request296ax improve reset --yes # destructive; only when user requests297298ax retro pending [--since=N] [--idle-min=N] [--json] # Step 0 backlog299ax retro brief --session=<id> [--out-dir=<path>] [--json]300ax retro emit --session=<id> [--source=<src>] [--from-file=<json>]301ax retro list [--since=N] [--limit=N] [--json]302303ax hooks summary [--since=N] [--tail=N]304ax hooks invocations [--command="<name>"] [--tail=N]305ax hooks cases <case-name> [--tail=N] [--window=N]306```307308`--force` on `accept` overwrites an existing SKILL.md scaffold. Only use309when the user explicitly says so.310311`reset --yes` wipes ALL proposal/experiment/checkpoint state. NEVER run312without explicit user confirmation in this session.313314## Failure modes315316- `ax improve list` returns empty → run `ax ingest --derive-only` once,317 retry. If still empty, evidence is genuinely thin; tell the user.318- `ax improve accept` reports `scaffold_exists` → ask the user if they319 want `--force` or to abandon.320- `ax improve verdict --set` reports `verdict_locked` → that experiment321 is already finalized; show the locked value and move on.322- `ax improve checkpoint` fails → measurement is unavailable for this323 retro. Say so, skip Step 3, and keep Step 2 going.324- `ax hooks summary` returns nothing → retry with `--since=30`; if325 still empty, the hook telemetry pipeline is idle, surface as a TODO.326- Read/query error → tell the user to check `docs/development.md#setup`327 (`AX_DUCKDB_DYLIB`).328329## Anti-patterns330331- Don't dump raw JSON. Render summaries.332- Don't run `ax improve accept` for every open proposal in a batch; the333 user must say yes per row.334- Don't write to `~/.claude/skills/` directly. The CLI handles that.335- Don't propose deleting a scaffolded SKILL.md mid-retro; that's a336 separate cleanup task.337- Don't auto-implement experiments from the hook pass. Recommendations338 only; the user decides + commits.