@theglitchking/persistent-planning 2.0.0 → 3.0.1
This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
- package/.claude-plugin/marketplace.json +45 -0
- package/.claude-plugin/plugin.json +1 -1
- package/CHANGELOG.md +67 -0
- package/README.md +46 -35
- package/commands/start-atom.md +93 -0
- package/commands/start-planning.md +74 -24
- package/commands/start-task.md +83 -0
- package/docs/atom-granularity.md +156 -0
- package/docs/lg-mode.md +135 -0
- package/docs/workspace-json.md +85 -0
- package/package.json +6 -2
- package/scripts/detect-mode.sh +67 -0
- package/scripts/init-atom.sh +139 -0
- package/scripts/init-phase.sh +141 -0
- package/scripts/init-planning.sh +233 -0
- package/scripts/init-task.sh +118 -0
- package/scripts/lib/planning.sh +161 -0
- package/templates/lg/atom.md +45 -0
- package/templates/lg/notes.md +40 -0
- package/templates/lg/phase.md +42 -0
- package/templates/lg/task.md +54 -0
|
@@ -0,0 +1,156 @@
|
|
|
1
|
+
---
|
|
2
|
+
title: Atom Granularity (anti-pattern guide)
|
|
3
|
+
tier: standard
|
|
4
|
+
domains:
|
|
5
|
+
- planning
|
|
6
|
+
status: active
|
|
7
|
+
last_updated: 2026-05-07
|
|
8
|
+
version: 1.0.0
|
|
9
|
+
audience:
|
|
10
|
+
- developers
|
|
11
|
+
purpose: When to spawn a standalone atom file vs. add an inline atom checkbox to task.md. The atom layer is load-bearing for subagent hand-off; this doc keeps it from being misused.
|
|
12
|
+
---
|
|
13
|
+
|
|
14
|
+
# Atom Granularity
|
|
15
|
+
|
|
16
|
+
This is anti-pattern guidance for **lg-mode** planning. Sm-mode users can ignore this — sm has only `task_plan.md` with inline checkboxes throughout.
|
|
17
|
+
|
|
18
|
+
## The two kinds of atoms
|
|
19
|
+
|
|
20
|
+
In lg mode, "atom" can mean two different artifacts:
|
|
21
|
+
|
|
22
|
+
1. **Inline atom checkbox** in `task.md`:
|
|
23
|
+
```markdown
|
|
24
|
+
## Atoms
|
|
25
|
+
- [ ] Bump version to 3.0.0 in package.json
|
|
26
|
+
- [ ] Update CHANGELOG entry
|
|
27
|
+
- [ ] Run npm publish
|
|
28
|
+
```
|
|
29
|
+
|
|
30
|
+
2. **Standalone atom file** at `.planning/<phase>/<task>/atoms/<atom-slug>.md`:
|
|
31
|
+
```markdown
|
|
32
|
+
---
|
|
33
|
+
title: Bump version to 3.0.0
|
|
34
|
+
tier: plan
|
|
35
|
+
plan_kind: atom
|
|
36
|
+
parent: release-3-0-0
|
|
37
|
+
sequence: 1
|
|
38
|
+
status: ready
|
|
39
|
+
---
|
|
40
|
+
|
|
41
|
+
# Atom: Bump version to 3.0.0
|
|
42
|
+
|
|
43
|
+
## What to do
|
|
44
|
+
...
|
|
45
|
+
## Inputs
|
|
46
|
+
...
|
|
47
|
+
## Expected outputs
|
|
48
|
+
...
|
|
49
|
+
## Acceptance criteria
|
|
50
|
+
...
|
|
51
|
+
```
|
|
52
|
+
|
|
53
|
+
Both are valid. The question is **when to use which**.
|
|
54
|
+
|
|
55
|
+
## The rule
|
|
56
|
+
|
|
57
|
+
**Inline checkbox**: simple, self-contained step that doesn't need its own context file.
|
|
58
|
+
The active agent handles it directly while working through the task.
|
|
59
|
+
|
|
60
|
+
**Standalone atom file**: a step that will be **handed off to a subagent**.
|
|
61
|
+
Subagents need explicit inputs / outputs / acceptance criteria they can read
|
|
62
|
+
structured rather than parse from prose. Standalone atoms exist to make the
|
|
63
|
+
hand-off contract explicit and machine-readable.
|
|
64
|
+
|
|
65
|
+
## Examples
|
|
66
|
+
|
|
67
|
+
### ✅ Use inline checkbox
|
|
68
|
+
|
|
69
|
+
```markdown
|
|
70
|
+
## Atoms
|
|
71
|
+
- [ ] Bump package.json to 3.0.0
|
|
72
|
+
- [ ] Add CHANGELOG entry under "## [3.0.0]"
|
|
73
|
+
- [ ] Run `npm test` and confirm all pass
|
|
74
|
+
```
|
|
75
|
+
|
|
76
|
+
These are mechanical, self-evident, and don't need their own files. The active
|
|
77
|
+
agent reads task.md, executes them, and ticks them off.
|
|
78
|
+
|
|
79
|
+
### ✅ Use standalone atom file
|
|
80
|
+
|
|
81
|
+
```markdown
|
|
82
|
+
## Atoms
|
|
83
|
+
(see atoms/ for files)
|
|
84
|
+
```
|
|
85
|
+
|
|
86
|
+
With:
|
|
87
|
+
|
|
88
|
+
```
|
|
89
|
+
atoms/
|
|
90
|
+
├── 01-extract-embedder-to-shared-package.md
|
|
91
|
+
├── 02-refactor-vault-indexer-to-registry-driven.md
|
|
92
|
+
└── 03-add-corpora-json-schema.md
|
|
93
|
+
```
|
|
94
|
+
|
|
95
|
+
Each of these is a meaty, multi-step refactor with non-obvious context (which
|
|
96
|
+
files to touch, what shape the resulting code should take, how to verify).
|
|
97
|
+
Subagents picking these up need explicit briefing — that's what the standalone
|
|
98
|
+
atom file provides.
|
|
99
|
+
|
|
100
|
+
## Anti-patterns
|
|
101
|
+
|
|
102
|
+
### 🚫 Standalone atom for a one-liner
|
|
103
|
+
|
|
104
|
+
If the atom file ends up being mostly empty (`## What to do` is one sentence,
|
|
105
|
+
`## Acceptance criteria` is "ran the command"), it's overhead. Use an inline
|
|
106
|
+
checkbox.
|
|
107
|
+
|
|
108
|
+
### 🚫 Inline checkboxes for multi-step subagent work
|
|
109
|
+
|
|
110
|
+
If the checkbox is `- [ ] Refactor the indexer to support multi-corpus`, you've
|
|
111
|
+
pushed too much into one inline checkbox. A subagent picking up "refactor the
|
|
112
|
+
indexer" has no idea what scope, what files, or what success looks like. Spawn
|
|
113
|
+
a standalone atom (or several — one per logical refactor step).
|
|
114
|
+
|
|
115
|
+
### 🚫 Mixing — inline checkboxes that are subagent hand-offs
|
|
116
|
+
|
|
117
|
+
Don't have inline checkboxes that say "subagent: do X" without an atom file.
|
|
118
|
+
Either it's small enough for the active agent (inline) or it's big enough for
|
|
119
|
+
hand-off (atom file). The line between them is "is the subagent going to need
|
|
120
|
+
to ask questions?"
|
|
121
|
+
|
|
122
|
+
## Heuristic
|
|
123
|
+
|
|
124
|
+
Ask: **could a fresh subagent walk into this and complete the work without
|
|
125
|
+
asking the user a clarifying question?**
|
|
126
|
+
|
|
127
|
+
- If yes → inline checkbox is fine
|
|
128
|
+
- If no → spawn an atom file with explicit Inputs / Outputs / Acceptance
|
|
129
|
+
criteria
|
|
130
|
+
|
|
131
|
+
## Sequence semantics
|
|
132
|
+
|
|
133
|
+
Standalone atoms have explicit `sequence:` ordering. The planning MCP's
|
|
134
|
+
`next_atom(task)` verb returns the next `status: ready` atom in sequence order.
|
|
135
|
+
|
|
136
|
+
Sequential matches the single-agent reality. If you have N atoms in a task,
|
|
137
|
+
they hand off one at a time, in order. This eliminates filesystem race
|
|
138
|
+
conditions on claim and matches how agentic coding actually flows today.
|
|
139
|
+
|
|
140
|
+
If you have a genuinely parallel-atom workload (multiple subagents working
|
|
141
|
+
simultaneously on independent atoms within one task), that's a Phase 4.x
|
|
142
|
+
conversation — today, atoms hand off one at a time.
|
|
143
|
+
|
|
144
|
+
## Reopen semantics
|
|
145
|
+
|
|
146
|
+
A `done` atom can be reopened to `in_progress` if a follow-up correction is
|
|
147
|
+
needed. The frontmatter gets a `reopened_at: <iso-timestamp>` audit field.
|
|
148
|
+
Don't use this for "the work was wrong, redo it" — for that, the cleaner move
|
|
149
|
+
is to add a NEW atom that explains what to fix and why. Reopening is for "this
|
|
150
|
+
was almost done but missed a small detail."
|
|
151
|
+
|
|
152
|
+
## See also
|
|
153
|
+
|
|
154
|
+
- `/start-atom` — slash command to spawn a standalone atom file
|
|
155
|
+
- `templates/lg/atom.md` — the atom file template
|
|
156
|
+
- `templates/lg/task.md` — the task template (inline checkbox section)
|
package/docs/lg-mode.md
ADDED
|
@@ -0,0 +1,135 @@
|
|
|
1
|
+
---
|
|
2
|
+
title: Lg-Mode Layered Planning Guide
|
|
3
|
+
tier: guide
|
|
4
|
+
domains:
|
|
5
|
+
- planning
|
|
6
|
+
status: active
|
|
7
|
+
last_updated: 2026-05-07
|
|
8
|
+
version: 1.0.0
|
|
9
|
+
audience:
|
|
10
|
+
- developers
|
|
11
|
+
purpose: Full guide to lg-mode (large/team) persistent-planning — phase / task / atom / notes layered model, scheduling defaults, subagent contract, and integration with semantic-memory MCP.
|
|
12
|
+
---
|
|
13
|
+
|
|
14
|
+
# Lg-Mode (Layered Planning)
|
|
15
|
+
|
|
16
|
+
Lg mode was introduced in **persistent-planning 3.0.0**. It complements the original sm-mode flow without replacing it — solo devs and quick spikes still get the v2 single-task experience.
|
|
17
|
+
|
|
18
|
+
## When to use lg mode
|
|
19
|
+
|
|
20
|
+
- 2+ contributors over the last 90 days (auto-detected → lg)
|
|
21
|
+
- Multi-week or multi-task project with strategic boundaries (phases)
|
|
22
|
+
- Subagent hand-off needed for parallel or sequenced work
|
|
23
|
+
- Wanting the plan to integrate with semantic-memory's MCP (lg plans carry HEWTD frontmatter)
|
|
24
|
+
|
|
25
|
+
If none of those apply, sm mode is faster and lighter. You can always run `/start-planning --mode lg "name"` to switch.
|
|
26
|
+
|
|
27
|
+
## The four layers
|
|
28
|
+
|
|
29
|
+
| Layer | File | Purpose |
|
|
30
|
+
|---|---|---|
|
|
31
|
+
| **Phase** | `<phase-slug>/phase.md` | Strategic grouping; multi-task boundary |
|
|
32
|
+
| **Task** | `<phase-slug>/<task-slug>/task.md` | Bounded deliverable; mid-level summary |
|
|
33
|
+
| **Atom** | `<phase-slug>/<task-slug>/atoms/<atom-slug>.md` | Subagent hand-off unit |
|
|
34
|
+
| **Notes** | `<phase-slug>/notes.md` or `<task-slug>/notes.md` | Cross-cutting references |
|
|
35
|
+
|
|
36
|
+
Notes are scoped to either a phase or a task (or both). Notes are NOT part of the hierarchy — they're cross-cutting context.
|
|
37
|
+
|
|
38
|
+
## Directory layout
|
|
39
|
+
|
|
40
|
+
```
|
|
41
|
+
.planning/
|
|
42
|
+
├── .meta/
|
|
43
|
+
│ └── workspace.json # {mode: "lg", auto_detected: true, ...}
|
|
44
|
+
├── archive/
|
|
45
|
+
│ └── <archived-phase-slug>/ # phases moved here on status: archived
|
|
46
|
+
└── <phase-slug>/
|
|
47
|
+
├── phase.md # the phase
|
|
48
|
+
├── notes.md # phase-scoped notes
|
|
49
|
+
└── <task-slug>/
|
|
50
|
+
├── task.md # the task
|
|
51
|
+
├── notes.md # task-scoped notes
|
|
52
|
+
└── atoms/
|
|
53
|
+
├── <atom-slug>.md # sequence: 1
|
|
54
|
+
└── <atom-slug>.md # sequence: 2
|
|
55
|
+
```
|
|
56
|
+
|
|
57
|
+
A standalone task (without a phase) lives at `.planning/<task-slug>/` — same as sm mode but with HEWTD frontmatter and the new templates.
|
|
58
|
+
|
|
59
|
+
## Lifecycle status
|
|
60
|
+
|
|
61
|
+
Each layer has a status enum tracked in frontmatter:
|
|
62
|
+
|
|
63
|
+
- **phase.status**: `draft | active | paused | done | archived`
|
|
64
|
+
- **task.status**: same enum
|
|
65
|
+
- **atom.status**: `ready | in_progress | done | blocked`
|
|
66
|
+
|
|
67
|
+
Status transitions are explicit. Atoms additionally support **reopen** (`done → in_progress`) with a `reopened_at: <iso-timestamp>` audit field for legitimate post-completion fixes.
|
|
68
|
+
|
|
69
|
+
When a phase is marked `archived`, the entire `<phase-slug>/` directory moves to `archive/<phase-slug>/`. Atoms and tasks within move with it.
|
|
70
|
+
|
|
71
|
+
## Scheduling: dependencies-first, then parallelism
|
|
72
|
+
|
|
73
|
+
Tasks declare scheduling intent in frontmatter:
|
|
74
|
+
|
|
75
|
+
```yaml
|
|
76
|
+
plan_kind: task
|
|
77
|
+
parent: foundation
|
|
78
|
+
depends_on: [hewtd-schema-extension] # this task waits for that one
|
|
79
|
+
parallelizable: false # only true if no inter-deps
|
|
80
|
+
```
|
|
81
|
+
|
|
82
|
+
The planning MCP's `next_task(phase)` verb (added in semantic-memory 1.0) walks the `depends_on` graph and returns the next ready task respecting the order. Tasks with `parallelizable: true` and no inter-deps can be returned in any order — perfect for subagent teams picking up work concurrently.
|
|
83
|
+
|
|
84
|
+
**Atoms within a task default to sequential** (`sequence: 1, 2, 3...`). Atom-level parallelism is a Phase 4.x conversation.
|
|
85
|
+
|
|
86
|
+
## Subagent contract
|
|
87
|
+
|
|
88
|
+
Lg-mode plans are designed to be **read by subagents via semantic-memory MCP verbs**, not by parsing markdown. The contract:
|
|
89
|
+
|
|
90
|
+
- `read_phase(slug)`, `read_task(slug)`, `read_atom(slug)`, `read_notes(scope?)`
|
|
91
|
+
- `list_phases(status?)`, `list_tasks(phase?, status?)`, `list_atoms(task?, status?)`
|
|
92
|
+
- `next_task(phase, exclude_in_progress?)` — respects depends_on + parallelizable
|
|
93
|
+
- `next_atom(task)` — returns the next ready atom in sequence
|
|
94
|
+
- `update_atom_status(slug, status)`, `update_task_status(slug, status)`, `update_phase_status(slug, status)`
|
|
95
|
+
- `get_planning_context(scope, slug)` — bundles parent chain + sibling status + relevant notes for one read; the subagent's primary "load my context" verb
|
|
96
|
+
- `append_notes(scope, slug, content)` — append-only writer for notes during execution
|
|
97
|
+
|
|
98
|
+
These verbs ship in semantic-memory 1.0 (registered conditionally on the `plans` corpus being active). When semantic-memory is absent, persistent-planning falls back to filesystem-based reads — slash commands still work; subagent comprehension degrades.
|
|
99
|
+
|
|
100
|
+
## HEWTD frontmatter
|
|
101
|
+
|
|
102
|
+
Every layer carries HEWTD-aligned frontmatter (`tier: plan`). The `version` field is intentionally omitted — HEWTD 2.2.0 makes it conditionally optional for plan-tier docs (plans use lifecycle status, not semver).
|
|
103
|
+
|
|
104
|
+
This means lg-mode plans:
|
|
105
|
+
- Validate against HEWTD's metadata schema
|
|
106
|
+
- Are searchable + filterable by HEWTD's domain / load_priority / status fields
|
|
107
|
+
- Get indexed by semantic-memory's `plans` corpus for free
|
|
108
|
+
- Get drift-detected against the codebase by semantic-memory's drift verb (when both code corpus + plans corpus are active)
|
|
109
|
+
|
|
110
|
+
## Migration from v2 (sm)
|
|
111
|
+
|
|
112
|
+
Existing `.planning/<task-slug>/{task_plan.md, notes.md}` directories continue to work without changes. They're treated as sm-mode tasks. The first time you run `/start-planning` on a project that auto-detects to lg, a `.planning/.meta/workspace.json` is written and lg-mode flow begins for new plans. Existing v2 plans aren't migrated — they coexist.
|
|
113
|
+
|
|
114
|
+
To explicitly migrate a v2 plan to lg, manually:
|
|
115
|
+
1. `mkdir .planning/<phase-slug>` and create `phase.md` with the high-level goal
|
|
116
|
+
2. Move the existing `<task-slug>/` under it
|
|
117
|
+
3. Convert `task_plan.md` → `task.md` (rename + add HEWTD frontmatter)
|
|
118
|
+
|
|
119
|
+
## Slash commands
|
|
120
|
+
|
|
121
|
+
| Command | Mode | Creates |
|
|
122
|
+
|---|---|---|
|
|
123
|
+
| `/start-planning "<name>"` | sm or lg (auto-detect) | sm: task; lg: phase |
|
|
124
|
+
| `/start-planning "<name>" --mode lg` | lg (explicit) | phase |
|
|
125
|
+
| `/start-planning "<name>" --mode sm` | sm (explicit) | task |
|
|
126
|
+
| `/start-task "<name>" --parent <phase>` | lg only | task under phase |
|
|
127
|
+
| `/start-atom "<name>" --parent <task>` | lg only | atom under task |
|
|
128
|
+
|
|
129
|
+
## See also
|
|
130
|
+
|
|
131
|
+
- `docs/workspace-json.md` — workspace.json schema reference
|
|
132
|
+
- `docs/atom-granularity.md` — when to spawn an atom file vs. inline checkbox
|
|
133
|
+
- `templates/lg/{phase,task,atom,notes}.md` — frontmatter shapes
|
|
134
|
+
- `scripts/detect-mode.sh` — mode resolution logic
|
|
135
|
+
- `scripts/init-{phase,task,atom}.sh` — init script implementations
|
|
@@ -0,0 +1,85 @@
|
|
|
1
|
+
---
|
|
2
|
+
title: workspace.json schema
|
|
3
|
+
tier: standard
|
|
4
|
+
domains:
|
|
5
|
+
- planning
|
|
6
|
+
status: active
|
|
7
|
+
last_updated: 2026-05-07
|
|
8
|
+
version: 1.0.0
|
|
9
|
+
audience:
|
|
10
|
+
- developers
|
|
11
|
+
purpose: Document the .planning/.meta/workspace.json schema introduced in v3.0 for sm/lg mode tracking
|
|
12
|
+
---
|
|
13
|
+
|
|
14
|
+
# `workspace.json` schema (v3.0)
|
|
15
|
+
|
|
16
|
+
Introduced in persistent-planning **3.0.0**. Tracks per-project planning mode and
|
|
17
|
+
detection state. Lives at `.planning/.meta/workspace.json`.
|
|
18
|
+
|
|
19
|
+
## Schema
|
|
20
|
+
|
|
21
|
+
```json
|
|
22
|
+
{
|
|
23
|
+
"schema_version": "1.0",
|
|
24
|
+
"mode": "sm" | "lg",
|
|
25
|
+
"auto_detected": true | false,
|
|
26
|
+
"detected_contributors": <integer>,
|
|
27
|
+
"created_at": "<ISO 8601 timestamp>"
|
|
28
|
+
}
|
|
29
|
+
```
|
|
30
|
+
|
|
31
|
+
## Field reference
|
|
32
|
+
|
|
33
|
+
| Field | Type | Required | Description |
|
|
34
|
+
|---|---|---|---|
|
|
35
|
+
| `schema_version` | string | yes | Schema version of this file. Currently `"1.0"`. |
|
|
36
|
+
| `mode` | `"sm"` \| `"lg"` | yes | Active planning mode for this project. |
|
|
37
|
+
| `auto_detected` | boolean | yes | `true` if mode was determined by the heuristic, `false` if explicitly set via `--mode`. |
|
|
38
|
+
| `detected_contributors` | integer | yes (when `auto_detected=true`) | Distinct git author email count over the last 90 days at detection time. |
|
|
39
|
+
| `created_at` | string (ISO 8601) | yes | When this workspace.json was first written. |
|
|
40
|
+
|
|
41
|
+
## Mode determination
|
|
42
|
+
|
|
43
|
+
`detect-mode.sh` resolves the active mode using this precedence (first match wins):
|
|
44
|
+
|
|
45
|
+
1. **Explicit override**: if `workspace.json` exists with a `"mode"` field, that value wins.
|
|
46
|
+
2. **Auto-detect**: count distinct git author emails over the last 90 days. ≥ 2 → `"lg"`. Otherwise → `"sm"`.
|
|
47
|
+
3. **Fallback**: if neither applies (no git repo, git fails), default to `"sm"`.
|
|
48
|
+
|
|
49
|
+
The override is sticky — once written, future runs read `workspace.json` and skip
|
|
50
|
+
re-detection. Override the override by editing `workspace.json` directly or by passing
|
|
51
|
+
`--mode sm` / `--mode lg` to `/start-planning` (which rewrites the file).
|
|
52
|
+
|
|
53
|
+
## Mode behavior
|
|
54
|
+
|
|
55
|
+
### `sm` (small / solo)
|
|
56
|
+
- Single-task model — `.planning/<task-slug>/{task_plan.md, notes.md}`
|
|
57
|
+
- Identical to v2 behavior; existing v2 plans continue to work without migration
|
|
58
|
+
- No HEWTD frontmatter on plans (frontmatter is plain text)
|
|
59
|
+
- Single slash command: `/start-planning "Task name"`
|
|
60
|
+
|
|
61
|
+
### `lg` (large / team)
|
|
62
|
+
- Layered model: phase → task → atom + cross-cutting notes
|
|
63
|
+
- Directory layout: `.planning/<phase-slug>/<task-slug>/{task.md, notes.md, atoms/<atom-slug>.md}`
|
|
64
|
+
- HEWTD frontmatter on every layer (`tier: plan`, conditionally version-exempt per HEWTD 2.2.0)
|
|
65
|
+
- Three slash commands: `/start-planning` (phase), `/start-task --parent <phase>`, `/start-atom --parent <task>`
|
|
66
|
+
- Sequential atom hand-offs; tasks can declare `depends_on` + `parallelizable` for subagent team scheduling
|
|
67
|
+
|
|
68
|
+
## Backwards compatibility
|
|
69
|
+
|
|
70
|
+
Existing `.planning/<task-slug>/` folders without `.meta/` continue to work as `sm`.
|
|
71
|
+
Mode detection only writes `workspace.json` when `/start-planning` is run after v3.0
|
|
72
|
+
upgrade — pure read operations don't trigger writes.
|
|
73
|
+
|
|
74
|
+
## Manual editing
|
|
75
|
+
|
|
76
|
+
Safe to edit by hand. Common changes:
|
|
77
|
+
|
|
78
|
+
- Switch mode: change `"mode"`, set `"auto_detected": false`
|
|
79
|
+
- Reset auto-detection: delete the file; the next `/start-planning` will re-detect
|
|
80
|
+
|
|
81
|
+
## See also
|
|
82
|
+
|
|
83
|
+
- `scripts/detect-mode.sh` — the resolution logic
|
|
84
|
+
- `templates/lg/{phase,task,atom,notes}.md` — frontmatter shape per layer
|
|
85
|
+
- `~/workspace/the-glitch-kingdom/persistent-planning/.planning/layered-planning-with-mcp-and-hewtd-frontmatter/task_plan.md` — the meta-plan that drove this design
|
package/package.json
CHANGED
|
@@ -1,6 +1,6 @@
|
|
|
1
1
|
{
|
|
2
2
|
"name": "@theglitchking/persistent-planning",
|
|
3
|
-
"version": "
|
|
3
|
+
"version": "3.0.1",
|
|
4
4
|
"description": "Persistent markdown-based planning with task directories, progress tracking, and context engineering for multi-step Claude Code workflows",
|
|
5
5
|
"type": "module",
|
|
6
6
|
"bin": {
|
|
@@ -13,7 +13,8 @@
|
|
|
13
13
|
"bin/",
|
|
14
14
|
"commands/",
|
|
15
15
|
"hooks/",
|
|
16
|
-
"scripts/
|
|
16
|
+
"scripts/",
|
|
17
|
+
"templates/",
|
|
17
18
|
"skills/",
|
|
18
19
|
"docs/",
|
|
19
20
|
".claude-plugin/",
|
|
@@ -54,5 +55,8 @@
|
|
|
54
55
|
"dependencies": {
|
|
55
56
|
"@theglitchking/claude-plugin-runtime": "^0.1.0",
|
|
56
57
|
"commander": "^14.0.0"
|
|
58
|
+
},
|
|
59
|
+
"devDependencies": {
|
|
60
|
+
"@theglitchking/semantic-pages": "^0.10.0"
|
|
57
61
|
}
|
|
58
62
|
}
|
|
@@ -0,0 +1,67 @@
|
|
|
1
|
+
#!/bin/bash
|
|
2
|
+
###############################################################################
|
|
3
|
+
# detect-mode.sh - Sm/lg mode detection for persistent-planning v3.0
|
|
4
|
+
#
|
|
5
|
+
# Usage:
|
|
6
|
+
# bash scripts/detect-mode.sh [--explain]
|
|
7
|
+
#
|
|
8
|
+
# Output:
|
|
9
|
+
# "sm" or "lg" on stdout. With --explain, also prints a one-line decision
|
|
10
|
+
# banner to stderr explaining which signals fired.
|
|
11
|
+
#
|
|
12
|
+
# Heuristic:
|
|
13
|
+
# - If $CLAUDE_PROJECT_DIR/.planning/.meta/workspace.json exists with a
|
|
14
|
+
# "mode" field, that wins (override is sticky).
|
|
15
|
+
# - Otherwise count distinct git authors over the last 90 days. Two or
|
|
16
|
+
# more distinct emails → "lg". Otherwise "sm".
|
|
17
|
+
# - If the repo isn't a git repo or git fails for any reason, default
|
|
18
|
+
# to "sm" (the safer/less-surprising option for solo flows).
|
|
19
|
+
#
|
|
20
|
+
# Why this design:
|
|
21
|
+
# - Solo devs get the historical sm experience with zero ceremony.
|
|
22
|
+
# - Multi-contributor projects get the layered model surface immediately.
|
|
23
|
+
# - The decision banner avoids "magic" — the user sees what fired.
|
|
24
|
+
# - The workspace.json override means a single --mode flag sticks for
|
|
25
|
+
# all subsequent runs (no flag needed every time).
|
|
26
|
+
###############################################################################
|
|
27
|
+
set -e
|
|
28
|
+
|
|
29
|
+
EXPLAIN=0
|
|
30
|
+
if [[ "${1:-}" == "--explain" ]]; then
|
|
31
|
+
EXPLAIN=1
|
|
32
|
+
fi
|
|
33
|
+
|
|
34
|
+
PROJECT_ROOT="${CLAUDE_PROJECT_DIR:-$(pwd)}"
|
|
35
|
+
WORKSPACE_JSON="${PROJECT_ROOT}/.planning/.meta/workspace.json"
|
|
36
|
+
|
|
37
|
+
# 1. Override wins if workspace.json exists
|
|
38
|
+
if [[ -f "$WORKSPACE_JSON" ]]; then
|
|
39
|
+
# Naive jq-free read: grep the mode line. workspace.json is small/structured.
|
|
40
|
+
MODE_FROM_JSON=$(grep -oE '"mode"[[:space:]]*:[[:space:]]*"(sm|lg)"' "$WORKSPACE_JSON" | sed -E 's/.*"(sm|lg)".*/\1/')
|
|
41
|
+
if [[ "$MODE_FROM_JSON" == "sm" || "$MODE_FROM_JSON" == "lg" ]]; then
|
|
42
|
+
echo "$MODE_FROM_JSON"
|
|
43
|
+
if [[ $EXPLAIN -eq 1 ]]; then
|
|
44
|
+
echo "[mode] $MODE_FROM_JSON (from .planning/.meta/workspace.json)" >&2
|
|
45
|
+
fi
|
|
46
|
+
exit 0
|
|
47
|
+
fi
|
|
48
|
+
fi
|
|
49
|
+
|
|
50
|
+
# 2. Auto-detect via git author count over 90 days
|
|
51
|
+
DETECTED="sm"
|
|
52
|
+
CONTRIB=0
|
|
53
|
+
if command -v git >/dev/null 2>&1 && git -C "$PROJECT_ROOT" rev-parse --git-dir >/dev/null 2>&1; then
|
|
54
|
+
CONTRIB=$(git -C "$PROJECT_ROOT" log --since="90 days ago" --format='%ae' 2>/dev/null | sort -u | wc -l | tr -d ' ')
|
|
55
|
+
if [[ "$CONTRIB" -ge 2 ]]; then
|
|
56
|
+
DETECTED="lg"
|
|
57
|
+
fi
|
|
58
|
+
fi
|
|
59
|
+
|
|
60
|
+
echo "$DETECTED"
|
|
61
|
+
if [[ $EXPLAIN -eq 1 ]]; then
|
|
62
|
+
if [[ "$DETECTED" == "lg" ]]; then
|
|
63
|
+
echo "[mode] lg (auto-detected: $CONTRIB distinct git authors over the last 90 days; threshold ≥ 2)" >&2
|
|
64
|
+
else
|
|
65
|
+
echo "[mode] sm (auto-detected: $CONTRIB distinct git authors over the last 90 days; threshold for lg is ≥ 2)" >&2
|
|
66
|
+
fi
|
|
67
|
+
fi
|
|
@@ -0,0 +1,139 @@
|
|
|
1
|
+
#!/bin/bash
|
|
2
|
+
###############################################################################
|
|
3
|
+
# init-atom.sh - Create a new atom (subagent hand-off unit) under a task in lg mode
|
|
4
|
+
#
|
|
5
|
+
# Usage:
|
|
6
|
+
# bash scripts/init-atom.sh "Atom Name" --parent <task-slug>
|
|
7
|
+
#
|
|
8
|
+
# Creates:
|
|
9
|
+
# .planning/<phase-slug>/<task-slug>/atoms/<atom-slug>.md
|
|
10
|
+
#
|
|
11
|
+
# The atom's sequence number is auto-assigned: 1 + (max existing sequence in
|
|
12
|
+
# the same task's atoms/ directory). Atoms within a task default to sequential
|
|
13
|
+
# processing.
|
|
14
|
+
#
|
|
15
|
+
# --parent must be a task-slug. The phase is auto-resolved by walking the
|
|
16
|
+
# .planning/ tree to find the task.
|
|
17
|
+
###############################################################################
|
|
18
|
+
set -e
|
|
19
|
+
|
|
20
|
+
SCRIPT_DIR="$(cd "$(dirname "${BASH_SOURCE[0]}")" && pwd)"
|
|
21
|
+
source "${SCRIPT_DIR}/lib/planning.sh"
|
|
22
|
+
|
|
23
|
+
# Parse arguments
|
|
24
|
+
ATOM_NAME=""
|
|
25
|
+
PARENT_TASK=""
|
|
26
|
+
while [[ $# -gt 0 ]]; do
|
|
27
|
+
case "$1" in
|
|
28
|
+
--parent)
|
|
29
|
+
PARENT_TASK="$2"
|
|
30
|
+
shift 2
|
|
31
|
+
;;
|
|
32
|
+
-h|--help)
|
|
33
|
+
cat <<EOF
|
|
34
|
+
Usage: bash scripts/init-atom.sh "Atom Name" --parent <task-slug>
|
|
35
|
+
|
|
36
|
+
Examples:
|
|
37
|
+
bash scripts/init-atom.sh "Update zod schema" --parent hewtd-schema-extension
|
|
38
|
+
bash scripts/init-atom.sh "Add plan-tier tests" --parent hewtd-schema-extension
|
|
39
|
+
EOF
|
|
40
|
+
exit 0
|
|
41
|
+
;;
|
|
42
|
+
*)
|
|
43
|
+
if [[ -z "$ATOM_NAME" ]]; then
|
|
44
|
+
ATOM_NAME="$1"
|
|
45
|
+
fi
|
|
46
|
+
shift
|
|
47
|
+
;;
|
|
48
|
+
esac
|
|
49
|
+
done
|
|
50
|
+
|
|
51
|
+
if [[ -z "$ATOM_NAME" || -z "$PARENT_TASK" ]]; then
|
|
52
|
+
planning_err "Both atom name and --parent <task-slug> are required."
|
|
53
|
+
echo "Usage: bash scripts/init-atom.sh \"Atom Name\" --parent <task-slug>"
|
|
54
|
+
exit 1
|
|
55
|
+
fi
|
|
56
|
+
|
|
57
|
+
ATOM_SLUG=$(planning_slugify "$ATOM_NAME")
|
|
58
|
+
|
|
59
|
+
if [[ -z "$ATOM_SLUG" ]]; then
|
|
60
|
+
planning_err "Atom name must contain at least one alphanumeric character."
|
|
61
|
+
exit 1
|
|
62
|
+
fi
|
|
63
|
+
|
|
64
|
+
MODE=$(planning_mode)
|
|
65
|
+
if [[ "$MODE" != "lg" ]]; then
|
|
66
|
+
planning_err "Current mode is '$MODE' but init-atom.sh requires lg mode."
|
|
67
|
+
exit 1
|
|
68
|
+
fi
|
|
69
|
+
|
|
70
|
+
ROOT=$(planning_root)
|
|
71
|
+
PLANNING="$(planning_dir)"
|
|
72
|
+
TODAY=$(planning_today)
|
|
73
|
+
TEMPLATE_DIR="${ROOT}/templates/lg"
|
|
74
|
+
|
|
75
|
+
if [[ ! -d "$TEMPLATE_DIR" ]]; then
|
|
76
|
+
TEMPLATE_DIR="${SCRIPT_DIR}/../templates/lg"
|
|
77
|
+
fi
|
|
78
|
+
if [[ ! -d "$TEMPLATE_DIR" ]]; then
|
|
79
|
+
planning_err "Cannot locate templates/lg directory."
|
|
80
|
+
exit 1
|
|
81
|
+
fi
|
|
82
|
+
|
|
83
|
+
# Find the parent task — walk .planning/<phase>/<task>/task.md
|
|
84
|
+
TASK_DIR=""
|
|
85
|
+
for phase_path in "${PLANNING}"/*/; do
|
|
86
|
+
candidate="${phase_path%/}/${PARENT_TASK}"
|
|
87
|
+
if [[ -f "${candidate}/task.md" ]]; then
|
|
88
|
+
TASK_DIR="$candidate"
|
|
89
|
+
break
|
|
90
|
+
fi
|
|
91
|
+
done
|
|
92
|
+
|
|
93
|
+
if [[ -z "$TASK_DIR" ]]; then
|
|
94
|
+
planning_err "Parent task '${PARENT_TASK}' not found under .planning/<phase>/."
|
|
95
|
+
echo ""
|
|
96
|
+
echo "Available tasks:"
|
|
97
|
+
for phase_path in "${PLANNING}"/*/; do
|
|
98
|
+
phase_slug=$(basename "$phase_path")
|
|
99
|
+
[[ "$phase_slug" == ".meta" || "$phase_slug" == "archive" ]] && continue
|
|
100
|
+
for task_path in "${phase_path%/}"/*/; do
|
|
101
|
+
task_slug=$(basename "$task_path")
|
|
102
|
+
if [[ -f "${task_path}task.md" ]]; then
|
|
103
|
+
echo " --parent ${task_slug} (in phase: ${phase_slug})"
|
|
104
|
+
fi
|
|
105
|
+
done
|
|
106
|
+
done
|
|
107
|
+
exit 1
|
|
108
|
+
fi
|
|
109
|
+
|
|
110
|
+
ATOMS_DIR="${TASK_DIR}/atoms"
|
|
111
|
+
mkdir -p "$ATOMS_DIR"
|
|
112
|
+
|
|
113
|
+
# Auto-assign sequence: 1 + max existing sequence in the atoms/ dir
|
|
114
|
+
NEXT_SEQUENCE=1
|
|
115
|
+
if compgen -G "${ATOMS_DIR}/*.md" >/dev/null 2>&1; then
|
|
116
|
+
MAX_SEQ=$(grep -h '^sequence:' "${ATOMS_DIR}"/*.md 2>/dev/null | grep -oE '[0-9]+' | sort -n | tail -1)
|
|
117
|
+
if [[ -n "$MAX_SEQ" ]]; then
|
|
118
|
+
NEXT_SEQUENCE=$((MAX_SEQ + 1))
|
|
119
|
+
fi
|
|
120
|
+
fi
|
|
121
|
+
|
|
122
|
+
planning_log "Initializing atom: ${ATOM_NAME} (parent: ${PARENT_TASK}, sequence: ${NEXT_SEQUENCE})"
|
|
123
|
+
|
|
124
|
+
planning_render_and_log \
|
|
125
|
+
"${TEMPLATE_DIR}/atom.md" \
|
|
126
|
+
"${ATOMS_DIR}/${ATOM_SLUG}.md" \
|
|
127
|
+
"atom at ${ATOMS_DIR}/${ATOM_SLUG}.md (sequence: ${NEXT_SEQUENCE})" \
|
|
128
|
+
"ATOM_TITLE_PLACEHOLDER=${ATOM_NAME}" \
|
|
129
|
+
"TASK_SLUG_PLACEHOLDER=${PARENT_TASK}" \
|
|
130
|
+
"ATOM_DATE_PLACEHOLDER=${TODAY}" \
|
|
131
|
+
"ATOM_SEQUENCE_PLACEHOLDER=${NEXT_SEQUENCE}"
|
|
132
|
+
|
|
133
|
+
echo ""
|
|
134
|
+
planning_ok "Atom '${ATOM_NAME}' ready"
|
|
135
|
+
echo ""
|
|
136
|
+
echo "Next steps:"
|
|
137
|
+
echo " 1. Edit ${ATOMS_DIR}/${ATOM_SLUG}.md to define what to do, inputs, outputs, and acceptance criteria"
|
|
138
|
+
echo " 2. A subagent will pick up this atom when status: ready"
|
|
139
|
+
echo " 3. Status transitions: ready → in_progress → done (or → blocked)"
|