@mmerterden/multi-agent-pipeline 14.2.1 → 15.0.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 (184) hide show
  1. package/CHANGELOG.md +118 -6
  2. package/README.md +20 -9
  3. package/README.tr.md +150 -0
  4. package/docs/FIGMA_PIPELINE.md +3 -3
  5. package/docs/adr/0006-skills-core-external-split.md +1 -1
  6. package/docs/adr/0009-claude-stack-skills-plugin-only.md +31 -0
  7. package/docs/adr/README.md +1 -0
  8. package/docs/architecture.md +24 -9
  9. package/docs/ecosystem.md +237 -0
  10. package/docs/features.md +5 -5
  11. package/index.js +2 -0
  12. package/install/_codex-agents.mjs +11 -2
  13. package/install/_common.mjs +65 -1
  14. package/install/_dev-only-files.mjs +0 -1
  15. package/install/_platform-filter.mjs +73 -7
  16. package/install/_plugin-skills.mjs +33 -8
  17. package/install/claude.mjs +144 -59
  18. package/install/codex.mjs +37 -7
  19. package/install/copilot.mjs +36 -11
  20. package/install/index.mjs +6 -2
  21. package/install/templates/codex-instructions.md +1 -1
  22. package/install/templates/copilot-instructions.md +15 -12
  23. package/package.json +1 -2
  24. package/pipeline/commands/multi-agent/SKILL.md +4 -2
  25. package/pipeline/commands/multi-agent/analysis/SKILL.md +5 -5
  26. package/pipeline/commands/multi-agent/analysis-resolve/SKILL.md +2 -2
  27. package/pipeline/commands/multi-agent/autopilot/SKILL.md +6 -2
  28. package/pipeline/commands/multi-agent/build-optimize/SKILL.md +9 -9
  29. package/pipeline/commands/multi-agent/channels/SKILL.md +16 -5
  30. package/pipeline/commands/multi-agent/complaint-analysis/SKILL.md +186 -0
  31. package/pipeline/commands/multi-agent/create-jira/SKILL.md +4 -4
  32. package/pipeline/commands/multi-agent/dev/SKILL.md +10 -23
  33. package/pipeline/commands/multi-agent/dev-autopilot/SKILL.md +10 -2
  34. package/pipeline/commands/multi-agent/dev-local/SKILL.md +10 -24
  35. package/pipeline/commands/multi-agent/dev-local-autopilot/SKILL.md +10 -3
  36. package/pipeline/commands/multi-agent/garbage-collect/SKILL.md +1 -1
  37. package/pipeline/commands/multi-agent/help/SKILL.md +19 -4
  38. package/pipeline/commands/multi-agent/ios-coding-standard/SKILL.md +2 -2
  39. package/pipeline/commands/multi-agent/jira/SKILL.md +13 -2
  40. package/pipeline/commands/multi-agent/language/SKILL.md +1 -1
  41. package/pipeline/commands/multi-agent/local/SKILL.md +6 -2
  42. package/pipeline/commands/multi-agent/local-autopilot/SKILL.md +6 -2
  43. package/pipeline/commands/multi-agent/log/SKILL.md +7 -1
  44. package/pipeline/commands/multi-agent/prune-prompts/SKILL.md +81 -0
  45. package/pipeline/commands/multi-agent/resume/SKILL.md +1 -1
  46. package/pipeline/commands/multi-agent/{ship → resume-local}/SKILL.md +13 -9
  47. package/pipeline/commands/multi-agent/setup/SKILL.md +5 -5
  48. package/pipeline/commands/multi-agent/stack/SKILL.md +55 -43
  49. package/pipeline/commands/multi-agent/store-ready/SKILL.md +3 -3
  50. package/pipeline/commands/multi-agent/sync/SKILL.md +18 -11
  51. package/pipeline/commands/multi-agent/testflight-validation/SKILL.md +1 -1
  52. package/pipeline/commands/multi-agent/uninstall/SKILL.md +2 -0
  53. package/pipeline/commands/multi-agent/update/SKILL.md +1 -1
  54. package/pipeline/lib/extract-conventions.sh +44 -15
  55. package/pipeline/lib/fetch-figma-annotations.sh +8 -1
  56. package/pipeline/lib/fetch-fortify.sh +23 -8
  57. package/pipeline/lib/figma-screenshot.sh +11 -1
  58. package/pipeline/lib/issue-fetcher.sh +77 -10
  59. package/pipeline/lib/md2confluence-v3.py +16 -2
  60. package/pipeline/lib/parse-complaints.sh +306 -0
  61. package/pipeline/lib/plan-todos.sh +5 -2
  62. package/pipeline/lib/post-pr-review.sh +8 -6
  63. package/pipeline/lib/shadow-git.sh +50 -9
  64. package/pipeline/lib/submodule-detector.sh +8 -1
  65. package/pipeline/multi-agent-refs/_input-parser.md +1 -1
  66. package/pipeline/multi-agent-refs/channels/confluence.md +3 -0
  67. package/pipeline/multi-agent-refs/channels/issue-comment.md +2 -2
  68. package/pipeline/multi-agent-refs/channels/jira.md +13 -2
  69. package/pipeline/multi-agent-refs/channels/pr-review-actions.md +1 -1
  70. package/pipeline/multi-agent-refs/channels/pr.md +20 -0
  71. package/pipeline/multi-agent-refs/channels/wiki.md +4 -4
  72. package/pipeline/multi-agent-refs/complaint-analysis-template.md +99 -0
  73. package/pipeline/multi-agent-refs/component-dispatch.md +6 -6
  74. package/pipeline/multi-agent-refs/cross-cli-contract.md +16 -16
  75. package/pipeline/multi-agent-refs/features/external-context-injection.md +1 -1
  76. package/pipeline/multi-agent-refs/features/stack-skill-routing.md +5 -5
  77. package/pipeline/multi-agent-refs/features/worktree-finalize.md +1 -1
  78. package/pipeline/multi-agent-refs/generate-issue.md +3 -3
  79. package/pipeline/multi-agent-refs/issue-jira-triad.md +3 -3
  80. package/pipeline/multi-agent-refs/payload-contracts.md +67 -0
  81. package/pipeline/multi-agent-refs/phases/modes.md +20 -0
  82. package/pipeline/multi-agent-refs/phases/phase-0-init.md +2 -2
  83. package/pipeline/multi-agent-refs/phases/phase-1-analysis.md +7 -7
  84. package/pipeline/multi-agent-refs/phases/phase-2-planning.md +5 -5
  85. package/pipeline/multi-agent-refs/phases/phase-3-dev.md +3 -3
  86. package/pipeline/multi-agent-refs/phases/phase-4-review.md +12 -12
  87. package/pipeline/multi-agent-refs/phases/phase-5-test.md +1 -1
  88. package/pipeline/multi-agent-refs/phases/phase-6-commit.md +8 -40
  89. package/pipeline/multi-agent-refs/phases/phase-7-report.md +5 -3
  90. package/pipeline/multi-agent-refs/phases.md +6 -0
  91. package/pipeline/multi-agent-refs/rules.md +2 -0
  92. package/pipeline/multi-agent-refs/tracker-contract.md +1 -1
  93. package/pipeline/multi-agent-refs/wiki-capture.md +2 -2
  94. package/pipeline/preferences-template.json +13 -5
  95. package/pipeline/rules/figma-pipeline.md +2 -2
  96. package/pipeline/schemas/agent-state.schema.json +1 -1
  97. package/pipeline/schemas/complaint-analysis-spec.schema.json +216 -0
  98. package/pipeline/schemas/migrations/prefs-2.5.0-to-2.6.0.mjs +46 -0
  99. package/pipeline/schemas/prefs.schema.json +277 -67
  100. package/pipeline/schemas/token-budget.json +2 -2
  101. package/pipeline/scripts/_stack-routing.mjs +79 -0
  102. package/pipeline/scripts/audit-log-rotate.sh +14 -1
  103. package/pipeline/scripts/build-skills-index.mjs +11 -0
  104. package/pipeline/scripts/build-stack-plugins.mjs +35 -60
  105. package/pipeline/scripts/check-derived-drift.mjs +65 -29
  106. package/pipeline/scripts/diff-explain.mjs +41 -3
  107. package/pipeline/scripts/diff-risk-score.mjs +72 -8
  108. package/pipeline/scripts/gc-worktrees.sh +4 -1
  109. package/pipeline/scripts/gen-mode-dispatch.mjs +1 -1
  110. package/pipeline/scripts/gen-skills-index.mjs +1 -1
  111. package/pipeline/scripts/learning-curve.mjs +8 -2
  112. package/pipeline/scripts/match-skills.mjs +8 -2
  113. package/pipeline/scripts/migrate-prefs.mjs +28 -20
  114. package/pipeline/scripts/output-quality-check.sh +15 -4
  115. package/pipeline/scripts/phase-tracker.sh +33 -12
  116. package/pipeline/scripts/phase0-exit-gate.mjs +3 -2
  117. package/pipeline/scripts/pre-commit-check.sh +69 -22
  118. package/pipeline/scripts/render-agent-log-cost.sh +8 -3
  119. package/pipeline/scripts/render-cost-summary.sh +42 -22
  120. package/pipeline/scripts/render-work-summary.sh +47 -13
  121. package/pipeline/scripts/review-scope.mjs +1 -1
  122. package/pipeline/scripts/run-aggregator.mjs +43 -14
  123. package/pipeline/scripts/scan-agent-config.sh +1 -1
  124. package/pipeline/scripts/skill-conformance.mjs +165 -30
  125. package/pipeline/scripts/smoke-cross-cli-behavior.sh +1 -1
  126. package/pipeline/scripts/smoke-schema-validation.sh +5 -1
  127. package/pipeline/scripts/test-gap-rules/android.json +25 -0
  128. package/pipeline/scripts/test-gap-rules/ios.json +34 -0
  129. package/pipeline/scripts/test-gap-rules/node.json +29 -0
  130. package/pipeline/scripts/test-gap-rules/python.json +25 -0
  131. package/pipeline/scripts/test-gap-scan.mjs +45 -6
  132. package/pipeline/scripts/uninstall.mjs +196 -14
  133. package/pipeline/scripts/update-issue-progress.sh +12 -16
  134. package/pipeline/scripts/validate-complaint-doc.mjs +229 -0
  135. package/pipeline/scripts/validate-reviewer.mjs +9 -3
  136. package/pipeline/scripts/worktree-finalize.sh +23 -2
  137. package/pipeline/skills/.skill-manifest.json +156 -108
  138. package/pipeline/skills/.skills-index.json +459 -13
  139. package/pipeline/skills/shared/README.md +15 -11
  140. package/pipeline/skills/shared/core/multi-agent-analysis-resolve/SKILL.md +1 -1
  141. package/pipeline/skills/shared/core/multi-agent-autopilot/SKILL.md +4 -0
  142. package/pipeline/skills/shared/core/multi-agent-build-optimize/SKILL.md +1 -1
  143. package/pipeline/skills/shared/core/multi-agent-complaint-analysis/SKILL.md +49 -0
  144. package/pipeline/skills/shared/core/multi-agent-create-jira/SKILL.md +1 -1
  145. package/pipeline/skills/shared/core/multi-agent-dev/SKILL.md +4 -17
  146. package/pipeline/skills/shared/core/multi-agent-dev-autopilot/SKILL.md +8 -0
  147. package/pipeline/skills/shared/core/multi-agent-dev-local/SKILL.md +5 -18
  148. package/pipeline/skills/shared/core/multi-agent-dev-local-autopilot/SKILL.md +8 -0
  149. package/pipeline/skills/shared/core/multi-agent-ios-coding-standard/SKILL.md +2 -2
  150. package/pipeline/skills/shared/core/multi-agent-language/SKILL.md +1 -1
  151. package/pipeline/skills/shared/core/multi-agent-local/SKILL.md +4 -0
  152. package/pipeline/skills/shared/core/multi-agent-local-autopilot/SKILL.md +4 -0
  153. package/pipeline/skills/shared/core/multi-agent-prune-prompts/SKILL.md +83 -0
  154. package/pipeline/skills/shared/core/{multi-agent-ship → multi-agent-resume-local}/SKILL.md +10 -6
  155. package/pipeline/skills/shared/core/multi-agent-stack/SKILL.md +79 -22
  156. package/pipeline/skills/shared/core/multi-agent-store-ready/SKILL.md +1 -1
  157. package/pipeline/skills/shared/core/multi-agent-sync/SKILL.md +8 -8
  158. package/pipeline/skills/shared/core/multi-agent-testflight-validation/SKILL.md +1 -1
  159. package/pipeline/skills/shared/external/ios-coding-standard/modules/_TEMPLATE.yml +2 -2
  160. package/pipeline/skills/shared/external/ios-coding-standard/references/rules.yml +368 -33
  161. package/pipeline/skills/shared/external/ios-coding-standard/references/swiftlint.draft.yml +1 -2
  162. package/pipeline/skills/shared/external/ios-coding-standard/scripts/check_structure.py +765 -0
  163. package/pipeline/skills/shared/external/ios-module-structure/SKILL.md +75 -0
  164. package/pipeline/skills/shared/external/ios-module-structure/modules/_TEMPLATE.yml +131 -0
  165. package/pipeline/skills/shared/external/ios-module-structure/references/rules.yml +559 -0
  166. package/pipeline/skills/shared/external/ios-module-structure/scripts/check_structure.py +765 -0
  167. package/pipeline/skills/shared/external/localization-reuse-map/SKILL.md +302 -0
  168. package/pipeline/skills/shared/external/localization-reuse-map/example-mapping.json +187 -0
  169. package/pipeline/skills/shared/external/localization-reuse-map/reference/format-and-output.md +156 -0
  170. package/pipeline/skills/shared/external/localization-reuse-map/reference/publish-and-snapshot.md +108 -0
  171. package/pipeline/skills/shared/external/localization-reuse-map/reference/sources-and-recipes.md +176 -0
  172. package/pipeline/skills/shared/external/localization-reuse-map/scripts/build-artifact.py +865 -0
  173. package/pipeline/skills/shared/external/localization-reuse-map/scripts/build-spreadsheet.py +335 -0
  174. package/pipeline/skills/shared/external/localization-reuse-map/scripts/fetch-annotations.py +344 -0
  175. package/pipeline/skills/shared/external/localization-reuse-map/scripts/fetch-legacy-labels.py +130 -0
  176. package/pipeline/skills/shared/external/localization-reuse-map/scripts/publish-confluence.py +264 -0
  177. package/pipeline/skills/shared/external/localization-reuse-map/scripts/render-key-shots.py +298 -0
  178. package/pipeline/skills/shared/external/localization-reuse-map/scripts/render-overlay.py +529 -0
  179. package/pipeline/skills/shared/external/localization-reuse-map/scripts/resolve-legacy-values.py +187 -0
  180. package/pipeline/skills/shared/external/localization-reuse-map/scripts/resolve-new-values.py +171 -0
  181. package/pipeline/skills/shared/external/localization-reuse-map/scripts/scan-screen-keys.py +184 -0
  182. package/pipeline/skills/shared/external/localization-reuse-map/scripts/snapshot-resources.sh +26 -0
  183. package/pipeline/skills/shared/external/localization-reuse-map/scripts/verify-map.py +173 -0
  184. package/pipeline/skills/skills-index.md +9 -5
