planning-with-files 3.20.7 → 3.22.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 +66 -61
- package/SKILL.md +1 -1
- 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.22.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.22.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.22.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.22.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.22.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.22.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.22.0/media/pwf-context-story-v1.mp4"><img src="https://raw.githubusercontent.com/OthmanAdi/planning-with-files/v3.22.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.22.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.22.0/docs/installation.md) | Plugin + SKILL.md + Hooks |
|
|
156
|
+
| Cursor | [Cursor Setup](https://github.com/OthmanAdi/planning-with-files/blob/v3.22.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.22.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.22.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.22.0/docs/gemini.md) | Skills + [Hooks](https://geminicli.com/docs/hooks/) |
|
|
160
|
+
| Kiro | [Kiro Setup](https://github.com/OthmanAdi/planning-with-files/blob/v3.22.0/docs/kiro.md) | [Agent Skills](https://kiro.dev/docs/skills/) |
|
|
161
|
+
| Codex | [Codex Setup](https://github.com/OthmanAdi/planning-with-files/blob/v3.22.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.22.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.22.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.22.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.22.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.22.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.22.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.22.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.22.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.22.0/docs/autohand.md) | `~/.autohand/skills/` or `.autohand/skills/` |
|
|
179
|
+
| Antigravity | [Antigravity Setup](https://github.com/OthmanAdi/planning-with-files/blob/v3.22.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.22.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.22.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.22.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.22.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,9 @@ 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.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). |
|
|
242
|
+
| **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). |
|
|
243
|
+
| **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
244
|
| **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
245
|
| **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
246
|
| **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 +329,7 @@ One hook fire measures 289ms wall-clock since the v3.6.0 optimization, down from
|
|
|
326
329
|
| **v2.7.0** | Gemini CLI support |
|
|
327
330
|
| **v2.2.0** | Session recovery, Windows PowerShell, OS-aware hooks |
|
|
328
331
|
|
|
329
|
-
[View all releases](https://github.com/OthmanAdi/planning-with-files/releases) · [CHANGELOG](https://github.com/OthmanAdi/planning-with-files/blob/v3.
|
|
332
|
+
[View all releases](https://github.com/OthmanAdi/planning-with-files/releases) · [CHANGELOG](https://github.com/OthmanAdi/planning-with-files/blob/v3.22.0/CHANGELOG.md)
|
|
330
333
|
|
|
331
334
|
> 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
335
|
|
|
@@ -364,7 +367,7 @@ One hook fire measures 289ms wall-clock since the v3.6.0 optimization, down from
|
|
|
364
367
|
|
|
365
368
|
*Built something? [Open an issue](https://github.com/OthmanAdi/planning-with-files/issues) to get listed!*
|
|
366
369
|
|
|
367
|
-
Full list of everyone who made this project better: [CONTRIBUTORS.md](https://github.com/OthmanAdi/planning-with-files/blob/v3.
|
|
370
|
+
Full list of everyone who made this project better: [CONTRIBUTORS.md](https://github.com/OthmanAdi/planning-with-files/blob/v3.22.0/CONTRIBUTORS.md).
|
|
368
371
|
|
|
369
372
|
</details>
|
|
370
373
|
|
|
@@ -384,7 +387,7 @@ Full list of everyone who made this project better: [CONTRIBUTORS.md](https://gi
|
|
|
384
387
|
| 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
388
|
| Hooks that quietly stop firing | `/plan-doctor` self-checks resolution, injection, attestation, install surfaces and per-fire latency |
|
|
386
389
|
|
|
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.
|
|
390
|
+
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.22.0/docs/long-running-agent-tasks.md).
|
|
388
391
|
|
|
389
392
|
### Installation routes
|
|
390
393
|
|
|
@@ -455,7 +458,7 @@ What each route actually ships:
|
|
|
455
458
|
| DeepSeek Harness `dsh plugin add` | yes, with the skill | **yes**, `/pwf`, `/pwf-status` | **yes**, plugin hooks incl. the gate |
|
|
456
459
|
| ClawHub / manual copy | yes | no | frontmatter hooks, see note |
|
|
457
460
|
|
|
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.
|
|
461
|
+
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.22.0/docs/installation.md#what-each-install-route-actually-ships).
|
|
459
462
|
|
|
460
463
|
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
464
|
|
|
@@ -472,7 +475,7 @@ One skill, three integration tiers. Know what your agent gets before you install
|
|
|
472
475
|
|
|
473
476
|
| Tier | Platforms | What you get |
|
|
474
477
|
|------|-----------|--------------|
|
|
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 |
|
|
478
|
+
| **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
479
|
| **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
480
|
| **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
481
|
|
|
@@ -492,7 +495,7 @@ Per-platform setup guides, discovery paths and sandbox runtimes are in the colla
|
|
|
492
495
|
- **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
496
|
- **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
497
|
|
|
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.
|
|
498
|
+
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.22.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.22.0/docs/long-running-agent-tasks.md).
|
|
496
499
|
|
|
497
500
|
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
501
|
|
|
@@ -533,7 +536,7 @@ Optional gated mode can request continuation only on a host that supports the re
|
|
|
533
536
|
|
|
534
537
|
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
538
|
|
|
536
|
-
Maintainer depth (hook architecture, dispatcher layout, parity tooling) lives in [AGENTS.md](https://github.com/OthmanAdi/planning-with-files/blob/v3.
|
|
539
|
+
Maintainer depth (hook architecture, dispatcher layout, parity tooling) lives in [AGENTS.md](https://github.com/OthmanAdi/planning-with-files/blob/v3.22.0/AGENTS.md) and [docs/](https://github.com/OthmanAdi/planning-with-files/tree/v3.22.0/docs/).
|
|
537
540
|
|
|
538
541
|
## Commands
|
|
539
542
|
|
|
@@ -697,12 +700,12 @@ Everything below is the proof and the reference half: the benchmarks and their l
|
|
|
697
700
|
|
|
698
701
|
## Benchmark Results
|
|
699
702
|
|
|
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.
|
|
703
|
+
> **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.22.0/docs/evals.md).
|
|
701
704
|
|
|
702
705
|
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
706
|
|
|
704
707
|
<p align="center">
|
|
705
|
-
<img src="https://raw.githubusercontent.com/OthmanAdi/planning-with-files/v3.
|
|
708
|
+
<img src="https://raw.githubusercontent.com/OthmanAdi/planning-with-files/v3.22.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
709
|
</p>
|
|
707
710
|
|
|
708
711
|
| Test | with_skill | without_skill |
|
|
@@ -714,17 +717,17 @@ Evaluated with Anthropic's [skill-creator](https://github.com/anthropics/skills/
|
|
|
714
717
|
|
|
715
718
|
### Recovery after a context wipe
|
|
716
719
|
|
|
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.
|
|
720
|
+
> **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.22.0/docs/evals.md#test-5-competitive-benchmark-v1-seven-planning-methods-head-to-head-2026-07-06-internal).
|
|
718
721
|
|
|
719
722
|
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
723
|
|
|
721
724
|
<p align="center">
|
|
722
|
-
<img src="https://raw.githubusercontent.com/OthmanAdi/planning-with-files/v3.
|
|
725
|
+
<img src="https://raw.githubusercontent.com/OthmanAdi/planning-with-files/v3.22.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
726
|
</p>
|
|
724
727
|
|
|
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.
|
|
728
|
+
**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.22.0/docs/benchmark/index.html) ([rendered view](https://htmlpreview.github.io/?https://github.com/OthmanAdi/planning-with-files/blob/master/docs/benchmark/index.html)).
|
|
726
729
|
|
|
727
|
-
[Full methodology and results](https://github.com/OthmanAdi/planning-with-files/blob/v3.
|
|
730
|
+
[Full methodology and results](https://github.com/OthmanAdi/planning-with-files/blob/v3.22.0/docs/evals.md) · [Technical write-up](https://github.com/OthmanAdi/planning-with-files/blob/v3.22.0/docs/article.md)
|
|
728
731
|
|
|
729
732
|
## File Structure
|
|
730
733
|
|
|
@@ -762,25 +765,25 @@ Every release maintains 20 tracked parity targets plus the gitignored ClawHub up
|
|
|
762
765
|
|
|
763
766
|
| Doc | What it covers |
|
|
764
767
|
|-----|----------------|
|
|
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/tree/v3.
|
|
768
|
+
| [docs/installation.md](https://github.com/OthmanAdi/planning-with-files/blob/v3.22.0/docs/installation.md) | Every install route, the route matrix, the trust prerequisite |
|
|
769
|
+
| [docs/quickstart.md](https://github.com/OthmanAdi/planning-with-files/blob/v3.22.0/docs/quickstart.md) | Your first planning session in 5 steps |
|
|
770
|
+
| [docs/workflow.md](https://github.com/OthmanAdi/planning-with-files/blob/v3.22.0/docs/workflow.md) | Day-to-day usage, plan lifecycle, topic handoffs |
|
|
771
|
+
| [docs/hermes.md](https://github.com/OthmanAdi/planning-with-files/blob/v3.22.0/docs/hermes.md) | Hermes Agent CLI and Desktop: install, `/pwf`, the `pre_verify` gate, Windows, migration from Claude Code |
|
|
772
|
+
| [docs/opencode.md](https://github.com/OthmanAdi/planning-with-files/blob/v3.22.0/docs/opencode.md) | OpenCode: the native plugin, `/pwf`, the `session.idle` gate, `pwf_*` tools |
|
|
773
|
+
| [docs/deepseek-harness.md](https://github.com/OthmanAdi/planning-with-files/blob/v3.22.0/docs/deepseek-harness.md) | DeepSeek Harness: the native plugin, profiles, `/pwf`, the turn-boundary gate, what DSH does not expose |
|
|
774
|
+
| [docs/evals.md](https://github.com/OthmanAdi/planning-with-files/blob/v3.22.0/docs/evals.md) | Full benchmark methodology, raw numbers, disclosed limits |
|
|
775
|
+
| [docs/troubleshooting.md](https://github.com/OthmanAdi/planning-with-files/blob/v3.22.0/docs/troubleshooting.md) | When hooks are quiet, plus `/plan-doctor` |
|
|
776
|
+
| [docs/claude-code-lost-context-after-compaction.md](https://github.com/OthmanAdi/planning-with-files/blob/v3.22.0/docs/claude-code-lost-context-after-compaction.md) | Recovering and preventing context loss from compaction |
|
|
777
|
+
| [docs/agent-forgets-plan-after-clear.md](https://github.com/OthmanAdi/planning-with-files/blob/v3.22.0/docs/agent-forgets-plan-after-clear.md) | The file-based fix when an agent forgets its plan after `/clear` |
|
|
778
|
+
| [docs/long-running-agent-tasks.md](https://github.com/OthmanAdi/planning-with-files/blob/v3.22.0/docs/long-running-agent-tasks.md) | Keeping a coding agent on track for hours: modes, gate, ledger |
|
|
779
|
+
| [MIGRATION.md](https://github.com/OthmanAdi/planning-with-files/blob/v3.22.0/MIGRATION.md) | v2 to v3 migration and host capability tiers |
|
|
780
|
+
| [SECURITY.md](https://github.com/OthmanAdi/planning-with-files/blob/v3.22.0/SECURITY.md) | Vulnerability reporting and hardening history |
|
|
781
|
+
| [CONTRIBUTING.md](https://github.com/OthmanAdi/planning-with-files/blob/v3.22.0/CONTRIBUTING.md) | How to contribute; authorship is preserved on merge |
|
|
782
|
+
| Per-platform guides | 19+ setup docs in [docs/](https://github.com/OthmanAdi/planning-with-files/tree/v3.22.0/docs/), linked from the [platform tables](#works-across-19-platforms) |
|
|
780
783
|
|
|
781
784
|
## Contributing
|
|
782
785
|
|
|
783
|
-
Contributions welcome. Start with [CONTRIBUTING.md](https://github.com/OthmanAdi/planning-with-files/blob/v3.
|
|
786
|
+
Contributions welcome. Start with [CONTRIBUTING.md](https://github.com/OthmanAdi/planning-with-files/blob/v3.22.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.22.0/CONTRIBUTORS.md), the CHANGELOG Thanks section, and the release notes.
|
|
784
787
|
|
|
785
788
|
## License
|
|
786
789
|
|
|
@@ -802,7 +805,7 @@ MIT License — feel free to use, modify, and distribute.
|
|
|
802
805
|
|
|
803
806
|
## Contributors
|
|
804
807
|
|
|
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.
|
|
808
|
+
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.22.0/CONTRIBUTORS.md).
|
|
806
809
|
|
|
807
810
|
<!-- contributor-portraits:start -->
|
|
808
811
|
<p align="center">
|
|
@@ -820,6 +823,8 @@ Code, documentation, and issue contributors. Select a portrait to open a GitHub
|
|
|
820
823
|
<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
824
|
<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
825
|
<a href="https://github.com/bailob" title="@bailob"><img src="https://github.com/bailob.png?size=56" width="48" height="48" alt="@bailob"></a>
|
|
826
|
+
<a href="https://github.com/SomSamantray" title="@SomSamantray"><img src="https://github.com/SomSamantray.png?size=56" width="48" height="48" alt="@SomSamantray"></a>
|
|
827
|
+
<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
828
|
<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
829
|
<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
830
|
<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 +853,7 @@ Code, documentation, and issue contributors. Select a portrait to open a GitHub
|
|
|
848
853
|
<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
854
|
<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
855
|
<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.
|
|
856
|
+
<a href="https://github.com/OthmanAdi/planning-with-files/blob/v3.22.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
857
|
<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
858
|
<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
859
|
<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 +886,6 @@ Code, documentation, and issue contributors. Select a portrait to open a GitHub
|
|
|
881
886
|
<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
887
|
<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
888
|
<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.
|
|
889
|
+
<a href="https://github.com/OthmanAdi/planning-with-files/blob/v3.22.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
890
|
</p>
|
|
886
891
|
<!-- 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.22.0"
|
|
32
32
|
---
|
|
33
33
|
|
|
34
34
|
# Planning with Files
|
package/package.json
CHANGED
|
@@ -1,6 +1,6 @@
|
|
|
1
1
|
{
|
|
2
2
|
"name": "planning-with-files",
|
|
3
|
-
"version": "3.
|
|
3
|
+
"version": "3.22.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 ""
|