@theglitchking/persistent-planning 3.1.0 → 3.4.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.
Files changed (63) hide show
  1. package/.claude-plugin/marketplace.json +2 -2
  2. package/.claude-plugin/plugin.json +1 -1
  3. package/.documentation/INDEX.md +15 -7
  4. package/.documentation/REGISTRY.md +2 -2
  5. package/.documentation/agents/INDEX.md +2 -2
  6. package/.documentation/agents/REGISTRY.md +2 -2
  7. package/.documentation/api/INDEX.md +2 -2
  8. package/.documentation/api/REGISTRY.md +2 -2
  9. package/.documentation/architecture/INDEX.md +5 -3
  10. package/.documentation/architecture/REGISTRY.md +8 -4
  11. package/.documentation/architecture/lg-mode.md +16 -0
  12. package/.documentation/architecture/lg-plan-artifact-lifecycle.md +104 -0
  13. package/.documentation/architecture/skill-linking-and-reclaim.md +84 -0
  14. package/.documentation/backups/INDEX.md +2 -2
  15. package/.documentation/backups/REGISTRY.md +2 -2
  16. package/.documentation/database/INDEX.md +2 -2
  17. package/.documentation/database/REGISTRY.md +2 -2
  18. package/.documentation/devops/INDEX.md +2 -2
  19. package/.documentation/devops/REGISTRY.md +2 -2
  20. package/.documentation/features/INDEX.md +2 -2
  21. package/.documentation/features/REGISTRY.md +2 -2
  22. package/.documentation/plans/INDEX.md +2 -2
  23. package/.documentation/plans/REGISTRY.md +2 -2
  24. package/.documentation/procedures/INDEX.md +4 -3
  25. package/.documentation/procedures/REGISTRY.md +6 -4
  26. package/.documentation/procedures/plan-completion-and-archive.md +34 -0
  27. package/.documentation/procedures/plugin-update-delivery.md +99 -0
  28. package/.documentation/quickstart/INDEX.md +2 -2
  29. package/.documentation/quickstart/REGISTRY.md +2 -2
  30. package/.documentation/reference/INDEX.md +10 -3
  31. package/.documentation/reference/REGISTRY.md +8 -4
  32. package/.documentation/reference/mandatory-frontmatter.md +71 -0
  33. package/.documentation/reference/skill-version-marker.md +70 -0
  34. package/.documentation/security/INDEX.md +2 -2
  35. package/.documentation/security/REGISTRY.md +2 -2
  36. package/.documentation/standards/INDEX.md +2 -2
  37. package/.documentation/standards/REGISTRY.md +2 -2
  38. package/.documentation/standards/mandatory-closing-phases.md +21 -1
  39. package/.documentation/testing/INDEX.md +2 -2
  40. package/.documentation/testing/REGISTRY.md +2 -2
  41. package/.documentation/testing/test-suite.md +38 -0
  42. package/.documentation/troubleshooting/INDEX.md +8 -8
  43. package/.documentation/troubleshooting/REGISTRY.md +20 -5
  44. package/.documentation/troubleshooting/plan-never-reads-complete.md +109 -0
  45. package/.documentation/troubleshooting/stale-skill-dir-drift.md +115 -0
  46. package/.documentation/workflows/INDEX.md +2 -2
  47. package/.documentation/workflows/REGISTRY.md +2 -2
  48. package/CHANGELOG.md +149 -0
  49. package/bin/persistent-planning.js +56 -6
  50. package/hooks/session-start.js +115 -3
  51. package/package.json +1 -1
  52. package/scripts/archive-plan.sh +3 -6
  53. package/scripts/init-atom.sh +7 -0
  54. package/scripts/init-phase.sh +58 -6
  55. package/scripts/init-planning.sh +18 -6
  56. package/scripts/init-task.sh +7 -0
  57. package/scripts/lib/planning.sh +122 -0
  58. package/scripts/lib/skill-link.js +177 -0
  59. package/scripts/link-skills.js +38 -0
  60. package/scripts/plan-status.sh +85 -10
  61. package/skills/persistent-planning/SKILL.md +5 -2
  62. package/templates/lg/phase.md +7 -4
  63. package/templates/lg/task.md +3 -2
@@ -3,7 +3,7 @@ title: Procedures Registry
3
3
  tier: reference
