@mmerterden/multi-agent-pipeline 20.27.2 → 20.28.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 (65) hide show
  1. package/CHANGELOG.md +28 -0
  2. package/README.md +6 -5
  3. package/README.tr.md +6 -5
  4. package/docs/adr/0008-installer-modularization-and-secret-leak-defense.md +0 -1
  5. package/docs/architecture.md +4 -4
  6. package/docs/ecosystem.md +5 -5
  7. package/docs/facts.json +14 -12
  8. package/docs/features.md +2 -0
  9. package/install/_dev-only-files.mjs +1 -0
  10. package/install/catalog-history.json +1 -1
  11. package/install/index.mjs +0 -2
  12. package/manifest.json +67 -44
  13. package/package.json +4 -1
  14. package/pipeline/agents/code-reviewer.md +1 -0
  15. package/pipeline/agents/test-gen-analyst.md +98 -0
  16. package/pipeline/commands/multi-agent/sync/SKILL.md +3 -3
  17. package/pipeline/commands/multi-agent/test-gen/SKILL.md +124 -0
  18. package/pipeline/multi-agent-refs/cross-cli-contract.md +11 -5
  19. package/pipeline/multi-agent-refs/features/doctor.md +13 -0
  20. package/pipeline/multi-agent-refs/features/test-classification.md +76 -0
  21. package/pipeline/multi-agent-refs/features/usage-reporting.md +17 -0
  22. package/pipeline/multi-agent-refs/help/en.md +1 -0
  23. package/pipeline/multi-agent-refs/help/tr.md +1 -0
  24. package/pipeline/multi-agent-refs/phases/operations.md +2 -2
  25. package/pipeline/multi-agent-refs/phases/phase-2-dev.md +6 -7
  26. package/pipeline/multi-agent-refs/phases/phase-3-review.md +3 -3
  27. package/pipeline/multi-agent-refs/phases/phase-5-report.md +6 -5
  28. package/pipeline/multi-agent-refs/test-gen/stages.md +227 -0
  29. package/pipeline/preferences-template.json +3 -0
  30. package/pipeline/schemas/prefs.schema.json +14 -0
  31. package/pipeline/schemas/test-gen-discovery.schema.json +73 -0
  32. package/pipeline/schemas/test-gen-gaps.schema.json +122 -0
  33. package/pipeline/schemas/test-gen-inventory.schema.json +59 -0
  34. package/pipeline/schemas/test-gen-results.schema.json +44 -0
  35. package/pipeline/scripts/_handle-patterns.mjs +166 -0
  36. package/pipeline/scripts/_http-post.mjs +141 -0
  37. package/pipeline/scripts/_stack-routing.mjs +4 -0
  38. package/pipeline/scripts/_test-gaming.mjs +227 -0
  39. package/pipeline/scripts/_unified-diff.mjs +104 -0
  40. package/pipeline/scripts/_worktree-snapshot.mjs +113 -0
  41. package/pipeline/scripts/doctor.mjs +51 -0
  42. package/pipeline/scripts/evidence-gate.mjs +74 -3
  43. package/pipeline/scripts/handle-diff-audit.mjs +188 -0
  44. package/pipeline/scripts/routine-registry.mjs +5 -1
  45. package/pipeline/scripts/run-ui-tests.sh +27 -3
  46. package/pipeline/scripts/test-classify.mjs +296 -0
  47. package/pipeline/scripts/test-gen-gate.mjs +409 -0
  48. package/pipeline/scripts/test-gen-state.mjs +313 -0
  49. package/pipeline/scripts/test-integrity-gate.mjs +76 -11
  50. package/pipeline/scripts/uninstall.mjs +1 -0
  51. package/pipeline/scripts/usage-register-beacon.mjs +239 -0
  52. package/pipeline/scripts/usage-register.mjs +128 -33
  53. package/pipeline/scripts/usage-report.mjs +43 -33
  54. package/pipeline/skills/.skill-manifest.json +23 -3
  55. package/pipeline/skills/.skills-index.json +57 -2
  56. package/pipeline/skills/shared/README.md +10 -5
  57. package/pipeline/skills/shared/core/multi-agent-sync/SKILL.md +3 -3
  58. package/pipeline/skills/shared/core/multi-agent-test-gen/SKILL.md +120 -0
  59. package/pipeline/skills/shared/external/fix-review-verdicts/SKILL.md +133 -0
  60. package/pipeline/skills/shared/external/handle-request/SKILL.md +97 -0
  61. package/pipeline/skills/shared/external/scenario-gap-analysis/SKILL.md +129 -0
  62. package/pipeline/skills/shared/external/scenario-gap-analysis/references/scenario-schema.md +60 -0
  63. package/pipeline/skills/shared/external/test-result-triage/SKILL.md +160 -0
  64. package/pipeline/skills/skills-index.md +7 -2
  65. package/install/_telemetry.mjs +0 -61
