codebyplan 1.11.1 → 1.12.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.
Files changed (56) hide show
  1. package/dist/cli.js +602 -345
  2. package/package.json +1 -1
  3. package/templates/README.md +1 -1
  4. package/templates/agents/cbp-cc-executor.md +1 -1
  5. package/templates/agents/cbp-e2e-maestro.md +202 -0
  6. package/templates/agents/cbp-e2e-playwright.md +229 -0
  7. package/templates/agents/cbp-e2e-tauri.md +184 -0
  8. package/templates/agents/cbp-e2e-vscode.md +203 -0
  9. package/templates/agents/cbp-e2e-xcuitest.md +224 -0
  10. package/templates/agents/cbp-improve-claude.md +1 -1
  11. package/templates/agents/cbp-round-executor.md +11 -11
  12. package/templates/agents/cbp-task-check.md +1 -1
  13. package/templates/agents/cbp-task-planner.md +2 -0
  14. package/templates/agents/cbp-testing-qa-agent.md +9 -9
  15. package/templates/context/testing/e2e.md +303 -0
  16. package/templates/hooks/cbp-statusline.mjs +44 -0
  17. package/templates/hooks/cbp-statusline.py +24 -2
  18. package/templates/hooks/cbp-statusline.sh +22 -2
  19. package/templates/hooks/validate-structure-lengths.sh +2 -0
  20. package/templates/hooks/validate-structure-smoke.sh +2 -1
  21. package/templates/hooks/validate-structure-templates.sh +1 -0
  22. package/templates/rules/README.md +8 -1
  23. package/templates/rules/context-file-loading.md +4 -1
  24. package/templates/rules/e2e-mandatory.md +70 -0
  25. package/templates/rules/supabase-branch-lifecycle.md +99 -0
  26. package/templates/settings.project.base.json +1 -2
  27. package/templates/skills/cbp-build-cc-agent/SKILL.md +16 -14
  28. package/templates/skills/cbp-build-cc-agent/reference/cbp-quality.md +4 -4
  29. package/templates/skills/cbp-build-cc-agent/scripts/validate-agent.sh +8 -6
  30. package/templates/skills/cbp-build-cc-mode/SKILL.md +4 -4
  31. package/templates/skills/cbp-build-cc-settings/reference/cbp-conventions.md +1 -2
  32. package/templates/skills/cbp-checkpoint-check/SKILL.md +12 -8
  33. package/templates/skills/cbp-checkpoint-create/SKILL.md +2 -0
  34. package/templates/skills/cbp-checkpoint-end/SKILL.md +27 -5
  35. package/templates/skills/cbp-checkpoint-plan/SKILL.md +2 -2
  36. package/templates/skills/cbp-checkpoint-plan/reference/e2e-discovery-probe.md +5 -5
  37. package/templates/skills/cbp-e2e-setup/SKILL.md +254 -0
  38. package/templates/skills/cbp-e2e-setup/reference/maestro.md +200 -0
  39. package/templates/skills/cbp-e2e-setup/reference/playwright.md +212 -0
  40. package/templates/skills/cbp-e2e-setup/reference/tauri.md +147 -0
  41. package/templates/skills/cbp-e2e-setup/reference/vscode.md +154 -0
  42. package/templates/skills/cbp-e2e-setup/reference/xcuitest.md +185 -0
  43. package/templates/skills/cbp-frontend-ui/SKILL.md +6 -6
  44. package/templates/skills/cbp-frontend-ux/SKILL.md +1 -1
  45. package/templates/skills/cbp-git-worktree-remove/SKILL.md +17 -1
  46. package/templates/skills/cbp-round-execute/SKILL.md +30 -17
  47. package/templates/skills/cbp-session-start/SKILL.md +27 -2
  48. package/templates/skills/cbp-ship-main/SKILL.md +13 -0
  49. package/templates/skills/cbp-supabase-branch-check/SKILL.md +12 -5
  50. package/templates/skills/cbp-supabase-migrate/SKILL.md +139 -9
  51. package/templates/skills/cbp-supabase-migrate/reference/preflight-dry-run.md +1 -1
  52. package/templates/skills/cbp-supabase-setup/SKILL.md +13 -7
  53. package/templates/skills/cbp-supabase-setup/reference/branching-setup.md +2 -2
  54. package/templates/skills/cbp-task-check/SKILL.md +2 -2
  55. package/templates/skills/cbp-task-start/SKILL.md +2 -0
  56. package/templates/agents/cbp-test-e2e-agent.md +0 -363
