@zalom/plastic 2.0.0-alpha.2 → 2.0.0-alpha.20

This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
Files changed (117) hide show
  1. package/agents/plastic-enforcer.md +3 -1
  2. package/agents/plastic-executor.md +9 -3
  3. package/hooks/hooks.json +12 -0
  4. package/hooks/message-display +134 -0
  5. package/hooks/statusline +4 -27
  6. package/package.json +2 -2
  7. package/scripts/agent-report +8 -2
  8. package/scripts/dashboard.rb +297 -18
  9. package/scripts/doctor.rb +652 -5
  10. package/scripts/end-intent +219 -0
  11. package/scripts/hook-capture +25 -113
  12. package/scripts/hook-message-display +81 -0
  13. package/scripts/hook-record +12 -4
  14. package/scripts/hook-session-start +23 -1
  15. package/scripts/index-projection +74 -0
  16. package/scripts/intent-screen +77 -0
  17. package/scripts/lib/action_graph_shim.rb +277 -0
  18. package/scripts/lib/arm.rb +26 -1
  19. package/scripts/lib/atomic_write.rb +31 -0
  20. package/scripts/lib/core_integrity.rb +71 -0
  21. package/scripts/lib/dashboard_screen.rb +40 -0
  22. package/scripts/lib/day_summary.rb +7 -2
  23. package/scripts/lib/doctor_core.rb +101 -5
  24. package/scripts/lib/doctor_session_ledger.rb +52 -0
  25. package/scripts/lib/graph_edges.rb +121 -0
  26. package/scripts/lib/graph_file.rb +246 -0
  27. package/scripts/lib/graph_tree.rb +98 -0
  28. package/scripts/lib/guarded_append.rb +155 -0
  29. package/scripts/lib/hook_registry.rb +14 -0
  30. package/scripts/lib/hook_replay.rb +211 -0
  31. package/scripts/lib/index_projection.rb +201 -0
  32. package/scripts/lib/installer_core.rb +131 -4
  33. package/scripts/lib/intent_screen.rb +309 -0
  34. package/scripts/lib/intent_screen_ansi.rb +262 -0
  35. package/scripts/lib/message_display.rb +586 -0
  36. package/scripts/lib/node_file.rb +214 -0
  37. package/scripts/lib/node_ids.rb +99 -0
  38. package/scripts/lib/node_ledger.rb +377 -0
  39. package/scripts/lib/node_packet.rb +886 -0
  40. package/scripts/lib/node_return.rb +199 -0
  41. package/scripts/lib/node_worktree.rb +337 -0
  42. package/scripts/lib/outcome_report.rb +440 -0
  43. package/scripts/lib/packet_wrapper.rb +132 -0
  44. package/scripts/lib/ready_set.rb +462 -0
  45. package/scripts/lib/release_guard.rb +16 -0
  46. package/scripts/lib/report_screen.rb +1967 -0
  47. package/scripts/lib/roadmap_graph.rb +210 -0
  48. package/scripts/lib/roadmap_migration.rb +95 -0
  49. package/scripts/lib/roadmap_queue.rb +155 -5
  50. package/scripts/lib/roadmap_render.rb +150 -0
  51. package/scripts/lib/roadmap_savepoint.rb +62 -12
  52. package/scripts/lib/runner_absorb.rb +620 -0
  53. package/scripts/lib/runner_answer.rb +206 -0
  54. package/scripts/lib/runner_core.rb +194 -0
  55. package/scripts/lib/runner_dispatch.rb +482 -0
  56. package/scripts/lib/runner_policy.rb +142 -0
  57. package/scripts/lib/runner_proposals.rb +254 -0
  58. package/scripts/lib/runner_rewind.rb +201 -0
  59. package/scripts/lib/runner_sweep.rb +231 -0
  60. package/scripts/lib/savepoint.rb +149 -12
  61. package/scripts/lib/screen_paint.rb +555 -0
  62. package/scripts/lib/screens/dashboard.rb +20 -0
  63. package/scripts/lib/screens/plan.rb +18 -0
  64. package/scripts/lib/screens/roadmap.rb +15 -0
  65. package/scripts/lib/session_git.rb +49 -18
  66. package/scripts/lib/session_ledger.rb +128 -0
  67. package/scripts/lib/verify_intent.rb +33 -0
  68. package/scripts/lib/work_graph_validator.rb +201 -0
  69. package/scripts/node-packet +92 -0
  70. package/scripts/node-transition +291 -0
  71. package/scripts/outcome-report +74 -0
  72. package/scripts/plastic-lock +8 -1
  73. package/scripts/ready-set +126 -0
  74. package/scripts/release-check +118 -0
  75. package/scripts/report-screen +281 -0
  76. package/scripts/roadmap-graph +119 -0
  77. package/scripts/roadmap-savepoint +7 -0
  78. package/scripts/runner +392 -0
  79. package/scripts/savepoint-note +69 -0
  80. package/scripts/spawn-preamble +9 -2
  81. package/scripts/validate-work-graph +39 -0
  82. package/scripts/verify-intent +2 -1
  83. package/skills/auto/SKILL.md +24 -17
  84. package/skills/auto/references/human-report-contract.md +136 -54
  85. package/skills/conventions/references/locks-and-worktrees.md +12 -0
  86. package/skills/dashboard/SKILL.md +13 -2
  87. package/skills/dashboard/templates/dashboard-global.md +1 -1
  88. package/skills/dashboard/templates/dashboard-project.md +2 -2
  89. package/skills/doctor/SKILL.md +10 -4
  90. package/skills/intent-continuing/SKILL.md +51 -41
  91. package/skills/intent-continuing/references/board-fill.md +9 -0
  92. package/skills/intent-continuing/references/boarding-matrix.md +6 -5
  93. package/skills/intent-continuing/references/context-management.md +1 -1
  94. package/skills/intent-ending/SKILL.md +36 -16
  95. package/skills/intent-executing/SKILL.md +17 -5
  96. package/skills/intent-executing/implementer-prompt.md +6 -1
  97. package/skills/intent-speccing/SKILL.md +7 -4
  98. package/skills/releasing/SKILL.md +39 -0
  99. package/skills/releasing/references/promotion-and-tagging.md +10 -6
  100. package/skills/releasing/references/release-lines.md +1 -1
  101. package/skills/roadmap/SKILL.md +26 -0
  102. package/skills/roadmap/references/file-format.md +10 -0
  103. package/templates/dashboard-screen.md +22 -0
  104. package/templates/display-fixture.md +21 -0
  105. package/templates/graph.md +16 -0
  106. package/templates/intent-screen.md +17 -0
  107. package/templates/node-decision.md +11 -0
  108. package/templates/node-research.md +11 -0
  109. package/templates/node-verify.md +13 -0
  110. package/templates/node-work.md +22 -0
  111. package/templates/outcome.md +19 -1
  112. package/templates/report-plan.md +15 -0
  113. package/templates/report-roadmap-delivered.md +10 -0
  114. package/templates/report-roadmap-plan.md +9 -0
  115. package/templates/report-roadmap-state.md +9 -0
  116. package/templates/report-state.md +11 -0
  117. package/templates/roadmap.md +13 -0
