planr 1.2.0 → 1.3.0-alpha.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.
- package/README.md +25 -0
- package/docs/CLI_REFERENCE.md +4 -1
- package/docs/HOOKS.md +34 -0
- package/docs/fixtures/mcp-contract.json +2 -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/README.md
CHANGED
|
@@ -22,6 +22,30 @@ 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.2.0: Model Routing
|
|
26
|
+
|
|
27
|
+
Declare once which model handles which work — every task then carries its own routing, and your agents delegate automatically:
|
|
28
|
+
|
|
29
|
+
```toml
|
|
30
|
+
# .planr/agents.toml (write it with `planr agents init`)
|
|
31
|
+
[profiles.frontender]
|
|
32
|
+
client = "cursor"
|
|
33
|
+
model = "opus"
|
|
34
|
+
skill = "frontend-design"
|
|
35
|
+
|
|
36
|
+
[[routes]]
|
|
37
|
+
match = { work_type = "frontend" }
|
|
38
|
+
profile = "frontender"
|
|
39
|
+
fallbacks = ["driver"]
|
|
40
|
+
```
|
|
41
|
+
|
|
42
|
+
- **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.
|
|
43
|
+
- **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.
|
|
44
|
+
- **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.
|
|
45
|
+
- **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`.
|
|
46
|
+
|
|
47
|
+
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).
|
|
48
|
+
|
|
25
49
|
## Install
|
|
26
50
|
|
|
27
51
|
```bash
|
|
@@ -137,6 +161,7 @@ Mid-project work (a new feature, refactor, or fix on an existing project) works
|
|
|
137
161
|
- [Skills](docs/SKILLS.md)
|
|
138
162
|
- [Long-Running Goals](docs/GOALS.md)
|
|
139
163
|
- [Model Routing](docs/MODEL_ROUTING.md) · [Worked Example: Web App](docs/EXAMPLE_WEBAPP.md)
|
|
164
|
+
- [Host Hooks](docs/HOOKS.md)
|
|
140
165
|
- [CLI Reference](docs/CLI_REFERENCE.md)
|
|
141
166
|
- [MCP Guide](docs/MCP_GUIDE.md)
|
|
142
167
|
- [Codex](docs/CODEX.md) · [Claude Code](docs/CLAUDE_CODE.md) · [Cursor](docs/CURSOR.md)
|
package/docs/CLI_REFERENCE.md
CHANGED
|
@@ -30,6 +30,7 @@ planr item update <item-id> [--title "..."] [--description "..."] [--work-type <
|
|
|
30
30
|
# plan task lists can declare work types inline: `### TASK-001 (backend): ...` / `- [ ] (frontend) ...` seed map build directly
|
|
31
31
|
planr item route <item-id> [--set <profile>|--clear]
|
|
32
32
|
planr link add <from-item> <to-item> --type blocks
|
|
33
|
+
planr prime [--hook-json]
|
|
33
34
|
planr pick [--work-type <type>] [--plan <plan-id>] [--peek]
|
|
34
35
|
planr pick release <item-id> [--force]
|
|
35
36
|
planr pick heartbeat [item-id]
|
|
@@ -65,7 +66,7 @@ planr agents init --profile|--skill|--route|--default-route|--interactive
|
|
|
65
66
|
planr agents list [--json]
|
|
66
67
|
planr agents check
|
|
67
68
|
planr doctor [--client codex|claude|cursor|all]
|
|
68
|
-
planr install codex|claude|cursor [--dry-run] [--no-mcp] [--force]
|
|
69
|
+
planr install codex|claude|cursor [--dry-run] [--no-mcp] [--force] [--no-hooks]
|
|
69
70
|
planr prompt cli|mcp|http [--client codex|claude|cursor|all]
|
|
70
71
|
planr prompt routing [--client codex|claude|cursor|all]
|
|
71
72
|
planr mcp
|
|
@@ -127,6 +128,8 @@ With `--json`, responses follow one convention so agents never guess where data
|
|
|
127
128
|
|
|
128
129
|
`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.
|
|
129
130
|
|
|
131
|
+
`prime` prints the compact state block host hooks inject at session start and after context compaction (project, map counts, held items with log status, goal contract, registry presence, next command); `--hook-json` emits the Claude Code SessionStart envelope. In a repo without a Planr database it exits silently and creates nothing — hooks must never break a session. Installs wire it into the host's hook system by default (`--no-hooks` skips; existing hook files are merged additively, never overwritten). Full guide: [Host Hooks](HOOKS.md).
|
|
132
|
+
|
|
130
133
|
`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.
|
|
131
134
|
|
|
132
135
|
`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.
|
package/docs/HOOKS.md
ADDED
|
@@ -0,0 +1,34 @@
|
|
|
1
|
+
# Host Hooks
|
|
2
|
+
|
|
3
|
+
`planr install codex|claude|cursor` wires Planr into the host's native hook system **by default** — skip it with `--no-hooks`. The hooks solve one problem: loop state must survive the moments context is created or destroyed. Every new session and every context compaction gets the map state injected automatically via `planr prime`, so recovery stops being discipline and becomes mechanism.
|
|
4
|
+
|
|
5
|
+
## What gets installed
|
|
6
|
+
|
|
7
|
+
| Host | File | Events | Runs |
|
|
8
|
+
| --- | --- | --- | --- |
|
|
9
|
+
| Cursor | `.cursor/hooks.json` | `sessionStart` | `planr prime --cursor-json` |
|
|
10
|
+
| | | `subagentStop` | `.cursor/hooks/planr-evidence-guard.sh` |
|
|
11
|
+
| Claude Code | `.claude/settings.json` | `SessionStart` (matcher `startup\|resume\|compact`) | `planr prime --hook-json` |
|
|
12
|
+
| Codex CLI | `.codex/hooks.json` | `SessionStart` | `planr prime` |
|
|
13
|
+
|
|
14
|
+
`planr prime` prints one compact, bounded state block (project, map counts, your held items with log status, the goal contract, registry presence, and the next command) — deterministic and read-only. `--hook-json` wraps it in the Claude Code SessionStart envelope (`hookSpecificOutput.additionalContext`); `--cursor-json` emits Cursor's `additional_context` shape.
|
|
15
|
+
|
|
16
|
+
Only session-start events are wired, deliberately: they are the one place all three hosts inject hook output as context, and Claude's `compact` source plus post-compaction session starts cover the compaction case. Pre/post-compaction events (`preCompact`, `PreCompact`, `PostCompact`) cannot restore model context and are not used.
|
|
17
|
+
|
|
18
|
+
The evidence guard is advisory and identity-scoped: a Cursor subagent that stops while *its own* pick (matched via `PLANR_WORKER_ID`/`PLANR_SESSION_ID`) has no completion log gets one follow-up message naming the item and the two ways out (`planr done ...` or `planr pick release ...`). Without an explicit worker identity it stays silent rather than steering the wrong agent toward foreign items. It never blocks.
|
|
19
|
+
|
|
20
|
+
## Design rules
|
|
21
|
+
|
|
22
|
+
- **Fail open, always.** Every hook command ends in `|| true` with a 10-second timeout; a missing, broken, or uninitialized planr never blocks a session. In a repo without a Planr database, `planr prime` exits silently and creates nothing.
|
|
23
|
+
- **Additive merge, planr owns only its own entries.** Existing hook files keep every foreign entry; planr entries are reconciled on re-install (current ones untouched, outdated ones upgraded in place, entries under retired events removed) — so `planr install <client>` after an update also refreshes the hooks. A file planr cannot parse as a JSON object is left untouched with a note in the install output — add the snippet manually in that case.
|
|
24
|
+
- **Default, not mandatory.** `--no-hooks` skips hook installation entirely; deleting the planr entries from the hook files removes the behavior with no other effect.
|
|
25
|
+
|
|
26
|
+
## Codex trust model
|
|
27
|
+
|
|
28
|
+
Codex requires reviewing hooks before they run: after installing, open `/hooks` in the Codex TUI once and trust the planr entries. Codex records trust against the hook definition's hash, so if a future planr version changes the hook commands, Codex will ask again — that is the host working as intended.
|
|
29
|
+
|
|
30
|
+
## Removing hooks
|
|
31
|
+
|
|
32
|
+
Delete the planr entries from `.cursor/hooks.json` / `.claude/settings.json` / `.codex/hooks.json` (and `.cursor/hooks/planr-evidence-guard.sh`). Nothing else depends on them.
|
|
33
|
+
|
|
34
|
+
See also: [Model Routing](MODEL_ROUTING.md), [Goals](GOALS.md), [CLI Reference](CLI_REFERENCE.md).
|
|
@@ -88,6 +88,8 @@
|
|
|
88
88
|
"planr prompt routing",
|
|
89
89
|
"planr agents init",
|
|
90
90
|
"planr agents init --profile|--skill|--route|--default-route|--interactive",
|
|
91
|
+
"planr prime",
|
|
92
|
+
"planr install codex|claude|cursor [--dry-run] [--no-mcp] [--force] [--no-hooks]",
|
|
91
93
|
"planr mcp",
|
|
92
94
|
"planr review annotate",
|
|
93
95
|
"planr review ingest",
|
|
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.
|
|
4
|
+
"version": "1.3.0-alpha.1",
|
|
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.3.0-alpha.1",
|
|
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",
|