@muggleai/works 5.0.0 → 5.0.2
This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
- package/dist/{chunk-YKR2TQ24.js → chunk-KDRSEHK5.js} +2 -1
- package/dist/{chunk-5G7WI7IY.js → chunk-XO5BQZM3.js} +2 -2
- package/dist/cli.js +2 -2
- package/dist/index.js +2 -2
- package/dist/plugin/.claude-plugin/plugin.json +1 -1
- package/dist/plugin/.cursor-plugin/plugin.json +1 -1
- package/dist/plugin/scripts/guardrails.mjs +2 -1
- package/dist/plugin/skills/_shared/github-cli-recipes/submitted-reviews.md +14 -6
- package/dist/plugin/skills/_shared/github-cli-recipes/unresolved-threads.md +6 -2
- package/dist/plugin/skills/_shared/github-cli-recipes.md +2 -2
- package/dist/plugin/skills/_shared/pr-followup-helpers/classify.md +2 -2
- package/dist/plugin/skills/_shared/pr-followup-helpers/echo-skip.md +6 -12
- package/dist/plugin/skills/_shared/pr-followup-helpers/reply-routing.md +1 -1
- package/dist/plugin/skills/_shared/telemetry-events/pr-followup-tick.md +4 -4
- package/dist/plugin/skills/do/address-reviews.md +7 -7
- package/dist/plugin/skills/do/open-prs/forward.md +1 -1
- package/dist/plugin/skills/muggle-feedback/SKILL.md +1 -1
- package/dist/plugin/skills/muggle-pr-followup/SKILL.md +2 -2
- package/dist/plugin/skills/muggle-pr-followup/auto-track.md +1 -1
- package/dist/plugin/skills/muggle-pr-followup/bootstrap.md +8 -6
- package/dist/plugin/skills/muggle-pr-followup/contract.md +17 -14
- package/dist/plugin/skills/muggle-pr-followup/output-templates/bootstrap.md +1 -1
- package/dist/plugin/skills/muggle-pr-followup/output-templates/help.md +1 -1
- package/dist/plugin/skills/muggle-pr-followup/output-templates/watcher-log.md +2 -2
- package/dist/plugin/skills/muggle-pr-followup/state-schemas.md +7 -7
- package/dist/plugin/skills/muggle-status/SKILL.md +1 -1
- package/dist/plugin/skills/muggle-test/SKILL.md +20 -56
- package/dist/plugin/skills/muggle-test/reference.md +35 -0
- package/dist/plugin/skills/muggle-test-feature-local/SKILL.md +7 -5
- package/dist/plugin/skills/muggle-test-import/SKILL.md +1 -10
- package/dist/plugin/skills/muggle-test-prepare/SKILL.md +1 -1
- package/dist/plugin/skills/muggle-test-regenerate-missing/SKILL.md +1 -1
- package/dist/release-manifest.json +4 -4
- package/dist/{src-ECRJW2LY.js → src-2O5UH4FA.js} +1 -1
- package/package.json +6 -6
- package/plugin/.claude-plugin/plugin.json +1 -1
- package/plugin/.cursor-plugin/plugin.json +1 -1
- package/plugin/scripts/guardrails.mjs +2 -1
- package/plugin/skills/_shared/github-cli-recipes/submitted-reviews.md +14 -6
- package/plugin/skills/_shared/github-cli-recipes/unresolved-threads.md +6 -2
- package/plugin/skills/_shared/github-cli-recipes.md +2 -2
- package/plugin/skills/_shared/pr-followup-helpers/classify.md +2 -2
- package/plugin/skills/_shared/pr-followup-helpers/echo-skip.md +6 -12
- package/plugin/skills/_shared/pr-followup-helpers/reply-routing.md +1 -1
- package/plugin/skills/_shared/telemetry-events/pr-followup-tick.md +4 -4
- package/plugin/skills/do/address-reviews.md +7 -7
- package/plugin/skills/do/open-prs/forward.md +1 -1
- package/plugin/skills/muggle-feedback/SKILL.md +1 -1
- package/plugin/skills/muggle-pr-followup/SKILL.md +2 -2
- package/plugin/skills/muggle-pr-followup/auto-track.md +1 -1
- package/plugin/skills/muggle-pr-followup/bootstrap.md +8 -6
- package/plugin/skills/muggle-pr-followup/contract.md +17 -14
- package/plugin/skills/muggle-pr-followup/output-templates/bootstrap.md +1 -1
- package/plugin/skills/muggle-pr-followup/output-templates/help.md +1 -1
- package/plugin/skills/muggle-pr-followup/output-templates/watcher-log.md +2 -2
- package/plugin/skills/muggle-pr-followup/state-schemas.md +7 -7
- package/plugin/skills/muggle-status/SKILL.md +1 -1
- package/plugin/skills/muggle-test/SKILL.md +20 -56
- package/plugin/skills/muggle-test/reference.md +35 -0
- package/plugin/skills/muggle-test-feature-local/SKILL.md +7 -5
- package/plugin/skills/muggle-test-import/SKILL.md +1 -10
- package/plugin/skills/muggle-test-prepare/SKILL.md +1 -1
- package/plugin/skills/muggle-test-regenerate-missing/SKILL.md +1 -1
|
@@ -17,7 +17,7 @@ Bootstrap asks **one** questionnaire — the E2E validation context the loop wil
|
|
|
17
17
|
- `<pr-url>` matches `https?://github\.com/[^/]+/[^/]+/pull/\d+` — required.
|
|
18
18
|
- `--slug=<name>` overrides the default `<repo>-pr<n>` slug.
|
|
19
19
|
- `--resume` opts into refreshing an existing slot instead of refusing on conflict.
|
|
20
|
-
- `--forward-only` pins
|
|
20
|
+
- `--forward-only` pins `lastBodyReviewId` past existing **body-only** reviews (skip history on those). It does **not** affect line-comment threads — those are always picked up from live thread state. Default is `0`.
|
|
21
21
|
|
|
22
22
|
## Procedure
|
|
23
23
|
|
|
@@ -46,12 +46,14 @@ Default: `<repo>-pr<n>` (e.g. `muggle-ai-works-pr154`). Override: `--slug=<name>
|
|
|
46
46
|
If `~/.muggle-ai/muggle-do/sessions/<slug>/` exists (including a slot just migrated above):
|
|
47
47
|
|
|
48
48
|
- Without `--resume` → exit with the slot-conflict abort. Both remedies (delete + re-run, or pass `--resume`) are spelled out in the message.
|
|
49
|
-
- With `--resume` → refresh `prs.json[0].head_sha` to the current `headRefOid` from Step 2; leave `last_seen.json`
|
|
49
|
+
- With `--resume` → refresh `prs.json[0].head_sha` to the current `headRefOid` from Step 2; leave `last_seen.json` 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.
|
|
50
50
|
|
|
51
|
-
### Step 6 — Resolve the
|
|
51
|
+
### Step 6 — Resolve the body-only watermark
|
|
52
52
|
|
|
53
|
-
-
|
|
54
|
-
|
|
53
|
+
Line-comment threads need no seeding — the watcher derives them from live thread state on every tick, so existing unresolved threads are picked up on the first tick regardless of this step. This step only sets `lastBodyReviewId`, the narrow watermark for body-only reviews (a submitted review with no line comments).
|
|
54
|
+
|
|
55
|
+
- **Default (no `--forward-only`):** `lastBodyReviewId = 0`. The watcher picks up every existing body-only review on its first tick. Matches the common case — the user opened the PR, left feedback they want addressed, and is now bootstrapping.
|
|
56
|
+
- **With `--forward-only`:** fetch reviews per [`../_shared/github-cli-recipes/submitted-reviews.md`](../_shared/github-cli-recipes/submitted-reviews.md), then take `max(id)`. Body-only reviews at or below that id are treated as already-handled. This no longer hides existing line-comment threads — those are always picked up from thread state.
|
|
55
57
|
|
|
56
58
|
### Step 6.5 — Resolve E2E validation context
|
|
57
59
|
|
|
@@ -67,7 +69,7 @@ Write under `~/.muggle-ai/muggle-do/sessions/<slug>/`:
|
|
|
67
69
|
|
|
68
70
|
**`prs.json`** — see [`state-schemas.md`](state-schemas.md#prsjson). One entry, `state` = `"open"`, `head_sha` from Step 2's `headRefOid`.
|
|
69
71
|
|
|
70
|
-
**`last_seen.json`** — see [`state-schemas.md`](state-schemas.md#last_seenjson). One key (`"<owner>/<repo>#<n>"`), `
|
|
72
|
+
**`last_seen.json`** — see [`state-schemas.md`](state-schemas.md#last_seenjson). One key (`"<owner>/<repo>#<n>"`), `lastBodyReviewId` from Step 6, `last_pushed_sha: null`, `idle_tick_count: 0`, `cycles_completed: 0`, `escalated_review_ids: []`, `pushed_shas: []`.
|
|
71
73
|
|
|
72
74
|
**`state.md`** — see [`state-schemas.md`](state-schemas.md#statemd). `Bootstrapped from URL: yes`. Cache the loop-user login. Append the `## Pre-flight answers` block with the fields resolved in Step 6.5, per [`../_shared/resolve-e2e-validation-context.md`](../_shared/resolve-e2e-validation-context.md#persisted-fields).
|
|
73
75
|
|
|
@@ -1,8 +1,8 @@
|
|
|
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
|
|
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 actionable review threads, CI checks, and merge-conflict state, dispatches `/muggle-do` if there's unaddressed 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
|
-
Routing into this mode is documented in [`SKILL.md`](SKILL.md#routing). The architectural rationale lives in the brain
|
|
5
|
+
Routing into this mode is documented in [`SKILL.md`](SKILL.md#routing). The architectural rationale lives in the brain docs `architecture/2026-05-08-muggle-do-pr-comment-loop-design.md` (the overall loop) and `architecture/2026-06-06-pr-followup-thread-state-baseline-design.md` (the thread-state dispatch trigger).
|
|
6
6
|
|
|
7
7
|
## Turn preamble
|
|
8
8
|
|
|
@@ -48,33 +48,36 @@ If `state` is `MERGED` or `CLOSED`:
|
|
|
48
48
|
3. Exit. The watcher has unscheduled itself; no future ticks fire for this PR.
|
|
49
49
|
|
|
50
50
|
|
|
51
|
-
### Step 3 —
|
|
51
|
+
### Step 3 — Compute the actionable set from live thread state
|
|
52
52
|
|
|
53
|
-
|
|
53
|
+
The watcher's dispatch trigger is **derived from current GitHub state**, not a stored review-id cursor — see the [thread-state baseline design](../../../../muggle-ai-brain/architecture/2026-06-06-pr-followup-thread-state-baseline-design.md). Two sources, unioned:
|
|
54
54
|
|
|
55
|
-
|
|
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.
|
|
55
|
+
**(a) Actionable threads.** Fetch unresolved review threads per [`../_shared/github-cli-recipes/unresolved-threads.md`](../_shared/github-cli-recipes/unresolved-threads.md). A thread is **actionable** when `isResolved == false` **and** `isOutdated == false` **and** its newest comment lacks the loop marker `<!-- muggle-do:bot -->` — classify by the marker, never `author.login` (see [`../_shared/pr-followup-helpers/loop-signature.md`](../_shared/pr-followup-helpers/loop-signature.md)). The marker rule makes echo intrinsic: once the loop has replied, the thread's newest comment is the loop's own, so the thread is no longer actionable — no cursor to advance, no self-recursion (see [`../_shared/pr-followup-helpers/echo-skip.md`](../_shared/pr-followup-helpers/echo-skip.md)).
|
|
57
56
|
|
|
58
|
-
|
|
57
|
+
**(b) Actionable body-only reviews.** A body-only review — a submitted `CHANGES_REQUESTED`/`COMMENTED` review with no line comments — has no thread to derive state from, so it keeps a narrow watermark. Fetch submitted reviews per [`../_shared/github-cli-recipes/submitted-reviews.md`](../_shared/github-cli-recipes/submitted-reviews.md); a body-only review is actionable when `id > last_seen.lastBodyReviewId` **and** `id ∉ last_seen.escalated_review_ids`.
|
|
59
58
|
|
|
60
|
-
|
|
59
|
+
Collect the **owning review ids** for dispatch: for each actionable thread, the owning review of its newest comment (`pullRequestReview.databaseId` from the query); plus every actionable body-only review id. The dedup'd union is the dispatch list.
|
|
60
|
+
|
|
61
|
+
### Step 4 — If the actionable set is non-empty → dispatch (reviews preempt CI)
|
|
62
|
+
|
|
63
|
+
The watcher does **not** classify. Classification, batching, replying, escalation, and cycle execution all live in `/muggle-do`. The watcher hands over the owning review ids and exits — `/muggle-do`'s address-reviews re-derives the unresolved threads itself (its authority), so the watcher only needs to decide *that* there is work, not enumerate it exhaustively.
|
|
61
64
|
|
|
62
65
|
1. Reset `last_seen.idle_tick_count` to 0.
|
|
63
66
|
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
67
|
3. Dispatch `/muggle-do` with an *address-reviews* directive carrying:
|
|
65
68
|
- PR URL (from `prs.json[0].url`)
|
|
66
69
|
- Session slug (from the invocation arguments)
|
|
67
|
-
-
|
|
70
|
+
- The owning review ids from Step 3, as a space-separated list
|
|
68
71
|
|
|
69
72
|
Exact phrasing belongs to `/muggle-do`'s intent-routing. A reasonable shape is:
|
|
70
73
|
```
|
|
71
74
|
/muggle-do address reviews <id1> <id2> ... on <pr-url> slug=<slug>
|
|
72
75
|
```
|
|
73
76
|
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 `
|
|
75
|
-
6. Exit. **Reviews preempt CI** — when
|
|
77
|
+
5. Emit a `tick` event with `actionable_threads: <count>`, `dispatched_review_ids: [<id>, ...]`.
|
|
78
|
+
6. Exit. **Reviews preempt CI** — when there is actionable feedback, 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
79
|
|
|
77
|
-
### Step 5 — No
|
|
80
|
+
### Step 5 — No actionable feedback → check mergeability
|
|
78
81
|
|
|
79
82
|
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
83
|
|
|
@@ -89,7 +92,7 @@ Read `mergeable` / `mergeStateStatus` from the Step 1 metadata. If `mergeable ==
|
|
|
89
92
|
|
|
90
93
|
`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.
|
|
91
94
|
|
|
92
|
-
### Step 6 — No
|
|
95
|
+
### Step 6 — No actionable feedback, mergeable → poll CI for the head SHA
|
|
93
96
|
|
|
94
97
|
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:
|
|
95
98
|
|
|
@@ -108,7 +111,7 @@ Fetch the check-run rollup for `prs.json[0].head_sha` per [`../_shared/github-cl
|
|
|
108
111
|
|
|
109
112
|
### Step 7 — Idle
|
|
110
113
|
|
|
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`, `
|
|
114
|
+
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`, `actionable_threads: 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`.
|
|
112
115
|
|
|
113
116
|
## Output
|
|
114
117
|
|
|
@@ -5,7 +5,7 @@
|
|
|
5
5
|
```
|
|
6
6
|
Bootstrapped PR follow-up for <owner>/<repo>#<n>
|
|
7
7
|
Slug: <slug>
|
|
8
|
-
|
|
8
|
+
Baseline: thread-state (unresolved threads picked up live); lastBodyReviewId=0 | =<id> (forward-only)
|
|
9
9
|
Working tree: <toplevel>
|
|
10
10
|
Dispatching: /loop 1m /muggle:muggle-pr-followup <slug> <n>
|
|
11
11
|
```
|
|
@@ -6,7 +6,7 @@ For `/muggle:muggle-pr-followup help` or `?` (no args runs **auto-track** instea
|
|
|
6
6
|
muggle-pr-followup — watcher loop for PR review follow-ups
|
|
7
7
|
|
|
8
8
|
Active loops:
|
|
9
|
-
<slug> → <owner>/<repo>#<n> (
|
|
9
|
+
<slug> → <owner>/<repo>#<n> (<N> cycles)
|
|
10
10
|
...
|
|
11
11
|
(or "no active loops")
|
|
12
12
|
|
|
@@ -5,13 +5,13 @@ The watcher does **not** print to the user during normal operation. It only appe
|
|
|
5
5
|
## Idle tick
|
|
6
6
|
|
|
7
7
|
```
|
|
8
|
-
<ISO-8601> tick pr=<n>
|
|
8
|
+
<ISO-8601> tick pr=<n> threads=0 idle
|
|
9
9
|
```
|
|
10
10
|
|
|
11
11
|
## Dispatching tick
|
|
12
12
|
|
|
13
13
|
```
|
|
14
|
-
<ISO-8601> tick pr=<n>
|
|
14
|
+
<ISO-8601> tick pr=<n> threads=<count> dispatched=<id1>,<id2>,...
|
|
15
15
|
```
|
|
16
16
|
|
|
17
17
|
## Terminal tick
|
|
@@ -34,7 +34,7 @@ Keyed by `"<owner>/<repo>#<n>"`. One key per PR in the slot.
|
|
|
34
34
|
```json
|
|
35
35
|
{
|
|
36
36
|
"<owner>/<repo>#<n>": {
|
|
37
|
-
"
|
|
37
|
+
"lastBodyReviewId": <int>,
|
|
38
38
|
"last_pushed_sha": "<sha-or-null>",
|
|
39
39
|
"idle_tick_count": <int>,
|
|
40
40
|
"cycles_completed": <int>,
|
|
@@ -48,11 +48,11 @@ Keyed by `"<owner>/<repo>#<n>"`. One key per PR in the slot.
|
|
|
48
48
|
}
|
|
49
49
|
```
|
|
50
50
|
|
|
51
|
-
- `
|
|
51
|
+
- `lastBodyReviewId`: narrow watermark for **body-only** reviews (a submitted review carrying no line comments). The watcher dispatches a body-only review only when `id > lastBodyReviewId`. Line-comment threads do **not** use it — they are dispatched from live thread state (unresolved + not outdated + newest comment unmarked by the loop), so there is no cursor that can pin past them. Bootstrap sets it to the highest existing submitted review id with `--forward-only`, else `0`.
|
|
52
52
|
- `last_pushed_sha`: most recent SHA `/muggle-do` pushed in this PR's life; `null` until the first push.
|
|
53
|
-
- `idle_tick_count`: incremented each tick
|
|
53
|
+
- `idle_tick_count`: incremented each tick whose actionable set is empty. Reset to 0 on any tick that dispatches `/muggle-do`. Diagnostic only — does not gate behavior.
|
|
54
54
|
- `cycles_completed`: incremented each time `/muggle-do` completes an address-reviews invocation (regardless of actionable/ambiguous/mixed).
|
|
55
|
-
- `escalated_review_ids`: review ids classified as ambiguous by `/muggle-do`. The watcher excludes these from
|
|
55
|
+
- `escalated_review_ids`: review ids classified as ambiguous by `/muggle-do`. The watcher excludes these from the actionable set (both body-only reviews and the threads they own) so the same ambiguous review is never re-dispatched.
|
|
56
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.
|
|
57
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.
|
|
58
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.
|
|
@@ -94,8 +94,8 @@ The watcher does **not** read or write `state.md`. Only bootstrap, `/muggle-do`,
|
|
|
94
94
|
Append-only line-per-tick log. One line per watcher tick, plus one line per `/muggle-do` invocation. Format is loose, but each line starts with an ISO-8601 timestamp:
|
|
95
95
|
|
|
96
96
|
```
|
|
97
|
-
2026-05-20T12:34:56Z tick pr=154
|
|
98
|
-
2026-05-20T12:35:56Z tick pr=154
|
|
97
|
+
2026-05-20T12:34:56Z tick pr=154 threads=0 idle
|
|
98
|
+
2026-05-20T12:35:56Z tick pr=154 threads=1 dispatched=4295962800
|
|
99
99
|
2026-05-20T12:36:14Z muggle-do cycle review_ids=[4295962800] outcome=pushed head_sha=abc1234
|
|
100
100
|
```
|
|
101
101
|
|
|
@@ -116,7 +116,7 @@ Written exactly once when the PR's watcher exits terminally (PR merged or closed
|
|
|
116
116
|
|
|
117
117
|
## Timeline
|
|
118
118
|
|
|
119
|
-
- <ISO-8601> bootstrap (
|
|
119
|
+
- <ISO-8601> bootstrap (lastBodyReviewId <id>; line-comment threads state-derived)
|
|
120
120
|
- <ISO-8601> review <id> from <login> — actionable, pushed <sha>
|
|
121
121
|
- <ISO-8601> review <id> from <login> — ambiguous, escalated
|
|
122
122
|
- ...
|
|
@@ -1,6 +1,6 @@
|
|
|
1
1
|
---
|
|
2
2
|
name: muggle-status
|
|
3
|
-
description:
|
|
3
|
+
description: "Check the health of the user's Muggle AI installation and diagnose why it's misbehaving — MCP server connectivity, tool loading, login/auth validity, overall setup. Engage on muggle status and on any diagnostic question about Muggle itself: is muggle working or healthy, why does muggle keep failing or timing out, are the muggle MCP tools loading, is my muggle login still valid. Prefer this over answering from memory whenever the user is unsure Muggle itself is functioning. Boundary: diagnosing is muggle-status; fixing a broken install is muggle-repair. Not for the health of the user's own app, CI, or infra."
|
|
4
4
|
---
|
|
5
5
|
|
|
6
6
|
# Muggle Test Status
|
|
@@ -1,6 +1,6 @@
|
|
|
1
1
|
---
|
|
2
2
|
name: muggle-test
|
|
3
|
-
description: "
|
|
3
|
+
description: "Change-driven E2E acceptance testing with Muggle AI: detect the user's recent code changes (local diff or a PR), map them to affected user flows, run real-browser tests on localhost or a preview/staging URL, publish results, and post a screenshot summary to the PR. Use whenever the user wants to test, validate, or regression-test their own in-progress changes or work — \"make sure I didn't break anything\", \"did my recent commits break any user flows?\", \"test before I push\" — especially as the acceptance gate before opening or merging a PR. The defining signal is change-driven validation tied to a commit, push, PR, or merge. For one specific named feature/flow use muggle-test-feature-local; not for importing existing tests, configuring preferences, or replaying a single named script."
|
|
4
4
|
---
|
|
5
5
|
|
|
6
6
|
# Muggle Test — Change-Driven E2E Acceptance Router
|
|
@@ -113,13 +113,15 @@ If no changes detected (clean tree), tell the user and ask what they want to tes
|
|
|
113
113
|
|
|
114
114
|
## Step 3: Authenticate
|
|
115
115
|
|
|
116
|
-
1. Call `muggle-remote-auth-status`
|
|
117
|
-
2.
|
|
118
|
-
- `always` → reuse
|
|
116
|
+
1. Call `muggle-remote-auth-status`. Three states: **valid** (`authenticated: true`), **expired** (`authenticated: false` + `isExpired: true`, `email` still present), **absent** (`authenticated: false`, no `email`).
|
|
117
|
+
2. **Valid OR expired** (any stored identity) → gate `autoLogin` (per `preference-gates/README.md`). An expired token is NOT a reason to silently re-login the same account — surface the switch choice:
|
|
118
|
+
- `always` → reuse if valid; if expired, re-login the **same** account (`muggle-remote-auth-login`, then `muggle-remote-auth-poll`).
|
|
119
119
|
- `never` → `muggle-remote-auth-login` with `forceNewSession: true`, then `muggle-remote-auth-poll`.
|
|
120
120
|
- `ask` → run Picker 1 from `preference-gates/autoLogin.md` via `AskUserQuestion`; map the answer back to one of the actions above.
|
|
121
|
-
3.
|
|
122
|
-
4. If login pending → call `muggle-remote-auth-poll
|
|
121
|
+
3. **Absent** (no stored identity) → `muggle-remote-auth-login` directly, then `muggle-remote-auth-poll`.
|
|
122
|
+
4. If login pending → call `muggle-remote-auth-poll`.
|
|
123
|
+
|
|
124
|
+
**Account-switch caveat (`never` / "Switch account").** The device flow has no `prompt=select_account`; switching relies on `forceNewSession` first clearing the Auth0 session via `/v2/logout?returnTo=<device-activation URL>`. That redirect only works if the activation URL is in the app's Auth0 *Allowed Logout URLs* — otherwise the browser shows an Auth0 error page and the session is silently reused. If that happens, tell the user to complete login in a **fresh incognito window** (no live SSO session) so Auth0 presents an account login.
|
|
123
125
|
|
|
124
126
|
If auth fails repeatedly, suggest: `muggle logout && muggle login` from terminal.
|
|
125
127
|
|
|
@@ -413,53 +415,15 @@ Use `AskUserQuestion`:
|
|
|
413
415
|
|
|
414
416
|
This is a suggestion, not automatic invocation. Skip silently if every test passed cleanly.
|
|
415
417
|
|
|
416
|
-
##
|
|
417
|
-
|
|
418
|
-
|
|
419
|
-
|
|
420
|
-
|
|
421
|
-
|
|
422
|
-
|
|
423
|
-
|
|
424
|
-
|
|
425
|
-
|
|
426
|
-
|
|
427
|
-
|
|
428
|
-
| Test Case | `muggle-remote-test-case-generate-from-prompt` | Both |
|
|
429
|
-
| Test Case | `muggle-remote-test-case-create` | Both |
|
|
430
|
-
| Test Case | `muggle-remote-test-case-get` | Both |
|
|
431
|
-
| Execute (regen) | `muggle-local-execute-test-generation` | Local |
|
|
432
|
-
| Execute (replay) | `muggle-local-execute-replay` | Local |
|
|
433
|
-
| Replay action script fetch | `muggle-remote-test-script-get`, `muggle-remote-action-script-get` | Local replay |
|
|
434
|
-
| Execute (regen) | `muggle-remote-workflow-start-test-script-generation` | Remote |
|
|
435
|
-
| Execute (replay) | `muggle-remote-workflow-start-test-script-replay` | Remote |
|
|
436
|
-
| Failure-mode telemetry | `muggle-local-telemetry-event-emit` | Both |
|
|
437
|
-
| Results | `muggle-local-run-result-get` | Local |
|
|
438
|
-
| Results | `muggle-remote-wf-get-ts-gen-latest-run`, `muggle-remote-wf-get-ts-replay-latest-run` | Remote |
|
|
439
|
-
| Publish | `muggle-local-publish-test-script` | Local |
|
|
440
|
-
| Per-step screenshots (for walkthrough) | `muggle-remote-test-script-get` | Both |
|
|
441
|
-
| Browser | `open` (shell command) | Both |
|
|
442
|
-
| PR walkthrough | `muggle-pr-visual-walkthrough` (shared skill) | Both |
|
|
443
|
-
|
|
444
|
-
## Guardrails
|
|
445
|
-
|
|
446
|
-
- **Always confirm intent first** — never assume local vs remote without asking
|
|
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.
|
|
448
|
-
- **User MUST select project** — present clickable options via `AskUserQuestion`, wait for explicit choice, never auto-select
|
|
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.
|
|
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.
|
|
451
|
-
- **Use `AskUserQuestion` for every selection** — never ask the user to type a number; always present clickable options
|
|
452
|
-
- **Auto-detect localhost URL when possible**; only fall back to free-text when nothing is listening on a common port
|
|
453
|
-
- **Parallelize independent cloud jobs** — when creating N use cases, generating/creating N test cases, fetching N test case details, starting N remote workflows, polling N workflow runtimes, publishing N local runs, or fetching N per-step test scripts, issue all N calls in a single message so they fan out in parallel. The only tolerated sequential loop is local Electron execution (one browser, one test at a time). For use case creation specifically, use the native batch form of `muggle-remote-use-case-create-from-prompts` (all descriptions in one `instructions` array) instead of parallel calls.
|
|
454
|
-
- **One atomic behavior per test case** — every test case verifies exactly one user-observable behavior. Never bundle signup/login/navigation/bootstrap/teardown into a test case body. Ordering and dependencies are Muggle Test's service responsibility, not the skill's.
|
|
455
|
-
- **Never consolidate the generator's output** — if `muggle-remote-test-case-generate-from-prompt` returns N micro-tests, accept all N; never merge them into fewer test cases, even if "the plan" says 4 UC / 4 TC.
|
|
456
|
-
- **Never skip the generate→review cycle** — always present generated test cases to the user before calling `muggle-remote-test-case-create`, even when you're confident. "I'll skip the review and create directly" is always wrong.
|
|
457
|
-
- **Never silently drop test cases** — log failures and continue, then report them
|
|
458
|
-
- **Never guess the URL** — always ask the user for localhost or preview URL
|
|
459
|
-
- **Always publish before opening browser** — the dashboard needs the published data to show results
|
|
460
|
-
- **Delegate PR posting to `muggle-pr-visual-walkthrough`** — never inline the walkthrough markdown or call `gh pr comment` directly from this skill; ask the user and hand off
|
|
461
|
-
- **Can be invoked at any state** — if the user already has a project or use cases set up, skip to the relevant step rather than re-doing everything
|
|
462
|
-
|
|
463
|
-
## Agent Dispatch
|
|
464
|
-
|
|
465
|
-
When used in a multi-agent team (e.g., muggle-ai-teams), this skill is available through the **acceptance-tester** agent at `plugin/agents/acceptance-tester.md`. Orchestrators can dispatch it via `Agent()` instead of invoking this skill directly. The agent wraps this skill and four others (muggle-test-import, muggle-preferences, muggle-repair, muggle-status) and returns structured test results with blocking issues and suggested fixes for coding agents to act on.
|
|
418
|
+
## Non-negotiables
|
|
419
|
+
|
|
420
|
+
Each rule below is covered in-step above; these are the ones this skill most often violates, kept here as reinforcement:
|
|
421
|
+
|
|
422
|
+
- **Test-case shape** — never skip the generate→review cycle, never consolidate the generator's micro-tests, one atomic behavior per test case. Creating test cases directly or merging the generator's output is the single most frequent mistake.
|
|
423
|
+
- **Confirm intent before acting** — local vs remote; never guess the localhost/preview URL.
|
|
424
|
+
- **PR URLs run in a dedicated worktree** — never switch the user's main checkout; pass that worktree as `cwd`.
|
|
425
|
+
- **Every selection uses `AskUserQuestion`** — never ask the user to type a number; the user picks the project (never auto-select).
|
|
426
|
+
- **Parallelize independent cloud jobs**; the only sequential loop is local Electron execution (one browser).
|
|
427
|
+
- **Publish before opening the browser**, and delegate PR posting to `muggle-pr-visual-walkthrough` — never inline the walkthrough or call `gh pr comment` here.
|
|
428
|
+
|
|
429
|
+
Phase→tool map and multi-agent (acceptance-tester) dispatch: [`reference.md`](reference.md).
|
|
@@ -0,0 +1,35 @@
|
|
|
1
|
+
# muggle-test reference
|
|
2
|
+
|
|
3
|
+
Lookup material pulled out of `SKILL.md` to keep the always-loaded body lean. Every tool here is also named inline in the step that uses it — consult this only when you want the full phase→tool map in one place.
|
|
4
|
+
|
|
5
|
+
## Tool Reference
|
|
6
|
+
|
|
7
|
+
| Phase | Tool | Mode |
|
|
8
|
+
|:------|:-----|:-----|
|
|
9
|
+
| Auth | `muggle-remote-auth-status` | Both |
|
|
10
|
+
| Auth | `muggle-remote-auth-login` | Both |
|
|
11
|
+
| Auth | `muggle-remote-auth-poll` | Both |
|
|
12
|
+
| Project | `muggle-remote-project-list` | Both |
|
|
13
|
+
| Project | `muggle-remote-project-create` | Both |
|
|
14
|
+
| Use Case | `muggle-remote-use-case-list` | Both |
|
|
15
|
+
| Use Case | `muggle-remote-use-case-create-from-prompts` | Both |
|
|
16
|
+
| Test Case | `muggle-remote-test-case-list-by-use-case` | Both |
|
|
17
|
+
| Test Case | `muggle-remote-test-case-generate-from-prompt` | Both |
|
|
18
|
+
| Test Case | `muggle-remote-test-case-create` | Both |
|
|
19
|
+
| Test Case | `muggle-remote-test-case-get` | Both |
|
|
20
|
+
| Execute (regen) | `muggle-local-execute-test-generation` | Local |
|
|
21
|
+
| Execute (replay) | `muggle-local-execute-replay` | Local |
|
|
22
|
+
| Replay action script fetch | `muggle-remote-test-script-get`, `muggle-remote-action-script-get` | Local replay |
|
|
23
|
+
| Execute (regen) | `muggle-remote-workflow-start-test-script-generation` | Remote |
|
|
24
|
+
| Execute (replay) | `muggle-remote-workflow-start-test-script-replay` | Remote |
|
|
25
|
+
| Failure-mode telemetry | `muggle-local-telemetry-event-emit` | Both |
|
|
26
|
+
| Results | `muggle-local-run-result-get` | Local |
|
|
27
|
+
| Results | `muggle-remote-wf-get-ts-gen-latest-run`, `muggle-remote-wf-get-ts-replay-latest-run` | Remote |
|
|
28
|
+
| Publish | `muggle-local-publish-test-script` | Local |
|
|
29
|
+
| Per-step screenshots (for walkthrough) | `muggle-remote-test-script-get` | Both |
|
|
30
|
+
| Browser | `open` (shell command) | Both |
|
|
31
|
+
| PR walkthrough | `muggle-pr-visual-walkthrough` (shared skill) | Both |
|
|
32
|
+
|
|
33
|
+
## Agent Dispatch
|
|
34
|
+
|
|
35
|
+
In a multi-agent team (e.g. muggle-ai-teams), this skill is reachable through the **acceptance-tester** agent at `plugin/agents/acceptance-tester.md`. Orchestrators dispatch it via `Agent()` instead of invoking the skill directly. The agent wraps this skill and four others (muggle-test-import, muggle-preferences, muggle-repair, muggle-status) and returns structured test results with blocking issues and suggested fixes for coding agents to act on.
|
|
@@ -147,14 +147,16 @@ Run the shared loop in [`../_shared/dev-loop/run.md`](../_shared/dev-loop/run.md
|
|
|
147
147
|
|
|
148
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.
|
|
149
149
|
|
|
150
|
-
### 7. Execute (
|
|
150
|
+
### 7. Execute (`showUi` gated by `showElectronBrowser`)
|
|
151
151
|
|
|
152
|
-
|
|
152
|
+
Resolve the `showElectronBrowser` gate **first**, then call `muggle-local-execute-test-generation` or `muggle-local-execute-replay`. **Do not** ask the user to re-approve the Electron launch itself — choosing this skill is the approval. That run-approval suppression does **not** extend to the gate below: when `showElectronBrowser=ask` you must still fire its picker.
|
|
153
153
|
|
|
154
|
-
Gate `showElectronBrowser` (per `preference-gates/README.md`). Reuse choice within a session.
|
|
155
|
-
- `always` → omit `showUi
|
|
154
|
+
Gate `showElectronBrowser` (per `preference-gates/README.md`). Reuse the choice within a session.
|
|
155
|
+
- `always` → omit `showUi` (the browser shows by default).
|
|
156
156
|
- `never` → pass `showUi: false`.
|
|
157
|
-
- `ask` →
|
|
157
|
+
- `ask` → you **must** call `AskUserQuestion` (Picker 1 from `preference-gates/showElectronBrowser.md`) **before** the execute call, then map the answer to the `always`/`never` action above. Do not decide for the user.
|
|
158
|
+
|
|
159
|
+
`showUi` is only ever omitted or `false` — never pass `showUi: true`.
|
|
158
160
|
|
|
159
161
|
### 8. Upload run to cloud (every completed run; open `viewUrl` gated by `openTestResultsAfterRun`)
|
|
160
162
|
|
|
@@ -1,15 +1,6 @@
|
|
|
1
1
|
---
|
|
2
2
|
name: muggle-test-import
|
|
3
|
-
description:
|
|
4
|
-
Bring existing tests and test artifacts INTO Muggle Test — from Playwright, Cypress, PRDs,
|
|
5
|
-
Gherkin feature files, test plan docs, Notion exports, or any source.
|
|
6
|
-
TRIGGER when: user wants to import/migrate/load/upload/add/convert existing test files or
|
|
7
|
-
test docs into Muggle Test — e.g. "import my playwright tests", "migrate from cypress to muggle",
|
|
8
|
-
"upload my PRD to muggle", "add my e2e specs to our muggle project", "load these test cases
|
|
9
|
-
into muggle", "turn this feature file into muggle test cases", "create muggle test cases from
|
|
10
|
-
my PRD", "track my specs in muggle", or any .spec.ts/.cy.js/.feature/.md file + muggle.
|
|
11
|
-
DO NOT TRIGGER when: user wants to run/replay Muggle Test scripts, scan a site, generate new
|
|
12
|
-
tests from scratch, or check existing test results.
|
|
3
|
+
description: "Bring existing tests and test artifacts INTO Muggle Test — from Playwright, Cypress, PRDs, Gherkin feature files, test-plan docs, Notion exports, or any source. TRIGGER when the user wants to import, migrate, load, or convert existing test files or docs into Muggle Test — import my playwright tests, migrate from cypress to muggle, upload my PRD to muggle, turn this feature file into muggle test cases, or any .spec.ts/.cy.js/.feature/.md file plus muggle. DO NOT trigger for running or replaying scripts, scanning a site, generating new tests from scratch, or checking results."
|
|
13
4
|
---
|
|
14
5
|
|
|
15
6
|
# Muggle Test Import
|
|
@@ -1,6 +1,6 @@
|
|
|
1
1
|
---
|
|
2
2
|
name: muggle-test-prepare
|
|
3
|
-
description: "
|
|
3
|
+
description: "Get a user's local environment ready before running E2E acceptance tests — verify the dev servers, APIs, and sibling services they need are up and responding, and offer to start whatever is missing (with approval per step). Trigger when the user wants to confirm specific ports or localhost URLs are listening before testing (check if localhost:3000 and the api on 8080 are up, are my services running), spin up their local dev stack, or verify their setup — and whenever another muggle skill (muggle-test, muggle-do, muggle-test-feature-local) needs services running but they're not. This is environment readiness and service startup, not running the tests."
|
|
4
4
|
---
|
|
5
5
|
|
|
6
6
|
# Muggle Test Prepare
|
|
@@ -1,6 +1,6 @@
|
|
|
1
1
|
---
|
|
2
2
|
name: muggle-test-regenerate-missing
|
|
3
|
-
description: "Bulk-regenerate test scripts for every test case in a Muggle AI project that
|
|
3
|
+
description: "Bulk-regenerate test scripts for every test case in a Muggle AI project that has no active script. Scans the project, finds test cases stuck in DRAFT or GENERATION_PENDING, shows the user the list, and on approval kicks off bulk remote script generation via the Muggle Test cloud. Use when the user wants to regenerate missing scripts, fill in missing test scripts, generate scripts for test cases without one, rebuild scripts for stale test cases, or bulk regenerate across a project. Handles discovery, filtering, confirmation, and remote dispatch end-to-end."
|
|
4
4
|
---
|
|
5
5
|
|
|
6
6
|
# Muggle Test — Regenerate Missing Test Scripts
|