@mmerterden/multi-agent-pipeline 14.2.2 → 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 (122) hide show
  1. package/CHANGELOG.md +76 -6
  2. package/README.md +15 -8
  3. package/README.tr.md +15 -8
  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 +7 -7
  9. package/docs/ecosystem.md +28 -28
  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 +19 -8
  17. package/install/claude.mjs +144 -59
  18. package/install/codex.mjs +28 -3
  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 +3 -3
  23. package/package.json +1 -2
  24. package/pipeline/commands/multi-agent/SKILL.md +2 -0
  25. package/pipeline/commands/multi-agent/analysis/SKILL.md +3 -3
  26. package/pipeline/commands/multi-agent/analysis-resolve/SKILL.md +2 -2
  27. package/pipeline/commands/multi-agent/build-optimize/SKILL.md +9 -9
  28. package/pipeline/commands/multi-agent/channels/SKILL.md +1 -1
  29. package/pipeline/commands/multi-agent/complaint-analysis/SKILL.md +186 -0
  30. package/pipeline/commands/multi-agent/dev/SKILL.md +1 -1
  31. package/pipeline/commands/multi-agent/dev-autopilot/SKILL.md +1 -1
  32. package/pipeline/commands/multi-agent/dev-local/SKILL.md +1 -1
  33. package/pipeline/commands/multi-agent/dev-local-autopilot/SKILL.md +1 -1
  34. package/pipeline/commands/multi-agent/garbage-collect/SKILL.md +1 -1
  35. package/pipeline/commands/multi-agent/help/SKILL.md +19 -4
  36. package/pipeline/commands/multi-agent/ios-coding-standard/SKILL.md +2 -2
  37. package/pipeline/commands/multi-agent/jira/SKILL.md +1 -1
  38. package/pipeline/commands/multi-agent/prune-prompts/SKILL.md +81 -0
  39. package/pipeline/commands/multi-agent/resume/SKILL.md +1 -1
  40. package/pipeline/commands/multi-agent/{ship → resume-local}/SKILL.md +8 -8
  41. package/pipeline/commands/multi-agent/setup/SKILL.md +5 -5
  42. package/pipeline/commands/multi-agent/stack/SKILL.md +55 -43
  43. package/pipeline/commands/multi-agent/store-ready/SKILL.md +3 -3
  44. package/pipeline/commands/multi-agent/sync/SKILL.md +18 -11
  45. package/pipeline/commands/multi-agent/testflight-validation/SKILL.md +1 -1
  46. package/pipeline/commands/multi-agent/uninstall/SKILL.md +2 -0
  47. package/pipeline/commands/multi-agent/update/SKILL.md +1 -1
  48. package/pipeline/lib/issue-fetcher.sh +1 -1
  49. package/pipeline/lib/parse-complaints.sh +306 -0
  50. package/pipeline/multi-agent-refs/channels/wiki.md +3 -3
  51. package/pipeline/multi-agent-refs/complaint-analysis-template.md +99 -0
  52. package/pipeline/multi-agent-refs/component-dispatch.md +6 -6
  53. package/pipeline/multi-agent-refs/cross-cli-contract.md +16 -16
  54. package/pipeline/multi-agent-refs/features/external-context-injection.md +1 -1
  55. package/pipeline/multi-agent-refs/features/stack-skill-routing.md +5 -5
  56. package/pipeline/multi-agent-refs/generate-issue.md +1 -1
  57. package/pipeline/multi-agent-refs/phases/modes.md +1 -1
  58. package/pipeline/multi-agent-refs/phases/phase-0-init.md +1 -1
  59. package/pipeline/multi-agent-refs/phases/phase-1-analysis.md +7 -7
  60. package/pipeline/multi-agent-refs/phases/phase-2-planning.md +5 -5
  61. package/pipeline/multi-agent-refs/phases/phase-3-dev.md +3 -3
  62. package/pipeline/multi-agent-refs/phases/phase-4-review.md +12 -12
  63. package/pipeline/multi-agent-refs/phases/phase-5-test.md +1 -1
  64. package/pipeline/multi-agent-refs/tracker-contract.md +1 -1
  65. package/pipeline/multi-agent-refs/wiki-capture.md +2 -2
  66. package/pipeline/preferences-template.json +13 -5
  67. package/pipeline/rules/figma-pipeline.md +2 -2
  68. package/pipeline/schemas/agent-state.schema.json +1 -1
  69. package/pipeline/schemas/complaint-analysis-spec.schema.json +216 -0
  70. package/pipeline/schemas/migrations/prefs-2.5.0-to-2.6.0.mjs +46 -0
  71. package/pipeline/schemas/prefs.schema.json +276 -66
  72. package/pipeline/schemas/token-budget.json +2 -2
  73. package/pipeline/scripts/_stack-routing.mjs +79 -0
  74. package/pipeline/scripts/audit-log-rotate.sh +4 -1
  75. package/pipeline/scripts/build-skills-index.mjs +11 -0
  76. package/pipeline/scripts/build-stack-plugins.mjs +28 -60
  77. package/pipeline/scripts/check-derived-drift.mjs +52 -28
  78. package/pipeline/scripts/gc-worktrees.sh +4 -1
  79. package/pipeline/scripts/gen-skills-index.mjs +1 -1
  80. package/pipeline/scripts/match-skills.mjs +8 -2
  81. package/pipeline/scripts/migrate-prefs.mjs +28 -20
  82. package/pipeline/scripts/phase-tracker.sh +13 -5
  83. package/pipeline/scripts/phase0-exit-gate.mjs +3 -2
  84. package/pipeline/scripts/run-aggregator.mjs +7 -2
  85. package/pipeline/scripts/scan-agent-config.sh +1 -1
  86. package/pipeline/scripts/skill-conformance.mjs +165 -30
  87. package/pipeline/scripts/smoke-cross-cli-behavior.sh +1 -1
  88. package/pipeline/scripts/test-gap-rules/android.json +25 -0
  89. package/pipeline/scripts/test-gap-rules/ios.json +34 -0
  90. package/pipeline/scripts/test-gap-rules/node.json +29 -0
  91. package/pipeline/scripts/test-gap-rules/python.json +25 -0
  92. package/pipeline/scripts/uninstall.mjs +158 -11
  93. package/pipeline/scripts/validate-complaint-doc.mjs +229 -0
  94. package/pipeline/scripts/validate-reviewer.mjs +9 -3
  95. package/pipeline/skills/.skill-manifest.json +156 -108
  96. package/pipeline/skills/.skills-index.json +449 -12
  97. package/pipeline/skills/shared/README.md +14 -10
  98. package/pipeline/skills/shared/core/multi-agent-analysis-resolve/SKILL.md +1 -1
  99. package/pipeline/skills/shared/core/multi-agent-build-optimize/SKILL.md +1 -1
  100. package/pipeline/skills/shared/core/multi-agent-complaint-analysis/SKILL.md +49 -0
  101. package/pipeline/skills/shared/core/multi-agent-dev/SKILL.md +1 -1
  102. package/pipeline/skills/shared/core/multi-agent-dev-autopilot/SKILL.md +1 -1
  103. package/pipeline/skills/shared/core/multi-agent-dev-local/SKILL.md +1 -1
  104. package/pipeline/skills/shared/core/multi-agent-dev-local-autopilot/SKILL.md +1 -1
  105. package/pipeline/skills/shared/core/multi-agent-ios-coding-standard/SKILL.md +2 -2
  106. package/pipeline/skills/shared/core/multi-agent-prune-prompts/SKILL.md +83 -0
  107. package/pipeline/skills/shared/core/{multi-agent-ship → multi-agent-resume-local}/SKILL.md +6 -6
  108. package/pipeline/skills/shared/core/multi-agent-stack/SKILL.md +79 -22
  109. package/pipeline/skills/shared/core/multi-agent-store-ready/SKILL.md +1 -1
  110. package/pipeline/skills/shared/core/multi-agent-sync/SKILL.md +8 -8
  111. package/pipeline/skills/shared/core/multi-agent-testflight-validation/SKILL.md +1 -1
  112. package/pipeline/skills/shared/external/ios-coding-standard/modules/_TEMPLATE.yml +2 -2
  113. package/pipeline/skills/shared/external/ios-coding-standard/references/rules.yml +368 -33
  114. package/pipeline/skills/shared/external/ios-coding-standard/references/swiftlint.draft.yml +1 -2
  115. package/pipeline/skills/shared/external/ios-coding-standard/scripts/check_structure.py +765 -0
  116. package/pipeline/skills/shared/external/ios-module-structure/SKILL.md +75 -0
  117. package/pipeline/skills/shared/external/ios-module-structure/modules/_TEMPLATE.yml +131 -0
  118. package/pipeline/skills/shared/external/ios-module-structure/references/rules.yml +559 -0
  119. package/pipeline/skills/shared/external/ios-module-structure/scripts/check_structure.py +765 -0
  120. package/pipeline/skills/shared/external/localization-reuse-map/example-mapping.json +53 -10
  121. package/pipeline/skills/shared/external/localization-reuse-map/reference/sources-and-recipes.md +4 -3
  122. package/pipeline/skills/skills-index.md +7 -4
