@chief-clancy/plan 0.4.1 → 0.4.2

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 CHANGED
@@ -101,9 +101,11 @@ sha256=d2c9f3a1b4e6c8f09123456789abcdef0123456789abcdef0123456789abcd
101
101
  approved_at=2026-04-08T22:30:00Z
102
102
  ```
103
103
 
104
- The full 64-character hex hash is what `.approved` actually stores — `/clancy:implement-from` (PR 8) reads the marker, hashes the current plan file the same way, and blocks implementation on any mismatch.
104
+ The full 64-character hex hash is what `.approved` actually stores — any plan-implementing tool reads the marker, hashes the current plan file the same way, and blocks implementation on any mismatch.
105
105
 
106
- The marker is the gate `/clancy:implement-from` (shipping in the next PR) checks before applying changes — if the plan file is edited after approval, the SHA mismatch blocks implementation until you re-approve. Clancy also tries to update the brief file's `<!-- planned:1,2 -->` marker to `<!-- approved:1 planned:1,2 -->` so `/clancy:plan --list` knows which rows are approved, but that brief-marker update is best-effort and may warn-and-skip if the expected brief metadata or matching marker is missing.
106
+ The marker is the gate plan-implementing tools check before applying changes — if the plan file is edited after approval, the SHA mismatch blocks implementation until you re-approve. A dedicated `/clancy:implement-from` slash command was originally scoped for the plan package but is **deferred** until `@chief-clancy/dev` is extracted (the slash command is convenience, not capability — Claude Code can already do the SHA gate + structured plan parse via natural-language instruction). In the meantime, you can apply approved plans by asking Claude Code directly — for example: `Implement .clancy/plans/add-dark-mode-2.md, verifying the .approved marker's sha256 first` — or by installing the full Clancy pipeline (`npx chief-clancy`) for the board-driven flow.
107
+
108
+ Clancy also tries to update the brief file's `<!-- planned:1,2 -->` marker to `<!-- approved:1 planned:1,2 -->` so `/clancy:plan --list` knows which rows are approved, but that brief-marker update is best-effort and may warn-and-skip if the expected brief metadata or matching marker is missing.
107
109
 
108
110
  ### Standalone+board (board credentials but no full pipeline)
109
111
 