@@ -1,72 +1,154 @@
1
- # Human Report Contract (per-stage EM-to-CTO briefing)
2
-
3
- This doc defines how the orchestrator briefs the human at each of the five stage boundaries
4
- (What, Why, How, Exec, Done) in auto mode; for small work only the How boundary fires (see
5
- `## Depth for small work`). It is the outward, human-facing counterpart to the
6
- internal report contract in `references/agent-report-contract.md`. Voice: an engineering
7
- manager briefing a CTO. Lead with impact, name the risk, leave the decision.
8
-
9
- ## The skeleton
10
-
11
- One fixed 3-line shape, reused at every stage:
12
-
13
- 1. **State**: what happened and what it means, impact first, one line.
14
- 2. **Risk**: the one thing that could bite, or "nothing flagged."
15
- 3. **Call**: the decision left to you, or the go-ahead I am taking.
16
-
17
- This is a shape, not a rigid template. Keep the order (State, then Risk, then Call) and keep it
18
- short. The words can flex to fit the stage.
19
-
20
- ## Per-stage content
21
-
22
- - **What**: State = the work I picked up and why it matters now. Risk = scope uncertainty.
23
- Call = confirm this is worth doing, or I proceed.
24
- - **Why**: State = the approach I chose, one line. Risk = the main trade-off. Call = the one
25
- decision I need (approve, or pick an option).
26
- - **How**: State = the plan shape (task count and what it builds). Risk = the riskiest task or
27
- dependency. Call = approve the plan to build.
28
- - **Exec**: State = what got built and the test result. Risk = residual failures or deviations.
29
- Call = go to review, or done.
30
- - **Done**: State = the delivered impact. Risk = residual risk. Call = the decision left to you
31
- (merge, release, accept).
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 mid-flight briefings collapse to one. Only the How briefing fires, and
36
- it folds in what the What and Why briefings would have said: the work picked up and the approach
37
- chosen go into its State line. The Exec briefing folds into the final owner report at End. Larger
38
- work sends all four. The shape does not change: still State, then Risk, then Call, and the per-stage
39
- content above still says what each line covers. This is a depth cut, not a new report. A delivery
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` (authored by `plastic-intent-ending`)
45
- and one EM-to-CTO owner report at the End stage. No stage or skill restates a delivery
46
- already written to `outcome.md`; point at it instead. Skills do not open with a banner that
47
- names the skill or restates the intent id and name the owner just typed. Announce only what
48
- the reader cannot already know: an error, a result, a choice with its reason, or a handoff.
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 human briefing, orchestrator to
55
- user, in prose. Different direction, different audience, different form. The orchestrator
56
- CONSUMES the intent 74 report to WRITE the human briefing defined here. The two never merge.
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, in full
61
- or in summary. It defines the report's shape only: what to say, in what order, and when to stop.
62
- Apply the `writing-style` skill for the wording.
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, the briefing lands at each stage boundary and the human acts on the Call line
67
- before the next stage starts.
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
- In auto mode, for larger work the orchestrator still emits the briefing at each boundary, as a
70
- running EM-to-CTO account. For small work only the How briefing fires; see `## Depth for small work` above for what it
71
- folds in. The Call line becomes the go-ahead the orchestrator takes itself and moves on, except at
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), **where we go next** (the most-valuable next work), and
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 Id column and every other cell blank,
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
@@ -11,7 +11,7 @@
11
11
 
