planr 1.4.0 → 1.5.1

This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
Files changed (60) hide show
  1. package/README.md +21 -61
  2. package/docs/ARCHITECTURE.md +4 -4
  3. package/docs/CLAUDE_CODE.md +2 -2
  4. package/docs/CLI_REFERENCE.md +6 -14
  5. package/docs/CODEX.md +6 -6
  6. package/docs/CURSOR.md +2 -2
  7. package/docs/EXAMPLE_WEBAPP.md +63 -97
  8. package/docs/GOALS.md +8 -25
  9. package/docs/INSTALL.md +3 -3
  10. package/docs/MCP_CONTRACT.md +6 -9
  11. package/docs/MODEL_ROUTING.md +20 -177
  12. package/docs/RELEASE.md +1 -1
  13. package/docs/ROUTING_BUNDLES.md +32 -0
  14. package/docs/SKILLS.md +35 -50
  15. package/docs/documentation/CONTRACT.md +164 -0
  16. package/docs/documentation/COVERAGE.md +91 -0
  17. package/docs/documentation/INFORMATION_ARCHITECTURE.md +147 -0
  18. package/docs/fixtures/mcp-contract.json +3 -11
  19. package/npm/native/darwin-arm64/planr +0 -0
  20. package/npm/native/darwin-x86_64/planr +0 -0
  21. package/npm/native/linux-arm64/planr +0 -0
  22. package/npm/native/linux-x86_64/planr +0 -0
  23. package/package.json +25 -14
  24. package/plugins/planr/.claude-plugin/plugin.json +1 -1
  25. package/plugins/planr/.codex-plugin/plugin.json +2 -2
  26. package/plugins/planr/skills/planr-loop/SKILL.md +1 -1
  27. package/docs/PRESET_COMPOSITION.md +0 -109
  28. package/docs/PRESET_EVALUATION.md +0 -118
  29. package/docs/PRESET_REGISTRY.md +0 -61
  30. package/evaluations/preset-suite-v1.toml +0 -127
  31. package/evaluations/sol-luna-codex-v1.toml +0 -42
  32. package/plugins/planr/skills/planr-loop/agents/planr-reviewer.toml +0 -23
  33. package/plugins/planr/skills/planr-loop/agents/planr-worker.toml +0 -21
  34. package/presets/bindings/claude-native.toml +0 -52
  35. package/presets/bindings/codex-openai.toml +0 -56
  36. package/presets/bindings/cursor-fable-grok.toml +0 -49
  37. package/presets/bindings/cursor-openai.toml +0 -49
  38. package/presets/bindings/mixed-host.toml +0 -64
  39. package/presets/policies/balanced.toml +0 -50
  40. package/presets/policies/low-usage.toml +0 -50
  41. package/presets/policies/max-quality.toml +0 -50
  42. package/presets/policies/read-only-audit.toml +0 -50
  43. package/website/README.md +0 -79
  44. package/website/_headers +0 -7
  45. package/website/alchemy-runtime.test.mjs +0 -21
  46. package/website/app.mjs +0 -216
  47. package/website/build-catalog.mjs +0 -135
  48. package/website/build-site.test.mjs +0 -69
  49. package/website/catalog-model.mjs +0 -185
  50. package/website/catalog-model.test.mjs +0 -124
  51. package/website/cloudflare-launcher.test.mjs +0 -38
  52. package/website/data/catalog.json +0 -307
  53. package/website/index.html +0 -122
  54. package/website/registry/manifest.toml +0 -48
  55. package/website/registry/report.md +0 -33
  56. package/website/registry/trusted-maintainers.toml +0 -6
  57. package/website/registry/verification.json +0 -7258
  58. package/website/serve.mjs +0 -41
  59. package/website/styles.css +0 -201
  60. package/website/test-fixtures/recommended.json +0 -72
package/README.md CHANGED
@@ -4,6 +4,10 @@
4
4
 
5
5
  Planr is a local-first planning and execution coordination tool for coding agents. It combines reviewable Markdown plans with a dependency-aware work map so Codex, Claude Code, Cursor, generic MCP clients, and human operators can drive the same work safely — from idea to verified completion.
6
6
 
