rcf-lite 0.9.0 → 0.11.0
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/CHANGELOG.md +95 -54
- package/README.md +8 -4
- package/bin/rcf.js +145 -57
- package/fixtures/canary-manifest.json +9 -9
- package/guidance/README.md +1 -1
- package/guidance/build-cycle-playbook.md +108 -51
- package/guidance/build-cycle.md +7 -7
- package/guidance/document-model.md +1 -1
- package/guidance/elicitation-playbook.md +29 -29
- package/guidance/harness-template.md +52 -10
- package/guidance/managed/README.md +1 -1
- package/guidance/managed/agent-instructions-block.hash +1 -1
- package/guidance/managed/agent-instructions-block.md +51 -9
- package/guidance/manifest.json +1 -1
- package/guidance/overview.md +4 -4
- package/package.json +4 -6
- package/rcf/adrs/adr-008.json +1 -1
- package/rcf/adrs/adr-009.json +4 -4
- package/rcf/code-nodes/cn-016.json +1 -1
- package/rcf/code-nodes/cn-019.json +1 -1
- package/rcf/code-nodes/cn-020.json +1 -1
- package/rcf/code-nodes/cn-021.json +1 -1
- package/rcf/code-nodes/cn-022.json +1 -1
- package/rcf/code-nodes/cn-049.json +1 -1
- package/rcf/code-nodes/cn-055.json +1 -1
- package/rcf/code-nodes/cn-057.json +5 -5
- package/rcf/code-nodes/cn-061.json +1 -1
- package/rcf/code-nodes/cn-066.json +1 -1
- package/rcf/code-nodes/cn-069.json +1 -1
- package/rcf/fbs/fbs-005.json +1 -1
- package/rcf/fbs/fbs-006.json +2 -2
- package/rcf/fbs/fbs-007.json +1 -1
- package/rcf/fbs/fbs-014.json +1 -1
- package/rcf/fbs/fbs-015.json +9 -8
- package/rcf/fbs/fbs-016.json +1 -1
- package/rcf/fbs/fbs-017.json +1 -1
- package/rcf/fbs/fbs-018.json +2 -2
- package/rcf/requirements/req-008.json +1 -1
- package/rcf/requirements/req-009.json +2 -2
- package/rcf/requirements/req-010.json +1 -1
- package/rcf/test-suites/PENDING.md +2 -2
- package/rcf/test-suites/ts-004.json +1 -1
- package/rcf/test-suites/ts-006.json +3 -3
- package/rcf/test-suites/ts-008.json +2 -2
- package/rcf/test-suites/ts-009.json +2 -2
- package/rcf/test-suites/ts-017.json +1 -1
- package/rcf/test-suites/ts-024.json +1 -1
- package/rcf/test-suites/ts-025.json +32 -18
- package/rcf/test-suites/ts-026.json +1 -1
- package/rcf/test-suites/ts-027.json +7 -7
- package/rcf/test-suites/ts-028.json +1 -1
- package/rcf/user-stories/us-1001.json +10 -10
- package/rcf/user-stories/us-1002.json +12 -12
- package/rcf/user-stories/us-1003.json +6 -6
- package/rcf/user-stories/us-805.json +2 -2
- package/rcf/user-stories/us-901.json +13 -13
- package/src/blueprint/conflicts.js +15 -15
- package/src/blueprint/supersede.js +6 -6
- package/src/build/bundle.js +3 -3
- package/src/build/formatters/markdown.js +9 -9
- package/src/build/mark.js +3 -3
- package/src/build/queue.js +1 -1
- package/src/cli/blueprint.js +3 -3
- package/src/cli/browser-verify.js +1 -1
- package/src/cli/build.js +139 -69
- package/src/cli/coverage.js +1 -1
- package/src/cli/create.js +3 -3
- package/src/cli/delete.js +2 -2
- package/src/cli/design.js +10 -10
- package/src/cli/fbs.js +1 -1
- package/src/cli/finalise.js +22 -20
- package/src/cli/help.js +267 -95
- package/src/cli/impact.js +1 -1
- package/src/cli/intake.js +3 -3
- package/src/cli/link.js +3 -3
- package/src/cli/preflight.js +2 -2
- package/src/cli/read.js +1 -1
- package/src/cli/req-baseline.js +2 -2
- package/src/cli/req-classify.js +3 -3
- package/src/cli/review.js +1 -1
- package/src/cli/standards.js +1 -1
- package/src/cli/test-suite.js +1 -1
- package/src/cli/trace.js +1 -1
- package/src/cli/ui-baseline.js +3 -3
- package/src/cli/ui-classify.js +4 -4
- package/src/cli/update.js +2 -2
- package/src/cli/validate.js +2 -2
- package/src/cli/view.js +12 -10
- package/src/core/store/writer.js +1 -1
- package/src/design/writer.js +3 -3
- package/src/finalise/detect.js +32 -38
- package/src/finalise/index.js +0 -1
- package/src/finalise/install.js +9 -8
- package/src/finalise/spawn.js +14 -10
- package/src/mcp/tools.js +1 -1
- package/src/req-baseline/gate.js +1 -1
- package/src/ui-baseline/manifest-writer.js +2 -2
- package/src/verify/cli/cleanup.js +1 -1
- package/src/verify/cli/mcp.js +1 -1
- package/src/verify/cli/provision.js +1 -1
- package/src/verify/cli/report.js +1 -1
- package/src/verify/cli/run.js +1 -1
- package/src/view-supervisor/manifest-writer.js +2 -2
- package/bin/rcf-verify.js +0 -122
- package/src/verify/cli/help.js +0 -56
|
@@ -11,10 +11,10 @@ Every command output shown below is real, captured against this repository's own
|
|
|
11
11
|
## 2. The loop at a glance
|
|
12
12
|
|
|
13
13
|
```
|
|
14
|
-
rcf build --next -> spec bundle for the next actionable item
|
|
14
|
+
rcf build bundle --next -> spec bundle for the next actionable item
|
|
15
15
|
execute the five stages its runbook prints:
|
|
16
16
|
Define -> Build -> Review -> Test -> Finalise
|
|
17
|
-
rcf build <fbs-id>
|
|
17
|
+
rcf build mark <fbs-id> <status>
|
|
18
18
|
-> record each lifecycle transition, then repeat
|
|
19
19
|
```
|
|
20
20
|
|
|
@@ -30,7 +30,7 @@ What good looks like:
|
|
|
30
30
|
- Your plan maps every in-scope AC id to intended work. An AC with no planned work, or planned work with no AC, is a plan defect.
|
|
31
31
|
- Ambiguity is settled before code. If two readings of an AC survive the read-through, that is an escalation (section 8), not a coin flip.
|
|
32
32
|
|
|
33
|
-
Referee: the bundle itself is the definition, and `rcf validate` confirms the tree you are building against is clean before you start.
|
|
33
|
+
Referee: the bundle itself is the definition, and `rcf define validate` confirms the tree you are building against is clean before you start.
|
|
34
34
|
|
|
35
35
|
Failure modes:
|
|
36
36
|
|
|
@@ -40,15 +40,15 @@ Failure modes:
|
|
|
40
40
|
**Third-party service dependencies belong on the FBS at Define.** When the plan touches a service the pre-flight session recorded (`preFlightConfig` - see elicitation playbook §8.5), write the `dependsOnServices` binding on the FBS now, not later:
|
|
41
41
|
|
|
42
42
|
```
|
|
43
|
-
rcf fbs <fbs-id> depends-on --service <id> --mode <attestationMode> --acs <acIds> [--preflight <pfc-id>]
|
|
43
|
+
rcf build fbs <fbs-id> depends-on --service <id> --mode <attestationMode> --acs <acIds> [--preflight <pfc-id>]
|
|
44
44
|
```
|
|
45
45
|
|
|
46
|
-
This is not a build-time optimisation; it is the seam the whole verification-integrity surface hangs on. `coverage --strict` at Stage 4 refuses when a TC covers an AC whose FBS was named in a preflight `affectedFbsIds` list but has no matching entry here; verify's deployed-verdict gate reads the same binding to decide whether a live-attested AC needs a live probe or a `MOCK-ONLY-DECLARED` verdict is the honest answer. If the plan touches a service the pre-flight session did NOT record - a runtime dependency discovered mid-Build - `rcf build --next` will warn and point at `rcf preflight` for a re-run; add the entry to the preflight record, then to the FBS.
|
|
46
|
+
This is not a build-time optimisation; it is the seam the whole verification-integrity surface hangs on. `coverage --strict` at Stage 4 refuses when a TC covers an AC whose FBS was named in a preflight `affectedFbsIds` list but has no matching entry here; verify's deployed-verdict gate reads the same binding to decide whether a live-attested AC needs a live probe or a `MOCK-ONLY-DECLARED` verdict is the honest answer. If the plan touches a service the pre-flight session did NOT record - a runtime dependency discovered mid-Build - `rcf build bundle --next` will warn and point at `rcf discover preflight` for a re-run; add the entry to the preflight record, then to the FBS.
|
|
47
47
|
|
|
48
48
|
Stage end: mark pickup and commit any plan artefacts the driving workflow requires.
|
|
49
49
|
|
|
50
50
|
```
|
|
51
|
-
$ rcf build FBS-012
|
|
51
|
+
$ rcf build mark FBS-012 inProgress
|
|
52
52
|
marked FBS-012 notStarted -> inProgress
|
|
53
53
|
```
|
|
54
54
|
|
|
@@ -56,7 +56,7 @@ marked FBS-012 notStarted -> inProgress
|
|
|
56
56
|
|
|
57
57
|
Worked micro-example. The FBS-005 bundle ("CLI read verbs") scopes three ACs: AC-301-1 (reading a valid document returns it and reports it as valid), AC-301-2 (reading an id with no file returns a structured not-found error naming the id), AC-301-3 (reading an invalid document returns both the content and the validation errors). Restated as a three-line plan:
|
|
58
58
|
|
|
59
|
-
1. AC-301-1: wire `rcf read <id>` to the store load; render content plus a validity line; test the valid path.
|
|
59
|
+
1. AC-301-1: wire `rcf define read <id>` to the store load; render content plus a validity line; test the valid path.
|
|
60
60
|
2. AC-301-2: return the structured not-found error with the id in it; test against a missing id.
|
|
61
61
|
3. AC-301-3: on schema failure, render content and errors together rather than either alone; test with a deliberately broken document.
|
|
62
62
|
|
|
@@ -66,21 +66,21 @@ Three ACs, three lines, nothing extra. That is the whole Define output for a sma
|
|
|
66
66
|
|
|
67
67
|
What good looks like:
|
|
68
68
|
|
|
69
|
-
- The FBS classifier fired at Define and printed a `[info] build: ui-classifier verdict=ui reason=keyword-scan (N signal(s))` line ahead of the bundle. That is the trigger to think about design, not to skip it: even for a `notUi` verdict, if the FBS visibly renders pixels the operator overrides via `rcf update <fbs-id> --set uiBearing=true` (spec section 4.4). A false positive costs the operator one override; a false negative ships another dated UI.
|
|
70
|
-
- A `uiBaseline` record exists on the manifest. If it does not, run `rcf ui-baseline init` before opening any Design substage verb. The interactive session presents every ruled default on one summary screen; press ENTER to accept, type a field name to edit one, type `edit-all` to walk them sequentially, type `cancel` to leave without writing. Every opt-out lands with a plain-text reason of at least twenty characters. Silence is never an opt-out.
|
|
69
|
+
- The FBS classifier fired at Define and printed a `[info] build: ui-classifier verdict=ui reason=keyword-scan (N signal(s))` line ahead of the bundle. That is the trigger to think about design, not to skip it: even for a `notUi` verdict, if the FBS visibly renders pixels the operator overrides via `rcf define update <fbs-id> --set uiBearing=true` (spec section 4.4). A false positive costs the operator one override; a false negative ships another dated UI.
|
|
70
|
+
- A `uiBaseline` record exists on the manifest. If it does not, run `rcf discover ui-baseline init` before opening any Design substage verb. The interactive session presents every ruled default on one summary screen; press ENTER to accept, type a field name to edit one, type `edit-all` to walk them sequentially, type `cancel` to leave without writing. Every opt-out lands with a plain-text reason of at least twenty characters. Silence is never an opt-out.
|
|
71
71
|
- Three artefacts land on the FBS's `designStage` block before the design is called complete: a `journeys[]` list (at least one walk-through of a real actor + goal + two to eight steps), a `navModel` (shape from `shared-persistent` | `shared-per-section` | `none-single-page` | `operator-declared-other`, at least one route with a path + label + authRequired boolean, and a `signedInAsAffordance` boolean), and a `themeAndA11y` block (theme mode from `light-default-with-toggle` | `dark-default-with-toggle` | `single-theme-declared`, the tokens-module path, the contrast-test path, and the `contrastTestAuthoredBeforePalette` boolean attestation).
|
|
72
|
-
- Author via the verbs, not by hand-editing: `rcf design <fbs-id> journeys add --id <slug> --actor "..." --goal "..." --step "..." --step "..."`, `rcf design <fbs-id> nav set --shape <shape> --route <path=label:authRequired> ...`, `rcf design <fbs-id> theme-a11y set --mode <mode> --tokens <path> --contrast-test <path> --contrast-before-palette true|false`. When all three are in place, `rcf design <fbs-id> --mark-complete` sets `designStageComplete: true` on the FBS record. Alternatively, dispatch the Design worker via `rcf design <fbs-id>` (no sub-verb) and let the subagent author the three artefacts against the baseline plus a sibling-FBS `designStage` context, then mark complete.
|
|
72
|
+
- Author via the verbs, not by hand-editing: `rcf define design <fbs-id> journeys add --id <slug> --actor "..." --goal "..." --step "..." --step "..."`, `rcf define design <fbs-id> nav set --shape <shape> --route <path=label:authRequired> ...`, `rcf define design <fbs-id> theme-a11y set --mode <mode> --tokens <path> --contrast-test <path> --contrast-before-palette true|false`. When all three are in place, `rcf define design <fbs-id> --mark-complete` sets `designStageComplete: true` on the FBS record. Alternatively, dispatch the Design worker via `rcf define design <fbs-id>` (no sub-verb) and let the subagent author the three artefacts against the baseline plus a sibling-FBS `designStage` context, then mark complete.
|
|
73
73
|
- The playbook mandate 5 vocabulary (`Button`, `Input`, `Card`, `Badge`, `Table`, `Notice`, single badge shape) is guidance-only in v1. For string-templated projects (server-rendered HTML by concatenation, no framework) the operator can hand-check the six-component vocabulary with a `grep -oE 'class="[^"]+"'` sweep of view files; the audit does not enforce it mechanically in v1.
|
|
74
74
|
|
|
75
|
-
Warning at Stage 2 entry (`rcf build <fbs-id>
|
|
75
|
+
Warning at Stage 2 entry (`rcf build mark <fbs-id> inProgress`): if the FBS is uiBearing and no `designStage` has been authored, one `[warn]` line points at `rcf define design <fbs-id>`. Not a refusal - pickup and planning can happen before design when the operator wants to think about the AC scope first. The hard refusal fires at Stage 5.
|
|
76
76
|
|
|
77
|
-
Refusal at Stage 5 entry (`rcf build <fbs-id>
|
|
77
|
+
Refusal at Stage 5 entry (`rcf build mark <fbs-id> complete`) on a uiBearing FBS when any of: `designStageComplete` is not true; `designStage.themeAndA11y.contrastTestAuthoredBeforePalette` is false; the baseline disagrees with a `designStage` paired field and no `operatorOptOuts[]` entry excuses it; the browser-verification verdict is `block` or `warn` without operator ack (see section 7).
|
|
78
78
|
|
|
79
|
-
Escalation: when the operator disagrees with the classifier, ratify or override via `rcf update <fbs-id> --set uiBearing=true|false`. The override records `verdict: operatorOverride` on `uiClassification`, keeping the classifier's evidence in `signals[]` for provenance. When the operator disagrees with a baseline default, record it as an explicit opt-out via `rcf ui-baseline opt-out --field <path> --reason "..." ` (at least twenty characters).
|
|
79
|
+
Escalation: when the operator disagrees with the classifier, ratify or override via `rcf define update <fbs-id> --set uiBearing=true|false`. The override records `verdict: operatorOverride` on `uiClassification`, keeping the classifier's evidence in `signals[]` for provenance. When the operator disagrees with a baseline default, record it as an explicit opt-out via `rcf discover ui-baseline opt-out --field <path> --reason "..." ` (at least twenty characters).
|
|
80
80
|
|
|
81
81
|
Stage end: commit. The `designStage` and `designStageComplete` write are the artefacts of this stage.
|
|
82
82
|
|
|
83
|
-
Worked micro-example. FBS-016 ("Web UI dashboard") classifies as UI-bearing on `dashboard` and `page` signals in the summary. `rcf ui-baseline init` runs once for the project, accepting the ruled defaults on ENTER. Three journeys sketched: signed-in-owner checks status; new-monitor add flow; unauthenticated visitor lands on login. `navModel` records the four authenticated routes (dashboard, monitors, monitor-detail, settings) as `shared-persistent` with `signedInAsAffordance: true`. `themeAndA11y` records `light-default-with-toggle`, tokens at `src/ui/tokens.ts`, contrast test at `test/ui-accessibility.test.ts`, `contrastTestAuthoredBeforePalette: true`. `rcf design FBS-016 --mark-complete` sets the boolean; Stage 2 opens.
|
|
83
|
+
Worked micro-example. FBS-016 ("Web UI dashboard") classifies as UI-bearing on `dashboard` and `page` signals in the summary. `rcf discover ui-baseline init` runs once for the project, accepting the ruled defaults on ENTER. Three journeys sketched: signed-in-owner checks status; new-monitor add flow; unauthenticated visitor lands on login. `navModel` records the four authenticated routes (dashboard, monitors, monitor-detail, settings) as `shared-persistent` with `signedInAsAffordance: true`. `themeAndA11y` records `light-default-with-toggle`, tokens at `src/ui/tokens.ts`, contrast test at `test/ui-accessibility.test.ts`, `contrastTestAuthoredBeforePalette: true`. `rcf define design FBS-016 --mark-complete` sets the boolean; Stage 2 opens.
|
|
84
84
|
|
|
85
85
|
## 4. Stage 2 - Build
|
|
86
86
|
|
|
@@ -88,7 +88,7 @@ What good looks like:
|
|
|
88
88
|
|
|
89
89
|
- Implement to the section-4 ACs using the section-5 context. The TACs name the components and boundaries you are expected to respect; the ADRs name decisions already taken, which you follow rather than relitigate.
|
|
90
90
|
- The bundle is the spec. When the code teaches you the spec is wrong, stop and escalate; do not quietly ship your improved version.
|
|
91
|
-
- As each AC lands, author or update its Code Node: `rcf create cn --path <file>[#symbol] --acs <ac-ids>`. Do this now - the mapping from symbol to AC is exactly what you are holding in your head mid-implementation, and Stage 5 refuses completion without it (section 9).
|
|
91
|
+
- As each AC lands, author or update its Code Node: `rcf define create cn --path <file>[#symbol] --acs <ac-ids>`. Do this now - the mapping from symbol to AC is exactly what you are holding in your head mid-implementation, and Stage 5 refuses completion without it (section 9).
|
|
92
92
|
- Small commits inside the stage are fine; the stage-end commit is mandatory.
|
|
93
93
|
|
|
94
94
|
Referee: none new at this stage. The bundle stays open; you check yourself against it.
|
|
@@ -111,8 +111,8 @@ What good looks like:
|
|
|
111
111
|
Referee:
|
|
112
112
|
|
|
113
113
|
```
|
|
114
|
-
$ rcf validate
|
|
115
|
-
rcf validate: tree is clean.
|
|
114
|
+
$ rcf define validate
|
|
115
|
+
rcf define validate: tree is clean.
|
|
116
116
|
```
|
|
117
117
|
|
|
118
118
|
Exit 0 when clean; exit 3 with issue lines when not (section 9 shows the failure shape).
|
|
@@ -122,7 +122,7 @@ Failure modes:
|
|
|
122
122
|
- **Rubber-stamp review.** Symptom: review completes in the time it takes to scroll. Correction: the per-AC question above, answered per AC, in writing if the workflow keeps review notes.
|
|
123
123
|
- **Reviewing only what changed rather than what was promised.** Symptom: the review walks the diff top to bottom and never opens section 4. Correction: walk the AC list as the outer loop, the diff as the inner one. This is where AC-skipping is cheapest to catch.
|
|
124
124
|
|
|
125
|
-
**Second gate on Stage 3: `rcf review <fbs-id>`.** After `rcf validate` clears the tree, run the test-theatre audit. The audit asks the meta-question the diff review does not: are the tests themselves honest? Five finding categories run deterministically over the FBS's in-scope ACs and their covering TSes:
|
|
125
|
+
**Second gate on Stage 3: `rcf build review <fbs-id>`.** After `rcf define validate` clears the tree, run the test-theatre audit. The audit asks the meta-question the diff review does not: are the tests themselves honest? Five finding categories run deterministically over the FBS's in-scope ACs and their covering TSes:
|
|
126
126
|
|
|
127
127
|
- `mockOnlyIntegrationClaim` - an integration-level TS whose every TC records `runtimeProvenance.profile` in `{mock, stub, fixture}` while at least one bound AC's aggregated attestation is `live` or `sandboxed`. This is the exact failure the whole 0.7.0 verification-integrity surface exists to catch (d-2026-07-30-142). Severity: block.
|
|
128
128
|
- `testPointerBroken` - a TC's `testPointer` fails to resolve to a real test in the working tree. Severity: block.
|
|
@@ -146,7 +146,7 @@ What good looks like:
|
|
|
146
146
|
Referee:
|
|
147
147
|
|
|
148
148
|
```
|
|
149
|
-
$ rcf coverage --strict
|
|
149
|
+
$ rcf audit coverage --strict
|
|
150
150
|
Coverage mode: strict (per-AC)
|
|
151
151
|
Requirements: 8 covered: 8 covered-unresolved: 0 uncovered: 0
|
|
152
152
|
|
|
@@ -155,7 +155,7 @@ Requirement Covered AC AC covered Test cases
|
|
|
155
155
|
REQ-001 yes AC-101-1 yes TC-001-init-clean-tree-roots
|
|
156
156
|
```
|
|
157
157
|
|
|
158
|
-
(Captured against this repo's tree, first rows shown; exit 0. This tree binds all 76 of its ACs to named existing tests via resolving `testPointer`s. It did not start there: the audit that built this test axis opened with 14 honestly-registered gaps in `rcf/test-suites/PENDING.md`, the referee exited 4 for as long as any row remained, and the register emptied only when every AC got a test that genuinely asserts its outcome - including one whole feature the tree claimed and the code lacked. CI now runs `rcf validate` and `rcf coverage --strict` as required steps, so this exit 0 is locked in: a stub TC or a new uncovered AC fails the build.) Strict mode is per-AC: every AC in scope needs a TC whose pointer resolves, and any gap exits 4. The `covered-unresolved` column is the third state: TC rows exist but at least one pointer does not resolve to a real test - a stub or a stale pointer - and it fails the gate exactly as uncovered does, with the offending pointers listed under the table. Read the table by AC id: this stage ends when your in-scope ACs show `AC covered: yes` with test cases listed. Gaps elsewhere in the tree may legitimately remain and will keep the tree-wide command at exit 4; narrow the verdict with a scope id (`rcf coverage <scope-id> --strict`, PRD / REQ / US ids accepted) to read the subtree you are working in.
|
|
158
|
+
(Captured against this repo's tree, first rows shown; exit 0. This tree binds all 76 of its ACs to named existing tests via resolving `testPointer`s. It did not start there: the audit that built this test axis opened with 14 honestly-registered gaps in `rcf/test-suites/PENDING.md`, the referee exited 4 for as long as any row remained, and the register emptied only when every AC got a test that genuinely asserts its outcome - including one whole feature the tree claimed and the code lacked. CI now runs `rcf define validate` and `rcf audit coverage --strict` as required steps, so this exit 0 is locked in: a stub TC or a new uncovered AC fails the build.) Strict mode is per-AC: every AC in scope needs a TC whose pointer resolves, and any gap exits 4. The `covered-unresolved` column is the third state: TC rows exist but at least one pointer does not resolve to a real test - a stub or a stale pointer - and it fails the gate exactly as uncovered does, with the offending pointers listed under the table. Read the table by AC id: this stage ends when your in-scope ACs show `AC covered: yes` with test cases listed. Gaps elsewhere in the tree may legitimately remain and will keep the tree-wide command at exit 4; narrow the verdict with a scope id (`rcf audit coverage <scope-id> --strict`, PRD / REQ / US ids accepted) to read the subtree you are working in.
|
|
159
159
|
|
|
160
160
|
Failure modes:
|
|
161
161
|
|
|
@@ -165,13 +165,13 @@ Failure modes:
|
|
|
165
165
|
**Runtime provenance is authored, not remembered.** Every TC authored or updated in a build cycle carries `runtimeProvenance` on the same edit as `status`. The pattern:
|
|
166
166
|
|
|
167
167
|
```
|
|
168
|
-
rcf test-suite <ts-id> provenance --tc <tc-id> --profile <mock|stub|fixture|live|mixed> \
|
|
168
|
+
rcf build test-suite <ts-id> provenance --tc <tc-id> --profile <mock|stub|fixture|live|mixed> \
|
|
169
169
|
[--env-var VAR ...] [--host host ...] [--notes "..."]
|
|
170
170
|
```
|
|
171
171
|
|
|
172
172
|
`coverage --strict` refuses (exit 4) when a TC covers an AC that binds a `dependsOnServices` entry and lacks a provenance block, and enforces the section 3.5 attestation × profile matrix on every remaining TC. Belt and braces: the PR body still names the runtime it verified against (section 15), but the chain is now the source of truth and the PR is a rendering.
|
|
173
173
|
|
|
174
|
-
**TS approval is a Stage 4 outcome, not an authoring guess.** Once `coverage --strict` exits 0 and the underlying test run exits 0, promote each touched TS with `rcf test-suite <ts-id> approve`. Stage 4 does this automatically at end-of-stage; the operator only needs the verb for manual override (a rare re-approval after `needsRevision` cycles, via `--force`). CI can add the opt-in `rcf coverage --strict --require-approved` gate to fail the build on any TS still `draft` after Stage 4.
|
|
174
|
+
**TS approval is a Stage 4 outcome, not an authoring guess.** Once `coverage --strict` exits 0 and the underlying test run exits 0, promote each touched TS with `rcf build test-suite <ts-id> approve`. Stage 4 does this automatically at end-of-stage; the operator only needs the verb for manual override (a rare re-approval after `needsRevision` cycles, via `--force`). CI can add the opt-in `rcf audit coverage --strict --require-approved` gate to fail the build on any TS still `draft` after Stage 4.
|
|
175
175
|
|
|
176
176
|
Stage end: commit.
|
|
177
177
|
|
|
@@ -180,8 +180,8 @@ Stage end: commit.
|
|
|
180
180
|
What good looks like:
|
|
181
181
|
|
|
182
182
|
- CI green on the branch; PR raised and merged per the driving workflow's convention. The PR body is written for the reviewer, evidence first - author it per section 12, not as a diff walk.
|
|
183
|
-
- `rcf build <fbs-id>
|
|
184
|
-
- `rcf finalise <fbs-id> --url <deploy-url>` writes `verified` after post-merge verification: the merged artefact observed doing the right thing by an independent verify run, not just the pre-merge tests remembered fondly. `--mark` cannot write `verified` - it caps at `complete`; the finalise gate promotes `complete -> verified` only when the verify run passes with ship authority.
|
|
183
|
+
- `rcf build mark <fbs-id> complete` after the merge, never before it. This refuses (exit 3, `missingCodeNodes`) if any in-scope AC still carries no Code Node - a reliability chain with optional links is not a chain. Author the missing CNs and retry, or, for a genuinely no-code spec (docs-only, config-only), declare `rcf build mark <fbs-id> complete --no-code-nodes` once.
|
|
184
|
+
- `rcf build finalise <fbs-id> --url <deploy-url>` writes `verified` after post-merge verification: the merged artefact observed doing the right thing by an independent verify run, not just the pre-merge tests remembered fondly. `--mark` cannot write `verified` - it caps at `complete`; the finalise gate promotes `complete -> verified` only when the verify run passes with ship authority.
|
|
185
185
|
- A working, documented local preview is present as the default outcome (section 14), and every verification claim in the PR names the runtime it was checked against (section 15). These are part of done, not extras.
|
|
186
186
|
|
|
187
187
|
Referee: CI, the finalise gate, plus the mark commands' own refusals (section 9).
|
|
@@ -194,7 +194,7 @@ Failure modes:
|
|
|
194
194
|
|
|
195
195
|
**The finalise gate reads the attestation, not just the exit code.** A passing verify run whose report carries per-AC verdicts in `{MOCK-ONLY-DECLARED, BLOCKED-BY-DECLARATION}` will not promote to `verified`. The gate stays at `complete -> verified` promotion, but a mock-only-declared AC refuses the promotion unless the operator explicitly ships the FBS complete-without-verified via `--ship-without-verified`. The summary always discloses these verdicts (whether the FBS ships or not) so the honest picture reaches the reviewer. Older verify reports without the `perAcVerdicts` field are handled gracefully - verify's train car may land later; older reports flow through with the pre-0.7.0 gate behaviour.
|
|
196
196
|
|
|
197
|
-
**Browser-verification gate (Track B, UI-bearing FBS only).** Before `--mark complete` on a uiBearing FBS, run `rcf
|
|
197
|
+
**Browser-verification gate (Track B, UI-bearing FBS only).** Before `--mark complete` on a uiBearing FBS, run `rcf verify browser <fbs-id>` against the local preview or a deployed URL. The verb writes a `browserVerification[]` record on the manifest and aggregates a verdict (pass / warn / block). `--mark complete` refuses when the verdict is `block` (unless the operator uses `--accept-block --reason "..."` per the ship-without-verified escape hatch) or `warn` (unless `operatorAckAt` is populated via `rcf verify browser <fbs-id> --ack`). The `agentScreenshotCritique` mode drives an injectable browser driver over every enumerated route x theme, records the DOM against the versioned `UI_INVARIANTS_V1` set (shared-nav presence, active-nav marker, signed-in-as affordance, theme toggle, default theme, focus rings, structural layout compare), and (when the FBS binds an auth REQ) runs the auth-REQ smoke pack (`GET /login`, `POST /logout`, `GET /login/verify?token=`). The `operatorSession` mode records the operator's ack alone; the ack is the evidence. Screenshots and DOM dumps land under `.rcf/artefacts/<bv-id>/`, gitignored via the 0.6.0 managed block.
|
|
198
198
|
|
|
199
199
|
Stage end: the merge is the commit.
|
|
200
200
|
|
|
@@ -223,7 +223,7 @@ Render it in the operator's language (section 17): the item named by its title,
|
|
|
223
223
|
|
|
224
224
|
The commands and their output, read at a glance. Exit codes: 0 success, 1 unexpected runtime failure, 2 usage error, 3 validation or broken references, 4 refused.
|
|
225
225
|
|
|
226
|
-
**`rcf validate`** - exit 0 and `rcf validate: tree is clean.` when clean. On issues, exit 3 with one line per issue naming the document and the rule, then a summary count. Captured in a scratch copy with a required field removed by hand:
|
|
226
|
+
**`rcf define validate`** - exit 0 and `rcf define validate: tree is clean.` when clean. On issues, exit 3 with one line per issue naming the document and the rule, then a summary count. Captured in a scratch copy with a required field removed by hand:
|
|
227
227
|
|
|
228
228
|
```
|
|
229
229
|
[error] validation REQ-001: / must have required property 'title'
|
|
@@ -234,9 +234,9 @@ The commands and their output, read at a glance. Exit codes: 0 success, 1 unexpe
|
|
|
234
234
|
|
|
235
235
|
Note the fan-out: one broken document produced two broken references. Fix the named document first, then re-validate.
|
|
236
236
|
|
|
237
|
-
**`rcf coverage --strict`** - exit 0 when every AC in scope has a TC whose `testPointer` resolves to a real test; exit 4 on any gap, with the per-AC table shown in section 6 above. A TC whose pointer does not resolve counts as `covered-unresolved` - a gap, not coverage - and is listed under the table with the reason (file missing, test missing). The `Test cases` column is the evidence trail.
|
|
237
|
+
**`rcf audit coverage --strict`** - exit 0 when every AC in scope has a TC whose `testPointer` resolves to a real test; exit 4 on any gap, with the per-AC table shown in section 6 above. A TC whose pointer does not resolve counts as `covered-unresolved` - a gap, not coverage - and is listed under the table with the reason (file missing, test missing). The `Test cases` column is the evidence trail.
|
|
238
238
|
|
|
239
|
-
**`rcf build <fbs-id> --strict`** - exit 4 instead of a bundle when the item is blocked. Captured in a scratch copy with a dependency reset to `notStarted`:
|
|
239
|
+
**`rcf build bundle <fbs-id> --strict`** - exit 4 instead of a bundle when the item is blocked. Captured in a scratch copy with a dependency reset to `notStarted`:
|
|
240
240
|
|
|
241
241
|
```
|
|
242
242
|
[error] refused build: FBS-012 is blocked by FBS-010 (notStarted)
|
|
@@ -244,10 +244,10 @@ Note the fan-out: one broken document produced two broken references. Fix the na
|
|
|
244
244
|
|
|
245
245
|
Without `--strict` the bundle renders anyway, flagged as a read-ahead; `--next` never selects blocked items.
|
|
246
246
|
|
|
247
|
-
**`rcf build <fbs-id>
|
|
247
|
+
**`rcf build mark <fbs-id> <status>`** - exit 0 with a one-line confirmation (`marked FBS-012 notStarted -> inProgress`). The lifecycle is forward-only (`notStarted -> inProgress -> complete -> verified`; forward jumps legal), but `--mark` caps at `complete`: `--mark verified` is refused with exit 4 and points to `rcf build finalise` (only the finalise gate writes `verified`). A backward mark is likewise refused with exit 4 and names the escape hatch:
|
|
248
248
|
|
|
249
249
|
```
|
|
250
|
-
[error] refused build: refusing backward transition complete -> inProgress on FBS-005; for a deliberate correction use: rcf update FBS-005 --set executionStatus=inProgress
|
|
250
|
+
[error] refused build: refusing backward transition complete -> inProgress on FBS-005; for a deliberate correction use: rcf define update FBS-005 --set executionStatus=inProgress
|
|
251
251
|
```
|
|
252
252
|
|
|
253
253
|
The escape hatch is for operator-sanctioned corrections. If you are reaching for it, you are in section 8's fourth case.
|
|
@@ -297,7 +297,7 @@ Parallel-safe tiers (items in the same tier have no dependency between them and
|
|
|
297
297
|
Next actionable: FBS-013
|
|
298
298
|
```
|
|
299
299
|
|
|
300
|
-
Two actionable items, and the tier column says how they relate: FBS-013 and FBS-014 share tier 0, meaning no dependency path connects them - they are parallel-safe, so a harness with two write workers on separate clones could take one each. `rcf build --next` picks the lowest buildOrder and emits its bundle. The header orients you in one glance - what, where in the queue, how big, what it hangs off:
|
|
300
|
+
Two actionable items, and the tier column says how they relate: FBS-013 and FBS-014 share tier 0, meaning no dependency path connects them - they are parallel-safe, so a harness with two write workers on separate clones could take one each. `rcf build bundle --next` picks the lowest buildOrder and emits its bundle. The header orients you in one glance - what, where in the queue, how big, what it hangs off:
|
|
301
301
|
|
|
302
302
|
```
|
|
303
303
|
# Spec bundle: FBS-013 - Deploy-aware elicitation and hosting guidance
|
|
@@ -317,11 +317,11 @@ Two actionable items, and the tier column says how they relate: FBS-013 and FBS-
|
|
|
317
317
|
Mark pickup, and the cycle is running:
|
|
318
318
|
|
|
319
319
|
```
|
|
320
|
-
$ rcf build FBS-013
|
|
320
|
+
$ rcf build mark FBS-013 inProgress
|
|
321
321
|
marked FBS-013 notStarted -> inProgress
|
|
322
322
|
```
|
|
323
323
|
|
|
324
|
-
From here it is the five stages, a commit per stage, `--mark complete` after the merge, `rcf finalise` to promote to `verified` after post-merge verification, and back to `rcf build --next`.
|
|
324
|
+
From here it is the five stages, a commit per stage, `--mark complete` after the merge, `rcf build finalise` to promote to `verified` after post-merge verification, and back to `rcf build bundle --next`.
|
|
325
325
|
|
|
326
326
|
## 11. Driving the whole queue
|
|
327
327
|
|
|
@@ -332,15 +332,15 @@ Sections 3 to 7 deliver one item. This section is the loop around them: how a si
|
|
|
332
332
|
**The loop.**
|
|
333
333
|
|
|
334
334
|
```
|
|
335
|
-
rcf build
|
|
336
|
-
rcf build --next -> bundle for that item
|
|
335
|
+
rcf build queue -> queue state; a "Next actionable" id means there is work
|
|
336
|
+
rcf build bundle --next -> bundle for that item
|
|
337
337
|
run its five stages (sections 3-7), commit per stage
|
|
338
|
-
rcf build <fbs-id>
|
|
339
|
-
rcf finalise <fbs-id> --url <deploy-url> (independent verify -> verified)
|
|
340
|
-
then rcf build --next again
|
|
338
|
+
rcf build mark <fbs-id> complete (after merge)
|
|
339
|
+
rcf build finalise <fbs-id> --url <deploy-url> (independent verify -> verified)
|
|
340
|
+
then rcf build bundle --next again
|
|
341
341
|
```
|
|
342
342
|
|
|
343
|
-
You are done when `rcf build --next` stops handing back bundles and prints instead:
|
|
343
|
+
You are done when `rcf build bundle --next` stops handing back bundles and prints instead:
|
|
344
344
|
|
|
345
345
|
```
|
|
346
346
|
# Build queue: nothing actionable
|
|
@@ -352,7 +352,7 @@ That line - not "I built the first one" - is the end of the loop. If it instead
|
|
|
352
352
|
|
|
353
353
|
**Keep the driving context thin (why one session is enough).** The reason a sixteen-item queue "won't fit in one session" is that the agent kept every item's bundle, diff and test detail in a single growing thread. It does not have to. If your harness can spawn sub-agents, run each FBS in its own worker:
|
|
354
354
|
|
|
355
|
-
- The driver (you) holds only the queue, the trace and the running tally of what is done. You call `rcf build --next`, hand the bundle id to a worker, and wait for a short structured result.
|
|
355
|
+
- The driver (you) holds only the queue, the trace and the running tally of what is done. You call `rcf build bundle --next`, hand the bundle id to a worker, and wait for a short structured result.
|
|
356
356
|
- The worker holds one item's full working set - the bundle, the diff, the tests, the referee outputs - runs the five stages, opens its PR, and returns a few lines: item id, ACs satisfied, referee outputs, PR link, and any escalation. Then its context is discarded.
|
|
357
357
|
- The driver's context stays flat across all sixteen items because it never holds more than a summary of any one. That is the mechanism that makes a small app's whole queue a single-session job.
|
|
358
358
|
|
|
@@ -362,7 +362,7 @@ Brief each worker with the same four things the bundle names: the item id, the f
|
|
|
362
362
|
|
|
363
363
|
**The handover protocol.** A handover is state capture, not a memory dump. A fresh session must be able to resume from it without re-eliciting anything or re-deriving the queue.
|
|
364
364
|
|
|
365
|
-
1. Run `rcf build` and `rcf validate` first, so the handover records the tree's true state, not your remembered state.
|
|
365
|
+
1. Run `rcf build` and `rcf define validate` first, so the handover records the tree's true state, not your remembered state.
|
|
366
366
|
2. Write a next-session handover doc (e.g. `rcf/handover.md`, or wherever the harness keeps session notes). It captures: what is complete/verified, what is in progress and exactly where it stopped, the next actionable id, any open escalation awaiting a ruling, and any decision taken in conversation that is not yet written into the tree.
|
|
367
367
|
3. Point the agent-instructions files at it. Add one line to `CLAUDE.md` and `AGENTS.md` telling the next session to read the handover before anything else. A handover doc nobody is instructed to open is not a handover.
|
|
368
368
|
|
|
@@ -381,8 +381,8 @@ When Finalise raises a PR, the body is for the reviewer - human or agent - and i
|
|
|
381
381
|
**The body, in this order:**
|
|
382
382
|
|
|
383
383
|
1. **What and why, traced.** What changed, mapped to the FBS and its in-scope ACs. The AC ids are the "why" - they are the spec this diff exists to satisfy, so a reviewer can check the diff against the promise, not against your description of it.
|
|
384
|
-
2. **Verification actually performed.** Not "tests pass". State what you ran and what it reported: the test command and its result, `rcf coverage --with-code` (or a story-scoped `rcf coverage <us-id> --strict`) with the per-AC lines, `rcf validate` clean. Paste the outputs - they are the evidence, and pasted referee output is not something a reviewer has to take on trust. **Every claim in this section names the runtime it was checked against** (section 15): "verified against the local preview", "e2e against wrangler dev (localhost)", "smoke-tested against the deployed runtime". A verification line with no named runtime is incomplete, and a line that implies the deployed runtime when the check never touched it is a defect, not a wording nicety.
|
|
385
|
-
3. **Per-AC evidence trail.** For each in-scope AC: where it is satisfied (file and symbol) and the test that proves it. This is what `rcf coverage --with-code` and `rcf trace` already give you; lift it in rather than reprose it.
|
|
384
|
+
2. **Verification actually performed.** Not "tests pass". State what you ran and what it reported: the test command and its result, `rcf audit coverage --with-code` (or a story-scoped `rcf audit coverage <us-id> --strict`) with the per-AC lines, `rcf define validate` clean. Paste the outputs - they are the evidence, and pasted referee output is not something a reviewer has to take on trust. **Every claim in this section names the runtime it was checked against** (section 15): "verified against the local preview", "e2e against wrangler dev (localhost)", "smoke-tested against the deployed runtime". A verification line with no named runtime is incomplete, and a line that implies the deployed runtime when the check never touched it is a defect, not a wording nicety.
|
|
385
|
+
3. **Per-AC evidence trail.** For each in-scope AC: where it is satisfied (file and symbol) and the test that proves it. This is what `rcf audit coverage --with-code` and `rcf audit trace` already give you; lift it in rather than reprose it.
|
|
386
386
|
4. **Known limits and deviations, declared.** Anything you escalated and how it was ruled, any deliberate deviation from the bundle and its reason, any gap the operator accepted. A declared limit survives review; the same limit found later by the reviewer is a defect and a trust hit.
|
|
387
387
|
|
|
388
388
|
**What not to do:** a file-by-file walk of the diff (the reviewer can read the diff), "all tests pass" with no command or output behind it, or any verification claim you did not actually run. Zero unverifiable claims - every line in the body is something the reviewer can independently check.
|
|
@@ -398,8 +398,8 @@ FBS-012 - MCP server over the full surface. Satisfies AC-301-1, AC-301-2, AC-301
|
|
|
398
398
|
|
|
399
399
|
## Verification performed
|
|
400
400
|
- <test command>: <result, e.g. 807 passing> (full suite) - runtime: <e.g. Node 24 on CI (local-dev), NOT the deployed runtime>
|
|
401
|
-
- rcf coverage --with-code: in-scope ACs covered, per-AC lines below
|
|
402
|
-
- rcf validate: tree is clean
|
|
401
|
+
- rcf audit coverage --with-code: in-scope ACs covered, per-AC lines below
|
|
402
|
+
- rcf define validate: tree is clean
|
|
403
403
|
- local preview: <how it was started and what was driven, e.g. `npm run dev`, seeded data, exercised path X>
|
|
404
404
|
<paste the referee outputs here>
|
|
405
405
|
|
|
@@ -422,9 +422,9 @@ A bug that reached a build is a bug a test did not catch, which is a behaviour a
|
|
|
422
422
|
|
|
423
423
|
**The order - do not jump to the code:**
|
|
424
424
|
|
|
425
|
-
1. **Reproduce, then trace the bug to its governing AC.** Which AC should have made the correct behaviour required? Walk the tree with `rcf trace` from the story or the offending source path, and `rcf coverage --with-code` to see whether the behaviour was ever covered at all.
|
|
425
|
+
1. **Reproduce, then trace the bug to its governing AC.** Which AC should have made the correct behaviour required? Walk the tree with `rcf audit trace` from the story or the offending source path, and `rcf audit coverage --with-code` to see whether the behaviour was ever covered at all.
|
|
426
426
|
2. **Name the gap.** Either no AC covers this scenario - the common case, usually a missing edge or failure path - or an AC covers it but too weakly (a happy-path AC where the bug lives in the failure path). Both are elicitation-depth misses; the standard for an adequate AC set is section 5 of the elicitation playbook.
|
|
427
|
-
3. **Fix the spec.** Add or strengthen the AC so the scenario is required (`rcf create ac` / `rcf update`), then add its TS/TC so the chain checks it. Now the tree would catch this class of bug on the next run.
|
|
427
|
+
3. **Fix the spec.** Add or strengthen the AC so the scenario is required (`rcf define create ac` / `rcf define update`), then add its TS/TC so the chain checks it. Now the tree would catch this class of bug on the next run.
|
|
428
428
|
4. **Fix the code against the corrected spec,** and prove it with the new test - the one that would have failed before your change and passes after it.
|
|
429
429
|
|
|
430
430
|
**Escalation:** if strengthening the AC changes agreed behaviour rather than closing an obvious gap, that is a spec decision, not a silent redraw. Surface it (section 8) before you change it. Tightening "returns an empty list on no match" onto an existing search AC is closing a gap; changing what the feature is supposed to do is a decision for the operator.
|
|
@@ -469,16 +469,16 @@ Both name the runtime, both refuse to imply the deployed profile, and both say p
|
|
|
469
469
|
|
|
470
470
|
## 16. In-loop fresh-context self-review
|
|
471
471
|
|
|
472
|
-
Self-verification is only as truthful as the runtime it verifies against, and a green suite plus a confident claim can still ship a user-facing defect. The independent verification gate is the durable answer to that, and it ships: `rcf finalise` runs the independent verifier against the deployed app and is the only thing that promotes an FBS from `complete` to `verified` (section 7). Nothing in this section changes that.
|
|
472
|
+
Self-verification is only as truthful as the runtime it verifies against, and a green suite plus a confident claim can still ship a user-facing defect. The independent verification gate is the durable answer to that, and it ships: `rcf build finalise` runs the independent verifier against the deployed app and is the only thing that promotes an FBS from `complete` to `verified` (section 7). Nothing in this section changes that.
|
|
473
473
|
|
|
474
474
|
What this section adds is the cheap check that runs **in the loop, between builds** - long before you reach the gate. Its value is finding the defect at FBS 6 instead of at the ship gate. It is subordinate to the gate, never a substitute for it, and it never writes `verified`.
|
|
475
475
|
|
|
476
476
|
- **What it is: a fresh-context reviewer dispatch, periodic and at the end.** Run a manual-review subagent in a fresh context **every few FBS builds** and **once more at the end of the build**. Fresh context matters: a reviewer carrying the build's own assumptions re-confirms them; a reviewer starting cold does not.
|
|
477
477
|
- **It drives the app, it does not read the code.** The reviewer starts the running application (the local preview is right there) and **drives it against the acceptance criteria** - exercises the real behaviour a user would - rather than reading the diff. Reading code re-checks intent; driving the app checks what was actually built.
|
|
478
478
|
- **It targets the defect classes green suites miss.** Name them for the reviewer: **session-class bugs** (state that leaks or resets across requests/sessions), **false-promise UI** (buttons and screens that imply an action the code never performs), **runtime mismatch** (passes on localhost, fails on the deployed runtime), **dead auth paths** (login/signup flows that never actually work end to end), and **dead code** (paths shipped but never reachable). These are exactly the classes a passing unit suite reports nothing about.
|
|
479
|
-
- **It is honestly scoped, and it is not the gate.** State plainly, every time: this is **an in-loop check, not the independent verification gate** - the gate is `rcf finalise` (section 7) - and it is **guidance and prompt-level, not a new subsystem**. A same-agent, same-programme reviewer is better than nothing and weaker than an independent check: worth running before the gate, not worth overclaiming after it. Say both. A self-review pass is never evidence for a `verified` mark; only the finalise gate produces that.
|
|
480
|
-
- **For UI-bearing FBSes, cross-reference to `rcf browser
|
|
481
|
-
- **Keep the review surface up across the pass.** `rcf view` gains `start | status | stop | logs` verbs and defaults to `--detach` on an interactive session (the pre-0.7.0 foreground default survives non-interactive callers, so CI scripts do not change behaviour). Start it once at the top of the loop; the supervisor persists across session death and the manifest carries `reviewSurface.viewServer` so a subsequent session can pick up where the last one left off. Explicit `rcf view stop` when the loop closes.
|
|
479
|
+
- **It is honestly scoped, and it is not the gate.** State plainly, every time: this is **an in-loop check, not the independent verification gate** - the gate is `rcf build finalise` (section 7) - and it is **guidance and prompt-level, not a new subsystem**. A same-agent, same-programme reviewer is better than nothing and weaker than an independent check: worth running before the gate, not worth overclaiming after it. Say both. A self-review pass is never evidence for a `verified` mark; only the finalise gate produces that.
|
|
480
|
+
- **For UI-bearing FBSes, cross-reference to `rcf verify browser`.** The in-loop reviewer's "drive the app against ACs" behaviour is a superset of what `rcf verify browser <fbs-id>` does (open every enumerated route on every declared theme, record the DOM, run the versioned invariant set, run the auth smoke pack). Reach for `rcf verify browser` first for uiBearing FBS: it writes a persisted `browserVerification[]` record on the manifest that the Stage 5 gate reads, and it names the exact invariants a passing browser check must satisfy. The self-review pass then adds the qualitative rubric on top (component consistency, typography, interaction affordances, modern-versus-dated feel) - the same rubric the browser-verify agent-mode critique carries on its record's `notes` field.
|
|
481
|
+
- **Keep the review surface up across the pass.** `rcf audit view` gains `start | status | stop | logs` verbs and defaults to `--detach` on an interactive session (the pre-0.7.0 foreground default survives non-interactive callers, so CI scripts do not change behaviour). Start it once at the top of the loop; the supervisor persists across session death and the manifest carries `reviewSurface.viewServer` so a subsequent session can pick up where the last one left off. Explicit `rcf audit view stop` when the loop closes.
|
|
482
482
|
|
|
483
483
|
## 17. Speaking to the operator
|
|
484
484
|
|
|
@@ -490,3 +490,60 @@ The queue, the bundles, the referee outputs and this playbook are your working v
|
|
|
490
490
|
- **Escalations lead with the decision.** Section 8's report shape is the content; deliver it in plain language, options short enough to choose between, one decision per message.
|
|
491
491
|
- **Check before you ask, and remember what you were granted.** Git state, remotes, CI status: run the command rather than asking. Permissions already given (branching, pushing, raising PRs): act on them; re-asking reads as not listening.
|
|
492
492
|
- **Confidence, honestly.** The operator steers; you drive the queue. Say what you are doing, not what the method requires of you, and say plainly when something is genuinely blocked - which is exactly when the operator must hear from you.
|
|
493
|
+
|
|
494
|
+
## 18. The driving playbook: method is yours, not the operator's
|
|
495
|
+
|
|
496
|
+
The three sections above (16 fresh-context self-review, 17 register) describe things the agent does. This section is why: the method's discipline runs on the driving side of the conversation, not the operator's. The operator states intent in plain words and expects to be guided; every method-shaped check, every chain-shaped finding, every named failure mode is the agent's job to carry out and translate. A build that only works because a non-technical operator noticed a missing acceptance criterion was, from the method's point of view, a broken build. Three behaviours make that concrete.
|
|
497
|
+
|
|
498
|
+
### 18.1 Validate the chain before you act on it
|
|
499
|
+
|
|
500
|
+
What good looks like:
|
|
501
|
+
|
|
502
|
+
- Every session boot runs `rcf define validate` before the first substantive turn, without the operator asking. A broken tree is reported to the operator in plain intent (18.2) and cleared before anything else. This is the "Session start" line from the harness fragment, taken seriously as a reflex rather than a suggestion.
|
|
503
|
+
- Every chain-touching operation runs the check that fits it, ahead of the operation, not after. Before `rcf build bundle --next`: `rcf define validate`. Before authoring or editing tree documents: `rcf define validate` on the current tree, so you start from a known-clean baseline. Before marking a stage complete: the referee output that gates that stage's exit. Before running a build spec you already hold: a fresh `rcf define validate` on the current state, because the tree may have moved since the bundle was fetched.
|
|
504
|
+
- On a scope-limited operation, run the scope-limited check first. `rcf audit coverage <us-id> --strict` before touching a story's tests; `rcf audit trace <ac-id>` before editing an AC with dependents. The tree-wide command is the default; a scope id narrows the read without weakening the gate.
|
|
505
|
+
|
|
506
|
+
Referee: the same referee the stage uses. The pre-action check does not replace the stage-end check; it moves the same check earlier, so drift is found before it costs a build.
|
|
507
|
+
|
|
508
|
+
Failure modes:
|
|
509
|
+
|
|
510
|
+
- **Reading the tree from memory.** Symptom: you plan against what the tree was two commits ago and the plan collides with the current state. Correction: never trust remembered tree state across a boundary (a new session, a returned dispatch, a merged PR); re-read via `rcf define validate` and the relevant `audit` verb.
|
|
511
|
+
- **Waiting to be asked.** Symptom: the operator has to say "run validate" before you run it. Correction: the check runs unprompted. If the operator ever has to name the verb, that is a defect in your driving, not a preference of theirs.
|
|
512
|
+
- **Skipping the check because "the bundle is fresh".** Symptom: you fetched the bundle five minutes ago and treat it as current truth after a merge, a tree edit, or a returned dispatch. Correction: freshness is measured in tree writes, not in wall-clock minutes.
|
|
513
|
+
|
|
514
|
+
Escalation: if the pre-action check fails and the finding is not a clean local fix (a missing field on one document), stop and surface it (18.2). Do not carry a broken tree into a build stage on the assumption it will sort itself out.
|
|
515
|
+
|
|
516
|
+
### 18.2 Surface findings in the operator's language
|
|
517
|
+
|
|
518
|
+
What good looks like:
|
|
519
|
+
|
|
520
|
+
- Every finding from a referee verb (`rcf define validate`, `rcf audit coverage`, `rcf audit trace`, `rcf audit impact`) is translated into the behaviour it is really about before it reaches the operator. The operator hears the missing check, not the missing row.
|
|
521
|
+
- The translation names the feature, not the document. "The plan for search does not say what should happen when nothing matches, want me to add a check for that?" beats "AC-207 has no covering TS". "Sign-up does not describe what happens on a bad token" beats "US-104's AC set is missing the failure path". If the operator asks "which id?", you name it; otherwise the id stays on disk.
|
|
522
|
+
- The plain-language surfacing is not a softening of the finding, it is a precise one. Method vocabulary compresses; plain language expands. If two chain findings translate to one plain-language ask, group them; if one chain finding translates to two distinct behaviour asks, split them. Faithful to the intent, not to the row count.
|
|
523
|
+
- One question at a time, decision-shaped. "Want me to add a check for that?" is a decision; "There is drift across three ACs, should I audit them?" is a hedge. When the finding needs a fix, propose the fix; when it needs a decision, put the decision.
|
|
524
|
+
|
|
525
|
+
Failure modes:
|
|
526
|
+
|
|
527
|
+
- **Reciting the referee output.** Symptom: the operator receives a paste of `rcf audit coverage --strict` with the offending row highlighted. Correction: keep referee output in the PR body and on disk; in chat, name the behaviour and the ask.
|
|
528
|
+
- **Method words leaking.** Symptom: "AC", "coverage", "traceability", "FBS", "chain", "strict" reach the operator on your side of the conversation. Correction: check the message before sending; those words belong in files. The exception is when the operator used them first.
|
|
529
|
+
- **Translating away the substance.** Symptom: "there is a small gap in the plan" hides that a whole failure path is missing. Correction: plain language is not vague language; the ask is as specific as the finding.
|
|
530
|
+
|
|
531
|
+
Escalation: if the finding is a spec-level ambiguity (two ACs cannot both hold, an AC has two readings that survive a careful read), section 8's escalation shape applies, still in plain language. Method terms do not become licit because the finding is complex.
|
|
532
|
+
|
|
533
|
+
### 18.3 The method's failure modes are yours to catch
|
|
534
|
+
|
|
535
|
+
What good looks like:
|
|
536
|
+
|
|
537
|
+
- Every failure mode named in this playbook is a self-check you run before it can turn into a defect. The sections above list them per stage; this subsection is the load-bearing statement that catching them is your job, not the operator's. A defect the operator has to spot in your work is a self-check you did not run.
|
|
538
|
+
- Before each stage-end commit, walk the stage's failure-mode list as a checklist. Stage 1: did the plan restate the FBS summary instead of the AC set; does any planned step trace to an AC id; did I keep the plan inside the bundle's scope. Stage 2: does every diff hunk map to an in-scope AC; did any new dependency arrive without an ADR; are Code Nodes authored as the code lands. Stage 3: did I walk the AC list as the outer loop, not the diff; is any deviation from the bundle documented, not smoothed over. Stage 4: did the referee actually run; does each test assert the AC's observable outcome and not the implementation's internals. Stage 5: is there any AC without a Code Node; am I marking complete before the merge, not after; does every verification claim name its runtime.
|
|
539
|
+
- The five escalation cases in section 8 are self-triggered too. You do not wait for the operator to notice the plan is stuck on an ambiguous AC; you stop, report the ambiguity in plain language (18.2), and wait.
|
|
540
|
+
- Test-honesty failure modes belong to you first. Editing a test to make it pass is the paradigm case: the referee has caught a real gap between code and spec, and rewriting the assertion hides the finding. When a test fails, the answer is to fix the code or fix the spec (RULE 4), never to fix the test into agreement with the wrong thing. Same for stubbing a broken pointer, deleting a failing assertion, or narrowing an AC to what the code happens to do.
|
|
541
|
+
- Build-scope failure modes belong to you first. Gold-plating past the AC set, silent dependency additions, refactors the bundle did not ask for, docs beyond the spec: the check is "did the bundle ask for this?", answered before the diff lands, not after review flags it.
|
|
542
|
+
|
|
543
|
+
Failure modes of the failure-mode discipline:
|
|
544
|
+
|
|
545
|
+
- **Waiting for the operator to notice.** Symptom: a defect is caught in operator review that a stage-end self-check would have caught. Correction: run the self-check at every stage end, and treat the operator's find as a signal to sharpen the checklist for the next item.
|
|
546
|
+
- **Self-check as narration.** Symptom: the report to the operator lists the checks you ran. Correction: the checks are silent; the report is the outcome. "Stage 4 done, coverage clean against the item's ACs" is the shape; the checklist itself stays on your side.
|
|
547
|
+
- **Trusting the referee to catch judgement failures.** Symptom: you rely on `rcf define validate` and `rcf audit coverage` to catch a test that is asserting the wrong thing. Correction: the referee checks structure; the judgement half (does this AC capture the intent; does this test assert the outcome, not the implementation) is your check, not the tool's. Overview §5 (Mechanical, not semantic) names the split.
|
|
548
|
+
|
|
549
|
+
Escalation: if the same failure mode recurs across items, that is a checklist gap or a bundle-shape gap; report it to the operator as a method-side finding (in plain language), not as a per-item slip.
|
package/guidance/build-cycle.md
CHANGED
|
@@ -1,23 +1,23 @@
|
|
|
1
1
|
# The RCF 5-stage build cycle
|
|
2
2
|
|
|
3
|
-
The normative statement of the cycle. Every FBS item is delivered by one pass of five stages, in this order, under these contracts. The spec bundle that `rcf build --next` emits carries the same cycle as its closing runbook, parameterised for the item in hand; if this page and a bundle ever disagree, the bundle is authoritative.
|
|
3
|
+
The normative statement of the cycle. Every FBS item is delivered by one pass of five stages, in this order, under these contracts. The spec bundle that `rcf build bundle --next` emits carries the same cycle as its closing runbook, parameterised for the item in hand; if this page and a bundle ever disagree, the bundle is authoritative.
|
|
4
4
|
|
|
5
5
|
## The five stages
|
|
6
6
|
|
|
7
7
|
**1. Define.**
|
|
8
|
-
Entry: you hold the item's spec bundle. Exit: your plan is confirmed against every in-scope acceptance criterion in the bundle's section 4, and pickup is recorded with `rcf build <fbs-id>
|
|
8
|
+
Entry: you hold the item's spec bundle. Exit: your plan is confirmed against every in-scope acceptance criterion in the bundle's section 4, and pickup is recorded with `rcf build mark <fbs-id> inProgress`. Referee: the bundle itself, plus `rcf define validate` on a clean tree.
|
|
9
9
|
|
|
10
10
|
**2. Build.**
|
|
11
|
-
Entry: a confirmed plan. Exit: the acceptance criteria are implemented, using the bundle's architectural context, with nothing beyond them; deviation from the bundle is escalation, not improvisation. Author or update Code Nodes (`rcf create cn --path <file>[#symbol] --acs <ac-ids>`) for the source as you write it - comprehension of which symbols serve which ACs is cheapest to capture now, and Stage 5 refuses completion without it. Referee: none at this stage beyond the bundle as the spec.
|
|
11
|
+
Entry: a confirmed plan. Exit: the acceptance criteria are implemented, using the bundle's architectural context, with nothing beyond them; deviation from the bundle is escalation, not improvisation. Author or update Code Nodes (`rcf define create cn --path <file>[#symbol] --acs <ac-ids>`) for the source as you write it - comprehension of which symbols serve which ACs is cheapest to capture now, and Stage 5 refuses completion without it. Referee: none at this stage beyond the bundle as the spec.
|
|
12
12
|
|
|
13
13
|
**3. Review.**
|
|
14
|
-
Entry: the implementation is complete. Exit: `rcf validate` comes back clean and the diff has been re-read against every in-scope acceptance criterion, with deviations documented. Referee: `rcf validate`.
|
|
14
|
+
Entry: the implementation is complete. Exit: `rcf define validate` comes back clean and the diff has been re-read against every in-scope acceptance criterion, with deviations documented. Referee: `rcf define validate`.
|
|
15
15
|
|
|
16
16
|
**4. Test.**
|
|
17
|
-
Entry: a reviewed diff. Exit: TS / TC documents and the tests they point to exist for the in-scope acceptance criteria, and `rcf coverage --strict` covers them - the referee checks the pointer, not just the row: a test case counts only when its `testPointer` resolves to a real test in the tree, and one that does not is reported as `covered-unresolved`, which fails the strict gate. Every "verified" or "tested" claim made in this stage names the runtime it was checked against and never implies verification on a deployed runtime that was not exercised. Referee: `rcf coverage --strict`.
|
|
17
|
+
Entry: a reviewed diff. Exit: TS / TC documents and the tests they point to exist for the in-scope acceptance criteria, and `rcf audit coverage --strict` covers them - the referee checks the pointer, not just the row: a test case counts only when its `testPointer` resolves to a real test in the tree, and one that does not is reported as `covered-unresolved`, which fails the strict gate. Every "verified" or "tested" claim made in this stage names the runtime it was checked against and never implies verification on a deployed runtime that was not exercised. Referee: `rcf audit coverage --strict`.
|
|
18
18
|
|
|
19
19
|
**5. Finalise.**
|
|
20
|
-
Entry: covered, reviewed work. Exit: CI green and the work merged per the driving workflow's convention, then `rcf build <fbs-id>
|
|
20
|
+
Entry: covered, reviewed work. Exit: CI green and the work merged per the driving workflow's convention, then `rcf build mark <fbs-id> complete` after the merge, and `verified` written by the finalise gate (`rcf build finalise <fbs-id> --url <deploy-url>`) once an independent post-merge verify run passes with ship authority. `--mark` caps at `complete` - it cannot write `verified`. `--mark complete` refuses (exit 3, missingCodeNodes) if any in-scope acceptance criterion still carries no Code Node - go back to Stage 2, or declare `--no-code-nodes` for a genuinely no-code spec. The PR body's verification section carries a runtime label on every claim. Referee: CI, the finalise gate, plus the mark commands' own refusals.
|
|
21
21
|
|
|
22
22
|
## Definition of done includes a working local preview
|
|
23
23
|
|
|
@@ -29,7 +29,7 @@ Each stage ends in a commit. The commit is the stage boundary: it makes the cycl
|
|
|
29
29
|
|
|
30
30
|
## The lifecycle is forward-only
|
|
31
31
|
|
|
32
|
-
`notStarted -> inProgress -> complete -> verified`. Forward jumps are legal, but the `--mark` ladder caps at `complete`: `--mark verified` is refused with exit 4 and points to `rcf finalise`, because `verified` is written only by the finalise gate after an independent verify run. Backward transitions are refused with exit 4; the deliberate-correction / manual-override escape hatch is `rcf update <fbs-id> --set executionStatus=<status>`, and reaching for it should be rare enough to be remarkable.
|
|
32
|
+
`notStarted -> inProgress -> complete -> verified`. Forward jumps are legal, but the `--mark` ladder caps at `complete`: `--mark verified` is refused with exit 4 and points to `rcf build finalise`, because `verified` is written only by the finalise gate after an independent verify run. Backward transitions are refused with exit 4; the deliberate-correction / manual-override escape hatch is `rcf define update <fbs-id> --set executionStatus=<status>`, and reaching for it should be rare enough to be remarkable.
|
|
33
33
|
|
|
34
34
|
## Depth
|
|
35
35
|
|
|
@@ -26,7 +26,7 @@ One page per document type, the reference rule that keeps the tree drift-proof,
|
|
|
26
26
|
|
|
27
27
|
**TC (Test Case).** One test: which AC it verifies, where the executable test lives (its test pointer), and its status.
|
|
28
28
|
|
|
29
|
-
**CN (Code Node).** The spec-to-code bridge: a working-tree source path, optionally `#symbol`-suffixed, that implements one or more acceptance criteria (`implementsAcIds`, which may be empty - an orphan CN is a legitimate state for utilities and glue code). `rcf validate` checks every CN's path/symbol against the working tree, so a rename or deletion that leaves the pointer dangling is caught the same way a broken spec-side reference is. Author CNs during Stage 2 of the build cycle (see below), not after: `rcf build
|
|
29
|
+
**CN (Code Node).** The spec-to-code bridge: a working-tree source path, optionally `#symbol`-suffixed, that implements one or more acceptance criteria (`implementsAcIds`, which may be empty - an orphan CN is a legitimate state for utilities and glue code). `rcf define validate` checks every CN's path/symbol against the working tree, so a rename or deletion that leaves the pointer dangling is caught the same way a broken spec-side reference is. Author CNs during Stage 2 of the build cycle (see below), not after: `rcf build mark <fbs-id> complete` refuses when an in-scope acceptance criterion has none. Full detail, including the honest limits, is `docs/code-nodes.md` in the rcf-build-lite repo.
|
|
30
30
|
|
|
31
31
|
## Edges live on the child
|
|
32
32
|
|