12
12
  ## Most-valuable next work
13
13
 
14
- | Id | What | Value | Disposition | Flags |
14
+ | Graph ID | Intent | Value | Disposition | Flags |
15
15
  | --- | --- | --- | --- | --- |
16
16
  {{next_work.rows}}
17
17
 
@@ -4,13 +4,13 @@
4
4
 
5
5
  **Active**
6
6
 
7
- | Id | What | Stage | Worker | Activity |
7
+ | Graph ID | Intent | Stage | Worker | Activity |
8
8
  | --- | --- | --- | --- | --- |
9
9
  {{active.rows}}
10
10
 
11
11
  **Most-valuable next work**
12
12
 
13
- | Id | What | Value | Disposition | Flags |
13
+ | Graph ID | Intent | Value | Disposition | Flags |
14
14
  | --- | --- | --- | --- | --- |
15
15
  {{next_work.rows}}
16
16
 
@@ -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), and the global store's own conventions/done-signals content. **Never carries a
82
- per-project finding**; that is `--store <slug>`'s job (see above). This is what
83
- `/plastic-doctor` invokes, and it also runs automatically after every `plastic-update`
84
- (informational, does not block or revert the update).
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
@@ -5,7 +5,7 @@ description: >-
5
5
  where we left off", "where was I", "what should I work on", names a specific intent to
6
6
  resume (by id or description, or `--intent {id}`), or names a roadmap or delivery batch to
7
7
  resume (`--roadmap {slug}`, "where is the roadmap", "where did that batch land"). Presents
8
- state and resumes at the last delivered station; it never asks auto or guided, never boots
8
+ state and resumes at the last delivered stage; it never asks auto or guided, never boots
9
9
  (the SessionStart hook owns boot), and never drives work autonomously (plastic-auto does).
10
10
  Absorbs the former continuing, project-continuing, and roadmap-continuing skills and the
11
11
  read half of the former intent-starting skill (intent 304).
@@ -45,32 +45,29 @@ specific intent or roadmap named.").
45
45
 
46
46
  ## Project route: land on the board
47
47
 
