@zalom/plastic 2.0.0-alpha.2 → 2.0.0-alpha.21
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/agents/plastic-enforcer.md +3 -1
- package/agents/plastic-executor.md +9 -3
- package/bin/test +24 -4
- package/hooks/call-budget +4 -0
- package/hooks/hooks.json +24 -0
- package/hooks/message-display +134 -0
- package/hooks/statusline +4 -27
- package/package.json +2 -2
- package/scripts/agent-report +8 -2
- package/scripts/dashboard.rb +297 -18
- package/scripts/doctor.rb +652 -5
- package/scripts/end-intent +219 -0
- package/scripts/hook-call-budget +222 -0
- package/scripts/hook-capture +25 -113
- package/scripts/hook-message-display +81 -0
- package/scripts/hook-record +12 -4
- package/scripts/hook-session-start +45 -7
- package/scripts/index-projection +74 -0
- package/scripts/intent-screen +77 -0
- package/scripts/lib/action_graph_shim.rb +277 -0
- package/scripts/lib/arm.rb +26 -1
- package/scripts/lib/atomic_write.rb +31 -0
- package/scripts/lib/compact_instructions.rb +5 -5
- package/scripts/lib/core_integrity.rb +71 -0
- package/scripts/lib/dashboard_screen.rb +40 -0
- package/scripts/lib/day_summary.rb +7 -2
- package/scripts/lib/doctor_core.rb +102 -5
- package/scripts/lib/doctor_session_ledger.rb +52 -0
- package/scripts/lib/graph_edges.rb +137 -0
- package/scripts/lib/graph_file.rb +246 -0
- package/scripts/lib/graph_tree.rb +98 -0
- package/scripts/lib/guarded_append.rb +155 -0
- package/scripts/lib/hook_registry.rb +28 -2
- package/scripts/lib/hook_replay.rb +211 -0
- package/scripts/lib/index_projection.rb +201 -0
- package/scripts/lib/installer_core.rb +141 -6
- package/scripts/lib/intent_screen.rb +309 -0
- package/scripts/lib/intent_screen_ansi.rb +262 -0
- package/scripts/lib/message_display.rb +586 -0
- package/scripts/lib/meter_watch.rb +179 -0
- package/scripts/lib/node_file.rb +214 -0
- package/scripts/lib/node_ids.rb +99 -0
- package/scripts/lib/node_ledger.rb +377 -0
- package/scripts/lib/node_packet.rb +908 -0
- package/scripts/lib/node_return.rb +199 -0
- package/scripts/lib/node_worktree.rb +337 -0
- package/scripts/lib/outcome_report.rb +440 -0
- package/scripts/lib/packet_wrapper.rb +132 -0
- package/scripts/lib/ready_set.rb +462 -0
- package/scripts/lib/release_guard.rb +16 -0
- package/scripts/lib/report_screen.rb +1967 -0
- package/scripts/lib/roadmap_graph.rb +210 -0
- package/scripts/lib/roadmap_migration.rb +95 -0
- package/scripts/lib/roadmap_queue.rb +155 -5
- package/scripts/lib/roadmap_render.rb +150 -0
- package/scripts/lib/roadmap_savepoint.rb +62 -12
- package/scripts/lib/runner_absorb.rb +620 -0
- package/scripts/lib/runner_answer.rb +206 -0
- package/scripts/lib/runner_core.rb +194 -0
- package/scripts/lib/runner_dispatch.rb +506 -0
- package/scripts/lib/runner_policy.rb +173 -0
- package/scripts/lib/runner_proposals.rb +275 -0
- package/scripts/lib/runner_rewind.rb +201 -0
- package/scripts/lib/runner_sweep.rb +231 -0
- package/scripts/lib/savepoint.rb +149 -12
- package/scripts/lib/screen_paint.rb +555 -0
- package/scripts/lib/screens/dashboard.rb +20 -0
- package/scripts/lib/screens/plan.rb +18 -0
- package/scripts/lib/screens/roadmap.rb +15 -0
- package/scripts/lib/session_git.rb +49 -18
- package/scripts/lib/session_ledger.rb +128 -0
- package/scripts/lib/session_usage.rb +190 -0
- package/scripts/lib/verify_intent.rb +33 -0
- package/scripts/lib/work_graph_validator.rb +201 -0
- package/scripts/meter-watch +57 -0
- package/scripts/node-packet +92 -0
- package/scripts/node-transition +291 -0
- package/scripts/outcome-report +74 -0
- package/scripts/plastic-lock +8 -1
- package/scripts/read-config +3 -3
- package/scripts/ready-set +126 -0
- package/scripts/release-check +118 -0
- package/scripts/report-screen +281 -0
- package/scripts/roadmap-graph +119 -0
- package/scripts/roadmap-savepoint +7 -0
- package/scripts/runner +397 -0
- package/scripts/savepoint-note +69 -0
- package/scripts/session-usage +56 -0
- package/scripts/spawn-preamble +9 -2
- package/scripts/validate-work-graph +39 -0
- package/scripts/verify-intent +2 -1
- package/skills/auto/SKILL.md +41 -34
- package/skills/auto/references/human-report-contract.md +136 -54
- package/skills/conventions/references/locks-and-worktrees.md +12 -0
- package/skills/dashboard/SKILL.md +13 -2
- package/skills/dashboard/templates/dashboard-global.md +1 -1
- package/skills/dashboard/templates/dashboard-project.md +2 -2
- package/skills/doctor/SKILL.md +10 -4
- package/skills/intent-continuing/SKILL.md +51 -41
- package/skills/intent-continuing/references/board-fill.md +9 -0
- package/skills/intent-continuing/references/boarding-matrix.md +6 -5
- package/skills/intent-continuing/references/context-management.md +1 -1
- package/skills/intent-ending/SKILL.md +36 -16
- package/skills/intent-executing/SKILL.md +21 -5
- package/skills/intent-executing/implementer-prompt.md +6 -1
- package/skills/intent-speccing/SKILL.md +7 -4
- package/skills/releasing/SKILL.md +39 -0
- package/skills/releasing/references/promotion-and-tagging.md +10 -6
- package/skills/releasing/references/release-lines.md +1 -1
- package/skills/roadmap/SKILL.md +26 -0
- package/skills/roadmap/references/file-format.md +10 -0
- package/templates/config.yml +3 -3
- package/templates/dashboard-screen.md +22 -0
- package/templates/display-fixture.md +21 -0
- package/templates/graph.md +16 -0
- package/templates/intent-screen.md +17 -0
- package/templates/node-decision.md +11 -0
- package/templates/node-research.md +11 -0
- package/templates/node-verify.md +13 -0
- package/templates/node-work.md +22 -0
- package/templates/outcome.md +19 -1
- package/templates/report-plan.md +15 -0
- package/templates/report-roadmap-delivered.md +10 -0
- package/templates/report-roadmap-plan.md +9 -0
- package/templates/report-roadmap-state.md +9 -0
- package/templates/report-state.md +11 -0
- package/templates/roadmap.md +13 -0
|
@@ -0,0 +1,39 @@
|
|
|
1
|
+
#!/usr/bin/env ruby
|
|
2
|
+
# encoding: UTF-8
|
|
3
|
+
# frozen_string_literal: true
|
|
4
|
+
|
|
5
|
+
# validate-work-graph - deterministic CLI over WorkGraphValidator (intent 334, n4).
|
|
6
|
+
#
|
|
7
|
+
# Checks whether one intent directory's graph.md and nodes/ form a valid work
|
|
8
|
+
# graph: needs targets resolve, node files reconcile with the declared graph,
|
|
9
|
+
# per-kind body sections are present, and (above the trivial bar) a verify
|
|
10
|
+
# node gates two or more work nodes with a failure-mode matrix per work node.
|
|
11
|
+
# Modelled on scripts/validate-intent: errors to stderr, same exit-code shape.
|
|
12
|
+
#
|
|
13
|
+
# Usage:
|
|
14
|
+
# validate-work-graph <intent_dir>
|
|
15
|
+
#
|
|
16
|
+
# Exit codes: 0 (valid), 1 (invalid or unreadable; report on stderr),
|
|
17
|
+
# 2 (usage - no argument given).
|
|
18
|
+
|
|
19
|
+
require_relative "lib/work_graph_validator"
|
|
20
|
+
|
|
21
|
+
intent_dir = ARGV.find { |a| !a.start_with?("--") }
|
|
22
|
+
|
|
23
|
+
if intent_dir.nil?
|
|
24
|
+
warn "usage: validate-work-graph <intent_dir>"
|
|
25
|
+
exit 2
|
|
26
|
+
end
|
|
27
|
+
|
|
28
|
+
dir = File.expand_path(intent_dir)
|
|
29
|
+
result = WorkGraphValidator.validate(dir)
|
|
30
|
+
|
|
31
|
+
if result[:ok]
|
|
32
|
+
puts "OK: #{dir}"
|
|
33
|
+
exit 0
|
|
34
|
+
end
|
|
35
|
+
|
|
36
|
+
warn "INVALID: #{dir}"
|
|
37
|
+
result[:missing].each { |m| warn "missing: #{m}" }
|
|
38
|
+
result[:errors].each { |e| warn e }
|
|
39
|
+
exit 1
|
package/scripts/verify-intent
CHANGED
|
@@ -15,7 +15,8 @@
|
|
|
15
15
|
# other flags exist.
|
|
16
16
|
#
|
|
17
17
|
# Checks, all run every invocation (the fourth only when --suite is given):
|
|
18
|
-
# 1. doctor - Doctor#run_intent_check(id, store: scope), fail-open on a crash
|
|
18
|
+
# 1. doctor - Doctor#run_intent_check(id, store: scope), fail-open on a crash; the doctor
|
|
19
|
+
# scan includes the intent_ticks_lag warning (intent 329)
|
|
19
20
|
# 2. em-dash - added lines only of `git diff <base>...HEAD`, never the whole tree
|
|
20
21
|
# 3. diffstat - `git diff --stat <base>...HEAD`, never a failure on its own
|
|
21
22
|
# 4. suite - the supplied --suite command, run with RUBYOPT cleared
|
package/skills/auto/SKILL.md
CHANGED
|
@@ -13,20 +13,18 @@ user-invocable: true
|
|
|
13
13
|
Announce: "Taking over intent [ID] - [name] for autonomous delivery."
|
|
14
14
|
|
|
15
15
|
**Advisory (not a rule).** At auto-mode start, recommend once that the user run this
|
|
16
|
-
orchestrating
|
|
17
|
-
|
|
18
|
-
|
|
19
|
-
|
|
20
|
-
|
|
21
|
-
deliberately; the auto pipeline never dispatches them.
|
|
16
|
+
orchestrating session on the best available thinking model (Fable, Opus, or whatever supersedes
|
|
17
|
+
them); this is advice only, and dispatched agents keep their configured model, never resolving
|
|
18
|
+
to Fable without an explicit `agents.models.<name>` config override. `plastic-advisor` and
|
|
19
|
+
`plastic-faux-advisor` are consultation roles the user or this session summons deliberately;
|
|
20
|
+
the auto pipeline never dispatches them.
|
|
22
21
|
|
|
23
22
|
## Precondition
|
|
24
23
|
|
|
25
24
|
An active intent MUST exist in INDEX.md. If none exists, refuse: "No active intent found.
|
|
26
25
|
Create one first with /plastic-intent-creating."
|
|
27
26
|
|
|
28
|
-
If several active intents exist, ask
|
|
29
|
-
at boarding, before delivery starts).
|
|
27
|
+
If several active intents exist, ask which to deliver (the one question auto asks at boarding).
|
|
30
28
|
|
|
31
29
|
**Picking work when no intent is specified.** If the user says "auto" without naming an intent
|
|
32
30
|
and none is active, consult the roadmap first (the primary planning surface), then fall back to
|
|
@@ -42,9 +40,8 @@ frontier batch is still delivering, report it and wait, never dispatch a later b
|
|
|
42
40
|
`exhausted` means fall back to `ruby ~/.plastic/scripts/dashboard.rb all --json` and work its
|
|
43
41
|
`dispatchable_queue` in `rank` order, leaving `human_only` and `next_big_thing` for the user.
|
|
44
42
|
|
|
45
|
-
QMD-first (when available): when the user describes the work
|
|
46
|
-
`ruby ~/.plastic/scripts/qmd-sync search "<terms>"`
|
|
47
|
-
authoritative intent file for the hit you take over. The command is a no-op when QMD is absent.
|
|
43
|
+
QMD-first (when available): when the user describes the work instead of naming an intent, run
|
|
44
|
+
`ruby ~/.plastic/scripts/qmd-sync search "<terms>"` first, then open the hit's authoritative intent file; a no-op when QMD is absent.
|
|
48
45
|
|
|
49
46
|
## Take the intent (do this FIRST)
|
|
50
47
|
|
|
@@ -67,8 +64,9 @@ Replace `<STORE>` (`~/.plastic/projects/<slug>/store` or `~/.plastic/store`) and
|
|
|
67
64
|
nonblank `CLAUDE_CODE_SESSION_ID` as Claude, otherwise passes no identity and the verb keys the
|
|
68
65
|
lock by a derived session key. Never guess identity from an absent runtime variable; an
|
|
69
66
|
unknown harness or thread stays unknown. Exit 1 means the lock is held, stale, excluded, or
|
|
70
|
-
corrupt
|
|
71
|
-
|
|
67
|
+
corrupt - or `inline_refused`: a conversation session may not arm an intent at all (owner rule
|
|
68
|
+
2026-08-31); dispatch the delivery team instead. `--allow-inline` exists only for an explicit
|
|
69
|
+
owner override. Do not proceed as the owner after an exit 1.
|
|
72
70
|
|
|
73
71
|
Read `../plastic-conventions/references/locks-and-worktrees.md` for what the lock and the
|
|
74
72
|
worktree mean and the station table behind them. Code edits happen only inside the worktree.
|
|
@@ -89,6 +87,12 @@ tier and no stage agent; depth follows the work.
|
|
|
89
87
|
Two boots is the normal delivery; the third is the exception the risk rule names. The lead is
|
|
90
88
|
this session (the `plastic-enforcer` role), never a dispatched agent.
|
|
91
89
|
|
|
90
|
+
A lead is a choice, not a requirement (D8, 355). `runner step` computes the plan and prints a
|
|
91
|
+
spawn block per node - agent, model, packet path, the test command, the call cap - fenced for a
|
|
92
|
+
session to paste into the Agent tool; the runner never spawns (327 D42). A lead earns its keep
|
|
93
|
+
on a graph carrying a decision node, weighing its `needs_decision` stop; a graph with none runs
|
|
94
|
+
end to end from `runner step` alone.
|
|
95
|
+
|
|
92
96
|
## Team
|
|
93
97
|
|
|
94
98
|
- **plastic-enforcer**: this session. Writes the Why and How record, dispatches, folds reviews,
|
|
@@ -147,13 +151,10 @@ each one as a delegate before (or when) it needs to write into the intent dir:
|
|
|
147
151
|
|
|
148
152
|
Only the owner can delegate. Delegates cannot re-delegate or release.
|
|
149
153
|
|
|
150
|
-
Headless note: in a headless or background run the session id may be unset; the arm verb then
|
|
151
|
-
|
|
152
|
-
written path. Verify the lock with `plastic-lock status` rather than assuming.
|
|
154
|
+
Headless note: in a headless or background run the session id may be unset; the arm verb then keys the lock by a derived key and the record hook still writes the ledger.
|
|
155
|
+
Verify with `plastic-lock status` rather than assuming.
|
|
153
156
|
|
|
154
|
-
Solo fallback: on a harness with no agent dispatch (Codex CLI today), this session walks the
|
|
155
|
-
five steps itself: it still writes the matrix, still writes the tests first, and reviews its own
|
|
156
|
-
plan against the matrix before code, saying so in `## Insights`.
|
|
157
|
+
Solo fallback: on a harness with no agent dispatch (Codex CLI today), this session walks the five steps itself, still writing the matrix and the tests first and reviewing its own plan against the matrix before code, saying so in `## Insights`.
|
|
157
158
|
|
|
158
159
|
## Stage-Aware Entry
|
|
159
160
|
|
|
@@ -168,6 +169,7 @@ ledger is missing (then rebuild it with `Savepoint.rebuild_savepoint`).
|
|
|
168
169
|
| `How plan.md created` / `How checklist.md created` / `Exec started` | Exec (verify plan, matrix, checklist) |
|
|
169
170
|
| `Exec outcome.md created` | Exec done; complete the intent |
|
|
170
171
|
| `Done delivered|abandoned` | Terminal; do not resume |
|
|
172
|
+
| A node or `Intent` transition line (`n1 running ...`, `Intent needs_decision ...`) | Exec; a graph delivery is in progress - drive it through `scripts/runner`'s three public verbs, `step` (one turn of the dispatch loop), `status` (renders ledger state, safe to poll constantly), and `answer` (closes a `needs_decision` node) - read node status through `NodeLedger.status` before dispatching anything, never re-derive it by eye |
|
|
171
173
|
|
|
172
174
|
Filesystem fallback, in order: `checklist.md` with items checked means resume Exec from the
|
|
173
175
|
first unchecked item; `plan.md` plus `checklist.md` means enter Exec; `spec.md` alone means
|
|
@@ -183,9 +185,7 @@ Announce which stage you are entering and why.
|
|
|
183
185
|
3. Decide: pick the best option per gap, record it in `## Context > ### Decisions` with the
|
|
184
186
|
rationale, and log it in `## Insights` with the `(autonomous)` marker through
|
|
185
187
|
`scripts/insight-append`.
|
|
186
|
-
4. Write `spec.md`.
|
|
187
|
-
|
|
188
|
-
Then How.
|
|
188
|
+
4. Write `spec.md`. Then How.
|
|
189
189
|
|
|
190
190
|
## How (the lead), then the plan review
|
|
191
191
|
|
|
@@ -200,9 +200,9 @@ Then How.
|
|
|
200
200
|
into the spec, the matrix, and the tests; record what was dropped and why in the action
|
|
201
201
|
file's review fold. A REVISE verdict is folded and not re-reviewed unless a finding changes
|
|
202
202
|
a decision.
|
|
203
|
-
5.
|
|
204
|
-
|
|
205
|
-
|
|
203
|
+
5. Print `ruby ~/.plastic/scripts/report-screen plan <intent_dir>` as the first characters of
|
|
204
|
+
the reply, nothing before it, no fence, before dispatching the executor (see
|
|
205
|
+
`references/human-report-contract.md` for the full binding table). It informs; it does not wait.
|
|
206
206
|
|
|
207
207
|
Then Exec.
|
|
208
208
|
|
|
@@ -214,7 +214,7 @@ Then Exec.
|
|
|
214
214
|
then builds, then drives the full suite green.
|
|
215
215
|
2. Read its return by code: DONE or DONE_WITH_CONCERNS proceeds; NEEDS_CONTEXT re-dispatches
|
|
216
216
|
with the missing context; BLOCKED stops under the error procedure.
|
|
217
|
-
3. Tick the checklist as items land (the executor does this; verify
|
|
217
|
+
3. Tick the checklist as items land (the executor does this); verify tick-versus-diff against the diff. A mismatch is a review finding, not a lead cleanup.
|
|
218
218
|
|
|
219
219
|
## Review by risk (boot 3, only when a rule fires)
|
|
220
220
|
|
|
@@ -251,8 +251,9 @@ every choice is non-destructive and the team has full autonomy.
|
|
|
251
251
|
|
|
252
252
|
Read `../plastic-conventions/references/completion-and-done.md` for what "intent done" means.
|
|
253
253
|
|
|
254
|
-
1.
|
|
255
|
-
2. Write `outcome.md` from `~/.plastic/templates/outcome.md` with `disposition: delivered
|
|
254
|
+
1. This is the merge gate: verify every checklist item is checked, verify tick-versus-diff against the diff, and confirm the suite is green once on the branch.
|
|
255
|
+
2. Write `outcome.md` from `~/.plastic/templates/outcome.md` with `disposition: delivered`,
|
|
256
|
+
`## Delivered` as the labeled table whose row labels match the action-file headings (317a).
|
|
256
257
|
3. Release, if configured: match the working directory against `~/.plastic/projects.yml`, read
|
|
257
258
|
`project.yml`'s `release` block, and act on `on_complete` (`commit`, `commit_and_push`,
|
|
258
259
|
`manual`), `verify` (green proceeds; red follows `on_red`: `fix_and_retry` up to twice,
|
|
@@ -268,10 +269,16 @@ Read `../plastic-conventions/references/completion-and-done.md` for what "intent
|
|
|
268
269
|
--session "$CLAUDE_CODE_SESSION_ID" \
|
|
269
270
|
--index-note "<what shipped>; <suite result>"
|
|
270
271
|
```
|
|
271
|
-
Exit 4
|
|
272
|
-
|
|
273
|
-
|
|
274
|
-
|
|
272
|
+
Exit 4: a live foreign session holds the lock. 5: the worktree is dirty (commit first, or
|
|
273
|
+
pass `--discard-worktree-changes` deliberately). 3: the lock survived the disarm
|
|
274
|
+
(`/plastic-doctor check the lock status`). 6: the structure check refused. Never leave an
|
|
275
|
+
orphaned worktree; run `git worktree prune` on a stale reference.
|
|
276
|
+
6. Print `ruby ~/.plastic/scripts/report-screen delivered <intent_dir>` once (D15/331f), and
|
|
277
|
+
`report-screen state` at each of the five triggers in `references/human-report-contract.md`
|
|
278
|
+
(a review verdict, a blocker, a merge/release, or an owner status ask; a mid-batch ask
|
|
279
|
+
instead runs `report-screen session <tier_root> --session "$CLAUDE_CODE_SESSION_ID"`, intent
|
|
280
|
+
330). Print each as the first characters of the reply: nothing before it, no fence, or the
|
|
281
|
+
hook cannot paint it.
|
|
275
282
|
|
|
276
283
|
## Error Handling
|
|
277
284
|
|
|
@@ -284,8 +291,8 @@ leaves the project broken.
|
|
|
284
291
|
|
|
285
292
|
- Read `references/agent-architecture.md` for the team model, the risk list, the headless note,
|
|
286
293
|
and the solo fallback when dispatching or when a harness has no agent dispatch.
|
|
287
|
-
- Read `references/human-report-contract.md` for the
|
|
288
|
-
How
|
|
294
|
+
- Read `references/human-report-contract.md` for the three report screens and the five
|
|
295
|
+
triggers before printing the How or Completion screen above.
|
|
289
296
|
- Read `references/agent-report-contract.md` for the completion report format when reading a
|
|
290
297
|
dispatched agent's return or synthesizing one.
|
|
291
298
|
- Read `references/end-tail.md` for what `Arm.disarm` does at the End tail and why the reindex
|
|
@@ -1,72 +1,154 @@
|
|
|
1
|
-
# Human Report Contract (
|
|
2
|
-
|
|
3
|
-
|
|
4
|
-
|
|
5
|
-
|
|
6
|
-
|
|
7
|
-
|
|
8
|
-
|
|
9
|
-
|
|
10
|
-
|
|
11
|
-
|
|
12
|
-
|
|
13
|
-
|
|
14
|
-
|
|
15
|
-
|
|
16
|
-
|
|
17
|
-
|
|
18
|
-
|
|
19
|
-
|
|
20
|
-
|
|
21
|
-
|
|
22
|
-
|
|
23
|
-
|
|
24
|
-
-
|
|
25
|
-
|
|
26
|
-
-
|
|
27
|
-
|
|
28
|
-
|
|
29
|
-
|
|
30
|
-
|
|
31
|
-
|
|
1
|
+
# Human Report Contract (the report screens, intent 317)
|
|
2
|
+
|
|
3
|
+
D15: the prose EM-to-CTO briefing this doc used to define is retired. The orchestrator now
|
|
4
|
+
prints one of these report screens, filled from the record by `scripts/report-screen`, never
|
|
5
|
+
written by eye:
|
|
6
|
+
|
|
7
|
+
- **`report-screen plan <intent_dir>`** - the pre-delivery report (intent 331b), printed once
|
|
8
|
+
at the How boundary, before the executor is dispatched: Asked, Decisions, Steps, Mode,
|
|
9
|
+
Reviewer, then the Steps table (Step, Action, What) and the Risks table.
|
|
10
|
+
- **`report-screen state <intent_dir> [--changed "<text>"]`** - the mid-delivery report. One
|
|
11
|
+
intent's field table (Store, Status, Stage, Savepoint, Progress, Next, Insight) plus a
|
|
12
|
+
`Changed` row naming what caused the print, and its Steps table.
|
|
13
|
+
- **`report-screen state --all <store_root>`** - the roster across every in-delivery intent,
|
|
14
|
+
most recently changed first, then one collapsed block (Stage, Next, Changed, first three
|
|
15
|
+
open steps) per intent.
|
|
16
|
+
- **`report-screen delivered <intent_dir>`** - the post-delivery report, printed once at close:
|
|
17
|
+
Asked, Delivered (with a Proven-by column), Evidence, Needs you.
|
|
18
|
+
- **`report-screen delay <intent_dir>`** - printed only on request ("why did X take so long"):
|
|
19
|
+
the delivery as a timeline plus the derived `Where the time went` line.
|
|
20
|
+
- **`report-screen session <tier_root>`** - the answer to an UNNAMED status ask ("where are we
|
|
21
|
+
with delivery", "what is the status"): one `delivered` screen per intent this session
|
|
22
|
+
completed, oldest first, then the `state --all` roster. Intent 330's ruling: a status ask
|
|
23
|
+
answers with what actually shipped, not the in-flight roster alone.
|
|
24
|
+
- **`dashboard.rb continue|project <slug> --screen`** - the dashboard screen (intent 331d):
|
|
25
|
+
Active, In delivery, Delivered, Roadmap, Sessions, Changed, then the Where-we-are and
|
|
26
|
+
Where-we-go-next tables. A separate script from the other four (`dashboard.rb`, not
|
|
27
|
+
`report-screen`), since it aggregates across a whole store or project rather than one
|
|
28
|
+
intent; it prints on `continue` and on loading a project, not as a delivery trigger.
|
|
29
|
+
|
|
30
|
+
## Binding table (intent 331f)
|
|
31
|
+
|
|
32
|
+
Every skill that shows state names its own report verb, one row per skill and trigger. Each
|
|
33
|
+
bound skill's file carries the SAME rule next to its verb: print the screen as the first
|
|
34
|
+
characters of the reply, nothing before it, no fence, or the hook cannot paint it.
|
|
35
|
+
|
|
36
|
+
| Skill | Trigger | Verb |
|
|
37
|
+
|---|---|---|
|
|
38
|
+
| `plastic-intent-continuing` | project route (continue, load project) | `dashboard.rb ... --screen` |
|
|
39
|
+
| `plastic-intent-continuing` | a named intent | `report-screen state` |
|
|
40
|
+
| `plastic-intent-continuing` | "where are we" (a status ask) | `report-screen session` |
|
|
41
|
+
| `plastic-intent-continuing` | "why so long" | `report-screen delay` |
|
|
42
|
+
| `plastic-intent-continuing` | a roadmap route | `report-screen roadmap ... state` |
|
|
43
|
+
| `plastic-auto` | the How boundary, before the executor | `report-screen plan` |
|
|
44
|
+
| `plastic-auto` | each of the five triggers | `report-screen state` |
|
|
45
|
+
| `plastic-auto` | close | `report-screen delivered` |
|
|
46
|
+
| `plastic-intent-ending` | the close | `report-screen delivered` |
|
|
47
|
+
| `plastic-intent-speccing` | the action files are written | `report-screen plan` |
|
|
48
|
+
| `plastic-roadmap` | create | `report-screen roadmap ... plan` |
|
|
49
|
+
| `plastic-roadmap` | read | `report-screen roadmap ... state` |
|
|
50
|
+
| `plastic-roadmap` | close | `report-screen roadmap ... delivered` |
|
|
51
|
+
| `plastic-dashboard` | any invocation | `dashboard.rb ... --screen` |
|
|
52
|
+
| `plastic-intent-executing` | after the red commit, and after the suite | `report-screen state` |
|
|
53
|
+
|
|
54
|
+
## A roadmap's own three reports (intent 331c)
|
|
55
|
+
|
|
56
|
+
A roadmap gets the same pre-, in-, and post-delivery shape as an intent, through
|
|
57
|
+
`report-screen roadmap <roadmap.md> plan|state|delivered [--ansi] [--store-root <dir>]`:
|
|
58
|
+
|
|
59
|
+
- **`roadmap plan`** - the pre-delivery report: the Goal's first sentence, the batch (or legacy
|
|
60
|
+
wave) count and intent count, the batch order, and when the roadmap was created; then the
|
|
61
|
+
full entries table.
|
|
62
|
+
- **`roadmap state`** - the in-delivery report: Goal, a Progress bar over intents delivered of
|
|
63
|
+
intents total (never batches), the frontier batch, who is delivering it and their lead, the
|
|
64
|
+
next queued entry, and the last ledger event; then the entries table with each entry's own
|
|
65
|
+
checklist progress and lead.
|
|
66
|
+
- **`roadmap delivered`** - the post-delivery report: a meta line (closed time, or `in progress`
|
|
67
|
+
when the goal is not yet reached; intent count; duration) directly under the title, the
|
|
68
|
+
delivered table with each entry's merge sha, and the `## Log` table.
|
|
69
|
+
|
|
70
|
+
Every cell traces to the roadmap file, `INDEX.md` (which always wins on status), the roadmap's
|
|
71
|
+
own savepoint ledger, or (falling back when no ledger file exists) the roadmap's `## Log` -
|
|
72
|
+
never a second parser: `RoadmapQueue`'s own public `roadmap` reader supplies every entry.
|
|
73
|
+
|
|
74
|
+
## The five triggers for `state`
|
|
75
|
+
|
|
76
|
+
Print `state` (one intent, or `--all` for the roster) on any of these; a checklist tick alone,
|
|
77
|
+
an executor's intermediate commit, or an agent going idle is NOT one of them:
|
|
78
|
+
|
|
79
|
+
| Trigger | Scope |
|
|
80
|
+
|---|---|
|
|
81
|
+
| A savepoint line lands (a stage boundary: Why, How, Exec started, outcome written, Done) | that intent |
|
|
82
|
+
| A review verdict returns (plan review or post-execution review), naming what it changed | that intent |
|
|
83
|
+
| A blocker or needs-input is logged | that intent |
|
|
84
|
+
| A merge or a release lands | that intent |
|
|
85
|
+
| The owner asks ("where are we", "state of X", "continue X") | all in delivery, or the one named |
|
|
86
|
+
|
|
87
|
+
`delivered` prints exactly once, at Completion. `delay` prints only when the owner asks why a
|
|
88
|
+
delivery took long.
|
|
89
|
+
|
|
90
|
+
Every verb prints the same plain Markdown on every harness (owner ruling 2026-08-31); where a
|
|
91
|
+
harness can paint it (Claude Code, through 316a's message-display hook), it substitutes a
|
|
92
|
+
painted rendering of that same output, never a different one, and no skill or script branches
|
|
93
|
+
on harness name to decide.
|
|
32
94
|
|
|
33
95
|
## Depth for small work
|
|
34
96
|
|
|
35
|
-
For small work in auto mode the
|
|
36
|
-
|
|
37
|
-
|
|
38
|
-
|
|
39
|
-
|
|
40
|
-
still ends with `outcome.md` plus one owner report.
|
|
97
|
+
For small work in auto mode, only the How-boundary `plan` screen prints mid-flight (intent
|
|
98
|
+
331f moved this print off `state`, since there is no separate briefing per stage any more).
|
|
99
|
+
Larger work prints `state` at every trigger in the table above. This is a
|
|
100
|
+
depth cut, not a different report: the screen's shape never changes, only how often it fires.
|
|
101
|
+
A delivery still ends with `outcome.md` plus one `delivered` screen.
|
|
41
102
|
|
|
42
103
|
## One report per audience
|
|
43
104
|
|
|
44
|
-
A delivery produces exactly two artifacts: `outcome.md` (
|
|
45
|
-
|
|
46
|
-
|
|
47
|
-
|
|
48
|
-
|
|
105
|
+
A delivery produces exactly two artifacts: `outcome.md` (generated by `scripts/end-intent`
|
|
106
|
+
from `graph.md`, `nodes/`, and the ledger when the intent has one, intent 339; hand-authored
|
|
107
|
+
by `plastic-intent-ending` otherwise) and one `delivered` screen at the End stage. No stage or skill restates a delivery already
|
|
108
|
+
written to `outcome.md`; point at it instead. Skills do not open with a banner that names the
|
|
109
|
+
skill or restates the intent id and name the owner just typed. Announce only what the reader
|
|
110
|
+
cannot already know: an error, a result, a choice with its reason, or a handoff.
|
|
49
111
|
|
|
50
112
|
## Boundary vs intent 74
|
|
51
113
|
|
|
52
114
|
Intent 74's report contract (`references/agent-report-contract.md`) is the INTERNAL,
|
|
53
115
|
machine-checked handoff from a dispatched specialist back to the orchestrator: a structured
|
|
54
|
-
envelope plus a per-role payload. This contract is the OUTWARD
|
|
55
|
-
|
|
56
|
-
|
|
116
|
+
envelope plus a per-role payload. This contract is the OUTWARD screen shown to the owner.
|
|
117
|
+
Different direction, different audience, different form. The orchestrator reads the intent 74
|
|
118
|
+
report and reflects it into the record (savepoint, outcome.md) that `report-screen` then
|
|
119
|
+
renders. The two never merge.
|
|
57
120
|
|
|
58
121
|
## Brevity: point, don't repeat
|
|
59
122
|
|
|
60
|
-
Surface rules are owned by the `writing-style` skill. This contract does not restate them
|
|
61
|
-
|
|
62
|
-
|
|
123
|
+
Surface rules are owned by the `writing-style` skill. This contract does not restate them. Its
|
|
124
|
+
job is naming which screen prints when, not the wording inside it - `report-screen` derives
|
|
125
|
+
every cell from the record (D14), so there is no prose left to style here.
|
|
63
126
|
|
|
64
127
|
## Emission: guided vs auto
|
|
65
128
|
|
|
66
|
-
In guided mode,
|
|
67
|
-
|
|
129
|
+
In guided mode, `state` prints at each stage boundary and the human decides before the next
|
|
130
|
+
stage starts.
|
|
131
|
+
|
|
132
|
+
In auto mode, `state` prints at every trigger for larger work; for small work only the How
|
|
133
|
+
boundary's `plan` screen prints (see `## Depth for small work` above). The orchestrator takes
|
|
134
|
+
the go-ahead itself and moves on, except at the existing hard stops (destructive action without
|
|
135
|
+
a safe alternative, project-path confirm).
|
|
136
|
+
|
|
137
|
+
## Column vocabulary (D5, intent 331f)
|
|
138
|
+
|
|
139
|
+
Owner ruling 2026-09-05 11:05 UTC: "What" is never a column name, because What is a stage, not
|
|
140
|
+
a value. The id column reads `Graph ID`; the title column reads `Intent`. Every Steps table
|
|
141
|
+
reads `Step | Status | Detail` (the plan screen's own Steps table reads
|
|
142
|
+
`Step | Action | Detail`); every Risks table reads `N | Risk`; the Delivered/Evidence/Needs-you
|
|
143
|
+
tables on the `delivered` screen read `Row | Detail | Proven by`, `Kind | Detail | Source`, and
|
|
144
|
+
`N | Need | Reason`. The plan screen's Asked row prints the intent title before its first
|
|
145
|
+
colon, never the whole intent line. This applies to every screen the family prints: `state`,
|
|
146
|
+
`roster`, `session`, `delivered`, `delay`, `plan`, `roadmap` (`plan`/`state`/`delivered`), and
|
|
147
|
+
`dashboard`. `outcome.md`'s own `| Row | What |` heading is an AUTHORING convention inside the
|
|
148
|
+
file a human writes, never a rendered header, and stays unchanged.
|
|
149
|
+
|
|
150
|
+
## Width bound (D7, intent 331f)
|
|
68
151
|
|
|
69
|
-
|
|
70
|
-
|
|
71
|
-
|
|
72
|
-
the existing hard stops (destructive action without a safe alternative, project-path confirm).
|
|
152
|
+
No rendered row passes 115 visible columns. A long cell (the roadmap Goal, an intent title, an
|
|
153
|
+
Asked line) truncates on a word boundary with a single ellipsis; `ReportScreen.fit_screen`
|
|
154
|
+
shrinks a table's widest column first, floor 8, before it ever truncates a whole row.
|
|
@@ -103,3 +103,15 @@ what gets written down.
|
|
|
103
103
|
| Exec | code on the intent branch, checklist checked off | heartbeat; code edits confined to the provisioned worktree; delegates write under the owner's lock | checklist boxes; savepoint milestones; the day-ledger line promotes when a project file lands |
|
|
104
104
|
| End (done) | mandatory `outcome.md` (`disposition: delivered\|abandoned`), INDEX moves to Completed or Abandoned | ordered End tail: verify, merge and remove worktrees, disarm clears `delivery.lock`, then the pointer is purge-eligible, and the QMD reindex runs LAST (after purge); `end-intent` backfills a placeholder `outcome.md` from the record and its structure check reports (never refuses) | savepoint `Done delivered` (or `abandoned`); takeover audits, if any, remain in savepoint.md |
|
|
105
105
|
| Maintenance (Future, Terminal, or Active-with-a-stale-or-no-lock) | `revisions.md` move-and-record entries | detects (never acquires) `delivery.lock`; defers and reports while the target's lock is FRESH (`Lock.fresh?`); a stale or absent lock is not-active, maintenance proceeds | append-only, rule-tagged `revisions.md` entry written in the same operation as the change, or the change is refused; lands via a fresh branch off store main merged back as one closed op, never `git add -A` |
|
|
106
|
+
|
|
107
|
+
## The write guard is not residue
|
|
108
|
+
|
|
109
|
+
`<type>.write.lock` (usually `delivery.write.lock`) is a deliberate sibling
|
|
110
|
+
inode used only for `flock`: no owner, no timestamp, no content, and it is
|
|
111
|
+
NEVER unlinked - deleting it while a writer holds the flock hands the next
|
|
112
|
+
writer a fresh inode at the same path, so two writers hold "the" guard at
|
|
113
|
+
once (see `scripts/lib/lock.rb`, the write-guard comment). A zero-byte
|
|
114
|
+
`*.write.lock` in a completed intent directory is by design; no cleaner may
|
|
115
|
+
sweep it, and it is already inside the store's `*.lock` gitignore rule.
|
|
116
|
+
(Intent 317a, A2: a review misread it as stale residue and nearly shipped
|
|
117
|
+
the sweep.)
|
|
@@ -7,7 +7,8 @@ user-invocable: false
|
|
|
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
|
|
10
|
+
**where we are** (recently worked; `Graph ID | Intent | Stage | Progress | Lead`),
|
|
11
|
+
**where we go next** (the most-valuable next work; `Rank | Graph ID | Intent | Reason`), and
|
|
11
12
|
**how to conduct it** (a disposition per intent). The human-facing surface is **Markdown**,
|
|
12
13
|
because the user's UI renders Markdown natively but collapses raw tool-call stdout.
|
|
13
14
|
|
|
@@ -22,6 +23,16 @@ state → byte-identical payload, regardless of model. Do NOT hand-summarize int
|
|
|
22
23
|
- `plastic-intent-continuing` lands on the board on a bare resume
|
|
23
24
|
- `plastic-auto` reads `--json` to choose the next dispatchable intent
|
|
24
25
|
|
|
26
|
+
## The screen surface (intent 331d/331f)
|
|
27
|
+
|
|
28
|
+
`dashboard.rb project <slug> --screen` (or `continue --screen` for the global board) is the
|
|
29
|
+
default surface on every invocation: print it as the first characters of the reply, nothing
|
|
30
|
+
before it, no fence, or the hook cannot paint it. It carries a title, six fields (Active, In
|
|
31
|
+
delivery, Delivered, Roadmap, Sessions, Changed), then the Where-we-are and Where-we-go-next
|
|
32
|
+
tables, its own grammar and painted form standing in for the filled Markdown template below.
|
|
33
|
+
`plastic-intent-continuing`'s project route prints it this way. The Markdown board (Step 1-4
|
|
34
|
+
below) stays available as the deeper prose surface a reader can ask for.
|
|
35
|
+
|
|
25
36
|
## Procedure (the Markdown board — default human surface)
|
|
26
37
|
|
|
27
38
|
### Step 1 — Get the data payload
|
|
@@ -70,7 +81,7 @@ Fill mechanically, no rewriting, no re-sorting:
|
|
|
70
81
|
re-truncate, or reword them. Never emit `<br>`.
|
|
71
82
|
- `next_work` → `| {id} | {what} | {value} | {disposition} | {flags_label} |`
|
|
72
83
|
- `active` → `| {id} | {what} | {stage} | {worker} | {activity} |`
|
|
73
|
-
Empty list → one full-width row with `_(none)_` in the
|
|
84
|
+
Empty list → one full-width row with `_(none)_` in the Graph ID column and every other cell blank,
|
|
74
85
|
matching that table's column count (e.g. `| _(none)_ | | | | |` for the 5-column next_work
|
|
75
86
|
table, `| _(none)_ | | | |` for the 5-column active table). Neither list carries an overflow
|
|
76
87
|
"+N more" row anymore (D5, intent 202): the true pool size rides on the payload as
|
|
@@ -4,13 +4,13 @@
|
|
|
4
4
|
|
|
5
5
|
**Active**
|
|
6
6
|
|
|
7
|
-
|
|
|
7
|
+
| Graph ID | Intent | Stage | Worker | Activity |
|
|
8
8
|
| --- | --- | --- | --- | --- |
|
|
9
9
|
{{active.rows}}
|
|
10
10
|
|
|
11
11
|
**Most-valuable next work**
|
|
12
12
|
|
|
13
|
-
|
|
|
13
|
+
| Graph ID | Intent | Value | Disposition | Flags |
|
|
14
14
|
| --- | --- | --- | --- | --- |
|
|
15
15
|
{{next_work.rows}}
|
|
16
16
|
|
package/skills/doctor/SKILL.md
CHANGED
|
@@ -78,10 +78,15 @@ project alone.
|
|
|
78
78
|
Runs the install-wide surface: agent registration, core files (including config-honoring
|
|
79
79
|
drift), manifest sync is core-only and not part of this run, deprecation checks, config-ask
|
|
80
80
|
checks, install-integrity checks, skill-lint (advisory), QMD reachability (unscoped, every
|
|
81
|
-
collection),
|
|
82
|
-
|
|
83
|
-
|
|
84
|
-
|
|
81
|
+
collection), the global store's own conventions/done-signals content, and the `display`
|
|
82
|
+
category (intent 331e): `display_hook_registered` (also runs at `--core`), `display_hook_paints`
|
|
83
|
+
(replays the shipped display fixture through the installed MessageDisplay hook and expects a
|
|
84
|
+
painted screen back, a pass when a known defeater like `NO_COLOR` is active, never a fail),
|
|
85
|
+
`display_not_defeated` (warns per active defeater and always names the undetectable verbose
|
|
86
|
+
transcript view), and `display_surfaces_documented` (the harness-adapters doc still names every
|
|
87
|
+
surface class). **Never carries a per-project finding**; that is `--store <slug>`'s job (see
|
|
88
|
+
above). This is what `/plastic-doctor` invokes, and it also runs automatically after every
|
|
89
|
+
`plastic-update` (informational, does not block or revert the update).
|
|
85
90
|
|
|
86
91
|
## When to Use
|
|
87
92
|
|
|
@@ -167,6 +172,7 @@ Use the `fix_hint` value to determine the correct action:
|
|
|
167
172
|
| "Remove each listed .tmp/<session>/ directory after confirming that session is gone" | For each listed directory, confirm no live session uses it (a live session rewrites its heartbeat on every prompt and edit), then remove that directory by hand; never remove an unlisted one |
|
|
168
173
|
| "For a day directory missing its <day>.md, run `file-session-intent --day <day> ...`" | Run `ruby ~/.plastic/scripts/file-session-intent --day <day> --carry-to <today> --store <store>` for the named day; rename or remove an entry that is not a `YYYYMMDD` day directory |
|
|
169
174
|
| "Run scripts/project-links ... PRESERVES ... --drop-unbacked-links" | Run `ruby ~/.plastic/scripts/maintenance-run --tool project-links --intent <id> --apply` for the one flagged id (never run bare `project-links` against a real store outside the rare owner-approved batch exception, D2) |
|
|
175
|
+
| "Re-run the Plastic installer to repair the hook registration ... (plastic-install --repair)" (`display_hook_registered`) | Run `npx -y @zalom/plastic@<channel> install --reinstall --claude` (the `plastic-install` skill's repair mode), then re-run doctor |
|
|
170
176
|
|
|
171
177
|
For fixes the agent cannot handle automatically, explain what the user needs
|
|
172
178
|
to do manually. The `revisions.md` remedy is curator-applied (a move-and-record
|