@zalom/plastic 1.1.0 → 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 (54) hide show
  1. package/PLASTIC.md +4 -2
  2. package/README.md +3 -3
  3. package/agents/plastic-enforcer.md +5 -2
  4. package/agents/plastic-future-intent-researcher.md +1 -1
  5. package/hooks/check-update +1 -1
  6. package/hooks/continue +1 -1
  7. package/package.json +1 -1
  8. package/scripts/dashboard.rb +29 -24
  9. package/scripts/doctor.rb +136 -5
  10. package/scripts/hook-continue +3 -3
  11. package/scripts/install.rb +2 -1
  12. package/scripts/lib/bridge.rb +81 -0
  13. package/scripts/lib/dashboard_banner.rb +8 -9
  14. package/scripts/lib/installer_core.rb +10 -3
  15. package/scripts/lib/legacy_bookend_amnesty.rb +35 -0
  16. package/scripts/lib/release_guard.rb +62 -0
  17. package/scripts/lib/roadmap_queue.rb +285 -0
  18. package/scripts/lib/roadmap_savepoint.rb +213 -0
  19. package/scripts/lib/worktree.rb +21 -0
  20. package/scripts/new-intent +1 -0
  21. package/scripts/read-config +3 -3
  22. package/scripts/roadmap-next +44 -0
  23. package/scripts/roadmap-savepoint +64 -0
  24. package/skills/auto/SKILL.md +22 -4
  25. package/skills/continuing/SKILL.md +34 -0
  26. package/skills/continuing/evals/evals.json +91 -0
  27. package/skills/dashboard/SKILL.md +17 -14
  28. package/skills/dashboard/references/classification.md +3 -3
  29. package/skills/dashboard/templates/dashboard-global.md +8 -23
  30. package/skills/dashboard/templates/dashboard-project.md +7 -26
  31. package/skills/doctor/SKILL.md +1 -1
  32. package/skills/install/SKILL.md +10 -10
  33. package/skills/intent-continuing/SKILL.md +26 -68
  34. package/skills/intent-continuing/evals/evals.json +26 -26
  35. package/skills/intent-continuing/references/context-management.md +15 -19
  36. package/skills/intent-savepoint/SKILL.md +12 -0
  37. package/skills/intent-starting/evals/evals.json +1 -1
  38. package/skills/project-continuing/SKILL.md +104 -0
  39. package/skills/project-continuing/evals/evals.json +100 -0
  40. package/skills/project-continuing/references/board-fill.md +33 -0
  41. package/skills/releasing/SKILL.md +48 -0
  42. package/skills/releasing/references/release-lines.md +105 -0
  43. package/skills/roadmap/SKILL.md +7 -1
  44. package/skills/roadmap/references/file-format.md +30 -1
  45. package/skills/roadmap/references/operations.md +26 -6
  46. package/skills/roadmap-continuing/SKILL.md +85 -0
  47. package/skills/roadmap-continuing/evals/evals.json +82 -0
  48. package/skills/roadmap-continuing/references/liveness-ranking.md +56 -0
  49. package/skills/skill-evaluating/evals/evals.json +1 -1
  50. package/skills/tutorial/references/track-2-auto.md +1 -1
  51. package/skills/uninstall/SKILL.md +2 -2
  52. package/skills/update/SKILL.md +2 -2
  53. package/templates/config.yml +2 -1
  54. package/templates/index.md +4 -1
@@ -0,0 +1,64 @@
1
+ #!/usr/bin/env ruby
2
+ # encoding: UTF-8
3
+ # frozen_string_literal: true
4
+
5
+ # roadmap-savepoint - deterministic CLI over RoadmapSavepoint (intent 134).
6
+ #
7
+ # The plastic-roadmap skill verbs and the coordinator flows call this instead of hand-writing
8
+ # ledger lines. append is idempotent on the (event, detail) pair; rebuild is the one operation
9
+ # allowed to overwrite the ledger, reconstructing it from the roadmap's own `## Log`.
10
+ #
11
+ # Usage:
12
+ # roadmap-savepoint append --roadmap <path> --event <event> --detail "<text>"
13
+ # roadmap-savepoint rebuild --roadmap <path>
14
+ #
15
+ # Exits non-zero with a usage line on stderr for an unknown verb or a missing required flag.
16
+
17
+ require_relative "lib/roadmap_savepoint"
18
+
19
+ def opt(args, name)
20
+ (i = args.index(name)) && args[i + 1]
21
+ end
22
+
23
+ def usage
24
+ warn "Usage: roadmap-savepoint append --roadmap <path> --event <event> --detail \"<text>\""
25
+ warn " roadmap-savepoint rebuild --roadmap <path>"
26
+ end
27
+
28
+ verb = ARGV.shift
29
+
30
+ case verb
31
+ when "append"
32
+ roadmap = opt(ARGV, "--roadmap")
33
+ event = opt(ARGV, "--event")
34
+ detail = opt(ARGV, "--detail")
35
+ if roadmap.nil? || event.nil? || detail.nil?
36
+ warn "append: pass --roadmap <path> --event <event> --detail \"<text>\""
37
+ usage
38
+ exit 2
39
+ end
40
+ begin
41
+ wrote = RoadmapSavepoint.append(roadmap, event, detail)
42
+ puts wrote ? "appended #{event} #{detail}" : "no-op (already recorded): #{event} #{detail}"
43
+ exit 0
44
+ rescue ArgumentError => e
45
+ warn "append: #{e.message}"
46
+ exit 2
47
+ end
48
+
49
+ when "rebuild"
50
+ roadmap = opt(ARGV, "--roadmap")
51
+ if roadmap.nil?
52
+ warn "rebuild: pass --roadmap <path>"
53
+ usage
54
+ exit 2
55
+ end
56
+ count = RoadmapSavepoint.rebuild(roadmap)
57
+ puts "rebuilt #{count} line#{count == 1 ? '' : 's'}"
58
+ exit 0
59
+
60
+ else
61
+ warn "roadmap-savepoint: unknown verb #{verb.inspect}. Use append|rebuild."
62
+ usage
63
+ exit 2
64
+ end
@@ -15,7 +15,9 @@ Announce: "Taking over intent [ID] - [name] for autonomous delivery."
15
15
  orchestrating main session on the best available thinking model (Fable, Opus, or whatever
16
16
  supersedes them) for the sharpest gating and synthesis. This is advice only: it changes no
