planr 1.2.0-alpha.1 → 1.2.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/docs/CLI_REFERENCE.md +4 -2
- package/docs/MODEL_ROUTING.md +6 -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 +1 -1
- package/plugins/planr/.claude-plugin/plugin.json +1 -1
- package/plugins/planr/.codex-plugin/plugin.json +1 -1
- package/plugins/planr/skills/planr-goal/SKILL.md +1 -1
- package/plugins/planr/skills/planr-loop/SKILL.md +1 -1
- package/plugins/planr/skills/planr-plan/SKILL.md +7 -6
- package/plugins/planr/skills/planr-work/SKILL.md +2 -0
package/docs/CLI_REFERENCE.md
CHANGED
|
@@ -27,9 +27,10 @@ planr item insert "title" --description "..." --after <item-id> [--before <item-
|
|
|
27
27
|
planr item amend <item-id> --note "..." [--tag amendment]
|
|
28
28
|
planr item replan <parent-id> --into "A, B, C" [--preview|--confirm]
|
|
29
29
|
planr item update <item-id> [--title "..."] [--description "..."] [--work-type <type>]
|
|
30
|
+
# plan task lists can declare work types inline: `### TASK-001 (backend): ...` / `- [ ] (frontend) ...` seed map build directly
|
|
30
31
|
planr item route <item-id> [--set <profile>|--clear]
|
|
31
32
|
planr link add <from-item> <to-item> --type blocks
|
|
32
|
-
planr pick
|
|
33
|
+
planr pick [--work-type <type>] [--plan <plan-id>] [--peek]
|
|
33
34
|
planr pick release <item-id> [--force]
|
|
34
35
|
planr pick heartbeat [item-id]
|
|
35
36
|
planr pick progress <item-id> --percent 0..100 [--note "..."]
|
|
@@ -47,6 +48,7 @@ planr artifact list [--item <item-id>]
|
|
|
47
48
|
planr event list [--item <item-id>] [--limit 50]
|
|
48
49
|
planr debug bundle [--item <item-id>] --preview
|
|
49
50
|
planr log add --item <item-id> --summary "..." [--files a --files b | --files a,b] [--cmd "..."] [--kind completion|progress|verification] [--profile <id>]
|
|
51
|
+
# machine consumers: --cmd writes the `commands` field in log JSON; --tests writes `tests`
|
|
50
52
|
planr review request <item-id>
|
|
51
53
|
planr review annotate <item-id> --message "..." [--severity info|warning|blocking] [--file path] [--line N] [--author "..."]
|
|
52
54
|
planr review ingest <item-id> (--from feedback.json|--stdin)
|
|
@@ -125,7 +127,7 @@ With `--json`, responses follow one convention so agents never guess where data
|
|
|
125
127
|
|
|
126
128
|
`done` is the compound worker command: it writes a completion log, then requests a review (`--review`) or closes the item, and optionally picks the next ready item (`--next`). Without `--next`, the response's `next` field carries the exact follow-up command instead (`planr pick --work-type review --json` after a review request, `planr pick --json` after a close), so every settlement output ends in an action. It chains the same single-owner operations as `log add`, `review request`, `close`, and `pick` — identical evidence, fewer commands. `done`, `close`, and `review close` report what the settlement `unlocked` (id, title, work type of every item that became ready), `done` and `close` echo the item's `post_condition` at completion time, and a `hint` asks for `--cmd`/`--tests` evidence when downstream items depend on an item that closed without any. `done`, `close`, `review close`, and the pick packet include a `remaining` progress snapshot so loop agents can evaluate their stop condition without an extra `map status` call. `remaining.counts` always carries the full status vocabulary (`pending`, `ready`, `picked`, `running`, `in_review`, `blocked`, `failed`, `cancelled`, `closed`, `closed_partial`) with explicit zeros — a missing count never has to be inferred.
|
|
127
129
|
|
|
128
|
-
`pick --json` returns one flat work packet in which every fact appears exactly once: `item`, `links`, `logs`, `runtime`, `recovery`, `conditions`, `approval`, recall context (`contexts`, `relevant_contexts`, `upstream_handoffs`, `review_history`, `source_links`, `possible_file_conflicts`), `close_effect`, `privacy`, `deeper_reads`, and `remaining`. Worker identity lives in `item.worker_id` and `runtime.worker_id`. Empty collections and inactive gates are omitted — a missing key means "empty". No separate `trace item` call is needed. Evidence written via `log add` or `done` by the pick owner refreshes the runtime heartbeat automatically. The same packet shape is returned by MCP `planr_pick_item`, HTTP `POST /v1/pick`, and `done --next`.
|
|
130
|
+
`pick --json` returns one flat work packet in which every fact appears exactly once: `item`, `links`, `logs`, `runtime`, `recovery`, `conditions`, `approval`, recall context (`contexts`, `relevant_contexts`, `upstream_handoffs`, `review_history`, `source_links`, `possible_file_conflicts`), `close_effect`, `privacy`, `deeper_reads`, and `remaining`. Worker identity lives in `item.worker_id` and `runtime.worker_id`. Empty collections and inactive gates are omitted — a missing key means "empty". No separate `trace item` call is needed. Evidence written via `log add` or `done` by the pick owner refreshes the runtime heartbeat automatically. The same packet shape is returned by MCP `planr_pick_item`, HTTP `POST /v1/pick`, and `done --next`. `pick --peek` (MCP: `"peek": true`) returns the same packet for the next pickable item *without* leasing it — no lease, heartbeat, or pick event is written, and the packet carries `"peek": true` with the item still `ready`. Built for dispatching drivers: read the routing block, dispatch the worker, and let the worker take the lease under its own identity — replacing the pick → `pick release --force` → re-pick sequence.
|
|
129
131
|
|
|
130
132
|
`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.
|
|
131
133
|
|
package/docs/MODEL_ROUTING.md
CHANGED
|
@@ -126,6 +126,10 @@ Every host has a silent override path — the `CLAUDE_CODE_SUBAGENT_MODEL` env v
|
|
|
126
126
|
|
|
127
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
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
|
+
|
|
129
133
|
## Failure Behavior
|
|
130
134
|
|
|
131
135
|
- **No registry file**: nothing changes. Pick packets simply have no `routing` key.
|
|
@@ -171,6 +175,8 @@ Create items with the use-case work type (`planr item create ... --work-type fro
|
|
|
171
175
|
|
|
172
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.
|
|
173
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
|
+
|
|
174
180
|
## Host Matrix
|
|
175
181
|
|
|
176
182
|
Where each host reads its model configuration from, and what silently defeats a pin there (state of July 2026):
|
|
Binary file
|
|
Binary file
|
|
Binary file
|
|
Binary file
|
package/package.json
CHANGED
|
@@ -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.2.0
|
|
4
|
+
"version": "1.2.0",
|
|
5
5
|
"author": {
|
|
6
6
|
"name": "instructa"
|
|
7
7
|
},
|
|
@@ -1,6 +1,6 @@
|
|
|
1
1
|
{
|
|
2
2
|
"name": "planr",
|
|
3
|
-
"version": "1.2.0
|
|
3
|
+
"version": "1.2.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",
|
|
@@ -42,7 +42,7 @@ Before `map build`, expand the plan's task list: the scaffold ships a single pla
|
|
|
42
42
|
planr link add <earlier-item> <later-item> --type blocks
|
|
43
43
|
```
|
|
44
44
|
|
|
45
|
-
If `planr agents list --json` shows routes with use-case `work_type` selectors (e.g. `frontend`, `backend`),
|
|
45
|
+
If `planr agents list --json` shows routes with use-case `work_type` selectors (e.g. `frontend`, `backend`), declare them in the plan's task list before building — `### TASK-00n (backend): ...` headings and `- [ ] (frontend) ...` items seed with that work type directly. For maps already built without annotations, retag (`planr item update <id> --work-type frontend`). Either way this is prep-agent work, never a question for the user.
|
|
46
46
|
|
|
47
47
|
## Store The Goal Contract
|
|
48
48
|
|
|
@@ -58,7 +58,7 @@ The loop never closes its own reviews when the host supports a second agent. Mak
|
|
|
58
58
|
|
|
59
59
|
## Skills Are The Prompts
|
|
60
60
|
|
|
61
|
-
When the host supports subagents, the driver never implements: it dispatches, audits, and synthesizes. Driver tokens go into `plan audit`, dispatch decisions, and conflict resolution — implementation and review run in the subagent roles, which the host wiring can pin to a cheaper tier (see the role files and `docs/GOALS.md` "Cost Tiering"). When the pick packet carries a `routing` block, dispatch on it: run the worker on the named profile's client and model, and move down the `fallbacks` chain when the primary hits a rate limit or is unavailable — the chain is ordered, so no mid-run registry edits. Workers report the profile they actually ran on (`done --profile <id>` or `PLANR_PROFILE`), so a host that silently overrode the pin shows up in `planr trace item` instead of staying invisible. Delegate with skill references plus an item id, nothing more:
|
|
61
|
+
When the host supports subagents, the driver never implements: it dispatches, audits, and synthesizes. Driver tokens go into `plan audit`, dispatch decisions, and conflict resolution — implementation and review run in the subagent roles, which the host wiring can pin to a cheaper tier (see the role files and `docs/GOALS.md` "Cost Tiering"). When the pick packet carries a `routing` block, dispatch on it: run the worker on the named profile's client and model, and move down the `fallbacks` chain when the primary hits a rate limit or is unavailable — the chain is ordered, so no mid-run registry edits. As the dispatching driver, read the packet with `planr pick --peek [--plan <id>]` — it returns the same packet without leasing, so the worker picks under its own identity and the maker/checker audit stays clean (never pick-and-release as the driver). Workers report the profile they actually ran on (`done --profile <id>` or `PLANR_PROFILE`), so a host that silently overrode the pin shows up in `planr trace item` instead of staying invisible. Delegate with skill references plus an item id, nothing more:
|
|
62
62
|
|
|
63
63
|
- Worker dispatch: `Use $planr-work on item <item-id>. Stop after requesting review.`
|
|
64
64
|
- Checker dispatch: `Use $planr-review on item <item-id>. Close the review with a verdict.`
|
|
@@ -53,15 +53,16 @@ A build plan must include:
|
|
|
53
53
|
|
|
54
54
|
## Route-Aware Tagging
|
|
55
55
|
|
|
56
|
-
Before
|
|
56
|
+
Before writing the task list, check whether the project declares model routing: `planr agents list --json`. If routes exist, their `work_type` selectors are the project's use-case vocabulary (e.g. `frontend`, `backend`, `design`) — and tagging is your job, not the user's; never ask a human to name work types.
|
|
57
57
|
|
|
58
|
-
|
|
59
|
-
|
|
60
|
-
|
|
61
|
-
|
|
58
|
+
Declare the use case in the task list itself — `map build` seeds annotated tasks with that work type directly:
|
|
59
|
+
|
|
60
|
+
```markdown
|
|
61
|
+
### TASK-001 (backend): REST API for todos
|
|
62
|
+
- [ ] (frontend) Build the form and list view
|
|
62
63
|
```
|
|
63
64
|
|
|
64
|
-
Match by the
|
|
65
|
+
Match by the task's actual work (UI/components/styling -> a `frontend` route, API/server/storage -> `backend`, and so on); unannotated tasks stay `code`, which the default route covers. For maps that were already built without annotations, retag instead: `planr item update <item-id> --work-type frontend`. The payoff: every pick packet then carries the right profile, model, and paired skill for its use case, so dispatch needs no human routing knowledge.
|
|
65
66
|
|
|
66
67
|
## Done
|
|
67
68
|
|
|
@@ -30,6 +30,8 @@ Live verification (browser flow, executed binary, real requests) gets its own lo
|
|
|
30
30
|
planr log add --item <item-id> --kind verification --summary "verified <flow>: <observed outcome>" --cmd "<exact command>"
|
|
31
31
|
```
|
|
32
32
|
|
|
33
|
+
The `--cmd` value must be copy-paste replayable: a real shell command (or a small script you committed), never a prose transcript like "start server; curl /; check stats". A reviewer replays your command verbatim — if it cannot run, the verification cannot be independently confirmed.
|
|
34
|
+
|
|
33
35
|
Log persistent evidence, not transient noise: a failure you immediately fixed belongs in the final log's narrative, not as a standalone failure log. Only record a failure separately when it blocks the item.
|
|
34
36
|
|
|
35
37
|
Evidence logging refreshes the heartbeat automatically — a separate `planr pick heartbeat` is only needed for long silent stretches without logs.
|