cc-workspace 4.2.1 → 4.4.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/README.md CHANGED
@@ -27,7 +27,7 @@ cd ~/projects/my-workspace
27
27
  npx cc-workspace init . "My Project"
28
28
  ```
29
29
 
30
- This creates an `orchestrator/` directory and installs 9 skills, 3 agents, 9 hooks, and 3 rules into `~/.claude/`.
30
+ This creates an `orchestrator/` directory and installs 10 skills, 4 agents, 9 hooks, and 3 rules into `~/.claude/`.
31
31
 
32
32
  ### Configure (one time)
33
33
 
@@ -47,7 +47,8 @@ The init agent will:
47
47
 
48
48
  ```bash
49
49
  cd orchestrator/
50
- claude --agent team-lead
50
+ claude --agent team-lead # orchestration sessions
51
+ claude --agent e2e-validator # E2E validation (beta)
51
52
  ```
52
53
 
53
54
  The team-lead offers 4 modes:
@@ -68,7 +69,7 @@ npx cc-workspace update
68
69
  Updates all components if the package version is newer:
69
70
  - **Global**: skills, rules, agents in `~/.claude/`
70
71
  - **Local** (if `orchestrator/` found): hooks, settings.json, CLAUDE.md, templates, _TEMPLATE.md
71
- - **Never overwritten**: workspace.md, constitution.md, plans/
72
+ - **Never overwritten**: workspace.md, constitution.md, plans/, e2e/
72
73
 
73
74
  ### Diagnostic
74
75
 
@@ -95,6 +96,15 @@ my-workspace/
95
96
  │ ├── workspace.md <- filled by workspace-init
96
97
  │ ├── constitution.md <- filled by workspace-init
97
98
  │ ├── .sessions/ <- session state (gitignored, created per session)
99
+ │ ├── e2e/ <- E2E test environment (beta)
100
+ │ │ ├── e2e-config.md <- agent memory (generated at first boot)
101
+ │ │ ├── docker-compose.e2e.yml <- generated at first boot
102
+ │ │ ├── tests/ <- headless API test scripts
103
+ │ │ ├── chrome/
104
+ │ │ │ ├── scenarios/ <- Chrome test flows per plan
105
+ │ │ │ ├── screenshots/ <- evidence
106
+ │ │ │ └── gifs/ <- recorded flows
107
+ │ │ └── reports/ <- per-plan E2E reports
98
108
  │ ├── templates/
99
109
  │ │ ├── workspace.template.md
100
110
  │ │ ├── constitution.template.md
@@ -198,6 +208,7 @@ parallel in each repo via Agent Teams.
198
208
  | **Teammates** | Sonnet 4.6 | Implement in an isolated worktree, test, commit. |
199
209
  | **Explorers** | Haiku | Read-only. Scan, verify consistency. |
200
210
  | **QA** | Sonnet 4.6 | Hostile mode. Min 3 problems found per service. |
211
+ | **E2E Validator** | Sonnet 4.6 | Containers + Chrome browser testing (beta). |
201
212
 
202
213
  ### The 4 session modes
203
214
 
@@ -235,7 +246,7 @@ Protection layers:
235
246
 
236
247
  ---
237
248
 
238
- ## The 9 skills
249
+ ## The 10 skills
239
250
 
240
251
  | Skill | Role | Trigger |
241
252
  |-------|------|---------|
@@ -248,19 +259,21 @@ Protection layers:
248
259
  | **cycle-retrospective** | Post-cycle learning (Haiku) | "Retro", "retrospective" |
249
260
  | **refresh-profiles** | Re-scan repo CLAUDE.md files (Haiku) | "Refresh profiles" |
250
261
  | **bootstrap-repo** | Generate a CLAUDE.md (Haiku) | "Bootstrap", "init CLAUDE.md" |
262
+ | **e2e-validator** | E2E validation: containers + Chrome (beta) | `claude --agent e2e-validator` |
251
263
 
252
264
  All use `context: fork` — a skill's result is not in context when the
253
265
  next one starts. The plan on disk is the source of truth.
254
266
 
255
267
  ---
256
268
 
257
- ## The 3 agents
269
+ ## The 4 agents
258
270
 
259
271
  | Agent | Model | Usage |
260
272
  |-------|-------|-------|
261
273
  | **team-lead** | Opus 4.6 | `claude --agent team-lead` — multi-service orchestration |
262
274
  | **workspace-init** | Sonnet 4.6 | `claude --agent workspace-init` — diagnostic + initial config |
263
275
  | **implementer** | Sonnet 4.6 | Task subagent with `isolation: worktree` — isolated implementation |
276
+ | **e2e-validator** | Sonnet 4.6 | `claude --agent e2e-validator` — E2E validation with containers + Chrome (beta) |
264
277
 
265
278
  ---
266
279
 
@@ -385,9 +398,14 @@ cc-workspace/
385
398
  ├── cycle-retrospective/SKILL.md
386
399
  ├── refresh-profiles/SKILL.md
387
400
  ├── bootstrap-repo/SKILL.md
401
+ ├── e2e-validator/
402
+ │ └── references/
403
+ │ ├── container-strategies.md
404
+ │ ├── test-frameworks.md
405
+ │ └── scenario-extraction.md
388
406
  ├── hooks/ <- 11 scripts (warning-only)
389
407
  ├── rules/ <- 3 rules
390
- └── agents/ <- 3 agents (team-lead, implementer, workspace-init)
408
+ └── agents/ <- 4 agents (team-lead, implementer, workspace-init, e2e-validator)
391
409
  ```