4
4
  domains: [procedures]
5
5
  status: active
6
- last_updated: '2026-08-31'
6
+ last_updated: '2026-09-04'
7
7
  version: '1.0.0'
8
8
  purpose: Quick reference for procedures documentation
9
9
  ---
@@ -16,23 +16,25 @@ purpose: Quick reference for procedures documentation
16
16
 
17
17
  | Metric | Value |
18
18
  |--------|-------|
19
- | Documents | 1 |
19
+ | Documents | 2 |
20
20
  | Category | features |
21
21
  | Load Priority | 6/10 |
22
22
 
23
23
  ## Active Documents
24
24
 
25
25
  - [Plan Completion and Archive](plan-completion-and-archive.md)
26
+ - [Plugin update delivery — what actually runs, and when](plugin-update-delivery.md)
26
27
 
27
28
  ## Recently Updated
28
29
 
30
+ - [Plugin update delivery — what actually runs, and when](plugin-update-delivery.md) - 2026-09-04
29
31
  - [Plan Completion and Archive](plan-completion-and-archive.md) - 2026-08-31
30
32
 
31
33
  ## By Status
32
34
 
33
35
  | Status | Count |
34
36
  |--------|-------|
35
- | active | 1 |
37
+ | active | 2 |
36
38
  | draft | 0 |
37
39
  | deprecated | 0 |
38
40
  | archived | 0 |
@@ -48,4 +50,4 @@ purpose: Quick reference for procedures documentation
48
50
 
49
51
  ---
50
52
 
51
- *Last updated: 2026-08-31*
53
+ *Last updated: 2026-09-04*
@@ -149,3 +149,37 @@ untouched and the update check still works.
149
149
  machine* got somewhere. Sharing it with every clone would grow the repository
150
150
  with reasoning nobody reads. If a particular plan is worth keeping, promote its
151
151
  findings into a real doc — which is what the mandatory documentation phase is for.
