@mmerterden/multi-agent-pipeline 10.4.0 → 10.5.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 CHANGED
@@ -14,6 +14,40 @@ Internal file-layout changes that don't affect the slash-command surface are sti
14
14
 
15
15
  ---
16
16
 
17
+ ## [10.5.0] - 2026-07-02
18
+
19
+ Stack skills move from the local `stack-swap` mechanic to versioned marketplace plugins.
20
+
21
+ ### Added
22
+
23
+ - **`build-stack-plugins.mjs`** — rebuilds each stack plugin's `knowledge/`
24
+ layer in the `{owner}/multi-agent-plugins` marketplace from the pipeline's
25
+ authoring source (`pipeline/skills/shared/external/`), regenerates each
26
+ `plugin.json` `skills[]`, and **bumps the patch version of any plugin whose
27
+ skill set changed**. Idempotent (`--dry-run` supported); a no-op run bumps
28
+ nothing. Cross-stack skills (accessibility audit, humanizer, Firebase) route
29
+ to `ai-common-engineering-toolkit`; Apple/Xcode-only skills stay in the iOS
30
+ plugin. This is the version-based-management backbone: the pipeline is the
31
+ single authoring source, the marketplace is a derived, versioned artifact.
32
+ - **`multi-agent:sync` Step 3c (PLUGINS)** — runs the generator, then commits +
33
+ pushes the plugins repo when a plugin version was bumped.
34
+
35
+ ### Changed
36
+
37
+ - **`/multi-agent:stack`** — selecting a stack no longer moves skill directories
38
+ via `stack-swap.sh`. It now enables the matching marketplace plugin(s) (stack
39
+ toolkit + `ai-common-engineering-toolkit`) in the current repo's
40
+ `.claude/settings.json` `enabledPlugins`, disabling the stack toolkits that
41
+ don't apply. Declarative, per-repo, versioned. No SessionStart hook.
42
+ - **`/multi-agent:update`** — added a step that refreshes the plugin marketplace
43
+ (`claude marketplace update multi-agent-plugins`) so the latest published
44
+ plugin versions are picked up alongside the pipeline update.
45
+
46
+ ### Deprecated
47
+
48
+ - **`stack-swap.sh`** — no longer wired to any SessionStart hook. Retained for
49
+ manual/offline use only; stack selection is now plugin enablement.
50
+
17
51
  ## [10.4.0] - 2026-07-02
18
52
 
19
53
  New `finish` command: run the pipeline tail over work you already did locally.
package/README.md CHANGED
@@ -528,7 +528,7 @@ Stack is auto-detected. Build commands, test runners, lint tools, and review foc
528
528
  | Fastest | `/multi-agent:dev-autopilot "task"` | `multi-agent-dev-autopilot "task"` | Zero interaction |
529
529
  | Test | `/multi-agent:test` | `multi-agent-test` | UI Bug Hunter - visual + accessibility |
530
530
  | Channels | `/multi-agent:channels <target>` | `multi-agent-channels <target>` | Post report to Jira / Confluence / Wiki / PR (multi-select, humanizer pass, reviewer-preserving) |
531
- | Stack | `/multi-agent:stack ios` | `multi-agent-stack ios` | Manually swap skill set per platform |
531
+ | Stack | `/multi-agent:stack ios` | `multi-agent-stack ios` | Select stack by enabling the matching marketplace plugin(s) |
532
532
  | Language | `/multi-agent:language [prompt\|output] <en\|tr>` | `multi-agent-language [prompt\|output] <en\|tr>` | Toggle `promptLanguage` (interactive prompts) and/or `outputLanguage` (assistant explanations). External payloads stay English. |
533
533
 
534
534
  ## UI Bug Hunter + Audit Tools
@@ -563,22 +563,22 @@ All audits run via **direct Bash commands** - no MCP server dependency. Pipeline
563
563
 
564
564
  **No external dependencies** - only standard Xcode CLI tools (iOS) and Android SDK (Android). Platform guides include **compliance rules** that map 1:1 to audit checks - follow the guide, pass the audit.
565
565
 
566
- ## Stack Swap
566
+ ## Stack Selection (marketplace plugins)
567
567
 
568
- Stack is auto-detected at session start by `pipeline/scripts/stack-swap.sh` (SessionStart hook) based on project markers (`.xcodeproj`, `build.gradle`, `package.json`, etc.). To override manually:
568
+ Stack skills ship as versioned plugins in the `{owner}/multi-agent-plugins` marketplace. Selecting a stack **enables the matching plugin(s)** in the repo's `.claude/settings.json` `enabledPlugins` — the stack toolkit plus `ai-common-engineering-toolkit` (cross-stack skills). This replaced the old `stack-swap.sh` mechanic (which physically moved skill directories on a SessionStart hook); enablement is now declarative, per-repo, and versioned.
569
569
 
570
570
  ```bash
571
571
  # Claude Code # Copilot CLI
572
- /multi-agent:stack multi-agent-stack # show current
573
- /multi-agent:stack ios multi-agent-stack ios # SwiftUI + Xcode
574
- /multi-agent:stack android multi-agent-stack android # Compose + Gradle
575
- /multi-agent:stack backend multi-agent-stack backend # Python/Node/Go
576
- /multi-agent:stack frontend multi-agent-stack frontend # React/Vue/Next
577
- /multi-agent:stack mobile multi-agent-stack mobile # iOS + Android
578
- /multi-agent:stack all multi-agent-stack all # load everything
572
+ /multi-agent:stack multi-agent-stack # show enabled plugins
573
+ /multi-agent:stack ios multi-agent-stack ios # SwiftUI toolkit + common
574
+ /multi-agent:stack android multi-agent-stack android # Compose toolkit + common
575
+ /multi-agent:stack backend multi-agent-stack backend # Python/Node toolkit + common
576
+ /multi-agent:stack frontend multi-agent-stack frontend # React/TSX toolkit + common
577
+ /multi-agent:stack mobile multi-agent-stack mobile # iOS + Android + common
578
+ /multi-agent:stack all multi-agent-stack all # all four toolkits + common
579
579
  ```