17
17
  behavior and blocks nothing if ignored. It concerns the human's MAIN session; dispatched
18
- subagents keep their pinned tier and never resolve to Fable.
18
+ subagents keep their pinned tier and never resolve to Fable, unless an explicit
19
+ `agents.models.<name>` config override names Fable for that role, in which case the override
20
+ is honored as written.
19
21
 
20
22
  ## Precondition
21
23
 
@@ -24,8 +26,22 @@ An active intent MUST exist in INDEX.md. If none exists, refuse: "No active inte
24
26
  If multiple active intents exist, ask the user which one to deliver (this is the only question auto asks).
25
27
 
26
28
  **Picking work when no intent is specified.** If the user says "auto" without naming an
27
- intent and none is active, consult the dashboard's machine-readable queue to choose the
28
- next dispatchable intent:
29
+ intent and none is active, consult the roadmap first (the primary planning surface), then
30
+ fall back to the dashboard queue. Read the tier's mid-flight roadmap:
31
+
32
+ ```bash
33
+ ruby ~/.plastic/scripts/roadmap-next --roadmaps-dir <tier>/roadmaps
34
+ ```
35
+
36
+ Branch on `state`:
37
+ - `dispatchable`: work its `dispatchable_queue` in `rank` order (the head is the next batch
38
+ entry). These are the current batch's `queued` intents, parallel-safe within the wave.
39
+ - `in_flight`: the frontier batch is still delivering. Report it and wait. Do NOT dispatch a
40
+ later batch and do NOT fall through to the dashboard, the roadmap is live.
41
+ - `none` or `exhausted`: no roadmap, or nothing left to dispatch. Fall back to the dashboard
42
+ queue below. (The global store has no roadmap, so it always reports `none` and falls back.)
43
+
44
+ Dashboard fallback:
29
45
 