@@ -0,0 +1,160 @@
1
+ ---
2
+ name: test-result-triage
3
+ description: "Judge each test result on changed code as product-bug, stale-test, valid or ambiguous (the default), and list behaviour no test covers. stale-test needs a diff file:line, product-bug needs evidence. Use when tests ran on a new commit, PR or fix. Not for writing or editing tests."
4
+ metadata:
5
+ source: multi-agent-pipeline
6
+ version: 1.0.0
7
+ ---
8
+
9
+ # Test result triage
10
+
11
+ The product moved to a new commit and the tests ran against it. For every test
12
+ that ran, decide what happens next. The decision is a plan for a human (or a
13
+ setting) to approve; this skill does not edit tests or product code.
14
+
15
+ Requires `@mmerterden/multi-agent-toolkit-mcp` >= v3.25.0 for
16
+ `test_results_classify`. On an older server, or with no server, derive the
17
+ input statuses by hand as section 2 describes and say in the report that the
18
+ run used the fallback.
19
+
20
+ ## 1. The verdicts
21
+
22
+ Each test that ran gets one of four verdicts:
23
+
24
+ | Verdict | Meaning | What follows |
25
+ |---|---|---|
26
+ | `product-bug` | The test is right: behaviour broke without intent. | A finding is filed. The test is not changed. |
27
+ | `stale-test` | Behaviour changed on purpose, or a handle moved; the test expects the old state. | The test is revised. |
28
+ | `valid` | The test still measures the right thing on the new code. | Nothing. |
29
+ | `ambiguous` | The evidence does not decide it. | A human decides. |
30
+
31
+ The fifth outcome, `new-scenario`, belongs to the change rather than to a test:
32
+ behaviour the change adds that no test exercises. It goes in `newScenarios`
33
+ (section 5) and on to `scenario-gap-analysis`, never as a verdict on a test
34
+ that ran.
35
+
36
+ **The default is `ambiguous`.** Marking a product bug as `stale-test` loosens
37
+ the test and buries the bug, which is the most expensive mistake this step can
38
+ make. Calling a red test `product-bug` without evidence sends a team chasing a
39
+ bug that is not there. Every verdict other than `ambiguous` needs positive
40
+ evidence from section 4; a red test that the change merely fails to explain
41
+ stays `ambiguous`.
42
+
43
+ ## 2. Inputs
44
+
45
+ - **Classified results.** When the multi-agent-toolkit MCP server provides
46
+ `test_results_classify`, use its output as the input. It compares the head
47
+ run with a base run (the unchanged commit) and a confirmation run, and gives
48
+ each test a status with a reason:
49
+
50
+ | Status | How triage treats it |
51
+ |---|---|
52
+ | `passed` | Rule 4. Without a change analysis, read the diff for the area the test covers before calling it `valid`. |
53
+ | `regression` | Green on base, red twice on head. Rules 1 to 3, in order. |
54
+ | `preexisting` | Red on base too, so this change did not cause it. Never `stale-test` on this diff's evidence. `ambiguous` with the reason "red before the change", listed in its own section; `product-bug` (preexisting) only with the product `file:line` that causes it. |
55
+ | `unstable` | Flipped on confirmation or has a recent flake history. `ambiguous`; never green, never a product bug. |
56
+ | `not_measured` | Base, setup or environment did not measure it. `ambiguous` with the tool's reason. |
57
+
58
+ Without the tool, derive the same distinctions by hand: a setup failure, a
59
+ missing device or a server that did not start is not measured, not red.
60
+ - **The change**: the diff from base to head, commit and PR titles, release
61
+ notes.
62
+ - **The change analysis**, if one ran: which areas it expected to change and
63
+ how (behaviour change, new feature, refactor with no behaviour change).
64
+ - **Run evidence**: failure message, failing step, trace, screenshot or DOM.
65
+
66
+ ## 3. Decision rules
67
+
68
+ Apply them in this order; the first that matches decides.
69
+
70
+ 1. **Red because an element or locator was not found** -> check the handle
71
+ before anything else. Search the new tree for the element (`git grep` the
72
+ identifier, the text, the component).
73
+ - The element exists but carries no handle: `ambiguous` with the reason
74
+ "handle missing", and a request for `handle-request`. Not a stale test.
75
+ - The diff renames or moves the handle on purpose: `stale-test`, with the
76
+ diff `file:line`.
77
+ - The element is gone and the removal is intentional (diff `file:line`
78
+ plus a title or note saying so): `stale-test`.
79
+ - The element is gone and nothing says it was intended: `ambiguous`,
80
+ unless rule 3 finds positive evidence of a bug.
81
+ 2. **Red, and the diff changes that behaviour on purpose** (a commit title, a
82
+ new flow, new copy) -> `stale-test`. Cite the diff `file:line` and the
83
+ intent signal.
84
+ 3. **Red, with positive evidence of a bug** -> `product-bug`. Positive
85
+ evidence is one of:
86
+ - the test checks a contract (data loss, an error code, an empty body,
87
+ request and response parity) and the diff does not change that contract
88
+ on purpose;
89
+ - a product `file:line` that produces the wrong result;
90
+ - the change analysis states that behaviour in this area did not change,
91
+ yet the test that passed on base now fails.
92
+ Name the behaviour that broke. A red test with none of these stays
93
+ `ambiguous`.
94
+ 4. **Green** -> do not pass it only because it is green. When the change
95
+ analysis or the diff shows the behaviour this test covers changed, check
96
+ whether the test asserts the old behaviour or the new one: old, passing by
97
+ accident, `stale-test`; new, `valid`. When neither touches the area,
98
+ `valid`.
99
+ 5. **Failed for an environmental reason** (timeout, server down, network,
100
+ device) -> `ambiguous` with the reason. Never a product bug.
101
+ 6. **Anything else** -> `ambiguous`, naming the missing evidence.
102
+
103
+ A test written in this same chain that stays red after revision has often
104
+ caught a real bug. Calling it `product-bug` still needs the product code
105
+ `file:line` that causes it.
106
+
107
+ Separately from the per-test verdicts, list behaviour the change adds that no
108
+ test exercised as `newScenarios`.
109
+
110
+ ## 4. Evidence per verdict
111
+
112
+ | Verdict | Required |
113
+ |---|---|
114
+ | `stale-test` | Diff `file:line` that changes the behaviour or the handle, and the intent signal (title, note, spec). |
115
+ | `product-bug` | Expected versus observed from the run, the behaviour that broke, and one piece of positive evidence from rule 3. |
116
+ | `valid` | The green run, plus for rule 4 the reason the test asserts the new behaviour or why the area is untouched. |
117
+ | `ambiguous` | Which piece of evidence is missing. |
118
+ | `newScenarios[]` entry | The new behaviour and the diff `file:line` that adds it. |
119
+
120
+ Many tests failing on the same handle or the same fixture form a cluster: prove
121
+ one representative, decide the cluster together, and say in the reason that it
122
+ was decided as a cluster.
123
+
124
+ ## 5. Output
125
+
126
+ Every test that ran gets a verdict; a red test left without one reaches a human
127
+ as "ambiguous: no verdict given", so leaving one out only delays it.
128
+
129
+ ```json
130
+ {
131
+ "verdicts": [
132
+ {
133
+ "testId": "checkout.spec.ts > applies coupon",
134
+ "verdict": "stale-test",
135
+ "reason": "coupon field moved into a sheet on purpose",
136
+ "evidence": "src/checkout/CouponSheet.tsx:18, PR title 'move coupon entry to a sheet'",
137
+ "inputStatus": "regression"
138
+ }
139
+ ],
140
+ "newScenarios": [{ "behaviour": "...", "diff": "file:line" }]
141
+ }
142
+ ```
143
+
144
+ Write a report next to it: verdict and reason per test, a summary table by
145
+ verdict, the `preexisting` section, and what could not be measured. On a long
146
+ run, work screen by screen and save after each one, so a timeout loses nothing
147
+ already decided.
148
+
149
+ ## Boundaries
150
+
151
+ - No test edits, no product code edits.
152
+ - No red test becomes `stale-test` while there is doubt.
153
+ - A `product-bug` verdict is a report, never an automatic change to the test.
154
+
155
+ ## Related
156
+
157
+ - `scenario-gap-analysis` for `newScenarios` entries.
158
+ - `handle-request` for elements that exist but carry no handle.
159
+ - `e2e-testing` for the passed / failed / blocked verdicts of a single run.
160
+ - `fix-review-verdicts` when the red test led to a fix that now needs review.
@@ -3,7 +3,7 @@
3
3
  > Auto-generated by `pipeline/scripts/build-skills-index.mjs` - do not hand-edit.
