From c2260d7383da2dc847b03023256353538dafae47 Mon Sep 17 00:00:00 2001 From: Brian Love Date: Thu, 21 May 2026 13:13:28 -0700 Subject: [PATCH 1/5] docs(spec): examples/chat e2e matrix sharding design MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit Goal: cut wall-time of `examples/chat — e2e` by running it across a 4-way matrix using Playwright's built-in --shard=N/M flag. Mirrors the cockpit fleet's matrix philosophy without restructuring the underlying e2e harness. Co-Authored-By: Claude Opus 4.7 (1M context) --- ...26-05-21-examples-chat-e2e-shard-design.md | 105 ++++++++++++++++++ 1 file changed, 105 insertions(+) create mode 100644 docs/superpowers/specs/2026-05-21-examples-chat-e2e-shard-design.md diff --git a/docs/superpowers/specs/2026-05-21-examples-chat-e2e-shard-design.md b/docs/superpowers/specs/2026-05-21-examples-chat-e2e-shard-design.md new file mode 100644 index 00000000..cc131a30 --- /dev/null +++ b/docs/superpowers/specs/2026-05-21-examples-chat-e2e-shard-design.md @@ -0,0 +1,105 @@ +# examples/chat e2e — matrix sharding design + +## Goal + +Reduce wall-time of the `examples/chat — e2e` CI job by running it across multiple GitHub Actions matrix shards in parallel, mirroring the cockpit fleet's matrix philosophy. Borrow the architectural pattern without restructuring the underlying e2e harness. + +## Current state + +- 31 tests across 19 spec files under `examples/chat/angular/e2e/`. +- Playwright config: `fullyParallel: false, workers: 1, retries: 2`. +- Bespoke `global-setup.ts` spawns aimock subprocess + `langgraph dev` (:2024, with `OPENAI_BASE_URL` pointed at aimock) + Angular dev server (:4200). +- Single CI job (`examples/chat — e2e`) runs all 31 tests sequentially. Observed wall time on recent runs: 6+ minutes. + +By contrast, the cockpit fleet runs 24 caps as a 24-way matrix with `max-parallel: 5`, finishing the whole fleet in ~5 minutes. Each cockpit cap has 1-2 tests and pays the same setup tax in parallel. + +## Approach: Playwright `--shard=N/M` + +A single change to `.github/workflows/ci.yml`: add a 4-way matrix to the `examples/chat — e2e` job and forward `--shard=${{ matrix.shard }}` to Playwright. + +```yaml +strategy: + fail-fast: false + matrix: + shard: ['1/4', '2/4', '3/4', '4/4'] +steps: + # ... existing setup steps ... + - run: npx nx e2e examples-chat-angular -- --shard=${{ matrix.shard }} +``` + +Job display name templated as `examples/chat — e2e (${{ matrix.shard }})` so each shard appears as a distinct required check. + +No application code, no test code, no harness changes. The bespoke `global-setup.ts`/`aimock-runner.ts` and the local `test-helpers.ts` stay as-is. + +## Why 4 shards (not 2, not 19) + +- **2 shards** — only halves wall time; under-uses parallelism budget. +- **19 shards** (one per spec) — 19× the setup tax (each shard spends ~1-2 min on `npm ci` + langgraph startup + Angular dev server for ~10s of actual tests). Setup dominates; mostly idle CPU. +- **4 shards** — sweet spot: ~8 tests/shard, ~30-60s of test work + ~1-2 min setup ≈ 2-3 min per shard. Quarters wall time without quadrupling CI compute waste. + +If the first run shows uneven distribution (one shard much slower than the others), we can either bump to 6 or move a specific spec file via test-file naming, but neither is in scope here. + +## Why Playwright `--shard` (not a custom matrix manifest) + +- Built-in flag; standard Playwright pattern. No custom dispatcher to maintain. +- Distributes test files by alphabetical sort + round-robin into M buckets. Deterministic across runs. +- New spec files are auto-assigned to a shard without manifest edits. +- Tradeoff: distribution is by file count, not by runtime. If one spec is much slower than the others, its shard runs longer. Acceptable given current uniformity of the suite. + +## URL routing and `--shard` interaction + +`--shard` divides test FILES, not tests within a file. `fullyParallel: false, workers: 1` inside a shard is preserved — tests within a file still run sequentially, so any intra-file ordering invariants are safe. Cross-file ordering was never relied on (Playwright doesn't guarantee it); this is verified by the fact that the local `playwright.config.ts` already uses `fullyParallel: false` without specifying file order. + +## Components affected + +| File | Change | +|---|---| +| `.github/workflows/ci.yml` | Add `strategy.matrix.shard` + `--shard` flag to the `examples/chat — e2e` job; update `name:` template | +| `examples/chat/angular/e2e/README.md` (if present) | Note the matrix shape | +| Branch protection rules (manual / out-of-PR) | Required-checks list must include `examples/chat — e2e (1/4)` … `(4/4)` instead of the singular old name | + +`examples/chat/angular/e2e/playwright.config.ts` — **no change**. `--shard` is a CLI flag; no config-side opt-in is needed. + +## Data flow per shard + +Identical to today, per shard: + +1. `actions/checkout`, `setup-node`, `npm ci` +2. `aimock` subprocess starts (replay mode, reads `e2e/fixtures/*.json`) +3. `langgraph dev` spawned on :2024 with `OPENAI_BASE_URL` pointed at aimock +4. Angular dev server boots on :4200 +5. Playwright runs `--shard=N/4` against http://localhost:4200 +6. Teardown via `global-teardown.ts` + +Each shard is fully self-contained — no shared state, no inter-shard communication. + +## Error handling + +- `fail-fast: false` — one shard's failure doesn't cancel siblings (so we see the full failure picture) +- Per-shard `retries: 2` — same semantics as today, just applied per shard +- Per-shard Playwright HTML report is uploaded as a separate artifact (artifact name templated `examples-chat-e2e-report-${{ matrix.shard }}` to avoid collision) + +## Required-checks update (post-merge action item) + +GitHub branch protection rules currently reference the singular `examples/chat — e2e` check. After this lands, that name no longer exists; the rule must be updated to require the 4 templated names. This is a repo-admin action, not a code change. Without it, the PR gate would wait forever on a name that's never reported. + +## Testing / validation + +1. **Local dry-run** — `npx nx e2e examples-chat-angular -- --shard=1/4 --list-files` confirms file distribution; sum across 1/4..4/4 = 19 unique files. +2. **First CI run** — observe per-shard wall time. Confirm aggregate test count = 31. Confirm no test runs twice. +3. **Stability check** — at least one green PR cycle on main before relying on the shape; watch for any newly-flaky tests surfaced by the changed relative ordering. + +## Out of scope + +- Migrating to `@ngaf-internal/e2e-harness` (deliberately tabled; bespoke setup has guards the shared factory lacks — see earlier audit) +- Reducing `retries` from 2 (orthogonal flake-reduction work) +- Enabling `fullyParallel: true` inside a shard (would require validating that shared dev servers tolerate parallel browser contexts; separate design) +- Re-tuning Playwright timeouts or browser config +- Speeding up the per-shard setup tax (langgraph startup, `npm ci`, Angular boot) +- Cross-shard test result aggregation beyond what GitHub Actions provides natively + +## Risks + +- **Uneven shard runtime**: if one spec dominates, its shard runs long; the other shards sit idle. Mitigation: monitor first run, re-tune count or split spec only if needed. +- **Flake surfaced by new ordering**: tests that implicitly relied on global state set by an earlier file may break. Mitigation: `retain-on-failure` traces already enabled; debug if observed. +- **Branch protection blocker**: PR cannot merge until the required-checks rule is updated. Mitigation: call this out in PR description. From 26e112f4b8ea73998cf7c2291e7b7167d0cfa168 Mon Sep 17 00:00:00 2001 From: Brian Love Date: Thu, 21 May 2026 13:14:27 -0700 Subject: [PATCH 2/5] =?UTF-8?q?docs(spec):=20refine=20e2e=20shard=20design?= =?UTF-8?q?=20=E2=80=94=20numeric=20matrix,=20artifact=20naming?= MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit Self-review fixes: - Matrix uses numeric `shard: [1, 2, 3, 4]` rather than `'1/4'` strings, because GitHub Actions artifact names cannot contain `/`. - Explicit `--skip-nx-cache` preservation + `--` separator placement. - Trace artifact name templated to avoid same-name collision across matrix jobs (actions/upload-artifact@v4 errors on identical names). - Required-checks list spelled out by full check name. Co-Authored-By: Claude Opus 4.7 (1M context) --- .../2026-05-21-examples-chat-e2e-shard-design.md | 14 ++++++++------ 1 file changed, 8 insertions(+), 6 deletions(-) diff --git a/docs/superpowers/specs/2026-05-21-examples-chat-e2e-shard-design.md b/docs/superpowers/specs/2026-05-21-examples-chat-e2e-shard-design.md index cc131a30..eb51bcc2 100644 --- a/docs/superpowers/specs/2026-05-21-examples-chat-e2e-shard-design.md +++ b/docs/superpowers/specs/2026-05-21-examples-chat-e2e-shard-design.md @@ -15,19 +15,21 @@ By contrast, the cockpit fleet runs 24 caps as a 24-way matrix with `max-paralle ## Approach: Playwright `--shard=N/M` -A single change to `.github/workflows/ci.yml`: add a 4-way matrix to the `examples/chat — e2e` job and forward `--shard=${{ matrix.shard }}` to Playwright. +A single change to `.github/workflows/ci.yml`: add a 4-way matrix to the `examples/chat — e2e` job and forward `--shard=N/4` to Playwright. Matrix uses a numeric `shard` index (1-4) rather than a `'N/M'` string, because GitHub Actions artifact names cannot contain `/`. ```yaml strategy: fail-fast: false matrix: - shard: ['1/4', '2/4', '3/4', '4/4'] + shard: [1, 2, 3, 4] steps: # ... existing setup steps ... - - run: npx nx e2e examples-chat-angular -- --shard=${{ matrix.shard }} + - run: npx nx e2e examples-chat-angular --skip-nx-cache -- --shard=${{ matrix.shard }}/4 ``` -Job display name templated as `examples/chat — e2e (${{ matrix.shard }})` so each shard appears as a distinct required check. +Job display name templated as `examples/chat — e2e (${{ matrix.shard }}/4)` so each shard appears as a distinct required check (e.g. `examples/chat — e2e (1/4)`, `examples/chat — e2e (2/4)`, …). + +The `--skip-nx-cache` flag from the current command is preserved; the `--` separator passes everything after it through to Playwright. No application code, no test code, no harness changes. The bespoke `global-setup.ts`/`aimock-runner.ts` and the local `test-helpers.ts` stay as-is. @@ -56,7 +58,7 @@ If the first run shows uneven distribution (one shard much slower than the other |---|---| | `.github/workflows/ci.yml` | Add `strategy.matrix.shard` + `--shard` flag to the `examples/chat — e2e` job; update `name:` template | | `examples/chat/angular/e2e/README.md` (if present) | Note the matrix shape | -| Branch protection rules (manual / out-of-PR) | Required-checks list must include `examples/chat — e2e (1/4)` … `(4/4)` instead of the singular old name | +| Branch protection rules (manual / out-of-PR) | Required-checks list must include `examples/chat — e2e (1/4)`, `examples/chat — e2e (2/4)`, `examples/chat — e2e (3/4)`, `examples/chat — e2e (4/4)` instead of the singular old name | `examples/chat/angular/e2e/playwright.config.ts` — **no change**. `--shard` is a CLI flag; no config-side opt-in is needed. @@ -77,7 +79,7 @@ Each shard is fully self-contained — no shared state, no inter-shard communica - `fail-fast: false` — one shard's failure doesn't cancel siblings (so we see the full failure picture) - Per-shard `retries: 2` — same semantics as today, just applied per shard -- Per-shard Playwright HTML report is uploaded as a separate artifact (artifact name templated `examples-chat-e2e-report-${{ matrix.shard }}` to avoid collision) +- Per-shard Playwright trace artifact name templated as `examples-chat-e2e-trace-shard-${{ matrix.shard }}` to avoid collision (`actions/upload-artifact@v4` does not merge same-named uploads across matrix jobs and would error on identical names) ## Required-checks update (post-merge action item) From b2e1968a622858830eec14cb7f59577c60aa5feb Mon Sep 17 00:00:00 2001 From: Brian Love Date: Thu, 21 May 2026 13:18:15 -0700 Subject: [PATCH 3/5] docs(plan): examples/chat e2e matrix sharding implementation plan Two-task plan: (1) edit ci.yml's examples-chat-e2e job to use a 4-way shard matrix + Playwright --shard flag + templated artifact name; (2) push, open PR, verify per-shard wall-time on first CI run. Spec: docs/superpowers/specs/2026-05-21-examples-chat-e2e-shard-design.md Co-Authored-By: Claude Opus 4.7 (1M context) --- .../2026-05-21-examples-chat-e2e-shard.md | 267 ++++++++++++++++++ 1 file changed, 267 insertions(+) create mode 100644 docs/superpowers/plans/2026-05-21-examples-chat-e2e-shard.md diff --git a/docs/superpowers/plans/2026-05-21-examples-chat-e2e-shard.md b/docs/superpowers/plans/2026-05-21-examples-chat-e2e-shard.md new file mode 100644 index 00000000..3b34f3e8 --- /dev/null +++ b/docs/superpowers/plans/2026-05-21-examples-chat-e2e-shard.md @@ -0,0 +1,267 @@ +# examples/chat e2e — matrix sharding Implementation Plan + +> **For agentic workers:** REQUIRED SUB-SKILL: Use superpowers:subagent-driven-development (recommended) or superpowers:executing-plans to implement this plan task-by-task. Steps use checkbox (`- [ ]`) syntax for tracking. + +**Goal:** Cut wall-time of the `examples/chat — e2e` CI job by running it across a 4-way matrix using Playwright's built-in `--shard=N/M` flag. + +**Architecture:** A single change site (`.github/workflows/ci.yml`): convert the `examples-chat-e2e` job from a single runner to a `matrix.shard: [1, 2, 3, 4]` job that forwards `--shard=N/4` to Playwright. Each shard runs ~8 of the 31 tests across the 19 spec files. Per-shard trace artifact is renamed to include the shard index to avoid name collisions in `actions/upload-artifact@v4`. Downstream jobs that `need:` this job (`release-please` aggregator at line 374, `demo-deploy` at line 544) continue to work as-is because GitHub aggregates matrix job results: `needs.examples-chat-e2e.result == 'success'` only if all 4 shards succeed. + +**Tech Stack:** GitHub Actions, Playwright (`@playwright/test`), Nx (`@nx/playwright:playwright` executor). + +**Out of scope** (per spec): harness consolidation, retry tuning, `fullyParallel: true` within a shard, timeout retuning, branch-protection rule updates (done by repo admin post-merge). + +--- + +### Task 1: Convert `examples-chat-e2e` to a 4-way shard matrix + +**Files:** +- Modify: `.github/workflows/ci.yml:242-271` + +- [ ] **Step 1: Read the current job text to confirm starting state** + +Run: `sed -n '242,271p' .github/workflows/ci.yml` + +Expected output begins with ` examples-chat-e2e:` and ends with the artifact `retention-days: 7` line. The current run command is: + +``` + - run: npx nx e2e examples-chat-angular --skip-nx-cache +``` + +The current artifact name is `examples-chat-e2e-trace`. + +If the output differs, stop and reconcile against the spec at `docs/superpowers/specs/2026-05-21-examples-chat-e2e-shard-design.md` before editing. + +- [ ] **Step 2: Apply the matrix + shard-flag + templated name + unique artifact** + +Replace the block at `.github/workflows/ci.yml:242-271` with: + +```yaml + examples-chat-e2e: + name: "examples/chat — e2e (${{ matrix.shard }}/4)" + needs: ci-scope + if: github.event_name == 'push' || needs.ci-scope.outputs.examples_chat == 'true' + runs-on: ubuntu-latest + timeout-minutes: 35 + strategy: + fail-fast: false + matrix: + shard: [1, 2, 3, 4] + steps: + - uses: actions/checkout@v6.0.2 + - uses: actions/setup-node@v6.3.0 + with: + node-version: 22 + cache: npm + - name: Install uv + uses: astral-sh/setup-uv@v8.0.0 + with: + python-version: '3.12' + - run: npm ci + - working-directory: examples/chat/python + run: uv sync + - run: npx playwright install --with-deps chromium + - run: npx nx e2e examples-chat-angular --skip-nx-cache -- --shard=${{ matrix.shard }}/4 + - name: Upload Playwright trace on failure + if: failure() + uses: actions/upload-artifact@v4 + with: + name: examples-chat-e2e-trace-shard-${{ matrix.shard }} + path: | + test-results/ + examples/chat/angular/e2e/test-results/ + retention-days: 7 +``` + +Three substantive changes vs. the prior block: +1. `name:` is quoted and templated with `${{ matrix.shard }}/4` so each matrix entry surfaces a distinct check name like `examples/chat — e2e (1/4)`. +2. New `strategy:` block above `steps:` with `fail-fast: false` and `matrix: { shard: [1, 2, 3, 4] }`. +3. The `npx nx e2e` line forwards `--shard=N/4` to Playwright after the Nx executor's `--` separator. `--skip-nx-cache` is preserved. +4. Artifact `name:` includes `-shard-${{ matrix.shard }}` — required because `actions/upload-artifact@v4` errors on duplicate artifact names across matrix entries. + +- [ ] **Step 3: Run a YAML syntax check** + +Run: `python3 -c "import yaml; yaml.safe_load(open('.github/workflows/ci.yml'))"` + +Expected: no output, exit code 0. + +If a `ScannerError` or `ParserError` fires, the most likely cause is indentation drift on the `strategy:` block. Compare against the cockpit-e2e job at `.github/workflows/ci.yml:273` for a reference matrix-strategy shape that already parses. + +- [ ] **Step 4: Confirm the downstream `needs:` references are still valid** + +Run: `grep -n 'examples-chat-e2e' .github/workflows/ci.yml` + +Expected: 4 matches — +- Line ~242: the job definition (` examples-chat-e2e:`) +- Line ~374: inside the aggregator job's `needs: [...]` list +- Line ~544: inside `demo-deploy`'s `needs: [examples-chat-smoke, examples-chat-e2e]` +- Line ~554: inside `demo-deploy`'s gate `if [ "${{ needs.examples-chat-e2e.result }}" != "success" ]` + +No changes to those four sites: GitHub aggregates matrix job results — `needs.examples-chat-e2e.result` is `success` iff every shard succeeds, `failure` if any shard fails. + +If the line numbers have drifted (e.g. another edit landed first), update this checklist's expectations but do NOT modify those lines. + +- [ ] **Step 5: Local dry-run — verify shard distribution** + +A local Playwright `--list-files` confirms that the 4 shards collectively cover the 19 spec files with no overlap. + +Run (from repo root, after `npm ci` if not already done): + +```bash +for n in 1 2 3 4; do + echo "=== shard $n/4 ===" + npx playwright test --config=examples/chat/angular/e2e/playwright.config.ts \ + --shard=$n/4 --list 2>/dev/null \ + | grep -E '\.spec\.ts' | sed 's/^ *//' | sort -u +done +``` + +Expected: +- Each shard prints a non-empty list of spec files. +- Union across all 4 shards has 19 unique paths (matches `ls examples/chat/angular/e2e/*.spec.ts | grep -v aimock-runner | wc -l`). +- Intersection between any two shards is empty. + +Quick union sanity check in one line: + +```bash +for n in 1 2 3 4; do npx playwright test --config=examples/chat/angular/e2e/playwright.config.ts --shard=$n/4 --list 2>/dev/null; done \ + | grep -oE 'examples/chat/angular/e2e/[a-z-]+\.spec\.ts' | sort -u | wc -l +``` + +Expected output: `19` (the count of `.spec.ts` files under that directory excluding `aimock-runner.spec.ts`, which is excluded by `testIgnore` in playwright.config.ts). + +If the count differs from 19, do NOT proceed — investigate. The most likely cause is that a new spec was added that Playwright doesn't include in any shard (unlikely with `--shard` default behavior, but possible if `testMatch` excludes it). + +- [ ] **Step 6: Commit** + +```bash +git add .github/workflows/ci.yml +git commit -m "ci: shard examples/chat e2e into 4 parallel matrix jobs + +Playwright's --shard=N/M flag auto-distributes the 19 spec files +across 4 GitHub Actions matrix entries. Mirrors the cockpit fleet's +matrix philosophy. Expected wall-time: ~6 min → ~2-3 min. + +- strategy.matrix.shard: [1, 2, 3, 4], fail-fast: false +- name templated: examples/chat — e2e (1/4), (2/4), ... +- --shard=N/4 passed through Nx executor's -- separator +- Trace artifact templated examples-chat-e2e-trace-shard-N to avoid + same-name collision in actions/upload-artifact@v4 + +Downstream needs: references (release aggregator, demo-deploy gate) +unchanged — GitHub aggregates matrix results automatically. + +POST-MERGE ACTION ITEM: update GitHub branch protection required-checks +list from 'examples/chat — e2e' to the 4 templated names. + +Spec: docs/superpowers/specs/2026-05-21-examples-chat-e2e-shard-design.md +" +``` + +--- + +### Task 2: Push, open PR, verify first CI run + +**Files:** +- None modified (CI observation + PR metadata only) + +- [ ] **Step 1: Push the branch** + +Run: `git push -u origin claude/chat-e2e-shard` + +Expected: push succeeds, branch tracked. + +- [ ] **Step 2: Open the PR** + +Run: + +```bash +gh pr create --title "ci: shard examples/chat e2e into 4 parallel matrix jobs" --body "$(cat <<'EOF' +## Summary + +- Convert the singular \`examples/chat — e2e\` CI job into a 4-way matrix using Playwright's built-in \`--shard=N/M\` flag. +- Mirrors the cockpit fleet's matrix philosophy without touching the underlying e2e harness. +- Expected wall-time: ~6 min → ~2-3 min. + +## ⚠️ Post-merge action item + +GitHub branch protection rules currently require the singular check \`examples/chat — e2e\`. After this lands, that name no longer exists; the rule must be updated to require all four templated names: + +- \`examples/chat — e2e (1/4)\` +- \`examples/chat — e2e (2/4)\` +- \`examples/chat — e2e (3/4)\` +- \`examples/chat — e2e (4/4)\` + +Until that update, future PR gates may fail to evaluate. **Repo admin should update branch protection immediately after merge.** + +## Test plan + +- [ ] All four \`examples/chat — e2e (N/4)\` matrix entries report success on this PR +- [ ] Per-shard wall-time is ~2-3 min (vs. ~6 min single-job baseline) +- [ ] Aggregate test count across shards is 31 (no test runs twice, no test is dropped) +- [ ] No flake surfaced by the changed relative test order + +Spec: \`docs/superpowers/specs/2026-05-21-examples-chat-e2e-shard-design.md\` +Plan: \`docs/superpowers/plans/2026-05-21-examples-chat-e2e-shard.md\` + +🤖 Generated with [Claude Code](https://claude.com/claude-code) +EOF +)" +``` + +Expected: a URL to the new PR is printed. + +- [ ] **Step 3: Wait for CI to start, then list the new check names** + +Run (a minute or two after the push): + +```bash +gh pr checks $(gh pr view --json number --jq .number) +``` + +Expected: 4 lines containing `examples/chat — e2e (1/4)` … `(4/4)`. If only 1 line for the old name appears, the matrix was not picked up — recheck Step 2 of Task 1. + +- [ ] **Step 4: After CI completes, verify per-shard outcomes** + +Run: + +```bash +PR=$(gh pr view --json number --jq .number) +RUN=$(gh run list --branch claude/chat-e2e-shard --workflow=ci.yml --limit 1 --json databaseId --jq '.[0].databaseId') +gh run view $RUN --json jobs --jq '.jobs[] | select(.name | startswith("examples/chat — e2e")) | {name, conclusion, startedAt, completedAt}' +``` + +Expected: 4 entries, each with `conclusion: "success"`. Note `startedAt`/`completedAt` to compute per-shard duration; the slowest shard is the new wall-time of this job. + +- [ ] **Step 5: Confirm aggregate test count from one shard's log (sanity check)** + +Run: + +```bash +JOB_ID=$(gh run view $RUN --json jobs --jq '.jobs[] | select(.name=="examples/chat — e2e (1/4)") | .databaseId') +gh run view --job=$JOB_ID --log 2>&1 | grep -E "[0-9]+ passed" | tail -3 +``` + +Expected: a line like `N passed (Mm Ss)` where N is roughly 31/4 ≈ 7-8 tests. Repeat for the other shards mentally; rough sum should be ≥31 (Playwright may report retries as additional "passed" entries). + +- [ ] **Step 6: Hand off to user for merge decision** + +The plan ends here. The user decides when to merge (and remembers to update branch protection — see PR body). + +--- + +## Verification checklist (entire plan) + +After all tasks: verify against spec at `docs/superpowers/specs/2026-05-21-examples-chat-e2e-shard-design.md`: + +- ✅ Matrix is 4-way with numeric shard values +- ✅ `fail-fast: false` +- ✅ Job display name templated with shard index +- ✅ `--shard=N/4` passed through Nx `--` separator +- ✅ `--skip-nx-cache` preserved +- ✅ Trace artifact name templated with shard index +- ✅ No application code, test code, or harness change +- ✅ `playwright.config.ts` unchanged +- ✅ Downstream `needs:` references untouched +- ✅ PR body flags the required-checks update for repo admin + +If any item is unchecked, return to the task that owns it before requesting review. From eae39323d16dc8e7337cef7043e41be33db18fd8 Mon Sep 17 00:00:00 2001 From: Brian Love Date: Thu, 21 May 2026 13:23:14 -0700 Subject: [PATCH 4/5] ci: shard examples/chat e2e into 4 parallel matrix jobs MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit Playwright's --shard=N/M flag auto-distributes the 18 spec files across 4 GitHub Actions matrix entries. Mirrors the cockpit fleet's matrix philosophy. Expected wall-time: ~6 min → ~2-3 min. - strategy.matrix.shard: [1, 2, 3, 4], fail-fast: false - name templated: examples/chat — e2e (1/4), (2/4), ... - --shard=N/4 passed through Nx executor's -- separator - Trace artifact templated examples-chat-e2e-trace-shard-N to avoid same-name collision in actions/upload-artifact@v4 Downstream needs: references (release aggregator, demo-deploy gate) unchanged — GitHub aggregates matrix results automatically. POST-MERGE ACTION ITEM: update GitHub branch protection required-checks list from 'examples/chat — e2e' to the 4 templated names. Spec: docs/superpowers/specs/2026-05-21-examples-chat-e2e-shard-design.md --- .github/workflows/ci.yml | 10 +++++++--- 1 file changed, 7 insertions(+), 3 deletions(-) diff --git a/.github/workflows/ci.yml b/.github/workflows/ci.yml index 01dbb44e..81dd6153 100644 --- a/.github/workflows/ci.yml +++ b/.github/workflows/ci.yml @@ -240,11 +240,15 @@ jobs: - run: npx nx run examples-chat-python:smoke --skip-nx-cache examples-chat-e2e: - name: examples/chat — e2e + name: "examples/chat — e2e (${{ matrix.shard }}/4)" needs: ci-scope if: github.event_name == 'push' || needs.ci-scope.outputs.examples_chat == 'true' runs-on: ubuntu-latest timeout-minutes: 35 + strategy: + fail-fast: false + matrix: + shard: [1, 2, 3, 4] steps: - uses: actions/checkout@v6.0.2 - uses: actions/setup-node@v6.3.0 @@ -259,12 +263,12 @@ jobs: - working-directory: examples/chat/python run: uv sync - run: npx playwright install --with-deps chromium - - run: npx nx e2e examples-chat-angular --skip-nx-cache + - run: npx nx e2e examples-chat-angular --skip-nx-cache -- --shard=${{ matrix.shard }}/4 - name: Upload Playwright trace on failure if: failure() uses: actions/upload-artifact@v4 with: - name: examples-chat-e2e-trace + name: examples-chat-e2e-trace-shard-${{ matrix.shard }} path: | test-results/ examples/chat/angular/e2e/test-results/ From b8130dfc87edd239d9f6862a3d9b93b7ff557ded Mon Sep 17 00:00:00 2001 From: "github-actions[bot]" <41898282+github-actions[bot]@users.noreply.github.com> Date: Thu, 21 May 2026 20:30:18 +0000 Subject: [PATCH 5/5] chore(docs): regenerate api docs --- apps/website/content/docs/licensing/api/api-docs.json | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/apps/website/content/docs/licensing/api/api-docs.json b/apps/website/content/docs/licensing/api/api-docs.json index c72b757c..9f450918 100644 --- a/apps/website/content/docs/licensing/api/api-docs.json +++ b/apps/website/content/docs/licensing/api/api-docs.json @@ -158,7 +158,7 @@ "name": "LicenseTier", "kind": "type", "description": "The tier a license grants.", - "signature": "\"developer-seat\" | \"app-deployment\" | \"enterprise\"", + "signature": "\"indie\" | \"developer_seat\" | \"app_deployment\" | \"enterprise\"", "examples": [] }, {