580
580
 
581
- Re-runs `stack-swap.sh` with a forced mode and loads the matching guide (`swiftui-guide.md`, `android-guide.md`, `backend-guide.md`, `frontend-guide.md`).
581
+ Add the marketplace once with `claude marketplace add {owner}/multi-agent-plugins`. Newly published plugin versions are pulled by `/multi-agent:update`. The plugins are rebuilt from `pipeline/skills/shared/external/` via `pipeline/scripts/build-stack-plugins.mjs` (run by `multi-agent:sync` Step 3c), which bumps the patch version of any plugin whose skill set changed. `stack-swap.sh` is retained for manual/offline use but is no longer wired to any hook.
582
582
 
583
583
  ## Setup
584
584
 
@@ -638,7 +638,8 @@ Runs unit tests, smoke suites, eval fixtures, schema validation, and lint - the
638
638
  | Script | Purpose |
639
639
  | ---------------------- | ------------------------------------------------ |
640
640
  | `pre-commit-check.sh` | Secret detection before commits |
641
- | `stack-swap.sh` | Auto-detect project stack on session start |
641
+ | `build-stack-plugins.mjs` | Rebuild stack plugins from `shared/external`, bump changed plugin versions |
642
+ | `stack-swap.sh` | Legacy stack skill-dir swap (manual/offline; no longer hooked) |
642
643
  | `keychain-save.sh` | Save tokens/JSON to macOS Keychain (interactive) |
643
644
  | `keychain.py` | Deterministic Python Keychain helper (get/set/delete/list/doctor); shell driver auto-delegates on macOS/Linux |
644
645
  | `github-ssh-setup.sh` | GitHub SSH key generation + config |
@@ -783,7 +784,8 @@ pipeline/
783
784
  01-10/ 10 adversarial eval fixtures
784
785
  scripts/
785
786
  pre-commit-check.sh Secret detection hook
786
- stack-swap.sh Auto stack detection (SessionStart)
787
+ build-stack-plugins.mjs Rebuild stack plugins + version bump
788
+ stack-swap.sh Legacy stack swap (manual; no longer hooked)
787
789
  keychain-save.sh Save tokens/JSON to macOS Keychain
788
790
  github-ssh-setup.sh GitHub SSH key generation + setup
789
791
  ui-tree-dumper.swift iOS accessibility tree dumper
