@muggleai/works 4.15.0 → 5.0.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 (54) 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/hooks/README.md +26 -0
  4. package/dist/plugin/hooks/hooks.json +39 -0
  5. package/dist/plugin/scripts/ensure-electron-app.sh +1 -1
  6. package/dist/plugin/scripts/guardrail-build-router.sh +9 -0
  7. package/dist/plugin/scripts/guardrail-e2e-gate.sh +8 -0
  8. package/dist/plugin/scripts/guardrail-pr-opened.sh +10 -0
  9. package/dist/plugin/scripts/guardrail-record-tests.sh +9 -0
  10. package/dist/plugin/scripts/guardrails.mjs +143 -0
  11. package/dist/plugin/skills/_shared/github-cli-recipes/pr-metadata.md +2 -1
  12. package/dist/plugin/skills/_shared/pr-followup-helpers/echo-skip.md +16 -0
  13. package/dist/plugin/skills/_shared/pr-followup-helpers.md +1 -0
  14. package/dist/plugin/skills/do/address-reviews.md +1 -1
  15. package/dist/plugin/skills/do/build.md +4 -0
  16. package/dist/plugin/skills/do/cleanup.md +6 -5
  17. package/dist/plugin/skills/do/fix-ci.md +1 -1
  18. package/dist/plugin/skills/do/input-routing.md +7 -6
  19. package/dist/plugin/skills/do/next-step.md +18 -0
  20. package/dist/plugin/skills/do/open-prs/forward.md +2 -0
  21. package/dist/plugin/skills/do/resolve-conflicts.md +62 -0
  22. package/dist/plugin/skills/muggle-do/SKILL.md +2 -2
  23. package/dist/plugin/skills/muggle-pr-followup/SKILL.md +1 -1
  24. package/dist/plugin/skills/muggle-pr-followup/contract.md +40 -16
  25. package/dist/plugin/skills/muggle-pr-followup/state-schemas.md +5 -1
  26. package/dist/plugin/skills/muggle-preferences/preference-gates/autoRouteBuildToMuggleDo.md +13 -0
  27. package/dist/release-manifest.json +4 -4
  28. package/package.json +6 -6
  29. package/plugin/.claude-plugin/plugin.json +1 -1
  30. package/plugin/.cursor-plugin/plugin.json +1 -1
  31. package/plugin/hooks/README.md +26 -0
  32. package/plugin/hooks/hooks.json +39 -0
  33. package/plugin/scripts/ensure-electron-app.sh +1 -1
  34. package/plugin/scripts/guardrail-build-router.sh +9 -0
  35. package/plugin/scripts/guardrail-e2e-gate.sh +8 -0
  36. package/plugin/scripts/guardrail-pr-opened.sh +10 -0
  37. package/plugin/scripts/guardrail-record-tests.sh +9 -0
  38. package/plugin/scripts/guardrails.mjs +143 -0
  39. package/plugin/skills/_shared/github-cli-recipes/pr-metadata.md +2 -1
  40. package/plugin/skills/_shared/pr-followup-helpers/echo-skip.md +16 -0
  41. package/plugin/skills/_shared/pr-followup-helpers.md +1 -0
  42. package/plugin/skills/do/address-reviews.md +1 -1
  43. package/plugin/skills/do/build.md +4 -0
  44. package/plugin/skills/do/cleanup.md +6 -5
  45. package/plugin/skills/do/fix-ci.md +1 -1
  46. package/plugin/skills/do/input-routing.md +7 -6
  47. package/plugin/skills/do/next-step.md +18 -0
  48. package/plugin/skills/do/open-prs/forward.md +2 -0
  49. package/plugin/skills/do/resolve-conflicts.md +62 -0
  50. package/plugin/skills/muggle-do/SKILL.md +2 -2
  51. package/plugin/skills/muggle-pr-followup/SKILL.md +1 -1
  52. package/plugin/skills/muggle-pr-followup/contract.md +40 -16
  53. package/plugin/skills/muggle-pr-followup/state-schemas.md +5 -1
  54. package/plugin/skills/muggle-preferences/preference-gates/autoRouteBuildToMuggleDo.md +13 -0
@@ -78,3 +78,5 @@ Append one short reminder tied to the gate value:
78
78
  - `always` → `Once merged, I'll run the cleanup sequence automatically.`
79
79
  - `never` → omit.
80
80
  - `ask` / absent → `Once merged, I'll check with you about cleanup.`