30
46
  ```bash
31
47
  ruby ~/.plastic/scripts/dashboard.rb all --json
@@ -108,7 +124,9 @@ Dispatch rule: sequential, one specialist per stage on one branch (the deliverab
108
124
 
109
125
  Spawn preamble (live-state injection): before dispatching any specialist, run `scripts/spawn-preamble <intent_dir> --role <role>` and PREPEND its output to that specialist's prompt. The preamble is a deterministic, filesystem-only snapshot of the active intent (id, intent line, current stage, and the provisioned code worktree path when one exists on disk) plus the honoring instruction, so every spawned agent boots with accurate live state instead of guessing. This is the authoritative L2 mechanism for harnesses whose sub-agents do not inherit a top-level session event (see `docs/reference/harness-adapters.md`).
110
126
 
111
- Dispatch-time model contract (belt-and-braces): alongside the preamble, resolve each specialist's model through the config chain (`read-config agents.models.<basename> --project <repo>`: project override, then global, then the shipped tier default) and pass it explicitly at dispatch. Never rely on the dispatched role's frontmatter alone; a resolved subagent model is never Fable.
127
+ Dispatch-time model contract (belt-and-braces): alongside the preamble, resolve each specialist's model through the config chain (`read-config agents.models.<basename> --project <repo>`: project override, then global, then the shipped tier default) and pass it explicitly at dispatch. Never rely on the dispatched role's frontmatter alone; a resolved subagent model is never Fable,
128
+ unless an explicit `agents.models.<name>` config override names Fable for that role, in which
129
+ case the override is honored as written.
112
130
 
113
131
  Completion report (require-then-synthesize): every dispatched specialist MUST end with a structured completion report as its final message. The preamble's `REPORT_CONTRACT` injects this and the role prompts carry the per-role format (see `references/agent-report-contract.md`). Because child-agent honor is best-effort across harnesses, this is decision-shaping, not a hard block. When a specialist returns no usable report (it went idle, emitted only a bare ping, or its message was lost to a mid-run interjection), run `scripts/agent-report <intent_dir> --role <role>` to synthesize a deterministic filesystem-derived report so the handoff account always exists. Use the agent-authored report when present, the synthesized one otherwise.
114
132
 
@@ -0,0 +1,34 @@
1
+ ---
2
+ name: plastic-continuing
3
+ description: >-
4
+ Use when the user says "continue", "resume", or "pick up where we left off", starts a new
5
+ session and wants to keep going, asks "what should I work on", or asks a where-was-I question
6
+ that never says "continue" (for example "where was I"). This is the front door for resuming
7
+ work: it dispatches to plastic-intent-continuing (a specific intent named to resume),
8
+ plastic-project-continuing (the default, general board landing), or
9
+ plastic-roadmap-continuing (a roadmap or delivery batch named to resume).
10
+ user-invocable: true
11
+ ---
12
+
13
+ # Continuing - the front door
14
+
15
+ `plastic-continuing` is the front door for resuming work (ruling 96: continuing routes,
16
+ starting does the lock plus resume plus work). It routes to exactly one of three skills and
17
+ does nothing else: no ledger-resume, no dashboard render, no roadmap read happens here.
18
+
19
+ ## Route
20
+
21
+ | Args / context | Route to |
22
+ |---|---|
23
+ | `--intent {id}`, or the user names one specific intent (by id or description) to resume | `plastic-intent-continuing` (intent route) |
24
+ | `--roadmap {slug}`, or the user asks to continue/resume a roadmap or delivery batch | `plastic-roadmap-continuing` (roadmap route) |
25
+ | bare "continue" / "resume" / no further target (default) | `plastic-project-continuing` (project route) |
26
+
27
+ ## Announce, then hand off
28
+
29
+ State the chosen route in one line before delegating (this is the router's own "present state
30
+ before any ask" - the router asks nothing itself). Example: "Routing to the project board (no
31
+ specific intent or roadmap named)."
32
+
33
+ Then hand off to the chosen skill. Do not inline any of the routed skill's own work here -
34
+ that belongs to the routes.
@@ -0,0 +1,91 @@
1
+ {
2
+ "skill_name": "plastic-continuing",
3
+ "notes": "Intent 158a1. New bare front-door router restored per intent 96 (D8). Scopes: description triggering (1-5) and routing behavior (6-9), the latter checked as convention against SKILL.md's routing table.",
4
+ "results": {
5
+ "triggering": { "cases": 5, "passed": 5, "run": "2026-07-10, one subagent per case" },
6
+ "behavior": { "cases": 4, "passed": 4, "evidence": "convention checks against skills/continuing/SKILL.md's routing table" }
7
+ },
8
+ "evals": [
9
+ {
10
+ "id": 1, "scope": "triggering", "set": "train",
11
+ "prompt": "continue",
12
+ "expected_output": "Activates plastic-continuing (the bare 'continue' keyword is the router's documented trigger).",
13
+ "files": [],
14
+ "assertions": [
15
+ { "type": "code", "check": "router CHOICE == plastic-continuing", "observed": "plastic-continuing", "result": "pass" }
16
+ ]
17
+ },
18
+ {
19
+ "id": 2, "scope": "triggering", "set": "train",
20
+ "prompt": "resume where we left off",
21
+ "expected_output": "Activates plastic-continuing.",
22
+ "files": [],
23
+ "assertions": [
24
+ { "type": "code", "check": "router CHOICE == plastic-continuing", "observed": "plastic-continuing", "result": "pass" }
25
+ ]
26
+ },
27
+ {
28
+ "id": 3, "scope": "triggering", "set": "validation",
29
+ "prompt": "pick up where we left off",
30
+ "expected_output": "Activates plastic-continuing.",
31
+ "files": [],
32
+ "assertions": [
33
+ { "type": "code", "check": "router CHOICE == plastic-continuing", "observed": "plastic-continuing", "result": "pass" }
34
+ ]
35
+ },
36
+ {
37
+ "id": 4, "scope": "triggering", "set": "validation",
38
+ "prompt": "where was I",
39
+ "expected_output": "Activates plastic-continuing (indirect trigger: a continue request that never says 'continue').",
40
+ "files": [],
41
+ "assertions": [
42
+ { "type": "code", "check": "router CHOICE == plastic-continuing", "observed": "plastic-continuing", "result": "pass" }
43
+ ]
44
+ },
45
+ {
46
+ "id": 5, "scope": "triggering", "set": "validation",
47
+ "prompt": "continue the for-loop in this function",
48
+ "expected_output": "Does NOT activate plastic-continuing. Near-miss: shares 'continue' but is a code-editing task.",
49
+ "files": [],
50
+ "assertions": [
51
+ { "type": "code", "check": "router CHOICE != plastic-continuing", "observed": "none", "result": "pass" }
52
+ ]
53
+ },
54
+ {
55
+ "id": 6, "scope": "behavior", "set": "train",
56
+ "prompt": "continue",
57
+ "expected_output": "Bare 'continue' with no further target dispatches to the project route (plastic-project-continuing), the routing table's default.",
58
+ "files": ["skills/continuing/SKILL.md"],
59
+ "assertions": [
60
+ { "type": "convention", "check": "routing table's default row maps bare continue/resume/no target to plastic-project-continuing", "observed": "present", "result": "pass" }
61
+ ]
62
+ },
63
+ {
64
+ "id": 7, "scope": "behavior", "set": "train",
65
+ "prompt": "continue --intent 4a",
66
+ "expected_output": "Dispatches to the intent route (plastic-intent-continuing).",
67
+ "files": ["skills/continuing/SKILL.md"],
68
+ "assertions": [
69
+ { "type": "convention", "check": "routing table maps --intent {id} to plastic-intent-continuing", "observed": "present", "result": "pass" }
70
+ ]
71
+ },
72
+ {
73
+ "id": 8, "scope": "behavior", "set": "validation",
74
+ "prompt": "resume the statusline-coloring intent",
75
+ "expected_output": "Dispatches to the intent route (plastic-intent-continuing): a specific intent named by description.",
76
+ "files": ["skills/continuing/SKILL.md"],
77
+ "assertions": [
78
+ { "type": "convention", "check": "routing table maps a named specific intent (by id or description) to plastic-intent-continuing", "observed": "present", "result": "pass" }
79
+ ]
80
+ },
81
+ {
82
+ "id": 9, "scope": "behavior", "set": "validation",
83
+ "prompt": "continue the consistency-dividend roadmap",
84
+ "expected_output": "Dispatches to the roadmap route (plastic-roadmap-continuing).",
85
+ "files": ["skills/continuing/SKILL.md"],
86
+ "assertions": [
87
+ { "type": "convention", "check": "routing table maps a named roadmap/delivery batch to plastic-roadmap-continuing", "observed": "present", "result": "pass" }
88
+ ]
89
+ }
90
+ ]
91
+ }
@@ -1,13 +1,13 @@
1
1
  ---
2
2
  name: plastic-dashboard
3
- description: Use when the user wants an overview of intents, asks "where are we", "what's next", "what should I work on", "show the dashboard", or invokes /plastic-dashboard. Renders a deterministic Value×Effort work cockpit as Markdown across the global store and all projects, and emits a machine-readable queue that auto mode consumes.
3
+ description: Use when the user wants an overview of intents, asks "where are we", "what's next", "what should I work on", "show the dashboard", or invokes /plastic-dashboard. Renders the intent store(s) as Markdown prose, the global board as a narrative of work done, each project board as a short summary plus its most-valuable next work, and emits a machine-readable queue that auto mode consumes.
4
4
  user-invocable: false
5
5
  ---
6
6
 
7
7
  # Dashboard — Plastic Work Cockpit
8
8
 
9
9
  A deterministic overview of the intent store(s). It answers three questions at a glance:
10
- **where we are** (recently worked), **where we go next** (a Value×Effort matrix), and
10
+ **where we are** (recently worked), **where we go next** (the most-valuable next work), and
11
11
  **how to conduct it** (a disposition per intent). The human-facing surface is **Markdown**,
12
12
  because the user's UI renders Markdown natively but collapses raw tool-call stdout.
13
13
 
@@ -19,7 +19,7 @@ state → byte-identical payload, regardless of model. Do NOT hand-summarize int
19
19
 
20
20
  - User invokes `/plastic-dashboard`
21
21
  - User asks "where are we", "what's next", "what should I work on", "show me the intents"
22
- - `plastic-intent-continuing` lands on the board on resume
22
+ - `plastic-project-continuing` lands on the board on resume
23
23
  - `plastic-auto` reads `--json` to choose the next dispatchable intent
24
24
 
25
25
  ## Procedure (the Markdown board — default human surface)
@@ -34,9 +34,9 @@ ruby ~/.plastic/scripts/dashboard.rb [continue|project <slug>] --data
34
34
  - `project <slug>` → that **project** board payload (`mode: "project"`).
35
35
 
36
36
  The payload is read-only JSON. Global-board fields: `date`, `store_health`, `recently_worked`,
37
- `matrix` (`quick_win`/`next_big`/`defer`/`triage`/`research`, each a list of `{line, bullet, ...}`),
38
- `counts`, `projects`, `project_totals`. Project-board fields: `slug`, `store_health`,
39
- `description`, `recently_worked`, `matrix`, `counts`, `active`, `future`.
37
+ `next_work` (a flat, rank-ordered list of `{id, intent, scope, lifecycle, value, disposition,
38
+ flags, line}`), `counts`, `projects`, `project_totals`. Project-board fields: `slug`,
39
+ `store_health`, `description`, `recently_worked`, `next_work`, `counts`, `active`, `future`.
40
40
 
41
41
  Each board load runs the scoped store check (`doctor --store <scope>`): the global board runs
42
42
  `--store global` and a project board runs `--store <slug>`. The result rides in the payload as
@@ -51,13 +51,16 @@ Templates live in this skill's `templates/` directory:
51
51
  `~/.claude/skills/plastic-dashboard/templates/dashboard-global.md` and
52
52
  `dashboard-project.md`.
53
53
 
54
- Fill mechanically no rewriting, no re-sorting:
55
- - `{{a.b.count}}` → the integer (e.g. `matrix.quick_win.count` = that list's length).
54
+ Fill mechanically, no rewriting, no re-sorting:
55
+ - `{{a.b.count}}` → the integer (e.g. `counts.active` = that count).
56
56
  - `{{...lines}}` → join the list's `.line` strings with **real newlines** (one per line).
57
- These lines are already glyph-led (the glyph is the bullet — never add `-`, never emit
58
- `<br>`). If a matrix quadrant list is empty, render `_(none)_`.
57
+ These are ordinary prose lines, not glyph-led bullets: never add a Markdown `-` bullet,
58
+ never emit `<br>`. If a list is empty, render `_(none)_`.
59
+ - `next_work.lines` → the most-valuable next work, already ranked; each line reads
60
+ `"<id> <intent, truncated>"`. Use each entry's `disposition`/`flags` fields when the prose
61
+ needs to say why an item is next.
59
62
  - `projects.lines` → one line per project:
60
- `- **{slug}** {description} · active {active} · done {done} · future {future} · last accessed {last_accessed_at[0,10]}`.
63
+ `- **{slug}**: {description}, active {active}, done {done}, future {future}, last accessed {last_accessed_at[0,10]}`.
61
64
  - Scalars (`{{date}}`, `{{slug}}`, `{{description}}`) → substitute verbatim.
62
65
 
63
66
  ### Step 3 — Present it (mandatory, every invocation)
@@ -112,7 +115,7 @@ a raw terminal. The Markdown board (`--data` + template) is the surface for the
112
115
  ## How classification works (deterministic)
113
116
 
114
117
  The script computes Effort/Value/Flags/Override/Caps; the agent never re-derives them.
115
- To explain or debug a quadrant assignment, read `references/classification.md`.
118
+ To explain or debug a ranking or disposition, read `references/classification.md`.
116
119
 
117
120
  ## Eval
118
121
 
@@ -123,7 +126,7 @@ intentional change means the skill is broken.
123
126
 
124
127
  ## Notes
125
128
 
126
- - Quadrant lists are **not** Markdown `-` bullets the glyph is the bullet (the boards are
127
- UI-only and may evolve, so they need not be valid Markdown lists). Never emit `<br>`.
129
+ - Board lines are ordinary prose, not a rigid grid: the boards are UI-only and may evolve,
130
+ so they need not be valid Markdown lists. Never emit `<br>`.
128
131
  - Clusters (Zettelkasten grouping in INDEX.md) are intentionally not rendered.
129
132
  - Additive: changes no core lifecycle, gate, or cycle logic.
@@ -1,7 +1,7 @@
1
1
  # How Classification Works (Deterministic)
2
2
 
3
3
  The script (`dashboard.rb`) computes Effort/Value/Flags/Override/Caps deterministically;
4
- the agent never re-derives them. Read this to explain or debug a quadrant assignment.
4
+ the agent never re-derives them. Read this to explain or debug a ranking or disposition.
5
5
 
6
6
  - **Effort** — small for `research`/`exploration`/`bugfix`, for already-scoped intents
7
7
  (plan/checklist exists), or a **branch id** (folgezettel depth ≥ 2, e.g. `4a`, `12b3`); big
@@ -16,7 +16,7 @@ the agent never re-derives them. Read this to explain or debug a quadrant assign
16
16
  the staleness threshold. All three kept low-noise by design.
17
17
  - **Override** — a `value: high|low` frontmatter field always wins (pre-stamped data, never
18
18
  model judgment at render time).
19
- - **Caps** quadrant lists and the project board's `active`/`future` lists are capped at 8
20
- entries plus a trailing "+N more" line; each entry's text is truncated to 120 characters
19
+ - **Caps**: the next-work list and the project board's `active`/`future` lists are capped at
20
+ 8 entries plus a trailing "+N more" line; each entry's text is truncated to 120 characters
21
21
  with a trailing ellipsis. Applies to the Markdown board only (the ASCII renderer has its own
22
22
  separate `CELL_CAP`).
@@ -1,31 +1,16 @@
1
- # 🧩 Plastic · Global Board {{date}}
1
+ # 🧩 Plastic · Global Board, {{date}}
2
2
 
3
- **Recently worked** · last 24h
3
+ **Recently worked** (last 24h)
4
4
  {{recently_worked.lines}}
5
5
 
6
- ## Where we go next · Value × Effort *(global intents only)*
6
+ ## Where we are
7
7
 
8
- | | Small effort | Big effort |
9
- |---|---|---|
10
- | **High value** | ⚡ **Quick win** · {{matrix.quick_win.count}} | ★ **Next big thing** · {{matrix.next_big.count}} |
11
- | **Low value** | → **Defer (agent)** · {{matrix.defer.count}} | ⚑ **Triage** · {{matrix.triage.count}} |
8
+ {{counts.active}} intents active, {{counts.done}} done, {{counts.future}} queued for later.
12
9
 
13
- **⚡ Quick win** small effort, high value
14
- {{matrix.quick_win.lines}}
15
-
16
- **★ Next big thing** — big effort, high value
17
- {{matrix.next_big.lines}}
18
-
19
- **→ Defer (agent)** — small effort, low value
20
- {{matrix.defer.lines}}
21
-
22
- **⚑ Triage** — big effort, low value
23
- {{matrix.triage.lines}}
24
-
25
- 🔬 **Research → agent**
26
- {{matrix.research.lines}}
27
-
28
- ## Projects · active {{project_totals.active}} · done {{project_totals.done}} · future {{project_totals.future}}
10
+ ## Projects, active {{project_totals.active}}, done {{project_totals.done}}, future {{project_totals.future}}
29
11
  {{projects.lines}}
30
12
 
13
+ ## Most-valuable next work
14
+ {{next_work.lines}}
15
+
31
16
  **What would you like to work on next?** (type an **intent id**, a **project name**, or anything **new** you'd like to start)
@@ -1,33 +1,11 @@
1
- # 📦 {{slug}} · Project Board {{date}}
1
+ # 📦 {{slug}} · Project Board, {{date}}
2
2
 
3
3
  {{description}}
4
4
 
5
- **Recently worked** · last 24h
5
+ **Recently worked** (last active work, last 24h)
6
6
  {{recently_worked.lines}}
7
7
 
8
- ## Where we go next · Value × Effort
9
-
10
- | | Small effort | Big effort |
11
- |---|---|---|
12
- | **High value** | ⚡ **Quick win** · {{matrix.quick_win.count}} | ★ **Next big thing** · {{matrix.next_big.count}} |
13
- | **Low value** | → **Defer (agent)** · {{matrix.defer.count}} | ⚑ **Triage** · {{matrix.triage.count}} |
14
-
15
- **⚡ Quick win** — small effort, high value
16
- {{matrix.quick_win.lines}}
17
-
18
- **★ Next big thing** — big effort, high value
19
- {{matrix.next_big.lines}}
20
-
21
- **→ Defer (agent)** — small effort, low value
22
- {{matrix.defer.lines}}
23
-
24
- **⚑ Triage** — big effort, low value
25
- {{matrix.triage.lines}}
26
-
27
- 🔬 **Research → agent**
28
- {{matrix.research.lines}}
29
-
30
- ## Intents · active {{counts.active}} · done {{counts.done}} · future {{counts.future}}
8
+ ## Intents, active {{counts.active}}, done {{counts.done}}, future {{counts.future}}
31
9
 
32
10
  **Active**
33
11
  {{active.lines}}
@@ -35,6 +13,9 @@
35
13
  **Future**
36
14
  {{future.lines}}
37
15
 
38
- **Legend** · What ◔ Why ◑ How ◕ Exec ● Done · ⚡ quick win ★ big → defer ⚑ triage 🔬 research
16
+ ## Most-valuable next work
17
+ {{next_work.lines}}
18
+
19
+ **Legend** · ○ What ◔ Why ◑ How ◕ Exec ● Done
39
20
 
40
21
  **What would you like to work on next?** (type an **intent id**, or **global** to go back)
@@ -13,7 +13,7 @@ Doctor has three scopes. Pick the right one for the situation:
13
13
  | Scope | Flag | When it runs | States |
14
14
  |-------|------|--------------|--------|
15
15
  | Core check | `--core` | SessionStart hook (automatic), also available on demand | Binary: pass or error |
16
- | Store check | `--store [global\|<slug>]` | Dashboard load, `plastic-intent-continuing` | Three-state: pass / warn / fail |
16
+ | Store check | `--store [global\|<slug>]` | Dashboard load, `plastic-project-continuing` | Three-state: pass / warn / fail |
17
17
  | Full check | (no flag) | After every update (automatic), or `/plastic-doctor` | Three-state: pass / warn / fail |
18
18
 
19
19
  ### `--core` (binary, manifest-backed)
@@ -1,13 +1,13 @@
1
1
  ---
2
2
  name: plastic-install
3
- description: 'Use when initializing Plastic globally (~/.plastic/) or locally in a project, or to re-install/repair a broken installation. Accepts channel flags (--alpha, --beta, --latest) to select release channel. First install defaults to --beta; reinstalls match the already-installed channel. Global install is recommended: it creates the global intent store as a git-backed repository. Local install creates .plastic/ in the current project for testing.'
3
+ description: 'Use when initializing Plastic globally (~/.plastic/) or locally in a project, or to re-install/repair a broken installation. Accepts channel flags (--alpha, --beta, --latest) to select release channel. First install defaults to --latest (stable); reinstalls match the already-installed channel. Global install is recommended: it creates the global intent store as a git-backed repository. Local install creates .plastic/ in the current project for testing.'
4
4
  user-invocable: true
5
5
  ---
6
6
 
7
7
  # Install Plastic
8
8
 
9
- > **Recommended path:** for a first install, run `npx -y @zalom/plastic@beta install --claude`
10
- > in your shell (or `bunx -y @zalom/plastic@beta install --claude` if you use Bun). This skill
9
+ > **Recommended path:** for a first install, run `npx -y @zalom/plastic@latest install --claude`
10
+ > in your shell (or `bunx -y @zalom/plastic@latest install --claude` if you use Bun). This skill
11
11
  > exists to **re-install or repair** an existing setup from inside the agent, and to
12
12
  > drive interactive global configuration. Whenever this skill performs an install or
13
13
  > re-install, it **runs `/plastic-doctor` afterward** and reports the result.
@@ -16,7 +16,7 @@ user-invocable: true
16
16
 
17
17
  If Plastic is installed, derive `<channel>` from `~/.plastic/VERSION`: a version containing
18
18
  `-alpha` means `@alpha`, `-beta` means `@beta`, otherwise `@latest`. If not installed
19
- (first install), default to `@beta`. The user can always override with
19
+ (first install), default to `@latest`. The user can always override with
20
20
  `--alpha` / `--beta` / `--latest`.
21
21
 
22
22
  ## Re-install / repair
@@ -35,18 +35,18 @@ Then **run `/plastic-doctor`** and report what it found.
35
35
 
36
36
  | Flag | Behavior |
37
37
  |------|----------|
38
- | `--latest` | Install from the stable channel |
39
- | `--beta` | Install from the beta channel (default on a first install) |
38
+ | `--latest` | Install from the stable channel (default on a first install) |
39
+ | `--beta` | Install from the beta channel |
40
40
  | `--alpha` | Install from the alpha channel |
41
41
 
42
42
  When invoked from within Claude Code (re-install or channel switch), the skill
43
43
  runs the appropriate npx command:
44
44
 
45
45
  ```bash
