@zalom/plastic 1.0.3 → 1.1.1

This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
Files changed (130) hide show
  1. package/PLASTIC-reference.md +11 -11
  2. package/PLASTIC.md +11 -9
  3. package/README.md +48 -1
  4. package/agents/plastic-enforcer.md +8 -5
  5. package/agents/plastic-future-intent-researcher.md +1 -1
  6. package/agents/plastic-intent-curator.md +9 -10
  7. package/agents/plastic-spec-specialist.md +9 -6
  8. package/bin/plastic.js +2 -2
  9. package/hooks/check-update +1 -1
  10. package/hooks/continue +1 -1
  11. package/package.json +1 -1
  12. package/scripts/dashboard.rb +29 -24
  13. package/scripts/doctor.rb +188 -9
  14. package/scripts/end-intent +330 -0
  15. package/scripts/hook-code-gate +1 -1
  16. package/scripts/hook-continue +2 -2
  17. package/scripts/hook-create-gate +2 -2
  18. package/scripts/hook-session-start +1 -1
  19. package/scripts/install.rb +2 -1
  20. package/scripts/lib/bridge.rb +116 -3
  21. package/scripts/lib/dashboard_banner.rb +8 -9
  22. package/scripts/lib/installer_core.rb +17 -8
  23. package/scripts/lib/legacy_bookend_amnesty.rb +35 -0
  24. package/scripts/lib/release_guard.rb +62 -0
  25. package/scripts/lib/roadmap_queue.rb +285 -0
  26. package/scripts/lib/roadmap_savepoint.rb +213 -0
  27. package/scripts/lib/store_provisioning.rb +1 -1
  28. package/scripts/lib/worktree.rb +21 -0
  29. package/scripts/new-intent +2 -1
  30. package/scripts/read-config +3 -3
  31. package/scripts/roadmap-next +44 -0
  32. package/scripts/roadmap-savepoint +64 -0
  33. package/scripts/{versions.rb → rollback.rb} +33 -41
  34. package/scripts/update.rb +1 -1
  35. package/skills/_active-intent-gate.md +1 -1
  36. package/skills/_decision-tables.md +50 -0
  37. package/skills/auto/SKILL.md +69 -68
  38. package/skills/auto/evals/evals.json +4 -4
  39. package/skills/auto/references/agent-architecture.md +2 -2
  40. package/skills/continuing/SKILL.md +23 -130
  41. package/skills/continuing/evals/evals.json +26 -80
  42. package/skills/dashboard/SKILL.md +18 -15
  43. package/skills/dashboard/references/classification.md +3 -3
  44. package/skills/dashboard/templates/dashboard-global.md +8 -23
  45. package/skills/dashboard/templates/dashboard-project.md +7 -26
  46. package/skills/doctor/SKILL.md +3 -3
  47. package/skills/install/SKILL.md +10 -10
  48. package/skills/{brainstorming → intent-brainstorming}/SKILL.md +43 -45
  49. package/skills/intent-brainstorming/evals/evals.json +67 -0
  50. package/skills/{brainstorming → intent-brainstorming}/references/design-principles.md +12 -17
  51. package/skills/intent-continuing/SKILL.md +99 -0
  52. package/skills/intent-continuing/evals/evals.json +145 -0
  53. package/skills/intent-continuing/references/context-management.md +28 -0
  54. package/skills/{creating-intent → intent-creating}/SKILL.md +3 -3
  55. package/skills/{creating-intent → intent-creating}/evals/evals.json +1 -1
  56. package/skills/{intent-discovery → intent-discovering}/SKILL.md +1 -1
  57. package/skills/intent-ending/SKILL.md +151 -0
  58. package/skills/intent-ending/evals/evals.json +74 -0
  59. package/skills/{executing-plan → intent-executing}/SKILL.md +75 -15
  60. package/skills/intent-executing/evals/evals.json +66 -0
  61. package/skills/{brainstorming-grill-me → intent-grilling}/SKILL.md +4 -4
  62. package/skills/{linking-intents → intent-linking}/SKILL.md +1 -1
  63. package/skills/{linking-intents → intent-linking}/evals/evals.json +1 -1
  64. package/skills/{lock → intent-locking}/SKILL.md +1 -1
  65. package/skills/{writing-plans → intent-planning}/SKILL.md +48 -20
  66. package/skills/intent-planning/evals/evals.json +66 -0
  67. package/skills/{writing-plans → intent-planning}/references/plan-format.md +31 -7
  68. package/skills/{research → intent-researching}/SKILL.md +2 -2
  69. package/skills/{research → intent-researching}/evals/evals.json +1 -1
  70. package/skills/{savepoint → intent-savepoint}/SKILL.md +13 -1
  71. package/skills/intent-speccing/SKILL.md +69 -0
  72. package/skills/intent-speccing/evals/evals.json +126 -0
  73. package/skills/intent-speccing/references/per-section-fill-rules.md +92 -0
  74. package/skills/intent-speccing/references/self-verify-checklist.md +38 -0
  75. package/skills/intent-starting/SKILL.md +2 -2
  76. package/skills/intent-starting/evals/evals.json +2 -2
  77. package/skills/project-continuing/SKILL.md +104 -0
  78. package/skills/project-continuing/evals/evals.json +100 -0
  79. package/skills/project-continuing/references/board-fill.md +33 -0
  80. package/skills/{creating-project → project-creating}/SKILL.md +2 -2
  81. package/skills/releasing/SKILL.md +66 -14
  82. package/skills/releasing/references/release-lines.md +105 -0
  83. package/skills/roadmap/SKILL.md +7 -1
  84. package/skills/roadmap/references/file-format.md +30 -1
  85. package/skills/roadmap/references/operations.md +26 -6
  86. package/skills/roadmap-continuing/SKILL.md +85 -0
  87. package/skills/roadmap-continuing/evals/evals.json +82 -0
  88. package/skills/roadmap-continuing/references/liveness-ranking.md +56 -0
  89. package/skills/{versions → rollback}/SKILL.md +30 -20
  90. package/skills/{creating-skills → skill-creating}/SKILL.md +2 -2
  91. package/skills/{creating-skills → skill-creating}/evals/evals.json +5 -5
  92. package/skills/{creating-skills → skill-creating}/references/progressive-disclosure.md +2 -2
  93. package/skills/{evaluating-skills → skill-evaluating}/SKILL.md +1 -1
  94. package/skills/{evaluating-skills → skill-evaluating}/evals/evals.json +3 -3
  95. package/skills/{intent-curator → store-curating}/SKILL.md +6 -7
  96. package/skills/{intent-curator → store-curating}/evals/evals.json +1 -1
  97. package/skills/{managing-index → store-indexing}/SKILL.md +6 -7
  98. package/skills/{managing-index → store-indexing}/evals/evals.json +1 -1
  99. package/skills/{add-project-store → store-provisioning}/SKILL.md +2 -2
  100. package/skills/tutorial/SKILL.md +65 -0
  101. package/skills/tutorial/evals/evals.json +186 -0
  102. package/skills/tutorial/references/track-1-guided.md +123 -0
  103. package/skills/tutorial/references/track-2-auto.md +95 -0
  104. package/skills/tutorial/references/track-3-projects-and-roadmaps.md +110 -0
  105. package/skills/uninstall/SKILL.md +2 -2
  106. package/skills/update/SKILL.md +3 -3
  107. package/templates/agents.md +7 -7
  108. package/templates/config.yml +2 -1
  109. package/templates/index.md +4 -1
  110. package/skills/brainstorming/evals/evals.json +0 -22
  111. package/skills/savepoint/references/context-management.md +0 -32
  112. /package/skills/{creating-intent → intent-creating}/references/lifecycle.md +0 -0
  113. /package/skills/{creating-intent → intent-creating}/references/wikilinks.md +0 -0
  114. /package/skills/{executing-plan → intent-executing}/code-quality-reviewer-prompt.md +0 -0
  115. /package/skills/{executing-plan → intent-executing}/implementer-prompt.md +0 -0
  116. /package/skills/{executing-plan → intent-executing}/spec-reviewer-prompt.md +0 -0
  117. /package/skills/{linking-intents → intent-linking}/references/zettelkasten.md +0 -0
  118. /package/skills/{continuing → intent-savepoint}/references/context-management.md +0 -0
  119. /package/skills/{creating-project → project-creating}/references/hubs-projects.md +0 -0
  120. /package/skills/{creating-project → project-creating}/references/project-scaffolding.md +0 -0
  121. /package/skills/{creating-skills → skill-creating}/references/agents.md +0 -0
  122. /package/skills/{creating-skills → skill-creating}/references/evals.md +0 -0
  123. /package/skills/{creating-skills → skill-creating}/references/hooks.md +0 -0
  124. /package/skills/{creating-skills → skill-creating}/references/scripts.md +0 -0
  125. /package/skills/{creating-skills → skill-creating}/references/skills.md +0 -0
  126. /package/skills/{creating-skills → skill-creating}/scripts/scaffold.rb +0 -0
  127. /package/skills/{evaluating-skills → skill-evaluating}/assets/eval-template.json +0 -0
  128. /package/skills/{evaluating-skills → skill-evaluating}/references/convention-checks.md +0 -0
  129. /package/skills/{evaluating-skills → skill-evaluating}/references/eval-methodology.md +0 -0
  130. /package/skills/{managing-index → store-indexing}/references/zettelkasten-linking.md +0 -0
