@mmerterden/multi-agent-pipeline 16.17.1 → 16.19.0
This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
- package/CHANGELOG.md +65 -0
- package/README.md +5 -5
- package/README.tr.md +2 -2
- package/docs/FIGMA_PIPELINE.md +1 -1
- package/docs/adr/0001-three-model-triage.md +4 -2
- package/docs/architecture.md +2 -2
- package/docs/ecosystem.md +13 -11
- package/docs/features.md +2 -2
- package/index.js +1 -1
- package/install/_common.mjs +25 -1
- package/install/_dev-only-files.mjs +2 -2
- package/install/_mcp-register.mjs +4 -3
- package/install/_plugin-skills.mjs +1 -3
- package/install/copilot.mjs +18 -9
- package/install/index.mjs +2 -4
- package/install/templates/copilot-instructions.md +7 -7
- package/package.json +1 -1
- package/pipeline/claude-md-template.md +2 -2
- package/pipeline/commands/multi-agent/SKILL.md +5 -5
- package/pipeline/commands/multi-agent/complaint-analysis/SKILL.md +1 -1
- package/pipeline/commands/multi-agent/design-check/SKILL.md +1 -1
- package/pipeline/commands/multi-agent/help/SKILL.md +2 -2
- package/pipeline/commands/multi-agent/local-autopilot/SKILL.md +1 -1
- package/pipeline/commands/multi-agent/review/SKILL.md +32 -18
- package/pipeline/commands/multi-agent/review-analysis/SKILL.md +1 -1
- package/pipeline/commands/multi-agent/store-ready/SKILL.md +2 -2
- package/pipeline/commands/multi-agent/sync/SKILL.md +2 -2
- package/pipeline/commands/sim-test.md +54 -15
- package/pipeline/lib/credential-inventory.sh +15 -2
- package/pipeline/lib/credential-store-resolver.sh +14 -4
- package/pipeline/lib/credential-store.sh +8 -2
- package/pipeline/lib/extract-conventions.sh +1 -14
- package/pipeline/lib/fetch-confluence.sh +12 -4
- package/pipeline/lib/fetch-crashlytics.sh +11 -8
- package/pipeline/lib/fetch-document.sh +1 -1
- package/pipeline/lib/fetch-figma-annotations.sh +7 -5
- package/pipeline/lib/fetch-fortify.sh +5 -3
- package/pipeline/lib/fetch-graylog.sh +5 -3
- package/pipeline/lib/figma-mcp-refresh.sh +1 -1
- package/pipeline/lib/figma-screenshot.sh +27 -24
- package/pipeline/lib/figma-token.sh +8 -4
- package/pipeline/lib/issue-fetcher.sh +0 -1
- package/pipeline/lib/jira-publish.sh +7 -5
- package/pipeline/lib/md2confluence-v3.py +13 -7
- package/pipeline/lib/multi-repo-pipeline.sh +18 -8
- package/pipeline/lib/plan-todos.sh +11 -0
- package/pipeline/lib/post-pr-review.sh +9 -2
- package/pipeline/lib/repo-cache.sh +18 -10
- package/pipeline/lib/review-watch.sh +60 -14
- package/pipeline/lib/shadow-git.sh +8 -4
- package/pipeline/lib/vercel-deploy.sh +2 -2
- package/pipeline/multi-agent-refs/_dev-context.md +5 -2
- package/pipeline/multi-agent-refs/analysis/locked.md +4 -4
- package/pipeline/multi-agent-refs/analysis/render.md +1 -1
- package/pipeline/multi-agent-refs/cross-cli-contract.md +1 -1
- package/pipeline/multi-agent-refs/outside-the-pipeline.md +6 -6
- package/pipeline/multi-agent-refs/phases/log-format.md +1 -1
- package/pipeline/multi-agent-refs/phases/modes.md +1 -1
- package/pipeline/multi-agent-refs/phases/phase-0-init.md +4 -2
- package/pipeline/multi-agent-refs/phases/phase-1-analysis.md +3 -3
- package/pipeline/multi-agent-refs/phases/phase-2-planning.md +5 -5
- package/pipeline/multi-agent-refs/phases/phase-4-review.md +26 -21
- package/pipeline/multi-agent-refs/platform-parity.md +40 -28
- package/pipeline/multi-agent-refs/tracker-contract.md +1 -1
- package/pipeline/rules/figma-pipeline.md +18 -72
- package/pipeline/rules/outside-the-pipeline.md +4 -3
- package/pipeline/schemas/agent-state.schema.json +1 -1
- package/pipeline/schemas/prefs.schema.json +38 -22
- package/pipeline/schemas/token-budget.json +1 -1
- package/pipeline/scripts/_stack-routing.mjs +1 -1
- package/pipeline/scripts/agent-guard.py +102 -21
- package/pipeline/scripts/anonymize-findings.mjs +7 -6
- package/pipeline/scripts/build-skills-index.mjs +14 -3
- package/pipeline/scripts/cost-budget-check.mjs +5 -3
- package/pipeline/scripts/cost-lib.sh +0 -15
- package/pipeline/scripts/diff-explain.mjs +22 -12
- package/pipeline/scripts/gc-refs.sh +6 -2
- package/pipeline/scripts/gc-tmp.sh +1 -1
- package/pipeline/scripts/gc-worktrees.sh +1 -1
- package/pipeline/scripts/gen-mode-dispatch.mjs +3 -3
- package/pipeline/scripts/github-ssh-setup.sh +7 -2
- package/pipeline/scripts/graph-build.mjs +2 -2
- package/pipeline/scripts/jira-wiki-escape.mjs +2 -1
- package/pipeline/scripts/keychain.py +12 -11
- package/pipeline/scripts/learning-curve.mjs +1 -1
- package/pipeline/scripts/migrate-prefs.mjs +1 -1
- package/pipeline/scripts/output-quality-check.sh +3 -1
- package/pipeline/scripts/phase-tracker.sh +1 -1
- package/pipeline/scripts/phase0-exit-gate.mjs +2 -1
- package/pipeline/scripts/plan-coverage-gate.mjs +2 -1
- package/pipeline/scripts/pre-commit-check.sh +23 -13
- package/pipeline/scripts/prune-logs.sh +1 -1
- package/pipeline/scripts/render-agent-log-cost.sh +3 -1
- package/pipeline/scripts/render-cost-summary.sh +4 -2
- package/pipeline/scripts/render-work-summary.sh +5 -3
- package/pipeline/scripts/repo-map.mjs +3 -2
- package/pipeline/scripts/scan-skills.sh +6 -2
- package/pipeline/scripts/search-logs.sh +8 -6
- package/pipeline/scripts/sign-skills.sh +3 -1
- package/pipeline/scripts/smoke-cross-cli-behavior.sh +1 -1
- package/pipeline/scripts/triage-memory.mjs +25 -4
- package/pipeline/scripts/uninstall.mjs +20 -12
- package/pipeline/scripts/update-check.sh +2 -2
- package/pipeline/scripts/update-issue-progress.sh +6 -5
- package/pipeline/scripts/validate-analysis-doc.mjs +6 -6
- package/pipeline/scripts/verify-skills.sh +3 -1
- package/pipeline/scripts/worktree-finalize.sh +22 -10
- package/pipeline/skills/.skill-manifest.json +81 -57
- package/pipeline/skills/.skills-index.json +19 -19
- package/pipeline/skills/shared/README.md +8 -8
- package/pipeline/skills/shared/core/multi-agent/SKILL.md +7 -7
- package/pipeline/skills/shared/core/multi-agent-design-check/SKILL.md +1 -1
- package/pipeline/skills/shared/core/multi-agent-help/SKILL.md +2 -2
- package/pipeline/skills/shared/core/multi-agent-local/SKILL.md +1 -1
- package/pipeline/skills/shared/core/multi-agent-local-autopilot/SKILL.md +2 -2
- package/pipeline/skills/shared/core/multi-agent-review/SKILL.md +23 -9
- package/pipeline/skills/shared/core/multi-agent-sync/SKILL.md +2 -2
- package/pipeline/skills/shared/external/NOTICE-dimillian-skills.md +56 -0
- package/pipeline/skills/shared/external/accessibility-compliance-accessibility-audit/SKILL.md +0 -4
- package/pipeline/skills/shared/external/api-patterns/SKILL.md +12 -24
- package/pipeline/skills/shared/external/app-store-changelog/references/release-notes-guidelines.md +34 -0
- package/pipeline/skills/shared/external/app-store-changelog/scripts/collect_release_changes.sh +33 -0
- package/pipeline/skills/shared/external/architecture/SKILL.md +7 -9
- package/pipeline/skills/shared/external/debugging-strategies/SKILL.md +0 -4
- package/pipeline/skills/shared/external/fastapi-pro/SKILL.md +0 -1
- package/pipeline/skills/shared/external/github-actions-templates/SKILL.md +0 -14
- package/pipeline/skills/shared/external/hig-components-content/SKILL.md +13 -13
- package/pipeline/skills/shared/external/hig-components-layout/SKILL.md +16 -16
- package/pipeline/skills/shared/external/hig-components-status/SKILL.md +6 -6
- package/pipeline/skills/shared/external/hig-components-system/SKILL.md +13 -13
- package/pipeline/skills/shared/external/hig-foundations/SKILL.md +23 -23
- package/pipeline/skills/shared/external/hig-inputs/SKILL.md +18 -18
- package/pipeline/skills/shared/external/hig-patterns/SKILL.md +30 -30
- package/pipeline/skills/shared/external/hig-platforms/SKILL.md +11 -11
- package/pipeline/skills/shared/external/hig-technologies/SKILL.md +33 -33
- package/pipeline/skills/shared/external/ios-coding-standard/references/STANDARD.md +52 -52
- package/pipeline/skills/shared/external/ios-coding-standard/references/lint-local.sh +1 -1
- package/pipeline/skills/shared/external/ios-coding-standard/references/rules.yml +11 -11
- package/pipeline/skills/shared/external/ios-developer/SKILL.md +0 -1
- package/pipeline/skills/shared/external/ios-module-structure/SKILL.md +7 -3
- package/pipeline/skills/shared/external/localization-reuse-map/SKILL.md +9 -15
- package/pipeline/skills/shared/external/macos-spm-app-packaging/SKILL.md +0 -5
- package/pipeline/skills/shared/external/macos-spm-app-packaging/assets/templates/bootstrap/Package.swift +17 -0
- package/pipeline/skills/shared/external/macos-spm-app-packaging/assets/templates/bootstrap/Sources/MyApp/Resources/.keep +0 -0
- package/pipeline/skills/shared/external/macos-spm-app-packaging/assets/templates/bootstrap/Sources/MyApp/main.swift +11 -0
- package/pipeline/skills/shared/external/macos-spm-app-packaging/assets/templates/bootstrap/version.env +2 -0
- package/pipeline/skills/shared/external/macos-spm-app-packaging/assets/templates/build_icon.sh +49 -0
- package/pipeline/skills/shared/external/macos-spm-app-packaging/assets/templates/compile_and_run.sh +63 -0
- package/pipeline/skills/shared/external/macos-spm-app-packaging/assets/templates/launch.sh +28 -0
- package/pipeline/skills/shared/external/macos-spm-app-packaging/assets/templates/make_appcast.sh +82 -0
- package/pipeline/skills/shared/external/macos-spm-app-packaging/assets/templates/package_app.sh +206 -0
- package/pipeline/skills/shared/external/macos-spm-app-packaging/assets/templates/setup_dev_signing.sh +52 -0
- package/pipeline/skills/shared/external/macos-spm-app-packaging/assets/templates/sign-and-notarize.sh +52 -0
- package/pipeline/skills/shared/external/macos-spm-app-packaging/assets/templates/version.env +2 -0
- package/pipeline/skills/shared/external/macos-spm-app-packaging/references/packaging.md +17 -0
- package/pipeline/skills/shared/external/macos-spm-app-packaging/references/release.md +32 -0
- package/pipeline/skills/shared/external/macos-spm-app-packaging/references/scaffold.md +79 -0
- package/pipeline/skills/shared/external/monorepo-architect/SKILL.md +0 -1
- package/pipeline/skills/shared/external/nodejs-backend-patterns/SKILL.md +0 -4
- package/pipeline/skills/shared/external/swift-concurrency-expert/references/approachable-concurrency.md +63 -0
- package/pipeline/skills/shared/external/swift-concurrency-expert/references/swift-6-2-concurrency.md +272 -0
- package/pipeline/skills/shared/external/swift-concurrency-expert/references/swiftui-concurrency-tour-wwdc.md +33 -0
- package/pipeline/skills/shared/external/swiftui-performance-audit/references/code-smells.md +150 -0
- package/pipeline/skills/shared/external/swiftui-performance-audit/references/demystify-swiftui-performance-wwdc23.md +46 -0
- package/pipeline/skills/shared/external/swiftui-performance-audit/references/optimizing-swiftui-performance-instruments.md +29 -0
- package/pipeline/skills/shared/external/swiftui-performance-audit/references/profiling-intake.md +44 -0
- package/pipeline/skills/shared/external/swiftui-performance-audit/references/report-template.md +47 -0
- package/pipeline/skills/shared/external/swiftui-performance-audit/references/understanding-hangs-in-your-app.md +33 -0
- package/pipeline/skills/shared/external/swiftui-performance-audit/references/understanding-improving-swiftui-performance.md +52 -0
- package/pipeline/skills/shared/external/swiftui-ui-patterns/references/app-wiring.md +201 -0
- package/pipeline/skills/shared/external/swiftui-ui-patterns/references/async-state.md +96 -0
- package/pipeline/skills/shared/external/swiftui-ui-patterns/references/components-index.md +46 -0
- package/pipeline/skills/shared/external/swiftui-ui-patterns/references/controls.md +57 -0
- package/pipeline/skills/shared/external/swiftui-ui-patterns/references/deeplinks.md +66 -0
- package/pipeline/skills/shared/external/swiftui-ui-patterns/references/focus.md +90 -0
- package/pipeline/skills/shared/external/swiftui-ui-patterns/references/form.md +97 -0
- package/pipeline/skills/shared/external/swiftui-ui-patterns/references/grids.md +71 -0
- package/pipeline/skills/shared/external/swiftui-ui-patterns/references/haptics.md +71 -0
- package/pipeline/skills/shared/external/swiftui-ui-patterns/references/input-toolbar.md +51 -0
- package/pipeline/skills/shared/external/swiftui-ui-patterns/references/lightweight-clients.md +93 -0
- package/pipeline/skills/shared/external/swiftui-ui-patterns/references/list.md +86 -0
- package/pipeline/skills/shared/external/swiftui-ui-patterns/references/loading-placeholders.md +38 -0
- package/pipeline/skills/shared/external/swiftui-ui-patterns/references/macos-settings.md +71 -0
- package/pipeline/skills/shared/external/swiftui-ui-patterns/references/matched-transitions.md +59 -0
- package/pipeline/skills/shared/external/swiftui-ui-patterns/references/media.md +73 -0
- package/pipeline/skills/shared/external/swiftui-ui-patterns/references/menu-bar.md +101 -0
- package/pipeline/skills/shared/external/swiftui-ui-patterns/references/navigationstack.md +159 -0
- package/pipeline/skills/shared/external/swiftui-ui-patterns/references/overlay.md +45 -0
- package/pipeline/skills/shared/external/swiftui-ui-patterns/references/performance.md +62 -0
- package/pipeline/skills/shared/external/swiftui-ui-patterns/references/previews.md +48 -0
- package/pipeline/skills/shared/external/swiftui-ui-patterns/references/scroll-reveal.md +133 -0
- package/pipeline/skills/shared/external/swiftui-ui-patterns/references/scrollview.md +87 -0
- package/pipeline/skills/shared/external/swiftui-ui-patterns/references/searchable.md +71 -0
- package/pipeline/skills/shared/external/swiftui-ui-patterns/references/sheets.md +155 -0
- package/pipeline/skills/shared/external/swiftui-ui-patterns/references/split-views.md +72 -0
- package/pipeline/skills/shared/external/swiftui-ui-patterns/references/tabview.md +114 -0
- package/pipeline/skills/shared/external/swiftui-ui-patterns/references/theming.md +71 -0
- package/pipeline/skills/shared/external/swiftui-ui-patterns/references/title-menus.md +93 -0
- package/pipeline/skills/shared/external/swiftui-ui-patterns/references/top-bar.md +49 -0
- package/pipeline/skills/shared/external/swiftui-view-refactor/references/mv-patterns.md +161 -0
- package/pipeline/skills/skills-index.md +8 -8
- package/pipeline/skills/shared/external/help-skills/SKILL.md +0 -166
|
@@ -1,7 +1,7 @@
|
|
|
1
1
|
---
|
|
2
2
|
description: "Run parallel review on a branch's diff or a Pull Request: 3 models on Claude Code (Fable + Opus + Sonnet), 3 models on Copilot CLI (GPT + Opus + Sonnet). On PR input, posts per-finding inline comments and sets approve/needs-work review state. Use when a branch diff or a pull request needs reviewing before it merges."
|
|
3
3
|
description-tr: "Bir branch diff'i veya Pull Request üzerinde paralel review koşar: Claude Code'da 3 model (Fable + Opus + Sonnet), Copilot CLI'da 3 model (GPT + Opus + Sonnet). PR girdisinde bulgu başına inline yorum atar ve approve/needs-work durumunu işaretler."
|
|
4
|
-
argument-hint: "[#N | repo#N | PR-URL | branch] - optional: PR by number/URL, repo+number, or local branch. Supports GitHub and Bitbucket Server URLs. If omitted (interactive), open GitHub + Bitbucket PRs are listed for multi-select; autopilot falls back to the current branch."
|
|
4
|
+
argument-hint: "[#N | repo#N | PR-URL | branch] [--with <path|owner/repo>] - optional: PR by number/URL, repo+number, or local branch. Supports GitHub and Bitbucket Server URLs. If omitted (interactive), open GitHub + Bitbucket PRs are listed for multi-select; autopilot falls back to the current branch. --with names the counterpart app repo for the platform-parity cross-check."
|
|
5
5
|
---
|
|
6
6
|
|
|
7
7
|
# multi-agent review - Review Only Mode
|
|
@@ -117,12 +117,12 @@ jq --arg sha "$HEAD_SHA" '.review.headCommitSha = $sha' "$AGENT_STATE" > "$tmp_s
|
|
|
117
117
|
**pr mode - bitbucket-server:**
|
|
118
118
|
|
|
119
119
|
```bash
|
|
120
|
-
# Resolve credentials via prefs.keychainMapping (never hardcode key names).
|
|
120
|
+
# Resolve credentials via prefs.global.keychainMapping (never hardcode key names).
|
|
121
121
|
. "$HOME/.claude/lib/credential-store-resolver.sh" \
|
|
122
122
|
|| . "$HOME/.copilot/lib/credential-store-resolver.sh"
|
|
123
123
|
resolve_credential_store
|
|
124
|
-
USER_KEY=$(jq -r '.keychainMapping.bitbucket_user' "$HOME/.claude/multi-agent-preferences.json")
|
|
125
|
-
TOKEN_KEY=$(jq -r '.keychainMapping.bitbucket_token' "$HOME/.claude/multi-agent-preferences.json")
|
|
124
|
+
USER_KEY=$(jq -r '.global.keychainMapping.bitbucket_user' "$HOME/.claude/multi-agent-preferences.json")
|
|
125
|
+
TOKEN_KEY=$(jq -r '.global.keychainMapping.bitbucket_token' "$HOME/.claude/multi-agent-preferences.json")
|
|
126
126
|
BB_USER=$("$CRED_STORE" get "$USER_KEY")
|
|
127
127
|
BB_TOKEN=$("$CRED_STORE" get "$TOKEN_KEY")
|
|
128
128
|
|
|
@@ -175,15 +175,25 @@ Scope note: a guide governs only files under its own directory - a guide found
|
|
|
175
175
|
|
|
176
176
|
### 3. Launch parallel reviewers - host-CLI dependent
|
|
177
177
|
|
|
178
|
+
Every host runs three reviewers; only the second slot differs, because GPT-5.4 exists on Copilot and Codex but not on Claude Code, where Opus fills it.
|
|
179
|
+
|
|
178
180
|
**Claude Code (3 in parallel):**
|
|
179
181
|
- Agent 1: `claude-fable-5` → security + architecture
|
|
180
|
-
- Agent 2: `claude-
|
|
182
|
+
- Agent 2: `claude-opus-5` → edge cases, alternate perspective
|
|
183
|
+
- Agent 3: `claude-sonnet-5` → general quality
|
|
181
184
|
|
|
182
185
|
**Copilot CLI (3 in parallel):**
|
|
183
186
|
- Agent 1: `claude-opus-5` → security + architecture (Fable 5 is not offered on Copilot CLI)
|
|
184
187
|
- Agent 2: `gpt-5.4` → edge cases, alternate perspective
|
|
185
188
|
- Agent 3: `claude-sonnet-5` → general quality
|
|
186
189
|
|
|
190
|
+
**Codex CLI (3 in parallel, single vendor):**
|
|
191
|
+
- Agent 1: `gpt-5.6` @ `xhigh` → security + architecture
|
|
192
|
+
- Agent 2: `gpt-5.4` @ `high` → edge cases, alternate perspective
|
|
193
|
+
- Agent 3: `gpt-5.6` @ `medium` → general quality
|
|
194
|
+
|
|
195
|
+
With the `fable` rung disabled by prefs the Claude Code panel is two reviewers (Opus + Sonnet); see `$HOME/.claude/multi-agent-refs/features/model-fallback.md`.
|
|
196
|
+
|
|
187
197
|
Each reviewer receives the diff, the module review guides from Step 2b (when any were found), plus the standard reviewer system prompt (see `$HOME/.claude/multi-agent-refs/phases/phase-4-review.md` for the prompt contract). Output: structured `findings[]` per reviewer.
|
|
188
198
|
|
|
189
199
|
### 4. Store-compliance cross-reference
|
|
@@ -203,21 +213,24 @@ Catalog-only - does NOT invoke binaries. For a full scan, use `/multi-agent:te
|
|
|
203
213
|
|
|
204
214
|
### 4b. Platform parity cross-check (advisory, read-only)
|
|
205
215
|
|
|
206
|
-
When
|
|
207
|
-
|
|
208
|
-
|
|
209
|
-
|
|
216
|
+
When a counterpart repo resolves whose `stack` is the other mobile platform and
|
|
217
|
+
the diff touches a screen, a service, a request model or a localization file,
|
|
218
|
+
compare the change against that repo on four axes: endpoints called, parameters
|
|
219
|
+
sent, business rules around the call, localization keys used.
|
|
210
220
|
|
|
211
|
-
|
|
212
|
-
|
|
213
|
-
|
|
214
|
-
|
|
221
|
+
The counterpart is resolved automatically, in both directions (ios ↔ android),
|
|
222
|
+
from four sources in this order, first hit wins: `--with <path|owner/repo>` (a
|
|
223
|
+
one-off override, remembered like any other resolution), then a remembered
|
|
224
|
+
`prefs.projects[<slug>].counterpartRoots[]`, then the primary checkout's sibling
|
|
225
|
+
directories, then `state.siblings[]` from the Phase 0 dev-context picker. None of
|
|
226
|
+
them is a precondition for the others. One match is used and remembered, so the
|
|
227
|
+
next review of the same project asks nothing.
|
|
215
228
|
|
|
216
|
-
|
|
217
|
-
|
|
218
|
-
|
|
229
|
+
Several candidates → interactive runs ask once; autopilot and non-interactive
|
|
230
|
+
runs skip silently, because an unattended run must not block on a picker. No
|
|
231
|
+
candidate → skip silently, run unaffected. Stack comes from marker files, and
|
|
232
|
+
you never guess a stack from the repo name.
|
|
219
233
|
|
|
220
|
-
No counterpart repo, or nothing comparable in the diff → skipped silently.
|
|
221
234
|
Contract: `$HOME/.claude/multi-agent-refs/platform-parity.md`.
|
|
222
235
|
|
|
223
236
|
### 5. Triage (Fable)
|
|
@@ -236,12 +249,13 @@ Triage also marks each finding as `accepted` (real issue), `deferred` (real but
|
|
|
236
249
|
| Model | Verdict | Blocking | Important | Suggestion |
|
|
237
250
|
|----------|-----------|----------|-----------|------------|
|
|
238
251
|
| Fable | approved | 0 | 1 | 3 |
|
|
252
|
+
| Opus | approved | 0 | 2 | 2 |
|
|
239
253
|
| Sonnet | rejected | 1 | 2 | 5 |
|
|
240
254
|
|
|
241
255
|
Consensus: ⚠ DISAGREEMENT - see Fable triage
|
|
242
256
|
```
|
|
243
257
|
|
|
244
|
-
This summary ALWAYS prints, regardless of input mode. The chat is the live conversation; on the PR side, the durable artifacts are inline comments + the review state (Step 7).
|
|
258
|
+
One row per reviewer that ran: Fable + Opus + Sonnet on Claude Code, Opus + GPT-5.4 + Sonnet on Copilot CLI, the three GPT rows on Codex CLI. This summary ALWAYS prints, regardless of input mode. The chat is the live conversation; on the PR side, the durable artifacts are inline comments + the review state (Step 7).
|
|
245
259
|
|
|
246
260
|
### 7. Post to PR - only when input.kind === "pr"
|
|
247
261
|
|
|
@@ -23,7 +23,7 @@ Read `$HOME/.claude/multi-agent-refs/analysis/review.md` and execute it:
|
|
|
23
23
|
|
|
24
24
|
## Why it cites Locked decisions
|
|
25
25
|
|
|
26
|
-
The analysis flow already declares
|
|
26
|
+
The analysis flow already declares 36 Locked decisions and two deterministic validators. A reviewer that says "I would have written this differently" gives the author nothing to act on; one that says "Locked 34: the Confluence page is in the evidence record but not in Section 21" gives them a fix and a reason. Findings that map to no rule are still allowed, but they are marked as judgement, not dressed up as a violation.
|
|
27
27
|
|
|
28
28
|
## What it never does
|
|
29
29
|
|
|
@@ -183,7 +183,7 @@ is a guess the user must be able to correct.
|
|
|
183
183
|
|
|
184
184
|
### Mode A - build from the branch
|
|
185
185
|
|
|
186
|
-
1. Worktree at `{projectRoot}/{
|
|
186
|
+
1. Worktree at `{projectRoot}/.worktrees/{taskId}` on the chosen branch (phase-0-init.md Step 6 convention; the `.worktrees` segment is fixed, not a preference).
|
|
187
187
|
**Never under `$HOME`**, never a direct checkout of the main working tree.
|
|
188
188
|
2. Resolve the scheme / module and workspace / project from prefs; ask if ambiguous.
|
|
189
189
|
3. Build:
|
|
@@ -329,7 +329,7 @@ Print, and stop:
|
|
|
329
329
|
declares - never run it
|
|
330
330
|
- `/multi-agent:store-ready --resume` to re-run after fixes
|
|
331
331
|
- `/multi-agent:channels` to land the findings in Jira / Confluence / Wiki / PR
|
|
332
|
-
-
|
|
332
|
+
- the enabled stack plugin's `fix-bug` skill (`ai-ios-toolkit:fix-bug` or the stack equivalent) when Gate 3 produced code-level findings
|
|
333
333
|
|
|
334
334
|
Never upload, never commit a Play edit, never bump the build number, never commit.
|
|
335
335
|
|
|
@@ -60,7 +60,7 @@ Run every step automatically:
|
|
|
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
62
|
Step 2: COPILOT Claude Code -> Copilot CLI (instructions + 55 sub-command skills)
|
|
63
|
-
Step 2b: CODEX Claude Code -> Codex CLI (1 router skill +
|
|
63
|
+
Step 2b: CODEX Claude Code -> Codex CLI (1 router skill + 55 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)
|
|
@@ -117,7 +117,7 @@ If nothing is stale → report "All targets up to date" and stop.
|
|
|
117
117
|
- `~/.claude/CLAUDE.md`, `~/.claude/rules/`, `~/.claude/knowledge/`
|
|
118
118
|
- `~/.claude/scripts/` - EXCEPT `pre-commit-check.sh`, `agent-guard.sh`, `agent-guard.py`, and `build-stack-plugins.mjs` (generic, synced)
|
|
119
119
|
- `~/.claude/settings.json`
|
|
120
|
-
- **Any `~/.claude/commands/multi-agent
|
|
120
|
+
- **Any `~/.claude/commands/multi-agent/*/SKILL.md` whose frontmatter has `local-only: true`** - these are user/repo-specific alias wrappers that delegate to a private marketplace plugin's 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/`.
|
|
121
121
|
```bash
|
|
122
122
|
# backstop: no local-only wrapper may exist in the synced target
|
|
123
123
|
grep -rl "^local-only: true" ~/multi-agent-pipeline/pipeline/commands/ 2>/dev/null \
|
|
@@ -1,6 +1,6 @@
|
|
|
1
1
|
---
|
|
2
2
|
description: "Mobile UI Bug Hunter - iOS Simulator (simctl) + Android Emulator (adb) - auto-detects platform"
|
|
3
|
-
allowed-tools: Agent, Bash, Read, Write, Edit, TaskCreate, TaskUpdate, TaskList, TaskGet, mcp__multi-agent-toolkit__ios_list_devices, mcp__multi-agent-toolkit__ios_boot_device, mcp__multi-agent-toolkit__ios_screenshot, mcp__multi-agent-toolkit__ios_tap, mcp__multi-agent-toolkit__ios_swipe, mcp__multi-agent-toolkit__ios_type_text, mcp__multi-agent-toolkit__ios_launch_app, mcp__multi-agent-toolkit__ios_terminate_app, mcp__multi-agent-toolkit__ios_list_apps, mcp__multi-agent-toolkit__ios_go_home, mcp__multi-agent-toolkit__ios_set_appearance, mcp__multi-agent-toolkit__ios_set_content_size, mcp__multi-agent-toolkit__ios_set_locale, mcp__multi-agent-toolkit__ios_open_url, mcp__multi-agent-toolkit__ios_status_bar, mcp__multi-agent-toolkit__ios_push_notification, mcp__multi-agent-toolkit__ios_grant_permission, mcp__multi-agent-toolkit__ios_revoke_permission, mcp__multi-agent-toolkit__ios_reset_permissions, mcp__multi-agent-toolkit__ios_set_location, mcp__multi-agent-toolkit__ios_clear_location, mcp__multi-agent-toolkit__ios_set_increase_contrast, mcp__multi-agent-toolkit__ios_record_video, mcp__multi-agent-toolkit__ios_add_media, mcp__multi-agent-toolkit__ios_keychain_reset, mcp__multi-agent-toolkit__ios_get_app_container, mcp__multi-agent-toolkit__ios_erase_device, mcp__multi-agent-toolkit__ios_get_ui_tree, mcp__multi-agent-toolkit__android_list_devices, mcp__multi-agent-toolkit__android_screenshot, mcp__multi-agent-toolkit__android_tap, mcp__multi-agent-toolkit__android_swipe, mcp__multi-agent-toolkit__android_type_text, mcp__multi-agent-toolkit__android_key_event, mcp__multi-agent-toolkit__android_launch_app, mcp__multi-agent-toolkit__android_stop_app, mcp__multi-agent-toolkit__android_list_packages, mcp__multi-agent-toolkit__android_go_home, mcp__multi-agent-toolkit__android_go_back, mcp__multi-agent-toolkit__android_get_ui_tree, mcp__multi-agent-toolkit__android_set_dark_mode, mcp__multi-agent-toolkit__android_set_font_scale, mcp__multi-agent-toolkit__android_set_locale, mcp__multi-agent-toolkit__android_set_location, mcp__multi-agent-toolkit__android_grant_permission, mcp__multi-agent-toolkit__android_revoke_permission, mcp__multi-agent-toolkit__android_record_screen, mcp__multi-agent-toolkit__android_install_apk, mcp__multi-agent-toolkit__android_uninstall_app, mcp__multi-agent-toolkit__android_logcat, mcp__multi-agent-toolkit__android_get_screen_size, mcp__multi-agent-toolkit__android_open_url, mcp__multi-agent-toolkit__android_clear_app_data
|
|
3
|
+
allowed-tools: Agent, Bash, Read, Write, Edit, TaskCreate, TaskUpdate, TaskList, TaskGet, mcp__multi-agent-toolkit__ios_list_devices, mcp__multi-agent-toolkit__ios_boot_device, mcp__multi-agent-toolkit__ios_screenshot, mcp__multi-agent-toolkit__ios_tap, mcp__multi-agent-toolkit__ios_swipe, mcp__multi-agent-toolkit__ios_type_text, mcp__multi-agent-toolkit__ios_launch_app, mcp__multi-agent-toolkit__ios_terminate_app, mcp__multi-agent-toolkit__ios_list_apps, mcp__multi-agent-toolkit__ios_go_home, mcp__multi-agent-toolkit__ios_set_appearance, mcp__multi-agent-toolkit__ios_set_content_size, mcp__multi-agent-toolkit__ios_set_locale, mcp__multi-agent-toolkit__ios_open_url, mcp__multi-agent-toolkit__ios_status_bar, mcp__multi-agent-toolkit__ios_push_notification, mcp__multi-agent-toolkit__ios_grant_permission, mcp__multi-agent-toolkit__ios_revoke_permission, mcp__multi-agent-toolkit__ios_reset_permissions, mcp__multi-agent-toolkit__ios_set_location, mcp__multi-agent-toolkit__ios_clear_location, mcp__multi-agent-toolkit__ios_set_increase_contrast, mcp__multi-agent-toolkit__ios_record_video, mcp__multi-agent-toolkit__ios_add_media, mcp__multi-agent-toolkit__ios_keychain_reset, mcp__multi-agent-toolkit__ios_get_app_container, mcp__multi-agent-toolkit__ios_erase_device, mcp__multi-agent-toolkit__ios_get_ui_tree, mcp__multi-agent-toolkit__ios_accessibility_audit, mcp__multi-agent-toolkit__ios_accessibility_audit_deep, mcp__multi-agent-toolkit__ios_list_crashes, mcp__multi-agent-toolkit__agent_run_steps, mcp__multi-agent-toolkit__android_list_devices, mcp__multi-agent-toolkit__android_screenshot, mcp__multi-agent-toolkit__android_tap, mcp__multi-agent-toolkit__android_swipe, mcp__multi-agent-toolkit__android_type_text, mcp__multi-agent-toolkit__android_key_event, mcp__multi-agent-toolkit__android_launch_app, mcp__multi-agent-toolkit__android_stop_app, mcp__multi-agent-toolkit__android_list_packages, mcp__multi-agent-toolkit__android_go_home, mcp__multi-agent-toolkit__android_go_back, mcp__multi-agent-toolkit__android_get_ui_tree, mcp__multi-agent-toolkit__android_set_dark_mode, mcp__multi-agent-toolkit__android_set_font_scale, mcp__multi-agent-toolkit__android_set_locale, mcp__multi-agent-toolkit__android_set_location, mcp__multi-agent-toolkit__android_grant_permission, mcp__multi-agent-toolkit__android_revoke_permission, mcp__multi-agent-toolkit__android_record_screen, mcp__multi-agent-toolkit__android_install_apk, mcp__multi-agent-toolkit__android_uninstall_app, mcp__multi-agent-toolkit__android_logcat, mcp__multi-agent-toolkit__android_get_screen_size, mcp__multi-agent-toolkit__android_open_url, mcp__multi-agent-toolkit__android_clear_app_data, mcp__multi-agent-toolkit__android_accessibility_audit, mcp__multi-agent-toolkit__android_list_crashes
|
|
4
4
|
---
|
|
5
5
|
|
|
6
6
|
# Mobile UI Bug Hunter
|
|
@@ -25,7 +25,7 @@ Auto-detects platform: iOS (simctl) or Android (adb). No external apps needed.
|
|
|
25
25
|
For iOS: use `mcp__multi-agent-toolkit__ios_*` tools
|
|
26
26
|
For Android: use `mcp__multi-agent-toolkit__android_*` tools
|
|
27
27
|
|
|
28
|
-
**Android extras**: `get_ui_tree` returns XML with bounds/text/resource-id (uiautomator dump), `logcat` for crash
|
|
28
|
+
**Android extras**: `get_ui_tree` returns XML with bounds/text/resource-id (uiautomator dump), `logcat` for live output, `list_crashes` for the crash buffer, `go_back` button.
|
|
29
29
|
|
|
30
30
|
## Activation
|
|
31
31
|
|
|
@@ -90,23 +90,34 @@ Call: ios_status_bar (time: "09:41", battery_level: 100)
|
|
|
90
90
|
|
|
91
91
|
### Step 3 - Systematic Screen Exploration
|
|
92
92
|
|
|
93
|
-
For each screen in the app:
|
|
93
|
+
For each screen in the app, read before you look, and batch what you can:
|
|
94
94
|
|
|
95
95
|
```
|
|
96
|
-
Call:
|
|
97
|
-
->
|
|
96
|
+
Call: ios_get_ui_tree (text: labels, frames, traits; ~0.1 s, no image)
|
|
97
|
+
-> pick tap targets from element frames, never by guessing pixels from a picture
|
|
98
|
+
|
|
99
|
+
Call: agent_run_steps (one round trip for a scripted sequence)
|
|
100
|
+
steps: [ {tool: "ios_tap", args: {x, y}}, {wait_ms: 400},
|
|
101
|
+
{tool: "ios_screenshot", args: {path: "<dir>/<screen>.png"}},
|
|
102
|
+
{tool: "ios_get_ui_tree", args: {}} ]
|
|
98
103
|
|
|
99
|
-
Call:
|
|
100
|
-
->
|
|
101
|
-
-> Navigate back: ios_swipe (left edge swipe) or tap back button coordinates
|
|
104
|
+
Call: ios_screenshot (inline, only when a visual judgment is needed)
|
|
105
|
+
-> Claude analyzes the image for bugs (see Bug Detection below)
|
|
102
106
|
```
|
|
103
107
|
|
|
108
|
+
Every inline `ios_screenshot` / `android_screenshot` is an 800 px JPEG (about 60 KB) by
|
|
109
|
+
default; pass `format: "png"` or a larger `max_width` only when a pixel-level look is the
|
|
110
|
+
point. Bulk captures (dark mode, dynamic type, locale sweeps) always go through `path`,
|
|
111
|
+
so a run of 100 screens does not push 100 images through the model: look at the ones
|
|
112
|
+
whose tree or diff changed. A screen whose tree is unchanged after a tap is the
|
|
113
|
+
"button did not respond" finding without a second image.
|
|
114
|
+
|
|
104
115
|
**Navigation strategy:**
|
|
105
116
|
|
|
106
|
-
1.
|
|
107
|
-
2. Tap each tab
|
|
108
|
-
3. On each screen: tap interactive elements -> screenshot
|
|
109
|
-
4. Scroll: `ios_swipe(200, 600, 200, 200)` to scroll down ->
|
|
117
|
+
1. Tree of the initial screen -> tab bar items are the elements with a tab-bar trait or the bottom row of buttons; use their frames
|
|
118
|
+
2. Tap each tab (batched via `agent_run_steps`) -> tree + file capture each
|
|
119
|
+
3. On each screen: tap interactive elements from the tree -> tree after; inline screenshot only where the tree cannot tell (layout, contrast, clipping)
|
|
120
|
+
4. Scroll: `ios_swipe(200, 600, 200, 200)` to scroll down -> tree, capture when new content appeared
|
|
110
121
|
5. Type in text fields: `ios_type_text("test input")`
|
|
111
122
|
|
|
112
123
|
### Step 4 - Variant Testing (based on input argument)
|
|
@@ -131,9 +142,24 @@ Call: ios_set_content_size("medium") // reset
|
|
|
131
142
|
|
|
132
143
|
**"accessibility":**
|
|
133
144
|
|
|
134
|
-
|
|
135
|
-
|
|
136
|
-
|
|
145
|
+
Two halves per screen, and the report keeps them apart: what the tool measured and what the screenshot suggests.
|
|
146
|
+
|
|
147
|
+
```
|
|
148
|
+
On each screen, after ios_screenshot:
|
|
149
|
+
Call: ios_accessibility_audit (Android: android_accessibility_audit)
|
|
150
|
+
-> findings[]: missing labels / contentDescription, controls a screen reader cannot
|
|
151
|
+
name, tap targets under 44pt (iOS) / 48dp (Android), missing identifiers,
|
|
152
|
+
reading order that does not follow the layout. Each finding becomes a BUG task
|
|
153
|
+
with the element identifier from the tree, not a guess from the pixels.
|
|
154
|
+
-> measurable:false (with a reason) means the tree could not be read (on iOS,
|
|
155
|
+
Simulator.app itself must be running, a booted device is not enough). Record
|
|
156
|
+
the screen as "not audited: <reason>" in the report. Never read it as clean.
|
|
157
|
+
-> Pass `scope: "<prefix>"` to narrow to one screen's identifiers when the tree is large.
|
|
158
|
+
```
|
|
159
|
+
|
|
160
|
+
The screenshot pass still runs on every screen for what the tree cannot see: poor contrast, text readability at default + large sizes, and visual crowding. Report those as screenshot findings, separately from the audit findings.
|
|
161
|
+
|
|
162
|
+
Optional deep pass (iOS only, minutes rather than seconds): when the project has an XCUITest target whose test calls `performAccessibilityAudit()`, run `ios_accessibility_audit_deep` (`scheme`, `project` or `workspace`, optional `test_identifier`) once at the end. It reaches contrast, Dynamic Type, clipped text, traits and hit regions that a tree dump cannot. The result says whether the named test ran; a test that never called the audit reports as "did not run", never as clean. Skip it, and say so in the report, when no such test exists.
|
|
137
163
|
|
|
138
164
|
**"screenshot <lang>":**
|
|
139
165
|
|
|
@@ -172,6 +198,17 @@ no Gate 3 and no Android parity, so the copy is gone rather than kept in sync.
|
|
|
172
198
|
- Run light mode -> all screens
|
|
173
199
|
- Run dark mode -> all screens
|
|
174
200
|
- Run large text -> all screens
|
|
201
|
+
- Crash sweep, after the last screen and before the report:
|
|
202
|
+
|
|
203
|
+
```
|
|
204
|
+
Call: ios_list_crashes (app: <process name>, since_min: <minutes since Step 1 launch>, limit: 20)
|
|
205
|
+
Android: android_list_crashes (lines: 200)
|
|
206
|
+
-> Every report / stack newer than the launch becomes a BUG task with severity Critical,
|
|
207
|
+
the crashed process and the top frame in the description.
|
|
208
|
+
-> Empty result -> "Crashes: none during this run" in the report. Only the bounded window
|
|
209
|
+
counts; older reports on the host are not this run's.
|
|
210
|
+
```
|
|
211
|
+
|
|
175
212
|
- Compile complete report
|
|
176
213
|
|
|
177
214
|
### Step 5 - Bug Detection (on EVERY screenshot)
|
|
@@ -233,6 +270,8 @@ Then output full report:
|
|
|
233
270
|
- Clean: {N}
|
|
234
271
|
- With bugs: {N}
|
|
235
272
|
- Critical: {N} | Major: {N} | Minor: {N}
|
|
273
|
+
- Accessibility audit (accessibility scenario): {N} audited, {N} not audited (reason per screen), deep pass: {ran / skipped: reason}
|
|
274
|
+
- Crashes (full scenario): {N} during this run
|
|
236
275
|
```
|
|
237
276
|
|
|
238
277
|
Save to: `$HOME/.claude/logs/sim-test/{bundle_id}/{timestamp}.md`
|
|
@@ -46,7 +46,8 @@
|
|
|
46
46
|
# not to enable, not a problem to report.
|
|
47
47
|
#
|
|
48
48
|
# Exit codes: 0 = inventory produced (or the queried key is present), 1 = queried key
|
|
49
|
-
# absent, 3 = usage
|
|
49
|
+
# absent, 2 = no credential helper on this host (nothing could be probed), 3 = usage
|
|
50
|
+
# error.
|
|
50
51
|
|
|
51
52
|
set -uo pipefail
|
|
52
53
|
|
|
@@ -290,11 +291,23 @@ if [ -n "$QUERY" ]; then
|
|
|
290
291
|
echo "$QUERY: present - can $(capability_of "$QUERY")"
|
|
291
292
|
fi
|
|
292
293
|
exit 0 ;;
|
|
293
|
-
2) echo "$QUERY: no credential helper on this host" >&2; exit
|
|
294
|
+
2) echo "$QUERY: no credential helper on this host - run the pipeline installer (credential-store.sh missing)" >&2; exit 2 ;;
|
|
294
295
|
*) echo "$QUERY: NOT AVAILABLE - onboard it via /multi-agent:setup before relying on it" >&2; exit 1 ;;
|
|
295
296
|
esac
|
|
296
297
|
fi
|
|
297
298
|
|
|
299
|
+
# Without a helper nothing can be probed: every mapped key would read as
|
|
300
|
+
# "mapped-but-missing" and the inventory would send the user to re-onboard
|
|
301
|
+
# tokens that are sitting in the store.
|
|
302
|
+
if [ -z "$STORE" ]; then
|
|
303
|
+
if [ "$MODE" = "json" ]; then
|
|
304
|
+
echo '{"status":"no-backend","reason":"credential-store.sh not found on this host","credentials":[]}'
|
|
305
|
+
else
|
|
306
|
+
echo "no credential helper on this host - run the pipeline installer (credential-store.sh missing)" >&2
|
|
307
|
+
fi
|
|
308
|
+
exit 2
|
|
309
|
+
fi
|
|
310
|
+
|
|
298
311
|
ROWS=""
|
|
299
312
|
while IFS=$'\t' read -r key mapped; do
|
|
300
313
|
[ -z "$key" ] && continue
|
|
@@ -81,12 +81,22 @@ MSG
|
|
|
81
81
|
return 1
|
|
82
82
|
}
|
|
83
83
|
|
|
84
|
-
# When sourced
|
|
85
|
-
#
|
|
86
|
-
#
|
|
87
|
-
|
|
84
|
+
# When sourced, auto-resolve into the caller's environment. When run directly
|
|
85
|
+
# (./credential-store-resolver.sh), print the resolved path or a non-zero exit
|
|
86
|
+
# code with the message above. zsh sources this too (the pipeline's Bash tool
|
|
87
|
+
# is zsh), where BASH_SOURCE is unset and $0 is the sourced file's own name, so
|
|
88
|
+
# the bash test alone always looked like a direct run there.
|
|
89
|
+
_csr_sourced=0
|
|
90
|
+
if [ -n "${ZSH_VERSION:-}" ]; then
|
|
91
|
+
case "${ZSH_EVAL_CONTEXT:-}" in *:file|*:file:*) _csr_sourced=1 ;; esac
|
|
92
|
+
elif [ -n "${BASH_SOURCE[0]:-}" ] && [ "${BASH_SOURCE[0]}" != "$0" ]; then
|
|
93
|
+
_csr_sourced=1
|
|
94
|
+
fi
|
|
95
|
+
if [ "$_csr_sourced" -eq 0 ]; then
|
|
96
|
+
unset _csr_sourced
|
|
88
97
|
resolve_credential_store && echo "$CRED_STORE"
|
|
89
98
|
else
|
|
99
|
+
unset _csr_sourced
|
|
90
100
|
# `|| :` matters, and it is not cosmetic.
|
|
91
101
|
#
|
|
92
102
|
# A sourced file runs in the caller's shell, so a bare failing command at this top
|
|
@@ -164,6 +164,10 @@ do_get() {
|
|
|
164
164
|
return 0
|
|
165
165
|
fi
|
|
166
166
|
audit_lookup "$logical" false
|
|
167
|
+
case "$rc" in
|
|
168
|
+
2) echo "ERR: credential backend unavailable on $PLATFORM" >&2; return 2 ;;
|
|
169
|
+
4) echo "ERR: credential backend error while reading '$logical'" >&2; return 4 ;;
|
|
170
|
+
esac
|
|
167
171
|
return 1
|
|
168
172
|
fi
|
|
169
173
|
local val=""
|
|
@@ -204,8 +208,10 @@ do_set() {
|
|
|
204
208
|
if [ "$val" = "-" ]; then
|
|
205
209
|
val=$(cat)
|
|
206
210
|
fi
|
|
207
|
-
|
|
208
|
-
|
|
211
|
+
# macOS writes go through `security -i` below: the secret travels on stdin
|
|
212
|
+
# and never lands on any argv, which is the property the delegate cannot
|
|
213
|
+
# promise from here.
|
|
214
|
+
if [ "$PLATFORM" != "macos" ] && delegate_to_python; then
|
|
209
215
|
printf '%s' "$val" | python3 "$KEYCHAIN_PY" set "$key" -
|
|
210
216
|
return $?
|
|
211
217
|
fi
|
|
@@ -2,7 +2,7 @@
|
|
|
2
2
|
# extract-conventions.sh
|
|
3
3
|
#
|
|
4
4
|
# Phase 1c helper for /multi-agent:analysis.
|
|
5
|
-
# Scans a repo and emits
|
|
5
|
+
# Scans a repo and emits 13 convention buckets as a single JSON object on stdout.
|
|
6
6
|
#
|
|
7
7
|
# Usage:
|
|
8
8
|
# extract-conventions.sh <repo-path> <platform>
|
|
@@ -202,19 +202,6 @@ files_to_json() {
|
|
|
202
202
|
printf '%s\n' "$input" | head -5 | jq -R . | jq -s .
|
|
203
203
|
}
|
|
204
204
|
|
|
205
|
-
# Top-N suffix frequency from a stream of file basenames.
|
|
206
|
-
# stdin: basenames (one per line)
|
|
207
|
-
# arg1: regex (POSIX ERE) capturing the suffix in group 1
|
|
208
|
-
# stdout: lines "count<TAB>suffix" sorted desc
|
|
209
|
-
suffix_freq() {
|
|
210
|
-
local re="$1"
|
|
211
|
-
grep -Eo "$re" 2>/dev/null \
|
|
212
|
-
| sort \
|
|
213
|
-
| uniq -c \
|
|
214
|
-
| sort -rn \
|
|
215
|
-
| sed -E 's/^ *([0-9]+) +/\1\t/'
|
|
216
|
-
}
|
|
217
|
-
|
|
218
205
|
# Run a bucket function with a soft timeout. We wrap the function in a subshell
|
|
219
206
|
# and use a watchdog so we stay compatible with macOS bash 3.2.
|
|
220
207
|
run_bucket_with_timeout() {
|
|
@@ -48,10 +48,12 @@ HOST_OVERRIDE="${CONFLUENCE_HOST_OVERRIDE:-}"
|
|
|
48
48
|
PAGE_ID=""
|
|
49
49
|
TIMEOUT="${CONFLUENCE_TIMEOUT_SECONDS:-20}"
|
|
50
50
|
|
|
51
|
+
need_value() { [ $# -ge 2 ] || { echo "ERR: $1 needs a value" >&2; exit 4; }; }
|
|
52
|
+
|
|
51
53
|
while [ $# -gt 0 ]; do
|
|
52
54
|
case "$1" in
|
|
53
|
-
--host) HOST_OVERRIDE="$2"; shift 2 ;;
|
|
54
|
-
--page-id) PAGE_ID="$2"; shift 2 ;;
|
|
55
|
+
--host) need_value "$@"; HOST_OVERRIDE="$2"; shift 2 ;;
|
|
56
|
+
--page-id) need_value "$@"; PAGE_ID="$2"; shift 2 ;;
|
|
55
57
|
-h|--help)
|
|
56
58
|
echo "usage: $0 <page-url> | $0 --host <host> --page-id <id>" >&2
|
|
57
59
|
exit 4 ;;
|
|
@@ -220,11 +222,17 @@ PAGE_ID_FINAL="$PAGE_ID_RESOLVED" \
|
|
|
220
222
|
SPACE_KEY_FINAL="$SPACE_KEY" \
|
|
221
223
|
PAGE_JSON_RAW="$PAGE_JSON" \
|
|
222
224
|
python3 - <<'PY'
|
|
223
|
-
import json, os, re, datetime, html
|
|
225
|
+
import json, os, re, sys, datetime, html
|
|
224
226
|
from html.parser import HTMLParser
|
|
225
227
|
|
|
226
228
|
raw = os.environ["PAGE_JSON_RAW"]
|
|
227
|
-
|
|
229
|
+
try:
|
|
230
|
+
data = json.loads(raw)
|
|
231
|
+
except ValueError:
|
|
232
|
+
# A 200 with an HTML body is an SSO login page or a proxy, not the page.
|
|
233
|
+
sys.stderr.write("ERR: Confluence GET for pageId=%s returned a non-JSON body (login page or proxy?)\n"
|
|
234
|
+
% os.environ.get("PAGE_ID_FINAL", ""))
|
|
235
|
+
sys.exit(3)
|
|
228
236
|
|
|
229
237
|
storage = ((data.get("body") or {}).get("storage") or {}).get("value") or ""
|
|
230
238
|
title = data.get("title") or "<untitled>"
|
|
@@ -67,13 +67,15 @@ ISSUE_ID=""
|
|
|
67
67
|
SESSION_ID=""
|
|
68
68
|
TIMEOUT="${FIREBASE_TIMEOUT_SECONDS:-20}"
|
|
69
69
|
|
|
70
|
+
need_value() { [ $# -ge 2 ] || { echo "ERR: $1 needs a value" >&2; exit 4; }; }
|
|
71
|
+
|
|
70
72
|
while [ $# -gt 0 ]; do
|
|
71
73
|
case "$1" in
|
|
72
|
-
--project) PROJECT_ID="$2"; shift 2 ;;
|
|
73
|
-
--platform) PLATFORM="$2"; shift 2 ;;
|
|
74
|
-
--bundle) BUNDLE="$2"; shift 2 ;;
|
|
75
|
-
--issue-id) ISSUE_ID="$2"; shift 2 ;;
|
|
76
|
-
--session-id) SESSION_ID="$2"; shift 2 ;;
|
|
74
|
+
--project) need_value "$@"; PROJECT_ID="$2"; shift 2 ;;
|
|
75
|
+
--platform) need_value "$@"; PLATFORM="$2"; shift 2 ;;
|
|
76
|
+
--bundle) need_value "$@"; BUNDLE="$2"; shift 2 ;;
|
|
77
|
+
--issue-id) need_value "$@"; ISSUE_ID="$2"; shift 2 ;;
|
|
78
|
+
--session-id) need_value "$@"; SESSION_ID="$2"; shift 2 ;;
|
|
77
79
|
-h|--help)
|
|
78
80
|
echo "usage: $0 <issue-url> | $0 --project ... --platform ... --bundle ... --issue-id ... [--session-id ...]" >&2
|
|
79
81
|
exit 4 ;;
|
|
@@ -234,6 +236,7 @@ fi
|
|
|
234
236
|
# 1. Build header + claim, base64url
|
|
235
237
|
# 2. Sign with the SA private key
|
|
236
238
|
# 3. POST to oauth2.googleapis.com/token
|
|
239
|
+
TOKEN_RC=0
|
|
237
240
|
ACCESS_TOKEN=$(SA_JSON_IN="$SA_JSON" python3 - <<'PY'
|
|
238
241
|
import base64, json, os, sys, time, urllib.parse, urllib.request
|
|
239
242
|
|
|
@@ -302,10 +305,10 @@ except Exception as e:
|
|
|
302
305
|
print("", file=sys.stderr)
|
|
303
306
|
sys.exit(2)
|
|
304
307
|
PY
|
|
305
|
-
)
|
|
308
|
+
) || TOKEN_RC=$?
|
|
306
309
|
|
|
307
|
-
if [ -z "$ACCESS_TOKEN" ]; then
|
|
308
|
-
echo "ERR: Firebase token exchange failed" >&2
|
|
310
|
+
if [ "$TOKEN_RC" -ne 0 ] || [ -z "$ACCESS_TOKEN" ]; then
|
|
311
|
+
echo "ERR: Firebase token exchange failed (exchange rc=$TOKEN_RC)" >&2
|
|
309
312
|
exit 3
|
|
310
313
|
fi
|
|
311
314
|
|
|
@@ -89,13 +89,15 @@ BATCH=4
|
|
|
89
89
|
log() { printf '%s\n' "$*" >&2; }
|
|
90
90
|
die() { local code="$1"; shift; log "fetch-figma-annotations: $*"; exit "$code"; }
|
|
91
91
|
|
|
92
|
+
need_value() { [ $# -ge 2 ] || die 1 "$1 requires a value"; }
|
|
93
|
+
|
|
92
94
|
while [ $# -gt 0 ]; do
|
|
93
95
|
case "$1" in
|
|
94
|
-
--file-key) FILE_KEY="$
|
|
95
|
-
--node-id) NODE_IDS="$
|
|
96
|
-
--url) URL="$
|
|
97
|
-
--lang-prefixes) LANG_PREFIXES="${2:-TR,EN}"; shift 2 ;;
|
|
98
|
-
--batch) BATCH="${2:-4}"; shift 2 ;;
|
|
96
|
+
--file-key) need_value "$@"; FILE_KEY="$2"; shift 2 ;;
|
|
97
|
+
--node-id) need_value "$@"; NODE_IDS="$2"; shift 2 ;;
|
|
98
|
+
--url) need_value "$@"; URL="$2"; shift 2 ;;
|
|
99
|
+
--lang-prefixes) need_value "$@"; LANG_PREFIXES="${2:-TR,EN}"; shift 2 ;;
|
|
100
|
+
--batch) need_value "$@"; BATCH="${2:-4}"; shift 2 ;;
|
|
99
101
|
-h|--help) grep -E '^#( |$)' "$0" | sed -E 's/^# ?//'; exit 0 ;;
|
|
100
102
|
*) die 1 "unknown argument: $1" ;;
|
|
101
103
|
esac
|
|
@@ -62,11 +62,13 @@ ISSUE_ID=""
|
|
|
62
62
|
TIMEOUT="${FORTIFY_TIMEOUT_SECONDS:-25}"
|
|
63
63
|
AUTH_SCHEME="${FORTIFY_AUTH_SCHEME:-auto}"
|
|
64
64
|
|
|
65
|
+
need_value() { [ $# -ge 2 ] || { echo "ERR: $1 needs a value" >&2; exit 4; }; }
|
|
66
|
+
|
|
65
67
|
while [ $# -gt 0 ]; do
|
|
66
68
|
case "$1" in
|
|
67
|
-
--version-id) VERSION_ID="$2"; shift 2 ;;
|
|
68
|
-
--issue) ISSUE_ID="$2"; shift 2 ;;
|
|
69
|
-
--instance-id) ISSUE_ID="$2"; shift 2 ;;
|
|
69
|
+
--version-id) need_value "$@"; VERSION_ID="$2"; shift 2 ;;
|
|
70
|
+
--issue) need_value "$@"; ISSUE_ID="$2"; shift 2 ;;
|
|
71
|
+
--instance-id) need_value "$@"; ISSUE_ID="$2"; shift 2 ;;
|
|
70
72
|
-h|--help)
|
|
71
73
|
echo "usage: $0 <ssc-url> | $0 --version-id <id> [--issue <id>] | $0 --instance-id <id>" >&2
|
|
72
74
|
exit 4 ;;
|
|
@@ -73,11 +73,13 @@ TIMEOUT="${GRAYLOG_TIMEOUT_SECONDS:-25}"
|
|
|
73
73
|
RANGE="${GRAYLOG_RANGE_SECONDS:-86400}"
|
|
74
74
|
LIMIT="${GRAYLOG_LIMIT:-200}"
|
|
75
75
|
|
|
76
|
+
need_value() { [ $# -ge 2 ] || { echo "ERR: $1 needs a value" >&2; exit 4; }; }
|
|
77
|
+
|
|
76
78
|
while [ $# -gt 0 ]; do
|
|
77
79
|
case "$1" in
|
|
78
|
-
--trx) TRX_ID="$2"; shift 2 ;;
|
|
79
|
-
--conv) CONV_ID="$2"; shift 2 ;;
|
|
80
|
-
--env) ENVIRONMENT="$2"; shift 2 ;;
|
|
80
|
+
--trx) need_value "$@"; TRX_ID="$2"; shift 2 ;;
|
|
81
|
+
--conv) need_value "$@"; CONV_ID="$2"; shift 2 ;;
|
|
82
|
+
--env) need_value "$@"; ENVIRONMENT="$2"; shift 2 ;;
|
|
81
83
|
-h|--help)
|
|
82
84
|
echo "usage: $0 --trx <transaction-id> | --conv <conversation-id> [--env auto|prod|test]" >&2
|
|
83
85
|
exit 4 ;;
|
|
@@ -85,7 +85,7 @@ refresh_grant_cfg() {
|
|
|
85
85
|
|
|
86
86
|
RESPONSE=$(curl -s --max-time 20 -X POST "$TOKEN_ENDPOINT" \
|
|
87
87
|
-H "Content-Type: application/x-www-form-urlencoded" \
|
|
88
|
-
-K <(refresh_grant_cfg))
|
|
88
|
+
-K <(refresh_grant_cfg)) || RESPONSE=""
|
|
89
89
|
|
|
90
90
|
NEW_ACCESS=$(printf '%s' "$RESPONSE" | jq -r '.access_token // empty' 2>/dev/null || true)
|
|
91
91
|
NEW_REFRESH=$(printf '%s' "$RESPONSE" | jq -r '.refresh_token // empty' 2>/dev/null || true)
|