@zalom/plastic 1.0.0-beta.9 → 1.0.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 (107) hide show
  1. package/PLASTIC-reference.md +133 -0
  2. package/PLASTIC.md +398 -82
  3. package/README.md +99 -82
  4. package/agents/plastic-brainstorming.md +12 -9
  5. package/agents/plastic-enforcer.md +52 -12
  6. package/agents/plastic-executor.md +10 -10
  7. package/agents/plastic-future-intent-researcher.md +4 -8
  8. package/agents/plastic-intent-curator.md +12 -14
  9. package/agents/plastic-intent-discovery.md +35 -0
  10. package/agents/plastic-planner.md +15 -10
  11. package/agents/plastic-spec-specialist.md +15 -10
  12. package/bin/plastic.js +7 -3
  13. package/hooks/code-gate +10 -1
  14. package/hooks/hooks.json +28 -3
  15. package/hooks/lock-gate +21 -0
  16. package/hooks/retrieval-gate +10 -0
  17. package/hooks/savepoint-pre +10 -0
  18. package/hooks/statusline +48 -6
  19. package/package.json +2 -1
  20. package/scripts/agent-report +21 -0
  21. package/scripts/dashboard.rb +98 -23
  22. package/scripts/doctor.rb +232 -5
  23. package/scripts/hook-auto-arm +1 -1
  24. package/scripts/hook-bash-gate +22 -4
  25. package/scripts/hook-code-gate +11 -6
  26. package/scripts/hook-continue +17 -0
  27. package/scripts/hook-create-gate +45 -9
  28. package/scripts/hook-gate-check +24 -23
  29. package/scripts/hook-lock-gate +83 -0
  30. package/scripts/hook-retrieval-gate +148 -0
  31. package/scripts/hook-savepoint-pre +32 -0
  32. package/scripts/hook-session-start +1 -1
  33. package/scripts/insight-append +51 -0
  34. package/scripts/install.rb +44 -7
  35. package/scripts/lib/agent_models.rb +43 -0
  36. package/scripts/lib/bridge.rb +924 -84
  37. package/scripts/lib/dashboard_banner.rb +42 -0
  38. package/scripts/lib/hook_registry.rb +95 -0
  39. package/scripts/lib/insights.rb +86 -0
  40. package/scripts/lib/installer_core.rb +100 -60
  41. package/scripts/lib/link_suggestions.rb +319 -0
  42. package/scripts/lib/lock.rb +375 -0
  43. package/scripts/lib/power_tools.rb +22 -21
  44. package/scripts/lib/preflight.rb +79 -0
  45. package/scripts/lib/qmd_sync.rb +15 -0
  46. package/scripts/lib/retrieval_gate.rb +211 -0
  47. package/scripts/lib/worktree.rb +384 -0
  48. package/scripts/link-suggest +213 -0
  49. package/scripts/new-intent +9 -1
  50. package/scripts/plastic-lock +164 -0
  51. package/scripts/read-config +4 -0
  52. package/scripts/spawn-preamble +11 -3
  53. package/scripts/update.rb +16 -7
  54. package/skills/auto/SKILL.md +126 -19
  55. package/skills/auto/references/agent-architecture.md +7 -4
  56. package/skills/auto/references/agent-report-contract.md +36 -1
  57. package/skills/auto/references/end-tail.md +56 -0
  58. package/skills/auto/references/human-report-contract.md +55 -0
  59. package/skills/auto/references/tiers.md +77 -0
  60. package/skills/brainstorming/SKILL.md +7 -34
  61. package/skills/brainstorming/references/design-principles.md +49 -0
  62. package/skills/continuing/SKILL.md +26 -7
  63. package/skills/creating-intent/SKILL.md +13 -28
  64. package/skills/creating-project/SKILL.md +11 -74
  65. package/skills/creating-project/references/project-scaffolding.md +97 -0
  66. package/skills/creating-skills/SKILL.md +65 -0
  67. package/skills/creating-skills/evals/evals.json +108 -0
  68. package/skills/creating-skills/references/agents.md +168 -0
  69. package/skills/creating-skills/references/evals.md +41 -0
  70. package/skills/creating-skills/references/hooks.md +248 -0
  71. package/skills/creating-skills/references/progressive-disclosure.md +176 -0
  72. package/skills/creating-skills/references/scripts.md +166 -0
  73. package/skills/creating-skills/references/skills.md +165 -0
  74. package/skills/creating-skills/scripts/scaffold.rb +313 -0
  75. package/skills/dashboard/SKILL.md +13 -11
  76. package/skills/dashboard/references/classification.md +22 -0
  77. package/skills/doctor/SKILL.md +10 -7
  78. package/skills/executing-plan/SKILL.md +4 -4
  79. package/skills/humanizer/SKILL.md +39 -0
  80. package/skills/humanizer/evals/evals.json +70 -0
  81. package/skills/humanizer/references/always-on-snippet.md +9 -0
  82. package/skills/humanizer/references/examples.md +48 -0
  83. package/skills/install/SKILL.md +75 -84
  84. package/skills/intent-curator/SKILL.md +5 -1
  85. package/skills/intent-discovery/SKILL.md +47 -0
  86. package/skills/intent-starting/SKILL.md +130 -0
  87. package/skills/intent-starting/evals/evals.json +117 -0
  88. package/skills/intent-starting/references/boarding-matrix.md +35 -0
  89. package/skills/linking-intents/SKILL.md +48 -12
  90. package/skills/lock/SKILL.md +41 -0
  91. package/skills/managing-index/SKILL.md +6 -0
  92. package/skills/releasing/SKILL.md +44 -29
  93. package/skills/releasing/references/promotion-and-tagging.md +60 -0
  94. package/skills/roadmap/SKILL.md +51 -0
  95. package/skills/roadmap/references/file-format.md +91 -0
  96. package/skills/roadmap/references/operations.md +78 -0
  97. package/skills/uninstall/SKILL.md +29 -11
  98. package/skills/update/SKILL.md +34 -23
  99. package/skills/versions/SKILL.md +27 -12
  100. package/skills/writing-plans/SKILL.md +10 -88
  101. package/skills/writing-plans/references/plan-format.md +102 -0
  102. package/templates/config.yml +8 -0
  103. package/templates/outcome.md +3 -0
  104. package/templates/revisions.md +58 -0
  105. package/templates/roadmap.md +30 -0
  106. package/skills/writing-instructions/SKILL.md +0 -159
  107. package/skills/writing-instructions/references/agentskills-spec.md +0 -135
