@mmerterden/multi-agent-pipeline 20.12.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.
Files changed (183) hide show
  1. package/CHANGELOG.md +97 -0
  2. package/README.md +8 -6
  3. package/README.tr.md +8 -6
  4. package/docs/architecture.md +3 -3
  5. package/docs/ecosystem.md +5 -5
  6. package/docs/facts.json +4 -4
  7. package/install/_common.mjs +1 -1
  8. package/install/_plugin-skills.mjs +13 -9
  9. package/install/catalog-history.json +1 -1
  10. package/install/codex.mjs +12 -12
  11. package/manifest.json +186 -120
  12. package/package.json +1 -1
  13. package/pipeline/commands/multi-agent/SKILL.md +1 -0
  14. package/pipeline/commands/multi-agent/analysis/SKILL.md +17 -82
  15. package/pipeline/commands/multi-agent/analysis-jira/SKILL.md +57 -7
  16. package/pipeline/commands/multi-agent/analysis-resolve/SKILL.md +2 -2
  17. package/pipeline/commands/multi-agent/autopilot/SKILL.md +8 -23
  18. package/pipeline/commands/multi-agent/autopilot-off/SKILL.md +25 -45
  19. package/pipeline/commands/multi-agent/channels/SKILL.md +11 -63
  20. package/pipeline/commands/multi-agent/design-check/SKILL.md +43 -178
  21. package/pipeline/commands/multi-agent/diff-explain/SKILL.md +2 -0
  22. package/pipeline/commands/multi-agent/doctor/SKILL.md +6 -0
  23. package/pipeline/commands/multi-agent/estimate/SKILL.md +65 -0
  24. package/pipeline/commands/multi-agent/feedback/SKILL.md +2 -2
  25. package/pipeline/commands/multi-agent/forget/SKILL.md +1 -0
  26. package/pipeline/commands/multi-agent/garbage-collect/SKILL.md +1 -0
  27. package/pipeline/commands/multi-agent/help/SKILL.md +5 -546
  28. package/pipeline/commands/multi-agent/kill/SKILL.md +14 -18
  29. package/pipeline/commands/multi-agent/prune-logs/SKILL.md +1 -0
  30. package/pipeline/commands/multi-agent/prune-prompts/SKILL.md +1 -0
  31. package/pipeline/commands/multi-agent/refactor/SKILL.md +7 -76
  32. package/pipeline/commands/multi-agent/review/SKILL.md +5 -0
  33. package/pipeline/commands/multi-agent/review-analysis/SKILL.md +8 -3
  34. package/pipeline/commands/multi-agent/scenario-audit/SKILL.md +79 -0
  35. package/pipeline/commands/multi-agent/serve/SKILL.md +6 -3
  36. package/pipeline/commands/multi-agent/setup/SKILL.md +12 -365
  37. package/pipeline/commands/multi-agent/status/SKILL.md +2 -0
  38. package/pipeline/commands/multi-agent/store-ready/SKILL.md +56 -184
  39. package/pipeline/commands/multi-agent/sync/SKILL.md +14 -267
  40. package/pipeline/contract/CHANGELOG.md +52 -0
  41. package/pipeline/contract/README.md +41 -1
  42. package/pipeline/contract/build.mjs +49 -7
  43. package/pipeline/contract/fixtures/error-invalid-request.json +1 -1
  44. package/pipeline/contract/fixtures/error-unauthorized.json +1 -1
  45. package/pipeline/contract/fixtures/error-unsigned.json +1 -1
  46. package/pipeline/contract/fixtures/launch-plan.json +1 -2
  47. package/pipeline/contract/fixtures/runs-awaiting-question.json +10 -3
  48. package/pipeline/contract/fixtures/runs-empty.json +1 -1
  49. package/pipeline/contract/fixtures/runs-failed.json +19 -6
  50. package/pipeline/contract/fixtures/runs-pr-opened-redacted.json +25 -8
  51. package/pipeline/contract/fixtures/runs-pr-opened.json +25 -8
  52. package/pipeline/contract/fixtures/runs-running.json +31 -4
  53. package/pipeline/contract/frozen/toolbox.json +13 -0
  54. package/pipeline/contract/manifest.json +112 -10
  55. package/pipeline/contract/types/index.d.ts +186 -17
  56. package/pipeline/lib/analysis-jira-write.sh +81 -27
  57. package/pipeline/lib/analysis-quality.mjs +261 -0
  58. package/pipeline/lib/analysis-sections.mjs +105 -0
  59. package/pipeline/lib/claude-sessions.mjs +93 -0
  60. package/pipeline/lib/credential-resolve.mjs +39 -0
  61. package/pipeline/lib/gc-report.sh +64 -0
  62. package/pipeline/lib/jira-epic-link.sh +54 -0
  63. package/pipeline/lib/unattended-settings-location.mjs +4 -0
  64. package/pipeline/lib/workspace-trust.mjs +73 -0
  65. package/pipeline/multi-agent-refs/analysis/intake.md +5 -3
  66. package/pipeline/multi-agent-refs/analysis/locked.md +12 -11
  67. package/pipeline/multi-agent-refs/analysis/redesign.md +3 -1
  68. package/pipeline/multi-agent-refs/analysis/render.md +24 -24
  69. package/pipeline/multi-agent-refs/analysis/resolve.md +1 -1
  70. package/pipeline/multi-agent-refs/analysis/resume.md +37 -0
  71. package/pipeline/multi-agent-refs/analysis/reusable-refs.md +25 -0
  72. package/pipeline/multi-agent-refs/analysis/review.md +16 -3
  73. package/pipeline/multi-agent-refs/analysis/synthesis.md +10 -2
  74. package/pipeline/multi-agent-refs/analysis-template-corporate.md +44 -9
  75. package/pipeline/multi-agent-refs/analysis-template.md +21 -14
  76. package/pipeline/multi-agent-refs/channels/board.md +17 -0
  77. package/pipeline/multi-agent-refs/channels/multi-repo.md +15 -0
  78. package/pipeline/multi-agent-refs/cross-cli-contract.md +8 -4
  79. package/pipeline/multi-agent-refs/design-check/build-launch.md +14 -0
  80. package/pipeline/multi-agent-refs/design-check/compare.md +44 -0
  81. package/pipeline/multi-agent-refs/design-check/drive-capture.md +35 -0
  82. package/pipeline/multi-agent-refs/design-check/export.md +37 -0
  83. package/pipeline/multi-agent-refs/design-check/figma-mapping.md +11 -0
  84. package/pipeline/multi-agent-refs/design-check/init-inventory.md +56 -0
  85. package/pipeline/multi-agent-refs/design-check/mcp-currency-gate.md +41 -0
  86. package/pipeline/multi-agent-refs/features/analysis-jira.md +69 -19
  87. package/pipeline/multi-agent-refs/features/analysis-outline.md +55 -0
  88. package/pipeline/multi-agent-refs/features/analysis-sources.md +60 -0
  89. package/pipeline/multi-agent-refs/help/en.md +273 -0
  90. package/pipeline/multi-agent-refs/help/tr.md +271 -0
  91. package/pipeline/multi-agent-refs/orchestrator/operations.md +99 -0
  92. package/pipeline/multi-agent-refs/orchestrator/phase-0-projects.md +72 -0
  93. package/pipeline/multi-agent-refs/orchestrator/phase-3-user-test.md +40 -0
  94. package/pipeline/multi-agent-refs/orchestrator/phase-4-5-projects.md +68 -0
  95. package/pipeline/multi-agent-refs/orchestrator/skill-loading.md +99 -0
  96. package/pipeline/multi-agent-refs/phases/phase-0-init.md +3 -2
  97. package/pipeline/multi-agent-refs/phases/phase-1-plan.md +1 -1
  98. package/pipeline/multi-agent-refs/phases/phase-2-dev.md +1 -1
  99. package/pipeline/multi-agent-refs/picker-contract.md +29 -0
  100. package/pipeline/multi-agent-refs/refactor/drift.md +49 -0
  101. package/pipeline/multi-agent-refs/refactor/run-errors.md +46 -0
  102. package/pipeline/multi-agent-refs/setup/discovery.md +84 -0
  103. package/pipeline/multi-agent-refs/setup/figma.md +27 -0
  104. package/pipeline/multi-agent-refs/setup/identity-routing.md +60 -0
  105. package/pipeline/multi-agent-refs/setup/token-save-flow.md +201 -0
  106. package/pipeline/multi-agent-refs/store-ready/build.md +49 -0
  107. package/pipeline/multi-agent-refs/store-ready/gate-1-static.md +37 -0
  108. package/pipeline/multi-agent-refs/store-ready/gate-3-policy.md +31 -0
  109. package/pipeline/multi-agent-refs/store-ready/preflight.md +50 -0
  110. package/pipeline/multi-agent-refs/store-ready/report.md +40 -0
  111. package/pipeline/multi-agent-refs/sync/codex.md +43 -0
  112. package/pipeline/multi-agent-refs/sync/dev-toolkit.md +174 -0
  113. package/pipeline/multi-agent-refs/sync/stack-plugins.md +51 -0
  114. package/pipeline/multi-agent-refs/tracker-contract.md +29 -4
  115. package/pipeline/schemas/agent-state.schema.json +13 -4
  116. package/pipeline/schemas/analysis-spec.schema.json +76 -2
  117. package/pipeline/schemas/autopilot-off-request.schema.json +20 -0
  118. package/pipeline/schemas/autopilot-off.schema.json +24 -0
  119. package/pipeline/schemas/autopilot-status.schema.json +63 -0
  120. package/pipeline/schemas/contract-error.schema.json +13 -2
  121. package/pipeline/schemas/gc-request.schema.json +31 -0
  122. package/pipeline/schemas/gc.schema.json +116 -0
  123. package/pipeline/schemas/kill-request.schema.json +22 -0
  124. package/pipeline/schemas/kill.schema.json +118 -0
  125. package/pipeline/schemas/launch-plan.schema.json +11 -2
  126. package/pipeline/schemas/launch-request.schema.json +7 -2
  127. package/pipeline/schemas/launch.json +65 -4
  128. package/pipeline/schemas/launch.schema.json +23 -8
  129. package/pipeline/schemas/prefs.schema.json +25 -4
  130. package/pipeline/schemas/repos.schema.json +39 -0
  131. package/pipeline/schemas/resume-request.schema.json +37 -0
  132. package/pipeline/schemas/run-log.schema.json +32 -0
  133. package/pipeline/schemas/run-questions.json +5 -1
  134. package/pipeline/schemas/run-questions.schema.json +1 -1
  135. package/pipeline/schemas/runs-index.schema.json +59 -3
  136. package/pipeline/scripts/_run-paths.mjs +8 -2
  137. package/pipeline/scripts/analysis-conform-coverage.mjs +96 -0
  138. package/pipeline/scripts/analysis-sources.mjs +264 -0
  139. package/pipeline/scripts/analysis-story-body.mjs +210 -0
  140. package/pipeline/scripts/analysis-story-tree.mjs +73 -12
  141. package/pipeline/scripts/analysis-tickets-writeback.mjs +101 -0
  142. package/pipeline/scripts/autopilot-control.mjs +223 -0
  143. package/pipeline/scripts/autopilot-runner.mjs +14 -39
  144. package/pipeline/scripts/build-references.mjs +19 -2
  145. package/pipeline/scripts/confluence-readback.mjs +129 -0
  146. package/pipeline/scripts/contract-server.mjs +373 -7
  147. package/pipeline/scripts/doctor.mjs +5 -2
  148. package/pipeline/scripts/estimate.mjs +223 -0
  149. package/pipeline/scripts/gate-ledger.mjs +64 -3
  150. package/pipeline/scripts/gc-plan.mjs +288 -0
  151. package/pipeline/scripts/gc-refs.sh +33 -2
  152. package/pipeline/scripts/gc-tmp.sh +33 -2
  153. package/pipeline/scripts/gc-worktrees.sh +42 -3
  154. package/pipeline/scripts/gen-mode-dispatch.mjs +3 -24
  155. package/pipeline/scripts/jira-wiki-escape.mjs +40 -0
  156. package/pipeline/scripts/launch-request.mjs +182 -10
  157. package/pipeline/scripts/phase-tracker.sh +62 -1
  158. package/pipeline/scripts/run-kill.mjs +232 -0
  159. package/pipeline/scripts/run-log.mjs +111 -0
  160. package/pipeline/scripts/runs-index.mjs +177 -11
  161. package/pipeline/scripts/scenario-audit.mjs +245 -0
  162. package/pipeline/scripts/validate-analysis-doc.mjs +204 -76
  163. package/pipeline/skills/.skill-manifest.json +27 -19
  164. package/pipeline/skills/shared/README.md +5 -3
  165. package/pipeline/skills/shared/core/multi-agent/SKILL.md +51 -450
  166. package/pipeline/skills/shared/core/multi-agent-analysis/SKILL.md +13 -2
  167. package/pipeline/skills/shared/core/multi-agent-analysis-jira/SKILL.md +56 -6
  168. package/pipeline/skills/shared/core/multi-agent-autopilot/SKILL.md +6 -0
  169. package/pipeline/skills/shared/core/multi-agent-autopilot-off/SKILL.md +26 -44
  170. package/pipeline/skills/shared/core/multi-agent-design-check/SKILL.md +31 -127
  171. package/pipeline/skills/shared/core/multi-agent-doctor/SKILL.md +6 -0
  172. package/pipeline/skills/shared/core/multi-agent-estimate/SKILL.md +61 -0
  173. package/pipeline/skills/shared/core/multi-agent-kill/SKILL.md +14 -19
  174. package/pipeline/skills/shared/core/multi-agent-refactor/SKILL.md +7 -76
  175. package/pipeline/skills/shared/core/multi-agent-review/SKILL.md +6 -1
  176. package/pipeline/skills/shared/core/multi-agent-review-analysis/SKILL.md +6 -1
  177. package/pipeline/skills/shared/core/multi-agent-review-issue/SKILL.md +1 -1
  178. package/pipeline/skills/shared/core/multi-agent-review-jira/SKILL.md +1 -1
  179. package/pipeline/skills/shared/core/multi-agent-scenario-audit/SKILL.md +77 -0
  180. package/pipeline/skills/shared/core/multi-agent-serve/SKILL.md +6 -3
  181. package/pipeline/skills/shared/core/multi-agent-setup/SKILL.md +206 -324
  182. package/pipeline/skills/shared/core/multi-agent-store-ready/SKILL.md +5 -0
  183. package/pipeline/skills/shared/core/multi-agent-sync/SKILL.md +4 -4
