@muggleai/works 4.13.1 → 4.15.0

This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
Files changed (137) hide show
  1. package/README.md +3 -3
  2. package/dist/plugin/.claude-plugin/plugin.json +1 -1
  3. package/dist/plugin/.cursor-plugin/plugin.json +1 -1
  4. package/dist/plugin/README.md +1 -1
  5. package/dist/plugin/agents/acceptance-tester.md +2 -0
  6. package/dist/plugin/commands/mbt.md +7 -0
  7. package/dist/plugin/commands/mdo.md +3 -3
  8. package/dist/plugin/commands/mprfollowup.md +7 -0
  9. package/dist/plugin/skills/CLAUDE.md +15 -0
  10. package/dist/plugin/skills/_aliases.json +2 -1
  11. package/dist/plugin/skills/_shared/ci-check-to-command.md +10 -0
  12. package/dist/plugin/skills/_shared/dev-loop/action-script.md +3 -0
  13. package/dist/plugin/skills/_shared/dev-loop/failures.md +14 -0
  14. package/dist/plugin/skills/_shared/dev-loop/fresh-session.md +10 -0
  15. package/dist/plugin/skills/_shared/dev-loop/publish.md +13 -0
  16. package/dist/plugin/skills/_shared/dev-loop/run.md +34 -0
  17. package/dist/plugin/skills/_shared/dev-loop/timeouts.md +6 -0
  18. package/dist/plugin/skills/_shared/failure-mode-handling.md +2 -2
  19. package/dist/plugin/skills/_shared/github-cli-recipes/pr-checks.md +22 -0
  20. package/dist/plugin/skills/_shared/github-cli-recipes.md +1 -0
  21. package/dist/plugin/skills/_shared/post-merge-cleanup.md +1 -1
  22. package/dist/plugin/skills/_shared/pr-branch-worktree.md +1 -1
  23. package/dist/plugin/skills/_shared/rebase-before-e2e.md +7 -1
  24. package/dist/plugin/skills/_shared/resolve-e2e-validation-context.md +1 -1
  25. package/dist/plugin/skills/_shared/resolve-rebase-conflicts.md +60 -0
  26. package/dist/plugin/skills/_shared/telemetry-events/muggle-do-cycle.md +8 -1
  27. package/dist/plugin/skills/_shared/telemetry-events/muggle-do-escalation.md +2 -1
  28. package/dist/plugin/skills/_shared/telemetry-events/pr-followup-tick.md +4 -0
  29. package/dist/plugin/skills/_shared/use-worktrees.md +2 -1
  30. package/dist/plugin/skills/do/address-reviews.md +7 -1
  31. package/dist/plugin/skills/do/build.md +2 -1
  32. package/dist/plugin/skills/do/cleanup.md +14 -0
  33. package/dist/plugin/skills/do/e2e-acceptance.md +5 -66
  34. package/dist/plugin/skills/do/fix-ci.md +60 -0
  35. package/dist/plugin/skills/do/input-routing.md +12 -0
  36. package/dist/plugin/skills/do/open-prs/forward.md +3 -3
  37. package/dist/plugin/skills/do/open-prs/update.md +1 -1
  38. package/dist/plugin/skills/do/pre-flight.md +3 -3
  39. package/dist/plugin/skills/mbt/SKILL.md +8 -0
  40. package/dist/plugin/skills/mdo/SKILL.md +3 -3
  41. package/dist/plugin/skills/mprfollowup/SKILL.md +8 -0
  42. package/dist/plugin/skills/muggle/SKILL.md +1 -0
  43. package/{plugin/skills/muggle-do-task → dist/plugin/skills/muggle-browser-task}/SKILL.md +1 -1
  44. package/dist/plugin/skills/muggle-do/SKILL.md +29 -10
  45. package/dist/plugin/skills/muggle-feedback/SKILL.md +1 -1
  46. package/dist/plugin/skills/muggle-pr-followup/CLAUDE.md +4 -5
  47. package/dist/plugin/skills/muggle-pr-followup/SKILL.md +5 -3
  48. package/dist/plugin/skills/muggle-pr-followup/auto-track.md +5 -1
  49. package/dist/plugin/skills/muggle-pr-followup/bootstrap.md +5 -3
  50. package/dist/plugin/skills/muggle-pr-followup/contract.md +34 -17
  51. package/dist/plugin/skills/muggle-pr-followup/finalize.md +29 -0
  52. package/dist/plugin/skills/muggle-pr-followup/reconcile.md +33 -0
  53. package/dist/plugin/skills/muggle-pr-followup/state-schemas.md +10 -2
  54. package/dist/plugin/skills/muggle-preferences/ops/configure.md +2 -1
  55. package/dist/plugin/skills/muggle-preferences/preference-gates/autoResolveConflicts.md +11 -0
  56. package/dist/plugin/skills/muggle-preferences/preference-gates/autoWatchPR.md +13 -0
  57. package/dist/plugin/skills/muggle-preferences/preference-gates/reusePreparePlan.md +11 -0
  58. package/dist/plugin/skills/muggle-status/SKILL.md +1 -1
  59. package/dist/plugin/skills/muggle-test/SKILL.md +30 -48
  60. package/dist/plugin/skills/muggle-test-feature-local/SKILL.md +20 -44
  61. package/dist/plugin/skills/muggle-test-prepare/SKILL.md +5 -1
  62. package/dist/plugin/skills/muggle-test-prepare/steps/check-running.md +7 -5
  63. package/dist/plugin/skills/muggle-test-prepare/steps/identify-services.md +2 -0
  64. package/dist/plugin/skills/muggle-test-prepare/steps/readiness-report.md +30 -0
  65. package/dist/plugin/skills/muggle-test-prepare/steps/reuse-plan.md +44 -0
  66. package/dist/release-manifest.json +4 -4
  67. package/package.json +7 -6
  68. package/plugin/.claude-plugin/plugin.json +1 -1
  69. package/plugin/.cursor-plugin/plugin.json +1 -1
  70. package/plugin/README.md +1 -1
  71. package/plugin/agents/acceptance-tester.md +2 -0
  72. package/plugin/commands/mbt.md +7 -0
  73. package/plugin/commands/mdo.md +3 -3
  74. package/plugin/commands/mprfollowup.md +7 -0
  75. package/plugin/skills/CLAUDE.md +15 -0
  76. package/plugin/skills/_aliases.json +2 -1
  77. package/plugin/skills/_shared/ci-check-to-command.md +10 -0
  78. package/plugin/skills/_shared/dev-loop/action-script.md +3 -0
  79. package/plugin/skills/_shared/dev-loop/failures.md +14 -0
  80. package/plugin/skills/_shared/dev-loop/fresh-session.md +10 -0
  81. package/plugin/skills/_shared/dev-loop/publish.md +13 -0
  82. package/plugin/skills/_shared/dev-loop/run.md +34 -0
  83. package/plugin/skills/_shared/dev-loop/timeouts.md +6 -0
  84. package/plugin/skills/_shared/failure-mode-handling.md +2 -2
  85. package/plugin/skills/_shared/github-cli-recipes/pr-checks.md +22 -0
  86. package/plugin/skills/_shared/github-cli-recipes.md +1 -0
  87. package/plugin/skills/_shared/post-merge-cleanup.md +1 -1
  88. package/plugin/skills/_shared/pr-branch-worktree.md +1 -1
  89. package/plugin/skills/_shared/rebase-before-e2e.md +7 -1
  90. package/plugin/skills/_shared/resolve-e2e-validation-context.md +1 -1
  91. package/plugin/skills/_shared/resolve-rebase-conflicts.md +60 -0
  92. package/plugin/skills/_shared/telemetry-events/muggle-do-cycle.md +8 -1
  93. package/plugin/skills/_shared/telemetry-events/muggle-do-escalation.md +2 -1
  94. package/plugin/skills/_shared/telemetry-events/pr-followup-tick.md +4 -0
  95. package/plugin/skills/_shared/use-worktrees.md +2 -1
  96. package/plugin/skills/do/address-reviews.md +7 -1
  97. package/plugin/skills/do/build.md +2 -1
  98. package/plugin/skills/do/cleanup.md +14 -0
  99. package/plugin/skills/do/e2e-acceptance.md +5 -66
  100. package/plugin/skills/do/fix-ci.md +60 -0
  101. package/plugin/skills/do/input-routing.md +12 -0
  102. package/plugin/skills/do/open-prs/forward.md +3 -3
  103. package/plugin/skills/do/open-prs/update.md +1 -1
  104. package/plugin/skills/do/pre-flight.md +3 -3
  105. package/plugin/skills/mbt/SKILL.md +8 -0
  106. package/plugin/skills/mdo/SKILL.md +3 -3
  107. package/plugin/skills/mprfollowup/SKILL.md +8 -0
  108. package/plugin/skills/muggle/SKILL.md +1 -0
  109. package/{dist/plugin/skills/muggle-do-task → plugin/skills/muggle-browser-task}/SKILL.md +1 -1
  110. package/plugin/skills/muggle-do/SKILL.md +29 -10
  111. package/plugin/skills/muggle-feedback/SKILL.md +1 -1
  112. package/plugin/skills/muggle-pr-followup/CLAUDE.md +4 -5
  113. package/plugin/skills/muggle-pr-followup/SKILL.md +5 -3
  114. package/plugin/skills/muggle-pr-followup/auto-track.md +5 -1
  115. package/plugin/skills/muggle-pr-followup/bootstrap.md +5 -3
  116. package/plugin/skills/muggle-pr-followup/contract.md +34 -17
  117. package/plugin/skills/muggle-pr-followup/finalize.md +29 -0
  118. package/plugin/skills/muggle-pr-followup/reconcile.md +33 -0
  119. package/plugin/skills/muggle-pr-followup/state-schemas.md +10 -2
  120. package/plugin/skills/muggle-preferences/ops/configure.md +2 -1
  121. package/plugin/skills/muggle-preferences/preference-gates/autoResolveConflicts.md +11 -0
  122. package/plugin/skills/muggle-preferences/preference-gates/autoWatchPR.md +13 -0
  123. package/plugin/skills/muggle-preferences/preference-gates/reusePreparePlan.md +11 -0
  124. package/plugin/skills/muggle-status/SKILL.md +1 -1
  125. package/plugin/skills/muggle-test/SKILL.md +30 -48
  126. package/plugin/skills/muggle-test-feature-local/SKILL.md +20 -44
  127. package/plugin/skills/muggle-test-prepare/SKILL.md +5 -1
  128. package/plugin/skills/muggle-test-prepare/steps/check-running.md +7 -5
  129. package/plugin/skills/muggle-test-prepare/steps/identify-services.md +2 -0
  130. package/plugin/skills/muggle-test-prepare/steps/readiness-report.md +30 -0
  131. package/plugin/skills/muggle-test-prepare/steps/reuse-plan.md +44 -0
  132. package/dist/plugin/commands/mrelease.md +0 -7
  133. package/dist/plugin/skills/mrelease/SKILL.md +0 -8
  134. package/dist/plugin/skills/muggle-works-npm-release/SKILL.md +0 -200
  135. package/plugin/commands/mrelease.md +0 -7
  136. package/plugin/skills/mrelease/SKILL.md +0 -8
  137. package/plugin/skills/muggle-works-npm-release/SKILL.md +0 -200