48
- Land on the Markdown board through the `plastic-dashboard` skill; rendering belongs there.
49
- Run the data payload and fill the matching template:
50
- - project loaded: `ruby ~/.plastic/scripts/dashboard.rb project <slug> --data`
51
- - otherwise (the global fallback): `ruby ~/.plastic/scripts/dashboard.rb continue --data`
52
-
53
- Fill the template from `plastic-dashboard`'s `templates/` and present the filled Markdown in
54
- your reply, every time: tool-call stdout and hook context are invisible to the user. Read
55
- `references/board-fill.md` for the fill mechanics and the store-health line when filling the
56
- board. The board load runs the scoped store check (`doctor --store <scope>`); its result
57
- arrives in the payload as `store_health` and is shown as one line of data, never a blocker.
58
-
59
- Priority order on the board: active intents first, then project context (governing plus
60
- tactical intents in a registered project), then stale future intents for triage, then fresh
61
- future intents as next work. A future intent older than `stale_threshold_days` (default 3) is
62
- surfaced for triage without action: activate, abandon, or leave. Activating moves it to
48
+ Print `ruby ~/.plastic/scripts/dashboard.rb project <slug> --screen` (or `continue --screen`
49
+ for the global fallback) as the first characters of the reply: nothing before it, no fence, or
50
+ the hook cannot paint it (intent 331d/331f). It carries a title, six fields (Active, In
51
+ delivery, Delivered, Roadmap, Sessions, Changed), then the Where-we-are and Where-we-go-next
52
+ tables. The board load runs the scoped store check (`doctor --store <scope>`); its result
53
+ rides in the payload as `store_health` and prints as one line of data, never a blocker.
54
+
55
+ Priority order on the underlying data: active intents first, then project context (governing
56
+ plus tactical intents in a registered project), then stale future intents for triage, then
57
+ fresh future intents as next work. A future intent older than `stale_threshold_days` (default
58
+ 3) is surfaced for triage without action: activate, abandon, or leave. Activating moves it to
63
59
  `## Active` in `INDEX.md` and auto-commits. The board's ranked next-work order is computed by
64
60
  `dashboard.rb`; cite the rule names only (Effort, Value, Flags, Override, Caps) and read
65
61
  `plastic-dashboard`'s `references/classification.md` for their definitions.
66
62
 
67
63
  When the tier root (the directory holding `INDEX.md`) has a mid-flight roadmap
68
64
  (`ruby ~/.plastic/scripts/roadmap-next --roadmaps-dir <root>/roadmaps` reports a `state`
69
- other than `none`), say so in one line and offer the roadmap route; the board still presents
65
+ other than `none`), say so in one line and offer the roadmap route; the screen still presents
70
66
  project state and stops.
71
67
 
72
68
  Then stop: "here is the state, what next?". Do not start executing work. When the user names
73
- an intent, take the intent route.
69
+ an intent, take the intent route. Read `references/board-fill.md` only when the reader asks
70
+ for the deeper prose board (`plastic-dashboard`'s Markdown surface still exists for that ask).
74
71
 
75
72
  ## Intent route: resume one intent from its ledger
76
73
 
@@ -79,19 +76,20 @@ QMD-first when the intent is named by description: run
79
76
  authoritative intent file. The command is a no-op when QMD is absent; fall back to
80
77
  `INDEX.md`.
81
78
 
82
- If the intent is terminal (`## Completed` or `## Abandoned` in `INDEX.md`): report only.
83
- Summarize its `outcome.md` and ask what is next; never reopen it.
79
+ If the intent is terminal (`## Completed` or `## Abandoned` in `INDEX.md`): print the
80
+ intent screen (Status shows the terminal section, Next is empty), summarize its
81
+ `outcome.md`, and ask what is next; never reopen it.
84
82
 
85
83
  For a live intent's directory:
86
84
 
87
85
  1. **Read `savepoint.md` first.** It is a deterministic, append-only ledger, one line per
88
- event, newest at the bottom: `{utc-iso8601} {Stage} {milestone}`. Classify the station
86
+ event, newest at the bottom: `{utc-iso8601} {Stage} {milestone}`. Classify the stage
89
87
  from the last line alone (the table in `references/boarding-matrix.md`, read when
90
88
  classifying), then verify only that line's artifact is real (sentinel-aware:
91
89
  `Savepoint.stage_file_present?`). Do not re-probe every lifecycle file.
92
- 2. **Drift.** When the last line disagrees with the files on disk, rebuild the ledger from
90
+ 2. **Stale ledger.** When the last line disagrees with the files on disk, rebuild the ledger from
93
91
  disk and note the correction. A rebuilt ledger is the file-landing skeleton, which still
94
- pins the station:
92
+ pins the stage:
95
93
  ```bash
96
94
  ruby -r ~/.plastic/scripts/lib/savepoint -e 'Savepoint.rebuild_savepoint("<intent_dir>")'
97
95
  ```