81
+
82
+ Regardless of the gate, also append: `Once it's merged or closed, I'll move to the next plan item — or ask where to go next if there's no plan.`
@@ -0,0 +1,62 @@
1
+ # Resolve-Conflicts (watcher-dispatched)
2
+
3
+ Rebase a PR whose branch conflicts with its base, resolve the conflicts behind a verify-or-rollback gate, and force-push — so a mergeable-blocked PR doesn't sit idle forever. A dumb-pipe dispatch like fix-ci: the watcher detects `mergeable == CONFLICTING` and hands off; the executor owns the rebase + resolution, never the decision to dispatch.
4
+
5
+ ## Turn preamble
6
+
7
+ ```
8
+ **/muggle-do resolve-conflicts** — rebasing <owner>/<repo>#<n> onto <base> to clear merge conflicts.
9
+ ```
10
+
11
+ ## Input
12
+
13
+ `$ARGUMENTS` carries a `github.com/.../pull/<n>` URL, `slug=<slug>`, and a `resolve conflicts` directive (no review ids, no failing check names). Parse all three.
14
+
15
+ ## Inputs from disk
16
+
17
+ From `~/.muggle-ai/muggle-do/sessions/<slug>/`: `prs.json` (PR + branch + `head_sha`), `last_seen.json` (`conflict_resolve_attempts`, `conflict_escalated_shas`, `pushed_shas`), `state.md` (worktree path, validation strategy, base branch).
18
+
19
+ ## Procedure
20
+
21
+ ### Step 1 — Re-attach
22
+
23
+ Materialize the PR branch in its worktree per [`../_shared/pr-branch-worktree.md`](../_shared/pr-branch-worktree.md) (or use `state.md`'s `worktreePath`). Capture `conflict_sha = prs.json[0].head_sha` and the base branch (`baseRefName` from [`../_shared/github-cli-recipes/pr-metadata.md`](../_shared/github-cli-recipes/pr-metadata.md)).
24
+
25
+ ### Step 2 — Rebase onto base + resolve
26
+
27
+ Run [`../_shared/rebase-before-e2e.md`](../_shared/rebase-before-e2e.md) against the base branch (it fires because a conflicting PR is behind). Conflict handling follows [`autoResolveConflicts`](../muggle-preferences/preference-gates/autoResolveConflicts.md):
28
+
29
+ - default `never` → abort and escalate per Step 5 (`kind: "rebase-conflict"`). The watcher keeps polling; the user resolves on GitHub, or opts into `autoResolveConflicts=always`.
30
+ - `always` → resolve behind the verify-or-rollback gate in [`../_shared/resolve-rebase-conflicts.md`](../_shared/resolve-rebase-conflicts.md).
31
+
32
+ ### Step 3 — Verify the resolution
33
+
34
+ Build (typecheck + lint on the changed surface) + unit suite must pass. Run E2E per [`e2e-acceptance.md`](e2e-acceptance.md) when app logic changed and the session carries validation context. A resolution that does not verify is rolled back → escalate per Step 5. **Never push an unverified merge.**
35
+
36
+ ### Step 4 — Force-push + respawn
37
+
38
+ Push with `--force-with-lease` (the rebase rewrote history). Append the new SHA to `last_seen.pushed_shas`; increment `last_seen.conflict_resolve_attempts[conflict_sha]`. Respawn the watcher as the last action:
39
+
40
+ ```
41
+ /loop 1m /muggle:muggle-pr-followup <slug> <n>
42
+ ```
43
+
44
+ The watcher cancelled its own cron when it dispatched this cycle ([`../muggle-pr-followup/contract.md`](../muggle-pr-followup/contract.md) Step 5b), so this restart is the single live watcher. Its next tick re-checks mergeability on the new head — the rebase is its own verify loop, bounded by the per-SHA attempt budget.
45
+
46
+ ### Step 5 — Escalate (can't resolve / budget spent)
47
+
48
+ When `autoResolveConflicts=never`, the resolution failed verification, or `conflict_resolve_attempts[conflict_sha]` has reached 2:
49
+
50
+ 1. Add `conflict_sha` to `last_seen.conflict_escalated_shas` so the watcher does not re-dispatch this SHA.
51
+ 2. Emit one terminal escalation naming the PR and the conflicting files.
52
+ 3. Respawn the watcher (last action) — it keeps polling for the user's manual resolution or any new reviews.
53
+
54
+ ### Step 6 — Telemetry
55
+
56
+ Emit one `muggle-do:cycle` event ([`../_shared/telemetry-events/muggle-do-cycle.md`](../_shared/telemetry-events/muggle-do-cycle.md)) with `outcome: "conflicts-resolved"` (a verified rebase pushed) or `"conflicts-escalated"`.
57
+
58
+ ## Guardrails
59
+
60
+ - Max 2 resolve attempts per SHA; then escalate rather than churn.
61
+ - Never push an unverified merge — verify-or-rollback always.
62
+ - The default `autoResolveConflicts=never` escalates to the user rather than guessing a merge. Auto-resolution is strictly opt-in.
@@ -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,7 +55,7 @@ When invoked with the directive (PR URL + slug + review ids), routes to [`../do/
56
55
 
57
56
  ## Input routing
58
57
 
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.
58
+ `/muggle-do` serves one interactive mode (the forward pipeline, from a fresh task) and four programmatic modes the watcher dispatches (address-reviews, fix-ci, resolve-conflicts, post-merge cleanup). Resolve `$ARGUMENTS` to a mode per [`../do/input-routing.md`](../do/input-routing.md) before doing anything else.
60
59
 
61
60
  ## Preferences
62
61
 
@@ -64,6 +63,7 @@ When invoked with the directive (PR URL + slug + review ids), routes to [`../do/
64
63
  | :--------- | :--- |
65
64
  | `autoE2ETest` | Stage 6 — run E2E every cycle (default `always`), or fold into pre-flight |
66
65
  | `autoResolveConflicts` | On rebase conflict — resolve autonomously behind a verify-or-rollback gate (opt-in), or abort + escalate (default `never`) |
66
+ | `autoRouteBuildToMuggleDo` | Front-door guardrail — route build/implement/fix requests through this pipeline (build delegated to superpowers); fired by the UserPromptSubmit guardrail, default `ask` |
67
67
 
68
68
  `autoUseWorktree`, `autoRebase`, `autoResolveConflicts`, `autoCreatePR`, `autoCleanup` fire from per-stage files.
69
69
 
@@ -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 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.
10
+ A watcher that babysits one open PR's review thread, CI, and merge-conflict state. Polls for new submitted reviews, check-run state, and mergeability; when review feedback lands, CI goes red, or the branch conflicts with its base, hands the work to `/muggle-do` and exits. On merge or close, it hands the terminal wrap-up to `/muggle-do` the same way — teardown when merged, then a next-step suggestion. `/muggle-do` is the executor — it classifies the reviews, fixes the failing checks, or rebases-and-resolves the conflict, 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
 
@@ -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 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.
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, CI checks, and merge-conflict state, dispatches `/muggle-do` if there's review feedback, fixable red CI, or an unmergeable branch, and exits. It does not classify, fix, resolve, 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
 
@@ -25,35 +25,43 @@ If either file is missing or the PR is not in `prs.json`, the tick is a no-op. L
25
25
 
26
26
  ## Procedure
27
27
 
28
+ ### Step 0 — Stale-fire guard
29
+
30
+ If `prs.json[0].state` on disk is already `merged` or `closed`, this slot was finalized by a prior tick and this is a stale (queued) fire — per-minute cron fires enqueued while the session was busy still drain after the cron is cancelled. Defensively cancel any lingering cron for this slug (`CronList` → the job whose command ends with `/muggle:muggle-pr-followup <slug> <n>` → `CronDelete`; no-op if none), append a `stale-tick` line to `followup.log`, and exit. Do not re-fetch or re-finalize.
31
+
28
32
  ### Step 1 — Refresh PR state
29
33
 
30
- Per [`../_shared/github-cli-recipes/pr-metadata.md`](../_shared/github-cli-recipes/pr-metadata.md). Update `prs.json[0].head_sha` and `prs.json[0].state` from the response.
34
+ Per [`../_shared/github-cli-recipes/pr-metadata.md`](../_shared/github-cli-recipes/pr-metadata.md). Update `prs.json[0].head_sha` and `prs.json[0].state` from the response; keep `mergeable` / `mergeStateStatus` from the same call for Step 5.
31
35
 
32
36
  ### Step 2 — Termination check
33
37
 
34
38
  If `state` is `MERGED` or `CLOSED`:
35
39
 
36
40
  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):
41
+ 2. Hand off the terminal wrap-up as the last action of the turn — for both `MERGED` and `CLOSED`:
38
42
 
39
43
  ```
40
- /muggle-do post-merge cleanup slug=<slug>
44
+ /muggle-do post-merge cleanup slug=<slug> state=<merged|closed>
41
45
  ```
42
46
 
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).
47
+ `/muggle-do` owns the worktree/branch knowledge: it runs teardown only on `merged` (honoring the `autoCleanup` gate — `closed` is unmerged, so the branch and any worktree stay intact), then suggests the next step. This is a runtime dispatch, not a doc dependency on `/muggle-do` — see the one-way rule in [`../CLAUDE.md`](../CLAUDE.md).
44
48
  3. Exit. The watcher has unscheduled itself; no future ticks fire for this PR.