@@ -1,40 +1,43 @@
1
1
  ---
2
2
  name: multi-agent-setup
3
3
  description: "First-run setup wizard: keychain token discovery, Git Identity onboarding, and pipeline preparation. Use when the pipeline is being set up for the first time, or tokens and git identity need onboarding."
4
+ argument-hint: "[jira-keys | hosts | accounts] - optional; no argument runs the whole onboarding"
4
5
  user-invocable: true
5
6
  metadata:
6
7
  language: en
7
8
  ---
8
9
 
10
+ `$HOME/.claude/multi-agent-refs/` ships with Claude Code.
11
+
12
+ ## Gotchas
13
+
14
+ - A token is read and written only through `~/.copilot/lib/credential-store.sh`. Never echo it, never pass it on argv, never paste it back to the user.
15
+ - A mapping in `keychainMapping` with no value in the store is not onboarded: offer the Token Save Flow, do not ask for the secret in chat.
16
+ - Hosts are stored without a scheme (`jira.example.com`); the callers add `https://`.
17
+ - Publishing tokens differ by registry: npmjs takes an npm token, GitHub Packages a classic PAT with `write:packages` from the account that owns the scope.
18
+
9
19
  ## Step 0 - What is actually wrong
10
20
 
11
21
  ```bash
12
- node "$HOME/.claude/scripts/doctor.mjs"
22
+ node "$HOME/.copilot/scripts/doctor.mjs"
13
23
  ```