@@ -0,0 +1,147 @@
1
+ # Tauri Reference
2
+
3
+ Full install, config, and test walkthrough for Tauri desktop apps using WebDriverIO +
4
+ tauri-driver. Source: upstream WebDriverIO docs + `.claude/context/testing/e2e.md`.
5
+
6
+ ## Prerequisites
7
+
8
+ - Rust toolchain: `rustup --version` (install via https://rustup.rs)
9
+ - `tauri-driver` binary: installed via Cargo (see Install below)
10
+ - Built Tauri binary: `cargo build` must complete before any tests run
11
+ - Node.js / pnpm available
12
+
13
+ ## Install
14
+
15
+ ```bash
16
+ # WebDriverIO runner + framework
17
+ pnpm add -D @wdio/cli @wdio/local-runner @wdio/mocha-framework @wdio/spec-reporter
18
+
19
+ # Tauri driver (native binary — needs Cargo)
20
+ cargo install tauri-driver
21
+ ```
22
+
23
+ Verify:
24
+
25
+ ```bash
26
+ which tauri-driver
27
+ tauri-driver --version
28
+ ```
29
+
30
+ ## wdio.conf.ts
31
+
32
+ Place at `apps/desktop/wdio.conf.ts` (or repo root for single-app repos):
33
+
34
+ ```ts
35
+ import { spawn, spawnSync } from "child_process";
36
+ import type { Options } from "@wdio/types";
37
+
38
+ // Path to your built Tauri binary
39
+ const BINARY_PATH = "./src-tauri/target/debug/your-app-name";
40
+
41
+ let tauriDriver: ReturnType<typeof spawn>;
42
+
43
+ export const config: Options.Testrunner = {
44
+ specs: ["./e2e/**/*.spec.ts"],
45
+ maxInstances: 1,
46
+ capabilities: [
47
+ {
48
+ "tauri:options": { application: BINARY_PATH },
49
+ maxInstances: 1,
50
+ },
51
+ ],
52
+ services: ["chromedriver"],
53
+ framework: "mocha",
54
+ reporters: ["spec"],
55
+ mochaOpts: { timeout: 60_000 },
56
+
57
+ beforeSession: async () => {
58
+ // Start tauri-driver before each session
59
+ tauriDriver = spawn("tauri-driver", [], {
60
+ stdio: [null, process.stdout, process.stderr],
61
+ });
62
+ },
63
+
64
+ afterSession: async () => {
65
+ // Kill tauri-driver after each session
66
+ tauriDriver.kill();
67
+ },
68
+ };
69
+ ```
70
+
71
+ ## Build before running
72
+
73
+ Tests will fail if the binary is stale or absent. Always build before running tests:
74
+
75
+ ```bash
76
+ # Build the Tauri app
77
+ cargo build --manifest-path apps/desktop/src-tauri/Cargo.toml
78
+
79
+ # Then run WebDriverIO
80
+ pnpm --filter @codebyplan/desktop wdio run wdio.conf.ts
81
+ ```
82
+
83
+ Or as a combined pnpm script:
84
+
85
+ ```json
86
+ {
87
+ "scripts": {
88
+ "e2e": "cargo build --manifest-path src-tauri/Cargo.toml && wdio run wdio.conf.ts",
89
+ "e2e:test": "wdio run wdio.conf.ts"
90
+ }
91
+ }
92
+ ```
93
+
94
+ ## Writing tests
95
+
96
+ Use `data-testid` attributes for stable targeting (Tauri WebView renders HTML):
97
+
98
+ ```ts
99
+ import { browser, $ } from "@wdio/globals";
100
+ import { expect } from "@wdio/globals";
101
+
102
+ describe("Desktop app", () => {
103
+ it("opens the main window", async () => {
104
+ const navBar = await $("[data-testid='nav']");
105
+ await expect(navBar).toBeDisplayed();
106
+ });
107
+
108
+ it("navigates to settings", async () => {
109
+ await $("[data-testid='settings-link']").click();
110
+ await expect($("[data-testid='settings-panel']")).toBeDisplayed();
111
+ });
112
+ });
113
+ ```
114
+
115
+ Prefer `data-testid` over CSS class selectors — SCSS Modules mangle class names.
116
+
117
+ ## Auth probe
118
+
119
+ `apps/desktop/e2e/_probe/auth.spec.ts`:
120
+
121
+ ```ts
122
+ import { browser, $ } from "@wdio/globals";
123
+ import { expect } from "@wdio/globals";
124
+
125
+ describe("auth probe", () => {
126
+ it("can reach the main window", async () => {
127
+ // Tauri desktop apps often skip network auth — adapt if your app has auth
128
+ const root = await $("[data-testid='app-root']");
129
+ await expect(root).toBeDisplayed();
130
+ });
131
+ });
132
+ ```
133
+
134
+ ## Pitfalls
135
+
136
+ **Must build before run** — tauri-driver launches the binary; if the binary doesn't
137
+ exist or is stale the session fails immediately with a confusing error.
138
+
139
+ **Binary path** — the `application` path in `capabilities` must be the exact path
140
+ to the compiled binary. Debug builds are under `src-tauri/target/debug/`, release
141
+ builds under `src-tauri/target/release/`.
142
+
143
+ **Port conflicts** — tauri-driver listens on port 4444 by default. Ensure no other
144
+ WebDriver session is running on the same port.
145
+
146
+ **CI** — Tauri desktop E2E on CI requires a display (Xvfb on Linux) and the full Rust
147
+ build toolchain. Use GitHub-hosted `ubuntu-latest` or `macos-latest` runners.
@@ -0,0 +1,154 @@
1
+ # VS Code Extension Reference
2
+
3
+ Full install, config, and test walkthrough for VS Code extension testing using
4
+ `@vscode/test-cli` and `@vscode/test-electron`. Source: upstream VS Code extension
5
+ testing docs.
6
+
7
+ ## Prerequisites
8
+
9
+ - VS Code installed (used as the test host)
10
+ - Node.js / pnpm available
11
+ - On Linux CI: Xvfb for a display server (extensions require a GUI)
12
+
13
+ ## Install
14
+
15
+ ```bash
16
+ pnpm add -D @vscode/test-cli @vscode/test-electron
17
+ ```
18
+
19
+ Verify:
20
+
21
+ ```bash
22
+ pnpm exec vscode-test --version
23
+ ```
24
+
25
+ ## .vscode-test.mjs
26
+
27
+ Create `.vscode-test.mjs` at the extension package root (e.g. `apps/vscode/`):
28
+
29
+ ```js
30
+ import { defineConfig } from "@vscode/test-cli";
31
+
32
+ export default defineConfig({
33
+ files: "e2e/**/*.test.js", // compiled output path (JS, not TS)
34
+ extensionDevelopmentPath: ".", // path to the extension package root
35
+ workspaceFolder: "test-fixtures/workspace", // optional: open a fixture workspace
36
+ mocha: {
37
+ timeout: 20_000,
38
+ ui: "bdd",
39
+ },
40
+ });
41
+ ```
42
+
43
+ For TypeScript source, compile tests before running:
44
+
45
+ ```json
46
+ {
47
+ "scripts": {
48
+ "test:e2e": "tsc -p tsconfig.test.json && vscode-test",
49
+ "test:e2e:watch": "vscode-test --watch"
50
+ }
51
+ }
52
+ ```
53
+
54
+ ## Extension host lifecycle
55
+
56
+ `@vscode/test-electron` downloads an isolated VS Code instance, installs your extension,
57
+ opens the workspace, and runs the Mocha suite inside the extension host process.
58
+
59
+ Tests import from `vscode` — the module is available because they run inside VS Code:
60
+
61
+ ```ts
62
+ import * as vscode from "vscode";
63
+ import * as assert from "assert";
64
+
65
+ suite("Extension", () => {
66
+ test("extension activates", async () => {
67
+ const ext = vscode.extensions.getExtension("yourpublisher.yourextension");
68
+ assert.ok(ext, "extension not found");
69
+ await ext.activate();
70
+ assert.ok(ext.isActive);
71
+ });
72
+
73
+ test("command is registered", async () => {
74
+ const commands = await vscode.commands.getCommands();
75
+ assert.ok(
76
+ commands.includes("yourextension.yourCommand"),
77
+ "command not registered"
78
+ );
79
+ });
80
+ });
81
+ ```
82
+
83
+ The test file runs inside the VS Code extension host — full `vscode` API is available,
84
+ including workspace, editors, commands, and diagnostics.
85
+
86
+ ## Directory structure
87
+
88
+ ```
89
+ apps/vscode/
90
+ .vscode-test.mjs
91
+ e2e/
92
+ _probe/
93
+ activation.test.ts
94
+ commands/
95
+ my-command.test.ts
96
+ test-fixtures/
97
+ workspace/ # optional: committed fixture files opened in tests
98
+ ```
99
+
100
+ ## Activation probe
101
+
102
+ `apps/vscode/e2e/_probe/activation.test.ts`:
103
+
104
+ ```ts
105
+ import * as vscode from "vscode";
106
+ import * as assert from "assert";
107
+
108
+ suite("Activation probe", () => {
109
+ test("extension activates without error", async () => {
110
+ // Replace with your publisher.extensionname from package.json
111
+ const ext = vscode.extensions.getExtension("yourpublisher.yourextension");
112
+ assert.ok(ext, "Extension not installed in test host");
113
+ if (!ext.isActive) {
114
+ await ext.activate();
115
+ }
116
+ assert.ok(ext.isActive, "Extension did not activate");
117
+ });
118
+ });
119
+ ```
120
+
121
+ ## CI (GitHub Actions)
122
+
123
+ Linux runners require Xvfb. Use the `xvfb-run` wrapper:
124
+
125
+ ```yaml
126
+ - name: Install dependencies
127
+ run: pnpm install
128
+
129
+ - name: Compile extension tests
130
+ run: pnpm --filter @codebyplan/vscode test:compile
131
+
132
+ - name: Run VS Code extension tests
133
+ run: xvfb-run -a pnpm --filter @codebyplan/vscode test:e2e
134
+ env:
135
+ DISPLAY: ':99.0'
136
+ ```
137
+
138
+ On macOS/Windows runners, Xvfb is not needed — `vscode-test` uses the native display.
139
+
140
+ ## Pitfalls
141
+
142
+ **Wrong extensionDevelopmentPath** — if the path in `.vscode-test.mjs` doesn't point
143
+ to the package root (where `package.json` has the `contributes` block), VS Code won't
144
+ find the extension and activation tests will fail silently.
145
+
146
+ **TypeScript source vs compiled output** — `@vscode/test-cli` runs compiled JS.
147
+ Always compile before invoking `vscode-test` in CI.
148
+
149
+ **Extension host isolation** — each test run downloads a fresh VS Code binary into a
150
+ temp dir. This is intentional; do not try to reuse the system VS Code installation.
151
+
152
+ **`vscode` module availability** — tests run inside the extension host, so `import
153
+ * as vscode from "vscode"` resolves correctly. The same import will fail if you try
154
+ to run these files with plain Node.js outside the host.
@@ -0,0 +1,185 @@
1
+ # XCUITest Reference
2
+
3
+ Full walkthrough for iOS native E2E testing with XCUITest via the Expo `withXCUITests`
4
+ plugin. Source: Apple XCUITest docs + Expo prebuild docs.
5
+
6
+ ## When to use XCUITest vs Maestro
7
+
8
+ | Scenario | Use |
9
+ | --- | --- |
10
+ | Standard UI flows (login, navigation, forms) | Maestro — simpler, cross-platform |
11
+ | Apple Watch companion app testing | XCUITest — Maestro can't target watchOS |
12
+ | HealthKit permission dialogs | XCUITest — system dialogs not reachable by Maestro |
13
+ | iOS system sheet interactions (share sheet, notification permissions) | XCUITest |
14
+ | Face ID / Touch ID prompts | XCUITest |
15
+ | Camera/microphone permission dialogs | XCUITest |
16
+
17
+ Choose Maestro first; escalate to XCUITest only when Maestro genuinely cannot reach
18
+ the target UI.
19
+
20
+ ## Prerequisites
21
+
22
+ - macOS with Xcode 15+ installed
23
+ - An active Apple Developer account (free tier sufficient for Simulator testing)
24
+ - Expo managed workflow with prebuild enabled
25
+ - `xcbeautify` for readable output: `brew install xcbeautify`
26
+
27
+ ## Setup — Expo withXCUITests plugin
28
+
29
+ Add the plugin to `app.config.ts` (or `app.config.js`):
30
+
31
+ ```ts
32
+ export default {
33
+ expo: {
34
+ plugins: [
35
+ ["expo-build-properties", { ios: { useFrameworks: "static" } }],
36
+ // Add your withXCUITests plugin config
37
+ ["./plugins/withXCUITests", {}],
38
+ ],
39
+ },
40
+ };
41
+ ```
42
+
43
+ If using the community `expo-xcuitest` plugin:
44
+
45
+ ```bash
46
+ pnpm add -D expo-xcuitest
47
+ ```
48
+
49
+ Then in `app.config.ts`:
50
+
51
+ ```ts
52
+ plugins: [
53
+ ["expo-xcuitest", { testTargetName: "AppUITests" }]
54
+ ]
55
+ ```
56
+
57
+ ## Prebuild
58
+
59
+ After updating `app.config.ts`, regenerate the native project:
60
+
61
+ ```bash
62
+ expo prebuild --platform ios --clean
63
+ ```
64
+
65
+ `--clean` ensures a fresh native project from the current config. Commit the generated
66
+ `ios/` directory so CI can build without running prebuild.
67
+
68
+ ## Swift test class
69
+
70
+ Create `ios/AppUITests/AppUITests.swift`:
71
+
72
+ ```swift
73
+ import XCTest
74
+
75
+ class AppUITests: XCTestCase {
76
+
77
+ var app: XCUIApplication!
78
+
79
+ override func setUpWithError() throws {
80
+ continueAfterFailure = false
81
+ app = XCUIApplication()
82
+
83
+ // Inject credentials via scheme environment variables
84
+ app.launchEnvironment["TEST_EMAIL"] = ProcessInfo.processInfo.environment["TEST_EMAIL"] ?? ""
85
+ app.launchEnvironment["TEST_PASSWORD"] = ProcessInfo.processInfo.environment["TEST_PASSWORD"] ?? ""
86
+
87
+ app.launch()
88
+ }
89
+
90
+ func testLoginFlow() throws {
91
+ // Wait for the login screen
92
+ let emailField = app.textFields["email-input"]
93
+ XCTAssertTrue(emailField.waitForExistence(timeout: 10))
94
+
95
+ emailField.tap()
96
+ emailField.typeText(app.launchEnvironment["TEST_EMAIL"]!)
97
+
98
+ let passwordField = app.secureTextFields["password-input"]
99
+ passwordField.tap()
100
+ passwordField.typeText(app.launchEnvironment["TEST_PASSWORD"]!)
101
+
102
+ app.buttons["sign-in-button"].tap()
103
+
104
+ // Assert post-login element
105
+ let dashboard = app.staticTexts["Dashboard"]
106
+ XCTAssertTrue(dashboard.waitForExistence(timeout: 15))
107
+ }
108
+ }
109
+ ```
110
+
111
+ ## accessibilityIdentifier targeting
112
+
113
+ Set `accessibilityIdentifier` in your React Native components so XCUITest can find them:
114
+
115
+ ```tsx
116
+ // In React Native
117
+ <TextInput
118
+ testID="email-input" // becomes accessibilityIdentifier on iOS
119
+ accessibilityLabel="Email"
120
+ />
121
+ ```
122
+
123
+ In XCUITest, query by identifier:
124
+
125
+ ```swift
126
+ app.textFields["email-input"] // TextInput
127
+ app.buttons["sign-in-button"] // TouchableOpacity / Pressable
128
+ app.staticTexts["Dashboard"] // Text component
129
+ ```
130
+
131
+ ## Credentials via scheme environment variables
132
+
133
+ Rather than hardcoding credentials, inject them via the Xcode scheme.
134
+
135
+ In Xcode: Product → Scheme → Edit Scheme → Run → Arguments → Environment Variables.
136
+ Add `TEST_EMAIL` and `TEST_PASSWORD` pointing to your local values.
137
+
138
+ For CI, pass them via `xcodebuild`:
139
+
140
+ ```bash
141
+ xcodebuild test \
142
+ -workspace ios/YourApp.xcworkspace \
143
+ -scheme YourApp \
144
+ -destination 'platform=iOS Simulator,name=iPhone 16,OS=latest' \
145
+ TEST_EMAIL="$TEST_EMAIL" \
146
+ TEST_PASSWORD="$TEST_PASSWORD" \
147
+ | xcbeautify
148
+ ```
149
+
150
+ ## Running tests
151
+
152
+ ```bash
153
+ xcodebuild test \
154
+ -workspace ios/YourApp.xcworkspace \
155
+ -scheme YourApp \
156
+ -destination 'platform=iOS Simulator,name=iPhone 16,OS=latest' \
157
+ | xcbeautify
158
+ ```
159
+
160
+ ## pnpm script
161
+
162
+ ```json
163
+ {
164
+ "scripts": {
165
+ "xcuitest": "xcodebuild test -workspace ios/YourApp.xcworkspace -scheme YourApp -destination 'platform=iOS Simulator,name=iPhone 16,OS=latest' | xcbeautify"
166
+ }
167
+ }
168
+ ```
169
+
170
+ ## Pitfalls
171
+
172
+ **Simulator not booted** — `xcodebuild` will boot the simulator if needed, but the
173
+ first run is slow. Pre-boot with `xcrun simctl boot "iPhone 16"` in CI setup.
174
+
175
+ **accessibilityIdentifier vs testID** — React Native maps `testID` to
176
+ `accessibilityIdentifier` on iOS. Ensure the component renders the prop all the way
177
+ through; some wrappers drop it.
178
+
179
+ **waitForExistence timeout** — always use `waitForExistence(timeout:)` rather than
180
+ asserting element existence immediately. React Native renders asynchronously; the
181
+ element may not be in the view hierarchy at the instant of the assertion.
182
+
183
+ **Derived data cache** — stale derived data can cause confusing failures. Clear with
184
+ `rm -rf ~/Library/Developer/Xcode/DerivedData` if tests pass locally but fail after
185
+ a schema change.
@@ -10,7 +10,7 @@ effort: xhigh
10
10
  Invoked twice per round in non-`claude_only` profiles:
11
11
 
12
12
  1. `round-executor` Step 3.8 — `phase: 'style_only'`, no e2e screenshots. Reviews token/spacing/typography/color/cohesion against the just-written code.
13
- 2. `/cbp-round-execute` Step 5b — `phase: 'screenshot_review'`, with screenshots from `test-e2e-agent`. Reviews rendered output and detects baseline regressions.
13
+ 2. `/cbp-round-execute` Step 5b — `phase: 'screenshot_review'`, with screenshots from the `cbp-e2e-*` specialists. Reviews rendered output and detects baseline regressions.
14
14
 
15
15
  Default `phase: 'full'` runs everything (back-compat for any caller not yet migrated). Inline counterpart of the up-front `frontend-design` skill — `frontend-design` decides direction before code; `frontend-ui` reviews and polishes after code.
16
16
 
@@ -36,7 +36,7 @@ input:
36
36
  context:
37
37
  checkpoint_goal: string
38
38
  round_requirements: string
39
- e2e_screenshots: # Required for phase 'screenshot_review' or 'full' (when present); empty / omitted for 'style_only'. Sourced from round.context.e2e_output.screenshots (populated by test-e2e-agent at /cbp-round-execute Step 5).
39
+ e2e_screenshots: # Required for phase 'screenshot_review' or 'full' (when present); empty / omitted for 'style_only'. Sourced from the aggregated round.context.e2e_outputs[*].screenshots (populated by the cbp-e2e-* specialists at /cbp-round-execute Step 5).
40
40
  - test_name: string
41
41
  path: string # Repo-relative or absolute path to PNG
42
42
  page_or_screen: string
@@ -213,7 +213,7 @@ The skill's auto-fix capability is for in-scope polish, not opportunistic sweeps
213
213
  **Specifically forbidden** (always out of scope, never edited regardless of `files_changed`):
214
214
 
215
215
  - `.claude/**` — managed infrastructure under user-level governance
216
- - Project test infrastructure (e.g., `playwright.config.*`, `e2e/**`) — governed by `test-e2e-agent`
216
+ - Project test infrastructure (e.g., `playwright.config.*`, `e2e/**`) — governed by the `cbp-e2e-*` specialist agents
217
217
  - DB migrations (e.g., `supabase/migrations/**`) — governed by `database-agent`
218
218
  - Vendor mirrors and read-only reference trees
219
219
 
@@ -254,9 +254,9 @@ Go beyond fixing violations — actively improve visual quality. If spacing coul
254
254
 
255
255
  - **Loaded twice per round** (non-`claude_only` profiles):
256
256
  1. `round-executor` Step 3.8 with `phase: 'style_only'` and empty `e2e_screenshots[]` — reviews the just-written code's tokens/spacing/typography/color/cohesion (mandatory when files_changed contains UI / styling files)
257
- 2. `/cbp-round-execute` Step 5b with `phase: 'screenshot_review'` and screenshots from `round.context.e2e_output.screenshots` — runs Phase 6.5 only (rendered-output review + baseline regressions). Skipped when no e2e ran (`claude_only` / `backend` / `has_ui_work === false`).
258
- - **Also invoked by**: `/cbp-checkpoint-check` (TASK-2 deliverable, future) with screenshots from a whole-checkpoint e2e run
259
- - **Consumes**: `e2e_screenshots[]` from `round.context.e2e_output.screenshots` (populated by `test-e2e-agent` at `/cbp-round-execute` Step 5)
257
+ 2. `/cbp-round-execute` Step 5b with `phase: 'screenshot_review'` and screenshots aggregated from `round.context.e2e_outputs[*].screenshots` — runs Phase 6.5 only (rendered-output review + baseline regressions). Skipped when no e2e ran (`claude_only` / `backend`, or no eligible framework in `.codebyplan/e2e.json`).
258
+ - **Also invoked by**: `/cbp-checkpoint-check` with screenshots aggregated from a whole-checkpoint e2e run
259
+ - **Consumes**: `e2e_screenshots[]` aggregated from `round.context.e2e_outputs[*].screenshots` (populated by the `cbp-e2e-*` specialists at `/cbp-round-execute` Step 5)
260
260
  - **Output written to**: `round.context.frontend_ui_review` — when invoked twice per round, the second invocation merges with the first
261
261
  - **Downstream gate**: this skill emits `findings[]` only. Baseline-regression findings surface as a BLOCKING gate at `/cbp-round-end` Step 7 (baselines never auto-accepted); rendered-visual critical findings are surfaced in the Step 7 findings presentation.
262
262
  - **Paired with**: `frontend-design` (pre-implementation aesthetic decision), `frontend-ux` (interaction-quality self-review, also Step 3.8)
@@ -148,7 +148,7 @@ This rule applies to every file. The skill's auto-fix surface exists because in-
148
148
  **Specifically forbidden** (always out of scope, never edited regardless of `files_changed`):
149
149
 
150
150
  - `.claude/**` — managed infrastructure under user-level governance
151
- - Project test infrastructure (e.g., `playwright.config.*`, `e2e/**`) — governed by `test-e2e-agent`
151
+ - Project test infrastructure (e.g., `playwright.config.*`, `e2e/**`) — governed by the `cbp-e2e-*` specialist agents
152
152
  - DB migrations (e.g., `supabase/migrations/**`) — governed by `database-agent`
153
153
  - Vendor mirrors and read-only reference trees
154
154
 
@@ -116,7 +116,12 @@ Only use `--force` if the user confirms.
116
116
 
117
117
  ### Step 9: Delete Branch (if requested)
118
118
 
119
- **Protected branch check:** If `$BRANCH_NAME` is `main`, `development`, or `preview` — refuse deletion and stop.
119
+ **Protected branch check:** Read the protected set from `.codebyplan/git.json`:
120
+ ```bash
121
+ PRODUCTION=$(jq -r '.branch_config.production // "main"' .codebyplan/git.json)
122
+ PROTECTED=$(jq -r '.branch_config.protected[]? // empty' .codebyplan/git.json)
123
+ ```
124
+ If `$BRANCH_NAME` equals `$PRODUCTION` or appears in `$PROTECTED` — refuse deletion and stop.
120
125
 
121
126
  **Checkpoint verification:** Before deleting a feat branch, verify that the associated checkpoint has completed via `/cbp-checkpoint-end`. If the checkpoint is still active, warn the user that unshipped work may be lost.
122
127
 
@@ -126,6 +131,17 @@ git branch -d "$BRANCH_NAME" && git push origin --delete "$BRANCH_NAME"
126
131
 
127
132
  Use `-d` (not `-D`) to prevent deleting unmerged work. If it fails because the branch is not fully merged, inform the user and ask if they want to force delete with `-D`.
128
133
 
134
+ After the git branch delete succeeds, run a conditional Supabase preview-branch teardown for `$BRANCH_NAME`:
135
+
136
+ > Lifecycle contract: see [[supabase-branch-lifecycle]].
137
+
138
+ - Call `mcp__supabase__list_branches` with `project_id: rrvtrumtkhrsbhcyrwvf`.
139
+ - Scan the returned list for an entry whose `name` exactly equals `$BRANCH_NAME`.
140
+ - If found: call `mcp__supabase__delete_branch` with its `branch_id`. Report "Supabase preview branch deleted: `$BRANCH_NAME`".
141
+ - If not found: no-op silently — the GitHub integration may have already removed it on PR close; not-found is success, NOT an error.
142
+ - If the `list_branches` call itself fails (network, auth, or a non-success response — distinct from a successful lookup that returns no match): emit a non-blocking warning that the Supabase preview branch for `$BRANCH_NAME` may still exist and should be verified in the dashboard. Do not treat an API failure as a not-found success.
143
+ - Never delete the parent project `rrvtrumtkhrsbhcyrwvf` itself or any persistent/production branch.
144
+
129
145
  ### Step 10: Show Result
130
146
 
131
147
  ```