4
4
  > Regenerate with `node pipeline/scripts/build-skills-index.mjs`.
5
5
 
6
- **229 skills** across 2 groups.
6
+ **234 skills** across 2 groups.
7
7
 
8
8
  | Group | Name | Platform | Description |
9
9
  |-------|------|----------|-------------|
@@ -24,7 +24,7 @@
24
24
  | external | `app-intents` | - | App Intents for Siri, Shortcuts, Spotlight, widgets, Control Center and Apple Intelligence: AppIntent actions, AppEntity and EntityQuery, Ap |
25
25
  | external | `app-store-changelog` | - | Generate user-facing App Store release notes from git history since the last tag. Use when release notes have to be written from the commits |
26
26
  | external | `app-store-optimization` | - | App Store Optimization (ASO) for ranking and conversion: keyword research; app name, subtitle and 100-byte keyword field; description and pr |
27
- | external | `app-store-review` | - | App Store submission readiness and rejection prevention: Review Guidelines 2.1, 2.3, 2.5.1, 3.1.1, 4.2 and 5.1.2, PrivacyInfo.xcprivacy mani |
27
+ | external | `app-store-review` | - | App Store submission readiness and rejection prevention: Review Guidelines 1.2, 2.1, 2.3, 2.3.14, 2.5.1, 2.5.19, 3.1.1, 4.2 and 5.1.2, uploa |
28
28
  | core | `apple-archive-compliance` | - | Apple App Store Review compliance - wraps the multi-agent-toolkit-mcp `ios_app_store_audit` tool (18-rule deep scan) with ITMS error code |
29
29
  | external | `apple-on-device-ai` | - | On-device AI on Apple hardware: Foundation Models (SystemLanguageModel, LanguageModelSession, @Generable and @Guide structured output, tool |
30
30
  | external | `architecture` | - | Stack-neutral architecture decisions: quality drivers, options with a trade-off matrix, reversibility, ADRs, fitness checks. Use when making |
@@ -61,9 +61,11 @@
61
61
  | external | `evidence-registry` | - | Check a package's real version, deprecation status and release notes on npm, PyPI, Maven Central or Swift Package Index. Use when a spec or |
62
62
  | external | `fastapi-pro` | - | FastAPI with Pydantic v2: lifespan, settings, Annotated dependencies, async SQLAlchemy 2.0 sessions, error handlers, background work, httpx |
63
63
  | external | `firebase` | - | You're a developer who has shipped dozens of Firebase projects. You've seen the easy path lead to security breaches, runaway costs, and impo |
64
+ | external | `fix-review-verdicts` | - | Independent fix review with three verdicts, test-gaming, scope and root-cause, each backed by file:line findings; the result is computed fro |
64
65
  | external | `github-actions-templates` | - | Authoring GitHub Actions workflows: triggers, matrices, caching, concurrency, least-privilege permissions, SHA pinning, OIDC, reusable workf |
65
66
  | core | `google-play-compliance` | - | Google Play Store publication compliance - bundletool + aapt2 + apksigner orchestration + 21-rule policy catalog with Play Console error c |
66
67
  | external | `gradle-kotlin-dsl` | - | Configure Android builds with Gradle Kotlin DSL, version catalogs (libs.versions.toml), convention plugins (build-logic module), common conf |
68
+ | external | `handle-request` | - | Add the test handles a scenario needs and answer each request with ADDED, ALREADY or COULD NOT ADD plus file:line or reason. Identity values |
67
69
  | external | `healthkit` | - | HealthKit on iOS, iPadOS, watchOS and visionOS: HKHealthStore authorization, sample, statistics and chart-ready collection queries, saving H |
68
70
  | external | `hig-app-icons` | - | iOS app icons: Icon Composer layered icons, default, dark, clear and tinted appearances, asset catalogs, alternate icons and the archive che |
69
71
  | external | `hig-components-content` | - | Apple HIG for content views mapped to SwiftUI: lists, tables, grids, charts, images, text, web views, empty states. Use when choosing or rev |
@@ -160,6 +162,7 @@
160
162
  | core | `multi-agent-test-accessibility` | - | Accessibility audit on a booted simulator / emulator: VoiceOver labels, sub-44pt tap targets, contrast, traits. Alias pinning the accessibil |
161
163
  | core | `multi-agent-test-dark-mode` | - | Dark mode UI test on a booted simulator / emulator: walk every screen light then dark, report contrast + colour bugs. Alias pinning the dark |
162
164
  | core | `multi-agent-test-dynamic-type` | - | Dynamic Type layout test on a booted simulator / emulator: re-walk every screen at XL through accessibility-extra-large, report truncation a |
165
+ | core | `multi-agent-test-gen` | - | Write the tests an app lacks, stage by stage, each gated on its artefact: inventory, read-only gap analysis, handles, tests, runs, per-test |
163
166
  | core | `multi-agent-test-screenshots` | - | App Store screenshot set from a booted simulator / emulator in a given locale, taken as an argument and defaulting to tr. Alias pinning the |
164
167
  | core | `multi-agent-testflight-validation` | - | iOS-pinned alias of store-ready: same three gates on an iOS build, one implementation. Validates a TestFlight / App Store package, never upl |
165
168
  | core | `multi-agent-uninstall` | - | Uninstall the pipeline from Claude Code + Copilot CLI. Keychain access tokens are always left untouched; --all-data also clears pipeline set |
@@ -182,6 +185,7 @@
182
185
  | external | `rest-api-design` | - | REST API design: HTTP methods, status codes, pagination, versioning, rate limiting, caching headers, OpenAPI documentation. Use when a REST |
183
186
  | external | `retrofit-networking` | - | Build networking layers on Android with Retrofit, OkHttp, and Kotlin Coroutines. Covers suspend functions in API interfaces, OkHttp intercep |
184
187
  | external | `room-database` | - | Implement Room database persistence on Android with @Entity, @Dao, @Database, Flow-based reactive queries, TypeConverters for complex types, |
188
+ | external | `scenario-gap-analysis` | - | Set an inventory against existing tests, sort each behaviour into COVERED, WRONGLY COVERED or MISSING, and write gaps as measurable, priorit |
185
189
  | external | `search-first` | - | Research-before-coding workflow. Before writing a custom implementation, check what already exists (repo utilities, installed libraries, pac |
186
190
  | external | `security-review` | - | Run a defensive, static security review of a diff or a repo: build a run-scoped threat model, find vulnerabilities joined to OWASP + CWE wit |
187
191
  | external | `shareplay-activities` | - | GroupActivities and SharePlay on iOS, macOS, tvOS and visionOS: GroupActivity, GroupSession lifecycle, messengers, playback sync, file trans |
@@ -220,6 +224,7 @@
220
224
  | external | `swiftui-view-refactor` | - | Refactor SwiftUI views into smaller components with stable, explicit data flow. Use when a SwiftUI view has grown too large and needs splitt |
221
225
  | external | `swiftui-webkit` | - | Web content in SwiftUI with WebKit for SwiftUI: WebView, WebPage, observable page state, navigation policies, link interception, JavaScript |
222
226
  | external | `tailwind-css` | - | Tailwind CSS v4: utility-first styling, responsive design, dark mode, custom themes, component patterns, and cn() utility. Use when styling |
227
+ | external | `test-result-triage` | - | Judge each test result on changed code as product-bug, stale-test, valid or ambiguous (the default), and list behaviour no test covers. stal |
223
228
  | external | `testing-backend` | - | Backend testing: pytest patterns (Python), Jest patterns (Node.js), integration testing, database fixtures/factories, API contract testing. |
224
229
  | external | `tipkit` | - | TipKit in-app tips (iOS 17+): Tip protocol, TipView, popoverTip, rules, events, TipGroup, styles, CloudKit sync. Use when building or review |
225
230
  | external | `typescript-patterns` | - | Modern TypeScript patterns: strict mode, utility types, generics, conditional types, type guards, discriminated unions, Zod validation. Use |
@@ -1,61 +0,0 @@
1
- /**
2
- * Anonymous install telemetry (opt-in only).
3
- *
4
- * Set `MULTI_AGENT_TELEMETRY=1` to enable. Nothing is sent otherwise.
5
- * Fire-and-forget; never throws and never delays the install.
6
- *
7
- * The payload is genuinely anonymous: package name, version, install
8
- * method, flags, platform/arch, and Node version. No usernames, emails,
9
- * hostnames, or other machine/user identifiers are collected.
10
- *
11
- * @module install/_telemetry
12
- */
13
-
14
- import { readFileSync } from "fs";
15
- import { platform, arch } from "os";
16
- import { join } from "path";
17
-
18
- /**
19
- * @param {{ packageRoot: string, flags: string[] }} ctx
20
- * @returns {Promise<void>}
21
- */
22
- export async function sendInstallTelemetry(ctx) {
23
- if (process.env.MULTI_AGENT_TELEMETRY !== "1") return;
24
-
25
- let method = "source";
26
- const npmExecPath = process.env.npm_execpath ?? "";
27
- if (npmExecPath.includes("npx-cli")) method = "npx";
28
- else if (process.env.npm_config_global === "true") method = "global";
29
- else if (process.env.npm_lifecycle_event === "install") method = "npm-install";
30
-
31
- let version = "unknown";
32
- try {
33
- const pkg = JSON.parse(readFileSync(join(ctx.packageRoot, "package.json"), "utf-8"));
34
- version = pkg.version ?? version;
35
- } catch {
36
- /* ignore */
37
- }
38
-
39
- const payload = {
40
- package: "@mmerterden/multi-agent-pipeline",
41
- version,
42
- method,
43
- flags: ctx.flags.filter((f) => f.startsWith("--")),
44
- platform: `${platform()} ${arch()}`,
45
- nodeVersion: process.version,
46
- };
47
-
48
- try {
49
- const ctrl = new AbortController();
50
- const timer = setTimeout(() => ctrl.abort(), 2000);
51
- await fetch("https://mmerterden.vercel.app/api/install-notify", {
52
- method: "POST",
53
- headers: { "Content-Type": "application/json" },
54
- body: JSON.stringify(payload),
55
- signal: ctrl.signal,
56
- });
57
- clearTimeout(timer);
58
- } catch {
59
- // Silent fail - never break the install if telemetry is unreachable
60
- }
61
- }