@mmerterden/multi-agent-pipeline 12.11.0 → 13.1.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.
Files changed (47) hide show
  1. package/CHANGELOG.md +179 -0
  2. package/README.md +24 -7
  3. package/index.js +5 -2
  4. package/install/_codex-agents.mjs +211 -0
  5. package/install/_codex-instructions.mjs +33 -0
  6. package/install/_managed-block.mjs +99 -0
  7. package/install/codex.mjs +478 -0
  8. package/install/copilot.mjs +34 -80
  9. package/install/index.mjs +25 -9
  10. package/install/templates/codex-instructions.md +45 -0
  11. package/package.json +5 -3
  12. package/pipeline/claude-md-template.md +1 -0
  13. package/pipeline/commands/multi-agent/SKILL.md +1 -1
  14. package/pipeline/commands/multi-agent/dev/SKILL.md +52 -6
  15. package/pipeline/commands/multi-agent/dev-local/SKILL.md +21 -0
  16. package/pipeline/commands/multi-agent/finish/SKILL.md +1 -1
  17. package/pipeline/commands/multi-agent/language/SKILL.md +2 -2
  18. package/pipeline/commands/multi-agent/setup/SKILL.md +69 -2
  19. package/pipeline/commands/multi-agent/sync/SKILL.md +128 -5
  20. package/pipeline/commands/multi-agent/testflight-validation/SKILL.md +219 -0
  21. package/pipeline/commands/multi-agent/update/SKILL.md +7 -4
  22. package/pipeline/multi-agent-refs/_input-parser.md +1 -1
  23. package/pipeline/multi-agent-refs/component-dispatch.md +40 -7
  24. package/pipeline/multi-agent-refs/cross-cli-contract.md +51 -17
  25. package/pipeline/multi-agent-refs/features/model-fallback.md +29 -0
  26. package/pipeline/multi-agent-refs/features/review-multi-repo.md +1 -1
  27. package/pipeline/multi-agent-refs/phases/log-format.md +1 -1
  28. package/pipeline/multi-agent-refs/phases/phase-0-init.md +43 -2
  29. package/pipeline/multi-agent-refs/phases/phase-1-analysis.md +24 -1
  30. package/pipeline/multi-agent-refs/phases/phase-3-dev.md +32 -0
  31. package/pipeline/multi-agent-refs/phases/phase-4-review.md +62 -5
  32. package/pipeline/multi-agent-refs/progress-contract.md +1 -1
  33. package/pipeline/multi-agent-refs/tracker-contract.md +17 -1
  34. package/pipeline/schemas/prefs.schema.json +296 -62
  35. package/pipeline/schemas/reviewer-output.schema.json +1 -1
  36. package/pipeline/schemas/triage-output.schema.json +1 -1
  37. package/pipeline/scripts/cost-table.json +15 -1
  38. package/pipeline/scripts/phase0-exit-gate.mjs +185 -0
  39. package/pipeline/scripts/smoke-cross-cli-behavior.sh +25 -10
  40. package/pipeline/scripts/uninstall.mjs +105 -9
  41. package/pipeline/scripts/update-check.sh +2 -1
  42. package/pipeline/skills/shared/core/multi-agent-dev/SKILL.md +21 -0
  43. package/pipeline/skills/shared/core/multi-agent-dev-local/SKILL.md +21 -0
  44. package/pipeline/skills/shared/core/multi-agent-language/SKILL.md +2 -2
  45. package/pipeline/skills/shared/core/multi-agent-setup/SKILL.md +48 -1
  46. package/pipeline/skills/shared/core/multi-agent-sync/SKILL.md +87 -6
  47. package/pipeline/skills/shared/core/multi-agent-testflight-validation/SKILL.md +120 -0
@@ -20,6 +20,7 @@ When invoked, it synchronizes all targets in order. It detects what changed, upd
20
20
  |---|-------|-----|-----|