@@ -99,21 +97,32 @@ For a live intent's directory:
99
97
  else the newest prior day) is the prior session's own account of where things stand; read
100
98
  it after the ledger, never instead of it.
101
99
  4. **Derive the next step:** the first unchecked item in `checklist.md` when it exists, else
102
- the next thing the station needs (see the matrix). The newest `## Insights` entry supplies
100
+ the next thing the stage needs (see the matrix). The newest `## Insights` entry supplies
103
101
  the human-readable context; an entry marked `(autonomous)` means an auto team was
104
102
  delivering it, so say so and offer to hand back to `plastic-auto`.
105
- 5. **Announce, then continue at that station:**
106
- ```
107
- Resuming intent [ID] - [name]
108
- Store: [global | project:<slug>]
109
- Station: [from the ledger's last line]
110
- Next step: [first unchecked checklist item | what the station needs]
111
- Context: [newest ## Insights entry | hand-off summary]
112
- Drift: [none | ledger rebuilt from disk]
113
- ```
114
- Then continue the work in the session's current mode. In auto mode the running team
115
- already holds the delivery lock; if a lock is held by a session that is gone, the
116
- `plastic-doctor` skill's lock section repairs or reclaims it.
103
+ 5. **Print the report screen as the first thing in the reply, then continue at that stage.**
104
+ The screen must open the message with nothing before it. On Claude Code, a fail-open
105
+ `MessageDisplay` hook recognizes a reply that opens this way and substitutes a styled ANSI
106
+ rendering for it there; the transcript and every other harness keep exactly this plain
107
+ form. For "where are we" on one named intent, run
108
+ `ruby ~/.plastic/scripts/report-screen state <intent_dir>` and print its output as it is:
109
+ the title, the field table, the `Changed` row, and the Steps table come from the record,
110
+ never by eye. For "where are we" with no intent named, run
111
+ `ruby ~/.plastic/scripts/report-screen session <tier_root> --session <this session's id>`
112
+ (intent 330; pass the id your harness gives you, or the screen widens to the whole day and
113
+ says so): it prints one
114
+ `delivered` screen per intent this session actually completed, oldest first, then the same
115
+ roster `report-screen state --all <store_root>` prints on its own - `state --all` stays the
116
+ right call when only the in-flight roster is wanted, with nothing delivered above it. Route
117
+ "why did X take so long" to `ruby ~/.plastic/scripts/report-screen delay <intent_dir>`
118
+ instead - every verb prints the same plain screen on any harness, painted only where the
119
+ harness supports it, with no branching on harness name. Under the `state` screen
120
+ write **What this means** as two to four bullets in plain words (what the intent is for,
121
+ what has landed, what is left, any defect named by step), then close with **needs input:**
122
+ naming the first open step. Then continue the work in the
123
+ session's current mode. In auto mode the running team already holds the delivery lock; if a
124
+ lock is held by a session that is gone, the `plastic-doctor` skill's lock section repairs or
125
+ reclaims it.
117
126
 
118
127
  ## Roadmap route: resume the mid-flight roadmap
119
128
 
@@ -127,10 +136,11 @@ For a live intent's directory:
127
136
  `delivering` or `blocked` entry wins, else the newest ledger or `## Log` timestamp.
128
137
  `roadmaps/<slug>.savepoint.md` is a derived signal read here, never a status field;
129
138
  `INDEX.md` stays the sole status writer.
130
- 2. **Present state:** the roadmap's `## Goal`, the current batch with each entry's mirrored
131
- status, the ledger's newest line beside the newest `## Log` line. Read
132
- `../plastic-conventions/references/roadmaps.md` for the file format and the status-mirror
133
- rule when a roadmap file needs interpreting.
139
+ 2. **Print state.** Print `ruby ~/.plastic/scripts/report-screen roadmap <roadmap.md> state` as
140
+ the first characters of the reply: nothing before it, no fence, or the hook cannot paint it.
141
+ It carries Goal, Progress, Frontier, Delivering, Next, and Changed, then the entries table -
142
+ never hand-typed. Read `../plastic-conventions/references/roadmaps.md` for the file format
143
+ and the status-mirror rule when a roadmap file needs interpreting.
134
144
  3. Then continue with the next dispatchable entry in the session's mode: direct work on it,
135
145
  or `plastic-auto` when the owner says auto. The coordinator that drives a batch appends
