@mmerterden/multi-agent-pipeline 20.16.0 → 20.17.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 (60) hide show
  1. package/CHANGELOG.md +30 -0
  2. package/README.md +6 -5
  3. package/README.tr.md +6 -5
  4. package/docs/architecture.md +3 -3
  5. package/docs/ecosystem.md +5 -5
  6. package/docs/facts.json +14 -12
  7. package/docs/features.md +9 -1
  8. package/install/catalog-history.json +1 -1
  9. package/install/claude.mjs +41 -6
  10. package/install/codex.mjs +3 -3
  11. package/manifest.json +62 -49
  12. package/package.json +1 -1
  13. package/pipeline/commands/multi-agent/bug-bash/SKILL.md +154 -0
  14. package/pipeline/commands/multi-agent/review/SKILL.md +13 -9
  15. package/pipeline/commands/multi-agent/setup/SKILL.md +8 -6
  16. package/pipeline/commands/multi-agent/sync/SKILL.md +4 -3
  17. package/pipeline/commands/multi-agent/update/SKILL.md +5 -1
  18. package/pipeline/commands/sim-test.md +71 -6
  19. package/pipeline/lib/plugin-skill-roots.mjs +80 -0
  20. package/pipeline/lib/usage-lifecycle.mjs +83 -0
  21. package/pipeline/multi-agent-refs/cross-cli-contract.md +20 -4
  22. package/pipeline/multi-agent-refs/features/assertion-judge.md +76 -0
  23. package/pipeline/multi-agent-refs/features/exploratory-testing.md +140 -0
  24. package/pipeline/multi-agent-refs/features/skill-conformance.md +1 -1
  25. package/pipeline/multi-agent-refs/features/usage-reporting.md +59 -5
  26. package/pipeline/multi-agent-refs/features/valven.md +30 -3
  27. package/pipeline/multi-agent-refs/help/en.md +2 -0
  28. package/pipeline/multi-agent-refs/help/tr.md +2 -0
  29. package/pipeline/multi-agent-refs/phases/phase-0-init.md +1 -1
  30. package/pipeline/multi-agent-refs/phases/phase-4-commit.md +2 -2
  31. package/pipeline/schemas/bug-bash-verification.schema.json +41 -0
  32. package/pipeline/schemas/explore-run.schema.json +108 -0
  33. package/pipeline/schemas/prefs.schema.json +1 -1
  34. package/pipeline/scripts/_stack-routing.mjs +2 -0
  35. package/pipeline/scripts/bug-bash.mjs +379 -0
  36. package/pipeline/scripts/explore-findings.mjs +410 -0
  37. package/pipeline/scripts/gen-skills-index.mjs +1 -2
  38. package/pipeline/scripts/pr-timeline.mjs +135 -0
  39. package/pipeline/scripts/pre-commit-check.sh +4 -2
  40. package/pipeline/scripts/skill-conformance.mjs +17 -71
  41. package/pipeline/scripts/smoke-cross-cli-behavior.sh +1 -1
  42. package/pipeline/scripts/uninstall.mjs +29 -8
  43. package/pipeline/scripts/usage-identity.mjs +36 -10
  44. package/pipeline/scripts/usage-register.mjs +95 -8
  45. package/pipeline/scripts/usage-report.mjs +52 -2
  46. package/pipeline/scripts/valven-gate.mjs +292 -11
  47. package/pipeline/skills/.skill-manifest.json +18 -10
  48. package/pipeline/skills/.skills-index.json +28 -6
  49. package/pipeline/skills/shared/README.md +6 -4
  50. package/pipeline/skills/shared/core/multi-agent-bug-bash/SKILL.md +150 -0
  51. package/pipeline/skills/shared/core/multi-agent-review/SKILL.md +1 -1
  52. package/pipeline/skills/shared/core/multi-agent-setup/SKILL.md +5 -1
  53. package/pipeline/skills/shared/core/multi-agent-sync/SKILL.md +4 -3
  54. package/pipeline/skills/shared/core/multi-agent-update/SKILL.md +4 -1
  55. package/pipeline/skills/shared/external/e2e-testing/SKILL.md +124 -0
  56. package/pipeline/skills/shared/external/e2e-testing/references/document-fixtures.md +65 -0
  57. package/pipeline/skills/shared/external/valven-rules/SKILL.md +93 -0
  58. package/pipeline/skills/shared/{core → external}/valven-rules/references/rules.yml +52 -6
  59. package/pipeline/skills/skills-index.md +4 -2
  60. package/pipeline/skills/shared/core/valven-rules/SKILL.md +0 -62
