planning-with-files 3.20.7 → 3.23.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 +70 -61
- package/SKILL.md +4 -2
- package/package.json +1 -1
- package/scripts/attest-plan.sh +62 -13
- package/scripts/check-complete.ps1 +2 -0
- package/scripts/check-complete.sh +3 -0
- package/scripts/init-session.ps1 +4 -2
- package/scripts/set-active-plan.ps1 +76 -5
package/README.md
CHANGED
|
@@ -1,5 +1,5 @@
|
|
|
1
1
|
<div align="center">
|
|
2
|
-
<img src="https://raw.githubusercontent.com/OthmanAdi/planning-with-files/v3.
|
|
2
|
+
<img src="https://raw.githubusercontent.com/OthmanAdi/planning-with-files/v3.23.0/media/pwf-banner-v5.webp" alt="PWF: Every task. Every step. Three planning files on a brass-inlaid base beneath an engraved arch" width="100%">
|
|
3
3
|
</div>
|
|
4
4
|
|
|
5
5
|
<h1 align="center">
|
|
@@ -30,9 +30,9 @@ Persistent file-based planning for AI coding agents and long-running agent tasks
|
|
|
30
30
|
</p>
|
|
31
31
|
|
|
32
32
|
<p align="center">
|
|
33
|
-
<a href="https://github.com/OthmanAdi/planning-with-files/blob/v3.
|
|
34
|
-
<a href="https://github.com/OthmanAdi/planning-with-files/blob/v3.
|
|
35
|
-
<a href="https://github.com/OthmanAdi/planning-with-files/blob/v3.
|
|
33
|
+
<a href="https://github.com/OthmanAdi/planning-with-files/blob/v3.23.0/docs/evals.md"><img src="https://img.shields.io/badge/benchmark-96.7%25_pass_(29%2F30)-2da44e?style=flat" alt="Benchmark: 96.7 percent assertion pass rate with skill"></a>
|
|
34
|
+
<a href="https://github.com/OthmanAdi/planning-with-files/blob/v3.23.0/docs/evals.md"><img src="https://img.shields.io/badge/blind_A%2FB-3%2F3_wins-2da44e?style=flat" alt="Blind A/B: 3 of 3 wins"></a>
|
|
35
|
+
<a href="https://github.com/OthmanAdi/planning-with-files/blob/v3.23.0/LICENSE"><img src="https://img.shields.io/github/license/OthmanAdi/planning-with-files?style=flat" alt="MIT license"></a>
|
|
36
36
|
</p>
|
|
37
37
|
|
|
38
38
|
<p align="center">
|
|
@@ -45,7 +45,7 @@ Persistent file-based planning for AI coding agents and long-running agent tasks
|
|
|
45
45
|
</p>
|
|
46
46
|
|
|
47
47
|
<p align="center">
|
|
48
|
-
<sub>Proof, comparisons and the repository reference are <a href="#reference">further down</a> · <a href="https://github.com/OthmanAdi/planning-with-files/blob/v3.
|
|
48
|
+
<sub>Proof, comparisons and the repository reference are <a href="#reference">further down</a> · <a href="https://github.com/OthmanAdi/planning-with-files/blob/v3.23.0/docs/installation.md">Full install guide</a></sub>
|
|
49
49
|
</p>
|
|
50
50
|
|
|
51
51
|
|
|
@@ -55,7 +55,7 @@ Persistent file-based planning for AI coding agents and long-running agent tasks
|
|
|
55
55
|
npx skills add OthmanAdi/planning-with-files --skill planning-with-files -g
|
|
56
56
|
```
|
|
57
57
|
|
|
58
|
-
All install methods: [docs/installation.md](https://github.com/OthmanAdi/planning-with-files/blob/v3.
|
|
58
|
+
All install methods: [docs/installation.md](https://github.com/OthmanAdi/planning-with-files/blob/v3.23.0/docs/installation.md).
|
|
59
59
|
|
|
60
60
|
---
|
|
61
61
|
|
|
@@ -64,7 +64,7 @@ All install methods: [docs/installation.md](https://github.com/OthmanAdi/plannin
|
|
|
64
64
|
Every coding agent loses its working memory when the context window resets. The plan does not have to die with it.
|
|
65
65
|
|
|
66
66
|
<p align="center">
|
|
67
|
-
<a href="https://github.com/OthmanAdi/planning-with-files/blob/v3.
|
|
67
|
+
<a href="https://github.com/OthmanAdi/planning-with-files/blob/v3.23.0/media/pwf-context-story-v1.mp4"><img src="https://raw.githubusercontent.com/OthmanAdi/planning-with-files/v3.23.0/media/pwf-context-story-v1.gif" alt="Illustrated workflow: planning files preserve the task state through a context reset" width="760"></a>
|
|
68
68
|
</p>
|
|
69
69
|
|
|
70
70
|
## Built for long-running agent tasks
|
|
@@ -141,7 +141,7 @@ npx skills add OthmanAdi/planning-with-files --skill planning-with-files-zht -g
|
|
|
141
141
|
|
|
142
142
|
These are real translations, not an English body with a translated description: the SKILL.md prose, the templates, and the user-facing output of `check-complete`, `init-session` and `session-catchup` are all localized. The status tokens stay literal English (`**Status:** complete`) on purpose, because `check-complete.sh` matches them with `grep -F`, so translating them would disable the completion gate.
|
|
143
143
|
|
|
144
|
-
Since v3.10.0 the variants also ship the full script surface: attestation, the Stop gate, the ledger, phase status and plan-doctor used to be canonical-only, which quietly made every non-English install a subset install. Full details, including what changed on the plugin route in v3.11.0, are in [docs/languages.md](https://github.com/OthmanAdi/planning-with-files/blob/v3.
|
|
144
|
+
Since v3.10.0 the variants also ship the full script surface: attestation, the Stop gate, the ledger, phase status and plan-doctor used to be canonical-only, which quietly made every non-English install a subset install. Full details, including what changed on the plugin route in v3.11.0, are in [docs/languages.md](https://github.com/OthmanAdi/planning-with-files/blob/v3.23.0/docs/languages.md).
|
|
145
145
|
|
|
146
146
|
They live under `skills/i18n/`, one directory deeper than the canonical skill. The install commands above are unchanged, because `npx skills add` resolves `--skill` by skill name across the whole repository. The Claude Code plugin scan reads `skills/*/SKILL.md` without recursing, so the plugin route registers the canonical skill alone and no longer carries five extra descriptions in every session's system prompt. On that route the `/plan-ar`, `/plan-de`, `/plan-es`, `/plan-zh` and `/plan-zht` commands read the translated skill from disk instead of invoking it by name.
|
|
147
147
|
|
|
@@ -152,18 +152,18 @@ They live under `skills/i18n/`, one directory deeper than the canonical skill. T
|
|
|
152
152
|
|
|
153
153
|
| IDE | Installation Guide | Integration |
|
|
154
154
|
|-----|-------------------|-------------|
|
|
155
|
-
| Claude Code | [Installation](https://github.com/OthmanAdi/planning-with-files/blob/v3.
|
|
156
|
-
| Cursor | [Cursor Setup](https://github.com/OthmanAdi/planning-with-files/blob/v3.
|
|
157
|
-
| GitHub Copilot | [Copilot Setup](https://github.com/OthmanAdi/planning-with-files/blob/v3.
|
|
158
|
-
| Mastra Code | [Mastra Setup](https://github.com/OthmanAdi/planning-with-files/blob/v3.
|
|
159
|
-
| Gemini CLI | [Gemini Setup](https://github.com/OthmanAdi/planning-with-files/blob/v3.
|
|
160
|
-
| Kiro | [Kiro Setup](https://github.com/OthmanAdi/planning-with-files/blob/v3.
|
|
161
|
-
| Codex | [Codex Setup](https://github.com/OthmanAdi/planning-with-files/blob/v3.
|
|
162
|
-
| Hermes Agent | [Hermes Setup](https://github.com/OthmanAdi/planning-with-files/blob/v3.
|
|
163
|
-
| CodeBuddy | [CodeBuddy Setup](https://github.com/OthmanAdi/planning-with-files/blob/v3.
|
|
164
|
-
| FactoryAI Droid | [Factory Setup](https://github.com/OthmanAdi/planning-with-files/blob/v3.
|
|
165
|
-
| OpenCode | [OpenCode Setup](https://github.com/OthmanAdi/planning-with-files/blob/v3.
|
|
166
|
-
| DeepSeek Harness | [DeepSeek Harness Setup](https://github.com/OthmanAdi/planning-with-files/blob/v3.
|
|
155
|
+
| Claude Code | [Installation](https://github.com/OthmanAdi/planning-with-files/blob/v3.23.0/docs/installation.md) | Plugin + SKILL.md + Hooks |
|
|
156
|
+
| Cursor | [Cursor Setup](https://github.com/OthmanAdi/planning-with-files/blob/v3.23.0/docs/cursor.md) | Skills + [hooks.json](https://cursor.com/docs/hooks) |
|
|
157
|
+
| GitHub Copilot | [Copilot Setup](https://github.com/OthmanAdi/planning-with-files/blob/v3.23.0/docs/copilot.md) | [Hooks](https://docs.github.com/en/copilot/reference/hooks-configuration) (incl. errorOccurred) |
|
|
158
|
+
| Mastra Code | [Mastra Setup](https://github.com/OthmanAdi/planning-with-files/blob/v3.23.0/docs/mastra.md) | Skills + [Hooks](https://mastra.ai/docs/mastra-code/configuration) |
|
|
159
|
+
| Gemini CLI | [Gemini Setup](https://github.com/OthmanAdi/planning-with-files/blob/v3.23.0/docs/gemini.md) | Skills + [Hooks](https://geminicli.com/docs/hooks/) |
|
|
160
|
+
| Kiro | [Kiro Setup](https://github.com/OthmanAdi/planning-with-files/blob/v3.23.0/docs/kiro.md) | [Agent Skills](https://kiro.dev/docs/skills/) |
|
|
161
|
+
| Codex | [Codex Setup](https://github.com/OthmanAdi/planning-with-files/blob/v3.23.0/docs/codex.md) | [Skills + Hooks](https://developers.openai.com/codex/skills) |
|
|
162
|
+
| Hermes Agent | [Hermes Setup](https://github.com/OthmanAdi/planning-with-files/blob/v3.23.0/docs/hermes.md) | Skill + native plugin (tools, `/pwf`, `pre_llm_call`, `post_tool_call`, `pre_verify` gate), CLI and Desktop |
|
|
163
|
+
| CodeBuddy | [CodeBuddy Setup](https://github.com/OthmanAdi/planning-with-files/blob/v3.23.0/docs/codebuddy.md) | [Skills + Hooks](https://www.codebuddy.ai/docs/cli/skills) |
|
|
164
|
+
| FactoryAI Droid | [Factory Setup](https://github.com/OthmanAdi/planning-with-files/blob/v3.23.0/docs/factory.md) | [Skills + Hooks](https://docs.factory.ai/cli/configuration/skills) |
|
|
165
|
+
| OpenCode | [OpenCode Setup](https://github.com/OthmanAdi/planning-with-files/blob/v3.23.0/docs/opencode.md) | Native plugin `opencode-planning-with-files` (`chat.message` injection, write reminders, compaction flush, `session.idle` gate, `pwf_*` tools, `/pwf` commands) + skill |
|
|
166
|
+
| DeepSeek Harness | [DeepSeek Harness Setup](https://github.com/OthmanAdi/planning-with-files/blob/v3.23.0/docs/deepseek-harness.md) | Native plugin `dsh-planning-with-files` (`agent/pre-step` injection, write reminders, post-compaction restore, `agent/turn-stopping` gate, `pwf_*` tools, `/pwf` commands) + skill |
|
|
167
167
|
|
|
168
168
|
</details>
|
|
169
169
|
|
|
@@ -172,13 +172,13 @@ They live under `skills/i18n/`, one directory deeper than the canonical skill. T
|
|
|
172
172
|
|
|
173
173
|
| IDE | Installation Guide | Skill Discovery Path |
|
|
174
174
|
|-----|-------------------|---------------------|
|
|
175
|
-
| Continue | [Continue Setup](https://github.com/OthmanAdi/planning-with-files/blob/v3.
|
|
176
|
-
| Pi Agent | [Pi Agent Setup](https://github.com/OthmanAdi/planning-with-files/blob/v3.
|
|
177
|
-
| OpenClaw | [OpenClaw Setup](https://github.com/OthmanAdi/planning-with-files/blob/v3.
|
|
178
|
-
| Autohand Code | [Autohand Code Setup](https://github.com/OthmanAdi/planning-with-files/blob/v3.
|
|
179
|
-
| Antigravity | [Antigravity Setup](https://github.com/OthmanAdi/planning-with-files/blob/v3.
|
|
180
|
-
| Kilocode | [Kilocode Setup](https://github.com/OthmanAdi/planning-with-files/blob/v3.
|
|
181
|
-
| AdaL CLI (Sylph AI) | [AdaL Setup](https://github.com/OthmanAdi/planning-with-files/blob/v3.
|
|
175
|
+
| Continue | [Continue Setup](https://github.com/OthmanAdi/planning-with-files/blob/v3.23.0/docs/continue.md) | `.continue/skills/` + [.prompt files](https://docs.continue.dev/customize/deep-dives/prompts) |
|
|
176
|
+
| Pi Agent | [Pi Agent Setup](https://github.com/OthmanAdi/planning-with-files/blob/v3.23.0/docs/pi-agent.md) | `.pi/skills/` ([npm package](https://www.npmjs.com/package/@mariozechner/pi-coding-agent)) |
|
|
177
|
+
| OpenClaw | [OpenClaw Setup](https://github.com/OthmanAdi/planning-with-files/blob/v3.23.0/docs/openclaw.md) | `.openclaw/skills/` ([docs](https://docs.openclaw.ai/tools/skills)) |
|
|
178
|
+
| Autohand Code | [Autohand Code Setup](https://github.com/OthmanAdi/planning-with-files/blob/v3.23.0/docs/autohand.md) | `~/.autohand/skills/` or `.autohand/skills/` |
|
|
179
|
+
| Antigravity | [Antigravity Setup](https://github.com/OthmanAdi/planning-with-files/blob/v3.23.0/docs/antigravity.md) | `.agent/skills/` ([docs](https://codelabs.developers.google.com/getting-started-with-antigravity-skills)) |
|
|
180
|
+
| Kilocode | [Kilocode Setup](https://github.com/OthmanAdi/planning-with-files/blob/v3.23.0/docs/kilocode.md) | `.kilocode/skills/` ([docs](https://kilo.ai/docs/agent-behavior/skills)) |
|
|
181
|
+
| AdaL CLI (Sylph AI) | [AdaL Setup](https://github.com/OthmanAdi/planning-with-files/blob/v3.23.0/docs/adal.md) | `.adal/skills/` ([docs](https://docs.sylph.ai/features/plugins-and-skills)) |
|
|
182
182
|
|
|
183
183
|
> **Note:** If your IDE uses the legacy Rules system instead of Skills, see the [`legacy-rules-support`](https://github.com/OthmanAdi/planning-with-files/tree/legacy-rules-support) branch.
|
|
184
184
|
|
|
@@ -189,7 +189,7 @@ They live under `skills/i18n/`, one directory deeper than the canonical skill. T
|
|
|
189
189
|
|
|
190
190
|
| Runtime | Status | Guide | Notes |
|
|
191
191
|
|---------|--------|-------|-------|
|
|
192
|
-
| BoxLite | ✅ Documented | [BoxLite Setup](https://github.com/OthmanAdi/planning-with-files/blob/v3.
|
|
192
|
+
| BoxLite | ✅ Documented | [BoxLite Setup](https://github.com/OthmanAdi/planning-with-files/blob/v3.23.0/docs/boxlite.md) | Run Claude Code + planning-with-files inside hardware-isolated micro-VMs |
|
|
193
193
|
|
|
194
194
|
> BoxLite is a sandbox runtime, not an IDE. Skills load via [ClaudeBox](https://github.com/boxlite-ai/claudebox), BoxLite's official Claude Code integration layer.
|
|
195
195
|
|
|
@@ -223,7 +223,7 @@ They are complementary stages, not alternatives. Plan mode is where you design a
|
|
|
223
223
|
|
|
224
224
|
### What happens to the plan files after a task is complete?
|
|
225
225
|
|
|
226
|
-
They are working memory, not a tracked deliverable. `task_plan.md`, `findings.md`, `progress.md`, and the `.planning/` directory are gitignored by default and are not archived automatically: the next task overwrites the root plan, and a slug directory just stops being active. Anything worth keeping should be promoted into code, a commit, or a doc. See [After Completion: What Happens to the Plan Files](https://github.com/OthmanAdi/planning-with-files/blob/v3.
|
|
226
|
+
They are working memory, not a tracked deliverable. `task_plan.md`, `findings.md`, `progress.md`, and the `.planning/` directory are gitignored by default and are not archived automatically: the next task overwrites the root plan, and a slug directory just stops being active. Anything worth keeping should be promoted into code, a commit, or a doc. See [After Completion: What Happens to the Plan Files](https://github.com/OthmanAdi/planning-with-files/blob/v3.23.0/docs/workflow.md#after-completion-what-happens-to-the-plan-files) for the full lifecycle and how to retain a completed plan. This is a deliberate default, not a missing feature; a completion-triggered archive step is a welcome opt-in extension.
|
|
227
227
|
|
|
228
228
|
### How fast are the hooks?
|
|
229
229
|
|
|
@@ -238,6 +238,10 @@ One hook fire measures 289ms wall-clock since the v3.6.0 optimization, down from
|
|
|
238
238
|
|
|
239
239
|
| Version | Highlights |
|
|
240
240
|
|---------|------------|
|
|
241
|
+
| **v3.23.0** | Public file-only recovery fixture with separate trial arms (#303). DSH V4 message-source compatibility (#306), resolver-based manual workflows (#300), and accurate Codex opt-out documentation (#302). |
|
|
242
|
+
| **v3.22.0** | OpenCode 2 support with native plugin registration, context injection, planning tools and the completion gate. OpenCode 1 remains supported; moved v2 sessions follow their current project (#298). |
|
|
243
|
+
| **v3.21.0** | Explicit root and named attestation targets preserve active selection and project containment (#296). PowerShell initialization retries the concurrent pointer pre-check race with bounded, validated attempts (#294). |
|
|
244
|
+
| **v3.20.8** | Claude Code sessions without a plan no longer end every reply with a Stop notice (#288). Cursor hooks move to the current schema with `sessionStart` injection (#262), Gemini CLI hooks inject through `BeforeAgent` and `AfterTool` `hookSpecificOutput` (#292), and both adapters' hook scripts are now executable on macOS and Linux; the Cursor stop hook stays silent once every phase is complete. PowerShell pointer replacement recovers or removes only its own `ReplaceFile` backup (#254). |
|
|
241
245
|
| **v3.20.7** | Fixes npm capability disclosure metadata and three unavailable contributor portrait endpoints. The npm package continues to ship the canonical skill and full repository README. |
|
|
242
246
|
| **v3.20.6** | Phase-status writers claim one lock owner even with Windows-native `mkdir` (#282). OpenCode, DSH and Hermes safely replace linked active pointers (#283, #284). PowerShell named plans reject read-only pointers before creation (#285), work under bracketed paths (#286), and retry transient concurrent pointer writes and inspection races (#287). The remaining `ReplaceFile` artifact case stays open in #254. |
|
|
243
247
|
| **v3.20.5** | OpenCode replay tolerates malformed parts (#273). Initialization reports attestation failures accurately (#277), analytics plans include Next Step (#279), and PowerShell denied writes fail without activating an incomplete named plan (#280). |
|
|
@@ -326,7 +330,7 @@ One hook fire measures 289ms wall-clock since the v3.6.0 optimization, down from
|
|
|
326
330
|
| **v2.7.0** | Gemini CLI support |
|
|
327
331
|
| **v2.2.0** | Session recovery, Windows PowerShell, OS-aware hooks |
|
|
328
332
|
|
|
329
|
-
[View all releases](https://github.com/OthmanAdi/planning-with-files/releases) · [CHANGELOG](https://github.com/OthmanAdi/planning-with-files/blob/v3.
|
|
333
|
+
[View all releases](https://github.com/OthmanAdi/planning-with-files/releases) · [CHANGELOG](https://github.com/OthmanAdi/planning-with-files/blob/v3.23.0/CHANGELOG.md)
|
|
330
334
|
|
|
331
335
|
> Parallel plan isolation (`.planning/YYYY-MM-DD-slug/` directories) and Codex session isolation shipped in v2.36.0. The `experimental/isolated-planning` branch was the earlier prototype; master is now the canonical location.
|
|
332
336
|
|
|
@@ -364,7 +368,7 @@ One hook fire measures 289ms wall-clock since the v3.6.0 optimization, down from
|
|
|
364
368
|
|
|
365
369
|
*Built something? [Open an issue](https://github.com/OthmanAdi/planning-with-files/issues) to get listed!*
|
|
366
370
|
|
|
367
|
-
Full list of everyone who made this project better: [CONTRIBUTORS.md](https://github.com/OthmanAdi/planning-with-files/blob/v3.
|
|
371
|
+
Full list of everyone who made this project better: [CONTRIBUTORS.md](https://github.com/OthmanAdi/planning-with-files/blob/v3.23.0/CONTRIBUTORS.md).
|
|
368
372
|
|
|
369
373
|
</details>
|
|
370
374
|
|
|
@@ -384,7 +388,7 @@ Full list of everyone who made this project better: [CONTRIBUTORS.md](https://gi
|
|
|
384
388
|
| Autonomous loops burn tokens on recitation | Autonomous mode drops the per-tool-call recitation and replaces the raw progress tail with a fixed-shape ledger summary; injection is KV-cache stable and one hook fire costs about 289 ms |
|
|
385
389
|
| Hooks that quietly stop firing | `/plan-doctor` self-checks resolution, injection, attestation, install surfaces and per-fire latency |
|
|
386
390
|
|
|
387
|
-
Everything in that table is opt-in per plan and byte-identical to the previous behavior when no mode marker is set. Details: [v3 Long-Running Agent Features](#v3-long-running-agent-features) and [docs/long-running-agent-tasks.md](https://github.com/OthmanAdi/planning-with-files/blob/v3.
|
|
391
|
+
Everything in that table is opt-in per plan and byte-identical to the previous behavior when no mode marker is set. Details: [v3 Long-Running Agent Features](#v3-long-running-agent-features) and [docs/long-running-agent-tasks.md](https://github.com/OthmanAdi/planning-with-files/blob/v3.23.0/docs/long-running-agent-tasks.md).
|
|
388
392
|
|
|
389
393
|
### Installation routes
|
|
390
394
|
|
|
@@ -455,7 +459,7 @@ What each route actually ships:
|
|
|
455
459
|
| DeepSeek Harness `dsh plugin add` | yes, with the skill | **yes**, `/pwf`, `/pwf-status` | **yes**, plugin hooks incl. the gate |
|
|
456
460
|
| ClawHub / manual copy | yes | no | frontmatter hooks, see note |
|
|
457
461
|
|
|
458
|
-
Skill-route installs can end up silently hook-less (project trust not accepted, or frontmatter hooks not registering on project-level installs). The hooks are the differentiating mechanism, so if they matter to you, use the plugin route, then verify with `/plan-doctor`. Full matrix and the two silent killers: [docs/installation.md](https://github.com/OthmanAdi/planning-with-files/blob/v3.
|
|
462
|
+
Skill-route installs can end up silently hook-less (project trust not accepted, or frontmatter hooks not registering on project-level installs). The hooks are the differentiating mechanism, so if they matter to you, use the plugin route, then verify with `/plan-doctor`. Full matrix and the two silent killers: [docs/installation.md](https://github.com/OthmanAdi/planning-with-files/blob/v3.23.0/docs/installation.md#what-each-install-route-actually-ships).
|
|
459
463
|
|
|
460
464
|
Install acting up? Open your agent and say: *"Read docs/installation.md and docs/troubleshooting.md from OthmanAdi/planning-with-files and fix my install."* Then run `/plan-doctor`.
|
|
461
465
|
|
|
@@ -472,7 +476,7 @@ One skill, three integration tiers. Know what your agent gets before you install
|
|
|
472
476
|
|
|
473
477
|
| Tier | Platforms | What you get |
|
|
474
478
|
|------|-----------|--------------|
|
|
475
|
-
| **Enhanced** (hooks + lifecycle automation) | Claude Code, Cursor, GitHub Copilot, Mastra Code, Gemini CLI, Kiro, Codex, Hermes Agent, CodeBuddy, Factory Droid, OpenCode, DeepSeek Harness | Plan injection every turn, progress reminders, completion check |
|
|
479
|
+
| **Enhanced** (hooks + lifecycle automation) | Claude Code, Cursor, GitHub Copilot, Mastra Code, Gemini CLI, Kiro, Codex, Hermes Agent, CodeBuddy, Factory Droid, OpenCode, DeepSeek Harness | Plan injection every turn (Cursor: at session start), progress reminders, completion check |
|
|
476
480
|
| **Standard Agent Skills** | Continue, Pi, OpenClaw, Autohand Code, Antigravity, Kilocode, AdaL CLI | SKILL.md discovery via `npx skills add`; the pattern without lifecycle hooks |
|
|
477
481
|
| **Agent Skills standard path** (in-tree since v3.7.0) | Zed, Amp, Warp, Devin, Antigravity, Gemini CLI, Cursor | `.agents/skills/planning-with-files/` discovered from a plain `git clone`, no per-tool setup |
|
|
478
482
|
|
|
@@ -492,7 +496,7 @@ Per-platform setup guides, discovery paths and sandbox runtimes are in the colla
|
|
|
492
496
|
- **Stall-aware gate.** The completion gate reads the ledger, not `progress.md` mtime, so a worker that stopped producing events releases the stop instead of looping.
|
|
493
497
|
- **One plan, many hosts.** Claude Code, Codex, Pi, Hermes and OpenCode read the same files, the same `.attestation` and the same gate counters, so a plan can be handed from one agent to another mid-run.
|
|
494
498
|
|
|
495
|
-
The contract and the `.mode` tokens are specified in the skill itself ([SKILL.md, Autonomous and Gated Modes](https://github.com/OthmanAdi/planning-with-files/blob/v3.
|
|
499
|
+
The contract and the `.mode` tokens are specified in the skill itself ([SKILL.md, Autonomous and Gated Modes](https://github.com/OthmanAdi/planning-with-files/blob/v3.23.0/skills/planning-with-files/SKILL.md#autonomous-and-gated-modes-v3)) and in [docs/long-running-agent-tasks.md](https://github.com/OthmanAdi/planning-with-files/blob/v3.23.0/docs/long-running-agent-tasks.md).
|
|
496
500
|
|
|
497
501
|
To find a saved plan, run the installed `scripts/set-active-plan.sh --list` helper from your project directory, or `scripts/set-active-plan.ps1 -List` in PowerShell. It lists named plans under that project's `.planning/` directory, with phase counts for the shipped English and translated templates. `[active]` marks the shared default pointer. Listing does not select a plan or attach a session; use the displayed ID as `PLAN_ID` before starting a concurrent task. Kiro's separate `.kiro/plan` layout is not part of this inventory.
|
|
498
502
|
|
|
@@ -533,7 +537,7 @@ Optional gated mode can request continuation only on a host that supports the re
|
|
|
533
537
|
|
|
534
538
|
Keep automatic compaction enabled. The `PreCompact` hook flushes the planning reminder before compaction, and the plugin `SessionStart` path restores the active plan for the continuation.
|
|
535
539
|
|
|
536
|
-
Maintainer depth (hook architecture, dispatcher layout, parity tooling) lives in [AGENTS.md](https://github.com/OthmanAdi/planning-with-files/blob/v3.
|
|
540
|
+
Maintainer depth (hook architecture, dispatcher layout, parity tooling) lives in [AGENTS.md](https://github.com/OthmanAdi/planning-with-files/blob/v3.23.0/AGENTS.md) and [docs/](https://github.com/OthmanAdi/planning-with-files/blob/v3.23.0/docs/).
|
|
537
541
|
|
|
538
542
|
## Commands
|
|
539
543
|
|
|
@@ -697,12 +701,12 @@ Everything below is the proof and the reference half: the benchmarks and their l
|
|
|
697
701
|
|
|
698
702
|
## Benchmark Results
|
|
699
703
|
|
|
700
|
-
> **Methodology note:** the 96.7% figure comes from the v2.21.0 evaluation run on `claude-sonnet-4-6` (2026-03-06). It measures file-pattern fidelity (does the agent create and maintain the 3-file structure), not goal-drift over long autonomous runs. Newer models and the autonomous-mode work are not yet covered by this number. Full methodology, dataset, and assertion list: [docs/evals.md](https://github.com/OthmanAdi/planning-with-files/blob/v3.
|
|
704
|
+
> **Methodology note:** the 96.7% figure comes from the v2.21.0 evaluation run on `claude-sonnet-4-6` (2026-03-06). It measures file-pattern fidelity (does the agent create and maintain the 3-file structure), not goal-drift over long autonomous runs. Newer models and the autonomous-mode work are not yet covered by this number. Full methodology, dataset, and assertion list: [docs/evals.md](https://github.com/OthmanAdi/planning-with-files/blob/v3.23.0/docs/evals.md).
|
|
701
705
|
|
|
702
706
|
Evaluated with Anthropic's [skill-creator](https://github.com/anthropics/skills/tree/main/skills/skill-creator) framework: skill v2.21.0, model `claude-sonnet-4-6`, 2026-03-06. 10 parallel subagents, 5 task types, 30 objectively verifiable assertions, 3 blind A/B comparisons.
|
|
703
707
|
|
|
704
708
|
<p align="center">
|
|
705
|
-
<img src="https://raw.githubusercontent.com/OthmanAdi/planning-with-files/v3.
|
|
709
|
+
<img src="https://raw.githubusercontent.com/OthmanAdi/planning-with-files/v3.23.0/media/benchmark-skill-vs-baseline.svg" width="860" alt="Eval results, with skill vs without: assertions passed 29 of 30 vs 2 of 30, 3-file pattern followed 5 of 5 vs 0 of 5, blind A/B wins 3 of 3 vs 0 of 3, average rubric score 10.0 vs 6.8">
|
|
706
710
|
</p>
|
|
707
711
|
|
|
708
712
|
| Test | with_skill | without_skill |
|
|
@@ -714,17 +718,17 @@ Evaluated with Anthropic's [skill-creator](https://github.com/anthropics/skills/
|
|
|
714
718
|
|
|
715
719
|
### Recovery after a context wipe
|
|
716
720
|
|
|
717
|
-
> **Internal benchmark, v1 (2026-07-06).** Author-run against v3.4.0, harness-authored tasks, deterministic grading, no LLM grades anything. Treat it as the project's own measurement, not an independent comparison. Full method, arms, disclosed limits, and grader validation: [docs/evals.md](https://github.com/OthmanAdi/planning-with-files/blob/v3.
|
|
721
|
+
> **Internal benchmark, v1 (2026-07-06).** Author-run against v3.4.0, harness-authored tasks, deterministic grading, no LLM grades anything. Treat it as the project's own measurement, not an independent comparison. Full method, arms, disclosed limits, and grader validation: [docs/evals.md](https://github.com/OthmanAdi/planning-with-files/blob/v3.23.0/docs/evals.md#test-5-competitive-benchmark-v1-seven-planning-methods-head-to-head-2026-07-06-internal).
|
|
718
722
|
|
|
719
723
|
Protocol: the session is hard-stopped at roughly half done, and a fresh session is told only "Continue the work in this directory." Every graded run across every arm ended pytest-green (77/77), so the difference is re-orientation cost, not correctness.
|
|
720
724
|
|
|
721
725
|
<p align="center">
|
|
722
|
-
<img src="https://raw.githubusercontent.com/OthmanAdi/planning-with-files/v3.
|
|
726
|
+
<img src="https://raw.githubusercontent.com/OthmanAdi/planning-with-files/v3.23.0/media/recovery-turns.svg" width="860" alt="Turns to resume after a context wipe, internal benchmark v1: 5.0 with planning-with-files, 13.3 for a raw agent with no planning method">
|
|
723
727
|
</p>
|
|
724
728
|
|
|
725
|
-
**With the planning files on disk, a resume took 5.0 turns on average; a raw agent took 13.3.** Planning-file recovery plus hook injection put phase state in front of the model before its first tool call, and the same run found no correctness penalty anywhere. This internal v1 used the earlier default transcript catchup; current automatic recovery is file-only and has not been re-benchmarked under the same protocol. An animated summary lives at [docs/benchmark/index.html](https://github.com/OthmanAdi/planning-with-files/blob/v3.
|
|
729
|
+
**With the planning files on disk, a resume took 5.0 turns on average; a raw agent took 13.3.** Planning-file recovery plus hook injection put phase state in front of the model before its first tool call, and the same run found no correctness penalty anywhere. This internal v1 used the earlier default transcript catchup; current automatic recovery is file-only and has not been re-benchmarked under the same protocol. Contributors can run that current protocol from [examples/file-only-recovery/](https://github.com/OthmanAdi/planning-with-files/blob/v3.23.0/examples/file-only-recovery/README.md). Running the fixture is not a new measurement of the 5.0 or 13.3 figures. An animated summary lives at [docs/benchmark/index.html](https://github.com/OthmanAdi/planning-with-files/blob/v3.23.0/docs/benchmark/index.html) ([rendered view](https://htmlpreview.github.io/?https://github.com/OthmanAdi/planning-with-files/blob/v3.23.0/docs/benchmark/index.html)).
|
|
726
730
|
|
|
727
|
-
[Full methodology and results](https://github.com/OthmanAdi/planning-with-files/blob/v3.
|
|
731
|
+
[Full methodology and results](https://github.com/OthmanAdi/planning-with-files/blob/v3.23.0/docs/evals.md) · [Technical write-up](https://github.com/OthmanAdi/planning-with-files/blob/v3.23.0/docs/article.md)
|
|
728
732
|
|
|
729
733
|
## File Structure
|
|
730
734
|
|
|
@@ -762,25 +766,25 @@ Every release maintains 20 tracked parity targets plus the gitignored ClawHub up
|
|
|
762
766
|
|
|
763
767
|
| Doc | What it covers |
|
|
764
768
|
|-----|----------------|
|
|
765
|
-
| [docs/installation.md](https://github.com/OthmanAdi/planning-with-files/blob/v3.
|
|
766
|
-
| [docs/quickstart.md](https://github.com/OthmanAdi/planning-with-files/blob/v3.
|
|
767
|
-
| [docs/workflow.md](https://github.com/OthmanAdi/planning-with-files/blob/v3.
|
|
768
|
-
| [docs/hermes.md](https://github.com/OthmanAdi/planning-with-files/blob/v3.
|
|
769
|
-
| [docs/opencode.md](https://github.com/OthmanAdi/planning-with-files/blob/v3.
|
|
770
|
-
| [docs/deepseek-harness.md](https://github.com/OthmanAdi/planning-with-files/blob/v3.
|
|
771
|
-
| [docs/evals.md](https://github.com/OthmanAdi/planning-with-files/blob/v3.
|
|
772
|
-
| [docs/troubleshooting.md](https://github.com/OthmanAdi/planning-with-files/blob/v3.
|
|
773
|
-
| [docs/claude-code-lost-context-after-compaction.md](https://github.com/OthmanAdi/planning-with-files/blob/v3.
|
|
774
|
-
| [docs/agent-forgets-plan-after-clear.md](https://github.com/OthmanAdi/planning-with-files/blob/v3.
|
|
775
|
-
| [docs/long-running-agent-tasks.md](https://github.com/OthmanAdi/planning-with-files/blob/v3.
|
|
776
|
-
| [MIGRATION.md](https://github.com/OthmanAdi/planning-with-files/blob/v3.
|
|
777
|
-
| [SECURITY.md](https://github.com/OthmanAdi/planning-with-files/blob/v3.
|
|
778
|
-
| [CONTRIBUTING.md](https://github.com/OthmanAdi/planning-with-files/blob/v3.
|
|
779
|
-
| Per-platform guides | 19+ setup docs in [docs/](https://github.com/OthmanAdi/planning-with-files/
|
|
769
|
+
| [docs/installation.md](https://github.com/OthmanAdi/planning-with-files/blob/v3.23.0/docs/installation.md) | Every install route, the route matrix, the trust prerequisite |
|
|
770
|
+
| [docs/quickstart.md](https://github.com/OthmanAdi/planning-with-files/blob/v3.23.0/docs/quickstart.md) | Your first planning session in 5 steps |
|
|
771
|
+
| [docs/workflow.md](https://github.com/OthmanAdi/planning-with-files/blob/v3.23.0/docs/workflow.md) | Day-to-day usage, plan lifecycle, topic handoffs |
|
|
772
|
+
| [docs/hermes.md](https://github.com/OthmanAdi/planning-with-files/blob/v3.23.0/docs/hermes.md) | Hermes Agent CLI and Desktop: install, `/pwf`, the `pre_verify` gate, Windows, migration from Claude Code |
|
|
773
|
+
| [docs/opencode.md](https://github.com/OthmanAdi/planning-with-files/blob/v3.23.0/docs/opencode.md) | OpenCode: the native plugin, `/pwf`, the `session.idle` gate, `pwf_*` tools |
|
|
774
|
+
| [docs/deepseek-harness.md](https://github.com/OthmanAdi/planning-with-files/blob/v3.23.0/docs/deepseek-harness.md) | DeepSeek Harness: the native plugin, profiles, `/pwf`, the turn-boundary gate, what DSH does not expose |
|
|
775
|
+
| [docs/evals.md](https://github.com/OthmanAdi/planning-with-files/blob/v3.23.0/docs/evals.md) | Full benchmark methodology, raw numbers, disclosed limits |
|
|
776
|
+
| [docs/troubleshooting.md](https://github.com/OthmanAdi/planning-with-files/blob/v3.23.0/docs/troubleshooting.md) | When hooks are quiet, plus `/plan-doctor` |
|
|
777
|
+
| [docs/claude-code-lost-context-after-compaction.md](https://github.com/OthmanAdi/planning-with-files/blob/v3.23.0/docs/claude-code-lost-context-after-compaction.md) | Recovering and preventing context loss from compaction |
|
|
778
|
+
| [docs/agent-forgets-plan-after-clear.md](https://github.com/OthmanAdi/planning-with-files/blob/v3.23.0/docs/agent-forgets-plan-after-clear.md) | The file-based fix when an agent forgets its plan after `/clear` |
|
|
779
|
+
| [docs/long-running-agent-tasks.md](https://github.com/OthmanAdi/planning-with-files/blob/v3.23.0/docs/long-running-agent-tasks.md) | Keeping a coding agent on track for hours: modes, gate, ledger |
|
|
780
|
+
| [MIGRATION.md](https://github.com/OthmanAdi/planning-with-files/blob/v3.23.0/MIGRATION.md) | v2 to v3 migration and host capability tiers |
|
|
781
|
+
| [SECURITY.md](https://github.com/OthmanAdi/planning-with-files/blob/v3.23.0/SECURITY.md) | Vulnerability reporting and hardening history |
|
|
782
|
+
| [CONTRIBUTING.md](https://github.com/OthmanAdi/planning-with-files/blob/v3.23.0/CONTRIBUTING.md) | How to contribute; authorship is preserved on merge |
|
|
783
|
+
| Per-platform guides | 19+ setup docs in [docs/](https://github.com/OthmanAdi/planning-with-files/blob/v3.23.0/docs/), linked from the [platform tables](#works-across-19-platforms) |
|
|
780
784
|
|
|
781
785
|
## Contributing
|
|
782
786
|
|
|
783
|
-
Contributions welcome. Start with [CONTRIBUTING.md](https://github.com/OthmanAdi/planning-with-files/blob/v3.
|
|
787
|
+
Contributions welcome. Start with [CONTRIBUTING.md](https://github.com/OthmanAdi/planning-with-files/blob/v3.23.0/CONTRIBUTING.md). Every shipped contribution is credited: commit authorship is preserved on merge, and contributors are listed in [CONTRIBUTORS.md](https://github.com/OthmanAdi/planning-with-files/blob/v3.23.0/CONTRIBUTORS.md), the CHANGELOG Thanks section, and the release notes.
|
|
784
788
|
|
|
785
789
|
## License
|
|
786
790
|
|
|
@@ -802,7 +806,7 @@ MIT License — feel free to use, modify, and distribute.
|
|
|
802
806
|
|
|
803
807
|
## Contributors
|
|
804
808
|
|
|
805
|
-
Code, documentation, and issue contributors. Select a portrait to open a GitHub profile or archived credit. [Full credits](https://github.com/OthmanAdi/planning-with-files/blob/v3.
|
|
809
|
+
Code, documentation, and issue contributors. Select a portrait to open a GitHub profile or archived credit. [Full credits](https://github.com/OthmanAdi/planning-with-files/blob/v3.23.0/CONTRIBUTORS.md).
|
|
806
810
|
|
|
807
811
|
<!-- contributor-portraits:start -->
|
|
808
812
|
<p align="center">
|
|
@@ -820,6 +824,11 @@ Code, documentation, and issue contributors. Select a portrait to open a GitHub
|
|
|
820
824
|
<a href="https://github.com/mvanhorn" title="@mvanhorn"><img src="https://github.com/mvanhorn.png?size=56" width="48" height="48" alt="@mvanhorn"></a>
|
|
821
825
|
<a href="https://github.com/ebrevdo" title="@ebrevdo"><img src="https://github.com/ebrevdo.png?size=56" width="48" height="48" alt="@ebrevdo"></a>
|
|
822
826
|
<a href="https://github.com/bailob" title="@bailob"><img src="https://github.com/bailob.png?size=56" width="48" height="48" alt="@bailob"></a>
|
|
827
|
+
<a href="https://github.com/as992949791" title="@as992949791"><img src="https://github.com/as992949791.png?size=56" width="48" height="48" alt="@as992949791"></a>
|
|
828
|
+
<a href="https://github.com/shuoxuekeji" title="@shuoxuekeji"><img src="https://github.com/shuoxuekeji.png?size=56" width="48" height="48" alt="@shuoxuekeji"></a>
|
|
829
|
+
<a href="https://github.com/Jinzy" title="@Jinzy"><img src="https://github.com/Jinzy.png?size=56" width="48" height="48" alt="@Jinzy"></a>
|
|
830
|
+
<a href="https://github.com/SomSamantray" title="@SomSamantray"><img src="https://github.com/SomSamantray.png?size=56" width="48" height="48" alt="@SomSamantray"></a>
|
|
831
|
+
<a href="https://github.com/mmychu" title="@mmychu"><img src="https://github.com/mmychu.png?size=56" width="48" height="48" alt="@mmychu"></a>
|
|
823
832
|
<a href="https://github.com/ericshunhinglee-cloud" title="@ericshunhinglee-cloud"><img src="https://github.com/ericshunhinglee-cloud.png?size=56" width="48" height="48" alt="@ericshunhinglee-cloud"></a>
|
|
824
833
|
<a href="https://github.com/ShaunLinTW" title="@ShaunLinTW"><img src="https://github.com/ShaunLinTW.png?size=56" width="48" height="48" alt="@ShaunLinTW"></a>
|
|
825
834
|
<a href="https://github.com/TayfurYldz" title="@TayfurYldz"><img src="https://github.com/TayfurYldz.png?size=56" width="48" height="48" alt="@TayfurYldz"></a>
|
|
@@ -848,7 +857,7 @@ Code, documentation, and issue contributors. Select a portrait to open a GitHub
|
|
|
848
857
|
<a href="https://github.com/Skulli485" title="@Skulli485"><img src="https://github.com/Skulli485.png?size=56" width="48" height="48" alt="@Skulli485"></a>
|
|
849
858
|
<a href="https://github.com/carterusedulm2-maker" title="@carterusedulm2-maker"><img src="https://github.com/carterusedulm2-maker.png?size=56" width="48" height="48" alt="@carterusedulm2-maker"></a>
|
|
850
859
|
<a href="https://github.com/gauravvojha" title="@gauravvojha"><img src="https://github.com/gauravvojha.png?size=56" width="48" height="48" alt="@gauravvojha"></a>
|
|
851
|
-
<a href="https://github.com/OthmanAdi/planning-with-files/blob/v3.
|
|
860
|
+
<a href="https://github.com/OthmanAdi/planning-with-files/blob/v3.23.0/CONTRIBUTORS.md" title="@CleanDev-Fix, archived credit"><img src="https://github.com/identicons/CleanDev-Fix.png" width="48" height="48" alt="@CleanDev-Fix"></a>
|
|
852
861
|
<a href="https://github.com/bmyury" title="@bmyury"><img src="https://github.com/bmyury.png?size=56" width="48" height="48" alt="@bmyury"></a>
|
|
853
862
|
<a href="https://github.com/oaabahussain" title="@oaabahussain"><img src="https://github.com/oaabahussain.png?size=56" width="48" height="48" alt="@oaabahussain"></a>
|
|
854
863
|
<a href="https://github.com/gavinlinasd" title="@gavinlinasd"><img src="https://github.com/gavinlinasd.png?size=56" width="48" height="48" alt="@gavinlinasd"></a>
|
|
@@ -881,6 +890,6 @@ Code, documentation, and issue contributors. Select a portrait to open a GitHub
|
|
|
881
890
|
<a href="https://github.com/Yigtwxx" title="@Yigtwxx"><img src="https://github.com/Yigtwxx.png?size=56" width="48" height="48" alt="@Yigtwxx"></a>
|
|
882
891
|
<a href="https://github.com/RioTheGreat-ai" title="@RioTheGreat-ai"><img src="https://github.com/RioTheGreat-ai.png?size=56" width="48" height="48" alt="@RioTheGreat-ai"></a>
|
|
883
892
|
<a href="https://github.com/kmichels" title="@kmichels"><img src="https://github.com/kmichels.png?size=56" width="48" height="48" alt="@kmichels"></a>
|
|
884
|
-
<a href="https://github.com/OthmanAdi/planning-with-files/blob/v3.
|
|
893
|
+
<a href="https://github.com/OthmanAdi/planning-with-files/blob/v3.23.0/CONTRIBUTORS.md" title="@voidborne-d, archived credit"><img src="https://github.com/identicons/voidborne-d.png" width="48" height="48" alt="@voidborne-d"></a>
|
|
885
894
|
</p>
|
|
886
895
|
<!-- contributor-portraits:end -->
|
package/SKILL.md
CHANGED
|
@@ -28,7 +28,7 @@ hooks:
|
|
|
28
28
|
- type: command
|
|
29
29
|
command: "[ -n \"${CLAUDE_PLUGIN_ROOT:-}\" ] && exit 0; SH=\"${CLAUDE_SKILL_DIR}/scripts/skill-hook.sh\"; [ -f \"$SH\" ] || SH=$(ls \"$HOME/.claude/skills/planning-with-files/scripts/skill-hook.sh\" \"$HOME/.claude/plugins/marketplaces/planning-with-files/scripts/skill-hook.sh\" 2>/dev/null | head -1); [ -n \"$SH\" ] && [ -f \"$SH\" ] && sh \"$SH\" --event=precompact; exit 0"
|
|
30
30
|
metadata:
|
|
31
|
-
version: "3.
|
|
31
|
+
version: "3.23.0"
|
|
32
32
|
---
|
|
33
33
|
|
|
34
34
|
# Planning with Files
|
|
@@ -325,9 +325,11 @@ For a "babysit until done" workflow, combine `/plan-loop` (cadence) with `/plan-
|
|
|
325
325
|
|
|
326
326
|
For skill-only installs (no `commands/` folder) or sessions where the slash command refuses to fire, the model can produce the same effect by executing the wrapper steps inline.
|
|
327
327
|
|
|
328
|
+
For parallel tasks, pin each host with its task's `PLAN_ID` before starting it, or use separate worktrees. Set `PWF_PLAN_ROOT` when the project root differs from the host's working directory. `.planning/.active_plan` is a shared default; switching it does not bind parallel sessions to their tasks.
|
|
329
|
+
|
|
328
330
|
**Manual `/plan-goal` procedure:**
|
|
329
331
|
|
|
330
|
-
1.
|
|
332
|
+
1. If set, validate `PWF_PLAN_ROOT` as an absolute, existing project root. When `PLAN_ID` is set, use the installed `scripts/resolve-plan-dir.sh` (or `.ps1`) and stop if it returns no directory; the explicit pin was rejected. With `PLAN_ID` unset, first run the resolver with `--check-ambiguity` (`-CheckAmbiguity` in PowerShell); if it returns `PWF_PLAN_AMBIGUOUS_V1`, stop and set a task-specific `PLAN_ID`. Then run the resolver normally and read the selected directory. If it returns no directory and the project root has `task_plan.md`, use the legacy root files; otherwise stop recovery.
|
|
331
333
|
2. Read the resolved `task_plan.md`.
|
|
332
334
|
3. Compose a goal condition. Default: `"all phases in task_plan.md report Status: complete and check-complete.sh reports ALL PHASES COMPLETE"`. If the user passed additional clauses, append them.
|
|
333
335
|
4. Issue Claude Code's native `/goal <condition>` (CC primitive, always available).
|
package/package.json
CHANGED
|
@@ -1,6 +1,6 @@
|
|
|
1
1
|
{
|
|
2
2
|
"name": "planning-with-files",
|
|
3
|
-
"version": "3.
|
|
3
|
+
"version": "3.23.0",
|
|
4
4
|
"description": "Official Planning with Files skill for AI coding agents. Keeps persistent project planning files and injects selected plan context. Automatic recovery reads project files only; explicit local session catchup has no network upload path. Includes scripts, templates, and a Pi Coding Agent extension.",
|
|
5
5
|
"keywords": [
|
|
6
6
|
"planning-with-files",
|
package/scripts/attest-plan.sh
CHANGED
|
@@ -6,16 +6,19 @@
|
|
|
6
6
|
# attested hash, surfacing a "[PLAN TAMPERED]" warning instead.
|
|
7
7
|
#
|
|
8
8
|
# Resolution:
|
|
9
|
-
# 1.
|
|
10
|
-
# 2. ./.planning
|
|
11
|
-
# 3.
|
|
12
|
-
# 4.
|
|
13
|
-
# 5.
|
|
9
|
+
# 1. --target root or <plan-id> → root or named plan under $PWF_PLAN_ROOT (default: cwd)
|
|
10
|
+
# 2. $PLAN_ID env var → ./.planning/$PLAN_ID/
|
|
11
|
+
# 3. ./.planning/.active_plan
|
|
12
|
+
# 4. Newest ./.planning/<dir>/ by mtime
|
|
13
|
+
# 5. Current directory when it is .planning/<valid-slug>/
|
|
14
|
+
# 6. Legacy ./task_plan.md at project root
|
|
14
15
|
#
|
|
15
16
|
# Usage:
|
|
16
17
|
# sh scripts/attest-plan.sh # attest the active plan
|
|
17
18
|
# sh scripts/attest-plan.sh --show # print the stored hash
|
|
18
19
|
# sh scripts/attest-plan.sh --clear # remove the attestation (re-open the plan)
|
|
20
|
+
# sh scripts/attest-plan.sh --target root # attest the legacy root plan
|
|
21
|
+
# sh scripts/attest-plan.sh --target <plan-id> # attest one named plan
|
|
19
22
|
|
|
20
23
|
set -u
|
|
21
24
|
|
|
@@ -42,6 +45,39 @@ resolve_from_slug_cwd() {
|
|
|
42
45
|
}
|
|
43
46
|
|
|
44
47
|
resolve_plan_file() {
|
|
48
|
+
if [ -n "${target:-}" ]; then
|
|
49
|
+
if [ "${target}" = "root" ]; then
|
|
50
|
+
target_root="."
|
|
51
|
+
if [ -n "${PWF_PLAN_ROOT:-}" ]; then
|
|
52
|
+
# Match the shared resolver's supported absolute local pins.
|
|
53
|
+
# A valid project-root junction is intentional, so resolve it.
|
|
54
|
+
case "${PWF_PLAN_ROOT}" in
|
|
55
|
+
\\\\*|//*|[A-Za-z]:[!\\/]*) return 1 ;;
|
|
56
|
+
/*|[A-Za-z]:[\\/]*) ;;
|
|
57
|
+
*) return 1 ;;
|
|
58
|
+
esac
|
|
59
|
+
target_root="$(cd "${PWF_PLAN_ROOT}" 2>/dev/null && pwd -P)" || return 1
|
|
60
|
+
fi
|
|
61
|
+
[ ! -L "${target_root}/task_plan.md" ] || return 1
|
|
62
|
+
[ -f "${target_root}/task_plan.md" ] || return 1
|
|
63
|
+
printf "%s\n" "${target_root}/task_plan.md"
|
|
64
|
+
return 0
|
|
65
|
+
fi
|
|
66
|
+
slug_is_valid "${target}" || return 1
|
|
67
|
+
# Reuse the binding, project-pin and containment rules. A flag replaces
|
|
68
|
+
# PLAN_ID for this call only; it does not change the shared pointer.
|
|
69
|
+
[ -f "${RESOLVER}" ] || return 1
|
|
70
|
+
target_dir="$(PLAN_ID="${target}" sh "${RESOLVER}" 2>/dev/null)" || return 1
|
|
71
|
+
[ -n "${target_dir}" ] || return 1
|
|
72
|
+
# Use the shell's physical path spelling: native Windows backslashes
|
|
73
|
+
# make sha256sum prefix its output with an escaped-filename marker.
|
|
74
|
+
target_dir="$(cd "${target_dir}" 2>/dev/null && pwd -P)" || return 1
|
|
75
|
+
[ ! -L "${target_dir}/task_plan.md" ] || return 1
|
|
76
|
+
[ -f "${target_dir}/task_plan.md" ] || return 1
|
|
77
|
+
printf "%s\n" "${target_dir}/task_plan.md"
|
|
78
|
+
return 0
|
|
79
|
+
fi
|
|
80
|
+
|
|
45
81
|
plan_dir=""
|
|
46
82
|
if [ -f "${RESOLVER}" ]; then
|
|
47
83
|
plan_dir="$(sh "${RESOLVER}" 2>/dev/null)"
|
|
@@ -80,7 +116,9 @@ resolve_plan_file() {
|
|
|
80
116
|
attestation_path_for() {
|
|
81
117
|
plan_file="$1"
|
|
82
118
|
plan_dir="$(dirname "${plan_file}")"
|
|
83
|
-
if [ "${
|
|
119
|
+
if [ "${target:-}" = "root" ]; then
|
|
120
|
+
printf "%s\n" "${plan_dir}/.plan-attestation"
|
|
121
|
+
elif [ "${plan_dir}" = "." ]; then
|
|
84
122
|
# Legacy mode: store at project root.
|
|
85
123
|
printf "%s\n" "./.plan-attestation"
|
|
86
124
|
else
|
|
@@ -101,14 +139,21 @@ compute_hash() {
|
|
|
101
139
|
}
|
|
102
140
|
|
|
103
141
|
mode="attest"
|
|
142
|
+
target=""
|
|
143
|
+
usage_error() {
|
|
144
|
+
printf "Usage: %s [--show|--clear|--target root|<plan-id>]\n" "$0" >&2
|
|
145
|
+
exit 2
|
|
146
|
+
}
|
|
104
147
|
case "${1:-}" in
|
|
105
|
-
--show) mode="show" ;;
|
|
106
|
-
--clear) mode="clear" ;;
|
|
107
|
-
|
|
108
|
-
|
|
109
|
-
|
|
110
|
-
|
|
148
|
+
--show) [ "$#" -eq 1 ] || usage_error; mode="show" ;;
|
|
149
|
+
--clear) [ "$#" -eq 1 ] || usage_error; mode="clear" ;;
|
|
150
|
+
--target)
|
|
151
|
+
[ "$#" -eq 2 ] || usage_error
|
|
152
|
+
[ -n "$2" ] || usage_error
|
|
153
|
+
target="$2"
|
|
111
154
|
;;
|
|
155
|
+
"") [ "$#" -eq 0 ] || usage_error ;;
|
|
156
|
+
*) usage_error ;;
|
|
112
157
|
esac
|
|
113
158
|
|
|
114
159
|
plan_file="$(resolve_plan_file)" || {
|
|
@@ -117,7 +162,9 @@ plan_file="$(resolve_plan_file)" || {
|
|
|
117
162
|
# a mistyped PLAN_ID attested a DIFFERENT plan at rc=0, and an operator
|
|
118
163
|
# who now sees a generic not-found is likely to go looking for the wrong
|
|
119
164
|
# problem. The selectors are bindings, so say which one refused.
|
|
120
|
-
if [ -n "${
|
|
165
|
+
if [ -n "${target:-}" ]; then
|
|
166
|
+
printf "[plan-attest] --target %s did not resolve to a plan. An explicit target is a binding: nothing was attested and no other plan was substituted.\n" "${target}" >&2
|
|
167
|
+
elif [ -n "${PLAN_ID:-}" ]; then
|
|
121
168
|
printf "[plan-attest] PLAN_ID=%s names no plan directory under .planning. An explicit selector is a binding: nothing was attested and no other plan was substituted.\n" "${PLAN_ID}" >&2
|
|
122
169
|
elif [ -n "${PWF_PLAN_ROOT:-}" ]; then
|
|
123
170
|
printf "[plan-attest] PWF_PLAN_ROOT=%s did not resolve to a project root holding a plan. An explicit pin is a binding: nothing was attested and no other plan was substituted.\n" "${PWF_PLAN_ROOT}" >&2
|
|
@@ -156,6 +203,8 @@ case "${mode}" in
|
|
|
156
203
|
fi
|
|
157
204
|
;;
|
|
158
205
|
attest)
|
|
206
|
+
printf "Plan: %s\n" "${plan_file}"
|
|
207
|
+
printf "Attestation: %s\n" "${attestation_file}"
|
|
159
208
|
hash_val="$(compute_hash "${plan_file}")" || exit 1
|
|
160
209
|
|
|
161
210
|
# v2.40: protect the write with an advisory flock when available so
|
|
@@ -51,6 +51,8 @@ if ($PlanFile -ne "") {
|
|
|
51
51
|
}
|
|
52
52
|
|
|
53
53
|
if (-not (Test-Path $PlanFile)) {
|
|
54
|
+
# Automatic gate checks have nothing to report without a plan; the explicit report keeps its notice.
|
|
55
|
+
if ($Gate) { exit 0 }
|
|
54
56
|
Write-Host '[planning-with-files] No task_plan.md found -- no active planning session.'
|
|
55
57
|
exit 0
|
|
56
58
|
}
|
|
@@ -79,6 +79,9 @@ else
|
|
|
79
79
|
fi
|
|
80
80
|
|
|
81
81
|
if [ ! -f "$PLAN_FILE" ]; then
|
|
82
|
+
# Automatic gate checks have nothing to report without a plan (header:
|
|
83
|
+
# "plans stay silent in --gate mode"); the explicit report keeps its notice.
|
|
84
|
+
[ "$GATE" -eq 1 ] && exit 0
|
|
82
85
|
echo "[planning-with-files] No task_plan.md found — no active planning session."
|
|
83
86
|
exit 0
|
|
84
87
|
fi
|
package/scripts/init-session.ps1
CHANGED
|
@@ -368,8 +368,10 @@ if ($UsePlanDir) {
|
|
|
368
368
|
# Another writer can replace the pointer between the selector's
|
|
369
369
|
# Get-Item and final-path check. Retry only that transient result.
|
|
370
370
|
$transientPointerRace = $selectorResult -is [System.Management.Automation.ErrorRecord] -and
|
|
371
|
-
$selectorResult.Exception.Message -
|
|
372
|
-
'Error: could not set the active plan pointer: the active plan pointer became unsafe during replacement'
|
|
371
|
+
$selectorResult.Exception.Message -in @(
|
|
372
|
+
'Error: could not set the active plan pointer: the active plan pointer became unsafe during replacement',
|
|
373
|
+
'Error: the active plan pointer must be a regular file within the project.'
|
|
374
|
+
)
|
|
373
375
|
if ($attempt -eq 5 -or -not $transientPointerRace) {
|
|
374
376
|
break
|
|
375
377
|
}
|
|
@@ -132,6 +132,54 @@ function Test-SafeActiveFile {
|
|
|
132
132
|
(Test-WithinRoot $ActiveFile)
|
|
133
133
|
}
|
|
134
134
|
|
|
135
|
+
function Test-SafeOwnedBackupFile {
|
|
136
|
+
param([string]$Path)
|
|
137
|
+
$item = Get-Item -LiteralPath $Path -Force -ErrorAction SilentlyContinue
|
|
138
|
+
if (-not $item) { return $false }
|
|
139
|
+
$linked = ([string]$item.LinkType) -in @('SymbolicLink', 'Junction')
|
|
140
|
+
return -not $item.PSIsContainer -and -not $linked -and (Test-WithinRoot $Path)
|
|
141
|
+
}
|
|
142
|
+
|
|
143
|
+
function Resolve-OwnedPointerBackup {
|
|
144
|
+
param([string]$BackupFile, [switch]$ReplaceSucceeded)
|
|
145
|
+
# ReplaceFile can move the old destination before failing to move the new
|
|
146
|
+
# file. A caller-named backup makes that intermediate state attributable to
|
|
147
|
+
# this invocation, so recover or delete only this GUID path. Never glob for
|
|
148
|
+
# ~RF*.TMP: a concurrent selector may own those files.
|
|
149
|
+
$maxAttempts = 20
|
|
150
|
+
for ($attempt = 1; $attempt -le $maxAttempts; $attempt++) {
|
|
151
|
+
$backupItem = Get-Item -LiteralPath $BackupFile -Force -ErrorAction SilentlyContinue
|
|
152
|
+
if (-not $backupItem) { return $true }
|
|
153
|
+
# A failed inspection is transient under concurrent writers: retry.
|
|
154
|
+
if (-not (Test-SafeOwnedBackupFile $BackupFile)) { Start-Sleep -Milliseconds 25; continue }
|
|
155
|
+
|
|
156
|
+
$currentActive = Get-Item -LiteralPath $ActiveFile -Force -ErrorAction SilentlyContinue
|
|
157
|
+
# After our own successful replacement the backup holds a superseded
|
|
158
|
+
# value: only delete it, never move it back over a newer pointer.
|
|
159
|
+
if ($ReplaceSucceeded -or $currentActive) {
|
|
160
|
+
if (-not $ReplaceSucceeded -and -not (Test-SafeActiveFile)) { Start-Sleep -Milliseconds 25; continue }
|
|
161
|
+
try {
|
|
162
|
+
[IO.File]::Delete($BackupFile)
|
|
163
|
+
return $true
|
|
164
|
+
} catch {
|
|
165
|
+
if ($attempt -eq $maxAttempts) { return $false }
|
|
166
|
+
}
|
|
167
|
+
} else {
|
|
168
|
+
try {
|
|
169
|
+
[IO.File]::Move($BackupFile, $ActiveFile)
|
|
170
|
+
return $true
|
|
171
|
+
} catch {
|
|
172
|
+
# Another selector may have recreated the pointer between the
|
|
173
|
+
# absence check and Move. Reinspect before deciding whether the
|
|
174
|
+
# owned backup is now redundant.
|
|
175
|
+
if ($attempt -eq $maxAttempts) { return $false }
|
|
176
|
+
}
|
|
177
|
+
}
|
|
178
|
+
Start-Sleep -Milliseconds 25
|
|
179
|
+
}
|
|
180
|
+
return $false
|
|
181
|
+
}
|
|
182
|
+
|
|
135
183
|
function Get-CurrentActivePlan {
|
|
136
184
|
if (-not (Test-SafeActiveFile -AllowLink)) { return "" }
|
|
137
185
|
try {
|
|
@@ -306,9 +354,16 @@ if ($activeItem -and -not (Test-SafeActiveFile)) {
|
|
|
306
354
|
$utf8NoBom = New-Object System.Text.UTF8Encoding($false)
|
|
307
355
|
# Replace the directory entry instead of truncating an existing inode: a
|
|
308
356
|
# hardlinked pointer must not overwrite another file. The exclusive temporary
|
|
309
|
-
# file
|
|
310
|
-
|
|
357
|
+
# file and caller-owned backup live beside the pointer, keeping replacement on
|
|
358
|
+
# the same filesystem. Naming the backup prevents ReplaceFile from inventing
|
|
359
|
+
# an unowned ~RF*.TMP path if its final rename fails.
|
|
360
|
+
$operationId = [guid]::NewGuid().ToString('N')
|
|
361
|
+
$tempFile = Join-Path $PlanRoot ('.active_plan.' + $operationId + '.tmp')
|
|
362
|
+
$backupFile = Join-Path $PlanRoot ('.active_plan.' + $operationId + '.replace-backup')
|
|
311
363
|
$createdTemp = $false
|
|
364
|
+
$failureMessage = ""
|
|
365
|
+
$backupResolved = $true
|
|
366
|
+
$replaced = $false
|
|
312
367
|
try {
|
|
313
368
|
$stream = [IO.File]::Open($tempFile, [IO.FileMode]::CreateNew, [IO.FileAccess]::Write, [IO.FileShare]::None)
|
|
314
369
|
$createdTemp = $true
|
|
@@ -325,24 +380,40 @@ try {
|
|
|
325
380
|
if (-not (Test-SafeActiveFile)) {
|
|
326
381
|
throw [InvalidOperationException]::new("the active plan pointer became unsafe during replacement")
|
|
327
382
|
}
|
|
328
|
-
[IO.File]::Replace($tempFile, $ActiveFile,
|
|
383
|
+
[IO.File]::Replace($tempFile, $ActiveFile, $backupFile)
|
|
329
384
|
} else {
|
|
330
385
|
[IO.File]::Move($tempFile, $ActiveFile)
|
|
331
386
|
}
|
|
387
|
+
$replaced = $true
|
|
332
388
|
break
|
|
333
389
|
} catch [IO.IOException] {
|
|
390
|
+
if (-not (Resolve-OwnedPointerBackup -BackupFile $backupFile)) {
|
|
391
|
+
throw [IO.IOException]::new("could not safely recover the active plan pointer after replacement failure")
|
|
392
|
+
}
|
|
334
393
|
if ($attempt -eq $maxAttempts) { throw }
|
|
335
394
|
Start-Sleep -Milliseconds 25
|
|
336
395
|
}
|
|
337
396
|
}
|
|
338
397
|
} catch {
|
|
339
|
-
|
|
340
|
-
exit 1
|
|
398
|
+
$failureMessage = $_.Exception.Message
|
|
341
399
|
} finally {
|
|
400
|
+
if (-not (Resolve-OwnedPointerBackup -BackupFile $backupFile -ReplaceSucceeded:$replaced)) {
|
|
401
|
+
# The pointer was written; a leftover backup is clutter, not failure.
|
|
402
|
+
if ($replaced) { Write-Warning "could not remove the replacement backup $backupFile" }
|
|
403
|
+
else { $backupResolved = $false }
|
|
404
|
+
}
|
|
342
405
|
if ($createdTemp -and (Test-Path -LiteralPath $tempFile)) {
|
|
343
406
|
Remove-Item -LiteralPath $tempFile -Force -ErrorAction SilentlyContinue
|
|
344
407
|
}
|
|
345
408
|
}
|
|
409
|
+
if (-not $backupResolved) {
|
|
410
|
+
Write-Error "Error: could not safely recover the active plan pointer backup."
|
|
411
|
+
exit 1
|
|
412
|
+
}
|
|
413
|
+
if ($failureMessage) {
|
|
414
|
+
Write-Error "Error: could not set the active plan pointer: $failureMessage"
|
|
415
|
+
exit 1
|
|
416
|
+
}
|
|
346
417
|
Write-Output "Active plan set to: $PlanId"
|
|
347
418
|
Write-Output "Path: $PlanDir"
|
|
348
419
|
Write-Output ""
|