46
- # Stable
46
+ # Stable (default on a first install)
47
47
  npx -y @zalom/plastic@latest install --claude
48
48
 
49
- # Beta (default on a first install)
49
+ # Beta
50
50
  npx -y @zalom/plastic@beta install --claude
51
51
 
52
52
  # Alpha
@@ -68,10 +68,10 @@ Run `/plastic-install` with no arguments.
68
68
  Check if `~/.plastic/VERSION` exists.
69
69
  - If yes: announce "Plastic is already installed at ~/.plastic/. Run `/plastic-update` to
70
70
  sync core files, or use the re-install command above to repair in place."
71
- - If no: run the fresh install command (default `@beta`, or the channel the user named):
71
+ - If no: run the fresh install command (default `@latest`, or the channel the user named):
72
72
 
73
73
  ```bash
74
- npx -y @zalom/plastic@beta install --claude
74
+ npx -y @zalom/plastic@latest install --claude
75
75
  ```
76
76
 
77
77
  This single command, via `install.rb` (`bootstrap` + `distribute`), creates `store/`,
@@ -1,61 +1,42 @@
1
1
  ---
2
2
  name: plastic-intent-continuing
3
- description: 'Use when the user says "continue", "resume", or "pick up where we left off", or when starting a new session. Continues work with the latest project context: lands on the right dashboard, then presents choices. Boot (health check, core context, version, statusline) is owned by the SessionStart hook, not this skill. Does not drive work autonomously (that is plastic-auto).'
3
+ description: >-
4
+ Use when a specific intent is named to resume, by id or by description, or on `continuing
5
+ --intent {id}`. Reads that intent's savepoint ledger and hands off to plastic-intent-starting.
6
+ The general "continue" / new-session triggers belong to the plastic-continuing router, not
7
+ here, so a bare "continue" does not settle on this skill directly. Boot (health check, core
8
+ context, version, statusline) is owned by the SessionStart hook, not this skill. Does not
9
+ drive work autonomously (that is plastic-auto).
4
10
  user-invocable: true