45
49
 
46
50
 
47
51
  ### Step 3 — Fetch new submitted reviews
48
52
 
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
+ Per [`../_shared/github-cli-recipes/submitted-reviews.md`](../_shared/github-cli-recipes/submitted-reviews.md). Exclude two kinds of review id:
54
+
55
+ - ids in `last_seen.escalated_review_ids` — already escalated; the watcher must not re-dispatch them.
56
+ - **echo reviews** per [`../_shared/pr-followup-helpers/echo-skip.md`](../_shared/pr-followup-helpers/echo-skip.md) — a review whose every comment carries the loop marker is the loop's own reply, surfaced by GitHub as a new review. Advance `last_seen.reviewId` past it and skip; never dispatch, or the watcher replies to itself forever.
50
57
 
51
58
  ### Step 4 — If one or more new reviews → dispatch (reviews preempt CI)
52
59
 
53
60
  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.
54
61
 
55
62
  1. Reset `last_seen.idle_tick_count` to 0.
56
- 2. Dispatch `/muggle-do` with an *address-reviews* directive carrying:
63
+ 2. **Stop this watcher (single-thread).** Cancel its cron so no tick fires while the dev cycle runs: `CronList`, find the job whose command ends with `/muggle:muggle-pr-followup <slug> <n>` (exact two-arg match), `CronDelete` it. `/muggle-do` respawns the watcher when the cycle finishes — exactly one cron ever, and no tick overlaps a running cycle.
64
+ 3. Dispatch `/muggle-do` with an *address-reviews* directive carrying:
57
65
  - PR URL (from `prs.json[0].url`)
