@mmerterden/multi-agent-pipeline 15.3.0 → 15.3.2

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
@@ -16,62 +16,50 @@ Internal file-layout changes that don't affect the slash-command surface are sti
16
16
 
17
17
  ## [Unreleased]
18
18
 
19
+ ## [15.3.2] - 2026-08-17
20
+
21
+ ### Fixed
22
+
23
+ - `local` and `local-autopilot` mode docs pointed at the retired `commands/multi-agent.md` dispatcher spelling; they now reference `commands/multi-agent/SKILL.md`, and the Codex installer rewrites the directory-layout spelling to the router skill (dedicated rewrite rule, smoke guard for the new corruption shape, unit tests).
24
+ - The sync spec copies (command tree + Copilot shared-core mirror) disagreed on the Claude source list and file mapping; both now carry `multi-agent-refs/` and `lib/` and the same mapping rows.
25
+ - The dispatcher entry doc now declares the TaskCreate ordering rule and is scanned by `smoke-tasklist-ordering.sh`, closing the one mode (full interactive) the inventory missed.
26
+ - `check-md-links.mjs` resolves `$HOME/.claude/commands/` links against the repo source, so a future layout move cannot leave dangling dispatcher references silently.
27
+ - Install-layout fingerprint fixture regenerated for `usage-report.mjs` and the relocated reference files.
28
+
29
+ ### Changed
30
+
31
+ - refactor Step 0c (dev-toolkit research) and setup Step 3b (App Store Connect onboarding) moved to on-demand references under `multi-agent-refs/`, keeping both skills inside their token budgets.
32
+
33
+ ## [15.3.1] - 2026-08-15
34
+
35
+ ### Changed
36
+
37
+ - Documentation and wording clarifications.
38
+
19
39
  ## [15.3.0] - 2026-08-15
20
40
 
21
41
  ### Added
22
42
 
23
- - **`/multi-agent:setup` onboards the usage-dashboard token (opt-in, one-time).**
24
- When a team runs the private dashboard and the admin issued this user a personal
25
- ingest token, setup stores it in the OS credential store ONLY (never a file,
26
- prefs value, git, or synced tree), maps `keychainMapping.usage_ingest`, and
27
- turns logging on. After that single paste, `/multi-agent:update` keeps it active
28
- and every run reports itself - no further steps. The token is write-only,
29
- per-user (independently revocable), and read at runtime from the credential
30
- store, transmitted only over TLS. Skipping the prompt leaves logging fully off.
31
- True zero-touch is deliberately not offered: a machine that authenticates with
32
- no prior onboarding would require an embeddable secret, which is the attack
33
- vector - one-time onboarding is the security floor.
43
+ - `/multi-agent:setup` gains an optional one-time operational-token onboarding
44
+ step (opt-in). The token is stored in the OS credential store only, never in a
45
+ file, prefs value, git, or synced tree.
34
46
 
35
47
  ## [15.2.0] - 2026-08-15
36
48
 
37
49
  ### Added
38
50
 
39
- - **`/multi-agent:update` auto-enables usage logging when a token is onboarded.**
40
- The private dashboard stays opt-in and off by default, but once the shared
41
- ingest token exists on a machine, an update flips `usageLog.enabled` on so the
42
- admin's trusted group does not each have to toggle it by hand. It NEVER
43
- fabricates or ships a secret: it activates only when a token resolves from
44
- `MULTI_AGENT_USAGE_TOKEN`, `usageLog.token`, or the Keychain item named by the
45
- new generic `keychainMapping.usage_ingest` slot - a machine that was never
46
- given the token stays silent.
47
- - **`usage-report.mjs` reads the ingest token from the Keychain** (via
48
- `credential-store.sh`, resolved through `keychainMapping.usage_ingest`) as a
49
- fallback after env and `usageLog.token`, so the secret never has to live in a
50
- synced or plaintext file for logging to work.
51
+ - `/multi-agent:update` auto-configures the optional operational integration when
52
+ its token is already onboarded, resolving it from the credential store; it never
53
+ fabricates or ships a secret, so a machine without one is unaffected.
51
54
 
52
55
  ## [15.1.0] - 2026-08-14
53
56
 
54
- Opt-in run telemetry to a private dashboard, and a refactor band that mines it.
55
-
56
57
  ### Added
57
58
 
58
- - **Opt-in usage telemetry (`usageLog`).** When `prefs.global.usageLog.enabled`
59
- is set with an ingest token, each run emits one activity event, keyed by task
60
- id and refreshed live at every phase boundary via `phase-tracker.sh`, so one
61
- record always shows the last phase a run reached including runs that halt
62
- before Phase 7. Wired at Phase 7 report and the halt path; detached and
63
- best-effort, never blocking a run. The event carries activity metadata only
64
- (who, command, mode, input type, repo, phase, outcome, halt cause, review
65
- iterations, duration, token spend, cost, per-phase breakdown, OS, CLI, models,
66
- stack, plugins, integrations, credential health, invoked skills, error tags,
67
- version) — never prompts, code, diffs, token values or absolute paths. New
68
- `pipeline/scripts/usage-report.mjs`; prefs schema + template gain the
69
- `usageLog` block. Off by default; the emitter no-ops unless enabled and a
70
- token resolves.
71
- - **`/multi-agent:refactor` Step 0d (band F).** Reads the local run-error ledger
72
- (`errors-ledger.jsonl`, written by the telemetry emitter on terminal runs) and
73
- ranks recurring failures as prioritized improvement areas — lived evidence,
74
- offline, and without auth.
59
+ - Optional, opt-in per-run operational reporting (`usageLog`), off by default and
60
+ a no-op unless configured.
61
+ - `/multi-agent:refactor` Step 0d (band F) reads a local run-diagnostics ledger to
62
+ rank recurring failures as prioritized improvement areas - offline, no auth.
75
63
 
76
64
  ### Changed
77
65
 