21
21
  | 1 | Claude Code (source of truth) | `~/.claude/commands/multi-agent.md` + `~/.claude/commands/multi-agent/` + `~/.claude/agents/` + `~/.claude/scripts/` | source |
22
22
  | 2 | Copilot CLI | `~/.copilot/copilot-instructions.md` + `~/.copilot/skills/` | <- from Claude |
23
+ | 2b | Codex CLI | `~/.codex/AGENTS.md` + `~/.codex/skills/multi-agent/` + `~/.codex/multi-agent-refs/` + `~/.codex/agents/*.toml` | <- from Claude (path-rewritten) |
23
24
  | 3 | multi-agent-pipeline repo | `~/multi-agent-pipeline/pipeline/` | <- from Claude (genericized) |
24
25
  | 4 | Website | `{owner}/{website-host}` | <- version + features |
25
26
  | 5 | dev-toolkit MCP server | resolved from `prefs.global.devToolkit` or the `mcpServers` registration | own repo: gate, commit, publish |
@@ -30,7 +31,8 @@ Run all steps automatically:
30
31
 
31
32
  ```
32
33
  Step 1: DETECT Compare timestamps, find stale targets
33
- Step 2: COPILOT Claude Code -> Copilot CLI (instructions + 42 sub-command skills)
34
+ Step 2: COPILOT Claude Code -> Copilot CLI (instructions + 43 sub-command skills)
35
+ Step 2b: CODEX Claude Code -> Codex CLI (1 router skill + 43 specs as refs + 8 agent TOML)
34
36
  Step 3: REPO Claude Code -> pipeline repo (genericized, personal data scrub)
35
37
  Step 3d: DEV-TOOLKIT Companion MCP server -> detect movement, ship gates, commit + publish
36
38
  Step 4: WEBSITE Version + phase/model counts -> {website-host} (i18n + projects.ts)
@@ -93,6 +95,41 @@ If nothing is stale -> report "All targets up to date" and stop.
93
95
  - `~/.claude/settings.json`
94
96
 
95
97
 
98
+ ## Codex Sync (Step 2b)
99
+
100
+ This step does **not** hand-copy files. The Codex tree is a *transform* of the Claude
101
+ tree, not a mirror: the 43 sub-command specs become reference files (Codex silently
102
+ truncates its skills block - see `cross-cli-contract.md` 2.6), every reference to a
103
+ CLI-owned tree is retargeted (`agents/<persona>.md` becomes `.toml`, the dispatcher
104
+ becomes the router skill), the 8 personas are regenerated as TOML with a model +
105
+ reasoning-effort map, and shared state (`logs/`, prefs, `knowledge/`) is deliberately
106
+ left under `~/.claude`.
107
+
108
+ That transform lives in `install/codex.mjs` and is gate-locked by
109
+ `smoke-codex-install.sh`. Describing it again in prose would give the pipeline two
110
+ definitions of the same thing, and the prose one would rot. So the step runs the
111
+ installer:
112
+
113
+ ```bash
114
+ cd "$HOME/multi-agent-pipeline" && node install.js --codex
115
+ ```
116
+
117
+ Verify:
118
+
119
+ ```bash
120
+ ls -1 "$HOME/.codex/skills" | grep -c '^multi-agent$' # want 1
121
+ find "$HOME/.codex/multi-agent-refs/commands" -name SKILL.md | wc -l # want the command count
122
+ grep -rhoE '(\$HOME|~)/\.claude/(agents|scripts|lib|schemas|commands|multi-agent-refs|rules)' \
123
+ "$HOME/.codex/skills" "$HOME/.codex/multi-agent-refs" | sort -u # want empty
124
+ ```
125
+
126
+ MCP is registered by the installer via `codex mcp add dev-toolkit` (idempotent,
127
+ skipped with a warning when `codex` is absent). Never hand-edit
128
+ `~/.codex/config.toml` - Codex owns it. Run this AFTER the REPO step, since the
129
+ installer reads the repo tree.
130
+
131
+ ---
132
+
96
133
  ## Dev-Toolkit Sync (Step 3d)
97
134
 
98
135
  The companion MCP server (`dev-toolkit-mcp`) is its own repo with its own registry. Pipeline skills call its tools and several declare a minimum version, so when it moves it has to ship.
@@ -114,13 +151,19 @@ When the toolkit ships its own gate script (`npm run gates` / `scripts/gates.sh`
114
151
 
115
152
  **Version bump**: patch for fixes and docs, minor for a new tool, major for a removed or renamed tool.
116
153
 
117
- **Ship**: commit with that repo's own convention, tag `v<version>`, push with `--tags`, then publish to the registry from `publishConfig` using a throwaway userconfig - never edit `~/.npmrc`, never a bare `npm publish`. The token depends on the registry: `npm.pkg.github.com` needs a GitHub PAT with `write:packages` (logical key `github`), `registry.npmjs.org` needs the `npm` key.
154
+ **Ship**: commit with that repo's own convention, tag `v<version>`, push with `--tags`, then publish to the registry from `publishConfig` using a throwaway userconfig - never edit `~/.npmrc`, never a bare `npm publish`. The token depends on the registry AND on the package scope: the registry picks the credential type, the scope picks the account. `npm.pkg.github.com` needs a **Classic** GitHub PAT with `write:packages`; `registry.npmjs.org` needs the `npm` key. Resolving on host alone misroutes on any machine with a work and a personal GitHub identity - prefer a scope-specific mapping (`github_<scope>`) and fall back to the generic `github` key only when there is one identity.
118
155
 
119
156
  ```bash
