planrails 0.5.0 → 0.5.1

This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
package/CHANGELOG.md CHANGED
@@ -1,5 +1,39 @@
1
1
  # Changelog
2
2
 
3
+ ## 0.5.1 — 2026-09-13
4
+
5
+ A fresh-context review of 0.5.0, run the same day, found the block — the one copy
6
+ of the rule that survives into a real plan — weaker than §4, and wrong in one
7
+ case: it matched a holder by name, and a name changes (accepting a plan in Claude
8
+ Code's plan mode retitles the session; `claude -n` and a resume can rename it), so
9
+ a live holder could read as stale and be taken over. This repo's own plan hit it
10
+ within the hour.
11
+
12
+ - **The block matches by session id.** Its paragraph now says what the line holds
13
+ (name · first 8 characters of the session id · since), that the id is what to
14
+ match, which listing to run and what it shows, the three outcomes — stop; stale
15
+ only when the id is unlisted *and* no other session in the checkout is live;
16
+ write your own line on `doing` and on a takeover — and what to do without a
17
+ listing: git is the record. Step 1 of the loop puts the session on the line.
18
+ - **§4** matches the id over the whole listing before any directory filter (a
19
+ session can hold a plan from another directory), drops the last-activity
20
+ advice, and adds the no-listing rule and "a plan you wrote in this session
21
+ already names you"; §1 speaks of plans in the plural and who holds each; the
22
+ "Why" bullet names no private repository.
23
+ - The skill puts the listing first and no longer says "or plausibly does"; the
24
+ worked example's `CLAUDE.md` carries the held-by sentence; the template pin now
25
+ fails when the NOW line is lost or the paragraph leaves the block. 74 tests.
26
+ - **Existing 0.5.0 plans:** replace the block's last paragraph and its step 1 with
27
+ the template's.
28
+ - Field-tested on these files, with PLAN.md hashes recorded and each case's start
29
+ state committed: a holder renamed after the claim was written was recognised
30
+ by its id and left alone; a plan with no line, a dirty PLAN.md and a busy peer
31
+ stopped the newcomer; told to continue the second of two plans, a session
32
+ claimed only that one and left the held plan byte-identical; a stale claim
33
+ with nothing else live was taken over with a correctly written line, and the
34
+ plan finished by the loop. 0.5.0's field test ran the block pasted into a 0.4.1
35
+ planner: the block was tested, §4 was not; this one runs the shipped bytes.
36
+
3
37
  ## 0.5.0 — 2026-09-13
4
38
 
5
39
  One method change, paid for by a real collision. The reload line loads an active
package/PLANNER.md CHANGED
@@ -1,4 +1,4 @@
1
- <!-- planrails 0.5.0 -->
1
+ <!-- planrails 0.5.1 -->
2
2
  # The Planner
3
3
 
4
4
  You are about to plan a piece of work with a person, then help execute it so the
@@ -58,8 +58,9 @@ tell you what the repo already says.
58
58
  2. **List `docs/`** and read the ones this feature touches. Use sub-agents for
59
59
  long files so your own context stays clear. Record each relevant doc's path
60
60
  and one line of what it holds.
61
- 3. **Read `.project-management/`.** Read the active plan in full; list the
62
- finished ones by id only.
61
+ 3. **Read `.project-management/`.** Read in full the plan this session is
62
+ assigned the person names it; if one plan is active, that one — and list
63
+ the others by id, with who holds each (NOW's `session:` line).
63
64
  4. **Read the last ~20 commits** (`git log --oneline -20`) for how the code moves.
64
65
 
65
66
  **A sub-agent's finding is a lead, not a fact.** If it names a file and line, you
@@ -73,7 +74,7 @@ READY — <project name>
73
74
  Stack: <language, framework, package manager>
74
75
  Always-on: <CLAUDE.md | AGENTS.md | README.md>
75
76
  Check: <the check command> Test: <the test command>
76
- Plans: <existing plan ids; which is active, or "none">
77
+ Plans: <existing plan ids; which are active and who holds each, or "none">
77
78
  Docs: <relevant doc paths, or "none">
78
79
  Touches: <the folders this feature will change>
79
80
  Questions: <up to 4 things the repo did not answer, or "none">
@@ -177,23 +178,30 @@ which plan you are on, or none. Before any task goes `doing` — even when the
177
178
  person just asked you to continue; they can forget which window holds the plan —
178
179
  re-read that line from disk (your reloaded copy may be older than the file), list
179
180
  the live sessions, and run `git status --short`. `claude agents --json` lists every
180
- live session on the machine: `name`, `sessionId`, `cwd`, `pid`, `status` (`busy`,
181
- `idle`, or `waiting` for the person) and `startedAt`; `--cwd <dir>` keeps those
182
- started under a directory, and a headless `claude -p` run is listed too. In Claude
183
- Code, `ListAgents` names you and the peers, but its bracketed ref is not the
184
- session id; the id is `$CLAUDE_CODE_SESSION_ID`. An entry changes on status, not
185
- on edits: last activity is the plan's `updated:` stamp or its transcript's mtime
186
- under `~/.claude/projects/`. Then decide:
187
-
188
- - The line names you: go on.
189
- - It names a live session that is not you: stop. Busy is mid-task; idle is between
190
- turns and still the holder; waiting means it needs the person — tell them.
191
- - It names a session the listing lacks: say so. No other live session in this
192
- checkout: take over, write your claim. One is: stop; the id tells whether it is
193
- that conversation resumed under a new name.
181
+ live session on the machine — an interactive one with `name`, `sessionId`, `cwd`,
182
+ `pid`, `status` (`busy`, `idle`, or `waiting` for the person) and `startedAt`; a
183
+ background one with `state` and a headless `claude -p` run is listed too. Match
184
+ the line's id against `sessionId` over the whole listing; `cwd` then tells which
185
+ peers are in this checkout. Never filter by directory before matching the id: a
186
+ session can hold a plan from another directory. Names are for people: accepting
187
+ a plan in Claude Code's plan mode retitles the session, `claude -n` and a resume
188
+ can rename it. In Claude Code, `ListAgents` names you and the peers, but its
189
+ bracketed ref is not the session id; the id is `$CLAUDE_CODE_SESSION_ID`. Then
190
+ decide:
191
+
192
+ - The line's id is yours, whatever your name is now: go on. A plan you wrote in
193
+ this session already names you.
194
+ - Its id is live and not yours: stop. Busy is mid-task; idle is between turns
195
+ and still the holder; waiting means it needs the person — tell them.
196
+ - Its id is not listed: the claim is stale only when no other session in this
197
+ checkout is live — then say so, take over, write your claim. When one is live,
198
+ stop and ask; it may be the holder under a new id, after a branch or a fork.
194
199
  - `none`, or no line (an older plan): a busy session in this checkout, or plan
195
200
  files dirty in `git status`: stop. Otherwise say what you saw in one line, write
196
201
  your claim, go on.
202
+ - No `claude` command (another agent), or a plan shared across machines: there is
203
+ no listing to consult. Git is the record: pull first, read a `doing` row with a
204
+ fresh `updated:` stamp as someone's work in flight, and ask.
197
205
  - A worktree is another checkout with its own copy of the plan: a merge concern
198
206
  later, not a clobber now. A sub-agent you briefed never runs this check; it
199
207
  never writes the plan.
@@ -279,9 +287,9 @@ the task `blocked` with the reason, and stop. Do not hand-fix state to look done
279
287
  3. **Update the docs** the work changed — in the same step, per the project's
280
288
  documentation guide if it has one.
281
289
  4. **Retire the plan.** Set its header to `status: done` and NOW's `session:` to
282
- `none`, then wrap its reload line in backticks, or delete it. Do not move a bare `@` line under a
283
- "Finished" heading: it still imports, and every retired plan would reload
284
- forever. The status comes first: the checker holds an `active` plan to its
290
+ `none`, then wrap its reload line in backticks, or delete it. Do not move a
291
+ bare `@` line under a "Finished" heading: it still imports, and every retired
292
+ plan would reload forever. The status comes first: the checker holds an `active` plan to its
285
293
  reload line. The plan files stay on disk; they are the record.
286
294
  5. **Graduate any lasting learning.** A learning that is true beyond this feature
287
295
  moves to the always-loaded file (`CLAUDE.md` / `AGENTS.md`), so it outlives the
@@ -322,12 +330,13 @@ Each line here was paid for by a real failure in earlier planning systems:
322
330
  path a reader cannot open is worse than none.
323
331
  - **The `session:` line and the check before `doing`** exist because the reload
324
332
  line loads a plan into every session opened in a checkout, not only the one
325
- working it. On 2026-09-13 in edodo-video, a second session, opened for a
326
- planrails upgrade, read the reloaded plan, was told "continue with T5",
327
- committed, and was starting T5b while the first session was mid-edit on the
328
- same files and the same PLAN.md; the owner interrupted. The person had asked,
329
- so the check runs even then. The claim is a lead and the live listing decides,
330
- so a stale line from a closed terminal blocks nobody.
333
+ working it. On 2026-09-13, a second session in one repo, opened for a tool
334
+ upgrade, read the reloaded plan, was told to continue, committed, and was
335
+ starting the next task while the first session was mid-edit on the same files
336
+ and the same PLAN.md; the owner interrupted. The person had asked, so the check
337
+ runs even then. The claim is a lead and the live listing decides, so a stale
338
+ line from a closed terminal blocks nobody — and it is matched by session id,
339
+ because the same day a session's name changed within the hour.
331
340
  - **Nothing the method needs is installed.** `npx planrails init` only copies two
332
341
  files, and you can copy them by hand instead. The old version was a heavy
333
342
  package, and that is what broke on the projects that were not npm — Python,
@@ -360,7 +369,7 @@ session: <none, or the session working this plan: name · the first 8 characters
360
369
 
361
370
  ## How to work this plan
362
371
  Read NOW, then Rules and Learnings; do not re-read Context. One task at a time:
363
- 1. Set it `doing`; point NOW at it.
372
+ 1. Set it `doing`; point NOW at it; put your session on its `session:` line.
364
373
  2. Do the work: fix causes, not symptoms; the simplest change that works end to end.
365
374
  3. Run the proof now. Paste `YYYY-MM-DD HH:MM · exit N · "last line"` into evidence. Every stamp comes from `date` run at that moment, never typed from memory.
366
375
  4. `done` only if N is 0. Point NOW at the next task; append an entry to LOG.md: did, files, proof, next, learned.
@@ -368,7 +377,7 @@ Read NOW, then Rules and Learnings; do not re-read Context. One task at a time:
368
377
 
369
378
  NOW is four lines for a stranger; on a long task note the sub-step, and update it before any turn ends. Blocked: say so in NOW, reason in the evidence cell. A task you will not do is `dropped`; its row stays. After a compaction, `git status --short` shows the in-flight work. Edit this file with the editor or a quoted heredoc; an unquoted shell string eats backticks. A self-contained task may go to a sub-agent briefed with its row, Rules, Decisions, Learnings and Context; it writes to a named file and reports a few lines, which are leads; you run the proof before pasting evidence. If the project runs Node, `node .project-management/planrails/check-plans.mjs` must pass. Full method: `.project-management/planrails/PLANNER.md` §4.
370
379
 
371
- The `session:` line names the one session working this plan. Before any task goes `doing`, even when asked to continue: re-read NOW from disk, run `claude agents --json` (in Claude Code, `ListAgents` names you) and `git status --short`. If the line names a live session that is not you, or says `none` while another session in this checkout is busy or plan files are dirty: stop, report what you found, and ask before writing to the plan, its files, or a commit. A named session the listing lacks is stale: say so, take over. Other reloaded plans are context; work only the one assigned in this session, and say which.
380
+ The `session:` line names the one session working this plan: name · first 8 characters of its session id · since. Match by id; names change. `claude agents --json` lists every live session on this machine with `sessionId`, `cwd` and `status`; in Claude Code your id is `$CLAUDE_CODE_SESSION_ID`. Before any task goes `doing`, even when asked to continue: re-read NOW from disk, run that listing and `git status --short`. Stop, report what you found, and ask before writing to the plan, its files, or a commit if the line's id is live and not yours, or if the line is `none` or missing while another session in this checkout is busy or plan files are dirty. If the id is not listed and no other session in this checkout is live, the claim is stale: say so, take over. On `doing` and on a takeover, write your own name · id · since, from `date`. Without a `claude` command, or on another machine, git is the record: pull first, treat a fresh `doing` row as someone's work in flight, and ask. Other reloaded plans are context; work only the one assigned in this session, and say which.
372
381
 
373
382
  ## Goal
374
383
  <4–5 sentences: what we are building and why. What is true when it ships. A mermaid diagram only if the architecture is non-trivial.>
package/README.md CHANGED
@@ -96,7 +96,7 @@ planner method does not depend on any language.
96
96
 
97
97
  ### As a `/planrails` command in Claude Code
98
98
 
99
- Copy [`skill/`](skill) to `~/.claude/skills/planrails/`. Then `/planrails` starts
99
+ Copy [`skill/`](https://github.com/vivmagarwal/planrails/tree/main/skill) to `~/.claude/skills/planrails/`. Then `/planrails` starts
100
100
  the same flow in any project that has run `npx planrails init` — the skill reads
101
101
  the project's own copy of `PLANNER.md`, so every project follows the version it
102
102
  has. (It is not called `/plan`, because Claude Code has a `/plan` of its own.)
@@ -199,8 +199,8 @@ it. One plan per session, one session per plan; the other reloaded plans are
199
199
  context. The claim is a lead, not a lock: a line left by a closed terminal blocks
200
200
  nobody, and the checker ignores the line. Field-tested with headless sessions: a
201
201
  second session told "Continue the active plan." stopped and asked while the first
202
- was live, took over when it was gone, and touched only the plan it was given when
203
- two were active.
202
+ was live — by its id, after the first had been renamed took over when it was
203
+ gone, and touched only the plan it was given when two were active.
204
204
 
205
205
  ## History
206
206
 
package/package.json CHANGED
@@ -1,6 +1,6 @@
1
1
  {
2
2
  "name": "planrails",
3
- "version": "0.5.0",
3
+ "version": "0.5.1",
4
4
  "description": "Plans that survive a lost session, and \"done\" that means done. A planner prompt and a tiny checker.",
5
5
  "type": "module",
6
6
  "license": "MIT",
@@ -1,5 +1,5 @@
1
1
  #!/usr/bin/env node
2
- // planrails 0.5.0
2
+ // planrails 0.5.1
3
3
  /**
4
4
  * check-plans — the machine-checked rails of the planner.
5
5
  *