@@ -75,7 +75,7 @@ If changes include UI files (iOS: `*View.swift`, `*Screen.swift`, `*Cell.swift`;
75
75
  - Missing `.accessibilityIdentifier` / `testTag` → **important**
76
76
  - Dynamic Type / font scaling not supported → **important**
77
77
 
78
- **iOS - Apple HIG compliance** (skills: `hig-patterns`, `hig-components-layout`, `hig-foundations`):
78
+ **iOS - Apple HIG compliance** (skills: `ai-ios-toolkit:hig-patterns`, `ai-ios-toolkit:hig-components-layout`, `ai-ios-toolkit:hig-foundations`):
79
79
  - Navigation pattern mismatch (e.g. custom back button instead of system) → **important**
80
80
  - Non-standard gesture without discoverability hint → **suggestion**
81
81
  - Missing safe area / keyboard avoidance → **important**
@@ -83,12 +83,12 @@ If changes include UI files (iOS: `*View.swift`, `*Screen.swift`, `*Cell.swift`;
83
83
 
84
84
  **iOS - SwiftUI interaction & accessibility conventions.** Gated to changed SwiftUI files. These are rule-registry territory as of v14.0.0, not a list transcribed here: Step 1.78 resolves them from whichever registry declares SwiftUI scope, so the criteria and their severities live in one place instead of drifting between this doc and the skill. Reviewers receive the resolved rule IDs. Native-SwiftUI-first unless the project's `figma-config` `ui.*` declares a custom system, in which case check against that system. Reference skills, when no registry covers the change: `figma-navigation`, `figma-overlays`, `figma-bottom-sheets`, `figma-to-swiftui`.
85
85
 
86
- **Android - Material Design compliance** (skills: `compose-components`, `android-architecture`):
86
+ **Android - Material Design compliance** (skills: `ai-android-toolkit:compose-components`, `ai-android-toolkit:android-architecture`):
87
87
  - Non-Material3 component when M3 equivalent exists → **suggestion**
88
88
  - Missing `contentDescription` on icons/images → **blocking**
89
89
  - Hardcoded dp values instead of Material spacing tokens → **suggestion**
90
90
 
91
- **App Store / Play Store readiness** (skills: `app-store-review`, `play-store-review`):
91
+ **App Store / Play Store readiness** (skills: `ai-ios-toolkit:app-store-review`, `ai-android-toolkit:play-store-review`):
92
92
  - Privacy: API usage without purpose string / permission rationale → **blocking**
93
93
  - Deprecated API usage flagged by latest SDK → **important**
94
94
 
@@ -249,7 +249,7 @@ Launch Agent instances **in parallel** using the shared `code-reviewer` subagent
249
249
  | ---------- | --------------- | --- | --- | --- | --- | --- |
250
250
  | Reviewer 1 | `code-reviewer` | `claude-fable-5` | `claude-opus-5` | `gpt-5.6` @ `xhigh` | Deep security + architecture | `api-security-best-practices`, `architecture` |
251
251
  | Reviewer 2 | `code-reviewer` | (not dispatched) | `gpt-5.4` | `gpt-5.4` @ `high` | Edge cases, different perspective | cross-model diversity |
252
- | Reviewer 3 | `code-reviewer` | `claude-sonnet-5` | `claude-sonnet-5` | `gpt-5.6` @ `medium` | Quality + correctness + naming | `clean-code`, stack-specific skill |
252
+ | Reviewer 3 | `code-reviewer` | `claude-sonnet-5` | `claude-sonnet-5` | `gpt-5.6` @ `medium` | Quality + correctness + naming | `ai-backend-toolkit:clean-code`, stack-specific skill |
253
253
  | Triage | triage persona | `claude-fable-5` | `claude-opus-5` | `gpt-5.6` @ `max` | Filter false positives + out-of-scope | - |
254
254
 
255
255
  Reviewer count per host: **Claude Code 2, Copilot CLI 3, Codex CLI 3**.
@@ -285,12 +285,12 @@ Each reviewer inherits the `code-reviewer` agent's focus areas (Security, Archit
285
285
 
286
286
  | Stack | Reviewer 1 (Fable / Opus on Copilot) | Reviewer 2 (GPT-5.4 - Copilot CLI only) | Reviewer 3 (Sonnet) |
287
287
  |-------|-------------------|-----------------------------------------|---------------------|
288
- | iOS/Swift | `ios-security`, `swiftui-performance`, `hig-patterns` | `swift-concurrency`, `ios-accessibility` | `swiftui-pro`, `swift-testing` |
289
- | Android/Kotlin | `android-security`, `android-performance` | `compose-testing`, `android-architecture` | `compose-components`, `kotlin-coroutines-expert` |
290
- | Python | `api-security-best-practices` | `fastapi-pro` | `python-patterns` |
291
- | Node.js | `api-security-best-practices` | `nodejs-backend-patterns` | `typescript-patterns` |
292
- | Docker | `docker-expert` | `docker-expert` | `ci-cd-pipelines` |
293
- | Generic | `security-review` | `clean-code` | `clean-code` |
288
+ | iOS/Swift | `ai-ios-toolkit:ios-security`, `ai-ios-toolkit:swiftui-performance`, `ai-ios-toolkit:hig-patterns` | `ai-ios-toolkit:swift-concurrency`, `ai-ios-toolkit:ios-accessibility` | `ai-ios-toolkit:swiftui-pro`, `ai-ios-toolkit:swift-testing` |
289
+ | Android/Kotlin | `ai-android-toolkit:android-security`, `ai-android-toolkit:android-performance` | `ai-android-toolkit:compose-testing`, `ai-android-toolkit:android-architecture` | `ai-android-toolkit:compose-components`, `ai-android-toolkit:kotlin-coroutines-expert` |
290
+ | Python | `ai-backend-toolkit:api-security-best-practices` | `ai-backend-toolkit:fastapi-pro` | `ai-backend-toolkit:python-patterns` |
291
+ | Node.js | `ai-backend-toolkit:api-security-best-practices` | `ai-backend-toolkit:nodejs-backend-patterns` | `ai-frontend-toolkit:typescript-patterns` |
292
+ | Docker | `ai-backend-toolkit:docker-expert` | `ai-backend-toolkit:docker-expert` | `ai-backend-toolkit:ci-cd-pipelines` |
293
+ | Generic | `security-review` | `ai-backend-toolkit:clean-code` | `ai-backend-toolkit:clean-code` |
294
294
 
295
295
  Skills are injected into reviewer prompt context - the reviewer uses them as reference, not as commands.
296
296
 
@@ -299,7 +299,7 @@ Skills are injected into reviewer prompt context - the reviewer uses them as r
299
299
  Runs when `state.taskType == "component"` **or** the diff touches SwiftUI UI files
300
300
  AND the task carried a Figma reference. Two checks, in order:
301
301
 
302
- 1. **`ai-ios-engineering-toolkit:figma-review`** over the implemented frames - the
302
+ 1. **`ai-ios-toolkit:figma-review`** over the implemented frames - the
303
303
  plugin's own component review, including the 14-item checklist that covers design
304
304
  tokens, accessibility identifiers, previews and Code Connect.
305
305
  2. **`/multi-agent:design-check`** for pixel + spacing + typography + colour
@@ -320,7 +320,7 @@ reading a diff cannot see spacing; something has to compare against the design.
320
320
  Skip only when the diff has no UI change. Record the outcome in
321
321
  `consensus.visualConformance` so Phase 7 reports whether it ran.
322
322
 
323
- **iOS/Swift - interaction & convention checks (conditional).** Step 1.78 resolves these. Where no registry covers the change, reviewers fall back to the analysis doc (Section 14 Code Connect mapping) and, when `ai-ios-engineering-toolkit` is enabled, that plugin's navigation / overlay / bottom-sheet + accessibility conventions.
323
+ **iOS/Swift - interaction & convention checks (conditional).** Step 1.78 resolves these. Where no registry covers the change, reviewers fall back to the analysis doc (Section 14 Code Connect mapping) and, when `ai-ios-toolkit` is enabled, that plugin's navigation / overlay / bottom-sheet + accessibility conventions.
324
324
 
325
325
  **Module review guides (conditional, all stacks).** Step 1.78 resolves them into `criteria-manifest.json` → `moduleGuides`. Inject with the directive: read each guide, apply its rules to the changed files under its directory - a guide governs only its own subtree, and its violations are findings triaged like any other. Same contract as `/multi-agent:review` Step 2b.
326
326
 
@@ -100,7 +100,7 @@ Tier 1 / Tier 2 records print `screenshotUrl` from the captured evidence (Tier 2
100
100
  bash $HOME/.claude/scripts/phase-tracker.sh now 5 "awaiting local test (user)"
101
101
  bash $HOME/.claude/scripts/phase-tracker.sh render
102
102
  ```
103
- The waiting state persists in `tracker-state.json` across the handoff; `/multi-agent:ship` and `/multi-agent:manual-test` CONTINUE this state file and never re-init it (`$HOME/.claude/multi-agent-refs/tracker-contract.md` "Continuation runs").
103
+ The waiting state persists in `tracker-state.json` across the handoff; `/multi-agent:resume-local` and `/multi-agent:manual-test` CONTINUE this state file and never re-init it (`$HOME/.claude/multi-agent-refs/tracker-contract.md` "Continuation runs").
104
104
  6. If fix needed:
105
105
  - Branch already has WIP commit (from step 2) - changes are safe
106
106
  - **Heal stale admin state first** (same contract as Phase 0 - step 3's
@@ -106,6 +106,8 @@ Branch **deterministically**, no implicit fallback. Read `agent-state.json` and
106
106
 
107
107
  #### Step 3 - PR Description (technical detail for reviewers)
108
108
 
109
+ **Section set + markup dialect: `channels/pr.md` - read it first.** Phase 7 channels replaces this body with that section set, so build to it. Required reading: `payload-contracts.md`.
110
+
109
111
  Generate a structured PR description based on task type. The PR body targets **code reviewers** - it should be technical: what changed, why, architecture decisions, how to verify.
110
112
 
111
113
  **required**: Run all generated text (PR body, commit message) through the `humanizer` skill before posting. This removes AI-generated patterns (inflated language, filler phrases, repetitive structure) and makes the output sound like a developer wrote it.
@@ -116,49 +118,15 @@ Generate a structured PR description based on task type. The PR body targets **c
116
118
  - Bitbucket: similar patterns
117
119
  - Use `Ref: #N`, `Related: #N`, or `See: {jiraId}` instead
118
120
 
119
- **Default Reviewers**: If `prefs.projects[{project}].defaultReviewers` exists, add `--reviewer` flags. If not, ask on first PR and save to preferences:
120
-
121
- ```
122
- Default reviewers for this project? (comma-separated GitHub usernames, or skip):
123
- ```
124
-
125
- Save to `prefs.projects[{project}].defaultReviewers: ["user1", "user2", "user3", "user4"]`
121
+ **Default Reviewers**: use `prefs.projects[{project}].defaultReviewers` when set; otherwise ask once ("Default reviewers for this project? comma-separated, or skip") and persist the answer there. Per-remote resolution rules are in "Default reviewers (required on every PR)" below - this is the prefs half only.
126
122
 
127
- **Standard PR (bug fix, feature, refactor):**
123
+ **Standard PR (bug fix, feature, refactor)** - invocation shape; body comes from a file so newlines survive:
128
124
 
129
125
  ```bash
130
126
  REVIEWERS=$(jq -r '.projects["'$PROJECT'"].defaultReviewers // [] | map("--reviewer " + .) | join(" ")' "$PREFS_FILE")
131
127
  gh pr create --base {baseBranch} --head {branch} $REVIEWERS \
132
128
  --title "{type}({scope}): {summary} [{jiraId}]" \
133
- --body "$(cat <<'EOF'
134
- ## Summary
135
- {1-3 bullet points: what changed and why}
136
-
137
- ## Jira
138
- {jiraId} - {jira summary or link}
139
-
140
- ## Technical Details
141
- ### Changes
142
- {For each changed file group, explain WHAT changed and WHY}
143
-
144
- ### Architecture
145
- {Any structural decisions: new files, moved code, pattern changes}
146
-
147
- ### Dependencies
148
- {New imports, framework changes, package updates - or "None"}
149
-
150
- ## How to Test
151
- 1. {Step-by-step manual test instructions}
152
- 2. {Verify specific behavior}
153
-
154
- ## Checklist
155
- - [ ] Build passes (0 errors, 0 warnings)
156
- - [ ] Tests pass
157
- - [ ] No hardcoded values (tokens used)
158
- - [ ] Accessibility verified
159
- - [ ] Dark mode verified
160
- EOF
161
- )"
129
+ --body-file /tmp/pr-body-$TASK_ID.md
162
130
  ```
163
131
 
164
132
  **UI Component PR (when SwiftUI component detected):**
@@ -175,9 +143,9 @@ Same `gh pr create` pattern with component-specific body sections:
175
143
 
176
144
  CRITICAL: PR description **MUST** preserve real newlines. Never embed `\n` literally - Bitbucket saves it verbatim. Never use HTML entities. Pattern: heredoc → `jq --rawfile` → `curl --data-binary @file`.
177
145
 
178
- Required payload fields: `title`, `description` (via rawfile), `fromRef` (id + repo slug + project key), `toRef` (same structure), `state: "OPEN"`, `open: true`, `closed: false`, `locked: false`, `reviewers: []`.
146
+ Required payload fields: `title`, `description` (via rawfile), `fromRef` (id + repo slug + project key), `toRef` (same structure), `state: "OPEN"`, `open: true`, `closed: false`, `locked: false`, `reviewers` (the fetched list - `[]` only if that endpoint really returned empty).
179
147
 
180
- To **update** an existing PR: fetch `version`, PUT with same rawfile pattern (version +1). GitHub: prefer `--body-file` over inline `--body`.
148
+ To **update** an existing PR: use the `channels/pr.md` PUT payload - required, not illustrative. It carries `reviewers`/`fromRef`/`toRef`/`draft` (a PUT clears omitted fields) and the GET's `version` unmodified (`version + 1` → 409). Refetch after, assert the reviewer count held. GitHub: `--body-file`.
181
149
 
182
150
  **Default reviewers (required on every PR)**
183
151
 
@@ -307,7 +275,7 @@ update_sibling_links "${PR_URLS[@]}"
307
275
 
308
276
  **Then finalize each repo's worktree**, serially and only now - `update_sibling_links` updates one PR per repo and the loop `cd`s per repo, so removing repo 1's worktree mid-loop breaks 2..N. Run `worktree-finalize.sh` once per repo with that repo's `--worktree` / `--project-root` / `--project`; each skips or removes independently.
309
277
 
310
- `update_sibling_links` does an UPDATE call per PR (Bitbucket: PUT with `version+1`; GitHub: `gh pr edit --body-file`). Idempotent: re-running with the same set is a no-op.
278
+ `update_sibling_links` does an UPDATE call per PR (Bitbucket: the `channels/pr.md` PUT payload, current `version`; GitHub: `gh pr edit --body-file`). Idempotent.
311
279
 
312
280
  ##### GitHub issue body - list all PRs
313
281
 
@@ -153,8 +153,8 @@ Skipped sections: when `planTodos.enabled` is false or no `plan.todos[]` was emi
153
153
 
154
154
  ## Timeline
155
155
 
156
- | # | Phase | Model | Duration | Status | Detail |
157
- | --- | ----- | ----- | -------- | ------ | ------ |
156
+ | # | Phase | Agent | Model | Duration | Tokens (in/out) | Status | Detail |
157
+ | --- | ----- | ----- | ----- | -------- | --------------- | ------ | ------ |
158
158
 
159
159
  ## Agent Activity Report
160
160
 
@@ -200,7 +200,7 @@ $HOME/.claude/scripts/log-metric.sh "$TASK_ID" 7 task.completed \
200
200
 
201
201
  **Per-run outcome metrics (evidence corpus):** also emit `run-metrics.mjs --state <agent-state.json>` and append/persist its JSON. It records the numbers that actually answer "did this run go well" - review iterations (rework loops), first-pass-clean, reviewer signal-to-noise (accepted / raw findings), consensus verdict, build outcome. Accumulating these across real runs is the real-world validation that golden tasks + benchmarks only approximate; keep the corpus so the pipeline's quality can be measured, not asserted.
202
202
 
203
- **Cost Breakdown emission (mandatory):** as part of agent-log compose, append the per-task cost block produced by `render-agent-log-cost.sh`. Best-effort - exit 2 (no tracker data) silently skipped:
203
+ **Cost Breakdown emission (mandatory):** as part of agent-log compose, append the per-task cost block produced by `render-agent-log-cost.sh`:
204
204
 
205
205
  ```bash
206
206
  COST_BLOCK=$(bash $HOME/.claude/scripts/render-agent-log-cost.sh "$TASK_ID" 2>/dev/null) && \
@@ -209,6 +209,8 @@ COST_BLOCK=$(bash $HOME/.claude/scripts/render-agent-log-cost.sh "$TASK_ID" 2>/d
209
209
 
210
210
  This is independent of the channels-side `reportContent.costSummary` (which gates the PR-body Cost Summary). agent-log always carries the breakdown when telemetry is present.
211
211
 
212
+ **Missing-telemetry disclosure (required).** Name untracked phase ids as cost-unavailable in the report and closing summary. Mechanic: `payload-contracts.md`.
213
+
212
214
  **Triage memory ingest (mandatory):** after Phase 4 produces a final triage output, persist the accepted/deferred/rejected rows into the per-repo triage corpus so Phase 1 enrichment and Phase 4 prior-art lookup can recall them on future tasks. Idempotent - re-running on the same task writes 0 rows.
213
215
 
214
216
  ```bash
@@ -63,6 +63,12 @@ $HOME/.claude/scripts/phase-tracker.sh update <N> failed # phase failed
63
63
  $HOME/.claude/scripts/phase-tracker.sh update <N> skipped # --dev mode etc.
64
64
  ```
65
65
 
66
+ After every LLM call (counts are additive; skipping this is why runs end with durations but no cost - nothing reconstructs spend afterwards):
67
+
68
+ ```bash
69
+ $HOME/.claude/scripts/phase-tracker.sh tokens <N> <in> <out> [cached]
70
+ ```
71
+
66
72
  For sub-phase progress (e.g. Phase 1's parallel Explore agents, Phase 4's reviewer dispatch + triage + validator gate, Phase 6's commit + push + PR sub-steps):
67
73
 
68
74
  ```bash
@@ -122,6 +122,8 @@ This is the single source of truth. When a contributor or model is unsure where
122
122
 
123
123
  4. **Terminal output, log lines, and `echo`/`printf` calls** also use real newlines - never `\n` literals. For multi-line messages, prefer heredoc.
124
124
 
125
+ 5. **Markup dialect is a second axis beyond language.** Markdown: PR body, GitHub issue, wiki files. Jira: wiki markup. Confluence: storage format. Wrong dialect renders literally. Table: `payload-contracts.md`.
126
+
125
127
  ## Issue Management
126
128
 
127
129
  - **NEVER auto-close** GitHub issues or Jira tickets. Closure requires team review (configurable, typically 4 approvals).
@@ -310,7 +310,7 @@ The `tasklist_id` meta from the previous session is replaced with the new IDs du
310
310
 
311
311
  ## Continuation runs (finish / manual-test)
312
312
 
313
- A pre-existing `tracker-state.json` for the task is never re-initialized. Rules for any command that continues an earlier run (`/multi-agent:ship`, `/multi-agent:manual-test`, resume):
313
+ A pre-existing `tracker-state.json` for the task is never re-initialized. Rules for any command that continues an earlier run (`/multi-agent:resume-local`, `/multi-agent:manual-test`, resume):
314
314
 
315
315
  1. `init` runs ONLY when no state file exists for the task. Otherwise the existing file is kept - phase history (elapsed, tokens, model, meta) survives.
316
316
  2. The continuing command re-declares its phase set with `add` - `add` is idempotent, so existing phases keep their name, status, and token history; only genuinely new phases are appended. The card renders phases sorted by numeric id, so mixed sets stay in order.
@@ -77,9 +77,9 @@ Save the answer to `prefs.global.wikiDefault` for next run. Migration script (`m
77
77
 
78
78
  ## Dispatch
79
79
 
80
- 1. Resolve wiki mode from `figmaConfig.wiki.mode` - one of `submodule`, `in-repo`, `github-wiki`, `separate-repo`. Each has a dedicated adapter inside the `figma-component-wiki` skill; see the `ai-ios-engineering-toolkit:figma-component-wiki` plugin skill for per-mode path layout and push semantics.
80
+ 1. Resolve wiki mode from `figmaConfig.wiki.mode` - one of `submodule`, `in-repo`, `github-wiki`, `separate-repo`. Each has a dedicated adapter inside the `figma-component-wiki` skill; see the `ai-ios-toolkit:figma-component-wiki` plugin skill for per-mode path layout and push semantics.
81
81
  2. Emit progress line: `→ writing wiki {componentName} (mode: {mode})`.
82
- 3. Dispatch to the plugin skill `ai-ios-engineering-toolkit:figma-component-wiki` (iOS) or `ai-android-engineering-toolkit:figma-component-wiki` (Android), passing `{componentName, componentPath, figmaConfig}`.
82
+ 3. Dispatch to the plugin skill `ai-ios-toolkit:figma-component-wiki` (iOS) or `ai-android-toolkit:figma-component-wiki` (Android), passing `{componentName, componentPath, figmaConfig}`.
83
83
  4. Skill returns `{ writtenPaths[], committedSha?, pushedRemote? }`. Write `writtenPaths` to Phase 7 summary's "Files written" section and push metadata (if any) to "External publishes".
84
84
  5. On adapter failure - log the adapter + mode + error, continue Phase 7. Wiki is a non-blocking augmentation; the Jira comment in Step 3 already carries the component summary, so the developer is never left in the dark if wiki misfires.
85
85
 
@@ -1,5 +1,5 @@
1
1
  {
2
- "schemaVersion": "2.5.0",
2
+ "schemaVersion": "2.6.0",
3
3
  "global": {
4
4
  "identities": [],
5
5
  "keychainMapping": {
@@ -46,7 +46,12 @@
46
46
  "autoDiff": false,
47
47
  "manualNote": false
48
48
  },
49
- "wikiScope": ["main", "ios", "screenshots", "index"],
49
+ "wikiScope": [
50
+ "main",
51
+ "ios",
52
+ "screenshots",
53
+ "index"
54
+ ],
50
55
  "autopilotReportTimeoutSeconds": 1800,
51
56
  "promptLanguage": "en",
52
57
  "outputLanguage": "en",
@@ -78,7 +83,7 @@
78
83
  "skillConformance": {
79
84
  "blockOnCoverageGap": false
80
85
  },
81
- "ship": {
86
+ "resumeLocal": {
82
87
  "autoFix": false
83
88
  }
84
89
  },
@@ -164,13 +169,16 @@
164
169
  }
165
170
  },
166
171
  "_derivedSkillSourcesTemplate": {
167
- "_comment": "Optional. Populate global.derivedSkillSources[] to let /multi-agent:refactor check whether skills you derived from an upstream marketplace plugin have been updated. Kept in your LOCAL prefs only (never synced), so it may reference private sources. Copy an entry like the one below. Set upstreamLocalClone when you have a working copy: the installed plugin cache is only as fresh as your last marketplace update, and a stale cache makes the drift check answer 'up to date' when it is four releases behind.",
172
+ "_comment": "Optional. Populate global.derivedSkillSources[] to let /multi-agent:refactor check whether skills you derived from an upstream marketplace plugin have been updated. Kept in your LOCAL prefs only (never synced), so it may reference private sources. Copy an entry like the one below. Set upstreamLocalClone when you have a working copy: the installed plugin cache is only as fresh as your last marketplace update, and a stale cache makes the drift check answer 'up to date' when it is four releases behind. Set driftAcknowledged to the current upstream version to accept a known drift without failing the gate; the gate re-fails when upstream moves past it.",
168
173
  "_example": {
169
174
  "label": "Component toolkit skills",
170
175
  "localPath": "plugins/<my-plugin>/skills/workflow",
171
176
  "upstreamMarketplace": "<installed-marketplace-name>",
172
177
  "upstreamPlugin": "<upstream-plugin-name>",
173
- "upstreamSkills": ["<skill-a>", "<skill-b>"],
178
+ "upstreamSkills": [
179
+ "<skill-a>",
180
+ "<skill-b>"
181
+ ],
174
182
  "derivedFromVersion": "0.0.0",
175
183
  "upstreamVersionSource": "marketplace.json",
176
184
  "upstreamLocalClone": "$HOME/<upstream-repo-working-copy>",
@@ -1,6 +1,6 @@
1
1
  ## Figma -> Component Generation
2
2
 
3
- Skill set lives in the marketplace plugins - `ai-ios-engineering-toolkit` (iOS/SwiftUI) and `ai-android-engineering-toolkit` (Android/Compose). Activated when the task contains a Figma URL and target files are `.swift` (iOS) or `.kt` (Android).
3
+ Skill set lives in the marketplace plugins - `ai-ios-toolkit` (iOS/SwiftUI) and `ai-android-toolkit` (Android/Compose). Activated when the task contains a Figma URL and target files are `.swift` (iOS) or `.kt` (Android).
4
4
 
5
5
  ### MUST: Figma access - 3-tier fallback chain (BLOCKING, pipeline-wide)
6
6
 
@@ -190,7 +190,7 @@ Phase 3.3: figma-iteration-commit → Batch iteration commit (if iterating)
190
190
  | Wiki | enabled/disabled | `wiki.enabled` |
191
191
  | Figma API | MCP / REST fallback | `figma.mcpEnabled` |
192
192
 
193
- Provider interfaces are defined inline in the plugin skill sets - see the `ai-ios-engineering-toolkit` and `ai-android-engineering-toolkit` marketplace plugins.
193
+ Provider interfaces are defined inline in the plugin skill sets - see the `ai-ios-toolkit` and `ai-android-toolkit` marketplace plugins.
194
194
 
195
195
  ### Optional Features (graceful skip when disabled)
196
196
 
@@ -144,7 +144,7 @@
144
144
  "skill": {
145
145
  "type": "string",
146
146
  "minLength": 1,
147
- "description": "Skill name as invoked, e.g. ios-coding-standard, ai-ios-engineering-toolkit:create-component, or a guide path for a stack guide."
147
+ "description": "Skill name as invoked, e.g. ios-coding-standard, ai-ios-toolkit:create-component, or a guide path for a stack guide."
148
148
  },
149
149
  "phase": {
150
150
  "type": "integer",
@@ -0,0 +1,216 @@
1
+ {
2
+ "$schema": "https://json-schema.org/draft/2020-12/schema",
3
+ "$id": "https://github.com/{owner}/multi-agent-pipeline/pipeline/schemas/complaint-analysis-spec.schema.json",
4
+ "version": "1.0.0",
5
+ "title": "Multi-Agent Pipeline - /multi-agent:complaint-analysis run state",
6
+ "description": "Contract for state.complaintSpec, the run state of the customer-complaint triage command. Complaints arrive redacted (parse-complaints.sh strips PII before anything lands here), each one carries its Graylog evidence status, repo evidence rows, and a triage verdict: client / bff (our responsibility, root-cause analysis) or core (routing recommendation only) or insufficient-evidence.",
7
+ "type": "object",
8
+ "additionalProperties": false,
9
+ "required": ["runName", "language", "repos", "complaints"],
10
+ "properties": {
11
+ "runName": {
12
+ "type": "string",
13
+ "minLength": 1,
14
+ "description": "Run name supplied by the user or defaulted to complaints-<YYYYMMDD>."
15
+ },
16
+ "phase": {
17
+ "type": "string",
18
+ "enum": [
19
+ "intake",
20
+ "fetching_graylog",
21
+ "correlating_repos",
22
+ "triaging",
23
+ "drafting",
24
+ "awaiting_output_decision",
25
+ "dispatching",
26
+ "reporting",
27
+ "done"
28
+ ],
29
+ "description": "Resume marker. Set after each phase boundary."
30
+ },
31
+ "language": {
32
+ "type": "string",
33
+ "enum": ["tr", "en"],
34
+ "description": "Report body language, resolved from prefs.global.outputLanguage."
35
+ },
36
+ "account": {
37
+ "type": ["string", "null"],
38
+ "description": "Account id resolved by the account picker; null for local-only flows."
39
+ },
40
+ "repos": {
41
+ "type": "array",
42
+ "minItems": 1,
43
+ "items": {
44
+ "type": "object",
45
+ "additionalProperties": false,
46
+ "required": ["name", "layer"],
47
+ "properties": {
48
+ "name": { "type": "string", "minLength": 1 },
49
+ "layer": {
50
+ "type": "string",
51
+ "enum": ["ios", "android", "web", "mobile-bff", "web-bff", "other"],
52
+ "description": "User-confirmed layer tag (Phase 0 Step 3b). core is NOT a layer here - it is the residual verdict, not a repo."
53
+ },
54
+ "localPath": { "type": ["string", "null"] },
55
+ "provider": { "type": ["string", "null"] }
56
+ }
57
+ },
58
+ "description": "Repos selected in the multi-select picker, each tagged with the layer it implements."
59
+ },
60
+ "input": {
61
+ "type": "object",
62
+ "additionalProperties": false,
63
+ "required": ["sources", "complaintCount", "redacted"],
64
+ "properties": {
65
+ "sources": {
66
+ "type": "array",
67
+ "minItems": 1,
68
+ "items": {
69
+ "type": "object",
70
+ "additionalProperties": false,
71
+ "required": ["type"],
72
+ "properties": {
73
+ "type": { "type": "string", "enum": ["file", "paste", "jira", "confluence"] },
74
+ "ref": {
75
+ "type": ["string", "null"],
76
+ "description": "File path, Jira issue key, or Confluence URL. null for paste."
77
+ },
78
+ "format": {
79
+ "type": ["string", "null"],
80
+ "enum": ["csv", "xlsx", "txt", "json", "text", null]
81
+ }
82
+ }
83
+ }
84
+ },
85
+ "complaintCount": { "type": "integer", "minimum": 0 },
86
+ "redacted": {
87
+ "type": "boolean",
88
+ "description": "Must be true for any run that dispatches output; only --no-redact debug runs of parse-complaints.sh produce false."
89
+ }
90
+ }
91
+ },
92
+ "complaints": {
93
+ "type": "array",
94
+ "items": {
95
+ "type": "object",
96
+ "additionalProperties": false,
97
+ "required": ["id", "textRedacted"],
98
+ "properties": {
99
+ "id": { "type": "string", "pattern": "^C-[0-9]{2,}$" },
100
+ "textRedacted": { "type": "string", "minLength": 1 },
101
+ "trxId": { "type": ["string", "null"] },
102
+ "convId": { "type": ["string", "null"] },
103
+ "date": { "type": ["string", "null"] },
104
+ "platformHint": { "type": ["string", "null"] },
105
+ "skipGraylog": {
106
+ "type": "boolean",
107
+ "default": false,
108
+ "description": "True when the user explicitly marked the complaint skip-graylog at the Phase 0 Step 5 id-confirmation loop."
109
+ },
110
+ "graylog": {
111
+ "type": "object",
112
+ "additionalProperties": false,
113
+ "required": ["status"],
114
+ "properties": {
115
+ "status": { "type": "string", "enum": ["pending", "ok", "degraded", "skipped"] },
116
+ "totalResults": { "type": "integer", "minimum": 0 },
117
+ "degradeReason": { "type": ["string", "null"] }
118
+ }
119
+ },
120
+ "repoEvidence": {
121
+ "type": "array",
122
+ "items": {
123
+ "type": "object",
124
+ "additionalProperties": false,
125
+ "required": ["repo", "layer", "file", "signal", "matchKind"],
126
+ "properties": {
127
+ "repo": { "type": "string" },
128
+ "layer": {
129
+ "type": "string",
130
+ "enum": ["ios", "android", "web", "mobile-bff", "web-bff", "other"]
131
+ },
132
+ "file": { "type": "string" },
133
+ "line": { "type": ["integer", "null"] },
134
+ "signal": {
135
+ "type": "string",
136
+ "description": "The Graylog-derived signal that matched: endpoint path, error code, exception name, message template, or source service name."
137
+ },
138
+ "matchKind": { "type": "string", "enum": ["direct", "partial"] }
139
+ }
140
+ }
141
+ },
142
+ "verdict": {
143
+ "type": "object",
144
+ "additionalProperties": false,
145
+ "required": ["category", "confidence", "rationale"],
146
+ "properties": {
147
+ "category": {
148
+ "type": "string",
149
+ "enum": ["client", "bff", "core", "insufficient-evidence"]
150
+ },
151
+ "layer": {
152
+ "type": ["string", "null"],
153
+ "enum": ["ios", "android", "web", "mobile-bff", "web-bff", null],
154
+ "description": "Set for client/bff verdicts; null for core and insufficient-evidence."
155
+ },
156
+ "confidence": { "type": "string", "enum": ["high", "medium", "low"] },
157
+ "rationale": { "type": "string", "minLength": 1 }
158
+ }
159
+ },
160
+ "handoff": {
161
+ "type": ["object", "null"],
162
+ "additionalProperties": false,
163
+ "description": "Present only for client/bff verdicts: development handoff grounded in the existing architecture (repoEvidence files as reference).",
164
+ "properties": {
165
+ "fixPlan": {
166
+ "type": "array",
167
+ "items": { "type": "string" },
168
+ "description": "2-5 numbered steps, each referencing a cited file:line or component, reuse-first."
169
+ },
170
+ "devPrompt": {
171
+ "type": ["string", "null"],
172
+ "description": "English prompt block ready for /multi-agent:dev or a Jira description; includes the [C-NN] id."
173
+ }
174
+ }
175
+ },
176
+ "routing": {
177
+ "type": ["object", "null"],
178
+ "additionalProperties": false,
179
+ "description": "Present only for core verdicts: the routing recommendation to the backend core team. Never contains fix analysis.",
180
+ "properties": {
181
+ "suspectedService": {
182
+ "type": ["string", "null"],
183
+ "description": "Graylog message source field of the failing upstream service."
184
+ },
185
+ "endpoint": { "type": ["string", "null"] },
186
+ "errorCode": { "type": ["string", "null"] },
187
+ "evidenceExcerpt": {
188
+ "type": ["string", "null"],
189
+ "description": "Short redacted English excerpt from the Graylog message."
190
+ },
191
+ "suggestedQueue": {
192
+ "type": ["string", "null"],
193
+ "description": "Optional team/queue label from prefs.projects[*].routing.coreTeamLabel; null when unset."
194
+ },
195
+ "confidence": { "type": ["string", "null"], "enum": ["high", "medium", "low", null] }
196
+ }
197
+ }
198
+ }
199
+ }
200
+ },
201
+ "outputs": {
202
+ "type": "object",
203
+ "additionalProperties": false,
204
+ "properties": {
205
+ "draftDir": { "type": ["string", "null"] },
206
+ "files": { "type": "array", "items": { "type": "string" } },
207
+ "destinations": {
208
+ "type": "array",
209
+ "items": { "type": "string", "enum": ["local", "confluence", "jira"] }
210
+ },
211
+ "confluencePageUrl": { "type": ["string", "null"] },
212
+ "jiraIssueKey": { "type": ["string", "null"] }
213
+ }
214
+ }
215
+ }
216
+ }
@@ -0,0 +1,46 @@
1
+ /**
2
+ * prefs-2.5.0-to-2.6.0.mjs - preference schema upgrade 2.5.0 -> 2.6.0
3
+ *
4
+ * v15.0.0 renamed the pipeline-tail command a second time: /multi-agent:finish
5
+ * (pre-2.5.0) became :ship (2.5.0) and is now :resume-local, because the command
6
+ * continues locally-done work through review/commit/report - it opens the PR but
7
+ * merges nothing, so "ship" oversold it. One preference key follows:
8
+ *
9
+ * - global.resumeLocal.autoFix (default FALSE)
10
+ * Carried across from global.ship.autoFix (itself carried from
11
+ * global.finish.autoFix): a user who opted into auto-fix did so
12
+ * deliberately, so the value survives every hop of the rename chain.
13
+ *
14
+ * Idempotent: safe on already-2.6.0 input. Non-destructive: an existing explicit
15
+ * value is preserved; the legacy `ship`/`finish` blocks are removed because they
16
+ * are no longer declared properties and would fail a closed `global`.
17
+ *
18
+ * @param {object} data - parsed JSON content of the preferences file
19
+ * @returns {object} - same data with schemaVersion = "2.6.0"
20
+ */
21
+ export default function migrate(data) {
22
+ const out = JSON.parse(JSON.stringify(data));
23
+
24
+ out.schemaVersion = "2.6.0";
25
+
26
+ if (!out.global) out.global = {};
27
+
28
+ if (typeof out.global.resumeLocal !== "object" || out.global.resumeLocal === null) {
29
+ out.global.resumeLocal = {};
30
+ }
31
+ if (typeof out.global.resumeLocal.autoFix !== "boolean") {
32
+ const legacy =
33
+ typeof out.global.ship?.autoFix === "boolean"
34
+ ? out.global.ship.autoFix
35
+ : out.global.finish?.autoFix;
36
+ out.global.resumeLocal.autoFix = typeof legacy === "boolean" ? legacy : false;
37
+ }
38
+ for (const key of ["ship", "finish"]) {
39
+ if (out.global[key] && typeof out.global[key] === "object") {
40
+ delete out.global[key].autoFix;
41
+ if (Object.keys(out.global[key]).length === 0) delete out.global[key];
42
+ }
43
+ }
44
+
45
+ return out;
46
+ }