@muggleai/works 4.14.0 → 4.15.1

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 (94) hide show
  1. package/dist/plugin/.claude-plugin/plugin.json +1 -1
  2. package/dist/plugin/.cursor-plugin/plugin.json +1 -1
  3. package/dist/plugin/agents/acceptance-tester.md +2 -0
  4. package/dist/plugin/commands/mbt.md +7 -0
  5. package/dist/plugin/commands/mdo.md +3 -3
  6. package/dist/plugin/skills/CLAUDE.md +15 -0
  7. package/dist/plugin/skills/_aliases.json +1 -0
  8. package/dist/plugin/skills/_shared/ci-check-to-command.md +10 -0
  9. package/dist/plugin/skills/_shared/dev-loop/action-script.md +3 -0
  10. package/dist/plugin/skills/_shared/dev-loop/failures.md +14 -0
  11. package/dist/plugin/skills/_shared/dev-loop/fresh-session.md +10 -0
  12. package/dist/plugin/skills/_shared/dev-loop/publish.md +13 -0
  13. package/dist/plugin/skills/_shared/dev-loop/run.md +34 -0
  14. package/dist/plugin/skills/_shared/dev-loop/timeouts.md +6 -0
  15. package/dist/plugin/skills/_shared/failure-mode-handling.md +2 -2
  16. package/dist/plugin/skills/_shared/github-cli-recipes/pr-checks.md +22 -0
  17. package/dist/plugin/skills/_shared/github-cli-recipes.md +1 -0
  18. package/dist/plugin/skills/_shared/post-merge-cleanup.md +1 -1
  19. package/dist/plugin/skills/_shared/pr-branch-worktree.md +1 -1
  20. package/dist/plugin/skills/_shared/rebase-before-e2e.md +7 -1
  21. package/dist/plugin/skills/_shared/resolve-rebase-conflicts.md +60 -0
  22. package/dist/plugin/skills/_shared/telemetry-events/muggle-do-cycle.md +8 -1
  23. package/dist/plugin/skills/_shared/telemetry-events/muggle-do-escalation.md +2 -1
  24. package/dist/plugin/skills/_shared/telemetry-events/pr-followup-tick.md +4 -0
  25. package/dist/plugin/skills/_shared/use-worktrees.md +2 -1
  26. package/dist/plugin/skills/do/address-reviews.md +6 -0
  27. package/dist/plugin/skills/do/cleanup.md +14 -0
  28. package/dist/plugin/skills/do/e2e-acceptance.md +5 -66
  29. package/dist/plugin/skills/do/fix-ci.md +60 -0
  30. package/dist/plugin/skills/do/input-routing.md +12 -0
  31. package/dist/plugin/skills/do/open-prs/forward.md +1 -1
  32. package/dist/plugin/skills/do/pre-flight.md +3 -3
  33. package/dist/plugin/skills/mbt/SKILL.md +8 -0
  34. package/dist/plugin/skills/mdo/SKILL.md +3 -3
  35. package/dist/plugin/skills/{muggle-do-task → muggle-browser-task}/SKILL.md +1 -1
  36. package/dist/plugin/skills/muggle-do/SKILL.md +3 -10
  37. package/dist/plugin/skills/muggle-pr-followup/CLAUDE.md +4 -5
  38. package/dist/plugin/skills/muggle-pr-followup/SKILL.md +4 -1
  39. package/dist/plugin/skills/muggle-pr-followup/auto-track.md +5 -1
  40. package/dist/plugin/skills/muggle-pr-followup/contract.md +33 -16
  41. package/dist/plugin/skills/muggle-pr-followup/finalize.md +29 -0
  42. package/dist/plugin/skills/muggle-pr-followup/reconcile.md +33 -0
  43. package/dist/plugin/skills/muggle-pr-followup/state-schemas.md +5 -1
  44. package/dist/plugin/skills/muggle-preferences/preference-gates/autoResolveConflicts.md +11 -0
  45. package/dist/plugin/skills/muggle-test/SKILL.md +14 -45
  46. package/dist/plugin/skills/muggle-test-feature-local/SKILL.md +5 -42
  47. package/dist/release-manifest.json +4 -4
  48. package/package.json +6 -6
  49. package/plugin/.claude-plugin/plugin.json +1 -1
  50. package/plugin/.cursor-plugin/plugin.json +1 -1
  51. package/plugin/agents/acceptance-tester.md +2 -0
  52. package/plugin/commands/mbt.md +7 -0
  53. package/plugin/commands/mdo.md +3 -3
  54. package/plugin/skills/CLAUDE.md +15 -0
  55. package/plugin/skills/_aliases.json +1 -0
  56. package/plugin/skills/_shared/ci-check-to-command.md +10 -0
  57. package/plugin/skills/_shared/dev-loop/action-script.md +3 -0
  58. package/plugin/skills/_shared/dev-loop/failures.md +14 -0
  59. package/plugin/skills/_shared/dev-loop/fresh-session.md +10 -0
  60. package/plugin/skills/_shared/dev-loop/publish.md +13 -0
  61. package/plugin/skills/_shared/dev-loop/run.md +34 -0
  62. package/plugin/skills/_shared/dev-loop/timeouts.md +6 -0
  63. package/plugin/skills/_shared/failure-mode-handling.md +2 -2
  64. package/plugin/skills/_shared/github-cli-recipes/pr-checks.md +22 -0
  65. package/plugin/skills/_shared/github-cli-recipes.md +1 -0
  66. package/plugin/skills/_shared/post-merge-cleanup.md +1 -1
  67. package/plugin/skills/_shared/pr-branch-worktree.md +1 -1
  68. package/plugin/skills/_shared/rebase-before-e2e.md +7 -1
  69. package/plugin/skills/_shared/resolve-rebase-conflicts.md +60 -0
  70. package/plugin/skills/_shared/telemetry-events/muggle-do-cycle.md +8 -1
  71. package/plugin/skills/_shared/telemetry-events/muggle-do-escalation.md +2 -1
  72. package/plugin/skills/_shared/telemetry-events/pr-followup-tick.md +4 -0
  73. package/plugin/skills/_shared/use-worktrees.md +2 -1
  74. package/plugin/skills/do/address-reviews.md +6 -0
  75. package/plugin/skills/do/cleanup.md +14 -0
  76. package/plugin/skills/do/e2e-acceptance.md +5 -66
  77. package/plugin/skills/do/fix-ci.md +60 -0
  78. package/plugin/skills/do/input-routing.md +12 -0
  79. package/plugin/skills/do/open-prs/forward.md +1 -1
  80. package/plugin/skills/do/pre-flight.md +3 -3
  81. package/plugin/skills/mbt/SKILL.md +8 -0
  82. package/plugin/skills/mdo/SKILL.md +3 -3
  83. package/plugin/skills/{muggle-do-task → muggle-browser-task}/SKILL.md +1 -1
  84. package/plugin/skills/muggle-do/SKILL.md +3 -10
  85. package/plugin/skills/muggle-pr-followup/CLAUDE.md +4 -5
  86. package/plugin/skills/muggle-pr-followup/SKILL.md +4 -1
  87. package/plugin/skills/muggle-pr-followup/auto-track.md +5 -1
  88. package/plugin/skills/muggle-pr-followup/contract.md +33 -16
  89. package/plugin/skills/muggle-pr-followup/finalize.md +29 -0
  90. package/plugin/skills/muggle-pr-followup/reconcile.md +33 -0
  91. package/plugin/skills/muggle-pr-followup/state-schemas.md +5 -1
  92. package/plugin/skills/muggle-preferences/preference-gates/autoResolveConflicts.md +11 -0
  93. package/plugin/skills/muggle-test/SKILL.md +14 -45
  94. package/plugin/skills/muggle-test-feature-local/SKILL.md +5 -42