@@ -79,7 +79,7 @@ After issue selection, inspect `maturity` from `~/.claude/lib/issue-fetcher.sh`:
79
79
  > **Empty description → parent candidate**: development sub-tasks are often filed with no description of their own, with the real requirements on the parent issue. Before scoring, `issue-fetcher.sh` fetches the issue's `parent` (single hop, no chasing the parent's parent). If the issue's own description is empty and the parent's isn't, it does **not** auto-substitute - it exposes `descriptor.parentKey` + `descriptor.parentDescription` as a candidate and adds `description_empty_parent_available` to `warnings` (not `blockers`) instead of the plain `description_empty` blocker. If the parent is also empty or unreachable, `description_empty` still blocks exactly as before.
80
80
  >
81
81
  > When `description_empty_parent_available` is present, ask a tailored question instead of the generic "Continue?" below:
82
- > - `question` (outputLanguage): "Bu issue'nun (`{KEY}`) açıklaması boş, ama parent'ın (`{parentKey}`) açıklaması var. Parent'ın açıklamasından devam edilsin mi?" / "This issue's (`{KEY}`) description is empty, but its parent (`{parentKey}`) has one. Continue using the parent's description?" — show a short excerpt of `parentDescription` for context.
82
+ > - `question` (outputLanguage): "Bu issue'nun (`{KEY}`) açıklaması boş, ama parent'ın (`{parentKey}`) açıklaması var. Parent'ın açıklamasından devam edilsin mi?" / "This issue's (`{KEY}`) description is empty, but its parent (`{parentKey}`) has one. Continue using the parent's description?" - show a short excerpt of `parentDescription` for context.
83
83
  > - `header` (English, <=12 chars): `"Parent desc"`
84
84
  > - `options`: `{ label: "Use parent's description" (Recommended), description: "Continue with descriptor.parentDescription as the working description for this task." }` / `{ label: "No, halt", description: "Treat like description_empty - fix the issue's own description in Jira first." }`
85
85
  > - **Accept** → set the working `description` to `parentDescription` for every later phase (analysis/dev/review all read this one substituted value); log the substitution (source issue + parent key) to `agent-log.md`.