152
+
153
+
154
+ ## Completion also gates on mandatory tasks (3.3.0+)
155
+
156
+ "Every checkbox checked" is necessary but no longer sufficient. A plan containing any
157
+ task with `mandatory: true` whose `status:` is not `done` (or `archived`) reads
158
+ `in progress` however the boxes add up, and `archive-plan.sh` refuses it through the
159
+ same pre-flight — there is still exactly one implementation of the rule.
160
+
161
+ Plans with no `mandatory:` frontmatter are unaffected.
162
+
163
+ Symptoms and fixes: [Plan never reads complete](../troubleshooting/plan-never-reads-complete.md).
164
+
165
+
166
+ ## What counts, and what does not (3.3.1+)
167
+
168
+ - **Checkboxes** are body content and are counted anywhere *except* inside a fenced code
169
+ block. A quoted example is documentation, not work. An unterminated fence swallows the
170
+ rest of the file — the safe direction, since ambiguous content is not counted as
171
+ outstanding.
172
+ - **`status:` and `mandatory:`** are frontmatter fields and are read *only* from the
173
+ leading `---` block. They are never matched in prose, tables or fenced examples, which
174
+ is stricter than fence-stripping alone.
175
+
176
+
177
+ ## What is tracked (3.4.0+)
178
+
179
+ Active plans are committed; only `.planning/.archive/` is gitignored. v1.0.0 ignored the
180
+ whole `.planning/` tree, which contradicted this procedure, `CLAUDE.md`, and the archive
181
+ rationale itself — and in lg mode, chosen because a team exists, it guaranteed no
182
+ teammate ever received the plans.
183
+
184
+ Repos carrying the old blanket line keep it: the init scripts warn once and never rewrite
185
+ a user's `.gitignore`. Replace `.planning/` with `.planning/.archive/` to start sharing.
@@ -0,0 +1,99 @@
1
+ ---
2
+ title: Plugin update delivery — what actually runs, and when
3
+ tier: guide
4
+ domains:
5
+ - procedures
6
+ audience:
7
+ - developers
8
+ tags:
9
+ - migration
10
+ status: active
11
+ last_updated: '2026-09-04'
12
+ version: 1.0.0
13
+ purpose: What actually executes on each of the two distribution paths, why a marketplace
14
+ install never runs npm postinstall, and how to ship a fix that repairs existing installs.
15
+ estimated_read_time: 3 minutes
16
+ word_count: 539
17
+ last_validated: '2026-09-04'
18
+ backlinks: []
19
+ ---
20
+
21
+ # Plugin update delivery — what actually runs, and when
22
+
23
+ This package ships down two paths. They execute **different code at different times**,
24
+ and a fix delivered through the wrong one reaches nobody. Read this before shipping any
25
+ change that has to repair or migrate an existing install.
26
+
27
+ ## The two paths
28
+
29
+ | | npm package | Claude Code marketplace plugin |
30
+ |---|---|---|
31
+ | Installed at | `node_modules/@theglitchking/persistent-planning` | `~/.claude/plugins/cache/persistent-planning-marketplace/persistent-planning/<version>/` |
32
+ | Runs `postinstall`? | **yes** | **no** |
33
+ | `node_modules` present? | yes | **no — the plugin cache has none** |
34
+ | Runtime resolved from | local `node_modules` | shared `~/.claude/plugins/npm-cache/node_modules/` |
35
+ | Runs every session | SessionStart hook | SessionStart hook |
36
+
37
+ ## The constraint
38
+
39
+ **A marketplace install never runs npm postinstall.**
40
+
41
+ So `runPostinstall()` — and therefore the skill linker, the reclaim, and the version
42
+ marker — never execute on a marketplace update. A repair wired only into postinstall
43
+ ships to npm consumers and silently misses every marketplace consumer.
44
+
45
+ That is not a corner case. In issue #10 the broken population *was* the marketplace
46
+ consumers, precisely because they were the ones postinstall could never reach.
47
+
48
+ `runPostinstall()` also returns `null` when `INIT_CWD` equals the package root
49
+ (dev-in-place), which is why this repo has no `.claude/skills/persistent-planning` of
50
+ its own.
51
+
52
+ ## The rule
53
+
54
+ > **Anything that must reach an existing install goes through the SessionStart hook.**
55
+ > It is the only code that runs every session in both shapes.
56
+
57
+ `hooks/session-start.js` `autoRepair()` is the reference implementation:
58
+
59
+ - **Fast path first.** Two `lstat`s settle the common "nothing to do" case before any
60
+ work happens. Never make a healthy install pay.
61
+ - **Once per plugin version.** Stamped as `repairedSkillsForVersion` in
62
+ `.claude/persistent-planning.json`. Stamped *regardless of outcome*, so a repair that
63
+ cannot succeed does not retry every session; a later release moves the version and
64
+ gets one fresh attempt.
65
+ - **Policy-gated.** `auto` repairs, `nudge` warns only, `off` does nothing. A user who
66
+ turned updates off did not consent to filesystem mutation.
67
+ - **Spawned, not imported.** The migration runs in a child process with a timeout, so a
68
+ failure is contained.
69
+ - **Fails open.** Every path is wrapped. A broken migration must never cost someone
70
+ their session start.
71
+ - **One stdout write.** The runtime owns the single `SessionStart` JSON response and
72
+ exposes no append hook; a second response line is invalid. Merge into the existing
73
+ intercept.
74
+
75
+ ## Release checklist addendum
76
+
77
+ The version appears in **three** places that must match — `package.json`,
78
+ `.claude-plugin/plugin.json`, `.claude-plugin/marketplace.json` (both `metadata.version`
79
+ and the plugin entry). See `CLAUDE.md`.
80
+
81
+ Two more things to verify for a migration release:
82
+
83
+ 1. **The `files` array actually ships the new code.** v3.0.0 shipped broken because
84
+ `scripts/` and `templates/` were missing from it. Check with `npm pack --dry-run` and
85
+ grep the listing for the files you added.
86
+ 2. **Test from a marketplace-shaped fixture** — no `node_modules`, no postinstall — not
87
+ from `npm install`. A test that passes under `npm install` proves nothing about the
88
+ population that is actually broken. `tests/run.sh` builds exactly this fixture.
89
+
90
+ If a fix depends on a new `@theglitchking/claude-plugin-runtime`, it needs a runtime
91
+ publish, a dependency-range bump here, and a coordinated rollout — marketplace consumers
92
+ resolve the runtime from a shared cache, not a vendored copy. Preferring a change that
93
+ keeps the runtime unchanged is usually worth real effort; the issue #10 reclaim is
94
+ deliberately ordered *before* the runtime's linker for that reason.
95
+
96
+ ## Related
97
+
98
+ - [Skill linking and reclaim](../architecture/skill-linking-and-reclaim.md)
99
+ - [Stale skill directory](../troubleshooting/stale-skill-dir-drift.md)
@@ -3,7 +3,7 @@ title: Quickstart Documentation Index
3
3
  tier: reference