5
11
  ---
6
12
 
7
- # Continuing
13
+ # Continuing (intent route)
8
14
 
9
- `plastic-intent-continuing` continues work. It presents the latest state via the dashboard and offers
10
- choices, then stops. It does NOT execute work autonomously (that is `plastic-auto`) and does
11
- NOT render the dashboard itself (it only invokes it).
15
+ `plastic-intent-continuing` is the intent route of `plastic-continuing`. It resumes ONE
16
+ specific intent by its savepoint ledger, then hands off to `plastic-intent-starting`. It does
17
+ NOT land on a dashboard and does NOT execute work autonomously (that is `plastic-auto`); both
18
+ of those are other routes' jobs.
12
19
 
13
20
  **Boot is not this skill's job.** The `hook-session-start` hook already runs by construction on
14
21
  every session start: it runs the core health check (`doctor --core`), primes `PLASTIC.md` +
15
- store/project state, and prints the `Plastic Core loaded v{version}` banner. The
22
+ store/project state, and prints the `Plastic Core loaded - v{version}` banner. The
16
23
  `plastic-statusline` hook sets the statusline. So by the time this skill runs, core is loaded
17
24
  and healthy (or the banner already warned otherwise). This skill picks up from there and
18
- continues work. This is the seam future continue-flags build on (see [[39]]).
25
+ resumes the named intent. This is the seam future continue-flags build on (see [[39]]).
19
26
 