@@ -0,0 +1,81 @@
1
+ ---
2
+ description: "Zero-base prompt review: measure the always-on instruction footprint, classify every rule block, propose keep/trial-removal/delete; applies only approved rows. Use when a new model ships or instructions have accumulated."
3
+ description-tr: "Sıfır-tabanlı prompt incelemesi: sürekli yüklü talimat yükünü ölçer, her kural bloğunu sınıflar, tut/dene/sil önerir; yalnızca onaylananı uygular."
4
+ argument-hint: "[--report-only]"
5
+ ---
6
+
7
+ # multi-agent prune-prompts - Zero-Base Prompt Review
8
+
9
+ Instruction files only grow. Every rule was added because some model once got
10
+ something wrong, and nobody deletes a rule once a workaround ships. A newer
11
+ model needs fewer of them; the ones it no longer needs are pure context tax on
12
+ every session, and stale rules actively mislead.
13
+
14
+ The discipline this command applies (after Boris Cherny's advice): on a model
15
+ upgrade, assume ZERO instructions are needed, and let each line earn its way
16
+ back. A line earns its way back only after the model gets the same thing wrong
17
+ repeatedly (three strikes) WITHOUT it. Instructions are a cache of past model
18
+ failures; a new model invalidates that cache.
19
+
20
+ ## Flow
21
+
22
+ ### 1. MEASURE - the always-on footprint
23
+
24
+ Estimate tokens (chars/4) for each layer the model carries into every session:
25
+
26
+ ```bash
27
+ wc -c "$HOME/.claude/CLAUDE.md" 2>/dev/null
28
+ wc -c "$HOME"/.claude/rules/*.md 2>/dev/null
29
+ find "$PWD" -maxdepth 2 -name "CLAUDE.md" -exec wc -c {} + 2>/dev/null
30
+ ```
31
+
32
+ Report a table: layer, file, estimated tokens, share of total. Flag any single
33
+ file above ~2,000 estimated tokens.
34
+
35
+ ### 2. CLASSIFY - what kind of line is each rule
36
+
37
+ Walk CLAUDE.md + each rules/ file section by section. Classify every
38
+ instruction block:
39
+
40
+ | Class | Meaning | Default verdict |
41
+ |---|---|---|
42
+ | **Constraint** | Facts the model cannot infer (hosts, key names, branch formats, team conventions) | keep |
43
+ | **Failure patch** | "Never do X" added after a model did X | trial removal - the current model may not need it |
44
+ | **Restatement** | Something the model does correctly anyway (write tests, guard early) | delete |
45
+ | **Stale** | References files, commands or workflows that no longer exist | delete |
46
+
47
+ For failure patches, note WHEN the patch was added if git history shows it -
48
+ a patch older than the current model's release is the strongest removal
49
+ candidate.
50
+
51
+ ### 3. REPORT - the zero-base proposal
52
+
53
+ One table, every block accounted for: file, section, class, verdict
54
+ (keep / trial-removal / delete), and the one-line reason. Never a sample -
55
+ if a section is not in the table, the review did not happen.
56
+
57
+ With `--report-only`, stop here.
58
+
59
+ ### 4. APPLY - only what the user approves
60
+
61
+ Present the table, ask which verdicts to apply (all deletes / all
62
+ trial-removals too / pick rows). For approved rows, edit the files. Trial
63
+ removals move the block into `~/.claude/rules/.pruned/<file>.md` with a
64
+ dated header rather than deleting outright, so a strike-out can be reverted
65
+ by moving the block back.
66
+
67
+ ### 5. THE THREE-STRIKE RULE going forward
68
+
69
+ After a prune, when the model gets something wrong that a removed rule used
70
+ to cover, do NOT restore it on the first miss. Record the miss (the
71
+ `.pruned/` file has a `strikes:` line per block). Restore the line only on
72
+ the third occurrence of the SAME failure. One line back at a time - never
73
+ the whole file.
74
+
75
+ ## Boundaries
76
+
77
+ - Never touches skill bodies or command files - those load on demand and are
78
+ not part of the always-on footprint. The lint gate (`lint-skills.mjs`)
79
+ owns their budgets.
80
+ - Never touches `multi-agent-preferences.json` or anything under `logs/`.
81
+ - Applies nothing without explicit approval on the report table.
@@ -10,7 +10,7 @@ argument-hint: "[#id] - optional: task ID (e.g. #2). If omitted, the most rece
10
10
 
11
11
  Resume a paused or failed task from the last successful phase.
12
12
 
13
- > **Not the same as `/multi-agent:ship`.** `resume` continues a **tracked pipeline task** (needs its `agent-state.json`/worktree) from where it stopped. `/multi-agent:ship` takes **ad-hoc local work** on the current branch (no prior task required) and runs the pipeline tail - Review → Build+Test → PR → Jira report - over it.
13
+ > **Not the same as `/multi-agent:resume-local`.** `resume` continues a **tracked pipeline task** (needs its `agent-state.json`/worktree) from where it stopped. `/multi-agent:resume-local` takes **ad-hoc local work** on the current branch (no prior task required) and runs the pipeline tail - Review → Build+Test → PR → Jira report - over it.
14
14
 
15
15
  ## Steps
16
16
 
@@ -4,11 +4,11 @@ description-tr: "Halihazırda bitmiş LOKAL işi pipeline kuyruğundan geçirir:
4
4
  allowed-tools: Agent, Bash, Read, Write, Edit, Glob, Grep, TaskCreate, TaskUpdate, TaskList, TaskGet, AskUserQuestion, WebFetch, WebSearch, Skill
5
5
  ---
6
6
 
7
- # multi-agent ship - Take Existing Branch Work Through the Pipeline Tail
7
+ # multi-agent resume-local - Take Existing Branch Work Through the Pipeline Tail
8
8
 
9
9
  > **Language (read FIRST)**: Before any status output, read `prefs.global.outputLanguage` and render every conversational line in it. `AskUserQuestion` `label`/`header` stay English, but its `question` and option `description`s render in `outputLanguage`; external payload bodies follow `outputLanguage` too (identifiers, commit messages, branch names stay English). Full contract: `$HOME/.claude/multi-agent-refs/rules.md` "Language Application".
10
10
 
11
- You already did the work locally - wrote code on the current branch and maybe tested it by hand, or committed it outside the pipeline entirely. (As of v14.0.0 the `--dev` family reviews its own output, so this command is for work that had no pipeline run behind it, not a patch for a mode that skipped review.) `/multi-agent:ship` picks up from there and runs the **pipeline tail** over that existing local work in one command: parallel review, a build + test success gate, commit/push + PR, then the technical analysis and a **Jira comment with test scenarios**. It does NOT re-develop - Analysis / Planning / Dev (phases 1-3) are intentionally skipped; the diff already on the branch IS the input.
11
+ You already did the work locally - wrote code on the current branch and maybe tested it by hand, or committed it outside the pipeline entirely. (As of v14.0.0 the `--dev` family reviews its own output, so this command is for work that had no pipeline run behind it, not a patch for a mode that skipped review.) `/multi-agent:resume-local` picks up from there and runs the **pipeline tail** over that existing local work in one command: parallel review, a build + test success gate, commit/push + PR, then the technical analysis and a **Jira comment with test scenarios**. It does NOT re-develop - Analysis / Planning / Dev (phases 1-3) are intentionally skipped; the diff already on the branch IS the input.
12
12
 
13
13
  ## When to use it
14
14
 
@@ -24,10 +24,10 @@ You already did the work locally - wrote code on the current branch and maybe
24
24
  ## Input
25
25
 
26
26
  ```bash
27
- /multi-agent:ship # current branch vs its base; resolve Jira id from branch name
28
- /multi-agent:ship PROJ-12345 # bind to an explicit Jira id for the Phase 7 comment
29
- /multi-agent:ship --base develop # override the base branch for the diff
30
- /multi-agent:ship autopilot # no gate prompts: auto-fix blocking findings, auto-PR, auto-comment
27
+ /multi-agent:resume-local # current branch vs its base; resolve Jira id from branch name
28
+ /multi-agent:resume-local PROJ-12345 # bind to an explicit Jira id for the Phase 7 comment
29
+ /multi-agent:resume-local --base develop # override the base branch for the diff
30
+ /multi-agent:resume-local autopilot # no gate prompts: auto-fix blocking findings, auto-PR, auto-comment
31
31
  ```
32
32
 
33
33
  ## Pipeline
@@ -54,7 +54,7 @@ Phases 1-3 (Analysis / Planning / Dev) are skipped by design - `ship` treats t
54
54
 
55
55
  - **Phase 4 Review** - run per `$HOME/.claude/multi-agent-refs/phases/phase-4-review.md` against the resolved diff: deterministic gates (Step 1.x), stack-specific parallel reviewers (Fable + Sonnet on Claude Code; GPT + Opus + Sonnet on Copilot CLI), Fable triage → `triage.accepted`. Blocking/important accepted findings:
56
56
  - interactive: present them and ask (`AskUserQuestion`) whether to fix now (loop back through a minimal Phase-3-style TDD fix) or proceed;
57
- - `autopilot` (or `prefs.global.ship.autoFix == true`): auto-fix accepted blocking/important findings, then re-review the fix, before advancing.
57
+ - `autopilot` (or `prefs.global.resumeLocal.autoFix == true`): auto-fix accepted blocking/important findings, then re-review the fix, before advancing.
58
58
  - **Phase 5 Build+Test** - the **automated success gate** (this is what "build+test success" means here; the interactive device user-test is `/multi-agent:manual-test`). Stack-aware: build via `figma-config.build` (iOS scheme / Android gradle / detected backend/frontend build) and run the existing test suite if present (`swift test` / `xcodebuild test` / `./gradlew test` / `pytest` / `npm test` / `vitest`). Require success to advance; on failure, surface logs and (interactive) stop or (autopilot) attempt a bounded fix loop. **If the repo has no tests, report "no tests present" - never fabricate test results.**
59
59
  - **Phase 6 Commit/PR** - per `$HOME/.claude/multi-agent-refs/phases/phase-6-commit.md`: stage + commit any remaining local changes with a conventional message (`{type}(scope): desc [{JIRA_KEY}-{id}]`), push, and open a PR **only if one does not already exist** for the branch. PR body per `$HOME/.claude/multi-agent-refs/rules.md "External System Outputs"` and `$HOME/.claude/rules/git-conventions.md` - `Ref: #N` / `Related: #N`, never `Closes/Fixes/Resolves`; NO AI/bot attribution anywhere.
60
60
  - **Phase 7 Report** - per `$HOME/.claude/multi-agent-refs/phases/phase-7-report.md` + `channels.md`: produce the **technical analysis** and **test scenarios**, then post to the configured channels. Default content for `ship`: a Jira **comment** carrying the technical analysis + the test scenarios (and, when the PR was opened, the PR description). Every body runs through the humanizer; bot/tool/AI signatures are FORBIDDEN in comments.
@@ -108,5 +108,5 @@ No TaskList widget. After every state change call `bash $HOME/.claude/scripts/ph
108
108
  ```bash
109
109
  /multi-agent:dev-local "PROJ-12345" # develop locally (Init→Dev→Commit→Report, no review/test)
110
110
  # ... you inspect / hand-test the change ...
111
- /multi-agent:ship # now: review + build/test + PR + Jira analysis & test scenarios
111
+ /multi-agent:resume-local # now: review + build/test + PR + Jira analysis & test scenarios
112
112
  ```
@@ -883,12 +883,12 @@ Stack skills ship as versioned plugins in the `{owner}/multi-agent-plugins` mark
883
883
  claude marketplace add {owner}/multi-agent-plugins 2>/dev/null || true
884
884
  ```
885
885
  2. Detect the project stack from markers and enable the matching plugin(s) plus the always-on common plugin in the project's `.claude/settings.json` `enabledPlugins`:
886
- - `.xcodeproj` / `Package.swift` / `*.xcworkspace` → `ai-ios-engineering-toolkit`
887
- - `build.gradle` / `settings.gradle` → `ai-android-engineering-toolkit`
888
- - `package.json` with `react`/`next` → `ai-frontend-engineering-toolkit`
886
+ - `.xcodeproj` / `Package.swift` / `*.xcworkspace` → `ai-ios-toolkit`
887
+ - `build.gradle` / `settings.gradle` → `ai-android-toolkit`
888
+ - `package.json` with `react`/`next` → `ai-frontend-toolkit`
889
889
  - `requirements.txt` / `pyproject.toml` / server `package.json` → `ai-backend-toolkit`
890
- - **no clear marker → default `ai-ios-engineering-toolkit`**
891
- `ai-common-engineering-toolkit@multi-agent-plugins` is always set `true` alongside the stack plugin.
890
+ - **no clear marker → default `ai-ios-toolkit`**
891
+ `ai-common-toolkit@multi-agent-plugins` is always set `true` alongside the stack plugin.
892
892
  3. Report the enabled set. To change later, run `/multi-agent:stack <ios|android|frontend|backend|...>` in the repo. Pipeline Phase 1 auto-detects the stack for its own routing regardless of enablement.
893
893
 
894
894
  The marketplace repo name (`multi-agent-plugins`) is generic; a different org points `{owner}` at its own fork - nothing in the pipeline is coupled to a specific account.
@@ -1,25 +1,29 @@
1
1
  ---
2
- description: "Select the active stack for this repo by enabling the matching marketplace plugin(s) in .claude/settings.json (ios/android/mobile/backend/frontend/fullstack/all). Use when a repo's stack changed or the wrong plugins are enabled for it."
3
- description-tr: "Bu repo için aktif stack'i seçer: eşleşen marketplace plugin'lerini .claude/settings.json'da etkinleştirir (ios/android/mobile/backend/frontend/fullstack/all)."
4
- allowed-tools: Bash, Read, Edit, Write
2
+ description: "Select the active stack(s) for this repo by enabling the matching marketplace plugin(s) in .claude/settings.json. Multi-select: pass several stacks (ios backend) or pick them in the native picker. Use when a repo's stack changed or the wrong plugins are enabled for it."
3
+ description-tr: "Bu repo için aktif stack'leri seçer: eşleşen marketplace plugin'lerini .claude/settings.json'da etkinleştirir. Çoklu seçim: birden fazla stack yazılabilir (ios backend) ya da native picker'dan seçilir."
4
+ argument-hint: "[ios|android|frontend|web|backend|mobile|fullstack|all ...]"
5
+ allowed-tools: Bash, Read, Edit, Write, AskUserQuestion
5
6
  ---
6
7
 
7
- # multi-agent stack - Select Stack via Plugin Enablement
8
+ # multi-agent stack - Select Stack(s) via Plugin Enablement
8
9
 
9
- Stack skills ship as plugins in the `{owner}/multi-agent-plugins` marketplace. Selecting a stack = **enabling the matching plugin(s)** in the current repo's `.claude/settings.json` `enabledPlugins`. The `ai-common-engineering-toolkit` (accessibility audit, humanizer, Firebase) is always enabled alongside the stack plugin.
10
+ Stack skills ship as plugins in the `{owner}/multi-agent-plugins` marketplace. Selecting a stack = **enabling the matching plugin(s)** in the current repo's `.claude/settings.json` `enabledPlugins`. The `ai-common-toolkit` (accessibility audit, humanizer, Firebase) is always enabled alongside the stack plugin(s).
11
+
12
+ On Claude Code the marketplace plugins are the ONLY source of stack skills - nothing is copied into `~/.claude/skills` anymore. A stack that is not enabled here is simply absent from the session. Copilot CLI and Codex CLI have no plugin loader; they receive a local copy filtered to the enabled stacks at install time, which is why step 5 below offers to refresh those copies after a change.
10
13
 
11
14
  This replaces the old `stack-swap.sh` mechanic that physically moved skill directories in `~/.claude/skills/`. There is no SessionStart hook and no directory shuffling - enablement is declarative, per-repo, and versioned.
12
15
 
13
16
  ## Usage
14
17
 
15
18
  ```bash
16
- /multi-agent:stack # show which plugins are enabled here
19
+ /multi-agent:stack # no arg → native multi-select picker (current state pre-noted)
17
20
  /multi-agent:stack ios # SwiftUI toolkit + common
21
+ /multi-agent:stack ios backend # any combination, space-separated
18
22
  /multi-agent:stack android # Compose toolkit + common
19
- /multi-agent:stack mobile # iOS + Android + common
23
+ /multi-agent:stack mobile # alias: ios + android + common
20
24
  /multi-agent:stack backend # Python / Node spec-driven toolkit + common
21
- /multi-agent:stack frontend # React / TSX toolkit + common
22
- /multi-agent:stack fullstack # frontend + backend + common
25
+ /multi-agent:stack frontend # React / TSX toolkit + common (alias: web)
26
+ /multi-agent:stack fullstack # alias: frontend + backend + common
23
27
  /multi-agent:stack all # all four stack toolkits + common
24
28
  ```
25
29
 
@@ -27,26 +31,37 @@ This replaces the old `stack-swap.sh` mechanic that physically moved skill direc
27
31
 
28
32
  | Stack | Plugins enabled (all `@multi-agent-plugins`) |
29
33
  |---|---|
30
- | `ios` | `ai-common-engineering-toolkit`, `ai-ios-engineering-toolkit` |
31
- | `android` | `ai-common-engineering-toolkit`, `ai-android-engineering-toolkit` |
32
- | `frontend` | `ai-common-engineering-toolkit`, `ai-frontend-engineering-toolkit` |
33
- | `backend` | `ai-common-engineering-toolkit`, `ai-backend-toolkit` |
34
- | `mobile` | common + `ai-ios-engineering-toolkit` + `ai-android-engineering-toolkit` |
35
- | `fullstack` | common + `ai-frontend-engineering-toolkit` + `ai-backend-toolkit` |
34
+ | `ios` | `ai-common-toolkit`, `ai-ios-toolkit` |
35
+ | `android` | `ai-common-toolkit`, `ai-android-toolkit` |
36
+ | `frontend` / `web` | `ai-common-toolkit`, `ai-frontend-toolkit` |
37
+ | `backend` | `ai-common-toolkit`, `ai-backend-toolkit` |
38
+ | `mobile` | common + `ai-ios-toolkit` + `ai-android-toolkit` |
39
+ | `fullstack` | common + `ai-frontend-toolkit` + `ai-backend-toolkit` |
36
40
  | `all` | common + all four stack toolkits |
37
41
 
42
+ Multiple args union their plugin sets: `ios backend` → common + iOS + backend.
43
+
38
44
  ## Behaviour
39
45
 
40
- 1. **No arg → status mode.** Read `.claude/settings.json` (repo) + `~/.claude/settings.json` (global) and print which `@multi-agent-plugins` plugins are currently enabled. Do not modify anything.
41
- 2. **Arg present → enable mode.** Ensure the marketplace is known, then write the matching `enabledPlugins` entries into the **current repo's** `.claude/settings.json`, disabling the stack toolkits that don't belong to the selected stack. `ai-common-engineering-toolkit` is always set to `true`.
42
- 3. **Unknown arg** → show the list above; do not guess.
46
+ 1. **No arg → native multi-select picker.** Read `.claude/settings.json` (repo) + `~/.claude/settings.json` (global) to learn the current state, then ask with `AskUserQuestion` (`multiSelect: true`) - NEVER a numbered text menu:
47
+ - `question` (in `outputLanguage`): which stacks should be active in this repo, noting the currently enabled ones
48
+ - `header`: "Stacks" (English, UI contract)
49
+ - `options` (4): `ios` / `android` / `frontend (web)` / `backend`, each `description` (in `outputLanguage`) naming the plugin it enables and marking the ones already enabled with "(currently on)" / "(şu an açık)"
50
+ - Empty selection or cancel → **status mode**: print the currently enabled `@multi-agent-plugins` plugins and exit without modifying anything.
51
+ 2. **Arg(s) present → enable mode.** Accept multiple space-separated stacks. Resolve each through the alias table (`web`→`frontend`, `mobile`→`ios android`, `fullstack`→`frontend backend`, `all`→every stack), union the plugin sets, then write the **current repo's** `.claude/settings.json`.
52
+ 3. **Write rules:**
53
+ - every plugin in the union is set to `true`
54
+ - every stack toolkit **not** in the union is set to `false` (leave non-`@multi-agent-plugins` entries untouched)
55
+ - `ai-common-toolkit@multi-agent-plugins` is always `true`
56
+ - **legacy-key cleanup**: delete any `ai-*-engineering-toolkit@multi-agent-plugins` keys - those plugin names were retired by the `ai-<stack>-toolkit` rename and a stale `true` there enables a plugin that no longer exists in the marketplace
57
+ 4. **Unknown arg** → show the table above; do not guess.
58
+ 5. **Copilot/Codex refresh offer.** Their local skill copies are filtered to the enabled stacks at install time, so after a change ask (single `AskUserQuestion`, not silent): "Refresh Copilot/Codex local copies now?" - Yes runs `node <pipelineRepo>/install.js --copilot --codex`, No leaves them stale with a one-line warning naming the command to run later. Skip this question entirely when neither `~/.copilot` nor `~/.codex` exists.
43
59
 
44
60
  ## Implementation
45
61
 
46
62
  ```bash
47
63
  REPO_SETTINGS=".claude/settings.json"
48
64
  MP="multi-agent-plugins"
49
- ARG="${1:-status}"
50
65
 
51
66
  # --- ensure the marketplace is known (idempotent) -------------------------
52
67
  if ! claude marketplace list 2>/dev/null | grep -q "$MP"; then
@@ -54,38 +69,35 @@ if ! claude marketplace list 2>/dev/null | grep -q "$MP"; then
54
69
  || echo "note: add the marketplace once with: claude marketplace add {owner}/multi-agent-plugins"
55
70
  fi
56
71
 
57
- COMMON="ai-common-engineering-toolkit@${MP}"
58
- IOS="ai-ios-engineering-toolkit@${MP}"
59
- ANDROID="ai-android-engineering-toolkit@${MP}"
60
- FRONTEND="ai-frontend-engineering-toolkit@${MP}"
72
+ COMMON="ai-common-toolkit@${MP}"
73
+ IOS="ai-ios-toolkit@${MP}"
74
+ ANDROID="ai-android-toolkit@${MP}"
75
+ FRONTEND="ai-frontend-toolkit@${MP}"
61
76
  BACKEND="ai-backend-toolkit@${MP}"
62
77
 
63
- if [ "$ARG" = "status" ]; then
64
- echo "Enabled multi-agent plugins (repo + global):"
65
- { [ -f "$REPO_SETTINGS" ] && cat "$REPO_SETTINGS"; cat "$HOME/.claude/settings.json"; } 2>/dev/null \
66
- | grep -oE "ai-[a-z-]+@${MP}\"[[:space:]]*:[[:space:]]*(true|false)" | sort -u
67
- exit 0
68
- fi
69
-
70
- # resolve the desired ON set
71
- case "$ARG" in
72
- ios) ON="$COMMON $IOS" ;;
73
- android) ON="$COMMON $ANDROID" ;;
74
- frontend) ON="$COMMON $FRONTEND" ;;
75
- backend) ON="$COMMON $BACKEND" ;;
76
- mobile) ON="$COMMON $IOS $ANDROID" ;;
77
- fullstack) ON="$COMMON $FRONTEND $BACKEND" ;;
78
- all) ON="$COMMON $IOS $ANDROID $FRONTEND $BACKEND" ;;
79
- *) echo "Unknown stack '$ARG'. One of: ios android mobile backend frontend fullstack all"; exit 1 ;;
80
- esac
78
+ # resolve every arg through the alias table, union the ON set
79
+ ON="$COMMON"
80
+ for ARG in "$@"; do
81
+ case "$ARG" in
82
+ ios) ON="$ON $IOS" ;;
83
+ android) ON="$ON $ANDROID" ;;
84
+ frontend|web) ON="$ON $FRONTEND" ;;
85
+ backend) ON="$ON $BACKEND" ;;
86
+ mobile) ON="$ON $IOS $ANDROID" ;;
87
+ fullstack) ON="$ON $FRONTEND $BACKEND" ;;
88
+ all) ON="$ON $IOS $ANDROID $FRONTEND $BACKEND" ;;
89
+ *) echo "Unknown stack '$ARG'. One of: ios android mobile backend frontend web fullstack all"; exit 1 ;;
90
+ esac
91
+ done
81
92
  ```
82
93
 
83
94
  After resolving `$ON`, edit `.claude/settings.json` (create `{ "enabledPlugins": {} }` if absent) so that:
84
95
  - every plugin in `$ON` is set to `true`,
85
96
  - every stack toolkit **not** in `$ON` is set to `false` (leave non-`@multi-agent-plugins` entries untouched),
86
- - `ai-common-engineering-toolkit@multi-agent-plugins` is always `true`.
97
+ - `ai-common-toolkit@multi-agent-plugins` is always `true`,
98
+ - every `ai-*-engineering-toolkit@multi-agent-plugins` key is **deleted** (retired names).
87
99
 
88
- Use the Read + Edit/Write tools (JSON must stay valid). Then print the resulting `enabledPlugins` block.
100
+ Use the Read + Edit/Write tools (JSON must stay valid). Then print the resulting `enabledPlugins` block and run step 5 (Copilot/Codex refresh offer).
89
101
 
90
102
  ## Notes
91
103
 
@@ -39,7 +39,7 @@ a package the store itself refuses, and a policy a human enforces.
39
39
  |---|---|---|
40
40
  | 1 Static | `ios_app_store_audit({archive_path, rules: "all"})` - 18 rules with real ITMS codes. Needs an `.xcarchive`. Reference: `apple-archive-compliance` skill | `android_apk_audit` plus the `google-play-compliance` skill's 21 rules: `bundletool validate` + manifest dump, `aapt2 dump badging`, `apksigner verify`, ABI / native scan. Needs an `.aab` (an `.apk` narrows it, see Step 3) |
41
41
  | 2 Authoritative | `ios_testflight_validate({ipa_path, platform: "ios", <credentials>})` → `xcrun altool --validate-app`. Needs an `.ipa` + credentials | **No client shipped.** Play's authoritative check exists only server-side, through a Publishing API draft edit that is validated and then abandoned. The pipeline has no tool for it, so this gate reports `SKIPPED (no local Play validator)` and the report says so. Do not substitute `bundletool validate` - that is Gate 1 |
42
- | 3 Policy | `app-store-review` skill vs repo source | `play-store-review` skill vs repo source |
42
+ | 3 Policy | `ai-ios-toolkit:app-store-review` skill vs repo source | `ai-android-toolkit:play-store-review` skill vs repo source |
43
43
 
44
44
  Gate 2's asymmetry is real and is reported as an asymmetry, not smoothed over. On
45
45
  iOS it is the only gate that catches a version+build pair already used - the most
@@ -248,7 +248,7 @@ reporting it here would fake a cleared gate.
248
248
  Load the platform's review skill and review the repo against it. This is the gate
249
249
  that catches what a human reviewer rejects, so it reads source, not the binary.
250
250
 
251
- **iOS** - `app-store-review`:
251
+ **iOS** - `ai-ios-toolkit:app-store-review`:
252
252
 
253
253
  | Area | Evidence to gather |
254
254
  |---|---|
@@ -260,7 +260,7 @@ that catches what a human reviewer rejects, so it reads source, not the binary.
260
260
  | IAP | anything unlocking features goes through StoreKit, with no external purchase path |
261
261
  | Sign in with Apple | present when a third-party social login is offered |
262
262
 
263
- **Android** - `play-store-review`:
263
+ **Android** - `ai-android-toolkit:play-store-review`:
264
264
 
265
265
  | Area | Evidence to gather |
266
266
  |---|---|
@@ -59,8 +59,8 @@ Run every step automatically:
59
59
  ```
60
60
  Step 1: PLATFORM Detect macOS / Linux / Windows (Git Bash / WSL); export PLATFORM env
61
61
  Step 1.5: DETECT Compare timestamps, find stale targets
62
- Step 2: COPILOT Claude Code -> Copilot CLI (instructions + 49 sub-command skills)
63
- Step 2b: CODEX Claude Code -> Codex CLI (1 router skill + 49 specs as refs + 8 agent TOML)
62
+ Step 2: COPILOT Claude Code -> Copilot CLI (instructions + 51 sub-command skills)
63
+ Step 2b: CODEX Claude Code -> Codex CLI (1 router skill + 51 specs as refs + 8 agent TOML)
64
64
  Step 3: REPO Claude Code -> pipeline repo (genericized, personal data scrub, bash -n on all sh)
65
65
  Step 3c: PLUGINS pipeline shared/external -> multi-agent-plugins marketplace (rebuild knowledge/,
66
66
  bump changed plugins' patch version, commit + push the plugins repo)
@@ -127,13 +127,13 @@ If nothing is stale → report "All targets up to date" and stop.
127
127
  - `~/.claude/CLAUDE.md`, `~/.claude/rules/`, `~/.claude/knowledge/`
128
128
  - `~/.claude/scripts/` - EXCEPT `pre-commit-check.sh`, `agent-guard.sh`, `agent-guard.py`, and `build-stack-plugins.mjs` (generic, synced)
129
129
  - `~/.claude/settings.json`
130
- - **Any `~/.claude/commands/multi-agent/*.md` whose frontmatter has `local-only: true`** - these are user/repo-specific alias wrappers that delegate to a private marketplace plugin (e.g. corporate `ai-ios-engineering-toolkit` skills exposed as `multi-agent:<name>`). Syncing them would leak the private plugin/skill names into the public pipeline. Filter before copy: skip every source file containing `local-only: true`, and after copy assert none reached `pipeline/commands/`.
130
+ - **Any `~/.claude/commands/multi-agent/*.md` whose frontmatter has `local-only: true`** - these are user/repo-specific alias wrappers that delegate to a private marketplace plugin (e.g. corporate `ai-ios-toolkit` skills exposed as `multi-agent:<name>`). Syncing them would leak the private plugin/skill names into the public pipeline. Filter before copy: skip every source file containing `local-only: true`, and after copy assert none reached `pipeline/commands/`.
131
131
  ```bash
132
132
  # backstop: no local-only wrapper may exist in the synced target
133
133
  grep -rl "^local-only: true" ~/multi-agent-pipeline/pipeline/commands/ 2>/dev/null \
134
134
  && { echo "ABORT: local-only wrapper leaked into pipeline/commands"; exit 1; } || true
135
135
  # backstop: no corporate marketplace/skill reference in the synced tree
136
- grep -rniE "ai-ios-engineering-toolkit:(create-ui-component|evolve-ui-component|fix-bug|branch-and-pr|backlog|code-connect|figma-utility|resource-utility|component-wiki|component-docs|figma-setup)" \
136
+ grep -rniE "ai-ios(-engineering)?-toolkit:(create-ui-component|evolve-ui-component|fix-bug|branch-and-pr|backlog|code-connect|figma-utility|resource-utility|component-wiki|component-docs|figma-setup)" \
137
137
  ~/multi-agent-pipeline/pipeline/commands/ 2>/dev/null \
138
138
  && { echo "ABORT: corporate reference leaked into pipeline/commands"; exit 1; } || true
139
139
  ```
@@ -176,7 +176,7 @@ If nothing is stale → report "All targets up to date" and stop.
176
176
  Unlike the Copilot step, this one does **not** hand-copy files. The Codex tree is a
177
177
  *transform* of the Claude tree, not a mirror of it, and the transform is real work:
178
178
 
179
- - the 49 sub-command specs become reference files, because Codex silently truncates
179
+ - the 51 sub-command specs become reference files, because Codex silently truncates
180
180
  its skills block (see `cross-cli-contract.md` 2.6 for the measurement)
181
181
  - every `$HOME/.claude/...` reference to a CLI-owned tree is retargeted, with
182
182
  `agents/<persona>.md` becoming `.toml` and the dispatcher becoming the router skill
@@ -233,13 +233,20 @@ node "$HOME/multi-agent-pipeline/pipeline/scripts/build-stack-plugins.mjs" --dry
233
233
 
234
234
  # 2. Apply: rebuild each stack plugin's knowledge/ from shared/external,
235
235
  # regenerate plugin.json skills[], bump the patch version of any plugin
236
- # whose skill set changed. Cross-stack skills -> ai-common-engineering-toolkit;
236
+ # whose skill set changed. Cross-stack skills -> ai-common-toolkit;
237
237
  # Apple/Xcode-only skills -> iOS plugin only.
238
238
  node "$HOME/multi-agent-pipeline/pipeline/scripts/build-stack-plugins.mjs"
239
239
  ```
240
240
 
241
241
  **Version-based management:** the generator bumps a plugin's `version` (patch) only when its skill set actually changed. Idempotent - a no-op run bumps nothing. Consumers pick up new versions via `/multi-agent:update` (which runs `claude marketplace update multi-agent-plugins`).
242
242
 
243
+ **Help + README freshness (mandatory when the generator reported any change):**
244
+
245
+ 1. Every plugin ships a `tools/help` skill that renders its catalog LIVE from `plugin.json`, so it needs no per-skill edits - but verify each changed plugin still registers it (`grep -c "./skills/tools/help" plugins/<name>/.claude-plugin/plugin.json` = 1) and that a new plugin gets one before publish.
246
+ 2. Plugin README tables sync through `python3 tools/bump.py <plugin> --set <version>`; run `python3 tools/bump.py --check` and treat DRIFT as a blocker.
247
+ 3. `python3 tools/validate.py` must be clean (it also enforces the CHANGELOG heading for every bumped version - write the entry, do not backdate).
248
+ 4. When the pipeline's command surface changed in the same sync (new/renamed `/multi-agent:*` commands), confirm `commands/multi-agent/help/SKILL.md` and both pipeline READMEs (`README.md`, `README.tr.md`) were updated in Step 3 before pushing here.
249
+
243
250
  **Publish (only if the generator reported bumps):**
244
251
 
245
252
  ```bash
@@ -484,21 +491,21 @@ When invoked with the `release` argument:
484
491
  > Codex takes the Step 2b path instead; see that section.
485
492
 
486
493
  This runs on the Claude <-> Copilot axis. Codex is NOT synced here: it receives the
487
- same 49 specs as reference files rather than as peer skills, via Step 2b - see
494
+ same 51 specs as reference files rather than as peer skills, via Step 2b - see
488
495
  `cross-cli-contract.md` 2.6 for why the parity axis differs per host.
489
496
 
490
497
  | Claude Code | Copilot CLI |
491
498
  |-------------|-------------|
492
499
  | `~/.claude/commands/multi-agent/{cmd}/SKILL.md` | `~/.copilot/skills/multi-agent-{cmd}/SKILL.md` |
493
500
 
494
- **49 commands are synced** (canonical inventory - must match `cross-cli-contract.md` section 1; drift = contract violation):
501
+ **51 commands are synced** (canonical inventory - must match `cross-cli-contract.md` section 1; drift = contract violation):
495
502
 
496
503
  ```
497
- analysis, analysis-resolve, autopilot, build-optimize, channels, create-jira, design-check, dev,
504
+ analysis, analysis-resolve, autopilot, build-optimize, channels, complaint-analysis, create-jira, design-check, dev,
498
505
  dev-autopilot, dev-local, dev-local-autopilot, diff-explain, forget, garbage-collect,
499
506
  help, ios-coding-standard, issue, jira, kill, language, local,
500
- local-autopilot, log, manual-test, prune-logs, purge, refactor, resume, review, review-issue, review-jira,
501
- routines, save, scan, search, setup, ship, stack, status, store-ready, sync, test, test-accessibility,
507
+ local-autopilot, log, manual-test, prune-logs, prune-prompts, purge, refactor, resume, review, review-issue, review-jira,
508
+ routines, save, scan, search, setup, resume-local, stack, status, store-ready, sync, test, test-accessibility,
502
509
  test-dark-mode, test-dynamic-type, test-screenshots, testflight-validation, uninstall, update
503
510
  ```
504
511
 
@@ -40,7 +40,7 @@ Unchanged from before the merge, on the iOS path:
40
40
  |---|---|---|
41
41
  | **1. Static** | `ios_app_store_audit` (18 rules, real ITMS codes) | an `.xcarchive` |
42
42
  | **2. Authoritative** | `ios_testflight_validate` → `altool --validate-app` | an `.ipa` + credentials |
43
- | **3. Policy** | `app-store-review` skill vs repo source | repo checkout |
43
+ | **3. Policy** | `ai-ios-toolkit:app-store-review` skill vs repo source | repo checkout |
44
44
 
45
45
  A skipped gate is never folded into the pass count, and the run never uploads. The
46
46
  report lands in `~/StoreChecks/ios-<repo>-<branch>-<timestamp>/report.md`.
@@ -28,6 +28,8 @@ Tokens in the OS credential store are NEVER removed by either mode.
28
28
  - `~/.claude/CLAUDE.md` (user customisations)
29
29
  - `~/.claude/rules/` (user-owned; installed write-if-missing, never overwritten)
30
30
  - User content OUTSIDE the `<!-- multi-agent-pipeline:begin/end -->` markers (`copilot-instructions.md`)
31
+ - Local-only alias wrappers (`local-only: true` frontmatter) under `commands/multi-agent/` (user-authored, exist nowhere else)
32
+ - User-authored skill dirs and agent files (only pipeline-shipped names are removed)
31
33
 
32
34
  Settings (`multi-agent-preferences.json`) and the log root (`~/.claude/logs/multi-agent/`) are kept by default and removed only when the user picks full cleanup (`--all-data`).
33
35
 
@@ -101,7 +101,7 @@ Update the pipeline in one command. Existing preferences are preserved; only ski
101
101
  ```
102
102
  Current: v3.6.0
103
103
  -> git pull origin main
104
- -> node install.js --all (49 commands, 50 scripts, 202 skills)
104
+ -> node install.js --all (50 commands, 80 scripts, 203 skills)
105
105
  -> migrate-prefs.mjs (0 changes - already v2.1.0)
106
106
 
107
107
  ✓ Updated: v3.6.0 → v3.7.0
@@ -402,7 +402,7 @@ sys.stdout.write((f.get("description") or "").replace("\x1f", " "))
402
402
  gh-url)
403
403
  OWNER=$(printf '%s' "$INPUT" | sed -E 's#https?://github.com/##; s#/.*##')
404
404
  REPO=$(printf '%s' "$INPUT" | sed -E 's#https?://github.com/[^/]+/##; s#/.*##')
405
- NUM=$(printf '%s' "$INPUT" | sed -E 's#.*/issues/##; s#[/?].*##')
405
+ NUM=$(printf '%s' "$INPUT" | sed -E 's#.*/issues/##; s#[/?#].*##')
406
406
  raw=$(fetch_github "$OWNER" "$REPO" "$NUM") || raw=""
407
407
  if [ -n "$raw" ]; then
408
408
  # Single python3 pass - see jira-id branch for rationale on the