136
146
  to `roadmaps/<slug>.savepoint.md` at its dispatch, merge, park, and handoff points with
@@ -141,6 +151,6 @@ For a live intent's directory:
141
151
  | Trigger | Read |
142
152
  |---|---|
143
153
  | Filling the board on the project route | `references/board-fill.md` |
144
- | Classifying the station from the ledger's last line | `references/boarding-matrix.md` |
154
+ | Classifying the stage from the ledger's last line | `references/boarding-matrix.md` |
145
155
  | Explaining why one roadmap ranked above another | `references/liveness-ranking.md` |
146
156
  | Saving or restoring context across a long session, or debugging a resume | `references/context-management.md` |
@@ -41,3 +41,12 @@ The project route's default target is the project board. When no project is load
41
41
  case where this route is reached without a registered project in scope), fall back to the
42
42
  global board payload (`dashboard.rb continue --data`) rather than failing. This mirrors the
43
43
  router's D6 default: a bare "continue" always lands somewhere useful.
44
+
45
+ ## The screen surface (intent 331d)
46
+
47
+ `dashboard.rb project <slug> --screen` (or `continue --screen`) prints the identical state -
48
+ Active, In delivery, Delivered, Roadmap, Sessions, Changed, then the Where-we-are and
49
+ Where-we-go-next tables - as a screen with its own grammar instead of a filled Markdown
50
+ template. It replaces this fill mechanism once intent 331f wires the project route to print
51
+ it first, the way the intent route already prints the intent screen first today; until then,
52
+ this page's fill rules stay the route's own surface.
@@ -1,8 +1,8 @@
1
- # Boarding matrix: which station a resume lands at
1
+ # Boarding matrix: which stage a resume lands at
2
2
 
3
- The station is derived from `savepoint.md`'s last line plus the real artifacts on disk.
3
+ The stage is derived from `savepoint.md`'s last line plus the real artifacts on disk.
4
4
  Classify from the last line alone, then verify only that line's artifact is real
5
- (sentinel-aware). On drift, rebuild the ledger from disk and note it.
5
+ (sentinel-aware). When the ledger is stale, rebuild it from disk and note it.
6
6
 
7
7
  | savepoint last line | latest delivered | lands at | continue with |
8
8
  |---|---|---|---|
@@ -10,11 +10,12 @@ Classify from the last line alone, then verify only that line's artifact is real
10
10
  | `Why started` (spec still sentinel) | What | **Why** | continue the conversation; rulings land as insights |
11
11
  | `Why spec.md created` | Why | **How** | the action files, `plan.md`, `checklist.md` |
12
12
  | `How started` / `How plan.md created` | (How in progress) | **How** | finish `plan.md` and `checklist.md` |
13
- | `How checklist.md created` / `Exec started` | How | **Exec** | do the work, tick the checklist |
13
+ | `How checklist.md created` / `Exec started` | How | **Exec** | do the work, check off the checklist |
14
14
  | `Exec outcome.md created` | Exec | **ready to complete** | the ending procedure (`plastic-intent-ending`) |
15
15
  | `Done delivered` / `Done abandoned` | terminal | **report only** | immutable; ask what is next |
16
+ | A node or `Intent` transition line (`n1 running ...`, `Intent needs_decision ...`) | Exec | **Exec** | a graph delivery is in progress; read node status through `NodeLedger.status`, never re-derive it by eye |
16
17
 
17
- ## Per-station behaviour (what "continue" means)
18
+ ## Per-stage behaviour (what "continue" means)
18
19
 
19
20
  - **Why**: continue the conversation, or run the work directly when the request is already
20
21
  clear; every ruling is recorded as it lands.
@@ -19,7 +19,7 @@ step looks stale):
19
19
  (see `SKILL.md`'s `## Conditional Ledger-Resume` for the full state table).
20
20
  2. Confirm the artifact that line implies (`plan.md`, `checklist.md`, `outcome.md`, ...) is
21
21
  present and non-empty on disk.
22
- 3. If the two disagree, the ledger has drifted: rebuild it rather than hand-editing:
22
+ 3. If the two disagree, the ledger is stale: rebuild it rather than hand-editing:
23
23
  `ruby -r ~/.plastic/scripts/lib/savepoint -e 'Savepoint.rebuild_savepoint("<intent_dir>")'`
24
24
  4. Re-read the rebuilt last line and re-derive the next step from `checklist.md`'s first
25
25
  unchecked item.