planr 1.3.0 → 1.5.0
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.
- package/README.md +9 -44
- package/docs/ARCHITECTURE.md +7 -2
- package/docs/CLI_REFERENCE.md +13 -5
- package/docs/CODEX.md +6 -6
- package/docs/EXAMPLE_WEBAPP.md +63 -97
- package/docs/GOALS.md +8 -25
- package/docs/INSTALL.md +2 -2
- package/docs/MCP_CONTRACT.md +3 -2
- package/docs/MODEL_ROUTING.md +20 -177
- package/docs/ROUTING_BUNDLES.md +32 -0
- package/docs/SKILLS.md +5 -3
- package/docs/fixtures/mcp-contract.json +8 -0
- package/npm/native/darwin-arm64/planr +0 -0
- package/npm/native/darwin-x86_64/planr +0 -0
- package/npm/native/linux-arm64/planr +0 -0
- package/npm/native/linux-x86_64/planr +0 -0
- package/package.json +3 -2
- package/plugins/planr/.claude-plugin/plugin.json +1 -1
- package/plugins/planr/.codex-plugin/plugin.json +1 -1
- package/plugins/planr/skills/planr-loop/SKILL.md +1 -1
- package/plugins/planr/skills/planr-loop/agents/planr-reviewer.toml +0 -23
- package/plugins/planr/skills/planr-loop/agents/planr-worker.toml +0 -21
package/README.md
CHANGED
|
@@ -22,49 +22,6 @@ Flat todo lists break down the moment real work has structure. Planr models work
|
|
|
22
22
|
|
|
23
23
|
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
24
|
|
|
25
|
-
## New in 1.3.0: Native Host Hooks
|
|
26
|
-
|
|
27
|
-
`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:
|
|
28
|
-
|
|
29
|
-
```text
|
|
30
|
-
## planr state
|
|
31
|
-
project: Hookboard | map: 5/5 settled | 0 ready, 0 picked, 0 in_review
|
|
32
|
-
goal contract: DONE when every in-scope map item is closed with log evidence, ...
|
|
33
|
-
routing: registry active (3 profiles; pick packets carry model routing)
|
|
34
|
-
next: planr plan audit pln-fc584c28 --json
|
|
35
|
-
```
|
|
36
|
-
|
|
37
|
-
- **`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.
|
|
38
|
-
- **Loop recovery becomes mechanism, not discipline** — an agent that restarts or compacts mid-loop picks up exactly where the map says it left off.
|
|
39
|
-
- **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.
|
|
40
|
-
- **Fail-open and additive** — hooks never block a session (10s timeout, always exit 0), existing hook files are merged, `--no-hooks` opts out.
|
|
41
|
-
|
|
42
|
-
Full guide: [Hooks](docs/HOOKS.md) · [Release notes](https://github.com/instructa/planr/releases/tag/v1.3.0).
|
|
43
|
-
|
|
44
|
-
## Model Routing (1.2.0)
|
|
45
|
-
|
|
46
|
-
Declare once which model handles which work — every task then carries its own routing, and your agents delegate automatically:
|
|
47
|
-
|
|
48
|
-
```toml
|
|
49
|
-
# .planr/agents.toml (write it with `planr agents init`)
|
|
50
|
-
[profiles.frontender]
|
|
51
|
-
client = "cursor"
|
|
52
|
-
model = "opus"
|
|
53
|
-
skill = "frontend-design"
|
|
54
|
-
|
|
55
|
-
[[routes]]
|
|
56
|
-
match = { work_type = "frontend" }
|
|
57
|
-
profile = "frontender"
|
|
58
|
-
fallbacks = ["driver"]
|
|
59
|
-
```
|
|
60
|
-
|
|
61
|
-
- **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.
|
|
62
|
-
- **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.
|
|
63
|
-
- **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.
|
|
64
|
-
- **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`.
|
|
65
|
-
|
|
66
|
-
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).
|
|
67
|
-
|
|
68
25
|
## Install
|
|
69
26
|
|
|
70
27
|
```bash
|
|
@@ -93,7 +50,7 @@ Manual downloads, from-source builds, and client wiring details: [Install Guide]
|
|
|
93
50
|
|
|
94
51
|
## Install The Plugin (Skills)
|
|
95
52
|
|
|
96
|
-
The plugin under `plugins/planr` carries the
|
|
53
|
+
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.
|
|
97
54
|
|
|
98
55
|
<a id="install-plugin-codex"></a>
|
|
99
56
|
<details>
|
|
@@ -174,6 +131,14 @@ the feature working in the browser. Iteration budget: 10.
|
|
|
174
131
|
|
|
175
132
|
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`.
|
|
176
133
|
|
|
134
|
+
## What's new
|
|
135
|
+
|
|
136
|
+
- **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).
|
|
137
|
+
- **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).
|
|
138
|
+
- **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).
|
|
139
|
+
|
|
140
|
+
For the complete release history, see the [Changelog](CHANGELOG.md).
|
|
141
|
+
|
|
177
142
|
## Docs
|
|
178
143
|
|
|
179
144
|
- [Install](docs/INSTALL.md)
|
package/docs/ARCHITECTURE.md
CHANGED
|
@@ -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
|
|
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.
|
|
@@ -40,10 +40,15 @@ Planr V1 is a single Rust binary with explicit module ownership. The crate stays
|
|
|
40
40
|
- `src/storage/rows.rs`: SQLite row mapping boundary. Owns row-to-DTO and row-to-JSON mapping functions.
|
|
41
41
|
- `src/planpack.rs`: Markdown package generation and parsing. Owns project context templates, product/build plan templates, plan metadata parsing, hashes, search body extraction, and task extraction.
|
|
42
42
|
- `src/agents.rs`: agent profile registry core. Owns `.planr/agents.toml` parsing, registry validation warnings, and the pure advisory `resolve_route` precedence logic (override > work_type > plan > default); no storage or host concerns.
|
|
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
|
+
- `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
|
+
- `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/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.
|
|
43
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.
|
|
44
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.
|
|
45
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.
|
|
46
|
-
- `src/rolefiles.rs`:
|
|
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.
|
|
47
52
|
- `src/util.rs`: small CLI-boundary utilities. Owns ids, timestamps, path helpers, output formatting, and safe file writes.
|
|
48
53
|
|
|
49
54
|
## Boundary Rules
|
package/docs/CLI_REFERENCE.md
CHANGED
|
@@ -49,7 +49,8 @@ planr artifact show <artifact-id>
|
|
|
49
49
|
planr artifact list [--item <item-id>]
|
|
50
50
|
planr event list [--item <item-id>] [--limit 50]
|
|
51
51
|
planr debug bundle [--item <item-id>] --preview
|
|
52
|
-
planr
|
|
52
|
+
planr trace item <item-id>
|
|
53
|
+
planr log add --item <item-id> --summary "..." [--files a --files b | --files a,b] [--cmd "..."] [--kind completion|progress|verification] [--profile <id>] [--route-audit <observation.json>]
|
|
53
54
|
# machine consumers: --cmd writes the `commands` field in log JSON; --tests writes `tests`
|
|
54
55
|
planr review request <item-id>
|
|
55
56
|
planr review annotate <item-id> --message "..." [--severity info|warning|blocking] [--file path] [--line N] [--author "..."]
|
|
@@ -66,6 +67,9 @@ planr agents init [--force]
|
|
|
66
67
|
planr agents init --profile|--skill|--route|--default-route|--interactive
|
|
67
68
|
planr agents list [--json]
|
|
68
69
|
planr agents check
|
|
70
|
+
planr routing bundle inspect <bundle.json>
|
|
71
|
+
planr routing bundle preview <bundle.json>
|
|
72
|
+
planr routing bundle apply <bundle.json>
|
|
69
73
|
planr doctor [--client codex|claude|cursor|all]
|
|
70
74
|
planr install codex|claude|cursor [--dry-run] [--no-mcp] [--force] [--no-hooks]
|
|
71
75
|
planr prompt cli|mcp|http [--client codex|claude|cursor|all]
|
|
@@ -123,7 +127,7 @@ With `--json`, responses follow one convention so agents never guess where data
|
|
|
123
127
|
|
|
124
128
|
`review close` writes `.planr/reviews/<review-item-id>.review.md` and registers it as a review artifact. A `not-complete` or `unclear` verdict creates fix and follow-up review work; the follow-up review gates the same target item, so the chain keeps working with `--close-target`. With `--close-target` (complete verdicts only) the reviewed item is closed in the same command, provided it already has a completion log; the artifact is rendered after the target transition, so it snapshots the final target status. `--close-target` is also available through MCP `planr_review_close` and HTTP `POST /v1/reviews/{id}/close` (`"close_target": true`). `review close` responses include the same `remaining` progress snapshot as `done` and `close`. `--reviewer <id>` records the checker's identity on the review log, artifact, and event (defaults to the worker id), keeping maker and checker distinguishable in the audit trail. Closing an already-settled review fails with error code `already_closed` instead of silently duplicating evidence logs. The maker/checker split is derived, not declared: `review_mode` compares the closing reviewer identity against the target item's lease holder and reports `single_agent`, `independent`, or `unattributed` in the response, review log, artifact, and event — no ceremony note required. An `unattributed` close explains itself in the output: it means the target has no recorded lease (work was never picked or its lease was released), not that the reviewer's identity was missing.
|
|
125
129
|
|
|
126
|
-
`trace item` on a review item inlines the target item and its evidence logs under `target`, so a reviewer's first trace already contains what is being audited. The human (non-JSON) mode renders the packet: status, owner, links, logs. When the item has a declared route
|
|
130
|
+
`trace item` on a review item inlines the target item and its evidence logs under `target`, so a reviewer's first trace already contains what is being audited. The human (non-JSON) mode renders the packet: status, owner, links, logs. When the item has a declared route, a run profile, or a route observation, the trace gains a `routing` section — the declared route next to every run's actual client/profile and, when supplied, its independent requested → resolved → effective model/effort/context-fork stages, transition reason, policy/binding provenance, and per-dimension metering confidence. Unknown effective host values remain `null`/`unavailable`; requested values are never copied forward as proof. MCP `planr_trace_item` returns the identical JSON shape.
|
|
127
131
|
|
|
128
132
|
`doctor` also reports the agent registry in all states without ever failing: absent (informational hint), degraded (parse error with line context), or loaded with profile/route counts, validation warnings, and per-artifact drift — a rendered role file whose content no longer matches what the current registry would render is flagged `drifted` with a `planr install <client> --force` hint, while files without the generated-from header are the user's (`manual`) and never flagged.
|
|
129
133
|
|
|
@@ -135,9 +139,13 @@ With `--json`, responses follow one convention so agents never guess where data
|
|
|
135
139
|
|
|
136
140
|
`pick --work-type <type>` restricts the lease to one work type, so checker agents pick only `review` items and makers only work items. `pick --plan <plan-id>` restricts the lease to one plan's items, so plan-scoped goal runs never pick work outside their contract even when other plans share the board; an unknown plan id is an error, never a silent unscoped pick. Both filters are available on MCP `planr_pick_item` and HTTP `POST /v1/pick` (`work_type`, `plan`). A null pick is never blind: `{"item": null}` carries a `reason` (`empty_map`, `all_settled`, `nothing_ready`, `ready_items_excluded_by_filter`) and the `remaining` snapshot. When ready work exists but the active filters rejected all of it, `excluded` lists each ready item with the cause (`work_type` mismatch, outside the `--plan` scope, or just requested by this worker) and `repair` carries the exact pick commands that would lease that work — across CLI, MCP, and HTTP. On a review item, `close_effect` previews the full `--close-target` cascade: it lists the work that closing the review (and with it the reviewed item) would unlock.
|
|
137
141
|
|
|
138
|
-
`
|
|
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.
|
|
139
143
|
|
|
140
|
-
`
|
|
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).
|
|
145
|
+
|
|
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).
|
|
147
|
+
|
|
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.
|
|
141
149
|
|
|
142
150
|
`artifact add` infers the mime type from the file extension when `--path` is given without `--mime` (PNG screenshots land as `image/png`, not `text/plain`); inline `--content` defaults to `text/plain`. The same inference applies on MCP `planr_artifact_add` and HTTP `POST /v1/artifacts`.
|
|
143
151
|
|
|
@@ -147,6 +155,6 @@ With `--json`, responses follow one convention so agents never guess where data
|
|
|
147
155
|
|
|
148
156
|
`serve` exposes the local review workspace at `/review` and its JSON projection at `/v1/review-workspace`.
|
|
149
157
|
|
|
150
|
-
`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),
|
|
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.
|
|
151
159
|
|
|
152
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
|
-
|
|
25
|
+
Optionally compile and apply a repository-local Codex routing bundle before starting the driver:
|
|
26
26
|
|
|
27
|
-
```
|
|
28
|
-
|
|
29
|
-
|
|
30
|
-
|
|
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
|
-
|
|
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/EXAMPLE_WEBAPP.md
CHANGED
|
@@ -1,138 +1,104 @@
|
|
|
1
1
|
# Worked Example: Routing a Small Web App
|
|
2
2
|
|
|
3
|
-
|
|
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
|
-
|
|
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
|
-
|
|
33
|
-
|
|
34
|
-
|
|
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
|
-
|
|
49
|
+
Validate without contacting a provider:
|
|
50
|
+
|
|
51
|
+
```bash
|
|
52
|
+
planr agents check
|
|
53
|
+
planr agents list
|
|
54
|
+
```
|
|
38
55
|
|
|
39
|
-
|
|
56
|
+
Alternatively, an external policy package can compile a strict RoutingBundle v1. Preview and apply it through the generic Core boundary:
|
|
40
57
|
|
|
41
|
-
|
|
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
|
-
|
|
64
|
+
## 2. Tag items by use case
|
|
44
65
|
|
|
45
66
|
```bash
|
|
46
67
|
planr item create "API: task CRUD endpoints" \
|
|
47
|
-
--description "
|
|
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 "
|
|
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
|
-
##
|
|
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
|
-
|
|
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
|
-
|
|
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
|
|
88
|
+
--summary "CRUD endpoints implemented; 8 tests green" \
|
|
104
89
|
--files server/routes/tasks.ts \
|
|
105
90
|
--tests "vitest --run: 8 passed" \
|
|
106
|
-
--profile
|
|
91
|
+
--profile backend-worker
|
|
107
92
|
```
|
|
108
93
|
|
|
109
|
-
`--profile`
|
|
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
|
-
|
|
96
|
+
## 5. Trace declared versus actual
|
|
114
97
|
|
|
115
98
|
```bash
|
|
116
|
-
planr trace item <
|
|
117
|
-
planr trace item <frontend-item>
|
|
99
|
+
planr trace item <item-id>
|
|
118
100
|
```
|
|
119
101
|
|
|
120
|
-
|
|
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
|
|
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
|
-
|
|
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"
|
|
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
|
-
|
|
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
|
|
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
|
-
-
|
|
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,7 +72,7 @@ planr prompt cli --client codex
|
|
|
72
72
|
planr prompt http
|
|
73
73
|
```
|
|
74
74
|
|
|
75
|
-
`planr install claude` writes a project `.mcp.json
|
|
75
|
+
`planr install claude` writes a project `.mcp.json` plus static workflow roles. `planr install cursor` writes `.cursor/mcp.json`, static workflow roles, and Planr skills, then prints a user-level MCP deeplink. `planr install codex` writes only the project MCP snippet. Optional model pins and generated host roles come from a repository-local routing bundle. Dry-runs print exact paths first; no command touches global user configuration.
|
|
76
76
|
|
|
77
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.
|
|
78
78
|
|
|
@@ -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
|
|
90
|
+
The repository ships a plugin under `plugins/planr` for Codex and Claude Code that bundles Planr workflow skills; Claude Code additionally registers static workflow roles. Cursor receives the same skills and static roles through `planr install cursor`. 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
|
|
package/docs/MCP_CONTRACT.md
CHANGED
|
@@ -41,7 +41,8 @@ Required groups:
|
|
|
41
41
|
- approval request, approve, deny, and list
|
|
42
42
|
- artifact add, list, and show
|
|
43
43
|
- event list and debug bundle preview
|
|
44
|
-
- log add and read
|
|
44
|
+
- trace item, log add, and log read (including three-stage route observations)
|
|
45
|
+
- provider-neutral RoutingBundle v1 inspection, repository-safe preview/apply, and durable application evidence
|
|
45
46
|
- review annotate, ingest, artifact, evidence, and close
|
|
46
47
|
- item close, context create, and search
|
|
47
48
|
|
|
@@ -63,7 +64,7 @@ HTTP mirrors the same rule: `GET /v1/reviews/:id/artifact` is read-only; `POST /
|
|
|
63
64
|
|
|
64
65
|
`planr install <client> --dry-run` prints project-scoped configuration for Codex, Claude Code, and Cursor. Non-dry install writes only repository-local files:
|
|
65
66
|
|
|
66
|
-
- Codex: `.planr/integrations/codex-mcp.toml
|
|
67
|
+
- Codex: `.planr/integrations/codex-mcp.toml`; optional `.codex/agents/` roles are routing-bundle artifacts
|
|
67
68
|
- Claude Code: `.mcp.json` plus `.claude/agents/` roles
|
|
68
69
|
- Cursor: `.cursor/mcp.json` plus `.cursor/agents/` roles and `.cursor/skills/` skill copies
|
|
69
70
|
|
package/docs/MODEL_ROUTING.md
CHANGED
|
@@ -1,196 +1,39 @@
|
|
|
1
|
-
# Model
|
|
1
|
+
# Model routing
|
|
2
2
|
|
|
3
|
-
|
|
4
|
-
|
|
5
|
-
The pattern this makes declarative: strongest model plans and judges, a cheap fast steerable model implements, token-hungry side work (browser verification, codebase analysis) goes to budget profiles. Without a registry that knowledge lives in CLAUDE.md prose, Codex agent TOMLs, and Cursor frontmatter — three dialects that drift. With a registry it travels inside every pick packet.
|
|
6
|
-
|
|
7
|
-
Routing is **advisory by design**: Planr never calls model providers and never blocks a pick because a profile is unavailable. Your host (Codex, Claude Code, Cursor, any MCP client) stays the dispatch authority.
|
|
8
|
-
|
|
9
|
-
Want the whole flow on a concrete project first? [Worked Example: Routing a Small Web App](EXAMPLE_WEBAPP.md) walks a frontend/backend todo app from pool declaration to the audit trail, with real outputs.
|
|
10
|
-
|
|
11
|
-
## Quick Start
|
|
12
|
-
|
|
13
|
-
One command writes a working starter registry — the cost-tiering defaults with a premium driver, a standard implementer, and a budget helper, commented so the tiers explain themselves:
|
|
14
|
-
|
|
15
|
-
```bash
|
|
16
|
-
planr agents init # writes .planr/agents.toml; never overwrites without --force
|
|
17
|
-
```
|
|
18
|
-
|
|
19
|
-
Or declare `.planr/agents.toml` by hand:
|
|
3
|
+
Planr Core treats routing as optional, advisory repository data. `.planr/agents.toml` declares opaque profiles and routes; Planr resolves them into pick packets but never calls a provider or claims that a requested model actually ran.
|
|
20
4
|
|
|
21
5
|
```toml
|
|
22
|
-
[profiles.
|
|
23
|
-
client = "
|
|
24
|
-
model = "
|
|
6
|
+
[profiles.worker]
|
|
7
|
+
client = "host-a"
|
|
8
|
+
model = "model-id"
|
|
9
|
+
agent_type = "repository-role"
|
|
25
10
|
effort = "high"
|
|
26
|
-
|
|
27
|
-
capabilities = ["orchestration", "review", "planning"]
|
|
28
|
-
notes = "Planner/architect and judge. Verdicts stay on this tier."
|
|
29
|
-
|
|
30
|
-
[profiles.gpt55-coder]
|
|
31
|
-
client = "codex"
|
|
32
|
-
model = "gpt-5.5"
|
|
33
|
-
effort = "xhigh"
|
|
34
|
-
cost_tier = "standard"
|
|
35
|
-
capabilities = ["code", "steerable"]
|
|
36
|
-
notes = "Primary implementer: strong, fast, cheap on subscription."
|
|
11
|
+
skill = "planr-work"
|
|
37
12
|
|
|
38
13
|
[[routes]]
|
|
39
14
|
match = { work_type = "code" }
|
|
40
|
-
profile = "
|
|
41
|
-
fallbacks = ["fable-driver"]
|
|
42
|
-
|
|
43
|
-
[[routes]]
|
|
44
|
-
match = { work_type = "review" }
|
|
45
|
-
profile = "fable-driver"
|
|
46
|
-
|
|
47
|
-
[route_default]
|
|
48
|
-
profile = "gpt55-coder"
|
|
49
|
-
fallbacks = ["fable-driver"]
|
|
50
|
-
```
|
|
51
|
-
|
|
52
|
-
Validate and inspect:
|
|
53
|
-
|
|
54
|
-
```bash
|
|
55
|
-
planr agents check # non-zero exit only on parse failure; warnings pass
|
|
56
|
-
planr agents list # resolved profiles, routes, and warnings
|
|
15
|
+
profile = "worker"
|
|
57
16
|
```
|
|
58
17
|
|
|
59
|
-
|
|
18
|
+
Create a neutral scaffold or an explicit registry:
|
|
60
19
|
|
|
61
20
|
```bash
|
|
62
|
-
planr
|
|
63
|
-
|
|
64
|
-
|
|
65
|
-
|
|
66
|
-
"routing": {
|
|
67
|
-
"profile": "gpt55-coder",
|
|
68
|
-
"client": "codex",
|
|
69
|
-
"model": "gpt-5.5",
|
|
70
|
-
"effort": "xhigh",
|
|
71
|
-
"cost_tier": "standard",
|
|
72
|
-
"fallbacks": ["fable-driver"],
|
|
73
|
-
"matched_selector": "work_type=code"
|
|
74
|
-
}
|
|
21
|
+
planr agents init
|
|
22
|
+
planr agents init --profile worker=host-a/model-id@high#standard --route code=worker
|
|
23
|
+
planr agents check
|
|
24
|
+
planr agents list --json
|
|
75
25
|
```
|
|
76
26
|
|
|
77
|
-
|
|
78
|
-
|
|
79
|
-
## The Registry File
|
|
80
|
-
|
|
81
|
-
`.planr/agents.toml` has three parts:
|
|
82
|
-
|
|
83
|
-
- `[profiles.<id>]` — a named agent setting. `client` (which host dispatches it: `codex`, `claude-code`, `cursor`, `generic-mcp`) and `model` are required; `effort`, `cost_tier` (`premium` | `standard` | `budget`), `capabilities`, and `notes` are optional. Model ids and aliases pass through verbatim — Planr does not validate them against provider catalogs, so new models need no Planr release.
|
|
84
|
-
- `[[routes]]` — `match` selects work (`work_type = "code"` or `plan = "pln-1234abcd"`), `profile` names the primary, `fallbacks` the ordered alternatives.
|
|
85
|
-
- `[route_default]` — catches everything no route matched.
|
|
86
|
-
|
|
87
|
-
Resolution precedence per item: **per-item override > `work_type` route > `plan` route > default**. Within a level, the first declared route wins. If a chain's primary profile id is unknown, the first known fallback is promoted; a chain with no known profiles falls through to the next precedence level, so a typo never swallows lower routes. `matched_selector` in the output tells you which rule fired (`override`, `work_type=<v>`, `plan=<v>`, or `default`).
|
|
27
|
+
Resolution order is per-item override, work type, plan, then default route. Unknown profiles fail open to the next applicable route. Host names, model ids, role selectors, effort values, and fallback behavior are opaque to Core.
|
|
88
28
|
|
|
89
|
-
|
|
29
|
+
Workers may report observed routing with logs and route-audit evidence. Requested-only values never become effective proof; missing effective evidence remains explicitly unavailable.
|
|
90
30
|
|
|
91
|
-
|
|
31
|
+
Host-specific model policies and generated repository roles are optional. The `planr-routing` workspace package compiles them into RoutingBundle v1, and Core safely previews and applies that bundle:
|
|
92
32
|
|
|
93
33
|
```bash
|
|
94
|
-
planr
|
|
95
|
-
planr
|
|
96
|
-
planr
|
|
34
|
+
planr-routing compile balanced --host codex-openai --output routing-bundle.json
|
|
35
|
+
planr routing bundle preview routing-bundle.json
|
|
36
|
+
planr routing bundle apply routing-bundle.json
|
|
97
37
|
```
|
|
98
38
|
|
|
99
|
-
|
|
100
|
-
|
|
101
|
-
Tier the roles, not just the models: workers run safely on cheaper tiers because the pick packet bounds their scope, while review verdicts should stay on the strongest tier — `agents check` warns when review work routes to a `budget` profile. Background: [Cost Tiering](GOALS.md#cost-tiering).
|
|
102
|
-
|
|
103
|
-
## Host-Native Rendering
|
|
104
|
-
|
|
105
|
-
Routes only matter if the host actually dispatches the declared model, so `planr install codex|claude|cursor` closes the gap: when a registry is present, the provisioned subagent role files are rendered with pins taken from it instead of the shipped static defaults. The `work_type=code` route pins the worker role, the `work_type=review` route pins the reviewer role, and each render uses the host's exact vocabulary — Codex TOML gets `model` and `model_reasoning_effort` (with `developer_instructions` always present, since Codex silently ignores a role file without it), Claude frontmatter gets `model:` and `effort:`, Cursor frontmatter gets `model:` only.
|
|
106
|
-
|
|
107
|
-
Two safety rules keep this predictable:
|
|
108
|
-
|
|
109
|
-
- **Client matching**: a role file only pins profiles whose `client` matches the install target, scanning the route's fallback chain for the first match. A review route pointing at a Cursor profile never writes a Cursor model id into a Codex TOML — that role keeps its static default instead.
|
|
110
|
-
- **Provision-once**: existing files are never overwritten. After editing the registry, re-render explicitly with `planr install <client> --force`. Rendered files start with a `# generated from .planr/agents.toml` header so you (and future audit tooling) can tell them from hand-maintained ones.
|
|
111
|
-
|
|
112
|
-
Without a registry, installs write the static role files byte-identically to previous releases.
|
|
113
|
-
|
|
114
|
-
## Prompt Routing
|
|
115
|
-
|
|
116
|
-
`planr prompt routing [--client codex|claude|cursor|all]` prints a paste-ready block for the driver session: the prioritization table (every route, profile, and fallback in precedence order), per-host dispatch guidance including the traps that silently defeat pins (Codex requires `fork_turns: "none"` and a session restart after re-rendering; the `CLAUDE_CODE_SUBAGENT_MODEL` env var preempts Claude frontmatter; Cursor plan mode, admin policy, and Max Mode override silently), and process-dispatch snippets (`codex exec`, `pi`, `opencode run`) for hosts without role files, pre-filled from the `work_type=code` route. `--json` carries the same content structured.
|
|
117
|
-
|
|
118
|
-
## Run Audit
|
|
119
|
-
|
|
120
|
-
Every host has a silent override path — the `CLAUDE_CODE_SUBAGENT_MODEL` env var, Cursor plan/admin/Max-Mode policy, Codex full-history forks, org allowlists — so a pin alone is not proof. The audit loop closes this: workers report the profile they actually ran on via `planr log add`/`planr done --profile <id>` (or the `PLANR_PROFILE` env var, which rendered role files can export), the profile lands on the recorded run, and when it differs from the item's declared route Planr emits an advisory `route_mismatch_observed` event with the declared and actual ids.
|
|
121
|
-
|
|
122
|
-
- `planr trace item <id>` shows the declared route next to every run's actual client/profile with a `mismatch` marker.
|
|
123
|
-
- Runs also record the host they observably executed under (`observed_client`, detected from environment variables the hosts set themselves — no flags); a run whose host differs from the declared route's client emits an advisory `client_mismatch_observed` event, which catches exactly the deviation profile self-report cannot: a different host standing in for the declared client, even when the model matched.
|
|
124
|
-
- `planr doctor` reports the registry state (absent, degraded with parse context, loaded with counts and warnings) and flags rendered role files that drifted from the current registry (`planr install <client> --force` re-renders).
|
|
125
|
-
- `planr export`/`import` carry the registry with the package, preview-first; an existing registry at the destination is never silently overwritten.
|
|
126
|
-
|
|
127
|
-
Everything here is advisory (ADR-001): mismatches never fail logging, reviews, or closes. No profile reported, no run recorded, or no registry means no comparison and no event.
|
|
128
|
-
|
|
129
|
-
One legitimate mismatch source to know: a driver adding a live-verification log to a routed item runs on the driver profile by design, which emits a `route_mismatch_observed` event. The payload carries `log_kind`, so audit consumers can discount `verification` entries and alarm only on `completion` mismatches.
|
|
130
|
-
|
|
131
|
-
For single-host pools (e.g. all-Cursor), declare the host's *exact* model slugs (`claude-opus-4-8-thinking-high`, not `opus`): dispatch APIs resolve slugs, not aliases, and a driver forced to map `fable-5` onto the nearest slug at dispatch time is a silent translation the audit cannot see.
|
|
132
|
-
|
|
133
|
-
## Failure Behavior
|
|
134
|
-
|
|
135
|
-
- **No registry file**: nothing changes. Pick packets simply have no `routing` key.
|
|
136
|
-
- **Malformed registry**: `planr agents check` fails with the parser's line context; everything else (`pick`, `map`, `install`) keeps working with routing omitted — installs fall back to the static role files.
|
|
137
|
-
- **Warnings** (unknown profile references, empty or duplicate selectors, budget-tier review routes, secret-like values) never block anything; `agents check` lists them and still exits zero.
|
|
138
|
-
- Never put credentials in the registry — it holds configuration strings only, and secret-like values are flagged.
|
|
139
|
-
|
|
140
|
-
## Use-Case Pools
|
|
141
|
-
|
|
142
|
-
Work types are free-form, and that makes them the use-case dimension: beyond the built-in vocabulary (`code`, `fix`, `review`, `docs`, ...), any string you pass to `--work-type` routes. Combined with per-profile skill pairing, the registry becomes a small agent pool — each use case names who runs it, on what model, with which skill:
|
|
143
|
-
|
|
144
|
-
```toml
|
|
145
|
-
[profiles.designer]
|
|
146
|
-
client = "claude-code"
|
|
147
|
-
model = "opus"
|
|
148
|
-
effort = "high"
|
|
149
|
-
cost_tier = "premium"
|
|
150
|
-
skill = "frontend-design" # dispatch this profile *with* this skill
|
|
151
|
-
|
|
152
|
-
[profiles.backender]
|
|
153
|
-
client = "codex"
|
|
154
|
-
model = "gpt-5.5"
|
|
155
|
-
effort = "xhigh"
|
|
156
|
-
cost_tier = "standard"
|
|
157
|
-
skill = "planr-work"
|
|
158
|
-
|
|
159
|
-
[[routes]]
|
|
160
|
-
match = { work_type = "frontend" }
|
|
161
|
-
profile = "designer"
|
|
162
|
-
fallbacks = ["driver"]
|
|
163
|
-
|
|
164
|
-
[[routes]]
|
|
165
|
-
match = { work_type = "design" }
|
|
166
|
-
profile = "designer"
|
|
167
|
-
|
|
168
|
-
[[routes]]
|
|
169
|
-
match = { work_type = "backend" }
|
|
170
|
-
profile = "backender"
|
|
171
|
-
fallbacks = ["driver"]
|
|
172
|
-
```
|
|
173
|
-
|
|
174
|
-
Create items with the use-case work type (`planr item create ... --work-type frontend`) — or retag existing ones with `planr item update <id> --work-type frontend`, which is how planning agents tag `map build` output against the declared routes (the planning skills read `agents list` and do this without user involvement) — and the pick packet carries the full pairing — `"profile": "designer"`, `"model": "opus"`, `"skill": "frontend-design"` — so the driver dispatches profile and skill together (`Use $frontend-design on item <id>` on the profile's client/model). Workers pull their slice of the pool with `planr pick --work-type frontend`. `skill` is passthrough vocabulary like model ids: Planr never validates it against installed skills, and profiles without one omit the key entirely. A profile that needs different skills for different use cases is simply two profiles.
|
|
175
|
-
|
|
176
|
-
Declare the `client` you will actually dispatch on. A loop running inside one host dispatches that host's subagents — an in-Cursor driver that dispatches Cursor subagents with per-dispatch models is running `client = "cursor"` profiles in practice, even when the model matches. A `client = "codex"` profile is only honest when the driver really spawns a Codex process (`codex exec ...`). This matters for the audit: workers report the *profile id*, so a profile whose declared client differs from the real dispatch host passes the mismatch check on the model alone — the client deviation stays invisible.
|
|
177
|
-
|
|
178
|
-
When do you actually need more than one client? Hosts with a full model catalog (Cursor) can serve an entire pool natively — an all-`cursor` registry with different models per profile is the normal case there. Cross-client profiles exist for two real situations: vendor-locked hosts (Claude Code dispatches only Anthropic models, Codex CLI only OpenAI models — a Claude-Code driver that wants a GPT implementer must process-dispatch via `codex exec`), and subscription economics (the same model can bill differently per host, so routing backend work through a flat-rate CLI subscription instead of the driver host's quota is a legitimate cost decision).
|
|
179
|
-
|
|
180
|
-
## Host Matrix
|
|
181
|
-
|
|
182
|
-
Where each host reads its model configuration from, and what silently defeats a pin there (state of July 2026):
|
|
183
|
-
|
|
184
|
-
| Host | Native mechanism | Rendered by `planr install`? | Silent overrides / traps |
|
|
185
|
-
| --- | --- | --- | --- |
|
|
186
|
-
| Cursor | `.cursor/agents/*.md` frontmatter `model: <id>` (default `inherit`) | yes (`cursor`) | Team-admin model policy, plan availability, and Max-Mode-only models override without error; legacy request-based plans force Composer for subagents; subagent transcripts record no model field, so the actual model cannot be verified from artifacts after the fact — the dispatch parameters in the driver session are the only record |
|
|
187
|
-
| Claude Code | `planr-worker.md`/`planr-reviewer.md` frontmatter `model:` + `effort:` | yes (`claude`) | `CLAUDE_CODE_SUBAGENT_MODEL` clamps frontmatter and per-invocation models with no signal ([#57718](https://github.com/anthropics/claude-code/issues/57718)); since v2.1.196 `inherit` behaves as unset; org `availableModels` allowlists fall back silently |
|
|
188
|
-
| Codex CLI | `.codex/agents/*.toml` with `model` + `model_reasoning_effort` | yes (`codex`) | `fork_turns = "all"` intentionally drops the child's `agent_type`/`model` — use `fork_turns = "none"` or a partial fork; the role registry loads at session start ([#26408](https://github.com/openai/codex/issues/26408)), so re-renders need a restart |
|
|
189
|
-
| opencode | `opencode.json` `agent.<name>.model = "provider/model-id"` or `.opencode/agents/*.md` frontmatter | no — use the `planr prompt routing` process snippet | Subagent inherits the primary model when unset; malformed `provider/model-id` strings (quoting, trailing newline) raise `ProviderModelNotFoundError` ([#5623](https://github.com/sst/opencode/issues/5623)) |
|
|
190
|
-
| Pi | none by design — process-level dispatch (`pi --provider --model --thinking`) or the `pi-subagents` extension (`.pi/agents/*.md`) | no — use the `planr prompt routing` process snippet | Extension model-scope enforcement against `enabledModels` is opt-in; without it, pins are best-effort |
|
|
191
|
-
|
|
192
|
-
For the hosts without rendered role files, `planr prompt routing` prints ready process-dispatch snippets pre-filled from the registry. Whatever the host does, the [run audit](#run-audit) catches silent overrides after the fact.
|
|
193
|
-
|
|
194
|
-
## Command Summary
|
|
195
|
-
|
|
196
|
-
The registry surface end to end: `planr agents init [--force]` scaffolds, `planr agents list|check` inspect and validate, `planr pick --json` carries the `routing` block, `planr item route [--set|--clear]` pins per item, the MCP tools (`planr_agents_list`, `planr_item_route`, `planr_item_route_set`, `planr_item_route_clear`) return identical JSON shapes, `planr install <client> [--force]` renders host role files from the registry, `planr prompt routing` prints the driver dispatch block, `planr log add`/`done --profile` (or `PLANR_PROFILE`) feed the run audit, `planr trace item` and `planr doctor` surface mismatches and drift, and `planr export`/`import` carry the registry preview-first.
|
|
39
|
+
Bundle application is restricted to the repository. Planr never edits user configuration such as `~/.codex/config.toml`. See [Routing Bundles](ROUTING_BUNDLES.md).
|
|
@@ -0,0 +1,32 @@
|
|
|
1
|
+
# Routing bundles
|
|
2
|
+
|
|
3
|
+
Planr Core is provider-neutral. It parses `.planr/agents.toml`, resolves routes into pick packets, records declared-versus-observed evidence, and safely previews or applies a strict RoutingBundle v1:
|
|
4
|
+
|
|
5
|
+
```bash
|
|
6
|
+
planr routing bundle inspect routing-bundle.json
|
|
7
|
+
planr routing bundle preview routing-bundle.json
|
|
8
|
+
planr routing bundle apply routing-bundle.json
|
|
9
|
+
```
|
|
10
|
+
|
|
11
|
+
Core accepts only allowlisted repository-local targets, verifies payload hashes, rejects absolute paths, traversal, symlinks, parent/child target collisions, conflicts, unsupported versions, and invalid payloads, and applies the validated set atomically. It never writes user configuration or files outside the repository.
|
|
12
|
+
|
|
13
|
+
A signed bundle is accepted only with an independent trust anchor supplied to every inspect, preview, or apply call:
|
|
14
|
+
|
|
15
|
+
```bash
|
|
16
|
+
planr routing bundle inspect signed-bundle.json \
|
|
17
|
+
--trusted-signer planr-maintainers \
|
|
18
|
+
--trusted-public-key-file /absolute/path/to/maintainer.pub
|
|
19
|
+
```
|
|
20
|
+
|
|
21
|
+
The bundle contains the signer id and signature, not a self-trusted public key. Both trust flags are required together; unsigned bundles require neither. An unsigned bundle also cannot label its evidence `verified` or `recommended`.
|
|
22
|
+
|
|
23
|
+
The `planr-routing` workspace package owns all volatile opinions: named policies, exact model ids, host bindings, generated role and skill files, capability probes, evaluation scenarios, signing, registry data, and the website catalog. A normal flow is:
|
|
24
|
+
|
|
25
|
+
```bash
|
|
26
|
+
planr-routing policy list
|
|
27
|
+
planr-routing compile balanced --host codex-openai --output routing-bundle.json
|
|
28
|
+
planr routing bundle preview routing-bundle.json
|
|
29
|
+
planr routing bundle apply routing-bundle.json
|
|
30
|
+
```
|
|
31
|
+
|
|
32
|
+
The package emits the same provider-neutral bundle contract for Codex, Claude Code, Cursor, and mixed-host configurations. Offline evaluation remains experimental; a recommendation requires complete authenticated live-host evidence. Missing authentication or missing effective model, effort, role, or context-fork evidence cannot pass.
|
package/docs/SKILLS.md
CHANGED
|
@@ -2,7 +2,7 @@
|
|
|
2
2
|
|
|
3
3
|
Planr ships agent-facing skill templates under `plugins/planr/skills/`.
|
|
4
4
|
|
|
5
|
-
The repository ships an installable plugin under `plugins/planr` for Codex
|
|
5
|
+
The repository ships an installable plugin under `plugins/planr` for Codex and Claude Code, while Cursor receives the same skills through `planr install cursor`. Marketplace manifests at the repo root (`.agents/plugins/marketplace.json`, `.claude-plugin/marketplace.json`) point at that subdirectory — Codex silently ignores marketplaces whose plugin source is the repo root itself. The shared package carries skills and Claude's independent workflow roles; optional model-specific host roles come only from a repository-local routing bundle, never from Planr Core or static fallbacks. The `planr` CLI must be installed separately (`brew install instructa/tap/planr`).
|
|
6
6
|
|
|
7
7
|
## Install As Plugin (preferred)
|
|
8
8
|
|
|
@@ -165,10 +165,12 @@ The CLI provisions the role files automatically — no manual copying:
|
|
|
165
165
|
|
|
166
166
|
```bash
|
|
167
167
|
planr project init "My Product" --client all # writes .codex/agents/*.toml, .claude/agents/*.md, and .cursor/agents/*.md
|
|
168
|
-
planr
|
|
168
|
+
planr agents init # generates canonical native Codex roles in an existing project
|
|
169
|
+
planr install claude # provisions Claude's independent roles
|
|
170
|
+
planr install cursor # provisions Cursor's independent roles and skills
|
|
169
171
|
```
|
|
170
172
|
|
|
171
|
-
|
|
173
|
+
Optional project-scoped model-routing files are generated by `planr-routing` bundles. Core workflow skills remain host-neutral, and bundle application never overwrites conflicts or writes user configuration.
|
|
172
174
|
|
|
173
175
|
Dispatches stay one line: `Use $planr-work on item <id>` and `Use $planr-review on item <id>`. The map and logs are the loop memory, so any iteration can resume from zero context.
|
|
174
176
|
|
|
@@ -1,6 +1,7 @@
|
|
|
1
1
|
{
|
|
2
2
|
"tools": [
|
|
3
3
|
"planr_project_show",
|
|
4
|
+
"planr_trace_item",
|
|
4
5
|
"planr_map_show",
|
|
5
6
|
"planr_map_status",
|
|
6
7
|
"planr_map_preview",
|
|
@@ -19,6 +20,9 @@
|
|
|
19
20
|
"planr_item_amend",
|
|
20
21
|
"planr_item_replan",
|
|
21
22
|
"planr_agents_list",
|
|
23
|
+
"planr_policy_show",
|
|
24
|
+
"planr_policy_check",
|
|
25
|
+
"planr_policy_admit",
|
|
22
26
|
"planr_item_route",
|
|
23
27
|
"planr_item_route_set",
|
|
24
28
|
"planr_item_route_clear",
|
|
@@ -99,7 +103,11 @@
|
|
|
99
103
|
"planr recover sweep",
|
|
100
104
|
"planr agents list",
|
|
101
105
|
"planr agents check",
|
|
106
|
+
"planr routing bundle inspect",
|
|
107
|
+
"planr routing bundle preview",
|
|
108
|
+
"planr routing bundle apply",
|
|
102
109
|
"planr item route",
|
|
110
|
+
"planr trace item",
|
|
103
111
|
"planr serve --port"
|
|
104
112
|
]
|
|
105
113
|
}
|
|
Binary file
|
|
Binary file
|
|
Binary file
|
|
Binary file
|
package/package.json
CHANGED
|
@@ -1,6 +1,6 @@
|
|
|
1
1
|
{
|
|
2
2
|
"name": "planr",
|
|
3
|
-
"version": "1.
|
|
3
|
+
"version": "1.5.0",
|
|
4
4
|
"description": "Local-first planning and execution coordination for coding agents.",
|
|
5
5
|
"license": "MIT",
|
|
6
6
|
"repository": {
|
|
@@ -22,7 +22,8 @@
|
|
|
22
22
|
"scripts": {
|
|
23
23
|
"build:native": "cargo build --release",
|
|
24
24
|
"test": "cargo test",
|
|
25
|
-
"pack:check": "npm pack --dry-run"
|
|
25
|
+
"pack:check": "npm pack --dry-run",
|
|
26
|
+
"routing": "cargo run --manifest-path planr-routing/Cargo.toml --"
|
|
26
27
|
},
|
|
27
28
|
"engines": {
|
|
28
29
|
"node": ">=18"
|
|
@@ -1,7 +1,7 @@
|
|
|
1
1
|
{
|
|
2
2
|
"name": "planr",
|
|
3
3
|
"description": "Skill-driven planning and execution loop for coding agents: one planr entry point, an autonomous planr-loop, and evidence-backed task graph skills powered by the planr CLI.",
|
|
4
|
-
"version": "1.
|
|
4
|
+
"version": "1.5.0",
|
|
5
5
|
"author": {
|
|
6
6
|
"name": "instructa"
|
|
7
7
|
},
|
|
@@ -1,6 +1,6 @@
|
|
|
1
1
|
{
|
|
2
2
|
"name": "planr",
|
|
3
|
-
"version": "1.
|
|
3
|
+
"version": "1.5.0",
|
|
4
4
|
"description": "Skill-driven planning and execution loop for coding agents: one $planr entry point, an autonomous $planr-loop, and evidence-backed task graph skills powered by the planr CLI.",
|
|
5
5
|
"author": {
|
|
6
6
|
"name": "instructa",
|
|
@@ -67,7 +67,7 @@ A worker subagent may take several items sequentially instead of being respawned
|
|
|
67
67
|
|
|
68
68
|
Host wiring:
|
|
69
69
|
|
|
70
|
-
-
|
|
70
|
+
- When a repository routing bundle supplies host roles, follow its generated routing skill exactly. Otherwise treat the profile in the pick packet as advisory and use the host's current dispatch contract. Never infer effective model or effort from a declaration alone.
|
|
71
71
|
- Claude Code: subagents preload via the `skills:` frontmatter field. The Planr plugin registers `planr-worker` and `planr-reviewer` automatically from its `agents/` directory; standalone installs copy them to `.claude/agents/`. The reviewer subagent is read-only except for `planr review` commands.
|
|
72
72
|
- Cursor: project subagents in `.cursor/agents/*.md` (Markdown templates in `agents/` next to this skill; `planr install cursor` provisions them). Dispatch explicitly: `/planr-worker implement item X`, `/planr-reviewer review item X`. Parallel dispatches are safe — the map's pick lease keeps one owner per item.
|
|
73
73
|
- Single-agent hosts: run worker and checker as separate sequential dispatches with a fresh read of map state in between; never carry the worker's self-assessment into the review step. The mode is recorded automatically: `review close` derives `review_mode` (`single_agent`/`independent`) from worker identity.
|
|
@@ -1,23 +0,0 @@
|
|
|
1
|
-
# Copy to .codex/agents/planr-reviewer.toml (project) or ~/.codex/agents/ (user).
|
|
2
|
-
# Adjust the skill path to where the Planr skills are installed.
|
|
3
|
-
name = "planr_reviewer"
|
|
4
|
-
description = "Independent findings-first reviewer for one Planr item. Audits evidence and closes the review with a verdict."
|
|
5
|
-
sandbox_mode = "workspace-write"
|
|
6
|
-
|
|
7
|
-
# Deliberately no model override: the reviewer is the truth gate and inherits
|
|
8
|
-
# the driver session's model. Make workers cheap, not the verdict.
|
|
9
|
-
|
|
10
|
-
developer_instructions = """
|
|
11
|
-
Use the planr-review skill exactly as written for the single item id you are given.
|
|
12
|
-
You did not write this code; audit it like an owner. Inspect the actual diff and rerun the
|
|
13
|
-
logged verification commands instead of trusting the worker's summary.
|
|
14
|
-
Close the review with `planr review close <review-id> --verdict ... --reviewer <your-id>` and
|
|
15
|
-
always pass `--reviewer` explicitly (e.g. `checker-1`): shell exports do not survive between
|
|
16
|
-
tool calls, and a review closed under the default identity corrupts the independence audit.
|
|
17
|
-
Findings must be specific and actionable. Do not edit implementation files; your only writes
|
|
18
|
-
are planr review commands.
|
|
19
|
-
"""
|
|
20
|
-
|
|
21
|
-
[[skills.config]]
|
|
22
|
-
path = "~/.codex/skills/planr-review/SKILL.md"
|
|
23
|
-
enabled = true
|
|
@@ -1,21 +0,0 @@
|
|
|
1
|
-
# Copy to .codex/agents/planr-worker.toml (project) or ~/.codex/agents/ (user).
|
|
2
|
-
# Adjust the skill path to where the Planr skills are installed.
|
|
3
|
-
name = "planr_worker"
|
|
4
|
-
description = "Implements exactly one picked Planr map item to evidence-backed completion, then requests review and stops."
|
|
5
|
-
|
|
6
|
-
# Cost tiering: the pick packet bounds the worker's scope, so it can run on a
|
|
7
|
-
# lower effort tier than the driver session. Verify the pin took effect after
|
|
8
|
-
# the first spawn (some Codex versions ignore custom agent files on spawn —
|
|
9
|
-
# openai/codex#26868); see docs/GOALS.md "Cost Tiering" for the smoke test.
|
|
10
|
-
model = "gpt-5.5"
|
|
11
|
-
model_reasoning_effort = "medium"
|
|
12
|
-
|
|
13
|
-
developer_instructions = """
|
|
14
|
-
Use the planr-work skill exactly as written for the single item id you are given.
|
|
15
|
-
Implement only that item. Log changed files and the real verification commands you ran.
|
|
16
|
-
Request review with `planr review request <item-id>` and stop. Never close reviews or items yourself.
|
|
17
|
-
"""
|
|
18
|
-
|
|
19
|
-
[[skills.config]]
|
|
20
|
-
path = "~/.codex/skills/planr-work/SKILL.md"
|
|
21
|
-
enabled = true
|