120
157
  NPMRC=$(mktemp); trap 'rm -f "$NPMRC"' EXIT
121
158
  REG=$(node -p "require('./package.json').publishConfig?.registry || 'https://registry.npmjs.org'")
122
159
  HOST=${REG#https://}; HOST=${HOST%/}
123
- case "$HOST" in npm.pkg.github.com*) KEY=github ;; *) KEY=npm ;; esac
160
+ SCOPE=$(node -p "(require('./package.json').name.match(/^@([^/]+)/)||[])[1] || ''")
161
+ case "$HOST" in
162
+ npm.pkg.github.com*) KEY=github; [ -n "$SCOPE" ] && KEY="github_$SCOPE" ;;
163
+ *) KEY=npm ;;
164
+ esac
165
+ # Fall back to the generic key when no scope-specific mapping exists.
166
+ bash "$HOME/.copilot/lib/credential-store.sh" get "$KEY" >/dev/null 2>&1 || KEY=github
124
167
  TOKEN=$(bash "$HOME/.claude/lib/credential-store.sh" get "$KEY")
125
168
  [ -n "$TOKEN" ] || echo "ABORT: no '$KEY' token - onboard it via /multi-agent:setup before publishing"
126
169
  printf '%s\n' "registry=$REG" "//$HOST/:_authToken=$TOKEN" > "$NPMRC"
@@ -167,24 +210,27 @@ When invoked with the `release` argument:
167
210
  7. DEV-TOOLKIT Ship the companion MCP server if it moved (Step 3d gates, then publish)
168
211
  8. WEBSITE Version + features -> {website-host}
169
212
  9. COPILOT Copilot CLI instructions + skills sync
213
+ 9b. CODEX Codex CLI router skill + refs + agent TOML (node install.js --codex)
170
214
  10. Report Summary: version, touched repos, deploy status
171
215
  ```
172
216
 
173
217
 
174
218
  ## Sub-Command Sync (Claude Code <-> Copilot CLI Skills)
175
219
 
220
+ > Codex takes the Step 2b path instead; see that section.
221
+
176
222
  | Claude Code | Copilot CLI |
177
223
  |-------------|-------------|
178
224
  | `~/.claude/commands/multi-agent/{cmd}.md` | `~/.copilot/skills/multi-agent-{cmd}/SKILL.md` |
179
225
 
180
- **42 commands are synced** (canonical inventory - must match `cross-cli-contract.md` section 1; drift = contract violation):
226
+ **43 commands are synced** (canonical inventory - must match `cross-cli-contract.md` section 1; drift = contract violation):
181
227
 
182
228
  ```