392
410
 
393
411
  ---
@@ -395,7 +413,7 @@ cc-workspace/
395
413
  ## Idempotence
396
414
 
397
415
  Both `init` and `update` are safe to re-run:
398
- - **Never overwritten**: `workspace.md`, `constitution.md`, `plans/*.md` (user content)
416
+ - **Never overwritten**: `workspace.md`, `constitution.md`, `plans/*.md`, `e2e/` (user content)
399
417
  - **Always regenerated**: `settings.json`, `block-orchestrator-writes.sh` (security), `CLAUDE.md`, `_TEMPLATE.md`
400
418
  - **Always copied**: hooks, templates
401
419
  - **Always regenerated on init**: `service-profiles.md` (fresh scan)
@@ -403,6 +421,87 @@ Both `init` and `update` are safe to re-run:
403
421
 
404
422
  ---
405
423
 
424
+ ## E2E Validator (beta)
425
+
426
+ A dedicated agent that validates completed plans by running services in containers
427
+ and testing scenarios — including Chrome browser-driven UI tests.
428
+
429
+ ```bash
430
+ cd orchestrator/
431
+ claude --agent e2e-validator
432
+ ```
433
+
434
+ ### First boot — setup
435
+
436
+ On first boot (no `e2e/e2e-config.md`), the agent:
437
+ 1. Reads `workspace.md` for repos and stacks
438
+ 2. Scans repos for existing `docker-compose.yml` and test frameworks
439
+ 3. If docker-compose exists: generates an overlay (`docker-compose.e2e.yml`)
440
+ 4. If not: builds the config interactively with you
441
+ 5. Writes `e2e/e2e-config.md` (its persistent memory)
442
+
443
+ ### Modes
444
+
445
+ | Mode | Description |
446
+ |------|-------------|
447
+ | `validate <plan>` | Test a specific completed plan (API tests) |
448
+ | `validate <plan> --chrome` | Same + Chrome browser UI tests |
449
+ | `run-all` | Run all E2E tests (headless) |
450
+ | `run-all --chrome` | Run all E2E tests + Chrome |
451
+ | `setup` | Re-run first boot setup |
452
+
453
+ Add `--fix` to any mode to dispatch teammates for fixing failures.
454
+
455
+ ### How it works
456
+
457
+ 1. Creates `/tmp/` worktrees on session branches (from the plan)
458
+ 2. Starts services via `docker compose up`
459
+ 3. Waits for health checks
460
+ 4. Runs existing test suites + generates API scenario tests from the plan
461
+ 5. With `--chrome`: drives Chrome via chrome-devtools MCP (navigate, fill forms,
462
+ click, take screenshots, record GIFs, check network requests and console)
463
+ 6. Generates report with evidence (screenshots, GIFs, network traces)
464
+ 7. Tears down containers and worktrees
465
+
466
+ ### Chrome testing
467
+
468
+ With `--chrome`, the agent:
469
+ - Navigates the frontend in your real Chrome browser
470
+ - Plays user scenarios extracted from the plan
471
+ - Takes screenshots at each step as evidence
472
+ - Records GIFs of complete flows
473
+ - Checks the 4 mandatory UX states (loading, empty, error, success)
474
+ - Tests responsive layouts (mobile viewport)
475
+ - Verifies network requests match the API contract
476
+ - Checks console for errors
477
+
478
+ ### Requirements
479
+
480
+ - **Docker** (docker compose v2)
481
+ - **Chrome** with chrome-devtools MCP server (for `--chrome` mode)
482
+ - Completed plan (all tasks ✅) with session branches
483
+
484
+ ---
485
+
486
+ ## Changelog v4.3.0 -> v4.4.0
487
+
488
+ | # | Feature | Detail |
489
+ |---|---------|--------|
490
+ | 1 | **E2E Validator agent (beta)** | New `e2e-validator` agent: validates completed plans by running services in containers. Supports headless API tests and Chrome browser-driven UI tests with screenshots and GIF recording. |
491
+ | 2 | **Chrome testing mode** | `--chrome` flag drives the user's Chrome browser via chrome-devtools MCP. Navigates, fills forms, clicks, takes screenshots, records GIFs, checks network and console. |
492
+ | 3 | **E2E directory structure** | `orchestrator/e2e/` created during init/update. Contains docker-compose overlay, test scripts, Chrome scenarios, screenshots, GIFs, and reports. Never overwritten by updates. |
493
+ | 4 | **Container strategies** | Reference docs for overlay and standalone docker-compose patterns per stack (PHP, Node, Python, Go, Vue, React). |
494
+ | 5 | **Scenario extraction** | Reference doc for extracting testable E2E scenarios from completed plans (API endpoints, Chrome flows, UX states). |
495
+ | 6 | **5 modes** | setup, validate, validate --chrome, run-all, run-all --chrome. Optional --fix dispatches teammates. |
496
+
497
+ ---
498
+
499
+ ## Changelog v4.2.0 -> v4.3.0
500
+
501
+ > Minor improvements and bug fixes.
502
+
503
+ ---
504
+
406
505
  ## Changelog v4.1.4 -> v4.2.0