package/package.json CHANGED
@@ -1,6 +1,6 @@
1
1
  {
2
2
  "name": "@chief-clancy/plan",
3
- "version": "0.4.1",
3
+ "version": "0.4.2",
4
4
  "private": false,
5
5
  "description": "Implementation planner for Claude Code — decompose briefs into actionable plans",
6
6
  "author": "Alex Clapperton",
@@ -2,7 +2,7 @@
2
2
 
3
3
  Approve a Clancy implementation plan. Behaviour depends on the install context and the argument:
4
4
 
5
- - **Local plan file:** `/clancy:approve-plan add-dark-mode-2` — write a `.clancy/plans/{stem}.approved` marker (with the plan's SHA-256 + approval timestamp) and update the source brief's row marker. The marker is the gate `/clancy:implement-from` checks before applying changes
5
+ - **Local plan file:** `/clancy:approve-plan add-dark-mode-2` — write a `.clancy/plans/{stem}.approved` marker (with the plan's SHA-256 + approval timestamp) and update the source brief's row marker. The marker is the gate any plan-implementing tool checks before applying changes (a dedicated `/clancy:implement-from` slash command is deferred until `@chief-clancy/dev` is extracted)
6
6
  - **Board ticket:** `/clancy:approve-plan PROJ-123` — promote an approved plan from a ticket comment to the ticket description, edit the plan comment with an approval note, swap the ticket labels (`CLANCY_LABEL_PLAN` → `CLANCY_LABEL_BUILD`, both with sensible defaults), and — only if `CLANCY_STATUS_PLANNED` is configured — transition the ticket status. Requires board credentials. Runs in both standalone+board and terminal modes (the full pipeline is not required for the board transport flow itself; it is only required for downstream `/clancy:implement` to consume the result)
7
7
  - **No argument:** auto-select the oldest unapproved plan. In standalone mode this scans `.clancy/plans/`; in standalone+board / terminal mode it scans `.clancy/progress.txt` for board tickets
8
8
 
@@ -4,7 +4,7 @@
4
4
 
5
5
  Approve a Clancy implementation plan. Behaviour depends on the install context:
6
6
 
7
- - **Standalone mode** (no `.clancy/.env`): write a local `.clancy/plans/{stem}.approved` marker file with the plan's SHA-256 and approval timestamp. The marker is the gate `/clancy:implement-from` checks before applying changes
7
+ - **Standalone mode** (no `.clancy/.env`): write a local `.clancy/plans/{stem}.approved` marker file with the plan's SHA-256 and approval timestamp. The marker is the gate any plan-implementing tool checks before applying changes (a dedicated `/clancy:implement-from` slash command is deferred until `@chief-clancy/dev` is extracted; users in the meantime ask Claude Code to apply the plan via natural-language instruction or install the full pipeline)
8
8
  - **Standalone+board mode** (`.clancy/.env` present, no full pipeline): with a board ticket key, run the existing comment-to-description transport flow; with a plan-file stem, write the local marker (board push lands in PR 9)
9
9
  - **Terminal mode** (full pipeline installed): existing behaviour — promote an approved plan from a ticket comment to the ticket description and transition the ticket to the implementation queue
10
10
 
@@ -360,7 +360,7 @@ After confirmation in plan-file stem mode, jump to Step 4a (local marker write).
360
360
 
361
361
  ## Step 4a — Write local marker
362
362
 
363
- Run this step instead of Steps 5, 5b, 6 when the resolved argument was a plan-file stem (standalone mode, or standalone+board / terminal mode where Step 2 found a matching plan file). Write a `.clancy/plans/{stem}.approved` marker that gates `/clancy:implement-from`.
363
+ Run this step instead of Steps 5, 5b, 6 when the resolved argument was a plan-file stem (standalone mode, or standalone+board / terminal mode where Step 2 found a matching plan file). Write a `.clancy/plans/{stem}.approved` marker that gates plan implementation (see "Marker is the gate for future implementation tooling" below for the deferral context).
364
364
 
365
365
  ### Compute the SHA-256
366
366
 
@@ -370,7 +370,7 @@ Run this step instead of Steps 5, 5b, 6 when the resolved argument was a plan-fi
370
370
  2. Compute the SHA-256 hash of those bytes — no normalisation (no line-ending fix, no trailing-whitespace strip, no BOM removal). Hex-encode lowercase.
371
371
  3. **Then** (only after the hash is computed) open the `.approved` marker for exclusive create as described below.
372
372
 
373
- The `.approved` file is **never** included in the hash — only `.clancy/plans/{stem}.md` is hashed, and only its on-disk byte content at the moment of step 1. PR 8's `/clancy:implement-from` re-reads the same plan file, hashes it the same way, and compares to the `sha256=` value stored in the marker. Any divergence (re-edit, line-ending change, trailing whitespace tweak) blocks implementation until re-approval.
373
+ The `.approved` file is **never** included in the hash — only `.clancy/plans/{stem}.md` is hashed, and only its on-disk byte content at the moment of step 1. The marker is designed so a future implementer (deferred to `@chief-clancy/dev`) can re-read the same plan file, hash it the same way, and compare to the `sha256=` value stored in the marker. Until that consumer ships, the gate is enforced manually: a user (or Claude Code via natural-language instruction) reads the marker, hashes the plan file, and refuses to apply the plan on mismatch. Any divergence (re-edit, line-ending change, trailing whitespace tweak) is detectable.
374
374
 
375
375
  ### Write the marker file with O_EXCL
376
376
 
@@ -381,7 +381,7 @@ sha256={hex sha256 of the plan file at approval time}
381
381
  approved_at={ISO 8601 UTC timestamp, e.g. 2026-04-08T22:30:00Z}
382
382
  ```
383
383
 
384
- Two `key=value` lines, each terminated with `\n`. No JSON, no extra whitespace, no comments. PR 8 parses this with a tolerant `^(sha256|approved_at)=(.+)$` regex per line.
384
+ Two `key=value` lines, each terminated with `\n`. No JSON, no extra whitespace, no comments. A future implementer (deferred to `@chief-clancy/dev`) will parse this with a tolerant `^(sha256|approved_at)=(.+)$` regex per line. Until that consumer ships, the format is also human-readable for ad-hoc verification.
385
385
 
386
386
  ### Handle EEXIST (already-approved)
387
387
 
@@ -397,9 +397,14 @@ To re-approve (e.g. after revising the plan):
397
397
 
398
398
  A `--fresh` flag for `/clancy:approve-plan` is not implemented in this release. Manual deletion is the supported re-approval path.
399
399
 
400
- ### Marker is the gate for /clancy:implement-from
400
+ ### Marker is the gate for future implementation tooling
401
401
 
402
- The `.approved` marker is the gate `/clancy:implement-from` checks before applying changes. PR 8 reads the marker, hashes the current plan file, and compares to the stored `sha256`. Match → proceed; mismatch → block with a "plan changed since approval" error. This is why the SHA must be computed over the plan file content (not just touched as an empty file).
402
+ The `.approved` marker is designed as the gate that any plan-implementing tool checks before applying changes. The conceptual flow: read the marker, hash the current plan file, compare to the stored `sha256`. Match → proceed; mismatch → block with a "plan changed since approval" error. This is why the SHA must be computed over the plan file content (not just touched as an empty file).
403
+
404
+ A dedicated `/clancy:implement-from` slash command is **deferred** until `@chief-clancy/dev` is extracted (the slash command is convenience, not capability — Claude Code can already do the SHA gate + structured plan parse via natural-language instruction). In the meantime, users apply approved plans by:
405
+
406
+ 1. Asking Claude Code to read the plan file directly: `Implement .clancy/plans/{stem}.md, verifying the .approved marker's sha256 first`
407
+ 2. Installing the full Clancy pipeline (`npx chief-clancy`) for the board-driven flow
403
408
 
404
409
  ### After writing the marker
405
410
 
@@ -1164,7 +1169,9 @@ Clancy — Approve Plan (local)
1164
1169
  Marker: .clancy/plans/{stem}.approved
1165
1170
  sha256: {first 12 hex chars}…
1166
1171
 
1167
- Next: /clancy:implement-from .clancy/plans/{stem}.md
1172
+ Next:
1173
+ • Ask Claude Code: "Implement .clancy/plans/{stem}.md (verify the .approved marker's sha256 first)"
1174
+ • Or run `npx chief-clancy` for the full board-driven pipeline
1168
1175
 
1169
1176
  "Book 'em, Lou."
1170
1177
  ```
@@ -1183,7 +1190,7 @@ Append to `.clancy/progress.txt`:
1183
1190
  YYYY-MM-DD HH:MM | {stem} | LOCAL_APPROVE_PLAN | sha256={first 12 hex}
1184
1191
  ```
1185
1192
 
1186
- The `LOCAL_APPROVE_PLAN` token mirrors the `LOCAL_PLAN` / `LOCAL_REVISED` convention used by `/clancy:plan --from` (see [`plan.md` Step 6](./plan.md)). PR 8's `/clancy:implement-from` does NOT scan progress.txt for approval state it reads the `.clancy/plans/{stem}.approved` marker directly. The log entry is for human audit only.
1193
+ The `LOCAL_APPROVE_PLAN` token mirrors the `LOCAL_PLAN` / `LOCAL_REVISED` convention used by `/clancy:plan --from` (see [`plan.md` Step 6](./plan.md)). The token is for human audit only any future plan-implementing tool reads the `.clancy/plans/{stem}.approved` marker directly rather than scanning `progress.txt` for approval state.
1187
1194
 
1188
1195
  ---
1189
1196
 
@@ -1105,9 +1105,9 @@ Scan `.clancy/plans/` for all `.md` files. For each file, parse the local plan h
1105
1105
  2. Marker exists. Read and validate its `sha256=` line (the marker body is two `key=value` lines: `sha256={hex}` and `approved_at={ISO 8601}`) AND hash the current plan file's bytes the same way `/clancy:approve-plan` Step 4a does (lowercase hex SHA-256, no normalisation, no line-ending fix)
1106
1106
  3. If the marker exists but is malformed, missing its `sha256=` line, has a non-hex or wrong-length `sha256` value, or otherwise cannot be parsed deterministically → `Stale (re-approve)` (verdict). Print a hint after the table: `Marker .clancy/plans/{plan-id}.approved is malformed. Delete it and re-run /clancy:approve-plan {plan-id} to recreate.` Folding this into `Stale` (rather than inventing a new state) keeps the inventory deterministic — the user's remediation is the same as for a hash drift: delete the marker and re-approve
1107
1107
  4. If the marker's valid `sha256` matches the current plan file's hash → `Approved` (verdict)
1108
- 5. If the marker exists and its valid `sha256` differs from the current hash → `Stale (re-approve)` (verdict) — the plan file was edited after approval. `/clancy:implement-from` (PR 8) will refuse to run against a stale plan until it is re-approved
1108
+ 5. If the marker exists and its valid `sha256` differs from the current hash → `Stale (re-approve)` (verdict) — the plan file was edited after approval. Any future plan-implementing tool will refuse to run against a stale plan until it is re-approved
1109
1109
 
1110
- A future `Implemented` state — derived from `LOCAL_IMPLEMENT` entries in `.clancy/progress.txt` — will be added by PR 8. Today the inventory shows three states (`Planned`, `Approved`, `Stale (re-approve)`), with malformed `.approved` markers folded into `Stale (re-approve)`; the table format is stable so PR 8's addition will be a one-line extension.
1110
+ A future `Implemented` state — derived from `LOCAL_IMPLEMENT` entries in `.clancy/progress.txt` — will land alongside the dedicated plan-implementing tool (deferred to `@chief-clancy/dev`). Today the inventory shows three states (`Planned`, `Approved`, `Stale (re-approve)`), with malformed `.approved` markers folded into `Stale (re-approve)`; the table format is stable so the future addition will be a one-line extension.
1111
1111
 
1112
1112
  A field is considered missing if the line is absent or its value is empty after the colon. Plans missing all expected fields are still listed (with `?` placeholders) so the user can find and clean them up.
1113
1113
 
@@ -645,9 +645,11 @@ describe('plan inventory step', () => {
645
645
  expect(content).toContain('plan file was edited after approval');
646
646
  });
647
647
 
648
- it('reserves an Implemented state for PR 8 without claiming it exists today', () => {
648
+ it('reserves an Implemented state for the deferred plan-implementing tool', () => {
649
649
  expect(content).toContain('Implemented');
650
- expect(content).toContain('PR 8');
650
+ expect(content).toMatch(
651
+ /deferred[\s\S]{0,120}(?:plan-implementing tool|future implementation tooling)|(?:plan-implementing tool|future implementation tooling)[\s\S]{0,120}deferred/i,
652
+ );
651
653
  expect(content).toContain('shows three states');
652
654
  });
653
655
 
@@ -853,9 +855,12 @@ describe('approve-plan local marker (Step 4a)', () => {
853
855
  expect(content).toContain('already approved');
854
856
  });
855
857
 
856
- it('explains the marker is the gate for /clancy:implement-from', () => {
857
- expect(content).toContain('/clancy:implement-from');
858
+ it('explains the marker is the gate for future implementation tooling', () => {
858
859
  expect(content).toContain('gate');
860
+ expect(content).toContain('future implementation tooling');
861
+ expect(content).toMatch(
862
+ /deferred[\s\S]{0,120}(?:plan-implementing tool|future implementation tooling)|(?:plan-implementing tool|future implementation tooling)[\s\S]{0,120}deferred/i,
863
+ );
859
864
  });
860
865
 
861
866
  it('after writing the marker, Step 4a jumps to Step 7 (log) and skips board flow', () => {
@@ -942,10 +947,10 @@ describe('approve-plan local-mode log + summary (Step 7)', () => {
942
947
  expect(content).toContain('sha256={first 12 hex}');
943
948
  });
944
949
 
945
- it('local success summary points to /clancy:implement-from', () => {
946
- expect(content).toContain(
947
- 'Next: /clancy:implement-from .clancy/plans/{stem}.md',
948
- );
950
+ it('local success summary points users at the deferred next-step paths', () => {
951
+ expect(content).toContain('Ask Claude Code:');
952
+ expect(content).toContain('Implement .clancy/plans/{stem}.md');
953
+ expect(content).toContain('npx chief-clancy');
949
954
  });
950
955
 
951
956
  it('preserves board-mode APPROVE_PLAN log entry', () => {