@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.
- package/PLASTIC.md +4 -2
- package/README.md +3 -3
- package/agents/plastic-enforcer.md +5 -2
- package/agents/plastic-future-intent-researcher.md +1 -1
- package/hooks/check-update +1 -1
- package/hooks/continue +1 -1
- package/package.json +1 -1
- package/scripts/dashboard.rb +29 -24
- package/scripts/doctor.rb +136 -5
- package/scripts/hook-continue +3 -3
- package/scripts/install.rb +2 -1
- package/scripts/lib/bridge.rb +81 -0
- package/scripts/lib/dashboard_banner.rb +8 -9
- package/scripts/lib/installer_core.rb +10 -3
- package/scripts/lib/legacy_bookend_amnesty.rb +35 -0
- package/scripts/lib/release_guard.rb +62 -0
- package/scripts/lib/roadmap_queue.rb +285 -0
- package/scripts/lib/roadmap_savepoint.rb +213 -0
- package/scripts/lib/worktree.rb +21 -0
- package/scripts/new-intent +1 -0
- package/scripts/read-config +3 -3
- package/scripts/roadmap-next +44 -0
- package/scripts/roadmap-savepoint +64 -0
- package/skills/auto/SKILL.md +22 -4
- package/skills/continuing/SKILL.md +34 -0
- package/skills/continuing/evals/evals.json +91 -0
- package/skills/dashboard/SKILL.md +17 -14
- package/skills/dashboard/references/classification.md +3 -3
- package/skills/dashboard/templates/dashboard-global.md +8 -23
- package/skills/dashboard/templates/dashboard-project.md +7 -26
- package/skills/doctor/SKILL.md +1 -1
- package/skills/install/SKILL.md +10 -10
- package/skills/intent-continuing/SKILL.md +26 -68
- package/skills/intent-continuing/evals/evals.json +26 -26
- package/skills/intent-continuing/references/context-management.md +15 -19
- package/skills/intent-savepoint/SKILL.md +12 -0
- package/skills/intent-starting/evals/evals.json +1 -1
- package/skills/project-continuing/SKILL.md +104 -0
- package/skills/project-continuing/evals/evals.json +100 -0
- package/skills/project-continuing/references/board-fill.md +33 -0
- package/skills/releasing/SKILL.md +48 -0
- package/skills/releasing/references/release-lines.md +105 -0
- package/skills/roadmap/SKILL.md +7 -1
- package/skills/roadmap/references/file-format.md +30 -1
- package/skills/roadmap/references/operations.md +26 -6
- package/skills/roadmap-continuing/SKILL.md +85 -0
- package/skills/roadmap-continuing/evals/evals.json +82 -0
- package/skills/roadmap-continuing/references/liveness-ranking.md +56 -0
- package/skills/skill-evaluating/evals/evals.json +1 -1
- package/skills/tutorial/references/track-2-auto.md +1 -1
- package/skills/uninstall/SKILL.md +2 -2
- package/skills/update/SKILL.md +2 -2
- package/templates/config.yml +2 -1
- 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
|
package/skills/auto/SKILL.md
CHANGED
|
@@ -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
|
|
28
|
-
|
|
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
|
|
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** (
|
|
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-
|
|
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
|
-
`
|
|
38
|
-
`counts`, `projects`, `project_totals`. Project-board fields: `slug`,
|
|
39
|
-
`description`, `recently_worked`, `
|
|
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
|
|
55
|
-
- `{{a.b.count}}` → the integer (e.g. `
|
|
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
|
|
58
|
-
`<br
|
|
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}
|
|
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
|
|
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
|
-
-
|
|
127
|
-
|
|
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
|
|
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
|
|
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
|
|
1
|
+
# 🧩 Plastic · Global Board, {{date}}
|
|
2
2
|
|
|
3
|
-
**Recently worked**
|
|
3
|
+
**Recently worked** (last 24h)
|
|
4
4
|
{{recently_worked.lines}}
|
|
5
5
|
|
|
6
|
-
## Where we
|
|
6
|
+
## Where we are
|
|
7
7
|
|
|
8
|
-
|
|
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
|
-
|
|
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
|
|
1
|
+
# 📦 {{slug}} · Project Board, {{date}}
|
|
2
2
|
|
|
3
3
|
{{description}}
|
|
4
4
|
|
|
5
|
-
**Recently worked**
|
|
5
|
+
**Recently worked** (last active work, last 24h)
|
|
6
6
|
{{recently_worked.lines}}
|
|
7
7
|
|
|
8
|
-
##
|
|
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
|
-
|
|
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)
|
package/skills/doctor/SKILL.md
CHANGED
|
@@ -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-
|
|
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)
|
package/skills/install/SKILL.md
CHANGED
|
@@ -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 --
|
|
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@
|
|
10
|
-
> in your shell (or `bunx -y @zalom/plastic@
|
|
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 `@
|
|
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
|
|
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
|
|
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 `@
|
|
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@
|
|
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:
|
|
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`
|
|
10
|
-
|
|
11
|
-
NOT
|
|
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
|
|
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
|
-
|
|
25
|
+
resumes the named intent. This is the seam future continue-flags build on (see [[39]]).
|
|
19
26
|
|
|
20
27
|
## When to Use
|
|
21
|
-
-
|
|
22
|
-
-
|
|
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**
|
|
28
|
-
2. **Local store**
|
|
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
|
-
|
|
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
|
|
82
|
+
5. **Announce, then hand off to `plastic-intent-starting`:**
|
|
102
83
|
```
|
|
103
|
-
Resuming intent [ID]
|
|
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
|
-
|
|
111
|
-
|
|
112
|
-
|
|
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
|
|
98
|
+
- Read `references/context-management.md` for the save/continue protocol and for
|
|
141
99
|
debugging the resume flow.
|