407
506
 
408
507
  | # | Feature | Detail |
package/bin/cli.js CHANGED
@@ -225,8 +225,10 @@ function generateSettings(orchDir) {
225
225
  // block-orchestrator-writes.sh is NOT here — it's in team-lead agent
226
226
  // frontmatter only. Putting it in settings.json would block teammates
227
227
  // from writing in their worktrees.
228
- withMatcher("Teammate", "validate-spawn-prompt.sh", 5),
229
- withMatcher("Bash", "guard-session-checkout.sh", 5)
228
+ // guard-session-checkout.sh is NOT here — it's in implementer agent
229
+ // frontmatter only. team-lead doesn't have Bash, and teammates don't
230
+ // inherit orchestrator hooks.
231
+ withMatcher("Teammate", "validate-spawn-prompt.sh", 5)
230
232
  ],
231
233
  SessionStart: [
232
234
  withoutMatcher("session-start-context.sh", 10)
@@ -281,6 +283,7 @@ You clarify, plan, delegate, track.
281
283
  cd orchestrator/
282
284
  claude --agent workspace-init # first time: diagnostic + config
283
285
  claude --agent team-lead # work sessions
286
+ claude --agent e2e-validator # E2E validation of completed plans
284
287
  \`\`\`
285
288
 
286
289
  ## Initialization (workspace-init)
@@ -303,8 +306,10 @@ Run once. Idempotent — can be re-run to re-diagnose.
303
306
  - Service profiles: \`./plans/service-profiles.md\`
304
307
  - Active plans: \`./plans/*.md\`
305
308
  - Active sessions: \`./.sessions/*.json\`
309
+ - E2E config: \`./e2e/e2e-config.md\`
310
+ - E2E reports: \`./e2e/reports/\`
306
311
 
307
- ## Skills (9)
312
+ ## Skills (10)
308
313
  - **dispatch-feature**: 4 modes, clarify → plan → waves → collect → verify
309
314
  - **qa-ruthless**: adversarial QA, min 3 findings per service
310
315
  - **cross-service-check**: inter-repo consistency
@@ -314,6 +319,7 @@ Run once. Idempotent — can be re-run to re-diagnose.
314
319
  - **cycle-retrospective**: post-cycle learning (haiku)
315
320
  - **refresh-profiles**: re-reads repo CLAUDE.md files (haiku)
316
321
  - **bootstrap-repo**: generates a CLAUDE.md for a repo (haiku)
322
+ - **e2e-validator**: E2E validation of completed plans (beta) — containers + Chrome
317
323
 
318
324
  ## Rules
319
325
  1. No code in repos — delegate to teammates
@@ -331,6 +337,7 @@ Run once. Idempotent — can be re-run to re-diagnose.
331
337
  13. Retrospective cycle after each completed feature
332
338
  14. Session branches for parallel isolation — teammates use session/{name}, never create own branches
333
339
  15. Never \`git checkout -b\` in repos — use \`git branch\` (no checkout) to avoid disrupting parallel sessions
340
+ 16. E2E validation via \`claude --agent e2e-validator\` after plans are complete
334
341
  `;
335
342
  }