@@ -0,0 +1,60 @@
1
+ # Fix-CI (watcher-dispatched)
2
+
3
+ Resolve red CI on a PR's head — lint/format, typecheck, and failing unit tests — verifying green before re-push. A dumb-pipe dispatch like address-reviews: the executor receives a PR URL, slug, and the failing check names, and fixes them — it owns the fix, not the decision to dispatch.
4
+
5
+ ## Turn preamble
6
+
7
+ ```
8
+ **/muggle-do fix-ci** — fixing <count> red check(s) on <owner>/<repo>#<n>.
9
+ ```
10
+
11
+ ## Input
12
+
13
+ `$ARGUMENTS` carries a `github.com/.../pull/<n>` URL, `slug=<slug>`, and the failing check names (no review ids). Parse all three.
14
+
15
+ ## Inputs from disk
16
+
17
+ From `~/.muggle-ai/muggle-do/sessions/<slug>/`: `prs.json` (PR + local checkout / branch), `last_seen.json` (`ci_fix_attempts`, `ci_escalated_shas`, `pushed_shas`), `state.md` (worktree path, validation strategy).
18
+
19
+ ## Procedure
20
+
21
+ ### Step 1 — Re-attach
22
+
23
+ Check out the PR branch in the session's working tree (per `state.md`). Capture `red_sha = prs.json[0].head_sha`.
24
+
25
+ ### Step 2 — Map each failing check to a local command
26
+
27
+ Per [`../_shared/ci-check-to-command.md`](../_shared/ci-check-to-command.md). Fix the in-scope checks in the working tree; record out-of-scope checks for escalation (Step 6).
28
+
29
+ ### Step 3 — Verify before push
30
+
31
+ - Build (typecheck + lint on the changed surface) + unit suite must pass.
32
+ - Run E2E (per [`../muggle-preferences/preference-gates/autoE2ETest.md`](../muggle-preferences/preference-gates/autoE2ETest.md)) only if the fix touched app logic; lint/format-only fixes skip E2E.
33
+
34
+ A fix that can't be made green locally is not pushed → Step 6.
35
+
36
+ ### Step 4 — Commit + push
37
+
38
+ Commit per the `fix(ci): <check> — <what>` convention ([`../_shared/pr-followup-helpers/reply-routing.md`](../_shared/pr-followup-helpers/reply-routing.md)). Push. Append the new SHA to `last_seen.pushed_shas`. **No PR replies** — the fix commit is the response.
39
+
40
+ ### Step 5 — Update state + respawn
41
+
42
+ - Increment `last_seen.ci_fix_attempts[red_sha]`.
43
+ - Respawn the watcher: `/loop 1m /muggle:muggle-pr-followup <slug> <n>`. CI on the new SHA is the verify loop — a still-red SHA returns as a fresh dispatch, bounded by the per-SHA fix budget (Step 6).
44
+
45
+ ### Step 6 — Escalate (budget spent or out of scope)
46
+
47
+ When the failing checks are all out of scope, or `ci_fix_attempts[red_sha]` has reached 3 with CI still red:
48
+
49
+ 1. Add `red_sha` to `last_seen.ci_escalated_shas` so the SHA is not re-fixed.
50
+ 2. Emit one terminal message naming the unresolved checks.
51
+ 3. Emit the cycle event with `outcome: "ci-escalated"` (Step 7). Do not loop further on this SHA.
52
+
53
+ ### Step 7 — Telemetry
54
+
55
+ Emit one `muggle-do:cycle` event ([`../_shared/telemetry-events/muggle-do-cycle.md`](../_shared/telemetry-events/muggle-do-cycle.md)): `outcome: "ci-fixed"` when a fix pushed, `"ci-escalated"` when escalated — with `ci_checks_in` / `ci_checks_fixed` / `ci_checks_escalated`.
56
+
57
+ ## Guardrails
58
+
59
+ - Max 3 fix attempts per SHA; out-of-scope checks escalate immediately rather than churn.
60
+ - No PR replies; the fix commit is the response.
@@ -0,0 +1,12 @@
1
+ # Input routing
2
+
3
+ How `/muggle-do` resolves `$ARGUMENTS` to a mode. Modes 1–3 are programmatic — dispatched by the watcher — so never ask on those. Inspect in order:
4
+
5
+ 1. **Address-reviews** — a `github.com/.../pull/<n>` URL **and** one or more review ids (integers ≥ 100000000) → [`address-reviews.md`](address-reviews.md).
6
+ 2. **Fix-CI** — a `github.com/.../pull/<n>` URL **and** a `fix ci` / `fix-ci` directive with failing check names (no review ids) → [`fix-ci.md`](fix-ci.md).
7
+ 3. **Post-merge cleanup** — a `cleanup` token and `slug=<slug>` (no PR URL, no review ids) → [`cleanup.md`](cleanup.md).
8
+ 4. **Empty / `help` / `menu` / `?`** → menu + session selector.
9
+ 5. **Task automation** (perform an action on a website) → `muggle:muggle-browser-task`.
10
+ 6. **Otherwise** → forward pipeline at Stage 1.
11
+
12
+ When in doubt between #5 and #6, ask one question.
@@ -40,13 +40,13 @@ Forward pipeline's Stage 7. Invoked by `/muggle-do` after stages 1–6 of a fres
40
40
 
