baldart 4.89.1 → 4.92.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 +87 -0
- package/VERSION +1 -1
- package/framework/.claude/agents/api-perf-cost-auditor.md +9 -0
- package/framework/.claude/agents/code-reviewer.md +9 -0
- package/framework/.claude/agents/codebase-architect.md +6 -0
- package/framework/.claude/agents/coder.md +1 -1
- package/framework/.claude/agents/markup-fidelity-verifier.md +24 -1
- package/framework/.claude/agents/qa-sentinel.md +9 -0
- package/framework/.claude/agents/security-reviewer.md +9 -0
- package/framework/.claude/agents/ui-expert.md +49 -0
- package/framework/.claude/agents/visual-fidelity-verifier.md +16 -12
- package/framework/.claude/skills/e2e-review/CHANGELOG.md +49 -0
- package/framework/.claude/skills/e2e-review/SKILL.md +178 -24
- package/framework/.claude/skills/new/CHANGELOG.md +29 -0
- package/framework/.claude/skills/new/SKILL.md +44 -2
- package/framework/.claude/skills/new/references/completeness.md +1 -0
- package/framework/.claude/skills/new/references/implement.md +19 -3
- package/framework/.claude/skills/new/references/review-cycle.md +23 -1
- package/framework/.claude/skills/new/references/team-mode.md +4 -0
- package/framework/.claude/skills/new/scripts/verify-item.sh +54 -0
- package/framework/.claude/skills/new2/CHANGELOG.md +30 -0
- package/framework/.claude/skills/new2/SKILL.md +35 -8
- package/framework/.claude/skills/ui-implement/CHANGELOG.md +15 -0
- package/framework/.claude/skills/ui-implement/SKILL.md +31 -6
- package/framework/.claude/skills/ui-implement/references/integration.md +12 -3
- package/framework/.claude/skills/ui-implement/scripts/check-bindings.mjs +103 -0
- package/framework/.claude/workflows/new-card-review.js +19 -5
- package/framework/.claude/workflows/new-final-review.js +24 -9
- package/framework/.claude/workflows/new2.js +50 -4
- package/framework/agents/code-search-protocol.md +24 -0
- package/framework/agents/design-system-protocol.md +27 -0
- package/framework/docs/WORKFLOWS.md +9 -4
- package/framework/scripts/structural-compare.mjs +178 -0
- package/package.json +1 -1
- package/src/commands/update.js +51 -5
|
@@ -1,7 +1,7 @@
|
|
|
1
1
|
---
|
|
2
2
|
name: e2e-review
|
|
3
3
|
effort: medium
|
|
4
|
-
version: 1.
|
|
4
|
+
version: 1.2.0
|
|
5
5
|
description: >
|
|
6
6
|
Deterministic, BLOCKING end-to-end review run after a feature is implemented.
|
|
7
7
|
Combines functional E2E (Playwright spec written by `coder`, executed via
|
|
@@ -181,10 +181,18 @@ system constraints into a machine-readable verification plan.
|
|
|
181
181
|
}
|
|
182
182
|
],
|
|
183
183
|
"non_functional_checks": ["loads in < 2s on slow 3G"],
|
|
184
|
-
"mockup_refs": [{"route": "/dashboard", "level": "local", "path": "mockups/dashboard.png"}]
|
|
184
|
+
"mockup_refs": [{"route": "/dashboard", "level": "local", "path": "mockups/dashboard.png"}],
|
|
185
|
+
"tablet_in_scope": false
|
|
185
186
|
}
|
|
186
187
|
```
|
|
187
188
|
|
|
189
|
+
5. **Tablet-in-scope detection (deterministic).** Set `tablet_in_scope: true` when
|
|
190
|
+
the card's title, `acceptance_criteria[]`, `scope`, or `requirements[]` mention
|
|
191
|
+
`tablet` (case-insensitive) or an explicit breakpoint in the 768–1024px band.
|
|
192
|
+
This drives the optional third viewport capture (Phase 3) and the tablet
|
|
193
|
+
responsive pass (Phase 4 step 2c). Default `false` — the tablet lane is
|
|
194
|
+
scope-driven, not unconditional (cost discipline).
|
|
195
|
+
|
|
188
196
|
---
|
|
189
197
|
|
|
190
198
|
## Phase 2 — Mockup Source Cascade (4 levels)
|
|
@@ -227,8 +235,17 @@ directory alongside its YAML:
|
|
|
227
235
|
|
|
228
236
|
**Structural source (route-free ground truth).** Independently of the image, record a
|
|
229
237
|
`structural_source` for the route when the mockup is **code**:
|
|
230
|
-
- `links.design` is an `.html` file →
|
|
231
|
-
|
|
238
|
+
- `links.design` is an `.html` file → FIRST probe it for an encoded Claude Design
|
|
239
|
+
offline bundle: run `node .framework/framework/scripts/extract-mockup-design.mjs
|
|
240
|
+
--input <abs html path> --out .baldart/e2e-review/<CARD-ID>/mockups/_src/` (always
|
|
241
|
+
exits 0, one JSON line on stdout). On `status: "ok"` the decoded JSX/CSS is the
|
|
242
|
+
richer ground truth → `structural_source = { level: "design_src", design_src_dir:
|
|
243
|
+
".baldart/e2e-review/<CARD-ID>/mockups/_src/" }`. On `status: "no-code"` /
|
|
244
|
+
`"skipped"` the raw markup is still diffable → `structural_source = { level:
|
|
245
|
+
"html", mockup_path: "<abs html path>" }`. **Never leave an `.html` mockup with no
|
|
246
|
+
`structural_source`** — a decode failure downgrades the source, it does not drop
|
|
247
|
+
the structural lane (that was the handoff gap that let an HTML mockup skip Phase
|
|
248
|
+
2.7 entirely).
|
|
232
249
|
- `links.design_src` is set / `mockups/_src/` exists (finished Claude Design CODE, v4.75)
|
|
233
250
|
→ `structural_source = { level: "design_src", design_src_dir: "<abs dir>" }`.
|
|
234
251
|
This feeds Phase 2.7 (`markup-fidelity-verifier`) and is what makes per-card fidelity
|
|
@@ -258,6 +275,35 @@ If none of (a)–(c) apply (no mockup, no design system):
|
|
|
258
275
|
|
|
259
276
|
The cascade output is appended to the plan under `mockup_refs[]`.
|
|
260
277
|
|
|
278
|
+
### Phase 2 closing step — Lane Matrix (verification-coverage ledger)
|
|
279
|
+
|
|
280
|
+
SSOT: `design-system-protocol.md` § "Route-Independent Fidelity & Coverage
|
|
281
|
+
Obligation" → 6. Verification-Lane Ledger. After the cascade, derive the
|
|
282
|
+
**planned lanes** per route and persist them into `plan.json` under `lanes`:
|
|
283
|
+
|
|
284
|
+
```json
|
|
285
|
+
"lanes": {
|
|
286
|
+
"/dashboard": {
|
|
287
|
+
"structural": "planned", // iff a structural_source was recorded
|
|
288
|
+
"visual_desktop": "planned", // iff mockup_source.level ∈ {figma, local, compliance-only}
|
|
289
|
+
"visual_mobile": "planned", // iff the route is renderable-in-plan and not marked desktop-only
|
|
290
|
+
"visual_tablet": "planned", // iff plan.tablet_in_scope == true (same renderability condition)
|
|
291
|
+
"quality": "planned", // iff a quality oracle exists (has_design_system OR ui_guidelines)
|
|
292
|
+
"functional": "planned" // iff ≥1 scenario touches the route
|
|
293
|
+
}
|
|
294
|
+
}
|
|
295
|
+
```
|
|
296
|
+
|
|
297
|
+
A lane that does not meet its condition is recorded `"not_planned"` (it will never
|
|
298
|
+
be asserted). As each later phase runs, update the route's lane in the state
|
|
299
|
+
directory to `"ran"` or `"skipped:<authorized reason>"` — this ledger is what
|
|
300
|
+
Phase 5 step 0 reconciles. The authorized skip reasons are ONLY:
|
|
301
|
+
`pixel_diff_below_threshold` (visual pre-filter passed — the comparison DID run),
|
|
302
|
+
`render_unavailable_structural_covered` (Phase 3.8 outcome on a code-form mockup),
|
|
303
|
+
`no_quality_oracle`, `harness_render_fidelity_guard`, `desktop_only_route`
|
|
304
|
+
(responsive passes), `quality_prefilter_skip` (Phase 4b gate). Anything else left
|
|
305
|
+
un-run is an under-run and blocks (Phase 5 step 0).
|
|
306
|
+
|
|
261
307
|
---
|
|
262
308
|
|
|
263
309
|
## Phase 2.7 — Structural Fidelity (route-free, runs BEFORE the browser)
|
|
@@ -278,6 +324,20 @@ For each such route:
|
|
|
278
324
|
1. **Resolve the implementation files** for the route from the diff / the card's File
|
|
279
325
|
Ownership Map (the `*.tsx` / `*.css` / `*.module.css` / `*.scss` / `*.svelte` / `*.vue`
|
|
280
326
|
the card touched under `${paths.app_dir}` / `${paths.components_root}`).
|
|
327
|
+
1b. **Deterministic pre-gate (structural-compare.mjs — signals, not verdicts).** Run:
|
|
328
|
+
|
|
329
|
+
```bash
|
|
330
|
+
node .framework/framework/scripts/structural-compare.mjs \
|
|
331
|
+
--mockup <structural_source dir|file> --impl <implementation files> \
|
|
332
|
+
> .baldart/e2e-review/<CARD-ID>/structural-signals-<route-slug>.json
|
|
333
|
+
```
|
|
334
|
+
|
|
335
|
+
One JSON line (`match | divergence | skipped` + graded-confidence findings). The
|
|
336
|
+
signals do NOT replace the verifier (a regex signature cannot see grids/landmarks
|
|
337
|
+
owned by composed primitives — necessary, not sufficient) and a `match` never
|
|
338
|
+
authorizes skipping step 2. They are **focus hints**: pass them to the verifier
|
|
339
|
+
below so it confirms or dismisses each deterministic signal explicitly instead of
|
|
340
|
+
rediscovering the obvious. Script errors fail open (`skipped`).
|
|
281
341
|
2. **Invoke `markup-fidelity-verifier`** (input contract in
|
|
282
342
|
[`markup-fidelity-verifier.md`](../../agents/markup-fidelity-verifier.md)):
|
|
283
343
|
|
|
@@ -295,7 +355,8 @@ For each such route:
|
|
|
295
355
|
"mockup_source": { ...the route's structural_source (html | design_src)... },
|
|
296
356
|
"implementation_files": [ ...abs paths the card touched for this route... ],
|
|
297
357
|
"tolerance": "<from config>",
|
|
298
|
-
"resolved_orphans": [ ...from the card's UI Element Inventory, as in Phase 4... ]
|
|
358
|
+
"resolved_orphans": [ ...from the card's UI Element Inventory, as in Phase 4... ],
|
|
359
|
+
"deterministic_signals": { ...the structural-compare.mjs output from step 1b... }
|
|
299
360
|
}
|
|
300
361
|
```
|
|
301
362
|
3. **Parse the JSON strictly** (same discipline as Phase 4). On malformed output log
|
|
@@ -360,9 +421,19 @@ capture the result + screenshots per route.
|
|
|
360
421
|
path: ".baldart/e2e-review/<CARD-ID>/screenshots/<route-slug>@mobile.png",
|
|
361
422
|
fullPage: true
|
|
362
423
|
});
|
|
424
|
+
// Tablet — ONLY when plan.tablet_in_scope == true (Phase 1 step 5).
|
|
425
|
+
await page.setViewportSize({ width: 768, height: 1024 });
|
|
426
|
+
await page.goto(route);
|
|
427
|
+
await page.waitForLoadState("networkidle");
|
|
428
|
+
await page.screenshot({
|
|
429
|
+
path: ".baldart/e2e-review/<CARD-ID>/screenshots/<route-slug>@tablet.png",
|
|
430
|
+
fullPage: true
|
|
431
|
+
});
|
|
363
432
|
Both screenshot paths are consumed by the visual-fidelity-verifier in
|
|
364
433
|
Phase 4 — do not change them. 375px is the canonical small-screen audit
|
|
365
|
-
width
|
|
434
|
+
width and 768px the canonical tablet audit width (design-system-protocol
|
|
435
|
+
Reference Tables); they are fixed, not config keys. Omit the tablet block
|
|
436
|
+
entirely when `tablet_in_scope` is false.
|
|
366
437
|
- For OTP-driven personas (test_plan.test_credentials.auth_method == "otp"),
|
|
367
438
|
use `await page.pause()` between phone-entry and code-entry. Document
|
|
368
439
|
the manual step in a test.step block.
|
|
@@ -470,10 +541,18 @@ still wrong).
|
|
|
470
541
|
For each `route` in `plan.routes[]`:
|
|
471
542
|
|
|
472
543
|
1. **Pre-filter with pixel-diff** (optimization to control Vision cost):
|
|
473
|
-
-
|
|
474
|
-
|
|
475
|
-
|
|
476
|
-
|
|
544
|
+
- **1a-pre. Viewport-dimension validation (BEFORE any diff).** Compare the
|
|
545
|
+
implementation screenshot's pixel WIDTH with the mockup image's (±5px for
|
|
546
|
+
rounding). On mismatch, the pixel-diff is meaningless — a diff computed
|
|
547
|
+
across different widths can land under the threshold while hiding a real
|
|
548
|
+
misalignment (the false-negative channel), or blow to 100% noise. Do NOT
|
|
549
|
+
run the pre-filter: log `viewport_dimension_mismatch (<impl>w vs <mock>w)`
|
|
550
|
+
in `gaps[]` and go DIRECTLY to step 2 (the Vision comparison judges
|
|
551
|
+
content, not pixel alignment). Never resize either image to force the diff.
|
|
552
|
+
- When `mockup_source.level in {figma, local}` (and dimensions validated), run
|
|
553
|
+
a pixel-level diff (any cheap library: `pixelmatch`, `looks-same`, or even
|
|
554
|
+
ImageMagick's `compare -metric AE`) between the implementation screenshot
|
|
555
|
+
and the mockup. Pass `pixel_diff_threshold` from config (default `0.02` = 2%).
|
|
477
556
|
- If the diff is **below** the threshold, skip the Vision call for this
|
|
478
557
|
route and record an empty findings array with
|
|
479
558
|
`pre_filter: "pixel_diff_below_threshold"`. This is the primary
|
|
@@ -561,6 +640,14 @@ For each `route` in `plan.routes[]`:
|
|
|
561
640
|
desktop-only in the plan. Cost is ~one extra verifier call per route — measured
|
|
562
641
|
marginal (~0.3% of a card run) because the 375px screenshot is lighter than the
|
|
563
642
|
1440px one and only renderable routes incur it.
|
|
643
|
+
2c. **Tablet responsive-integrity pass** *(only when `plan.tablet_in_scope ==
|
|
644
|
+
true`)*. Same contract as step 2b with the `<route-slug>@tablet.png`
|
|
645
|
+
screenshot, `"viewport": { "width": 768, "height": 1024 }` and
|
|
646
|
+
`viewport_role: "tablet"`. This closes the "responsive middle" gap: a card
|
|
647
|
+
whose ACs promise tablet behaviour (the 768–1024px band) was previously
|
|
648
|
+
verified only at 1440px + 375px, so a grid that collapses at the wrong
|
|
649
|
+
breakpoint hid between the two audited widths. Findings are tagged
|
|
650
|
+
`viewport_role: "tablet"` and deduplicate alongside the other passes.
|
|
564
651
|
3. **Parse the agent's JSON response** strictly. If the response is malformed
|
|
565
652
|
or contains prose outside the JSON, log
|
|
566
653
|
`verifier_protocol_violation` in `gaps[]` and treat the route's findings
|
|
@@ -596,7 +683,24 @@ mockup) **and `mockup_source.level == "harness-render"` per-primitive PNGs from
|
|
|
596
683
|
arrive here, NEVER at Phase 4 fidelity). Skip a route only when no screenshot was
|
|
597
684
|
captured, or when BOTH `features.has_design_system: false` AND
|
|
598
685
|
`${paths.ui_guidelines}` is unset (no quality oracle at all — log
|
|
599
|
-
`no_quality_oracle` in `gaps[]`)
|
|
686
|
+
`no_quality_oracle` in `gaps[]`), or on the **quality pre-filter** below.
|
|
687
|
+
|
|
688
|
+
**Quality pre-filter skip (authorized lane skip).** When ALL of these hold for a
|
|
689
|
+
route, skip the critic and mark the route's quality lane
|
|
690
|
+
`skipped:quality_prefilter_skip` in the Lane Matrix:
|
|
691
|
+
- `features.has_design_system: true` (the surface is built from a governed
|
|
692
|
+
registry), AND
|
|
693
|
+
- the route's structural lane (Phase 2.7) ran with ZERO gating findings, AND
|
|
694
|
+
- the route's desktop visual pass was pre-filtered clean
|
|
695
|
+
(`pixel_diff_below_threshold` — the render is pixel-faithful to an
|
|
696
|
+
APPROVED mockup).
|
|
697
|
+
Rationale: quality scoring is advisory-leaning by calibration
|
|
698
|
+
(`design-system-protocol.md` § Gating philosophy), and a render that is both
|
|
699
|
+
structure- and pixel-faithful to a user-approved mockup composed of governed
|
|
700
|
+
primitives has no room for a *gating* quality finding — the critic spawn is pure
|
|
701
|
+
cost there. **Never apply this skip to `harness-render` PNGs** (isolated quality
|
|
702
|
+
IS their purpose) or when the route has no mockup (`level: skip` — the critic is
|
|
703
|
+
then the only design oracle). **i18n note:** a harness PNG flagged
|
|
600
704
|
`i18n-incomplete` (raw `t()` keys rendered — no provider) is passed with that
|
|
601
705
|
disclaimer so the critic does not raise false `typography`/`hierarchy` findings on
|
|
602
706
|
placeholder text.
|
|
@@ -645,6 +749,23 @@ For each such `route`:
|
|
|
645
749
|
**Goal**: combine functional + visual findings into a single verdict using
|
|
646
750
|
the canonical severity taxonomy from `visual-fidelity-verifier.md`.
|
|
647
751
|
|
|
752
|
+
0. **Lane-coverage assertion (runs FIRST — before any verdict math).** SSOT:
|
|
753
|
+
`design-system-protocol.md` § "...→ 6. Verification-Lane Ledger". Reconcile
|
|
754
|
+
the Lane Matrix from Phase 2 against what actually executed: every
|
|
755
|
+
route×lane marked `"planned"` must now be `"ran"` or
|
|
756
|
+
`"skipped:<authorized reason>"` (the closed reason set from the Phase 2
|
|
757
|
+
closing step). For every planned lane still `not_run`, synthesize a
|
|
758
|
+
**`verification-coverage-gap`** finding (Critical, `source: "coverage"`,
|
|
759
|
+
`route`, `lane`, `description: "planned lane never executed"`). Like
|
|
760
|
+
`coverage-gap`, it is NOT fixable by an agent — it bypasses the Phase 5b
|
|
761
|
+
self-heal loop and maps to `blocked`. This is the global guard against the
|
|
762
|
+
FEAT-0064 under-run (a "fidelity review" in which the visual + quality
|
|
763
|
+
verifiers were never spawned and the verdict recorded nothing): a lane
|
|
764
|
+
under-run can never again surface as a pass. There is NO self-served
|
|
765
|
+
"accepted (harness limit)" verdict — accepting an un-run lane requires the
|
|
766
|
+
explicit override path (manual mode, human reason) or the caller's
|
|
767
|
+
escalation (programmatic mode returns `blocked`).
|
|
768
|
+
|
|
648
769
|
1. **Compose** the `findings[]` array:
|
|
649
770
|
- **Structural findings** from Phase 2.7 (`source: "structural"`) — route-free
|
|
650
771
|
code-structure divergence (`markup-fidelity-verifier`).
|
|
@@ -654,12 +775,15 @@ the canonical severity taxonomy from `visual-fidelity-verifier.md`.
|
|
|
654
775
|
orchestrator-synthesized `coverage-gap` (Phase 4 step 1c — a required check that
|
|
655
776
|
could not run at all).
|
|
656
777
|
- Design-quality findings from Phase 4b (`source: "design-quality"`).
|
|
778
|
+
- Coverage findings from step 0 (`source: "coverage"` —
|
|
779
|
+
`verification-coverage-gap`).
|
|
657
780
|
- Each finding carries: `severity`, `category` (or `dimension` for
|
|
658
781
|
design-quality), `source`, `route`, `description`, `expected`, `actual`,
|
|
659
782
|
`fix_hint`, `evidence`, `ds_drift_code`, `confidence`. All sources
|
|
660
783
|
share the **same canonical severity taxonomy**, so the tolerance filter in
|
|
661
|
-
step 2 applies to them uniformly — no per-source special-casing. (`coverage-gap
|
|
662
|
-
and `data-state-mismatch` are Critical and gate in
|
|
784
|
+
step 2 applies to them uniformly — no per-source special-casing. (`coverage-gap`,
|
|
785
|
+
`verification-coverage-gap` and `data-state-mismatch` are Critical and gate in
|
|
786
|
+
every tolerance.)
|
|
663
787
|
2. **Apply tolerance filter** based on
|
|
664
788
|
`features.e2e_review.fidelity_tolerance`:
|
|
665
789
|
- `strict` (DEFAULT): Critical + Major + Minor all gate. Additionally,
|
|
@@ -680,12 +804,13 @@ applies only when `verdict == "blocked"` AND `iteration < max`.
|
|
|
680
804
|
|
|
681
805
|
For each iteration:
|
|
682
806
|
|
|
683
|
-
0. **`coverage-gap` findings bypass the loop.**
|
|
684
|
-
agent (the route still will not render —
|
|
685
|
-
|
|
686
|
-
|
|
687
|
-
|
|
688
|
-
|
|
807
|
+
0. **`coverage-gap` and `verification-coverage-gap` findings bypass the loop.** Neither is
|
|
808
|
+
fixable by any agent (`coverage-gap`: the route still will not render — a harness/data
|
|
809
|
+
limitation; `verification-coverage-gap`: a planned lane never executed — an
|
|
810
|
+
orchestration failure, not a code defect). Do NOT spawn a fixer for either. They keep
|
|
811
|
+
the verdict `blocked` and flow straight to the override path below (programmatic mode
|
|
812
|
+
returns `blocked`; `/new` escalates to a follow-up card). If coverage findings are the
|
|
813
|
+
ONLY gating findings, skip the rest of this loop entirely.
|
|
689
814
|
|
|
690
815
|
1. **Route the remaining gating findings to the right fixer by `source`**, then spawn the
|
|
691
816
|
fixer(s). **Fidelity is UI-scoped**: `source == "structural"` (layout/grid/order —
|
|
@@ -713,7 +838,8 @@ For each iteration:
|
|
|
713
838
|
|
|
714
839
|
## Rules
|
|
715
840
|
- File ownership: stay within the card's allowed file set (see
|
|
716
|
-
/
|
|
841
|
+
"$(git rev-parse --git-common-dir)/baldart/run/batch-tracker-<FIRST-CARD-ID>.md"
|
|
842
|
+
## File Ownership Map — the durable tracker location, new/SKILL.md § Context Tracking).
|
|
717
843
|
- One fix per finding. Reuse existing tokens / primitives before inventing
|
|
718
844
|
new ones (cite ${paths.design_system}/INDEX.md + tokens-reference.md).
|
|
719
845
|
- For a `structural` `layout-break`, match the mockup's layout exactly (e.g.
|
|
@@ -740,7 +866,8 @@ For each iteration:
|
|
|
740
866
|
|
|
741
867
|
## Rules
|
|
742
868
|
- File ownership: stay within the card's allowed file set (see
|
|
743
|
-
/
|
|
869
|
+
"$(git rev-parse --git-common-dir)/baldart/run/batch-tracker-<FIRST-CARD-ID>.md"
|
|
870
|
+
## File Ownership Map — the durable tracker location, new/SKILL.md § Context Tracking).
|
|
744
871
|
- One fix per finding when possible. Reuse existing tokens / primitives
|
|
745
872
|
before inventing new ones (cite ${paths.design_system}/INDEX.md +
|
|
746
873
|
tokens-reference.md).
|
|
@@ -753,12 +880,27 @@ For each iteration:
|
|
|
753
880
|
|
|
754
881
|
Both fixers run in `bypassPermissions` mode when called by `/new`.
|
|
755
882
|
|
|
883
|
+
**Spawn ONLY the non-empty bucket(s)** — when every gating finding is UI-scoped,
|
|
884
|
+
no `coder` is spawned (and vice versa); a fixer with an empty findings list is a
|
|
885
|
+
wasted spawn.
|
|
886
|
+
|
|
756
887
|
2. **Re-run the affected verifiers**: Phase 2.7 (structural, route-free — re-run when a
|
|
757
888
|
`structural` fix was applied), Phase 3 (functional), Phase 3.8 (re-render / state),
|
|
758
889
|
Phase 4 (visual), and Phase 4b (quality) with fresh screenshots. Increment `iteration`.
|
|
759
|
-
(A `coverage-gap`-only block does not enter this loop — see step 0.)
|
|
760
|
-
|
|
761
|
-
|
|
890
|
+
(A `coverage-gap`-only block does not enter this loop — see step 0.) Deliberately NOT
|
|
891
|
+
narrowed to "only the lane that failed": a fix can regress a lane that previously
|
|
892
|
+
passed, and a selectively-skipped lane would be exactly the under-run the Phase 5
|
|
893
|
+
step 0 Lane-Ledger assertion exists to block. The Phase 4 pixel-diff pre-filter and
|
|
894
|
+
the Phase 4b quality pre-filter already make a clean re-run cheap.
|
|
895
|
+
3. **Re-aggregate and re-decide** (back to Phase 5 step 1), with **convergence
|
|
896
|
+
detection (v4.92.0)**: compare the new gating-finding set with the pre-fix one by
|
|
897
|
+
`(route, source, category, region)`. If the fix produced **NEW gating findings that
|
|
898
|
+
were not present before** (the fixer is regressing while fixing — the documented
|
|
899
|
+
non-convergent failure mode), do NOT burn another iteration: STOP the loop now and
|
|
900
|
+
transition to the override path with both sets in the report (`convergence:
|
|
901
|
+
"diverging"`). Shrinking-or-equal sets keep iterating normally.
|
|
902
|
+
4. **STOP** when `verdict == "passed"` OR `iteration == max` OR convergence detection
|
|
903
|
+
fired (step 3).
|
|
762
904
|
|
|
763
905
|
When the loop exhausts iterations and findings remain, transition to the
|
|
764
906
|
**override path** below.
|
|
@@ -796,6 +938,17 @@ Write the final report to `.baldart/e2e-review/<CARD-ID>/report.json`:
|
|
|
796
938
|
"compliance-only": 1,
|
|
797
939
|
"skip": 0
|
|
798
940
|
},
|
|
941
|
+
"lane_coverage": "complete" | "incomplete",
|
|
942
|
+
"lanes": {
|
|
943
|
+
"/dashboard": {
|
|
944
|
+
"structural": "ran",
|
|
945
|
+
"visual_desktop": "skipped:pixel_diff_below_threshold",
|
|
946
|
+
"visual_mobile": "ran",
|
|
947
|
+
"visual_tablet": "not_planned",
|
|
948
|
+
"quality": "ran",
|
|
949
|
+
"functional": "ran"
|
|
950
|
+
}
|
|
951
|
+
},
|
|
799
952
|
"functional": {
|
|
800
953
|
"scenarios_total": 5,
|
|
801
954
|
"passed": 5,
|
|
@@ -908,6 +1061,7 @@ and starts from Phase 3 (skipping plan extraction and mockup cascade).
|
|
|
908
1061
|
| `quality_critic_protocol_violation` in gaps | `ui-quality-critic` returned prose mixed with JSON | Re-spawn the critic once; if persistent, surface to user (likely a model regression). Treat that route's quality findings as empty meanwhile |
|
|
909
1062
|
| `verifier_protocol_violation` in gaps | `visual-fidelity-verifier` returned prose mixed with JSON | Re-spawn the verifier once; if persistent, surface to user (likely a model regression) |
|
|
910
1063
|
| `coverage-gap` (Critical) on a route | An image-only mockup route could not be rendered in any lane and its state could not be reached | Correct by design — the gate BLOCKS instead of silently passing. Add a reach-state recipe to `.baldart/overlays/e2e-review.md` (seed / select populated context), or provide an HTML/`design_src` mockup so the route-free structural pass covers it. Never override without fixing the lane |
|
|
1064
|
+
| `verification-coverage-gap` (Critical) on a route×lane | A lane the Phase 2 Lane Matrix planned was never executed (verifier not spawned / phase silently skipped) — the FEAT-0064 under-run | Correct by design — an under-run blocks, never passes. Re-run the skill; if the lane keeps under-running, that is an orchestration bug to report, not a finding to override |
|
|
911
1065
|
| `data-state-mismatch` (Critical) on a route | Render opened an empty / wrong-tenant / error state; mockup depicts a populated state | The reach-state loop (Phase 3.8) should seed/select a populated context. If it has no recipe and cannot auto-seek, add `select_populated_context` / `seed_data` to the e2e-review overlay |
|
|
912
1066
|
| `markup_verifier_protocol_violation` in gaps | `markup-fidelity-verifier` returned prose mixed with JSON | Re-spawn once; if persistent, surface to user. Treat that route's structural findings as empty meanwhile |
|
|
913
1067
|
|
|
@@ -2,6 +2,35 @@
|
|
|
2
2
|
|
|
3
3
|
Formato: [Keep a Changelog](https://keepachangelog.com/) · [SemVer](https://semver.org/).
|
|
4
4
|
|
|
5
|
+
## 1.3.0 — 2026-07-02
|
|
6
|
+
|
|
7
|
+
- **Hot-file economy (T2.A)**: il briefing "Codebase Context" passa il baseline
|
|
8
|
+
per PATH (`/tmp/arch-baseline-<CARD-ID>.md`, guardia `[BASELINE-READ-FAIL]`) e
|
|
9
|
+
la disciplina range-read sui file > 800 righe è SSOT in
|
|
10
|
+
`code-search-protocol.md` § "Large-file read discipline" (Hot-File Map emesso
|
|
11
|
+
dal contratto terse di `codebase-architect`).
|
|
12
|
+
- **Empty-scope guard (T2.B)**: Phase 2.5x + team-mode D.1.6 non invocano più
|
|
13
|
+
`new-card-review` a scope vuoto (cluster no-op misurati agents=0).
|
|
14
|
+
- **verify-item.sh (T2.C)**: la Grep-verification discipline del completeness è
|
|
15
|
+
ora CODE (`scripts/verify-item.sh` — exit 2 = UNVERIFIED mai Missing);
|
|
16
|
+
composizioni shell hand-rolled per quei check = protocol violation.
|
|
17
|
+
|
|
18
|
+
## 1.2.0 — 2026-07-02
|
|
19
|
+
|
|
20
|
+
- **AUTONOMOUS OFF-CONTEXT DELEGATION GATE** (kickoff, pre-Phase-0): un batch
|
|
21
|
+
`-auto` viene delegato di default al motore workflow `new2` (pipeline per-card
|
|
22
|
+
off-context) quando Workflow tool + `new2.js` + skill `new2` sono presenti, il
|
|
23
|
+
batch è migration-free e non è `-auto-ship`. Driver misurato su 3 run reali:
|
|
24
|
+
turn-tax orchestrator = 53–59% dei token fatturati (contesto accumulato
|
|
25
|
+
ri-servito a ogni turno). Delega MANDATORY a condizioni verdi (no discretion,
|
|
26
|
+
come i gate Phase 2.5x/F.1.5); escape hatch `-inline`; il path classico resta
|
|
27
|
+
SSOT per interattivo / Codex / `-auto-ship` / migrazioni dichiarate.
|
|
28
|
+
- Nuovo token `-inline` / `--inline` nel parser (`FORCE_INLINE`).
|
|
29
|
+
- Phase 2.6: consumo additivo `lane_coverage`/`lanes` dal report `/e2e-review`
|
|
30
|
+
(`[E2E-LANE-UNDERRUN]`, niente chiusura fidelity-AC su under-run — T1.A).
|
|
31
|
+
- Coarse fallback UI: binding-compliance verificata con `check-bindings.mjs`
|
|
32
|
+
(T1.A) + obbligo build-with-eyes nel briefing [UI-ONLY] (T1.B).
|
|
33
|
+
|
|
5
34
|
## 1.1.2 — 2026-07-01
|
|
6
35
|
|
|
7
36
|
- Context economy: trimmed the top-level **RUNTIME PORTABILITY** citation to a one-liner (cite, don't restate — the detail lives in `runtime-portability-protocol.md`). ~470 chars off the SKILL.md core, which sits in context every turn. No behavior change.
|
|
@@ -1,7 +1,7 @@
|
|
|
1
1
|
---
|
|
2
2
|
name: new
|
|
3
3
|
effort: medium
|
|
4
|
-
version: 1.
|
|
4
|
+
version: 1.3.0
|
|
5
5
|
description: >
|
|
6
6
|
Orchestrate a team of specialized agents to implement one or more backlog cards
|
|
7
7
|
end-to-end inside a dedicated worktree, with code review, doc review, QA, and
|
|
@@ -45,7 +45,49 @@ If no card IDs are provided, ask the user which cards to implement.
|
|
|
45
45
|
|
|
46
46
|
**Opt-in session telemetry (`-stats` / `--stats`)**: strip `-stats` / `--stats` from the args list exactly like `-full` (it is NOT a card ID), and set an internal flag `STATS=true` for this run. When present, Phase 8 additionally measures REAL token + wall-clock cost per agent role (coder, code-reviewer, …) by post-processing the session transcripts — zero model-token overhead, runs in Bash after the work is done. When absent, Phase 8 behaves exactly as before. The flag is batch-scoped and composes with `-full` (`/new FEAT-005 -full -stats`).
|
|
47
47
|
|
|
48
|
-
**Autonomous run (`-auto` / `--auto`, `-auto-ship` / `--auto-ship`)**: strip these tokens from the args list exactly like `-full`/`-stats` (they are NOT card IDs). `-auto` / `--auto` sets `AUTONOMOUS=true`; `-auto-ship` / `--auto-ship` sets `AUTO_SHIP=true` AND implies `AUTONOMOUS=true`. When `AUTONOMOUS` is set the orchestrator runs the WHOLE batch without ever calling `AskUserQuestion` — every decision gate is resolved deterministically per § "AUTONOMOUS RESOLUTION RULE" below. The flags are **batch-scoped** and compose with `-full`/`-stats` (`/new FEAT-005 -full -auto`). `AUTONOMOUS` is ALSO set when the environment already signals an unattended run — env `BALDART_AUTONOMOUS`, `CI`, or `GITHUB_ACTIONS` (unify with that existing codepath: treat the env signal and the flag as the same `AUTONOMOUS` state; `AUTO_SHIP` is flag-only). **Record `AUTONOMOUS` / `AUTO_SHIP` in the Phase-0 tracker** (the recovery SSOT — write them once into `## Issues & Flags` or a dedicated tracker field; never re-derive them per turn, since a compaction would otherwise lose the run mode).
|
|
48
|
+
**Autonomous run (`-auto` / `--auto`, `-auto-ship` / `--auto-ship`)**: strip these tokens from the args list exactly like `-full`/`-stats` (they are NOT card IDs). `-auto` / `--auto` sets `AUTONOMOUS=true`; `-auto-ship` / `--auto-ship` sets `AUTO_SHIP=true` AND implies `AUTONOMOUS=true`. When `AUTONOMOUS` is set the orchestrator runs the WHOLE batch without ever calling `AskUserQuestion` — every decision gate is resolved deterministically per § "AUTONOMOUS RESOLUTION RULE" below. The flags are **batch-scoped** and compose with `-full`/`-stats` (`/new FEAT-005 -full -auto`). `AUTONOMOUS` is ALSO set when the environment already signals an unattended run — env `BALDART_AUTONOMOUS`, `CI`, or `GITHUB_ACTIONS` (unify with that existing codepath: treat the env signal and the flag as the same `AUTONOMOUS` state; `AUTO_SHIP` is flag-only). **Record `AUTONOMOUS` / `AUTO_SHIP` in the Phase-0 tracker** (the recovery SSOT — write them once into `## Issues & Flags` or a dedicated tracker field; never re-derive them per turn, since a compaction would otherwise lose the run mode). Also strip `-inline` / `--inline` (sets `FORCE_INLINE=true` — the escape hatch of the delegation gate below; NOT a card ID).
|
|
49
|
+
|
|
50
|
+
## AUTONOMOUS OFF-CONTEXT DELEGATION GATE (v4.90.0 — fires at kickoff, BEFORE Phase 0)
|
|
51
|
+
|
|
52
|
+
Forensics on three real `-auto` batches showed the **orchestrator's own turn-tax is
|
|
53
|
+
53–59% of the whole run's billed tokens** (an ever-growing accumulated context,
|
|
54
|
+
replayed via `cache_read` on every one of 400–700 turns) — while the genuinely new
|
|
55
|
+
tokens are a rounding error. An `-auto` run has, by definition, **no human gates**:
|
|
56
|
+
exactly the case the workflow-hosted `new2` engine was built for (the entire per-card
|
|
57
|
+
pipeline runs in an isolated background runtime whose output never enters this
|
|
58
|
+
context). So an `-auto` batch is delegated off-context **by default**:
|
|
59
|
+
|
|
60
|
+
**Delegate — invoke the `new2` skill — when ALL of these hold** (checked once, at
|
|
61
|
+
kickoff, right after arg parsing):
|
|
62
|
+
|
|
63
|
+
1. `AUTONOMOUS == true` AND `AUTO_SHIP == false` (the `AUTO_SHIP` deploy boundary —
|
|
64
|
+
§ "AUTONOMOUS SAFETY BOUNDARY" — is implemented by THIS skill's
|
|
65
|
+
production/merge phases only; an `-auto-ship` run stays inline).
|
|
66
|
+
2. `FORCE_INLINE == false` (the user did not pass `-inline`).
|
|
67
|
+
3. The `Workflow` tool is available in this session AND `.claude/workflows/new2.js`
|
|
68
|
+
is linked AND the `new2` skill is available.
|
|
69
|
+
4. No epic card in the batch declares `migration_plan.required: true` (cheap YAML
|
|
70
|
+
probe on the batch's `group.parent` epics). A declared migration keeps the
|
|
71
|
+
classic path — its Phase 0 step 1b owns the owner-gated apply under
|
|
72
|
+
§ "AUTONOMOUS RESOLUTION RULE"; `new2`'s own migration gate is interactive.
|
|
73
|
+
|
|
74
|
+
**Action**: log ONE tracker line `[DELEGATED] -auto batch → new2 engine
|
|
75
|
+
(off-context): <residual args>` and invoke the `new2` skill with the SAME residual
|
|
76
|
+
invocation — card IDs + `-full` + `-stats` + `effort=<level>` (its grammar is
|
|
77
|
+
identical; do NOT forward `-auto`/`-auto-ship`/`-inline`, which new2 does not
|
|
78
|
+
parse — new2 IS autonomous by contract). `new2` owns the run end-to-end
|
|
79
|
+
(pre-flight → per-card pipeline → final review → merge → follow-up
|
|
80
|
+
materialization → truthful telemetry) and this orchestrator does NOT re-run any
|
|
81
|
+
phase: relay new2's final report verbatim and stop. **This delegation is
|
|
82
|
+
MANDATORY when the conditions hold — no discretion** (the same no-discretion
|
|
83
|
+
contract as the Phase 2.5x / F.1.5 workflow gates; running inline with the
|
|
84
|
+
conditions green is a protocol violation that costs the measured 53–59%).
|
|
85
|
+
|
|
86
|
+
**Else** — any condition fails (interactive run, Codex / no Workflow tool,
|
|
87
|
+
`-auto-ship`, declared migration, `-inline`, missing new2) → run the classic
|
|
88
|
+
inline path below exactly as written. The classic prose remains the SSOT for all
|
|
89
|
+
semantics; the delegation only changes WHERE the batch executes, never what it
|
|
90
|
+
does.
|
|
49
91
|
|
|
50
92
|
## Effort
|
|
51
93
|
|
|
@@ -10,6 +10,7 @@ Before triggering any review, you MUST verify that the coder agent implemented *
|
|
|
10
10
|
> 1. **Quote-broken pattern.** Code-shaped tokens contain shell/regex metacharacters — a TS union literal `mode:'catalog'|'picker'`, an object key, anything with `'` `"` `|` `[]` `?` `(`. Embedding such a pattern in an `echo "=== … ===" && grep …` block or an unquoted `-E` arg breaks the shell/regex parse → the grep matches **nothing even though the code is there**. **Search literals with `rg -F '<exact string>'` (fixed-string, no regex), single-quote the WHOLE pattern, and run ONE pattern per `rg` call** — never fold the search token into a quoted header/echo composition.
|
|
11
11
|
> 2. **`0 matches` ≠ absent.** A zero-match result is ambiguous (true miss vs. broken pattern / wrong file / wrong escaping). Do NOT classify an item `Missing`/`Partial` on a 0-match alone. **If the 0-match CONTRADICTS the coder completion report's claim that the item is implemented, treat it as a likely broken grep — re-confirm by reading the report's cited `file:line` (or a corrected `rg -F`) BEFORE flagging or spawning a gap-fix agent.** Never re-spawn a coder on a 0-match alone. When unsure, a targeted `Read` at the report's `file:line` is more reliable than a hand-rolled grep.
|
|
12
12
|
> 3. **Binary-heuristic false-empty.** Plain `grep` decides a file is *binary* when it sees a byte it reads as non-text (a non-UTF-8 byte, an accented char under some locales) or very long lines, and then prints `Binary file … matches` / **nothing** instead of the line — so a perfectly valid source file (e.g. an 8000-line `data.ts` with accented strings) silently returns 0 matches for tokens that ARE present. The mandated `rg` does NOT have this failure mode (it searches UTF-8 and long lines fine). **Always reach for `rg -F` first; if you must use `grep`, force text mode with `grep -a`.** A 0-match from plain `grep` on a file you KNOW was just modified is almost always this artifact — switch to `rg`/`grep -a` and re-check before concluding the code is missing.
|
|
13
|
+
> 4. **Canonical runner (v4.91.0 — use the SCRIPT, not hand-rolled shell).** All three guards above are CODE in `scripts/verify-item.sh` — run every per-item check through it: `bash .claude/skills/new/scripts/verify-item.sh '<exact literal>' <changed files...>` (one pattern per call; the pattern is a single argv, so metacharacters cannot break the parse). Exit `0` = FOUND (with `file:line`); exit `2` = **UNVERIFIED — not Missing**: confirm via a targeted `Read` at the completion report's cited `file:line` before classifying or spawning a gap-fixer; exit `3` = the FILES were wrong (fix the paths first). Hand-rolled `echo "===" && grep …` compositions for these checks are now a protocol violation.
|
|
13
14
|
|
|
14
15
|
**Step-by-step**:
|
|
15
16
|
|
|
@@ -135,7 +135,15 @@
|
|
|
135
135
|
[if field is empty/missing, read PRD Section 1b from card's links.prd path]
|
|
136
136
|
|
|
137
137
|
### Codebase Context
|
|
138
|
-
|
|
138
|
+
Architecture baseline: Read /tmp/arch-baseline-<CARD-ID>.md BEFORE writing any
|
|
139
|
+
code — it holds the file paths, exact line numbers, type signatures, existing
|
|
140
|
+
patterns to follow, high-risk paths, and the ## Hot-File Map (per-symbol line
|
|
141
|
+
ranges for files > 800 lines: Read those RANGES, never the whole file —
|
|
142
|
+
`code-search-protocol.md` § "Large-file read discipline"). If the baseline file
|
|
143
|
+
is missing/unreadable, report `[BASELINE-READ-FAIL] <path>` in your completion
|
|
144
|
+
report and derive the context yourself per Phase 1 — do NOT code blind.
|
|
145
|
+
[do NOT paste the baseline content here — pass the path only (§ "Context
|
|
146
|
+
economy" rule 4); inline ONLY the plan-auditor corrections/anti-patterns below]
|
|
139
147
|
[include any corrections or anti-patterns flagged by plan-auditor grounding check]
|
|
140
148
|
|
|
141
149
|
### Design Reference (UI cards only — include if card has links.design)
|
|
@@ -184,7 +192,12 @@
|
|
|
184
192
|
Only `action: new` entries (confirmed at `/prd` time) may introduce a component.
|
|
185
193
|
UI scope + `features.has_design_system: true` but NO `component_bindings` → run
|
|
186
194
|
the cascade below as your own reconciliation before writing code (do not assume
|
|
187
|
-
a mockup affordance is a new component).
|
|
195
|
+
a mockup affordance is a new component). **After the build, compliance is
|
|
196
|
+
VERIFIED deterministically** — run
|
|
197
|
+
`node .claude/skills/ui-implement/scripts/check-bindings.mjs --bindings-json
|
|
198
|
+
'<bindings as JSON>' --files <touched files>` (exit 3 = `binding-not-honored`,
|
|
199
|
+
Critical → one fix retry, then blocked; `/ui-implement` Step 5b is the SSOT of
|
|
200
|
+
this gate — the coarse fallback runs the same script).
|
|
188
201
|
|
|
189
202
|
### i18n constraint (include when `features.has_i18n: true`)
|
|
190
203
|
No user-facing string may be hardcoded. Externalize every label through the
|
|
@@ -196,7 +209,10 @@
|
|
|
196
209
|
curates the registry afterwards; the anti-hardcoded linter is the gate.
|
|
197
210
|
|
|
198
211
|
### [UI-ONLY] Registry-first BLOCKING pre-work (include ONLY when briefing = "ui-expert")
|
|
199
|
-
You are spawned as `ui-expert`.
|
|
212
|
+
You are spawned as `ui-expert`. When the card has a mockup, your own
|
|
213
|
+
`ui-expert.md` § "Build-with-eyes" self-check contract applies (bounded
|
|
214
|
+
structural + visual self-check BEFORE returning — report its one-line
|
|
215
|
+
outcome). Before writing any UI code, you MUST complete
|
|
200
216
|
the registry-first cascade defined in
|
|
201
217
|
`framework/.claude/agents/ui-expert.md` § "Authoritative Style Reference —
|
|
202
218
|
Registry-First Protocol" (the SSOT lives in
|
|
@@ -58,6 +58,16 @@ so it surfaces in telemetry.
|
|
|
58
58
|
```
|
|
59
59
|
`codexScriptPath` — resolve the Codex companion path ONCE per `/new` run (glob in `references/team-mode.md` § Step D delegation) and reuse it here + at the Final, so the workflow skips its internal Haiku resolver; omit when stdout is empty (the workflow self-resolves as fallback).
|
|
60
60
|
|
|
61
|
+
**Empty-scope pre-invocation guard (v4.91.0).** If `scopeFiles` resolves EMPTY (the card's
|
|
62
|
+
committed diff has no files — e.g. its work was absorbed by a prior in-batch commit), do
|
|
63
|
+
NOT invoke the workflow: it would only schedule an empty cluster that immediately no-ops
|
|
64
|
+
(measured: two `new-card-review` runs with `agents=0, dur=0` in one real batch — a wasted
|
|
65
|
+
invocation + wake each). Log `review-cluster: SKIP (empty diff — nothing to review)` and
|
|
66
|
+
proceed to Phase 2.6. This mirrors the workflow's own internal no-op guard; the guard
|
|
67
|
+
belongs HERE too so the invocation itself is saved. (An empty diff on a card that was
|
|
68
|
+
supposed to change code is suspicious — cross-check `alreadyCommitted` / the tracker
|
|
69
|
+
before treating it as fine.)
|
|
70
|
+
|
|
61
71
|
The workflow runs Simplify + Codex (agent-launched, code-reviewer fallback) + qa-sentinel + security,
|
|
62
72
|
FP-checks each specialist's own findings, then the **domain writer applies its VERIFIED findings**
|
|
63
73
|
(canonical writer map v4.26.1: `security` → `security-reviewer`; `code`/`perf`/`migration`/`test`/
|
|
@@ -228,10 +238,22 @@ When the gate above passes, the orchestrator invokes `/e2e-review` in
|
|
|
228
238
|
"findings": [ ... ],
|
|
229
239
|
"ds_drift_codes": [ "DS_TOKENS_DRIFT" | "DS_COMPONENT_STALE" | "DS_INDEX_DRIFT" ],
|
|
230
240
|
"gaps": [ ... ],
|
|
241
|
+
"lane_coverage": "complete" | "incomplete",
|
|
242
|
+
"lanes": { "<route>": { "<lane>": "ran|skipped:<reason>|not_planned" } },
|
|
231
243
|
"transcript_paths": [ ... ]
|
|
232
244
|
}
|
|
233
245
|
```
|
|
234
246
|
|
|
247
|
+
`lane_coverage` / `lanes` (additive, e2e-review ≥1.1.0): the skill's own
|
|
248
|
+
Lane Matrix reconciliation (`design-system-protocol.md` § Verification-Lane
|
|
249
|
+
Ledger). An unauthorized lane under-run already surfaces as a
|
|
250
|
+
`verification-coverage-gap` finding → `status: "blocked"`, so no NEW gating
|
|
251
|
+
logic is needed here — but log the field in the tracker line, and treat a
|
|
252
|
+
`"passed"` accompanied by `lane_coverage: "incomplete"` (possible only from
|
|
253
|
+
an older skill version or a protocol violation) like the suspicious-skip
|
|
254
|
+
case: record `[E2E-LANE-UNDERRUN]` in `## Issues & Flags` and do NOT close
|
|
255
|
+
fidelity ACs on it.
|
|
256
|
+
|
|
235
257
|
#### Gating logic (BLOCKING)
|
|
236
258
|
|
|
237
259
|
| `status` from `/e2e-review` | Orchestrator action |
|
|
@@ -257,7 +279,7 @@ of the skill (skipping plan extraction and mockup cascade).
|
|
|
257
279
|
Append to `## Current Card` and (on completion) carry into `## Completed Cards`:
|
|
258
280
|
|
|
259
281
|
```
|
|
260
|
-
e2e-review: <status> | iterations: <N> | findings: <X critical, Y major, Z minor> | drift: [<codes>] | tolerance: <strict|balanced|lenient>
|
|
282
|
+
e2e-review: <status> | iterations: <N> | findings: <X critical, Y major, Z minor> | drift: [<codes>] | lanes: <complete|incomplete> | tolerance: <strict|balanced|lenient>
|
|
261
283
|
```
|
|
262
284
|
|
|
263
285
|
#### Out of scope for this phase
|
|
@@ -209,6 +209,10 @@ After ALL agents in the group complete successfully:
|
|
|
209
209
|
Map slice), `qaTier` (`full` iff the GROUP max is `deep`/risk-escalated per D.1.5 — mirrors D.4's
|
|
210
210
|
group predicate; else `light`), `hasSecurityFiles` (scope ∩ `paths.high_risk_modules`),
|
|
211
211
|
`runSimplify:true`, `archBaselinePath` (`/tmp/arch-baseline-group-<FIRST-CARD-ID>.md`).
|
|
212
|
+
**Empty-scope pre-invocation guard (v4.91.0, mirrors Phase 2.5x):** drop from `cards[]` any card
|
|
213
|
+
whose `scopeFiles` resolves EMPTY (absorbed by a prior in-batch commit — cross-check the tracker),
|
|
214
|
+
and if the WHOLE wave's `cards[]` ends up empty, do NOT invoke the workflow at all — log
|
|
215
|
+
`D.1.6: SKIP (empty wave scope — nothing to review)` instead of scheduling a no-op cluster.
|
|
212
216
|
```
|
|
213
217
|
Workflow({ name: 'new-card-review', args: {
|
|
214
218
|
cards: [ …one entry per non-trivial card in the wave… ],
|
|
@@ -0,0 +1,54 @@
|
|
|
1
|
+
#!/usr/bin/env bash
|
|
2
|
+
# verify-item.sh — deterministic single-item grep verification for /new Phase 2.5
|
|
3
|
+
# (T2.C, framework v4.91.0). Encodes the "Grep-verification discipline" of
|
|
4
|
+
# completeness.md as CODE, so the three prose-documented failure modes cannot
|
|
5
|
+
# recur by hand-rolled shell composition:
|
|
6
|
+
# 1. quote-broken pattern → the pattern is ONE argv, searched fixed-string (-F),
|
|
7
|
+
# never interpolated into an echo/regex composition.
|
|
8
|
+
# 2. `0 matches` ≠ absent → exit 2 prints UNVERIFIED, never "Missing" — the
|
|
9
|
+
# caller MUST confirm via a targeted Read before classifying/spawning a fixer.
|
|
10
|
+
# 3. binary false-empty → rg searches NUL/UTF-8 files as text; the grep
|
|
11
|
+
# fallback forces text mode with -a.
|
|
12
|
+
#
|
|
13
|
+
# Usage: verify-item.sh '<exact literal pattern>' <file> [<file> ...]
|
|
14
|
+
# Output: one line — "FOUND <n> match(es); first: <file>:<line>" or
|
|
15
|
+
# "UNVERIFIED: 0 matches — NOT proof of Missing; Read the completion
|
|
16
|
+
# report's cited file:line before classifying"
|
|
17
|
+
# Exit: 0 = found · 2 = unverified (0 matches) · 3 = usage/no readable files
|
|
18
|
+
# (never 1, so a caller cannot confuse it with grep's no-match code)
|
|
19
|
+
|
|
20
|
+
set -u
|
|
21
|
+
|
|
22
|
+
if [ "$#" -lt 2 ]; then
|
|
23
|
+
echo "usage: verify-item.sh '<exact literal pattern>' <file> [<file> ...]" >&2
|
|
24
|
+
exit 3
|
|
25
|
+
fi
|
|
26
|
+
|
|
27
|
+
pattern="$1"; shift
|
|
28
|
+
|
|
29
|
+
files=()
|
|
30
|
+
for f in "$@"; do
|
|
31
|
+
[ -f "$f" ] && [ -r "$f" ] && files+=("$f")
|
|
32
|
+
done
|
|
33
|
+
if [ "${#files[@]}" -eq 0 ]; then
|
|
34
|
+
echo "UNVERIFIED: no readable files among the $# provided — verify the paths before classifying anything"
|
|
35
|
+
exit 3
|
|
36
|
+
fi
|
|
37
|
+
|
|
38
|
+
if command -v rg >/dev/null 2>&1; then
|
|
39
|
+
# rg: fixed-string, line numbers, filename always (-H), NUL-safe text search.
|
|
40
|
+
out="$(rg -F -n -H --no-messages -- "$pattern" "${files[@]}" 2>/dev/null)"
|
|
41
|
+
else
|
|
42
|
+
# grep fallback: -a forces text mode (binary-heuristic guard), -F fixed-string.
|
|
43
|
+
out="$(grep -a -F -n -H -- "$pattern" "${files[@]}" 2>/dev/null)"
|
|
44
|
+
fi
|
|
45
|
+
|
|
46
|
+
if [ -n "$out" ]; then
|
|
47
|
+
n="$(printf '%s\n' "$out" | wc -l | tr -d ' ')"
|
|
48
|
+
first="$(printf '%s\n' "$out" | head -1 | cut -d: -f1,2)"
|
|
49
|
+
echo "FOUND ${n} match(es); first: ${first}"
|
|
50
|
+
exit 0
|
|
51
|
+
fi
|
|
52
|
+
|
|
53
|
+
echo "UNVERIFIED: 0 matches for the pattern in ${#files[@]} file(s) — NOT proof of Missing (completeness.md discipline #2): Read the completion report's cited file:line (or re-check the pattern) BEFORE classifying or spawning a gap-fixer"
|
|
54
|
+
exit 2
|