@@ -71,7 +71,7 @@ If `prs.json` is empty, **do not dispatch** — record the reason in `result.md`
71
71
 
72
72
  ## Post-merge cleanup
73
73
 
74
- Gated by `autoCleanup`. Fires in a follow-up turn after merge — never from this stage. See [`../../_shared/post-merge-cleanup.md`](../../_shared/post-merge-cleanup.md).
74
+ Gated by `autoCleanup`. Triggered when the watcher's terminal tick observes the merge and dispatches `/muggle-do`'s cleanup directive ([`../cleanup.md`](../cleanup.md)) — never from this stage. See [`../../_shared/post-merge-cleanup.md`](../../_shared/post-merge-cleanup.md).
75
75
 
76
76
  Append one short reminder tied to the gate value:
77
77
 
@@ -26,8 +26,8 @@ Before asking anything, gather every fact you can resolve without the user:
26
26
 
27
27
  1. **Candidate repo(s).** Match keywords in the task description against configured repo names. If one repo is an obvious match, propose it as the default; if two or three are plausible, list them.
28
28
  2. **Current branch and default branch** for each candidate repo. Run `git -C <repo> symbolic-ref refs/remotes/origin/HEAD --short` and `git -C <repo> branch --show-current`. If the current branch is the default, the pre-flight must collect a new branch name.
29
- 3. **Running dev server.** Detect listening ports and reconcile env-file URL/port using [`../_shared/dev-server-readiness.md`](../_shared/dev-server-readiness.md).
30
- 4. **Running backend.** Probe backend health per [`../_shared/dev-server-readiness.md`](../_shared/dev-server-readiness.md) ("Backend health"). Note up/down.
29
+ 3. **Local environment readiness.** Invoke [`muggle-test-prepare`](../muggle-test-prepare/SKILL.md) — the owner of dev-server/backend detection and service start (idempotent; it probes via `dev-server-readiness.md` internally). Use what it reports as the dev-server/URL pre-flight signal.
30
+ 4. **Backend health.** Covered by the same `muggle-test-prepare` invocation above (it probes backend health); note up/down.
31
31
  5. **Muggle Test MCP auth.** Call `muggle-remote-auth-status`. If expired, you will ask to re-auth in the questionnaire.
32
32
  6. **Candidate Muggle Test projects.** Call `muggle-remote-project-list` and rank by semantic match against the task description and the repo's dev URL.
33
33
  7. **Existing test-user secrets.** For each candidate Muggle Test project, call `muggle-remote-secret-list` and note whether `managed_profile_email` / `managed_profile_password` exist.