58
66
  - Session slug (from the invocation arguments)
59
67
  - Every new review id from Step 3, as a space-separated list
@@ -62,11 +70,26 @@ The watcher does **not** classify. Classification, batching, replying, escalatio
62
70
  ```
63
71
  /muggle-do address reviews <id1> <id2> ... on <pr-url> slug=<slug>
64
72
  ```
65
- 3. Append a dispatching line to `followup.log` per [`output-templates/watcher-log.md`](output-templates/watcher-log.md).
66
- 4. Emit a `tick` event with `reviews_seen: <count>`, `dispatched_review_ids: [<id>, ...]`.
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).
73
+ 4. Append a dispatching line to `followup.log` per [`output-templates/watcher-log.md`](output-templates/watcher-log.md).
74
+ 5. Emit a `tick` event with `reviews_seen: <count>`, `dispatched_review_ids: [<id>, ...]`.
75
+ 6. Exit. **Reviews preempt CI** — when reviews land, this tick dispatches address-reviews and never polls CI. The watcher is now stopped; the dev cycle owns the PR and restarts the watcher when it finishes. (The watcher also self-unschedules in Step 2, terminal.)
76
+
77
+ ### Step 5 — No new reviews → check mergeability
78
+
79
+ Read `mergeable` / `mergeStateStatus` from the Step 1 metadata. If `mergeable == CONFLICTING` (or `mergeStateStatus == DIRTY`), **and** `conflict_resolve_attempts[head_sha] < 2`, **and** `head_sha` ∉ `conflict_escalated_shas` → dispatch and exit:
80
+
81
+ 1. Reset `last_seen.idle_tick_count` to 0.
82
+ 2. **Stop this watcher (single-thread):** cancel its cron exactly as in Step 4 — `/muggle-do`'s resolve-conflicts respawns it when the cycle is done.
83
+ 3. Dispatch `/muggle-do` with a *resolve-conflicts* directive (PR URL + slug; no review ids, no check names):
84
+ ```
85
+ /muggle-do resolve conflicts on <pr-url> slug=<slug>
86
+ ```
87
+ 4. Append a dispatching line to `followup.log`; emit a `tick` event with `conflicting: true`, `dispatched_resolve_conflicts: true`.
88
+ 5. Exit. The dev cycle owns the PR; its respawn restarts the watcher, whose next tick re-checks mergeability on the new head — the rebase is its own verify loop, bounded by the per-SHA attempt budget.
89
+
90
+ `mergeable == MERGEABLE` / `UNKNOWN` (GitHub still computing — treat as not-conflicting this tick), or budget spent (`conflict_resolve_attempts[head_sha] >= 2` or `head_sha` ∈ `conflict_escalated_shas`) → fall through to CI.
68
91
 
