cc-workspace 4.0.3 → 4.0.5

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
@@ -1,4 +1,4 @@
1
- # Claude Code Multi-Workspace Orchestrator v4.0
1
+ # Claude Code Multi-Workspace Orchestrator v4.0.5
2
2
 
3
3
  A system to pilot multi-service projects from Claude Code.
4
4
  The orchestrator (Opus) never codes in repos. It clarifies, plans,
@@ -66,8 +66,10 @@ claude --agent team-lead
66
66
  npx cc-workspace update
67
67
  ```
68
68
 
69
- Updates global components (~/.claude/) if the package version is newer.
70
- Workspace files (workspace.md, constitution.md, plans/) are never overwritten.
69
+ Updates all components if the package version is newer:
70
+ - **Global**: skills, rules, agents in `~/.claude/`
71
+ - **Local** (if orchestrator/ found): hooks, settings.json, CLAUDE.md, templates, _TEMPLATE.md
72
+ - **Never overwritten**: workspace.md, constitution.md, plans/
71
73
 
72
74
  ### Diagnostic
73
75
 
@@ -164,7 +166,7 @@ detects if the target path is in a repo (presence of `.git/`).
164
166
 
165
167
  Protection layers:
166
168
  1. `disallowedTools: Bash` in agent frontmatter
167
- 2. `allowed-tools` whitelist in agent frontmatter
169
+ 2. `tools` whitelist in agent frontmatter (note: `allowed-tools` is the skill equivalent)
168
170
  3. `PreToolUse` path-aware hook in agent frontmatter
169
171
  4. `block-orchestrator-writes.sh` hook in .claude/hooks/
170
172
 
@@ -224,7 +226,7 @@ All hooks are **non-blocking** (exit 0 + warning). No hook blocks the session.
224
226
  | Template | Usage |
225
227
  |----------|-------|
226
228
  | `workspace.template.md` | Structure for workspace.md (project, service map, relationships, rules, onboarding) |
227
- | `constitution.template.md` | Structure for constitution.md (project rules 13+) |
229
+ | `constitution.template.md` | Structure for constitution.md (your engineering principles) |
228
230
  | `claude-md.template.md` | Standardized structure for repo CLAUDE.md files (stack, arch, rules, tests, anti-patterns) |
229
231
 
230
232
  ---
@@ -251,17 +253,13 @@ The `orchestrator/` directory is portable:
251
253
 
252
254
  ## The constitution
253
255
 
254
- ### Global (scoped to workspace)
256
+ `constitution.md` in orchestrator/. You define **all** your engineering
257
+ principles here — security, UX, code quality, process, project-specific rules.
258
+ The `workspace-init` agent helps you write it interactively.
255
259
 
256
- 12 universal principles in `~/.claude/rules/constitution-en.md`.
257
- Scoped to orchestrator files (`workspace.md`, `plans/**`, etc.).
258
- **v4.0**: teammates no longer receive it automatically.
259
- The orchestrator includes it in every spawn prompt.
260
-
261
- ### Project (to customize)
262
-
263
- `constitution.md` in orchestrator/. Contains **only** project-specific
264
- rules (numbered 13+).
260
+ There is no global constitution imposed by the package. Each workspace
261
+ defines its own rules. The orchestrator includes the full constitution
262
+ in every teammate spawn prompt (teammates don't receive it automatically).
265
263
 
266
264
  ---
267
265
 
@@ -307,7 +305,6 @@ cc-workspace/
307
305
  ├── LICENSE
308
306
 
309
307
  └── global-skills/ <- components installed in ~/.claude/
310
- ├── constitution.md <- 12 principles (EN)
311
308
  ├── templates/
312
309
  │ ├── workspace.template.md
313
310
  │ ├── constitution.template.md
@@ -335,12 +332,12 @@ cc-workspace/
335
332
 
336
333
  ## Idempotence
337
334
 
338
- The setup is safe to re-run:
339
- - Does not overwrite `workspace.md` or `constitution.md` if already present
340
- - Always regenerates `service-profiles.md` (fresh scan)
341
- - Always regenerates `settings.json` and `block-orchestrator-writes.sh` (security)
342
- - Templates are always copied
343
- - Global components are only updated if the version is newer
335
+ Both `init` and `update` are safe to re-run:
336
+ - **Never overwritten**: `workspace.md`, `constitution.md`, `plans/*.md` (user content)
337
+ - **Always regenerated**: `settings.json`, `block-orchestrator-writes.sh` (security), `CLAUDE.md`, `_TEMPLATE.md`
338
+ - **Always copied**: hooks, templates
339
+ - **Always regenerated on init**: `service-profiles.md` (fresh scan)
340
+ - **Global components**: only updated if the version is newer (or `--force`)
344
341
 
345
342
  ---
346
343
 
@@ -357,7 +354,7 @@ The setup is safe to re-run:
357
354
  | 7 | **Warning-only hooks** | No more blocking hooks (exit 2 -> exit 0). |
358
355
  | 8 | **verify-cycle-complete removed** | No more exit blocking. |
359
356
  | 9 | **Orchestrator can write** | In orchestrator/ only. Dynamic path-aware hook. |
360
- | 10 | **Scoped constitution** | `globs: ["*"]` -> orchestrator files only. |
357
+ | 10 | **Per-workspace constitution** | No global constitution each workspace defines its own rules. |
361
358
  | 11 | **30-line limit removed** | The orchestrator adapts verbosity to context. |
362
359
  | 12 | **Structured templates** | workspace.template.md + constitution.template.md + claude-md.template.md. |
363
360
 
package/bin/cli.js CHANGED
@@ -324,7 +324,7 @@ You clarify, plan, delegate, track.
324
324
 
325
325
  ## Security
326
326
  - \`disallowedTools: Bash\` — no direct shell
327
- - \`allowed-tools\` : Read, Write, Edit, Glob, Grep, Task, Teammate, SendMessage
327
+ - \`tools\` : Read, Write, Edit, Glob, Grep, Task(implementer, Explore), Teammate, SendMessage
328
328
  - Hook \`PreToolUse\` path-aware: allows orchestrator/, blocks sibling repos
329
329
 
330
330
  > settings.json contains env vars + hooks registration.
@@ -424,6 +424,80 @@ function planTemplateContent() {
424
424
  `;
425
425
  }
426
426
 
427
+ // ─── Update local orchestrator/ components ──────────────────
428
+ // Called by `update` when run from a workspace that contains orchestrator/
429
+ // or from inside orchestrator/ itself.
430
+ function updateLocal() {
431
+ const cwd = process.cwd();
432
+ // Detect if we're inside orchestrator/ or in the parent workspace
433
+ let orchDir;
434
+ if (fs.existsSync(path.join(cwd, "workspace.md"))) {
435
+ orchDir = cwd; // inside orchestrator/
436
+ } else if (fs.existsSync(path.join(cwd, "orchestrator", "workspace.md"))) {
437
+ orchDir = path.join(cwd, "orchestrator");
438
+ } else {
439
+ return false; // no local orchestrator found
440
+ }
441
+
442
+ step(`Updating local: ${c.dim}${orchDir}${c.reset}`);
443
+ let count = 0;
444
+
445
+ // ── Hooks (always overwrite — security critical) ──
446
+ const hooksDir = path.join(orchDir, ".claude", "hooks");
447
+ if (fs.existsSync(hooksDir)) {
448
+ generateBlockHook(hooksDir);
449
+ count++;
450
+ const hooksSrc = path.join(SKILLS_DIR, "hooks");
451
+ if (fs.existsSync(hooksSrc)) {
452
+ for (const f of fs.readdirSync(hooksSrc)) {
453
+ if (!f.endsWith(".sh") || f === "verify-cycle-complete.sh") continue;
454
+ copyFile(path.join(hooksSrc, f), path.join(hooksDir, f));
455
+ fs.chmodSync(path.join(hooksDir, f), 0o755);
456
+ count++;
457
+ }
458
+ }
459
+ ok(`${count} hooks updated`);
460
+ }
461
+
462
+ // ── settings.json (always regenerate — hook registration) ──
463
+ const settingsPath = path.join(orchDir, ".claude", "settings.json");
464
+ if (fs.existsSync(path.join(orchDir, ".claude"))) {
465
+ generateSettings(orchDir);
466
+ ok("settings.json regenerated");
467
+ }
468
+
469
+ // ── Templates (always overwrite — reference docs) ──
470
+ const templatesDir = path.join(SKILLS_DIR, "templates");
471
+ const localTemplates = path.join(orchDir, "templates");
472
+ if (fs.existsSync(templatesDir) && fs.existsSync(localTemplates)) {
473
+ let tplCount = 0;
474
+ for (const f of fs.readdirSync(templatesDir)) {
475
+ if (f.endsWith(".md")) {
476
+ copyFile(path.join(templatesDir, f), path.join(localTemplates, f));
477
+ tplCount++;
478
+ }
479
+ }
480
+ ok(`${tplCount} templates updated`);
481
+ }
482
+
483
+ // ── CLAUDE.md (always overwrite — generated file, not user content) ──
484
+ const claudeMd = path.join(orchDir, "CLAUDE.md");
485
+ fs.writeFileSync(claudeMd, claudeMdContent());
486
+ ok("CLAUDE.md updated");
487
+
488
+ // ── Plan template (always overwrite — structure only) ──
489
+ const planTpl = path.join(orchDir, "plans", "_TEMPLATE.md");
490
+ if (fs.existsSync(path.join(orchDir, "plans"))) {
491
+ fs.writeFileSync(planTpl, planTemplateContent());
492
+ ok("_TEMPLATE.md updated");
493
+ }
494
+
495
+ // ── NEVER touch: workspace.md, constitution.md, plans/*.md, service-profiles.md ──
496
+ info(`${c.dim}workspace.md, constitution.md, plans/ — preserved${c.reset}`);
497
+
498
+ return true;
499
+ }
500
+
427
501
  // ─── Setup workspace ────────────────────────────────────────
428
502
  function setupWorkspace(workspacePath, projectName) {
429
503
  const wsAbs = path.resolve(workspacePath);
@@ -685,10 +759,15 @@ switch (command) {
685
759
  const force = args.includes("--force");
686
760
  log(BANNER);
687
761
  const updated = installGlobals(force);
688
- if (!updated) {
762
+ const localUpdated = (updated || force) ? updateLocal() : false;
763
+ if (!updated && !force) {
689
764
  log(`\n ${c.dim}Already up to date. Use --force to reinstall.${c.reset}\n`);
690
765
  } else {
691
- log(`\n ${c.green}${c.bold}Update complete.${c.reset}\n`);
766
+ if (localUpdated) {
767
+ log(`\n ${c.green}${c.bold}Update complete (globals + local orchestrator/).${c.reset}\n`);
768
+ } else {
769
+ log(`\n ${c.green}${c.bold}Update complete (globals only — no local orchestrator/ found).${c.reset}\n`);
770
+ }
692
771
  }
693
772
  break;
694
773
  }
@@ -721,7 +800,9 @@ switch (command) {
721
800
  log(` Installs global skills/rules/agents if version is newer.`);
722
801
  log("");
723
802
  log(` ${c.cyan}npx cc-workspace update${c.reset} ${c.dim}[--force]${c.reset}`);
724
- log(` Update global components to this package version.`);
803
+ log(` Update global components (skills, rules, agents).`);
804
+ log(` Also updates local orchestrator/ if found (hooks, settings, CLAUDE.md, templates).`);
805
+ log(` Never overwrites: workspace.md, constitution.md, plans/.`);
725
806
  log("");
726
807
  log(` ${c.cyan}npx cc-workspace doctor${c.reset}`);
727
808
  log(` Check all components are installed and consistent.`);
@@ -7,9 +7,8 @@ description: >
7
7
  (Agent Teams teammates get automatic isolation).
8
8
  isolation: worktree
9
9
  model: sonnet
10
- allowed-tools: Read, Write, Edit, MultiEdit, Bash, Glob, Grep
10
+ tools: Read, Write, Edit, MultiEdit, Bash, Glob, Grep
11
11
  memory: project
12
- effort: medium
13
12
  maxTurns: 50
14
13
  ---
15
14
 
@@ -6,10 +6,9 @@ description: >
6
6
  quality. Never codes in repos — can write in orchestrator/.
7
7
  Triggered via claude --agent team-lead.
8
8
  model: opus
9
- allowed-tools: Read, Write, Edit, Glob, Grep, Task, Teammate, SendMessage
9
+ tools: Read, Write, Edit, Glob, Grep, Task(implementer, Explore), Teammate, SendMessage
10
10
  disallowedTools: Bash
11
11
  memory: project
12
- effort: high
13
12
  maxTurns: 200
14
13
  hooks:
15
14
  PreToolUse:
@@ -6,9 +6,8 @@ description: >
6
6
  Interactively configures workspace.md and constitution.md if [UNCONFIGURED].
7
7
  Run once via: claude --agent workspace-init
8
8
  model: sonnet
9
- allowed-tools: Read, Write, Edit, Bash, Glob, Grep, Task
9
+ tools: Read, Write, Edit, Bash, Glob, Grep, Task(Explore)
10
10
  memory: project
11
- effort: medium
12
11
  maxTurns: 80
13
12
  ---
14
13
 
@@ -7,6 +7,7 @@ description: >
7
7
  or when a repo is detected without CLAUDE.md during setup.
8
8
  argument-hint: "[repo-path]"
9
9
  context: fork
10
+ agent: general-purpose
10
11
  disable-model-invocation: true
11
12
  model: haiku
12
13
  allowed-tools: Read, Write, Glob, Grep, Bash
@@ -8,6 +8,7 @@ description: >
8
8
  "cross-service", "aligned", "pre-merge".
9
9
  argument-hint: "[feature-name]"
10
10
  context: fork
11
+ agent: general-purpose
11
12
  disable-model-invocation: true
12
13
  allowed-tools: Read, Write, Glob, Grep, Task
13
14
  ---
@@ -8,6 +8,7 @@ description: >
8
8
  "capitalize", "lessons learned", "what did we learn", "improve docs".
9
9
  argument-hint: "[feature-name]"
10
10
  context: fork
11
+ agent: general-purpose
11
12
  disable-model-invocation: true
12
13
  model: haiku
13
14
  allowed-tools: Read, Write, Glob, Grep, Task
@@ -85,6 +85,8 @@ You are teammate-[service]. Read the CLAUDE.md in your repo first.
85
85
 
86
86
  ## Explore/Haiku subagent template (read-only)
87
87
 
88
+ Use `Task` with `subagent_type: Explore` and `model: haiku` for lightweight scans.
89
+
88
90
  ```
89
91
  You are an explorer scanning [target]. Read-only — do NOT modify any files.
90
92
 
@@ -94,3 +96,11 @@ You are an explorer scanning [target]. Read-only — do NOT modify any files.
94
96
  ## Report format
95
97
  [what to extract and how to format the findings]
96
98
  ```
99
+
100
+ ## Failure handling
101
+
102
+ When a teammate reports back:
103
+ - **Test regression or missing file** (recoverable): fix plan, re-dispatch ONCE
104
+ - **Architectural decision not in plan** (blocking): STOP the wave, escalate to user
105
+ - **No report after extended time**: send a status request via SendMessage
106
+ - **Max re-dispatches per teammate per wave**: 2. After that, escalate to user.
@@ -7,6 +7,7 @@ description: >
7
7
  "prepare merge", "merge-prep", "ready to merge".
8
8
  argument-hint: "[feature-name]"
9
9
  context: fork
10
+ agent: general-purpose
10
11
  disable-model-invocation: true
11
12
  allowed-tools: Read, Write, Glob, Grep, Bash, Task
12
13
  ---
@@ -7,6 +7,7 @@ description: >
7
7
  Use when a plan was just written or user says "review plan", "vérifie le plan".
8
8
  argument-hint: "[plan-name.md]"
9
9
  context: fork
10
+ agent: Explore
10
11
  disable-model-invocation: true
11
12
  model: haiku
12
13
  allowed-tools: Read, Glob, Grep
@@ -5,6 +5,7 @@ description: >
5
5
  listed in workspace.md. Use when conventions changed, or user says
6
6
  "refresh profiles", "update profiles", "re-read CLAUDE.md files".
7
7
  context: fork
8
+ agent: Explore
8
9
  disable-model-invocation: true
9
10
  model: haiku
10
11
  allowed-tools: Read, Write, Glob, Grep
@@ -12,7 +12,7 @@ If you write code for a repo (not a markdown plan), you have failed — delegate
12
12
 
13
13
  ## Security layers (3 layers in agent frontmatter — no settings.json pollution)
14
14
  1. **Agent frontmatter**: `disallowedTools` — refused at model level
15
- 2. **Agent frontmatter**: `allowed-tools` — whitelist of permitted tools
15
+ 2. **Agent frontmatter**: `tools` — whitelist of permitted tools (note: `allowed-tools` is for skills only)
16
16
  3. **Agent hook**: `PreToolUse` in frontmatter — structured deny response
17
17
 
18
18
  ## Routing table
@@ -24,18 +24,6 @@ If you write code for a repo (not a markdown plan), you have failed — delegate
24
24
  | Explorers / cross-checks | **Haiku** | `model: haiku` in skill/agent frontmatter |
25
25
  | Plan review | **Haiku** | `model: haiku` in skill frontmatter |
26
26
 
27
- ## Effort levels
28
- | Role | Effort | Rationale |
29
- |------|--------|-----------|
30
- | Orchestrator (team-lead) | **high** | Complex planning, multi-step reasoning |
31
- | Implementation teammates | **medium** | Focused implementation, clear scope |
32
- | QA investigators | **medium** | Thorough but bounded analysis |
33
- | Explorers / cross-checks (Haiku) | **low** | Fast scans, read-only |
34
- | Plan review (Haiku) | **low** | Structural checks, no deep reasoning |
35
-
36
- Effort levels are set in agent frontmatter (`effort: high|medium|low|max`).
37
- Use `max` only for critical debugging or complex architectural decisions.
38
-
39
27
  ## Custom agent `implementer`
40
28
  For Task subagents that need to write code in an isolated worktree,
41
29
  use `@implementer` (frontmatter with `isolation: worktree`).
package/package.json CHANGED
@@ -1,6 +1,6 @@
1
1
  {
2
2
  "name": "cc-workspace",
3
- "version": "4.0.3",
3
+ "version": "4.0.5",
4
4
  "description": "Claude Code multi-workspace orchestrator — skills, hooks, agents, and templates for multi-service projects",
5
5
  "bin": {
6
6
  "cc-workspace": "./bin/cli.js"