baldart 3.17.1 → 3.18.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 +75 -0
- package/README.md +21 -12
- package/VERSION +1 -1
- package/framework/.claude/agents/REGISTRY.md +1 -0
- package/framework/.claude/agents/visual-fidelity-verifier.md +319 -0
- package/framework/.claude/commands/design-review.md +2 -0
- package/framework/.claude/skills/e2e-review/SKILL.md +552 -0
- package/framework/.claude/skills/new/SKILL.md +99 -85
- package/framework/.claude/skills/playwright-skill/SKILL.md +29 -0
- package/framework/.claude/skills/prd/assets/card-template.yml +7 -0
- package/framework/.claude/skills/webapp-testing/SKILL.md +23 -0
- package/framework/AGENTS.md +1 -0
- package/framework/docs/PROJECT-CONFIGURATION.md +20 -1
- package/framework/templates/baldart.config.template.yml +38 -0
- package/package.json +1 -1
- package/src/commands/configure.js +58 -0
|
@@ -811,93 +811,107 @@ After completeness is verified, clean up the implementation before it reaches re
|
|
|
811
811
|
If any valid finding revealed a reusable pattern or common mistake, append 1-line to `## Lessons Learned`:
|
|
812
812
|
`SIMPLIFY: <pattern> — <file>`
|
|
813
813
|
|
|
814
|
-
### Phase 2.6 —
|
|
815
|
-
|
|
816
|
-
This phase
|
|
817
|
-
|
|
818
|
-
|
|
819
|
-
|
|
820
|
-
|
|
821
|
-
|
|
822
|
-
|
|
823
|
-
|
|
824
|
-
|
|
825
|
-
|
|
826
|
-
|
|
827
|
-
|
|
828
|
-
|
|
829
|
-
|
|
830
|
-
|
|
831
|
-
|
|
832
|
-
|
|
833
|
-
|
|
834
|
-
|
|
835
|
-
|
|
836
|
-
|
|
837
|
-
|
|
838
|
-
|
|
839
|
-
|
|
840
|
-
|
|
841
|
-
|
|
842
|
-
|
|
843
|
-
|
|
844
|
-
|
|
845
|
-
|
|
846
|
-
|
|
847
|
-
|
|
848
|
-
|
|
849
|
-
|
|
850
|
-
|
|
851
|
-
## Test Credentials
|
|
852
|
-
Persona: [from test_plan.test_credentials.persona]
|
|
853
|
-
Auth method: [from test_plan.test_credentials.auth_method]
|
|
854
|
-
Credentials: [from test_plan.test_credentials.credentials]
|
|
855
|
-
Store: [from test_plan.test_credentials.store]
|
|
856
|
-
Notes: [from test_plan.test_credentials.notes]
|
|
857
|
-
|
|
858
|
-
## Auth Handling
|
|
859
|
-
- If persona is CUSTOMER with OTP auth: navigate to login, enter phone number,
|
|
860
|
-
then use `await test.step('OTP input (manual)', async () => { await page.pause() })`
|
|
861
|
-
to pause for manual OTP entry by the user. After pause resumes, continue the flow.
|
|
862
|
-
- If persona is MERCHANT with password auth: use page.fill() for username/password
|
|
863
|
-
fields, then submit the login form. No manual intervention needed.
|
|
864
|
-
|
|
865
|
-
## Test Data Prerequisites
|
|
866
|
-
[paste test_data_prerequisites — data that must exist in the persistence layer before the test runs]
|
|
867
|
-
|
|
868
|
-
## Guidelines
|
|
869
|
-
- Use page.getByRole(), page.getByText(), page.getByTestId() for selectors
|
|
870
|
-
- Use expect(locator) assertions with auto-waiting
|
|
871
|
-
- Group related steps with test.describe()
|
|
872
|
-
- Implement ALL scenarios from the PRD test plan (not just happy path)
|
|
873
|
-
- Use baseURL from config (just page.goto('/relative-path'))
|
|
874
|
-
- Do NOT use chromium.launch() or manual browser management
|
|
875
|
-
- For OTP flows: use page.pause() and document it clearly in test output
|
|
814
|
+
### Phase 2.6 — End-to-End Review (BLOCKING, since v3.18.0)
|
|
815
|
+
|
|
816
|
+
This phase delegates to the `/e2e-review` skill — a deterministic, BLOCKING
|
|
817
|
+
orchestrator that combines functional E2E (Playwright spec written by `coder`,
|
|
818
|
+
executed via `playwright-skill`) with visual fidelity diff
|
|
819
|
+
(`visual-fidelity-verifier` multimodal agent), aggregates findings under a
|
|
820
|
+
strict severity gate, runs a bounded self-heal loop, and either passes /
|
|
821
|
+
blocks / accepts an explicit user override.
|
|
822
|
+
|
|
823
|
+
The skill replaces the previous advisory pair (legacy Phase 2.6 E2E testing
|
|
824
|
+
and Phase 2.7 visual design review). It runs by default on every UI card,
|
|
825
|
+
auto-skips on backend-only cards, and BLOCKS the commit on gating findings.
|
|
826
|
+
|
|
827
|
+
#### Gate (skip the whole phase when any of the below is true)
|
|
828
|
+
|
|
829
|
+
| Condition | Action |
|
|
830
|
+
|-----------|--------|
|
|
831
|
+
| `features.has_e2e_review: false` in `baldart.config.yml` | **SKIP** — log `"e2e-review: SKIP (feature disabled — run `npx baldart configure` to enable)"`. Preserves backwards compatibility for pre-3.18 consumers. |
|
|
832
|
+
| Card has no `links.design` AND `git diff --name-only` shows no file under `${paths.app_dir}` AND no file under `${paths.components_primitives}` AND no `*.tsx` / `*.css` / `*.scss` / `*.svelte` / `*.vue` anywhere | **SKIP** — log `"e2e-review: SKIP (backend-only card)"`. |
|
|
833
|
+
| Card type is `docs`, `chore`, or `config` | **SKIP** — same log. |
|
|
834
|
+
|
|
835
|
+
#### Invocation contract
|
|
836
|
+
|
|
837
|
+
When the gate above passes, the orchestrator invokes `/e2e-review` in
|
|
838
|
+
**programmatic mode**:
|
|
839
|
+
|
|
840
|
+
1. **Update tracker**: phase = "2.6-e2e-review".
|
|
841
|
+
2. Spawn the skill with the payload:
|
|
842
|
+
|
|
843
|
+
```json
|
|
844
|
+
{
|
|
845
|
+
"card_id": "<CARD-ID>",
|
|
846
|
+
"worktree_path": "<absolute worktree path>",
|
|
847
|
+
"mode": "programmatic",
|
|
848
|
+
"tolerance": "<features.e2e_review.fidelity_tolerance>",
|
|
849
|
+
"max_self_heal_iterations": "<features.e2e_review.max_self_heal_iterations>"
|
|
850
|
+
}
|
|
876
851
|
```
|
|
877
|
-
|
|
878
|
-
|
|
879
|
-
|
|
852
|
+
|
|
853
|
+
The skill is responsible for: reading the card YAML + `test_plan`, deriving
|
|
854
|
+
routes from the diff, walking the 4-level mockup cascade (Figma MCP →
|
|
855
|
+
local image → compliance-only → skip), generating the Playwright spec via
|
|
856
|
+
`coder`, executing it headless, invoking `visual-fidelity-verifier` per
|
|
857
|
+
route, and returning a single JSON object.
|
|
858
|
+
|
|
859
|
+
3. Parse the returned JSON. The contract is:
|
|
860
|
+
|
|
861
|
+
```json
|
|
862
|
+
{
|
|
863
|
+
"status": "passed" | "blocked" | "overridden" | "skipped" | "error",
|
|
864
|
+
"iterations": 0,
|
|
865
|
+
"findings": [ ... ],
|
|
866
|
+
"ds_drift_codes": [ "DS_TOKENS_DRIFT" | "DS_COMPONENT_STALE" | "DS_INDEX_DRIFT" ],
|
|
867
|
+
"gaps": [ ... ],
|
|
868
|
+
"transcript_paths": [ ... ]
|
|
869
|
+
}
|
|
880
870
|
```
|
|
881
|
-
|
|
882
|
-
|
|
883
|
-
|
|
884
|
-
|
|
885
|
-
|
|
886
|
-
|
|
887
|
-
|
|
888
|
-
|
|
889
|
-
|
|
890
|
-
|
|
891
|
-
|
|
892
|
-
|
|
893
|
-
|
|
894
|
-
|
|
895
|
-
|
|
896
|
-
|
|
897
|
-
|
|
898
|
-
|
|
899
|
-
|
|
900
|
-
|
|
871
|
+
|
|
872
|
+
#### Gating logic (BLOCKING)
|
|
873
|
+
|
|
874
|
+
| `status` from `/e2e-review` | Orchestrator action |
|
|
875
|
+
|----|----|
|
|
876
|
+
| `"passed"` | Log result in tracker. Proceed to Phase 3 (doc review + code review). |
|
|
877
|
+
| `"skipped"` | Log skip reason. Proceed to Phase 3. |
|
|
878
|
+
| `"overridden"` | Log override + reason in `## Issues & Flags` as `[E2E-OVERRIDE] <reason>`. Proceed to Phase 3. |
|
|
879
|
+
| `"blocked"` | **STOP the card**. Log findings in tracker + `## Issues & Flags` as `[E2E-BLOCKED] <count> gating findings (<categories>)`. Ask the user whether to (a) override with reason, (b) escalate (open follow-up card), or (c) abandon this card and continue the batch. Do NOT proceed to Phase 3 silently. |
|
|
880
|
+
| `"error"` | Log error in `## Issues & Flags`. Ask the user whether to retry, skip, or abandon. Do NOT proceed silently. |
|
|
881
|
+
|
|
882
|
+
#### Re-run trigger (after Phase 3.7 `/codexreview`)
|
|
883
|
+
|
|
884
|
+
If the mandatory `/codexreview` gate in Phase 3.7 modifies any file under
|
|
885
|
+
`${paths.app_dir}`, `${paths.components_primitives}`, or any `*.css` /
|
|
886
|
+
`*.scss`, the orchestrator MUST re-invoke `/e2e-review` BEFORE the Phase 4
|
|
887
|
+
commit. This protects against code-review changes that silently reintroduce
|
|
888
|
+
visual / functional drift. The re-run reuses the same
|
|
889
|
+
`.baldart/e2e-review/<CARD-ID>/` state directory and starts from Phase 3
|
|
890
|
+
of the skill (skipping plan extraction and mockup cascade).
|
|
891
|
+
|
|
892
|
+
#### Tracker output
|
|
893
|
+
|
|
894
|
+
Append to `## Current Card` and (on completion) carry into `## Completed Cards`:
|
|
895
|
+
|
|
896
|
+
```
|
|
897
|
+
e2e-review: <status> | iterations: <N> | findings: <X critical, Y major, Z minor> | drift: [<codes>] | tolerance: <strict|balanced|lenient>
|
|
898
|
+
```
|
|
899
|
+
|
|
900
|
+
#### Out of scope for this phase
|
|
901
|
+
|
|
902
|
+
- Mockup re-design (the skill never modifies the mockup — only the
|
|
903
|
+
implementation).
|
|
904
|
+
- Code review or doc review (those remain Phase 3 / 3.7 responsibilities).
|
|
905
|
+
- Unit-test execution (that is `qa-sentinel`).
|
|
906
|
+
- Visual polish beyond gating findings (advisory Minor findings under
|
|
907
|
+
balanced/lenient tolerance are logged but not actioned).
|
|
908
|
+
|
|
909
|
+
#### Legacy cards
|
|
910
|
+
|
|
911
|
+
Cards written before v3.18.0 (without a `test_plan` block) still work — the
|
|
912
|
+
skill's Phase 1 falls back to deriving Gherkin scenarios from
|
|
913
|
+
`acceptance_criteria` directly. The mockup cascade gracefully degrades when
|
|
914
|
+
`links.design` is missing.
|
|
901
915
|
|
|
902
916
|
---
|
|
903
917
|
|
|
@@ -17,6 +17,35 @@ All browser testing uses the **Playwright Test CLI** via `playwright.config.ts`
|
|
|
17
17
|
**Overlay:** loads `.baldart/overlays/playwright-skill.md` if present — project-specific test URLs, auth helpers, theming pairing assertions.
|
|
18
18
|
**On missing/empty keys:** ask the user; do not assume defaults. See `framework/agents/project-context.md` § 3.
|
|
19
19
|
|
|
20
|
+
## MCP dependencies
|
|
21
|
+
|
|
22
|
+
See [framework/docs/MCP-INTEGRATION.md](../../../docs/MCP-INTEGRATION.md) for the BALDART MCP integration contract and the rationale behind this section.
|
|
23
|
+
|
|
24
|
+
**None.** This skill uses the **Playwright Test CLI** (`@playwright/test`) directly via `npm run test:e2e` — `.spec.ts` files under `${paths.e2e_tests_dir}`. It does NOT use Playwright MCP. Consumers don't need any MCP configured to use this skill. For ad-hoc interactive browser debugging during bug investigation (not E2E test authoring) see [bug/SKILL.md](../bug/SKILL.md), which DOES require `mcp__playwright__browser_*`.
|
|
25
|
+
|
|
26
|
+
## E2E Review Integration (since v3.18.0)
|
|
27
|
+
|
|
28
|
+
This skill is the tooling layer consumed by `/e2e-review` Phase 3 (functional
|
|
29
|
+
E2E). When the orchestrator invokes this skill, the contract is:
|
|
30
|
+
|
|
31
|
+
- The `coder` agent generates the `.spec.ts` under `${paths.e2e_tests_dir}/`
|
|
32
|
+
from a Gherkin verification plan persisted at
|
|
33
|
+
`.baldart/e2e-review/<CARD-ID>/plan.json` (do not invent scenarios outside
|
|
34
|
+
the plan).
|
|
35
|
+
- The spec MUST screenshot every route in scope and save the file at
|
|
36
|
+
`.baldart/e2e-review/<CARD-ID>/screenshots/<route-slug>.png` — that path is
|
|
37
|
+
consumed verbatim by the `visual-fidelity-verifier` agent in Phase 4.
|
|
38
|
+
- Execution is **headless** in programmatic mode (invocation from `/new`);
|
|
39
|
+
headed mode is reserved for OTP flows during manual `/e2e-review` runs.
|
|
40
|
+
- Failed scenarios become functional findings in the aggregate report; the
|
|
41
|
+
severity is determined by the orchestrator (auth/payments/data-mutation =
|
|
42
|
+
Critical; display-only = Major; flaky-passed-on-retry = Minor).
|
|
43
|
+
|
|
44
|
+
No logic of this skill changes for E2E-review consumption — the consumer
|
|
45
|
+
simply requires the conventions above. See
|
|
46
|
+
[`framework/.claude/skills/e2e-review/SKILL.md`](../e2e-review/SKILL.md) Phase 3
|
|
47
|
+
for the full contract.
|
|
48
|
+
|
|
20
49
|
## Quick Reference
|
|
21
50
|
|
|
22
51
|
| Action | Command |
|
|
@@ -131,6 +131,13 @@ canonical_docs:
|
|
|
131
131
|
additional_refs:
|
|
132
132
|
- "{{${paths.adrs_dir}/ADR-XXXXX.md}}"
|
|
133
133
|
|
|
134
|
+
# test_plan is consumed BOTH by `/new` Phase 2.6 (legacy fallback path) AND by
|
|
135
|
+
# `/e2e-review` (since v3.18.0). The /e2e-review skill maps each test_scenarios[]
|
|
136
|
+
# entry into a Gherkin scenario in Phase 1 (Verification Plan Extraction).
|
|
137
|
+
# When the card has `links.design`, the same scenarios additionally drive the
|
|
138
|
+
# per-route visual fidelity check in Phase 4. Keep scenario.description short
|
|
139
|
+
# and action-oriented (one user-facing intent per scenario) so the Gherkin
|
|
140
|
+
# translation reads cleanly. See framework/.claude/skills/e2e-review/SKILL.md.
|
|
134
141
|
test_plan:
|
|
135
142
|
e2e_required: {{true|false}}
|
|
136
143
|
e2e_rationale: "{{reason from evaluation tree}}"
|
|
@@ -15,6 +15,29 @@ license: Complete terms in LICENSE.txt
|
|
|
15
15
|
|
|
16
16
|
---
|
|
17
17
|
|
|
18
|
+
## E2E Review Integration (since v3.18.0)
|
|
19
|
+
|
|
20
|
+
This skill is the tooling layer consumed by `/e2e-review` in **compliance-only
|
|
21
|
+
mode** (Phase 2 cascade level c) and as a fallback for runtime inspection.
|
|
22
|
+
When invoked from the orchestrator:
|
|
23
|
+
|
|
24
|
+
- Use the Python Playwright helpers to fetch the rendered DOM's computed
|
|
25
|
+
styles (CSS color / spacing / radius / shadow values) for the routes in
|
|
26
|
+
scope when no mockup image is available.
|
|
27
|
+
- The compliance check reads `${paths.design_system}/tokens-reference.md` and
|
|
28
|
+
flags any computed value that does not match a token (the
|
|
29
|
+
`visual-fidelity-verifier` agent owns the actual cross-reference; this
|
|
30
|
+
skill only surfaces the runtime values).
|
|
31
|
+
- The server lifecycle helper (`scripts/with_server.py`) MAY be used to start
|
|
32
|
+
/ stop the dev server when the orchestrator runs outside a worktree that
|
|
33
|
+
already has one running.
|
|
34
|
+
|
|
35
|
+
No logic of this skill changes for E2E-review consumption — see
|
|
36
|
+
[`framework/.claude/skills/e2e-review/SKILL.md`](../e2e-review/SKILL.md)
|
|
37
|
+
Phase 2 (compliance-only branch) for the full contract.
|
|
38
|
+
|
|
39
|
+
---
|
|
40
|
+
|
|
18
41
|
To test local web applications, write native Python Playwright scripts.
|
|
19
42
|
|
|
20
43
|
**Helper Scripts Available**:
|
package/framework/AGENTS.md
CHANGED
|
@@ -16,6 +16,7 @@ This file is generic. Paths referenced as `${paths.X}` resolve from `baldart.con
|
|
|
16
16
|
| PRD workflow, PRD sessions | `features.has_prd_workflow: true` |
|
|
17
17
|
| LLM wiki overlay sync | `features.has_wiki_overlay: true` |
|
|
18
18
|
| Design-system blocking reads | `features.has_design_system: true` |
|
|
19
|
+
| E2E review BLOCKING gate (Phase 2.6 of `/new` invokes `/e2e-review`) | `features.has_e2e_review: true` |
|
|
19
20
|
|
|
20
21
|
When a MUST rule's feature is `false` or its target file does not exist, the rule is **silent** — do not invent a workflow that isn't there. Project-specific terminology (audience segments, domain entities, brand voice) comes from `identity.audience_segments`, `agents/coding-standards.md`, and skill overlays under `.baldart/overlays/`. See `agents/project-context.md` for the full protocol.
|
|
21
22
|
|
|
@@ -107,7 +107,26 @@ Empty string `""` means the concept doesn't exist in your project. Skills gated
|
|
|
107
107
|
| `prd_dir` | `docs/prd` | prd, prd-add, ui-design |
|
|
108
108
|
| `references_dir` | `docs/references` | new, prd, context-primer, doc-writing-for-rag, simplify |
|
|
109
109
|
| `wiki_dir` | `docs/wiki` | capture, context-primer |
|
|
110
|
-
| `e2e_tests_dir` | `tests/e2e` | playwright-skill |
|
|
110
|
+
| `e2e_tests_dir` | `tests/e2e` | playwright-skill, e2e-review (v3.18.0) |
|
|
111
|
+
|
|
112
|
+
### 4.2.1 `e2e_review` — tuning for the BLOCKING end-to-end review gate (v3.18.0+)
|
|
113
|
+
|
|
114
|
+
Only consulted when `features.has_e2e_review: true`. The block governs how the `/e2e-review` skill (auto-invoked by `/new` Phase 2.6 on UI cards) decides what blocks, how aggressively it retries, and what counts as an acceptable user override.
|
|
115
|
+
|
|
116
|
+
```yaml
|
|
117
|
+
e2e_review:
|
|
118
|
+
fidelity_tolerance: strict # strict | balanced | lenient
|
|
119
|
+
max_self_heal_iterations: 2
|
|
120
|
+
pixel_diff_threshold: 0.02
|
|
121
|
+
require_override_reason: true
|
|
122
|
+
```
|
|
123
|
+
|
|
124
|
+
| Key | Type | Default | Effect |
|
|
125
|
+
|---|---|---|---|
|
|
126
|
+
| `fidelity_tolerance` | enum (`strict`/`balanced`/`lenient`) | `strict` | `strict` blocks on Critical + Major + Minor findings (Minor with `confidence: low` auto-demote to advisory to absorb font-rendering / anti-aliasing variance); `balanced` blocks on Critical + Major, Minor advisory; `lenient` blocks on Critical only. |
|
|
127
|
+
| `max_self_heal_iterations` | int | `2` | After gating findings, the orchestrator re-spawns `coder` with the findings as fix instructions and re-runs functional + visual phases. Matches the existing `/new` Phase 2.5 retry policy. After exhaustion, the override path engages. |
|
|
128
|
+
| `pixel_diff_threshold` | float `0.0`–`1.0` | `0.02` | When the implementation screenshot vs mockup pixel-diff is below this fraction, the orchestrator skips the Vision call for that route and treats it as a pass. Primary latency / cost saver — most routes pass pixel-diff cleanly. Set higher to skip Vision more aggressively; set to `0.0` to always invoke Vision. |
|
|
129
|
+
| `require_override_reason` | bool | `true` | When self-heal exhausts iterations and the user chooses to override the gate, a written reason is mandatory. The reason is recorded both in the batch tracker's `## Issues & Flags` (as `[E2E-OVERRIDE] <reason>`) and in `.baldart/e2e-review/<CARD-ID>/report.json`. Set `false` to allow silent override (not recommended). |
|
|
111
130
|
|
|
112
131
|
### 4.3 `identity` — brand and audience facts
|
|
113
132
|
|
|
@@ -145,6 +145,44 @@ features:
|
|
|
145
145
|
# `baldart configure` installs the relevant language servers when enabled.
|
|
146
146
|
has_lsp_layer: false
|
|
147
147
|
|
|
148
|
+
# End-to-end review BLOCKING gate (since v3.18.0). When true, /new Phase 2.6
|
|
149
|
+
# invokes the /e2e-review skill, which combines functional E2E (Playwright
|
|
150
|
+
# spec written by `coder`, executed via playwright-skill) with visual
|
|
151
|
+
# fidelity diff (`visual-fidelity-verifier` multimodal agent). Findings are
|
|
152
|
+
# aggregated under a severity gate (strict by default) with a bounded
|
|
153
|
+
# self-heal loop. Replaces the legacy advisory Phase 2.6 + 2.7. Requires
|
|
154
|
+
# `@playwright/test` installed and `paths.e2e_tests_dir` set. Auto-skips on
|
|
155
|
+
# backend-only cards and on cards without `links.design` when no UI files
|
|
156
|
+
# changed. See framework/.claude/skills/e2e-review/SKILL.md.
|
|
157
|
+
has_e2e_review: false
|
|
158
|
+
|
|
159
|
+
# ─── E2E REVIEW ──────────────────────────────────────────────────────────
|
|
160
|
+
# Tuning for the /e2e-review skill (only consulted when has_e2e_review: true).
|
|
161
|
+
e2e_review:
|
|
162
|
+
# Severity floor that BLOCKS the commit.
|
|
163
|
+
# strict — Critical + Major + Minor block (default, recommended for
|
|
164
|
+
# design-system-strict projects); Minor findings with
|
|
165
|
+
# `confidence: low` auto-demote to advisory (anti font-rendering
|
|
166
|
+
# false positive).
|
|
167
|
+
# balanced — Critical + Major block; Minor advisory.
|
|
168
|
+
# lenient — Critical blocks; Major + Minor advisory.
|
|
169
|
+
fidelity_tolerance: strict
|
|
170
|
+
|
|
171
|
+
# Max self-heal iterations before falling through to the override path. The
|
|
172
|
+
# orchestrator re-spawns `coder` with the gating findings and re-runs the
|
|
173
|
+
# functional + visual phases. 2 matches the existing Phase 2.5 retry policy.
|
|
174
|
+
max_self_heal_iterations: 2
|
|
175
|
+
|
|
176
|
+
# Pre-filter pixel-diff threshold (0.0–1.0). When the implementation vs
|
|
177
|
+
# mockup pixel diff is below this value, the orchestrator skips the Vision
|
|
178
|
+
# call for that route and treats it as a pass. Primary latency / cost saver.
|
|
179
|
+
pixel_diff_threshold: 0.02
|
|
180
|
+
|
|
181
|
+
# When true, the override path (after self-heal exhaustion) requires the
|
|
182
|
+
# user to provide a written reason that is recorded in the tracker's
|
|
183
|
+
# `## Issues & Flags` and in `.baldart/e2e-review/<CARD-ID>/report.json`.
|
|
184
|
+
require_override_reason: true
|
|
185
|
+
|
|
148
186
|
# ─── LSP ─────────────────────────────────────────────────────────────────
|
|
149
187
|
# State of the LSP layer for this project. Populated by `baldart configure`
|
|
150
188
|
# (and by `npx baldart lsp install` / the `/lsp-bootstrap` skill). Leave
|
package/package.json
CHANGED
|
@@ -560,6 +560,7 @@ async function interactivePrompts(merged, detected) {
|
|
|
560
560
|
['has_prd_workflow', 'Project uses PRD workflow (docs/prd/)?'],
|
|
561
561
|
['has_wiki_overlay', 'Project has LLM-wiki overlay (docs/wiki/)?'],
|
|
562
562
|
['has_lsp_layer', 'Enable LSP symbol-search layer? (recommended for large codebases)'],
|
|
563
|
+
['has_e2e_review', 'Enable BLOCKING end-to-end review (Phase 2.6 of /new invokes /e2e-review — functional + visual fidelity gate)?'],
|
|
563
564
|
]) {
|
|
564
565
|
const [key, question] = flag;
|
|
565
566
|
const currentVal = merged.features[key];
|
|
@@ -619,6 +620,62 @@ async function interactivePrompts(merged, detected) {
|
|
|
619
620
|
merged.paths[key] = await promptForKey(`${label}`, proposed);
|
|
620
621
|
}
|
|
621
622
|
|
|
623
|
+
// ---- E2E review tuning (since v3.18.0) --------------------------------
|
|
624
|
+
// Only runs when the user opted in above. Populates the e2e_review.*
|
|
625
|
+
// sub-section with the severity floor, self-heal cap, pixel pre-filter
|
|
626
|
+
// threshold, and override-reason requirement. Idempotent: re-running
|
|
627
|
+
// configure on an already-installed project re-asks each value with the
|
|
628
|
+
// current YAML value as default.
|
|
629
|
+
merged.e2e_review = merged.e2e_review || {};
|
|
630
|
+
if (merged.features.has_e2e_review === true) {
|
|
631
|
+
UI.section('E2E review tuning (/e2e-review skill — Phase 2.6 of /new)');
|
|
632
|
+
const tolDefault = merged.e2e_review.fidelity_tolerance || 'strict';
|
|
633
|
+
const tolerance = await UI.select(
|
|
634
|
+
`Severity floor that BLOCKS the commit (current: ${tolDefault})`,
|
|
635
|
+
[
|
|
636
|
+
{ name: 'strict — Critical + Major + Minor block (recommended for design-system-strict projects)', value: 'strict' },
|
|
637
|
+
{ name: 'balanced — Critical + Major block; Minor advisory', value: 'balanced' },
|
|
638
|
+
{ name: 'lenient — Critical blocks; Major + Minor advisory', value: 'lenient' },
|
|
639
|
+
]
|
|
640
|
+
);
|
|
641
|
+
merged.e2e_review.fidelity_tolerance = tolerance;
|
|
642
|
+
|
|
643
|
+
const maxIterDefault = merged.e2e_review.max_self_heal_iterations ?? 2;
|
|
644
|
+
const maxIter = await promptForKey(
|
|
645
|
+
'Max self-heal iterations before override path',
|
|
646
|
+
String(maxIterDefault)
|
|
647
|
+
);
|
|
648
|
+
merged.e2e_review.max_self_heal_iterations = Number.isFinite(Number(maxIter)) ? Number(maxIter) : 2;
|
|
649
|
+
|
|
650
|
+
const diffDefault = merged.e2e_review.pixel_diff_threshold ?? 0.02;
|
|
651
|
+
const diffThr = await promptForKey(
|
|
652
|
+
'Pixel-diff pre-filter threshold (0.0 = always invoke Vision, 1.0 = never)',
|
|
653
|
+
String(diffDefault)
|
|
654
|
+
);
|
|
655
|
+
merged.e2e_review.pixel_diff_threshold = Number.isFinite(Number(diffThr)) ? Number(diffThr) : 0.02;
|
|
656
|
+
|
|
657
|
+
const reqReasonDefault = merged.e2e_review.require_override_reason !== undefined
|
|
658
|
+
? merged.e2e_review.require_override_reason
|
|
659
|
+
: true;
|
|
660
|
+
merged.e2e_review.require_override_reason = await promptForKey(
|
|
661
|
+
'Require a written reason when the user overrides the gate after self-heal exhaustion?',
|
|
662
|
+
reqReasonDefault,
|
|
663
|
+
'confirm'
|
|
664
|
+
);
|
|
665
|
+
|
|
666
|
+
if (!merged.paths.e2e_tests_dir) {
|
|
667
|
+
UI.info(
|
|
668
|
+
'E2E review requires `paths.e2e_tests_dir` set and `@playwright/test` installed.\n' +
|
|
669
|
+
'The path prompt above asked for the directory — confirm it exists or run `npm i -D @playwright/test` later.'
|
|
670
|
+
);
|
|
671
|
+
}
|
|
672
|
+
} else {
|
|
673
|
+
UI.info(
|
|
674
|
+
'has_e2e_review=false — /new Phase 2.6 silently skips the BLOCKING gate.\n' +
|
|
675
|
+
'Re-run `baldart configure` to enable when you want functional + visual fidelity enforced per card.'
|
|
676
|
+
);
|
|
677
|
+
}
|
|
678
|
+
|
|
622
679
|
// ---- LSP layer (since v3.10.0) ----------------------------------------
|
|
623
680
|
// Only runs when the user opted in above. Idempotent: re-running configure
|
|
624
681
|
// on an already-installed project re-detects, asks which servers to keep,
|
|
@@ -836,6 +893,7 @@ async function configure(opts = {}) {
|
|
|
836
893
|
`Backlog: ${detected.features.has_backlog ? 'yes' : 'no'}`,
|
|
837
894
|
`ADRs: ${detected.features.has_adrs ? 'yes' : 'no'}`,
|
|
838
895
|
`API docs: ${detected.features.has_api_docs ? 'yes' : 'no'}`,
|
|
896
|
+
`E2E review: ${detected.features.has_e2e_review === true ? 'yes' : detected.features.has_e2e_review === false ? 'no' : '— (will ask)'}`,
|
|
839
897
|
`Charting libs: ${detected.stack.charting.canonical.join(', ') || '—'}`,
|
|
840
898
|
`Animation libs: ${detected.stack.animation.canonical.join(', ') || '—'}`,
|
|
841
899
|
`E2E framework: ${detected.stack.testing.e2e || '—'}`,
|