@mmerterden/multi-agent-pipeline 20.13.0 → 20.15.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 +61 -0
- package/README.md +8 -6
- package/README.tr.md +7 -5
- package/docs/architecture.md +3 -3
- package/docs/ecosystem.md +5 -5
- package/docs/facts.json +4 -4
- package/install/catalog-history.json +1 -1
- package/manifest.json +156 -96
- package/package.json +1 -1
- package/pipeline/commands/multi-agent/analysis/SKILL.md +11 -80
- package/pipeline/commands/multi-agent/autopilot/SKILL.md +2 -23
- package/pipeline/commands/multi-agent/autopilot-off/SKILL.md +24 -45
- package/pipeline/commands/multi-agent/channels/SKILL.md +11 -63
- package/pipeline/commands/multi-agent/design-check/SKILL.md +43 -178
- package/pipeline/commands/multi-agent/diff-explain/SKILL.md +2 -0
- package/pipeline/commands/multi-agent/estimate/SKILL.md +65 -0
- package/pipeline/commands/multi-agent/help/SKILL.md +5 -546
- package/pipeline/commands/multi-agent/kill/SKILL.md +13 -18
- package/pipeline/commands/multi-agent/refactor/SKILL.md +7 -76
- package/pipeline/commands/multi-agent/review-analysis/SKILL.md +1 -1
- package/pipeline/commands/multi-agent/scenario-audit/SKILL.md +79 -0
- package/pipeline/commands/multi-agent/serve/SKILL.md +6 -3
- package/pipeline/commands/multi-agent/setup/SKILL.md +12 -365
- package/pipeline/commands/multi-agent/status/SKILL.md +2 -0
- package/pipeline/commands/multi-agent/store-ready/SKILL.md +56 -184
- package/pipeline/commands/multi-agent/sync/SKILL.md +14 -267
- package/pipeline/contract/CHANGELOG.md +52 -0
- package/pipeline/contract/README.md +41 -1
- package/pipeline/contract/build.mjs +49 -7
- package/pipeline/contract/fixtures/error-invalid-request.json +1 -1
- package/pipeline/contract/fixtures/error-unauthorized.json +1 -1
- package/pipeline/contract/fixtures/error-unsigned.json +1 -1
- package/pipeline/contract/fixtures/launch-plan.json +1 -2
- package/pipeline/contract/fixtures/runs-awaiting-question.json +10 -3
- package/pipeline/contract/fixtures/runs-empty.json +1 -1
- package/pipeline/contract/fixtures/runs-failed.json +19 -6
- package/pipeline/contract/fixtures/runs-pr-opened-redacted.json +25 -8
- package/pipeline/contract/fixtures/runs-pr-opened.json +25 -8
- package/pipeline/contract/fixtures/runs-running.json +31 -4
- package/pipeline/contract/frozen/toolbox.json +13 -0
- package/pipeline/contract/manifest.json +112 -10
- package/pipeline/contract/types/index.d.ts +186 -17
- package/pipeline/lib/claude-sessions.mjs +93 -0
- package/pipeline/lib/credential-resolve.mjs +39 -0
- package/pipeline/lib/gc-report.sh +64 -0
- package/pipeline/lib/unattended-settings-location.mjs +4 -0
- package/pipeline/lib/workspace-trust.mjs +73 -0
- package/pipeline/multi-agent-refs/analysis/intake.md +5 -3
- package/pipeline/multi-agent-refs/analysis/locked.md +8 -7
- package/pipeline/multi-agent-refs/analysis/render.md +4 -3
- package/pipeline/multi-agent-refs/analysis/resolve.md +1 -1
- package/pipeline/multi-agent-refs/analysis/resume.md +37 -0
- package/pipeline/multi-agent-refs/analysis/reusable-refs.md +25 -0
- package/pipeline/multi-agent-refs/channels/board.md +17 -0
- package/pipeline/multi-agent-refs/channels/multi-repo.md +15 -0
- package/pipeline/multi-agent-refs/cross-cli-contract.md +4 -4
- package/pipeline/multi-agent-refs/design-check/build-launch.md +14 -0
- package/pipeline/multi-agent-refs/design-check/compare.md +44 -0
- package/pipeline/multi-agent-refs/design-check/drive-capture.md +35 -0
- package/pipeline/multi-agent-refs/design-check/export.md +37 -0
- package/pipeline/multi-agent-refs/design-check/figma-mapping.md +11 -0
- package/pipeline/multi-agent-refs/design-check/init-inventory.md +56 -0
- package/pipeline/multi-agent-refs/design-check/mcp-currency-gate.md +41 -0
- package/pipeline/multi-agent-refs/features/analysis-outline.md +55 -0
- package/pipeline/multi-agent-refs/features/analysis-sources.md +60 -0
- package/pipeline/multi-agent-refs/help/en.md +273 -0
- package/pipeline/multi-agent-refs/help/tr.md +271 -0
- package/pipeline/multi-agent-refs/orchestrator/operations.md +99 -0
- package/pipeline/multi-agent-refs/orchestrator/phase-0-projects.md +72 -0
- package/pipeline/multi-agent-refs/orchestrator/phase-3-user-test.md +40 -0
- package/pipeline/multi-agent-refs/orchestrator/phase-4-5-projects.md +68 -0
- package/pipeline/multi-agent-refs/orchestrator/skill-loading.md +99 -0
- package/pipeline/multi-agent-refs/phases/phase-0-init.md +3 -2
- package/pipeline/multi-agent-refs/phases/phase-1-plan.md +1 -1
- package/pipeline/multi-agent-refs/phases/phase-2-dev.md +1 -1
- package/pipeline/multi-agent-refs/picker-contract.md +29 -0
- package/pipeline/multi-agent-refs/refactor/drift.md +49 -0
- package/pipeline/multi-agent-refs/refactor/run-errors.md +46 -0
- package/pipeline/multi-agent-refs/setup/discovery.md +84 -0
- package/pipeline/multi-agent-refs/setup/figma.md +27 -0
- package/pipeline/multi-agent-refs/setup/identity-routing.md +60 -0
- package/pipeline/multi-agent-refs/setup/token-save-flow.md +201 -0
- package/pipeline/multi-agent-refs/store-ready/build.md +49 -0
- package/pipeline/multi-agent-refs/store-ready/gate-1-static.md +37 -0
- package/pipeline/multi-agent-refs/store-ready/gate-3-policy.md +31 -0
- package/pipeline/multi-agent-refs/store-ready/preflight.md +50 -0
- package/pipeline/multi-agent-refs/store-ready/report.md +40 -0
- package/pipeline/multi-agent-refs/sync/codex.md +43 -0
- package/pipeline/multi-agent-refs/sync/dev-toolkit.md +174 -0
- package/pipeline/multi-agent-refs/sync/stack-plugins.md +51 -0
- package/pipeline/multi-agent-refs/tracker-contract.md +29 -4
- package/pipeline/schemas/agent-state.schema.json +13 -4
- package/pipeline/schemas/analysis-spec.schema.json +56 -4
- package/pipeline/schemas/autopilot-off-request.schema.json +20 -0
- package/pipeline/schemas/autopilot-off.schema.json +24 -0
- package/pipeline/schemas/autopilot-status.schema.json +63 -0
- package/pipeline/schemas/contract-error.schema.json +13 -2
- package/pipeline/schemas/gc-request.schema.json +31 -0
- package/pipeline/schemas/gc.schema.json +116 -0
- package/pipeline/schemas/kill-request.schema.json +22 -0
- package/pipeline/schemas/kill.schema.json +118 -0
- package/pipeline/schemas/launch-plan.schema.json +11 -2
- package/pipeline/schemas/launch-request.schema.json +7 -2
- package/pipeline/schemas/launch.json +65 -4
- package/pipeline/schemas/launch.schema.json +23 -8
- package/pipeline/schemas/prefs.schema.json +3 -3
- package/pipeline/schemas/repos.schema.json +39 -0
- package/pipeline/schemas/resume-request.schema.json +37 -0
- package/pipeline/schemas/run-log.schema.json +32 -0
- package/pipeline/schemas/run-questions.json +5 -1
- package/pipeline/schemas/run-questions.schema.json +1 -1
- package/pipeline/schemas/runs-index.schema.json +59 -3
- package/pipeline/scripts/_run-paths.mjs +8 -2
- package/pipeline/scripts/analysis-conform-coverage.mjs +96 -0
- package/pipeline/scripts/analysis-sources.mjs +264 -0
- package/pipeline/scripts/autopilot-control.mjs +223 -0
- package/pipeline/scripts/autopilot-runner.mjs +14 -39
- package/pipeline/scripts/build-references.mjs +5 -1
- package/pipeline/scripts/confluence-readback.mjs +4 -23
- package/pipeline/scripts/contract-server.mjs +373 -7
- package/pipeline/scripts/doctor.mjs +5 -2
- package/pipeline/scripts/estimate.mjs +223 -0
- package/pipeline/scripts/gate-ledger.mjs +64 -3
- package/pipeline/scripts/gc-plan.mjs +288 -0
- package/pipeline/scripts/gc-refs.sh +33 -2
- package/pipeline/scripts/gc-tmp.sh +33 -2
- package/pipeline/scripts/gc-worktrees.sh +42 -3
- package/pipeline/scripts/gen-mode-dispatch.mjs +3 -24
- package/pipeline/scripts/launch-request.mjs +182 -10
- package/pipeline/scripts/phase-tracker.sh +62 -1
- package/pipeline/scripts/run-kill.mjs +232 -0
- package/pipeline/scripts/run-log.mjs +111 -0
- package/pipeline/scripts/runs-index.mjs +177 -11
- package/pipeline/scripts/scenario-audit.mjs +245 -0
- package/pipeline/scripts/validate-analysis-doc.mjs +84 -6
- package/pipeline/skills/.skill-manifest.json +24 -16
- package/pipeline/skills/shared/README.md +5 -3
- package/pipeline/skills/shared/core/multi-agent/SKILL.md +51 -450
- package/pipeline/skills/shared/core/multi-agent-analysis/SKILL.md +7 -1
- package/pipeline/skills/shared/core/multi-agent-autopilot-off/SKILL.md +26 -44
- package/pipeline/skills/shared/core/multi-agent-design-check/SKILL.md +31 -127
- package/pipeline/skills/shared/core/multi-agent-estimate/SKILL.md +61 -0
- package/pipeline/skills/shared/core/multi-agent-kill/SKILL.md +14 -19
- package/pipeline/skills/shared/core/multi-agent-refactor/SKILL.md +7 -76
- package/pipeline/skills/shared/core/multi-agent-review/SKILL.md +1 -1
- package/pipeline/skills/shared/core/multi-agent-review-analysis/SKILL.md +1 -1
- package/pipeline/skills/shared/core/multi-agent-review-issue/SKILL.md +1 -1
- package/pipeline/skills/shared/core/multi-agent-review-jira/SKILL.md +1 -1
- package/pipeline/skills/shared/core/multi-agent-scenario-audit/SKILL.md +77 -0
- package/pipeline/skills/shared/core/multi-agent-serve/SKILL.md +6 -3
- package/pipeline/skills/shared/core/multi-agent-setup/SKILL.md +205 -324
- package/pipeline/skills/shared/core/multi-agent-store-ready/SKILL.md +5 -0
- package/pipeline/skills/shared/core/multi-agent-sync/SKILL.md +4 -4
|
@@ -15,8 +15,7 @@ Catch, before you upload, what App Store Connect or the Play Console would send
|
|
|
15
15
|
back after you do.
|
|
16
16
|
|
|
17
17
|
**Local-only.** No commits, no push, no PR, no channels unless you ask at the end.
|
|
18
|
-
A worktree, when
|
|
19
|
-
working tree.
|
|
18
|
+
A worktree, when needed, only archives without touching your working tree.
|
|
20
19
|
|
|
21
20
|
**It never ships.** iOS runs `--validate-app`, never `--upload-app`. Android
|
|
22
21
|
never commits a Play edit: when Google Play is onboarded, Gate 2 uploads the
|
|
@@ -26,12 +25,17 @@ accident.
|
|
|
26
25
|
|
|
27
26
|
**Input**: $ARGUMENTS
|
|
28
27
|
|
|
28
|
+
## Gotchas
|
|
29
|
+
|
|
30
|
+
- A skipped gate is reported as skipped with its reason, never folded into a pass: a green static audit says nothing about what the store's validator will say.
|
|
31
|
+
- The Play throwaway edit is deleted whether validation passes or fails.
|
|
32
|
+
- Gate 3 reads source, not the binary: a policy finding cites `file:line` in the repo the package was built from.
|
|
33
|
+
|
|
29
34
|
## Why three gates, and why the same three on both platforms
|
|
30
35
|
|
|
31
|
-
Each gate sees
|
|
32
|
-
|
|
33
|
-
|
|
34
|
-
a package the store itself refuses, and a policy a human enforces.
|
|
36
|
+
Each gate sees what the others cannot, so no single one is "the check". The
|
|
37
|
+
failure modes are the same on both platforms: a malformed package, a package the
|
|
38
|
+
store refuses, a policy a human enforces.
|
|
35
39
|
|
|
36
40
|
| Gate | Sees | Blind to |
|
|
37
41
|
|---|---|---|
|
|
@@ -47,12 +51,10 @@ a package the store itself refuses, and a policy a human enforces.
|
|
|
47
51
|
| 2 Authoritative | `ios_testflight_validate({ipa_path, platform: "ios", <credentials>})` → `xcrun altool --validate-app`, plus `store_asc_next_build_number` for whether the build number is already used. Needs an `.ipa` + credentials | With `google_play` onboarded: `store_play_validate_bundle({package_name, bundle_path})` - Google validates the `.aab` in a throwaway Publishing API edit that is then deleted, never committed. Without it, Play's check exists only server-side and nothing local reproduces it, so this gate reports `SKIPPED (no local Play validator)` with the reason `Google Play not onboarded`. Do not substitute `bundletool validate` - that is Gate 1 |
|
|
48
52
|
| 3 Policy | `ai-ios-toolkit:app-store-review` skill vs repo source | `ai-android-toolkit:play-store-review` skill vs repo source |
|
|
49
53
|
|
|
50
|
-
Gate 2's asymmetry is
|
|
51
|
-
|
|
52
|
-
|
|
53
|
-
|
|
54
|
-
Without both, an Android run clears at most 2 of 3 gates and must never print
|
|
55
|
-
`passed`.
|
|
54
|
+
Gate 2's asymmetry is reported, not smoothed over. On iOS it is the only gate that
|
|
55
|
+
catches a version+build pair already used. On Android it runs only with Google Play
|
|
56
|
+
onboarded and the throwaway-edit upload approved; without both, an Android run
|
|
57
|
+
clears at most 2 of 3 gates and never prints `passed`.
|
|
56
58
|
|
|
57
59
|
The `store_*` tools need `@mmerterden/multi-agent-toolkit-mcp` ≥ v3.17.0. On an
|
|
58
60
|
older server they are absent, and each branch below that uses one falls back to
|
|
@@ -94,22 +96,13 @@ English, per `$HOME/.claude/multi-agent-refs/picker-contract.md`. Print the
|
|
|
94
96
|
|
|
95
97
|
1. **Repo** - from `prefs.projects` matching the detected platform. A single match
|
|
96
98
|
auto-resolves (say so in the breadcrumb, do not silently skip the step).
|
|
97
|
-
2. **Branch** - the branch to validate.
|
|
98
|
-
|
|
99
|
-
|
|
100
|
-
|
|
101
|
-
|
|
102
|
-
|
|
103
|
-
|
|
104
|
-
| `could not read Password`, `Authentication failed`, `403` | credential | store the PAT in the credential helper or switch the remote to SSH. **A VPN cannot fix this**, and the base ref being stale is unrelated to what broke - do not offer the cached-ref fallback. |
|
|
105
|
-
| `Could not resolve host`, `Operation timed out`, `Connection refused` | network | retry / continue on the cached ref with an explicit warning / switch remote / abort, per `$HOME/.claude/multi-agent-refs/rules.md` |
|
|
106
|
-
| `Repository not found`, `404` | wrong remote | show `git remote -v` and ask |
|
|
107
|
-
|
|
108
|
-
Always print the observed stderr line next to the classification. Asserting
|
|
109
|
-
`unreachable (VPN/DNS)` for a missing-credential error that returns in under a
|
|
110
|
-
second sends the user to fix something that was never broken.
|
|
111
|
-
- Offer the current branch, the default branch, and any `release/*` /
|
|
112
|
-
`tkdevelop/*` heads.
|
|
99
|
+
2. **Branch** - the branch to validate. Run `git fetch --prune` first, capturing
|
|
100
|
+
**stderr**. **If the fetch fails, do not silently fall back to a cached ref**, and
|
|
101
|
+
**classify before naming a cause** (credential / network / wrong remote), printing
|
|
102
|
+
the observed stderr line next to the classification. A credential failure never
|
|
103
|
+
gets the cached-ref fallback. Then offer the current branch, the default branch,
|
|
104
|
+
and any `release/*` / `tkdevelop/*` heads.
|
|
105
|
+
Full procedure: `$HOME/.claude/multi-agent-refs/store-ready/preflight.md`. Read it for the fetch-failure table.
|
|
113
106
|
3. **Mode** - how the build is obtained:
|
|
114
107
|
- `Supply a build` (Mode B, default) - fastest, no signing needed in-run.
|
|
115
108
|
- `Build from this branch` (Mode A) - iOS needs a distribution certificate and
|
|
@@ -120,33 +113,17 @@ English, per `$HOME/.claude/multi-agent-refs/picker-contract.md`. Print the
|
|
|
120
113
|
|
|
121
114
|
Report every line; a missing prerequisite is a halt, not a warning.
|
|
122
115
|
|
|
123
|
-
**iOS
|
|
124
|
-
|
|
125
|
-
|
|
126
|
-
|
|
127
|
-
|
|
128
|
-
```
|
|
129
|
-
|
|
130
|
-
Then resolve credentials, and **state which tier is active in the report**:
|
|
131
|
-
|
|
132
|
-
| Tier | Source | Effect |
|
|
133
|
-
|---|---|---|
|
|
134
|
-
| 1 | ASC API key - key id, issuer id and `.p8` in the Keychain (`appstore_connect_key_id`, `appstore_connect_issuer_id`, `appstore_connect_private_key`), read by the toolkit through the store reference file. `store_status` reports it as `appStoreConnect.configured` | Gate 2 runs; call `ios_testflight_validate` with neither `api_key_id` nor `apple_id` so it uses that key |
|
|
135
|
-
| 2 | Apple ID + app-specific password, referenced as a keychain item | Gate 2 runs |
|
|
136
|
-
| 3 | neither | **Gate 2 reports `SKIPPED`, and the run says so in the verdict line** |
|
|
137
|
-
|
|
138
|
-
Multi-provider accounts need `--provider-public-id`. When it is not in prefs, run
|
|
139
|
-
`ios_testflight_validate({list_providers: true})` once and ask which provider.
|
|
116
|
+
**iOS**: `altool` and `xcodebuild` must resolve. Then resolve credentials and
|
|
117
|
+
**state which tier is active in the report**: tier 1 ASC API key (`store_status`
|
|
118
|
+
reports `appStoreConnect.configured`), tier 2 Apple ID + app-specific password,
|
|
119
|
+
tier 3 neither, where **Gate 2 reports `SKIPPED`, and the run says so in the verdict
|
|
120
|
+
line**. Multi-provider accounts need `--provider-public-id`; ask when it is not in prefs.
|
|
140
121
|
|
|
141
|
-
**Android
|
|
122
|
+
**Android**: `bundletool`, `aapt2` and `apksigner` must resolve.
|
|
142
123
|
|
|
143
|
-
|
|
144
|
-
command -v bundletool >/dev/null || echo "MISSING: bundletool"
|
|
145
|
-
command -v aapt2 >/dev/null || echo "MISSING: aapt2 (Android SDK build-tools)"
|
|
146
|
-
command -v apksigner >/dev/null || echo "MISSING: apksigner (Android SDK build-tools)"
|
|
147
|
-
```
|
|
124
|
+
Full procedure: `$HOME/.claude/multi-agent-refs/store-ready/preflight.md`. Read it for Step 2 (commands, tier table, provider lookup).
|
|
148
125
|
|
|
149
|
-
Then resolve whether Gate 2 can run. Call `store_status` (no probe) and read
|
|
126
|
+
Then resolve whether Android Gate 2 can run. Call `store_status` (no probe) and read
|
|
150
127
|
`googlePlay.configured`:
|
|
151
128
|
|
|
152
129
|
| State | Gate 2 |
|
|
@@ -155,8 +132,7 @@ Then resolve whether Gate 2 can run. Call `store_status` (no probe) and read
|
|
|
155
132
|
| `googlePlay.configured: true` and `MULTI_AGENT_UNATTENDED=1` | `SKIPPED (no local Play validator)`, reason: the toolkit refuses the upload in an unattended run |
|
|
156
133
|
| not configured, or no `store_status` tool | `SKIPPED (no local Play validator)`, reason: `Google Play not onboarded` (`/multi-agent:setup` Step 3d) |
|
|
157
134
|
|
|
158
|
-
Say which one it is
|
|
159
|
-
one with it needs to know why Gate 2 did not run.
|
|
135
|
+
Say which one it is.
|
|
160
136
|
|
|
161
137
|
Credentials come from `/multi-agent:setup`; never prompt for a secret value in
|
|
162
138
|
chat.
|
|
@@ -178,81 +154,30 @@ findings.
|
|
|
178
154
|
|
|
179
155
|
## Step 3 - obtain the build
|
|
180
156
|
|
|
181
|
-
|
|
182
|
-
|
|
183
|
-
- **iOS `.xcarchive`** → Gate 1 runs on it. To reach Gate 2 the archive must be
|
|
184
|
-
exported, so run `ios_export_ipa` (see Mode A for the signing inputs).
|
|
185
|
-
- **iOS `.ipa` only** → **Gate 1 is `SKIPPED (needs .xcarchive)`.** The static audit
|
|
186
|
-
reads archive structure an `.ipa` does not carry. Do not present a two-gate run as
|
|
187
|
-
a full pass; say which gate did not run and why, and offer to re-run with the
|
|
188
|
-
archive.
|
|
189
|
-
- **Android `.aab`** → Gate 1 runs in full.
|
|
190
|
-
- **Android `.apk` only** → Gate 1 runs the rules that do not need a bundle and
|
|
191
|
-
**lists the rules it could not apply**. An `.apk` cannot answer bundle-level
|
|
192
|
-
questions (per-ABI splits, dynamic features, Play App Signing expectations).
|
|
193
|
-
|
|
194
|
-
When no path is given, pick the newest artifact and print which one you picked:
|
|
195
|
-
|
|
196
|
-
```
|
|
197
|
-
iOS: newest .xcarchive under ~/Library/Developer/Xcode/Archives/**
|
|
198
|
-
Android: newest .aab under **/build/outputs/bundle/**/*.aab
|
|
199
|
-
```
|
|
157
|
+
Mode B (supply a build) and Mode A (build from the branch). Full procedure:
|
|
158
|
+
`$HOME/.claude/multi-agent-refs/store-ready/build.md`. Read it for Step 3. Rules that hold either way:
|
|
200
159
|
|
|
201
|
-
|
|
202
|
-
|
|
203
|
-
|
|
204
|
-
|
|
205
|
-
|
|
206
|
-
|
|
207
|
-
|
|
208
|
-
|
|
209
|
-
|
|
210
|
-
- **iOS**: `ios_xcodebuild({workspace|project, scheme, action: "archive", configuration: "Release", destination: "generic/platform=iOS"})`.
|
|
211
|
-
Note the destination: the simulator default would produce an archive that
|
|
212
|
-
cannot be exported for distribution.
|
|
213
|
-
- **Android**: `./gradlew bundleRelease` (or the release variant the module
|
|
214
|
-
declares). A debug-signed bundle fails Gate 1 signing rules for the wrong
|
|
215
|
-
reason - if no release signing config resolves, halt and say so rather than
|
|
216
|
-
auditing a debug artifact.
|
|
217
|
-
4. **iOS export**:
|
|
218
|
-
`ios_export_ipa({archive_path, output_dir, method: "app-store-connect", team_id, provisioning_profiles?, signing_style?})`.
|
|
219
|
-
Leave `allow_provisioning_updates` off unless the user asks: it lets xcodebuild
|
|
220
|
-
create or modify profiles in the developer account, which a validation run has no
|
|
221
|
-
business doing.
|
|
222
|
-
5. A failed build or export halts with the parsed errors. The usual iOS causes are a
|
|
223
|
-
missing distribution certificate, a profile that does not match the bundle ID, or
|
|
224
|
-
`signing_style: "manual"` with no `provisioning_profiles` map.
|
|
160
|
+
- **iOS `.ipa` only** → **Gate 1 is `SKIPPED (needs .xcarchive)`**; never present a
|
|
161
|
+
two-gate run as a full pass. An Android `.apk` **lists the rules it could not apply**.
|
|
162
|
+
- Never validate an artifact whose provenance you did not state; print which one you picked.
|
|
163
|
+
- Mode A worktree at `{projectRoot}/.worktrees/{taskId}`, **never under `$HOME`**, never
|
|
164
|
+
a direct checkout of the main working tree.
|
|
165
|
+
- iOS archives with `destination: "generic/platform=iOS"`. Android with no release
|
|
166
|
+
signing config halts; never audit a debug artifact.
|
|
167
|
+
- Leave `allow_provisioning_updates` off unless the user asks.
|
|
168
|
+
- A failed build or export halts with the parsed errors.
|
|
225
169
|
|
|
226
170
|
## Step 4 - Gate 1, static package audit
|
|
227
171
|
|
|
228
|
-
- **iOS**: `ios_app_store_audit({archive_path, rules: "all"})
|
|
229
|
-
`apple-archive-compliance` skill
|
|
230
|
-
|
|
231
|
-
|
|
232
|
-
|
|
233
|
-
|
|
234
|
-
|
|
235
|
-
node -e "import('@mmerterden/multi-agent-toolkit-mcp/tools/ios-app-store-audit/index.js').then(m => m.runAudit({ archivePath: '<path>', rules: 'all' }).then(r => console.log(JSON.stringify(r))))"
|
|
236
|
-
```
|
|
237
|
-
|
|
238
|
-
Use the fallback only when the tool is genuinely absent, and say in the report
|
|
239
|
-
which path ran - a rule set that silently differed between two invocations is
|
|
240
|
-
worse than a missing gate.
|
|
241
|
-
|
|
242
|
-
Then, whichever path ran, count `<archive>/dSYMs/*.dSYM`. Zero is a blocking
|
|
243
|
-
finding: `[SYMBOLS] archive carries no dSYM; crash reports will not symbolicate`,
|
|
244
|
-
with the hint `DEBUG_INFORMATION_FORMAT = dwarf-with-dsym` for the Release
|
|
245
|
-
configuration. This check runs from the package alone and does not need the
|
|
246
|
-
MCP tool.
|
|
247
|
-
- **Android**: `android_apk_audit` on the artifact, plus the
|
|
248
|
-
`google-play-compliance` skill's 21 rules - `bundletool validate` and manifest
|
|
249
|
-
dump, `aapt2 dump badging`, `apksigner verify`, ABI / native scan.
|
|
172
|
+
- **iOS**: `ios_app_store_audit({archive_path, rules: "all"})`, per the
|
|
173
|
+
`apple-archive-compliance` skill. The direct-package fallback runs only when the
|
|
174
|
+
tool is genuinely absent, and the report says which path ran. An archive with no
|
|
175
|
+
dSYM (`<archive>/dSYMs/*.dSYM` count zero) is a blocking `[SYMBOLS]` finding.
|
|
176
|
+
- **Android**: `android_apk_audit` plus the `google-play-compliance` skill's 21 rules.
|
|
177
|
+
A `minifyEnabled true` module whose build produced no `mapping.txt` is a blocking
|
|
178
|
+
`[SYMBOLS]` finding.
|
|
250
179
|
|
|
251
|
-
|
|
252
|
-
`mapping.txt`, raise the same class of blocking finding:
|
|
253
|
-
`[SYMBOLS] minified bundle carries no mapping.txt; crash reports will not
|
|
254
|
-
deobfuscate`. This check reads the module config and the build output alone
|
|
255
|
-
and does not need the MCP tool.
|
|
180
|
+
Full procedure: `$HOME/.claude/multi-agent-refs/store-ready/gate-1-static.md`. Read it for Gate 1.
|
|
256
181
|
|
|
257
182
|
`error` findings are blocking; `warning` is advisory. Group by severity and keep
|
|
258
183
|
each finding's ITMS / Play policy code - Gate 2 may return the same code on iOS,
|
|
@@ -304,32 +229,9 @@ check. If the real upload is later refused as "already used", raise `versionCode
|
|
|
304
229
|
Load the platform's review skill and review the repo against it. This is the gate
|
|
305
230
|
that catches what a human reviewer rejects, so it reads source, not the binary.
|
|
306
231
|
|
|
307
|
-
**iOS** - `ai-ios-toolkit:app-store-review
|
|
308
|
-
|
|
309
|
-
|
|
310
|
-
|---|---|
|
|
311
|
-
| Purpose strings | every `NS*UsageDescription` in Info.plist - present, specific, user-facing, and matching what the code actually does with the data |
|
|
312
|
-
| Privacy manifest | `PrivacyInfo.xcprivacy` exists, declares required-reason APIs, and matches the SDKs actually linked |
|
|
313
|
-
| Tracking | if any tracking API or SDK is present, an ATT prompt exists and runs before collection |
|
|
314
|
-
| Account deletion | if the app creates accounts, an in-app deletion path exists (guideline 5.1.1(v)) |
|
|
315
|
-
| Privacy policy | reachable in-app and in the metadata |
|
|
316
|
-
| IAP | anything unlocking features goes through StoreKit, with no external purchase path |
|
|
317
|
-
| Sign in with Apple | present when a third-party social login is offered |
|
|
318
|
-
| Crash symbolication | a dSYM upload step exists: an Xcode run-script calling `upload-symbols`, or a Crashlytics / Sentry / Datadog upload in CI |
|
|
319
|
-
|
|
320
|
-
**Android** - `ai-android-toolkit:play-store-review`:
|
|
321
|
-
|
|
322
|
-
| Area | Evidence to gather |
|
|
323
|
-
|---|---|
|
|
324
|
-
| Permissions | every `uses-permission` justified by a feature, no sensitive permission without its declaration form |
|
|
325
|
-
| Data safety | the declared data-safety answers match what the code collects and transmits |
|
|
326
|
-
| Target API level | meets the current Play requirement for new releases |
|
|
327
|
-
| Privacy policy | reachable in-app and in the listing |
|
|
328
|
-
| Billing | anything unlocking features goes through Play Billing, with no external purchase path |
|
|
329
|
-
| Account deletion | if the app creates accounts, an in-app deletion path exists, plus the web deletion URL Play requires |
|
|
330
|
-
| Content rating | the questionnaire answers match the app's actual content |
|
|
331
|
-
| Signing | Play App Signing configured, upload key distinct from the app signing key |
|
|
332
|
-
| Crash symbolication | a `mapping.txt` upload exists: the Firebase Crashlytics Gradle plugin, or the Play App Bundle deobfuscation file |
|
|
232
|
+
**iOS** - `ai-ios-toolkit:app-store-review`; **Android** - `ai-android-toolkit:play-store-review`.
|
|
233
|
+
Both cover a `Crash symbolication` row (dSYM upload step / `mapping.txt` upload).
|
|
234
|
+
Full procedure: `$HOME/.claude/multi-agent-refs/store-ready/gate-3-policy.md`. Read it for Gate 3 (the per-platform area tables).
|
|
333
235
|
|
|
334
236
|
For each: `pass` / `fail` / `not-applicable` with the evidence path that justifies
|
|
335
237
|
it. `not-applicable` needs a reason - an unexamined area is not a pass.
|
|
@@ -337,40 +239,10 @@ it. `not-applicable` needs a reason - an unexamined area is not a pass.
|
|
|
337
239
|
## Step 7 - report
|
|
338
240
|
|
|
339
241
|
Write to `~/StoreChecks/<platform>-<repo>-<branch>-<timestamp>/report.md` and print
|
|
340
|
-
a summary
|
|
341
|
-
|
|
342
|
-
|
|
343
|
-
|
|
344
|
-
Platform:<ios|android>
|
|
345
|
-
Build: <artifact path> · <bundle id / applicationId> <version> (<build>)
|
|
346
|
-
Auth: tier <1|2|none> · <method> (iOS only)
|
|
347
|
-
Sweep: <n> findings | SKIPPED (<reason>)
|
|
348
|
-
|
|
349
|
-
Gate 1 static audit PASS | FAIL (<n> blocking, <n> advisory) | SKIPPED (<reason>)
|
|
350
|
-
Gate 2 store validation PASS | FAIL (<n> issues) | SKIPPED (<reason>)
|
|
351
|
-
Gate 3 policy review PASS | FAIL (<n> findings) | <n> not-applicable
|
|
352
|
-
|
|
353
|
-
Blocking - fix before uploading
|
|
354
|
-
[ITMS-90683] Info.plist: NSCameraUsageDescription missing
|
|
355
|
-
guideline 5.1.1 Data Collection and Storage
|
|
356
|
-
<hint>
|
|
357
|
-
<file:line>
|
|
358
|
-
|
|
359
|
-
Advisory
|
|
360
|
-
...
|
|
361
|
-
|
|
362
|
-
Not run
|
|
363
|
-
Gate 2: no local Play validator - Google Play not onboarded; the authoritative check is server-side only
|
|
364
|
-
|
|
365
|
-
Open questions
|
|
366
|
-
Gate 2 (Android): versionCode <n> went to a discarded edit; Google does not document whether that reserves it
|
|
367
|
-
|
|
368
|
-
Before rollout (human inputs, not verified)
|
|
369
|
-
Phased rollout: <1% -> 10% -> 50% -> 100% | full>
|
|
370
|
-
Halt thresholds: crash-free < 99.5% (iOS, Android) or ANR > 0.47% (Android) => pause the rollout
|
|
371
|
-
Rollback / forward-fix owner: <name>
|
|
372
|
-
Forward-fix plan: <one line>
|
|
373
|
-
```
|
|
242
|
+
a summary: verdict line, per-gate status, Blocking / Advisory / Not run / Open
|
|
243
|
+
questions, and the `Before rollout` block (phased rollout, `Halt thresholds`,
|
|
244
|
+
rollback / forward-fix owner, forward-fix plan).
|
|
245
|
+
Full procedure: `$HOME/.claude/multi-agent-refs/store-ready/report.md`. Read it for Step 7 (the report layout).
|
|
374
246
|
|
|
375
247
|
Rules for the report:
|
|
376
248
|
|
|
@@ -24,6 +24,13 @@ When invoked, it synchronizes all targets in order. It detects what changed, upd
|
|
|
24
24
|
| `multi-agent-toolkit` | Run Step 3d only: gate, commit and publish the companion MCP server |
|
|
25
25
|
| `"change description"` | Apply the description to every target at once |
|
|
26
26
|
|
|
27
|
+
## Gotchas
|
|
28
|
+
|
|
29
|
+
- The pre-push gate is timing-sensitive: under heavy load a deadline test fails closed. Re-run it on a quiet machine; never push with `--no-verify`.
|
|
30
|
+
- `npm publish` answering 202 means the registry is still processing. Verify with the registry's dist-tags before moving `required`, which is asked for every release.
|
|
31
|
+
- The installed tree is localized (Turkish descriptions, `model: opus` while fable is off). Normalize before copying into the repo, or the public tree ships the local form.
|
|
32
|
+
- Synced shell runs on BSD userland: BSD grep has no Perl-regex flag, and `sed` has no `\b` or `\|`. A pattern that silently matches nothing reads as "clean".
|
|
33
|
+
|
|
27
34
|
## Targets
|
|
28
35
|
|
|
29
36
|
| # | Target | Path | Direction |
|
|
@@ -66,7 +73,7 @@ Run every step automatically:
|
|
|
66
73
|
```
|
|
67
74
|
Step 0: DOCTOR doctor.mjs - exit 2 or 4 stops the sync
|
|
68
75
|
Step 1.5: DETECT Compare timestamps, find stale targets
|
|
69
|
-
Step 2: COPILOT Claude Code -> Copilot CLI (instructions +
|
|
76
|
+
Step 2: COPILOT Claude Code -> Copilot CLI (instructions + 63 sub-command skills)
|
|
70
77
|
Step 2b: CODEX Claude Code -> Codex CLI (1 router skill + sub-command specs as refs + agent TOML)
|
|
71
78
|
Step 3: REPO Claude Code -> pipeline repo (genericized, personal data scrub, bash -n on all sh)
|
|
72
79
|
Step 3c: PLUGINS pipeline shared/external -> multi-agent-plugins marketplace (rebuild knowledge/,
|
|
@@ -99,7 +106,6 @@ Step 0 gate rules and why: `features/doctor.md`.
|
|
|
99
106
|
4. **Do not duplicate** - summary in Copilot, full spec in Claude. Keep this distinction.
|
|
100
107
|
5. **Report** - show a short diff summary after sync
|
|
101
108
|
|
|
102
|
-
|
|
103
109
|
---
|
|
104
110
|
|
|
105
111
|
## Pipeline Repo Sync Rules (CRITICAL)
|
|
@@ -168,274 +174,15 @@ Step 0 gate rules and why: `features/doctor.md`.
|
|
|
168
174
|
|
|
169
175
|
## Codex Sync (Step 2b)
|
|
170
176
|
|
|
171
|
-
|
|
172
|
-
*transform* of the Claude tree, not a mirror of it, and the transform is real work:
|
|
173
|
-
|
|
174
|
-
- the sub-command specs become reference files, because Codex silently truncates
|
|
175
|
-
its skills block (see `cross-cli-contract.md` 2.6 for the measurement)
|
|
176
|
-
- every `$HOME/.claude/...` reference to a CLI-owned tree is retargeted, with
|
|
177
|
-
`agents/<persona>.md` becoming `.toml` and the dispatcher becoming the router skill
|
|
178
|
-
- the personas under `agents/` are regenerated as TOML with a model + reasoning-effort mapping
|
|
179
|
-
- shared state (`logs/`, prefs, `knowledge/`) is deliberately NOT retargeted
|
|
180
|
-
|
|
181
|
-
That logic lives in `install/codex.mjs` and is gate-locked by
|
|
182
|
-
`smoke-codex-install.sh`. Re-describing it here in prose would give the pipeline two
|
|
183
|
-
definitions of the same transform, and the prose copy would be the one that rots. So
|
|
184
|
-
the step runs the installer's Codex target:
|
|
185
|
-
|
|
186
|
-
```bash
|
|
187
|
-
cd "$HOME/multi-agent-pipeline"
|
|
188
|
-
node install.js --codex
|
|
189
|
-
```
|
|
190
|
-
|
|
191
|
-
**Verify** (the installer is quiet about correctness, only about counts):
|
|
192
|
-
|
|
193
|
-
```bash
|
|
194
|
-
# exactly one pipeline skill: more than one means the skills block will truncate
|
|
195
|
-
ls -1 "$HOME/.codex/skills" | grep -c '^multi-agent$' # want 1
|
|
196
|
-
# every sub-command reachable as a ref
|
|
197
|
-
find "$HOME/.codex/multi-agent-refs/commands" -name SKILL.md | wc -l # want the command count
|
|
198
|
-
# no reference left pointing at a tree a Codex-only install does not have
|
|
199
|
-
grep -rhoE '(\$HOME|~)/\.claude/(agents|scripts|lib|schemas|commands|multi-agent-refs|rules)' \
|
|
200
|
-
"$HOME/.codex/skills" "$HOME/.codex/multi-agent-refs" | sort -u # want empty
|
|
201
|
-
```
|
|
202
|
-
|
|
203
|
-
**MCP**: the installer runs `codex mcp add multi-agent-toolkit` itself. It is idempotent, and
|
|
204
|
-
it is skipped with a warning when `codex` is not on `PATH` - never hand-edit
|
|
205
|
-
`~/.codex/config.toml`, which Codex owns (marketplace and plugin state live there
|
|
206
|
-
too).
|
|
207
|
-
|
|
208
|
-
**Order matters**: run this AFTER Step 3 (REPO), because the installer reads the repo
|
|
209
|
-
tree. Running it before means Codex gets the previous revision.
|
|
210
|
-
|
|
211
|
-
---
|
|
177
|
+
Full procedure: `$HOME/.claude/multi-agent-refs/sync/codex.md`. Read it before Step 2b; it runs after Step 3.
|
|
212
178
|
|
|
213
179
|
## Stack-Plugin Sync (Step 3c)
|
|
214
180
|
|
|
215
|
-
|
|
216
|
-
|
|
217
|
-
**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.
|
|
218
|
-
|
|
219
|
-
**Flow:**
|
|
220
|
-
|
|
221
|
-
```bash
|
|
222
|
-
PLUGINS_REPO="$HOME/multi-agent-plugins"
|
|
223
|
-
[ ! -d "$PLUGINS_REPO/.git" ] && gh repo clone mmerterden/multi-agent-plugins "$PLUGINS_REPO"
|
|
224
|
-
cd "$PLUGINS_REPO" && git pull origin main
|
|
225
|
-
|
|
226
|
-
# 1. Preview what would change (routing + version bumps), no writes:
|
|
227
|
-
node "$HOME/multi-agent-pipeline/pipeline/scripts/build-stack-plugins.mjs" --dry-run
|
|
228
|
-
|
|
229
|
-
# 2. Apply: rebuild each stack plugin's knowledge/ from shared/external,
|
|
230
|
-
# regenerate plugin.json skills[], bump the patch version of any plugin
|
|
231
|
-
# whose skill set changed. Cross-stack skills -> ai-common-toolkit;
|
|
232
|
-
# Apple/Xcode-only skills -> iOS plugin only.
|
|
233
|
-
node "$HOME/multi-agent-pipeline/pipeline/scripts/build-stack-plugins.mjs"
|
|
234
|
-
```
|
|
235
|
-
|
|
236
|
-
**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 refreshes the catalog with `claude plugin marketplace update multi-agent-plugins`, then runs `claude plugin update` for each installed plugin).
|
|
237
|
-
|
|
238
|
-
**Help + README freshness (mandatory when the generator reported any change):**
|
|
239
|
-
|
|
240
|
-
1. Every plugin ships a `tools/help` skill that renders its catalog LIVE from `plugin.json`, so it needs no per-skill edits - but verify each changed plugin still registers it (`grep -c "./skills/tools/help" plugins/<name>/.claude-plugin/plugin.json` = 1) and that a new plugin gets one before publish.
|
|
241
|
-
2. Plugin README tables sync through `python3 tools/bump.py <plugin> --set <version>`; run `python3 tools/bump.py --check` and treat DRIFT as a blocker.
|
|
242
|
-
3. `python3 tools/validate.py` must be clean (it also enforces the CHANGELOG heading for every bumped version - write the entry, do not backdate).
|
|
243
|
-
4. When the pipeline's command surface changed in the same sync (new/renamed `/multi-agent:*` commands), confirm `commands/multi-agent/help/SKILL.md` and both pipeline READMEs (`README.md`, `README.tr.md`) were updated in Step 3 before pushing here.
|
|
244
|
-
|
|
245
|
-
**Publish (only if the generator reported bumps):**
|
|
246
|
-
|
|
247
|
-
```bash
|
|
248
|
-
cd "$PLUGINS_REPO"
|
|
249
|
-
if ! git diff --quiet; then
|
|
250
|
-
# Identity: routed for {owner} (platformIdentityRouting). Never a literal: this file
|
|
251
|
-
# installs everywhere and would misattribute a downstream user's commits.
|
|
252
|
-
git config user.name "{identity.name}"
|
|
253
|
-
git config user.email "{identity.email}"
|
|
254
|
-
git add -A
|
|
255
|
-
git commit -m "chore: rebuild stack plugins from pipeline shared/external"
|
|
256
|
-
gh auth switch --user {owner} 2>/dev/null || true
|
|
257
|
-
git push origin main
|
|
258
|
-
fi
|
|
259
|
-
```
|
|
260
|
-
|
|
261
|
-
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.
|
|
262
|
-
|
|
263
|
-
---
|
|
181
|
+
Full procedure: `$HOME/.claude/multi-agent-refs/sync/stack-plugins.md`. Read it before Step 3c.
|
|
264
182
|
|
|
265
183
|
## Dev-Toolkit Sync (Step 3d)
|
|
266
184
|
|
|
267
|
-
|
|
268
|
-
|
|
269
|
-
**Resolution**: identical to `/multi-agent:refactor` Step 0c - `prefs.global.devToolkit` first, then auto-detect from the `mcpServers` registration (`~/.claude.json`, `~/.claude/settings.json`), then skip. `enabled: false` skips.
|
|
270
|
-
|
|
271
|
-
**Detect movement**:
|
|
272
|
-
|
|
273
|
-
```bash
|
|
274
|
-
DT="<resolved localPath>"; cd "$DT"
|
|
275
|
-
git fetch origin --quiet 2>/dev/null || true
|
|
276
|
-
DIRTY=$(git status --porcelain)
|
|
277
|
-
AHEAD=$(git log --oneline @{u}..HEAD 2>/dev/null | wc -l | tr -d ' ')
|
|
278
|
-
VER=$(node -p "require('./package.json').version")
|
|
279
|
-
TAGGED=$(git tag --list "v$VER")
|
|
280
|
-
```
|
|
281
|
-
|
|
282
|
-
Moved = `DIRTY` non-empty, or `AHEAD` > 0, or no tag for `VER`. Nothing moved -> report `multi-agent-toolkit: up to date (v$VER)` and continue with the sync.
|
|
283
|
-
|
|
284
|
-
**Ship gates** - all must pass before commit or publish. A gate failure aborts THIS step only, reported with file + line; the rest of the sync continues.
|
|
285
|
-
|
|
286
|
-
**Prefer the repo's own gate script.** When the toolkit ships one (`npm run gates`, or `scripts/gates.sh`), run THAT and skip the inline list below - the repo owns the definition, this skill only owns the requirement. The inline gates are the fallback for a repo that has none, and the checklist the gate script itself must cover.
|
|
287
|
-
|
|
288
|
-
```bash
|
|
289
|
-
cd "$DT"
|
|
290
|
-
if node -e "process.exit(require('./package.json').scripts?.gates ? 0 : 1)" 2>/dev/null; then
|
|
291
|
-
npm run gates || echo "ABORT: multi-agent-toolkit gates failed"
|
|
292
|
-
elif [ -f scripts/gates.sh ]; then
|
|
293
|
-
bash scripts/gates.sh || echo "ABORT: multi-agent-toolkit gates failed"
|
|
294
|
-
else
|
|
295
|
-
: # run the inline gates below
|
|
296
|
-
fi
|
|
297
|
-
```
|
|
298
|
-
|
|
299
|
-
1. **Syntax**: `node --check index.js` plus every `tools/**/*.js`.
|
|
300
|
-
2. **Boot + inventory**: handshake the server over stdio and count the registered tools.
|
|
301
|
-
|
|
302
|
-
```bash
|
|
303
|
-
TOOLS=$(printf '%s\n' \
|
|
304
|
-
'{"jsonrpc":"2.0","id":1,"method":"initialize","params":{"protocolVersion":"2024-11-05","capabilities":{},"clientInfo":{"name":"sync","version":"1"}}}' \
|
|
305
|
-
'{"jsonrpc":"2.0","method":"notifications/initialized"}' \
|
|
306
|
-
'{"jsonrpc":"2.0","id":2,"method":"tools/list"}' \
|
|
307
|
-
| node index.js 2>/dev/null \
|
|
308
|
-
| node -e 'let b="";process.stdin.on("data",d=>b+=d).on("end",()=>{const m=b.split("\n").filter(Boolean).map(l=>{try{return JSON.parse(l)}catch{return null}}).find(x=>x&&x.id===2&&x.result&&x.result.tools);console.log(m?m.result.tools.length:0)})')
|
|
309
|
-
[ "${TOOLS:-0}" -gt 0 ] || echo "ABORT: the toolkit served 0 tools"
|
|
310
|
-
```
|
|
311
|
-
|
|
312
|
-
3. **Advertised-count match**: `$TOOLS` must equal every advertised count (`package.json` `description`, the `README.md` header and its per-family rows). Fix the docs, never the gate - a stale count has shipped before.
|
|
313
|
-
4. **Packaging**: every directory the server loads at runtime must be inside `files[]`. A missing entry publishes a broken package (this has already caused one patch release).
|
|
314
|
-
|
|
315
|
-
```bash
|
|
316
|
-
PACK=$(npm pack --dry-run 2>&1)
|
|
317
|
-
for d in tools/*/; do printf '%s' "$PACK" | grep -q "$d" || echo "ABORT: $d missing from files[]"; done
|
|
318
|
-
```
|
|
319
|
-
|
|
320
|
-
5. **stdout hygiene**: `grep -rn "console\.log(" index.js tools/` must be empty - stdout carries the JSON-RPC frames, diagnostics belong on `console.error`.
|
|
321
|
-
6. **Personal-data scan**: no absolute `/Users/<name>` paths, no tokens, no corporate hostnames in the shipped files.
|
|
322
|
-
7. **Version contract**: every pipeline-side minimum (the `cross-cli-contract.md` tool table, `design-check`'s MCP requirement, `apple-archive-compliance`) must be satisfied by the version about to ship. A newly added tool that a pipeline skill now needs -> bump that declared minimum in the pipeline during this same sync.
|
|
323
|
-
|
|
324
|
-
**Version bump**: patch for fixes and docs, minor for a new tool, major for a removed or renamed tool (pipeline minimums depend on the surface).
|
|
325
|
-
|
|
326
|
-
**Ship**:
|
|
327
|
-
|
|
328
|
-
```bash
|
|
329
|
-
gh auth switch --user {owner}
|
|
330
|
-
git add -A
|
|
331
|
-
git commit -F "/tmp/release-msg-$NEW.txt" # "{type}(v$NEW): {what changed}", written with the file tool
|
|
332
|
-
git tag "v$NEW" && git push origin main --tags
|
|
333
|
-
```
|
|
334
|
-
|
|
335
|
-
Publish to the registry declared in `publishConfig` through a throwaway userconfig. Never edit `~/.npmrc`, and never a bare `npm publish` - it lands on whichever registry the ambient config happens to name.
|
|
336
|
-
|
|
337
|
-
**The token depends on the registry AND on the package scope.** The registry picks
|
|
338
|
-
the credential *type*; the scope picks the *account*. Resolving on host alone
|
|
339
|
-
misroutes on any machine with more than one GitHub identity, which is the common
|
|
340
|
-
case for anyone with a work and a personal account.
|
|
341
|
-
|
|
342
|
-
| Registry | Credential type | Account chosen by |
|
|
343
|
-
|---|---|---|
|
|
344
|
-
| `npm.pkg.github.com` | GitHub PAT with `write:packages` (Classic; fine-grained PATs are not fully supported for Packages) | the package scope, e.g. `@{owner}` → the `{owner}` account's PAT |
|
|
345
|
-
| `registry.npmjs.org` | npm token (logical key `npm`) | the npm account that owns the scope |
|
|
346
|
-
|
|
347
|
-
Resolve the scope first, then the key:
|
|
348
|
-
|
|
349
|
-
```bash
|
|
350
|
-
SCOPE=$(node -p "(require('./package.json').name.match(/^@([^/]+)/)||[])[1] || ''")
|
|
351
|
-
# Prefer a scope-specific mapping; fall back to the generic key only when the
|
|
352
|
-
# machine has exactly one GitHub identity.
|
|
353
|
-
KEY=$(node -e '
|
|
354
|
-
const fs=require("fs"),os=require("os"),p=os.homedir()+"/.claude/multi-agent-preferences.json";
|
|
355
|
-
const km=(JSON.parse(fs.readFileSync(p,"utf8")).global||{}).keychainMapping||{};
|
|
356
|
-
const scope=process.argv[1];
|
|
357
|
-
process.stdout.write(km[`github_${scope}`] ? `github_${scope}` : "github");
|
|
358
|
-
' "$SCOPE")
|
|
359
|
-
```
|
|
360
|
-
|
|
361
|
-
**Pre-flight the scope, do not learn it from a 403.** GitHub tells you a token's
|
|
362
|
-
scopes on any authenticated request, so check before uploading rather than after:
|
|
363
|
-
|
|
364
|
-
```bash
|
|
365
|
-
scope_ok() { # $1 = token; prints the login, non-zero when write:packages is absent
|
|
366
|
-
local hdrs; hdrs=$(curl -sI -H "Authorization: token $1" https://api.github.com/user)
|
|
367
|
-
printf '%s' "$hdrs" | grep -i '^x-oauth-scopes:' | grep -q 'write:packages'
|
|
368
|
-
}
|
|
369
|
-
```
|
|
370
|
-
|
|
371
|
-
**Candidate order for a `npm.pkg.github.com` publish.** The scope matters more than
|
|
372
|
-
where the token is stored, and the two are not correlated: on a machine with a work
|
|
373
|
-
and a personal identity, the hand-made PAT in the credential store may be the wrong
|
|
374
|
-
account or the right account without `write:packages`, while the `gh` CLI's own
|
|
375
|
-
OAuth token for that account often has it.
|
|
376
|
-
|
|
377
|
-
1. `github_<scope>` from `keychainMapping` (a PAT deliberately onboarded for this scope)
|
|
378
|
-
2. `gh auth token -u <scope>` - gh's stored OAuth token for that account
|
|
379
|
-
3. the generic `github` key - only when the machine has one GitHub identity
|
|
380
|
-
|
|
381
|
-
Take the first candidate that passes `scope_ok` AND whose `login` matches the
|
|
382
|
-
package scope. If none qualifies, stop before `npm publish` and report which
|
|
383
|
-
candidates were tried, what login each resolved to, and which scope was missing.
|
|
384
|
-
That report is the actionable output; a 403 body is not.
|
|
385
|
-
|
|
386
|
-
Measured on this machine, which is why the order is what it is:
|
|
387
|
-
|
|
388
|
-
| Candidate | login | scopes |
|
|
389
|
-
|---|---|---|
|
|
390
|
-
| `keychainMapping.github` | corporate EMU account | cannot publish to a personal scope under any grant |
|
|
391
|
-
| the personal PAT in the store | personal | `admin:public_key, gist, read:org, repo` - no `write:packages` |
|
|
392
|
-
| `gh auth token -u {owner}` | personal | `gist, read:org, repo, workflow, write:packages` ✓ |
|
|
393
|
-
|
|
394
|
-
**Two 403s mean two different things, and neither says "wrong token" plainly:**
|
|
395
|
-
|
|
396
|
-
- `Unauthorized: As an Enterprise Managed User, you cannot access this content` -
|
|
397
|
-
the resolved token belongs to a corporate EMU account, which cannot publish to a
|
|
398
|
-
personal scope at all. The mapping points at the wrong identity. Map the personal
|
|
399
|
-
account's PAT under `github_<scope>` and re-run; do not "fix" this by granting
|
|
400
|
-
the EMU token more scopes, because no scope makes an EMU account able to write
|
|
401
|
-
to a personal namespace.
|
|
402
|
-
- `The token provided does not match expected scopes` - right account, missing
|
|
403
|
-
permission. The PAT needs **Classic** with `write:packages` (plus `repo` for a
|
|
404
|
-
private package). Regenerate it at
|
|
405
|
-
`https://github.com/settings/tokens/new?scopes=write:packages,read:packages,repo`
|
|
406
|
-
and re-onboard via `/multi-agent:setup`.
|
|
407
|
-
|
|
408
|
-
Report which of the two it was. "Permission denied" alone sends the user to
|
|
409
|
-
regenerate a token that was never the problem.
|
|
410
|
-
|
|
411
|
-
```bash
|
|
412
|
-
NPMRC=$(mktemp); trap 'rm -f "$NPMRC"' EXIT
|
|
413
|
-
REG=$(node -p "require('./package.json').publishConfig?.registry || 'https://registry.npmjs.org'")
|
|
414
|
-
HOST=${REG#https://}; HOST=${HOST%/}
|
|
415
|
-
case "$HOST" in npm.pkg.github.com*) KEY=github ;; *) KEY=npm ;; esac
|
|
416
|
-
TOKEN=$(bash "$HOME/.claude/lib/credential-store.sh" get "$KEY")
|
|
417
|
-
[ -n "$TOKEN" ] || echo "ABORT: no '$KEY' token - onboard it via /multi-agent:setup before publishing"
|
|
418
|
-
printf '%s\n' "registry=$REG" "//$HOST/:_authToken=$TOKEN" > "$NPMRC"
|
|
419
|
-
npm publish --userconfig "$NPMRC"
|
|
420
|
-
```
|
|
421
|
-
|
|
422
|
-
Verify the publish landed: on GitHub Packages `npm view <package> version --userconfig "$NPMRC"`; on npmjs read the registry directly (`curl -s https://registry.npmjs.org/<package>/latest`) rather than `npm view`, which can answer from a stale cache.
|
|
423
|
-
|
|
424
|
-
**Required release** (optional; ask first even in `release` mode, it halts every older install): `npm dist-tag add "$(node -p "require('./package.json').name")@$VER" required --userconfig "$NPMRC"`. Out of band, so promote or demote any time. Contract: `multi-agent-refs/rules.md` "Supported Version Gate".
|
|
425
|
-
|
|
426
|
-
**Approval**: outside autopilot and outside `release`, ask before shipping.
|
|
427
|
-
|
|
428
|
-
> "multi-agent-toolkit moved (N changed files, M unpushed commits, v$VER). What should I do?"
|
|
429
|
-
|
|
430
|
-
- Commit + push (no publish)
|
|
431
|
-
- Commit + push + publish v$NEW
|
|
432
|
-
- Skip this step
|
|
433
|
-
|
|
434
|
-
With `release`, or in autopilot, run the full ship path without asking. If the working copy holds band-E work from `/multi-agent:refactor` that was never approved, do not ship it silently - report it and ask.
|
|
435
|
-
|
|
436
|
-
**Consumer note**: a path-based stdio registration (`node <localPath>/index.js`) picks the change up on the next MCP restart with no reinstall; a packaged registration (`npx <package>`) needs the published version. State which one the resolved config uses in the Step 6 report.
|
|
437
|
-
|
|
438
|
-
---
|
|
185
|
+
Full procedure: `$HOME/.claude/multi-agent-refs/sync/dev-toolkit.md`. Read it before Step 3d, and for `/multi-agent:sync multi-agent-toolkit`.
|
|
439
186
|
|
|
440
187
|
## Website Sync (Step 4)
|
|
441
188
|
|
|
@@ -493,15 +240,15 @@ same specs as reference files rather than as peer skills, via Step 2b - see
|
|
|
493
240
|
|-------------|-------------|
|
|
494
241
|
| `~/.claude/commands/multi-agent/{cmd}/SKILL.md` | `~/.copilot/skills/multi-agent-{cmd}/SKILL.md` |
|
|
495
242
|
|
|
496
|
-
**
|
|
243
|
+
**63 commands are synced** (canonical inventory - must match `cross-cli-contract.md` section 1; drift = contract violation):
|
|
497
244
|
|
|
498
245
|
```
|
|
499
246
|
analysis, analysis-jira, analysis-resolve, autopilot, autopilot-off, autopilot-on,
|
|
500
247
|
autopilot-status, build-optimize, channels, complaint-analysis, create-jira,
|
|
501
|
-
design-check, diff-explain, doctor, feedback, forget, garbage-collect, graph, help,
|
|
248
|
+
design-check, diff-explain, doctor, estimate, feedback, forget, garbage-collect, graph, help,
|
|
502
249
|
ios-coding-standard, issue, jira, kill, language, log,
|
|
503
250
|
manual-test, model, prune-logs, prune-prompts, purge, refactor, research, resume, review, review-analysis, review-issue, review-jira, route-off, route-on, route-status,
|
|
504
|
-
routines, save, scaffold, scan, search, security-review, serve, setup, stack, status, steer, store-ready, sync, test,
|
|
251
|
+
routines, save, scaffold, scan, scenario-audit, search, security-review, serve, setup, stack, status, steer, store-ready, sync, test,
|
|
505
252
|
test-accessibility, test-dark-mode, test-dynamic-type, test-screenshots,
|
|
506
253
|
testflight-validation, uninstall, update
|
|
507
254
|
```
|