20
27
  ## When to Use
21
- - UserPromptSubmit hook detects "continue" (automatic)
22
- - User says "continue", "resume", or "pick up where we left off"
23
- - Starting a new session and you want to resume work with the latest context
28
+ - A specific intent is named to resume, by id or by description
29
+ - `continuing --intent {id}`
24
30
 
25
31
  ## Determine Store
26
32
 
27
- 1. **Global store** `~/.plastic/INDEX.md` exists → global mode.
28
- 2. **Local store** a project store under `~/.plastic/projects/{slug}/` whose registered
33
+ 1. **Global store** - `~/.plastic/INDEX.md` exists → global mode.
34
+ 2. **Local store** - a project store under `~/.plastic/projects/{slug}/` whose registered
29
35
  path (in `~/.plastic/projects.yml`) matches the current working directory → project mode.
30
36
  The SessionStart hook already detects this; here you only need the slug to scope the
31
- dashboard.
37
+ named intent's store.
32
38
  3. If neither exists → announce "No Plastic store found. Run /plastic-install."
33
39
 
34
- ## Continue (present the dashboard)
35
-
36
- Land on the Markdown board via the `plastic-dashboard` skill. Rendering belongs there, not
37
- here — run the data payload and fill + present the matching template:
38
- - Project loaded → `ruby ~/.plastic/scripts/dashboard.rb project <slug> --data`
39
- - Otherwise → `ruby ~/.plastic/scripts/dashboard.rb continue --data`
40
-
41
- Fill the matching template from this skill's `templates/` and **present the filled Markdown
42
- in your reply** (every time, non-optional). If the reply does not contain the filled Markdown,
43
- the user sees nothing — tool-call stdout and hook `additionalContext` are both invisible to
44
- them. `hook-continue` also emits a one-line `systemMessage` summary as a hook-owned fallback;
45
- treat it as a floor only, never as a substitute for presenting the full board here. See
46
- `plastic-dashboard` for the fill rules and entry flow.
47
-
48
- The board load runs the scoped store check on every load (`doctor --store <scope>`): the
49
- global board runs `--store global` and a project board runs `--store <slug>`. The result
50
- arrives in the payload as `store_health`; surface it as a one-line store-health note. It is
51
- non-fatal (a warn or fail is shown as data, it does not block continuing).
52
-
53
- ### Then stop
54
- Present "here is the state, what next?" and wait. Offer active intents first, then future
55
- intents. Do not start executing work. The branches below are the only follow-ups:
56
- - User/agent names a specific intent to continue → **Conditional ledger-resume** (below).
57
- - User says "auto" / an agent is instructed to deliver → hand to `plastic-auto`.
58
-
59
40
  ## Conditional Ledger-Resume
