@zalom/plastic 1.1.0 → 1.1.2
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 +12 -9
- package/README.md +3 -3
- package/agents/plastic-enforcer.md +8 -4
- package/agents/plastic-executor.md +5 -5
- package/agents/plastic-future-intent-researcher.md +1 -1
- package/agents/plastic-planner.md +15 -11
- 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 +180 -5
- package/scripts/hook-continue +3 -3
- package/scripts/install.rb +2 -1
- package/scripts/lib/bridge.rb +114 -11
- package/scripts/lib/dashboard_banner.rb +8 -9
- package/scripts/lib/installer_core.rb +12 -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/skill_lint.rb +304 -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/scripts/skill-lint +50 -0
- package/skills/auto/SKILL.md +32 -11
- package/skills/auto/references/tiers.md +4 -3
- 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-planning/SKILL.md +11 -11
- package/skills/intent-planning/evals/evals.json +20 -5
- package/skills/intent-planning/references/plan-format.md +9 -5
- 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-1-guided.md +5 -4
- 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
|
@@ -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.
|
|
@@ -1,15 +1,15 @@
|
|
|
1
1
|
{
|
|
2
2
|
"skill_name": "plastic-intent-continuing",
|
|
3
|
-
"notes": "Intent
|
|
3
|
+
"notes": "Intent 158a1: slimmed to the specific-intent resume route of plastic-continuing (D8, extract not duplicate). Bare 'continue' now belongs to the router; triggering evals 1-4 were recast so this skill's positives always name a specific intent, and eval 4 asserts bare 'continue' does NOT settle here directly. Behavior eval 11 (dashboard selection) was removed, relocated to plastic-project-continuing's evals. Behavior eval 15 is new: the terminal handoff goes to plastic-intent-starting, not directly to plastic-auto. Scopes: description triggering (1-8) and behavior/convention compliance of the ledger-resume skill (9-15).",
|
|
4
4
|
"results": {
|
|
5
|
-
"triggering": { "cases": 8, "passed": 8, "run": "2026-
|
|
6
|
-
"behavior": { "cases":
|
|
5
|
+
"triggering": { "cases": 8, "passed": 8, "run": "2026-07-10, one subagent per case" },
|
|
6
|
+
"behavior": { "cases": 7, "passed": 7, "evidence": "convention checks against skills/intent-continuing/SKILL.md after the 158a1 extraction" }
|
|
7
7
|
},
|
|
8
8
|
"evals": [
|
|
9
9
|
{
|
|
10
10
|
"id": 1, "scope": "triggering", "set": "train",
|
|
11
|
-
"prompt": "continue",
|
|
12
|
-
"expected_output": "Activates plastic-intent-continuing (
|
|
11
|
+
"prompt": "continue intent 4a",
|
|
12
|
+
"expected_output": "Activates plastic-intent-continuing (a specific intent named by id).",
|
|
13
13
|
"files": [],
|
|
14
14
|
"assertions": [
|
|
15
15
|
{ "type": "code", "check": "router CHOICE == plastic-intent-continuing", "observed": "plastic-intent-continuing", "result": "pass" }
|
|
@@ -17,8 +17,8 @@
|
|
|
17
17
|
},
|
|
18
18
|
{
|
|
19
19
|
"id": 2, "scope": "triggering", "set": "train",
|
|
20
|
-
"prompt": "resume
|
|
21
|
-
"expected_output": "Activates plastic-intent-continuing.",
|
|
20
|
+
"prompt": "resume the statusline-coloring intent",
|
|
21
|
+
"expected_output": "Activates plastic-intent-continuing (a specific intent named by description).",
|
|
22
22
|
"files": [],
|
|
23
23
|
"assertions": [
|
|
24
24
|
{ "type": "code", "check": "router CHOICE == plastic-intent-continuing", "observed": "plastic-intent-continuing", "result": "pass" }
|
|
@@ -26,8 +26,8 @@
|
|
|
26
26
|
},
|
|
27
27
|
{
|
|
28
28
|
"id": 3, "scope": "triggering", "set": "validation",
|
|
29
|
-
"prompt": "
|
|
30
|
-
"expected_output": "Activates plastic-intent-continuing.",
|
|
29
|
+
"prompt": "continuing --intent 96",
|
|
30
|
+
"expected_output": "Activates plastic-intent-continuing (the --intent form).",
|
|
31
31
|
"files": [],
|
|
32
32
|
"assertions": [
|
|
33
33
|
{ "type": "code", "check": "router CHOICE == plastic-intent-continuing", "observed": "plastic-intent-continuing", "result": "pass" }
|
|
@@ -35,11 +35,11 @@
|
|
|
35
35
|
},
|
|
36
36
|
{
|
|
37
37
|
"id": 4, "scope": "triggering", "set": "train",
|
|
38
|
-
"prompt": "
|
|
39
|
-
"expected_output": "
|
|
38
|
+
"prompt": "continue",
|
|
39
|
+
"expected_output": "Does NOT settle on plastic-intent-continuing directly. Bare 'continue' with no specific intent named belongs to the plastic-continuing router, which defaults to plastic-project-continuing.",
|
|
40
40
|
"files": [],
|
|
41
41
|
"assertions": [
|
|
42
|
-
{ "type": "code", "check": "router CHOICE
|
|
42
|
+
{ "type": "code", "check": "router CHOICE != plastic-intent-continuing", "observed": "plastic-continuing", "result": "pass" }
|
|
43
43
|
]
|
|
44
44
|
},
|
|
45
45
|
{
|
|
@@ -72,7 +72,7 @@
|
|
|
72
72
|
{
|
|
73
73
|
"id": 8, "scope": "triggering", "set": "validation",
|
|
74
74
|
"prompt": "what's the dashboard look like right now",
|
|
75
|
-
"expected_output": "
|
|
75
|
+
"expected_output": "Does NOT activate plastic-intent-continuing directly; an overview request without a specific intent named is a dashboard/project-board task.",
|
|
76
76
|
"files": [],
|
|
77
77
|
"assertions": [
|
|
78
78
|
{ "type": "code", "check": "router CHOICE != plastic-intent-continuing", "observed": "plastic-dashboard", "result": "pass" }
|
|
@@ -97,16 +97,7 @@
|
|
|
97
97
|
]
|
|
98
98
|
},
|
|
99
99
|
{
|
|
100
|
-
"id": 11, "scope": "behavior", "set": "
|
|
101
|
-
"prompt": "Is dashboard selection project-aware?",
|
|
102
|
-
"expected_output": "Project loaded -> `dashboard.rb project <slug>`; otherwise -> `dashboard.rb continue`. Skill only invokes, does not render.",
|
|
103
|
-
"files": ["skills/intent-continuing/SKILL.md"],
|
|
104
|
-
"assertions": [
|
|
105
|
-
{ "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 dashboard)' section", "result": "pass" }
|
|
106
|
-
]
|
|
107
|
-
},
|
|
108
|
-
{
|
|
109
|
-
"id": 12, "scope": "behavior", "set": "validation",
|
|
100
|
+
"id": 11, "scope": "behavior", "set": "validation",
|
|
110
101
|
"prompt": "Is ledger-resume conditional and ledger-driven?",
|
|
111
102
|
"expected_output": "Resume fires only when a specific intent is named; reads savepoint.md last line as stage, verifies the stage file, rebuilds on drift, derives next step from first unchecked checklist item.",
|
|
112
103
|
"files": ["skills/intent-continuing/SKILL.md"],
|
|
@@ -115,7 +106,7 @@
|
|
|
115
106
|
]
|
|
116
107
|
},
|
|
117
108
|
{
|
|
118
|
-
"id":
|
|
109
|
+
"id": 12, "scope": "behavior", "set": "validation",
|
|
119
110
|
"prompt": "Are the stale prose-savepoint fields gone?",
|
|
120
111
|
"expected_output": "No 'In progress' / 'Blockers' fields read from a prose savepoint remain; the ledger model is used instead.",
|
|
121
112
|
"files": ["skills/intent-continuing/SKILL.md"],
|
|
@@ -124,7 +115,7 @@
|
|
|
124
115
|
]
|
|
125
116
|
},
|
|
126
117
|
{
|
|
127
|
-
"id":
|
|
118
|
+
"id": 13, "scope": "behavior", "set": "validation",
|
|
128
119
|
"prompt": "Is the 'Determine Store' local-store gap filled?",
|
|
129
120
|
"expected_output": "Step 2 of Determine Store describes local/project-store detection (no empty step).",
|
|
130
121
|
"files": ["skills/intent-continuing/SKILL.md"],
|
|
@@ -133,13 +124,22 @@
|
|
|
133
124
|
]
|
|
134
125
|
},
|
|
135
126
|
{
|
|
136
|
-
"id":
|
|
127
|
+
"id": 14, "scope": "behavior", "set": "validation",
|
|
137
128
|
"prompt": "QMD is present. The user says: continue the work on the statusline coloring (names the intent by description, not id).",
|
|
138
129
|
"expected_output": "Before scanning the store with grep/Read to locate the named intent, runs `ruby ~/.plastic/scripts/qmd-sync search \"statusline coloring\"` to surface the candidate intent, then opens the authoritative intent file for the hit it resumes. No-op fallback to INDEX.md / file scan when QMD is absent.",
|
|
139
130
|
"files": ["skills/intent-continuing/SKILL.md"],
|
|
140
131
|
"assertions": [
|
|
141
132
|
{ "type": "human", "check": "qmd-sync search is run before grep/Read when the intent is named by description; authoritative file opened for the hit", "observed": "Conditional Ledger-Resume carries the QMD-first step: run qmd-sync search before grep/Read, then open the authoritative file; no-op fallback when QMD is absent", "result": "pass" }
|
|
142
133
|
]
|
|
134
|
+
},
|
|
135
|
+
{
|
|
136
|
+
"id": 15, "scope": "behavior", "set": "train",
|
|
137
|
+
"prompt": "Does the ledger-resume's terminal handoff go to plastic-intent-starting or directly to plastic-auto?",
|
|
138
|
+
"expected_output": "Step 5 announces state then hands off to plastic-intent-starting, which takes the lock and asks 'auto or guided?' exactly once; plastic-intent-starting's own auto branch is the one that hands to plastic-auto. This skill never hands to plastic-auto directly.",
|
|
139
|
+
"files": ["skills/intent-continuing/SKILL.md"],
|
|
140
|
+
"assertions": [
|
|
141
|
+
{ "type": "convention", "check": "step 5 hands off to plastic-intent-starting, not plastic-auto; the single ask is attributed to plastic-intent-starting", "observed": "present in 'Conditional Ledger-Resume' step 5", "result": "pass" }
|
|
142
|
+
]
|
|
143
143
|
}
|
|
144
144
|
]
|
|
145
145
|
}
|
|
@@ -1,4 +1,4 @@
|
|
|
1
|
-
# Context Management (
|
|
1
|
+
# Context Management (Save, then resume-flow debugging)
|
|
2
2
|
|
|
3
3
|
## Save Point
|
|
4
4
|
Triggered by PreCompact hook or manually:
|
|
@@ -7,26 +7,22 @@ Triggered by PreCompact hook or manually:
|
|
|
7
7
|
3. Update active intent's `savepoint.md` (in-progress, next steps, blockers, discoveries)
|
|
8
8
|
4. Add observations to `## Insights`
|
|
9
9
|
5. Update INDEX.md
|
|
10
|
-
6. Commit: `cd ~/.plastic && git add . && git commit -m "chore: savepoint
|
|
10
|
+
6. Commit: `cd ~/.plastic && git add . && git commit -m "chore: savepoint - [intent name]"`
|
|
11
11
|
7. Notify user to `/clear`
|
|
12
12
|
|
|
13
|
-
##
|
|
14
|
-
Triggered by UserPromptSubmit hook when user says "continue". Priority order:
|
|
13
|
+
## Debugging the resume flow
|
|
15
14
|
|
|
16
|
-
|
|
17
|
-
|
|
18
|
-
2. Read active intent's `intent.md` → what and why
|
|
19
|
-
3. Read active intent's `savepoint.md` → where we left off
|
|
20
|
-
4. Read active intent's `checklist.md` → what's next
|
|
21
|
-
5. Announce: intent name, current state, next step, blockers
|
|
22
|
-
6. Resume
|
|
15
|
+
When a resume looks wrong (the announced stage does not match what is on disk, or the next
|
|
16
|
+
step looks stale):
|
|
23
17
|
|
|
24
|
-
|
|
25
|
-
|
|
26
|
-
2.
|
|
27
|
-
|
|
18
|
+
1. Read `savepoint.md`'s last line directly; that line alone is the source of truth for stage
|
|
19
|
+
(see `SKILL.md`'s `## Conditional Ledger-Resume` for the full state table).
|
|
20
|
+
2. Confirm the artifact that line implies (`plan.md`, `checklist.md`, `outcome.md`, ...) is
|
|
21
|
+
present and non-empty on disk.
|
|
22
|
+
3. If the two disagree, the ledger has drifted: rebuild it rather than hand-editing:
|
|
23
|
+
`ruby -r ~/.plastic/scripts/lib/bridge -e 'Bridge.rebuild_savepoint("<intent_dir>")'`
|
|
24
|
+
4. Re-read the rebuilt last line and re-derive the next step from `checklist.md`'s first
|
|
25
|
+
unchecked item.
|
|
28
26
|
|
|
29
|
-
|
|
30
|
-
-
|
|
31
|
-
- **abandon** — mark as abandoned
|
|
32
|
-
- **defer to agent** — implement, research, or ideate
|
|
27
|
+
The general "land on the board / priority order / stale future intents" flow now lives in
|
|
28
|
+
`plastic-project-continuing`; this file no longer duplicates it.
|
|
@@ -1,6 +1,6 @@
|
|
|
1
1
|
---
|
|
2
2
|
name: plastic-intent-planning
|
|
3
|
-
description: "Write implementation plans from a spec. Produces plan.md, checklist.md, and
|
|
3
|
+
description: "Write implementation plans from a spec. Produces plan.md, checklist.md, and at least one real actions/ACTION_N.md (every tier) in the active intent directory."
|
|
4
4
|
user-invocable: true
|
|
5
5
|
---
|
|
6
6
|
|
|
@@ -31,12 +31,12 @@ If the spec covers multiple independent subsystems, it should have been broken i
|
|
|
31
31
|
|
|
32
32
|
## Tier shapes
|
|
33
33
|
|
|
34
|
-
Read the spec's stamped `Tier:` line (written by intent-speccing) and pick the
|
|
34
|
+
Read the spec's stamped `Tier:` line (written by intent-speccing) and pick the action shape it calls for. Every tier produces at least one REAL action file in `actions/`; the tier only changes how many:
|
|
35
35
|
|
|
36
|
-
- **S or M (default):**
|
|
36
|
+
- **S or M (default):** write ONE consolidated `actions/ACTION_1.md` that carries the whole ordered delivery (the steps plus the exact changes). `plan.md` still holds the overall map and `checklist.md` still mirrors the task list. You may split into a few action files when that reads cleaner, but one real action file is the floor.
|
|
37
37
|
- **L (many independent tasks, dispatched in parallel):** self-contained `actions/ACTION_N.md`, one per task, each readable without the plan (see `references/plan-format.md`).
|
|
38
38
|
|
|
39
|
-
|
|
39
|
+
A `.gitkeep` never counts as an action, and an empty `actions/` fails the How gate at every tier. At S/M, keep it to a single consolidated action file rather than one-per-task; over-splitting a small intent is the S/M failure mode, an empty `actions/` is the tier-wide one.
|
|
40
40
|
|
|
41
41
|
## File Structure
|
|
42
42
|
|
|
@@ -97,11 +97,11 @@ If you find issues, fix them inline. No need to re-review, just fix and move on.
|
|
|
97
97
|
## Plastic Artifacts
|
|
98
98
|
|
|
99
99
|
After writing `plan.md`, create `checklist.md` (execution registry following the
|
|
100
|
-
FORM: `## In Progress`, `## Completed`, `## Session Log`)
|
|
101
|
-
|
|
102
|
-
|
|
103
|
-
|
|
104
|
-
|
|
100
|
+
FORM: `## In Progress`, `## Completed`, `## Session Log`) and at least one real
|
|
101
|
+
`actions/ACTION_N.md` (self-contained, in an `actions/` directory inside the intent
|
|
102
|
+
directory). At S/M write one consolidated `actions/ACTION_1.md`; at L write one
|
|
103
|
+
`actions/ACTION_N.md` per task (see Tier shapes above). For the exact format of
|
|
104
|
+
both, read `references/plan-format.md`.
|
|
105
105
|
|
|
106
106
|
## Owner-decision hard-gate items
|
|
107
107
|
|
|
@@ -118,12 +118,12 @@ When collecting owner rulings for `[ORCHESTRATOR]` hard-gate items, read
|
|
|
118
118
|
## Gate position
|
|
119
119
|
|
|
120
120
|
- **Before:** `spec.md` exists.
|
|
121
|
-
- **Produces:** `plan.md` and `
|
|
121
|
+
- **Produces:** `plan.md`, `checklist.md`, and at least one real `actions/ACTION_N.md` (every tier; one consolidated file at S/M, one per task at L).
|
|
122
122
|
- **Next:** /plastic-intent-executing.
|
|
123
123
|
|
|
124
124
|
## Git Commit
|
|
125
125
|
|
|
126
|
-
After writing all artifacts (plan.md, checklist.md, actions/
|
|
126
|
+
After writing all artifacts (plan.md, checklist.md, and the actions/ACTION_N.md files), commit to the store:
|
|
127
127
|
|
|
128
128
|
```bash
|
|
129
129
|
cd {store_root} && git add . && git commit -m "docs: plan for intent {id}: {name}"
|
|
@@ -1,18 +1,18 @@
|
|
|
1
1
|
{
|
|
2
2
|
"skill_name": "plastic-intent-planning",
|
|
3
|
-
"notes": "Intent 164
|
|
3
|
+
"notes": "Intent 164, updated by 133a. Evals for the writing-plans skill: action-file enforcement at every tier (S/M consolidate the delivery into one real actions/ACTION_1.md, L writes one actions/ACTION_N.md per task) and the checklist FORM plus [ORCHESTRATOR] hard-gate item convention. All assertions are pending a real observed run per the plastic-evaluating-skills convention.",
|
|
4
4
|
"evals": [
|
|
5
5
|
{
|
|
6
6
|
"id": 1,
|
|
7
7
|
"scope": "behavior",
|
|
8
8
|
"set": "train",
|
|
9
9
|
"prompt": "spec.md is stamped Tier: M and describes a single subsystem change touching four files across two tasks. Write the plan.",
|
|
10
|
-
"expected_output": "Produces
|
|
10
|
+
"expected_output": "Produces plan.md plus checklist.md plus at least one real actions/ACTION_N.md. At M the planner consolidates the whole delivery into a single actions/ACTION_1.md (it may split into a few files if that reads cleaner); the actions/ directory is never left empty or .gitkeep-only. checklist.md mirrors plan.md's task list.",
|
|
11
11
|
"files": [],
|
|
12
12
|
"assertions": [
|
|
13
13
|
{
|
|
14
14
|
"type": "code",
|
|
15
|
-
"check": "
|
|
15
|
+
"check": "at least one real (non-empty, non-.gitkeep) file exists under actions/ for this intent; checklist.md exists and mirrors plan.md's task list",
|
|
16
16
|
"result": "expect-pass"
|
|
17
17
|
}
|
|
18
18
|
]
|
|
@@ -22,12 +22,12 @@
|
|
|
22
22
|
"scope": "behavior",
|
|
23
23
|
"set": "train",
|
|
24
24
|
"prompt": "spec.md is stamped Tier: S and describes a single-file config change. Write the plan.",
|
|
25
|
-
"expected_output": "Produces
|
|
25
|
+
"expected_output": "Produces plan.md plus checklist.md plus one consolidated actions/ACTION_1.md carrying the whole ordered delivery (the steps plus the exact changes). The actions/ directory is never left empty or .gitkeep-only, matching the every-tier action-file rule.",
|
|
26
26
|
"files": [],
|
|
27
27
|
"assertions": [
|
|
28
28
|
{
|
|
29
29
|
"type": "code",
|
|
30
|
-
"check": "
|
|
30
|
+
"check": "at least one real (non-empty, non-.gitkeep) actions/ACTION_N.md exists under actions/ for this intent; no empty or .gitkeep-only actions/ dir remains",
|
|
31
31
|
"result": "expect-pass"
|
|
32
32
|
}
|
|
33
33
|
]
|
|
@@ -61,6 +61,21 @@
|
|
|
61
61
|
"result": "expect-pass"
|
|
62
62
|
}
|
|
63
63
|
]
|
|
64
|
+
},
|
|
65
|
+
{
|
|
66
|
+
"id": 5,
|
|
67
|
+
"scope": "behavior",
|
|
68
|
+
"set": "validation",
|
|
69
|
+
"prompt": "spec.md is stamped Tier: S. A prior draft left actions/ with only a .gitkeep. Write the plan and its actions.",
|
|
70
|
+
"expected_output": "Writes at least one real actions/ACTION_1.md (non-empty, not the placeholder sentinel, not a .gitkeep) that consolidates the whole S-tier delivery. Leaving actions/ empty or .gitkeep-only is a plan failure that would block the How gate; the planner never does this at any tier.",
|
|
71
|
+
"files": [],
|
|
72
|
+
"assertions": [
|
|
73
|
+
{
|
|
74
|
+
"type": "code",
|
|
75
|
+
"check": "actions/ contains at least one real action file (non-empty *.md, first line not the placeholder sentinel); no .gitkeep-only or empty actions/ dir remains",
|
|
76
|
+
"result": "expect-pass"
|
|
77
|
+
}
|
|
78
|
+
]
|
|
64
79
|
}
|
|
65
80
|
]
|
|
66
81
|
}
|
|
@@ -28,8 +28,9 @@ plan.md so the shape matches on the first pass.
|
|
|
28
28
|
|
|
29
29
|
**Intent:** {id}: {name}
|
|
30
30
|
|
|
31
|
-
**Tier:** S|M|L, copied from the spec's stamped `Tier:` line.
|
|
32
|
-
|
|
31
|
+
**Tier:** S|M|L, copied from the spec's stamped `Tier:` line. Every tier produces at
|
|
32
|
+
least one real `actions/ACTION_N.md`; S and M consolidate the delivery into one action
|
|
33
|
+
file, L uses one `actions/ACTION_N.md` per task.
|
|
33
34
|
|
|
34
35
|
---
|
|
35
36
|
```
|
|
@@ -112,10 +113,13 @@ of tier (S, M, or L):
|
|
|
112
113
|
|
|
113
114
|
## actions/ACTION_N.md format
|
|
114
115
|
|
|
115
|
-
|
|
116
|
-
|
|
116
|
+
Every tier writes at least one real action file here (see the parent SKILL.md's
|
|
117
|
+
`## Tier shapes`): S and M consolidate the whole delivery into a single
|
|
118
|
+
`actions/ACTION_1.md`, L writes one file per task.
|
|
117
119
|
|
|
118
|
-
|
|
120
|
+
Each action is self-contained: a subagent (or a solo executor) can execute it without
|
|
121
|
+
reading the plan. It carries the ordered steps to deliver the task plus the exact changes
|
|
122
|
+
to make (for code, the anchor or `file:line` and the old/new text).
|
|
119
123
|
|
|
120
124
|
```markdown
|
|
121
125
|
# Action {N}: {task title}
|
|
@@ -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:
|
|
@@ -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-
|
|
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" }
|
|
@@ -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.
|