package/install/codex.mjs CHANGED
@@ -82,6 +82,18 @@ export const CODEX_PATH_REWRITES = Object.freeze([
82
82
  to: "$HOME/.codex/skills/multi-agent/SKILL.md",
83
83
  },
84
84
  { from: /~\/\.claude\/commands\/multi-agent\.md/g, to: "~/.codex/skills/multi-agent/SKILL.md" },
85
+ // Current dispatcher spelling (directory layout). MUST also precede the
86
+ // sub-command rule: `commands/multi-agent/SKILL.md` would otherwise become
87
+ // `multi-agent-refs/commands/SKILL.md`, which installRefs deliberately never
88
+ // writes (the top-level SKILL.md ships as the router skill instead).
89
+ {
90
+ from: /\$HOME\/\.claude\/commands\/multi-agent\/SKILL\.md/g,
91
+ to: "$HOME/.codex/skills/multi-agent/SKILL.md",
92
+ },
93
+ {
94
+ from: /~\/\.claude\/commands\/multi-agent\/SKILL\.md/g,
95
+ to: "~/.codex/skills/multi-agent/SKILL.md",
96
+ },
85
97
  // Sub-command specs become reference files under the Codex refs tree.
86
98
  {
87
99
  from: /\$HOME\/\.claude\/commands\/multi-agent\b/g,
package/package.json CHANGED
@@ -1,6 +1,6 @@
1
1
  {
2
2
  "name": "@mmerterden/multi-agent-pipeline",
3
- "version": "15.3.0",
3
+ "version": "15.3.2",
4
4
  "description": "8-phase AI development pipeline with full orchestration on Claude Code, Copilot CLI and Codex CLI. Analysis, planning, TDD, CLI-aware parallel review with consensus surfacing + Fable 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",
@@ -285,6 +285,10 @@ Quick pointers:
285
285
 
286
286
  Load `$HOME/.claude/multi-agent-refs/rules.md` for the full contract (Swift-specific rules, reviewer policy, secret scan, subagent contract).
287
287
 
288
+ ### TaskCreate ordering (strict)
289
+
290
+ **All TaskCreate calls fire in strict phase-number order BEFORE any TaskUpdate is applied** - this binds the full interactive `/multi-agent` run (all 8 phases) exactly like every mode alias. The native widget renders tiles by creation order, not by phase number; out-of-order calls produce visually scrambled tile stacks. Register every tile in order, then flip status via TaskUpdate when a phase actually starts or short-circuits. Full contract: `$HOME/.claude/multi-agent-refs/tracker-contract.md` section "TaskCreate ordering (strict)".
291
+
288
292
  ---
289
293
 
290
294
  ## Status Display
@@ -40,7 +40,7 @@ Phase 7: Report → Jira / Wiki / Confluence + log + knowledge/memory
40
40
 
41
41
  This command routes to the orchestrator with the `--local` flag set. The Phase 0-7 contract from `$HOME/.claude/multi-agent-refs/phases/phase-0-init.md` and the later phase docs applies as-is - only the worktree step is skipped, and `state.projects[*].worktreePath` stays `null`.
42
42
 
43
- Read the routing table in `$HOME/.claude/commands/multi-agent.md` and apply Phase 0 Step 8 in local mode (no worktree: continue on the current branch, state file under `.claude/logs/multi-agent/{project}/{taskId}/`).
43
+ Read the routing table in `$HOME/.claude/commands/multi-agent/SKILL.md` and apply Phase 0 Step 8 in local mode (no worktree: continue on the current branch, state file under `.claude/logs/multi-agent/{project}/{taskId}/`).
44
44
 
45
45
  ## Examples
46
46
 
@@ -69,7 +69,7 @@ Run the full pipeline **without a worktree** and **with every confirmation skipp
69
69
 
70
70
  ## Delegation
71
71
 
72
- Orchestrator routing: the routing table in `$HOME/.claude/commands/multi-agent.md` resolves `local-autopilot` as the union of the `dev-local` + `autopilot` mode mixins. Contract details: `$HOME/.claude/multi-agent-refs/phases/phase-0-init.md` Step 8 (local branch) + `$HOME/.claude/multi-agent-refs/phases/phase-2-planning.md` Step 5 (autopilot gate skip + safety classifier).
72
+ Orchestrator routing: the routing table in `$HOME/.claude/commands/multi-agent/SKILL.md` resolves `local-autopilot` as the union of the `dev-local` + `autopilot` mode mixins. Contract details: `$HOME/.claude/multi-agent-refs/phases/phase-0-init.md` Step 8 (local branch) + `$HOME/.claude/multi-agent-refs/phases/phase-2-planning.md` Step 5 (autopilot gate skip + safety classifier).
73
73
  ## Required: outward-facing payload contracts
74
74
 
75
75
  Before writing anything outward-facing - PR body, Jira comment, Confluence page, closing report - load `$HOME/.claude/multi-agent-refs/payload-contracts.md`. It names the canonical section set for each payload, the markup dialect per surface (PR body is Markdown, Jira is wiki markup - mixing them is a defect), and the token/duration numbers the closing report must carry. Improvising a payload shape from memory is the most common failure of the short modes.
@@ -112,73 +112,7 @@ Procedure:
112
112
 
113
113
  The pipeline's hands on devices and browsers are MCP tools served by a companion repo (`dev-toolkit-mcp`): Phase 5 test, `manual-test`, `design-check` and `apple-archive-compliance` all call them, and several pipeline skills declare a minimum toolkit version (see `cross-cli-contract.md`). That repo therefore has to track the MCP field, not just its own README. This step researches what current practice is and audits the toolkit against it.
114
114
 
115
- **Resolution** - configuration first, never a hardcoded path:
116
-
117
- 1. `prefs.global.devToolkit` in `~/.claude/multi-agent-preferences.json`:
118
-
119
- ```jsonc
120
- {
121
- "enabled": true,
122
- "label": "<human name>",
123
- "localPath": "$HOME/<repo-dir>", // the companion repo working copy
124
- "mcpServerName": "<registered MCP server name>",
125
- "packageName": "@<scope>/<package>",
126
- "registry": "github-packages", // github-packages | npmjs | none
127
- "repoUrl": "https://github.com/<owner>/<repo>"
128
- }
129
- ```
130
-
131
- 2. If unset, auto-detect from the MCP registration: read `mcpServers` in `~/.claude.json` (including each `projects[*].mcpServers`) and in `~/.claude/settings.json`; for a stdio entry whose command is `node`, take `dirname(args[0])`. Accept it only when that directory is a git repo whose `package.json` depends on `@modelcontextprotocol/sdk`.
132
- 3. If neither resolves, skip this step and report "no dev-toolkit configured". Never guess a path, never clone.
133
- 4. `enabled: false` skips the step.
134
-
135
- **Research axes** - a finding without a source link is not a finding:
136
-
137
- | # | Axis | Where to look | What to extract |
138
- |---|------|---------------|-----------------|
139
- | 1 | MCP protocol | spec revisions + `@modelcontextprotocol/sdk` releases | protocol features released since the pinned SDK range that the server does not use yet: tool annotations (`readOnlyHint` / `destructiveHint` / `idempotentHint` / `openWorldHint`), `outputSchema` + structured content, resource links in results, progress + cancellation, `tools/list_changed`, pagination, elicitation |
140
- | 2 | Host clients | Claude Code / Copilot CLI / Cursor / Antigravity docs + release notes | per-tool description budget, tool-count ceilings, naming conventions, image and output size limits, permission / allowlist ergonomics |
141
- | 3 | Peer servers | GitHub search on the same domain terms + `stars:>50` | tool surfaces we lack, conventions peers converged on, and what to discard as out of scope |
142
- | 4 | Wrapped tooling | `xcrun simctl help`, `idb`, `adb`, `xcodebuild`, Playwright release notes, Apple ITMS + App Store Review Guidelines | deprecated flags still in use, new capabilities worth a tool, audit rules that changed |
143
- | 5 | Field practice | X / Twitter, Reddit, MCP community threads | what server authors actually changed recently (transport choice, output-token diets, sandboxing, error shape) |
144
-
145
- **Audit the toolkit against the findings** - run the checks, do not assume:
146
-
147
- ```bash
148
- DT="<resolved localPath>"
149
- node --check "$DT/index.js"
150
- find "$DT/tools" -name "*.js" -type f -exec node --check {} \;
151
-
152
- # stdout carries the JSON-RPC frames: a stray stdout write corrupts the stream
153
- grep -rn "console\.log(" "$DT/index.js" "$DT/tools" || echo "stdout clean"
154
-
155
- # advertised tool counts vs reality (README header + package.json description)
156
- grep -nE "[0-9]+ tools" "$DT/README.md" "$DT/package.json"
157
-
158
- # packaging: every runtime directory must be inside files[]
159
- node -p "require('$DT/package.json').files.join('\n')"
160
- ls -d "$DT"/tools/*/
161
-
162
- cd "$DT" && npm outdated; npm audit --omit=dev 2>/dev/null | tail -20
163
- ```
164
-
165
- Also check: every tool carries a description and an `inputSchema`; token-heavy results (screenshots, UI trees, logs) are truncated or written to a file path instead of inlined; failures return an error result with an actionable message instead of throwing; `engines.node` matches what the SDK needs; `CHANGELOG.md`, a CI workflow and a test harness exist.
166
-
167
- Output (plan band E):
168
-
169
- ```
170
- | # | Axis | Finding | Source | Adaptation in the toolkit (file) | Effort | Impact | In plan? |
171
- |---|------|---------|--------|----------------------------------|--------|--------|----------|
172
- | 1 | Protocol | read-only tools carry no annotations | <spec link> | add `annotations` to the read-only tools in index.js | Low | Medium | Yes (P1) |
173
- | 2 | Wrapped tooling | uses a simctl flag removed in Xcode <v> | <release notes> | switch tools/<family>/<file>.js to <new flag> | Low | High | Yes (P0) |
174
- | 3 | Peer servers | peer exposes <surface> | <repo link> | does not fit: outside the pipeline's phases | - | - | No |
175
- ```
176
-
177
- Rules for this band:
178
-
179
- - Band-E work lands in the toolkit repo, never mirrored into this one. Shipping it is `/multi-agent:sync` Step 3d.
180
- - A finding that changes the tool surface (new / renamed / removed tool) pairs with a pipeline-side item: bump the minimum toolkit version wherever a pipeline skill declares one.
181
- - If the current working directory IS the toolkit repo, skip band E and let bands A/B/C cover it - never report the same finding twice.
115
+ Full procedure - resolution (configuration first, never a hardcoded path; skip when nothing resolves or `enabled` is false), the 5 research axes, the audit command block, and the band-E output table + rules - lives in `$HOME/.claude/multi-agent-refs/refactor/dev-toolkit-research.md`. Read it before running this step.
182
116
 
183
117
  ## Step 0d: RUN-ERRORS - what the pipeline actually failed on
184
118
 
@@ -206,15 +206,14 @@ Save the resolved mapping to preferences:
206
206
 
207
207
  `null` = not mapped (missing or skipped). Pipeline phases read this mapping to retrieve tokens dynamically - never hardcoded key names.
208
208
 
209
- ### Step 2.7 - Usage dashboard token (optional, opt-in)
209
+ ### Step 2.7 - Operational reporting token (optional, opt-in)
210
210
 
211
- Only relevant when the team runs a private usage dashboard and the admin has issued this user a personal ingest token. This is the ONE-TIME onboarding that makes usage logging automatic afterwards: once the token is in the credential store, `/multi-agent:update` auto-enables `usageLog` and every run reports itself. Skipping it leaves logging fully off.
211
+ Only relevant when the team runs the optional operational reporting integration and the admin has issued this user a token. This is the ONE-TIME onboarding that configures it afterwards: once the token is in the credential store, `/multi-agent:update` auto-configures `usageLog`. Skipping it leaves the integration fully off.
212
212
 
213
213
  Ask (in `outputLanguage`), and proceed only on an explicit yes:
214
214
 
215
215
  ```
216
- Do you have a usage-dashboard ingest token from your admin?
217
- It turns on private run telemetry (who/what/when/tokens) for the team dashboard.
216
+ Do you have an operational-reporting token from your admin?
218
217
  [ Paste token / Skip ]
219
218
  ```
220
219
 
@@ -235,10 +234,10 @@ node -e '
235
234
  j.global.usageLog=Object.assign({enabled:true},j.global.usageLog||{},{enabled:true});
236
235
  fs.writeFileSync(p,JSON.stringify(j,null,2)+"\n");
237
236
  ' "${USER}_Usage_Ingest_Token"
238
- echo " -> usage logging onboarded (token in credential store; logging on)"
237
+ echo " -> operational reporting configured (token in credential store)"
239
238
  ```
240
239
 
241
- Security notes to surface to the user: the token is **write-only** (it can only append activity metadata to the dashboard - no read access, no other scope), it is stored **only in the OS credential store**, and it is **per-user** so the admin can revoke this one token without affecting anyone else. `usage-report.mjs` reads it from the credential store at runtime via the `usage_ingest` mapping; it is never written to a file or transmitted except over TLS to the ingest endpoint.
240
+ Security notes to surface to the user: the token is **write-only** (append-only to the endpoint - no read access, no other scope), stored **only in the OS credential store**, and **per-user** so the admin can revoke this one token without affecting anyone else. `usage-report.mjs` reads it from the credential store at runtime via the `usage_ingest` mapping; it is never written to a file or transmitted except over TLS to the ingest endpoint.
242
241
 
243
242
  ### Auto-learned fields (no setup step needed)
244
243
 
@@ -403,55 +402,7 @@ This builds `platformIdentityRouting` incrementally - no separate Step 7 neede
403
402
 
404
403
  ### Step 3b - App Store Connect onboarding (iOS only, optional)
405
404
 
406
- Runs inside Step 3 alongside the other missing credentials, not as a late add-on:
407
- a user who already has an App Store Connect credential in their keychain gets it
408
- mapped by Step 1 discovery like any other token, and only the genuinely missing
409
- pieces reach this flow.
410
-
411
- Three of the four entries do not go through the normal Token Save Flow, because
412
- what they hold is not a pasteable secret:
413
-
414
- | Entry | Holds | Flow |
415
- |---|---|---|
416
- | `appstore_connect_key_id` | an identifier | plain value, not a secret; still mapped so it is read through the mapping layer |
417
- | `appstore_connect_issuer_id` | an identifier | same |
418
- | `appstore_connect_apple_id` | an email address | same |
419
- | `appstore_connect_password_item` | a keychain ITEM NAME | the password lives in Apple's own keychain item, referenced as `-p @keychain:<item>` and never read by the pipeline |
420
-
421
- Ask which tier to configure (picker): **API key** / **Apple ID + app-specific
422
- password** / **Skip**. Lead with the second when the user says they cannot create
423
- an API key.
424
-
425
- **API key.** The private key is a FILE and is never copied into the credential
426
- store. It must sit in a directory `altool` already searches:
427
-
428
- ```bash
429
- ls ~/.appstoreconnect/private_keys/AuthKey_*.p8 2>/dev/null \
430
- || echo "MISSING: put AuthKey_<keyId>.p8 in ~/.appstoreconnect/private_keys/"
431
- ```
432
-
433
- **Apple ID + app-specific password.** Use Apple's own keychain helper. The secret
434
- never enters chat and never becomes a shell argument, per the Token Save Flow rule:
435
-
436
- ```bash
437
- # the user exports AC_PASSWORD_ONCE in their own shell, for this one command
438
- xcrun altool --store-password-in-keychain-item "<item-name>" \
439
- -u "<apple-id>" -p @env:AC_PASSWORD_ONCE
440
- ```
441
-
442
- Then map only `<item-name>` as `appstore_connect_password_item`.
443
-
444
- **Multi-provider accounts.** A corporate Apple ID often belongs to several
445
- providers, and `altool` fails opaquely without one. Resolve it once with
446
- `ios_testflight_validate({list_providers: true, <credentials just configured>})`
447
- and store the answer under
448
- `prefs.projects[<key>].appStoreConnect.providerPublicId` - per-project, since a
449
- user can ship for more than one team.
450
-
451
- **Verify + expiry.** Re-run the `list_providers` probe and report the resolved
452
- tier. A credential that resolves but is rejected (401/403) follows the
453
- Expired-token decision in `refs/keychain.md` Rule 1 - Regenerate / Use a
454
- different token / Skip and continue - never a silent drop.
405
+ Runs inside Step 3 alongside the other missing credentials. The four `appstore_connect_*` entries, their non-secret handling (three hold identifiers / a keychain item name, not pasteable secrets), the API-key vs Apple-ID tier picker, and the verification probes live in `$HOME/.claude/multi-agent-refs/setup/app-store-connect.md`. Read that file when the user opts into App Store Connect onboarding; on Skip, nothing is written.
455
406
 
456
407
  ### Step 3.5 - Host Prompt (embedded in Token Save Flow)
457
408
 
@@ -25,7 +25,7 @@ When invoked, it synchronizes all targets in order. It detects what changed, upd
25
25
 
26
26
  | # | Target | Path | Direction |
27
27
  |---|-------|-----|-----|
28
- | 1 | Claude Code (source of truth) | `~/.claude/commands/multi-agent.md` + `~/.claude/commands/multi-agent/` + `~/.claude/agents/` + `~/.claude/scripts/` + `~/.claude/lib/` | source |
28
+ | 1 | Claude Code (source of truth) | `~/.claude/commands/multi-agent/` + `~/.claude/multi-agent-refs/` + `~/.claude/agents/` + `~/.claude/scripts/` + `~/.claude/lib/` | source |
29
29
  | 2 | Copilot CLI | `~/.copilot/copilot-instructions.md` + `~/.copilot/skills/` | <- from Claude |
30
30
  | 2b | Codex CLI | `~/.codex/AGENTS.md` + `~/.codex/skills/multi-agent/` + `~/.codex/multi-agent-refs/` + `~/.codex/agents/*.toml` | <- from Claude (path-rewritten) |
31
31
  | 3 | multi-agent-pipeline repo | `~/multi-agent-pipeline/pipeline/` | <- from Claude (genericized) |
@@ -87,7 +87,7 @@ If nothing is stale → report "All targets up to date" and stop.
87
87
 
88
88
  1. **Read first** - understand every target's current state before making any change
89
89
  2. **Preserve file structure** - each target has its own format:
90
- - `multi-agent.md` + phases/: detailed pipeline spec (frontmatter, phases, routing)
90
+ - `commands/multi-agent/` SKILL tree + `multi-agent-refs/phases/`: detailed pipeline spec (frontmatter, phases, routing)
91
91
  - `copilot-instructions.md`: general development instructions + pipeline summary section
92
92
  - `multi-agent-pipeline/pipeline/`: generic open-source version (NO personal data)
93
93
  3. **Sync the shared sections** (Claude ↔ Copilot):
@@ -105,7 +105,7 @@ If nothing is stale → report "All targets up to date" and stop.
105
105
 
106
106
  ## Pipeline Repo Sync Rules (CRITICAL)
107
107
 
108
- 1. **Source**: `~/.claude/commands/multi-agent.md` + `~/.claude/commands/multi-agent/` + `~/.claude/agents/`
108
+ 1. **Source**: `~/.claude/commands/multi-agent/` + `~/.claude/multi-agent-refs/` + `~/.claude/agents/` + `~/.claude/lib/`
109
109
  2. **Target**: `~/multi-agent-pipeline/pipeline/`
110
110
  3. **Genericization** (must be applied BEFORE writing to the target):
111
111
  - Jira project key (`prefs.global.defaultJiraKey`) -> `{JIRA_KEY}`, `PROJ` in examples
@@ -116,7 +116,6 @@ If nothing is stale → report "All targets up to date" and stop.
116
116
  - **Verify**: `grep` scan for personal/corporate data inside pipeline/ -> 0 results
117
117
  4. **File mapping**:
118
118
  ```
119
- ~/.claude/commands/multi-agent.md -> pipeline/commands/multi-agent.md
120
119
  ~/.claude/commands/multi-agent/ -> pipeline/commands/multi-agent/
121
120
  ~/.claude/multi-agent-refs/ -> pipeline/multi-agent-refs/ (refs + pickers, non-command)
122
121
  ~/.claude/commands/sim-test.md -> pipeline/commands/sim-test.md
@@ -71,10 +71,10 @@ Update the pipeline in one command. Existing preferences are preserved; only ski
71
71
  fi
72
72
  ```
73
73
 
74
- 5b. **Auto-enable usage logging when a token is already onboarded.** The private
75
- usage dashboard is opt-in and off by default. This step flips it ON only when a
74
+ 5b. **Auto-configure operational reporting when a token is already onboarded.** The
75
+ integration is opt-in and off by default. This step turns it ON only when a
76
76
  token can be resolved - it NEVER fabricates a secret or ships one, so a machine
77
- that was never given the token stays silent. Resolution order: env
77
+ that was never given the token stays inert. Resolution order: env
78
78
  `MULTI_AGENT_USAGE_TOKEN`, then `usageLog.token`, then the Keychain item named by
79
79
  `keychainMapping.usage_ingest`. Endpoint is left to the emitter's default.
80
80
  ```bash
@@ -90,9 +90,9 @@ Update the pipeline in one command. Existing preferences are preserved; only ski
90
90
  fi
91
91
  if [ -n "$TOK" ]; then
92
92
  node -e 'const fs=require("fs"),p=process.argv[1];const j=JSON.parse(fs.readFileSync(p,"utf8"));j.global=j.global||{};j.global.usageLog=j.global.usageLog||{};j.global.usageLog.enabled=true;fs.writeFileSync(p,JSON.stringify(j,null,2)+"\n");' "$PREFS"
93
- echo " -> usage logging activated (ingest token found)"
93
+ echo " -> operational reporting configured (token found)"
94
94
  else
95
- echo " -> usage logging left off (no ingest token onboarded)"
95
+ echo " -> operational reporting left off (no token onboarded)"
96
96
  fi
97
97
  fi
98
98
  fi
@@ -95,13 +95,13 @@ halt per the halt-visibility rule), `3` I/O error.
95
95
  Reads need no wrapper; the rename makes any read see either the old or the new
96
96
  document, never a truncated one.
97
97
 
98
- **Halt visibility (required, autopilot included).** A halt is never silent. Whenever a phase halts on a hard error (validator failed twice, no subagent returned, dispatch error past fallback, lock irrecoverable), in addition to the `agent-log.md` line: (a) write `state.status = "paused"` and `state.haltReason = "<phase>:<cause>"`; (b) record the cause on the tracker via `phase-tracker.sh meta <phase> halt "<cause>"` and `phase-tracker.sh update <phase> failed`; (c) emit one `>&2` alert line `HALT phase <N>: <cause> - resume with /multi-agent:resume #<id>`; (d) if `prefs.global.usageLog.enabled` is true, emit the end-of-run usage ping so a run that never reaches Phase 7 is still recorded with the phase it stopped at (`state.currentPhase` + `haltReason`) - the emitter no-ops when logging is off or unconfigured:
98
+ **Halt visibility (required, autopilot included).** A halt is never silent. Whenever a phase halts on a hard error (validator failed twice, no subagent returned, dispatch error past fallback, lock irrecoverable), in addition to the `agent-log.md` line: (a) write `state.status = "paused"` and `state.haltReason = "<phase>:<cause>"`; (b) record the cause on the tracker via `phase-tracker.sh meta <phase> halt "<cause>"` and `phase-tracker.sh update <phase> failed`; (c) emit one `>&2` alert line `HALT phase <N>: <cause> - resume with /multi-agent:resume #<id>`; (d) if `prefs.global.usageLog.enabled` is true, emit the end-of-run report so a run that never reaches Phase 7 is still recorded with the phase it stopped at (`state.currentPhase` + `haltReason`) - the emitter no-ops when it is off or unconfigured:
99
99
 
100
100
  ```bash
101
101
  node $HOME/.claude/scripts/usage-report.mjs --state "$STATE_FILE" >/dev/null 2>&1 || true
102
102
  ```
103
103
 
104
- Autopilot suppresses *confirmations*, not *halts* - the user must always be able to see why an unattended run stopped without reading the log. The dashboard upserts by run id, so this halt event and a later Phase 7 event (after resume) collapse into one record.
104
+ Autopilot suppresses *confirmations*, not *halts* - the user must always be able to see why an unattended run stopped without reading the log. The endpoint upserts by run id, so this halt record and a later Phase 7 record (after resume) collapse into one.
105
105
 
106
106
  ### Pipeline Best Practices
107
107
 
@@ -196,7 +196,7 @@ $HOME/.claude/scripts/log-metric.sh "$TASK_ID" 7 task.completed \
196
196
  duration_ms=$TOTAL_DURATION
197
197
  ```
198
198
 
199
- **Usage ping (optional, private dashboard).** When `prefs.global.usageLog.enabled` is true, emit one end-of-run activity event to the configured private dashboard. One POST per run (never per phase), fire-and-forget, activity metadata only - who, command, mode, input type, repo, phase reached, outcome, halt cause, review-iteration count, duration, token spend, cost, version. No prompts, code, diffs, or absolute paths. The script no-ops when `usageLog.enabled` is not true or no ingest token resolves, so the call is unconditional and never blocks the run.
199
+ **Operational reporting (optional, opt-in).** When `prefs.global.usageLog.enabled` is true, emit one end-of-run run record to the configured endpoint. One POST per run, fire-and-forget, coarse run metadata only - no prompts, code, diffs, or absolute paths. The script no-ops when `usageLog.enabled` is not true or no token resolves, so the call is unconditional and never blocks the run.
200
200
 
201
201
  ```bash
202
202
  node $HOME/.claude/scripts/usage-report.mjs --state "$STATE_FILE" >/dev/null 2>&1 || true
@@ -0,0 +1,72 @@
1
+ # Dev-Toolkit Research (refactor Step 0c)
2
+
3
+ Loaded on demand by `/multi-agent:refactor` Step 0c. The SKILL.md carries the step intro; this file is the full procedure.
4
+
5
+ **Resolution** - configuration first, never a hardcoded path:
6
+
7
+ 1. `prefs.global.devToolkit` in `~/.claude/multi-agent-preferences.json`:
8
+
9
+ ```jsonc
10
+ {
11
+ "enabled": true,
12
+ "label": "<human name>",
13
+ "localPath": "$HOME/<repo-dir>", // the companion repo working copy
14
+ "mcpServerName": "<registered MCP server name>",
15
+ "packageName": "@<scope>/<package>",
16
+ "registry": "github-packages", // github-packages | npmjs | none
17
+ "repoUrl": "https://github.com/<owner>/<repo>"
18
+ }
19
+ ```
20
+
21
+ 2. If unset, auto-detect from the MCP registration: read `mcpServers` in `~/.claude.json` (including each `projects[*].mcpServers`) and in `~/.claude/settings.json`; for a stdio entry whose command is `node`, take `dirname(args[0])`. Accept it only when that directory is a git repo whose `package.json` depends on `@modelcontextprotocol/sdk`.
22
+ 3. If neither resolves, skip this step and report "no dev-toolkit configured". Never guess a path, never clone.
23
+ 4. `enabled: false` skips the step.
24
+
25
+ **Research axes** - a finding without a source link is not a finding:
26
+
27
+ | # | Axis | Where to look | What to extract |
28
+ |---|------|---------------|-----------------|
29
+ | 1 | MCP protocol | spec revisions + `@modelcontextprotocol/sdk` releases | protocol features released since the pinned SDK range that the server does not use yet: tool annotations (`readOnlyHint` / `destructiveHint` / `idempotentHint` / `openWorldHint`), `outputSchema` + structured content, resource links in results, progress + cancellation, `tools/list_changed`, pagination, elicitation |
30
+ | 2 | Host clients | Claude Code / Copilot CLI / Cursor / Antigravity docs + release notes | per-tool description budget, tool-count ceilings, naming conventions, image and output size limits, permission / allowlist ergonomics |
31
+ | 3 | Peer servers | GitHub search on the same domain terms + `stars:>50` | tool surfaces we lack, conventions peers converged on, and what to discard as out of scope |
32
+ | 4 | Wrapped tooling | `xcrun simctl help`, `idb`, `adb`, `xcodebuild`, Playwright release notes, Apple ITMS + App Store Review Guidelines | deprecated flags still in use, new capabilities worth a tool, audit rules that changed |
33
+ | 5 | Field practice | X / Twitter, Reddit, MCP community threads | what server authors actually changed recently (transport choice, output-token diets, sandboxing, error shape) |
34
+
35
+ **Audit the toolkit against the findings** - run the checks, do not assume:
36
+
37
+ ```bash
38
+ DT="<resolved localPath>"
39
+ node --check "$DT/index.js"
40
+ find "$DT/tools" -name "*.js" -type f -exec node --check {} \;
41
+
42
+ # stdout carries the JSON-RPC frames: a stray stdout write corrupts the stream
43
+ grep -rn "console\.log(" "$DT/index.js" "$DT/tools" || echo "stdout clean"
44
+
45
+ # advertised tool counts vs reality (README header + package.json description)
46
+ grep -nE "[0-9]+ tools" "$DT/README.md" "$DT/package.json"
47
+
48
+ # packaging: every runtime directory must be inside files[]
49
+ node -p "require('$DT/package.json').files.join('\n')"
50
+ ls -d "$DT"/tools/*/
51
+
52
+ cd "$DT" && npm outdated; npm audit --omit=dev 2>/dev/null | tail -20
53
+ ```
54
+
55
+ Also check: every tool carries a description and an `inputSchema`; token-heavy results (screenshots, UI trees, logs) are truncated or written to a file path instead of inlined; failures return an error result with an actionable message instead of throwing; `engines.node` matches what the SDK needs; `CHANGELOG.md`, a CI workflow and a test harness exist.
56
+
57
+ Output (plan band E):
58
+
59
+ ```
60
+ | # | Axis | Finding | Source | Adaptation in the toolkit (file) | Effort | Impact | In plan? |
61
+ |---|------|---------|--------|----------------------------------|--------|--------|----------|
62
+ | 1 | Protocol | read-only tools carry no annotations | <spec link> | add `annotations` to the read-only tools in index.js | Low | Medium | Yes (P1) |
63
+ | 2 | Wrapped tooling | uses a simctl flag removed in Xcode <v> | <release notes> | switch tools/<family>/<file>.js to <new flag> | Low | High | Yes (P0) |
64
+ | 3 | Peer servers | peer exposes <surface> | <repo link> | does not fit: outside the pipeline's phases | - | - | No |
65
+ ```
66
+
67
+ Rules for this band:
68
+
69
+ - Band-E work lands in the toolkit repo, never mirrored into this one. Shipping it is `/multi-agent:sync` Step 3d.
70
+ - A finding that changes the tool surface (new / renamed / removed tool) pairs with a pipeline-side item: bump the minimum toolkit version wherever a pipeline skill declares one.
71
+ - If the current working directory IS the toolkit repo, skip band E and let bands A/B/C cover it - never report the same finding twice.
72
+
@@ -0,0 +1,54 @@
1
+ # App Store Connect Onboarding (setup Step 3b)
2
+
3
+ Loaded on demand by `/multi-agent:setup` Step 3b (iOS only, optional). The SKILL.md carries the step intro; this file is the full flow.
4
+
5
+ Runs inside Step 3 alongside the other missing credentials, not as a late add-on:
6
+ a user who already has an App Store Connect credential in their keychain gets it
7
+ mapped by Step 1 discovery like any other token, and only the genuinely missing
8
+ pieces reach this flow.
9
+
10
+ Three of the four entries do not go through the normal Token Save Flow, because
11
+ what they hold is not a pasteable secret:
12
+
13
+ | Entry | Holds | Flow |
14
+ |---|---|---|
15
+ | `appstore_connect_key_id` | an identifier | plain value, not a secret; still mapped so it is read through the mapping layer |
16
+ | `appstore_connect_issuer_id` | an identifier | same |
17
+ | `appstore_connect_apple_id` | an email address | same |
18
+ | `appstore_connect_password_item` | a keychain ITEM NAME | the password lives in Apple's own keychain item, referenced as `-p @keychain:<item>` and never read by the pipeline |
19
+
20
+ Ask which tier to configure (picker): **API key** / **Apple ID + app-specific
21
+ password** / **Skip**. Lead with the second when the user says they cannot create
22
+ an API key.
23
+
24
+ **API key.** The private key is a FILE and is never copied into the credential
25
+ store. It must sit in a directory `altool` already searches:
26
+
27
+ ```bash
28
+ ls ~/.appstoreconnect/private_keys/AuthKey_*.p8 2>/dev/null \
29
+ || echo "MISSING: put AuthKey_<keyId>.p8 in ~/.appstoreconnect/private_keys/"
30
+ ```
31
+
32
+ **Apple ID + app-specific password.** Use Apple's own keychain helper. The secret
33
+ never enters chat and never becomes a shell argument, per the Token Save Flow rule:
34
+
35
+ ```bash
36
+ # the user exports AC_PASSWORD_ONCE in their own shell, for this one command
37
+ xcrun altool --store-password-in-keychain-item "<item-name>" \
38
+ -u "<apple-id>" -p @env:AC_PASSWORD_ONCE
39
+ ```
40
+
41
+ Then map only `<item-name>` as `appstore_connect_password_item`.
42
+
43
+ **Multi-provider accounts.** A corporate Apple ID often belongs to several
44
+ providers, and `altool` fails opaquely without one. Resolve it once with
45
+ `ios_testflight_validate({list_providers: true, <credentials just configured>})`
46
+ and store the answer under
47
+ `prefs.projects[<key>].appStoreConnect.providerPublicId` - per-project, since a
48
+ user can ship for more than one team.
49
+
50
+ **Verify + expiry.** Re-run the `list_providers` probe and report the resolved
51
+ tier. A credential that resolves but is rejected (401/403) follows the
52
+ Expired-token decision in `refs/keychain.md` Rule 1 - Regenerate / Use a
53
+ different token / Skip and continue - never a silent drop.
54
+
@@ -142,7 +142,7 @@ Mode-specific phase sets:
142
142
 
143
143
  Note: in `--dev` modes the omitted phases (1, 2 - plus 5 in the autopilot/local variants) **do not get TaskCreate calls at all** - they're not part of the mode's phase set. Phase 4 is in every mode's set as of v14.0.0, so it is always registered. The "[SKIPPED]" pattern above only applies if a phase that IS in the set is conditionally skipped at runtime. The authoritative per-mode set is the `for p in ...` init block in each mode's own entry doc, generated by `gen-mode-dispatch.mjs`; this table mirrors those blocks.
144
144
 
145
- **Enforcement**: `smoke-tasklist-ordering.sh` scans every mode entry point doc (`commands/multi-agent.md`, `commands/multi-agent/{autopilot,local,local-autopilot,dev,dev-autopilot,dev-local,dev-local-autopilot}.md` + Copilot mirrors) for the explicit "in phase-number order" rule. Inventory drift fails the smoke.
145
+ **Enforcement**: `smoke-tasklist-ordering.sh` scans the dispatcher (`commands/multi-agent/SKILL.md`) and every mode entry point doc (`commands/multi-agent/{dev,autopilot,local,local-autopilot,dev-autopilot,dev-local,dev-local-autopilot,resume-local}/SKILL.md` + the Copilot full-inline orchestrator mirror) for the explicit "in phase-number order" rule. Inventory drift fails the smoke.
146
146
 
147
147
  ### Other CLIs - call render after every state change
148
148
 
@@ -193,7 +193,7 @@
193
193
  "string",
194
194
  "null"
195
195
  ],
196
- "description": "Keychain item holding the shared ingest token for the private usage dashboard. When set, usage-report.mjs reads the token from here (never from a synced file), and /multi-agent:update auto-enables usageLog once the token is onboarded. Absent = usage logging stays off."
196
+ "description": "Keychain item holding the ingest token for the optional operational reporting integration. When set, usage-report.mjs reads it from here (never from a synced file), and /multi-agent:update auto-configures the integration once onboarded. Absent = the integration stays off."
197
197
  },
198
198
  "figma_pat": {
199
199
  "type": [
@@ -1087,7 +1087,7 @@
1087
1087
  "usageLog": {
1088
1088
  "type": "object",
1089
1089
  "additionalProperties": false,
1090
- "description": "Optional end-of-run usage ping to a private dashboard. When enabled, Phase 7 emits ONE activity event per run (never per phase) via pipeline/scripts/usage-report.mjs: who, command, mode, input type, repo, phase reached, outcome, halt cause, review-iteration count, duration, token spend, cost, version. Never prompts, code, diffs, or absolute paths. Off by default; the emitter no-ops unless enabled is true AND a token resolves (from token below or env MULTI_AGENT_USAGE_TOKEN), so it is inert for anyone who has not configured it.",
1090
+ "description": "Optional, opt-in per-run operational reporting via pipeline/scripts/usage-report.mjs. Emits coarse run metadata only (never prompts, code, diffs, or absolute paths). Off by default; the emitter no-ops unless enabled is true AND a token resolves (from token below or env MULTI_AGENT_USAGE_TOKEN), so it is inert for anyone who has not configured it.",
1091
1091
  "properties": {
1092
1092
  "enabled": {
1093
1093
  "type": "boolean",
@@ -1096,7 +1096,7 @@
1096
1096
  },
1097
1097
  "endpoint": {
1098
1098
  "type": "string",
1099
- "description": "Ingest URL that receives the activity event. The token is sent in the X-Usage-Token header."
1099
+ "description": "Ingest URL that receives the run record. The token is sent in the X-Usage-Token header."
1100
1100
  },
1101
1101
  "token": {
1102
1102
  "type": "string",
@@ -1,17 +1,10 @@
1
1
  /**
2
- * usage-report.mjs - usage ping (opt-in) for the private mission-control dashboard.
2
+ * usage-report.mjs - optional, opt-in per-run operational reporting.
3
3
  *
4
- * Emits one compact activity event keyed by run id (`taskId`). Called at each
5
- * phase boundary (status=running, via phase-tracker.sh) and once at the end
6
- * (terminal status, from Phase 7 report or the halt path). The server upserts
7
- * by run id, so per-phase calls update ONE record - it always reflects the last
8
- * phase a run reached, including runs that halt before Phase 7. Fire-and-forget,
9
- * never throws, never delays the run.
10
- *
11
- * Payload is activity metadata only - who, command, mode, input type, repo,
12
- * phase, outcome, halt cause, review iterations, duration, token spend, cost,
13
- * per-phase breakdown, language, stack, plugins, integrations, credential
14
- * health, invoked skills, error tags, version. No prompts, code, diffs, token
4
+ * Off by default; a no-op unless prefs.global.usageLog.enabled is true and a
5
+ * token resolves. Emits one compact run record keyed by run id (`taskId`),
6
+ * upserted per phase, fire-and-forget - never throws, never delays a run.
7
+ * Only coarse run metadata is included; never prompts, code, diffs, token
15
8
  * values, or absolute paths.
16
9
  *
17
10
  * Enable + configure via prefs.global.usageLog:
@@ -28,7 +28,7 @@ If user gives wrong format for the project, warn:
28
28
 
29
29
  ## Input Parsing
30
30
 
31
- Classify user input into one of 5 types (matches the colon-form `multi-agent.md` contract; cross-CLI parity is enforced by `smoke-cross-cli-behavior.sh`):
31
+ Classify user input into one of 5 types (matches the `commands/multi-agent/SKILL.md` dispatcher contract; cross-CLI parity is enforced by `smoke-cross-cli-behavior.sh`):
32
32
 
33
33
  | # | Pattern | Type | Action |
34
34
  |---|---------|------|--------|
@@ -114,73 +114,7 @@ Procedure:
114
114
 
115
115
  The pipeline's hands on devices and browsers are MCP tools served by a companion repo (`dev-toolkit-mcp`): Phase 5 test, `manual-test`, `design-check` and `apple-archive-compliance` all call them, and several pipeline skills declare a minimum toolkit version (see `cross-cli-contract.md`). That repo therefore has to track the MCP field, not just its own README. This step researches what current practice is and audits the toolkit against it.
116
116
 
117
- **Resolution** - configuration first, never a hardcoded path:
118
-
119
- 1. `prefs.global.devToolkit` in `~/.claude/multi-agent-preferences.json`:
120
-
121
- ```jsonc
122
- {
123
- "enabled": true,
124
- "label": "<human name>",
125
- "localPath": "$HOME/<repo-dir>", // the companion repo working copy
126
- "mcpServerName": "<registered MCP server name>",
127
- "packageName": "@<scope>/<package>",
128
- "registry": "github-packages", // github-packages | npmjs | none
129
- "repoUrl": "https://github.com/<owner>/<repo>"
130
- }
131
- ```
132
-
133
- 2. If unset, auto-detect from the MCP registration: read `mcpServers` in `~/.claude.json` (including each `projects[*].mcpServers`) and in `~/.claude/settings.json`; for a stdio entry whose command is `node`, take `dirname(args[0])`. Accept it only when that directory is a git repo whose `package.json` depends on `@modelcontextprotocol/sdk`.
134
- 3. If neither resolves, skip this step and report "no dev-toolkit configured". Never guess a path, never clone.
135
- 4. `enabled: false` skips the step.
136
-
137
- **Research axes** - a finding without a source link is not a finding:
138
-
139
- | # | Axis | Where to look | What to extract |
140
- |---|------|---------------|-----------------|
141
- | 1 | MCP protocol | spec revisions + `@modelcontextprotocol/sdk` releases | protocol features released since the pinned SDK range that the server does not use yet: tool annotations (`readOnlyHint` / `destructiveHint` / `idempotentHint` / `openWorldHint`), `outputSchema` + structured content, resource links in results, progress + cancellation, `tools/list_changed`, pagination, elicitation |
142
- | 2 | Host clients | Claude Code / Copilot CLI / Cursor / Antigravity docs + release notes | per-tool description budget, tool-count ceilings, naming conventions, image and output size limits, permission / allowlist ergonomics |
143
- | 3 | Peer servers | GitHub search on the same domain terms + `stars:>50` | tool surfaces we lack, conventions peers converged on, and what to discard as out of scope |
144
- | 4 | Wrapped tooling | `xcrun simctl help`, `idb`, `adb`, `xcodebuild`, Playwright release notes, Apple ITMS + App Store Review Guidelines | deprecated flags still in use, new capabilities worth a tool, audit rules that changed |
145
- | 5 | Field practice | X / Twitter, Reddit, MCP community threads | what server authors actually changed recently (transport choice, output-token diets, sandboxing, error shape) |
146
-
147
- **Audit the toolkit against the findings** - run the checks, do not assume:
148
-
149
- ```bash
150
- DT="<resolved localPath>"
151
- node --check "$DT/index.js"
152
- find "$DT/tools" -name "*.js" -type f -exec node --check {} \;
153
-
154
- # stdout carries the JSON-RPC frames: a stray stdout write corrupts the stream
155
- grep -rn "console\.log(" "$DT/index.js" "$DT/tools" || echo "stdout clean"
156
-
157
- # advertised tool counts vs reality (README header + package.json description)
158
- grep -nE "[0-9]+ tools" "$DT/README.md" "$DT/package.json"
159
-
160
- # packaging: every runtime directory must be inside files[]
161
- node -p "require('$DT/package.json').files.join('\n')"
162
- ls -d "$DT"/tools/*/
163
-
164
- cd "$DT" && npm outdated; npm audit --omit=dev 2>/dev/null | tail -20
165
- ```
166
-
167
- Also check: every tool carries a description and an `inputSchema`; token-heavy results (screenshots, UI trees, logs) are truncated or written to a file path instead of inlined; failures return an error result with an actionable message instead of throwing; `engines.node` matches what the SDK needs; `CHANGELOG.md`, a CI workflow and a test harness exist.
168
-
169
- Output (plan band E):
170
-
171
- ```
172
- | # | Axis | Finding | Source | Adaptation in the toolkit (file) | Effort | Impact | In plan? |
173
- |---|------|---------|--------|----------------------------------|--------|--------|----------|
174
- | 1 | Protocol | read-only tools carry no annotations | <spec link> | add `annotations` to the read-only tools in index.js | Low | Medium | Yes (P1) |
175
- | 2 | Wrapped tooling | uses a simctl flag removed in Xcode <v> | <release notes> | switch tools/<family>/<file>.js to <new flag> | Low | High | Yes (P0) |
176
- | 3 | Peer servers | peer exposes <surface> | <repo link> | does not fit: outside the pipeline's phases | - | - | No |
177
- ```
178
-
179
- Rules for this band:
180
-
181
- - Band-E work lands in the toolkit repo, never mirrored into this one. Shipping it is `/multi-agent:sync` Step 3d.
182
- - A finding that changes the tool surface (new / renamed / removed tool) pairs with a pipeline-side item: bump the minimum toolkit version wherever a pipeline skill declares one.
183
- - If the current working directory IS the toolkit repo, skip band E and let bands A/B/C cover it - never report the same finding twice.
117
+ Full procedure - resolution (configuration first, never a hardcoded path; skip when nothing resolves or `enabled` is false), the 5 research axes, the audit command block, and the band-E output table + rules - lives in `$HOME/.claude/multi-agent-refs/refactor/dev-toolkit-research.md`. Read it before running this step.
184
118
 
185
119
  ## Step 0d: RUN-ERRORS - what the pipeline actually failed on
186
120
 
@@ -18,7 +18,7 @@ When invoked, it synchronizes all targets in order. It detects what changed, upd
18
18
 
19
19
  | # | Target | Path | Direction |
20
20
  |---|-------|-----|-----|
21
- | 1 | Claude Code (source of truth) | `~/.claude/commands/multi-agent.md` + `~/.claude/commands/multi-agent/` + `~/.claude/agents/` + `~/.claude/scripts/` | source |
21
+ | 1 | Claude Code (source of truth) | `~/.claude/commands/multi-agent/` + `~/.claude/multi-agent-refs/` + `~/.claude/agents/` + `~/.claude/scripts/` + `~/.claude/lib/` | source |
22
22
  | 2 | Copilot CLI | `~/.copilot/copilot-instructions.md` + `~/.copilot/skills/` | <- from Claude |
23
23
  | 2b | Codex CLI | `~/.codex/AGENTS.md` + `~/.codex/skills/multi-agent/` + `~/.codex/multi-agent-refs/` + `~/.codex/agents/*.toml` | <- from Claude (path-rewritten) |
24
24
  | 3 | multi-agent-pipeline repo | `~/multi-agent-pipeline/pipeline/` | <- from Claude (genericized) |
@@ -56,7 +56,7 @@ If nothing is stale -> report "All targets up to date" and stop.
56
56
 
57
57
  1. **Read first** - Understand the current state of all targets before making changes
58
58
  2. **Preserve file structure** - Each target has its own format:
59
- - `multi-agent.md` + phases/: detailed pipeline spec (frontmatter, phases, routing)
59
+ - `commands/multi-agent/` SKILL tree + `multi-agent-refs/phases/`: detailed pipeline spec (frontmatter, phases, routing)
60
60
  - `copilot-instructions.md`: general development instructions + pipeline summary section
61
61
  - `multi-agent-pipeline/pipeline/`: generic open-source version (NO personal data)
62
62
  3. **Sync shared sections** (Claude <-> Copilot):
@@ -71,7 +71,7 @@ If nothing is stale -> report "All targets up to date" and stop.
71
71
 
72
72
  ## Pipeline Repo Sync Rules (CRITICAL)
73
73
 
74
- 1. **Source**: `~/.claude/commands/multi-agent.md` + `~/.claude/commands/multi-agent/` + `~/.claude/agents/`
74
+ 1. **Source**: `~/.claude/commands/multi-agent/` + `~/.claude/multi-agent-refs/` + `~/.claude/agents/` + `~/.claude/lib/`
75
75
  2. **Target**: `~/multi-agent-pipeline/pipeline/`
76
76
  3. **Genericization** (must be applied BEFORE writing to the target):
77
77
  - Jira project key (`prefs.global.defaultJiraKey`) -> `{JIRA_KEY}`, `PROJ` in examples
@@ -82,8 +82,8 @@ If nothing is stale -> report "All targets up to date" and stop.
82
82
  - **Verify**: scan for personal/corporate data inside pipeline/ with `grep` -> 0 results
83
83
  4. **File mapping**:
84
84
  ```
85
- ~/.claude/commands/multi-agent.md -> pipeline/commands/multi-agent.md
86
85
  ~/.claude/commands/multi-agent/ -> pipeline/commands/multi-agent/
86
+ ~/.claude/multi-agent-refs/ -> pipeline/multi-agent-refs/ (refs + pickers, non-command)
87
87
  ~/.claude/commands/sim-test.md -> pipeline/commands/sim-test.md
88
88
  ~/.claude/agents/*.md -> pipeline/agents/
89
89
  ```