183
229
  analysis, analysis-resolve, autopilot, build-optimize, channels, create-jira, design-check, dev,
184
230
  dev-autopilot, dev-local, dev-local-autopilot, diff-explain, finish, forget, garbage-collect,
185
231
  help, issue, jira, kill, language, local,
186
232
  local-autopilot, log, manual-test, prune-logs, purge, refactor, resume, review, review-issue, review-jira,
187
- routines, save, scan, search, setup, stack, status, sync, test, uninstall, update
233
+ routines, save, scan, search, setup, stack, status, sync, test, testflight-validation, uninstall, update
188
234
  ```
189
235
 
190
236
  **NOT synced**: `refs/*` - Lazy-load references, Claude Code specific
@@ -200,8 +246,43 @@ routines, save, scan, search, setup, stack, status, sync, test, uninstall, updat
200
246
  | `gh` CLI (personal) | `{owner}` gh auth (Keychain) |
201
247
  | `gh` CLI (work) | `${USER}_{work-gh-alias}` gh auth (Keychain) |
202
248
  | npm publish | `NODE_AUTH_TOKEN` - `GITHUB_TOKEN` in CI, Keychain PAT locally |
203
- | dev-toolkit publish (Step 3d) | `npm` logical Keychain key -> throwaway `--userconfig`, registry from that repo's `publishConfig` |
249
+ | dev-toolkit publish (Step 3d) | scope-resolved key (`github_<scope>`, else `github`, else `npm`) -> throwaway `--userconfig`, registry from that repo's `publishConfig` |
204
250
 
205
251
  ```bash
206
252
  gh auth switch --user {owner} # for personal repos
207
253
  ```
254
+
255
+
256
+ ## Pre-flight the token scope
257
+
258
+ GitHub reports a token's scopes on any authenticated request, so check before
259
+ uploading instead of reading it out of a 403:
260
+
261
+ ```bash
262
+ curl -sI -H "Authorization: token $TOKEN" https://api.github.com/user \
263
+ | grep -i '^x-oauth-scopes:' | grep -q 'write:packages'
264
+ ```
265
+
266
+ Candidate order for `npm.pkg.github.com`, because storage location and scope are
267
+ not correlated: `github_<scope>` from the mapping, then `gh auth token -u <scope>`
268
+ (gh's own OAuth token often carries `write:packages` when a hand-made PAT does
269
+ not), then the generic `github` key only on a single-identity machine. Take the
270
+ first candidate whose scopes include `write:packages` AND whose login matches the
271
+ package scope. If none qualifies, stop before publishing and report each candidate
272
+ with the login it resolved to and the scope it was missing - that is the
273
+ actionable output, not a 403 body.
274
+
275
+ ## Publish 403s: two causes, two fixes
276
+
277
+ Neither message says "wrong token" plainly, and they need opposite responses:
278
+
279
+ - `Unauthorized: As an Enterprise Managed User, you cannot access this content` -
280
+ the resolved token belongs to a corporate EMU account, which cannot publish to a
281
+ personal scope at all. No scope grant fixes this; map the personal account's PAT
282
+ under `github_<scope>`.
283
+ - `The token provided does not match expected scopes` - right account, missing
284
+ permission. Regenerate as a **Classic** PAT with `write:packages`
285
+ (plus `repo` for a private package) and re-onboard through setup.
286
+
287
+ Always report which of the two occurred. "Permission denied" alone sends the user
288
+ to regenerate a token that was never the problem.
@@ -0,0 +1,120 @@
1
+ ---
2
+ name: multi-agent-testflight-validation
3
+ language: en
4
+ description: "Pre-submission validation for a TestFlight / App Store build (iOS, local-only). Three gates: static archive audit, Apple's own `altool --validate-app`, and a Review-Guidelines check. ITMS codes are mapped to the rule each implies. Validates only, never uploads. Use when a build is about to go to TestFlight, or a submission was rejected and you need why."
5
+ user-invocable: true
6
+ argument-hint: "[repo] - empty = pick from prefs; repo name or path; --ipa=<path>; --archive=<path>; --resume"
7
+ ---
8
+
9
+ # multi-agent-testflight-validation - pre-submission validation
10
+
11
+ Catch, before you upload, what App Store Connect would send back after you do.
12
+
13
+ **Local-only**: no commits, no push, no PR, no channels. **It never uploads** - only
14
+ `--validate-app` is ever invoked, never `--upload-app`.
15
+
16
+ ## Why three gates
17
+
18
+ Each sees something the others structurally cannot, so reporting one as "the check"
19
+ is how a build passes locally and gets rejected anyway.
20
+
21
+ | Gate | Runs | Needs | Sees | Blind to |
22
+ |---|---|---|---|---|
23
+ | **1. Static** | `ios_app_store_audit` (18 rules) | `.xcarchive` | privacy manifest, required-reason API, Info.plist, signing, entitlements, embedded SDK, IPv6, debug leak | anything account-dependent |
24
+ | **2. Authoritative** | `ios_testflight_validate` → `altool --validate-app` | `.ipa` + credentials | unregistered bundle ID, profile/app-record mismatch, **version+build already used**, entitlement not provisioned | the Review Guidelines |
25
+ | **3. Guideline** | `app-store-review` skill + repo evidence | repo checkout | ATT, privacy policy, account deletion, IAP, purpose-string wording | anything not in source |
26
+
27
+ Most "we passed validation and still got rejected" cases are Gate 3 findings:
28
+ Apple's validator does not read the Review Guidelines.
29
+
30
+ ## Flow
31
+
32
+ **0. Input.** `(empty)` → ask · `my-ios-app`/path → that repo · `--ipa=<path>` →
33
+ Mode B without Gate 1 · `--archive=<path>` → Mode B with all gates · `--resume`.
34
+ State at `~/.claude/logs/multi-agent/<task_id>/agent-state.json`,
35
+ `taskId = TFV-<repo>-<yyyymmddHHMM>`. Register phases with
36
+ `bash ~/.copilot/scripts/phase-tracker.sh` and render with
37
+ `phase-tracker.sh render` at every boundary.
38
+
39
+ **1. Pickers.** Repo (iOS entries in `prefs.projects`; a single match auto-resolves,
40
+ and the breadcrumb says so) → branch → mode. Print
41
+ `Step <i>/<n>: <what this decides>` for each. On `git fetch` failure do **not**
42
+ silently use a cached ref, and **classify the failure before naming a cause**:
43
+ `could not read Password` / `Authentication failed` / `403` is a credential
44
+ problem, not a network one, and a VPN cannot fix it; `Could not resolve host` /
45
+ `Operation timed out` is the network. Show the stderr line verbatim next to your
46
+ classification, then offer the remedy that matches it. Only the network case gets
47
+ the continue-on-a-stale-ref option: for a credential failure, staleness is
48
+ unrelated to what broke.
49
+
50
+ **2. Pre-flight.** `xcrun --find altool` and `xcodebuild -version`; a missing
51
+ prerequisite halts. Resolve credentials and name the active tier in the report:
52
+ tier 1 ASC API key (key id + issuer id from the keychain via
53
+ `prefs.global.keychainMapping`, `.p8` at
54
+ `~/.appstoreconnect/private_keys/AuthKey_<keyId>.p8`), tier 2 Apple ID +
55
+ app-specific password by keychain reference, tier 3 none → **Gate 2 is `SKIPPED`
56
+ and the verdict line says so**. Credentials come from `/multi-agent:setup`; never
57
+ prompt for a secret value in chat. Tier 2 needs no elevated App Store Connect
58
+ role, which matters when API-key creation is not permitted on the account.
59
+
60
+ **3. Obtain the build.**
61
+ - Mode B `.xcarchive` → Gate 1 runs; export with `ios_export_ipa` to reach Gate 2.
62
+ - Mode B `.ipa` only → **Gate 1 `SKIPPED (needs .xcarchive)`**. The static audit
63
+ reads archive structure an `.ipa` does not carry. Do not present a two-gate run
64
+ as a full pass.
65
+ - Mode A → worktree at `{projectRoot}/{worktreeBasePath}/{taskId}` (**never under
66
+ `$HOME`**) → `ios_xcodebuild({action: "archive", configuration: "Release",
67
+ destination: "generic/platform=iOS"})` - the simulator default would produce a
68
+ non-distributable archive - then `ios_export_ipa({method:
69
+ "app-store-connect", team_id, ...})`. Leave `allow_provisioning_updates` off
70
+ unless asked: it lets xcodebuild create or modify profiles in the developer
71
+ account, which a validation run has no business doing.
72
+
73
+ **4. Gate 1.** `ios_app_store_audit({archive_path, rules: "all"})`. `error` blocks,
74
+ `warning` advises. Keep each ITMS code - Gate 2 may return the same one, and that
75
+ agreement tells the user it is real.
76
+
77
+ **5. Gate 2.** `ios_testflight_validate({ipa_path, platform: "ios", <creds>})`.
78
+ Render the verdict as returned: `PASS` / `FAIL` (each issue with ITMS code, mapped
79
+ guideline, hint) / `SKIPPED` (with the reason, **never as a pass**). This is the
80
+ only gate that catches an already-used build number - the most common wasted
81
+ upload - so when it fails on that, name the next free build number.
82
+
83
+ **6. Gate 3.** Load `app-store-review` and check, with an evidence path each:
84
+ purpose strings (present, specific, matching actual use) · `PrivacyInfo.xcprivacy`
85
+ (exists, declares required-reason APIs, matches linked SDKs) · ATT before any
86
+ tracking · in-app account deletion when accounts are created · privacy policy
87
+ reachable · IAP through StoreKit with no external purchase path · Sign in with
88
+ Apple alongside third-party social login. Mark `pass` / `fail` /
89
+ `not-applicable`, and `not-applicable` needs a reason - an unexamined area is not
90
+ a pass.
91
+
92
+ **7. Report.** `~/TestFlightChecks/<repo>-<branch>-<timestamp>/report.md` plus a
93
+ printed summary:
94
+
95
+ ```
96
+ Verdict: <N> of 3 gates cleared[, <M> skipped]
97
+ Build: <path> · <bundle id> <version> (<build>)
98
+ Auth: tier <1|2|none> · <method>
99
+
100
+ Gate 1 static audit PASS | FAIL (<n> blocking, <n> advisory) | SKIPPED (<reason>)
101
+ Gate 2 Apple validation PASS | FAIL (<n> issues) | SKIPPED (<reason>)
102
+ Gate 3 guideline review PASS | FAIL (<n> findings) | <n> not-applicable
103
+
104
+ Blocking - fix before uploading
105
+ [ITMS-90683] Info.plist: NSCameraUsageDescription missing
106
+ guideline 5.1.1 Data Collection and Storage
107
+ <hint> · <file:line>
108
+
109
+ Not run
110
+ Gate 1: needs an .xcarchive; only an .ipa was supplied
111
+ ```
112
+
113
+ A skipped gate is never folded into the pass count. Every blocking finding carries
114
+ a file path or an ITMS code. No AI or assistant attribution anywhere; real
115
+ newlines, no HTML entities.
116
+
117
+ **8. Offer, do not act.** Print the exact `xcrun altool --upload-app` command for
118
+ when the gates are clear (uploading stays an explicit human act), plus
119
+ `--resume` after fixes and `/multi-agent:fix-bug` for code-level Gate 3 findings.
120
+ Never upload, never bump the build number, never commit.