@@ -6,34 +6,70 @@ description: Use when creating connections between intents, the user says "link"
6
6
  # Linking Intents
7
7
 
8
8
  ## When to Use
9
- - During intent creation (automatic ask about related intents)
9
+ - During intent creation (automatic: ask about related intents)
10
10
  - User says "link", "connect", "relates to"
11
11
  - Agent discovers a relationship between intents during work
12
12
 
13
- ## Connection Types (Ranked by Strength)
13
+ ## Discovery and ranking are separate
14
14
 
15
- ### 1. Direct Links (Strongest)
16
- Explicit wikilinks in the `## Links` section. Bidirectional — add to both intents.
15
+ Two distinct steps, do not conflate them:
17
16
 
18
- ```markdown
19
- ## Links
20
- - [[1a]] research this plan is based on
21
- ```
17
+ 1. **Discovery** (finding candidate related intents) may use any tool: grep, find, ripgrep,
18
+ or QMD/Serena when present (QMD-first per the project rule). Discovery casts a wide net.
19
+ 2. **Ranking** the candidates is a CONTEXT-INFLUENCE judgement: read each candidate's `## Intent`
20
+ and `## Context` and ask whether that context actually informed this intent. Ranking is NOT a
21
+ structural metric (no shared-file or shared-symbol grading: on intent 90, matching whole files
22
+ flagged 35 intents because ~20 touch `bridge.rb`). It is NOT a similarity score either (QMD
23
+ relevance measures topic proximity, not influence). A script cannot make this call; an agent
24
+ does.
25
+
26
+ ## The three tiers (by context influence)
27
+
28
+ - **sources:** the foundational context that shaped this intent's CREATION (a split, an idea born
29
+ during development, a merge). Earns an edge. Decided by origin, never inferred.
30
+ - **chain:** the context that materially helps DELIVER this intent. HIGH bar: only the genuinely
31
+ delivery-moving intents, not everything in the same area. Earns an edge, reflected in `## Links`.
32
+ Worked example (intent 90): 79 created it so 79 is a source; 80 deferred the exact fix 90 makes,
33
+ so its context directly helps delivery and 80 is chain; 49/66/73 are same-area background, so
34
+ they get a shared tag and no link.
35
+ - **tags:** loose theme grouping for search. NOT a link.
36
+
37
+ **Timing.** The influence judgement happens at What/Why (and during upkeep), guided by this rule.
38
+ It does not wait for code to exist; it is reasoning over the candidate's context, not over a diff.
39
+
40
+ **Record the call.** For every edge an agent adds, store a rating (high / medium / low) plus a
41
+ one-line reason as a dated line under the intent file's `## Insights` section (per 96 D3, link
42
+ rationale lives in the intent file, not a side file). It stays out of frontmatter (graph only) and
43
+ out of the projected `## Links` label, so the audit trail never breaks the projection identity.
44
+
45
+ ## `## Links` is derived (never author it by hand)
46
+
47
+ `## Links` is a DERIVED view of `sources` then `chain`, not a place to write links. Never
48
+ hand-write a `## Links` line, and never auto-delete one. To add a link, add the frontmatter
49
+ edge (below), then let the projection regenerate the section (`scripts/project-links`).
50
+
51
+ Run `scripts/link-suggest <id>` to gather candidate intents WITH each one's Intent and Context (the
52
+ evidence you judge influence on) and to flag drift (a `## Links` line with no frontmatter edge
53
+ behind it). To record a confirmed edge plus its rating and reason, run it with
54
+ `--record <id> --edge <sources|chain> --rating <high|medium|low> --reason "..." --confirm`. It never
55
+ grades influence itself, never writes an edge without `--confirm`, and never deletes.
56
+
57
+ ## Connection Types (the frontmatter edges)
22
58
 
23
- ### 2. Sources (Backward)
59
+ ### 1. Sources (Backward)
24
60
  The `sources` array in frontmatter. The direct ascendant(s) this intent was created from / emerged from the lifecycle of (formation, not topic similarity), backward links to the work it was built out of:
25
61
  ```yaml
26
62
  sources: ["1a", "1a2"]
27
63
  ```
28
64
 
29
- ### 3. Chain (Forward)
65
+ ### 2. Chain (Forward)
30
66
  The `chain` array in frontmatter. What this intent spawned AND related-but-not-spawned successors it leads to, forward links to children, follow-on, and related work:
31
67
  ```yaml
32
68
  chain: ["1b1", "1b2"]
33
69
  ```
34
70
 
35
- ### 4. Tags (Weakest)
36
- Shared tags in frontmatter enable filtered discovery. Use `project-<name>` tags for project membership.
71
+ ### 3. Tags (for discovery, not links)
72
+ Shared tags in frontmatter enable filtered discovery. Use `project-<name>` tags for project membership. A shared tag is a loose theme grouping: it earns NO edge.
37
73
  ```yaml
38
74
  tags: [plastic, project-reddit-kb]
39
75
  ```
@@ -0,0 +1,41 @@
1
+ ---
2
+ name: lock
3
+ description: Inspect, repair, release, or reclaim an intent's delivery lock. Use when a lock-gate deny names /plastic-lock, when resuming interrupted work after a crash, reboot, or /tmp wipe, when a lock reads held or stale, or when the user says "fix the lock", "who holds the lock", or "reclaim the lock".
4
+ ---
5
+
6
+ # Plastic Lock
7
+
8
+ Command-only wrapper around `~/.plastic/scripts/plastic-lock`. The durable
9
+ delivery lock is a `delivery.lock` file in the intent directory: ownership is
10
+ session-keyed, liveness is a lease (the owner's hooks refresh the file mtime;
11
+ stale means the heartbeat is older than the TTL). The /tmp bridge is only a
12
+ cache; the lock file wins every disagreement.
13
+
14
+ ## Verbs
15
+
16
+ Run from the project (the intent resolves from this session's bridge), or pass
17
+ `--intent-dir` explicitly:
18
+
19
+ | Verb | What it does | When |
20
+ |---|---|---|
21
+ | `status` | Report the lock file, bridge cache, freshness, agreement | Always safe; run first |
22
+ | `fix` | Idempotent repair: rebuild lock + bridge from disk truth for THIS session. Never touches a fresh foreign lock | Interrupted work, corrupted state, /tmp wiped, legacy pid locks |
23
+ | `release` | Owner clears the lock | Ending or abandoning a boarding |
24
+ | `reclaim` | Explicit takeover of a STALE lock; appends an audit line to savepoint.md | The owner is gone and the lease expired |
25
+ | `delegate` | Owner registers a subagent session under the lock (`--delegate <session-id>`) | Auto-mode orchestration |
26
+
27
+ ```
28
+ ruby ~/.plastic/scripts/plastic-lock status
29
+ ruby ~/.plastic/scripts/plastic-lock fix --intent-dir <store>/<id>--<slug>
30
+ ruby ~/.plastic/scripts/plastic-lock reclaim --intent-dir <store>/<id>--<slug>
31
+ ruby ~/.plastic/scripts/plastic-lock delegate --delegate <subagent-session-id>
32
+ ```
33
+
34
+ ## Rules
35
+
36
+ - `fix` exits non-zero when another session holds a FRESH lock: back off, do
37
+ not retry in a loop. `status` shows the owner.
38
+ - `reclaim` refuses a fresh lock. There is no silent reclaim anywhere; every
39
+ takeover is audited in the intent's savepoint.md.
40
+ - Acquiring a lock for new work is NOT this skill's job: board through
41
+ `/plastic-intent-starting`, which calls the same repair internally.
@@ -41,6 +41,12 @@ Topic-based groupings. Manually curated. Create a new cluster when 3+ intents sh
41
41
  ### Completed
42
42
  All completed intents with dates. Links preserved, never deleted.
43
43
 
44
+ When you move an intent INTO Completed or Abandoned, run the closing acts of the transfer in the canonical End-tail order (see PLASTIC.md `## Delivery Isolation and the Single-Owner Lock`):
45
+
46
+ 1. Author a real `outcome.md` in the intent directory from `~/.plastic/templates/outcome.md`, with the frontmatter `disposition: delivered` for a completed intent or `disposition: abandoned` for an abandoned one. `outcome.md` is MANDATORY at every terminal, delivered and abandoned alike: on abandon it records the abandonment reason and replaces the scaffolded placeholder sentinel (never leave `outcome.md` a placeholder at a terminal).
47
+ 2. Stamp the terminal savepoint bookend (intent 81), so the ledger's last line records the disposition: `ruby -r ~/.plastic/scripts/lib/bridge -e 'Bridge.append_terminal_savepoint("<intent_dir>", "delivered")'` (use `"abandoned"` for an abandoned intent). Idempotent.
48
+ 3. Refresh the QMD index for that store LAST, after the terminal move and savepoint (no-op when QMD is absent), in the background so it never blocks: `ruby ~/.plastic/scripts/qmd-sync reindex --store <store-root> --async`.
49
+
44
50
  ## Workflow
45
51
 
46
52
  QMD-first (when available): when you need to locate a specific intent (to reclassify, flag, or
@@ -20,6 +20,7 @@ Project configuration drives the workflow - no hardcoded assumptions.
20
20
  - [ ] Run post-push actions (GitHub release, npm publish, etc.)
21
21
  - [ ] Verify release sync (npm dist-tag, GitHub "Latest", git tag all show the new version)
22
22
  - [ ] Complete active intent
23
+ - [ ] Clean up the intent's worktrees (merge-then-remove)
23
24
 
24
25
  ## Workflow
25
26
 
@@ -84,6 +85,12 @@ git merge <branch-name> --no-ff -m "feat: merge intent [ID] - [description]"
84
85
 
85
86
  Always `--no-ff` to preserve branch history in the merge commit.
86
87
 
88
+ **Worktree-isolated intents (intent 73c3).** A worktree-delivered intent's code lives on
89
+ `plastic/{id}--{slug}`, merged together with cleanup in step 9, not on a hand-made feature
90
+ branch. Do not delete the worktree before its branch is merged, or the work is lost. For
91
+ the full rationale and the already-merged-by-hand no-op case, read
92
+ `references/promotion-and-tagging.md`.
93
+
87
94
  ### 4. Bump Version
88
95
 
89
96
  Determine which files to update from project.yml:
@@ -94,8 +101,20 @@ Determine which files to update from project.yml:
94
101
 
95
102
  Update the version string in each file, then commit:
96
103
 
104
+ **Cut the CHANGELOG entry.** Before committing, edit `CHANGELOG.md` at the repo root so
105
+ the changelog change rides this same version-bump commit and reaches the tag. Write one
106
+ line in the existing shape:
107
+
108
+ `` `<version>` - shipped <date>; collected <intent-id> (<one-line summary>) ``
109
+
110
+ Prepend it as the first bullet under `## Released` (newest-first). If this version was
111
+ sitting under `## Unreleased`, move it out of that section and into `## Released`. Keep
112
+ the line intent-centric narrative (which intents the cut collected and why), NOT commit
113
+ detail: step 5's tag-message changelog and step 7's `gh release create --generate-notes`
114
+ already own the commit-level detail, so do not duplicate it here.
115
+
97
116
  ```bash
98
- git add <version-files>
117
+ git add <version-files> CHANGELOG.md
99
118
  git commit -m "chore: bump version to X.Y.Z - [one-line summary]"
100
119
  ```
101
120
 
@@ -207,6 +226,27 @@ A release IS a delivery. The active intent that drove this work must be complete
207
226
 
208
227
  **If no active intent exists for this release**, that itself is a problem - work happened outside the intent system. Log it and move on, but flag it.
209
228
 
229
+ ### 9. Clean Up the Intent's Worktrees (merge-then-remove)
230
+
231
+ A release is the merge-then-remove path for the intent's worktrees (intent 73c3): the
232
+ intent's code branch is merged back into the default branch BEFORE the worktree is removed.
233
+ Drive it through `Worktree.finish` with `merge: true`, which merges the code branch, then
234
+ removes both worktrees (code + paired store), prunes both repos, and clears the worktree block
235
+ from the bridge:
236
+
237
+ ```bash
238
+ ruby -r ~/.plastic/scripts/lib/worktree -r ~/.plastic/scripts/lib/bridge -e \
239
+ 'b = Bridge.discover_bridge(session: ENV["CLAUDE_CODE_SESSION_ID"], cwd: Dir.pwd); Worktree.finish(b, merge: true) if b'
240
+ ```
241
+
242
+ (Uses `discover_bridge`, not a bare session-keyed `Bridge.read`, because a session can own more
243
+ than one live bridge now — intent 131 — and `discover_bridge` resolves the right one for this cwd.)
244
+
245
+ Honor the worktree-cleanup rule: never leave an orphaned worktree, and run `git worktree
246
+ prune` in the affected repo if you hit a stale reference. For why this is the one place the
247
+ merge-vs-remove policy lands on merge, and the fail-open/idempotent guarantees of `finish`,
248
+ read `references/promotion-and-tagging.md`.
249
+
210
250
  ## Conventions
211
251
 
212
252
  - **Annotated tags only** - `git tag -a`, never lightweight tags
@@ -219,34 +259,9 @@ A release IS a delivery. The active intent that drove this work must be complete
219
259
  - **Verify sync** - after pushing, confirm npm dist-tag, GitHub "Latest", and the git tag all show the new version
220
260
  - **Branch cleanup** - delete merged feature branches: `git branch -d <branch>`
221
261
 
222
- ## Promotion
223
-
224
- To promote a release across channels, use `--promote`:
225
-
226
- ```bash
227
- plastic-releasing --promote beta # promotes current alpha → beta
228
- plastic-releasing --promote stable # promotes current beta → stable
229
- ```
230
-
231
- **Promotion rules:**
232
- - Linear only: alpha → beta → stable. Cannot skip channels.
233
- - `--promote beta`: reads version from `package.json`, changes `-alpha.N` suffix
234
- to `-beta.1`, publishes with `--tag beta`.
235
- - `--promote stable`: reads version from `package.json`, strips pre-release suffix
236
- entirely (e.g., `1.0.0-beta.3` → `1.0.0`), publishes to `latest`.
237
- - Version files are bumped and committed as in a normal release.
238
- - An annotated tag is created for the promoted version.
239
-
240
- ## Retroactive Tagging
241
-
242
- For repos without prior tags, tag historical releases:
243
-
244
- ```bash
245
- git tag -a v0.1.0 <commit-sha> -m "v0.1.0 - [description]"
246
- ```
247
-
248
- Use `git log --oneline` to find the right commits (look for version bump commits or major feature merges).
249
-
250
262
  ## References
251
263
 
264
+ - When promoting a pre-release across channels (`--promote beta`/`--promote stable`) or
265
+ tagging a historical release retroactively, read `references/promotion-and-tagging.md`
266
+ for the exact commands and rules first
252
267
  - Read `references/deprecations.md` for the full deprecation process, severity levels, deprecations.yml schema, and dismissal rules when adding or managing deprecations
@@ -0,0 +1,60 @@
1
+ # Promotion, Retroactive Tagging, and Worktree Merge Rationale
2
+
3
+ Occasional variant paths off the main release workflow: promoting a pre-release
4
+ across channels, tagging historical releases retroactively, and the deep rationale
5
+ for why the intent's worktree is merged before removal.
6
+
7
+ ## Table of Contents
8
+
9
+ - [Worktree merge-then-remove rationale](#worktree-merge-then-remove-rationale)
10
+ - [Promotion](#promotion)
11
+ - [Retroactive Tagging](#retroactive-tagging)
12
+
13
+ ## Worktree merge-then-remove rationale
14
+
15
+ **Worktree-isolated intents (intent 73c3).** When the intent was delivered in a Plastic
16
+ worktree (the bridge has a provisioned `worktree` block), its code lives on the branch
17
+ `plastic/{id}--{slug}` inside `<repo>/.claude/worktrees/{id}--{slug}`, not on a hand-made
18
+ feature branch. The merge-then-remove of that worktree is handled together with cleanup in
19
+ Workflow step 9, which merges `plastic/{id}--{slug}` into the default branch BEFORE removing the
20
+ worktree. If you already merged here by hand, step 9 is a clean no-op merge ("Already up to
21
+ date") and proceeds straight to removal. Do not delete the worktree before its branch is
22
+ merged, or the work is lost.
23
+
24
+ A release is the merge-then-remove path for the intent's worktrees. This is the one place
25
+ the merge-vs-remove policy lands on "merge": the intent's code branch (`plastic/{id}--{slug}`)
26
+ is merged back into the repo's default branch BEFORE the worktree is removed, so the
27
+ integrated work is never lost. (The disarm path in `plastic-auto`, by contrast, is a plain
28
+ remove because no release is merging the branch.)
29
+
30
+ `Worktree.finish` is fail-open and idempotent: a conflicting merge is aborted and logged (the
31
+ worktree is still removed rather than stranded), and a second call with the block already
32
+ cleared is a no-op.
33
+
34
+ ## Promotion
35
+
36
+ To promote a release across channels, use `--promote`:
37
+
38
+ ```bash
39
+ plastic-releasing --promote beta # promotes current alpha → beta
40
+ plastic-releasing --promote stable # promotes current beta → stable
41
+ ```
42
+
43
+ **Promotion rules:**
44
+ - Linear only: alpha → beta → stable. Cannot skip channels.
45
+ - `--promote beta`: reads version from `package.json`, changes `-alpha.N` suffix
46
+ to `-beta.1`, publishes with `--tag beta`.
47
+ - `--promote stable`: reads version from `package.json`, strips pre-release suffix
48
+ entirely (e.g., `1.0.0-beta.3` → `1.0.0`), publishes to `latest`.
49
+ - Version files are bumped and committed as in a normal release.
50
+ - An annotated tag is created for the promoted version.
51
+
52
+ ## Retroactive Tagging
53
+
54
+ For repos without prior tags, tag historical releases:
55
+
56
+ ```bash
57
+ git tag -a v0.1.0 <commit-sha> -m "v0.1.0 - [description]"
58
+ ```
59
+
60
+ Use `git log --oneline` to find the right commits (look for version bump commits or major feature merges).
@@ -0,0 +1,51 @@
1
+ ---
2
+ name: plastic-roadmap
3
+ description: Use when the user wants to plan a delivery batch, order waves of intents, ship a batch of tickets in one go, track a named collection of intents toward a goal, or asks for a "roadmap". Creates and maintains a roadmap file, a delivery-side collection of intents (the counterpart to a release), separate from INDEX.md status tracking.
4
+ ---
5
+
6
+ # Roadmap
7
+
8
+ A roadmap is a named, ordered, delivery-side collection of intents: the delivery-side counterpart
9
+ to a release (completion-side, `CHANGELOG.md`). It lives at `roadmaps/{slug}.md`, a sibling of
10
+ `INDEX.md` wherever `INDEX.md` lives: the global tier's `~/.plastic/roadmaps/` (beside
11
+ `~/.plastic/INDEX.md`), or a project's root, `~/.plastic/projects/{slug}/roadmaps/` (beside that
12
+ project's `INDEX.md` and `project.yml`). It never sits inside `store/`, which holds intent
13
+ directories, not project artifacts.
14
+
15
+ A roadmap file has four parts: a title/meta header, `## Goal` (prose), `## Waves` (ordered; entries
16
+ inside a wave are parallel-safe, waves run sequentially), and an append-only dated `## Log`. Each
17
+ wave entry mirrors that intent's status in `INDEX.md` (`queued`/`delivering`/`delivered`/
18
+ `abandoned`/`blocked`).
19
+
20
+ **`INDEX.md` is the single writer of intent status; on any conflict INDEX wins and the roadmap
21
+ entry is corrected to match.**
22
+
23
+ The skill operates on the file directly via Read/Edit; no helper script.
24
+
25
+ ## Verbs
26
+
27
+ | Verb | When | Mechanics |
28
+ |------|------|-----------|
29
+ | Create | user wants to start a new roadmap / plan a delivery batch | `references/operations.md#create` |
30
+ | Add / reorder entries | user wants to add intents to a wave or resequence waves | `references/operations.md#add--reorder-entries` |
31
+ | Sync status mirror | an entry's status may be stale against INDEX | `references/operations.md#sync-status-mirror` |
32
+ | Append log line | a roadmap event just happened (created, wave done, closed) | `references/operations.md#append-a-log-line` |
33
+ | Read / consume | a human or a coordinator needs the roadmap's current state | `references/operations.md#read--consume` |
34
+ | Close / archive | the roadmap's `## Goal` is reached | `references/operations.md#close--archive` |
35
+
36
+ See `references/file-format.md` for the exact entry-line shape, status vocabulary, checkbox/log
37
+ format, and a worked example. See `references/operations.md` for step-by-step mechanics of each
38
+ verb above.
39
+
40
+ ## Notes
41
+
42
+ - File location and the four-section shape are identical across tiers; do not invent a different
43
+ layout per project. The general rule: `roadmaps/` is a sibling of `INDEX.md`, wherever `INDEX.md`
44
+ lives.
45
+ - `## Goal` is a checkable prose condition read by a human or agent, not an executable checker.
46
+ - Wave entries render as checkboxes (`- [x] ... — delivered` / `- [ ] ... — <status>`); a human
47
+ reading cold should see shipped/running/next within a minute. `## Log` lines are one-sentence,
48
+ EM-to-CTO-voice, dated, and link each entry-intent's `outcome.md` (lossless-by-reference).
49
+ - Additive: this skill introduces no gate, lock, or hook, and does not change `INDEX.md`'s section
50
+ list or the intent frontmatter schema.
51
+ - Closing a roadmap moves it to `roadmaps/archived/{slug}.md` so `roadmaps/` lists only live ones.
@@ -0,0 +1,91 @@
1
+ # Roadmap File Format
2
+
3
+ ## Location
4
+
5
+ `roadmaps/{slug}.md`, a sibling of `INDEX.md`, wherever `INDEX.md` lives. For the global tier
6
+ that is `~/.plastic/roadmaps/{slug}.md` (beside `~/.plastic/INDEX.md`); for any project it is
7
+ that project's root, `~/.plastic/projects/{slug}/roadmaps/{slug}.md` (beside that project's
8
+ `INDEX.md` and `project.yml`). `roadmaps/` never sits inside `store/`: `store/` holds intent
9
+ directories, not project artifacts. Create the `roadmaps/` directory the first time a tier gets a
10
+ roadmap.
11
+
12
+ `roadmaps/` lists only live (open or in-flight) roadmaps. Once a roadmap's `## Goal` is reached,
13
+ its file moves to `roadmaps/archived/{slug}.md` (see Close/archive in `operations.md`); the
14
+ `archived/` subdirectory is scaffolded once, alongside `roadmaps/`, with a `.gitkeep`.
15
+
16
+ ## The four sections (in order)
17
+
18
+ 1. **Title/meta header** — `# Roadmap: <name>` plus a one-line meta sentence naming what the
19
+ roadmap delivers and which tier (project or global) it lives in.
20
+ 2. **`## Goal`** — a checkable prose condition: one or a few sentences a human or coordinator reads
21
+ to decide the roadmap is done. Not an executable checker, not a list of tasks.
22
+ 3. **`## Waves`** — ordered waves (`### Wave 1`, `### Wave 2`, ...). Entries inside a wave are
23
+ parallel-safe (can be dispatched together); waves run top to bottom, sequentially (wave 2 does
24
+ not start until wave 1's entries are no longer `queued`/`delivering`).
25
+ 4. **`## Log`** — append-only, dated, one line per event. Newest entry at the bottom. Never edit or
26
+ remove an existing log line.
27
+
28
+ ## Entry line shape
29
+
30
+ One line per intent, inside its wave, as a Markdown checkbox:
31
+
32
+ ```
33
+ - [x] <intent-id> <title> — delivered
34
+ - [ ] <intent-id> <title> — <status>
35
+ ```
36
+
37
+ `<intent-id>` and `<title>` match the intent's `INDEX.md` entry (terse, not a summary). The
38
+ checkbox is checked (`[x]`) once `<status>` is `delivered`, unchecked (`[ ]`) for every other
39
+ status. The checkbox is a rendering of the mirrored status token, not a second piece of state: a
40
+ human scanning the file sees at a glance what shipped (checked) and what has not (unchecked),
41
+ while the trailing token still carries the precise state (`queued`/`delivering`/`blocked`/
42
+ `abandoned`) when unchecked.
43
+
44
+ ## Status vocabulary
45
+
46
+ `queued` | `delivering` | `delivered` | `abandoned` | `blocked`
47
+
48
+ Status is a **mirror** of `INDEX.md`. `INDEX.md` is the single writer of intent status; on any
49
+ conflict INDEX wins and the roadmap entry (both its token and its checkbox) is corrected to match
50
+ it. The roadmap never sets a status that INDEX does not already reflect.
51
+
52
+ ## Log line shape
53
+
54
+ One line per event, starting `YYYY-MM-DD HH:MM UTC` (human-readable, sortable, zone-explicit so
55
+ same-day parallel deliveries can still be ordered), in plain-language EM-to-CTO voice: what shipped
56
+ and why it matters to a non-expert reader, no jargon or internal codenames, ending with a link to
57
+ that entry-intent's `outcome.md`:
58
+
59
+ ```
60
+ - <YYYY-MM-DD HH:MM UTC> <one plain-language sentence: what shipped, its impact> — see store/<id>--<slug>/outcome.md
61
+ ```
62
+
63
+ The log line never restates `outcome.md` detail; it points at it (lossless-by-reference). This
64
+ complements, and does not replace, `INDEX.md`'s `## Completed` section or `CHANGELOG.md`.
65
+
66
+ ## Worked example
67
+
68
+ ```
69
+ # Roadmap: Stable 1.0
70
+
71
+ Delivery-side collection of intents that close out the pre-1.0 hardening pass, plastic project store.
72
+
73
+ ## Goal
74
+ All intents below are delivered, the suite is green, and a 1.0.0 release is cut.
75
+
76
+ ## Waves
77
+ Entries in a wave are parallel-safe; waves run top to bottom. The checkbox tracks delivered/not;
78
+ the token after the em-dash carries the precise mirrored status (queued | delivering | delivered |
79
+ abandoned | blocked); INDEX wins on any conflict.
80
+
81
+ ### Wave 1
82
+ - [x] 121 Fix bash gate redirect parsing — delivered
83
+ - [ ] 130 Proportional cycle tiers — delivering
84
+
85
+ ### Wave 2
86
+ - [x] 124 Roadmap feature — delivered
87
+
88
+ ## Log
89
+ - 2026-07-06 14:32 UTC Shipped the bash-gate redirect fix so quoted arrows and heredoc trailers
90
+ stop blocking legitimate commits — see store/121--fix-bash-gate-redirect-parsing/outcome.md.
91
+ ```
@@ -0,0 +1,78 @@
1
+ # Roadmap Operations
2
+
3
+ All six verbs operate on the Markdown file directly (Read/Edit). No helper script exists or is
4
+ needed; the file is small and the edits are mechanical.
5
+
6
+ **Human-comprehension goal.** Every operation below should leave the file such that a cold reader
7
+ (no INDEX.md, no intent directories open) can answer "what's shipped, what's running, what's
8
+ next" in under a minute, just from this one file.
9
+
10
+ ## Create
11
+
12
+ 1. Pick a `slug` (kebab-case, descriptive) and a `title`.
13
+ 2. Resolve the tier root: the directory that holds `INDEX.md` (a project's root, beside
14
+ `project.yml`, or `~/.plastic/` for the global tier). `roadmaps/` is always a sibling of
15
+ `INDEX.md`, never inside `store/`. Create `roadmaps/` there if it does not exist yet.
16
+ 3. Copy `templates/roadmap.md` to `roadmaps/{slug}.md`.
17
+ 4. Fill the header (`# Roadmap: <title>` + the one-line meta) and write a real `## Goal` prose
18
+ condition.
19
+ 5. Add at least one `## Waves` wave with real entries (see Add / reorder below), each entry's
20
+ status mirroring that intent's current `INDEX.md` status.
21
+ 6. Append the first `## Log` line, a short `YYYY-MM-DD HH:MM UTC`-prefixed plain-language note
22
+ that the roadmap was created.
23
+
24
+ ## Add / reorder entries
25
+
26
+ - **Add**: append an entry line (`- <intent-id> <title> — <status>`) to the target wave. Pick the
27
+ intent's title and status straight from `INDEX.md`.
28
+ - **New wave**: add a new `### Wave N` heading after the last wave; entries in it are gated behind
29
+ every earlier wave's entries leaving `queued`/`delivering`.
30
+ - **Reorder**: move an entry line to a different wave, or move a `### Wave` heading (with its
31
+ entries) earlier or later. Reordering never changes an entry's status; it only changes when the
32
+ entry is eligible to run.
33
+ - After any add/reorder, append a `## Log` line describing the change (e.g.
34
+ `- <YYYY-MM-DD HH:MM UTC> added 132 to wave 2`).
35
+
36
+ ## Sync status mirror
37
+
38
+ 1. Read the intent's real status from `INDEX.md` (`## Active`, `## Future`, `## Completed`, or
39
+ `## Abandoned`).
40
+ 2. Compare to the roadmap entry's `<status>` token.
41
+ 3. If they differ, **INDEX wins**: rewrite the roadmap entry's status token to match INDEX, and
42
+ flip its checkbox in the same edit (`[x]` when the new status is `delivered`, `[ ]` otherwise).
43
+ Never edit INDEX.md from the roadmap skill; the roadmap is a mirror, not a second writer.
44
+ 4. Append a `## Log` line recording the change. When the new status is `delivered`, write the
45
+ one-line EM-to-CTO entry described in `file-format.md` (date, what shipped and its impact in
46
+ plain language, then a link to that intent's `outcome.md`). For other transitions, write a
47
+ short dated plain-language line (no codenames, no jargon).
48
+
49
+ ## Append a log line
50
+
51
+ - One line per event, starting `YYYY-MM-DD HH:MM UTC`, appended at the bottom of `## Log`. Never
52
+ edit or delete an existing line (append-only).
53
+ - Every line is plain language a non-expert can read, never a codename or a raw `field -> value`.
54
+ A delivery event follows the EM-to-CTO one-line shape with an `outcome.md` link (see
55
+ `file-format.md`); bookkeeping events (created, an intent added to a wave, a wave completed, a
56
+ roadmap closed) are short dated plain-language lines.
57
+
58
+ ## Read / consume
59
+
60
+ - A human reading the file gets the current picture directly: `## Goal` for the target, `## Waves`
61
+ for what is queued/delivering/delivered per wave (checkboxes give the shipped/not-shipped view at
62
+ a glance), `## Log` for a one-line, plain-language history with a link into each intent's
63
+ `outcome.md` for detail.
64
+ - A future coordinator (for example, an auto-mode dispatcher) reads `## Waves` top to bottom:
65
+ a wave is eligible to dispatch once every entry in the previous wave is no longer
66
+ `queued`/`delivering`; within an eligible wave, entries still `queued` are parallel-dispatchable.
67
+ Always re-sync against `INDEX.md` before dispatch decisions, since INDEX is the source of truth.
68
+
69
+ ## Close / archive
70
+
71
+ 1. Confirm the roadmap's `## Goal` prose condition is met (every entry `delivered` or explicitly
72
+ `abandoned` with a recorded reason, plus whatever else the goal states).
73
+ 2. Create `roadmaps/archived/` beside `roadmaps/` (both siblings of `INDEX.md`) if it does not
74
+ exist yet.
75
+ 3. Move the file: `roadmaps/{slug}.md` -> `roadmaps/archived/{slug}.md`. `roadmaps/` itself then
76
+ lists only live (open or in-flight) roadmaps.
77
+ 4. Append the final `## Log` line before or as part of the move:
78
+ `- <YYYY-MM-DD HH:MM UTC> roadmap closed`.
@@ -9,15 +9,21 @@ The installer tracks every file it writes in a manifest, so uninstall is exact a
9
9
  leaves no orphans. Prefer running it through the CLI; this skill wraps the same
10
10
  underlying uninstaller and adds reporting + verification.
11
11
 
12
+ ## Channel rule
13
+
14
+ If Plastic is installed, derive `<channel>` from `~/.plastic/VERSION`: a version containing
15
+ `-alpha` means `@alpha`, `-beta` means `@beta`, otherwise `@latest`. If not installed,
16
+ default to `@beta`. The user can always override with `--alpha` / `--beta` / `--latest`.
17
+
12
18
  ## Procedure
13
19
 
14
20
  ### Step 1: Run the uninstaller
15
21
 
16
22
  ```bash
17
- npx @zalom/plastic@latest uninstall --claude
23
+ npx -y @zalom/plastic@<channel> uninstall --claude
18
24
  ```
19
25
 
20
- (Use `--codex` / `--hermes` / `--all` to target other agents. `bunx` works too.)
26
+ (Use `--codex` / `--hermes` / `--all` to target other agents. `bunx -y @zalom/plastic@<channel> uninstall --claude` works too.)
21
27
 
22
28
  This removes, for the targeted agent:
23
29
  - all `~/.claude/skills/plastic-*/` skills
@@ -29,8 +35,8 @@ This removes, for the targeted agent:
29
35
 
30
36
  ### Step 2: Report removed vs left
31
37
 
32
- Relay the uninstaller's output to the user what was **removed** and what was
33
- **left in place**:
38
+ Relay the uninstaller's output to the user: what was **removed** and what was
39
+ **left in place**.
34
40
  - **Left:** `~/.plastic/` (intent store, history, projects) and any non-Plastic
35
41
  settings.json entries.
36
42
 
@@ -39,21 +45,33 @@ Relay the uninstaller's output to the user — what was **removed** and what was
39
45
  Tell the user to confirm:
40
46
 
41
47
  ```bash
42
- ls ~/.claude/skills | grep '^plastic-' # no output
43
- ls ~/.claude/hooks | grep '^plastic-' # no output
44
- grep -n plastic ~/.claude/settings.json # no plastic hook/plugin refs
48
+ ls ~/.claude/skills | grep '^plastic-' # -> no output
49
+ ls ~/.claude/hooks | grep '^plastic-' # -> no output
50
+ grep -n plastic ~/.claude/settings.json # -> no plastic hook/plugin refs
51
+ ```
52
+
53
+ ### Step 4: Report + offer the data decision
54
+
55
+ Emit the reporting block, using the Step 3 checks for the verification line:
56
+
57
+ ```
58
+ Plastic uninstall (<channel>)
59
+ Command: npx -y @zalom/plastic@<channel> uninstall --claude <flags>
60
+ Version: removed
61
+ Verification: <Step 3 results, or "clean">
45
62
  ```
46
63
 
47
- ### Step 4: Offer the data decision
64
+ Then:
48
65
 
49
66
  ```
50
67
  Plastic is uninstalled from [agent].
51
68
  Your intent store at ~/.plastic/ is untouched.
52
69
 
53
70
  Delete it too?
54
- a) Keep everything (recommended) re-install anytime with npx
55
- b) Delete everything now removes ~/.plastic/ entirely (irreversible)
71
+ a) Keep everything (recommended): re-install anytime with npx
72
+ b) Delete everything now: removes ~/.plastic/ entirely (irreversible)
56
73
  ```
57
74
 
58
- - **Keep:** "Your data is at ~/.plastic/. Re-install anytime with `npx @zalom/plastic@latest install --claude`."
75
+ - **Keep:** "Your data is at ~/.plastic/. Re-install anytime with
76
+ `npx -y @zalom/plastic@beta install --claude` (or your channel)."
59
77
  - **Delete:** run `rm -rf ~/.plastic/` and confirm.