{
  "markdown": "# Agentic SDLC Orchestrator\n\nReusable, provider-native operating kit for project-scale agentic software delivery across\nCodex, Claude Code, and other skill-capable hosts. cmux is an optional view/event layer;\ntmux is never a baseline requirement.\n\n**Install it.** [mise](https://mise.jdx.dev) is the only bootstrap prerequisite. Read\n`mise.toml` before step 2 — that step authorizes whatever it says at that moment:\n\n```bash\ngit clone https://github.com/Codeseys-Labs/agentic-sdlc.git && cd agentic-sdlc\nmise trust ./mise.toml          # persistent, per-path, and needs your explicit approval\nmise --locked install           # 12 pinned tools, ~1.3 GB\nmise run lifecycle:install -- --agent claude   # or --agent codex; one plane per run, no default\n```\n\nThe dispatcher is `bin/ccodex` in the tree you just cloned; run it from there, or let mise expose\nit (see [`ccodex` — the operator dispatcher](#ccodex-the-operator-dispatcher)). There is no\nseparate step that copies it into `~/.local/bin`.\n\nThen `mise run lifecycle:status -- --agent claude` should report `N ok, 0 conflict, 0 absent`. Full walkthrough with\nthe reasoning behind each step: [Quickstart from a clean clone](#quickstart-from-a-clean-clone).\nEvery command with what it does: [`ccodex` — the operator dispatcher](#ccodex-the-operator-dispatcher)\nand [the task table](#install-and-run-the-bundle). Verified from nothing on a fresh\n`ubuntu:24.04` container against the public remote — `docs/research/2026-08-08-fresh-host-install-verification.md`\nrecords the transcript, including two defects it found.\n\n**Architecture: an open plugin — the multi-host pattern, since no unified plugin standard\nexists (verified 2026-07).** The portable layer is the `skills/` tree (the\n[Agent Skills](https://agentskills.io) format, natively read by Claude Code, Codex, Gemini\nCLI, OpenCode, Cursor, Goose, Kiro, and ~40 hosts) + a root `AGENTS.md` router (read by\nCodex/Gemini/OpenCode). On top sit THIN per-host manifests, all version-locked by\n`scripts/bump-version.sh`:\n\n| Host | Manifest |\n|---|---|\n| Claude Code | `.claude-plugin/{plugin,marketplace}.json` |\n| Codex CLI | `.codex-plugin/plugin.json` + `.agents/plugins/marketplace.json` |\n| Gemini CLI | `gemini-extension.json` (contextFileName → AGENTS.md) |\n| OpenCode / Goose / Kiro / others | pure skills-tree discovery via the symlink installer |\n\nAdding a skill means adding a `skills/<name>/SKILL.md` directory. The installer, validator, and\nall distribution planes pick it up automatically. Never hand-edit one manifest's version.\n`scripts/bump-version.sh <x.y.z>` writes all of them; `--check` gates drift in CI — the\nvalidator reports a disagreeing manifest as an error, so the gate and CI fail closed on drift.\n\nThe baseline shape:\n\n```text\nAgent entrypoint (Codex, Claude Code, or another capable host)\n  -> provider-native roles/subagents/workflows (or direct execution)\n  -> Seeds queue\n  -> git worktrees\n  -> tests/review\n  -> squash/rebase/PR\n\nOptional adapters:\n  + cmux for an already-active view/event layer\n  + tmux only when an optional adapter uses it\n```\n\n**Capability-negotiated baseline:** a host may run the native Frame -> Ship loop only after the\nrequired Git, Seeds, gate, trust, and selected-adapter capabilities are present, pinned where\napplicable, and verified. Missing, untrusted, unpinned, or ambiguous required capability\nfails closed. An unselected optional adapter does not block the native path. Never install,\nstart, or enable cmux or tmux merely to use this bundle.\n\n## Contents\n\n**The rule on third-party skill libraries has two parts, and the distinction between them is\nthe whole point: this bundle never *vendors* a foreign library's bytes, and it can *invoke* a\nlibrary's own installer on explicit request.**\n\n- **Never vendored.** No foreign library's bytes are copied into this repository's tree. That\n  is what would trigger a `NOTICE` donor obligation under ADR-0001, drag another licence into\n  this distribution, freeze one snapshot of somebody else's catalog, and put entries this\n  bundle did not author onto its own selection surface. Foreign *ideas* enter here by exactly\n  one path: an adapted `references/*.md` file with a root `NOTICE` donor entry landed in the\n  same change, re-expressed in this bundle's own prose rather than copied.\n- **Installable on request, from a closed catalog.** `libraries:list`, `libraries:status`, and\n  `libraries:install` support exactly `mattpocock/skills`, ECC (`affaan-m/ECC`), and\n  hyperresearch through each library's *own* front door. Unlisted libraries—including gstack—are\n  operator-owned foreign state until separately verified and onboarded; these tasks do not adopt,\n  inspect for ownership, migrate, or remove them. Running a supported third party's installer\n  copies nothing here: the bytes land in the\n  operator's home, written by the library's own code, under its own name and licence, exactly\n  as if the operator had typed the command. So no donor obligation attaches. These tasks are\n  opt-in and collision-checked, and **no gate leaf, `contributor:setup`, deprecated `setup`,\n  or `lifecycle:install` path reaches them** — `check`'s dependency closure is `validate`, `test`,\n  `self-test`, `secrets`, and `contributor:setup` contains only `lifecycle:install` plus\n  `hooks:install`. Installation is therefore a deliberate choice, never a side effect.\n\nThe installer's ownership model is what makes the two coexist: an entry this bundle does not\nown is classified `foreign` and preserved rather than replaced. Decisions and evidence:\n`docs/adr/0009-external-skill-libraries-are-opt-in-through-their-own-front-doors.md` (the\nopt-in mechanism) and\n`docs/adr/0008-third-party-skill-libraries-are-the-operators-own-install.md` (the\nno-vendoring rule it refines), plus `skills/external-skill-libraries/`.\n\n- `skills/agentic-sdlc/`: the flagship, provider-native orchestration skill\n  for any skill-capable CLI agent.\n- `skills/codex-research-os/`: vendored research-team OS — a repo-scaffolding installer\n  (`scripts/install_research_os.py`) that bootstraps a 17-role research organization\n  (director + specialists), claim/experiment ledgers, greenfield/brownfield workflows,\n  schemas, and Make validation gates into any target repo. Pairs with the flagship's\n  `references/research-team.md` (the distilled principles).\n- `skills/model-tier-rightsizing/`: first-class model-routing skill. Load it before any\n  model dispatch. Its four-tier policy pairs exact Sol/Fable for frontier derail work,\n  Terra/Opus for judgment-workhorse silent-degrade work, and Luna/Sonnet for capable-volume\n  visible-retry work; the mechanical floor selects the cheapest certified fully gated route.\n  The canonical calibration records exact IDs, explicit requested effort, transport hazards,\n  evidence boundaries, complements, controls, quotas, and roadmap lanes. Selection is by task\n  fit, independent perspective, quota, and verified transport—not provider preference or\n  artificial all-six representation. The flagship hands off through\n  `references/tiered-orchestration.md`.\n- `skills/dispatching-exact-ocx-models/`: exact-route dispatch seam after rightsizing resolves a\n  `RuntimeAssignment`. It distinguishes generated `ocx-*` Agent types from Workflow `agent()`\n  injection, checks model-visible tool compatibility, and requires verified post-run identity.\n- `skills/reviewing-overengineering/`: independent complexity/deletion audit for one immutable\n  plan or diff. It pairs deletion pressure with a safety-preservation rebuttal and classifies work\n  as essential safety complexity, accidental complexity removable now, or speculative deferral.\n  Ponytail may complement it but is never required.\n- `skills/cmux-event-bus-messaging/`: optional cmux-only event-bus pub/sub pattern (publish via\n  `cmux log --source msg:<topic>`, subscribe via `cmux events` with replay/resume, the\n  claim-check pattern, both race gotchas). Pairs with `references/cmux-integration.md`\n  and `scripts/cmux-bus.sh`.\n- `skills/repo-toolchain-gates/`: the standard local gate stack — mise (pinned toolchain\n  incl. CI-parity linter pins + task-runner; `mise run check` = THE gate), lefthook\n  (pre-commit/pre-push enforcement, installed via mise `[tools]`), betterleaks (secrets\n  gate incl. full-history scans). Includes the two verified worktree facts: hooks ARE\n  shared into worktrees, mise trust is NOT. Pairs with `references/seeds-worktrees.md`.\n- `skills/stacked-prs/`: the tool-agnostic stacked-PR methodology — ship a chain of small\n  dependent PRs instead of one fat branch (small-batch rationale, stack structure,\n  bottom-up merge, the restack discipline, when NOT to stack). The PR-landing strategy for\n  dependent Seeds in a wave.\n- `skills/stacked-prs-gh-cli/`: the same with ONLY plain `gh` + git — no gt/spr/ghstack.\n  gh has no `stack` command (v2.95); GitHub's primitives are `--base` targeting + explicit\n  retarget/requery/restack. Covers the squash-merge `--onto` restack gotcha and\n  `--force-with-lease` safety. Pairs with `stacked-prs`.\n  - `references/sdlc-loop.md` — phase gates, backflow, done criteria.\n  - `references/seeds-worktrees.md` — Seeds queue, native worktree waves, PR flow, optional\n    worker/view adapters, and the canonical in-workspace `.worktrees/<seed-id>-<slug>/`\n    substrate rule (never a sibling directory).\n  - `references/worktree-lifecycle.md` — one wave worktree end to end, each step with its\n    refusal and recovery: create, gate, review, integrate (squash-preferred, and why),\n    reconcile through the conductor-only record seam, clean up. Includes the executed Git\n    facts behind those refusals.\n  - `references/cmux-integration.md` — optional cmux view/event integration. Load only when\n    cmux is already active or explicitly requested.\n  - `references/delegation-planes.md` — native-first per-provider decision matrices plus\n    optional durable/mixed-engine adapters.\n  - `references/worktree-integration.md` — fan-in hazards: merge-base footprint, placeholder\n    traps, re-gate-on-main, clean-apply ≠ semantic correctness, squash-scope discipline.\n  - `references/mission-loop.md` — the autonomous **backlog-zero doctrine**: 8-class\n    milestone classification (only ACTIVE_MILESTONE executes), seeds-first no-inline-fixes,\n    WIP caps, priority math, the concurrent critique team, honest definition of done.\n  - `references/tiered-orchestration.md` — model-tier assignment, honest provider/model\n    resolution, the native-first capability ladder with optional adapters, bounded backflow,\n    and worker lifecycle at scale.\n  - `references/research-team.md` — **evidence-graded research teams** for standing\n    research efforts: the evidence ladder (promote slowly, downgrade quickly), role\n    separation-of-powers (attacker ≠ fixer, writer ≠ originator), one-loop discipline\n    with a recorded next-action, greenfield/brownfield loops, the cheapest-decisive-\n    experiment rule, gates-as-executables (no decorative model pins).\n- `agents/claude/sdlc-*.md` + `agents/codex/sdlc-*.toml`: eight role agents in both CLI\n  forms (symlinked globally) — **cartographer** (read-only Discover mapper), planner,\n  implementer, reviewer, **researcher** (bounded unknown-resolution), **critic** (standing\n  snapshot-only critique team), **integrator** (the only merging agent), **documentarian**\n  (read-only documentation worker — evidence-linked doc proposals for conductor capture,\n  writes only its own artifact). Full loop wiring:\n  cartographers (parallel, per area) → planner → implementers → reviewers → integrator,\n  critic concurrent, researchers on demand. Provider-neutral role definitions contain no static\n  model/effort pin, never dispatch, and consume a conductor-supplied certified\n  `RuntimeAssignment` with a certified exact model ID. `resolution_state` must be `resolved`.\n  Exact model/effort request injection is mandatory and immutable. `resolved_provider` and\n  `resolved_model_id` require verified model identity; independently observed provider/model\n  source may be unavailable only for a unique exact-ID mapping backed by immutable request/model\n  evidence. Effective effort/context readback may be honestly unavailable; requested values never\n  become readback. If the assignment is requested, inherited, unresolved, incomplete, or cannot\n  inject both requested model and effort, the conductor stops before dispatch and returns one\n  SeedProposal. Prompt prose does not enforce a Codex model or effort.\n- `agents/codex/research/`: the 17-role research-team TOMLs (repo-scoped reference\n  copies — NOT globally installed; see its README; scaffolded per-repo by\n  codex-research-os).\n- `commands/sdlc-{init,frame,wave,mission,rightsize}.md`: Claude Code slash commands —\n  `/sdlc-init` activates Agentic SDLC inside a repository without reinstalling global\n  capabilities. It establishes a reviewed tracked Git baseline, Seeds queue,\n  mise/lefthook/betterleaks gate stack, per-worktree trust policy, cross-host `AGENTS.md`\n  guidance, and CI parity. It is a reviewed runbook: claims of idempotence or Git-wave readiness\n  require observed evidence; it preserves existing project policy and stops on ambiguity. `/sdlc-frame` frames one run,\n  `/sdlc-wave` runs one Seeds-backed Git-worktree wave, `/sdlc-mission` runs an\n  autonomous backlog-zero mission with concurrent critique and bounded backflow, and\n  `/sdlc-rightsize` discovers the operator's live OCX routes plus usable Claude-subscription\n  passthrough, asks only environment-relevant source/model/task/budget questions, and produces a\n  regenerable v2 `.agentic-sdlc/rightsize/model-task-map.json` + `.md` + `.evidence.json` trio. Published\n  benchmarks nominate candidates; only an explicitly approved, bounded target-local evaluation\n  can recommend `role-qualified`, and the checked-in runtime receipt policy still separately\n  controls production admission. `mise run rightsize:evaluate -- plan ...` is read-only;\n  `evaluate` consumes provider/subscription capacity only with its exact displayed authorization\n  digest. Neither a benchmark, local evaluation, nor map authorizes dispatch (see\n  `skills/model-tier-rightsizing/references/model-task-map-schema.md`,\n  `docs/adr/0015-local-evaluation-is-the-rightsizing-promotion-boundary.md`, and\n  `skills/model-tier-rightsizing/references/workflow-prompt-budget.md`).\n- `.claude-plugin/{plugin.json,marketplace.json}`: the repo doubles as a Claude Code\n  plugin/marketplace — `claude plugin marketplace add <path-or-git-url>` then\n  `claude plugin install agentic-sdlc@agentic-sdlc` is an alternative to\n  symlinks. The marketplace source may be this repository's public Git URL, so no clone\n  is required first; see [Install as a Claude Code plugin](#install-as-a-claude-code-plugin).\n  `plugin/` is the marketplace entry's `source`: a directory holding the plugin manifest\n  plus real copies of `skills/`, `agents/claude/`, `commands/`, `output-styles/`, and\n  `workflows/`. It exists because Claude Code discovers agents only in a plugin\n  root's own `agents/`, and this repo nests the Claude roster one level down under\n  `agents/claude/`; installing from the repo root therefore finds the skills but zero\n  agents. Copies, not symlinks, and both shapes were measured on Claude Code 2.1.245\n  (agentic-sdlc-d0ab): a component directory that IS a symlink is read without being\n  followed, so `claude plugin validate ./plugin --strict` exited 1 with one warning per\n  link, and a materialisation carrying only the plugin subtree — what a `github` or\n  `archive` source fetches, reproducible offline with `git archive HEAD plugin` — left\n  every link dangling and installed at exit 0 while reporting `Skills (0)  Agents (0)`.\n  With copies, that same subtree install reports `Skills (18)  Agents (8)`, and\n  `claude plugin validate ./plugin --strict` passes with zero warnings. The argument form\n  decides what is validated: a directory dispatches on the manifest it finds, so\n  `claude plugin validate .` validates the marketplace catalog and passes, while\n  `claude plugin validate .claude-plugin/plugin.json` walks the repo root AS a plugin and\n  passes non-strict only — strict flags two deliberate repo files, the root `CLAUDE.md`\n  and the Codex roster README. Pointing a manifest field at the shared tree instead is not\n  available: `\"skills\": \"../skills\"` is refused as a path-traversal attempt. `mise run\n  validate` re-derives every copy from its source and fails on any drift, so a stale\n  `plugin/` is repaired with\n  `uv run --python 3.12.11 --script scripts/sync_plugin_tree.py --write` rather than by\n  hand. The manifest also declares `outputStyles` and `workflows` — the two kinds no\n  component walk discovers — and deliberately declares no `hooks`, because a plugin's\n  hooks surface auto-enables with the plugin.\n- `scripts/check-agentic-sdlc-prereqs.sh`: native-baseline preflight plus informational\n  checks for optional adapters. Missing cmux or tmux never fails it.\n- `scripts/install-skill-bundle.sh`: **one-shot global install for every native agent CLI\n  present** (Claude Code skill+agents+commands, Codex skill+role TOMLs). Symlinks by default; `--copy`\n  to copy. Never clobbers non-symlink files.\n- `scripts/validate-bundle.sh`: pre-commit/CI gate — SKILL.md frontmatter, name==dirname,\n  the 1024-char Codex description cap (silent-skip trap), broken references, TOML/JSON\n  parses, shell `bash -n`, plugin manifest validation, secret/internal-hostname sweep.\n- `scripts/cmux-bus.sh`: optional cmux-only event-bus helper (pub/sub/seq).\n\n## First task: a small hello world\n\nAfter the bundle is installed, start with one small, local change rather than a mission or a\nmulti-worker plan. Three terms are enough for the first pass: **Seeds** is the project's durable\nwork queue; a **Frame** is the short plan for one task; and a **Wave** is the reviewed worktree\nexecution of ready Seeds.\n\n1. In the target project, if its Seeds queue is absent, route to\n   [`/sdlc-init`](commands/sdlc-init.md) and stop. It is a reviewed activation runbook: it\n   establishes evidence for the Git baseline, queue, gates, and guidance, or stops on a conflict.\n   Do not use Frame or Wave to improvise activation.\n2. Frame one observable task, for example:\n\n   ```text\n   /sdlc-frame Add a hello command that prints \"hello\" and one test for it.\n   ```\n\n   The Frame records the done condition, scope, required gate, review point, queue state, and any\n   outward operation that would need separate explicit approval.\n3. If a certified delegation route is available, run the ready task through\n   [`/sdlc-wave`](commands/sdlc-wave.md). Every actual worker or model spawn still requires a\n   conductor-supplied certified `RuntimeAssignment`; an inherited, unresolved, or unverified route\n   stops before dispatch.\n4. If no certified delegation route exists, the Frame may choose **exactly one** bounded,\n   non-delegated conductor execution instead. It runs in one clean, dedicated Git worktree with\n   the same framed scope, acceptance criteria, gate, snapshot review, and conductor-only queue\n   reconciliation as a Wave. It has zero workers, zero model spawns, and no `RuntimeAssignment`\n   claim. It is not a convenience fallback: stop rather than execute when the task needs another worker,\n   another direct pass or retry, parallel work, or cannot be bounded and reviewed.\n5. Review the stable diff, run the named gate, and reconcile findings before describing the task as\n   complete. A gate, review, queue state, or local status never authorizes a push, PR mutation,\n   merge, publication, deployment, or another outward effect.\n\nThe detailed command flow lives in [`/sdlc-frame`](commands/sdlc-frame.md) and\n[`/sdlc-wave`](commands/sdlc-wave.md); both route an absent queue back to\n[`/sdlc-init`](commands/sdlc-init.md).\n\n## Install and run the bundle\n\nThe commands below describe the **current** checkout-backed distribution, which stays the home\nfor customization, contribution, gates, and release building. A prerelease quick install exists\nand is container-proven (2026-08-24, v0.7.4), EXACT-VERSION ONLY: declare\n`[tools.\"github:Codeseys-Labs/agentic-sdlc\"]` with `version = \"0.7.4\"` and `prerelease = true`,\nrun `mise install`, and the installed tree exposes exactly one command, `ccodex`. Running\n`mise trust` on that tree's reviewed `mise.toml` is a persistent mutation needing your explicit\noperation-specific approval; after it, `ccodex bundle install --agent claude`\nactivates the plugin. **That spelling is retired now** — it refuses at exit 2 naming\n`ccodex install --scope user --agent <claude|codex>` — and the sentence keeps the verb it\nexecuted because it records what the container proved, not what to type. Until the acquisition\nhalf lands, `mise run lifecycle:install -- --agent claude` is the working equivalent on a release\ntree: the top-level `install` is the receipted activation and refuses without an acquired\ncandidate. The unversioned `mise use -g github:Codeseys-Labs/agentic-sdlc` does not\nresolve a prerelease and is not claimed to work. The release tree carries no `.git`; gates and\nSeeds stay on the managed checkout. Contract, payload split, and boundaries:\n[`docs/plans/2026-08-14T163833Z-Install-UX.md`](docs/plans/2026-08-14T163833Z-Install-UX.md) and\nADR-0011 as amended.\n\n### Managed fetch, without cloning by hand\n\nIf you would rather not choose a directory or track where the tree lives,\n`scripts/bootstrap-agentic-sdlc.sh` fetches this repository into a managed location and then\nstops, printing the remaining commands instead of running them. Download it, read it, then run\nit — in that order, because it is a script that clones:\n\n```bash\ncurl -fsSL -o bootstrap-agentic-sdlc.sh \\\n  https://raw.githubusercontent.com/Codeseys-Labs/agentic-sdlc/main/scripts/bootstrap-agentic-sdlc.sh\nless bootstrap-agentic-sdlc.sh\nbash bootstrap-agentic-sdlc.sh --dry-run\nbash bootstrap-agentic-sdlc.sh\n```\n\n`--dry-run` prints the exact `git clone` it would run and creates nothing. `--remote <git-url>`\nselects the exact Git remote (rather than relying only on `AGENTIC_SDLC_REMOTE`), and `--ref`\nselects its branch or tag. The managed clone lands in\n`${XDG_DATA_HOME:-$HOME/.local/share}/agentic-sdlc`, reported by `--print-path` and overridable\nwith `AGENTIC_SDLC_HOME`; the resolved commit is recorded in\n`${XDG_STATE_HOME:-$HOME/.local/state}/agentic-sdlc/bootstrap-receipt.json`. Its final handoff\nprints the receipt, checkout commit, reviewed files, exact trust/toolchain commands, an explicit\nClaude-or-Codex install choice, and the status verification command. Removing both paths removes\neverything the script created. Re-running is idempotent: it reports the existing clone's ref and\ncommit, refuses rather than clobbering an unexpected remote, a dirty tree, or a ref mismatch, and\nfetches only under `--update`. `--help` documents each of those flags without running a tool.\n\nThe script requires mise and git and installs neither, so it adds no bootstrap prerequisite. It\ndeliberately does not trust the config, resolve the toolchain, or install bundle entries: those\nstay separate approvals against a tree you have read, and it prints them as steps 2 through 5\nbelow. HTTPS authenticates the transport, not the contents — nothing here verifies a signature\nover the fetched commit, so read the tree before trusting it. `docs/adr/0011` records why the\nclone is managed rather than eliminated: the tasks still come from a tree on disk, because every\ntask command and installed symlink resolves against one. For a genuinely tree-free install of the\nplugin payload alone, see the marketplace plane below.\n\n### Quickstart from a clean clone\n\nFive steps, in order, from an empty directory. Step 3 is a persistent mutation with its own\napproval gate; steps 2 and 3 are what a fresh clone otherwise fails on. The managed fetch above\nreplaces step 1 only.\n\n1. Clone the repository and enter it. Obtaining the source needs Git, which stays a\n   runtime-readiness capability rather than a second bootstrap prerequisite:\n\n   ```bash\n   git clone https://github.com/Codeseys-Labs/agentic-sdlc.git\n   cd agentic-sdlc\n   ```\n\n2. Review the two files that step 3 authorizes: `mise.toml` (the pinned toolchain and every\n   task command) and `mise.lock` (per-platform source URLs and SHA-256 checksums). Read them\n   before trusting them; the trust decision covers whatever they say at that moment.\n\n3. Trust the reviewed config. This is a persistent per-path mutation. It requires explicit\n   operation-specific approval for that exact config path; a general clone, run, or\n   implementation approval never covers it:\n\n   ```bash\n   mise trust ./mise.toml\n   ```\n\n   Skipping this step is the first-run failure: every later `mise` command in the repository\n   exits with `config files are not trusted`. To validate without persisting anything, use\n   `mise --no-config --cd . exec ...` instead of trusting.\n\n4. Resolve the locked toolchain. `mise.lock` pins **12 tools** — `uv`, `node`, `npm`, `bun`,\n   `lefthook`, `jq`, `ripgrep`, `fd`, `gh`, `betterleaks`, `opencodex`, and `seeds-cli` — for\n   roughly 1.3 GB and about 30 seconds on a warm network. mise ships `auto_install` enabled, so\n   skipping this step does not avoid the cost: the first `mise run <task>` installs all 12\n   without prompting.\n\n   ```bash\n   mise --locked install\n   ```\n\n5. Choose an install plane explicitly. Claude entries go under the configured Claude home\n   (`~/.claude` by default); Codex entries go under the configured Codex home (`~/.codex` by\n   default, or `CODEX_HOME`). `--agent` is REQUIRED on install, status, and uninstall — there is\n   no default and no wildcard, and a selector-free run refuses at exit 2 naming both planes. To use\n   non-default roots, pass `--claude-home <path>` and `--codex-home <path>` after `--`.\n\n   ```bash\n   mise run lifecycle:install -- --agent claude\n   # or: mise run lifecycle:install -- --agent codex\n   # inspect one plane without writing: mise run lifecycle:status -- --agent claude\n   ```\n\n   A detected Claude marketplace install is reported once as a Claude-plane conflict and blocks\n   only direct Claude installation; Codex continues. Use either the marketplace or direct\n   installation for Claude, not both. Foreign or changed entries are preserved with a reason and\n   a retry instruction; never delete a reported path merely to make the installer green.\n\n6. Nothing further is needed to reach the dispatcher. `bin/ccodex` is committed in the tree and\n   self-locates its distribution root as the parent of its own `bin/`, so `<checkout>/bin/ccodex`\n   works immediately and mise's `github:` backend exposes exactly that one command on an installed\n   release. There is no install step that writes a second copy into `${XDG_BIN_HOME:-$HOME/.local/bin}`\n   — see [the dispatcher section](#ccodex-the-operator-dispatcher) and, if you ran the retired\n   installer on an earlier release, [Retired: the operator-tools PATH plane](#retired-the-operator-tools-path-plane).\n\nEach bundle lifecycle action ends in a terminal summary. `mise run lifecycle:status -- --agent\n<claude|codex>` reports only\nentries already present in the lifecycle ownership record: either\n`no owned entries for this host (run: mise run lifecycle:install)`\nor an `N ok, M conflict, K absent` summary — the empty-plane line quoted here in full, remedy hint\nincluded, because the truncated paraphrase is a shape the product never prints\n(`agentic-sdlc-b97e`; `tests/test_verification_runbook_contract.py` now binds both shapes to\n`status_summary()`'s own returns). It does not inventory unowned names in a configured\ncollection. Before installation, or when a path may have been installed through another checkout,\nuse `mise run lifecycle:install -- --agent <claude|codex> --dry-run`; that read-only preview discovers\nan occupied unowned destination, reports it as preserved, and never adopts, overwrites, or removes\nit. Install and uninstall summaries separately name installed/removed, preserved, planned, and\nconflict counts. `mise run check` runs the authoritative gate. Each command's exit code and output\nare evidence about that run only; neither authorizes any outward effect.\n\n**Mise 2026.4.27 or newer is the only bootstrap prerequisite.** It is the managed-tool bootstrap,\nnot the sole readiness prerequisite. The checked-in `mise.toml` pins `uv`. `mise.lock` records\nsource URLs and SHA-256 checksums for Linux, macOS, and Windows. `uv` supplies Python `3.12.11`\nfor every authoritative Python entrypoint. Git, a verified Seeds distribution, supported trust\nbehavior, repository gates, and the selected adapter remain runtime-readiness capabilities, not\nadditional bootstrap prerequisites. Resolve and record the actual provider/model only when the\nadapter proves it; otherwise record inherited or unresolved.\n\nEvery v1 dispatch receipt uses exactly `requested_model_id`, `requested_effort`,\n`requested_context_form`, request-injection evidence, resolved provider/model identity evidence,\nand effective effort/context readback status plus evidence. Request-injection evidence binds\ncanonical exact requested model/effort/context bytes, adapter identity/version/config digest, and\nrequest-byte digest. It validates internal consistency only: it never proves external injection,\nno-bypass enforcement, or spawned-worker identity. Effective effort/context may be `unavailable`\nwhen the transport does not expose them; requested values never become readback. An external\nharness calls receipt admission immediately before spawn and correlates its digest. It remains\nresponsible for injection, no-bypass, and spawn identity; this repository supplies no host\nlauncher. Only an admitted, certified tuple can reach spawn. Exact Claude `[1m]` forms remain\ndenied pending tuple-specific policy evidence; base Claude eligibility and calibration-supported\nGPT `[1m]` tuples remain. A passing local status or gate never authorizes push, publication, PR\nmutation, merge, deployment, credential, or other outward effect.\n\nThe flagship skill ships the portable Node-stdlib `tools/seeds-launcher.mjs`. From an exact clean\nGit distribution root, run its explicit `bootstrap --distribution <distribution-root>` mode under\nNode `22.23.2`. Both bootstrap and inspect reject any other executing Node. Bootstrap rejects\nnested, staged, dirty, untracked, or ignored distribution content, then alone runs reviewed\n`mise --locked install`. That install isolates HOME, mise config/data/cache, hooks, npmrc, and\nregistry selection from ambient values. Only the reviewed root `mise.toml`/adjacent lock, the\nfixed official npm registry, npm backend, and private empty configs select acquisition. It\nresolves exact config-free Node `22.23.2`, Bun `1.4.0`, and Seeds `npm:@os-eco/seeds-cli@0.5.15`\nroots. It accepts the released package's benign string `engines.bun` compatibility metadata\nwhile rejecting actual config/macro/preload controls. It atomically publishes an exact Git\ncommit/tree and tool-hash receipt. The Seeds lock proves the exact version and npm backend, not\ntarball or transitive dependency integrity. Neither that claim nor the receipt closes a same-UID\nTOCTOU race between validation and execution.\n\nBefore any persistent `mise trust` operation—including the bootstrap below—obtain explicit\noperation-specific approval for the exact reviewed config path. The same gate applies to\npersistent Codex/global config edits, shell aliases, and credential writes; a general run or\nimplementation approval is insufficient. Process-scoped validation may instead use\n`mise --no-config --cd <repo> exec ...` without persisting trust.\n\nBootstrap the repository and inspect the available lifecycle tasks:\n\n```bash\nmise -C <distribution-root> tasks\n<exact-node-22.23.2-root>/bin/node <installed-flagship>/tools/seeds-launcher.mjs bootstrap --distribution <exact-clean-git-root>\n```\n\nAfter explicit bootstrap, read-only Seeds operations use `inspect --target <target>` against only\nthe active receipt. Inspect never installs, networks, calls mise, or repairs state. It allows only\n`--version`, `prime`, `ready [--format json]`, and `blocked [--format json]`; all other input fails\nbefore exact Bun starts. Exact Node uses `shell:false` to invoke only absolute recorded Bun and entry\npaths. Bun receives `--config=<trusted-empty-file>`, `--no-env-file`, and `--no-install`; its\nallowlisted environment isolates target `bunfig`, `.env`, package configuration, ambient `BUN_*`,\n`NODE_OPTIONS`, npm/mise overrides, and unreviewed Seeds debug settings. PATH contains only the\nindependently recorded Git directory, with system/global Git config isolation.\n\nQueue mutation uses `record` with `--queue-writer conductor`. A repository with no `.seeds` node may\nuse only `--expect-queue absent init`; the launcher rejects existing/partial/file/symlink/redirected\nsurfaces, snapshots `.gitattributes`, and refuses non-UTF-8 or exact-line/substr-match-ambiguous\nprestates before mutation. It invokes exact pinned `init --json` and verifies exactly the five\ninitializer files plus only the precise missing merge-union append. Existing queues require an\nexact sha256 and admit only verified create/update deltas. Standalone claim, close, delete, prune,\ndisposition, sync, and other mutation forms remain forbidden. The prerequisite checker exposes\nseparate exact-runtime inspect, init, and record front doors; the skill and\n`references/seeds-worktrees.md` define their unambiguous contracts.\n\nMise trust is scoped to each absolute config path. Every linked worktree needs separate\nexplicit operation-specific approval before trusting its reviewed `mise.toml`, after reviewing\nthe diff. `MISE_PARANOID=1` deliberately rejects an untrusted worktree. After that approval,\napply `MISE_PARANOID=1 mise trust <worktree>/mise.toml`, then rerun the command. Locked\nresolution fails closed when the current platform is absent from `mise.lock`.\n\nEvery task this repository defines, so `mise tasks` never reveals an undocumented one:\n\n| Task | Purpose |\n|---|---|\n| `lifecycle:install` / `lifecycle:status` / `lifecycle:uninstall` | Install, inspect, or remove entries for one plane on the current host. Each requires `-- --agent claude` or `-- --agent codex`; a selector-free run refuses at exit 2. |\n| `lifecycle:install:claude` | Install only the Claude Code plane on the current host. |\n| `lifecycle:install:codex` | Install only the Codex plane on the current host. |\n| `lifecycle:install:all-hosts` | Install the current host and, from WSL, the native Windows host too. |\n| `lifecycle:status:all-hosts` | Report current-host and native-Windows state when run from WSL. |\n| `research-os:install` | Scaffold the repo-scoped research OS through pinned uv/Python; pass installer arguments after `--`. `--target` is required, so there is no implicit current-directory scaffold. |\n| `claude:statusline:status` / `claude:statusline:activate` / `claude:statusline:deactivate` | Inspect or explicitly manage only Claude Code's `statusLine` fields. |\n| `claude:hooks:status` / `claude:hooks:activate` / `claude:hooks:deactivate` | Inspect or explicitly wire one installed agent hook into your Claude settings, one owned `hooks.<Event>` array element at a time (`-- --hook <name>`, never \"all\"). Each activation is its own settings mutation, no `lifecycle:*` path reaches it, and a foreign or modified element is preserved and reported. |\n| `release:build` | Build the deterministic unpublished-candidate archive of the committed HEAD tree into `dist/`. Refuses a dirty tree. A built archive is evidence of what was archived, never a release or a publication. |\n| `release:smoke` | Run `policy/release-smoke.v1.json` against an EXTRACTED archive (`-- --tree <extracted-root>`). Every case asserts report content rather than a bare exit code, because exit 3 is a legitimate status here. A tree inside this checkout is refused rather than smoke-tested as the artifact. |\n| `usage:report` | Advisory read-only usage projection over the local evidence stores. Subscription cost is always unpriced, the default output is dollar-free, refusals appear in the output itself, and there is no cross-store total because the two stores overlap unprovably. Never a gate leaf, and a report authorizes nothing. |\n| `ocx:launch` / `ocx:ultracode` | Launch Claude Code through the gateway using your own `~/.claude` login — native Claude models on your subscription, gateway models on their own providers — normally or with session-only Ultracode. Ordinary permissions are the default; a first `--yolo` is the explicit unsafe bypass profile. |\n| `ocx:status` / `ocx:restart` / `ocx:configure` | Report opencodex gateway reachability, restart it cleanly, or configure providers through their own login flows. |\n| `libraries:list` / `libraries:status` | List the installable external skill libraries with their front doors and surface cost, or report which are already present in this home. Read-only. |\n| `libraries:install` | Install explicitly named external skill libraries through their own front doors; dry run unless `--yes`. Vendors nothing into this tree, and no gate leaf, `contributor:setup`, or deprecated `setup` path reaches it. |\n| `libraries:migrate` | De-duplicate a name another channel holds for the same upstream: retire that channel's copies through its own removal path, then install. Dry run unless `--yes`; names at least one library, never migrates everything. |\n| `mermaid:provision` | Provision the pinned Linux x64 Mermaid browser runtime. Downloads a pinned browser, so it is an explicit operator step and never a gate leaf. |\n| `mermaid:linux-test` | Run the bounded Linux Mermaid renderer tests; they skip with named reasons when the runtime is absent. |\n| `rightsize:evaluate` | Explicit non-gate rightsizing CLI: discover, plan, evaluate after digest-bound approval, or deterministically render prior evidence. Live evaluation may consume provider/subscription capacity and send the selected task-pack data outward. |\n| `validate` | Run the portable bundle validator alone (the pre-commit hook's subset). |\n| `test` | Run the installer test suite. |\n| `self-test` | Exercise install/status/uninstall in an isolated home. |\n| `secrets` | Scan tracked plus nonignored-untracked regular files with the pinned scanner and tracked extend-only config. Symlinks and paths beneath symlinked parents are not followed; ignored runtime state stays out, and history remains a separate consented step. |\n| `check` | Run the authoritative validation, tests, self-test, and secrets gate. Last measured on Linux 2026-08-26: the `test` leaf ran 2426 tests in 426s (`OK (skipped=13)`), while `validate` and `self-test` each finished in under 5s and `secrets` scanned about 12 MB in 15s, so the suite dominates and 15 minutes is a reasonable budget — more on a loaded host, since gate runs contend for CPU and I/O. Treat both numbers as stale-by-design: the count grows with the suite, the clock varies by host, and the gate's verdict is the evidence. |\n| `hooks:install` | Install the checked-in lefthook hooks. |\n| `contributor:setup` | Install the configured bundle planes plus this repository's Git hooks. |\n| `setup` | One-release deprecated forwarder to `contributor:setup`. |\n\nA normal Unix install uses symlinks. On Windows, automatic mode uses directory junctions\nfor directories and file symlinks for files. When the host cannot create those links, it\nfalls back to copies. Strict link mode does not use that fallback. The installer records\nper-entry ownership in the platform state directory (`XDG_STATE_HOME` on Unix,\n`LOCALAPPDATA` on Windows). Lifecycle operations use that record to distinguish bundle\nentries from user files. Write-capable lifecycle commands are serialized per state file.\nOwnership is BYTE identity: a record carries the digest of the bytes this lifecycle published, and\nnothing else identifies the destination. There is no birth-timestamp or device/inode requirement, so\nthere is no minimum libc and no filesystem that has to expose `statx` birth time — a host where\n`cp -r` works can install. See \"Ownership and lifecycle rules\" below for what that costs.\n\n```bash\nmise run lifecycle:install -- --agent claude\nmise run lifecycle:status -- --agent claude\nmise run check\n```\n\nThe native Windows path runs the ordinary current-host task; it does not invoke WSL. When\n`lifecycle:install:all-hosts` or `lifecycle:status:all-hosts` is run from WSL, it runs the WSL\ncurrent-host lifecycle first and then invokes the native Windows mise task. The two host\nsummaries remain separate, and the native task's arguments and exit code are preserved.\n\n### Where the statusline comes from\n\nThe Claude/Codex bundle installer and the plugin do not own shell aliases, PATH, or global Claude\nsettings, and no lifecycle here writes into a PATH directory at all. Writing your `settings.json` is\na persistent user-environment mutation that requires explicit operation-specific approval for that\nexact file; a general install approval never covers it.\n\nThe packaged statusline is one **bundle ledger row**: `lifecycle:install -- --agent claude` publishes\n`assets/claude/statusline-command.sh` to `<claude-home>/.claude/statusline/agentic-sdlc-statusline`\nat mode `0755`, and that owned path is the only place `claude:statusline:activate` will take a\ncommand from — so a statusline that is absent, unowned, drifted, or unexecutable is a named refusal\nrather than a `statusLine.command` pointing at bytes no lifecycle owns. Installing it does not\nactivate it; writing `statusLine.type` and `statusLine.command` into your settings is the separate\noperation-specific grant below.\n\n```bash\nmise run lifecycle:install -- --agent claude   # publishes the owned statusline command\nmise run claude:statusline:status           # read-only: active | inactive | unmanaged | conflict\n```\n\nActivation, dry run, and removal are covered under\n[Which login a launch uses](#which-login-a-launch-uses), which is where the settings-mutation grant\nis described.\n\n### Retired: the operator-tools PATH plane\n\nAn earlier release shipped a separate Unix operator-tools lifecycle that rendered `ccodex` and\n`agentic-sdlc-statusline` into `${XDG_BIN_HOME:-$HOME/.local/bin}` and refused unless that directory\nwas already on `PATH`. **It is deleted.** `bin/ccodex` is committed, self-locating, and exposed\ndirectly by mise, so a second dispatcher existed only to be placed on `PATH` by a lifecycle that\nwould not edit `PATH`.\n\nDeleting the installer deleted `operator-tools:uninstall` with it, so **if you ran it, you still own\nthose files and nothing here will remove them for you.** `ccodex doctor` names the leftover\nstore whenever it is present. Remove them by hand:\n\n```bash\nrm -f \"${XDG_BIN_HOME:-$HOME/.local/bin}/ccodex\" \\\n      \"${XDG_BIN_HOME:-$HOME/.local/bin}/agentic-sdlc-statusline\"\nrm -rf \"${XDG_STATE_HOME:-$HOME/.local/state}/agentic-sdlc-operator-tools\"\n```\n\nTwo things worth checking while you are there. A stale `~/.local/bin/ccodex` earlier on `PATH` than\nmise's shim keeps answering as if nothing changed — `type ccodex` tells you which file wins. And if\nyou activated the statusline through the old plane, `statusLine.command` in your Claude settings\nstill points into `~/.local/bin`; re-run `claude:statusline:activate` after a\n`lifecycle:install -- --agent claude` so it names the owned ledger path instead. The historical\n`ocx-launch` and `ocx-ultracode` aliases, if you have them, are removed the same manual way.\n\n### `ccodex` — the operator dispatcher\n\n`ccodex` is the whole daily use surface without mise in the way. Plain `claude` remains the direct\nAnthropic-routed CLI; `ccodex launch` adds the gateway to that same login, so one session serves\nboth catalogs — native claude ids pass through to Anthropic on your subscription and gateway ids\nroute to their own providers (ADR-0014). It is not a separate non-Anthropic-only route. Fresh\nNothing here creates `ocx-launch` or `ocx-ultracode`; if an old release left you copies, remove them\nby hand (see [the retirement section](#retired-the-operator-tools-path-plane)). Every gateway command remains reachable as\n`ccodex ocx <verb>`, the low-level compatibility form; `ccodex --help` prints the surface at any time.\n\n**Gateway plane** — running one Claude Code session that can reach both catalogs:\n\n| Command | What it does |\n|---|---|\n| `ccodex ensure` | Ensure the gateway is healthy without launching Claude Code. |\n| `ccodex launch [--yolo] [claude args...]` | Ensure the gateway is healthy — start it if down, restart once if half-up — then launch Claude Code in the caller's current workspace through the distribution's pinned gateway toolchain, using your own `~/.claude` login. Native claude models pass through to Anthropic on your subscription while gateway models route to their own providers, in one session. Fails closed if the gateway never becomes healthy, and refuses (exit 3) when exported, persistent, or explicit `--settings` configuration would silently defeat the route. Accepted Claude arguments are forwarded unchanged. A first `--yolo` is consumed by ccodex and explicitly selects Claude Code's permission-bypass mode; it is unsafe outside an isolated, disposable environment. Use `-- --yolo` only to forward that spelling literally. |\n| `ccodex launch --model <id>` | Pick any id in the running gateway's live catalog, including a namespaced one: `--model muse/muse-spark-1.2`. Run `ccodex models` for the list. |\n| `ccodex ultracode [--yolo] [claude args...]` | The same fail-closed launch path with session Ultracode applied. Ordinary permissions remain the default. A first `--yolo` explicitly selects the same unsafe permission-bypass mode as `ccodex launch --yolo`; this is the ccodex equivalent of the historical `ccode-ultracode` alias. Ultracode owns the session `--settings` value and refuses a competing setting. |\n| `ccodex status` | Read-only supervision view: pid, port, uptime, healthy/down, log location, configured providers each compared against the LIVE catalog, whether anything exported here or in the settings documents Claude Code reads for `env` would defeat the gateway route — the check NAMES the documents it read and what it did not read — and the attribution log command. Exit 0 means the gateway answered an identity-checked probe at that moment — evidence, not authorization. |\n| `ccodex restart` | Stop the gateway cleanly, then ensure it is back up. Fails closed on an unclean stop. Interrupts in-flight turns in every routed session, and `ocx` rewrites shared `~/.codex` config as part of its lifecycle. |\n\n**Providers and models** — what a launched session can actually pick:\n\n| Command | What it does |\n|---|---|\n| `ccodex providers` | Configured providers, and which are LIVE in the running gateway. A provider in the config file is **not** live until `ccodex restart` has published it — check here rather than trusting an add's success message. |\n| `ccodex models` | The running gateway's flat live catalog. Muse models appear as ordinary namespaced entries, not as a separate plane. |\n| `ccodex set-fast-model [<exact-model-id\\|->]` | With no argument, choose a Claude Code family or a model in the gateway's live OCX catalog, or clear the override to use the normal subscription Haiku slot. One argument preserves the exact noninteractive path; `-` clears. The write goes through OpenCodex and is **not** Auto mode's permission classifier. Claude families are entitlement-checked when used; only the OCX rows are proven live when the menu is built. |\n| `ccodex configure` | With no arguments, print the admitted configuration surface in detail. |\n| `ccodex configure provider add\\|edit\\|remove\\|set-default <name> ...` | Reviewed provider mutation for non-Anthropic providers. Writes the **config file only** — see [the key sequence below](#adding-a-provider-that-needs-an-api-key). |\n| `ccodex configure account add-key <name>` | Store a provider API key, read **only** from piped stdin. |\n| `ccodex configure account list\\|current <name>` | Masked credential inspection. |\n| `ccodex configure help <verb>` | Inspect the upstream `ocx` surface without running it. |\n\n**Experimental non-Claude Auto fallback, per launch only.** Claude Code exposes no supported\n`classifierModel` setting. The only documented indirect experiment is to exclude Sonnet 5 from one\nlaunch, which makes current Claude Code fall back to the session model when that route is otherwise\neligible:\n\n```bash\nauto_settings='{\"availableModels\":[\"gpt-5.6-sol\"]}'\nccodex launch --model gpt-5.6-sol --permission-mode auto --settings \"$auto_settings\"\n```\n\nUse the same exact routed ID in both places and keep all inline settings in that one document.\n`availableModels` constrains session, subagent, workflow, skill, and advisor selection for the\nwhole launch—not only Auto—and routed GPT/Muse Auto support is undocumented. This recipe is not an\nidentity claim; a real claim needs a separately approved bounded canary with request-correlated\ngateway attribution. See\n[`docs/research/2026-08-12-claude-code-auto-mode-controls.md`](docs/research/2026-08-12-claude-code-auto-mode-controls.md).\n\n**Installed-bundle lifecycle** — managing what is installed, without mise:\n\n| Command | What it does |\n|---|---|\n| `ccodex install\\|status\\|update\\|uninstall --scope user\\|project --agent claude\\|codex` | The one lifecycle verb family. BOTH selectors are required on all four; a run missing either refuses at exit 2 naming the flag, and there is no default and no wildcard for either. `--scope project [--project PATH]` resolves ONE repository root — the named path, or a walk up from the working directory — and keys that plane by it, so two worktrees of one repository are two independent planes; project scope is copy-only, and an unresolvable, forbidden, or non-git root refuses at exit 3 by name with nothing written. `--agent codex` refuses project scope by name: its configured root IS its agent root, so it has no repository-local collection. Project scope places the whole selected plane's payload set, workflow bytes included: it is the ONE path that owns a repository's `.claude/workflows/` since the per-file `claude:workflows:*` manager was deleted, so a placement there enables the workflow at the target's next session — every completed project-scope run says so — while hook bytes land inert, since wiring one into settings is its own grant. An already-enabled copy byte-identical to the payload's own bytes is adopted as removable; a drifted one is preserved and named. |\n| `ccodex doctor [--json]` | The whole-box read: every state store, by absolute path, with a verdict each. No selectors — \"what is on this machine\" spans every scope by definition. Six rows today, each carrying a component, a `live`/`retired` kind, and `present`/`absent`/`unreadable`; an absent store is still named, so the count is a fact about this distribution rather than about your machine. This sentence was aspirational until 2026-08-26 — a populated host used to read out three of the six — and it is now checked by a test that re-derives the store set from the source (gh #8 acceptance 9). Naming a store never creates it, and only a retired one carries a removal remedy. |\n| `ccodex recover --dry-run [--json]` / `--apply <plan-sha256>` | Propose the one pending transition this host can carry and render the digest that approves exactly that plan, or resume it. The approval IS the digest. |\n| `ccodex bundle …` / `ccodex sdlc …` | **Retired.** Both refuse at exit 2 with the replacement invocation named. The checkout tasks that shared the `bundle` name are `lifecycle:*` now. |\n| `ccodex libraries list\\|status` | List installable external skill libraries with their front doors and surface cost, or report which are already in this home. Read-only. |\n| `ccodex libraries install <name> [--yes]` | Install a named external library through **its own** front door. Dry run unless `--yes`; vendors nothing into this tree. |\n| `ccodex libraries migrate <name> [--yes]` | Retire another channel's copies of the same upstream through that channel's own removal path, then install. Dry run unless `--yes`. |\n| `ccodex statusline status\\|activate\\|deactivate` | Inspect or explicitly manage only Claude Code's `statusLine` fields. Inactive until you activate it. |\n| `ccodex version` | This command's resolved repository root and runtime dependencies. |\n\n**Help, and how to reach the wrapped tool's help.** `ccodex <verb> --help` prints that verb's own\nhelp and **runs nothing** — no gateway, no session state, no constructed settings. To reach the\nhelp of the tool *behind* a launch verb, end this command's options with `--`:\n\n```bash\nccodex launch --help                # this verb's help; prepares nothing, launches nothing\nccodex launch -- --help             # `--` forwards verbatim: Claude Code's OWN help\nccodex launch -- --print \"prompt\"   # any Claude Code argument, through a prepared session\n                                     # Claude Code's own help, only if gateway is already healthy\n```\n\n`providers` and `models` are the two exceptions: they take no options of their own, so they run\nthe query rather than printing a help page, and `models` exits 1 when the gateway is down because\nan unanswerable query is a failure rather than a refusal.\n\n**Exit codes**, uniform across every route: `0` ok · `1` failure or unhealthy · `2` usage ·\n`3` refused, meaning a boundary declined the operation rather than failing at it.\n\nOnly the **use** surface is installed. The maintenance tasks — `test`, `validate`, `check`,\n`secrets`, `self-test`, `mermaid:*`, `hooks:install` — are deliberately absent, because they\nbelong to working *on* this repository rather than to using what it installed; run those with\n`mise run <task>` inside the checkout. One owned dispatcher rather than a dozen named commands\nmeans one ownership record, one place a new verb appears, and no PATH namespace land-grab.\n\n**A shell function or alias named `ccodex` will shadow this command.** Bash resolves functions\nand aliases before `PATH`, so a leftover definition silently wins and the installed dispatcher is\nnever reached — the symptom is `ccodex --help` printing the *wrapped tool's* help instead of the\ntable above. Diagnose with `type ccodex`: it must report a **file** inside a distribution tree's own\n`bin/` — a checkout's, or mise's install directory for the version you selected — not a function, not\nan alias, and not a leftover copy in `${XDG_BIN_HOME:-$HOME/.local/bin}` from the retired PATH plane.\n`which ccodex` is not enough, since it reports the file that a function is hiding.\n\n### Adding a provider that needs an API key\n\n`provider add` writes the provider's SHAPE only. **It accepts no key** — it has no `--api-key`\nflag and it does not read stdin, so a key piped to it is silently dropped and every later request\nfails with `401 invalid_api_key` while the routing itself looks correct in the attribution log.\nThe key goes in through a different verb, and the gateway must already be running **and already\nrestarted** when it does. Measured end to end in one clean run on 2026-08-23:\n\n```bash\n# 1. the gateway must be UP: add-key stores nothing against a stopped proxy.\nccodex ensure\n\n# 2. the provider's shape. No key here.\nccodex configure provider add muse --adapter openai-responses \\\n  --base-url https://api.meta.ai/v1 --default-model muse-spark-1.2\n\n# 3. the PUBLISH step: step 2 wrote the config file, not the running catalog.\nccodex restart\n\n# 4. the key, read only from piped stdin -- never argv, which `ps` exposes host-wide.\nprintf '%s' \"$YOUR_KEY\" | ccodex configure account add-key muse --label my-key\n\n# 5. confirm, then use it.\nccodex providers                    # muse should be LIVE, not merely configured\nccodex launch --model muse/muse-spark-1.2\n```\n\nAfter step 4 the provider carries `apiKey` and `apiKeyPool`; before it, only `adapter`, `baseUrl`,\nand `defaultModel`. Check with `ccodex providers` rather than trusting step 2's success message.\n\n**Step 3 is the publish step, and step 4 is why it has to come first.** `add-key` validates the\nprovider against what the RUNNING gateway serves rather than against the config file, so run\nbetween steps 2 and 3 it fails `Error: unknown provider` for a provider `ccodex providers` listed\nas configured one command earlier, and against a stopped proxy it fails `Proxy not reachable`.\nMeasured 2026-08-23 in one container with no Codex installed and `ocx sync` never run: the restart\nalone took the live catalog from 7 ids serving none of the new provider to 420 serving 413 of it,\nand the key then stored on the first try. Both constraints are upstream opencodex behavior,\nreproduced against the raw pinned binary, and neither is in the configure help — the message says\n`unknown provider` where it means *configured but not yet published*. What `add-key` needs is a\nrunning gateway whose catalog already includes the provider, and a restart after the provider add\nis the only order that guarantees it. The older 2026-08-08 sequence in\n[`docs/research/2026-08-08-fresh-host-install-verification.md`](docs/research/2026-08-08-fresh-host-install-verification.md)\nstored a key before its restart because its `ensure` came after the provider add and started a\ngateway that was down — a cold start rather than a stale one.\n\nTwo upstream notes. `ocx sync` — which the post-mutation notice names — needs Codex installed and\nreports `Codex config not found` on a host without it; the gateway still starts and still routes,\nso the restart path above is sufficient. And `ocx ensure` may log\n`Provider model discovery ... failed with HTTP 401 [fallback=configured]` for a key-authenticated\nprovider: that is ocx not sending the key on its discovery probe, it is harmless, and the\nconfigured model id is used instead.\n\n**Reasoning models need a real token budget.** `muse-spark-1.2` spent 163 of 176 completion tokens\non reasoning for a two-word answer. A `max_tokens` that looks generous for the visible reply\nreturns `content: null` with `finish_reason: \"length\"` — which reads exactly like a broken\ncredential and is not. Size the budget for the reasoning trace.\n\n**A distribution tree is required, and `ccodex` resolves every tool through that tree's own pins.**\n`ccodex` is a thin entry point rather than a self-contained copy: its launcher and Python lifecycle\nscripts live in the tree beside it, and it resolves `ocx`, `jq`, `uv`, and the pinned CPython through\nthat tree's reviewed `mise.toml` + `mise.lock` at the moment a verb needs them. Nothing is bound at\ninstall time any more — the retired operator-tools plane was the only thing that ever rendered\nabsolute tool paths into a dispatcher, and deleting it removed both the binding step and the refresh\nstep that kept it current. The consequence to know is that the pinned toolchain must be resolvable\nin the tree the dispatcher located, and `mise` itself is found on `PATH` because it is this\nrepository's documented sole bootstrap prerequisite. Launch and Ultracode start Claude Code in the\ncaller's physical current workspace; the tree selects code and runtime identity, not the project\nClaude works on. `$AGENTIC_SDLC_OCX` and `$AGENTIC_SDLC_JQ` remain caller-supplied exact-absolute\noverrides, admitted only as absolute paths, and nothing shipped here sets either.\n\nNo shell startup file or PATH value is edited. Every launch route delegates to\n`scripts/opencodex-claude.sh`, so identity-checked supervision and the route-integrity\nrefusals remain mandatory, including validation of every explicit `--settings` value before the\ngateway starts. The ADR-0005 credential refusal, the environment scrub, and the\nseparate Claude config dir are GONE from this launcher (ADR-0014): it uses your own `~/.claude`\nso Claude Code can present its existing login to the gateway. `ccodex ultracode` refuses a\ncompeting `--settings`; on either launch form, `--yolo` refuses competing permission controls.\nLaunch/resta",
  "bytes": 60000,
  "sha": "9b57ef1c5cf0e0d0bbdb08ca128d84d3edaba8e9784f606236d8fb722ed9f5e8",
  "repo_slug": "codeseys-labs/agentic-sdlc",
  "fonte": "repo",
  "truncated": false,
  "api": "https://agentalog.com/api/listings/plg_codeseys_labs_agentic_sdlc_da63a92f/readme"
}