@muggleai/works 5.0.3 → 5.0.4
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/dist/plugin/.claude-plugin/plugin.json +1 -1
- package/dist/plugin/.cursor-plugin/plugin.json +1 -1
- package/dist/plugin/skills/_shared/debug-failed-run.md +53 -0
- package/dist/plugin/skills/_shared/github-cli-recipes/pr-metadata.md +14 -2
- package/dist/plugin/skills/_shared/github-cli-recipes.md +1 -1
- package/dist/plugin/skills/_shared/telemetry-events/pr-followup-tick.md +1 -1
- package/dist/plugin/skills/do/e2e-acceptance.md +2 -0
- package/dist/plugin/skills/muggle-pr-followup/contract.md +7 -5
- package/dist/plugin/skills/muggle-test/SKILL.md +10 -20
- package/dist/plugin/skills/muggle-test-feature-local/SKILL.md +4 -13
- package/dist/release-manifest.json +4 -4
- package/package.json +6 -6
- package/plugin/.claude-plugin/plugin.json +1 -1
- package/plugin/.cursor-plugin/plugin.json +1 -1
- package/plugin/skills/_shared/debug-failed-run.md +53 -0
- package/plugin/skills/_shared/github-cli-recipes/pr-metadata.md +14 -2
- package/plugin/skills/_shared/github-cli-recipes.md +1 -1
- package/plugin/skills/_shared/telemetry-events/pr-followup-tick.md +1 -1
- package/plugin/skills/do/e2e-acceptance.md +2 -0
- package/plugin/skills/muggle-pr-followup/contract.md +7 -5
- package/plugin/skills/muggle-test/SKILL.md +10 -20
- package/plugin/skills/muggle-test-feature-local/SKILL.md +4 -13
|
@@ -1,7 +1,7 @@
|
|
|
1
1
|
{
|
|
2
2
|
"name": "muggle",
|
|
3
3
|
"description": "Run real-browser end-to-end (E2E) acceptance tests on your web app from any AI coding agent. Generate test scripts from plain English, replay them on localhost, capture screenshots, and validate user flows like signup, checkout, and dashboards. Works across Claude Code, Cursor, Codex, and Windsurf.",
|
|
4
|
-
"version": "5.0.
|
|
4
|
+
"version": "5.0.4",
|
|
5
5
|
"author": {
|
|
6
6
|
"name": "Muggle AI",
|
|
7
7
|
"email": "support@muggle-ai.com"
|
|
@@ -2,7 +2,7 @@
|
|
|
2
2
|
"name": "muggle",
|
|
3
3
|
"displayName": "Muggle AI",
|
|
4
4
|
"description": "Ship quality products with AI-powered end-to-end (E2E) acceptance testing that validates your web app like a real user — from Claude Code and Cursor to PR.",
|
|
5
|
-
"version": "5.0.
|
|
5
|
+
"version": "5.0.4",
|
|
6
6
|
"author": {
|
|
7
7
|
"name": "Muggle AI",
|
|
8
8
|
"email": "support@muggle-ai.com"
|
|
@@ -0,0 +1,53 @@
|
|
|
1
|
+
# Debug a Failed Run — Shared Reference
|
|
2
|
+
|
|
3
|
+
> Presentation layer for a single failed run. Turns one non-passing terminal run — local or remote — into a debug path: **evidence → diagnosis → a guaranteed user choice that always offers "give feedback & rerun".** Used by `muggle-test` (Step 7C), `muggle-test-feature-local`, and the `muggle-do` e2e stage. Depends on [`failure-mode-handling.md`](./failure-mode-handling.md) for the bucket taxonomy and telemetry schema — never the reverse. Don't restate its tables; read them.
|
|
4
|
+
|
|
5
|
+
## The guarantee
|
|
6
|
+
|
|
7
|
+
Every non-passing terminal run MUST route through this doc before it is reported. A failure is never summarized-and-dropped: the user is always shown *what happened* and is always presented a selection in which **"give feedback & rerun" is a first-class option**. "Skip — just report" stays selectable but is never the default.
|
|
8
|
+
|
|
9
|
+
The guarantee binds **interactive** callers. An autonomous caller with no user to prompt (the `acceptance-tester` agent) runs Steps 1–2 (evidence + diagnosis into its structured report) and skips Step 3's interactive offer.
|
|
10
|
+
|
|
11
|
+
## Inputs (the caller passes these in)
|
|
12
|
+
|
|
13
|
+
- `runId` (local) or workflow runtime id (remote).
|
|
14
|
+
- `mode` — `replay` or `regen`, the mode that failed.
|
|
15
|
+
- `testCaseId`, `projectId`.
|
|
16
|
+
- A re-execute handle — the loop/tool the caller used to run this case, so a rerun re-enters the same execution path.
|
|
17
|
+
|
|
18
|
+
## Step 1 — Gather evidence
|
|
19
|
+
|
|
20
|
+
Read **structured run fields**, never the `execute` stdout tail (see [`dev-loop/failures.md`](./dev-loop/failures.md)). Assemble:
|
|
21
|
+
|
|
22
|
+
- **Attempted steps + reasoning** — local: the attempted steps + `summaryStep` halt reason from `action-script.json` in `artifactsDir`; remote: the per-step list + `summaryStep` from `muggle-remote-wf-get-ts-gen-latest-run` / `muggle-remote-wf-get-ts-replay-latest-run`.
|
|
23
|
+
- **Visual evidence** — a failed run already preserves the full step-by-step on disk: every per-step frame under `<artifactsDir>/electron-runtime/screenshot/` (with per-step label data under `.../dataset/`), alongside the step script at `<artifactsDir>/action-script.json`. `run-result-get` returns `artifactsDir` — read the whole set there; don't trust a step's `screenshotLocalPath`, which points at the original runtime dir. Once published — failed runs are published too, see [`dev-loop/publish.md`](./dev-loop/publish.md) — the same frames are cloud-hosted per step as `screenshotUrl`, the form remote runs expose directly.
|
|
24
|
+
- **Verdict** — `Status` + `Error`.
|
|
25
|
+
|
|
26
|
+
## Step 2 — Diagnose
|
|
27
|
+
|
|
28
|
+
Classify into the failure bucket per [`failure-mode-handling.md`](./failure-mode-handling.md) — §B for a replay failure, §C for a regen failure. That bucket **is** the initial diagnosis. Phrase it for a human ("Looks like a **stale script** — the selectors moved; the product itself probably still works"), not as a telemetry label. Emit the `replay-failure-classified` / `regen-failure-classified` event now, before presenting anything.
|
|
29
|
+
|
|
30
|
+
## Step 3 — Present the debug card, then the guaranteed offer
|
|
31
|
+
|
|
32
|
+
Show the **debug card** first: attempted steps + reasoning, the failing step's screenshot (or a one-line note if a path is genuinely absent), and the one-line diagnosis.
|
|
33
|
+
|
|
34
|
+
Then present one `AskUserQuestion` whose options are:
|
|
35
|
+
|
|
36
|
+
1. **Give feedback & rerun** — always present. Invoke the `muggle-feedback` skill with this run's anchor (`runId` local / `testScriptId` remote) so the user says what should have happened, then re-execute per Step 4.
|
|
37
|
+
2. **The bucket's recommended action** from §B/§C (regenerate, report bug, share defect, retry…). Label it `(Recommended)` — it is the classifier's pick.
|
|
38
|
+
3. **Retry as-is**.
|
|
39
|
+
4. **Skip — just report** — last, never the default.
|
|
40
|
+
|
|
41
|
+
The bucket's recommended action and its alternatives live in `failure-mode-handling.md` §B/§C — read them there, don't restate them.
|
|
42
|
+
|
|
43
|
+
**Feedback anchor by lane.** Feedback attaches to a cloud action-script id. `muggle-feedback` owns resolving it: for a **local** run it publishes/uploads first when the run isn't already published; for a **remote** run it uses the existing script. Pass `runId` (local) or `testScriptId` (remote) and let it resolve the anchor — don't resolve or upload here.
|
|
44
|
+
|
|
45
|
+
## Step 4 — Rerun (always regen)
|
|
46
|
+
|
|
47
|
+
On "give feedback & rerun": once `muggle-feedback` returns, re-execute the test case in **regen** mode — feedback adjusts the agent's course, so the prior script is discarded; replay is never the rerun path. Local: the regen branch of [`dev-loop/run.md`](./dev-loop/run.md). Remote: `muggle-remote-workflow-start-test-script-generation`. Read the new run's result back through this doc (Step 1) so a second failure is debugged too.
|
|
48
|
+
|
|
49
|
+
## Step 5 — Resolve
|
|
50
|
+
|
|
51
|
+
Emit the `replay-failure-resolved` / `regen-failure-resolved` event with `userAction` set to the pick (`feedback-rerun`, the bucket action, `retry`, or `skip`) — one `*-classified` and one `*-resolved` per failure, per [`failure-mode-handling.md`](./failure-mode-handling.md) §D.
|
|
52
|
+
|
|
53
|
+
Process failures one at a time so the user isn't drowning in pickers.
|
|
@@ -1,6 +1,6 @@
|
|
|
1
1
|
# PR metadata snapshot
|
|
2
2
|
|
|
3
|
-
Fetch the fields the watcher and bootstrap need
|
|
3
|
+
Fetch the fields the watcher and bootstrap need.
|
|
4
4
|
|
|
5
5
|
```bash
|
|
6
6
|
gh pr view <pr-number> --repo <owner>/<repo> \
|
|
@@ -10,4 +10,16 @@ gh pr view <pr-number> --repo <owner>/<repo> \
|
|
|
10
10
|
- `state` is one of `OPEN`, `MERGED`, `CLOSED`.
|
|
11
11
|
- `headRefOid` is the current head SHA — store as `head_sha` in `prs.json`.
|
|
12
12
|
- `headRefName` is the branch — must match the working tree's branch in bootstrap.
|
|
13
|
-
- `mergeable` is `MERGEABLE`, `CONFLICTING`, or `UNKNOWN` (GitHub still computing — treat as
|
|
13
|
+
- `mergeable` is `MERGEABLE`, `CONFLICTING`, or `UNKNOWN` (GitHub still computing — treat as not-conflicting this tick). The watcher's **conflict** signal is `mergeable == CONFLICTING` (corroborated by `mergeStateStatus == DIRTY`).
|
|
14
|
+
|
|
15
|
+
## Behind-by (out-of-date detection)
|
|
16
|
+
|
|
17
|
+
`mergeStateStatus == BEHIND` is **not** a reliable out-of-date signal. GitHub collapses merge state into one value with precedence — `DIRTY` (conflict) and `BLOCKED` (missing required review, pending/failing required check) outrank `BEHIND` and mask it, and `BEHIND` surfaces *at all* only when the base enforces "require branches up to date." So a PR that is genuinely behind **and** awaiting review reports `BLOCKED`; `BEHIND` never shows, and its staleness goes unseen.
|
|
18
|
+
|
|
19
|
+
Detect out-of-date straight from commit ancestry instead — independent of merge-state precedence, review state, and branch protection:
|
|
20
|
+
|
|
21
|
+
```bash
|
|
22
|
+
gh api repos/<owner>/<repo>/compare/<baseRefName>...<head_sha> --jq '.behind_by'
|
|
23
|
+
```
|
|
24
|
+
|
|
25
|
+
`behind_by > 0` ⇒ the head is missing that many base commits ⇒ out of date. `0` ⇒ current with base. (`ahead_by` counts the head's own commits — ignore it.) This is the watcher's out-of-date trigger; it is exact even while `mergeable == UNKNOWN`.
|
|
@@ -8,7 +8,7 @@ Skills assume a working `gh auth status`. Auth errors surface verbatim from `gh`
|
|
|
8
8
|
|
|
9
9
|
| Recipe | Use case |
|
|
10
10
|
| :----- | :------- |
|
|
11
|
-
| [`pr-metadata`](github-cli-recipes/pr-metadata.md) | Snapshot PR state, head SHA, branch — watcher + bootstrap. |
|
|
11
|
+
| [`pr-metadata`](github-cli-recipes/pr-metadata.md) | Snapshot PR state, head SHA, branch, conflict + `behind_by` out-of-date detection — watcher + bootstrap. |
|
|
12
12
|
| [`submitted-reviews`](github-cli-recipes/submitted-reviews.md) | Fetch a review by id / watcher's body-only-review check. |
|
|
13
13
|
| [`pr-checks`](github-cli-recipes/pr-checks.md) | Check-run rollup for the head SHA — watcher's CI poll. |
|
|
14
14
|
| [`line-comments-for-review`](github-cli-recipes/line-comments-for-review.md) | Pull a review's line comments — `/muggle-do` per-comment routing. |
|
|
@@ -23,7 +23,7 @@ One per watcher iteration (idle or not).
|
|
|
23
23
|
|
|
24
24
|
- `actionable_threads`: count of actionable items this tick — unresolved, non-outdated threads whose newest comment is unmarked, plus body-only reviews past `lastBodyReviewId` — **after** filtering by the escalated set.
|
|
25
25
|
- `dispatched_review_ids`: owning review ids handed to `/muggle-do`. Empty when idle.
|
|
26
|
-
- `rebase_needed`: true when the branch is behind (`
|
|
26
|
+
- `rebase_needed`: true when the branch is behind its base (`behind_by > 0`) or conflicting (`mergeable == CONFLICTING`). `false` when reviews were dispatched (reviews preempt the mergeability check).
|
|
27
27
|
- `dispatched_rebase`: true when this tick dispatched `/muggle-do` with a rebase directive.
|
|
28
28
|
- `checks_red`: count of failing checks on the head SHA. `0` when reviews or a rebase were dispatched (both preempt the CI poll) or CI was green/pending.
|
|
29
29
|
- `dispatched_ci_fix`: true when this tick dispatched `/muggle-do` with a fix-ci directive.
|
|
@@ -145,6 +145,8 @@ For each test case:
|
|
|
145
145
|
|
|
146
146
|
**Overall:** PASS | FAIL | PARTIAL | INCONCLUSIVE | BLOCKED | SKIPPED — see [`../_shared/failure-mode-handling.md`](../_shared/failure-mode-handling.md) section F for the canonical taxonomy.
|
|
147
147
|
|
|
148
|
+
Failed runs use the same evidence + diagnosis assembly as the interactive debug path ([`../_shared/debug-failed-run.md`](../_shared/debug-failed-run.md) Steps 1–2) — write that evidence into the **Failed** block above. This stage is autonomous, so it skips Step 3's interactive offer.
|
|
149
|
+
|
|
148
150
|
## Hard constraints
|
|
149
151
|
|
|
150
152
|
- **Do NOT shut down the dev server.** The caller manages dev-server lifecycle.
|
|
@@ -31,7 +31,7 @@ If `prs.json[0].state` on disk is already `merged` or `closed`, this slot was fi
|
|
|
31
31
|
|
|
32
32
|
### Step 1 — Refresh PR state
|
|
33
33
|
|
|
34
|
-
Per [`../_shared/github-cli-recipes/pr-metadata.md`](../_shared/github-cli-recipes/pr-metadata.md). Update `prs.json[0].head_sha` and `prs.json[0].state` from the response; keep `mergeable`
|
|
34
|
+
Per [`../_shared/github-cli-recipes/pr-metadata.md`](../_shared/github-cli-recipes/pr-metadata.md). Update `prs.json[0].head_sha` and `prs.json[0].state` from the response; keep `mergeable` (conflict signal) for Step 5, and run the recipe's `compare` call to capture `behind_by` (out-of-date signal) for Step 5.
|
|
35
35
|
|
|
36
36
|
### Step 2 — Termination check
|
|
37
37
|
|
|
@@ -79,10 +79,12 @@ The watcher does **not** classify. Classification, batching, replying, escalatio
|
|
|
79
79
|
|
|
80
80
|
### Step 5 — No actionable feedback → keep the branch rebased on its base
|
|
81
81
|
|
|
82
|
-
A merge-ready branch is **current with its base** — neither conflicting nor behind.
|
|
82
|
+
A merge-ready branch is **current with its base** — neither conflicting nor behind. From the Step 1 metadata, the branch needs a rebase when either:
|
|
83
83
|
|
|
84
|
-
- `mergeable == CONFLICTING`
|
|
85
|
-
- `
|
|
84
|
+
- `mergeable == CONFLICTING` (corroborated by `mergeStateStatus == DIRTY`) — conflicts with the base, **or**
|
|
85
|
+
- `behind_by > 0` — out of date with the base. Read this from the `compare` call (commit ancestry), **never** from `mergeStateStatus == BEHIND`: GitHub masks `BEHIND` behind `DIRTY`/`BLOCKED` and only surfaces it under "require branches up to date" protection, so a stale PR that is also awaiting review or has a red required check reports `BLOCKED` — and its staleness would go unseen. See [`../_shared/github-cli-recipes/pr-metadata.md`](../_shared/github-cli-recipes/pr-metadata.md#behind-by-out-of-date-detection).
|
|
86
|
+
|
|
87
|
+
This trigger is **independent of approval and CI state**: an out-of-date branch is rebased whether or not it has been reviewed, approved, or has green checks. The watcher acts on staleness directly — it never waits for an approval to surface it.
|
|
86
88
|
|
|
87
89
|
If a rebase is due **and** `conflict_resolve_attempts[head_sha] < 2` **and** `head_sha` ∉ `conflict_escalated_shas` → dispatch and exit:
|
|
88
90
|
|
|
@@ -96,7 +98,7 @@ If a rebase is due **and** `conflict_resolve_attempts[head_sha] < 2` **and** `he
|
|
|
96
98
|
4. Append a dispatching line to `followup.log`; emit a `tick` event with `rebase_needed: true`, `dispatched_rebase: true`.
|
|
97
99
|
5. Exit. The dev cycle owns the PR; its respawn restarts the watcher, whose next tick re-checks the branch against its base on the new head — the rebase is its own verify loop, bounded by the per-SHA attempt budget.
|
|
98
100
|
|
|
99
|
-
|
|
101
|
+
Otherwise — `behind_by == 0` and not conflicting (`mergeable == UNKNOWN` is fine here: `behind_by` is exact while GitHub is still computing conflict state, so a stale branch still triggers), or budget spent (`conflict_resolve_attempts[head_sha] >= 2` or `head_sha` ∈ `conflict_escalated_shas`) → fall through to CI.
|
|
100
102
|
|
|
101
103
|
### Step 6 — No actionable feedback, branch current → poll CI for the head SHA
|
|
102
104
|
|
|
@@ -297,7 +297,7 @@ Checkout flow FAILED 15.7s 12 https://www.muggle-ai.co
|
|
|
297
297
|
Total: 3 tests | 2 passed | 1 failed | 37.1s
|
|
298
298
|
```
|
|
299
299
|
|
|
300
|
-
For failures
|
|
300
|
+
For failures, don't hand-write a verdict in the summary — route each through the debug path (Step 7C).
|
|
301
301
|
|
|
302
302
|
## Step 7B: Execute — Remote Mode
|
|
303
303
|
|
|
@@ -341,20 +341,11 @@ Login with invalid creds COMPLETED rt-def456
|
|
|
341
341
|
Checkout flow QUEUED rt-ghi789
|
|
342
342
|
```
|
|
343
343
|
|
|
344
|
-
## Step 7C: Route
|
|
344
|
+
## Step 7C: Route every failed run through the debug path
|
|
345
345
|
|
|
346
|
-
For every run with `status: "failed"` (or any non-passing terminal state) from 7A or 7B,
|
|
346
|
+
For every run with `status: "failed"` (or any non-passing terminal state) from 7A or 7B, route through [`_shared/debug-failed-run.md`](../_shared/debug-failed-run.md). This is **mandatory** — a failure is never reported without it. The debug path gathers evidence (attempted steps + reasoning + screenshot), diagnoses via [`_shared/failure-mode-handling.md`](../_shared/failure-mode-handling.md) (§B replay / §C regen), shows the debug card, and presents the guaranteed selection in which **"give feedback & rerun"** is always an option and "skip" is never the default.
|
|
347
347
|
|
|
348
|
-
|
|
349
|
-
- **Regen-mode failures** — section C (buckets: `transient` / `infra` / `agent-course` / `product-uxux`).
|
|
350
|
-
|
|
351
|
-
For each failed run:
|
|
352
|
-
1. Read the run with `muggle-local-run-result-get` (local) or `muggle-remote-wf-get-ts-gen-latest-run` / `muggle-remote-wf-get-ts-replay-latest-run` (remote) and extract signals per the heuristics in the shared doc.
|
|
353
|
-
2. Emit `replay-failure-classified` or `regen-failure-classified` via `muggle-local-telemetry-event-emit` **before** asking the user.
|
|
354
|
-
3. Present the recommended action via `AskUserQuestion` along with the alternatives the shared doc lists for that bucket.
|
|
355
|
-
4. After the user picks, emit the matching `*-resolved` event with `userAction` set to what they chose.
|
|
356
|
-
|
|
357
|
-
Process failures one at a time so the user isn't drowning in pickers — but emit telemetry per failure regardless.
|
|
348
|
+
Pass it per failed run: the `runId` (local) or workflow runtime id (remote), the `mode` that failed, `testCaseId`, `projectId`, and the execution handle (local: the dev loop from "Run the dev loop"; remote: 7B's workflow-start) so a rerun re-enters the same path. Process failures one at a time so the user isn't drowning in pickers.
|
|
358
349
|
|
|
359
350
|
## Step 8: Open Results in Browser
|
|
360
351
|
|
|
@@ -403,23 +394,22 @@ Once a PR exists for this work, offer to keep watching its review thread.
|
|
|
403
394
|
|
|
404
395
|
The `/mprfollowup` shortcut starts the same watcher manually at any time.
|
|
405
396
|
|
|
406
|
-
## Step 10: Offer feedback on
|
|
407
|
-
|
|
408
|
-
After the report is complete, if **any** test in the run had a `failed` or unexpected status (or the user verbally flags something looked off), suggest the feedback skill:
|
|
397
|
+
## Step 10: Offer feedback on a clean pass
|
|
409
398
|
|
|
410
|
-
|
|
399
|
+
Failures already got a guaranteed feedback-&-rerun offer in Step 7C's debug path — don't re-ask for them here.
|
|
411
400
|
|
|
412
|
-
|
|
413
|
-
- **Yes — give feedback** → invoke the `muggle-feedback` skill via the `Skill` tool
|
|
401
|
+
This step is only for a run that **passed** but the user flags as off (a misclick, wrong element, a summary that doesn't match intent). When that happens, use `AskUserQuestion`:
|
|
402
|
+
- **Yes — give feedback** → invoke the `muggle-feedback` skill via the `Skill` tool, passing the run's `runId` (local) or `testScriptId` (remote) as anchor context so the submit flow opens with the correct script already loaded.
|
|
414
403
|
- **No — skip**
|
|
415
404
|
|
|
416
|
-
|
|
405
|
+
Skip silently if nothing looked off.
|
|
417
406
|
|
|
418
407
|
## Non-negotiables
|
|
419
408
|
|
|
420
409
|
Each rule below is covered in-step above; these are the ones this skill most often violates, kept here as reinforcement:
|
|
421
410
|
|
|
422
411
|
- **Test-case shape** — never skip the generate→review cycle, never consolidate the generator's micro-tests, one atomic behavior per test case. Creating test cases directly or merging the generator's output is the single most frequent mistake.
|
|
412
|
+
- **Every failure routes through the debug path** — no failed run is summarized-and-dropped. Step 7C → [`_shared/debug-failed-run.md`](../_shared/debug-failed-run.md) is mandatory, "give feedback & rerun" is always offered, and "skip" is never the default.
|
|
423
413
|
- **Confirm intent before acting** — local vs remote; never guess the localhost/preview URL.
|
|
424
414
|
- **PR URLs run in a dedicated worktree** — never switch the user's main checkout; pass that worktree as `cwd`.
|
|
425
415
|
- **Every selection uses `AskUserQuestion`** — never ask the user to type a number; the user picks the project (never auto-select).
|
|
@@ -174,22 +174,13 @@ Read the run record per [`../_shared/dev-loop/failures.md`](../_shared/dev-loop/
|
|
|
174
174
|
|
|
175
175
|
- Include in the report: status, duration, pass/fail summary, per-step summary (passed runs), artifact paths, errors if failed, and script view URL when publishing ran.
|
|
176
176
|
|
|
177
|
-
### 9a. Route
|
|
177
|
+
### 9a. Route a failed run through the debug path
|
|
178
178
|
|
|
179
|
-
If the run's status is `failed` or any non-passing terminal state,
|
|
179
|
+
If the run's status is `failed` or any non-passing terminal state, route through [`_shared/debug-failed-run.md`](../_shared/debug-failed-run.md) — **mandatory**; a failure is never reported without it. It gathers evidence (attempted steps + reasoning + screenshot), diagnoses via [`_shared/failure-mode-handling.md`](../_shared/failure-mode-handling.md) (§B replay / §C regen), shows the debug card, and presents the guaranteed selection in which **"give feedback & rerun"** is always offered and "skip" is never the default.
|
|
180
180
|
|
|
181
|
-
|
|
182
|
-
- **Regen-mode run failed** (the user picked "Generate new script" or no script existed) → section C (buckets: `transient` / `infra` / `agent-course` / `product-uxux`).
|
|
181
|
+
Pass it: the `runId`, the `mode` that failed (replay if the user picked an existing script in Step 5, else regen), `testCaseId`, `projectId`, and the local execution handle so a rerun re-enters the same path.
|
|
183
182
|
|
|
184
|
-
|
|
185
|
-
1. Read the run via `muggle-local-run-result-get` and extract signals per the heuristics in the shared doc.
|
|
186
|
-
2. Emit `replay-failure-classified` or `regen-failure-classified` via `muggle-local-telemetry-event-emit` **before** asking the user.
|
|
187
|
-
3. Present the recommended action via `AskUserQuestion` with the alternatives the shared doc lists for that bucket.
|
|
188
|
-
4. After the user picks, emit the matching `*-resolved` event with `userAction`.
|
|
189
|
-
|
|
190
|
-
If the user picks `muggle-feedback` from any bucket's options, invoke the `muggle-feedback` skill via the `Skill` tool, passing the just-finished `runId` so the submit flow opens with this run preloaded.
|
|
191
|
-
|
|
192
|
-
Skip silently when the run passed cleanly — failure-mode events are by definition about failures.
|
|
183
|
+
Skip only when the run passed cleanly — the debug path is by definition about failures.
|
|
193
184
|
|
|
194
185
|
### 9b. Remind the user to guide the agent (every Electron invocation)
|
|
195
186
|
|
|
@@ -1,7 +1,7 @@
|
|
|
1
1
|
{
|
|
2
|
-
"release": "5.0.
|
|
3
|
-
"buildId": "run-
|
|
4
|
-
"commitSha": "
|
|
5
|
-
"buildTime": "2026-06-
|
|
2
|
+
"release": "5.0.4",
|
|
3
|
+
"buildId": "run-52-1",
|
|
4
|
+
"commitSha": "d27f03da1295aa4e58c8e2ba6a26a0e76c7700c9",
|
|
5
|
+
"buildTime": "2026-06-09T21:46:24Z",
|
|
6
6
|
"serviceName": "muggle-ai-works-mcp"
|
|
7
7
|
}
|
package/package.json
CHANGED
|
@@ -1,7 +1,7 @@
|
|
|
1
1
|
{
|
|
2
2
|
"name": "@muggleai/works",
|
|
3
3
|
"mcpName": "io.github.multiplex-ai/muggle",
|
|
4
|
-
"version": "5.0.
|
|
4
|
+
"version": "5.0.4",
|
|
5
5
|
"description": "Ship quality products with AI-powered E2E acceptance testing that validates your web app like a real user — from Claude Code and Cursor to PR.",
|
|
6
6
|
"type": "module",
|
|
7
7
|
"main": "dist/index.js",
|
|
@@ -41,14 +41,14 @@
|
|
|
41
41
|
"test:watch": "vitest"
|
|
42
42
|
},
|
|
43
43
|
"muggleConfig": {
|
|
44
|
-
"electronAppVersion": "1.2.
|
|
44
|
+
"electronAppVersion": "1.2.3",
|
|
45
45
|
"downloadBaseUrl": "https://github.com/multiplex-ai/muggle-ai-works/releases/download",
|
|
46
46
|
"runtimeTargetDefault": "production",
|
|
47
47
|
"checksums": {
|
|
48
|
-
"darwin-arm64": "
|
|
49
|
-
"darwin-x64": "
|
|
50
|
-
"linux-x64": "
|
|
51
|
-
"win32-x64": "
|
|
48
|
+
"darwin-arm64": "f46cfc5f052021f13de7d7721276d58863b958ec717631e98b97b7cd3d0fe4fa",
|
|
49
|
+
"darwin-x64": "e2254373a0bb3fffa46b236629c5d54a611ab05e138104a98f6f60a5d1280805",
|
|
50
|
+
"linux-x64": "ff5698fdbc1d65f436b75d860ebe50ee7171c7726565fa0ab2149a6f1cde4d13",
|
|
51
|
+
"win32-x64": "35ffa7af1767e802c7670c85205ea11961cb5583aa5dc30947d142eb7c734ff5"
|
|
52
52
|
}
|
|
53
53
|
},
|
|
54
54
|
"dependencies": {
|
|
@@ -1,7 +1,7 @@
|
|
|
1
1
|
{
|
|
2
2
|
"name": "muggle",
|
|
3
3
|
"description": "Run real-browser end-to-end (E2E) acceptance tests on your web app from any AI coding agent. Generate test scripts from plain English, replay them on localhost, capture screenshots, and validate user flows like signup, checkout, and dashboards. Works across Claude Code, Cursor, Codex, and Windsurf.",
|
|
4
|
-
"version": "5.0.
|
|
4
|
+
"version": "5.0.4",
|
|
5
5
|
"author": {
|
|
6
6
|
"name": "Muggle AI",
|
|
7
7
|
"email": "support@muggle-ai.com"
|
|
@@ -2,7 +2,7 @@
|
|
|
2
2
|
"name": "muggle",
|
|
3
3
|
"displayName": "Muggle AI",
|
|
4
4
|
"description": "Ship quality products with AI-powered end-to-end (E2E) acceptance testing that validates your web app like a real user — from Claude Code and Cursor to PR.",
|
|
5
|
-
"version": "5.0.
|
|
5
|
+
"version": "5.0.4",
|
|
6
6
|
"author": {
|
|
7
7
|
"name": "Muggle AI",
|
|
8
8
|
"email": "support@muggle-ai.com"
|
|
@@ -0,0 +1,53 @@
|
|
|
1
|
+
# Debug a Failed Run — Shared Reference
|
|
2
|
+
|
|
3
|
+
> Presentation layer for a single failed run. Turns one non-passing terminal run — local or remote — into a debug path: **evidence → diagnosis → a guaranteed user choice that always offers "give feedback & rerun".** Used by `muggle-test` (Step 7C), `muggle-test-feature-local`, and the `muggle-do` e2e stage. Depends on [`failure-mode-handling.md`](./failure-mode-handling.md) for the bucket taxonomy and telemetry schema — never the reverse. Don't restate its tables; read them.
|
|
4
|
+
|
|
5
|
+
## The guarantee
|
|
6
|
+
|
|
7
|
+
Every non-passing terminal run MUST route through this doc before it is reported. A failure is never summarized-and-dropped: the user is always shown *what happened* and is always presented a selection in which **"give feedback & rerun" is a first-class option**. "Skip — just report" stays selectable but is never the default.
|
|
8
|
+
|
|
9
|
+
The guarantee binds **interactive** callers. An autonomous caller with no user to prompt (the `acceptance-tester` agent) runs Steps 1–2 (evidence + diagnosis into its structured report) and skips Step 3's interactive offer.
|
|
10
|
+
|
|
11
|
+
## Inputs (the caller passes these in)
|
|
12
|
+
|
|
13
|
+
- `runId` (local) or workflow runtime id (remote).
|
|
14
|
+
- `mode` — `replay` or `regen`, the mode that failed.
|
|
15
|
+
- `testCaseId`, `projectId`.
|
|
16
|
+
- A re-execute handle — the loop/tool the caller used to run this case, so a rerun re-enters the same execution path.
|
|
17
|
+
|
|
18
|
+
## Step 1 — Gather evidence
|
|
19
|
+
|
|
20
|
+
Read **structured run fields**, never the `execute` stdout tail (see [`dev-loop/failures.md`](./dev-loop/failures.md)). Assemble:
|
|
21
|
+
|
|
22
|
+
- **Attempted steps + reasoning** — local: the attempted steps + `summaryStep` halt reason from `action-script.json` in `artifactsDir`; remote: the per-step list + `summaryStep` from `muggle-remote-wf-get-ts-gen-latest-run` / `muggle-remote-wf-get-ts-replay-latest-run`.
|
|
23
|
+
- **Visual evidence** — a failed run already preserves the full step-by-step on disk: every per-step frame under `<artifactsDir>/electron-runtime/screenshot/` (with per-step label data under `.../dataset/`), alongside the step script at `<artifactsDir>/action-script.json`. `run-result-get` returns `artifactsDir` — read the whole set there; don't trust a step's `screenshotLocalPath`, which points at the original runtime dir. Once published — failed runs are published too, see [`dev-loop/publish.md`](./dev-loop/publish.md) — the same frames are cloud-hosted per step as `screenshotUrl`, the form remote runs expose directly.
|
|
24
|
+
- **Verdict** — `Status` + `Error`.
|
|
25
|
+
|
|
26
|
+
## Step 2 — Diagnose
|
|
27
|
+
|
|
28
|
+
Classify into the failure bucket per [`failure-mode-handling.md`](./failure-mode-handling.md) — §B for a replay failure, §C for a regen failure. That bucket **is** the initial diagnosis. Phrase it for a human ("Looks like a **stale script** — the selectors moved; the product itself probably still works"), not as a telemetry label. Emit the `replay-failure-classified` / `regen-failure-classified` event now, before presenting anything.
|
|
29
|
+
|
|
30
|
+
## Step 3 — Present the debug card, then the guaranteed offer
|
|
31
|
+
|
|
32
|
+
Show the **debug card** first: attempted steps + reasoning, the failing step's screenshot (or a one-line note if a path is genuinely absent), and the one-line diagnosis.
|
|
33
|
+
|
|
34
|
+
Then present one `AskUserQuestion` whose options are:
|
|
35
|
+
|
|
36
|
+
1. **Give feedback & rerun** — always present. Invoke the `muggle-feedback` skill with this run's anchor (`runId` local / `testScriptId` remote) so the user says what should have happened, then re-execute per Step 4.
|
|
37
|
+
2. **The bucket's recommended action** from §B/§C (regenerate, report bug, share defect, retry…). Label it `(Recommended)` — it is the classifier's pick.
|
|
38
|
+
3. **Retry as-is**.
|
|
39
|
+
4. **Skip — just report** — last, never the default.
|
|
40
|
+
|
|
41
|
+
The bucket's recommended action and its alternatives live in `failure-mode-handling.md` §B/§C — read them there, don't restate them.
|
|
42
|
+
|
|
43
|
+
**Feedback anchor by lane.** Feedback attaches to a cloud action-script id. `muggle-feedback` owns resolving it: for a **local** run it publishes/uploads first when the run isn't already published; for a **remote** run it uses the existing script. Pass `runId` (local) or `testScriptId` (remote) and let it resolve the anchor — don't resolve or upload here.
|
|
44
|
+
|
|
45
|
+
## Step 4 — Rerun (always regen)
|
|
46
|
+
|
|
47
|
+
On "give feedback & rerun": once `muggle-feedback` returns, re-execute the test case in **regen** mode — feedback adjusts the agent's course, so the prior script is discarded; replay is never the rerun path. Local: the regen branch of [`dev-loop/run.md`](./dev-loop/run.md). Remote: `muggle-remote-workflow-start-test-script-generation`. Read the new run's result back through this doc (Step 1) so a second failure is debugged too.
|
|
48
|
+
|
|
49
|
+
## Step 5 — Resolve
|
|
50
|
+
|
|
51
|
+
Emit the `replay-failure-resolved` / `regen-failure-resolved` event with `userAction` set to the pick (`feedback-rerun`, the bucket action, `retry`, or `skip`) — one `*-classified` and one `*-resolved` per failure, per [`failure-mode-handling.md`](./failure-mode-handling.md) §D.
|
|
52
|
+
|
|
53
|
+
Process failures one at a time so the user isn't drowning in pickers.
|
|
@@ -1,6 +1,6 @@
|
|
|
1
1
|
# PR metadata snapshot
|
|
2
2
|
|
|
3
|
-
Fetch the fields the watcher and bootstrap need
|
|
3
|
+
Fetch the fields the watcher and bootstrap need.
|
|
4
4
|
|
|
5
5
|
```bash
|
|
6
6
|
gh pr view <pr-number> --repo <owner>/<repo> \
|
|
@@ -10,4 +10,16 @@ gh pr view <pr-number> --repo <owner>/<repo> \
|
|
|
10
10
|
- `state` is one of `OPEN`, `MERGED`, `CLOSED`.
|
|
11
11
|
- `headRefOid` is the current head SHA — store as `head_sha` in `prs.json`.
|
|
12
12
|
- `headRefName` is the branch — must match the working tree's branch in bootstrap.
|
|
13
|
-
- `mergeable` is `MERGEABLE`, `CONFLICTING`, or `UNKNOWN` (GitHub still computing — treat as
|
|
13
|
+
- `mergeable` is `MERGEABLE`, `CONFLICTING`, or `UNKNOWN` (GitHub still computing — treat as not-conflicting this tick). The watcher's **conflict** signal is `mergeable == CONFLICTING` (corroborated by `mergeStateStatus == DIRTY`).
|
|
14
|
+
|
|
15
|
+
## Behind-by (out-of-date detection)
|
|
16
|
+
|
|
17
|
+
`mergeStateStatus == BEHIND` is **not** a reliable out-of-date signal. GitHub collapses merge state into one value with precedence — `DIRTY` (conflict) and `BLOCKED` (missing required review, pending/failing required check) outrank `BEHIND` and mask it, and `BEHIND` surfaces *at all* only when the base enforces "require branches up to date." So a PR that is genuinely behind **and** awaiting review reports `BLOCKED`; `BEHIND` never shows, and its staleness goes unseen.
|
|
18
|
+
|
|
19
|
+
Detect out-of-date straight from commit ancestry instead — independent of merge-state precedence, review state, and branch protection:
|
|
20
|
+
|
|
21
|
+
```bash
|
|
22
|
+
gh api repos/<owner>/<repo>/compare/<baseRefName>...<head_sha> --jq '.behind_by'
|
|
23
|
+
```
|
|
24
|
+
|
|
25
|
+
`behind_by > 0` ⇒ the head is missing that many base commits ⇒ out of date. `0` ⇒ current with base. (`ahead_by` counts the head's own commits — ignore it.) This is the watcher's out-of-date trigger; it is exact even while `mergeable == UNKNOWN`.
|
|
@@ -8,7 +8,7 @@ Skills assume a working `gh auth status`. Auth errors surface verbatim from `gh`
|
|
|
8
8
|
|
|
9
9
|
| Recipe | Use case |
|
|
10
10
|
| :----- | :------- |
|
|
11
|
-
| [`pr-metadata`](github-cli-recipes/pr-metadata.md) | Snapshot PR state, head SHA, branch — watcher + bootstrap. |
|
|
11
|
+
| [`pr-metadata`](github-cli-recipes/pr-metadata.md) | Snapshot PR state, head SHA, branch, conflict + `behind_by` out-of-date detection — watcher + bootstrap. |
|
|
12
12
|
| [`submitted-reviews`](github-cli-recipes/submitted-reviews.md) | Fetch a review by id / watcher's body-only-review check. |
|
|
13
13
|
| [`pr-checks`](github-cli-recipes/pr-checks.md) | Check-run rollup for the head SHA — watcher's CI poll. |
|
|
14
14
|
| [`line-comments-for-review`](github-cli-recipes/line-comments-for-review.md) | Pull a review's line comments — `/muggle-do` per-comment routing. |
|
|
@@ -23,7 +23,7 @@ One per watcher iteration (idle or not).
|
|
|
23
23
|
|
|
24
24
|
- `actionable_threads`: count of actionable items this tick — unresolved, non-outdated threads whose newest comment is unmarked, plus body-only reviews past `lastBodyReviewId` — **after** filtering by the escalated set.
|
|
25
25
|
- `dispatched_review_ids`: owning review ids handed to `/muggle-do`. Empty when idle.
|
|
26
|
-
- `rebase_needed`: true when the branch is behind (`
|
|
26
|
+
- `rebase_needed`: true when the branch is behind its base (`behind_by > 0`) or conflicting (`mergeable == CONFLICTING`). `false` when reviews were dispatched (reviews preempt the mergeability check).
|
|
27
27
|
- `dispatched_rebase`: true when this tick dispatched `/muggle-do` with a rebase directive.
|
|
28
28
|
- `checks_red`: count of failing checks on the head SHA. `0` when reviews or a rebase were dispatched (both preempt the CI poll) or CI was green/pending.
|
|
29
29
|
- `dispatched_ci_fix`: true when this tick dispatched `/muggle-do` with a fix-ci directive.
|
|
@@ -145,6 +145,8 @@ For each test case:
|
|
|
145
145
|
|
|
146
146
|
**Overall:** PASS | FAIL | PARTIAL | INCONCLUSIVE | BLOCKED | SKIPPED — see [`../_shared/failure-mode-handling.md`](../_shared/failure-mode-handling.md) section F for the canonical taxonomy.
|
|
147
147
|
|
|
148
|
+
Failed runs use the same evidence + diagnosis assembly as the interactive debug path ([`../_shared/debug-failed-run.md`](../_shared/debug-failed-run.md) Steps 1–2) — write that evidence into the **Failed** block above. This stage is autonomous, so it skips Step 3's interactive offer.
|
|
149
|
+
|
|
148
150
|
## Hard constraints
|
|
149
151
|
|
|
150
152
|
- **Do NOT shut down the dev server.** The caller manages dev-server lifecycle.
|
|
@@ -31,7 +31,7 @@ If `prs.json[0].state` on disk is already `merged` or `closed`, this slot was fi
|
|
|
31
31
|
|
|
32
32
|
### Step 1 — Refresh PR state
|
|
33
33
|
|
|
34
|
-
Per [`../_shared/github-cli-recipes/pr-metadata.md`](../_shared/github-cli-recipes/pr-metadata.md). Update `prs.json[0].head_sha` and `prs.json[0].state` from the response; keep `mergeable`
|
|
34
|
+
Per [`../_shared/github-cli-recipes/pr-metadata.md`](../_shared/github-cli-recipes/pr-metadata.md). Update `prs.json[0].head_sha` and `prs.json[0].state` from the response; keep `mergeable` (conflict signal) for Step 5, and run the recipe's `compare` call to capture `behind_by` (out-of-date signal) for Step 5.
|
|
35
35
|
|
|
36
36
|
### Step 2 — Termination check
|
|
37
37
|
|
|
@@ -79,10 +79,12 @@ The watcher does **not** classify. Classification, batching, replying, escalatio
|
|
|
79
79
|
|
|
80
80
|
### Step 5 — No actionable feedback → keep the branch rebased on its base
|
|
81
81
|
|
|
82
|
-
A merge-ready branch is **current with its base** — neither conflicting nor behind.
|
|
82
|
+
A merge-ready branch is **current with its base** — neither conflicting nor behind. From the Step 1 metadata, the branch needs a rebase when either:
|
|
83
83
|
|
|
84
|
-
- `mergeable == CONFLICTING`
|
|
85
|
-
- `
|
|
84
|
+
- `mergeable == CONFLICTING` (corroborated by `mergeStateStatus == DIRTY`) — conflicts with the base, **or**
|
|
85
|
+
- `behind_by > 0` — out of date with the base. Read this from the `compare` call (commit ancestry), **never** from `mergeStateStatus == BEHIND`: GitHub masks `BEHIND` behind `DIRTY`/`BLOCKED` and only surfaces it under "require branches up to date" protection, so a stale PR that is also awaiting review or has a red required check reports `BLOCKED` — and its staleness would go unseen. See [`../_shared/github-cli-recipes/pr-metadata.md`](../_shared/github-cli-recipes/pr-metadata.md#behind-by-out-of-date-detection).
|
|
86
|
+
|
|
87
|
+
This trigger is **independent of approval and CI state**: an out-of-date branch is rebased whether or not it has been reviewed, approved, or has green checks. The watcher acts on staleness directly — it never waits for an approval to surface it.
|
|
86
88
|
|
|
87
89
|
If a rebase is due **and** `conflict_resolve_attempts[head_sha] < 2` **and** `head_sha` ∉ `conflict_escalated_shas` → dispatch and exit:
|
|
88
90
|
|
|
@@ -96,7 +98,7 @@ If a rebase is due **and** `conflict_resolve_attempts[head_sha] < 2` **and** `he
|
|
|
96
98
|
4. Append a dispatching line to `followup.log`; emit a `tick` event with `rebase_needed: true`, `dispatched_rebase: true`.
|
|
97
99
|
5. Exit. The dev cycle owns the PR; its respawn restarts the watcher, whose next tick re-checks the branch against its base on the new head — the rebase is its own verify loop, bounded by the per-SHA attempt budget.
|
|
98
100
|
|
|
99
|
-
|
|
101
|
+
Otherwise — `behind_by == 0` and not conflicting (`mergeable == UNKNOWN` is fine here: `behind_by` is exact while GitHub is still computing conflict state, so a stale branch still triggers), or budget spent (`conflict_resolve_attempts[head_sha] >= 2` or `head_sha` ∈ `conflict_escalated_shas`) → fall through to CI.
|
|
100
102
|
|
|
101
103
|
### Step 6 — No actionable feedback, branch current → poll CI for the head SHA
|
|
102
104
|
|
|
@@ -297,7 +297,7 @@ Checkout flow FAILED 15.7s 12 https://www.muggle-ai.co
|
|
|
297
297
|
Total: 3 tests | 2 passed | 1 failed | 37.1s
|
|
298
298
|
```
|
|
299
299
|
|
|
300
|
-
For failures
|
|
300
|
+
For failures, don't hand-write a verdict in the summary — route each through the debug path (Step 7C).
|
|
301
301
|
|
|
302
302
|
## Step 7B: Execute — Remote Mode
|
|
303
303
|
|
|
@@ -341,20 +341,11 @@ Login with invalid creds COMPLETED rt-def456
|
|
|
341
341
|
Checkout flow QUEUED rt-ghi789
|
|
342
342
|
```
|
|
343
343
|
|
|
344
|
-
## Step 7C: Route
|
|
344
|
+
## Step 7C: Route every failed run through the debug path
|
|
345
345
|
|
|
346
|
-
For every run with `status: "failed"` (or any non-passing terminal state) from 7A or 7B,
|
|
346
|
+
For every run with `status: "failed"` (or any non-passing terminal state) from 7A or 7B, route through [`_shared/debug-failed-run.md`](../_shared/debug-failed-run.md). This is **mandatory** — a failure is never reported without it. The debug path gathers evidence (attempted steps + reasoning + screenshot), diagnoses via [`_shared/failure-mode-handling.md`](../_shared/failure-mode-handling.md) (§B replay / §C regen), shows the debug card, and presents the guaranteed selection in which **"give feedback & rerun"** is always an option and "skip" is never the default.
|
|
347
347
|
|
|
348
|
-
|
|
349
|
-
- **Regen-mode failures** — section C (buckets: `transient` / `infra` / `agent-course` / `product-uxux`).
|
|
350
|
-
|
|
351
|
-
For each failed run:
|
|
352
|
-
1. Read the run with `muggle-local-run-result-get` (local) or `muggle-remote-wf-get-ts-gen-latest-run` / `muggle-remote-wf-get-ts-replay-latest-run` (remote) and extract signals per the heuristics in the shared doc.
|
|
353
|
-
2. Emit `replay-failure-classified` or `regen-failure-classified` via `muggle-local-telemetry-event-emit` **before** asking the user.
|
|
354
|
-
3. Present the recommended action via `AskUserQuestion` along with the alternatives the shared doc lists for that bucket.
|
|
355
|
-
4. After the user picks, emit the matching `*-resolved` event with `userAction` set to what they chose.
|
|
356
|
-
|
|
357
|
-
Process failures one at a time so the user isn't drowning in pickers — but emit telemetry per failure regardless.
|
|
348
|
+
Pass it per failed run: the `runId` (local) or workflow runtime id (remote), the `mode` that failed, `testCaseId`, `projectId`, and the execution handle (local: the dev loop from "Run the dev loop"; remote: 7B's workflow-start) so a rerun re-enters the same path. Process failures one at a time so the user isn't drowning in pickers.
|
|
358
349
|
|
|
359
350
|
## Step 8: Open Results in Browser
|
|
360
351
|
|
|
@@ -403,23 +394,22 @@ Once a PR exists for this work, offer to keep watching its review thread.
|
|
|
403
394
|
|
|
404
395
|
The `/mprfollowup` shortcut starts the same watcher manually at any time.
|
|
405
396
|
|
|
406
|
-
## Step 10: Offer feedback on
|
|
407
|
-
|
|
408
|
-
After the report is complete, if **any** test in the run had a `failed` or unexpected status (or the user verbally flags something looked off), suggest the feedback skill:
|
|
397
|
+
## Step 10: Offer feedback on a clean pass
|
|
409
398
|
|
|
410
|
-
|
|
399
|
+
Failures already got a guaranteed feedback-&-rerun offer in Step 7C's debug path — don't re-ask for them here.
|
|
411
400
|
|
|
412
|
-
|
|
413
|
-
- **Yes — give feedback** → invoke the `muggle-feedback` skill via the `Skill` tool
|
|
401
|
+
This step is only for a run that **passed** but the user flags as off (a misclick, wrong element, a summary that doesn't match intent). When that happens, use `AskUserQuestion`:
|
|
402
|
+
- **Yes — give feedback** → invoke the `muggle-feedback` skill via the `Skill` tool, passing the run's `runId` (local) or `testScriptId` (remote) as anchor context so the submit flow opens with the correct script already loaded.
|
|
414
403
|
- **No — skip**
|
|
415
404
|
|
|
416
|
-
|
|
405
|
+
Skip silently if nothing looked off.
|
|
417
406
|
|
|
418
407
|
## Non-negotiables
|
|
419
408
|
|
|
420
409
|
Each rule below is covered in-step above; these are the ones this skill most often violates, kept here as reinforcement:
|
|
421
410
|
|
|
422
411
|
- **Test-case shape** — never skip the generate→review cycle, never consolidate the generator's micro-tests, one atomic behavior per test case. Creating test cases directly or merging the generator's output is the single most frequent mistake.
|
|
412
|
+
- **Every failure routes through the debug path** — no failed run is summarized-and-dropped. Step 7C → [`_shared/debug-failed-run.md`](../_shared/debug-failed-run.md) is mandatory, "give feedback & rerun" is always offered, and "skip" is never the default.
|
|
423
413
|
- **Confirm intent before acting** — local vs remote; never guess the localhost/preview URL.
|
|
424
414
|
- **PR URLs run in a dedicated worktree** — never switch the user's main checkout; pass that worktree as `cwd`.
|
|
425
415
|
- **Every selection uses `AskUserQuestion`** — never ask the user to type a number; the user picks the project (never auto-select).
|
|
@@ -174,22 +174,13 @@ Read the run record per [`../_shared/dev-loop/failures.md`](../_shared/dev-loop/
|
|
|
174
174
|
|
|
175
175
|
- Include in the report: status, duration, pass/fail summary, per-step summary (passed runs), artifact paths, errors if failed, and script view URL when publishing ran.
|
|
176
176
|
|
|
177
|
-
### 9a. Route
|
|
177
|
+
### 9a. Route a failed run through the debug path
|
|
178
178
|
|
|
179
|
-
If the run's status is `failed` or any non-passing terminal state,
|
|
179
|
+
If the run's status is `failed` or any non-passing terminal state, route through [`_shared/debug-failed-run.md`](../_shared/debug-failed-run.md) — **mandatory**; a failure is never reported without it. It gathers evidence (attempted steps + reasoning + screenshot), diagnoses via [`_shared/failure-mode-handling.md`](../_shared/failure-mode-handling.md) (§B replay / §C regen), shows the debug card, and presents the guaranteed selection in which **"give feedback & rerun"** is always offered and "skip" is never the default.
|
|
180
180
|
|
|
181
|
-
|
|
182
|
-
- **Regen-mode run failed** (the user picked "Generate new script" or no script existed) → section C (buckets: `transient` / `infra` / `agent-course` / `product-uxux`).
|
|
181
|
+
Pass it: the `runId`, the `mode` that failed (replay if the user picked an existing script in Step 5, else regen), `testCaseId`, `projectId`, and the local execution handle so a rerun re-enters the same path.
|
|
183
182
|
|
|
184
|
-
|
|
185
|
-
1. Read the run via `muggle-local-run-result-get` and extract signals per the heuristics in the shared doc.
|
|
186
|
-
2. Emit `replay-failure-classified` or `regen-failure-classified` via `muggle-local-telemetry-event-emit` **before** asking the user.
|
|
187
|
-
3. Present the recommended action via `AskUserQuestion` with the alternatives the shared doc lists for that bucket.
|
|
188
|
-
4. After the user picks, emit the matching `*-resolved` event with `userAction`.
|
|
189
|
-
|
|
190
|
-
If the user picks `muggle-feedback` from any bucket's options, invoke the `muggle-feedback` skill via the `Skill` tool, passing the just-finished `runId` so the submit flow opens with this run preloaded.
|
|
191
|
-
|
|
192
|
-
Skip silently when the run passed cleanly — failure-mode events are by definition about failures.
|
|
183
|
+
Skip only when the run passed cleanly — the debug path is by definition about failures.
|
|
193
184
|
|
|
194
185
|
### 9b. Remind the user to guide the agent (every Electron invocation)
|
|
195
186
|
|