4
4
  domains: [quickstart]
5
5
  status: active
6
- last_updated: '2026-08-31'
6
+ last_updated: '2026-09-04'
7
7
  version: '1.0.0'
8
8
  purpose: Complete listing of quickstart documentation
9
9
  ---
@@ -39,4 +39,4 @@ This domain covers: quickstart, quick-start, getting-started, setup, install, in
39
39
 
40
40
  ---
41
41
 
42
- *Last updated: 2026-08-31*
42
+ *Last updated: 2026-09-04*
@@ -3,7 +3,7 @@ title: Quickstart Registry
3
3
  tier: reference
4
4
  domains: [quickstart]
5
5
  status: active
6
- last_updated: '2026-08-31'
6
+ last_updated: '2026-09-04'
7
7
  version: '1.0.0'
8
8
  purpose: Quick reference for quickstart documentation
9
9
  ---
@@ -48,4 +48,4 @@ purpose: Quick reference for quickstart documentation
48
48
 
49
49
  ---
50
50
 
51
- *Last updated: 2026-08-31*
51
+ *Last updated: 2026-09-04*
@@ -3,7 +3,7 @@ title: Reference Documentation Index
3
3
  tier: reference
4
4
  domains: [reference]
5
5
  status: active
6
- last_updated: '2026-08-31'
6
+ last_updated: '2026-09-04'
7
7
  version: '1.0.0'
8
8
  purpose: Complete listing of reference documentation
9
9
  ---
@@ -14,7 +14,7 @@ purpose: Complete listing of reference documentation
14
14
 
15
15
  ## Overview
16
16
 
17
- - **Total Documents:** 1
17
+ - **Total Documents:** 3
18
18
  - **Domain:** `reference/`
19
19
  - **Category:** development
20
20
  - **Load Priority:** 7/10
@@ -27,6 +27,13 @@ purpose: Complete listing of reference documentation
27
27
  |----------|--------|---------|-------|
28
28
  | [workspace.json schema](workspace-json.md) | active | 2026-05-07 | 358 |
29
29
 
30
+ ### References
31
+
32
+ | Document | Status | Updated | Words |
33
+ |----------|--------|---------|-------|
34
+ | [`mandatory:` task frontmatter](mandatory-frontmatter.md) | active | 2026-09-04 | 270 |
35
+ | [Skill version marker (`.version`)](skill-version-marker.md) | active | 2026-09-04 | 295 |
36
+
30
37
  ## Keywords
31
38
 
32
39
  This domain covers: schema, frontmatter, workspace.json, field, enum, cli, flags, reference, contract
@@ -39,4 +46,4 @@ This domain covers: schema, frontmatter, workspace.json, field, enum, cli, flags
39
46
 
40
47
  ---
41
48
 
42
- *Last updated: 2026-08-31*
49
+ *Last updated: 2026-09-04*
@@ -3,7 +3,7 @@ title: Reference Registry
3
3
  tier: reference
4
4
  domains: [reference]
5
5
  status: active
6
- last_updated: '2026-08-31'
6
+ last_updated: '2026-09-04'
7
7
  version: '1.0.0'
8
8
  purpose: Quick reference for reference documentation
9
9
  ---
@@ -16,23 +16,27 @@ purpose: Quick reference for reference documentation
16
16
 
17
17
  | Metric | Value |
18
18
  |--------|-------|
19
- | Documents | 1 |
19
+ | Documents | 3 |
20
20
  | Category | development |
21
21
  | Load Priority | 7/10 |
22
22
 
23
23
  ## Active Documents
24
24
 
25
+ - [`mandatory:` task frontmatter](mandatory-frontmatter.md)
26
+ - [Skill version marker (`.version`)](skill-version-marker.md)
25
27
  - [workspace.json schema](workspace-json.md)
26
28
 
27
29
  ## Recently Updated
28
30
 