package/package.json CHANGED
@@ -1,6 +1,6 @@
1
1
  {
2
2
  "name": "@mmerterden/multi-agent-pipeline",
3
- "version": "10.4.0",
3
+ "version": "10.5.0",
4
4
  "description": "8-phase AI development pipeline with full orchestration on Claude Code, Copilot CLI, Cursor, Antigravity, and VS Code Copilot Chat. Analysis, planning, TDD, CLI-aware parallel review with consensus surfacing + Opus triage, default-FAIL evidence gates, secret + intent guards, per-phase cost ledger, persistent learnings memory, wiki generation, commit automation. Token-preserving uninstall.",
5
5
  "type": "module",
6
6
  "main": "index.js",
@@ -120,7 +120,7 @@ Setup & Maintenance:
120
120
 
121
121
  /multi-agent:setup First-run wizard - Keychain tokens + Git identity + language
122
122
  /multi-agent:language [en|tr] Show or set outputLanguage (promptLanguage stays English)
123
- /multi-agent:stack <id> Manually switch active skill set (ios / android / backend / frontend / fullstack / all)
123
+ /multi-agent:stack <id> Select stack by enabling the matching marketplace plugin(s) (ios / android / backend / frontend / fullstack / all)
124
124
  /multi-agent:sync Sync ecosystem (Claude Code + Copilot CLI + pipeline + website + remote-control)
125
125
  /multi-agent:update Pull latest pipeline + reinstall + run migrations
126
126
  /multi-agent:delete Uninstall pipeline from every CLI (Keychain tokens left intact, double confirm)
@@ -177,7 +177,7 @@ Key Features:
177
177
 
178
178
  Multi-Platform iOS, Android, Backend, Frontend - auto-detected
179
179
  Build Queue xcodebuild/Gradle serialized with lock file - parallel safe
180
- Stack Aware Auto-detects iOS/Android/Python/Node/Go/Docker, loads matching skill set
180
+ Stack Aware Auto-detects iOS/Android/Python/Node/Go/Docker, uses the enabled stack plugin's skills
181
181
  Det. Gates Build + lint + test + secret scan BEFORE AI review
182
182
  Multi-Repo Per-repo worktrees, per-repo identity, integration build before commit
183
183
  Identity Routing Git identity auto-picked from repo origin URL (corporate vs personal)
@@ -327,7 +327,7 @@ Setup & Maintenance:
327
327
 
328
328
  /multi-agent:setup İlk kurulum sihirbazı - Keychain token + Git kimliği + dil
329
329
  /multi-agent:language [en|tr] outputLanguage'ı göster veya ayarla (promptLanguage İngilizce kalır)
330
- /multi-agent:stack <id> Aktif skill set'i manuel değiştir (ios / android / backend / frontend / fullstack / all)
330
+ /multi-agent:stack <id> Stack'i eşleşen marketplace plugin'i etkinleştirerek seç (ios / android / backend / frontend / fullstack / all)
331
331
  /multi-agent:sync Ekosistemi senkronize et (Claude Code + Copilot CLI + pipeline + website + remote-control)
332
332
  /multi-agent:update En son pipeline'ı çek + reinstall + migration çalıştır
333
333
  /multi-agent:delete Pipeline'ı tüm CLI'lerden kaldır (Keychain token dokunulmaz, çift onay)
@@ -384,7 +384,7 @@ Temel Özellikler:
384
384
 
385
385
  Multi-Platform iOS, Android, Backend, Frontend - otomatik tespit
386
386
  Build Queue xcodebuild/Gradle lock file ile seri - parallel güvenli
387
- Stack Aware iOS/Android/Python/Node/Go/Docker algılanır, eşleşen skill set yüklenir
387
+ Stack Aware iOS/Android/Python/Node/Go/Docker algılanır, etkin stack plugin'inin skilleri kullanılır
388
388
  Det. Gates AI review'dan ÖNCE build + lint + test + secret scan
389
389
  Multi-Repo Repo başına worktree, repo başına identity, commit öncesi entegrasyon build'i
390
390
  Identity Routing Repo origin URL'sinden git kimliği seçimi (kurumsal vs kişisel)
@@ -1,48 +1,94 @@
1
1
  ---
2
- description: "Manually switch the active skill set by platform (ios/android/mobile/backend/frontend/fullstack/all)."
3
- allowed-tools: Bash
2
+ description: "Select the active stack for this repo by enabling the matching marketplace plugin(s) in .claude/settings.json (ios/android/mobile/backend/frontend/fullstack/all)."
3
+ allowed-tools: Bash, Read, Edit, Write
4
4
  ---
5
5
 
6
- # multi-agent stack - Manual Stack Swap
6
+ # multi-agent stack - Select Stack via Plugin Enablement
7
7
 
8
- The `pipeline/scripts/stack-swap.sh` SessionStart hook auto-detects the stack from the project. This command manually overrides that decision - it switches the active skill set in `~/.claude/skills/` and moves the non-matching skills to `~/.claude/skills-inactive/`.
8
+ Stack skills ship as plugins in the `{owner}/multi-agent-plugins` marketplace. Selecting a stack = **enabling the matching plugin(s)** in the current repo's `.claude/settings.json` `enabledPlugins`. The `ai-common-engineering-toolkit` (accessibility audit, humanizer, Firebase) is always enabled alongside the stack plugin.
9
+
10
+ This replaces the old `stack-swap.sh` mechanic that physically moved skill directories in `~/.claude/skills/`. There is no SessionStart hook and no directory shuffling — enablement is declarative, per-repo, and versioned.
9
11
 
10
12
  ## Usage
11
13
 
12
14
  ```bash
13
- /multi-agent:stack # show current state
14
- /multi-agent:stack ios # SwiftUI + Xcode
15
- /multi-agent:stack android # Compose + Gradle
16
- /multi-agent:stack mobile # iOS + Android together
17
- /multi-agent:stack backend # Python / Node / Go
18
- /multi-agent:stack frontend # React / Vue / Next
19
- /multi-agent:stack fullstack # backend + frontend
20
- /multi-agent:stack all # activate everything
15
+ /multi-agent:stack # show which plugins are enabled here
16
+ /multi-agent:stack ios # SwiftUI toolkit + common
17
+ /multi-agent:stack android # Compose toolkit + common
18
+ /multi-agent:stack mobile # iOS + Android + common
19
+ /multi-agent:stack backend # Python / Node spec-driven toolkit + common
20
+ /multi-agent:stack frontend # React / TSX toolkit + common
21
+ /multi-agent:stack fullstack # frontend + backend + common
22
+ /multi-agent:stack all # all four stack toolkits + common
21
23
  ```
22
24
 
25
+ ## Stack → plugin map
26
+
27
+ | Stack | Plugins enabled (all `@multi-agent-plugins`) |
28
+ |---|---|
29
+ | `ios` | `ai-common-engineering-toolkit`, `ai-ios-engineering-toolkit` |
30
+ | `android` | `ai-common-engineering-toolkit`, `ai-android-engineering-toolkit` |
31
+ | `frontend` | `ai-common-engineering-toolkit`, `ai-frontend-engineering-toolkit` |
32
+ | `backend` | `ai-common-engineering-toolkit`, `ai-backend-toolkit` |
33
+ | `mobile` | common + `ai-ios-engineering-toolkit` + `ai-android-engineering-toolkit` |
34
+ | `fullstack` | common + `ai-frontend-engineering-toolkit` + `ai-backend-toolkit` |
35
+ | `all` | common + all four stack toolkits |
36
+
23
37
  ## Behaviour
24
38
 
25
- 1. No arg → status mode: print the active skill count, do **not** move any files.
26
- 2. Arg present → run `$HOME/.claude/scripts/stack-swap.sh <arg>`.
27
- 3. The script prints JSON on stdout (`{"systemMessage": "..."}`) - show the `systemMessage` value to the user.
28
- 4. Unknown arg → the script returns `exit 1` with an error message; do not re-prompt, show the list to the user.
39
+ 1. **No arg → status mode.** Read `.claude/settings.json` (repo) + `~/.claude/settings.json` (global) and print which `@multi-agent-plugins` plugins are currently enabled. Do not modify anything.
40
+ 2. **Arg present → enable mode.** Ensure the marketplace is known, then write the matching `enabledPlugins` entries into the **current repo's** `.claude/settings.json`, disabling the stack toolkits that don't belong to the selected stack. `ai-common-engineering-toolkit` is always set to `true`.
41
+ 3. **Unknown arg** show the list above; do not guess.
29
42
 
30
43
  ## Implementation
31
44
 
32
45
  ```bash
33
- SCRIPT="$HOME/.claude/scripts/stack-swap.sh"
46
+ REPO_SETTINGS=".claude/settings.json"
47
+ MP="multi-agent-plugins"
48
+ ARG="${1:-status}"
34
49
 
35
- if [ ! -x "$SCRIPT" ]; then
36
- echo "stack-swap.sh not found at $SCRIPT - run install.js --all to deploy pipeline scripts."
37
- exit 1
50
+ # --- ensure the marketplace is known (idempotent) -------------------------
51
+ if ! claude marketplace list 2>/dev/null | grep -q "$MP"; then
52
+ claude marketplace add {owner}/multi-agent-plugins 2>/dev/null \
53
+ || echo "note: add the marketplace once with: claude marketplace add {owner}/multi-agent-plugins"
38
54
  fi
39
55
 
40
- ARG="${1:-status}"
41
- "$SCRIPT" "$ARG"
56
+ COMMON="ai-common-engineering-toolkit@${MP}"
57
+ IOS="ai-ios-engineering-toolkit@${MP}"
58
+ ANDROID="ai-android-engineering-toolkit@${MP}"
59
+ FRONTEND="ai-frontend-engineering-toolkit@${MP}"
60
+ BACKEND="ai-backend-toolkit@${MP}"
61
+
62
+ if [ "$ARG" = "status" ]; then
63
+ echo "Enabled multi-agent plugins (repo + global):"
64
+ { [ -f "$REPO_SETTINGS" ] && cat "$REPO_SETTINGS"; cat "$HOME/.claude/settings.json"; } 2>/dev/null \
65
+ | grep -oE "ai-[a-z-]+@${MP}\"[[:space:]]*:[[:space:]]*(true|false)" | sort -u
66
+ exit 0
67
+ fi
68
+
69
+ # resolve the desired ON set
70
+ case "$ARG" in
71
+ ios) ON="$COMMON $IOS" ;;
72
+ android) ON="$COMMON $ANDROID" ;;
73
+ frontend) ON="$COMMON $FRONTEND" ;;
74
+ backend) ON="$COMMON $BACKEND" ;;
75
+ mobile) ON="$COMMON $IOS $ANDROID" ;;
76
+ fullstack) ON="$COMMON $FRONTEND $BACKEND" ;;
77
+ all) ON="$COMMON $IOS $ANDROID $FRONTEND $BACKEND" ;;
78
+ *) echo "Unknown stack '$ARG'. One of: ios android mobile backend frontend fullstack all"; exit 1 ;;
79
+ esac
42
80
  ```
43
81
 
82
+ After resolving `$ON`, edit `.claude/settings.json` (create `{ "enabledPlugins": {} }` if absent) so that:
83
+ - every plugin in `$ON` is set to `true`,
84
+ - every stack toolkit **not** in `$ON` is set to `false` (leave non-`@multi-agent-plugins` entries untouched),
85
+ - `ai-common-engineering-toolkit@multi-agent-plugins` is always `true`.
86
+
87
+ Use the Read + Edit/Write tools (JSON must stay valid). Then print the resulting `enabledPlugins` block.
88
+
44
89
  ## Notes
45
90
 
46
- - A manual swap takes effect immediately, but to refresh Claude Code's skill discovery completely, **restart the conversation**.
47
- - If you want auto-detect to take over again, the next SessionStart is enough - the hook re-evaluates `cwd`. Manual overrides are not persisted.
48
- - Pipeline Phase 1 stack detection is independent of this command (it reads project files). `stack` only affects which skill set is active.
91
+ - Enablement is per-repo and declarative commit `.claude/settings.json` so teammates get the same stack.
92
+ - Restart the conversation (or reload the window) for Claude Code to pick up newly enabled plugins.
93
+ - Pipeline Phase 1 stack detection is independent (it reads project files); `stack` only sets which plugin skill set is active.
94
+ - Legacy: `~/.claude/scripts/stack-swap.sh` is retained for manual/offline use but is no longer wired to any hook. Prefer plugin enablement.
@@ -61,7 +61,7 @@ Run every step automatically:
61
61
  Step 0: FIGMA_SYNC SKIP (deprecated - feedback_figma_source_deprecated)
62
62
  Step 1: PLATFORM Detect macOS / Linux / Windows (Git Bash / WSL); export PLATFORM env
63
63
  Step 1.5: DETECT Compare timestamps, find stale targets
64
- Step 2: COPILOT Claude Code -> Copilot CLI (instructions + 35 sub-command skills)
64
+ Step 2: COPILOT Claude Code -> Copilot CLI (instructions + 34 sub-command skills)
65
65
  Step 2a: CODEX Claude Code -> Codex CLI (global ~/.codex prompt + AGENTS.md + config.toml mcp)
66
66
  - runs via `node pipeline/scripts/sync-adapters.mjs`, which fires the
67
67
  codex adapter ONCE (global) when `~/.codex` exists on this machine
@@ -70,6 +70,8 @@ Step 2b: ADAPTERS Cursor / Antigravity / Copilot Chat per-project rule files r
70
70
  - `--no-adapters` skips this step entirely
71
71
  - writes files + a LOCAL commit per project; push stays the user's call
72
72
  Step 3: REPO Claude Code -> pipeline repo (genericized, personal data scrub, bash -n on all sh)
73
+ Step 3c: PLUGINS pipeline shared/external -> multi-agent-plugins marketplace (rebuild knowledge/,
74
+ bump changed plugins' patch version, commit + push the plugins repo)
73
75
  Step 4: WEBSITE Version + phase/model counts -> {website-host} (i18n + projects.ts)
74
76
  Step 5: REMOTE Pipeline references -> remote-control README
75
77
  Step 6: Commit Commit + push all changed repos
@@ -215,7 +217,7 @@ Adapter sync orchestration goes through `pipeline/scripts/sync-adapters.mjs` -
215
217
  5. **Files NOT synced** (local-only, may contain personal data):
216
218
  - `~/.claude/multi-agent-preferences.json`
217
219
  - `~/.claude/CLAUDE.md`, `~/.claude/rules/`, `~/.claude/knowledge/`
218
- - `~/.claude/scripts/` - EXCEPT `pre-commit-check.sh` and `stack-swap.sh` (generic, synced)
220
+ - `~/.claude/scripts/` - EXCEPT `pre-commit-check.sh`, `stack-swap.sh` (legacy, retained for manual use), and `build-stack-plugins.mjs` (generic, synced)
219
221
  - `~/.claude/settings.json`
220
222
 
221
223
  6. **Cross-platform smoke gate** (final step of the REPO sync, before push):
@@ -234,6 +236,48 @@ Adapter sync orchestration goes through `pipeline/scripts/sync-adapters.mjs` -
234
236
 
235
237
  ---
236
238
 
239
+ ## Stack-Plugin Sync (Step 3c)
240
+
241
+ Stack skills are distributed as versioned plugins in the `{owner}/multi-agent-plugins` marketplace. The pipeline's `pipeline/skills/shared/external/` is the **single authoring source**; the marketplace is a derived, versioned publish artifact. This step rebuilds it and publishes only when something changed.
242
+
243
+ **Source of truth:** author/vendor knowledge skills in `pipeline/skills/shared/external/` (the pipeline's own phases also consume them). The plugins' authored lifecycle skills (`index` / `reference` / `workflow` / `tools`) live in the plugins repo and are never touched by sync.
244
+
245
+ **Flow:**
246
+
247
+ ```bash
248
+ PLUGINS_REPO="$HOME/multi-agent-plugins"
249
+ [ ! -d "$PLUGINS_REPO/.git" ] && gh repo clone {owner}/multi-agent-plugins "$PLUGINS_REPO"
250
+ cd "$PLUGINS_REPO" && git pull origin main
251
+
252
+ # 1. Preview what would change (routing + version bumps), no writes:
253
+ node "$HOME/multi-agent-pipeline/pipeline/scripts/build-stack-plugins.mjs" --dry-run
254
+
255
+ # 2. Apply: rebuild each stack plugin's knowledge/ from shared/external,
256
+ # regenerate plugin.json skills[], bump the patch version of any plugin
257
+ # whose skill set changed. Cross-stack skills -> ai-common-engineering-toolkit;
258
+ # Apple/Xcode-only skills -> iOS plugin only.
259
+ node "$HOME/multi-agent-pipeline/pipeline/scripts/build-stack-plugins.mjs"
260
+ ```
261
+
262
+ **Version-based management:** the generator bumps a plugin's `version` (patch) only when its skill set actually changed. Idempotent — a no-op run bumps nothing. Consumers pick up new versions via `/multi-agent:update` (which runs `claude marketplace update multi-agent-plugins`).
263
+
264
+ **Publish (only if the generator reported bumps):**
265
+
266
+ ```bash
267
+ cd "$PLUGINS_REPO"
268
+ if ! git diff --quiet; then
269
+ git config user.name "$(git config user.name)"; git config user.email "$(git config user.email)"
270
+ git add -A
271
+ git commit -m "chore: rebuild stack plugins from pipeline shared/external"
272
+ gh auth switch --user {owner} 2>/dev/null || true
273
+ git push origin main
274
+ fi
275
+ ```
276
+
277
+ Never author skills directly in the plugins repo's `knowledge/` — they will be overwritten on the next rebuild. Author in `shared/external`, then run this step.
278
+
279
+ ---
280
+
237
281
  ## Website Sync (Step 4)
238
282
 
239
283
  Propagate pipeline version, phase count, model count, and feature descriptions to the website.
@@ -302,11 +346,11 @@ This step runs only on the Claude <-> Copilot axis. Cursor / Copilot Chat do not
302
346
  |-------------|-------------|
303
347
  | `~/.claude/commands/multi-agent/{cmd}.md` | `~/.copilot/skills/multi-agent-{cmd}/SKILL.md` |
304
348
 
305
- **35 commands are synced** (canonical inventory - must match `cross-cli-contract.md` section 1; drift = contract violation):
349
+ **34 commands are synced** (canonical inventory - must match `cross-cli-contract.md` section 1; drift = contract violation):
306
350
 
307
351
  ```
308
352
  analysis, analysis-resolve, autopilot, build-optimize, channels, delete, dev,
309
- dev-autopilot, dev-local, dev-local-autopilot, diff-explain, finish, garbage-collect,
353
+ dev-autopilot, dev-local, dev-local-autopilot, diff-explain, garbage-collect,
310
354
  help, issue, jira, kill, language, local, local-autopilot, log, manual-test,
311
355
  prune-logs, purge, refactor, resume, review, scan, search, setup, stack, status,
312
356
  sync, test, update
@@ -17,7 +17,7 @@ Update the pipeline in one command. Existing preferences are preserved; only ski
17
17
  done
18
18
  if [ -z "$PIPE_DIR" ]; then
19
19
  echo "Pipeline repo not found. Clone it:"
20
- echo " git clone git@github.com:mmerterden/multi-agent-pipeline.git"
20
+ echo " git clone git@github.com:{owner}/multi-agent-pipeline.git"
21
21
  exit 1
22
22
  fi
23
23
  ```
@@ -38,6 +38,19 @@ Update the pipeline in one command. Existing preferences are preserved; only ski
38
38
  node "$PIPE_DIR/install.js" --all
39
39
  ```
40
40
 
41
+ 4b. **Update the stack-plugin marketplace** (pulls the latest plugin versions):
42
+ ```bash
43
+ # Stack skills ship as versioned plugins in {owner}/multi-agent-plugins.
44
+ # Refresh the marketplace so newly published plugin versions are picked up.
45
+ if claude marketplace list 2>/dev/null | grep -q "multi-agent-plugins"; then
46
+ claude marketplace update multi-agent-plugins 2>/dev/null \
47
+ || claude marketplace add {owner}/multi-agent-plugins 2>/dev/null
48
+ echo " -> marketplace multi-agent-plugins refreshed"
49
+ else
50
+ echo " -> marketplace not added yet; add with: claude marketplace add {owner}/multi-agent-plugins"
51
+ fi
52
+ ```
53
+
41
54
  5. **Migrate preferences** (if there is an old schema):
42
55
  ```bash
43
56
  if [ -f "$HOME/.claude/scripts/migrate-prefs.mjs" ]; then
@@ -0,0 +1,137 @@
1
+ #!/usr/bin/env node
2
+ /**
3
+ * build-stack-plugins.mjs
4
+ *
5
+ * Rebuild the per-stack plugin `knowledge/` trees in the multi-agent-plugins
6
+ * marketplace from the pipeline's authoring source (pipeline/skills/shared/external),
7
+ * regenerate each plugin.json `skills[]`, and bump the patch version of any plugin
8
+ * whose skill set changed. This is the version-based management backbone: the
9
+ * pipeline is the single authoring source; the marketplace is a derived, versioned
10
+ * publish artifact.
11
+ *
12
+ * The authored lifecycle skills (index / reference / workflow / tools) live in the
13
+ * plugin repo and are NEVER touched here — only the `knowledge/` layer + plugin.json
14
+ * knowledge entries are regenerated.
15
+ *
16
+ * Routing mirrors pipeline/scripts/stack-swap.sh patterns. Genuinely cross-stack
17
+ * skills go to ai-common-engineering-toolkit (not into each stack plugin). Apple/
18
+ * Xcode-only vendored skills that match no stack pattern belong to iOS only.
19
+ *
20
+ * Usage:
21
+ * node build-stack-plugins.mjs [--plugins-repo <path>] [--pipeline <path>] [--dry-run]
22
+ *
23
+ * Exit code 0 always (report-only); prints a JSON-ish summary + per-plugin diff.
24
+ */
25
+ import {
26
+ readdirSync, existsSync, rmSync, cpSync, readFileSync, writeFileSync, mkdirSync, statSync,
27
+ } from 'node:fs';
28
+ import { join } from 'node:path';
29
+
30
+ const args = process.argv.slice(2);
31
+ const getArg = (k, d) => { const i = args.indexOf(k); return i >= 0 ? args[i + 1] : d; };
32
+ const HOME = process.env.HOME;
33
+ const PLUGINS_REPO = getArg('--plugins-repo', join(HOME, 'multi-agent-plugins'));
34
+ const PIPE_ROOT = getArg('--pipeline', join(HOME, 'multi-agent-pipeline'));
35
+ const EXTERNAL = join(PIPE_ROOT, 'pipeline/skills/shared/external');
36
+ const DRY = args.includes('--dry-run');
37
+
38
+ const COMMON_PLUGIN = 'ai-common-engineering-toolkit';
39
+ const COMMON_SKILLS = ['accessibility-compliance-accessibility-audit', 'firebase', 'humanizer'];
40
+
41
+ // Apple/Xcode-only skills that match no stack pattern → iOS plugin only.
42
+ const APPLE_ONLY = [
43
+ 'avkit', 'cryptokit', 'metrickit-diagnostics', 'pdfkit', 'spm-build-analysis',
44
+ 'swiftlint', 'xcode-build-benchmark', 'xcode-build-fixer', 'xcode-build-orchestrator',
45
+ 'xcode-compilation-analyzer', 'xcode-project-analyzer',
46
+ ];
47
+
48
+ // stack → matching pattern (mirrors stack-swap.sh IOS/ANDROID/BACKEND/FRONTEND patterns)
49
+ const STACK_PATTERNS = {
50
+ 'ai-ios-engineering-toolkit': /(swiftui|swift-|ios-|hig-|apple-|storekit|widgetkit|healthkit|homekit|mapkit|musickit|passkit|pencilkit|realitykit|weatherkit|alarmkit|callkit|cloudkit|coreml|core-|eventkit|energykit|permissionkit|tipkit|shareplay|live-activities|background-processing|app-store|app-clips|app-intents|authentication|contacts-framework|device-integrity|macos-|natural-language|photos-camera|push-notifications|speech-recognition|swiftdata|vision-framework|debugging-instruments|help-skills)/i,
51
+ 'ai-android-engineering-toolkit': /(android|compose-|kotlin-|room-database|retrofit-|gradle-|play-store)/i,
52
+ 'ai-backend-toolkit': /(fastapi|nodejs|docker|api-pattern|api-security|github-actions|observability|architecture|monorepo|clean-code|debugging-strategies|agentflow|closed-loop|context-compression|python-patterns|database-patterns|rest-api-design|testing-backend|ci-cd-pipelines)/i,
53
+ 'ai-frontend-engineering-toolkit': /(react-|nextjs-|typescript-|tailwind-|vue-|web-accessibility|web-performance|css-modern|web-testing|html-semantic)/i,
54
+ };
55
+
56
+ const isDir = (p) => { try { return statSync(p).isDirectory(); } catch { return false; } };
57
+ const listDirs = (p) => (existsSync(p) ? readdirSync(p).filter((n) => isDir(join(p, n))) : []);
58
+
59
+ // --- 1. enumerate authoring source ---------------------------------------
60
+ if (!existsSync(EXTERNAL)) {
61
+ console.error(`source not found: ${EXTERNAL}`);
62
+ process.exit(0);
63
+ }
64
+ const allSkills = listDirs(EXTERNAL);
65
+
66
+ // --- 2. compute desired knowledge set per plugin -------------------------
67
+ const desired = { [COMMON_PLUGIN]: new Set() };
68
+ for (const p of Object.keys(STACK_PATTERNS)) desired[p] = new Set();
69
+
70
+ const unrouted = [];
71
+ for (const skill of allSkills) {
72
+ if (COMMON_SKILLS.includes(skill)) { desired[COMMON_PLUGIN].add(skill); continue; }
73
+ if (APPLE_ONLY.includes(skill)) { desired['ai-ios-engineering-toolkit'].add(skill); continue; }
74
+ let matched = false;
75
+ for (const [plugin, re] of Object.entries(STACK_PATTERNS)) {
76
+ if (re.test(skill)) { desired[plugin].add(skill); matched = true; }
77
+ }
78
+ if (!matched) unrouted.push(skill);
79
+ }
80
+
81
+ // --- 3. sync each plugin's knowledge/ + regenerate plugin.json -----------
82
+ const report = [];
83
+ for (const [plugin, want] of Object.entries(desired)) {
84
+ const pdir = join(PLUGINS_REPO, 'plugins', plugin);
85
+ const kdir = join(pdir, 'skills', 'knowledge');
86
+ const pjPath = join(pdir, '.claude-plugin', 'plugin.json');
87
+ if (!existsSync(pjPath)) { report.push({ plugin, error: 'plugin.json missing' }); continue; }
88
+
89
+ const have = new Set(listDirs(kdir));
90
+ const toAdd = [...want].filter((s) => !have.has(s)).sort();
91
+ const toRemove = [...have].filter((s) => !want.has(s)).sort();
92
+ const changed = toAdd.length > 0 || toRemove.length > 0;
93
+
94
+ if (!DRY && changed) {
95
+ if (!existsSync(kdir)) mkdirSync(kdir, { recursive: true });
96
+ for (const s of toAdd) cpSync(join(EXTERNAL, s), join(kdir, s), { recursive: true });
97
+ for (const s of toRemove) rmSync(join(kdir, s), { recursive: true, force: true });
98
+ }
99
+
100
+ // regenerate plugin.json skills[]: keep non-knowledge entries, rebuild knowledge set
101
+ const pj = JSON.parse(readFileSync(pjPath, 'utf8'));
102
+ const nonKnowledge = (pj.skills || []).filter((s) => !s.startsWith('./skills/knowledge/'));
103
+ const finalKnowledge = (DRY ? [...want] : listDirs(kdir)).map((s) => `./skills/knowledge/${s}`);
104
+ const newSkills = [...new Set([...nonKnowledge, ...finalKnowledge])].sort();
105
+ const skillsChanged = JSON.stringify(pj.skills) !== JSON.stringify(newSkills);
106
+
107
+ const oldV = pj.version || '0.1.0';
108
+ let newV = oldV;
109
+ if (changed || skillsChanged) {
110
+ const [maj, min, patch] = oldV.split('.').map((n) => parseInt(n, 10) || 0);
111
+ newV = `${maj}.${min}.${patch + 1}`;
112
+ }
113
+ if (!DRY && (changed || skillsChanged)) {
114
+ pj.skills = newSkills;
115
+ pj.version = newV;
116
+ writeFileSync(pjPath, `${JSON.stringify(pj, null, 2)}\n`);
117
+ }
118
+ report.push({ plugin, added: toAdd, removed: toRemove, skillCount: newSkills.length, version: oldV === newV ? oldV : `${oldV} → ${newV}`, bumped: oldV !== newV });
119
+ }
120
+
121
+ // --- 4. report ------------------------------------------------------------
122
+ console.log(`build-stack-plugins ${DRY ? '(dry-run)' : ''}`);
123
+ console.log(`source: ${EXTERNAL} (${allSkills.length} skills)`);
124
+ console.log(`target: ${PLUGINS_REPO}`);
125
+ for (const r of report) {
126
+ if (r.error) { console.log(` ✗ ${r.plugin}: ${r.error}`); continue; }
127
+ const flag = r.bumped ? 'BUMPED' : 'unchanged';
128
+ console.log(` ${r.plugin}: skills=${r.skillCount} version=${r.version} [${flag}]`);
129
+ if (r.added.length) console.log(` + ${r.added.join(', ')}`);
130
+ if (r.removed.length) console.log(` - ${r.removed.join(', ')}`);
131
+ }
132
+ if (unrouted.length) {
133
+ console.log(` ⚠ unrouted (matched no stack, not common/apple-only) — NOT copied anywhere:`);
134
+ console.log(` ${unrouted.join(', ')}`);
135
+ }
136
+ const anyBump = report.some((r) => r.bumped);
137
+ console.log(anyBump ? 'result: changes detected (versions bumped)' : 'result: all plugins up to date');
@@ -1,55 +1,50 @@
1
1
  ---
2
2
  name: multi-agent-stack
3
3
  language: en
4
- description: "Manually switch the active skill set by platform (ios/android/mobile/backend/frontend/fullstack/all)."
4
+ description: "Select the active stack for this repo by enabling the matching marketplace plugin(s) in .claude/settings.json (ios/android/mobile/backend/frontend/fullstack/all)."
5
5
  user-invocable: true
6
6
  ---
7
7
 
8
- # multi-agent stack - Manual Stack Swap
8
+ # multi-agent stack - Select Stack via Plugin Enablement
9
9
 
10
- The `pipeline/scripts/stack-swap.sh` SessionStart hook auto-detects the stack from the project. This command manually overrides that decision - it changes the active skill set and moves non-matching skills to `skills-inactive/`.
10
+ Stack skills ship as plugins in the `{owner}/multi-agent-plugins` marketplace. Selecting a stack = **enabling the matching plugin(s)** in the current repo's `.claude/settings.json` `enabledPlugins`. The `ai-common-engineering-toolkit` (accessibility audit, humanizer, Firebase) is always enabled alongside the stack plugin.
11
+
12
+ This replaces the old `stack-swap.sh` mechanic that physically moved skill directories. No SessionStart hook, no directory shuffling — enablement is declarative, per-repo, and versioned.
11
13
 
12
14
  ## Usage
13
15
 
14
16
  ```bash
15
- multi-agent-stack # show the current state
16
- multi-agent-stack ios # SwiftUI + Xcode
17
- multi-agent-stack android # Compose + Gradle
18
- multi-agent-stack mobile # iOS + Android together
19
- multi-agent-stack backend # Python / Node / Go
20
- multi-agent-stack frontend # React / Vue / Next
21
- multi-agent-stack fullstack # backend + frontend
22
- multi-agent-stack all # activate everything
17
+ multi-agent-stack # show which plugins are enabled here
18
+ multi-agent-stack ios # SwiftUI toolkit + common
19
+ multi-agent-stack android # Compose toolkit + common
20
+ multi-agent-stack mobile # iOS + Android + common
21
+ multi-agent-stack backend # Python / Node spec-driven toolkit + common
22
+ multi-agent-stack frontend # React / TSX toolkit + common
23
+ multi-agent-stack fullstack # frontend + backend + common
24
+ multi-agent-stack all # all four stack toolkits + common
23
25
  ```
24
26
 
25
- ## Behaviour
27
+ ## Stack → plugin map
26
28
 
27
- 1. No arg status mode: show the active skill count, do **not** move any files.
28
- 2. With an arg → run `stack-swap.sh <arg>`.
29
- 3. The script's stdout is JSON (`{"systemMessage": "..."}`) - print the `systemMessage` value to the user.
30
- 4. Unknown arg → the script returns `exit 1` + an error message; do not ask for the value again, show the user the list.
29
+ | Stack | Plugins enabled (all `@multi-agent-plugins`) |
30
+ |---|---|
31
+ | `ios` | `ai-common-engineering-toolkit`, `ai-ios-engineering-toolkit` |
32
+ | `android` | `ai-common-engineering-toolkit`, `ai-android-engineering-toolkit` |
33
+ | `frontend` | `ai-common-engineering-toolkit`, `ai-frontend-engineering-toolkit` |
34
+ | `backend` | `ai-common-engineering-toolkit`, `ai-backend-toolkit` |
35
+ | `mobile` | common + `ai-ios-engineering-toolkit` + `ai-android-engineering-toolkit` |
36
+ | `fullstack` | common + `ai-frontend-engineering-toolkit` + `ai-backend-toolkit` |
37
+ | `all` | common + all four stack toolkits |
31
38
 
32
- ## Implementation
39
+ ## Behaviour
33
40
 
34
- ```bash
35
- # Both CLIs install pipeline scripts under their own home dir. Prefer Copilot's
36
- # own scripts if present; fall back to Claude Code's scripts when running under
37
- # --all install (shared machine, either CLI's copy is up-to-date).
38
- if [ -x "$HOME/.copilot/scripts/stack-swap.sh" ]; then
39
- SCRIPT="$HOME/.copilot/scripts/stack-swap.sh"
40
- elif [ -x "$HOME/.claude/scripts/stack-swap.sh" ]; then
41
- SCRIPT="$HOME/.claude/scripts/stack-swap.sh"
42
- else
43
- echo "stack-swap.sh not found - run install.js --copilot (or --all) to deploy pipeline scripts."
44
- exit 1
45
- fi
46
-
47
- ARG="${1:-status}"
48
- "$SCRIPT" "$ARG"
49
- ```
41
+ 1. **No arg → status mode.** Read `.claude/settings.json` (repo) + the global settings and print which `@multi-agent-plugins` plugins are enabled. Modify nothing.
42
+ 2. **Arg present enable mode.** Ensure the marketplace is known (`claude marketplace add {owner}/multi-agent-plugins`), then write the matching `enabledPlugins` entries into the current repo's `.claude/settings.json`, setting the stack toolkits that don't belong to `false`. `ai-common-engineering-toolkit` is always `true`.
43
+ 3. **Unknown arg** show the list above; do not guess.
50
44
 
51
45
  ## Notes
52
46
 
53
- - A manual swap takes effect immediately, but to fully refresh Copilot CLI's skill discovery, **restart the conversation**.
54
- - If you want auto-detect to take over again, the next SessionStart is enough - the hook looks at `cwd` and decides again. The manual override is not permanent.
55
- - Pipeline Phase 1 stack detection is independent of this command (it looks at project files). `stack` only affects which skill set is active.
47
+ - Enablement is per-repo and declarative commit `.claude/settings.json` so teammates get the same stack.
48
+ - Restart the conversation to pick up newly enabled plugins.
49
+ - Pipeline Phase 1 stack detection is independent (it reads project files); `stack` only sets which plugin skill set is active.
50
+ - Legacy: `stack-swap.sh` is retained for manual/offline use but is no longer wired to any hook.
@@ -90,7 +90,8 @@ If nothing is stale -> report "All targets up to date" and stop.
90
90
  5. **Files NOT synced** (local-only, may contain personal data):
91
91
  - `~/.claude/multi-agent-preferences.json`
92
92
  - `~/.claude/CLAUDE.md`, `~/.claude/rules/`, `~/.claude/knowledge/`
93
- - `~/.claude/scripts/` - EXCEPT `pre-commit-check.sh` and `stack-swap.sh` (generic, synced)
93
+ - `~/.claude/scripts/` - EXCEPT `pre-commit-check.sh`, `stack-swap.sh` (legacy, retained), and `build-stack-plugins.mjs` (generic, synced)
94
+ - Step 3c (PLUGINS): rebuild the `{owner}/multi-agent-plugins` marketplace from `shared/external` via `build-stack-plugins.mjs` (bumps changed plugins' patch version), then commit + push the plugins repo
94
95
  - `~/.claude/settings.json`
95
96
 
96
97
 
@@ -16,6 +16,8 @@ Update the pipeline with a single command. Preferences are preserved; only skill
16
16
  2. Record the current version
17
17
  3. `git pull origin main`
18
18
  4. `node install.js --all` (Claude + Copilot)
19
+ 4b. Refresh the stack-plugin marketplace so the latest plugin versions are picked up:
20
+ `claude marketplace update multi-agent-plugins` (or `claude marketplace add {owner}/multi-agent-plugins` if not yet added)
19
21
  5. `node migrate-prefs.mjs` (if there is a schema upgrade)
20
22
  6. Show the new version + changelog
21
23
  7. Smoke test (schema + cross-cli)