14
24
 
15
- Run it before the first question and again at the end. The first run turns setup
16
- from a fixed script into a targeted one: there is no point asking for a token
17
- that is already mapped and answering. The second run is the only honest way to
18
- end - "setup complete" is a claim, and the doctor's exit code is the evidence for
19
- or against it. Report both in `outputLanguage`, and if the second run still shows
20
- a BLOCK, say so plainly rather than closing on the word "complete".
25
+ Run it before the first question and again at the end. The first run makes setup targeted: never ask for a token that is already mapped and answering. The second run is how setup ends - "setup complete" is a claim, and the doctor's exit code is the evidence. Report both in `outputLanguage`; if the second run still shows a BLOCK, say so plainly rather than closing on the word "complete".
21
26
 
22
- ## Setup (Keychain Token + Git Identity Onboarding)
27
+ ## Setup (Credential Store + Git Identity Onboarding)
23
28
 
24
- Self-contained setup - works with inline `security` commands, no external script **required**. If `$HOME/.claude/scripts/keychain-save.sh` exists, it can be used as an interactive alternative but is not mandatory. The `setup` command starts interactive onboarding.
29
+ Uses `~/.copilot/lib/credential-store.sh` to read/write secrets in the macOS Keychain (`security`, built in); the pipeline is macOS only (ADR-0012). Run `~/.copilot/lib/credential-store.sh doctor` first - it prints the platform and whether the backend is usable. The shell driver auto-delegates `get`/`set`/`delete` to the deterministic Python helper at `$HOME/.copilot/scripts/keychain.py` (Python 3 stdlib only, no external deps). The Python path writes both `-l` (label) and `-s` (service) attributes so items are findable regardless of how callers look them up. Set `KEYCHAIN_DELEGATE=0` to force the raw shell path.
25
30
 
26
31
  ### Step 0 - Language Selection
27
32
 
28
- Ask BEFORE anything else. The pipeline has two language fields:
33
+ Ask BEFORE anything else, so every subsequent setup prompt and the rest of the pipeline honour the choice. The pipeline has two language axes:
29
34
 
30
- | Field | Controls | Configurable? |
31
- |---|---|---|
32
- | `promptLanguage` | The picker's structural UI chrome only: the `AskUserQuestion` `header` chip, host error UI, internal contract identifiers | **No - fixed to `en`.** The chip is capped at 12 characters, which most Turkish equivalents overflow. |
33
- | `outputLanguage` | The assistant's non-interactive explanations, status updates, error messages, and pipeline-generated reports | Yes - set here, change later via `/multi-agent-language <en\|tr>` |
35
+ - `promptLanguage`: picker chrome only (the `AskUserQuestion` `header` chip, host error UI, internal contract identifiers). **Not configurable - fixed to `en`**; the chip is capped at 12 chars, which most Turkish equivalents overflow.
36
+ - `outputLanguage`: the assistant's non-interactive explanations, status updates, error messages and pipeline-generated reports. Set here, changeable later via `/multi-agent-language <en|tr>`.
34
37
 
35
- `promptLanguage` is seeded as `"en"` and never offered to the user. External payloads (commits, PR/Jira/wiki, reviewer/triage prompts, agent-log.md) always stay English regardless.
38
+ `promptLanguage` is seeded as `"en"` and never offered to the user. **External payloads always stay English** (commits, PR titles/bodies, Jira comments, wiki content, reviewer/triage prompts, agent-log.md).
36
39
 
37
- **Step 0 - outputLanguage** (English UI per skill-prompt rules):
40
+ The wizard asks one question (English UI per skill-prompt rules):
38
41
 
39
42
  ```
40
43
  Which language should the assistant use for ITS OWN explanations,
@@ -46,62 +49,39 @@ Select (1-2):
46
49
 
47
50
  **Rules:**
48
51
 
49
- - Already set in prefs → skip silently. Change later via `/multi-agent-language <en|tr>` or `/multi-agent-language output <en|tr>`.
50
- - New value → validate against `["en", "tr"]`, atomic write to `prefs.global.outputLanguage`, force `prefs.global.promptLanguage = "en"`, echo confirmation in the chosen `outputLanguage`.
51
- - Unknown input → re-ask once, then abort with a hint pointing to `/multi-agent-language`.
52
+ - **Already set in prefs** → skip silently. User can change later with `/multi-agent-language <en|tr>` or `/multi-agent-language output <en|tr>`.
53
+ - **New value** → validate against the schema enum (`en`, `tr`), write `prefs.global.outputLanguage` via atomic rename, force `prefs.global.promptLanguage = "en"`, then echo a confirmation in the just-chosen `outputLanguage`:
54
+ - `en`: `outputLanguage=<Y>. promptLanguage stays "en". External payloads (PR bodies, Jira comments, reviewer prompts) stay English regardless.`
55
+ - `tr`: `outputLanguage=<Y>. promptLanguage "en" sabit. Dış çıktılar (PR açıklamaları, Jira yorumları, review istemleri) her durumda İngilizce kalır.`
56
+ - **Unknown input** → re-ask once, then abort setup with a hint pointing to `/multi-agent-language`.
52
57
 
53
- ### Step 1 - Dynamic Keychain Discovery
58
+ From here on, every prompt in Steps 1-6 follows the per-field matrix in
59
+ `$HOME/.claude/multi-agent-refs/rules.md` ("Language Application"): `question`, `label`
60
+ and `description` render in `outputLanguage`, `header` stays English; wizard status and
61
+ the post-setup summary follow `outputLanguage`. `promptLanguage` governs only the button
62
+ and chip chrome, never the question a user reads.
54
63
 
55
- Instead of checking only hardcoded key names, discover ALL user keys and intelligently map them to services.
64
+ ### Step 0.5 - Dependency check
56
65
 
57
- **1a. Discover all keys:**
58
66
  ```bash
