@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
|
@@ -0,0 +1,100 @@
|
|
|
1
|
+
{
|
|
2
|
+
"skill_name": "plastic-project-continuing",
|
|
3
|
+
"notes": "Intent 158a1. New project route, absorbing intent-continuing's Continue/Priority Order/Stale Future Intents sections (move, not duplicate). Scopes: description triggering (1-3) and behavior/convention compliance (4-10), the latter checked against SKILL.md.",
|
|
4
|
+
"results": {
|
|
5
|
+
"triggering": { "cases": 3, "passed": 3, "run": "2026-07-10, one subagent per case" },
|
|
6
|
+
"behavior": { "cases": 7, "passed": 7, "evidence": "convention checks against skills/project-continuing/SKILL.md after the 158a1 extraction; id 10 (intent 170) added for the research-dispatch wiring of plastic-future-intent-researcher" }
|
|
7
|
+
},
|
|
8
|
+
"evals": [
|
|
9
|
+
{
|
|
10
|
+
"id": 1, "scope": "triggering", "set": "train",
|
|
11
|
+
"prompt": "what should I work on in this project",
|
|
12
|
+
"expected_output": "Activates plastic-project-continuing.",
|
|
13
|
+
"files": [],
|
|
14
|
+
"assertions": [
|
|
15
|
+
{ "type": "code", "check": "router CHOICE == plastic-project-continuing", "observed": "plastic-project-continuing", "result": "pass" }
|
|
16
|
+
]
|
|
17
|
+
},
|
|
18
|
+
{
|
|
19
|
+
"id": 2, "scope": "triggering", "set": "train",
|
|
20
|
+
"prompt": "land me on the project board",
|
|
21
|
+
"expected_output": "Activates plastic-project-continuing.",
|
|
22
|
+
"files": [],
|
|
23
|
+
"assertions": [
|
|
24
|
+
{ "type": "code", "check": "router CHOICE == plastic-project-continuing", "observed": "plastic-project-continuing", "result": "pass" }
|
|
25
|
+
]
|
|
26
|
+
},
|
|
27
|
+
{
|
|
28
|
+
"id": 3, "scope": "triggering", "set": "validation",
|
|
29
|
+
"prompt": "continue",
|
|
30
|
+
"expected_output": "Bare 'continue' with no specific intent or roadmap named reaches plastic-project-continuing via plastic-continuing's default route.",
|
|
31
|
+
"files": [],
|
|
32
|
+
"assertions": [
|
|
33
|
+
{ "type": "code", "check": "router CHOICE == plastic-project-continuing", "observed": "plastic-project-continuing", "result": "pass" }
|
|
34
|
+
]
|
|
35
|
+
},
|
|
36
|
+
{
|
|
37
|
+
"id": 4, "scope": "behavior", "set": "train",
|
|
38
|
+
"prompt": "Is dashboard selection project-aware?",
|
|
39
|
+
"expected_output": "Project loaded -> `dashboard.rb project <slug> --data` -> fills dashboard-project.md; otherwise -> `dashboard.rb continue --data`. Skill only invokes, does not render.",
|
|
40
|
+
"files": ["skills/project-continuing/SKILL.md"],
|
|
41
|
+
"assertions": [
|
|
42
|
+
{ "type": "convention", "check": "both dashboard invocations present and gated on project detection", "observed": "'dashboard.rb project <slug>' and 'dashboard.rb continue' in the 'Continue (present the board)' section", "result": "pass" }
|
|
43
|
+
]
|
|
44
|
+
},
|
|
45
|
+
{
|
|
46
|
+
"id": 5, "scope": "behavior", "set": "train",
|
|
47
|
+
"prompt": "Does the skill cite the classification rules by name instead of copying the logic?",
|
|
48
|
+
"expected_output": "SKILL.md's 'Deciding rules' section names Effort/Value/Flags/Override/Caps and points to plastic-dashboard's references/classification.md; it does not restate the rule definitions.",
|
|
49
|
+
"files": ["skills/project-continuing/SKILL.md"],
|
|
50
|
+
"assertions": [
|
|
51
|
+
{ "type": "convention", "check": "rule names cited, no copied Effort/Value/Flags/Override/Caps definitions", "observed": "present in 'Deciding rules'", "result": "pass" }
|
|
52
|
+
]
|
|
53
|
+
},
|
|
54
|
+
{
|
|
55
|
+
"id": 6, "scope": "behavior", "set": "train",
|
|
56
|
+
"prompt": "Does the project route ask 'auto or guided?' before stopping?",
|
|
57
|
+
"expected_output": "No. The project route presents state then stops; it asks nothing. The single ask lives in plastic-intent-starting once a specific intent is named.",
|
|
58
|
+
"files": ["skills/project-continuing/SKILL.md"],
|
|
59
|
+
"assertions": [
|
|
60
|
+
{ "type": "convention", "check": "no 'auto or guided' ask anywhere in SKILL.md", "observed": "absent", "result": "pass" }
|
|
61
|
+
]
|
|
62
|
+
},
|
|
63
|
+
{
|
|
64
|
+
"id": 7, "scope": "behavior", "set": "validation",
|
|
65
|
+
"prompt": "Does the skill present the board before stopping?",
|
|
66
|
+
"expected_output": "The filled Markdown board is presented in the reply (non-optional), then a 'Then stop' section waits for the user.",
|
|
67
|
+
"files": ["skills/project-continuing/SKILL.md"],
|
|
68
|
+
"assertions": [
|
|
69
|
+
{ "type": "convention", "check": "presentation is mandatory and precedes the 'Then stop' wait", "observed": "present", "result": "pass" }
|
|
70
|
+
]
|
|
71
|
+
},
|
|
72
|
+
{
|
|
73
|
+
"id": 8, "scope": "behavior", "set": "validation",
|
|
74
|
+
"prompt": "Does the skill carry the intent-149 coordination note?",
|
|
75
|
+
"expected_output": "A 'Coordination' section records that intent 149 has landed (dashboard demoted to prose, no Value x Effort grid) and confirms the rule-name citations and the dashboard.rb project <slug> --data -> dashboard-project.md path still resolve.",
|
|
76
|
+
"files": ["skills/project-continuing/SKILL.md"],
|
|
77
|
+
"assertions": [
|
|
78
|
+
{ "type": "convention", "check": "'149' present with the landed coordination note", "observed": "present: 'Intent 149 has landed' with confirmed rule-name citations and dashboard.rb path", "result": "pass" }
|
|
79
|
+
]
|
|
80
|
+
},
|
|
81
|
+
{
|
|
82
|
+
"id": 9, "scope": "behavior", "set": "validation",
|
|
83
|
+
"prompt": "Are Priority Order and Stale Future Intents present here and only here (not in intent-continuing)?",
|
|
84
|
+
"expected_output": "Both sections are present verbatim in this skill; they no longer exist in skills/intent-continuing/SKILL.md.",
|
|
85
|
+
"files": ["skills/project-continuing/SKILL.md", "skills/intent-continuing/SKILL.md"],
|
|
86
|
+
"assertions": [
|
|
87
|
+
{ "type": "convention", "check": "'## Priority Order' and '## Stale Future Intents' present here, absent from intent-continuing", "observed": "present here, absent there", "result": "pass" }
|
|
88
|
+
]
|
|
89
|
+
},
|
|
90
|
+
{
|
|
91
|
+
"id": 10, "scope": "behavior", "set": "validation",
|
|
92
|
+
"prompt": "In the stale-future-intent triage, the user picks option c) Defer to agent: research. What happens?",
|
|
93
|
+
"expected_output": "A real dispatch, not a label: plastic-future-intent-researcher's model is resolved via `read-config agents.models.<basename> --project <repo>` (never bare frontmatter, sanctioned-override-aware), the agent is dispatched via the Agent tool on the selected stale future intent and writes its findings into that intent's `## Context`, then the skill re-presents the stale-future-intent triage.",
|
|
94
|
+
"files": ["skills/project-continuing/SKILL.md"],
|
|
95
|
+
"assertions": [
|
|
96
|
+
{ "type": "convention", "check": "the 'Defer to agent: research' paragraph under Stale Future Intents resolves the model via read-config (not bare frontmatter), dispatches plastic-future-intent-researcher via the Agent tool, and re-presents the triage after the agent returns", "observed": "'Defer to agent: research.' paragraph present: resolves via read-config agents.models.<basename> --project <repo>, dispatches subagent_type plastic-future-intent-researcher, findings land in ## Context, then re-presents the triage", "result": "pass" }
|
|
97
|
+
]
|
|
98
|
+
}
|
|
99
|
+
]
|
|
100
|
+
}
|
|
@@ -0,0 +1,33 @@
|
|
|
1
|
+
# Board Fill Mechanics
|
|
2
|
+
|
|
3
|
+
Depth reference for the "Continue (present the board)" section of `SKILL.md`. The fill itself
|
|
4
|
+
is mechanical; `plastic-dashboard` owns the rules, this page is a pointer plus the detail that
|
|
5
|
+
would otherwise bloat the SKILL.md body.
|
|
6
|
+
|
|
7
|
+
## Fill rules (owned by plastic-dashboard, summarized here for convenience)
|
|
8
|
+
|
|
9
|
+
- `{{a.b.count}}` -> the integer (e.g. `counts.active` is that count).
|
|
10
|
+
- `{{...lines}}` -> join the list's `.line` strings with real newlines (one per line). These
|
|
11
|
+
are ordinary prose lines; never add a `-` prefix, never emit `<br>`. An empty list renders
|
|
12
|
+
`_(none)_`.
|
|
13
|
+
- `next_work.lines` -> the most-valuable next work, already ranked and capped.
|
|
14
|
+
- `active.lines` / `future.lines` (project board) -> one line per intent, already formatted.
|
|
15
|
+
- Scalars (`{{date}}`, `{{slug}}`, `{{description}}`) -> substitute verbatim.
|
|
16
|
+
|
|
17
|
+
No re-sorting, no re-summarizing, no hand-written prose replacing a line the payload already
|
|
18
|
+
supplies. Same store state produces a byte-identical payload regardless of model.
|
|
19
|
+
|
|
20
|
+
## Store-health surfacing
|
|
21
|
+
|
|
22
|
+
Every board load runs the scoped `doctor --store <scope>` check server-side (inside
|
|
23
|
+
`dashboard.rb`, not this skill). The payload carries the result as `store_health` (`{scope,
|
|
24
|
+
status, summary, failing_checks}`). Render it as a single line, for example `store health:
|
|
25
|
+
pass (3/3)` or `store health: warn (orphaned_intents)`. A warn or fail is informational only;
|
|
26
|
+
it never blocks presenting the board.
|
|
27
|
+
|
|
28
|
+
## Project vs. global fallback
|
|
29
|
+
|
|
30
|
+
The project route's default target is the project board. When no project is loaded (the rare
|
|
31
|
+
case where this route is reached without a registered project in scope), fall back to the
|
|
32
|
+
global board payload (`dashboard.rb continue --data`) rather than failing. This mirrors the
|
|
33
|
+
router's D6 default: a bare "continue" always lands somewhere useful.
|
|
@@ -15,6 +15,7 @@ Project configuration drives the workflow - no hardcoded assumptions.
|
|
|
15
15
|
- [ ] All tests pass (or verification skipped per config)
|
|
16
16
|
- [ ] Merge feature branch to main
|
|
17
17
|
- [ ] Bump version in configured version files
|
|
18
|
+
- [ ] Stable-cut guard passes (version files agree, no pre-release suffix; stable/latest cuts only)
|
|
18
19
|
- [ ] Commit version bump
|
|
19
20
|
- [ ] Create annotated tag
|
|
20
21
|
- [ ] Push to remote with tags
|
|
@@ -94,6 +95,25 @@ the full rationale and the already-merged-by-hand no-op case, read
|
|
|
94
95
|
|
|
95
96
|
### 4. Bump Version
|
|
96
97
|
|
|
98
|
+
**Stable-cut guard.** Before touching any version file for a stable (no pre-release suffix,
|
|
99
|
+
`latest`) cut, run the guard in `scripts/lib/release_guard.rb`:
|
|
100
|
+
|
|
101
|
+
```ruby
|
|
102
|
+
require "./scripts/lib/release_guard"
|
|
103
|
+
result = ReleaseGuard.check(
|
|
104
|
+
package_json: "package.json",
|
|
105
|
+
plugin_json: ".claude-plugin/plugin.json",
|
|
106
|
+
marketplace_json: ".claude-plugin/marketplace.json",
|
|
107
|
+
stable: true
|
|
108
|
+
)
|
|
109
|
+
raise "release guard failed: #{result.mismatches} #{result.prerelease_suffix}" unless result.ok?
|
|
110
|
+
```
|
|
111
|
+
|
|
112
|
+
If it reports a mismatch or a pre-release-suffix violation, stop and resolve it before bumping
|
|
113
|
+
any file. For a beta or alpha cut, pass `stable: false`; only version-file agreement is checked,
|
|
114
|
+
a pre-release suffix is expected. Read `references/release-lines.md` for the stable-line
|
|
115
|
+
guarantees this guard protects.
|
|
116
|
+
|
|
97
117
|
Determine which files to update from project.yml:
|
|
98
118
|
|
|
99
119
|
- If `release.version_files` is set: update ALL listed files (they must stay in sync).
|
|
@@ -252,6 +272,32 @@ prune` in the affected repo if you hit a stale reference. For why this is the on
|
|
|
252
272
|
merge-vs-remove policy lands on merge, and the fail-open/idempotent guarantees of `finish`,
|
|
253
273
|
read `references/promotion-and-tagging.md`.
|
|
254
274
|
|
|
275
|
+
## Release lines and channels
|
|
276
|
+
|
|
277
|
+
Two lanes get code to a release, on top of the workflow above.
|
|
278
|
+
|
|
279
|
+
- **Default lane.** Branch, merge to main, cut stable, publish to npm `latest`. This is the
|
|
280
|
+
workflow in the steps above, unchanged. Use it for additive, suite-verifiable,
|
|
281
|
+
low-blast-radius work.
|
|
282
|
+
- **Beta-verified lane.** Branch, merge to `beta`, publish to the npm `beta` channel, verify in
|
|
283
|
+
real use, then merge to main and cut stable. Use it for work that changes operational
|
|
284
|
+
substrate, or carries data, migration, lock, or state-format risk, or that a hermetic suite
|
|
285
|
+
cannot fully validate on its own.
|
|
286
|
+
|
|
287
|
+
**Stable-line guarantees.** An external `latest` user can rely on:
|
|
288
|
+
|
|
289
|
+
- `main` is always green and releasable; no pending revert awaiting re-land sits on `main`.
|
|
290
|
+
- A stable release carries no pre-release suffix, publishes to `latest`, and the newest release
|
|
291
|
+
always carries the GitHub "Latest" badge.
|
|
292
|
+
- The three version files always agree, checked by `scripts/lib/release_guard.rb` (see Bump
|
|
293
|
+
Version above).
|
|
294
|
+
- A stable cut collects only intents that cleared their lane's verification bar.
|
|
295
|
+
- Channel semantics are fixed: `latest` is stable, `beta` is the verification line, `alpha` is
|
|
296
|
+
experimental.
|
|
297
|
+
|
|
298
|
+
Read `references/release-lines.md` for the full lane-routing detail, the version-line map, and
|
|
299
|
+
the intent-41 re-land playbook.
|
|
300
|
+
|
|
255
301
|
## Conventions
|
|
256
302
|
|
|
257
303
|
- **Annotated tags only** - `git tag -a`, never lightweight tags
|
|
@@ -266,6 +312,8 @@ read `references/promotion-and-tagging.md`.
|
|
|
266
312
|
|
|
267
313
|
## References
|
|
268
314
|
|
|
315
|
+
- Read `references/release-lines.md` for the two release lanes, the stable-line guarantees,
|
|
316
|
+
the version-line map, and the intent-41 re-land playbook before starting any release
|
|
269
317
|
- When promoting a pre-release across channels (`--promote beta`/`--promote stable`) or
|
|
270
318
|
tagging a historical release retroactively, read `references/promotion-and-tagging.md`
|
|
271
319
|
for the exact commands and rules first
|
|
@@ -0,0 +1,105 @@
|
|
|
1
|
+
# Release Lines and Channels
|
|
2
|
+
|
|
3
|
+
The two release lanes, the version-line map, and the intent-41 re-land playbook: the deep
|
|
4
|
+
material behind SKILL.md's "Release lines and channels" section.
|
|
5
|
+
|
|
6
|
+
## Table of Contents
|
|
7
|
+
|
|
8
|
+
- [The two lanes](#the-two-lanes)
|
|
9
|
+
- [Routing rule](#routing-rule)
|
|
10
|
+
- [Stable-line guarantees](#stable-line-guarantees)
|
|
11
|
+
- [Version-line map](#version-line-map)
|
|
12
|
+
- [Intent 41 re-land playbook](#intent-41-re-land-playbook)
|
|
13
|
+
|
|
14
|
+
## The two lanes
|
|
15
|
+
|
|
16
|
+
**Default lane.** Branch, merge to `main` with `--no-ff`, cut stable, publish to npm `latest`.
|
|
17
|
+
This is the workflow SKILL.md documents step by step. It is the path for additive,
|
|
18
|
+
suite-verifiable, low-blast-radius work: new skills, prose, deterministic scripts, anything a
|
|
19
|
+
green Minitest run can fully vouch for.
|
|
20
|
+
|
|
21
|
+
**Beta-verified lane.** Branch, merge to the `beta` branch, publish to the npm `beta` dist-tag,
|
|
22
|
+
verify in real use, then merge `beta` into `main` and cut stable. It sits on top of the existing
|
|
23
|
+
promotion mechanics (`--promote beta` / `--promote stable`, linear only, see
|
|
24
|
+
`promotion-and-tagging.md`); it names when to use them, not new machinery.
|
|
25
|
+
|
|
26
|
+
## Routing rule
|
|
27
|
+
|
|
28
|
+
Work rides the beta-verified lane when it changes operational substrate, carries data,
|
|
29
|
+
migration, lock, or state-format risk, or cannot be fully validated by a hermetic suite alone.
|
|
30
|
+
Everything else merges straight to main.
|
|
31
|
+
|
|
32
|
+
Intent 41's DB layer is the archetypal beta-lane case: it replaces the bridge, lock, and session
|
|
33
|
+
file formats with a new persistent SQLite substrate. A green suite proves the code correct; it
|
|
34
|
+
cannot prove the new substrate survives real, uncontrolled usage, so real-use verification on
|
|
35
|
+
beta comes first.
|
|
36
|
+
|
|
37
|
+
The manual-first roadmap's eight 1.1.0 intents (158a, 163, 161, 164, 165, 168, 166, 159) are all
|
|
38
|
+
default-lane: skill directory renames, prose rewrites, deterministic step scripts. Additive, and
|
|
39
|
+
fully suite-verified.
|
|
40
|
+
|
|
41
|
+
## Stable-line guarantees
|
|
42
|
+
|
|
43
|
+
What an external `latest` user can rely on:
|
|
44
|
+
|
|
45
|
+
1. `main` is always green and releasable. No pending revert awaiting re-land sits on `main`.
|
|
46
|
+
When something needs beta verification, it comes out of `main` the same day that need is
|
|
47
|
+
found (the 226023f precedent), never left half-landed.
|
|
48
|
+
2. A stable release carries no pre-release suffix, publishes to npm `latest`, and the newest
|
|
49
|
+
stable release always carries the GitHub "Latest" badge (`gh release create --latest` on
|
|
50
|
+
every cut).
|
|
51
|
+
3. The three repo version files (`package.json`, `.claude-plugin/plugin.json`,
|
|
52
|
+
`.claude-plugin/marketplace.json`) always agree. Checked mechanically by
|
|
53
|
+
`scripts/lib/release_guard.rb`.
|
|
54
|
+
4. A stable cut collects only intents that cleared their lane's bar: default-lane intents by a
|
|
55
|
+
green suite, beta-lane intents by suite green plus their lane's own verification (real-use
|
|
56
|
+
signal, owner sign-off).
|
|
57
|
+
5. Channel semantics are fixed: `latest` is stable and what an external user should run; `beta`
|
|
58
|
+
is the verification line, published but expected to move; `alpha` is experimental,
|
|
59
|
+
pre-verification.
|
|
60
|
+
|
|
61
|
+
## Version-line map
|
|
62
|
+
|
|
63
|
+
| Line | State | What lands here |
|
|
64
|
+
|---|---|---|
|
|
65
|
+
| `1.1.x` | Current stable line (main) | Additive or low-risk work merged straight to main; interim stable cuts, including 171's wave-6 cut, stay in this line |
|
|
66
|
+
| `1.2.0-beta.1` | On beta (`9ec194b`, unpublished) | Intent 41's DB layer, restored over 1.1.0 by revert-of-revert (`c48601a` then `9ec194b`) |
|
|
67
|
+
| `1.2.0` | Reserved | The stable graduation of the DB layer, once beta verification passes; not claimed by any interim `1.1.x` cut |
|
|
68
|
+
|
|
69
|
+
A beta-graduated substrate change claims its reserved minor at the moment it actually merges to
|
|
70
|
+
main, not before. Nothing else on the `1.1.x` line is blocked waiting for `1.2.0`.
|
|
71
|
+
|
|
72
|
+
## Intent 41 re-land playbook
|
|
73
|
+
|
|
74
|
+
Written for the wave-6 cut intent (171) and any future reader to pick a version without
|
|
75
|
+
re-deriving this decision.
|
|
76
|
+
|
|
77
|
+
**Current state.** The revert-of-revert already sits on the `beta` branch at `9ec194b`, on top
|
|
78
|
+
of 1.1.0, versioned `1.2.0-beta.1` (`c48601a`). There is nothing left to execute on the git side;
|
|
79
|
+
this playbook describes what happens next, not a pending action.
|
|
80
|
+
|
|
81
|
+
**Preconditions**, both required before any npm publish of `1.2.0-beta.1`:
|
|
82
|
+
|
|
83
|
+
- (a) One documentation pass over beta-line skills and docs for the hybrid savepoint contract:
|
|
84
|
+
on beta, only the terminal Done bookend still writes a live `savepoint.md`; every other
|
|
85
|
+
milestone lives in `savepoint_events` plus a committed JSONL export. Beta-line prose that
|
|
86
|
+
still assumes an always-live ledger needs updating first, so a beta-line reader does not
|
|
87
|
+
mistake an empty ledger for a broken one.
|
|
88
|
+
- (b) The owner's manual verification of the DB layer in real use. This is a dogfood signal,
|
|
89
|
+
distinct from the independently-reviewed green suite that already exists on beta.
|
|
90
|
+
|
|
91
|
+
**Trigger**, owner-gated: the owner publishes `1.2.0-beta.1` to the npm `beta` dist-tag. This is
|
|
92
|
+
explicitly not this intent's, nor any agent's, call to make.
|
|
93
|
+
|
|
94
|
+
**Verification.** An external tester plus the owner verify the DB layer on the beta channel.
|
|
95
|
+
|
|
96
|
+
**Completion.** Once verified, `beta` merges into `main`, `1.2.0` is cut stable, and it publishes
|
|
97
|
+
to npm `latest`.
|
|
98
|
+
|
|
99
|
+
**Version mechanics.** `1.2.0` is reserved for this graduation. The `1.1.x` line stays the
|
|
100
|
+
stable line until `1.2.0` actually lands. `1.2.0-beta.1` graduates to `1.2.0` stable by dropping
|
|
101
|
+
the pre-release suffix; nothing else about the version number changes.
|
|
102
|
+
|
|
103
|
+
**Consumed by 171.** The wave-6 consistency-dividend cut stays in the `1.1.x` line. It does not
|
|
104
|
+
ride intent 41 and needs no further derivation: intent 41 keeps its own `1.2.0` line on beta,
|
|
105
|
+
independent of whatever `1.1.x` number 171 lands on.
|
package/skills/roadmap/SKILL.md
CHANGED
|
@@ -21,7 +21,10 @@ wave entry mirrors that intent's status in `INDEX.md` (`queued`/`delivering`/`de
|
|
|
21
21
|
**`INDEX.md` is the single writer of intent status; on any conflict INDEX wins and the roadmap
|
|
22
22
|
entry is corrected to match.**
|
|
23
23
|
|
|
24
|
-
The skill operates on the file directly via Read/Edit
|
|
24
|
+
The skill operates on the roadmap file directly via Read/Edit. The one deterministic helper it
|
|
25
|
+
uses is the savepoint ledger writer (`scripts/roadmap-savepoint`, `append`/`rebuild`); every verb's
|
|
26
|
+
closing step calls `append` after its Read/Edit, and the roadmap `.md` file itself stays
|
|
27
|
+
Read/Edit-only.
|
|
25
28
|
|
|
26
29
|
## Verbs
|
|
27
30
|
|
|
@@ -50,3 +53,6 @@ verb above.
|
|
|
50
53
|
- Additive: this skill introduces no gate, lock, or hook, and does not change `INDEX.md`'s section
|
|
51
54
|
list or the intent frontmatter schema.
|
|
52
55
|
- Closing a roadmap moves it to `roadmaps/archived/{slug}.md` so `roadmaps/` lists only live ones.
|
|
56
|
+
- Every verb also appends a machine ledger line to the roadmap's name-paired
|
|
57
|
+
`roadmaps/{slug}.savepoint.md`, the derived counterpart to the human `## Log`; see
|
|
58
|
+
`references/file-format.md` for its shape and location.
|
|
@@ -11,7 +11,9 @@ roadmap.
|
|
|
11
11
|
|
|
12
12
|
`roadmaps/` lists only live (open or in-flight) roadmaps. Once a roadmap's `## Goal` is reached,
|
|
13
13
|
its file moves to `roadmaps/archived/{slug}.md` (see Close/archive in `operations.md`); the
|
|
14
|
-
`archived/` subdirectory is scaffolded once, alongside `roadmaps/`, with a `.gitkeep`.
|
|
14
|
+
`archived/` subdirectory is scaffolded once, alongside `roadmaps/`, with a `.gitkeep`. Its
|
|
15
|
+
name-paired ledger, `roadmaps/{slug}.savepoint.md` (see Savepoint ledger below), moves alongside
|
|
16
|
+
it in the same Close/archive step.
|
|
15
17
|
|
|
16
18
|
## The four sections (in order)
|
|
17
19
|
|
|
@@ -63,6 +65,33 @@ that entry-intent's `outcome.md`:
|
|
|
63
65
|
The log line never restates `outcome.md` detail; it points at it (lossless-by-reference). This
|
|
64
66
|
complements, and does not replace, `INDEX.md`'s `## Completed` section or `CHANGELOG.md`.
|
|
65
67
|
|
|
68
|
+
## Savepoint ledger
|
|
69
|
+
|
|
70
|
+
`roadmaps/{slug}.savepoint.md` is the name-paired sibling of `roadmaps/{slug}.md`: the machine
|
|
71
|
+
counterpart to the human `## Log`, moving to `roadmaps/archived/{slug}.savepoint.md` alongside its
|
|
72
|
+
roadmap on close (see Close/archive). It is created lazily by the first `append` call; there is no
|
|
73
|
+
template to scaffold.
|
|
74
|
+
|
|
75
|
+
Line shape, one event per line, append-only, newest at the bottom:
|
|
76
|
+
|
|
77
|
+
```
|
|
78
|
+
<UTC-iso8601> <event> <detail>
|
|
79
|
+
```
|
|
80
|
+
|
|
81
|
+
Two-space fields, mirroring the intent-dir cycle-step ledger (`savepoint.md`). The controlled event
|
|
82
|
+
vocabulary: `created`, `dispatched`, `parked`, `merged`, `release`, `handoff`, `closed`, and
|
|
83
|
+
optionally `added`, `reordered`, `wave`. The `(event, detail)` pair is the idempotency key, so
|
|
84
|
+
re-appending the same pair is a no-op.
|
|
85
|
+
|
|
86
|
+
`## Log` and the ledger record the same events in two voices: the Log is the dated, one-sentence,
|
|
87
|
+
EM-to-CTO-plain-language record a human reads cold; the ledger is the terse, machine-timestamped,
|
|
88
|
+
controlled-vocabulary record a coordinator reads at a glance. Both are append-only; neither edits
|
|
89
|
+
the other.
|
|
90
|
+
|
|
91
|
+
The ledger is derived and rebuildable (`ruby ~/.plastic/scripts/roadmap-savepoint rebuild --roadmap
|
|
92
|
+
roadmaps/{slug}.md`, reconstructing it from `## Log`), never a status source: `INDEX.md` stays the
|
|
93
|
+
single writer of intent status, exactly as for the roadmap file itself.
|
|
94
|
+
|
|
66
95
|
## Worked example
|
|
67
96
|
|
|
68
97
|
```
|
|
@@ -20,7 +20,10 @@ next" in under a minute, just from this one file.
|
|
|
20
20
|
status mirroring that intent's current `INDEX.md` status.
|
|
21
21
|
6. Append the first `## Log` line, a short `YYYY-MM-DD HH:MM UTC`-prefixed plain-language note
|
|
22
22
|
that the roadmap was created.
|
|
23
|
-
7.
|
|
23
|
+
7. Append the ledger event (derived, idempotent, safe to re-run; never writes INDEX or roadmap
|
|
24
|
+
status; creates `roadmaps/<slug>.savepoint.md` lazily): `ruby ~/.plastic/scripts/roadmap-savepoint
|
|
25
|
+
append --roadmap roadmaps/<slug>.md --event created --detail "<slug>: <title>"`.
|
|
26
|
+
8. Refresh the QMD index for this roadmap (no-op when QMD is absent), in the background so it
|
|
24
27
|
never blocks: `ruby ~/.plastic/scripts/qmd-sync reindex --store <roadmaps-dir> --async`.
|
|
25
28
|
|
|
26
29
|
## Add / reorder entries
|
|
@@ -34,6 +37,10 @@ next" in under a minute, just from this one file.
|
|
|
34
37
|
entry is eligible to run.
|
|
35
38
|
- After any add/reorder, append a `## Log` line describing the change (e.g.
|
|
36
39
|
`- <YYYY-MM-DD HH:MM UTC> added 132 to wave 2`).
|
|
40
|
+
- Append the ledger event (derived, idempotent, safe to re-run; never writes INDEX or roadmap
|
|
41
|
+
status): `ruby ~/.plastic/scripts/roadmap-savepoint append --roadmap roadmaps/<slug>.md --event
|
|
42
|
+
added --detail "<id> to wave N"` for an add, or `--event reordered` for a reorder (describe the
|
|
43
|
+
move in `<detail>`).
|
|
37
44
|
- Refresh the QMD index for this roadmap (no-op when QMD is absent), in the background so it
|
|
38
45
|
never blocks: `ruby ~/.plastic/scripts/qmd-sync reindex --store <roadmaps-dir> --async`.
|
|
39
46
|
|
|
@@ -49,7 +56,12 @@ next" in under a minute, just from this one file.
|
|
|
49
56
|
one-line EM-to-CTO entry described in `file-format.md` (date, what shipped and its impact in
|
|
50
57
|
plain language, then a link to that intent's `outcome.md`). For other transitions, write a
|
|
51
58
|
short dated plain-language line (no codenames, no jargon).
|
|
52
|
-
5.
|
|
59
|
+
5. Append the ledger event, only when the status token actually changed (derived, idempotent,
|
|
60
|
+
never writes INDEX or roadmap status): map the new status to its mechanized event (`delivered`
|
|
61
|
+
-> `merged`, `delivering` -> `dispatched`, `blocked`/`abandoned` -> `parked`), then `ruby
|
|
62
|
+
~/.plastic/scripts/roadmap-savepoint append --roadmap roadmaps/<slug>.md --event <event>
|
|
63
|
+
--detail "<intent-id>"` (add a sha in `<detail>` when one is known).
|
|
64
|
+
6. Refresh the QMD index for this roadmap (no-op when QMD is absent), in the background so it
|
|
53
65
|
never blocks: `ruby ~/.plastic/scripts/qmd-sync reindex --store <roadmaps-dir> --async`.
|
|
54
66
|
|
|
55
67
|
## Append a log line
|
|
@@ -60,6 +72,10 @@ next" in under a minute, just from this one file.
|
|
|
60
72
|
A delivery event follows the EM-to-CTO one-line shape with an `outcome.md` link (see
|
|
61
73
|
`file-format.md`); bookkeeping events (created, an intent added to a wave, a wave completed, a
|
|
62
74
|
roadmap closed) are short dated plain-language lines.
|
|
75
|
+
- Append the matching ledger event (derived, idempotent, never writes INDEX or roadmap status):
|
|
76
|
+
when the line records a release cut, `ruby ~/.plastic/scripts/roadmap-savepoint append --roadmap
|
|
77
|
+
roadmaps/<slug>.md --event release --detail "<version>"`; otherwise append the mechanized event
|
|
78
|
+
matching the bookkeeping line just written (see the per-verb event mapping on this page).
|
|
63
79
|
- Refresh the QMD index for this roadmap (no-op when QMD is absent), in the background so it
|
|
64
80
|
never blocks: `ruby ~/.plastic/scripts/qmd-sync reindex --store <roadmaps-dir> --async`.
|
|
65
81
|
|
|
@@ -80,9 +96,13 @@ next" in under a minute, just from this one file.
|
|
|
80
96
|
`abandoned` with a recorded reason, plus whatever else the goal states).
|
|
81
97
|
2. Create `roadmaps/archived/` beside `roadmaps/` (both siblings of `INDEX.md`) if it does not
|
|
82
98
|
exist yet.
|
|
83
|
-
3.
|
|
84
|
-
|
|
85
|
-
|
|
99
|
+
3. Append the ledger closed event, while the roadmap is still at its live path (derived,
|
|
100
|
+
idempotent, never writes INDEX or roadmap status): `ruby ~/.plastic/scripts/roadmap-savepoint
|
|
101
|
+
append --roadmap roadmaps/<slug>.md --event closed --detail "<slug>"`.
|
|
102
|
+
4. Move BOTH files: `roadmaps/{slug}.md` -> `roadmaps/archived/{slug}.md` AND
|
|
103
|
+
`roadmaps/{slug}.savepoint.md` -> `roadmaps/archived/{slug}.savepoint.md`. `roadmaps/` itself
|
|
104
|
+
then lists only live (open or in-flight) roadmaps.
|
|
105
|
+
5. Append the final `## Log` line before or as part of the move:
|
|
86
106
|
`- <YYYY-MM-DD HH:MM UTC> roadmap closed`.
|
|
87
|
-
|
|
107
|
+
6. Refresh the QMD index for this roadmap (no-op when QMD is absent), in the background so it
|
|
88
108
|
never blocks: `ruby ~/.plastic/scripts/qmd-sync reindex --store <roadmaps-dir> --async`.
|
|
@@ -0,0 +1,85 @@
|
|
|
1
|
+
---
|
|
2
|
+
name: plastic-roadmap-continuing
|
|
3
|
+
description: >-
|
|
4
|
+
Use when the user wants to continue or resume a roadmap, pick up a mid-flight delivery batch,
|
|
5
|
+
asks "where is the roadmap", or wants to resume the wave that was shipping, including an
|
|
6
|
+
indirect ask that never names a roadmap directly (for example "where did that batch of
|
|
7
|
+
tickets land"). This is the roadmap route of plastic-continuing: it finds the tier's
|
|
8
|
+
mid-flight roadmap, presents its state, then asks how to proceed exactly once.
|
|
9
|
+
user-invocable: true
|
|
10
|
+
---
|
|
11
|
+
|
|
12
|
+
# Roadmap Continuing - resume the mid-flight roadmap
|
|
13
|
+
|
|
14
|
+
`plastic-roadmap-continuing` is the roadmap route of `plastic-continuing`. It finds the tier's
|
|
15
|
+
mid-flight roadmap, presents its state, then asks the user how to proceed, exactly once.
|
|
16
|
+
|
|
17
|
+
Before intent 158a1 there was no automated way to do this: the `171` (consistency-dividend)
|
|
18
|
+
roadmap handoff had to be resumed by hand, carried as a free-prose note in `171`'s own
|
|
19
|
+
`## Insights`. This skill closes that gap.
|
|
20
|
+
|
|
21
|
+
## Find the mid-flight roadmap
|
|
22
|
+
|
|
23
|
+
1. Determine the tier (project vs. global) and enumerate that tier's live `roadmaps/*.md`
|
|
24
|
+
(exclude `roadmaps/archived/`). Read via Read/glob, or `plastic-roadmap`'s Read/consume
|
|
25
|
+
verb. See `plastic-roadmap`'s `references/file-format.md` for the file grammar; do not
|
|
26
|
+
duplicate it here.
|
|
27
|
+
2. For each candidate, also read its paired ledger `roadmaps/<slug>.savepoint.md` when present
|
|
28
|
+
(see `plastic-roadmap`'s `references/file-format.md#savepoint-ledger`): its last line(s) are a
|
|
29
|
+
cheaper, precise last-event signal (for example `dispatched 134` or `merged 172`), read
|
|
30
|
+
alongside the existing `## Waves`/`## Log` judgment. The ledger is read-only here, a derived
|
|
31
|
+
signal, never a new status field; INDEX.md stays the sole status writer.
|
|
32
|
+
3. Rank liveness by calling the shared reader in which mode (one implementation across the
|
|
33
|
+
auto loop and this skill):
|
|
34
|
+
|
|
35
|
+
```bash
|
|
36
|
+
ruby ~/.plastic/scripts/roadmap-next --roadmaps-dir <tier>/roadmaps --which
|
|
37
|
+
```
|
|
38
|
+
|
|
39
|
+
Read `state` and the winning `roadmap`. When `state` is `tie`, `tie_candidates` lists the
|
|
40
|
+
equally-live roadmaps to present side by side; the single "auto or guided?" ask below
|
|
41
|
+
doubles as the resolution. `roadmap-next` liveness-ranks the same way this skill used to do
|
|
42
|
+
by eye (a `delivering` or `blocked` entry wins, else the newest ledger or `## Log`
|
|
43
|
+
timestamp), now deterministically. See `references/liveness-ranking.md` for the algorithm it
|
|
44
|
+
implements.
|
|
45
|
+
4. A genuine tie (two candidates equally live) is presented to the user and resolved by the
|
|
46
|
+
single ask below, not silently picked.
|
|
47
|
+
|
|
48
|
+
## Present state
|
|
49
|
+
|
|
50
|
+
Present the chosen roadmap's `## Goal`, the current wave with each entry's mirrored status, the
|
|
51
|
+
ledger's newest line(s) (the last mechanized event) alongside the newest `## Log` line, before any
|
|
52
|
+
ask, so the coordinator sees the machine last-event at a glance.
|
|
53
|
+
|
|
54
|
+
## Ask once
|
|
55
|
+
|
|
56
|
+
Ask "auto or guided?" exactly once, after presenting state, mirroring
|
|
57
|
+
`plastic-intent-starting`'s single-ask contract:
|
|
58
|
+
- **guided** -> continue step by step with the user.
|
|
59
|
+
- **auto** -> hand off to `plastic-auto` to drive the next wave or entry.
|
|
60
|
+
|
|
61
|
+
Never re-ask. No new roadmap or INDEX status field is invented anywhere in this flow.
|
|
62
|
+
|
|
63
|
+
## The shared reader
|
|
64
|
+
|
|
65
|
+
Liveness ranking and frontier selection live in one place, `scripts/lib/roadmap_queue.rb`
|
|
66
|
+
(intent 148), behind the `scripts/roadmap-next` CLI. This skill calls it in which mode rather
|
|
67
|
+
than ranking roadmaps in prose, so the auto loop (`plastic-auto`) and this skill share exactly
|
|
68
|
+
one implementation (no forked ranking logic). 158a1 originally added no script because the
|
|
69
|
+
benefit was marginal for a read-time judgment; the auto-loop consumer flipped that calculus by
|
|
70
|
+
making the ranking load-bearing and deterministic. The reader is read-only: it consumes the
|
|
71
|
+
roadmap `.md`, the 134 `<slug>.savepoint.md` ledger, and INDEX.md, and writes nothing. INDEX.md
|
|
72
|
+
stays the single status writer.
|
|
73
|
+
|
|
74
|
+
## Caller contract: who writes the ledger
|
|
75
|
+
|
|
76
|
+
This skill is a reader, not a writer, of `roadmaps/<slug>.savepoint.md`. The coordinator flows
|
|
77
|
+
(`plastic-auto`, the enforcer, and this skill's own resume-and-hand-off path) call `ruby
|
|
78
|
+
~/.plastic/scripts/roadmap-savepoint append` at their own dispatch, merge, park, handoff, and
|
|
79
|
+
release points, the same events `plastic-roadmap`'s verbs append at their closing steps. A
|
|
80
|
+
resuming coordinator therefore both reads the ledger here and writes to it as it drives the next
|
|
81
|
+
wave or entry.
|
|
82
|
+
|
|
83
|
+
## References
|
|
84
|
+
|
|
85
|
+
- `references/liveness-ranking.md` - the read-time ranking algorithm and the tie rule.
|
|
@@ -0,0 +1,82 @@
|
|
|
1
|
+
{
|
|
2
|
+
"skill_name": "plastic-roadmap-continuing",
|
|
3
|
+
"notes": "Intent 158a1. New roadmap route, closing the gap that forced the 171 (consistency-dividend) roadmap handoff to be resumed by hand. Scopes: description triggering (1-3) and behavior/convention compliance (4-8), the latter checked against SKILL.md.",
|
|
4
|
+
"results": {
|
|
5
|
+
"triggering": { "cases": 3, "passed": 3, "run": "2026-07-10, one subagent per case" },
|
|
6
|
+
"behavior": { "cases": 5, "passed": 5, "evidence": "convention checks against skills/roadmap-continuing/SKILL.md and references/liveness-ranking.md" }
|
|
7
|
+
},
|
|
8
|
+
"evals": [
|
|
9
|
+
{
|
|
10
|
+
"id": 1, "scope": "triggering", "set": "train",
|
|
11
|
+
"prompt": "continue the roadmap",
|
|
12
|
+
"expected_output": "Activates plastic-roadmap-continuing.",
|
|
13
|
+
"files": [],
|
|
14
|
+
"assertions": [
|
|
15
|
+
{ "type": "code", "check": "router CHOICE == plastic-roadmap-continuing", "observed": "plastic-roadmap-continuing", "result": "pass" }
|
|
16
|
+
]
|
|
17
|
+
},
|
|
18
|
+
{
|
|
19
|
+
"id": 2, "scope": "triggering", "set": "train",
|
|
20
|
+
"prompt": "resume the delivery batch we were shipping",
|
|
21
|
+
"expected_output": "Activates plastic-roadmap-continuing.",
|
|
22
|
+
"files": [],
|
|
23
|
+
"assertions": [
|
|
24
|
+
{ "type": "code", "check": "router CHOICE == plastic-roadmap-continuing", "observed": "plastic-roadmap-continuing", "result": "pass" }
|
|
25
|
+
]
|
|
26
|
+
},
|
|
27
|
+
{
|
|
28
|
+
"id": 3, "scope": "triggering", "set": "validation",
|
|
29
|
+
"prompt": "where did that batch of tickets land",
|
|
30
|
+
"expected_output": "Activates plastic-roadmap-continuing (indirect trigger: a roadmap-resume request that never names 'roadmap' or 'continue').",
|
|
31
|
+
"files": [],
|
|
32
|
+
"assertions": [
|
|
33
|
+
{ "type": "code", "check": "router CHOICE == plastic-roadmap-continuing", "observed": "plastic-roadmap-continuing", "result": "pass" }
|
|
34
|
+
]
|
|
35
|
+
},
|
|
36
|
+
{
|
|
37
|
+
"id": 4, "scope": "behavior", "set": "train",
|
|
38
|
+
"prompt": "Does the skill rank liveness correctly when a wave entry is delivering or blocked?",
|
|
39
|
+
"expected_output": "A roadmap with any delivering/blocked wave entry wins the ranking outright over every other candidate.",
|
|
40
|
+
"files": ["skills/roadmap-continuing/references/liveness-ranking.md"],
|
|
41
|
+
"assertions": [
|
|
42
|
+
{ "type": "convention", "check": "delivering/blocked-wins rule documented as step 2 of the algorithm", "observed": "present", "result": "pass" }
|
|
43
|
+
]
|
|
44
|
+
},
|
|
45
|
+
{
|
|
46
|
+
"id": 5, "scope": "behavior", "set": "train",
|
|
47
|
+
"prompt": "Does the skill fall back to newest Log date when no candidate is delivering/blocked?",
|
|
48
|
+
"expected_output": "Among remaining candidates, the most recent ## Log entry timestamp wins.",
|
|
49
|
+
"files": ["skills/roadmap-continuing/references/liveness-ranking.md"],
|
|
50
|
+
"assertions": [
|
|
51
|
+
{ "type": "convention", "check": "newest-Log-date fallback documented as step 3", "observed": "present", "result": "pass" }
|
|
52
|
+
]
|
|
53
|
+
},
|
|
54
|
+
{
|
|
55
|
+
"id": 6, "scope": "behavior", "set": "train",
|
|
56
|
+
"prompt": "Does the skill present the roadmap state before asking?",
|
|
57
|
+
"expected_output": "The '## Present state' section (Goal, current wave, newest Log line) runs before the '## Ask once' section.",
|
|
58
|
+
"files": ["skills/roadmap-continuing/SKILL.md"],
|
|
59
|
+
"assertions": [
|
|
60
|
+
{ "type": "convention", "check": "Present state precedes Ask once in document order", "observed": "present", "result": "pass" }
|
|
61
|
+
]
|
|
62
|
+
},
|
|
63
|
+
{
|
|
64
|
+
"id": 7, "scope": "behavior", "set": "validation",
|
|
65
|
+
"prompt": "Does the skill ask 'auto or guided?' exactly once?",
|
|
66
|
+
"expected_output": "Exactly one ask, after presenting state; never re-asked.",
|
|
67
|
+
"files": ["skills/roadmap-continuing/SKILL.md"],
|
|
68
|
+
"assertions": [
|
|
69
|
+
{ "type": "convention", "check": "the literal phrase 'auto or guided' appears on exactly one line of SKILL.md", "observed": "one occurrence", "result": "pass" }
|
|
70
|
+
]
|
|
71
|
+
},
|
|
72
|
+
{
|
|
73
|
+
"id": 8, "scope": "behavior", "set": "validation",
|
|
74
|
+
"prompt": "Does the skill invent a new roadmap or INDEX status field, or add a new script?",
|
|
75
|
+
"expected_output": "No. Liveness is computed at read time from existing files; INDEX.md stays the sole status writer; the enumeration/ranking is prose, not a helper script.",
|
|
76
|
+
"files": ["skills/roadmap-continuing/SKILL.md", "skills/roadmap-continuing/references/liveness-ranking.md"],
|
|
77
|
+
"assertions": [
|
|
78
|
+
{ "type": "convention", "check": "no new field or script introduced; 'No new script' section present", "observed": "present", "result": "pass" }
|
|
79
|
+
]
|
|
80
|
+
}
|
|
81
|
+
]
|
|
82
|
+
}
|