336
343
 
@@ -417,7 +424,7 @@ function updateLocal() {
417
424
  const hooksDir = path.join(orchDir, ".claude", "hooks");
418
425
  if (fs.existsSync(hooksDir)) {
419
426
  // Clean obsolete hooks before copying new ones
420
- const obsoleteHooks = ["block-orchestrator-writes.sh", "worktree-create-context.sh", "verify-cycle-complete.sh"];
427
+ const obsoleteHooks = ["block-orchestrator-writes.sh", "worktree-create-context.sh", "verify-cycle-complete.sh", "guard-session-checkout.sh"];
421
428
  for (const f of obsoleteHooks) {
422
429
  const fp = path.join(hooksDir, f);
423
430
  if (fs.existsSync(fp)) fs.unlinkSync(fp);
@@ -474,8 +481,19 @@ function updateLocal() {
474
481
  ok(".sessions/ created");
475
482
  }
476
483
 
477
- // ── NEVER touch: workspace.md, constitution.md, plans/*.md, service-profiles.md ──
478
- info(`${c.dim}workspace.md, constitution.md, plans/ — preserved${c.reset}`);
484
+ // ── e2e/ (create if missing never overwrite existing) ──
485
+ const e2eDir = path.join(orchDir, "e2e");
486
+ if (!fs.existsSync(e2eDir)) {
487
+ mkdirp(path.join(e2eDir, "tests"));
488
+ mkdirp(path.join(e2eDir, "chrome", "scenarios"));
489
+ mkdirp(path.join(e2eDir, "chrome", "screenshots"));
490
+ mkdirp(path.join(e2eDir, "chrome", "gifs"));
491
+ mkdirp(path.join(e2eDir, "reports"));
492
+ ok("e2e/ directory created");
493
+ }
494
+
495
+ // ── NEVER touch: workspace.md, constitution.md, plans/*.md, e2e/ ──
496
+ info(`${c.dim}workspace.md, constitution.md, plans/, e2e/ — preserved${c.reset}`);
479
497
 
480
498
  return true;
481
499
  }
@@ -491,6 +509,11 @@ function setupWorkspace(workspacePath, projectName) {
491
509
  mkdirp(path.join(orchDir, "plans"));
492
510
  mkdirp(path.join(orchDir, "templates"));
493
511
  mkdirp(path.join(orchDir, ".sessions"));
512
+ mkdirp(path.join(orchDir, "e2e", "tests"));
513
+ mkdirp(path.join(orchDir, "e2e", "chrome", "scenarios"));
514
+ mkdirp(path.join(orchDir, "e2e", "chrome", "screenshots"));
515
+ mkdirp(path.join(orchDir, "e2e", "chrome", "gifs"));
516
+ mkdirp(path.join(orchDir, "e2e", "reports"));
494
517
  ok("Structure created");
495
518
 
496
519
  // ── Templates ──
@@ -573,7 +596,9 @@ function setupWorkspace(workspacePath, projectName) {
573
596
  fs.writeFileSync(gi, [
574
597
  ".claude/bash-commands.log", ".claude/worktrees/", ".claude/modified-files.log",
575
598
  ".sessions/",
576
- "plans/*.md", "!plans/_TEMPLATE.md", "!plans/service-profiles.md", ""
599
+ "plans/*.md", "!plans/_TEMPLATE.md", "!plans/service-profiles.md",
600
+ "e2e/chrome/screenshots/", "e2e/chrome/gifs/", "e2e/reports/",
601
+ "e2e/docker-compose.e2e.yml", "e2e/e2e-config.md", ""
577
602
  ].join("\n"));
578
603
  ok(".gitignore");
579
604
  }
@@ -631,13 +656,14 @@ function setupWorkspace(workspacePath, projectName) {
631
656
  log(` ${c.dim}Directory${c.reset} ${orchDir}`);
632
657
  log(` ${c.dim}Repos${c.reset} ${repos.length} detected`);
633
658
  log(` ${c.dim}Hooks${c.reset} ${hookCount} scripts`);
634
- log(` ${c.dim}Skills${c.reset} 9 ${c.dim}(~/.claude/skills/)${c.reset}`);
659
+ log(` ${c.dim}Skills${c.reset} 10 ${c.dim}(~/.claude/skills/)${c.reset}`);
635
660
  log("");
636
661
  log(` ${c.bold}Next steps:${c.reset}`);
637
662
  log(` ${c.cyan}cd orchestrator/${c.reset}`);
638
663
  log(` ${c.cyan}claude --agent workspace-init${c.reset} ${c.dim}# first time: diagnostic + config${c.reset}`);
639
664
  log(` ${c.dim} └─ type "go" to start the diagnostic${c.reset}`);
640
665
  log(` ${c.cyan}claude --agent team-lead${c.reset} ${c.dim}# orchestration sessions${c.reset}`);
666
+ log(` ${c.cyan}claude --agent e2e-validator${c.reset} ${c.dim}# E2E validation (beta)${c.reset}`);
641
667
  if (reposWithoutClaude.length > 0) {
642
668
  log("");
643
669
  warn(`${reposWithoutClaude.length} repo(s) without CLAUDE.md: ${c.bold}${reposWithoutClaude.join(", ")}${c.reset}`);
@@ -672,7 +698,7 @@ function doctor() {
672
698
  // Skills count
673
699
  if (fs.existsSync(GLOBAL_SKILLS)) {
674
700
  const skills = fs.readdirSync(GLOBAL_SKILLS, { withFileTypes: true }).filter(e => e.isDirectory());
675
- check(`Skills (${skills.length}/9)`, skills.length >= 9, `only ${skills.length} found`);
701
+ check(`Skills (${skills.length}/10)`, skills.length >= 10, `only ${skills.length} found`);
676
702
  }
677
703
 
678
704
  // Rules
@@ -681,7 +707,7 @@ function doctor() {
681
707
  }
682
708
 
683
709
  // Agents
684
- for (const a of ["team-lead.md", "implementer.md", "workspace-init.md"]) {
710
+ for (const a of ["team-lead.md", "implementer.md", "workspace-init.md", "e2e-validator.md"]) {
685
711
  check(`Agent: ${a}`, fs.existsSync(path.join(GLOBAL_AGENTS, a)), "missing");
686
712
  }
687
713
 
@@ -704,6 +730,7 @@ function doctor() {
704
730
  check("templates/", fs.existsSync(path.join(cwd, "templates")), "missing");
705
731
  check(".claude/hooks/", fs.existsSync(path.join(cwd, ".claude", "hooks")), "missing");
706
732
  check(".sessions/", fs.existsSync(path.join(cwd, ".sessions")), "missing — run: npx cc-workspace update");
733
+ check("e2e/", fs.existsSync(path.join(cwd, "e2e")), "missing — run: npx cc-workspace update");
707
734
  const configured = !fs.readFileSync(path.join(cwd, "workspace.md"), "utf8").includes("[UNCONFIGURED]");
708
735
  check("workspace.md configured", configured, "[UNCONFIGURED] — run: claude --agent workspace-init");
709
736
  } else if (hasOrch) {
@@ -840,6 +867,7 @@ switch (command) {
840
867
  log(` ${c.cyan}claude --agent workspace-init${c.reset} ${c.dim}# first time${c.reset}`);
841
868
  log(` ${c.dim} └─ type "go" to start the diagnostic${c.reset}`);
842
869
  log(` ${c.cyan}claude --agent team-lead${c.reset} ${c.dim}# work sessions${c.reset}`);
870
+ log(` ${c.cyan}claude --agent e2e-validator${c.reset} ${c.dim}# E2E validation (beta)${c.reset}`);
843
871
  log("");
844
872
  break;
845
873
  }