@@ -55,7 +55,7 @@ Present **one `AskUserQuestion`** (or the platform's structured-selection equiva
55
55
  8. **Test-user credentials** — only if validation is Local E2E AND the Auth0 tenant in the repo differs from the tenant the managed secrets were created under. Options: "Reuse existing secrets (may fail if tenant mismatch — will surface failure)" / "Create new secrets for this tenant (provide email + password)" / "Switch to staging replay".
56
56
  9. **PR target branch** — default: the repo's default branch. "Use default" / "Target a different branch".
57
57
  10. **Re-auth Muggle Test MCP?** — only if auth was missing/expired. "Log in now" / "Abort".
58
- 11. **Worktree for this change?** — gate: [`autoUseWorktree`](../muggle-preferences/preference-gates/autoUseWorktree.md). Options: create a sibling worktree, or work in the current checkout.
58
+ 11. **Worktree for this change?** — gate: [`autoUseWorktree`](../muggle-preferences/preference-gates/autoUseWorktree.md). Options: create a dedicated worktree (per [`../_shared/use-worktrees.md`](../_shared/use-worktrees.md)), or work in the current checkout.
59
59
  12. **Rebase onto `origin/<default>` first?** — gate: [`autoRebase`](../muggle-preferences/preference-gates/autoRebase.md), only if `behind > 0`. Options: rebase before stage 6, or run as-is.
60
60
  13. **Run E2E at the end of every cycle?** — gate: [`autoE2ETest`](../muggle-preferences/preference-gates/autoE2ETest.md), only if step 10's silent detection resolved to `ask`. Options: always run stage 6, or ask each cycle.
61
61
 
@@ -0,0 +1,8 @@
1
+ ---
2
+ name: mbt
3
+ description: Explicit short alias for the `muggle-browser-task` skill. ONLY invoke when the user explicitly types `mbt` or `/mbt` — never auto-trigger from any other phrasing.
4
+ ---
5
+
6
+ # mbt — alias for muggle-browser-task
7
+
8
+ Invoke the `muggle-browser-task` skill via the Skill tool. Forward any user-provided arguments unchanged.
@@ -1,8 +1,8 @@
1
1
  ---
2
2
  name: mdo
3
- description: Explicit short alias for the `muggle-do-task` skill. ONLY invoke when the user explicitly types `mdo` or `/mdo` — never auto-trigger from any other phrasing.
3
+ description: Explicit short alias for the `muggle-do` skill. ONLY invoke when the user explicitly types `mdo` or `/mdo` — never auto-trigger from any other phrasing.
4
4
  ---
5
5
 
6
- # mdo — alias for muggle-do-task
6
+ # mdo — alias for muggle-do
7
7
 
8
- Invoke the `muggle-do-task` skill via the Skill tool. Forward any user-provided arguments unchanged.
8
+ Invoke the `muggle-do` skill via the Skill tool. Forward any user-provided arguments unchanged.
@@ -1,5 +1,5 @@
1
1
  ---
2
- name: muggle-do-task
2
+ name: muggle-browser-task
3
3
  description: Run a browser automation task on a website using natural language. Finds or creates the Muggle Test project, use case, test case, and script, then executes locally via the electron app. Use when the user wants to perform an action on a website (post, fill a form, click through a flow) rather than implement a code change.
4
4
  ---
5
5
 
@@ -1,7 +1,6 @@
1
1
  ---
2
2
  name: muggle-do
3
3
  description: Unified Muggle AI workflow entry point. Use when user types muggle do or asks for autonomous implementation to PR. Also handles the `address-reviews` directive (dispatched by the muggle-pr-followup watcher when new submitted reviews land on a PR).
4
- disable-model-invocation: true
5
4
  ---
6
5
 
7
6
  # Muggle Test Do
@@ -56,22 +55,16 @@ When invoked with the directive (PR URL + slug + review ids), routes to [`../do/
56
55
 
57
56
  ## Input routing
58
57
 
59
- Inspect `$ARGUMENTS` in this order:
60
-
61
- 1. **Address-reviews** — input contains a `github.com/.../pull/<n>` URL **and** one or more integers ≥ 100000000 (review id shape) → [`../do/address-reviews.md`](../do/address-reviews.md). Programmatic; never ask.
62
- 2. **Empty / `help` / `menu` / `?`** → menu + session selector.
63
- 3. **Task automation** (perform an action on a website) → `muggle:muggle-do-task`.
64
- 4. **Otherwise** → forward pipeline at Stage 1.
65
-
66
- When in doubt between #3 and #4, ask one question.
58
+ `/muggle-do` serves one interactive mode (the forward pipeline, from a fresh task) and three programmatic modes the watcher dispatches (address-reviews, fix-ci, post-merge cleanup). Resolve `$ARGUMENTS` to a mode per [`../do/input-routing.md`](../do/input-routing.md) before doing anything else.
67
59
 
68
60
  ## Preferences
69
61
 
70
62
  | Preference | Gate |
71
63
  | :--------- | :--- |
72
64
  | `autoE2ETest` | Stage 6 — run E2E every cycle (default `always`), or fold into pre-flight |
65
+ | `autoResolveConflicts` | On rebase conflict — resolve autonomously behind a verify-or-rollback gate (opt-in), or abort + escalate (default `never`) |
73
66
 
74
- `autoUseWorktree`, `autoRebase`, `autoCreatePR`, `autoCleanup` fire from per-stage files.
67
+ `autoUseWorktree`, `autoRebase`, `autoResolveConflicts`, `autoCreatePR`, `autoCleanup` fire from per-stage files.
75
68
 
76
69
  ## Session model
77
70
 
@@ -1,6 +1,6 @@
1
1
  # muggle-pr-followup — folder TOC
2
2
 
3
- This folder holds the watcher loop for PR review follow-ups. The watcher is a **dumb pipe**: it polls for new submitted reviews and dispatches `/muggle-do` when there are any. Cycle execution, classification, replies, and escalation all live in `/muggle-do`'s address-reviews mode — see [stage-8 design](../../../../muggle-ai-brain/architecture/2026-05-08-muggle-do-pr-comment-loop-design.md) for the architectural rationale.
3
+ This folder holds the watcher loop for PR review follow-ups. The watcher is a **dumb pipe**: it polls for new submitted reviews and CI checks and dispatches `/muggle-do` when there's review feedback or fixable red CI. Cycle execution, classification, replies, and escalation all live in `/muggle-do`'s address-reviews mode — see [stage-8 design](../../../../muggle-ai-brain/architecture/2026-05-08-muggle-do-pr-comment-loop-design.md) for the architectural rationale.
4
4
 
5
5
  ## Files in this folder
6
6
 
@@ -8,6 +8,8 @@ This folder holds the watcher loop for PR review follow-ups. The watcher is a **
8
8
  - [`auto-track.md`](auto-track.md) — the no-args procedure: discovers PRs pushed this session (any repo) and seeds one poll-only watcher each. Seeds no E2E context — the watcher only watches.
9
9
  - [`bootstrap.md`](bootstrap.md) — the bootstrap procedure (asks once for the E2E validation context, seeds state, dispatches the first watcher).
10
10
  - [`contract.md`](contract.md) — the watcher per-tick procedure (poll → dispatch → exit).
11
+ - [`finalize.md`](finalize.md) — shared termination sequence for a terminal PR (mark terminal, `result.md`, log/telemetry, unschedule cron, post-merge cleanup handoff). Called by `contract.md` and `reconcile.md`.
12
+ - [`reconcile.md`](reconcile.md) — sweep that finalizes slots whose PR went terminal while polling lapsed; runs at the top of auto-track and on demand.
11
13
  - [`state-schemas.md`](state-schemas.md) — canonical JSON shapes of session state files.
12
14
  - [`output-templates.md`](output-templates.md) — TOC of message templates; per-group files in `output-templates/`.
13
15
 
@@ -21,7 +23,4 @@ Shared with other skills, under `../_shared/`:
21
23
  - [`telemetry-events.md`](../_shared/telemetry-events.md) — TOC of canonical event shapes; per-event files in `_shared/telemetry-events/`.
22
24
  - [`github-cli-recipes.md`](../_shared/github-cli-recipes.md) — TOC of reusable `gh` / `git` snippets; per-recipe files in `_shared/github-cli-recipes/`.
23
25
 
24
- Caller-specific, under `../do/`:
25
-
26
- - [`open-prs.md`](../do/open-prs.md) — TOC for the create-or-update PR stage; per-mode files in `do/open-prs/`.
27
- - [`resolve-reminder.md`](../do/resolve-reminder.md) — `/muggle-do`'s per-round stage that nudges the reviewer to resolve addressed-but-still-open threads.
26
+ Callers (e.g. `/muggle-do`) reference this folder, not the reverse — see [`../CLAUDE.md`](../CLAUDE.md) for the one-way-dependency rule.
@@ -7,7 +7,7 @@ description: Use this skill when the user wants a pull request's incoming review
7
7
 
8
8
  > Telemetry first step: see [`../_shared/telemetry-emit.md`](../_shared/telemetry-emit.md). Use `skillName: "muggle-pr-followup"`.
9
9
 
10
- A watcher that babysits one open PR's review thread. Polls for new submitted reviews; when any land, hands them off to `/muggle-do` and exits. `/muggle-do` is the executor — it classifies the reviews, runs the work, pushes, replies per comment, and respawns the watcher.
10
+ A watcher that babysits one open PR's review thread and CI. Polls for new submitted reviews and check-run state; when review feedback lands or CI goes red, hands the work to `/muggle-do` and exits. On merge, it hands off post-merge cleanup to `/muggle-do` the same way. `/muggle-do` is the executor — it classifies the reviews or fixes the failing checks, pushes, replies per comment, and respawns the watcher.
11
11
 
12
12
  **The watcher is a dumb pipe.** It does not classify reviews, iterate cycles, post replies, or escalate. All of that lives in `/muggle-do`. See [stage-8 design](../../../../muggle-ai-brain/architecture/2026-05-08-muggle-do-pr-comment-loop-design.md) for the rationale.
13
13
 
@@ -26,6 +26,9 @@ The skill recognizes its mode by inspecting `$ARGUMENTS` and falling back to on-
26
26
  | `<pr-number>` alone | zero or multiple matches | **error:** ambiguous; list candidates and exit |
27
27
  | empty | — | **auto-track** → [`auto-track.md`](auto-track.md) |
28
28
  | `help` / `?` | — | **help:** list active loops per [`output-templates/help.md`](output-templates/help.md) |
29
+ | `reconcile` / `sweep` (optional `<slug>`) | — | **reconcile** → [`reconcile.md`](reconcile.md) |
30
+
31
+ Auto-track runs **reconcile** first, so a no-arg invocation also finalizes any slot whose PR merged or closed while its watcher was down (expired cron, ended session). Reconcile never re-arms a watcher.
29
32
 
30
33
  Bootstrap accepts three optional trailing flags:
31
34
 
@@ -2,7 +2,7 @@
2
2
 
3
3
  The procedure for the **auto-track mode** of `muggle-pr-followup` — invoked when the skill is dispatched with **no arguments**. Routing is in [`SKILL.md`](SKILL.md#routing).
4
4
 
5
- Auto-track discovers the PRs you pushed or opened during this Claude Code session — across **any repo** — and starts one **poll-only watcher** per PR. The watcher only watches: it seeds nothing about E2E. Running and posting E2E is `/muggle-do`'s job; a watcher with no validation context yields a `SKIPPED` E2E verdict when `/muggle-do` runs — see [`../do/e2e-acceptance.md`](../do/e2e-acceptance.md) Step 0.
5
+ Auto-track discovers the PRs you pushed or opened during this Claude Code session — across **any repo** — and starts one **poll-only watcher** per PR. The watcher only watches: it seeds nothing about E2E. Running and posting E2E is `/muggle-do`'s job; a watcher with no validation context yields a `SKIPPED` E2E verdict when `/muggle-do` runs.
6
6
 
7
7
  ## Turn preamble
8
8
 
@@ -16,6 +16,10 @@ Auto-track discovers the PRs you pushed or opened during this Claude Code sessio
16
16
 
17
17
  ## Procedure
18
18
 
19
+ ### Step 0 — Reconcile existing slots
20
+
21
+ Run [`reconcile.md`](reconcile.md) first. A no-arg invocation is the natural moment to finalize any slot whose PR merged or closed while its watcher was down — an expired `/loop` cron or an ended session leaves termination un-run (see reconcile's rationale). Then continue discovering new PRs below.
22
+
19
23
  ### Step 1 — Discover candidate PRs from session context
20
24
 
21
25
  A PR counts as **pushed this session** if, earlier in this conversation, you:
@@ -1,6 +1,6 @@
1
1
  # Watcher Per-Tick Contract
2
2
 
3
- The procedure for the **tick mode** of `muggle-pr-followup` — one polling iteration scoped to one PR. The watcher is a dumb pipe: it polls for new submitted reviews, dispatches `/muggle-do` if there are any, and exits. It does not classify, amend requirements, post replies, run cycles, or escalate.
3
+ The procedure for the **tick mode** of `muggle-pr-followup` — one polling iteration scoped to one PR. The watcher is a dumb pipe: it polls for new submitted reviews and CI checks, dispatches `/muggle-do` if there's review feedback or fixable red CI, and exits. It does not classify, fix, amend requirements, post replies, run cycles, or escalate.
4
4
 
5
5
  Routing into this mode is documented in [`SKILL.md`](SKILL.md#routing). The architectural rationale lives in the brain doc `architecture/2026-05-08-muggle-do-pr-comment-loop-design.md`.
6
6
 
@@ -33,25 +33,22 @@ Per [`../_shared/github-cli-recipes/pr-metadata.md`](../_shared/github-cli-recip
33
33
 
34
34
  If `state` is `MERGED` or `CLOSED`:
35
35
 
36
- 1. Mark the entry terminal in `prs.json`.
37
- 2. Write `result.md` per [`state-schemas.md`](state-schemas.md#resultmd).
38
- 3. Append a terminal line to `followup.log` per [`output-templates/watcher-log.md`](output-templates/watcher-log.md).
39
- 4. Emit a `tick` event with `terminal: true` per [`../_shared/telemetry-events/pr-followup-tick.md`](../_shared/telemetry-events/pr-followup-tick.md).
40
- 5. **Cancel the cron schedule that fires this watcher.** `/loop 1m ...` from bootstrap was registered via `CronCreate`; a fixed-interval cron keeps firing regardless of whether the skill re-dispatches. Call `CronList`, find any job whose command ends with `/muggle:muggle-pr-followup <slug> <pr-number>` (exact two-arg match), and `CronDelete` it. No-op if none matches — the tick may have been invoked manually rather than via `/loop`.
41
- 6. Exit. The watcher has now unscheduled itself; no future ticks will fire for this PR.
36
+ 1. Finalize the slot per [`finalize.md`](finalize.md) — mark terminal, write `result.md`, log + telemetry, unschedule this watcher's cron.
37
+ 2. **If `MERGED`**, hand off post-merge cleanup as the last action of the turn (skip on `CLOSED` — unmerged, leave the branch and any worktree intact):
42
38
 
43
- ### Step 3 — Fetch new submitted reviews
39
+ ```
40
+ /muggle-do post-merge cleanup slug=<slug>
41
+ ```
42
+
43
+ `/muggle-do` owns the worktree/branch knowledge and honors the `autoCleanup` gate. This is a runtime dispatch, not a doc dependency on `/muggle-do` — see the one-way rule in [`../CLAUDE.md`](../CLAUDE.md).
44
+ 3. Exit. The watcher has unscheduled itself; no future ticks fire for this PR.
44
45
 
45
- Per [`../_shared/github-cli-recipes/submitted-reviews.md`](../_shared/github-cli-recipes/submitted-reviews.md). **Also exclude review ids that appear in `last_seen.escalated_review_ids`** — those have already been escalated and the watcher must not re-dispatch them.
46
46
 
47
- ### Step 4 — If zero new reviews → idle
47
+ ### Step 3 — Fetch new submitted reviews
48
48
 
49
- 1. Increment `last_seen.idle_tick_count`.
50
- 2. Append an idle line to `followup.log` per [`output-templates/watcher-log.md`](output-templates/watcher-log.md).
51
- 3. Emit a `tick` event with `idle: true`, `reviews_seen: 0`, `dispatched_review_ids: []`.
52
- 4. Exit. The next tick fires in 1 min via `/loop`.
49
+ Per [`../_shared/github-cli-recipes/submitted-reviews.md`](../_shared/github-cli-recipes/submitted-reviews.md). **Also exclude review ids that appear in `last_seen.escalated_review_ids`** — those have already been escalated and the watcher must not re-dispatch them.
53
50
 
54
- ### Step 5 — If one or more new reviews → dispatch
51
+ ### Step 4 — If one or more new reviews → dispatch (reviews preempt CI)
55
52
 
56
53
  The watcher does **not** classify. Classification, batching, replying, escalation, and cycle execution all live in `/muggle-do`. The watcher's job is to hand over the list of new review ids and exit.
57
54
 
@@ -67,7 +64,27 @@ The watcher does **not** classify. Classification, batching, replying, escalatio
67
64
  ```
68
65
  3. Append a dispatching line to `followup.log` per [`output-templates/watcher-log.md`](output-templates/watcher-log.md).
69
66
  4. Emit a `tick` event with `reviews_seen: <count>`, `dispatched_review_ids: [<id>, ...]`.
70
- 5. Exit. The cron schedule from bootstrap keeps firing the watcher every minute, so the next tick still arrives even though this turn dispatched `/muggle-do`. The watcher only self-unschedules in Step 2 (terminal).
67
+ 5. Exit. **Reviews preempt CI** — when reviews land, this tick dispatches address-reviews and never polls CI. The cron keeps firing; the next tick still arrives. The watcher only self-unschedules in Step 2 (terminal).
68
+
69
+ ### Step 5 — No new reviews → poll CI for the head SHA
70
+
71
+ Fetch the check-run rollup for `prs.json[0].head_sha` per [`../_shared/github-cli-recipes/pr-checks.md`](../_shared/github-cli-recipes/pr-checks.md), then:
72
+
73
+ - **Any check still pending** (`bucket == "pending"`) → idle (wait for checks to settle).
74
+ - **All checks green / skipped, or no checks** → idle (green path).
75
+ - **One or more checks red** (`bucket == "fail"`), **and** `ci_fix_attempts[head_sha] < 3`, **and** `head_sha` ∉ `ci_escalated_shas` → dispatch and exit:
76
+ 1. Reset `last_seen.idle_tick_count` to 0.
77
+ 2. Dispatch `/muggle-do` with a *fix-ci* directive carrying the PR URL, slug, and the red check names (no review ids):
78
+ ```
79
+ /muggle-do fix ci <check-1> <check-2> ... on <pr-url> slug=<slug>
80
+ ```
81
+ 3. Append a dispatching line to `followup.log`; emit a `tick` event with `checks_red: <count>`, `dispatched_ci_fix: true`.
82
+ 4. Exit. The next tick re-checks CI on the new head SHA — CI itself is the verify loop.
83
+ - **One or more red, but `ci_fix_attempts[head_sha] >= 3` or `head_sha` ∈ `ci_escalated_shas`** → idle. The fix budget is spent; `/muggle-do`'s fix-ci stage already recorded the escalation. The watcher does not re-dispatch.
84
+
85
+ ### Step 6 — Idle
86
+
87
+ Any idle branch (Steps 4–5 that did not dispatch): increment `last_seen.idle_tick_count`, append an idle line to `followup.log` per [`output-templates/watcher-log.md`](output-templates/watcher-log.md), emit a `tick` event with `idle: true`, `reviews_seen: 0`, `dispatched_review_ids: []`, `checks_red: <count or 0>`, `dispatched_ci_fix: false`. Exit. The next tick fires in 1 min via `/loop`.
71
88
 
72
89
  ## Output
73
90
 
@@ -0,0 +1,29 @@
1
+ # Finalize a Terminal PR
2
+
3
+ The shared, **pure** termination sequence for a follow-up slot whose PR is `MERGED` or `CLOSED`. Called by [`contract.md`](contract.md) Step 2 (a tick observed the transition) and [`reconcile.md`](reconcile.md) (a sweep found a slot whose polling lapsed before the transition). One slot, run once.
4
+
5
+ This step only finalizes — marks the slot terminal, writes the record, unschedules the cron. It **dispatches nothing**. Post-merge cleanup is a separate, caller-owned concern: the tick ([`contract.md`](contract.md)) hands it off; a reconcile backfill skips it.
6
+
7
+ ## Inputs
8
+
9
+ - `<slug>`, `<owner>/<repo>`, `<n>` — the slot's PR.
10
+ - `state` — `MERGED` or `CLOSED`, from a fresh [`../_shared/github-cli-recipes/pr-metadata.md`](../_shared/github-cli-recipes/pr-metadata.md).
11
+ - `mergeCommit` + `mergedAt` when `MERGED`.
12
+
13
+ ## Procedure
14
+
15
+ ### Step 1 — Mark the slot terminal
16
+
17
+ Rewrite `prs.json[0].state` to `merged` / `closed` ([`state-schemas.md`](state-schemas.md#prsjson)). That state plus the `result.md` written next are the terminal marker — there is no separate flag.
18
+
19
+ ### Step 2 — Write `result.md`
20
+
21
+ Once, per [`state-schemas.md`](state-schemas.md#resultmd). Pull `cycles_completed`, `pushed_shas`, and `escalated_review_ids` from `last_seen.json`.
22
+
23
+ ### Step 3 — Log and telemetry
24
+
25
+ Append the terminal line per [`output-templates/watcher-log.md`](output-templates/watcher-log.md). Emit one `tick` event with `terminal: true` per [`../_shared/telemetry-events/pr-followup-tick.md`](../_shared/telemetry-events/pr-followup-tick.md).
26
+
27
+ ### Step 4 — Unschedule the cron
28
+
29
+ Call `CronList`, find any job whose command ends with `/muggle:muggle-pr-followup <slug> <n>` (exact two-arg match), and `CronDelete` it. No-op when none matches — a manually-run tick, or a cron that already expired. Recurring `/loop` crons auto-expire after 7 days; that lapse is the gap [`reconcile.md`](reconcile.md) exists to catch.
@@ -0,0 +1,33 @@
1
+ # Reconcile Procedure
2
+
3
+ The procedure for the **reconcile mode** of `muggle-pr-followup` — a sweep that finalizes session slots whose PR went terminal while polling was lapsed. Routing is in [`SKILL.md`](SKILL.md#routing).
4
+
5
+ Termination is otherwise tick-driven ([`contract.md`](contract.md) Step 2): a slot finalizes only when a tick fires and observes `MERGED` / `CLOSED`. If the tick stream stops first — the recurring `/loop` cron auto-expires after 7 days, the session ends, or the machine is off when the PR merges — no tick catches the transition, and the slot is left un-finalized: no `result.md`, no post-merge cleanup, and a surviving cron would keep polling a dead PR. Reconcile is the catch-up.
6
+
7
+ ## Input
8
+
9
+ `$ARGUMENTS` is `reconcile` (or `sweep`), optionally followed by a `<slug>` to scope the sweep to one slot.
10
+
11
+ ## Procedure
12
+
13
+ ### Step 1 — Enumerate slots
14
+
15
+ List `~/.muggle-ai/muggle-do/sessions/*/` dirs that contain a `prs.json`. Skip any that already have a `result.md` — those are finalized. Scope to a single `<slug>` if the arg gave one.
16
+
17
+ ### Step 2 — Refresh live state
18
+
19
+ For each candidate, fetch the PR per [`../_shared/github-cli-recipes/pr-metadata.md`](../_shared/github-cli-recipes/pr-metadata.md) using `prs.json[0].url`. A `gh` failure on one slot (deleted repo, missing auth) → log it to that slot's `followup.log` and skip; never abort the whole sweep.
20
+
21
+ ### Step 3 — Finalize the terminal ones
22
+
23
+ For each candidate whose live `state` is `MERGED` or `CLOSED`, run [`finalize.md`](finalize.md). `finalize.md` dispatches nothing, so a backfilled merge gets no post-merge cleanup — its branch is typically long gone, and the `autoCleanup` gate governs if the user runs cleanup later. Slots still `open` are left untouched — reconcile finalizes, it does not re-arm a watcher (re-arming an open PR is [`auto-track.md`](auto-track.md)'s job).
24
+
25
+ ### Step 4 — Report
26
+
27
+ One line: slots scanned, finalized (with final state each), and left open. Silent only when zero slots exist.
28
+
29
+ ## Invariants
30
+
31
+ - **Idempotent.** A slot with `result.md` is never re-finalized; once everything terminal is swept, re-running is a no-op.
32
+ - **Finalize-only.** Reconcile never seeds, re-arms, or dispatches a watcher. Open slots pass through untouched.
33
+ - **Per-slot isolation.** One slot's `gh` failure never blocks finalizing the others.
@@ -39,7 +39,9 @@ Keyed by `"<owner>/<repo>#<n>"`. One key per PR in the slot.
39
39
  "idle_tick_count": <int>,
40
40
  "cycles_completed": <int>,
41
41
  "escalated_review_ids": [<int>, ...],
42
- "pushed_shas": ["<sha>", ...]
42
+ "pushed_shas": ["<sha>", ...],
43
+ "ci_fix_attempts": { "<sha>": <int> },
44
+ "ci_escalated_shas": ["<sha>", ...]
43
45
  }
44
46
  }
45
47
  ```
@@ -50,6 +52,8 @@ Keyed by `"<owner>/<repo>#<n>"`. One key per PR in the slot.
50
52
  - `cycles_completed`: incremented each time `/muggle-do` completes an address-reviews invocation (regardless of actionable/ambiguous/mixed).
51
53
  - `escalated_review_ids`: review ids classified as ambiguous by `/muggle-do`. The watcher excludes these from future review fetches so the same ambiguous review is never re-dispatched.
52
54
  - `pushed_shas`: every SHA `/muggle-do` has pushed for this PR. Append-only. Used by the resolve-reminder stage to recognize threads addressed by the loop.
55
+ - `ci_fix_attempts`: per-SHA count of fix-ci cycles `/muggle-do` has run. The watcher stops dispatching fix-ci for a SHA once its count reaches 3. Keyed by head SHA.
56
+ - `ci_escalated_shas`: head SHAs whose CI the fix-ci stage gave up on (attempts exhausted or only out-of-scope checks). The watcher excludes these from CI dispatch so a hopeless SHA is never re-fixed.
53
57
 
54
58
  ## `state.md`
55
59
 
@@ -0,0 +1,11 @@
1
+ # `autoResolveConflicts`
2
+
3
+ When a rebase onto `origin/{default}` hits conflicts, resolve them autonomously behind a verify-or-rollback gate, or stop and escalate. Default `never` — the loop aborts the rebase and escalates exactly as before. Opt in with `always` to resolve conflicts without a human.
4
+
5
+ **Picker 1** — header `Resolve rebase conflicts?`, question `"Rebase onto origin/{default} hit conflicts in {conflicted} file(s) — resolve them autonomously?"`
6
+ - `Resolve autonomously` — `Resolve the conflicts, then re-verify (build + unit + E2E) before any push; roll back and escalate if verification fails.` → `always`
7
+ - `Stop and escalate` — `Abort the rebase, restore the branch, and hand the conflict to me.` → `never`
8
+
9
+ **Silent action**
10
+ - `always` → `Resolving rebase conflicts autonomously (verify-or-rollback)`
11
+ - `never` → `Aborting rebase and escalating — conflicts in {conflicted} file(s)`
@@ -235,6 +235,10 @@ If the user picks "Override one or more", let them flip the mode for any test ca
235
235
 
236
236
  ## Step 7A: Execute — Local Mode
237
237
 
238
+ ### Local environment readiness
239
+
240
+ Before anything else, invoke [`muggle-test-prepare`](../muggle-test-prepare/SKILL.md) — the readiness/service-start owner (idempotent; halt on what it surfaces). The URL gate below only *selects* the target; prepare is what guarantees something is listening and compiled.
241
+
238
242
  ### Pre-flight question — Local URL (gated by `autoSelectLocalHost`)
239
243
 
240
244
  Skill responsibilities (the rest is in `preference-gates/autoSelectLocalHost.md`):
@@ -255,45 +259,18 @@ Gate `showElectronBrowser` (per `preference-gates/README.md`). Resolve once; app
255
259
 
256
260
  Before execution, fetch full test case details for all selected test cases by issuing **all** `muggle-remote-test-case-get` calls in parallel (single message, multiple tool calls).
257
261
 
258
- ### Determine `freshSession` per test case
259
-
260
- Before executing each test case, inspect its content (title, goal, instructions, preconditions) for signals that it requires a **clean browser state** — no prior cookies, localStorage, or logged-in session. Set `freshSession: true` when the test case involves any of:
261
-
262
- - **Registration / sign-up** — creating a new account
263
- - **Login / authentication** — verifying the login flow itself (not a test that merely *uses* login as a prerequisite)
264
- - **Cookie consent / GDPR banners** — verifying first-visit consent prompts
265
- - **Onboarding flows** — first-time user experiences that only appear on a fresh session
266
-
267
- If none of the above apply, omit `freshSession` (defaults to `false`, preserving any existing session state). Evaluate this per test case — in a batch, some may need it and others may not.
268
-
269
- ### Run sequentially (Electron constraint)
262
+ ### Run the dev loop
270
263
 
271
- Execution itself **must** be sequential because there is only one local Electron browser. For each test case, in the order chosen, branch on the mode picked in Step 6f:
264
+ Execute each selected test case via the shared loop in [`../_shared/dev-loop/run.md`](../_shared/dev-loop/run.md): [sequential replay/regen](../_shared/dev-loop/run.md), [`actionScript` as-is](../_shared/dev-loop/action-script.md), [`freshSession`](../_shared/dev-loop/fresh-session.md), and [`timeoutMs`](../_shared/dev-loop/timeouts.md).
272
265
 
273
- **Regen-mode test case:**
274
- 1. Call `muggle-local-execute-test-generation`:
275
- - `testCase`: Full test case object from the parallel fetch above
276
- - `localUrl`: User's local URL from the pre-flight question
277
- - `cwd`: Absolute path of the active working directory — the PR-branch worktree if one was created in Step 2, otherwise the user's repo root. Drives the cross-worktree single-flight lock so concurrent muggle-test runs from different branches serialize.
278
- - `showUi`: from the `showElectronBrowser` resolution — omit (default visible) for `always`, pass `false` for `never`
279
- - `freshSession`: `true` if the test case requires a clean browser state (see above), omit otherwise
280
- 2. Store the returned `runId` and tag the result `mode: "regen"`.
266
+ Caller glue:
267
+ - `mode` per test case comes from Step 6f; `localUrl` from the pre-flight question; `showUi` from the `showElectronBrowser` resolution.
268
+ - `cwd` = the PR-branch worktree from Step 2 if one was created, else the user's repo root — it drives the cross-worktree single-flight lock so concurrent muggle-test runs from different branches serialize.
269
+ - On a failed run, continue the batch and route it through Step 7C after completion.
281
270
 
282
- **Replay-mode test case:**
283
- 1. Fetch the action script: `muggle-remote-test-script-get` (latest replayable script id) → `muggle-remote-action-script-get` (full `actionScript` — use as-is, never edit). For batches, fan these calls out in parallel before the sequential execution loop begins.
284
- 2. Call `muggle-local-execute-replay`:
285
- - `testScript`: from `muggle-remote-test-script-get`
286
- - `actionScript`: from `muggle-remote-action-script-get`
287
- - `localUrl`, `cwd`, `showUi`, `freshSession`: same resolution as regen
288
- 3. Store the returned `runId` and tag the result `mode: "replay"`.
271
+ ### Collect results
289
272
 
290
- If a run fails, log it and continue to the next — do not abort the batch. Failures are routed through Step 7C's post-failure handler after the batch completes.
291
-
292
- ### Collect results (in parallel)
293
-
294
- For every `runId`, issue all `muggle-local-run-result-get` calls in parallel. Extract from the **structured response only** (not from `execute`'s stdout tail, which is a truncated display excerpt): `Status`, `Error`, `Duration`, and the `Artifacts` section (always present after a run completes — names `artifactsDir` and lists the files actually on disk).
295
-
296
- For passed runs, `results.md` inside `artifactsDir` is the step-by-step verdict — read it before summarizing. For failed runs, `stdout.log` + `stderr.log` are always present and `action-script.json` is present when generation reached the step-emission stage (typical for `goal_not_achievable`); use `Error` as the headline verdict and route through Step 7C.
273
+ Fetch every `runId` per [`../_shared/dev-loop/failures.md`](../_shared/dev-loop/failures.md), reading structured fields and [interpreting failures](../_shared/dev-loop/failures.md) — never `execute`'s stdout tail. Issue the `muggle-local-run-result-get` calls in parallel; use `Error` as the headline for failures and route through Step 7C.
297
274
 
298
275
  ### Publish each run to cloud (gated by `autoPublishLocalResults`)
299
276
 
@@ -304,15 +281,7 @@ Gate `autoPublishLocalResults` (per `preference-gates/README.md`):
304
281
 
305
282
  ### Publish logic (when publishing is enabled)
306
283
 
307
- For every completed run, issue all `muggle-local-publish-test-script` calls in parallel (single message, multiple tool calls):
308
- - `runId`: The local run ID
309
- - `cloudTestCaseId`: The cloud test case ID
310
-
311
- This returns:
312
- - `viewUrl`: Direct link to view this test run on the Muggle AI dashboard
313
- - `testScriptId`, `actionScriptId`, `workflowRuntimeId`
314
-
315
- Store every `viewUrl` — these are used in the next steps.
284
+ Publish every completed run per [`../_shared/dev-loop/publish.md`](../_shared/dev-loop/publish.md) — parallel `muggle-local-publish-test-script` with the zero-step `muggle-remote-local-run-upload` fallback. Store every `viewUrl`, `testScriptId`, `actionScriptId` — used in the next steps.
316
285
 
317
286
  ### Report summary
318
287
 
@@ -475,7 +444,7 @@ This is a suggestion, not automatic invocation. Skip silently if every test pass
475
444
  ## Guardrails
476
445
 
477
446
  - **Always confirm intent first** — never assume local vs remote without asking
478
- - **PR URLs always run in a dedicated worktree** — never switch the user's main checkout. Create or reuse `<repo>/.claude/worktrees/<sanitized-branch>` and pass that path as the `cwd` parameter to local execute tools. The cross-worktree single-flight lock relies on this to serialize concurrent runs from different branches.
447
+ - **PR URLs always run in a dedicated worktree** — never switch the user's main checkout. Materialize per [`_shared/pr-branch-worktree.md`](../_shared/pr-branch-worktree.md) and pass that path as `cwd` to local execute tools; the cross-worktree single-flight lock relies on it to serialize concurrent runs from different branches.
479
448
  - **User MUST select project** — present clickable options via `AskUserQuestion`, wait for explicit choice, never auto-select
480
449
  - **Best-effort shortlist use cases** — use the change summary to narrow the list to the most relevant 1–5 use cases and pre-check them; never dump every use case in the project on the user. Always leave an escape hatch to reveal the full list.
481
450
  - **Best-effort shortlist test cases** — same idea: pre-check the test cases most relevant to the change summary; never enumerate every test case attached to a use case. Always leave an escape hatch to reveal the full list.
@@ -143,41 +143,9 @@ Before deciding the target's script, resolve its prerequisite chain from the bac
143
143
 
144
144
  ### 6. Load data for the chosen path
145
145
 
146
- **Determine `freshSession`**
146
+ Run the shared loop in [`../_shared/dev-loop/run.md`](../_shared/dev-loop/run.md): [`freshSession`](../_shared/dev-loop/fresh-session.md), [replay vs regen](../_shared/dev-loop/run.md), [`actionScript` as-is](../_shared/dev-loop/action-script.md), [`timeoutMs`](../_shared/dev-loop/timeouts.md), and [failure interpretation](../_shared/dev-loop/failures.md).
147
147
 
148
- Before calling either execution tool, inspect the test case content (title, goal, instructions, preconditions) for signals that the test requires a **clean browser state** — no prior cookies, localStorage, or logged-in session. Pass `freshSession: true` when the test case involves any of:
149
-
150
- - **Registration / sign-up** — creating a new account
151
- - **Login / authentication** — verifying the login flow itself (not a test that merely *uses* login as a prerequisite)
152
- - **Cookie consent / GDPR banners** — verifying first-visit consent prompts
153
- - **Onboarding flows** — first-time user experiences that only appear on a fresh session
154
-
155
- If none of the above apply, omit `freshSession` (defaults to `false`, preserving any existing session state).
156
-
157
- **Generate**
158
-
159
- 1. `muggle-remote-test-case-get`
160
- 2. `muggle-local-execute-test-generation` with that test case + `localUrl` (optional: `showUi: false` for headless — defaults to visible; **`freshSession`** — see above; **`timeoutMs`** — see below)
161
-
162
- **Replay**
163
-
164
- 1. `muggle-remote-test-script-get` — note `actionScriptId`
165
- 2. `muggle-remote-action-script-get` with that id — full `actionScript`
166
- **Use the API response as-is.** Do not edit, shorten, or rebuild `actionScript`; replay needs full `label` paths for element lookup.
167
- 3. `muggle-local-execute-replay` with `testScript`, `actionScript`, `localUrl` (optional: `showUi: false` for headless — defaults to visible; **`freshSession`** — see above; **`timeoutMs`** — see below)
168
-
169
- ### Local execution timeout (`timeoutMs`)
170
-
171
- The MCP client often uses a **default wait of 300000 ms (5 minutes)** for `muggle-local-execute-test-generation` and `muggle-local-execute-replay`. **Exploratory script generation** (Auth0 login, dashboards, multi-step wizards, many LLM iterations) routinely **runs longer than 5 minutes** while Electron is still healthy.
172
-
173
- - **Always pass `timeoutMs`** for flows that may be long — for example **`600000` (10 min)** or **`900000` (15 min)** — unless the user explicitly wants a short cap.
174
- - If the tool reports **`Electron execution timed out after 300000ms`** (or similar) **but** Electron logs show the run still progressing (steps, screenshots, LLM calls), treat it as **orchestration timeout**, not an Electron app defect: **increase `timeoutMs` and retry**.
175
- - **Test case design:** Preconditions like "a test run has already completed" on an **empty account** can force many steps (sign-up, new project, crawl). Prefer an account/project that **already has** the needed state, or narrow the test goal so generation does not try to create a full project from scratch unless that is intentional.
176
-
177
- ### Interpreting `failed` / non-zero Electron exit
178
-
179
- - **`Electron execution timed out after 300000ms`:** Orchestration wait too short — see **`timeoutMs`** above.
180
- - **Exit code 26** (and messages like **LLM failed to generate / replay action script**): Often corresponds to a completed exploration whose **outcome was goal not achievable** (`goal_not_achievable`, summary with `halt`) — e.g. verifying "view script after a successful run" when **no run or script exists yet** in the UI. Use `muggle-local-run-result-get` and read the **summary / structured summary**; do not assume an Electron crash. **Fix:** choose a **project that already has** completed runs and scripts, or **change the test case** so preconditions match what localhost can satisfy (e.g. include steps to create and run a test first, or assert only empty-state UI when no runs exist).
148
+ Caller glue: `mode` is the path chosen in §5; `localUrl` from §4; `cwd` = the repo root, or the prepared worktree when one is in use.
181
149
 
182
150
  ### 7. Execute (no approval prompt; `showUi` gated by `showElectronBrowser`)
183
151
 
@@ -192,21 +160,16 @@ Gate `showElectronBrowser` (per `preference-gates/README.md`). Reuse choice with
192
160
 
193
161
  Upload pass-or-fail. Failed runs still need cloud-hosted screenshots and per-step actions for the PR walkthrough — without them reviewers see only a generic "failed" link. The `status` field in the upload payload tells the backend whether to promote the run's action script as the test case's canonical replay script (passed → promote; failed → record only).
194
162
 
195
- - `muggle-local-publish-test-script`
163
+ - Publish per [`../_shared/dev-loop/publish.md`](../_shared/dev-loop/publish.md) — includes the zero-step `muggle-remote-local-run-upload` fallback.
196
164
  - Gate `openTestResultsAfterRun` (per `preference-gates/README.md`):
197
165
  - `always` → open `viewUrl` automatically (`open "<viewUrl>"` on macOS or OS equivalent).
198
166
  - `never` → print the URL only.
199
167
  - `ask` → run Picker 1 from `preference-gates/openTestResultsAfterRun.md` via `AskUserQuestion`; map the answer back to one of the actions above.
200
168
 
201
- If publish rejects with `has no generated actionScript steps to publish` (true zero-step runs — Electron never produced an action), fall back to `muggle-remote-local-run-upload` directly with whatever data exists (`summaryStep`, `errorMessage`, empty `actionScript`). This still gets the failure summary and any goal-not-achievable verdict onto the dashboard so reviewers can see why the run failed. Capture the returned `actionScriptId` and `viewUrl` from this fallback path the same way you would from publish.
202
-
203
169
  ### 9. Report
204
170
 
205
- **Do not diagnose from `execute`'s response stdout tail.** That tail is a truncated excerpt for human display and routinely cuts off mid-sentence. The only ground truth is the run record.
171
+ Read the run record per [`../_shared/dev-loop/failures.md`](../_shared/dev-loop/failures.md) and [failure interpretation](../_shared/dev-loop/failures.md) — never diagnose from `execute`'s stdout tail.
206
172
 
207
- - `muggle-local-run-result-get` with the run id from execute.
208
- - **Read in this order:** `Status` → `Error` → **`Artifacts` section** (always present after a run completes; names `artifactsDir` and lists the files actually on disk: `action-script.json`, `results.md`, `screenshots/`, `stdout.log`, `stderr.log`). On a `passed` run, `results.md` is the step-by-step verdict with screenshot links — read it before summarizing.
209
- - **On failure**, the `Artifacts` section is still present. `stdout.log` + `stderr.log` are always there. `action-script.json` is there when generation got far enough to emit it (typical for `goal_not_achievable` / mid-progress crashes — the file holds the agent's attempted steps + halt summary). `results.md` and per-step screenshots are absent on failure (electron-app only emits those on the successful completion path) — don't hunt elsewhere on disk for them.
210
173
  - 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.
211
174
 
212
175
  ### 9a. Route failures through the failure-mode handler
@@ -270,7 +233,7 @@ The `/mprfollowup` shortcut starts the same watcher manually at any time.
270
233
  - If replayable scripts exist, do not default to generation without user choice.
271
234
  - No hiding failures: surface errors and artifact paths.
272
235
  - **Always offer the agent-guidance reminder after every Electron run** (Step 9b) — pass or fail — unless 9a already routed the user into `muggle-feedback`. Never silently end a run without giving the user a one-click path to flag what was wrong.
273
- - Replay: never hand-built or simplified `actionScript` — only from `muggle-remote-action-script-get`.
236
+ - Replay/timeout discipline per [`../_shared/dev-loop/run.md`](../_shared/dev-loop/run.md) — never hand-build `actionScript`; always pass `timeoutMs`.
274
237
  - Use `AskUserQuestion` for every selection — project, use case, test case, script. Never ask the user to type a number.
275
238
  - Project, use case, and test case selection lists must always include "Create new ...". Include "Show full list" whenever the API returned at least one row for that step; omit "Show full list" when the list is empty (offer "Create new ..." only). For creates, use preview tools (`muggle-remote-use-case-prompt-preview`, `muggle-remote-test-case-generate-from-prompt`) before persisting.
276
239
  - PR posting is always optional and always delegated to the `muggle:muggle-pr-visual-walkthrough` skill — never inline the walkthrough markdown or call `gh pr comment` directly from this skill.
@@ -1,7 +1,7 @@
1
1
  {
2
- "release": "4.14.0",
3
- "buildId": "run-45-1",
4
- "commitSha": "47f4274095fc578a67e19811afc335a1b8e0c0b4",
5
- "buildTime": "2026-05-29T22:27:05Z",
2
+ "release": "4.15.1",
3
+ "buildId": "run-47-1",
4
+ "commitSha": "4bac13c8822d5c6b6989a3d800dc983f63556ab1",
5
+ "buildTime": "2026-06-02T22:17:47Z",
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": "4.14.0",
4
+ "version": "4.15.1",
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.0.107",
44
+ "electronAppVersion": "1.0.109",
45
45
  "downloadBaseUrl": "https://github.com/multiplex-ai/muggle-ai-works/releases/download",
46
46
  "runtimeTargetDefault": "production",
47
47
  "checksums": {
48
- "darwin-arm64": "d10a2d49f4300123c2e6fefe3ad9d85b17b079d97b6326f8ea80547c2e8bf735",
49
- "darwin-x64": "5466d9fc9ef280c85a723cb4288fceffa1869e1b1d84156773a6366e85443952",
50
- "linux-x64": "24d7ebb5bdb56345644e24180008226b49fdb1b0a605c455ba45950df58faa5e",
51
- "win32-x64": "62498ddb31336285dafb1320f1e43199dac7ada2bdd57223cb9eb4f4ac03e5a7"
48
+ "darwin-arm64": "9c2fa21b4e090c8b6f1acedf1bdbd824f0032a5d91d6f9abd3ca25cebee7f417",
49
+ "darwin-x64": "3369988c627be5d362d5d9c8312f9902063a98a53d308695b40873211960501c",
50
+ "linux-x64": "a986757132b45a4299a44c3dd1f3945ba6814d299e677380e2061f18da44b511",
51
+ "win32-x64": "29ab5400d7dca049e4a3e75b76bc3e06398b88743f0a49d38fa6ae531fc980fe"
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": "4.14.0",
4
+ "version": "4.15.1",
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": "4.14.0",
5
+ "version": "4.15.1",
6
6
  "author": {
7
7
  "name": "Muggle AI",
8
8
  "email": "support@muggle-ai.com"
@@ -22,6 +22,8 @@ You operate through skills — never call raw MCP tools directly.
22
22
 
23
23
  Select the skill based on what the orchestrator asks you to do. If the task doesn't clearly map to one skill, ask for clarification.
24
24
 
25
+ The run loop these skills execute (replay/regen, timeouts, publish, screenshots) lives in [`../skills/_shared/dev-loop/run.md`](../skills/_shared/dev-loop/run.md) — you reach it through `muggle-test`, never by calling MCP tools yourself.
26
+
25
27
  ## Input Contract
26
28
 
27
29
  The orchestrator provides a dispatch prompt with: