@zalom/plastic 1.9.0 → 1.10.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 (92) hide show
  1. package/PLASTIC.md +23 -8
  2. package/README.md +15 -4
  3. package/agents/plastic-enforcer.md +3 -2
  4. package/agents/plastic-intent-discovery.md +7 -0
  5. package/bin/plastic.js +17 -8
  6. package/hooks/auto-arm +2 -2
  7. package/hooks/bash-gate +1 -1
  8. package/hooks/check-update +1 -1
  9. package/hooks/continue +2 -2
  10. package/hooks/edit-gates +1 -1
  11. package/hooks/future-intent-check +2 -2
  12. package/hooks/gate-check +3 -3
  13. package/hooks/power-tools +1 -1
  14. package/hooks/session-start +1 -1
  15. package/package.json +1 -1
  16. package/scripts/codex-hook +50 -106
  17. package/scripts/doctor.rb +132 -1080
  18. package/scripts/exec-worktree +103 -0
  19. package/scripts/hash-intent +1 -1
  20. package/scripts/hook-bash-gate +19 -0
  21. package/scripts/hook-code-gate +4 -1
  22. package/scripts/hook-continue +2 -2
  23. package/scripts/hook-create-gate +6 -3
  24. package/scripts/hook-gate-check +17 -0
  25. package/scripts/hook-links-gate +4 -1
  26. package/scripts/hook-lock-gate +7 -3
  27. package/scripts/hook-savepoint-pre +4 -1
  28. package/scripts/hook-session-start +21 -15
  29. package/scripts/lib/apply_patch_envelope.rb +46 -13
  30. package/scripts/lib/bridge.rb +83 -15
  31. package/scripts/lib/codex_edit_gates.rb +138 -0
  32. package/scripts/lib/doctor_core.rb +1087 -0
  33. package/scripts/lib/edit_gates.rb +61 -5
  34. package/scripts/lib/exec_worktree.rb +325 -0
  35. package/scripts/lib/harness_text.rb +57 -0
  36. package/scripts/lib/hook_registry.rb +32 -28
  37. package/scripts/lib/installer_core.rb +67 -7
  38. package/scripts/lib/lock.rb +196 -47
  39. package/scripts/lib/ruby_probe.rb +60 -0
  40. package/scripts/lib/scaffold_intent.rb +392 -0
  41. package/scripts/lib/spec_header.rb +83 -0
  42. package/scripts/lib/start_intent.rb +296 -0
  43. package/scripts/lib/verify_intent.rb +262 -0
  44. package/scripts/lib/worktree.rb +15 -1
  45. package/scripts/link-suggest +1 -1
  46. package/scripts/maintenance-run +5 -5
  47. package/scripts/migrate-to-global +2 -2
  48. package/scripts/restore-intent-v1 +1 -1
  49. package/scripts/scaffold-intent +120 -0
  50. package/scripts/start-intent +89 -0
  51. package/scripts/verify-intent +73 -0
  52. package/skills/agent-advisor/SKILL.md +5 -5
  53. package/skills/auto/SKILL.md +42 -32
  54. package/skills/auto/references/agent-architecture.md +1 -1
  55. package/skills/auto/references/agent-report-contract.md +1 -1
  56. package/skills/auto/references/human-report-contract.md +22 -3
  57. package/skills/auto/references/tiers.md +24 -2
  58. package/skills/conventions/references/completion-and-done.md +3 -0
  59. package/skills/conventions/references/gates-and-enforcement.md +28 -12
  60. package/skills/conventions/references/locks-and-worktrees.md +3 -3
  61. package/skills/conventions/references/tiers-and-dispatch.md +7 -6
  62. package/skills/dashboard/SKILL.md +1 -1
  63. package/skills/doctor/SKILL.md +6 -5
  64. package/skills/doctor/references/gates-stuck-detection.md +13 -8
  65. package/skills/doctor/report.md +1 -1
  66. package/skills/install/SKILL.md +1 -1
  67. package/skills/intent-brainstorming/SKILL.md +0 -2
  68. package/skills/intent-creating/SKILL.md +6 -6
  69. package/skills/intent-creating/references/lifecycle.md +1 -1
  70. package/skills/intent-discovering/SKILL.md +10 -3
  71. package/skills/intent-ending/SKILL.md +8 -7
  72. package/skills/intent-executing/SKILL.md +27 -19
  73. package/skills/intent-grilling/SKILL.md +5 -3
  74. package/skills/intent-planning/SKILL.md +7 -3
  75. package/skills/intent-researching/SKILL.md +0 -2
  76. package/skills/intent-starting/SKILL.md +10 -2
  77. package/skills/project-creating/SKILL.md +0 -2
  78. package/skills/project-creating/references/project-scaffolding.md +1 -1
  79. package/skills/releasing/SKILL.md +1 -1
  80. package/skills/releasing/references/promotion-and-tagging.md +14 -8
  81. package/skills/releasing/references/release-lines.md +1 -1
  82. package/skills/skill-creating/SKILL.md +5 -2
  83. package/skills/store-indexing/SKILL.md +8 -5
  84. package/skills/store-indexing/references/zettelkasten-linking.md +1 -1
  85. package/skills/tutorial/references/track-1-guided.md +2 -2
  86. package/skills/tutorial/references/track-2-auto.md +9 -6
  87. package/skills/tutorial/references/track-3-projects-and-roadmaps.md +1 -1
  88. package/skills/uninstall/SKILL.md +6 -9
  89. package/templates/agents.md +12 -12
  90. package/templates/config.yml +6 -7
  91. package/templates/index.md +6 -3
  92. package/templates/spec.md +1 -1
@@ -43,7 +43,7 @@ shared one still is.
43
43
  The bridge resolves the current session in a fixed precedence: the stdin `session_id` first, then
44
44
  the `CLAUDE_CODE_SESSION_ID` environment variable, then a derived key when neither is present. A
45
45
  bridge is purge-eligible by terminal state, not by age: it is removed only once its intent is no
46
- longer active, never on a timer. See `docs/internals.md` for depth.
46
+ longer active, never on a timer. See [`docs/internals.md`](https://github.com/zalom/plastic/blob/main/docs/internals.md) for depth.
47
47
 
48
48
  The delivery lock arbitrates at the whole-intent grain: it decides who may work
49
49
  an intent at all. Underneath it, a per-artifact claim token (intent 111)
@@ -58,7 +58,7 @@ work is unaffected; it engages, and denies, only when a second writer tries to
58
58
  take a fresh claim someone else already holds. A stale or corrupt claim fails
59
59
  open (the write proceeds, the claim yields) and the condition is surfaced in
60
60
  `plastic-lock status`, which lists any live claims alongside the delivery
61
- lock. See `plastic-lock claim`/`release-claim` and `docs/internals.md` for the
61
+ lock. See `plastic-lock claim`/`release-claim` and [`docs/internals.md`](https://github.com/zalom/plastic/blob/main/docs/internals.md) for the
62
62
  full mechanism.
63
63
 
64
64
  There is exactly one lock in Plastic: `delivery.lock` (exclusive, one owner plus delegates),
@@ -108,6 +108,6 @@ each station.
108
108
  | What (create) | `<id>--<slug>.md`, born complete | no lock yet; no bridge | create-gate validates the proposed intent content (Write, Edit, and MCP edits) | savepoint `What` line; intent listed in INDEX `## Active` |
109
109
  | Why | `spec.md` | owner writes refresh the lease (lock file mtime heartbeat) | gate-check requires the intent file with `## Intent` before spec.md; lock-gate admits only the owner or a delegate | savepoint `Why started`, `Why spec.md created` |
110
110
  | How | `plan.md`, `actions/ACTION_N.md` (at least one), `checklist.md` | heartbeat on writes; the code gate stays closed until plan.md, checklist.md, and a real action file all exist | gate-check requires spec.md before plan.md, and plan.md plus a real actions/ACTION_N.md before checklist.md | savepoint `How started`, `How plan.md created`, `How checklist.md created`, `Exec started` |
111
- | Exec | code on the intent branch, checklist checked off | heartbeat; code edits confined to the provisioned worktree; delegates write under the owner's lock; bash, interpreter, and MCP writes gated the same way | code-gate, worktree-gate, bash-gate, lock-gate | checklist boxes; savepoint milestones |
111
+ | Exec | code on the intent branch, checklist checked off | heartbeat; code edits confined to the provisioned worktree; delegates write under the owner's lock; bash, interpreter, and MCP writes gated the same way | the five edit-path gates (savepoint-pre, lock-gate, code-gate with its stage and worktree rules, links-gate, create-gate) plus bash-gate for shell writes | checklist boxes; savepoint milestones |
112
112
  | End (done) | mandatory `outcome.md` (`disposition: delivered\|abandoned`), INDEX moves to Completed or Abandoned | ordered End tail: verify, merge and remove worktrees, disarm clears `delivery.lock`, then the bridge is purge-eligible, and the QMD reindex runs LAST (after purge) | gate-check blocks outcome.md while checklist items are unchecked | savepoint `Done delivered` (or `abandoned`); takeover audits, if any, remain in savepoint.md |
113
113
  | Maintenance (Future, Terminal, or Active-with-a-stale-or-no-lock) | `revisions.md` move-and-record entries | detects (never acquires) `delivery.lock`; defers and reports while the target's lock is FRESH (`Lock.fresh?`); a stale or absent lock is not-active, maintenance proceeds | none enforced by any gate; the maintenance tool or skill itself checks `Lock.fresh?` (see WORK vs MAINTENANCE in `references/maintenance-and-revisions.md`) | append-only, rule-tagged `revisions.md` entry written in the same operation as the change, or the change is refused; lands via a fresh branch off store main merged back as one closed op, never `git add -A` |
@@ -38,10 +38,10 @@ user or the main session states a TIER (S, M, or L) and an EFFORT line in the br
38
38
  effort is `xhigh` for `plastic-advisor` and `max` for `plastic-faux-advisor`.
39
39
 
40
40
  Config is harness-scoped, keys matching `InstallerCore::DEFAULT_AGENTS` exactly (`claude`,
41
- `codex`, never `claude_code`): `advisor.enabled` (false skips installing both agents and the
42
- skill), `advisor.claude.default` (which agent the skill routes to), `advisor.claude.primary`
43
- and `.secondary` (the two slots, agent NAMES never model names, so a slot can point at a
44
- locally registered agent). Each agent's actual model is a plain `agents.models.claude.<name>`
41
+ `codex`, `hermes`, never `claude_code`): `advisor.enabled` (false skips installing both agents and the
42
+ skill), `advisor.claude.default` (which agent the skill routes to; an agent NAME never a model
43
+ name, so it can point at a locally registered agent, and the only advisor routing key the
44
+ installer writes). Each agent's actual model is a plain `agents.models.claude.<name>`
45
45
  override, the SAME harness-scoped mechanism every other agent uses, resolved through
46
46
  `InstallerCore#agent_model_overrides(harness:)`; there is no separate advisor-model key.
47
47
  `agents.models` is harness-scoped from this release (`agents.models.claude.*`,
@@ -92,7 +92,7 @@ belt-and-braces on top of the frontmatter pin.
92
92
  **Cross-harness portability.** The dispatch and model-tier contract above is harness-facing. The
93
93
  adapter layer that maps Plastic's hooks and model aliases onto each supported agent runtime
94
94
  (Claude, Codex, Hermes) is the cross-harness portability layer; see
95
- docs/reference/harness-adapters.md for the adapter contract.
95
+ [`harness-adapters.md`](https://github.com/zalom/plastic/blob/main/docs/reference/harness-adapters.md) for the adapter contract.
96
96
 
97
97
  **Spawn preamble (intent 152).** `scripts/spawn-preamble` emits a live-state block purely from
98
98
  filesystem state: the active intent, stage, role/cycle-step, the honor instruction, and the
@@ -128,7 +128,8 @@ succession at a glance (last line = where we are).
128
128
  ### Auto-Mode Human Reporting (intent 92)
129
129
 
130
130
  In auto mode the orchestrator briefs the human at every lifecycle stage boundary in a fixed,
131
- impact-first shape (the EM-to-CTO report contract): State, then Risk, then Call. It leads with
131
+ impact-first shape (the EM-to-CTO report contract): State, then Risk, then Call. This is the
132
+ depth at M and L; at S the briefing fires once, at How. It leads with
132
133
  what changed and why it matters, names one risk, and leaves the decision to the human. Separately,
133
134
  the `plastic-humanizer` skill cleans authored prose (specs, outcomes, READMEs, release notes) of
134
135
  AI tells and slop; it is for documents, not for every reply.
@@ -157,7 +157,7 @@ To explain or debug a ranking or disposition, read `references/classification.md
157
157
 
158
158
  The eval is the payload + golden snapshots: run the engine against the fixture store and
159
159
  assert the `--data` payload shape/sorting/classification and the byte-identical `--json` +
160
- text goldens in `test/fixtures/dashboard/`. See `test/dashboard_test.rb`. Drift without an
160
+ text goldens in [`test/fixtures/dashboard/`](https://github.com/zalom/plastic/tree/main/test/fixtures/dashboard). See [`dashboard_test.rb`](https://github.com/zalom/plastic/blob/main/test/dashboard_test.rb). Drift without an
161
161
  intentional change means the skill is broken.
162
162
 
163
163
  ## Notes
@@ -36,8 +36,9 @@ Each manifest maps a file path to its SHA256.
36
36
 
37
37
  **On failure**, the report states this guided route, in order:
38
38
 
39
- 1. Run `plastic doctor --fix` (the Fix all / Select individually / Skip router from
40
- Step 4-5 below).
39
+ 1. Offer fixes in the `/plastic-doctor` conversation (the Fix all / Select individually /
40
+ Skip router from Steps 4-5 below); doctor itself only reports, and each chosen repair
41
+ is dispatched to the maintenance tool or skill that owns it.
41
42
  2. If that does not resolve it, roll back to the last known-good version via
42
43
  `plastic-rollback` (restores from the local, append-only `versions.json` ledger of
43
44
  versions actually run).
@@ -159,8 +160,8 @@ Use the `fix_hint` value to determine the correct action:
159
160
  | "Remove stale references from INDEX.md" | Edit INDEX.md to remove ghost references |
160
161
  | "Inject the missing required frontmatter field(s)" | Edit the intent's `{ID}--{slug}.md` frontmatter to add the missing key (e.g. `chain: []`) without touching other keys |
161
162
  | "Run: provision-project-store {slug}" | Run `provision-project-store <slug>` (or invoke the `plastic-store-provisioning` skill) to create the missing store |
162
- | "Re-run installer" | Run `npx -y @zalom/plastic@<channel> install --agent <agent>` (channel: -alpha->@alpha, -beta->@beta, else @latest) |
163
- | "Run the Plastic installer to bootstrap the store" | Run `npx -y @zalom/plastic@<channel> install --agent <agent>` (channel: -alpha->@alpha, -beta->@beta, else @latest) to restore the global store's plastic_home directory or INDEX.md |
163
+ | "Re-run installer" | Run `npx -y @zalom/plastic@<channel> install --claude` (or `--codex`/`--hermes`/`--all` for that agent; channel: -alpha->@alpha, -beta->@beta, else @latest) |
164
+ | "Run the Plastic installer to bootstrap the store" | Run `npx -y @zalom/plastic@<channel> install --claude` (or `--codex`/`--hermes`/`--all`; channel: -alpha->@alpha, -beta->@beta, else @latest) to restore the global store's plastic_home directory or INDEX.md |
164
165
  | "Dispatch plastic-store-curating ... revisions.md ..." | Invoke the `plastic-store-curating` (or the agent) to relocate the flagged section or ref into the intent's `revisions.md` via move-and-record (one dated, `[rule: <tag>]`-tagged entry per item), per plastic-conventions > references/maintenance-and-revisions.md. For a missing required section, restore or reproject it instead. |
165
166
  | "Run scripts/project-links ... PRESERVES ... --drop-unbacked-links" | Run `ruby ~/.plastic/scripts/maintenance-run --tool project-links --intent <id> --apply` for the one flagged id (never run bare `project-links` against a real store outside the rare owner-approved batch exception, D2) |
166
167
 
@@ -206,4 +207,4 @@ This keeps the update flow clean when nothing is wrong.
206
207
 
207
208
  ## References
208
209
 
209
- - Read `references/gates-stuck-detection.md` for the full gate enforcement table, bridge file pattern, and stuck detection thresholds when diagnosing gate failures or stuck agents
210
+ - Read `references/gates-stuck-detection.md` for the full gate enforcement table, bridge file pattern, and the recorded stuck-detection signals when diagnosing gate failures or stuck agents
@@ -28,11 +28,16 @@ Hard blocking — hooks exit with code 2 when gates fail.
28
28
 
29
29
  ## Stuck Detection
30
30
 
31
- | Condition | Threshold | Action |
32
- |---|---|---|
33
- | Consecutive gate failures | 3+ | Warning |
34
- | Consecutive gate failures | 5+ | Force savepoint + escalate |
35
- | No activity | 5+ min | Warning |
36
- | No activity | 10+ min | Force savepoint + escalate |
37
- | Context pressure | 80% | Warning |
38
- | Context pressure | 90% | Force savepoint |
31
+ No automatic stuck detector ships today: no threshold fires, and nothing forces a savepoint
32
+ or escalates on its own. What exists is recorded data, and reading it is the diagnosing
33
+ agent's judgment:
34
+
35
+ - `build.gate_failures` in the bridge file: `scripts/hook-gate-check` increments it on every
36
+ blocked write and resets it to 0 on a passing one. Nothing reads the counter back; a high
37
+ value is a signal for you, not a trigger for the system.
38
+ - `build.last_activity` in the bridge file: updated on passing writes. There are no
39
+ inactivity timers, and context pressure is not tracked anywhere.
40
+
41
+ When diagnosing, treat repeated denies of the same gate with no station progress (compare
42
+ the savepoint ledger) as stuck: stop, read the deny reason, and route through the resolving
43
+ command it names.
@@ -97,4 +97,4 @@ Checked at: {{timestamp}}
97
97
  FOOTER -- always include this line exactly as written.
98
98
  ===================================================================== -->
99
99
 
100
- Run `plastic doctor --fix` to auto-fix all fixable issues, or ask me to fix them now.
100
+ Doctor only reports; it never fixes anything itself. Ask me to fix these issues and I will offer Fix all / Select individually / Skip, then route each chosen repair through the tool that owns it.
@@ -187,7 +187,7 @@ Version: none -> <installed>
187
187
  Doctor: <summary or "all clear">
188
188
  ```
189
189
 
190
- Then: "Read `docs/guides/your-first-intent-in-10-minutes.md` for your first intent, start to finish."
190
+ Then: "Read [`your-first-intent-in-10-minutes.md`](https://github.com/zalom/plastic/blob/main/docs/guides/your-first-intent-in-10-minutes.md) for your first intent, start to finish."
191
191
 
192
192
  ### Local Install (testing/legacy)
193
193
 
@@ -8,8 +8,6 @@ user-invocable: true
8
8
 
9
9
  Help turn ideas into fully formed designs through natural collaborative dialogue.
10
10
 
11
- Announce: "I'm using the brainstorming skill to explore the design for intent {id}: {name}."
12
-
13
11
  Start by understanding the current project context, then ask questions one at a time, in prose, to refine the idea. Once you understand what you're building, present the design and collect the owner's rulings on it. This skill's product is the enriched Why, not spec.md.
14
12
 
15
13
  <HARD-GATE>
@@ -42,7 +42,7 @@ When creating a tactical intent in a project store:
42
42
  - **Global:** `~/.plastic/store/`
43
43
  - **Project:** `~/.plastic/projects/{slug}/store/`
44
44
 
45
- ### 1b. Check for a Duplicate or Predecessor (QMD-first)
45
+ ### 2. Check for a Duplicate or Predecessor (QMD-first)
46
46
 
47
47
  QMD-first (when available): before scanning the store with grep/Read, run
48
48
  `ruby ~/.plastic/scripts/qmd-sync search "<terms>"` to surface candidate, prior, or duplicate
@@ -50,7 +50,7 @@ intents, then open the authoritative intent file for any hit you act on. The com
50
50
  when QMD is absent, so fall back to the existing INDEX.md / file scan. Do this before allocating
51
51
  the id so a near-duplicate can be reused and a true predecessor can be set in `--sources`.
52
52
 
53
- ### 2. Decide Branch vs Root
53
+ ### 3. Decide Branch vs Root
54
54
 
55
55
  Decide this BEFORE scaffolding, because it sets whether you pass `--parent`.
56
56
  Having a "parent" in mind does NOT automatically mean branch. Choose by meaning:
@@ -85,7 +85,7 @@ Read `../plastic-conventions/references/knowledge-graph.md` for the full linking
85
85
  tiers of influence, sources versus chain, and how the `## Links` projection is derived. This path
86
86
  resolves relative to this skill's own installed directory.
87
87
 
88
- ### 3. Determine Intent Properties
88
+ ### 4. Determine Intent Properties
89
89
 
90
90
  Ask or infer from context:
91
91
  - **intent**: one-line description
@@ -100,11 +100,11 @@ Ask or infer from context:
100
100
 
101
101
  `chain` carries what this intent spawns AND related-but-not-spawned successors it leads to;
102
102
  it starts empty and is populated later. See
103
- `docs/concepts/how-plastic-sources-and-chains-intents.md` for the full model.
103
+ [`how-plastic-sources-and-chains-intents.md`](https://github.com/zalom/plastic/blob/main/docs/concepts/how-plastic-sources-and-chains-intents.md) for the full model.
104
104
  Place the intent in `## Active` or `## Future` in INDEX.md (status is
105
105
  convention-derived, not a frontmatter field).
106
106
 
107
- ### 4. Scaffold via new-intent (single call)
107
+ ### 5. Scaffold via new-intent (single call)
108
108
 
109
109
  Delegate id allocation, directory and file creation, the born-complete intent
110
110
  file, the sentinel placeholder lifecycle files, the reciprocal file links, and
@@ -112,7 +112,7 @@ self-validation to one `new-intent` invocation. Do NOT hand-author any of these
112
112
  files.
113
113
 
114
114
  ```bash
115
- "${CLAUDE_PLUGIN_ROOT}/scripts/new-intent" \
115
+ ruby ~/.plastic/scripts/new-intent \
116
116
  --store "<STORE>" --intent "<one-line>" --slug "<slug>" \
117
117
  [--parent "<parent_id>"] [--author "<author>"] \
118
118
  [--sources "id,id"] [--tags "project-<slug>,tag"]
@@ -73,7 +73,7 @@ State is derived from what exists, not from what's declared.
73
73
 
74
74
  1. Determine the target store: `~/.plastic/store/` for global intents (default), `~/.plastic/projects/{slug}/store/` for project intents
75
75
  2. Decide branch vs root (this sets whether you pass `--parent`)
76
- 3. Scaffold with one call: `"${CLAUDE_PLUGIN_ROOT}/scripts/new-intent" --store <store> --intent "<one-line>" --slug <slug> [--parent <id>] [--sources id,id] [--tags ...]`. This allocates the id, creates the directory plus `actions/` and `resources/`, renders the born-complete intent file (frontmatter plus `## Intent`, `## Context`, `## Outcome`, `## Insights`, `## Links`), writes the sentinel placeholder lifecycle files, wires the reciprocal links, and self-validates.
76
+ 3. Scaffold with one call: `ruby ~/.plastic/scripts/new-intent --store <store> --intent "<one-line>" --slug <slug> [--parent <id>] [--sources id,id] [--tags ...]`. This allocates the id, creates the directory plus `actions/` and `resources/`, renders the born-complete intent file (frontmatter plus `## Intent`, `## Context`, `## Outcome`, `## Insights`, `## Links`), writes the sentinel placeholder lifecycle files, wires the reciprocal links, and self-validates.
77
77
  4. Update the appropriate `INDEX.md` — add to Active section and appropriate cluster
78
78
 
79
79
  The intent file is born complete with all five sanctioned `##` sections; the lifecycle files (`spec.md`/`plan.md`/`checklist.md`/`outcome.md`) are sentinel placeholders that read as "stage not reached" until an agent fills them and deletes the `<!-- plastic:placeholder -->` first line.
@@ -11,8 +11,6 @@ user-invocable: false
11
11
 
12
12
  # Intent Discovery — What-stage context deposit
13
13
 
14
- Announce: "Discovering context for intent [ID] — [name]."
15
-
16
14
  Runs once, at intent activation, after the lock is armed and before Why. It gathers what is
17
15
  already known so Why does not start cold, and deposits it as a resource the
18
16
  Why-stage brainstorming agent reads.
@@ -21,9 +19,18 @@ Why-stage brainstorming agent reads.
21
19
  Inside `plastic-intent-starting`, right after the bridge is armed, under the
22
20
  lock. Dispatched as the `plastic-intent-discovery` background agent.
23
21
 
22
+ **Precondition for skipping: a size of S already on record, and no graph edges.** Read the
23
+ activating intent's `chain` and `sources` frontmatter fields first. When a `Tier: S` line is
24
+ already stamped at the top of `spec.md` AND both fields are empty, the pass does not run:
25
+ write the single line `no chain/sources, discovery skipped` to
26
+ `resources/discovery--<slug>.md` and stop there. Sizing happens at Why, which is after this
27
+ stage, so a first activation usually has no size yet and the full pass runs. Never guess a
28
+ size to unlock the skip. At M or L, or when either field is filled, run the full pass below.
29
+
24
30
  ## What it does
25
31
  1. **Read the intent's links.** Load the activating intent file's `chain` and
26
- `sources` frontmatter fields.
32
+ `sources` frontmatter fields. If both are empty and a size of S is already on record, apply
33
+ the skip above and stop.
27
34
  2. **QMD-first discovery.** Search the Plastic stores with
28
35
  `scripts/qmd-sync search "<terms>"` (or the `qmd` skill), scoped to the
29
36
  relevant `plastic-*` collections, across completed predecessor work named in
@@ -62,8 +62,8 @@ for orchestrator-owned or completion-tracking items.
62
62
  `## Links` projection). On a refusal, fix via the OWNING tool, never a
63
63
  hand edit of the check's own output:
64
64
  - checklist/outcome content - finish it yourself, the same as before.
65
- - links projection - `scripts/project-links --intent <id> --apply` via
66
- `maintenance-run`.
65
+ - links projection - run
66
+ `ruby ~/.plastic/scripts/maintenance-run --tool project-links --intent <id> --apply`.
67
67
  - a savepoint issue - advisory only (WARN, never blocks): run
68
68
  `plastic-intent-savepoint` to rebuild via `Bridge.rebuild_savepoint` if
69
69
  you want it clean, but it never refuses the close on its own.
@@ -171,8 +171,9 @@ historical record of what was planned.
171
171
 
172
172
  ## Routing
173
173
 
174
- `plastic-releasing`, `plastic-auto`, the curator agent, `store-curating`, and
175
- `store-indexing` all delegate their mechanical close to this skill (or call
176
- `scripts/end-intent` directly for steps 1-5). None of them restate the
177
- outcome/INDEX/savepoint/disarm prose inline any more; if you find one that
178
- does, that surface has drifted and should route here instead.
174
+ `plastic-releasing`, `plastic-auto`, `plastic-intent-executing`, the curator
175
+ agent, `store-curating`, and `store-indexing` all delegate their mechanical
176
+ close to this skill (or call `scripts/end-intent` directly for steps 1-5).
177
+ None of them restate the outcome/INDEX/savepoint/disarm prose inline any
178
+ more; if you find one that does, that surface has drifted and should route
179
+ here instead.
@@ -1,6 +1,6 @@
1
1
  ---
2
2
  name: plastic-intent-executing
3
- description: Use when you have a written implementation plan to execute. Default mode is subagent-driven (dispatches fresh subagent per task with two-stage review). Fallback mode is inline execution for environments without subagent support. If superpowers:subagent-driven-development or superpowers:executing-plans are available, delegates to them.
3
+ description: Use when you have a written implementation plan to execute. Default mode is subagent-driven (at L a fresh subagent per task with two-stage review, at S and M one executor dispatch for the whole consolidated action). Fallback mode is inline execution for environments without subagent support. If superpowers:subagent-driven-development or superpowers:executing-plans are available, delegates to them.
4
4
  user-invocable: true
5
5
  ---
6
6
 
@@ -8,9 +8,7 @@ user-invocable: true
8
8
 
9
9
  ## Overview
10
10
 
11
- Load plan from the active intent's `plan.md`, execute all tasks, review between tasks, report when complete.
12
-
13
- **Announce at start:** "I'm using the executing-plan skill to implement this plan."
11
+ Load plan from the active intent's `plan.md`, execute all tasks, review per the tier gate below, report when complete.
14
12
 
15
13
  ## Step 0: Sync Worktree First
16
14
 
@@ -42,7 +40,12 @@ If `superpowers:subagent-driven-development` is available as a skill, delegate t
42
40
  - Superpowers skills respect "user preferences for plan/spec location"; Plastic IS that preference
43
41
 
44
42
  ### Subagent-Driven (Default)
45
- Dispatches a fresh subagent per task. Controller never implements, only dispatches, reviews, and tracks progress. Two-stage review after each task: spec compliance first, then code quality.
43
+ Dispatches subagents to do the work. The controller never implements. It dispatches, reviews, and tracks progress. How many dispatches it makes depends on the tier stamped at the top of `spec.md` (the `Tier:` line, the single authoritative record). `plan.md` carries a bold `**Tier:**` field copied from it, a convenience only:
44
+
45
+ - **S or M:** one executor dispatch implements the whole consolidated action from `plan.md` plus `checklist.md` in one pass. There is no per-task implementer-then-two-reviewers loop.
46
+ - **L:** a fresh subagent per task, and a two-stage review after each task: spec compliance first, then code quality.
47
+
48
+ The final independent review in Step 3 runs at every tier. It is a separate agent with fresh context, and it is never the maker.
46
49
 
47
50
  ### Inline (Fallback)
48
51
  Executes tasks sequentially in the current session. Use when subagents aren't available or user explicitly requests inline mode.
@@ -59,6 +62,19 @@ Run Step 0 (Sync Worktree First) before this step.
59
62
 
60
63
  ### Step 2: Execute Each Task
61
64
 
65
+ Read the `Tier:` line stamped at the top of `spec.md` first (the authority), then follow the matching branch. `plan.md`'s bold `**Tier:**` field is a convenience copy of the same value, useful when `spec.md` is not already open.
66
+
67
+ #### At S or M: one executor dispatch
68
+
69
+ Dispatch ONE executor subagent and give it the whole delivery: every task's full text from `plan.md` (pasted in, never a file reference), the checklist items it must tick, the project context from CLAUDE.md, and the active intent context from `{ID}--{slug}.md`. In auto mode this is the `plastic-executor` agent; elsewhere use the `implementer-prompt.md` template. The executor implements the consolidated action in order, ticks each item as it lands (see `## Tick-as-you-land`), and drives the test suite green.
70
+
71
+ Read its response by code:
72
+ - DONE or DONE_WITH_CONCERNS → proceed to Step 3. Run no per-task spec review and no per-task quality review at these tiers; Step 3's final review covers the work.
73
+ - NEEDS_CONTEXT → provide the missing context, re-dispatch the executor.
74
+ - BLOCKED → stop, report to the user, wait for resolution.
75
+
76
+ #### At L: one subagent per task
77
+
62
78
  For each task sequentially (never parallel: conflict risk):
63
79
 
64
80
  **a. Dispatch implementer subagent**
@@ -85,17 +101,13 @@ Only after spec compliance passes. Reviews clean code, testing, architecture. Pa
85
101
  Follow `## Tick-as-you-land` below: move the task's checklist item to `## Completed` and add a `## Session Log` row in the same edit.
86
102
 
87
103
  ### Step 3: Final Review
88
- After all tasks complete, dispatch a final reviewer for the entire implementation.
104
+ After all tasks complete, dispatch a final reviewer for the entire implementation. This runs at every tier, S, M, and L. The reviewer is a separate agent with fresh context and is never the maker. At S and M this is the only review the work gets, so if it returns changes, re-dispatch the executor to fix them, then re-review.
89
105
 
90
106
  ### Step 4: Update Intent and Complete
91
107
  Capture observations in `## Insights`. When ALL checklist items are checked:
92
108
 
93
- 1. Write `outcome.md` with detailed results in the intent directory, using the `${CLAUDE_PLUGIN_ROOT}/templates/outcome.md` form. Set the frontmatter `disposition: delivered` (the delivered terminal). `outcome.md` is mandatory at every terminal and self-declares its disposition (canonical done-marker in PLASTIC.md).
94
- 2. Write `## Outcome` summary in the intent file (1-2 sentences)
95
- 3. Move intent from `## Active` to `## Completed` in INDEX.md (with today's date)
96
- 4. Update cluster entries to show `_(completed)_`
97
- 5. Auto-commit: `cd <store-root> && git add . && git commit -m "feat: complete intent <ID>: <name>"`
98
- 6. QMD reindex LAST (canonical End tail). As the final End-tail step, after the terminal move and any disarm, ALWAYS refresh the QMD search index for this store (no-op when QMD is absent), running in the background so it never blocks the turn: `ruby ~/.plastic/scripts/qmd-sync reindex --store <store-root> --async`. Completion is the lifecycle event that keeps the search index fresh, and the reindex runs last so the index never references a bridge or lock that is about to disappear (see PLASTIC.md `## Delivery Isolation and the Single-Owner Lock`).
109
+ 1. Update the intent's cluster entries in `INDEX.md` to show `_(completed)_`. Do this first, so the store auto-commit in the next step picks it up. `plastic-intent-ending` does not cover cluster maintenance (`store-indexing` and `store-curating` own it), so doing it here keeps the step from being lost.
110
+ 2. Hand the mechanical close to `plastic-intent-ending`. It owns `outcome.md`, the intent file's `## Outcome` stamp, the INDEX terminal move, the savepoint `Done` line, the store auto-commit, disarm, the QMD reindex, and the EM-to-CTO owner report, as ONE delegation. Author the outcome.md content when that skill asks for it; do not restate the mechanical steps here.
99
111
 
100
112
  **This is NOT optional.** An intent with all checklist items done but no Outcome is a broken state. Complete the intent immediately, do not leave it for later.
101
113
 
@@ -117,12 +129,8 @@ For each task:
117
129
  ### Step 3: Update Intent and Complete
118
130
  Capture observations in `## Insights`. When ALL checklist items are checked:
119
131
 
120
- 1. Write `outcome.md` with detailed results in the intent directory, using the `${CLAUDE_PLUGIN_ROOT}/templates/outcome.md` form. Set the frontmatter `disposition: delivered` (the delivered terminal). `outcome.md` is mandatory at every terminal and self-declares its disposition (canonical done-marker in PLASTIC.md).
121
- 2. Write `## Outcome` summary in the intent file (1-2 sentences)
122
- 3. Move intent from `## Active` to `## Completed` in INDEX.md (with today's date)
123
- 4. Update cluster entries to show `_(completed)_`
124
- 5. Auto-commit: `cd <store-root> && git add . && git commit -m "feat: complete intent <ID>: <name>"`
125
- 6. QMD reindex LAST (canonical End tail). As the final End-tail step, after the terminal move and any disarm, ALWAYS refresh the QMD search index for this store (no-op when QMD is absent), running in the background so it never blocks the turn: `ruby ~/.plastic/scripts/qmd-sync reindex --store <store-root> --async`. Completion is the lifecycle event that keeps the search index fresh, and the reindex runs last so the index never references a bridge or lock that is about to disappear (see PLASTIC.md `## Delivery Isolation and the Single-Owner Lock`).
132
+ 1. Update the intent's cluster entries in `INDEX.md` to show `_(completed)_`. Do this first, so the store auto-commit in the next step picks it up. `plastic-intent-ending` does not cover cluster maintenance (`store-indexing` and `store-curating` own it), so doing it here keeps the step from being lost.
133
+ 2. Hand the mechanical close to `plastic-intent-ending`. It owns `outcome.md`, the intent file's `## Outcome` stamp, the INDEX terminal move, the savepoint `Done` line, the store auto-commit, disarm, the QMD reindex, and the EM-to-CTO owner report, as ONE delegation. Author the outcome.md content when that skill asks for it; do not restate the mechanical steps here.
126
134
 
127
135
  **This is NOT optional.** Complete the intent immediately when work is done.
128
136
 
@@ -171,7 +179,7 @@ persisting each ruling with `--stage Exec`.
171
179
 
172
180
  - **Before:** `plan.md` and `checklist.md` exist; the worktree is armed.
173
181
  - **Produces:** code changes, a ticked checklist, and (for audits or sweeps) a methods report in `resources/`.
174
- - **Next:** intent-ending owns `outcome.md` (see intent 161). This skill's own Update-Intent-and-Complete step above is unchanged by this note.
182
+ - **Next:** `plastic-intent-ending` owns `outcome.md` and the rest of the mechanical close (see intent 161). The Update-Intent-and-Complete step above hands off to it.
175
183
 
176
184
  Read `../plastic-conventions/references/lifecycle-and-savepoints.md` for the subagent
177
185
  report-home contract this handoff relies on.
@@ -53,20 +53,22 @@ This process is thorough. It typically takes 20-45 minutes for a complex design.
53
53
 
54
54
  > "We've covered [areas]. Still to explore: [areas]. Continue, or pause and capture what we have?"
55
55
 
56
- If the user wants to pause, capture all decisions made so far into the active intent's spec.md.
56
+ If the user wants to pause, capture all decisions made so far into the active intent's `## Context` / `### Decisions`, ready for /plastic-intent-speccing to consolidate later.
57
57
 
58
58
  ### 5. Close Out
59
59
 
60
60
  When all branches are resolved:
61
61
 
62
- 1. Write the complete spec to the active intent directory (`spec.md`)
62
+ 1. Record every ruling in the active intent's `## Context` / `### Decisions`, then hand off
63
+ to /plastic-intent-speccing to consolidate them into `spec.md` (that skill owns
64
+ `spec.md` exclusively)
63
65
  2. List all decisions made
64
66
  3. List any deferred items (things the user explicitly chose to decide later)
65
67
  4. Proceed to Autonomous Handoff Offer (step 6)
66
68
 
67
69
  ### 6. Autonomous Handoff Offer
68
70
 
69
- After closing out (spec written, decisions listed), assess whether the agent has enough context to deliver the intent autonomously.
71
+ After closing out (decisions listed, spec consolidated by /plastic-intent-speccing), assess whether the agent has enough context to deliver the intent autonomously.
70
72
 
71
73
  **Self-assessment checklist:**
72
74
  - All key decisions resolved (no open "it depends" or "TBD")
@@ -12,8 +12,6 @@ Write comprehensive implementation plans assuming the engineer has zero context
12
12
 
13
13
  Assume they are a skilled developer, but know almost nothing about our toolset or problem domain. Assume they don't know good test design very well.
14
14
 
15
- **Announce at start:** "I'm using the writing-plans skill to plan intent {id}: {name}."
16
-
17
15
  ## Active Intent Gate
18
16
 
19
17
  Before proceeding, resolve the active intent:
@@ -55,13 +53,19 @@ This structure informs the task decomposition. Each task should produce self-con
55
53
 
56
54
  ## Bite-Sized Task Granularity
57
55
 
58
- **Each step is one action (2-5 minutes):**
56
+ Granularity follows the `Tier:` line the spec stamped.
57
+
58
+ **At M or L, each step is one action (2-5 minutes):**
59
59
  - "Write the failing test" - step
60
60
  - "Run it to make sure it fails" - step
61
61
  - "Implement the minimal code to make the test pass" - step
62
62
  - "Run the tests and make sure they pass" - step
63
63
  - "Commit" - step
64
64
 
65
+ **At S, size each step to the work.** Do not slice a small delivery into fixed 2-5 minute steps. Keep steps coarse enough to read in one pass, and let the one consolidated `actions/ACTION_1.md` carry the whole delivery. Each step still names its exact file paths, its exact changes, and how it is verified. Only the slicing relaxes.
66
+
67
+ This changes granularity, nothing else. Every tier still produces at least one real `actions/ACTION_N.md`, and an empty or `.gitkeep`-only `actions/` still fails the How gate (see `## Tier shapes` above).
68
+
65
69
  ## Plan Format
66
70
 
67
71
  For the exact plan/task/checklist/action format (the Plan Document Header
@@ -8,8 +8,6 @@ user-invocable: true
8
8
 
9
9
  Investigate a topic related to the active intent. Choose the right depth, produce a cited report.
10
10
 
11
- **Announce at start:** "I'm researching [topic] for intent {id} — {name}."
12
-
13
11
  ## Active Intent Gate
14
12
 
15
13
  Before proceeding, resolve the active intent:
@@ -10,8 +10,6 @@ user-invocable: true
10
10
 
11
11
  # Intent Starting — board a session onto an intent
12
12
 
13
- Announce: "Boarding intent [ID] — [name]."
14
-
15
13
  `plastic-intent-starting` is the Start procedure. It boards a session onto one intent: take
16
14
  the lock FIRST, confirm the delivery state, ask **auto or guided ONCE**, board at the latest
17
15
  delivered station, then run the cycle to Done. The What → Why → How → Exec stations are the
@@ -70,6 +68,16 @@ This path resolves relative to this skill's own installed directory.
70
68
  lock-owner-only rule is untouched. This is advisory context for Why, not a gate: if
71
69
  discovery yields nothing, proceed to Why normally.
72
70
 
71
+ **Skip the dispatch only at Tier S, when there is nothing to discover.** The skip fires
72
+ only when BOTH hold: a size of S is already on record for this intent, and the activating
73
+ intent's `chain` and `sources` frontmatter fields are both empty. On record means a
74
+ stamped `Tier: S` line at the top of `spec.md`. Sizing happens at Why, which is after this
75
+ step, so a first activation usually has no size yet: run the pass. The skip mainly earns
76
+ its keep on a re-activated intent that is already sized S. Never guess a size here to
77
+ unlock the skip. When both conditions hold, write the single line
78
+ `no chain/sources, discovery skipped` to `resources/discovery--<slug>.md` in its place,
79
+ then go to Why.
80
+
73
81
  **Session id resolution (verbatim from `plastic-auto`).** The first argument is the session
74
82
  id the bridge is keyed by: pass the hook stdin `session_id` when you have it; in the executable
75
83
  snippets, a nonblank `CODEX_THREAD_ID` identifies Codex, otherwise a nonblank
@@ -10,8 +10,6 @@ user-invocable: true
10
10
 
11
11
  # Creating a Project
12
12
 
13
- Announce: "Creating project `<slug>` from intent [ID] — [name]."
14
-
15
13
  ## Precondition
16
14
 
17
15
  An active intent must exist with enough context to define a project — at minimum: name/slug, path, and key decisions from `## Context > ### Decisions`.
@@ -74,7 +74,7 @@ Update the project's `~/.plastic/projects/{slug}/INDEX.md`:
74
74
  # Index
75
75
 
76
76
  ## Active
77
- - [1 — <intent name>](store/1--<slug>/1.md) — implementation, from: global:<ID>
77
+ - [1 — <intent name>](store/1--<slug>/1--<slug>.md) — implementation, from: global:<ID>
78
78
  ```
79
79
 
80
80
  **For multi-intent spawning (Hub):**
@@ -332,7 +332,7 @@ the intent-41 re-land playbook.
332
332
 
333
333
  - Read `references/release-lines.md` for the two release lanes, the stable-line guarantees,
334
334
  the version-line map, and the intent-41 re-land playbook before starting any release
335
- - When promoting a pre-release across channels (`--promote beta`/`--promote stable`) or
335
+ - When promoting a pre-release across channels (alpha to beta, beta to stable) or
336
336
  tagging a historical release retroactively, read `references/promotion-and-tagging.md`
337
337
  for the exact commands and rules first
338
338
  - Read `references/deprecations.md` for the full deprecation process, severity levels, deprecations.yml schema, and dismissal rules when adding or managing deprecations
@@ -33,21 +33,27 @@ cleared is a no-op.
33
33
 
34
34
  ## Promotion
35
35
 
36
- To promote a release across channels, use `--promote`:
36
+ Promotion is not a CLI flag; there is no `--promote` command. It is a set of steps the
37
+ agent performs during the releasing workflow, reusing the normal release mechanics
38
+ (version bump, tag, `npm publish` with the channel's dist-tag, GitHub release):
37
39
 
38
40
  ```bash
39
- plastic-releasing --promote beta # promotes current alpha beta
40
- plastic-releasing --promote stable # promotes current beta → stable
41
+ # Promote alpha → beta: set version files from -alpha.N to -beta.1, commit, tag, then
42
+ npm publish --access public --tag beta
43
+
44
+ # Promote beta → stable: strip the pre-release suffix (e.g., 1.0.0-beta.3 → 1.0.0),
45
+ # commit, tag, then
46
+ npm publish --access public # no --tag flag publishes to latest
41
47
  ```
42
48
 
43
49
  **Promotion rules:**
44
50
  - 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
51
  - Version files are bumped and committed as in a normal release.
50
- - An annotated tag is created for the promoted version.
52
+ - An annotated tag is created for the promoted version, and the GitHub release is cut
53
+ as in the normal workflow (`gh release create ... --latest` for stable).
54
+ - To point a channel at an already-published version without republishing, move the
55
+ dist-tag directly: `npm dist-tag add @zalom/plastic@<version> <channel>`. To move the
56
+ GitHub "Latest" badge: `gh release edit <tag> --latest`.
51
57
 
52
58
  ## Retroactive Tagging
53
59
 
@@ -20,7 +20,7 @@ green Minitest run can fully vouch for.
20
20
 
21
21
  **Beta-verified lane.** Branch, merge to the `beta` branch, publish to the npm `beta` dist-tag,
22
22
  verify in real use, then merge `beta` into `main` and cut stable. It sits on top of the existing
23
- promotion mechanics (`--promote beta` / `--promote stable`, linear only, see
23
+ promotion mechanics (agent-performed channel promotion, linear only, see
24
24
  `promotion-and-tagging.md`); it names when to use them, not new machinery.
25
25
 
26
26
  ## Routing rule
@@ -35,8 +35,11 @@ routes each authoring task to the reference that holds the depth.
35
35
  - Build at least three evals before writing extensive docs.
36
36
  - Match determinism to fragility: a deterministic script for fragile or
37
37
  repeated mechanical steps, prose for judgment calls.
38
- - Imperative voice, no second person. No em-dashes or en-dashes in any shipped
39
- skill or doc (use commas, periods, parentheses, colons).
38
+ - Imperative voice, no second person. User-facing docs (README, docs/, AGENTS.md,
39
+ CLAUDE.md) never use em-dashes or en-dashes, and newly authored skill text avoids
40
+ them (use commas, periods, parentheses, colons). Existing internal files and the
41
+ sanctioned template emissions (templates/index.md's INDEX line shape) are not
42
+ violations.
40
43
 
41
44
  ## Route the authoring task to its reference
42
45
 
@@ -14,20 +14,20 @@ user-invocable: false
14
14
 
15
15
  ## INDEX.md Structure
16
16
 
17
- INDEX.md is a Zettelkasten main structure note - the brain's entry point. It has four sections:
17
+ INDEX.md is a Zettelkasten main structure note - the brain's entry point. It has five sections:
18
18
 
19
19
  ### Active
20
20
  Intents currently being worked on. Max 1-2 for focus.
21
21
  ```markdown
22
22
  ## Active
23
- - [1a2 — Design Plastic](store/1a2--design-plastic-state-system/1a2.md) — decision, human
23
+ - [1a2 — Design Plastic](store/1a2--design-plastic-state-system/1a2--design-plastic-state-system.md) — decision, human
24
24
  ```
25
25
 
26
26
  ### Future
27
27
  Intents parked for later. May be picked up by agents.
28
28
  ```markdown
29
29
  ## Future
30
- - [1b1 — Build Reddit KB](store/1b1--build-reddit-knowledge-base/1b1.md) — implementation, human
30
+ - [1b1 — Build Reddit KB](store/1b1--build-reddit-knowledge-base/1b1--build-reddit-knowledge-base.md) — implementation, human
31
31
  ```
32
32
 
33
33
  ### Clusters
@@ -35,10 +35,13 @@ Topic-based groupings. Manually curated. Create a new cluster when 3+ intents sh
35
35
  ```markdown
36
36
  ## Clusters
37
37
  ### Reddit Knowledge Base
38
- - [1a — Research](store/1a--research-reddit-saved-posts/1a.md)
39
- - [1a1 — Plan](store/1a1--plan-reddit-knowledge-base/1a1.md)
38
+ - [1a — Research](store/1a--research-reddit-saved-posts/1a--research-reddit-saved-posts.md)
39
+ - [1a1 — Plan](store/1a1--plan-reddit-knowledge-base/1a1--plan-reddit-knowledge-base.md)
40
40
  ```
41
41
 
42
+ ### Abandoned
43
+ Intents ended without delivery. Links preserved, never deleted.
44
+
42
45
  ### Completed
43
46
  All completed intents with dates. Links preserved, never deleted.
44
47