59
- DISCOVERED=$(security dump-keychain 2>/dev/null | grep '"svce"' | awk -F'"' '{print $4}' | grep -i "^${USER}" | sort -u)
60
- echo "$DISCOVERED"
67
+ ~/.copilot/lib/credential-store.sh doctor
68
+ command -v pdftotext >/dev/null 2>&1 || echo "pdftotext: MISSING"
61
69
  ```
62
70
 
63
- **1b. Standard key names (convention):**
64
-
65
- These are the RECOMMENDED key names. When creating NEW keys, use these. But existing keys under different names are perfectly valid - the discovery step will find them.
66
-
67
- | Service ID | Standard Key Name | Search Keywords |
68
- |------------|------------------|-----------------|
69
- | `jira` | `${USER}_Jira_Access_Token` | `jira` |
70
- | `bitbucket_token` | `${USER}_Bitbucket_Access_Token` | `bitbucket` + (`token` or `access` or `pass`) |
71
- | `bitbucket_user` | `${USER}_Bitbucket_Username` | `bitbucket` + (`user` or `name`) |
72
- | `github` | `${USER}_Github_Access_Token` | `github` or `gh` (exclude `ssh`) |
73
- | `confluence` | `${USER}_Confluence_Access_Token` | `confluence` |
74
- | `figma` | `${USER}_Figma_Access_Token` | `figma` + NOT `mcp` |
75
- | `figma_mcp` | `${USER}_Figma_Mcp_Access_Token` | `figma` + `mcp` |
76
- | `fortify` | `${USER}_Fortify_Access_Token` | `fortify` |
77
- | `firebase` | `${USER}_Firebase_Access_Json` | `firebase` (any variant: `sa`, `service`, `account`, `access`, `json`) |
78
- | `jenkins` | `${USER}_Jenkins_Access_Token` | `jenkins` |
79
- | `appstore_connect_private_key` | `${USER}_AppStoreConnect_Private_Key` | (`appstore` or `asc` or `app_store`) + (`private` or `p8`) |
80
- | `google_play` | `${USER}_GooglePlay_Access_Json` | (`googleplay` or `google_play` or `play_console` or `play`) + (`service` or `account` or `access` or `json` or `console`), NOT `firebase` |
81
-
82
- **1c. Resolution logic (per service):**
83
-
84
- For each service in the table above, follow this order:
85
-
86
- 1. **Check standard key** -> `~/.copilot/lib/credential-store.sh get "<standard_key>" 2>/dev/null`
87
- - Found -> auto-map, done
88
- 2. **Search discovered keys** -> filter `$DISCOVERED` by the service's search keywords (case-insensitive)
89
- - Exactly 1 match -> show: `"Found '${matched_key}' for ${service} - use this? (enter=yes / n=skip)"` -> if yes, map it
90
- - Multiple matches -> show numbered list, user picks:
91
- ```
92
- Multiple keys found for GitHub:
93
- 1. ${USER}_Github
94
- 2. ${USER}_Github_Access_Token_Old
95
- 3. ${USER}_Github_Access_Token
96
- Select [number] or skip:
97
- ```
98
- - 0 matches -> MISSING
99
-
100
- **1d. Check preferences for existing mapping:**
101
-
102
- Before running discovery, check `prefs.global.keychainMapping`. If a mapping already exists for a service AND the mapped key still exists in Keychain -> skip discovery for that service (show as already mapped from preferences).
103
-
104
- If a previously mapped key NO LONGER exists in Keychain -> clear the stale mapping, re-run discovery for that service.
71
+ | Output | Action |
72
+ |--------|--------|
73
+ | `Backend: ✓` | Continue to Step 1 |
74
+ | Platform `unknown` or `ERR: macOS only` | Halt - the pipeline runs on macOS only (ADR-0012). |
75
+ | `pdftotext: MISSING` | Advisory. Print `brew install poppler`, continue. `.docx` needs nothing. |
76
+
77
+ ### Credential Key Naming Rule
78
+
79
+ - **New token** (first-time creation in Step 3): ALWAYS use the standard key name (`${USER}_Jira_Access_Token`, etc.). This ensures cross-machine consistency.
80
+ - **Existing token** (discovered in Step 1): NEVER rename or migrate. Map the discovered key name as-is into `keychainMapping`. The mapping layer abstracts the actual key name - the pipeline never reads the credential store directly by standard name.
81
+
82
+ ### Step 1 - Dynamic Credential Discovery
83
+
84
+ Full procedure: `$HOME/.claude/multi-agent-refs/setup/discovery.md`. Read it for Step 1.
105
85
 
106
86
  ### Step 2 - Show Discovery Summary + Save Mapping
107
87
 
@@ -122,317 +102,204 @@ Keychain Token Discovery (${USER}):
122
102
  Mapped: 8 | Missing: 4
123
103
  ```
124
104
 
125
- Save the resolved mapping to preferences:
105
+ Save the resolved mapping to `prefs.global.keychainMapping` - every service ID gets an entry, the discovered key name verbatim or `null` when nothing was found:
106
+
126
107
  ```json
127
- {
128
- "global": {
129
- "keychainMapping": {
130
- "jira": "${USER}_Jira_Access_Token",
131
- "bitbucket_token": "${USER}_Bitbucket_Access_Token",
132
- "bitbucket_user": "${USER}_Bitbucket_Username",
133
- "github": "${USER}_Github",
134
- "confluence": null,
135
- "figma": "${USER}_Figma_Access_Token",
136
- "figma_mcp": "${USER}_Figma_Mcp_Access_Token",
137
- "fortify": null,
138
- "firebase": "${USER}_Firebase_Access_Json",
139
- "jenkins": null
140
- }
141
- }
142
- }
108
+ { "jira": "${USER}_Jira_Access_Token", "github": "${USER}_Github", "confluence": null, "...": "..." }
143
109
  ```
144
110
 
111
+ Full key list and shape: `$HOME/.claude/multi-agent-refs/keychain.md`.
112
+
145
113
  `null` = not mapped (missing or skipped). Pipeline phases read this mapping to retrieve tokens dynamically - never hardcoded key names.
146
114
 
147
115
  ### Step 2.7 - Operational reporting
148
116
 
149
- ```bash
150
- node "$HOME/.claude/scripts/usage-register.mjs"
151
- ```
117
+ Ask (in `outputLanguage`), and proceed only on an explicit yes:
152
118
 
153
- Requests a per-machine **write-only** token when none resolves, stores it in the
154
- credential store only, and switches reporting on. Registration used to happen
155
- only in update, so a machine that ran setup and nothing else never reported at
156
- all. `usageLog.optOut: true` blocks it permanently; an unreachable endpoint
157
- leaves reporting off with one line. Contract:
158
- `$HOME/.claude/multi-agent-refs/features/usage-reporting.md`.
159
-
160
- ### Step 3 - Jira Project Key (auto-learned)
161
-
162
- Jira project keys are NOT asked during setup. They are auto-learned from pipeline usage:
163
- - User runs `/multi-agent ABC-123` → `ABC` is extracted and saved to `prefs.global.defaultJiraKey` (first ever) and `prefs.projects[{project}].jiraProjectKeys` (per-project).
164
- - User later runs `/multi-agent MOBILE-456` in a different project → `MOBILE` is added to that project's keys.
165
- - Multiple keys accumulate over time - most recent first, deduped.
119
+ ```
120
+ Do you have an operational-reporting token from your admin?
121
+ [ Paste token / Skip ]
122
+ ```
166
123
 
167
- Phase 0 Step 1 (Parse Input) handles extraction and persistence. No setup interaction needed.
124
+ On paste, store it in the credential store ONLY - never in a file, prefs value,
125
+ git or any synced tree - under the standard per-user name, so it is revocable on
126
+ its own:
168
127
 
169
- ### Step 4 - Git Identity Setup (one-time)
128
+ ```bash
129
+ pbpaste | ~/.copilot/lib/credential-store.sh set "${USER}_Usage_Ingest_Token" -
130
+ pbcopy < /dev/null
131
+ ```
170
132
 
171
- Git identities are NOT secrets - stored in the preferences file, not Keychain:
133
+ Then, **whether they pasted or skipped**, run:
172
134
 
173
135
  ```bash
174
- PREFS_FILE="$HOME/.claude/multi-agent-preferences.json"
136
+ node "$HOME/.copilot/scripts/usage-register.mjs"
175
137
  ```
176
138
 
177
- If no identities exist in `prefs.global.gitIdentities` (first run):
178
- ```
179
- Let's set up git identity.
139
+ It maps whatever token exists and switches reporting on, and requests a
140
+ per-machine write-only one when none resolves. Setup is a registration entry point
141
+ in its own right, so a machine that runs setup and never runs update still reports.
142
+ What is sent, what never is, and `usageLog.optOut`:
143
+ `$HOME/.claude/multi-agent-refs/features/usage-reporting.md`.
180
144
 
181
- Identity 1 (corporate):
182
- Author name: ___
183
- Email: ___
184
- ```
145
+ ### Auto-learned fields (no setup step needed)
185
146
 
186
- After each identity, ask with a native `AskUserQuestion` picker (never a typed y/n):
187
- - `question`: "Add another git identity?" (rendered in `outputLanguage`)
188
- - `header`: "Identity" (English, <=12 chars)
189
- - `options`:
190
- - `{ label: "Add another", description: "Collect one more name + email identity" }`
191
- - `{ label: "Done", description: "Finish identity setup and save" }`
147
+ **Jira Project Key**: auto-learned from pipeline usage. User runs `/multi-agent ABC-123` → `ABC` is extracted and saved to `prefs.global.defaultJiraKey` (first ever) and `prefs.projects[{project}].jiraProjectKeys` (per-project). Multiple keys accumulate over time - most recent first, deduped. Phase 0 Step 1 (Parse Input) handles extraction.
192
148
 
193
- **Add another** → collect the next identity (e.g. Identity 2, personal: author name + email), then re-ask. **Done** → save.
149
+ **Git Identity**: auto-learned from token onboarding. Each token saved in Step 3 triggers an identity prompt (see Token Save Flow Step C). No separate identity setup step.
194
150
 
