# Upgrade Guide — vNEXT

<!-- assembled-by: assemble-next-md -->
<!-- bump: minor -->

## What Changed

Release notes are now authored as per-PR **fragments** instead of a single shared
`upgrades/NEXT.md`. Each PR drops its release note at `upgrades/next/<slug>.md`,
touching a distinct file, so two concurrent PRs never collide on the release
notes — the bottleneck that made many-agent merges un-landable in real time.

A new pure script, `scripts/assemble-next-md.mjs`, folds every fragment (sorted
deterministically by filename) — plus any legacy `upgrades/NEXT.md`, for backward
compatibility — into a single `upgrades/NEXT.md`, merging by section: one What
Changed, one What to Tell Your User, one Summary of New Capabilities, one Evidence,
each being the concatenation of that section across all inputs. Non-canonical
sections are preserved and appended. The emitted bump directive is the highest tier
among the fragments (major beats minor beats patch); it is a documentation hint only
— the real release tier still comes from `.instar/release-tier.json`, which is
untouched.

The publish workflow gains ONE new step, "Assemble release-note fragments", placed
immediately before the existing "Check if NEXT.md has content to publish" step.
Everything downstream — the tier gate, version resolution, the rename, the upgrade
guide check, publish, and commit — is unchanged. With no fragments and no legacy
NEXT.md, the assemble step does nothing and the existing skip logic fires exactly as
before, so the no-fragments path reproduces current behavior byte-for-byte. After a
release is cut, consumed fragments are deleted (`rm -f upgrades/next/*.md`) and the
existing commit step stages the deletions. The pre-push gate is now fragment-aware:
it validates the assembled result in-memory (never writing NEXT.md to disk during
pre-push), so a PR that ships only a fragment passes the same section and content
checks the publish gate enforces, and a malformed fragment fails the push loudly.
`upgrades/NEXT.md` remains fully supported as a legacy, backward-compatible path.

## What to Tell Your User

If you run a Codex-based agent, it can now run in autonomous mode and keep itself going across
many turns until the goal is met — the same way a Claude agent does. Before, a Codex agent in
autonomous mode would quietly stop after a single turn. Nothing to configure; it applies on the
next update, and Claude agents are unaffected.

Behind the scenes, the way I prepare release notes got a lot more robust. Each
change now writes its own small note in its own file, instead of every change
fighting over one shared notes file. That means when several updates are being
prepared at the same time, they no longer block each other, so improvements reach
you faster and with less risk of a release getting stuck. Nothing changes about how
I talk to you — this is purely a smoother release pipeline on my side.

## Summary of New Capabilities

- `setup-autonomous.sh` now enables native /goal delegation for Codex agents (detected via config
  `enabledFrameworks` containing `codex-cli`), not just Claude Code >= 2.1.139. Codex autonomous
  mode auto-delegates to native /goal; the stop-hook's existing `goal_mode:native` branch defers.
- `PostUpdateMigrator` marker bump (`native-goal/set` → `IS_CODEX_AGENT`) re-deploys the fixed
  setup script to existing agents.

| Capability | How to Use |
|-----------|-----------|
| Per-PR release-note fragments | Write `upgrades/next/<slug>.md` (one file per change) |
| Fragment assembler | `node scripts/assemble-next-md.mjs` (runs automatically in publish) |
| Legacy NEXT.md | Still supported — folded in for backward compatibility |

## Evidence

- Root cause traced by reading setup-autonomous.sh: the native /goal hand-off existed but was
  gated on `claude --version >= 2.1.139` (empty for a codex agent → codex fell to the dark
  Phase-1 no-op). Proven live in round 2 that codex /goal sustains 1→2→3 across turns.
- Unit: `tests/unit/autonomous-codex-native-goal-detection.test.ts` — both sides of the
  decision boundary (codex enables, Claude/absent skips, multi-framework enables, missing config
  best-effort skips).
- Unit: `tests/unit/PostUpdateMigrator-autonomousStopHook.test.ts` — a prior native-/goal setup
  is re-deployed by the marker bump; all existing cases stay green (8 tests).
- `tsc --noEmit` + `npm run lint` clean.
- Spec: `docs/specs/codex-autonomy-native-goal-autowire.md` (+ `.eli16.md`).
- Side-effects: `upgrades/side-effects/codex-autonomy-native-goal-autowire.md`.
- Final proof is the live drive: Codey running the real /autonomous skill and sustaining multi-turn.

## What Changed — Codex agents now run autonomous mode on their own (Claude parity)

When you put an agent in autonomous mode, it should keep working across many turns until the job
is done. Claude agents already did this (via the stop hook). Codex agents did NOT — they would
quietly stop after one turn. Codex actually has its own way to sustain a multi-turn run (its
built-in /goal loop), and instar already handed the goal off to it automatically — but only
behind a check for "Claude command-line version 2.1.139+", which is empty for a Codex agent. So
Codex agents fell through that Claude-shaped gate and never got the hand-off.

This adds a small framework-aware fallback: if the Claude check doesn't apply, instar detects a
Codex agent (from its own config) and hands the goal to Codex's native /goal loop. Now a Codex
agent in autonomous mode sustains multi-turn work automatically, the same as a Claude agent. The
Claude path is unchanged, and the sensitive stop hook is untouched.