7
+ [**View the Demo →**](https://x.com/kevinkern/status/2066957434564808884?s=20)
8
+
9
+ [**Documentation →**](https://planr.so/docs)
10
+
7
11
  ```text
8
12
  idea -> product plan -> build plan -> map -> pick -> log -> review/evidence -> close
9
13
  ```
@@ -22,61 +26,6 @@ Flat todo lists break down the moment real work has structure. Planr models work
22
26
 
23
27
  Three layers make that work: **Plans** (reviewable Markdown packages), the **Map** (live dependency graph with picks, reviews, logs), and **Agent loops** (skills, CLI, and MCP workflows for every major coding agent). Full model: [Task Graph Model](docs/TASK_GRAPH_MODEL.md) and [Operating Model](docs/OPERATING_MODEL.md).
24
28
 
25
- ## New in 1.4.0: Verified Presets & Catalog
26
-
27
- Planr now ships a verified preset system for composing a provider-neutral usage policy with a host binding, previewing every repository-local change, and applying the result only after confirmation:
28
-
29
- ```bash
30
- planr agents preset list
31
- planr agents preset apply balanced --binding codex-openai --preview
32
- planr agents preset apply balanced --binding codex-openai --confirm
33
- ```
34
-
35
- The built-in catalog includes four policies, five host bindings, and 20 declared safe pairs. Reproducible evaluation, signed registry verification, and the public [Planr Preset Catalog](https://planr-test-catalog.office-35d.workers.dev/) keep recommendation evidence inspectable without making the registry a runtime dependency. Full guides: [Preset Composition](docs/PRESET_COMPOSITION.md) · [Preset Evaluation](docs/PRESET_EVALUATION.md) · [Preset Registry](docs/PRESET_REGISTRY.md).
36
-
37
- ## New in 1.3.0: Native Host Hooks
38
-
39
- `planr install codex|claude|cursor` now wires Planr into the host's native hook system by default — every new session (including post-compaction restarts) gets one compact state block injected automatically:
40
-
41
- ```text
42
- ## planr state
43
- project: Hookboard | map: 5/5 settled | 0 ready, 0 picked, 0 in_review
44
- goal contract: DONE when every in-scope map item is closed with log evidence, ...
45
- routing: registry active (3 profiles; pick packets carry model routing)
46
- next: planr plan audit pln-fc584c28 --json
47
- ```
48
-
49
- - **`planr prime`** — the state block behind the hooks: project, map counts, held items with log status, goal contract, and the next command. Silent in repos without a Planr database.
50
- - **Loop recovery becomes mechanism, not discipline** — an agent that restarts or compacts mid-loop picks up exactly where the map says it left off.
51
- - **Evidence guard (Cursor)** — a subagent that stops while its own pick has no completion log gets one advisory reminder naming the item and the two ways out.
52
- - **Fail-open and additive** — hooks never block a session (10s timeout, always exit 0), existing hook files are merged, `--no-hooks` opts out.
53
-
54
- Full guide: [Hooks](docs/HOOKS.md) · [Release notes](https://github.com/instructa/planr/releases/tag/v1.3.0).
55
-
56
- ## Model Routing (1.2.0)
57
-
58
- Declare once which model handles which work — every task then carries its own routing, and your agents delegate automatically:
59
-
60
- ```toml
61
- # .planr/agents.toml (write it with `planr agents init`)
62
- [profiles.frontender]
63
- client = "cursor"
64
- model = "opus"
65
- skill = "frontend-design"
66
-
67
- [[routes]]
68
- match = { work_type = "frontend" }
69
- profile = "frontender"
70
- fallbacks = ["driver"]
71
- ```
72
-
73
- - **Routing travels in the pick packet** — `planr pick --json` hands the worker its profile, model, and paired skill; `planr pick --peek` lets dispatching drivers read it without taking the lease.
74
- - **Rendered into your hosts' native config** — `planr install codex|claude|cursor` writes the subagent role files with model pins from the registry, in each host's exact vocabulary.
75
- - **Declared vs. actual, with receipts** — workers report the profile they ran on, runs record the observed host, and `planr trace item` shows deviations as advisory markers.
76
- - **Use-case pools** — free-form work types (`frontend`, `backend`, ...) declared right in the plan's task list (`### TASK-001 (backend): ...`), plus per-item pins via `planr item route`.
77
-
78
- Routing is advisory by design: Planr never dispatches models and never blocks a pick — hosts stay the authority. Full guide: [Model Routing](docs/MODEL_ROUTING.md) · replayable walkthrough: [Worked Example: Web App](docs/EXAMPLE_WEBAPP.md) · [Release notes](https://github.com/instructa/planr/releases/tag/v1.2.0).
79
-
80
29
  ## Install
81
30
 
82
31
  ```bash
@@ -95,7 +44,7 @@ Or with the release installer:
95
44
  curl -fsSL https://raw.githubusercontent.com/instructa/planr/main/scripts/install.sh | sh
96
45
  ```
97
46
 
98
- Then initialize a project (also provisions the worker/reviewer subagent roles for your client):
47
+ Then initialize a project. When selected, Claude Code and Cursor also receive standalone project worker/reviewer roles; Codex workflow skills come from its plugin:
99
48
 
100
49
  ```bash
101
50
  planr project init "My Product" --client all
@@ -105,7 +54,7 @@ Manual downloads, from-source builds, and client wiring details: [Install Guide]
105
54
 
106
55
  ## Install The Plugin (Skills)
107
56
 
108
- The plugin under `plugins/planr` carries the nine Planr skills plus the `planr-worker` and `planr-reviewer` subagent roles. The `planr` CLI (above) is required separately.
57
+ The plugin under `plugins/planr` carries the ten Planr workflow skills. Optional model-routing roles come from repository-local routing bundles. The `planr` CLI (above) is required separately.
109
58
 
110
59
  <a id="install-plugin-codex"></a>
111
60
  <details>
@@ -141,7 +90,7 @@ One command installs everything the plugin would carry:
141
90
 
142
91
  ```bash
143
92
  planr install cursor # writes .cursor/mcp.json, .cursor/agents/, and .cursor/skills/
144
- planr install cursor --no-mcp # skills and subagents only, no MCP config
93
+ planr install cursor --no-mcp # project skills, subagents, and hooks; no MCP config
145
94
  ```
146
95
 
147
96
  The dry-run also prints a one-click `cursor://` deeplink for user-level MCP install. Marketplace listing is pending review. Multitasking with Cursor subagents: [Cursor guide](docs/CURSOR.md).
@@ -163,7 +112,7 @@ planr prompt cli
163
112
 
164
113
  ## Tell Your Agent
165
114
 
166
- Two skills drive everything. `$planr` routes any request to the right stage skill from live map state; `$planr-loop` drives one feature through work, live verification, and independent review until the map is clean.
115
+ Remember one public entry point: `$planr`. It routes the request from live Planr state, including planning-only work and autonomous-goal preparation. Stage skills are advanced surfaces selected by the router.
167
116
 
168
117
  Start a new product from an idea:
169
118
 
@@ -174,10 +123,13 @@ Create a production-ready Habit Tracker web app plan. Create the product plan,
174
123
  split an MVP build plan, check it, then build the Planr map. Do not implement yet.
175
124
  ```
176
125
 
177
- Ship one feature autonomously until verified:
126
+ For a long autonomous run, prepare outside the driver first. The preparation result prints a real plan id; Codex or Claude Code then starts only the plan-bound loop driver:
178
127
 
179
128
  ```text
180
- Use $planr-loop.
129
+ Use $planr to prepare an autonomous goal for the weekly overview feature.
130
+
131
+ /goal Use $planr-loop on plan <plan-id>. The loop contract is stored in planr
132
+ context (tag: goal-contract).
181
133
 
182
134
  Goal: ship the weekly overview feature. DONE when every in-scope map item is closed
183
135
  with log evidence, all reviews are closed complete, and a live verification log shows
@@ -186,6 +138,14 @@ the feature working in the browser. Iteration budget: 10.
186
138
 
187
139
  Mid-project work (a new feature, refactor, or fix on an existing project) works the same — it gets its own feature-scoped plan and extends the existing map. Both journeys with example prompts: [Two Journeys](docs/SKILLS.md#two-journeys-new-project-vs-existing-project). Watch progress anytime with `planr map show`.
188
140
 
141
+ ## What's new
142
+
143
+ - **1.5.0 — Optional routing policies:** Planr Core stays provider-neutral while the independently buildable `planr-routing` package owns model policies and host bindings for Codex, Claude Code, Cursor, and mixed-host setups. Start with [Routing Bundles](docs/ROUTING_BUNDLES.md), the [`planr-routing` guide](planr-routing/docs/MODEL_ROUTING_POLICY.md), and the [1.5.0 release notes](https://github.com/instructa/planr/releases/tag/v1.5.0).
144
+ - **1.4.0 — Verified presets:** Added policy-driven composition, evaluation, signed registry evidence, and the public catalog. See the [1.4.0 release notes](https://github.com/instructa/planr/releases/tag/v1.4.0).
145
+ - **1.3.0 — Native host hooks:** Added automatic session-state injection and loop recovery for supported hosts. See the [Hooks guide](docs/HOOKS.md) and [1.3.0 release notes](https://github.com/instructa/planr/releases/tag/v1.3.0).
146
+
147
+ For the complete release history, see the [Changelog](CHANGELOG.md).
148
+
189
149
  ## Docs
190
150
 
191
151
  - [Install](docs/INSTALL.md)
@@ -6,7 +6,7 @@ Planr V1 is a single Rust binary with explicit module ownership. The crate stays
6
6
 
7
7
  - `src/`: the Rust CLI (module ownership below).
8
8
  - `tests/e2e.rs`: real CLI, MCP, HTTP, import, review-gate, run-log, and concurrent-pick tests.
9
- - `plugins/planr/`: the installable plugin payload — all nine skills, the worker and reviewer subagent roles, and the per-host plugin manifests.
9
+ - `plugins/planr/`: the installable plugin payload — all ten skills, independent Claude/Cursor worker and reviewer role assets, and the per-host plugin manifests. Native Codex role TOMLs are generated from the selected binding instead of shipped here.
10
10
  - `.agents/plugins/marketplace.json`, `.claude-plugin/marketplace.json`: marketplace manifests pointing Codex and Claude Code at `plugins/planr`.
11
11
  - `docs/`: user and contributor guides; `docs/planr-spec/` is the production specification package for Planr V1.
12
12
  - `examples/real-world-flow.md`: executable real-world operator flow.
@@ -43,12 +43,12 @@ Planr V1 is a single Rust binary with explicit module ownership. The crate stays
43
43
  - `src/usage_policy.rs`: provider-neutral Usage Policy v1 core. Owns strict `.planr/policy.toml` parsing, policy and task-contract vocabulary, materiality classification, budget/concurrency validation, and the pure five-way transition resolver; it contains no provider ids, host dispatch, or execution-permission behavior.
44
44
  - `src/execution_policy.rs`: execution admission core. Owns per-role filesystem, network, tool/MCP, structured command, environment, hook, secret, and approval grants; permission-diff previews; bounded task-contract admission; fail-closed command grammar; and isolated write-scope concurrency. It never selects models or mutates graph state. `src/app/policy.rs` binds that pure decision to the current SQLite lease owner and pick token, and only treats an admission from that exact lease generation as authoritative.
45
45
  - `src/route_audit.rs`: provider-neutral run-observation contract. Owns strict requested/resolved/effective route stages, model/effort/fork enforcement confidence, transition provenance, policy/binding versions, and per-dimension metering confidence. It rejects requested-only values in the effective stage rather than inferring host execution.
46
- - `src/preset.rs`: pure preset-composition core. Owns versioned host-binding types, abstract-role compatibility, model/effort/fork capability validation, deterministic registry projection, verification age, permission additions, and provenance-lock vocabulary; it performs no writes.
47
- - `src/app/presets.rs`: shared CLI/MCP preset application service and repository-artifact writer. Owns preview/conflict reporting, canonical-root and allowlist enforcement, symlink/traversal rejection, create-only apply, rollback on write failure, and `policy_applied`/rejection events.
46
+ - `src/routing_bundle.rs`: provider-neutral RoutingBundle v1 contract and repository transaction boundary. Owns validation, hashes, signatures, allowlisted paths, conflict and symlink rejection, atomic apply, rollback, and application receipts.
47
+ - `planr-routing/`: independently buildable workspace package that owns model policies, host bindings, generated host artifacts, probes, evaluation, signing, registry data, and catalog publication.
48
48
  - `src/app/agents.rs`: routing application boundary. Owns the `agents` and `item route` command handlers, the shared `*_value` JSON shapes reused by MCP, per-item route facts assembly, and registry-aware role content selection for installs.
49
49
  - `src/app/agents_init.rs`: registry bootstrap boundary. Owns `planr agents init` — the static cost-tiering scaffold and, per the agent-pool plan, the flag-spec builder and interactive wizard.
50
50
  - `src/integrations.rs`: agent-client integration descriptor boundary. Owns Codex, Claude Code, Cursor, MCP install metadata, MCP tool schemas, MCP resources, and MCP text response wrapping.
51
- - `src/rolefiles.rs`: host role file boundary. Owns the shipped static subagent role files and Cursor skills payloads, plus the pure renderers that re-pin role files from registry profiles (Codex TOML with strict field names, Claude/Cursor markdown frontmatter) under the generated-from header.
51
+ - `src/rolefiles.rs`: static host workflow roles and Cursor skill payloads. It does not select or pin models; generated routing artifacts belong to `planr-routing` bundles.
52
52
  - `src/util.rs`: small CLI-boundary utilities. Owns ids, timestamps, path helpers, output formatting, and safe file writes.
53
53
 
54
54
  ## Boundary Rules
@@ -38,7 +38,7 @@ planr install claude
38
38
  planr doctor --client claude
39
39
  ```
40
40
 
41
- Dry-run prints both project-scope `.mcp.json` content and the user-scope CLI form. The non-dry command writes only this repository's `.mcp.json`.
41
+ Dry-run prints both project-scope `.mcp.json` content and the optional user-scope CLI form. The non-dry command writes this repository's `.mcp.json`, standalone worker/reviewer roles, and additive fail-open session hooks. Workflow skills and plugin agents come from the Claude Code plugin. Use `--no-mcp` to omit `.mcp.json`, or `--no-hooks` to omit hook reconciliation.
42
42
 
43
43
  Claude Code should treat Planr map state as authoritative and use Markdown plans as context.
44
44
 
@@ -49,4 +49,4 @@ planr review ingest <item-id> --from .planr/tmp/claude-review.json
49
49
  planr review artifact <review-item-id>
50
50
  ```
51
51
 
52
- Planr does not install shell hooks or edit global Claude Code configuration. The review item remains open until `planr review close` records the final verdict.
52
+ Planr does not edit global Claude Code configuration. Project hooks live in `.claude/settings.json`, preserve foreign entries, and can be omitted with `--no-hooks`. The review item remains open until `planr review close` records the final verdict.
@@ -67,11 +67,9 @@ planr agents init [--force]
67
67
  planr agents init --profile|--skill|--route|--default-route|--interactive
68
68
  planr agents list [--json]
69
69
  planr agents check
70
- planr agents preset list [--json]
71
- planr agents preset apply <policy-path-or-id> --binding <binding-path-or-id> [--preview|--confirm]
72
- planr agents preset registry verify <manifest> --entry <id> --content-root <dir> [--trust-store <path>] [--at-unix <timestamp>] [--host <host>]
73
- planr agents preset registry import <manifest> --entry <id> --content-root <dir> [--trust-store <path>] [--at-unix <timestamp>] [--host <host>] [--preview|--confirm]
74
- planr agents preset registry list [--at-unix <timestamp>]
70
+ planr routing bundle inspect <bundle.json>
71
+ planr routing bundle preview <bundle.json>
72
+ planr routing bundle apply <bundle.json>
75
73
  planr doctor [--client codex|claude|cursor|all]
76
74
  planr install codex|claude|cursor [--dry-run] [--no-mcp] [--force] [--no-hooks]
77
75
  planr prompt cli|mcp|http [--client codex|claude|cursor|all]
@@ -143,15 +141,9 @@ With `--json`, responses follow one convention so agents never guess where data
143
141
 
144
142
  `policy show` and `policy check` inspect the provider-neutral Usage Policy v1 file (`.planr/policy.toml`). A missing policy is an explicit successful state that preserves existing advisory routing; a malformed or unsafe policy fails `check` with parser/field diagnostics and leaves enforcement unavailable. Usage Policy v1 fixes delegation depth at one and keeps retry, availability fallback, quality escalation, quota downgrade, and safety stop as distinct transition contracts. Its separate `execution` section declares bounded per-role filesystem, network, tool/MCP, structured command, environment, hook, secret-reference, and approval grants. `policy admit <request.json>` requires the picked item's current `item_id` and `pick_token`, authorizes the current worker as lease owner, evaluates a bounded task contract before delegation, previews any permission addition, records the decision and lease generation, rejects unclassified commands and destructive or out-of-scope work, permits overlapping readers, and admits concurrent writers only for disjoint scopes isolated in distinct worktrees. Released or recovered leases never inherit historical admitted scopes. MCP `planr_policy_show`, `planr_policy_check`, and `planr_policy_admit`, plus HTTP `POST /v1/policy/admit`, call the same admission service and return the same decision shape.
145
143
 
146
- `agents preset list` enumerates the embedded catalog: `balanced`, `low-usage`, `max-quality`, and `read-only-audit` policies; `codex-openai`, `cursor-openai`, `cursor-fable-grok`, `claude-native`, and `mixed-host` bindings; source checksums; and every declared safe pair. MCP `planr_presets_list` returns the identical catalog.
144
+ `routing bundle inspect|preview|apply` is Planr Core's only policy-package boundary. It accepts RoutingBundle v1, validates payload hashes, restricts targets to allowlisted repository-local paths, rejects traversal, symlinks, parent/child collisions, conflicts, and unsupported versions, and applies the validated set atomically. Signed bundles require both `--trusted-signer` and an external `--trusted-public-key-file`; a key embedded beside the content is never trusted. It never edits user configuration. Named policies, model ids, host bindings, evaluation, signing, and catalog operations are provided by the optional `planr-routing` package. See [Routing Bundles](ROUTING_BUNDLES.md).
147
145
 
148
- `agents preset apply <policy-path-or-id> --binding <binding-path-or-id>` composes a provider-neutral Usage Policy v1 file with a strict, versioned host binding. Embedded id pairs report `pack.status = safe`; explicit file inputs remain allowed custom compositions and receive a clear non-safe warning even if they reuse built-in ids. Preview is the default and reports compatibility, per-role permission additions, verification age, provenance, content hashes, every normalized repository-relative target, create/unchanged/conflict state, and a redacted old/proposed configuration projection. Policy limits/transitions and generated registry routes, concrete models/efforts, and fallbacks are therefore auditable before confirmation without returning secret-like values. `--confirm` writes exactly the conflict-free preview to `.planr/policy.toml`, `.planr/agents.toml`, `.planr/preset.lock.toml`, and allowlisted repository-local host artifacts; it never overwrites different existing files. Absolute paths, traversal, symlink crossings, user/home/global configuration, and repository `.codex/config.toml` fail before the first write. Secret-like binding metadata is rejected with field-only diagnostics before dispatch/warning output or mutation. Bindings own exact client/model/effort and fork capabilities: Codex cross-tier dispatch is keyed by the binding host identity, defaults to `none`, rejects `all`, and accepts a positive partial fork only with declared limits and non-blank capability evidence. Host-specific bindings require every profile client to match the host; explicit cross-client mappings use `host = "mixed-host"`. MCP `planr_preset_apply` calls the same application service and returns the identical shape (`confirm` defaults to false). Binding schema and repository-boundary details: [Preset Composition](PRESET_COMPOSITION.md).
149
-
150
- `agents preset evaluate [--report-dir <dir>] [--at-unix <timestamp>] [--host <host>] [--live-host-command <absolute-executable> [--live-host-arg <arg>]... [--trusted-telemetry-signer <registry-id> --trusted-telemetry-collector <absolute-executable>]]` defaults to the embedded offline simulation: no process/network execution, estimated projections, unavailable effective routes, and no recommendation. Explicit live mode creates a Planr-controlled challenge/workspace for every versioned task. The adapter must read the challenge and write a bounded strict-schema artifact whose independently computed hash, candidate/task/input/artifact binding, challenge binding, and task oracle Planr validates. Live `evidence_complete` requires every required task execution and oracle pass; missing or invalid artifacts produce `unverified` candidates and make report-level `reproducible_evidence` false. Policy tool/write capabilities remain authoritative. Without telemetry, host route and tool/token/credit claims remain estimated and recommendation-ineligible. The all-or-none telemetry flags select a signer and collector independently pinned in `.planr/trusted-telemetry.toml`. Planr creates a fresh run UUID and task challenge, invokes the hash-pinned collector only after independently reading the artifact, verifies the registry-pinned Ed25519 signature and exact run/suite/time/task/input/artifact/challenge/host bindings, then promotes only receipt-backed effective route and usage dimensions to `telemetry_receipt`/`trusted`. Caller-supplied keys, run ids, and precomputed bundles are not accepted; missing, replayed, or tampered post-run receipts fail closed. Valid complete telemetry makes `recommended` reachable on CLI and MCP. Constant responders, public-label request mappers, and read-only candidates on write fixtures cannot recommend. Full protocol: [Preset Evaluation](PRESET_EVALUATION.md).
151
-
152
- `agents preset registry verify/import/list` implements the optional declarative registry boundary. Verification checks version compatibility, host compatibility, lifecycle/revocation, exact byte lengths and SHA-256 digests, canonical policy/binding semantics and safe artifacts, and optional Ed25519 signatures against separately pinned maintainer keys. `recommended` additionally requires a current canonical evaluation bound to the shipped policy/binding bytes, independently derived metrics and thresholds, task/oracle/result-hash completeness, and trusted route/metering evidence; a trusted signature alone cannot promote it. Import previews by default and, on `--confirm`, atomically caches only manifest-declared files plus the original manifest below `.planr/registry/cache/`. Offline listing treats the receipt as inventory only and re-verifies the manifest hash, signature, manifest-owned checksums, and freshness, so coordinated content/receipt tampering fails closed and a registry outage cannot affect active projects or already verified content. See [Preset Registry](PRESET_REGISTRY.md).
153
-
154
- `agents init` writes a commented starter registry with the cost-tiering defaults (premium driver that keeps the verdicts, standard steerable implementer, budget helper for token-hungry side work, plus code/fix/review/default routes) and names the follow-up commands; an existing `.planr/agents.toml` is never overwritten without `--force`. Individual pools generate from repeatable spec flags — `--profile designer=claude-code/opus@high#premium` declares a profile, `--skill designer=frontend-design` pairs it with a skill, `--route frontend=designer,driver` routes a use-case work type with fallbacks, `--default-route` catches the rest; validation is fail-closed (unknown profile references and malformed specs error, naming the grammar, before anything is written), and consistent specs generate a zero-warning registry. `--interactive` walks the same questions as guided prompts (requires a terminal; conflicts with spec flags) and can render the host role files at the end. `agents list` and `agents check` inspect the agent profile registry (`.planr/agents.toml`): named profiles (host client, model, effort, cost tier) and advisory routes from work selectors to profiles. When a registry resolves for a picked item, the pick packet carries a `routing` block — profile, client, model, effort, cost tier, fallback chain, and the matched selector — resolved with precedence per-item override > `work_type` > `plan` > default route. `item route` shows an item's resolved route and its source (`override` or `policy`), pins a registry profile with `--set <profile>` (emits `route_overridden`), and unpins with `--clear` (emits `route_override_cleared`); a pinned profile that later disappears from the registry falls back to policy routing with a repair hint. The same JSON shapes are exposed over MCP: `planr_agents_list` and `planr_item_route` read, `planr_item_route_set` and `planr_item_route_clear` mutate. Routing is advisory: Planr never dispatches models, a missing registry just omits the block, a malformed one degrades picking to no-routing (only `agents check` fails, with the parser's line context), and validation warnings (unknown profile references, duplicate selectors, review work on a budget tier, secret-like values) never affect exit codes. When a registry is present, `install codex|claude|cursor` renders the subagent role files with model pins from it — the `work_type=code` route pins the worker, the `work_type=review` route pins the reviewer, and a role only pins profiles whose `client` matches the install target (a Cursor-profile review route never writes a Cursor model into a Codex TOML). Rendered files carry a `# generated from .planr/agents.toml` header; without a registry (or when no matching route resolves) the shipped static role files are written byte-identically, and existing files are never overwritten without `install --force`. Full guide: [Model Routing](MODEL_ROUTING.md).
146
+ `agents init` writes a provider-neutral `.planr/agents.toml` scaffold or compiles explicit profile and route flags. `agents list` and `agents check` inspect it, while pick packets carry the resolved opaque profile, host, model, effort, tier, skill, route chain, and matched selector. Full guide: [Model Routing](MODEL_ROUTING.md).
155
147
 
156
148
  `log add` and `done` accept `--profile <id>` — the registry profile the run actually executed on (`PLANR_PROFILE` env is the fallback, so rendered role files can export it). They also accept `--route-audit <observation.json>` for the strict three-stage observation contract. A route audit records each stage's model, effort, and context-fork value with enforcement state (`verified`, `requested_only`, `estimated`, or `unavailable`), an evidence-source enum, typed transition plus reason, policy/binding ids and versions, and wall-time/tool/token/credit values with independent confidence. It is stored in run metadata, projected into its durable log and trace, and emits local route-stage/transition events. The profile remains backward compatible: when it differs from the item's declared route, Planr emits advisory `route_mismatch_observed`. Runs without commands/tests record neither a run nor a route observation. MCP `planr_log_add` and HTTP item log accept the same optional `route_observation` object.
157
149
 
@@ -163,6 +155,6 @@ With `--json`, responses follow one convention so agents never guess where data
163
155
 
164
156
  `serve` exposes the local review workspace at `/review` and its JSON projection at `/v1/review-workspace`.
165
157
 
166
- `prompt` prints ready-to-use agent instructions without editing global config. Use `prompt cli` for shell agents, `prompt mcp` for MCP setup text, and `prompt http` for localhost automation/review workspace usage. `prompt routing` emits a paste-ready model-prioritization block for the driver session: the route table from `.planr/agents.toml` (every route, profile, and fallback), per-host dispatch guidance with the known traps (Codex `fork_turns: "none"` and session-restart requirement, the Claude `CLAUDE_CODE_SUBAGENT_MODEL` env preemption, Cursor's silent plan/policy/Max-Mode overrides), and process-dispatch snippets (`codex exec`, `pi`, `opencode run`) for hosts without role files; `--json` carries the same content structured, and a missing or unreadable registry still prints the host guidance with a pointer instead of failing.
158
+ `prompt` prints ready-to-use agent instructions without editing global config. Use `prompt cli` for shell agents, `prompt mcp` for MCP setup text, and `prompt http` for localhost automation/review workspace usage. `prompt routing` emits a paste-ready model-prioritization block for the driver session: the route table from `.planr/agents.toml` (every route, profile, and fallback), native Codex `agent_type` plus explicit fork guidance referring to the generated repository role TOMLs, the Claude `CLAUDE_CODE_SUBAGENT_MODEL` env preemption, Cursor's silent plan/policy/Max-Mode overrides, and process-dispatch snippets (`pi`, `opencode run`) only for hosts without role files. `--json` carries the same content structured, and a missing or unreadable registry still prints the host guidance with a pointer instead of failing.
167
159
 
168
160
  `export` writes a reusable Planr JSON package with package requirements metadata, graph state, contexts, optional logs, optional plan file snapshots, review artifact snapshots, and — when present — the agent registry (`.planr/agents.toml`) as a raw snapshot. `import` previews JSON packages by default and mutates only with `--confirm`; the preview names the registry with its exact action (`create`, `identical`, or `conflict`), and an existing registry that differs is never overwritten — the conflict is reported with a hint to remove the local file first. Packages without a registry import unchanged.
package/docs/CODEX.md CHANGED
@@ -22,15 +22,15 @@ $planr-goal <your goal>
22
22
 
23
23
  The stop condition lives in Planr (`--tag goal-contract`), so a dead session resumes with the same starter line from zero chat context.
24
24
 
25
- Run the driver session on your strongest tier (e.g. `gpt-5.5` at `model_reasoning_effort = "high"` in `~/.codex/config.toml`). The provisioned worker role pins a cheaper tier; the reviewer deliberately inherits the session model:
25
+ Optionally compile and apply a repository-local Codex routing bundle before starting the driver:
26
26
 
27
- ```toml
28
- # .codex/agents/planr-worker.toml
29
- model = "gpt-5.5"
30
- model_reasoning_effort = "medium"
27
+ ```bash
28
+ planr-routing compile balanced --host codex-openai --output routing-bundle.json
29
+ planr routing bundle preview routing-bundle.json
30
+ planr routing bundle apply routing-bundle.json
31
31
  ```
32
32
 
33
- Verify the pin once: some Codex versions ignore custom agent files on spawn ([openai/codex#26868](https://github.com/openai/codex/issues/26868)) and the child silently inherits the parent model. Spawn `planr_worker` on a trivial item and confirm the child metadata shows the pinned model and effort with a non-null `agent_path`. Full workflow, recovery, per-host variants, and the tiering rationale: [Long-Running Goals](GOALS.md).
33
+ The bundle generates repository-local roles and a routing skill. Follow that generated skill exactly, restart after role changes, and confirm child metadata reports the expected model, effort, role path, and context-fork behavior. Full workflow: [Long-Running Goals](GOALS.md).
34
34
 
35
35
  ## MCP
36
36
 
package/docs/CURSOR.md CHANGED
@@ -19,13 +19,13 @@ Re-running the command refreshes `.cursor/mcp.json` but never overwrites edited
19
19
 
20
20
  ## Skills And Agents Only (No MCP)
21
21
 
22
- The skills are CLI-first — they drive the `planr` binary directly through the terminal — so MCP is optional. For a plugin-style install that writes only the subagents and skills:
22
+ The skills are CLI-first — they drive the `planr` binary directly through the terminal — so MCP is optional. To install project subagents, skills, and the default hooks without MCP:
23
23
 
24
24
  ```bash
25
25
  planr install cursor --no-mcp
26
26
  ```
27
27
 
28
- This writes `.cursor/agents/` and `.cursor/skills/` and nothing else: no `.cursor/mcp.json`, no deeplink. Everything below (subagent dispatch, parallel work, goal loops) works identically in this mode because the skills call `planr pick`, `planr done`, `planr review ...` as shell commands. `--no-mcp --dry-run` lists the files that would be written. The flag works for `claude` and `codex` too (roles only; their skills ship via each host's plugin system).
28
+ This writes `.cursor/agents/`, `.cursor/skills/`, and the default project hooks, but no `.cursor/mcp.json` or deeplink. Add `--no-hooks` when hooks must also be skipped. Everything below works in this mode because the skills call the Planr CLI directly. `--no-mcp --dry-run` lists the roles and skills and states whether the non-dry run would reconcile hooks. For Claude Code the flag writes standalone project roles and hooks but no project skills; for Codex it writes hooks only. Their workflow skills come from their respective plugins.
29
29
 
30
30
  ## One-Click MCP Install
31
31
 
@@ -1,138 +1,104 @@
1
1
  # Worked Example: Routing a Small Web App
2
2
 
3
- A complete, replayable walkthrough of [model routing](MODEL_ROUTING.md) on a real shape of work: a todo web app with a frontend and a backend, implemented by different models. Every output below is from an actual run copy the commands into an empty directory and you get the same results.
3
+ This provider-neutral example routes a todo web app by work type. Planr Core treats every profile field as opaque data and does not select a host or model.
4
4
 
5
- The pool we want:
6
-
7
- | Use case | Who runs it | Paired skill |
8
- | --- | --- | --- |
9
- | planning + review | Fable on Cursor (the driver session) | — |
10
- | frontend, design | Opus on Claude Code | `frontend-design` |
11
- | backend | GPT-5.5 on Codex | `planr-work` |
12
-
13
- ## Step 1: Project and pool — two commands, once
5
+ ## 1. Create the project and registry
14
6
 
15
7
  ```bash
16
8
  planr project init "Todo Webapp"
17
-
18
- planr agents init \
19
- --profile driver=cursor/fable-5@high#premium \
20
- --profile frontender=claude-code/opus@high#premium \
21
- --profile backender=codex/gpt-5.5@xhigh#standard \
22
- --skill frontender=frontend-design \
23
- --skill backender=planr-work \
24
- --route frontend=frontender,driver \
25
- --route backend=backender,driver \
26
- --route review=driver \
27
- --default-route backender,driver
28
-
29
- planr agents check
9
+ planr agents init
30
10
  ```
31
11
 
32
- ```text
33
- wrote .planr/agents.toml (generated from the flag specs)
34
- agent registry check passed
12
+ Edit the repository-local `.planr/agents.toml` with profiles owned by your team or routing package:
13
+
14
+ ```toml
15
+ [profiles.frontend-worker]
16
+ client = "your-host"
17
+ model = "your-fast-model"
18
+ effort = "medium"
19
+ cost_tier = "budget"
20
+ skill = "planr-work"
21
+
22
+ [profiles.backend-worker]
23
+ client = "your-host"
24
+ model = "your-engineering-model"
25
+ effort = "high"
26
+ cost_tier = "standard"
27
+ skill = "planr-work"
28
+
29
+ [profiles.independent-reviewer]
30
+ client = "your-host"
31
+ model = "your-review-model"
32
+ effort = "high"
33
+ cost_tier = "premium"
34
+ skill = "planr-review"
35
+
36
+ [[routes]]
37
+ match = { work_type = "frontend" }
38
+ profile = "frontend-worker"
39
+
40
+ [[routes]]
41
+ match = { work_type = "backend" }
42
+ profile = "backend-worker"
43
+
44
+ [[routes]]
45
+ match = { work_type = "review" }
46
+ profile = "independent-reviewer"
35
47
  ```
36
48
 
37
- Prefer questions over flags? `planr agents init --interactive` walks the same inputs as guided prompts and can render the host role files at the end. Either way, validation is fail-closed: a typo in a profile reference errors before anything is written.
49
+ Validate without contacting a provider:
50
+
51
+ ```bash
52
+ planr agents check
53
+ planr agents list
54
+ ```
38
55
 
39
- Note what the routes encode: review work is pinned to the premium driver (verdicts stay strong), everything else runs on the cheaper tier its use case calls for, and every route falls back to the driver when the primary hits a rate limit.
56
+ Alternatively, an external policy package can compile a strict RoutingBundle v1. Preview and apply it through the generic Core boundary:
40
57
 
41
- ## Step 2: Items carry the use case as their work type
58
+ ```bash
59
+ planr routing bundle inspect routing-bundle.json
60
+ planr routing bundle preview routing-bundle.json
61
+ planr routing bundle apply routing-bundle.json
62
+ ```
42
63
 
43
- Work types are free-form, so the use case is just `--work-type`:
64
+ ## 2. Tag items by use case
44
65
 
45
66
  ```bash
46
67
  planr item create "API: task CRUD endpoints" \
47
- --description "Express routes GET/POST/PATCH/DELETE /api/tasks with sqlite store" \
68
+ --description "GET/POST/PATCH/DELETE /api/tasks with sqlite store" \
48
69
  --work-type backend
49
70
 
50
71
  planr item create "UI: task list and add form" \
51
- --description "React list view + optimistic add form against /api/tasks" \
52
- --work-type frontend
53
-
54
- planr item create "UI: design pass on empty and error states" \
55
- --description "Empty state, loading skeleton, error toast" \
72
+ --description "List view and optimistic add form" \
56
73
  --work-type frontend
57
74
  ```
58
75
 
59
- ## Step 3: The pick decides who works
60
-
61
- Same board, two different answers. The backend pull:
76
+ ## 3. Pick and dispatch
62
77
 
63
78
  ```bash
64
79
  planr pick --work-type backend --json
65
80
  ```
66
81
 
67
- ```json
68
- "routing": {
69
- "profile": "backender",
70
- "client": "codex",
71
- "model": "gpt-5.5",
72
- "effort": "xhigh",
73
- "cost_tier": "standard",
74
- "skill": "planr-work",
75
- "fallbacks": ["driver"],
76
- "matched_selector": "work_type=backend"
77
- }
78
- ```
79
-
80
- And the frontend pull:
81
-
82
- ```bash
83
- planr pick --work-type frontend --json
84
- ```
85
-
86
- ```json
87
- "routing": {
88
- "profile": "frontender",
89
- "client": "claude-code",
90
- "model": "opus",
91
- "skill": "frontend-design",
92
- "fallbacks": ["driver"],
93
- "matched_selector": "work_type=frontend"
94
- }
95
- ```
82
+ The pick packet contains the selected opaque profile, client, model, effort, skill, and selector. The host remains responsible for dispatching it; Planr never claims that the requested model actually ran.
96
83
 
97
- The driver session dispatches from the packet alone: the backend item goes to Codex (`codex exec --model gpt-5.5 -c model_reasoning_effort="xhigh" ...` — `planr prompt routing` prints this snippet pre-filled), the frontend item to a Claude Code subagent dispatched with its paired skill (`Use $frontend-design on item <id>`). Two workers can pull in parallel — each `pick --work-type <use-case>` takes its own lane, and the pick lease keeps one owner per item.
98
-
99
- ## Step 4: Workers close with evidence and their profile
84
+ ## 4. Close with evidence
100
85
 
101
86
  ```bash
102
87
  planr done <item-id> \
103
- --summary "CRUD endpoints implemented; 8 supertest cases green" \
88
+ --summary "CRUD endpoints implemented; 8 tests green" \
104
89
  --files server/routes/tasks.ts \
105
90
  --tests "vitest --run: 8 passed" \
106
- --profile backender
91
+ --profile backend-worker
107
92
  ```
108
93
 
109
- `--profile` (or the `PLANR_PROFILE` env var) records which registry profile the run actually executed on. It is part of the evidence, not a formality the next step is why.
110
-
111
- ## Step 5: The trace proves the plan was followed
94
+ `--profile` records the run's claimed profile. For stronger evidence, attach a route observation that keeps requested, host-resolved, and effective values separate.
112
95
 
113
- Every host has a silent override path (env clamps, admin policies, fork semantics — see the [host matrix](MODEL_ROUTING.md#host-matrix)), so a pin alone is not proof. In this run, the backend item was closed on the declared profile and the frontend item deliberately on the wrong one:
96
+ ## 5. Trace declared versus actual
114
97
 
115
98
  ```bash
116
- planr trace item <backend-item>
117
- planr trace item <frontend-item>
99
+ planr trace item <item-id>
118
100
  ```
119
101
 
120
- ```text
121
- routing declared: backender (work_type=backend)
122
- run run-5552fad6 profile backender
123
-
124
- routing declared: frontender (work_type=frontend)
125
- run run-bc0994cb profile driver (differs from declared route; advisory)
126
- ```
127
-
128
- The mismatch also lands as a `route_mismatch_observed` event (`planr event list`). Advisory by design: nothing blocked, but the drift is on record instead of invisible.
129
-
130
- ## The whole model in one line each
131
-
132
- 1. **Declare** the pool once: `planr agents init` (flags, wizard, or the plain scaffold).
133
- 2. **Tag** items with their use case: `--work-type frontend|backend|...` — free-form.
134
- 3. **Pick** routes: every packet carries profile, model, skill, and fallbacks.
135
- 4. **Deliver** with `--profile` as part of the evidence.
136
- 5. **Trace** proves declared vs. actual — silent overrides get caught.
102
+ A mismatch is recorded as advisory evidence instead of silently rewritten. Missing effective-host evidence stays unavailable and is never inferred from the registry.
137
103
 
138
- One-off exceptions never need a registry edit: `planr item route <id> --set driver` pins a single gnarly item to the premium tier and `--clear` restores policy. Details and failure behavior: [Model Routing](MODEL_ROUTING.md); the cost logic behind the tiers: [GOALS.md Cost Tiering](GOALS.md#cost-tiering).
104
+ One-off exceptions use `planr item route <id> --set <profile>`; `--clear` restores policy resolution. See [Model Routing](MODEL_ROUTING.md) and [Routing Bundles](ROUTING_BUNDLES.md).
package/docs/GOALS.md CHANGED
@@ -87,12 +87,15 @@ Iteration 1 reads the map and the stored contract: items already settled stay se
87
87
 
88
88
  ### Codex with `/goal`
89
89
 
90
- The recommended combination. Install the plugin and provision the subagent roles once:
90
+ Install the plugin, initialize the repository, and optionally apply a repository routing bundle:
91
91
 
92
92
  ```bash
93
93
  codex plugin marketplace add instructa/planr
94
94
  codex plugin add planr@planr
95
- planr project init "My Product" --client codex # writes .codex/agents/planr-worker.toml + planr-reviewer.toml
95
+ planr project init "My Product"
96
+ planr-routing compile balanced --host codex-openai --output routing-bundle.json
97
+ planr routing bundle preview routing-bundle.json
98
+ planr routing bundle apply routing-bundle.json
96
99
  ```
97
100
 
98
101
  Then:
@@ -102,7 +105,7 @@ $planr-goal <your goal> # prep: plan, map, contract, starter command
102
105
  /goal Use $planr-loop on plan <plan-id>. The loop contract is stored in planr context (tag: goal-contract).
103
106
  ```
104
107
 
105
- The `/goal` PM dispatches `spawn the planr_worker agent for item <id>` and `spawn the planr_reviewer agent for item <id>` the role files preload `$planr-work` and `$planr-review`, so dispatches stay one line. Codex Automations work the same way: set the automation prompt to the starter line. The provisioned worker role pins a cheaper effort tier; see [Cost Tiering](#cost-tiering).
108
+ When a routing bundle is applied, the `/goal` PM follows its generated repository skill and roles. The bundle owner decides exact models, effort, role names, and fork policy; Planr only carries the resulting opaque route in pick packets. Codex Automations use the same starter line.
106
109
 
107
110
  ### Claude Code
108
111
 
@@ -142,29 +145,9 @@ Any MCP-capable agent uses the same flow over `planr mcp`. Every session starts
142
145
 
143
146
  ## Cost Tiering
144
147
 
145
- A goal run has three roles with different intelligence needs, so they should not all run on the same model tier:
148
+ A goal run has distinct roles with different intelligence needs. Planr represents those decisions as opaque profiles and routes; it does not choose providers, models, effort levels, fallback chains, or host-native role names.
146
149
 
147
- - **Driver** (the `/goal` session): decomposition, dispatch decisions, conflict resolution, final synthesis. Run it on the strongest model you have this is never configured in Planr files, it is simply the model of the main session.
148
- - **Worker**: bounded implementation. `planr pick --json` is a complete handoff packet (one item, scope, evidence format, stop after review request), so the worker runs safely on a cheaper tier.
149
- - **Reviewer**: the truth gate. It inherits the driver's model on purpose — make workers cheap, not the verdict.
150
-
151
- Where each host configures the worker tier (the shipped role files carry these defaults):
152
-
153
- | Host | Driver | Worker | Configured in |
154
- | --- | --- | --- | --- |
155
- | Codex | session default (e.g. `gpt-5.5` at `high`) | `model = "gpt-5.5"`, `model_reasoning_effort = "medium"` | `.codex/agents/planr-worker.toml` |
156
- | Claude Code | session model (e.g. `fable` at `high` via `/model` + `/effort`) | `model: opus`, `effort: medium` | `planr-worker.md` frontmatter |
157
- | Cursor | chat model of the driving session | `model: inherit` by default; pin a cheaper Cursor model id | `.cursor/agents/planr-worker.md` frontmatter |
158
-
159
- The defaults use aliases and generic names so they track model generations; pin a full model id (e.g. `claude-opus-4-8`) only if you need determinism, and use `model: sonnet` as the budget alternative. The role files are user-owned copies — `planr project init` provisions them once and never overwrites local edits — so changing the tier is editing one line.
160
-
161
- To declare the tiering itself — which model handles which work type, with fallbacks for rate limits — use the agent profile registry (`.planr/agents.toml`): the routing recommendation then travels inside every `planr pick --json` packet, so the driver dispatches the right tier without consulting this table mid-run. `planr agents init` writes a working starter registry with these defaults; see [Model Routing](MODEL_ROUTING.md). The role files above still carry the host-native pins (`planr install <client> --force` re-renders them from the registry); the registry is the declared source of truth for the routing decision.
162
-
163
- Traps to verify once per setup — every one of them is silent (the run still works, just at driver prices), which is why the smoke test is worth the two minutes:
164
-
165
- - **Claude Code:** the `CLAUDE_CODE_SUBAGENT_MODEL` environment variable clamps every subagent's `model:` frontmatter and per-invocation model with no signal in the `tool_result` ([anthropics/claude-code#57718](https://github.com/anthropics/claude-code/issues/57718)); since v2.1.196, setting it to `inherit` behaves like unset, so that is the safe pin for "driver decides". Org-managed `availableModels` allowlists are equally quiet: a frontmatter model outside the allowlist falls back to inherit without warning. Make sure the env var is unset (or `inherit`), then dispatch the worker on a trivial item and confirm the subagent's messages in the session log (`~/.claude/projects/<project>/*.jsonl`) carry the worker model, not the driver's.
166
- - **Codex:** the spawn regressions that made children ignore custom agent files ([openai/codex#26868](https://github.com/openai/codex/issues/26868), [#26363](https://github.com/openai/codex/issues/26363)) are fixed in v0.138+, but two traps remain. First, `fork_turns = "all"` (the multi-agent v2 default) intentionally drops the child's `agent_type` and `model` so the fork replays the parent exactly — dispatch that should honor the worker pin needs `fork_turns = "none"` or a partial fork. Second, the role registry is loaded once at session start ([#26408](https://github.com/openai/codex/issues/26408)): after editing or re-rendering `.codex/agents/*.toml`, restart the session, or the child spawns from the stale definitions. Spawn `planr_worker` on a trivial item and confirm the child metadata shows the pinned model and effort with a non-null `agent_path`.
167
- - **Cursor:** `model: <id>` in `.cursor/agents/planr-worker.md` frontmatter can be overridden without an error by team-admin model policies, plan availability (a model your plan lacks resolves to a fallback), and Max-Mode-only models. On legacy request-based plans, subagents are forced onto Composer regardless of the pin. Dispatch the worker once and check which model the subagent transcript reports before trusting the pin.
150
+ An optional routing-policy package can map planning, exploration, implementation, mechanical work, and independent review onto different cost or quality tiers. If a routing bundle generated repository roles, follow its generated instructions and verify effective child metadata because declarations alone are not proof. The official package and its host-specific caveats live under [`planr-routing`](../planr-routing/docs/MODEL_ROUTING_POLICY.md); the Core contract is documented in [Model Routing](MODEL_ROUTING.md).
168
151
 
169
152
  ## Coming From Other Goal Tools
170
153
 
package/docs/INSTALL.md CHANGED
@@ -72,9 +72,9 @@ planr prompt cli --client codex
72
72
  planr prompt http
73
73
  ```
74
74
 
75
- `planr install claude` writes a project `.mcp.json`; `planr install cursor` writes `.cursor/mcp.json` plus the Planr skills under `.cursor/skills/` and prints a one-click user-level MCP deeplink; `planr install codex` writes a project MCP snippet. All install commands also provision the `planr-worker` and `planr-reviewer` subagent role files (`.codex/agents/`, `.claude/agents/`, `.cursor/agents/`) without overwriting existing edits; `planr project init --client <client|all>` does the same at init time. Dry-runs print the exact config and scope notes first.
75
+ `planr install codex` writes a project MCP snippet and project hooks; its workflow skills come from the Codex plugin, and it writes no project roles or skills. `planr install claude` writes project `.mcp.json`, standalone worker/reviewer roles, and hooks; workflow skills come from the Claude Code plugin. `planr install cursor` writes project MCP, roles, all ten skills, and hooks, then prints an optional user-level MCP deeplink. Optional model pins come from a repository-local routing bundle. Dry-runs print the complete repository artifact and hook-reconciliation paths without writing them; no command silently edits global user configuration.
76
76
 
77
- Skills-and-agents-only setups (no MCP) use `--no-mcp`: `planr install cursor --no-mcp` writes the subagents and skills but no MCP config the skills drive the `planr` CLI directly, so nothing is lost except MCP tool access.
77
+ `--no-mcp` skips only the project MCP artifact. Codex then reconciles hooks only; Claude Code writes standalone project roles and hooks but no project skills; Cursor writes project roles, skills, and hooks. Add `--no-hooks` to skip hooks as well. The Codex and Claude Code plugins remain the owners of their workflow skills.
78
78
 
79
79
  Runtime surfaces:
80
80
 
@@ -87,7 +87,7 @@ Open `http://127.0.0.1:7526/review` after `planr serve` for the local browser re
87
87
 
88
88
  ## Agent Skills And Plugin
89
89
 
90
- The repository ships a plugin under `plugins/planr` for Codex, Claude Code, and Cursor that bundles the Planr skills (`$planr`, `$planr-loop`, stage and capability skills) and the subagent roles. The plugin carries skills and roles only; the CLI above must be installed separately. See [Skills](SKILLS.md) for plugin install commands and the skill workflow.
90
+ The repository ships a plugin under `plugins/planr` for Codex and Claude Code that bundles all ten workflow skills; Claude Code additionally registers plugin worker/reviewer agents. The Codex plugin does not register project agents. Cursor receives the ten skills and both project agents through `planr install cursor` (or its plugin manifest). Model-specific role files are optional routing-bundle artifacts. The CLI above must be installed separately. See [Skills](SKILLS.md).
91
91
 
92
92
  ## From Source
93
93