195
- Save to preferences JSON:
196
- ```json
197
- {
198
- "global": {
199
- "gitIdentities": [
200
- {"name": "AUTHOR_NAME", "email": "AUTHOR_EMAIL"},
201
- {"name": "AUTHOR_NAME_2", "email": "AUTHOR_EMAIL_2"}
202
- ]
203
- }
204
- }
205
- ```
151
+ ### Step 3 - Interactive token onboarding (for missing tokens)
152
+
153
+ Git identities are NOT asked as a separate step. They are learned when tokens are added via the Token Save Flow below. Each token save triggers an identity prompt:
206
154
 
207
- Show result:
208
155
  ```
209
- Git Identities (saved to preferences):
210
- 1. {Full Name - Organization} <{corporate@email.com}>
211
- 2. {Full Name} <{personal@email.com}>
156
+ Token saved. Which git identity uses this token?
157
+ 1. Ada Lovelace <ada@example.com>
158
+ 2. Ada Lovelace <ada@personal.com>
159
+ n. Create new identity
160
+ Select:
212
161
  ```
213
162
 
214
- ### Step 5 - Interactive token onboarding (for missing tokens)
163
+ - First token ever → no existing identities → asks name + email → creates identity → maps token
164
+ - Subsequent tokens → pick existing or create new → maps token to that identity's `servicePatMap`
165
+ - Multiple accounts per platform supported (e.g. two GitHub tokens, each mapped to a different identity)
166
+ - Identity is stored in `prefs.global.identities[]`, token-to-identity binding in `identity.servicePatMap`
215
167
 
216
- For each MISSING service, run the **Token Save Flow** (see `setup.md` for full spec).
168
+ **Legacy compatibility**: If `prefs.global.gitIdentities` (deprecated) is present, `migrate-prefs.mjs` renames it to `identities` automatically.
217
169
 
218
- Summary: ask `[1] Add now / [2] Skip` → if add, user copies token to clipboard, presses Enter → pipeline reads from clipboard via `pbpaste`, saves to Keychain, clears clipboard. Token never appears in terminal.
170
+ For each MISSING service, run the **Token Save Flow** below. When creating new tokens, use the **standard key name** from Step 1b table.
219
171
 
220
- The same flow is reused at Phase 0 runtime when a token is expired (401/403).
172
+ #### Sequential onboarding loop (strict)
221
173
 
222
- ### Step 6 - Verify all
174
+ The Step 2 discovery summary is never the end of setup. Immediately after showing it, walk the missing services ONE BY ONE in this fixed order and run the Token Save Flow for each:
223
175
 
224
- Re-run scan from Step 1. Show final status:
225
- ```
226
- All tokens present. Pipeline ready to use.
227
-
228
- Optional per-project features (configured on first use, nothing to do now):
229
- • Phase 5 Report Step 2 Wiki - auto-generates component wiki pages + Figma
230
- screenshots. Activates when (a) task is a component AND (b) a Figma token
231
- is in Keychain. Four adapters supported: submodule / in-repo / github-wiki
232
- / separate-repo. First run asks: use auto-detected path, use a custom
233
- path, skip once, or disable for this project (persisted).
234
- • channels - post-hoc multi-channel reporter (Jira/Confluence/Wiki/PR), works on any branch with an open PR. v5.7+ replaces the older `enrich` command.
235
- • Default reviewers - auto-fetched from Bitbucket default-reviewers endpoint
236
- or GitHub CODEOWNERS on first PR.
237
-
238
- Next step:
239
- /multi-agent "PROJ-12345" -> start your first task
240
- /multi-agent help -> full usage guide
241
- ```
176
+ 1. `jira`
177
+ 2. `bitbucket_token` (then `bitbucket_user` right after, if missing)
178
+ 3. `github`
179
+ 4. `confluence`
180
+ 5. `figma` - Figma Personal Access Token (Tier 2, REST)
181
+ 6. `figma_mcp` - Figma MCP auth (Tier 1); its own prompt, never folded into the PAT prompt
182
+ 7. `fortify`
183
+ 8. `graylog`
184
+ 9. `firebase`
185
+ 10. `jenkins`
186
+ 11. App Store Connect block (Step 3b; only when the target repo is iOS)
187
+ 12. Google Play block (Step 3d; only when the target repo is Android)
242
188
 
243
- If still missing, show which ones and let user skip (pipeline will re-ask for any needed token at Phase 0).
189
+ Loop rules:
244
190
 
245
- ### Token -> Source Mapping
246
-
247
- Standard key names (used when creating NEW tokens). Discovery may find existing keys under different names - that's fine, the mapping in preferences handles it.
248
-
249
- | Service ID | Standard Key Name | Type | Where to Get |
250
- |------------|------------------|------|---------------|
251
- | `jira` | `${USER}_Jira_Access_Token` | PAT | Jira -> Profile -> Personal Access Tokens (VPN required) |
252
- | `bitbucket_token` | `${USER}_Bitbucket_Access_Token` | App Password | Bitbucket -> Personal settings -> App passwords |
253
- | `bitbucket_user` | `${USER}_Bitbucket_Username` | Plain text | Bitbucket profile username |
254
- | `github` | `${USER}_Github_Access_Token` | PAT | GitHub Settings -> Tokens (scopes: repo, read:org, project) |
255
- | `confluence` | `${USER}_Confluence_Access_Token` | PAT | Confluence -> Profile -> Personal Access Tokens (VPN required) |
256
- | `figma` | `${USER}_Figma_Access_Token` | PAT | Figma Developer Settings (max 90 days) |
257
- | `figma_mcp` | `${USER}_Figma_Mcp_Access_Token` | OAuth | Automatic via Claude Code Figma MCP remote auth |
258
- | `fortify` | `${USER}_Fortify_Access_Token` | API Token | Fortify SSC -> Token Management (VPN required) |
259
- | `firebase` | `${USER}_Firebase_Access_Json` | Firebase service-account JSON | Firebase Console -> Project settings -> Service accounts -> Generate new private key. Store the file as issued; project id is read straight out of it. |
260
- | `jenkins` | `${USER}_Jenkins_Access_Token` | API Token | Jenkins -> User -> Configure -> API Token |
261
- | `appstore_connect_private_key` | `${USER}_AppStoreConnect_Private_Key` | Full PEM text of `AuthKey_<keyId>.p8` | App Store Connect -> Users and Access -> Integrations -> App Store Connect API. Stored from the file via stdin after `probe-store-key.mjs --asc` accepts it |
262
- | `google_play` | `${USER}_GooglePlay_Access_Json` | Service-account JSON, as issued | Play Console -> Setup -> API access. Stored from the file via stdin after `probe-store-key.mjs --play` accepts it |
263
- | - | Git Identities | JSON (preferences) | Stored in `$HOME/.claude/multi-agent-preferences.json` - not Keychain |
191
+ - **One prompt per service.** Never collapse the list into a single "add missing tokens now?" yes/no, and never offer one multi-select covering all services: each service has its own source URL, key name, identity binding and host prompt, so each gets its own Token Save Flow pass.
192
+ - **Each service pass asks, in order: token → author → host.** Step A/B collect the secret, Step C binds the git identity (author) - Bitbucket and GitHub included; every saved token gets an author - and Step 3.5 asks the host domain inline for hosted services (jira, confluence, bitbucket, fortify, graylog) - plus the Fortify project versions and the optional Graylog test instance. GitHub and Figma skip the host question (fixed domains); `bitbucket_user` skips author binding (username, not a PAT). Never end a service pass with the token saved but the author or a required host unasked.
193
+ - **Skip is per-service.** A Skip answer leaves that service's `keychainMapping` at `null` and the loop continues with the next service. Skips never abort the loop.
194
+ - **`figma` and `figma_mcp` are distinct credentials for distinct tiers - ask both.** Skipping the PAT does not imply skipping MCP, and vice versa. The `figma_mcp` pass opens with a Remote / Local mode question instead of a clipboard paste (see "Figma MCP Setup" below): Remote generates a `figu_` OAuth token for the current user, Local wires the PAT-based local server.
195
+ - The loop ends only when every missing service has been asked exactly once; then continue to Step 4 (Verify all).
264
196
 