31
+ - [`mandatory:` task frontmatter](mandatory-frontmatter.md) - 2026-09-04
32
+ - [Skill version marker (`.version`)](skill-version-marker.md) - 2026-09-04
29
33
  - [workspace.json schema](workspace-json.md) - 2026-05-07
30
34
 
31
35
  ## By Status
32
36
 
33
37
  | Status | Count |
34
38
  |--------|-------|
35
- | active | 1 |
39
+ | active | 3 |
36
40
  | draft | 0 |
37
41
  | deprecated | 0 |
38
42
  | archived | 0 |
@@ -48,4 +52,4 @@ purpose: Quick reference for reference documentation
48
52
 
49
53
  ---
50
54
 
51
- *Last updated: 2026-08-31*
55
+ *Last updated: 2026-09-04*
@@ -0,0 +1,71 @@
1
+ ---
2
+ title: '`mandatory:` task frontmatter'
3
+ tier: reference
4
+ domains:
5
+ - reference
6
+ audience:
7
+ - developers
8
+ tags: []
9
+ status: active
10
+ last_updated: '2026-09-04'
11
+ version: 1.0.0
12
+ purpose: >-
13
+ Contract for the mandatory: task frontmatter field — who sets it, what reads it, and
14
+ why absent must mean no enforcement for legacy plans.
15
+ estimated_read_time: 2 minutes
16
+ word_count: 270
17
+ last_validated: '2026-09-04'
18
+ backlinks: []
19
+ ---
20
+
21
+ # `mandatory:` task frontmatter
22
+
23
+ A boolean in an lg task's frontmatter marking it as one of the phase's mandatory
24
+ closing tasks. It is what turns "a phase cannot be done until both closers are done"
25
+ from a sentence in a template into something `plan-status.sh` enforces.
26
+
27
+ ```yaml
28
+ ---
29
+ title: Validate success through comprehensive testing
30
+ plan_kind: task
31
+ status: draft
32
+ depends_on: []
33
+ parallelizable: false
34
+ mandatory: true
35
+ ---
36
+ ```
37
+
38
+ ## Contract
39
+
40
+ | | |
41
+ |---|---|
42
+ | **Lives in** | `<phase>/<task>/task.md` frontmatter |
43
+ | **Default** | `false` — `templates/lg/task.md` ships it explicitly |
44
+ | **Set to `true` by** | `init-phase.sh`, on the two scaffolded closers only |
45
+ | **Read by** | `scripts/plan-status.sh` (`unfinished_mandatory()`) |
46
+ | **Effect** | a plan with any `mandatory: true` task whose `status` is neither `done` nor `archived` cannot read `COMPLETE`, however the checkboxes add up |
47
+ | **Absent means** | no enforcement — legacy behavior, exactly as before |
48
+
49
+ ## Why absent must mean "no enforcement"
50
+
51
+ Plans created before 3.3.0 have no closer directories and no `mandatory:` frontmatter.
52
+ Treating absence as `true`, or inferring closers by title, would retroactively reopen
53
+ finished plans — worse than the bug this field fixes. The gate is strictly additive and
54
+ the test suite asserts a legacy plan still reads `COMPLETE`.
55
+
56
+ ## Where it is enforced — once
57
+
58
+ `plan-status.sh` is the single implementation of "is this plan done?" per `CLAUDE.md`.
59
+ `archive-plan.sh` inherits the gate through its existing pre-flight call rather than
60
+ carrying a second copy of the rule, and `--complete` / `--nudge` — which the
61
+ SessionStart hook and `archive-plan.sh` consume — honour it too.
62
+
63
+ Ticking a checkbox is **not** sufficient for a mandatory task. The task's own `status:`
64
+ must be `done`. That distinction is the whole point: a closer that was ticked but never
65
+ performed is exactly the failure this guards.
66
+
67
+ ## Related
68
+
69
+ - [lg plan artifact lifecycle](../architecture/lg-plan-artifact-lifecycle.md)
70
+ - [Plan completion and archive](../procedures/plan-completion-and-archive.md)
71
+ - [Plan never reads complete](../troubleshooting/plan-never-reads-complete.md)
@@ -0,0 +1,70 @@
1
+ ---
2
+ title: Skill version marker (`.version`)
3
+ tier: reference
4
+ domains:
5
+ - reference
6
+ audience:
7
+ - developers
8
+ tags: []
9
+ status: active
10
+ last_updated: '2026-09-04'
11
+ version: 1.0.0
12
+ purpose: >-
13
+ Contract for the .version marker written beside SKILL.md — who writes it, when it
14
+ is deliberately not written, and why it is the secondary drift signal.
15
+ estimated_read_time: 2 minutes
16
+ word_count: 295
17
+ last_validated: '2026-09-04'
18
+ backlinks: []
19
+ ---
20
+
21
+ # Skill version marker (`.version`)
22
+
23
+ A one-line file beside `SKILL.md` recording which package version a linked skill came
24
+ from. Written by `scripts/link-skills.js`, read by `scripts/lib/skill-link.js`.
25
+
26
+ ```
27
+ .claude/skills/persistent-planning/.version -> "3.2.0\n"
28
+ ```
29
+
30
+ ## Contract
31
+
32
+ | | |
33
+ |---|---|
34
+ | **Path** | `.claude/skills/<skill-name>/.version` |
35
+ | **Contents** | the package's `version`, plus a trailing newline |
36
+ | **Written by** | `writeVersionMarkers()`, after the linker runs |
37
+ | **Read by** | `readSkillVersion(consumerRoot, name)` — returns the string, or `null` |
38
+ | **Written when** | the skill resolves to `symlink-ok` |
39
+ | **Never written when** | the destination is a real directory |
40
+ | **Absent means** | unknown — never "current" |
41
+
42
+ ## Why only healthy symlinks are stamped
43
+
44
+ Stamping a real directory would write "3.2.0" into a frozen pre-3.1.0 copy and mark
45
+ stale code as current — defeating the check it exists to support. A real directory is
46
+ left unstamped precisely so it reads as unknown.
47
+
48
+ Because a healthy skill dir is a symlink into the package, the marker written through
49
+ it lands in the package and is correct for free.
50
+
51
+ ## Why not `package.json`
52
+
53
+ A `package.json` inside a skill directory invites npm to treat that directory as a
54
+ package and changes module resolution underneath it. A plain `.version` file cannot.
55
+ `skills/*/.version` is gitignored so a local install cannot commit a stray marker.
56
+
57
+ ## This is the secondary signal
58
+
59
+ The **primary** drift signal is structural: is `.claude/skills/<name>` a symlink into
60
+ this package? A real directory is always drift, because nothing in the current system
61
+ creates one. That check needs no marker and cannot itself go stale.
62
+
63
+ The marker answers the follow-up question — *how far behind is it* — and is the only
64
+ signal available on install shapes where a symlink is impossible (Windows without
65
+ developer mode, some CI checkouts). Treat a missing marker as unknown, never as fine.
66
+
67
+ ## Related
68
+
69
+ - [Skill linking and reclaim](../architecture/skill-linking-and-reclaim.md)
70
+ - [Stale skill directory](../troubleshooting/stale-skill-dir-drift.md)
@@ -3,7 +3,7 @@ title: Security Documentation Index
3
3
  tier: reference