@@ -1,5 +1,5 @@
1
1
  {
2
- "skill_name": "plastic-research",
2
+ "skill_name": "plastic-intent-researching",
3
3
  "notes": "Intent 66a. Spec for the QMD-first step before researching (reuse prior intents/reports before grep/Read or web search). Runner is intent 76; spec only.",
4
4
  "evals": [
5
5
  {
@@ -1,5 +1,5 @@
1
1
  ---
2
- name: plastic-savepoint
2
+ name: plastic-intent-savepoint
3
3
  description: Use when verifying or repairing an intent's savepoint ledger, when the user says "save" or "savepoint", or when a PreCompact hook fires. The ledger is written automatically by the gate hook at each lifecycle boundary; this skill only reads, verifies, and rebuilds it.
4
4
  user-invocable: false
5
5
  ---
@@ -42,6 +42,18 @@ Read the active store's `INDEX.md` and extract intents under `## Active`.
42
42
  - Confirm the **last line's stage** matches the stage derived from files-on-disk
43
43
  (`Bridge.derive_stage`). If they disagree, or the file is missing/empty, the ledger has
44
44
  drifted.
45
+ - Run `Bridge.savepoint_phantom_lines(intent_dir)` (pure, disk-only, no bridge or session
46
+ resolution; intent 134). It flags a line disk evidence contradicts: a file-landing milestone
47
+ whose file is absent or still a sentinel placeholder, a duplicate `(stage, milestone)` pair, or
48
+ a state line (`How started` / `Exec started`) whose stage prerequisites are absent. If it
49
+ returns any lines:
50
+ - **LIVE intent (INDEX `## Active`):** rebuild via step 3 below.
51
+ - **INDEX `## Completed`/`## Abandoned` intent:** REPORT the phantom lines and STOP. Do not
52
+ rewrite. Completed intents are immutable. A repair is available only under an explicit human
53
+ grant, following the 124a precedent: rebuild the file-landing skeleton (step 3), then
54
+ re-append the terminal `Done <disposition>` bookend with the disposition read from
55
+ `outcome.md`'s `disposition:` frontmatter and the timestamp recovered from the merge commit or
56
+ the file's mtime, never invented.
45
57
 
46
58
  ### 3. Rebuild on drift
47
59
  Reconstruct from the filesystem rather than hand-editing:
@@ -0,0 +1,69 @@
1
+ ---
2
+ name: plastic-intent-speccing
3
+ description: >
4
+ Consolidate the enriched Why (`## Context`, `### Decisions`, `## Insights`) into `spec.md`
5
+ through a deterministic, judgment-free numbered sequence. Use when the user types the command
6
+ to turn the brainstorm into a spec, asks to "write the spec", "spec this intent", "consolidate
7
+ into spec.md", or the active intent is at Why with enough Decisions on record to close it out.
8
+ Also fires on an indirect request that never names spec.md, such as "turn what we just
9
+ discussed into the contract the planner builds from." Distinct from `plastic-intent-brainstorming`
10
+ (the exploration that produces the enriched Why, upstream of this skill) and
11
+ `plastic-intent-planning` (turns an existing spec.md into plan.md for How, downstream of this
12
+ skill).
13
+ user-invocable: true
14
+ ---
15
+
16
+ # Intent Speccing
17
+
18
+ Consolidate the enriched Why into `spec.md` through eight fixed steps, one action per step. The
19
+ next action is never a judgment call: when a section cannot be filled from what is on record,
20
+ step 5 is to stop and ask, never invent.
21
+
22
+ ## Precondition
23
+
24
+ Run only when the active intent is at Why (its `## Intent` and enriched `## Context` plus
25
+ `### Decisions` exist, `spec.md` does not yet exist or is being redone) and the user has asked to
26
+ consolidate that Why into the spec. If no intent is active, or the active intent is not at Why,
27
+ report that and stop; do not guess which intent is meant.
28
+
29
+ ## The 8-step sequence
30
+
31
+ | Step | Action |
32
+ |---|---|
33
+ | 1 | Confirm the precondition above. |
34
+ | 2 | Read inputs in fixed order and build a ruling ledger: (a) `## Context` and `### Decisions`; (b) `## Insights` newest-last, so a later ruling supersedes an earlier conflicting one; (c) `resources/discovery--<slug>.md`; (d) any other `resources/*.md`. |
35
+ | 3 | Decide the tier: adopt the brainstorming `Tier:` recommendation from Decisions or Insights; otherwise apply the PLASTIC.md tiers rubric (S = single mechanism or file cluster, M = one subsystem, L = cross-cutting or novel design). |
36
+ | 4 | Fill the template section by section, all 8 sections in template order. Read `references/per-section-fill-rules.md` now, filling the template is the trigger. Write the tier as the literal top line above `# Spec:`. Encode every ruling into its matching section, later supersedes earlier on conflict. A collapsed single-line S/M section is complete and valid; do not pad it. |
37
+ | 5 | Gap rule: if any section cannot be filled from the ledger built in step 2, STOP and ask the user for the missing ruling. Never invent scope to fill a gap. |
38
+ | 6 | State the gate position (below) so the user knows what happens next. |
39
+ | 7 | Self-verify against the checklist. Read `references/self-verify-checklist.md` now, verifying before presenting is the trigger. Fix any failing check, then re-verify from the top. |
40
+ | 8 | Present `spec.md` for the user-review gate, then hand off to `plastic-intent-planning` for How. |
41
+
42
+ ## Gate position (step 6)
43
+
44
+ The Why stage's deliverable is `spec.md`; the gate is satisfied the moment a complete, real
45
+ `spec.md` exists (this is the gates-by-name framing: gate-check enforces spec.md before plan.md,
46
+ not the Transition Gates table row). Writing `plan.md` is what opens the code gate for Exec, and
47
+ writing `plan.md` is not this skill's job, that is `plastic-intent-planning`. State this to the user
48
+ at step 6 so the handoff at step 8 is expected, not a surprise.
49
+
50
+ ## Tier stamp (step 3, convention only)
51
+
52
+ Write `Tier: S|M|L` as the literal first line of the file, above the `# Spec:` heading. This line
53
+ is convention-only: the orchestrator and the planner read it, no gate and no doctor check
54
+ validates it.
55
+
56
+ ## Completion report
57
+
58
+ State, in this order: which file was written (`spec.md`, new or rewritten), the stamped `Tier:`
59
+ value, the count of Acceptance Criteria produced (the surface the planner will cover), which
60
+ `## Insights` rulings superseded an earlier Decision (if any) and where each landed, and the
61
+ handoff target (`plastic-intent-planning`). If step 5 stopped for a missing ruling, report that
62
+ instead: which section, what is missing, and the question put to the user.
63
+
64
+ ## References
65
+
66
+ | Trigger | Read |
67
+ |---|---|
68
+ | Filling the template (step 4) | `references/per-section-fill-rules.md` |
69
+ | Self-verifying before presenting (step 7) | `references/self-verify-checklist.md` |
@@ -0,0 +1,126 @@
1
+ {
2
+ "skill_name": "plastic-intent-speccing",
3
+ "notes": "Intent 163. Scopes: description triggering (1-4) and behavior (5-8: all-8-sections output, mandatory superseding-ruling case, STOP-and-ask gap rule, tabular alternatives with no em-dash). No dedicated Ruby test file backs this skill yet (natural-language guided command), so all assertions are result: expect-pass pending a real observed run, per the intent-starting evals.json convention.",
4
+ "evals": [
5
+ {
6
+ "id": 1,
7
+ "scope": "triggering",
8
+ "set": "train",
9
+ "prompt": "The active intent is at Why with Context and Decisions recorded. Consolidate the enriched Why into spec.md.",
10
+ "expected_output": "Activates plastic-intent-speccing (the user-typed Why-to-How consolidation command).",
11
+ "files": [],
12
+ "assertions": [
13
+ {
14
+ "type": "code",
15
+ "check": "router CHOICE == plastic-intent-speccing",
16
+ "result": "expect-pass"
17
+ }
18
+ ]
19
+ },
20
+ {
21
+ "id": 2,
22
+ "scope": "triggering",
23
+ "set": "train",
24
+ "prompt": "Turn what we just discussed into the contract the planner builds from.",
25
+ "expected_output": "Activates plastic-intent-speccing; an indirect trigger that names neither the skill nor spec.md.",
26
+ "files": [],
27
+ "assertions": [
28
+ {
29
+ "type": "code",
30
+ "check": "router CHOICE == plastic-intent-speccing",
31
+ "result": "expect-pass"
32
+ }
33
+ ]
34
+ },
35
+ {
36
+ "id": 3,
37
+ "scope": "triggering",
38
+ "set": "validation",
39
+ "prompt": "Brainstorm this intent.",
40
+ "expected_output": "Does NOT activate plastic-intent-speccing; activates plastic-intent-brainstorming (exploration that produces the enriched Why, upstream of speccing).",
41
+ "files": [],
42
+ "assertions": [
43
+ {
44
+ "type": "code",
45
+ "check": "router CHOICE != plastic-intent-speccing",
46
+ "result": "expect-pass"
47
+ }
48
+ ]
49
+ },
50
+ {
51
+ "id": 4,
52
+ "scope": "triggering",
53
+ "set": "validation",
54
+ "prompt": "Write the plan.",
55
+ "expected_output": "Does NOT activate plastic-intent-speccing; activates plastic-intent-planning (turns an existing spec.md into plan.md for How, downstream of speccing).",
56
+ "files": [],
57
+ "assertions": [
58
+ {
59
+ "type": "code",
60
+ "check": "router CHOICE != plastic-intent-speccing",
61
+ "result": "expect-pass"
62
+ }
63
+ ]
64
+ },
65
+ {
66
+ "id": 5,
67
+ "scope": "behavior",
68
+ "set": "train",
69
+ "prompt": "Intent Y is at Why: Context describes the problem and goal, and 5 Decisions are recorded resolving scope, approach, and one rejected alternative. Consolidate into spec.md.",
70
+ "expected_output": "Produces spec.md with Tier: S|M|L as the literal top line above the Spec heading; all 8 template sections present once, in template order (Problem, Goals, Non-Goals, Approach, Alternatives Considered, Decisions, Acceptance Criteria, Open Questions); no template placeholder text remains; every recorded Decision is encoded into its matching section.",
71
+ "files": [],
72
+ "assertions": [
73
+ {
74
+ "type": "human",
75
+ "check": "Tier line is literally the first line of the file; all 8 sections appear once each, in template order; no placeholder text; every Decision traces to a section",
76
+ "result": "expect-pass"
77
+ }
78
+ ]
79
+ },
80
+ {
81
+ "id": 6,
82
+ "scope": "behavior",
83
+ "set": "train",
84
+ "prompt": "Intent Z has Decisions recording D4: ship the setting as a CLI flag. A later Insights entry, timestamped after D4, reads: superseding ruling, ship as a config-file setting instead of a CLI flag, per user correction. Consolidate into spec.md.",
85
+ "expected_output": "The produced spec Approach and Decisions sections encode the LATER ruling (config-file setting); the superseded earlier Decision (CLI flag) does not stand as the shipped design in any section. The Decisions section notes that the later Insight supersedes D4.",
86
+ "files": [],
87
+ "assertions": [
88
+ {
89
+ "type": "human",
90
+ "check": "Approach and Decisions state the config-file setting, not the CLI flag; no section still asserts the CLI-flag path as the shipped design",
91
+ "result": "expect-pass"
92
+ }
93
+ ]
94
+ },
95
+ {
96
+ "id": 7,
97
+ "scope": "behavior",
98
+ "set": "validation",
99
+ "prompt": "Intent W is at Why. Context says the team wants error handling that is more resilient, but no Decision or Insight states which specific mechanism (retry, circuit breaker, or fallback) was chosen. Consolidate into spec.md.",
100
+ "expected_output": "Stops at step 5 (the gap rule) instead of inventing an Approach; asks the user which error-handling mechanism was decided, naming the missing ruling and the section it blocks.",
101
+ "files": [],
102
+ "assertions": [
103
+ {
104
+ "type": "human",
105
+ "check": "no invented Approach or Decisions content fills the gap; the agent asks for the missing ruling instead of guessing a default mechanism",
106
+ "result": "expect-pass"
107
+ }
108
+ ]
109
+ },
110
+ {
111
+ "id": 8,
112
+ "scope": "behavior",
113
+ "set": "validation",
114
+ "prompt": "Intent V has Decisions recording 3 rejected alternatives, each with a one-line reason it lost. Consolidate into spec.md.",
115
+ "expected_output": "Alternatives Considered renders as a table (Alternative, Not chosen because), not the bullet-dash form shown in the template; the produced spec file contains no em-dashes or en-dashes anywhere in the file.",
116
+ "files": [],
117
+ "assertions": [
118
+ {
119
+ "type": "human",
120
+ "check": "Alternatives Considered is a two-column table with one row per rejected alternative; a full-file dash-glyph scan of the produced spec file finds none",
121
+ "result": "expect-pass"
122
+ }
123
+ ]
124
+ }
125
+ ]
126
+ }
@@ -0,0 +1,92 @@
1
+ # Per-Section Fill Rules
2
+
3
+ The single shared method for turning the enriched Why into `spec.md`. Both
4
+ `plastic-intent-speccing` (guided) and the `plastic-spec-specialist` agent (auto) point here;
5
+ neither restates these rules. One fill rule per template section, in template order.
6
+
7
+ Read the ruling ledger first (built in step 2 of the SKILL.md sequence): `## Context` plus
8
+ `### Decisions`, then `## Insights` newest-last (a later ruling supersedes an earlier
9
+ conflicting one), then `resources/discovery--<slug>.md`, then any other `resources/*.md`.
10
+ Every rule below names which part of that ledger feeds the section.
11
+
12
+ ## 1. Problem
13
+
14
+ Source: the intent's `## Intent` line plus the problem narrative in `## Context`.
15
+
16
+ State the problem as a problem, not a solution: what is broken, missing, or costly today, for
17
+ whom. Do not describe the fix here, that belongs in Approach. If `## Insights` records a later
18
+ reframe of the problem (a scope correction, a retargeted root cause), the later framing wins.
19
+
20
+ ## 2. Goals
21
+
22
+ Source: explicit goal statements in `## Context`, plus any `### Decisions` entry that commits to
23
+ delivering a specific outcome.
24
+
25
+ One bullet per goal, each a concrete, observable outcome the delivery must reach. Encode every
26
+ Decision that commits to an outcome as its own bullet, do not compress two Decisions into one
27
+ vague goal. A single-line collapsed Goals section (S/M tier) is complete if it names every
28
+ outcome; do not pad it with restated Problem text.
29
+
30
+ ## 3. Non-Goals
31
+
32
+ Source: `### Decisions` entries that name something explicitly out of scope, and `## Insights`
33
+ rulings that narrowed scope after the initial brainstorm.
34
+
35
+ One bullet per excluded item, each naming what is out and, briefly, why (a sibling intent owns
36
+ it, a scope-reframe ruling cut it, it is a future intent). If a later Insight narrows scope
37
+ further than an earlier Decision, the Insight's narrower boundary is the one recorded.
38
+
39
+ ## 4. Approach
40
+
41
+ Source: every `### Decisions` entry that describes HOW, resolved into one coherent narrative.
42
+
43
+ Write prose, not a decision list. Synthesize the chosen path so it reads as one design: what
44
+ gets built, in what shape, and how the pieces fit. Every Decision that shapes the approach must
45
+ be traceable to a sentence here, but do not restate each Decision by its Dn label, that
46
+ enumeration belongs in the Decisions section. Use a table only where the Approach itself compares
47
+ options inline (rare; usually that comparison belongs in Alternatives Considered instead).
48
+
49
+ ## 5. Alternatives Considered
50
+
51
+ Source: `### Decisions` entries and `## Insights` rulings that name a rejected path and the
52
+ reason it lost.
53
+
54
+ Render as a table, not the template's bullet-dash form, so the reason column stays uniform and
55
+ free of dash-glyph punctuation:
56
+
57
+ | Alternative | Not chosen because |
58
+ |---|---|
59
+ | <rejected path> | <the ruling's stated reason, paraphrased> |
60
+
61
+ One row per rejected alternative. If two Decisions reject variants of the same alternative, merge
62
+ them into one row rather than duplicating it. Never use an em-dash or en-dash in the reason
63
+ column; write "because" or a colon instead.
64
+
65
+ ## 6. Decisions
66
+
67
+ Source: `### Decisions` verbatim, in the order recorded, one entry per Decision.
68
+
69
+ One bullet per decision, each keeping its `Dn` label and its ruling in paraphrase or verbatim.
70
+ Do not drop a decision because it seems minor: every Decision must appear here even if its effect
71
+ on the shipped Approach or Goals is small. When `## Insights` records a later ruling that
72
+ supersedes an earlier Decision, add or amend the bullet to state the later ruling and note which
73
+ earlier Decision it supersedes.
74
+
75
+ ## 7. Acceptance Criteria
76
+
77
+ Source: any criteria named directly in `### Decisions` or `## Insights`, plus one inferred
78
+ criterion per Goal that has no explicit criterion on record.
79
+
80
+ One checkbox bullet per criterion, each concretely checkable: a fact a reviewer can confirm true
81
+ or false by inspection, a command, or a file, never a vague quality judgment. Every Goal must map
82
+ to at least one criterion. A criterion that cannot be checked without more interpretation is not
83
+ done, rewrite it or ask (the gap rule, SKILL.md step 5).
84
+
85
+ ## 8. Open Questions
86
+
87
+ Source: any question raised during Why that has no matching Decision or Insight resolving it.
88
+
89
+ List each unresolved question as its own bullet. If every question raised during Why has a
90
+ resolving Decision or Insight, write `None` and, directly under it, one line per resolved
91
+ question naming which Decision or Insight resolved it (so a reader can audit the resolution
92
+ instead of taking "None" on faith).
@@ -0,0 +1,38 @@
1
+ # Self-Verify Checklist
2
+
3
+ Run this before presenting spec.md (SKILL.md step 7). Ten checks: the four points of
4
+ brainstorming's proven Spec Self-Review, merged with the six binding output checks this skill
5
+ adds. Fix any failing check, then re-verify from the top; do not present a spec that fails one of
6
+ these.
7
+
8
+ ## Brainstorming's four Spec Self-Review points
9
+
10
+ 1. **Placeholder scan.** Any "TBD", "TODO", incomplete section, or vague requirement left in the
11
+ draft? Fix it before moving on.
12
+ 2. **Internal consistency.** Do any two sections contradict each other? Does the Approach
13
+ actually match what Goals and Acceptance Criteria describe?
14
+ 3. **Scope check.** Is this spec focused enough for a single implementation plan, or does the
15
+ Problem actually describe more than one independent piece of work that needs decomposing
16
+ first?
17
+ 4. **Ambiguity check.** Could any requirement be read two different ways? If so, pick one
18
+ reading and rewrite the line so only that reading survives.
19
+
20
+ ## The six binding output checks
21
+
22
+ 5. **No template placeholder text remains.** No literal `<intent name>`, `<alternative>`, `...`,
23
+ sample bracket text, or other template filler from `templates/spec.md` survives anywhere in
24
+ the artifact.
25
+ 6. **Tier stamp is the top line.** `Tier: S|M|L` is the literal first line of the file, above the
26
+ `# Spec:` heading, not folded into a section body.
27
+ 7. **All 8 sections present, in template order.** Problem, Goals, Non-Goals, Approach,
28
+ Alternatives Considered, Decisions, Acceptance Criteria, Open Questions, each present once, in
29
+ that order, none merged into another.
30
+ 8. **Every `## Insights` ruling is traceable to a spec line.** Walk the Insights log entry by
31
+ entry: each one lands in some section of the spec. Where two rulings conflict, the later one
32
+ (further down the log) is the one that landed, and the earlier one does not silently persist
33
+ in a different section.
34
+ 9. **Acceptance criteria are concretely checkable.** Each Acceptance Criteria bullet reads as a
35
+ fact a reviewer can confirm true or false by inspection, a command, or a named file, not a
36
+ quality judgment a reviewer would have to interpret.
37
+ 10. **No em-dashes or en-dashes anywhere in the artifact.** Scan the full file; replace any dash
38
+ glyph with a comma, period, parenthesis, or colon.
@@ -57,7 +57,7 @@ enforces it: without a held lock, mutating writes to this active intent's dir ar
57
57
  4. **Dispatch What-stage discovery (under the lock).** Right after arming, when the intent
58
58
  was just activated in step 1 (on a resume that already has
59
59
  `resources/discovery--<slug>.md`, skip: discovery runs once per intent, at activation
60
- only), dispatch the `plastic-intent-discovery` agent (see the `plastic-intent-discovery`
60
+ only), dispatch the `plastic-intent-discovery` agent (see the `plastic-intent-discovering`
61
61
  skill), now that this session owns the lock, deposit authorized as the owner session. Resolve its
62
62
  model explicitly and pass it at dispatch time (belt-and-braces): `read-config
63
63
  agents.models.plastic-intent-discovery --project <repo>`. The agent runs QMD discovery
@@ -88,7 +88,7 @@ that message, never delete a lock file by hand.
88
88
  Read `savepoint.md` and classify from the **last line** alone, then verify ONLY that line's
89
89
  artifact is real (sentinel-aware via `Bridge.stage_file_present?`). On drift (the last line
90
90
  disagrees with files on disk), rebuild the ledger from disk and note the correction. Do not
91
- inline the rebuild; the `plastic-savepoint` skill owns it:
91
+ inline the rebuild; the `plastic-intent-savepoint` skill owns it:
92
92
  ```bash
93
93
  ruby -r ~/.plastic/scripts/lib/bridge -e 'Bridge.rebuild_savepoint("<intent_dir>")'
94
94
  ```
@@ -40,7 +40,7 @@
40
40
  "scope": "triggering",
41
41
  "set": "validation",
42
42
  "prompt": "continue",
43
- "expected_output": "Does NOT activate plastic-intent-starting; bare 'continue' is plastic-continuing (no specific intent named).",
43
+ "expected_output": "Does NOT activate plastic-intent-starting; bare 'continue' is plastic-continuing (the router, no specific intent named).",
44
44
  "files": [],
45
45
  "assertions": [
46
46
  { "type": "code", "check": "router CHOICE != plastic-intent-starting", "result": "expect-pass" }
@@ -51,7 +51,7 @@
51
51
  "scope": "triggering",
52
52
  "set": "validation",
53
53
  "prompt": "create a new intent for the uploader retry policy",
54
- "expected_output": "Does NOT activate plastic-intent-starting; activates plastic-creating-intent.",
54
+ "expected_output": "Does NOT activate plastic-intent-starting; activates plastic-intent-creating.",
55
55
  "files": [],
56
56
  "assertions": [
57
57
  { "type": "code", "check": "router CHOICE != plastic-intent-starting", "result": "expect-pass" }
@@ -0,0 +1,104 @@
1
+ ---
2
+ name: plastic-project-continuing
3
+ description: >-
4
+ Use when the user wants to land on the project board, asks "what should I work on" in this
5
+ project, or wants active intents plus the most-valuable next work surfaced. This is the
6
+ default route of plastic-continuing for a bare "continue" with no specific intent or roadmap
7
+ named. It presents state and stops without asking how to proceed - that single mode question
8
+ lives in plastic-intent-starting, once the user names a specific intent to work.
9
+ user-invocable: true
10
+ ---
11
+
12
+ # Project Continuing - land on the board
13
+
14
+ `plastic-project-continuing` is the project route of `plastic-continuing`. It lands on the
15
+ Markdown board, presents active work and the most-valuable next work, and stops. It does not
16
+ resume a specific intent by ledger (that is `plastic-intent-continuing`) and it asks nothing.
17
+
18
+ ## Continue (present the board)
19
+
20
+ Land on the Markdown board via the `plastic-dashboard` skill. Rendering belongs there, not
21
+ here - run the data payload and fill + present the matching template:
22
+ - Project loaded -> `ruby ~/.plastic/scripts/dashboard.rb project <slug> --data`
23
+ - Otherwise (no project loaded, the global fallback) -> `ruby ~/.plastic/scripts/dashboard.rb continue --data`
24
+
25
+ Fill the matching template from `plastic-dashboard`'s `templates/` and **present the filled
26
+ Markdown in your reply** (every time, non-optional). If the reply does not contain the filled
27
+ Markdown, the user sees nothing - tool-call stdout and hook `additionalContext` are both
28
+ invisible to them. `hook-continue` also emits a one-line `systemMessage` summary as a
29
+ hook-owned fallback; treat it as a floor only, never as a substitute for presenting the full
30
+ board here. See `plastic-dashboard` for the fill mechanics (`references/board-fill.md` has the
31
+ scoped detail).
32
+
33
+ The board load runs the scoped store check on every load (`doctor --store <scope>`): the
34
+ global board runs `--store global` and a project board runs `--store <slug>`. The result
35
+ arrives in the payload as `store_health`; surface it as a one-line store-health note. It is
36
+ non-fatal (a warn or fail is shown as data, it does not block continuing).
37
+
38
+ ## Priority Order
39
+
40
+ 1. **Active intents first** - surface work in progress.
41
+ 2. **Project context** - if in a registered project, show governing + tactical intents.
42
+ 3. **Stale future intents** - surface for triage (see below).
43
+ 4. **Fresh future intents** - offer as next work.
44
+
45
+ ## Stale Future Intents
46
+
47
+ If a future intent's `created` date is older than the configured `stale_threshold_days`
48
+ (default 3), surface it for triage without taking action:
49
+
50
+ ```
51
+ Stale future intents (no action taken):
52
+
53
+ - [ID - name] (X days old)
54
+ a) Activate - start working on it now
55
+ b) Abandon - mark as abandoned
56
+ c) Defer to agent: implement | research | ideate
57
+ d) Auto - go fully autonomous (invokes plastic-auto)
58
+ ```
59
+
60
+ When the user activates a future intent, move it to `## Active` in INDEX.md and auto-commit.
61
+
62
+ **Defer to agent: research.** Selecting `research` is a real dispatch, not a label. Resolve
63
+ `plastic-future-intent-researcher`'s model via `read-config agents.models.<basename> --project
64
+ <repo>` (project override, then global, then the shipped tier default) rather than relying on
65
+ bare frontmatter, which also honors a sanctioned `agents.models.<name>` override if one is
66
+ configured. Dispatch the agent (Agent tool, `subagent_type: "plastic-future-intent-researcher"`)
67
+ on the selected stale future intent, passing the resolved model explicitly. The agent writes its
68
+ findings into that intent's `## Context` (see `agents/plastic-future-intent-researcher.md`); it
69
+ does not itself dispatch further sub-agents. Once it returns, re-present the stale-future-intent
70
+ triage so the user can act on the fresh findings now on record.
71
+
72
+ ## Deciding rules
73
+
74
+ The board's ranked next-work order is deterministic, computed by `dashboard.rb`; this skill
75
+ never re-derives it. Cite the rule NAMES only when explaining a ranking or disposition: Effort,
76
+ Value, Flags, Override, Caps. Read `plastic-dashboard`'s `references/classification.md` for the
77
+ definitions; do not restate or copy them here.
78
+
79
+ ## Then stop
80
+
81
+ Present "here is the state, what next?" and wait. Offer active intents first, then future
82
+ intents. Do not start executing work. The only follow-up from here:
83
+ - User/agent names a specific intent to continue -> hand to `plastic-intent-continuing`
84
+ (which reads the ledger and, in turn, hands to `plastic-intent-starting` for the single
85
+ auto-or-guided ask).
86
+
87
+ ## Coordination
88
+
89
+ Intent 149 has landed: the dashboard is demoted to prose (no Value x Effort grid). This skill
90
+ was built against the live INDEX.md-parsing `--data` path (147, the DB cutover, has not
91
+ landed). Its rule-name citations (`classification.md`, cited by name, not logic) and the
92
+ `dashboard.rb project <slug> --data` -> `dashboard-project.md` path still resolve.
93
+
94
+ Intent 148 landed: roadmaps are the primary planning surface. When the tier has a mid-flight
95
+ roadmap (`ruby ~/.plastic/scripts/roadmap-next --roadmaps-dir <tier>/roadmaps` reports a `state`
96
+ other than `none`), the roadmap route (`plastic-roadmap-continuing`) is the live surface for
97
+ "what to work next", and `plastic-continuing` routes there. This board still presents project
98
+ state and stops, asking nothing (unchanged): it does not itself dispatch, re-rank, or resume a
99
+ roadmap. The global store and any project with no roadmap report `none`, so this board stays the
100
+ default route for them.
101
+
102
+ ## References
103
+
104
+ - `references/board-fill.md` - the template-fill mechanics and store-health surfacing detail.
@@ -0,0 +1,100 @@
1
+ {
2
+ "skill_name": "plastic-project-continuing",
3
+ "notes": "Intent 158a1. New project route, absorbing intent-continuing's Continue/Priority Order/Stale Future Intents sections (move, not duplicate). Scopes: description triggering (1-3) and behavior/convention compliance (4-10), the latter checked against SKILL.md.",
4
+ "results": {
5
+ "triggering": { "cases": 3, "passed": 3, "run": "2026-07-10, one subagent per case" },
6
+ "behavior": { "cases": 7, "passed": 7, "evidence": "convention checks against skills/project-continuing/SKILL.md after the 158a1 extraction; id 10 (intent 170) added for the research-dispatch wiring of plastic-future-intent-researcher" }
7
+ },
8
+ "evals": [
9
+ {
10
+ "id": 1, "scope": "triggering", "set": "train",
11
+ "prompt": "what should I work on in this project",
12
+ "expected_output": "Activates plastic-project-continuing.",
13
+ "files": [],
14
+ "assertions": [
15
+ { "type": "code", "check": "router CHOICE == plastic-project-continuing", "observed": "plastic-project-continuing", "result": "pass" }
16
+ ]
17
+ },
18
+ {
19
+ "id": 2, "scope": "triggering", "set": "train",
20
+ "prompt": "land me on the project board",
21
+ "expected_output": "Activates plastic-project-continuing.",
22
+ "files": [],
23
+ "assertions": [
24
+ { "type": "code", "check": "router CHOICE == plastic-project-continuing", "observed": "plastic-project-continuing", "result": "pass" }
25
+ ]
26
+ },
27
+ {
28
+ "id": 3, "scope": "triggering", "set": "validation",
29
+ "prompt": "continue",
30
+ "expected_output": "Bare 'continue' with no specific intent or roadmap named reaches plastic-project-continuing via plastic-continuing's default route.",
31
+ "files": [],
32
+ "assertions": [
33
+ { "type": "code", "check": "router CHOICE == plastic-project-continuing", "observed": "plastic-project-continuing", "result": "pass" }
34
+ ]
35
+ },
36
+ {
37
+ "id": 4, "scope": "behavior", "set": "train",
38
+ "prompt": "Is dashboard selection project-aware?",
39
+ "expected_output": "Project loaded -> `dashboard.rb project <slug> --data` -> fills dashboard-project.md; otherwise -> `dashboard.rb continue --data`. Skill only invokes, does not render.",
40
+ "files": ["skills/project-continuing/SKILL.md"],
41
+ "assertions": [
42
+ { "type": "convention", "check": "both dashboard invocations present and gated on project detection", "observed": "'dashboard.rb project <slug>' and 'dashboard.rb continue' in the 'Continue (present the board)' section", "result": "pass" }
43
+ ]
44
+ },
45
+ {
46
+ "id": 5, "scope": "behavior", "set": "train",
47
+ "prompt": "Does the skill cite the classification rules by name instead of copying the logic?",
48
+ "expected_output": "SKILL.md's 'Deciding rules' section names Effort/Value/Flags/Override/Caps and points to plastic-dashboard's references/classification.md; it does not restate the rule definitions.",
49
+ "files": ["skills/project-continuing/SKILL.md"],
50
+ "assertions": [
51
+ { "type": "convention", "check": "rule names cited, no copied Effort/Value/Flags/Override/Caps definitions", "observed": "present in 'Deciding rules'", "result": "pass" }
52
+ ]
53
+ },
54
+ {
55
+ "id": 6, "scope": "behavior", "set": "train",
56
+ "prompt": "Does the project route ask 'auto or guided?' before stopping?",
57
+ "expected_output": "No. The project route presents state then stops; it asks nothing. The single ask lives in plastic-intent-starting once a specific intent is named.",
58
+ "files": ["skills/project-continuing/SKILL.md"],
59
+ "assertions": [
60
+ { "type": "convention", "check": "no 'auto or guided' ask anywhere in SKILL.md", "observed": "absent", "result": "pass" }
61
+ ]
62
+ },
63
+ {
64
+ "id": 7, "scope": "behavior", "set": "validation",
65
+ "prompt": "Does the skill present the board before stopping?",
66
+ "expected_output": "The filled Markdown board is presented in the reply (non-optional), then a 'Then stop' section waits for the user.",
67
+ "files": ["skills/project-continuing/SKILL.md"],
68
+ "assertions": [
69
+ { "type": "convention", "check": "presentation is mandatory and precedes the 'Then stop' wait", "observed": "present", "result": "pass" }
70
+ ]
71
+ },
72
+ {
73
+ "id": 8, "scope": "behavior", "set": "validation",
74
+ "prompt": "Does the skill carry the intent-149 coordination note?",
75
+ "expected_output": "A 'Coordination' section records that intent 149 has landed (dashboard demoted to prose, no Value x Effort grid) and confirms the rule-name citations and the dashboard.rb project <slug> --data -> dashboard-project.md path still resolve.",
76
+ "files": ["skills/project-continuing/SKILL.md"],
77
+ "assertions": [
78
+ { "type": "convention", "check": "'149' present with the landed coordination note", "observed": "present: 'Intent 149 has landed' with confirmed rule-name citations and dashboard.rb path", "result": "pass" }
79
+ ]
80
+ },
81
+ {
82
+ "id": 9, "scope": "behavior", "set": "validation",
83
+ "prompt": "Are Priority Order and Stale Future Intents present here and only here (not in intent-continuing)?",
84
+ "expected_output": "Both sections are present verbatim in this skill; they no longer exist in skills/intent-continuing/SKILL.md.",
85
+ "files": ["skills/project-continuing/SKILL.md", "skills/intent-continuing/SKILL.md"],
86
+ "assertions": [
87
+ { "type": "convention", "check": "'## Priority Order' and '## Stale Future Intents' present here, absent from intent-continuing", "observed": "present here, absent there", "result": "pass" }
88
+ ]
89
+ },
90
+ {
91
+ "id": 10, "scope": "behavior", "set": "validation",
92
+ "prompt": "In the stale-future-intent triage, the user picks option c) Defer to agent: research. What happens?",
93
+ "expected_output": "A real dispatch, not a label: plastic-future-intent-researcher's model is resolved via `read-config agents.models.<basename> --project <repo>` (never bare frontmatter, sanctioned-override-aware), the agent is dispatched via the Agent tool on the selected stale future intent and writes its findings into that intent's `## Context`, then the skill re-presents the stale-future-intent triage.",
94
+ "files": ["skills/project-continuing/SKILL.md"],
95
+ "assertions": [
96
+ { "type": "convention", "check": "the 'Defer to agent: research' paragraph under Stale Future Intents resolves the model via read-config (not bare frontmatter), dispatches plastic-future-intent-researcher via the Agent tool, and re-presents the triage after the agent returns", "observed": "'Defer to agent: research.' paragraph present: resolves via read-config agents.models.<basename> --project <repo>, dispatches subagent_type plastic-future-intent-researcher, findings land in ## Context, then re-presents the triage", "result": "pass" }
97
+ ]
98
+ }
99
+ ]
100
+ }
@@ -0,0 +1,33 @@
1
+ # Board Fill Mechanics
2
+
3
+ Depth reference for the "Continue (present the board)" section of `SKILL.md`. The fill itself
4
+ is mechanical; `plastic-dashboard` owns the rules, this page is a pointer plus the detail that
5
+ would otherwise bloat the SKILL.md body.
6
+
7
+ ## Fill rules (owned by plastic-dashboard, summarized here for convenience)
8
+
9
+ - `{{a.b.count}}` -> the integer (e.g. `counts.active` is that count).
10
+ - `{{...lines}}` -> join the list's `.line` strings with real newlines (one per line). These
11
+ are ordinary prose lines; never add a `-` prefix, never emit `<br>`. An empty list renders
12
+ `_(none)_`.
13
+ - `next_work.lines` -> the most-valuable next work, already ranked and capped.
14
+ - `active.lines` / `future.lines` (project board) -> one line per intent, already formatted.
15
+ - Scalars (`{{date}}`, `{{slug}}`, `{{description}}`) -> substitute verbatim.
16
+
17
+ No re-sorting, no re-summarizing, no hand-written prose replacing a line the payload already
18
+ supplies. Same store state produces a byte-identical payload regardless of model.
19
+
20
+ ## Store-health surfacing
21
+
22
+ Every board load runs the scoped `doctor --store <scope>` check server-side (inside
23
+ `dashboard.rb`, not this skill). The payload carries the result as `store_health` (`{scope,
24
+ status, summary, failing_checks}`). Render it as a single line, for example `store health:
25
+ pass (3/3)` or `store health: warn (orphaned_intents)`. A warn or fail is informational only;
26
+ it never blocks presenting the board.
27
+
28
+ ## Project vs. global fallback
29
+
30
+ The project route's default target is the project board. When no project is loaded (the rare
31
+ case where this route is reached without a registered project in scope), fall back to the
32
+ global board payload (`dashboard.rb continue --data`) rather than failing. This mirrors the
33
+ router's D6 default: a bare "continue" always lands somewhere useful.