265
- ### Inline Token Save Pattern
197
+ ---
266
198
 
267
- All tokens go through `~/.copilot/lib/credential-store.sh`, which wraps the macOS Keychain and auto-delegates to `~/.copilot/scripts/keychain.py`. The Python path writes both `-l` (label) and `-s` (service) attributes so existing manually-added entries with either convention remain findable.
199
+ ### Token Save Flow (reusable)
268
200
 
269
- ```bash
270
- # PAT / API Key (from clipboard)
271
- pbpaste | ~/.copilot/lib/credential-store.sh set "<SERVICE_NAME>" -
272
- pbcopy < /dev/null # clear clipboard
201
+ Full procedure: `$HOME/.claude/multi-agent-refs/setup/token-save-flow.md`. Read it for every token prompt (Steps 3, 3b, 3c and any command that saves a token).
273
202
 
274
- # Non-secret value typed inline (a secret on argv is visible to ps and lands in shell history)
275
- ~/.copilot/lib/credential-store.sh set "<SERVICE_NAME>" "<VALUE>"
203
+ ### Step 3b - App Store Connect onboarding (iOS only, optional)
276
204
 
277
- # JSON file (stored as issued - the store round-trips newlines byte-exactly)
278
- ~/.copilot/lib/credential-store.sh set "<SERVICE_NAME>" - < /path/to/file.json
205
+ Runs inside Step 3. Every part of the API key lives in the Keychain, the `.p8` included: ask for the `.p8` as a path, validate it BEFORE saving with `node "$HOME/.copilot/scripts/probe-store-key.mjs" --asc ...` (exit 0 only), map `appstore_connect_private_key`, store it from the file with `credential-store.sh set appstore_connect_private_key - < <AuthKey_<keyId>.p8>`, run `node "$HOME/.copilot/scripts/write-store-config.mjs"`, then offer (picker, default keep) to delete the file. `store_asc_*` and `ios_testflight_validate` then read the key from the Keychain. The five entries, the tier picker and the probes: `$HOME/.claude/multi-agent-refs/setup/app-store-connect.md`. On Skip, nothing is written.
279
206
 
280
- # Read
281
- ~/.copilot/lib/credential-store.sh get "<SERVICE_NAME>"
282
- ```
207
+ ### Step 3c - Firebase / Crashlytics onboarding (optional)
283
208
 
284
- For maximum stdin hygiene (the secret never lands on argv / shell history), use the Python helper directly with the `-` sentinel:
209
+ Runs inside Step 3. Measure first - `bash "$HOME/.copilot/lib/fetch-crashlytics.sh" --probe` answers `tier-1-ready` / `tier-1-no-grant` / `malformed` / `unreachable` - then ask by that answer, never blind. Store the Firebase service-account JSON as issued; never base64 it. Skip writes nothing. Then offer appId discovery: `bash "$HOME/.copilot/scripts/firebase-app-discovery.sh" <repo> --json` reads the pairs the repo already carries, for `firebase.accounts[].apps[]` - it saves a round trip per run; skipping costs nothing. The picker, both tiers, the role-request wording and the v1alpha caveat: `$HOME/.claude/multi-agent-refs/setup/firebase.md`.
285
210
 
286
- ```bash
287
- pbpaste | ~/.copilot/scripts/keychain.py set "<SERVICE_NAME>" -
288
- ```
211
+ ### Step 3d - Google Play onboarding (Android only, optional)
289
212
 
290
- ### Figma MCP Setup (optional)
213
+ Runs inside Step 3, only when the target repo is Android. One entry, `google_play`: the service-account JSON the toolkit's `store_play_*` tools use, which lets `/multi-agent-store-ready` run Android Gate 2. Ask for the JSON's path, validate BEFORE saving with `node "$HOME/.copilot/scripts/probe-store-key.mjs" --play --service-account <path>`, map `google_play`, then `credential-store.sh set google_play - < <path>` and `write-store-config.mjs`. Account prerequisites, the picker and the probe hints: `$HOME/.claude/multi-agent-refs/setup/google-play.md`. Skip writes nothing.
291
214
 
292
- Figma MCP works in two modes:
215
+ ### Step 3.5 - Host Prompt (embedded in Token Save Flow)
293
216
 
294
- **Remote MCP** (Claude Code built-in):
295
- - Automatic - comes as `claude_ai_Figma` in Claude Code settings.json
296
- - If token renewal needed: re-auth from within Claude Code
217
+ Full procedure: `$HOME/.claude/multi-agent-refs/setup/token-save-flow.md`. Read it for the host question inside the Token Save Flow.
297
218
 
298
- **Local MCP** (@anthropic-ai/figma-mcp package, with PAT):
299
- ```bash
300
- # 1. Save PAT to keychain (stdin sentinel keeps the value off argv)
301
- pbpaste | ~/.copilot/scripts/keychain.py set "${USER}_Figma_Access_Token" -
302
- pbcopy < /dev/null
219
+ ### Step 3.6 - Per-account host overrides (optional)
303
220
 
304
- # 2. Add MCP to Claude Code settings.json
305
- # ~/.claude/settings.json -> mcpServers -> figma
306
- ```
221
+ **Runs only when** `~/.copilot/lib/account-resolver.sh` returns **more than one** account AND at least one account has Jira or Bitbucket tokens.
307
222
 
308
- ### App Store Connect Credentials (optional, iOS only)
223
+ Use case: one user with two identities (e.g. agency + client), each with its own Jira host; `prefs.global.hosts.jira` holds only one default.
309
224
 
310
- Unlocks Gate 2 of `multi-agent-testflight-validation` - Apple's own
311
- `altool --validate-app`, the only check that sees an unregistered bundle ID, a
312
- profile that does not match the App Store Connect app record, or a version+build
313
- pair already used. Skipping is a first-class answer: the validation command still
314
- runs its static audit and guideline review and reports Gate 2 as `SKIPPED` with
315
- the reason, never as a pass.
225
+ For each non-default account, ask once: "Account {label} has Jira/Bitbucket tokens but no host override yet. Use the global default ({hosts.jira}) or set a per-account host?" with options **1) Use global default** / **2) Set per-account host**. On `2`, prompt for `jiraHost` / `bitbucketHost` / `confluenceHost` (each optional) and save to `prefs.global.accounts[]`, e.g. `{ "id": "client-x", "jiraHost": "jira.client-x.example.com", "bitbucketHost": "bitbucket.client-x.example.com" }`.
316
226
 
317
- Ask (picker): **API key** / **Apple ID + app-specific password** / **Skip**.
227
+ `account-resolver.sh` reads this on every invocation; per-account override wins over `global.hosts.*`. Skip this step on autopilot - `accounts[]` stays empty until the user opts in via `/multi-agent-setup accounts`, which opens this editor without re-running token discovery.
318
228
 
319
- **API key** - needs an Admin or App Manager role in App Store Connect. Every part
320
- lives in the Keychain, the `.p8` included. Map the key id and issuer id as
321
- `appstore_connect_key_id` / `appstore_connect_issuer_id` (identifiers, stored as
322
- plain values). Ask for the `.p8` as a path, never its contents, and validate it
323
- BEFORE saving:
229
+ ---
324
230
 
325
- ```bash
326
- node "$HOME/.copilot/scripts/probe-store-key.mjs" --asc \
327
- --key-id "<key id>" --issuer-id "<issuer id>" --p8 "<path to AuthKey_<keyId>.p8>"
328
- ```
231
+ ### Step 4 - Verify all
329
232
 