4
4
  domains: [security]
5
5
  status: active
6
- last_updated: '2026-08-31'
6
+ last_updated: '2026-09-04'
7
7
  version: '1.0.0'
8
8
  purpose: Complete listing of security documentation
9
9
  ---
@@ -40,4 +40,4 @@ This domain covers: security, auth, authentication, authorization, oauth, jwt, k
40
40
 
41
41
  ---
42
42
 
43
- *Last updated: 2026-08-31*
43
+ *Last updated: 2026-09-04*
@@ -3,7 +3,7 @@ title: Security Registry
3
3
  tier: reference
4
4
  domains: [security]
5
5
  status: active
6
- last_updated: '2026-08-31'
6
+ last_updated: '2026-09-04'
7
7
  version: '1.0.0'
8
8
  purpose: Quick reference for security documentation
9
9
  ---
@@ -35,4 +35,4 @@ purpose: Quick reference for security documentation
35
35
 
36
36
  ---
37
37
 
38
- *Last updated: 2026-08-31*
38
+ *Last updated: 2026-09-04*
@@ -3,7 +3,7 @@ title: Standards Documentation Index
3
3
  tier: reference
4
4
  domains: [standards]
5
5
  status: active
6
- last_updated: '2026-08-31'
6
+ last_updated: '2026-09-04'
7
7
  version: '1.0.0'