69
- ### Step 5 — No new reviews → poll CI for the head SHA
92
+ ### Step 6 — No new reviews, mergeable → poll CI for the head SHA
70
93
 
71
94
  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
95
 
@@ -74,17 +97,18 @@ Fetch the check-run rollup for `prs.json[0].head_sha` per [`../_shared/github-cl
74
97
  - **All checks green / skipped, or no checks** → idle (green path).
75
98
  - **One or more checks red** (`bucket == "fail"`), **and** `ci_fix_attempts[head_sha] < 3`, **and** `head_sha` ∉ `ci_escalated_shas` → dispatch and exit:
76
99
  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):
100
+ 2. **Stop this watcher (single-thread):** cancel its cron exactly as in Step 4 — `/muggle-do`'s fix-ci respawns it when the cycle is done.
101
+ 3. Dispatch `/muggle-do` with a *fix-ci* directive carrying the PR URL, slug, and the red check names (no review ids):
78
102
  ```
79
103
  /muggle-do fix ci <check-1> <check-2> ... on <pr-url> slug=<slug>
80
104
  ```
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.
105
+ 4. Append a dispatching line to `followup.log`; emit a `tick` event with `checks_red: <count>`, `dispatched_ci_fix: true`.
106
+ 5. Exit. The dev cycle owns the PR; its respawn restarts the watcher, whose next tick re-checks CI on the new head SHA — CI itself is the verify loop.
83
107
  - **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
108
 
85
- ### Step 6 — Idle
109
+ ### Step 7 — Idle
86
110
 
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`.
111
+ Any idle branch (Steps 4–6 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: []`, `conflicting: <bool>`, `dispatched_resolve_conflicts: false`, `checks_red: <count or 0>`, `dispatched_ci_fix: false`. Exit. The next tick fires in 1 min via `/loop`.
88
112
 
89
113
  ## Output
90
114
 
@@ -41,7 +41,9 @@ Keyed by `"<owner>/<repo>#<n>"`. One key per PR in the slot.
41
41
  "escalated_review_ids": [<int>, ...],
42
42
  "pushed_shas": ["<sha>", ...],
43
43
  "ci_fix_attempts": { "<sha>": <int> },
44
- "ci_escalated_shas": ["<sha>", ...]
44
+ "ci_escalated_shas": ["<sha>", ...],
45
+ "conflict_resolve_attempts": { "<sha>": <int> },
46
+ "conflict_escalated_shas": ["<sha>", ...]
45
47
  }
46
48
  }
47
49
  ```
@@ -54,6 +56,8 @@ Keyed by `"<owner>/<repo>#<n>"`. One key per PR in the slot.
54
56
  - `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
57
  - `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
58
  - `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.
59
+ - `conflict_resolve_attempts`: per-SHA count of resolve-conflicts cycles `/muggle-do` has run. The watcher stops dispatching resolve-conflicts for a SHA once its count reaches 2. Keyed by head SHA.
60
+ - `conflict_escalated_shas`: head SHAs whose merge conflict resolve-conflicts gave up on (attempts exhausted, or `autoResolveConflicts=never`). The watcher excludes these from conflict dispatch so an unresolvable SHA is never re-attempted.
57
61
 
58
62
  ## `state.md`
59
63
 
@@ -0,0 +1,13 @@
1
+ # `autoRouteBuildToMuggleDo`
2
+
3
+ When the user asks to build, implement, or fix something, controls whether the front-door guardrail routes the work through `/muggle-do` — the orchestrator that runs requirements → build (delegated to superpowers' design→plan→review) → impact → unit tests → E2E → PR → watcher — or lets the request proceed however the model would otherwise handle it. Fires once per session, on the first build-intent prompt (UserPromptSubmit guardrail).
4
+
5
+ **Picker 1** — header `Route to muggle-do?`, question `"This looks like a build request — run it through /muggle-do (E2E + PR + watcher, build delegated to superpowers)?"`
6
+ - `Route it` — `Enter the /muggle-do pipeline.` → `always`
7
+ - `Ask me next time` — `Decide per request.` → `ask`
8
+ - `No — proceed normally` — `Handle it without /muggle-do.` → `never`
9
+
10
+ **Silent action**
11
+ - `always` → `Routing build requests through /muggle-do`
12
+ - `ask` → `Asking about routing to muggle-do`
13
+ - `never` → `Not routing to muggle-do`