60
41
 
61
42
  Fires ONLY when the user explicitly asks to continue a SPECIFIC intent, or an agent is
@@ -98,44 +79,21 @@ For that intent's directory:
98
79
  - "advance to the next lifecycle stage" (e.g. ledger shows Why/spec.md → next is How).
99
80
  - The newest `## Insights` entry supplies human-readable context (Insights are
100
81
  append-only, newest at the bottom).
101
- 5. **Announce and stop:**
82
+ 5. **Announce, then hand off to `plastic-intent-starting`:**
102
83
  ```
103
- Resuming intent [ID] [name]
84
+ Resuming intent [ID] - [name]
104
85
  Store: [global | project:<slug> | local]
105
86
  Stage: [from ledger last line]
106
87
  Next step: [first unchecked checklist item | advance to <stage>]
107
88
  Context: [newest ## Insights entry]
108
89
  Drift: [none | ledger rebuilt from filesystem]
109
90
  ```
110
- Then proceed with the next step. Autonomy is `plastic-auto`'s job if the intent's
111
- `## Insights` contains `(autonomous)` entries, it was being delivered autonomously; hand
112
- to `plastic-auto` to continue from the current stage.
113
-
114
- ## Priority Order
115
-
116
- 1. **Active intents first** — surface work in progress.
117
- 2. **Project context** — if in a registered project, show governing + tactical intents.
118
- 3. **Stale future intents** — surface for triage (see below).
119
- 4. **Fresh future intents** — offer as next work.
120
-
121
- ## Stale Future Intents
122
-
123
- If a future intent's `created` date is older than the configured `stale_threshold_days`
124
- (default 3), surface it for triage without taking action:
125
-
126
- ```
127
- Stale future intents (no action taken):
128
-
129
- - [ID — name] (X days old)
130
- a) Activate — start working on it now
131
- b) Abandon — mark as abandoned
132
- c) Defer to agent: implement | research | ideate
133
- d) Auto — go fully autonomous (invokes plastic-auto)
134
- ```
135
-
136
- When the user activates a future intent, move it to `## Active` in INDEX.md and auto-commit.
91
+ Hand off to `plastic-intent-starting`: it takes the lock, boards at this station, and is
92
+ where the single "auto or guided?" ask for the intent route lives, asked there exactly
93
+ once and never duplicated here. Its auto branch is the one that hands off to `plastic-auto`;
94
+ this skill never hands to `plastic-auto` directly.
137
95
 
138
96
  ## References
139
97
 
140
- - Read `references/context-management.md` for the full save/continue protocol and for
98
+ - Read `references/context-management.md` for the save/continue protocol and for
141
99
  debugging the resume flow.