8
8
  purpose: Complete listing of standards documentation
9
9
  ---
@@ -40,4 +40,4 @@ This domain covers: standard, standards, convention, conventions, pattern, patte
40
40
 
41
41
  ---
42
42
 
43
- *Last updated: 2026-08-31*
43
+ *Last updated: 2026-09-04*
@@ -3,7 +3,7 @@ title: Standards Registry
3
3
  tier: reference
4
4
  domains: [standards]
5
5
  status: active
6
- last_updated: '2026-08-31'
6
+ last_updated: '2026-09-04'
7
7
  version: '1.0.0'
8
8
  purpose: Quick reference for standards documentation
9
9
  ---
@@ -50,4 +50,4 @@ purpose: Quick reference for standards documentation
50
50
 
51
51
  ---
52
52
 
53
- *Last updated: 2026-08-31*
53
+ *Last updated: 2026-09-04*
@@ -25,7 +25,7 @@ Every plan this plugin creates ends with the same two units of work, in the same
25
25
  order, no exceptions:
26
26
 
27
27
  1. **Validate success through comprehensive testing**
28
- 2. **Documentation pass — create / update / deprecate docs**
28
+ 2. **Documentation pass — create / update / deprecate as many docs as needed to capture what was done, where it lives, how to troubleshoot it**
29
29
 
30
30
  They are seeded into the templates so an agent never has to remember them, and
31
31
  they are marked `MANDATORY` in the artifact itself so an agent re-reading the
@@ -123,3 +123,23 @@ npm test
123
123
  | Closing phases are no longer last | Work appended below them | Move the new phases above the pair and renumber |
124
124
  | `npm test` fails on "documentation phase is last" | A template edit added a checkbox after the pair, or reworded the pair | Restore the ordering in `scripts/init-planning.sh` / `templates/lg/phase.md` |
125
125
  | Phase marked `done` with closing tasks unchecked | Skipped the gate | Not done — finish both, then mark the phase |
126
+
127
+
128
+ ## How they are enforced (3.3.0+)
129
+
130
+ In lg mode the two closers are no longer only checkbox lines. `init-phase.sh` scaffolds
131
+ each as a real task directory — `task.md` with `mandatory: true`, `notes.md`, `atoms/`,
132
+ and seeded atoms — so they are addressable artifacts like every other task.
133
+
134
+ Two mechanisms keep the rule true rather than advisory:
135
+
136
+ - **Ordering by construction.** `init-task.sh` inserts every new task *above* the first
137
+ MANDATORY entry, so the closers cannot be pushed out of last place by adding work.
138
+ - **Completion gated on status.** `plan-status.sh` refuses `COMPLETE` while any
139
+ `mandatory: true` task's own `status:` is not `done`. Ticking its checkbox is not
140
+ enough — a closer that was ticked but never performed is exactly the failure being
141
+ guarded.
142
+
143
+ Legacy plans without `mandatory:` frontmatter keep their previous behavior; the gate is
144
+ strictly additive. See [`mandatory:` frontmatter](../reference/mandatory-frontmatter.md)
145
+ and [lg plan artifact lifecycle](../architecture/lg-plan-artifact-lifecycle.md).
@@ -3,7 +3,7 @@ title: Testing Documentation Index
3
3
  tier: reference
4
4
  domains: [testing]
5
5
  status: active
6
- last_updated: '2026-08-31'
6
+ last_updated: '2026-09-04'
7
7
  version: '1.0.0'
8
8
  purpose: Complete listing of testing documentation
9
9
  ---
@@ -39,4 +39,4 @@ This domain covers: test, testing, tests, unit, unit-test, integration, integrat
39
39
 
40
40
  ---
41
41
 
42
- *Last updated: 2026-08-31*
42
+ *Last updated: 2026-09-04*
@@ -3,7 +3,7 @@ title: Testing Registry
3
3
  tier: reference
4
4
  domains: [testing]
5
5
  status: active
6
- last_updated: '2026-08-31'
6
+ last_updated: '2026-09-04'
7
7
  version: '1.0.0'
8
8
  purpose: Quick reference for testing documentation
9
9
  ---
@@ -48,4 +48,4 @@ purpose: Quick reference for testing documentation
48
48
 