41
41
  After every repo is processed, build the watcher manifest and dispatch one watcher loop per opened PR. The dispatches are the LAST action this stage takes.
42
42
 
43
- Write `.muggle-do/sessions/<slug>/prs.json` per [`../../muggle-pr-followup/state-schemas.md`](../../muggle-pr-followup/state-schemas.md#prsjson):
43
+ Write `~/.muggle-ai/muggle-do/sessions/<slug>/prs.json` per [`../../muggle-pr-followup/state-schemas.md`](../../muggle-pr-followup/state-schemas.md#prsjson):
44
44
 
45
45
  ```json
46
46
  [{ "repo": "owner/repo", "number": 142, "url": "...", "head_sha": "...", "state": "open" }]
47
47
  ```
48
48
 
49
- Seed `.muggle-do/sessions/<slug>/last_seen.json` per [`../../muggle-pr-followup/state-schemas.md`](../../muggle-pr-followup/state-schemas.md#last_seenjson) — empty cursor shape with `pushed_shas: []`. Forward mode never has prior reviews to skip, so `reviewId: 0`.
49
+ Seed `~/.muggle-ai/muggle-do/sessions/<slug>/last_seen.json` per [`../../muggle-pr-followup/state-schemas.md`](../../muggle-pr-followup/state-schemas.md#last_seenjson) — empty cursor shape with `pushed_shas: []`. Forward mode never has prior reviews to skip, so `reviewId: 0`.
50
50
 
51
51
  **Do not** seed `cycle.json` or `requirements.md`. The watcher is a dumb pipe; `/muggle-do` reads reviews off GitHub.
52
52
 
@@ -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
 
@@ -13,7 +13,7 @@ Does **not** create a PR, seed session state, or dispatch a watcher (`/muggle-do
13
13
  ## Inputs
14
14
 
15
15
  - Per-repo: path, branch (head ref name).
16
- - The existing PR URL + number from `.muggle-do/sessions/<slug>/prs.json`.
16
+ - The existing PR URL + number from `~/.muggle-ai/muggle-do/sessions/<slug>/prs.json`.
17
17
  - **Optional** E2E acceptance report from stage 6. Produced by [`../e2e-acceptance.md`](../e2e-acceptance.md); schema in [`../../muggle-pr-visual-walkthrough/SKILL.md`](../../muggle-pr-visual-walkthrough/SKILL.md).
18
18
 
19
19
  ## Procedure
@@ -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.
@@ -0,0 +1,8 @@
1
+ ---
2
+ name: mprfollowup
3
+ description: Explicit short alias for the `muggle-pr-followup` skill. ONLY invoke when the user explicitly types `mprfollowup` or `/mprfollowup` — never auto-trigger from any other phrasing.
4
+ ---
5
+
6
+ # mprfollowup — alias for muggle-pr-followup
7
+
8
+ Invoke the `muggle-pr-followup` skill via the Skill tool. Forward any user-provided arguments unchanged.
@@ -37,6 +37,7 @@ If the user intent clearly matches one command, route directly — no menu neede
37
37
  - test localhost/validate single feature/test a feature → `muggle-test-feature-local`
38
38
  - build/implement from request/end-to-end → `muggle-do`
39
39
  - post results to PR/attach walkthrough/visual evidence on PR → `muggle-pr-visual-walkthrough`
40
+ - watch my PR for reviews/follow up on PR reviews/babysit PR review thread → `muggle-pr-followup`
40
41
  - give feedback on a run/the test was wrong/step N didn't work/show my feedback/delete feedback → `muggle-feedback`
41
42
 
42
43
  If intent is ambiguous, use `AskUserQuestion` with the most likely options rather than asking the user to type a clarification.
@@ -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
 
@@ -25,32 +25,51 @@ Runs an autonomous dev cycle from requirements to PR. **Fire and review:** user
25
25
 
26
26
  Stage 7 dispatches one watcher per opened PR as its last action.
27
27
 
28
+ ## Execution protocol (non-negotiable)
29
+
30
+ The pipeline table lists **pointers, not summaries**. Open each stage's file and execute from it — running a stage off its one-line row here is how tests, E2E, and session state get silently skipped. If you have not read a stage's file this run, you have not run that stage.
31
+
32
+ **Bootstrap before any code, in order:**
33
+ 1. Emit telemetry — [`../_shared/telemetry-emit.md`](../_shared/telemetry-emit.md), `skillName: "muggle-do"`.
34
+ 2. Create `~/.muggle-ai/muggle-do/sessions/<slug>/` with `state.md` + `iterations/001.md` (pre-flight owns this; do it even when running unattended).
35
+ 3. `TodoWrite` one item per stage 1–8 — these stages are the checklist; never swap in your own decomposition.
36
+
37
+ **Per stage:** read the file → execute it → append a marker to `iterations/<NNN>.md` citing the evidence that file requires (jest exit code, E2E verdict + `runId`, screenshot path). A stage is done only when its evidence is written, never on recollection.
38
+
39
+ ### "Autonomous" / "without my intervention" collapses exactly one thing
40
+ Best-effort the Stage-1 questionnaire and don't ask. It does **not** license skipping telemetry, session artifacts, requirements, unit tests, E2E (`autoE2ETest` defaults to `always`), browser verification, the gate below, or the watcher hand-off. Run the whole pipeline silently — never a shortcut.
41
+
42
+ ### Definition of Done — gate before Stage 7
43
+ Do not create or update a PR until each line holds, or is waived by a one-line reason written into `state.md` (silence is not a waiver):
44
+ - `requirements.md` written (forward runs)
45
+ - Build clean — typecheck + lint on changed files
46
+ - New/changed logic carries unit tests (authored in Stage 3; Stage 5 only runs the suite)
47
+ - Unit suite run, PASS recorded
48
+ - E2E verdict recorded with `runId` per `autoE2ETest` — or `[E2E FAILING]` / `SKIPPED` + reason
49
+ - UI changes verified in a real browser with evidence (screenshot path or muggle `runId`); `curl` + `grep` is not verification
50
+
51
+ Opening a PR with an unchecked, unwaived line is a cycle failure.
52
+
28
53
  ## Address-reviews flow
29
54
 
30
55
  When invoked with the directive (PR URL + slug + review ids), routes to [`../do/address-reviews.md`](../do/address-reviews.md). Shares stages 3–6 + walkthrough with the forward pipeline; skips pre-flight, requirements, and PR creation. See the orchestrator for the cycle's exact step order, classification rules, and respawn logic.
31
56
 
32
57
  ## Input routing
33
58
 
34
- Inspect `$ARGUMENTS` in this order:
35
-
36
- 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.
37
- 2. **Empty / `help` / `menu` / `?`** → menu + session selector.
38
- 3. **Task automation** (perform an action on a website) → `muggle:muggle-do-task`.
39
- 4. **Otherwise** → forward pipeline at Stage 1.
40
-
41
- When in doubt between #3 and #4, ask one question.
59
+ `/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.
42
60
 
43
61
  ## Preferences
44
62
 
45
63
  | Preference | Gate |
46
64
  | :--------- | :--- |
47
65
  | `autoE2ETest` | Stage 6 — run E2E every cycle (default `always`), or fold into pre-flight |
66
+ | `autoResolveConflicts` | On rebase conflict — resolve autonomously behind a verify-or-rollback gate (opt-in), or abort + escalate (default `never`) |
48
67
 
49
- `autoUseWorktree`, `autoRebase`, `autoCreatePR`, `autoCleanup` fire from per-stage files.
68
+ `autoUseWorktree`, `autoRebase`, `autoResolveConflicts`, `autoCreatePR`, `autoCleanup` fire from per-stage files.
50
69
 
51
70
  ## Session model
52
71
 
53
- `.muggle-do/sessions/<slug>/`. Schemas: [`../muggle-pr-followup/state-schemas.md`](../muggle-pr-followup/state-schemas.md).
72
+ `~/.muggle-ai/muggle-do/sessions/<slug>/`. Schemas: [`../muggle-pr-followup/state-schemas.md`](../muggle-pr-followup/state-schemas.md).
54
73
 
55
74
  | File | Owner |
56
75
  | :--- | :---- |
@@ -1,6 +1,6 @@
1
1
  ---
2
2
  name: muggle-feedback
3
- description: Capture feedback on a generated Muggle Test action script — either step-level or whole-script — and submit it so the system can analyze it and regenerate affected scripts. Use when the user has just run a Muggle Test (local or remote) and wants to flag what went wrong, when they paste a Muggle dashboard URL with a test script or run, or when they want to view or delete previously submitted feedback. Triggers on: '/muggle-feedback', 'give feedback on this run', 'the test was wrong', 'step N didn't work', 'the script clicked the wrong button', 'flag this run', 'the summary is wrong', 'show my feedback', 'list feedback', 'delete that feedback'. Skill auto-detects the run context from a recent local run, a remote run, or a Muggle dashboard URL in the prompt.
3
+ description: Use when the user wants to flag that a generated Muggle Test action script — or one specific step in it — did the wrong thing, and have it captured so Muggle can analyze and regenerate affected scripts. Covers any report that a script or step is wrong, broken, or misbehaving (clicked the wrong element, bad summary, "step N didn't work", "broken at the submit step"), whether the user just ran a test locally or remotely or pastes a Muggle dashboard run/script URL and points at what failed. Also use to view, list, or delete previously submitted feedback. Triggers on '/muggle-feedback', 'give feedback on this run', 'the test was wrong', 'flag this run', 'show/list/delete my feedback'. Auto-detects run context from a recent local run, a remote run, or a dashboard URL in the prompt.
4
4
  ---
5
5
 
6
6
  # Muggle Test Feedback
@@ -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.
@@ -1,14 +1,13 @@
1
1
  ---
2
2
  name: muggle-pr-followup
3
- description: Watcher loop for PR review follow-ups. Polls one PR for new submitted reviews and dispatches `/muggle-do` (address-reviews mode) when there are any. A dumb pipe — no classification, no cycle execution, no replies. Run it with no args to auto-track every PR you pushed this session (poll-only watchers, any repo). Use `/loop 1m /muggle:muggle-pr-followup <slug> <pr-number>` for ongoing polling, or `/muggle:muggle-pr-followup <pr-url>` to bootstrap a fresh watcher on an existing PR (asks once for the E2E validation context, then runs unattended).
4
- disable-model-invocation: true
3
+ description: Use this skill when the user wants a pull request's incoming review feedback handled for them — it watches one PR's review thread and, each time a reviewer submits new comments, dispatches the work to address them. Engage on PR-review-follow-up intent: "watch my PR and address review comments as they come in", "keep an eye on PR #123 and respond to reviewer feedback", "follow up on my PR's reviews", "babysit my PR's review thread", "auto-handle reviews on the PR I just opened", "I'm stepping away — handle my PR's reviews while I'm gone". Run with no args to track every PR you pushed this session (any repo); pass a PR URL to start watching a specific one. This is PR-review-specific automation: when the recurring thing the user wants handled is a PR's review comments, use this — not the generic `loop` skill. It only watches and dispatches; the actual edits and replies are `muggle-do`. Not for posting test results to a PR (use muggle-pr-visual-walkthrough).
5
4
  ---
6
5
 
7
6
  # muggle-pr-followup
8
7
 
9
8
  > Telemetry first step: see [`../_shared/telemetry-emit.md`](../_shared/telemetry-emit.md). Use `skillName: "muggle-pr-followup"`.
10
9
 
11
- 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.
12
11
 
13
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.
14
13
 
@@ -27,6 +26,9 @@ The skill recognizes its mode by inspecting `$ARGUMENTS` and falling back to on-
27
26
  | `<pr-number>` alone | zero or multiple matches | **error:** ambiguous; list candidates and exit |
28
27
  | empty | — | **auto-track** → [`auto-track.md`](auto-track.md) |
29
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.
30
32
 
31
33
  Bootstrap accepts three optional trailing flags:
32
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:
@@ -37,11 +37,13 @@ Per [`../_shared/github-cli-recipes/verify-working-tree.md`](../_shared/github-c
37
37
 
38
38
  ### Step 4 — Resolve the slug
39
39
 
40
- Default: `<repo>-pr<n>` (e.g. `muggle-ai-works-pr154`). Override: `--slug=<name>`. Session dir is `.muggle-do/sessions/<slug>/` relative to the caller's working tree.
40
+ Default: `<repo>-pr<n>` (e.g. `muggle-ai-works-pr154`). Override: `--slug=<name>`. Session dir is `~/.muggle-ai/muggle-do/sessions/<slug>/` (under the user's home, shared across repos; the slug's repo-pr<n> prefix keeps it unique).
41
41
 
42
42
  ### Step 5 — Idempotency check
43
43
 
44
- If `.muggle-do/sessions/<slug>/` exists:
44
+ **Legacy-slot migration.** Pre-move sessions lived at the repo-relative `.muggle-do/sessions/<slug>/` ([`state-schemas.md`](state-schemas.md#legacy-location)). If the new home-dir slot is absent but `<working-tree>/.muggle-do/sessions/<slug>/` exists (working tree from Step 3), move it to the new location first — this carries an in-flight watcher's cursor, `escalated_review_ids`, and `pushed_shas` across the upgrade. Bootstrap is the only stage that performs this: it is the one entry point that knows the old repo-relative path (the cwd), and it is the natural re-entry point after a plugin upgrade. A slot that fails to migrate loses nothing durable — GitHub holds the reviews, so a fresh bootstrap (cursor `0`) re-processes them.
45
+
46
+ If `~/.muggle-ai/muggle-do/sessions/<slug>/` exists (including a slot just migrated above):
45
47
 
46
48
  - Without `--resume` → exit with the slot-conflict abort. Both remedies (delete + re-run, or pass `--resume`) are spelled out in the message.
47
49
  - With `--resume` → refresh `prs.json[0].head_sha` to the current `headRefOid` from Step 2; leave `last_seen.json` and the cursor untouched. If `state.md` already has a `## Pre-flight answers` block, skip to Step 8; if not (older session), run Step 6.5 to backfill it, then skip to Step 8.
@@ -61,7 +63,7 @@ Capture the fields for Step 7. Do **not** run E2E now — the first watcher tick
61
63
 
62
64
  Identify the loop user once per [`../_shared/github-cli-recipes/loop-user-identity.md`](../_shared/github-cli-recipes/loop-user-identity.md); cache in `state.md`.
63
65
 
64
- Write under `.muggle-do/sessions/<slug>/`:
66
+ Write under `~/.muggle-ai/muggle-do/sessions/<slug>/`:
65
67
 
66
68
  **`prs.json`** — see [`state-schemas.md`](state-schemas.md#prsjson). One entry, `state` = `"open"`, `head_sha` from Step 2's `headRefOid`.
67
69
 
@@ -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
 
@@ -16,7 +16,7 @@ Routing into this mode is documented in [`SKILL.md`](SKILL.md#routing). The arch
16
16
 
17
17
  ## Inputs from disk
18
18
 
19
- Read these from `.muggle-do/sessions/<slug>/`:
19
+ Read these from `~/.muggle-ai/muggle-do/sessions/<slug>/`:
20
20
 
21
21
  - `prs.json` — see [`state-schemas.md`](state-schemas.md#prsjson). The watcher touches the single entry whose `number` matches the dispatched PR number.
22
22
  - `last_seen.json` — see [`state-schemas.md`](state-schemas.md#last_seenjson). Keyed by `"<owner>/<repo>#<n>"`.
@@ -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.
@@ -1,9 +1,13 @@
1
1
  # Session State Schemas
2
2
 
3
- Canonical shapes for the JSON files in a PR-follow-up session slot. The slot path is `.muggle-do/sessions/<slug>/` (the caller's session dir; `muggle-do` is the current and only caller).
3
+ Canonical shapes for the JSON files in a PR-follow-up session slot. The slot path is `~/.muggle-ai/muggle-do/sessions/<slug>/` (under the user's home, shared across repos; `muggle-do` is the current and only caller).
4
4
 
5
5
  All files are atomic writes — the caller rewrites the whole file each time, never mutates in place. Use a temp file + rename if the platform supports it.
6
6
 
7
+ ## Legacy location
8
+
9
+ Before the move to the user's home, slots lived at the repo-relative `.muggle-do/sessions/<slug>/` (one per working tree, still gitignored). Bootstrap's Step 5 migrates a legacy slot to the home-dir location on the next run for that PR; nothing else reads the old path. The state is ephemeral and reconstructible from GitHub, so an un-migrated slot costs only a re-bootstrap, not data.
10
+
7
11
  ## `prs.json`
8
12
 
9
13
  A list of one entry. (Historical: the file is an array for forward-compat with the original session-wide model. Today, each PR has its own session slot, so the array always has exactly one entry.)
@@ -35,7 +39,9 @@ Keyed by `"<owner>/<repo>#<n>"`. One key per PR in the slot.
35
39
  "idle_tick_count": <int>,
36
40
  "cycles_completed": <int>,
37
41
  "escalated_review_ids": [<int>, ...],
38
- "pushed_shas": ["<sha>", ...]
42
+ "pushed_shas": ["<sha>", ...],
43
+ "ci_fix_attempts": { "<sha>": <int> },
44
+ "ci_escalated_shas": ["<sha>", ...]
39
45
  }
40
46
  }
41
47
  ```
@@ -46,6 +52,8 @@ Keyed by `"<owner>/<repo>#<n>"`. One key per PR in the slot.
46
52
  - `cycles_completed`: incremented each time `/muggle-do` completes an address-reviews invocation (regardless of actionable/ambiguous/mixed).
47
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.
48
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.
49
57
 
50
58
  ## `state.md`
51
59
 
@@ -28,7 +28,8 @@ For each option: label = key name, description = first paragraph of `preference-
28
28
  - `multiSelect: true`, `header: "Auth & session"` — `autoLogin`, `autoSelectProject`, `checkForUpdates`, `verboseOutput`
29
29
  - `multiSelect: true`, `header: "Test setup"` — `autoSelectLocalHost`, `autoDetectChanges`, `autoReuseValidationContext`
30
30
  - `multiSelect: true`, `header: "Test run"` — `showElectronBrowser`, `openTestResultsAfterRun`, `autoPublishLocalResults`
31
- - `multiSelect: true`, `header: "Suggestions & PR"` — `suggestRelatedUseCases`, `suggestRelatedTestCases`, `postPRVisualWalkthrough`, `autoCreatePR`
31
+ - `multiSelect: true`, `header: "Suggestions"` — `suggestRelatedUseCases`, `suggestRelatedTestCases`
32
+ - `multiSelect: true`, `header: "PR"` — `postPRVisualWalkthrough`, `autoCreatePR`, `autoWatchPR`
32
33
  - `multiSelect: true`, `header: "Branch hygiene"` — `autoUseWorktree`, `autoRebase`, `autoCleanup`
33
34
  - `multiSelect: false`, `header: "E2E acceptance"` — `autoE2ETest`. Options: `Always run Stage 6 at the end` (`always` — default), `Ask each cycle` (`ask`). No `never` option.
34
35
  - `multiSelect: false`, `header: "Default mode"` — `defaultExecutionMode`. Options: `Local — run on my computer` (`local`), `Remote — run in the Muggle Test cloud` (`remote`), `Ask each time` (don't change).
@@ -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)`
@@ -0,0 +1,13 @@
1
+ # `autoWatchPR`
2
+
3
+ After a PR is sent at the end of a test run, controls whether Muggle starts a `muggle-pr-followup` watcher on it — a loop that polls the PR for newly submitted reviews and hands them to `/muggle-do` to address — or leaves you to start one yourself with `/mprfollowup`. Fires once a PR exists (muggle-test, muggle-test-feature-local), reusing the E2E validation context from that run so the watcher never re-prompts. Substitute `{pr}`.
4
+
5
+ **Picker 1** — header `Watch PR?`, question `"Watch '{pr}' for review follow-ups and address them as they land?"`
6
+ - `Watch it` — `Start a muggle-pr-followup loop on this PR.` → `always`
7
+ - `Ask me next time` — `Decide per run.` → `ask`
8
+ - `Skip — I'll watch it myself` — `Leave it; run /mprfollowup later if you want.` → `never`
9
+
10
+ **Silent action**
11
+ - `always` → `Watching {pr} for review follow-ups`
12
+ - `ask` → `Asking about PR watching`
13
+ - `never` → `Not watching {pr}`