@@ -0,0 +1,150 @@
1
+ ---
2
+ name: multi-agent-bug-bash
3
+ description: "Bug bash: parallel exploratory sessions by charter and persona, each with a budget; a finding is reported only when a repro test fails for its reason. Use when an app or branch needs broad bug hunting."
4
+ user-invocable: true
5
+ argument-hint: "[scope] [--platform ios|android|web] [--charters <file>] - scope: an area, a branch to diff against its base, or empty for the whole app"
6
+ metadata:
7
+ language: en
8
+ not-for: test, review, scenario-audit
9
+ ---
10
+
11
+ # multi-agent-bug-bash
12
+
13
+ **Input**: $ARGUMENTS
14
+
15
+ Several exploratory sessions run at once, each on one area with one posture.
16
+ What they report are claims. A claim becomes a bug in the report only when a
17
+ reproducing test fails with `ASSERTION_FAILED` on the assertion that encodes it;
18
+ everything else is listed as rejected, with the reason.
19
+
20
+ Scripts: `$HOME/.claude/scripts/bug-bash.mjs` (charters, merge, proof rule),
21
+ `$HOME/.claude/scripts/explore-findings.mjs` (per-session budget, stop rules,
22
+ judge). Contracts, read before Step 1:
23
+
24
+ ```
25
+ $HOME/.claude/multi-agent-refs/features/exploratory-testing.md
26
+ $HOME/.claude/multi-agent-refs/features/assertion-judge.md
27
+ ```
28
+
29
+ Log dir: `$HOME/.claude/logs/bug-bash/{repo}/{timestamp}/` (`LOG` below).
30
+
31
+ ## Gotchas
32
+
33
+ - "The explorer reported it" is not "confirmed". No passing proof, no bug.
34
+ - One charter, one area. A charter that spans the app ends at its budget having skimmed everything.
35
+ - Explorers that share an account report each other's edits as bugs: one test account per charter, typed by `secret_ref`.
36
+ - Against a deployed environment other people use, the bash is read-only: no sign-ups, purchases, submissions or injection-shaped input. A firewall block is the firewall working, not a finding.
37
+ - Mobile explorers need one booted device each; web explorers one browser `session` each.
38
+
39
+ ## Step 1 - Prepare
40
+
41
+ 1. Platform: `--platform`, else detect as `multi-agent-test` does. Mobile: list
42
+ booted devices; the parallel width is `min(4, devices)`. Web: the app URL,
43
+ width 4.
44
+ 2. Toolkit: locators, expect steps, verdict codes, `secret_ref`, `trace.md`,
45
+ web `session` and `save_as` / `replay` need
46
+ `@mmerterden/multi-agent-toolkit-mcp` ≥ v3.19.0. On an older server, say so
47
+ once and run with UI-tree taps; the proof rule does not change.
48
+ 3. Ask (one question to the user) for what the local app cannot do: integrations
49
+ without keys, seed data, what must never be tapped (payments, real
50
+ accounts), and the test accounts by credential name. This becomes the
51
+ charter context and the triage reference for Step 5.
52
+
53
+ ## Step 2 - Charters
54
+
55
+ With `--charters <file>`, use it. Otherwise read the screens, navigation and
56
+ forms (for a branch, `git diff --stat` against its base) and write 5-10
57
+ charters to `$LOG/charters.json`:
58
+
59
+ ```json
60
+ [{"slug": "cart", "persona": "skeptic", "area": "Cart", "start": "Cart tab",
61
+ "goal": "Starting at the Cart tab, change quantities and check every total against its rows",
62
+ "budget": {"steps": 6, "minutes": 10, "tokens": 120000}, "account": "bb-cart"}]
63
+ ```
64
+
65
+ Personas: `first-time-user`, `skeptic` (numbers and copy), `fuzzer` (edge
66
+ input; name the exact matrix in the goal), `state-keeper` (relaunch, back,
67
+ reload), `error-paths`, or `custom` with `stance`. Validate:
68
+
69
+ ```bash
70
+ node "$HOME/.claude/scripts/bug-bash.mjs" charters --file "$LOG/charters.json"
71
+ ```
72
+
73
+ Exit 1 lists what to fix. Show the charters in one table and confirm once
74
+ (autopilot: proceed).
75
+
76
+ ## Step 3 - Fan out
77
+
78
+ One explorer subagent per charter, at most the Step 1 width at a time (one task
79
+ each where the host can start them, otherwise sequentially). Each gets
80
+ its charter, the persona's stance, the Step 1 context, its device or session,
81
+ and these orders:
82
+
83
+ - Write `$LOG/sessions/<slug>.json` in the explore-run shape as you go: goal,
84
+ persona, platform, budget, usage, steps, findings.
85
+ - Run `explore-findings.mjs check --run <file>` before every step; stop when
86
+ it says so.
87
+ - Report every finding with expected, observed, repro, severity 1-5, kind and
88
+ evidence on disk. Credentials by `secret_ref` only.
89
+ - A visual or semantic claim is decided by a fresh judge (assertion-judge.md),
90
+ not by you.
91
+ - Never fix anything, never commit.
92
+
93
+ A session that ends `blocked` is kept: its causes go in the report.
94
+
95
+ ## Step 4 - Merge
96
+
97
+ ```bash
98
+ node "$HOME/.claude/scripts/bug-bash.mjs" merge --sessions "$LOG/sessions" > "$LOG/merged.json"
99
+ ```
100
+
101
+ Candidates `BB-1..n` merge one defect seen by several charters. Warnings and
102
+ findings that failed the contract are kept apart.
103
+
104
+ ## Step 5 - Triage, then verify
105
+
106
+ Sort every candidate before writing any test; read the source to do it.
107
+
108
+ | Bucket | Sign | Outcome |
109
+ |---|---|---|
110
+ | artifact | the explorer misread: lazy content not loaded, text split in the tree but whole on screen, a sheet it never scrolled | `rejected` with the check that settled it |
111
+ | environment | fails on a key, service or limit only the local stack lacks | `rejected`; `productionRisk: true` when production users would see the bad handling |
112
+ | design | code, tests or copy say it is intended | `rejected`, citing where |
113
+ | fixture | seed data lacks what real records have | `rejected`, naming the field |
114
+ | candidate | none of the above | verify |
115
+
116
+ Verify with one subagent per area (up to the Step 1 width), each with its
117
+ candidates and these orders:
118
+
119
+ 1. Read `observed` against the evidence; a contradiction rejects it here.
120
+ 2. Write a repro test in the project's own UI test framework (XCUITest,
121
+ Compose / Espresso, Playwright), or as a toolkit step sequence saved with
122
+ `save_as` whose last step is an `expect_*` assertion. It follows the repro
123
+ and asserts `expected`, so it fails today and passes once fixed. Put it under
124
+ a `BugBash` / `bugbash` directory and keep it out of the gating suite.
125
+ 3. Run it alone. Confirmed only when it fails with `ASSERTION_FAILED` on the
126
+ assertion that encodes the finding (`failedAt` equals `assertion`). A
127
+ failing XCTest / JUnit / Playwright `expect` on that line counts as
128
+ `ASSERTION_FAILED`; a build error, timeout, missing element or a different
129
+ assertion means the test is wrong: fix it and rerun. A passing test means
130
+ the finding did not reproduce.
131
+ 4. Record `$LOG/verifications.json` entries:
132
+ `{id, status, repro: {path, command, code, assertion, failedAt, trace?}, rootCause?, reason?, note?, productionRisk?}`.
133
+
134
+ ## Step 6 - Report
135
+
136
+ ```bash
137
+ node "$HOME/.claude/scripts/bug-bash.mjs" report --merged "$LOG/merged.json" \
138
+ --verifications "$LOG/verifications.json" > "$LOG/report.md"
139
+ ```
140
+
141
+ The script demotes any confirmed entry without a passing proof to `unproven`
142
+ and any candidate without an entry to `unverified`. Print the report: confirmed
143
+ bugs first (repro test, root cause, evidence, charters), then unverified
144
+ production risks, rejected by reason, warnings, and the charter table. Close
145
+ with the areas no charter reached and which parts are mechanical (the proof
146
+ rule, the stop rules) versus judgement (triage, the charters themselves).
147
+
148
+ Then offer, one question: fix the confirmed bugs through `multi-agent` with
149
+ each repro test as the acceptance check (green test = fixed, kept as the
150
+ regression test), or stop. **No commit, no push, no issue from this command.**
@@ -37,7 +37,7 @@ Skip Phase 0-3 and review a diff only. Input shapes: a PR (`#N`, `repo#N`, GitHu
37
37
  # bitbucket PR: curl -u "$BB_USER:$BB_TOKEN" .../pull-requests/$N/diff?contextLines=10
38
38
  ```
39
39
 
40
- 2c. **Valven delivery rules** - required on every input. Run `node "$HOME/.claude/scripts/valven-gate.mjs" --mode review --out "$VG_FILE"` plus the input's sources: a branch adds `--repo . --base origin/develop --head <ref>`; a PR adds `--branch <headRef> --pr-body-file <body> --commits-file <one subject per line>` (GitHub `gh pr view --json headRefName,body,commits`, Bitbucket `fromRef.displayId`, `description`, `/commits`) and either `--repo . --base origin/<baseRef> --head FETCH_HEAD` after `git fetch origin <headRef>` when the cwd is that repo, or `--diff-file <patch>` (rework then reports `not-measured`). Exit 0 clean, 1 findings, 2 could not run: print `Valven: not measured (<reason>)`, never "passed". `findings[]` (`tag: valven`) join the reviewer findings at step 5 and are accepted unless the task is exempt, so an `important` one makes step 7 NEEDS WORK. Old-work findings (`VLV-AGE-01`, `VLV-BEHIND-01`, `VLV-TRACE-03`; commit lines are `<ISO author date>\t<subject>`) get the `valven-port.mjs` plan in their fix: new branch, dropped commits, then "open the new PR, close this one". When `splitRequired`, run `valven-split.mjs` with the same base and head (no `--apply`) and add its slice table to the `VLV-SIZE-01` fix. The registry's judgement rules (`VLV-SCOPE-02`, `VLV-PRDESC-02`, from `$HOME/.claude/skills/valven-rules/references/rules.yml`) go into every reviewer prompt in step 3. Contract: `$HOME/.claude/skills/valven-rules/SKILL.md`.
40
+ 2c. **Valven delivery rules** - required on every input. Run `node "$HOME/.claude/scripts/valven-gate.mjs" --mode review --out "$VG_FILE"` plus the input's sources: a branch adds `--repo . --base origin/develop --head <ref>`; a PR adds `--branch <headRef> --pr-body-file <body> --commits-file <one subject per line> --pr-meta-file <timeline>` (GitHub: `node "$HOME/.claude/scripts/pr-timeline.mjs" --repo <owner/repo> --pr <N> --out <file>` writes the PR with its ready-for-review time and bot-typed reviews; read the head ref, body and commits from it and pass it as the timeline. Bitbucket `fromRef.displayId`, `description`, `/commits`, and a timeline written as `{createdAt, readyAt, isDraft, reviewerCount, firstReviewAt, approvedAt, mergedAt, closedAt}` from the PR and `/activities`, reviews by the author left out) and either `--repo . --base origin/<baseRef> --head FETCH_HEAD` after `git fetch origin <headRef>` when the cwd is that repo, or `--diff-file <patch>` (rework then reports `not-measured`). Exit 0 clean, 1 findings, 2 could not run: print `Valven: not measured (<reason>)`, never "passed". `findings[]` (`tag: valven`) join the reviewer findings at step 5 and are accepted unless the task is exempt, so an `important` one makes step 7 NEEDS WORK. Old-work findings (`VLV-AGE-01`, `VLV-BEHIND-01`, `VLV-TRACE-03`; commit lines are `<ISO author date>\t<subject>`) get the `valven-port.mjs` plan in their fix: new branch, dropped commits, then "open the new PR, close this one". When `splitRequired`, run `valven-split.mjs` with the same base and head (no `--apply`) and add its slice table to the `VLV-SIZE-01` fix. The duration rules (`VLV-CYCLE-01..03`) are `suggestion` findings with a Valven score and never set NEEDS WORK on their own; `VLV-PICKUP-01` is `important` for no reviewer and a `suggestion` for a draft older than 3 hours. Step 6 adds `Valven scores: churn · coding · pickup · review` from the report's `scores`, `-` where one is missing. The registry's judgement rules (`VLV-SCOPE-02`, `VLV-PRDESC-02`, from the `valven-rules` skill's `references/rules.yml`) go into every reviewer prompt in step 3. Contract: the `valven-rules` skill.
41
41
 
42
42
  3. **Start parallel reviewers** - three on every host; only the second slot differs, because GPT-5.4 exists on Copilot and Codex but not on Claude Code, where Opus fills it:
43
43
 
@@ -133,9 +133,13 @@ pbcopy < /dev/null
133
133
  Then, **whether they pasted or skipped**, run:
134
134
 
135
135
  ```bash
136
- node "$HOME/.copilot/scripts/usage-register.mjs"
136
+ node "$HOME/.copilot/scripts/usage-register.mjs" --json
137
137
  ```
138
138
 
139
+ If its JSON line says `"needsPersonalAccount":true`, offer to tie this machine to
140
+ the person's own GitHub account once (the "Personal account" step in
141
+ `$HOME/.claude/multi-agent-refs/features/usage-reporting.md`).
142
+
139
143
  It maps whatever token exists and switches reporting on, and requests a
140
144
  per-machine write-only one when none resolves. Setup is a registration entry point
141
145
  in its own right, so a machine that runs setup and never runs update still reports.
@@ -33,7 +33,7 @@ Run all steps automatically:
33
33
  ```
34
34
  Step 0: DOCTOR node $HOME/.claude/scripts/doctor.mjs - exit 2 or 4 STOPS the sync
35
35
  Step 1: DETECT Compare timestamps, find stale targets
36
- Step 2: COPILOT Claude Code -> Copilot CLI (instructions + 63 sub-command skills)
36
+ Step 2: COPILOT Claude Code -> Copilot CLI (instructions + 64 sub-command skills)
37
37
  Step 2b: CODEX Claude Code -> Codex CLI (1 router skill + sub-command specs as refs + agent TOML)
38
38
  Step 3: REPO Claude Code -> pipeline repo (genericized, personal data scrub)
39
39
  Step 3d: DEV-TOOLKIT Companion MCP server -> detect movement, ship gates, commit + publish
@@ -96,6 +96,7 @@ If nothing is stale -> report "All targets up to date" and stop.
96
96
  - `~/.claude/scripts/` - EXCEPT `pre-commit-check.sh` and `build-stack-plugins.mjs` (generic, synced)
97
97
  - Step 3c (PLUGINS): rebuild the `{owner}/multi-agent-plugins` marketplace from `shared/external` via `build-stack-plugins.mjs` (bumps changed plugins' patch version), then commit + push the plugins repo. On any change also verify help + README freshness: every plugin registers `./skills/tools/help` in plugin.json, `tools/bump.py --check` shows no DRIFT, `tools/validate.py` clean (CHANGELOG entry per bumped version), and pipeline help/READMEs reflect any command-surface change from Step 3
98
98
  - `~/.claude/settings.json`
99
+ - `~/.claude/multi-agent-refs/registries/` - the installer copies gate registries there from `pipeline/skills/shared/external`; the repo already holds the source
99
100
 
100
101
 
101
102
  ## Codex Sync (Step 2b)
@@ -228,11 +229,11 @@ When invoked with the `release` argument:
228
229
  |-------------|-------------|
229
230
  | `~/.claude/commands/multi-agent/{cmd}/SKILL.md` | `~/.copilot/skills/multi-agent-{cmd}/SKILL.md` |
230
231
 
231
- **63 commands are synced** (canonical inventory - must match `cross-cli-contract.md` section 1; drift = contract violation):
232
+ **64 commands are synced** (canonical inventory - must match `cross-cli-contract.md` section 1; drift = contract violation):
232
233
 
233
234
  ```
234
235
  analysis, analysis-jira, analysis-resolve, autopilot, autopilot-off,
235
- autopilot-on, autopilot-status, build-optimize, channels, complaint-analysis,
236
+ autopilot-on, autopilot-status, bug-bash, build-optimize, channels, complaint-analysis,
236
237
  create-jira, design-check, diff-explain, doctor, estimate, feedback, forget,
237
238
  garbage-collect, graph, help, ios-coding-standard, issue, jira, kill,
238
239
  language, log, manual-test, model, prune-logs,
@@ -38,12 +38,15 @@ Update the pipeline with a single command. Preferences are preserved; only skill
38
38
  4b. Refresh the stack-plugin marketplace so the latest plugin versions are picked up:
39
39
  `bash "$HOME/.claude/scripts/plugin-refresh.sh" {owner}` (adds the marketplace if needed, refreshes it, then runs `claude plugin update` for every installed plugin)
40
40
  5. `node migrate-prefs.mjs` (if there is a schema upgrade)
41
- 5b. `node "$HOME/.claude/scripts/usage-register.mjs"` - operational reporting.
41
+ 5b. `node "$HOME/.claude/scripts/usage-register.mjs" --json` - operational reporting.
42
42
  It requests a per-machine **write-only** token when none resolves, stores it in
43
43
  the credential store only, and switches reporting on. A no-op when a token is
44
44
  already onboarded, and permanently blocked by `usageLog.optOut: true`. Offline
45
45
  or endpoint down leaves reporting off with one line, never an error. Contract:
46
46
  `$HOME/.claude/multi-agent-refs/features/usage-reporting.md`.
47
+ If its JSON line says `"needsPersonalAccount":true`, offer to tie this machine to
48
+ the person's own GitHub account once (the "Personal account" step in
49
+ `$HOME/.claude/multi-agent-refs/features/usage-reporting.md`).
47
50
  6. Show the new version + changelog
48
51
  7. Smoke test (schema + cross-cli)
49
52
 
@@ -0,0 +1,124 @@
1
+ ---
2
+ name: e2e-testing
3
+ description: |
4
+ End-to-end testing of a running web or mobile app through the
5
+ multi-agent-toolkit MCP server: element locators instead of coordinates,
6
+ expect steps that return passed / failed / blocked verdicts with codes,
7
+ secrets by secret_ref, failure traces, saved and replayed step sequences,
8
+ parallel web sessions, and synthetic passport / residence permit / visa
9
+ fixtures for MRZ and document-scan tests. Use when driving an app on a
10
+ simulator, emulator or browser to check a flow, writing a repro for a UI
11
+ bug, or testing an MRZ or document-scan feature.
12
+ metadata:
13
+ source: multi-agent-pipeline
14
+ version: 1.0.0
15
+ ---
16
+
17
+ # E2E testing with the toolkit
18
+
19
+ Drive the app, assert exact outcomes deterministically, leave judgement only
20
+ to what cannot be compared, and keep a step that could not run apart from a
21
+ product that ran and was wrong.
22
+
23
+ Requires `@mmerterden/multi-agent-toolkit-mcp` ≥ v3.19.0 for everything below
24
+ except the base `ios_*` / `android_*` / `web_*` tools. On an older server, read
25
+ the UI tree, tap frame centres, and say in the result that the run used the
26
+ fallback. Tool inputs come from the server's own schema; the names here are
27
+ the contract.
28
+
29
+ ## 1. Locate, then act
30
+
31
+ | Platform | Locate | Act |
32
+ |---|---|---|
33
+ | iOS | `ui_locate` | `ios_tap_element`, `ios_type_text` |
34
+ | Android | `ui_locate` | `android_tap_element`, `android_type_text` |
35
+ | Web | `web_snapshot` / `ui_locate` | `web_click`, `web_type`, `web_select_option` |
36
+
37
+ Locator order: accessibility identifier, then role plus label, then visible
38
+ text. Text is last because it changes with locale and copy edits.
39
+
40
+ - `LOCATOR_NOT_FOUND`: nothing matched. Read the tree; the element may be
41
+ off-screen (scroll), not loaded yet (wait), or renamed.
42
+ - `LOCATOR_AMBIGUOUS`: several matched. Narrow by role or container; never pick
43
+ the first one.
44
+
45
+ Both are automation failures, not product bugs. Fix the locator and retry once;
46
+ still failing, record the step as blocked (automation).
47
+
48
+ Coordinates (`ios_tap`, `android_tap`) are for what has no element: a canvas, a
49
+ map, a chart point.
50
+
51
+ ## 2. Assert with expect steps
52
+
53
+ Inside `agent_run_steps`, an `expect_text`, `expect_element` or `expect_url`
54
+ step checks one exact claim and the run returns a verdict:
55
+
56
+ | Verdict | Code | Meaning |
57
+ |---|---|---|
58
+ | `passed` | - | every expect step held |
59
+ | `failed` | `ASSERTION_FAILED` | an expect step did not hold: a product failure |
60
+ | `blocked` | `CREDENTIAL_MISSING` | a secret_ref named an unknown credential |
61
+ | `blocked` | `ENVIRONMENT_UNAVAILABLE` | device, browser or backend not reachable |
62
+ | `blocked` | `SEED_DATA_MISSING` | the data the flow needs is not there |
63
+ | `blocked` | `BUDGET_EXCEEDED` | the step or time budget ran out |
64
+ | `blocked` | `REPLAY_DIVERGED` | a replayed sequence no longer matches the screen |
65
+
66
+ Report blocked apart from failed. "Checkout is broken" and "the run had no test
67
+ account" must never be the same line.
68
+
69
+ Use an expect step for anything exact: a total, a label, a route, an element
70
+ present or absent. A visual or semantic claim (clipping, contrast, "the error
71
+ explains what to do") is not an expect step: hand it to a fresh judge that sees
72
+ only the claim and the current screenshot or UI tree, never the run that led
73
+ there. Inconclusive is a failure, not a pass.
74
+
75
+ ## 3. Secrets
76
+
77
+ Type credentials with `secret_ref: "<name>"`, never the value. The value never
78
+ reaches the transcript, a log, a screenshot caption, a finding or a test file.
79
+ A finding names the account (`secret_ref:checkout-user`), not its password.
80
+
81
+ ## 4. Traces, save and replay
82
+
83
+ - A failed `agent_run_steps` writes a `trace.md`: the steps, the failing step,
84
+ the screen at failure. Attach its path to the bug, not a paraphrase of it.
85
+ - `save_as: "<name>"` stores a sequence that reached a state; `replay` runs it
86
+ again. A replay ending in an expect step is a repro: it fails with
87
+ `ASSERTION_FAILED` while the bug exists and passes once it is fixed.
88
+ - `REPLAY_DIVERGED` means the app no longer follows the recorded path. Look at
89
+ what changed before re-recording.
90
+
91
+ ## 5. Parallel web sessions
92
+
93
+ Pass `session: "<name>"` to the web tools to keep sessions apart: one per
94
+ explorer, one per test account. Two explorers on one session or one account
95
+ report each other's edits as bugs.
96
+
97
+ ## 6. A repro that proves a bug
98
+
99
+ 1. Follow the bug's repro steps with locators.
100
+ 2. End with the assertion that encodes the expected behaviour.
101
+ 3. Run it alone. It proves the bug only when it fails with `ASSERTION_FAILED`
102
+ on that assertion. Any other failure (a locator, a timeout, a build error, a
103
+ different assertion) means the test is wrong. A pass means the bug did not
104
+ reproduce.
105
+ 4. Keep it out of the gating suite until the fix lands; then it is the
106
+ regression test.
107
+
108
+ In a project test framework the same rule holds: a failing `XCTAssert`,
109
+ JUnit / Compose assertion or Playwright `expect` on the encoding line is
110
+ `ASSERTION_FAILED`.
111
+
112
+ ## 7. MRZ and document-scan features
113
+
114
+ `document_mrz_build` and `document_generate` produce synthetic passport (TD3),
115
+ residence permit (TD1) and visa (MRV-A / MRV-B) fixtures labelled TEST
116
+ SPECIMEN, with every ICAO 9303 check digit computed. Recipes, edge cases and
117
+ how to get the image into a simulator: `references/document-fixtures.md`.
118
+
119
+ ## Related
120
+
121
+ - `/multi-agent:test` and `/multi-agent:bug-bash` run this contract with
122
+ budgets, stop rules and a findings schema.
123
+ - `accessibility-compliance-accessibility-audit` for the accessibility half of
124
+ a screen check.
@@ -0,0 +1,65 @@
1
+ # Document fixtures for MRZ and document-scan tests
2
+
3
+ Synthetic travel documents for testing a feature that reads a machine readable
4
+ zone (MRZ): a passport scanner, a residence permit upload, a visa check.
5
+ Requires `@mmerterden/multi-agent-toolkit-mcp` ≥ v3.19.0.
6
+
7
+ ## The two tools
8
+
9
+ | Tool | Returns | Writes |
10
+ |---|---|---|
11
+ | `document_mrz_build` | `{format, lines, checkDigits, documentNumber, truncated, fields}` | nothing |
12
+ | `document_generate` | the same plus `{path, width, height, label, layout}` | a PNG |
13
+
14
+ Formats: `passport` is TD3 (2 lines of 44), `residence_permit` is TD1 (3 lines
15
+ of 30), `visa` is MRV-A (2x44, default) or MRV-B (2x36) via `visa_format`.
16
+
17
+ Main inputs: `type`, `surname`, `given_names`, `nationality`, `issuing_state`
18
+ (defaults to nationality), `birth_date` and `expiry_date` as `YYYY-MM-DD`,
19
+ `sex` (`M`, `F`, `X`), `document_number` (omit it for a deterministic synthetic
20
+ number from `seed`), `optional_data`. `document_generate` adds `output`,
21
+ `include_data_block` and `scale`.
22
+
23
+ Every PNG carries a fixed "TEST SPECIMEN - NOT A TRAVEL DOCUMENT" label and a
24
+ plain layout. It is a test input for a parser and an OCR pipeline, not a
25
+ document likeness.
26
+
27
+ ## Rules
28
+
29
+ - Synthetic identities only. Use made-up names and the ICAO test codes (`UTO`
30
+ for nationality and issuing state) unless the test is about a specific
31
+ country's rules. Never a real person's data, never a real document number.
32
+ - Fix `seed` in a test so the fixture is the same on every run.
33
+ - Assert on what the app extracted against `fields`, not against a re-read of
34
+ the image: the tool's `fields` and `checkDigits` are the expected values.
35
+
36
+ ## Getting the fixture to the app
37
+
38
+ | Path into the app | How |
39
+ |---|---|
40
+ | Photo library import | iOS: `ios_add_media` with the PNG `path`. Android: copy it to the device's pictures folder with adb and trigger a media scan |
41
+ | Debug deep link or test hook | pass `lines` straight in, when the app has a debug entry for MRZ text |
42
+ | Live camera | a simulator or emulator has no camera stream to aim at the image; this path needs a device and stays a manual check. Say so in the result |
43
+
44
+ ## Cases worth a test each
45
+
46
+ | Case | Input |
47
+ |---|---|
48
+ | Happy path, each format | one `passport`, one `residence_permit`, one `visa` |
49
+ | Long names | a surname or given names longer than the line allows; check `truncated` and that the app does not reject a valid truncated zone |
50
+ | Transliteration | names with diacritics or non-Latin letters; the zone carries the ICAO transliteration, the data block the original |
51
+ | Sex `X` | written `<` in the zone; the app must not require `M` or `F` |
52
+ | Expired document | `expiry_date` in the past; the app's own rule decides, the zone stays valid |
53
+ | TD1 number overflow | a document number longer than 9 characters spills into the optional field |
54
+ | Broken check digit | build a valid zone, then change one digit in `lines` before passing it in; the app must reject it |
55
+
56
+ ## A repro with a fixture
57
+
58
+ 1. `document_generate` with a fixed `seed` and the case's input.
59
+ 2. Put the PNG into the app's import path (table above).
60
+ 3. Drive the scan with locators.
61
+ 4. `expect_text` for each extracted field against `fields`: document number,
62
+ birth date, expiry date, names.
63
+
64
+ The last step failing with `ASSERTION_FAILED` on one field is the bug, and the
65
+ same sequence saved with `save_as` is its regression test.
@@ -0,0 +1,93 @@
1
+ ---
2
+ name: valven-rules
3
+ description: "Delivery-flow rules from metrics Valven reports: PR size, one concern per PR, tests with source, issue keys, no WIP commits, churn, PR body, and coding, pickup and review time on Valven's bands. Use when developing, opening or reviewing a pull request held to these rules, or splitting a branch into stacked PRs."
4
+ user-invocable: false
5
+ metadata:
6
+ source: multi-agent-pipeline
7
+ language: en
8
+ standards-registry: references/rules.yml
9
+ ---
10
+
11
+ # valven-rules
12
+
13
+ The registry is `references/rules.yml`. It holds two blocks:
14
+
15
+ | Block | Who checks it | Read by |
16
+ |---|---|---|
17
+ | `gate_rules` | the multi-agent pipeline's `valven-gate.mjs`, from the diff, the commits, the branch name, the PR body and the PR timeline | the gate only |
18
+ | `rules` | the reviewers, as judgement | `skill-conformance.mjs`, which puts them in `${CRITERIA}` |
19
+
20
+ Measured rules stay out of `rules` on purpose: a reviewer asked for a verdict on a line count
21
+ either recounts it or guesses, and both are worse than the number the script already has.
22
+
23
+ ## Development Behaviors
24
+
25
+ Valven scores four durations and a churn rate per developer. The bands are Valven's table; each
26
+ bound is exclusive.
27
+
28
+ | Rule | Measures | 100 | 75 | 50 | 0 |
29
+ |---|---|---|---|---|---|
30
+ | `VLV-REWORK-01` | removed lines written in the last 21 days | 0% churn | linear | linear | 100% churn |
31
+ | `VLV-CYCLE-01` | first commit to the pull request opening | < 30 min | < 2.5 h | < 24 h | later |
32
+ | `VLV-CYCLE-02` | ready for review to the first review | < 1 h | < 3 h | < 14 h | later |
33
+ | `VLV-CYCLE-03` | first review to approval or merge | < 30 min | < 3 h | < 18 h | later |
34
+
35
+ A duration in the 50 or 0 band is a `suggestion`: the time has passed, so the pull request cannot
36
+ fix it, and the finding names the habit that does. `VLV-PICKUP-01` is the part the author can fix
37
+ now: a pull request without a reviewer is `important`; a draft older than 3 hours is a
38
+ `suggestion`, because an unattended run opens a draft on purpose. A pull request still waiting is
39
+ measured up to now, a merged or closed one up to then, and a draft never marked ready has no pickup
40
+ time yet and is not asked for a reviewer. Reviews by the author, by bots, pending ones and ones left
41
+ before the pull request was ready do not count.
42
+
43
+ The habits behind good scores:
44
+
45
+ - Open the pull request as soon as the first slice works; ship the next slice as its own PR.
46
+ - Open it ready for review once its gates pass, with the default reviewers assigned.
47
+ - Reviewers check their queue at fixed times every day.
48
+ - Answer every review comment the same day, in one round, and push the fixes together.
49
+ - Settle the requirement before rewriting code written in the last three weeks.
50
+
51
+ Deploy time is not a rule: a release train or a store review sets it, not the pull request.
52
+ Activity and balance are team distributions, not properties of one pull request.
53
+
54
+ ## Where it runs in the pipeline
55
+
56
+ | Point | Command | A violation |
57
+ |---|---|---|
58
+ | Phase 1 Step 6 | plan estimates lines per task against `VLV-SIZE-01` | the plan proposes stacked slices before any code exists |
59
+ | Phase 2 exit, Gate 6 | `valven-gate.mjs --mode dev` | blocks the handoff to Review; size findings set `state.valven.splitRequired` |
60
+ | Phase 4, before push | `valven-gate.mjs --mode commit`, then `valven-split.mjs` when a split is required | the branch ships as stacked pull requests, one per slice |
61
+ | Phase 3 Step 1.762 and `/multi-agent:review` | `valven-gate.mjs --mode review`, with `--pr-meta-file` for a pull request | findings merge into triage with `tag: valven`; an accepted important one sets NEEDS WORK |
62
+
63
+ Thresholds: `prefs.global.valven.thresholds` overrides any rule's numeric keys per rule ID, for
64
+ example `{"VLV-SIZE-01": {"important_over": 300}}`. `prefs.global.valven.enabled: false` turns
65
+ the gate off and logs `valven: disabled by prefs`, so a skipped check never reads as a pass. A
66
+ rule the gate cannot measure is reported `not-measured` with the reason.
67
+
68
+ ## Without the pipeline
69
+
70
+ Apply the registry by hand before opening or approving a pull request, with the base branch as
71
+ `BASE`. Read each threshold from `gate_rules`, never from memory:
72
+
73
+ | Rules | Measure with |
74
+ |---|---|
75
+ | `VLV-SIZE-01`, `VLV-SIZE-02`, `VLV-SCOPE-01`, `VLV-HOTFIX-01` | `git diff --numstat -M "$(git merge-base BASE HEAD)"`, generated files, lockfiles and snapshots left out |
76
+ | `VLV-TEST-01` | the same diff: a changed source file without a changed test file |
77
+ | `VLV-TRACE-01..03`, `VLV-COMMIT-01`, `VLV-AGE-01` | `git log --format='%aI %s' BASE..HEAD` and the branch name |
78
+ | `VLV-BEHIND-01` | `git rev-list --count HEAD..BASE` and the merge-base's commit date |
79
+ | `VLV-CYCLE-*`, `VLV-PICKUP-01` | `gh pr view --json author,closedAt,createdAt,isDraft,mergedAt,reviewRequests,reviews`, the ready-for-review time from the pull request's `READY_FOR_REVIEW_EVENT` timeline item and each review author's type (GraphQL), and the oldest commit's author date |
80
+
81
+ State which rules were measured and which were not; an unmeasured rule is not a pass.
82
+
83
+ ## Splitting and old work
84
+
85
+ When `VLV-SIZE-01`, `VLV-SIZE-02` or `VLV-SCOPE-01` fails, the branch ships as stacked pull
86
+ requests of at most the size budget: pure renames and moves first, each test file with the source
87
+ it pairs with, then models and services, view models and use cases, views, and the rest. A single
88
+ file larger than the budget is its own slice and is reported, never cut. The pipeline's
89
+ `valven-split.mjs` plans and applies the stack.
90
+
91
+ `VLV-AGE-01`, `VLV-BEHIND-01` and `VLV-TRACE-03` mean the branch carries old or foreign work. The
92
+ change moves to a fresh branch from the current base as one commit (the pipeline's
93
+ `valven-port.mjs`); the old history is not rebased. Port first, then split.
@@ -1,12 +1,13 @@
1
- version: 1.0.0
2
- updated: 2026-10-02
1
+ version: 1.1.0
2
+ updated: 2026-10-07
3
3
  owner: delivery flow
4
4
  description: >
5
5
  Delivery-flow rules derived from the metrics Valven reports per team and per
6
6
  developer: cycle time, rework rate, review responsiveness, PR complexity,
7
- commit risk, lead time for changes and change failure rate. Valven publishes no
8
- formulas or thresholds, so every threshold below is a stated default that
9
- prefs.global.valven.thresholds overrides.
7
+ commit risk, lead time for changes and change failure rate. The Development
8
+ Behaviors bands (churn, coding, pickup and review time) are Valven's own scoring
9
+ table; every other threshold is a stated default, because Valven publishes no
10
+ formula for it. prefs.global.valven.thresholds overrides any of them.
10
11
 
11
12
  # The whole change set is in scope: these rules judge the shape of a pull
12
13
  # request, not the language inside it. Generated output, lockfiles and recorded
@@ -79,7 +80,7 @@ gate_rules:
79
80
  fix: squash them into the commit they amend before pushing
80
81
  - id: VLV-REWORK-01
81
82
  title: At most 30% of the removed lines were written in the last 21 days
82
- metric: Rework Rate
83
+ metric: Rework Rate, Churn rate (Development Behaviors, scored 100 - churn %)
83
84
  severity: important
84
85
  ratio_over: 0.30
85
86
  window_days: 21
@@ -125,6 +126,51 @@ gate_rules:
125
126
  modes: [commit, review]
126
127
  fix: move the commits of the other issue to their own branch and PR
127
128
 
129
+ # Development Behaviors: cycle time breakdown. Each duration is scored into
130
+ # Valven's bands (100 / 75 / 50 / 0; every bound exclusive). A score of 50 or
131
+ # 0 is reported as a suggestion: the time has already passed, so the pull
132
+ # request cannot fix it, and the finding names the habit that does. Deploy
133
+ # time is not a rule: a release train or a store review sets it, not the
134
+ # pull request.
135
+ - id: VLV-CYCLE-01
136
+ title: Coding time, from the first commit to opening the pull request, stays under 2.5 hours
137
+ metric: Cycle Time (coding)
138
+ severity: suggestion
139
+ full_under_minutes: 30
140
+ three_quarter_under_minutes: 150
141
+ half_under_minutes: 1440
142
+ modes: [commit, review]
143
+ fix: open the pull request as soon as the first slice works; ship the next slice as its own pull request
144
+ - id: VLV-CYCLE-02
145
+ title: Pickup time, from ready-for-review to the first review, stays under 3 hours
146
+ metric: Cycle Time (pickup), Review Responsiveness
147
+ severity: suggestion
148
+ full_under_minutes: 60
149
+ three_quarter_under_minutes: 180
150
+ half_under_minutes: 840
151
+ modes: [review]
152
+ fix: assign the reviewers when the pull request opens; reviewers check their queue at fixed times every day
153
+ - id: VLV-CYCLE-03
154
+ title: Review time, from the first review to approval, stays under 3 hours
155
+ metric: Cycle Time (review), Review Responsiveness
156
+ severity: suggestion
157
+ full_under_minutes: 30
158
+ three_quarter_under_minutes: 180
159
+ half_under_minutes: 1080
160
+ modes: [review]
161
+ fix: answer every comment the same day in one round and push the fixes together
162
+ # A missing reviewer is important: the author fixes it now. A long-lived
163
+ # draft is a suggestion, because an unattended run opens a draft on purpose
164
+ # and a person decides when it is ready.
165
+ - id: VLV-PICKUP-01
166
+ title: A pull request has a reviewer and does not sit as a draft for more than 3 hours
167
+ metric: Cycle Time (pickup), Review Responsiveness
168
+ severity: important
169
+ draft_minutes_over: 180
170
+ draft_severity: suggestion
171
+ modes: [review]
172
+ fix: assign the default reviewers; mark the pull request ready for review once its gates pass, or close it
173
+
128
174
  # Judgement rules. skill-conformance.mjs selects these for every diff, so each
129
175
  # reviewer returns a verdict per ID.
130
176
  rules:
@@ -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
- **221 skills** across 2 groups.
6
+ **223 skills** across 2 groups.
7
7
 
8
8
  | Group | Name | Platform | Description |
9
9
  |-------|------|----------|-------------|
@@ -54,6 +54,7 @@
54
54
  | external | `debugging-strategies` | - | Language-neutral debugging method: reproduce, minimise, falsifiable hypotheses, git bisect, instrumentation, production traces, concurrency |
55
55
  | external | `device-integrity` | - | DeviceCheck and App Attest: DCDevice tokens and per-device bits, DCAppAttestService key generation, attestation and assertions. Use when add |
56
56
  | external | `docker-expert` | - | Dockerfiles and images: multi-stage builds, BuildKit cache and secret mounts, slim or distroless bases, non-root, healthchecks, scanning, mu |
57
+ | external | `e2e-testing` | - | End-to-end testing of a running web or mobile app through the multi-agent-toolkit MCP server: element locators instead of coordinates, expec |
57
58
  | external | `energykit` | - | EnergyKit on iOS 26: grid electricity forecasts via ElectricityGuidance, EnergyVenue, EV and HVAC load events, ElectricityInsightService his |
58
59
  | external | `eventkit-calendar` | - | EventKit and EventKitUI: adding events to the user's calendar, creating reminders, recurrence rules, calendar or reminders access, event edi |
59
60
  | external | `evidence-github` | - | Search GitHub for facts an analysis can cite - a known issue in a dependency, the PR that fixed it, what a release actually changed, prior a |
@@ -100,6 +101,7 @@
100
101
  | core | `multi-agent-autopilot-off` | - | Turn off continuous mode on this machine: the schedule is removed, work already running finishes, the repo selection is kept. Use when the m |
101
102
  | core | `multi-agent-autopilot-on` | - | Turn on continuous mode on THIS machine: pick the repos it watches; labelled GitHub issues and assigned+labelled Jira items then run in a wo |
102
103
  | core | `multi-agent-autopilot-status` | - | Show what continuous mode is doing here: what runs at which phase, what is queued, what waits for an answer, what PRs it opened today. Use w |
104
+ | core | `multi-agent-bug-bash` | - | Bug bash: parallel exploratory sessions by charter and persona, each with a budget; a finding is reported only when a repro test fails for i |
103
105
  | core | `multi-agent-build-optimize` | - | Wrapper that dispatches to xcode-build-orchestrator on iOS repos. Benchmarks the current Xcode build, runs compilation / project / SPM analy |
104
106
  | core | `multi-agent-channels` | - | Multi-channel reporter - Jira/Confluence/Wiki/PR description. Multi-select channels + content, humanizer pass, reviewer-preserving Bitbuck |
105
107
  | core | `multi-agent-complaint-analysis` | - | Customer-complaint triage. Ingests complaints (paste, csv/xlsx/txt/json file, Jira issue, Confluence URL), fetches Graylog evidence per trx/ |
@@ -215,7 +217,7 @@
215
217
  | external | `testing-backend` | - | Backend testing: pytest patterns (Python), Jest patterns (Node.js), integration testing, database fixtures/factories, API contract testing. |
216
218
  | external | `tipkit` | - | TipKit in-app tips (iOS 17+): Tip protocol, TipView, popoverTip, rules, events, TipGroup, styles, CloudKit sync. Use when building or review |
217
219
  | external | `typescript-patterns` | - | Modern TypeScript patterns: strict mode, utility types, generics, conditional types, type guards, discriminated unions, Zod validation. Use |
218
- | core | `valven-rules` | - | Delivery-flow rules from the metrics Valven reports: PR size, one concern per PR, tests with source, issue keys, no WIP commits, rework, PR |
220
+ | external | `valven-rules` | - | Delivery-flow rules from metrics Valven reports: PR size, one concern per PR, tests with source, issue keys, no WIP commits, churn, PR body, |
219
221
  | external | `vision-framework` | - | On-device computer vision with Vision and VisionKit: OCR, face detection and landmarks, barcode and QR scanning, person and instance segment |
220
222
  | external | `vue-composition` | - | Vue 3 Composition API: ref, reactive, computed, watch, composables, Pinia state management, Vue Router 4, script setup. Use when building or |
221
223
  | external | `weatherkit` | - | WeatherKit on iOS: current, hourly, daily and minute forecasts, alerts, historical statistics, dataset selection, caching. Use when integrat |