49
49
  ---
50
50
 
51
- *Last updated: 2026-08-31*
51
+ *Last updated: 2026-09-04*
@@ -86,3 +86,41 @@ never failed is not known to test anything.
86
86
  | Tests pass locally, lg mode broken for installed users | `templates/` or `scripts/` missing from the `files` array in `package.json` | Add them, verify with `npm pack` before publishing |
87
87
 
88
88
  That last row is not hypothetical — it is exactly how v3.0.0 shipped broken.
89
+
90
+
91
+ ## The marketplace-shaped fixture
92
+
93
+ The skill-reclaim tests (issue #10) build a consumer workspace with **no
94
+ `node_modules`**, mirroring a Claude Code marketplace install — the shape that never
95
+ runs npm postinstall, and the shape that was actually broken. Driving the SessionStart
96
+ hook against it proves a repair lands with no `npm install` anywhere in the path.
97
+
98
+ A test that only passes under `npm install` proves nothing about that population. See
99
+ [Plugin update delivery](../procedures/plugin-update-delivery.md).
100
+
101
+ ## Assert by diff, not by feature-grep
102
+
103
+ When checking that generated output matches a template, `diff` it. During triage of
104
+ issue #10 a keyword count (`phases: 6 | closers: 2`) reported two known-stale copies as
105
+ healthy; only `diff` exposed the 23-line gap, including an entirely missing
106
+ `## On Completion` block.
107
+
108
+ Likewise, assertions against the SessionStart payload parse it as JSON rather than
109
+ string-matching. The failure being guarded is an invalid second response line — a
110
+ substring check would pass on malformed output.
111
+
112
+
113
+ ## Assert after mutation, not at render
114
+
115
+ The ordering rule for the mandatory closers went unenforced for a long time while a
116
+ test claimed to cover it. That test asserted the order of two checkbox lines in a
117
+ *freshly rendered template* — which can never be wrong, because nothing had happened to
118
+ it yet.
119
+
120
+ Assertions about an invariant must mutate the plan first: create a phase, add several
121
+ tasks, then check the closers are still last. The issue #12 block does this throughout,
122
+ including against a hand-reordered, partially-checked, annotated list.
123
+
124
+ The same instinct applies elsewhere in this suite: verify generated output by `diff`
125
+ rather than keyword count, and parse the SessionStart payload as JSON rather than
126
+ string-matching it.
@@ -3,7 +3,7 @@ title: Troubleshooting Documentation Index
3
3
  tier: reference
4
4
  domains: [troubleshooting]
5
5
  status: active
6
- last_updated: '2026-08-31'
6
+ last_updated: '2026-09-04'
7
7
  version: '1.0.0'
8
8
  purpose: Complete listing of troubleshooting documentation
9
9
  ---
@@ -14,20 +14,20 @@ purpose: Complete listing of troubleshooting documentation
14
14
 
15
15
  ## Overview
16
16
 
17
- - **Total Documents:** 0
17
+ - **Total Documents:** 2
18
18
  - **Domain:** `troubleshooting/`
19
19
  - **Category:** advanced
20
20
  - **Load Priority:** 6/10
21
21
 
22
22
  ## Documents
23
23
 
24
- *No documents in this domain yet.*
24
+ ### Guides
25
25
 
26
- To add a document:
26
+ | Document | Status | Updated | Words |
27
+ |----------|--------|---------|-------|
28
+ | [A plan won't read COMPLETE](plan-never-reads-complete.md) | active | 2026-09-04 | 264 |
29
+ | [Stale skill directory — commands run frozen code](stale-skill-dir-drift.md) | active | 2026-09-04 | 403 |
27
30
 
28
- 1. Create a markdown file in this directory
29
- 2. Add YAML frontmatter with required metadata
30
- 3. Run `npx hit-em-with-the-docs integrate <file>`
31
31
  ## Keywords
32
32
 
33
33
  This domain covers: troubleshooting, troubleshoot, debug, debugging, issue, issues, problem, problems, error, errors
@@ -40,4 +40,4 @@ This domain covers: troubleshooting, troubleshoot, debug, debugging, issue, issu
40
40
 
41
41
  ---
42
42
 
43
- *Last updated: 2026-08-31*
43
+ *Last updated: 2026-09-04*