@zalom/plastic 2.0.0-alpha.17 → 2.0.0-alpha.19
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/package.json +2 -2
- package/scripts/dashboard.rb +20 -0
- package/scripts/doctor.rb +120 -2
- package/scripts/end-intent +134 -8
- package/scripts/hook-capture +4 -105
- package/scripts/lib/action_graph_shim.rb +277 -0
- package/scripts/lib/atomic_write.rb +31 -0
- package/scripts/lib/graph_edges.rb +121 -0
- package/scripts/lib/graph_file.rb +246 -0
- package/scripts/lib/guarded_append.rb +155 -0
- package/scripts/lib/installer_core.rb +32 -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 +873 -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 +122 -12
- package/scripts/lib/roadmap_queue.rb +161 -3
- package/scripts/lib/roadmap_savepoint.rb +26 -5
- package/scripts/lib/savepoint.rb +123 -12
- package/scripts/lib/work_graph_validator.rb +201 -0
- package/scripts/node-packet +92 -0
- package/scripts/node-transition +291 -0
- package/scripts/outcome-report +74 -0
- package/scripts/ready-set +126 -0
- package/scripts/release-check +118 -0
- package/scripts/report-screen +8 -1
- package/scripts/roadmap-savepoint +7 -0
- package/scripts/validate-work-graph +39 -0
- package/skills/auto/SKILL.md +2 -3
- package/skills/auto/references/human-report-contract.md +3 -2
- package/skills/intent-continuing/references/boarding-matrix.md +1 -0
- package/skills/intent-ending/SKILL.md +30 -19
- package/skills/intent-executing/SKILL.md +1 -1
- 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/templates/graph.md +16 -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 +8 -6
package/scripts/report-screen
CHANGED
|
@@ -17,6 +17,7 @@
|
|
|
17
17
|
# report-screen session <tier_root> [--session <id>] [--since <iso>]
|
|
18
18
|
# [--ledger-root <dir>] [--ansi]
|
|
19
19
|
# report-screen roadmap <roadmap.md> plan|state|delivered [--ansi] [--store-root <dir>]
|
|
20
|
+
# report-screen archive <store_root> [--ansi]
|
|
20
21
|
#
|
|
21
22
|
# --ansi delegates to ScreenPaint (intent 317a, D1), the parser/re-layouter
|
|
22
23
|
# in the shared TUI core. Selection is by capability, never by harness:
|
|
@@ -267,8 +268,14 @@ when "roadmap"
|
|
|
267
268
|
roadmap_store_root = store_root_flag ? File.expand_path(store_root_flag) : nil
|
|
268
269
|
out = ReportScreen.render_roadmap(path: roadmap_path, verb: sub_verb, store_root: roadmap_store_root)
|
|
269
270
|
$stdout.write paint(out, ansi_enabled)
|
|
271
|
+
when "archive"
|
|
272
|
+
usage_abort("usage: report-screen archive <store_root>") unless target
|
|
273
|
+
store_root = File.expand_path(target)
|
|
274
|
+
usage_abort("#{store_root} is not a store (no INDEX.md)") unless File.exist?(File.join(store_root, "INDEX.md"))
|
|
275
|
+
out = ReportScreen.render_archive(store_root)
|
|
276
|
+
$stdout.write paint(out, ansi_enabled)
|
|
270
277
|
else
|
|
271
|
-
usage_abort("unknown verb #{verb.inspect} (use plan|state|delivered|delay|session|roadmap)")
|
|
278
|
+
usage_abort("unknown verb #{verb.inspect} (use plan|state|delivered|delay|session|roadmap|archive)")
|
|
272
279
|
end
|
|
273
280
|
|
|
274
281
|
exit 0
|
|
@@ -18,6 +18,7 @@
|
|
|
18
18
|
# rebuilds an empty ledger.
|
|
19
19
|
|
|
20
20
|
require_relative "lib/roadmap_savepoint"
|
|
21
|
+
require_relative "lib/guarded_append"
|
|
21
22
|
|
|
22
23
|
def opt(args, name)
|
|
23
24
|
(i = args.index(name)) && args[i + 1]
|
|
@@ -47,6 +48,12 @@ when "append"
|
|
|
47
48
|
rescue ArgumentError => e
|
|
48
49
|
warn "append: #{e.message}"
|
|
49
50
|
exit 2
|
|
51
|
+
rescue GuardedAppend::Unavailable => e
|
|
52
|
+
# Intent 335 (spec D14): the write guard could not be taken; nothing was written. Exit 4
|
|
53
|
+
# rather than let a backtrace reach the six skill recipes that drive this CLI - it rescues
|
|
54
|
+
# ArgumentError alone today and would otherwise print one straight to the terminal.
|
|
55
|
+
warn "append: #{e.message}"
|
|
56
|
+
exit 4
|
|
50
57
|
end
|
|
51
58
|
|
|
52
59
|
when "rebuild"
|
|
@@ -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/skills/auto/SKILL.md
CHANGED
|
@@ -169,6 +169,7 @@ ledger is missing (then rebuild it with `Savepoint.rebuild_savepoint`).
|
|
|
169
169
|
| `How plan.md created` / `How checklist.md created` / `Exec started` | Exec (verify plan, matrix, checklist) |
|
|
170
170
|
| `Exec outcome.md created` | Exec done; complete the intent |
|
|
171
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 - read node status through `NodeLedger.status` before dispatching anything, never re-derive it by eye |
|
|
172
173
|
|
|
173
174
|
Filesystem fallback, in order: `checklist.md` with items checked means resume Exec from the
|
|
174
175
|
first unchecked item; `plan.md` plus `checklist.md` means enter Exec; `spec.md` alone means
|
|
@@ -184,9 +185,7 @@ Announce which stage you are entering and why.
|
|
|
184
185
|
3. Decide: pick the best option per gap, record it in `## Context > ### Decisions` with the
|
|
185
186
|
rationale, and log it in `## Insights` with the `(autonomous)` marker through
|
|
186
187
|
`scripts/insight-append`.
|
|
187
|
-
4. Write `spec.md`.
|
|
188
|
-
|
|
189
|
-
Then How.
|
|
188
|
+
4. Write `spec.md`. Then How.
|
|
190
189
|
|
|
191
190
|
## How (the lead), then the plan review
|
|
192
191
|
|
|
@@ -102,8 +102,9 @@ A delivery still ends with `outcome.md` plus one `delivered` screen.
|
|
|
102
102
|
|
|
103
103
|
## One report per audience
|
|
104
104
|
|
|
105
|
-
A delivery produces exactly two artifacts: `outcome.md` (
|
|
106
|
-
|
|
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
|
|
107
108
|
written to `outcome.md`; point at it instead. Skills do not open with a banner that names the
|
|
108
109
|
skill or restates the intent id and name the owner just typed. Announce only what the reader
|
|
109
110
|
cannot already know: an error, a result, a choice with its reason, or a handoff.
|
|
@@ -13,6 +13,7 @@ Classify from the last line alone, then verify only that line's artifact is real
|
|
|
13
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
18
|
## Per-stage behaviour (what "continue" means)
|
|
18
19
|
|
|
@@ -51,28 +51,39 @@ on disk is what the record becomes, so before the call:
|
|
|
51
51
|
reported gap that lands verbatim in the backfilled `## Follow-ups`.
|
|
52
52
|
2. Confirm every acceptance criterion in spec.md is verifiable (tests pass,
|
|
53
53
|
or the manual check described in its HOW line was actually run).
|
|
54
|
-
3. Decide what you have to say.
|
|
55
|
-
|
|
56
|
-
`scripts/
|
|
57
|
-
|
|
58
|
-
|
|
59
|
-
|
|
60
|
-
|
|
54
|
+
3. Decide what you have to say. For an intent with a `graph.md`, `outcome.md` is
|
|
55
|
+
GENERATED by `scripts/end-intent` itself, through `scripts/lib/outcome_report.rb`
|
|
56
|
+
(`scripts/outcome-report` is its standalone CLI, useful for checking the
|
|
57
|
+
generated text before the close): `## Delivered`, `## Verification`,
|
|
58
|
+
`## Graph diff`, and `## Findings` are read straight from `graph.md`, `nodes/`,
|
|
59
|
+
and the ledger every time, never hand-typed. `## Summary`, `## Needs you`, and
|
|
60
|
+
`## Follow-ups`, and every frontmatter key but `disposition`, are preserved
|
|
61
|
+
byte for byte when you author them and generated as plain facts otherwise, so
|
|
62
|
+
writing a summary yourself still works exactly as before. For an intent with
|
|
63
|
+
no `graph.md`, or when the generated text would be refused by the close's own
|
|
64
|
+
gates, a spec.md, plan.md, action file, or outcome.md left as the scaffold
|
|
65
|
+
placeholder is written from the record by `scripts/end-intent` (the intent
|
|
66
|
+
file's `## Intent`, `### Decisions`, and `## Insights`, the checklist, the
|
|
67
|
+
diff on the intent's own worktree). A file you wrote, even under a
|
|
68
|
+
still-present sentinel, is never touched.
|
|
61
69
|
|
|
62
70
|
### Step 1-5. Run `scripts/end-intent`
|
|
63
71
|
|
|
64
|
-
Author outcome.md yourself when
|
|
65
|
-
set the frontmatter to `disposition: delivered`
|
|
66
|
-
fill `## Summary`, `## Delivered`, `## Verification`,
|
|
67
|
-
`| Row | What |` table: one row per thing delivered,
|
|
68
|
-
recognizes, not a method name or an implementation summary
|
|
69
|
-
belongs in `## Summary`). Each row's label must appear as a standalone token
|
|
70
|
-
in an action-file heading
|
|
71
|
-
|
|
72
|
-
|
|
73
|
-
|
|
74
|
-
|
|
75
|
-
|
|
72
|
+
Author outcome.md yourself when the summary deserves more prose than the generator's
|
|
73
|
+
plain facts: copy `templates/outcome.md`, set the frontmatter to `disposition: delivered`
|
|
74
|
+
or `disposition: abandoned`, and fill `## Summary`, `## Delivered`, `## Verification`,
|
|
75
|
+
`## Follow-ups`. `## Delivered` is a `| Row | What |` table: one row per thing delivered,
|
|
76
|
+
in plain wording a reader recognizes, not a method name or an implementation summary
|
|
77
|
+
(that detail belongs in `## Summary`). Each row's label must appear as a standalone token
|
|
78
|
+
in an action-file heading (or a node-file heading, for an intent whose graph replaces
|
|
79
|
+
actions/ with nodes/) that owns the matrix table (`### S1 - ...` or
|
|
80
|
+
`## n1 failure-mode matrix` with a table beneath it proves that row; a table-less
|
|
81
|
+
heading naming the label is skipped); that heading's matrix rows become the row's
|
|
82
|
+
Proven-by cell on `report-screen delivered`'s post-delivery screen. `## Needs you` is
|
|
83
|
+
the literal None or a `| N | What | Why |` table. On abandon, `## Summary` states the
|
|
84
|
+
abandonment reason and the trail (see Pivot below). An intent with a `graph.md` and no
|
|
85
|
+
hand-written outcome.md gets one generated instead (Step 0.3 above); a placeholder
|
|
86
|
+
outcome.md on an intent with no `graph.md` is backfilled from the record, with the
|
|
76
87
|
close's disposition and the `--outcome-summary` line as its summary. Also author
|
|
77
88
|
the rich INDEX entry note now (a short line in the store's existing
|
|
78
89
|
Completed/Abandoned convention: mode, what shipped or why it was
|
|
@@ -75,7 +75,7 @@ Apply the auto skill's risk rule to the executor's return and the diff: a matrix
|
|
|
75
75
|
|
|
76
76
|
Whenever a review verdict returns - the plan review before code, or the post-execution review above - the lead appends a `Review` line: `ruby ~/.plastic/scripts/savepoint-note <intent_dir> --kind Review --text "<verdict, what changed>"` (intent 317, D17). This is the other half of what `report-screen delay` reads.
|
|
77
77
|
|
|
78
|
-
**The D19 heading convention.** An action file's `## Delivered` row (in `outcome.md`) is proven by the first `actions/ACTION_N.md` heading that carries that row's label as a standalone token AND owns the matrix table (322 D1r) - `### Row A -` with a table beneath it proves row A, `### S1 -` proves row S1; a heading that only names the label, with no table under it, is skipped. Write action-file section headings so the label they prove is unambiguous (never a substring another label could also match, like `A` inside `AB`); `report-screen delivered`'s Proven-by column renders `not recorded` when no heading owns a matching table and no matrix row cell carries the label either.
|
|
78
|
+
**The D19 heading convention.** An action file's `## Delivered` row (in `outcome.md`) is proven by the first `actions/ACTION_N.md` OR `nodes/*.md` heading that carries that row's label as a standalone token AND owns the matrix table (322 D1r, 334 D10r) - `### Row A -` with a table beneath it proves row A, `### S1 -` proves row S1, `## n1 failure-mode matrix` proves row n1; a heading that only names the label, with no table under it, is skipped. Readers check `actions/` first, then `nodes/` (334 D15r). Write action-file or node-file section headings so the label they prove is unambiguous (never a substring another label could also match, like `A` inside `AB`); `report-screen delivered`'s Proven-by column renders `not recorded` when no heading owns a matching table and no matrix row cell carries the label either.
|
|
79
79
|
|
|
80
80
|
### Step 4: Update Intent and Complete
|
|
81
81
|
Capture observations in `## Insights`. When ALL checklist items are checked:
|
|
@@ -206,6 +206,45 @@ The dist-tag is derived from the version string in `package.json`:
|
|
|
206
206
|
- Contains `-beta` → `--tag beta`
|
|
207
207
|
- No pre-release suffix → no `--tag` flag (publishes to `latest`)
|
|
208
208
|
|
|
209
|
+
#### `npm_publish_workflow`
|
|
210
|
+
|
|
211
|
+
The tag pushed in step 6 starts the project's publish workflow (GitHub Actions, keyed on the
|
|
212
|
+
workflow file `publish.yml`) instead of a local `npm publish`. The workflow runs with a
|
|
213
|
+
short-lived, per-run OIDC credential, so no npm token exists in this session or on this
|
|
214
|
+
machine.
|
|
215
|
+
|
|
216
|
+
1. **Confirm a run exists for the tag.** A tag cut from a ref that does not carry the
|
|
217
|
+
workflow starts no run at all, and silence would read as success:
|
|
218
|
+
|
|
219
|
+
```bash
|
|
220
|
+
gh run list --workflow publish.yml --limit 5
|
|
221
|
+
```
|
|
222
|
+
|
|
223
|
+
2. **Follow the run.**
|
|
224
|
+
|
|
225
|
+
```bash
|
|
226
|
+
gh run watch <run-id>
|
|
227
|
+
```
|
|
228
|
+
|
|
229
|
+
3. **Verify the registry, not just the run.** The release is not done until the new version
|
|
230
|
+
shows up on the expected channel:
|
|
231
|
+
|
|
232
|
+
```bash
|
|
233
|
+
npm view <package> dist-tags
|
|
234
|
+
```
|
|
235
|
+
|
|
236
|
+
The dist-tag is derived from the version string in `package.json`, the same rule
|
|
237
|
+
`ReleaseGuard.dist_tag` implements:
|
|
238
|
+
|
|
239
|
+
| Version contains | dist-tag |
|
|
240
|
+
| --- | --- |
|
|
241
|
+
| `-alpha` | `alpha` |
|
|
242
|
+
| `-beta` | `beta` |
|
|
243
|
+
| no pre-release suffix | `latest` |
|
|
244
|
+
|
|
245
|
+
Do not run `npm whoami` on this path. npm documents that `whoami` does not reflect OIDC
|
|
246
|
+
authentication, so on a workflow-published project it can only mislead.
|
|
247
|
+
|
|
209
248
|
#### Other values
|
|
210
249
|
|
|
211
250
|
If `on_green` contains an action not listed above, log it:
|
|
@@ -34,18 +34,22 @@ cleared is a no-op.
|
|
|
34
34
|
## Promotion
|
|
35
35
|
|
|
36
36
|
Promotion is not a CLI flag; there is no `--promote` command. It is a set of steps the
|
|
37
|
-
agent performs during the releasing workflow, reusing the normal release mechanics
|
|
38
|
-
|
|
37
|
+
agent performs during the releasing workflow, reusing the normal release mechanics (version
|
|
38
|
+
bump, tag, GitHub release). For a project on the `npm_publish_workflow` post-push action,
|
|
39
|
+
the tag push itself starts the publish; there is no local publish command to run.
|
|
39
40
|
|
|
40
41
|
```bash
|
|
41
|
-
# Promote alpha → beta: set version files from -alpha.N to -beta.1, commit, tag,
|
|
42
|
-
|
|
42
|
+
# Promote alpha → beta: set version files from -alpha.N to -beta.1, commit, tag, push.
|
|
43
|
+
# The publish workflow reads the new version and publishes to the beta dist-tag.
|
|
43
44
|
|
|
44
45
|
# Promote beta → stable: strip the pre-release suffix (e.g., 1.0.0-beta.3 → 1.0.0),
|
|
45
|
-
# commit, tag,
|
|
46
|
-
npm publish --access public # no --tag flag publishes to latest
|
|
46
|
+
# commit, tag, push. The publish workflow reads the new version and publishes to latest.
|
|
47
47
|
```
|
|
48
48
|
|
|
49
|
+
A project still on the `npm_publish` action (publishing locally from the session) runs
|
|
50
|
+
`npm publish --access public --tag <channel>` at this point instead, per that action's own
|
|
51
|
+
section in SKILL.md.
|
|
52
|
+
|
|
49
53
|
**Promotion rules:**
|
|
50
54
|
- Linear only: alpha → beta → stable. Cannot skip channels.
|
|
51
55
|
- Version files are bumped and committed as in a normal release.
|
|
@@ -78,7 +78,7 @@ re-deriving this decision.
|
|
|
78
78
|
of 1.1.0, versioned `1.2.0-beta.1` (`c48601a`). There is nothing left to execute on the git side;
|
|
79
79
|
this playbook describes what happens next, not a pending action.
|
|
80
80
|
|
|
81
|
-
**Preconditions**, both required before any
|
|
81
|
+
**Preconditions**, both required before any publish of `1.2.0-beta.1`:
|
|
82
82
|
|
|
83
83
|
- (a) One documentation pass over beta-line skills and docs for the hybrid savepoint contract:
|
|
84
84
|
on beta, only the terminal Done bookend still writes a live `savepoint.md`; every other
|
|
@@ -0,0 +1,16 @@
|
|
|
1
|
+
# Graph: <intent name>
|
|
2
|
+
|
|
3
|
+
## Goal
|
|
4
|
+
<What this intent's graph delivers once every node reaches done.>
|
|
5
|
+
|
|
6
|
+
## Decisions
|
|
7
|
+
- D1 <first ruling made while building this graph>
|
|
8
|
+
|
|
9
|
+
## Graph
|
|
10
|
+
Edges, `needs` only; the head needs the tail done. The literal target `nothing` declares a root.
|
|
11
|
+
- n1 needs nothing
|
|
12
|
+
|
|
13
|
+
## Status
|
|
14
|
+
| Node | State | Detail |
|
|
15
|
+
| --- | --- | --- |
|
|
16
|
+
| n1 | planned | |
|
|
@@ -0,0 +1,22 @@
|
|
|
1
|
+
---
|
|
2
|
+
node: n1
|
|
3
|
+
kind: work
|
|
4
|
+
files: [path/to/file.rb, test/path_to_file_test.rb]
|
|
5
|
+
budget: 100000
|
|
6
|
+
---
|
|
7
|
+
# n1 - <one-line description of what this node builds>
|
|
8
|
+
|
|
9
|
+
<Why this node exists and what it changes, in a sentence or two.>
|
|
10
|
+
|
|
11
|
+
## n1 failure-mode matrix
|
|
12
|
+
| Operation | Failure mode | Test |
|
|
13
|
+
| --- | --- | --- |
|
|
14
|
+
| <operation> | <what goes wrong without this code, and its consequence> | `some_test#test_name` |
|
|
15
|
+
|
|
16
|
+
## Steps
|
|
17
|
+
1. Red: the matrix's tests above, committed before any code.
|
|
18
|
+
2. Write the code that makes them pass.
|
|
19
|
+
3. Green, then the whole suite at its baseline.
|
|
20
|
+
|
|
21
|
+
## Proven by
|
|
22
|
+
(filled at close from the ledger: commit, suite counts, review verdict)
|
package/templates/outcome.md
CHANGED
|
@@ -9,12 +9,14 @@ disposition: delivered|abandoned
|
|
|
9
9
|
## Delivered
|
|
10
10
|
<!-- One row per thing delivered, in plain wording a reader recognizes, not
|
|
11
11
|
an implementation summary; the technical detail belongs in ## Summary. Each
|
|
12
|
-
row's label must appear as a standalone token in an actions/*.md
|
|
13
|
-
that owns the matrix table (for example "### S1 - ..."
|
|
14
|
-
it proves row S1
|
|
15
|
-
|
|
16
|
-
|
|
17
|
-
|
|
12
|
+
row's label must appear as a standalone token in an actions/*.md OR
|
|
13
|
+
nodes/*.md heading that owns the matrix table (for example "### S1 - ..."
|
|
14
|
+
with a table beneath it proves row S1, or "## n1 failure-mode matrix" proves
|
|
15
|
+
row n1); that heading's matrix rows become the row's Proven-by cell on the
|
|
16
|
+
delivered screen (intent 317 D19, 317a, 322 D1r, 334 D10r). Readers resolve
|
|
17
|
+
actions/ first, then nodes/ (334 D15r). A label with no owning heading falls
|
|
18
|
+
back to a matrix row cell that carries it, when one under a heading named
|
|
19
|
+
"matrix" exists (322 D3r). -->
|
|
18
20
|
| Row | What |
|
|
19
21
|
| --- | --- |
|
|
20
22
|
| S1 | ... |
|