330
- It prints `{ok, store, status, hint}` and no key material. On exit 1 show the
331
- `hint` (`401`: key id / issuer id do not match this `.p8`, the key was revoked, or
332
- the clock is off; `403`: the key's role cannot read apps) and save nothing. On
333
- exit 0, map `appstore_connect_private_key` first (`set` resolves the logical key
334
- through the mapping), then store the file through stdin and write the toolkit's
335
- store reference file:
233
+ Re-run scan from Step 1. Show final status:
234
+ `All tokens present. Pipeline ready to use.` Then list the optional per-project features (configured on first use, nothing to do now): **Phase 5 Report Step 2 Wiki** (component wiki pages + Figma screenshots; activates when the task is a component AND a Figma token is in Keychain; adapters submodule / in-repo / github-wiki / separate-repo; first run asks: auto-detected path, custom path, skip once, or disable for this project, persisted); **channels** (post-hoc multi-channel reporter for Jira/Confluence/Wiki/PR, any branch with an open PR); **Default reviewers** (auto-fetched from the Bitbucket default-reviewers endpoint or GitHub CODEOWNERS on first PR). Next step: `/multi-agent "PROJ-12345"` to start a first task, `/multi-agent-help` for the full usage guide.
336
235
 
337
- ```bash
338
- ~/.copilot/lib/credential-store.sh set appstore_connect_private_key - < "<path to AuthKey_<keyId>.p8>"
339
- node "$HOME/.copilot/scripts/write-store-config.mjs"
340
- ```
236
+ If still missing, show which ones and let user skip (pipeline will re-ask for any needed token at Phase 0).
341
237
 
342
- Then offer (picker, default **Keep file**) to delete the `.p8` from disk; Apple
343
- does not let it be downloaded again, so the choice is the user's. The toolkit's
344
- `store_asc_*` tools and `ios_testflight_validate` (called with neither
345
- `api_key_id` nor `apple_id`) read the key from the Keychain through that
346
- reference file.
238
+ ### Step 5 - Repo Discovery (optional)
347
239
 
348
- **Apple ID + app-specific password** - usable by **any Apple ID holder, no elevated
349
- role**, which is the realistic path when API-key creation is not permitted on the
350
- account. Lead with this option when the user says they cannot create an API key.
351
- The password goes into Apple's own keychain helper, which is what
352
- `altool -p @keychain:<item>` reads - never into chat, never into an argument:
240
+ Pre-populates the Phase 0 project picker with repos the user is active in, merging three independent sources: local `$HOME` scan (depth 3, repo markers), Bitbucket (last 90 days, token-gated), GitHub (owner + collaborator, push in last 90 days, token-gated). A failing source skips only itself and is reported (never swallowed); discovery is idempotent and never destructive.
353
241
 
354
- ```bash
355
- # export AC_PASSWORD_ONCE in your own shell first, for this one command
356
- xcrun altool --store-password-in-keychain-item "<item-name>" \
357
- -u "<apple-id>" -p @env:AC_PASSWORD_ONCE
358
242
  ```
243
+ Step 5 - Repo Discovery (optional)
244
+ Scan for recent repos now to pre-populate the Phase 0 picker?
359
245
 
360
- Map only the ITEM NAME as `appstore_connect_password_item`, plus the Apple ID as
361
- `appstore_connect_apple_id`. The password stays in the keychain and is referenced,
362
- never read by the pipeline.
246
+ y - all three (local + Bitbucket + GitHub, ~10-30s)
247
+ l - local scan only (fastest, no network)
248
+ n - skip (Phase 0 will prompt for repo path manually)
249
+ ```
363
250
 
364
- **Multi-provider accounts.** A corporate Apple ID often belongs to several
365
- providers and altool fails opaquely without one. Resolve it once with
366
- `ios_testflight_validate({list_providers: true, ...})` and store the id under
367
- `prefs.projects[<key>].appStoreConnect.providerPublicId` - per-project, since a
368
- user can ship for more than one team.
251
+ The scan commands, merge-by-origin dedup, the multi-select picker, the `recentProjects` / `serviceStatus` prefs shapes and the skip / degrade rules live in `$HOME/.claude/multi-agent-refs/setup/repo-discovery.md` - read that file when the user opts in.
369
252
 
370
- A credential that resolves but is rejected (401/403) follows the Expired-token
371
- decision (Regenerate / Use a different token / Skip and continue) rather than
372
- being silently dropped.
253
+ ### Step 6 - Remember as Multi-Repo Group (optional)
373
254
 
374
- ### Google Play Credentials (optional, Android only)
255
+ After Step 5, if the user picked **2 or more** repos, offer to remember the combination as a named group; Phase 0's project picker surfaces saved groups at the top, so a multi-repo task becomes a single keypress next time. Auto-skipped if Step 5 was skipped or fewer than 2 repos were selected (single-repo selection is a no-op).
375
256
 
376
- Asked only when the target repo is Android, as the App Store Connect block is asked
377
- only for iOS. One entry, `google_play`: the service-account JSON the toolkit's
378
- `store_play_*` tools authenticate with. With it, `multi-agent-store-ready` hands
379
- Android Gate 2 to Google instead of reporting it `SKIPPED`.
257
+ ```
258
+ Step 6 - Remember as a multi-repo group (optional)
259
+ You picked 2 repos: Checkout, UIComponents.
260
+ Save this combo for one-tap selection in Phase 0?
261
+ Group name (Enter for auto): [Checkout + UIComponents]
262
+ Skip with 'n'.
263
+ ```
380
264
 
381
- Ask (picker): **Add Google Play** / **Skip**. Before asking for the file, say what
382
- the account needs: Play Console -> Setup -> API access (link a Cloud project,
383
- create the service account, download its JSON key); Play Console -> Users and
384
- permissions (invite the account's `client_email` with app permissions); and the
385
- **Google Play Android Developer API** plus the **Google Play Developer Reporting
386
- API** enabled in that Cloud project.
265
+ - **Auto-name** (suggested, editable): 2 repos `"<repoA> + <repoB>"`; 3-4 repos `"<repoA>, <repoB>, <repoC>(+1)"`; 5+ repos `"<repoA> + <count-1> more"`. Labels use the human label from `recentProjects` (path basename, not the full path).
266
+ - **Save** to schema `global.recentGroups[]` (`repos` required, `label` / `count` / `lastUsed` optional), e.g. `{ "label": "Checkout + UIComponents", "repos": ["~/dev/Checkout", "~/dev/UIComponents"], "count": 1, "lastUsed": "2026-04-15T21:08:00Z" }`.
267
+ - **LRU + dedup**: a new group is unshifted to the front. The same set of `repos` (order-independent compare) bumps the existing entry to the front, increments `count`, updates `lastUsed`; do NOT create a duplicate. Schema cap is 10 entries; the oldest past the cap are dropped.
268
+ - **`n`** → not saved; the picker still works for one-time use, and a future Phase 0 selection of the same combo re-prompts.
387
269
 
388
- Ask for the JSON's path, never its contents. Validate BEFORE saving:
270
+ ### Step 7 - Platform Identity Routing (optional)
389
271
 
390
- ```bash
391
- node "$HOME/.copilot/scripts/probe-store-key.mjs" --play --service-account "<path to service-account.json>"
392
- ```
272
+ Full procedure: `$HOME/.claude/multi-agent-refs/setup/identity-routing.md`. Read it for Step 7.
393
273
 
394
- On exit 1 show the `hint` and save nothing: `403` with `SERVICE_DISABLED` means an
395
- API is off in the Cloud project; any other `403` means the account is not invited
396
- in Play Console. On exit 0, map `google_play` first, then:
274
+ ### Cross-Platform Notes (Step 1-9) and Token -> Source Mapping
397
275
 
398
- ```bash
399
- ~/.copilot/lib/credential-store.sh set google_play - < "<path to service-account.json>"
400
- node "$HOME/.copilot/scripts/write-store-config.mjs"
401
- ```
276
+ Every read and write goes through `~/.copilot/lib/credential-store.sh`, which wraps the macOS Keychain; stay on the helper rather than calling `security` directly. Clipboard handling and the no-backend case: `$HOME/.claude/multi-agent-refs/keychain.md` "Credential store mechanics". Standard key names are a convention for NEW tokens; the key names, token types and where to generate each one live in `$HOME/.claude/multi-agent-refs/keychain.md` "Standard key names". Git identities are stored in preferences, never in the credential store.
402
277
 
403
- ### Firebase / Crashlytics Access (optional, any platform)
278
+ ### Inline Token Save Pattern
404
279
 
405
- Discovery maps a stored service-account JSON like any other credential, but it
406
- cannot see the thing that decides whether Crashlytics is readable: a freshly
407
- generated `firebase-adminsdk-*` account authenticates perfectly and holds no
408
- Crashlytics role. Measure it, do not assume it:
280
+ All tokens go through `~/.copilot/lib/credential-store.sh` (auto-delegates to `~/.copilot/scripts/keychain.py`, see Setup above).
409
281
 
410
282
  ```bash
411
- bash "$HOME/.claude/lib/fetch-crashlytics.sh" --probe
412
- ```
283
+ # PAT / API Key / JSON contents (from clipboard)
284
+ pbpaste | ~/.copilot/lib/credential-store.sh set "<SERVICE_NAME>" -
285
+ pbcopy < /dev/null # clear clipboard
286
+
287
+ # Non-secret value typed inline (a secret on argv is visible to ps and lands in shell history)
288
+ ~/.copilot/lib/credential-store.sh set "<SERVICE_NAME>" "<VALUE>"
413
289
 
414
- Ask (picker): **Complete tier 1** / **Set up tier 2** / **Skip**.
290
+ # Key file from disk (the .p8, the Google Play JSON; or when the clipboard is unavailable)
291
+ ~/.copilot/lib/credential-store.sh set "<SERVICE_NAME>" - < /path/to/file.json
415
292
 
416
- **Tier 1 - service account.** Store the JSON exactly as Firebase Console issued
417
- it; it is multi-line and the store round-trips it byte for byte. Never base64 it -
418
- a wrapper on the way in that nothing unwraps on the way out is how this path
419
- stayed broken. When the probe says `tier-1-no-grant`, the fix is one line to an
420
- Owner: grant `roles/firebasecrashlytics.viewer` on the project to that service
421
- account. Read-only, and narrower than `roles/firebase.viewer`.
293
+ # Read - a JSON value comes back exactly as it was stored, newlines included
294
+ ~/.copilot/lib/credential-store.sh get "<SERVICE_NAME>"
422
295
 
423
- **Tier 2 - interactive session + MCP.** `firebase login` opens a browser and does
424
- not work from inside an agent harness; the user runs it in their own terminal.
425
- Both halves are required - a login with no MCP server registered reaches nothing.
426
- It is the bridge while a role request moves, never the durable answer: autopilot
427
- and url-enrichment run with nobody at the keyboard.
296
+ # Maximum stdin hygiene (the secret never lands on argv / shell history): the Python helper with the - sentinel
297
+ pbpaste | ~/.copilot/scripts/keychain.py set "<SERVICE_NAME>" -
298
+ ```
428
299
 
429
- **appId discovery.** `scripts/firebase-app-discovery.sh <repo> --json` reads the
430
- bundle-id / appId pairs the repo's `GoogleService-Info*.plist` and
431
- `google-services.json` already carry, shaped for
432
- `prefs.global.firebase.accounts[].apps[]`. Merging them saves the fetcher a
433
- Management API round trip per run; skipping it changes nothing else.
300
+ ### Figma MCP Setup (Remote / Local question)
434
301
 
435
- Full mechanics and the v1alpha caveat: `multi-agent-refs/setup/firebase.md`.
302
+ Full procedure: `$HOME/.claude/multi-agent-refs/setup/figma.md`. Read it for the Figma MCP question.
436
303
 
437
304
  ### Security Rules
438
305
 
@@ -444,25 +311,40 @@ Full mechanics and the v1alpha caveat: `multi-agent-refs/setup/firebase.md`.
444
311
 
445
312
  ### Setup from Scratch Summary
446
313
 
447
- To set up multi-agent on a new machine:
314
+ On a new machine: (1) `npx @{npm-scope}/multi-agent-pipeline install`; (2) `/multi-agent-setup`; (3) the interactive flow: token scan (shows what is missing) -> Git Identity creation (name + email) -> inline commands for missing tokens -> final verification; (4) ready: `/multi-agent "PROJ-12345"`, `/multi-agent "https://github.com/.../issues/42"` or `/multi-agent "bug description"`.
448
315
 
449
- ```
450
- 1. Install the toolkit:
451
- npx @mmerterden/multi-agent-pipeline install
452
-
453
- 2. Start setup:
454
- /multi-agent setup
455
-
456
- 3. Interactive flow:
457
- -> Token scan (shows what is missing)
458
- -> Git Identity creation (name + email)
459
- -> Inline commands for missing tokens
460
- -> Final verification
461
-
462
- 4. Ready:
463
- /multi-agent "PROJ-12345"
464
- /multi-agent "https://github.com/.../issues/42"
465
- /multi-agent "bug description"
466
- ```
316
+ All tokens are optional in the sense that every service can be answered with Skip - but the ASKING is not optional: the Step 3 sequential loop still walks every missing service one by one (token → author → host). Phase 0 re-asks at runtime only for tokens the user skipped here.
317
+
318
+ ### Step 8 - Enforcement hooks (optional, Claude Code)
319
+
320
+ Offer to merge `$HOME/.claude/templates/claude-hooks.json`: three `PreToolUse` gates that block on a non-zero exit (secret scan, agent-guard, read-size) plus three capture hooks that block nothing (`PreCompact`, `SessionEnd`, `SessionStart`). What each does: `$HOME/.claude/multi-agent-refs/picker-contract.md`.
321
+
322
+ - Ask (picker): "Install the pipeline's hooks into `~/.claude/settings.json`?" Default Yes.
323
+ - On Yes, deep-merge EVERY event in the template's `hooks` object, not `PreToolUse` alone - merging one event silently drops the capture hooks. Preserve existing hooks; never duplicate a matcher already calling the same script.
324
+ - Say what the merge does NOT cover: only the three gates need no run-specific arguments, so only they are hookable; the rest are phase-enforced.
325
+ - Say what it does not turn on: the read-size gate is inert until `prefs.global.bulkRead.mode` is set. Recommend `observe` first. Why, and the Phase 3 exemption: `$HOME/.claude/multi-agent-refs/picker-contract.md`.
326
+
327
+ ### Step 9 - Default stack plugin enablement
328
+
329
+ Stack skills ship as versioned plugins in the `{owner}/multi-agent-plugins` marketplace. On first setup, wire the stack so the pipeline works out of the box.
330
+
331
+ 1. Ensure the marketplace is known (idempotent):
332
+ ```bash
333
+ bash "$HOME/.copilot/scripts/plugin-refresh.sh" {owner} --add-only
334
+ ```
335
+ 2. Ask the detector, then derive (no marker list here; a second list would drift from the detector):
336
+
337
+ ```bash
338
+ eval "$(bash $HOME/.copilot/lib/stack-detect.sh "$PROJECT_ROOT")" # MA_STACKS, MA_STACK_WHY
339
+ node -e 'import(process.env.HOME+"/.copilot/scripts/_stack-routing.mjs").then(m=>
340
+ console.log(m.pluginsForStacks(process.argv[1].split(" ").filter(Boolean)).plugins.join(" ")))' "$MA_STACKS"
341
+ ```
342
+
343
+ Report `MA_STACK_WHY` with the result. `ai-common-toolkit` and
344
+ `ai-analyst-toolkit` are in every answer, the empty one included: neither is
345
+ stack-specific. **No marker matched is an answer** - those two, not a guess.
346
+ A name the marketplace does not carry is dropped with `dropped[]` naming it,
347
+ so a toolkit that was never shipped is caught before it fails to load.
348
+ 3. Report the enabled set. To change later, run `/multi-agent-stack <ios|android|web|backend|...>` in the repo. Pipeline Phase 1 auto-detects the stack for its own routing regardless of enablement.
467
349
 
468
- All tokens are optional - pipeline will ask for any needed token at Phase 0. Setup only does pre-preparation.
350
+ The marketplace name (`multi-agent-plugins`) is generic; a different org points `{owner}` at its own fork.