@muggleai/works 4.12.0 → 4.12.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/plugin/.claude-plugin/plugin.json +1 -1
- package/dist/plugin/.cursor-plugin/plugin.json +1 -1
- package/dist/plugin/skills/_shared/pr-followup-helpers/allow-list.md +5 -3
- package/dist/plugin/skills/_shared/pr-followup-helpers/classify.md +15 -0
- package/dist/plugin/skills/_shared/telemetry-events/muggle-do-cycle.md +2 -1
- package/dist/plugin/skills/muggle-pr-followup/SKILL.md +2 -1
- package/dist/plugin/skills/muggle-pr-followup/bootstrap.md +4 -2
- package/dist/plugin/skills/muggle-pr-followup/output-templates/bootstrap.md +1 -1
- package/dist/plugin/skills/muggle-test/SKILL.md +14 -6
- package/dist/release-manifest.json +4 -4
- package/package.json +106 -106
- package/plugin/.claude-plugin/plugin.json +1 -1
- package/plugin/.cursor-plugin/plugin.json +1 -1
- package/plugin/skills/_shared/pr-followup-helpers/allow-list.md +5 -3
- package/plugin/skills/_shared/pr-followup-helpers/classify.md +15 -0
- package/plugin/skills/_shared/telemetry-events/muggle-do-cycle.md +2 -1
- package/plugin/skills/muggle-pr-followup/SKILL.md +2 -1
- package/plugin/skills/muggle-pr-followup/bootstrap.md +4 -2
- package/plugin/skills/muggle-pr-followup/output-templates/bootstrap.md +1 -1
- package/plugin/skills/muggle-test/SKILL.md +14 -6
|
@@ -1,7 +1,7 @@
|
|
|
1
1
|
{
|
|
2
2
|
"name": "muggle",
|
|
3
3
|
"description": "Run real-browser end-to-end (E2E) acceptance tests on your web app from any AI coding agent. Generate test scripts from plain English, replay them on localhost, capture screenshots, and validate user flows like signup, checkout, and dashboards. Works across Claude Code, Cursor, Codex, and Windsurf.",
|
|
4
|
-
"version": "4.12.
|
|
4
|
+
"version": "4.12.2",
|
|
5
5
|
"author": {
|
|
6
6
|
"name": "Muggle AI",
|
|
7
7
|
"email": "support@muggle-ai.com"
|
|
@@ -2,7 +2,7 @@
|
|
|
2
2
|
"name": "muggle",
|
|
3
3
|
"displayName": "Muggle AI",
|
|
4
4
|
"description": "Ship quality products with AI-powered end-to-end (E2E) acceptance testing that validates your web app like a real user — from Claude Code and Cursor to PR.",
|
|
5
|
-
"version": "4.12.
|
|
5
|
+
"version": "4.12.2",
|
|
6
6
|
"author": {
|
|
7
7
|
"name": "Muggle AI",
|
|
8
8
|
"email": "support@muggle-ai.com"
|
|
@@ -1,6 +1,8 @@
|
|
|
1
1
|
# Reviewer allow-list
|
|
2
2
|
|
|
3
|
-
The address-reviews flow only acts on reviews submitted by users in the **allow-list** = (requested reviewers ∪ CODEOWNERS) − bots
|
|
3
|
+
The address-reviews flow only acts on reviews submitted by users in the **allow-list** = (requested reviewers ∪ CODEOWNERS ∪ {PR author}) − bots. Re-resolve every invocation — never cache across cycles.
|
|
4
|
+
|
|
5
|
+
The PR author is implicitly a valid reviewer: in single-account workflows, the human running the agent and the PR's author are the same identity, and the agent must honor their reviews. The agent itself never appears in the submitted-reviews list (it pushes commits and posts inline replies; it does not submit GitHub reviews), so there's no self-loop risk from including the author.
|
|
4
6
|
|
|
5
7
|
## Step 1: requested reviewers
|
|
6
8
|
|
|
@@ -14,7 +16,7 @@ gh pr view <number> --repo <owner>/<repo> --json reviewRequests,author
|
|
|
14
16
|
gh api orgs/<org>/teams/<slug>/members --jq '.[].login'
|
|
15
17
|
```
|
|
16
18
|
|
|
17
|
-
Record `prAuthor = author.login` for the
|
|
19
|
+
Record `prAuthor = author.login` for the inclusion step.
|
|
18
20
|
|
|
19
21
|
## Step 2: CODEOWNERS
|
|
20
22
|
|
|
@@ -43,7 +45,7 @@ If no CODEOWNERS file exists in any location, the CODEOWNERS contribution is emp
|
|
|
43
45
|
|
|
44
46
|
## Step 3: filter
|
|
45
47
|
|
|
46
|
-
Allow-list = (requested reviewers ∪ CODEOWNERS
|
|
48
|
+
Allow-list = (requested reviewers ∪ CODEOWNERS ∪ `{prAuthor}`) − bot logins.
|
|
47
49
|
|
|
48
50
|
Bot logins:
|
|
49
51
|
|
|
@@ -2,6 +2,21 @@
|
|
|
2
2
|
|
|
3
3
|
Classify the **review as a unit** — but reply per line comment (threaded), not per review.
|
|
4
4
|
|
|
5
|
+
## Pre-check: self-loop filter
|
|
6
|
+
|
|
7
|
+
GitHub auto-creates a synthetic review every time the agent posts `POST /comments/<id>/replies`. That review has the loop user as author, an empty body, and contains only the agent's own reply comments (`in_reply_to_id != null`). It carries no reviewer intent and must not trigger another cycle.
|
|
8
|
+
|
|
9
|
+
A review is a **self-loop** iff:
|
|
10
|
+
|
|
11
|
+
- `body` is empty, AND
|
|
12
|
+
- every line comment under it has `in_reply_to_id != null`
|
|
13
|
+
|
|
14
|
+
Self-loops bypass the actionable/ambiguous decision entirely. Action: advance the cursor silently. No push, no reply, no resolve-reminder, no escalation, no entry in `escalated_review_ids`. Telemetry: emit one `cycle` event with `outcome: "self-loop-skip"`.
|
|
15
|
+
|
|
16
|
+
Only reviews that survive the self-loop check proceed to classify below.
|
|
17
|
+
|
|
18
|
+
## Actionable vs ambiguous
|
|
19
|
+
|
|
5
20
|
| Class | Signal | Action |
|
|
6
21
|
| :---- | :----- | :----- |
|
|
7
22
|
| **actionable** | Review names at least one concrete change or asks an answerable question. Soft phrasing counts when there's a concrete referent. | Treat as amended requirements; run **one** implementation cycle for the whole review; reply **threaded per line comment** referencing the new SHA (top-level only when the review is body-only). |
|
|
@@ -14,7 +14,7 @@ One per address-reviews invocation, regardless of outcome.
|
|
|
14
14
|
"review_ids_ambiguous": [<int>, ...],
|
|
15
15
|
"head_sha_before": "<sha-or-null>",
|
|
16
16
|
"head_sha_after": "<sha-or-null>",
|
|
17
|
-
"outcome": "pushed" | "escalated" | "mixed" | "no-op"
|
|
17
|
+
"outcome": "pushed" | "escalated" | "mixed" | "no-op" | "self-loop-skip"
|
|
18
18
|
}
|
|
19
19
|
```
|
|
20
20
|
|
|
@@ -23,3 +23,4 @@ One per address-reviews invocation, regardless of outcome.
|
|
|
23
23
|
- `"escalated"` — all reviews were ambiguous; no push.
|
|
24
24
|
- `"mixed"` — both branches happened in the same invocation.
|
|
25
25
|
- `"no-op"` — every input id was already in the escalated set; no work.
|
|
26
|
+
- `"self-loop-skip"` — review was a synthetic wrapper around the agent's own reply (empty body + all line comments are replies). Cursor advanced silently; no work, no escalation.
|
|
@@ -27,10 +27,11 @@ The skill recognizes two modes by inspecting `$ARGUMENTS` and falling back to on
|
|
|
27
27
|
| `<pr-number>` alone | zero or multiple matches | **error:** ambiguous; list candidates and exit |
|
|
28
28
|
| empty / `help` / `?` | — | **help:** list active loops per [`output-templates/help.md`](output-templates/help.md) |
|
|
29
29
|
|
|
30
|
-
Bootstrap accepts
|
|
30
|
+
Bootstrap accepts three optional trailing flags:
|
|
31
31
|
|
|
32
32
|
- `--slug=<name>` — override the default `<repo>-pr<n>` slug
|
|
33
33
|
- `--resume` — opt in to reusing an existing session slot (default is refuse on conflict)
|
|
34
|
+
- `--forward-only` — pin cursor past existing reviews (skip history). Default is cursor 0, which processes prior submitted reviews on the first tick.
|
|
34
35
|
|
|
35
36
|
## Folder TOC
|
|
36
37
|
|
|
@@ -12,11 +12,12 @@ Bootstrap is **non-interactive**: it runs straight through, prompts the user for
|
|
|
12
12
|
|
|
13
13
|
## Input
|
|
14
14
|
|
|
15
|
-
`$ARGUMENTS = <pr-url> [--slug=<name>] [--resume]`
|
|
15
|
+
`$ARGUMENTS = <pr-url> [--slug=<name>] [--resume] [--forward-only]`
|
|
16
16
|
|
|
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 the cursor past existing reviews (skip history). Default is cursor 0 — the watcher will pick up prior submitted reviews on its first tick.
|
|
20
21
|
|
|
21
22
|
## Procedure
|
|
22
23
|
|
|
@@ -47,7 +48,8 @@ If `.muggle-do/sessions/<slug>/` exists:
|
|
|
47
48
|
|
|
48
49
|
### Step 6 — Resolve the initial cursor
|
|
49
50
|
|
|
50
|
-
|
|
51
|
+
- **Default (no `--forward-only`):** cursor is `0`. The watcher will pick up every existing submitted review on its first tick. This matches the common case where the user opened the PR, left review comments they want addressed, and is now running bootstrap.
|
|
52
|
+
- **With `--forward-only`:** fetch reviews per [`../_shared/github-cli-recipes/submitted-reviews.md`](../_shared/github-cli-recipes/submitted-reviews.md), then take `max(id)`. The watcher only acts on later submissions. Use when bootstrapping a PR with stale/already-handled prior reviews you don't want re-processed.
|
|
51
53
|
|
|
52
54
|
### Step 7 — Seed state files
|
|
53
55
|
|
|
@@ -5,7 +5,7 @@
|
|
|
5
5
|
```
|
|
6
6
|
Bootstrapped PR follow-up for <owner>/<repo>#<n>
|
|
7
7
|
Slug: <slug>
|
|
8
|
-
Cursor: review #<id> (forward-only) | empty (no prior reviews)
|
|
8
|
+
Cursor: 0 (will process <N> existing review(s) on first tick) | review #<id> (forward-only) | empty (no prior reviews)
|
|
9
9
|
Working tree: <toplevel>
|
|
10
10
|
Dispatching: /loop 1m /muggle:muggle-pr-followup <slug> <n>
|
|
11
11
|
```
|
|
@@ -54,19 +54,19 @@ Gates run per `preference-gates/README.md`.
|
|
|
54
54
|
|
|
55
55
|
Parse the user's query and explicitly confirm their expectation. There are exactly two modes:
|
|
56
56
|
|
|
57
|
-
### Mode A: Local Test Generation
|
|
57
|
+
### Mode A: Local Test Generation (default for PRs)
|
|
58
58
|
> Test impacted use cases/test cases against **localhost** using the Electron browser.
|
|
59
59
|
>
|
|
60
60
|
> Execution tool: `muggle-local-execute-test-generation`
|
|
61
61
|
|
|
62
|
-
Signs the user wants this: mentions "localhost", "local", "my machine", "dev server", "my changes locally", or just "test my changes" in a repo context.
|
|
62
|
+
Signs the user wants this: mentions "localhost", "local", "my machine", "dev server", "my changes locally", or just "test my changes" in a repo context. **Also: passing a GitHub PR/issue/repo URL (`github.com/<org>/<repo>/pull/<n>`) defaults to Local mode** — PR review almost always means checking out the branch and validating against the dev server, not testing the PR's preview deployment.
|
|
63
63
|
|
|
64
64
|
### Mode B: Remote Test Generation
|
|
65
65
|
> Ask Muggle Test's cloud to generate test scripts against a **preview/staging URL**.
|
|
66
66
|
>
|
|
67
67
|
> Execution tool: `muggle-remote-workflow-start-test-script-generation`
|
|
68
68
|
|
|
69
|
-
Signs the user wants this: mentions "preview", "staging", "deployed", "preview URL", "test on preview", "test the deployment", or provides
|
|
69
|
+
Signs the user wants this: mentions "preview", "staging", "deployed", "preview URL", "test on preview", "test the deployment", or provides an actual **deployed** preview/staging URL (e.g. `*.vercel.app`, `staging.foo.com`, custom preview domains). GitHub PR URLs do **not** count — see Mode A.
|
|
70
70
|
|
|
71
71
|
### Confirming (gated by `defaultExecutionMode`)
|
|
72
72
|
|
|
@@ -87,15 +87,23 @@ Gate `autoDetectChanges` (per `preference-gates/README.md`):
|
|
|
87
87
|
|
|
88
88
|
### Analysis (when scan is enabled)
|
|
89
89
|
|
|
90
|
-
Analyze the
|
|
90
|
+
Analyze the changes to understand what's impacted. Two sources, picked by what the user passed:
|
|
91
91
|
|
|
92
|
+
**Working directory** (default):
|
|
92
93
|
1. Run `git status` and `git diff --stat` for an overview
|
|
93
94
|
2. Run `git diff` (or `git diff --cached` if staged) to read actual diffs
|
|
94
|
-
|
|
95
|
+
|
|
96
|
+
**PR URL** (user passed `github.com/<org>/<repo>/pull/<n>`):
|
|
97
|
+
1. `gh pr diff <n> --repo <org>/<repo> --name-only` for the changed file list
|
|
98
|
+
2. `gh pr diff <n> --repo <org>/<repo>` for the actual diff
|
|
99
|
+
3. The repo lives at a sibling path (e.g. `C:\Users\stan4\Github\<repo>`) — `cd` into it and verify the PR branch is checked out before running tests; if not, ask the user to check it out (or offer to do it).
|
|
100
|
+
|
|
101
|
+
Either way:
|
|
102
|
+
1. Identify impacted feature areas:
|
|
95
103
|
- Changed UI components, pages, routes
|
|
96
104
|
- Modified API endpoints or data flows
|
|
97
105
|
- Updated form fields, validation, user interactions
|
|
98
|
-
|
|
106
|
+
2. Produce a concise **change summary** — a list of impacted features
|
|
99
107
|
|
|
100
108
|
Present:
|
|
101
109
|
> "Here's what changed: [list]. I'll scope E2E acceptance testing to these areas."
|
|
@@ -1,7 +1,7 @@
|
|
|
1
1
|
{
|
|
2
|
-
"release": "4.12.
|
|
3
|
-
"buildId": "run-
|
|
4
|
-
"commitSha": "
|
|
5
|
-
"buildTime": "2026-05-
|
|
2
|
+
"release": "4.12.2",
|
|
3
|
+
"buildId": "run-40-1",
|
|
4
|
+
"commitSha": "9039582dcc85172dff58bcebc185d8aaa495f947",
|
|
5
|
+
"buildTime": "2026-05-22T04:16:07Z",
|
|
6
6
|
"serviceName": "muggle-ai-works-mcp"
|
|
7
7
|
}
|
package/package.json
CHANGED
|
@@ -1,108 +1,108 @@
|
|
|
1
1
|
{
|
|
2
|
-
|
|
3
|
-
|
|
4
|
-
|
|
5
|
-
|
|
6
|
-
|
|
7
|
-
|
|
8
|
-
|
|
9
|
-
|
|
10
|
-
|
|
11
|
-
|
|
12
|
-
|
|
13
|
-
|
|
14
|
-
|
|
15
|
-
|
|
16
|
-
|
|
17
|
-
|
|
18
|
-
|
|
19
|
-
|
|
20
|
-
|
|
21
|
-
|
|
22
|
-
|
|
23
|
-
|
|
24
|
-
|
|
25
|
-
|
|
26
|
-
|
|
27
|
-
|
|
28
|
-
|
|
29
|
-
|
|
30
|
-
|
|
31
|
-
|
|
32
|
-
|
|
33
|
-
|
|
34
|
-
|
|
35
|
-
|
|
36
|
-
|
|
37
|
-
|
|
38
|
-
|
|
39
|
-
|
|
40
|
-
|
|
41
|
-
|
|
42
|
-
|
|
43
|
-
|
|
44
|
-
|
|
45
|
-
|
|
46
|
-
|
|
47
|
-
|
|
48
|
-
|
|
49
|
-
|
|
50
|
-
|
|
51
|
-
|
|
52
|
-
|
|
53
|
-
|
|
54
|
-
|
|
55
|
-
|
|
56
|
-
|
|
57
|
-
|
|
58
|
-
|
|
59
|
-
|
|
60
|
-
|
|
61
|
-
|
|
62
|
-
|
|
63
|
-
|
|
64
|
-
|
|
65
|
-
|
|
66
|
-
|
|
67
|
-
|
|
68
|
-
|
|
69
|
-
|
|
70
|
-
|
|
71
|
-
|
|
72
|
-
|
|
73
|
-
|
|
74
|
-
|
|
75
|
-
|
|
76
|
-
|
|
77
|
-
|
|
78
|
-
|
|
79
|
-
|
|
80
|
-
|
|
81
|
-
|
|
82
|
-
|
|
83
|
-
|
|
84
|
-
|
|
85
|
-
|
|
86
|
-
|
|
87
|
-
|
|
88
|
-
|
|
89
|
-
|
|
90
|
-
|
|
91
|
-
|
|
92
|
-
|
|
93
|
-
|
|
94
|
-
|
|
95
|
-
|
|
96
|
-
|
|
97
|
-
|
|
98
|
-
|
|
99
|
-
|
|
100
|
-
|
|
101
|
-
|
|
102
|
-
|
|
103
|
-
|
|
104
|
-
|
|
105
|
-
|
|
106
|
-
|
|
107
|
-
|
|
2
|
+
"name": "@muggleai/works",
|
|
3
|
+
"mcpName": "io.github.multiplex-ai/muggle",
|
|
4
|
+
"version": "4.12.2",
|
|
5
|
+
"description": "Ship quality products with AI-powered E2E acceptance testing that validates your web app like a real user — from Claude Code and Cursor to PR.",
|
|
6
|
+
"type": "module",
|
|
7
|
+
"main": "dist/index.js",
|
|
8
|
+
"bin": {
|
|
9
|
+
"muggle": "bin/muggle.js"
|
|
10
|
+
},
|
|
11
|
+
"files": [
|
|
12
|
+
"dist",
|
|
13
|
+
"plugin",
|
|
14
|
+
"bin/muggle.js",
|
|
15
|
+
"scripts/postinstall.mjs"
|
|
16
|
+
],
|
|
17
|
+
"scripts": {
|
|
18
|
+
"clean": "rimraf dist",
|
|
19
|
+
"build": "tsup && node scripts/strip-telemetry-comments.mjs && node scripts/write-release-manifest.mjs && node scripts/sync-versions.mjs && node scripts/build-plugin.mjs",
|
|
20
|
+
"build:plugin": "node scripts/build-plugin.mjs",
|
|
21
|
+
"sync:versions": "node scripts/sync-versions.mjs",
|
|
22
|
+
"build:release": "npm run build",
|
|
23
|
+
"verify:plugin": "node scripts/verify-plugin-marketplace.mjs",
|
|
24
|
+
"verify:contracts": "node scripts/verify-compatibility-contracts.mjs",
|
|
25
|
+
"verify:electron-release-checksums": "node scripts/verify-electron-release-checksums.mjs",
|
|
26
|
+
"verify:upgrade-experience": "node scripts/verify-upgrade-experience.mjs",
|
|
27
|
+
"build:workspace": "turbo run build",
|
|
28
|
+
"typecheck:workspace": "turbo run typecheck",
|
|
29
|
+
"lint:workspace": "turbo run lint",
|
|
30
|
+
"test:workspace": "turbo run test",
|
|
31
|
+
"dev:workspace": "turbo run dev",
|
|
32
|
+
"bootstrap": "npm install && npm run build",
|
|
33
|
+
"bootstrap:workspace": "pnpm install && pnpm run build:workspace",
|
|
34
|
+
"postinstall": "node scripts/postinstall.mjs",
|
|
35
|
+
"start": "node dist/index.js",
|
|
36
|
+
"dev": "tsx watch src/index.ts",
|
|
37
|
+
"lint": "eslint . --fix",
|
|
38
|
+
"lint:check": "eslint .",
|
|
39
|
+
"typecheck": "tsc --noEmit",
|
|
40
|
+
"test": "vitest run",
|
|
41
|
+
"test:watch": "vitest"
|
|
42
|
+
},
|
|
43
|
+
"muggleConfig": {
|
|
44
|
+
"electronAppVersion": "1.0.93",
|
|
45
|
+
"downloadBaseUrl": "https://github.com/multiplex-ai/muggle-ai-works/releases/download",
|
|
46
|
+
"runtimeTargetDefault": "production",
|
|
47
|
+
"checksums": {
|
|
48
|
+
"darwin-arm64": "79edb82904ff247a3176d7f25e6aea879bde0befe9f50ae1c977f9de01e09278",
|
|
49
|
+
"darwin-x64": "2b13541aee90eec7cff3e0d92a963fa2508f91a195aee3774edd851f69a45442",
|
|
50
|
+
"linux-x64": "438d8c80602c6c9746a2b5a11c9236d11997827ca74376e0e0fef1952f38640c",
|
|
51
|
+
"win32-x64": "6ccac8d05d40ce6d6b976f3079cbc7ca4bb3714d3d5b67776a72cd9bbf324f53"
|
|
52
|
+
}
|
|
53
|
+
},
|
|
54
|
+
"dependencies": {
|
|
55
|
+
"@modelcontextprotocol/sdk": "^1.25.3",
|
|
56
|
+
"applicationinsights": "^3.14.0",
|
|
57
|
+
"axios": "^1.7.9",
|
|
58
|
+
"commander": "^14.0.3",
|
|
59
|
+
"open": "^11.0.0",
|
|
60
|
+
"ulid": "^3.0.2",
|
|
61
|
+
"uuid": "^14.0.0",
|
|
62
|
+
"winston": "^3.17.0",
|
|
63
|
+
"zod": "^4.3.6"
|
|
64
|
+
},
|
|
65
|
+
"devDependencies": {
|
|
66
|
+
"@anthropic-ai/claude-agent-sdk": "^0.2.133",
|
|
67
|
+
"@eslint/js": "^10.0.1",
|
|
68
|
+
"@muggleai/mcp": "file:packages/mcps",
|
|
69
|
+
"@muggleai/workflows": "file:packages/workflows",
|
|
70
|
+
"@types/node": "^25.5.2",
|
|
71
|
+
"@types/uuid": "^11.0.0",
|
|
72
|
+
"@typescript-eslint/eslint-plugin": "^8.34.0",
|
|
73
|
+
"@typescript-eslint/parser": "^8.34.0",
|
|
74
|
+
"eslint": "^10.2.0",
|
|
75
|
+
"eslint-plugin-unused-imports": "^4.2.0",
|
|
76
|
+
"rimraf": "^6.0.1",
|
|
77
|
+
"tsup": "^8.5.1",
|
|
78
|
+
"tsx": "^4.19.2",
|
|
79
|
+
"turbo": "^2.9.4",
|
|
80
|
+
"typescript": "^6.0.2",
|
|
81
|
+
"vitest": "^4.0.18"
|
|
82
|
+
},
|
|
83
|
+
"engines": {
|
|
84
|
+
"node": ">=22.0.0"
|
|
85
|
+
},
|
|
86
|
+
"keywords": [
|
|
87
|
+
"mcp",
|
|
88
|
+
"model-context-protocol",
|
|
89
|
+
"muggle-ai",
|
|
90
|
+
"e2e-testing",
|
|
91
|
+
"testing",
|
|
92
|
+
"automation",
|
|
93
|
+
"localhost",
|
|
94
|
+
"ai-coding",
|
|
95
|
+
"user-experience",
|
|
96
|
+
"cursor",
|
|
97
|
+
"claude-code",
|
|
98
|
+
"vibe-coding"
|
|
99
|
+
],
|
|
100
|
+
"author": "Muggle AI",
|
|
101
|
+
"license": "MIT",
|
|
102
|
+
"packageManager": "pnpm@10.0.0",
|
|
103
|
+
"repository": {
|
|
104
|
+
"type": "git",
|
|
105
|
+
"url": "git+https://github.com/multiplex-ai/muggle-ai-works.git"
|
|
106
|
+
},
|
|
107
|
+
"homepage": "https://www.muggle-ai.com/muggleTestV0/docs/mcp/mcp-overview"
|
|
108
108
|
}
|
|
@@ -1,7 +1,7 @@
|
|
|
1
1
|
{
|
|
2
2
|
"name": "muggle",
|
|
3
3
|
"description": "Run real-browser end-to-end (E2E) acceptance tests on your web app from any AI coding agent. Generate test scripts from plain English, replay them on localhost, capture screenshots, and validate user flows like signup, checkout, and dashboards. Works across Claude Code, Cursor, Codex, and Windsurf.",
|
|
4
|
-
"version": "4.12.
|
|
4
|
+
"version": "4.12.2",
|
|
5
5
|
"author": {
|
|
6
6
|
"name": "Muggle AI",
|
|
7
7
|
"email": "support@muggle-ai.com"
|
|
@@ -2,7 +2,7 @@
|
|
|
2
2
|
"name": "muggle",
|
|
3
3
|
"displayName": "Muggle AI",
|
|
4
4
|
"description": "Ship quality products with AI-powered end-to-end (E2E) acceptance testing that validates your web app like a real user — from Claude Code and Cursor to PR.",
|
|
5
|
-
"version": "4.12.
|
|
5
|
+
"version": "4.12.2",
|
|
6
6
|
"author": {
|
|
7
7
|
"name": "Muggle AI",
|
|
8
8
|
"email": "support@muggle-ai.com"
|
|
@@ -1,6 +1,8 @@
|
|
|
1
1
|
# Reviewer allow-list
|
|
2
2
|
|
|
3
|
-
The address-reviews flow only acts on reviews submitted by users in the **allow-list** = (requested reviewers ∪ CODEOWNERS) − bots
|
|
3
|
+
The address-reviews flow only acts on reviews submitted by users in the **allow-list** = (requested reviewers ∪ CODEOWNERS ∪ {PR author}) − bots. Re-resolve every invocation — never cache across cycles.
|
|
4
|
+
|
|
5
|
+
The PR author is implicitly a valid reviewer: in single-account workflows, the human running the agent and the PR's author are the same identity, and the agent must honor their reviews. The agent itself never appears in the submitted-reviews list (it pushes commits and posts inline replies; it does not submit GitHub reviews), so there's no self-loop risk from including the author.
|
|
4
6
|
|
|
5
7
|
## Step 1: requested reviewers
|
|
6
8
|
|
|
@@ -14,7 +16,7 @@ gh pr view <number> --repo <owner>/<repo> --json reviewRequests,author
|
|
|
14
16
|
gh api orgs/<org>/teams/<slug>/members --jq '.[].login'
|
|
15
17
|
```
|
|
16
18
|
|
|
17
|
-
Record `prAuthor = author.login` for the
|
|
19
|
+
Record `prAuthor = author.login` for the inclusion step.
|
|
18
20
|
|
|
19
21
|
## Step 2: CODEOWNERS
|
|
20
22
|
|
|
@@ -43,7 +45,7 @@ If no CODEOWNERS file exists in any location, the CODEOWNERS contribution is emp
|
|
|
43
45
|
|
|
44
46
|
## Step 3: filter
|
|
45
47
|
|
|
46
|
-
Allow-list = (requested reviewers ∪ CODEOWNERS
|
|
48
|
+
Allow-list = (requested reviewers ∪ CODEOWNERS ∪ `{prAuthor}`) − bot logins.
|
|
47
49
|
|
|
48
50
|
Bot logins:
|
|
49
51
|
|
|
@@ -2,6 +2,21 @@
|
|
|
2
2
|
|
|
3
3
|
Classify the **review as a unit** — but reply per line comment (threaded), not per review.
|
|
4
4
|
|
|
5
|
+
## Pre-check: self-loop filter
|
|
6
|
+
|
|
7
|
+
GitHub auto-creates a synthetic review every time the agent posts `POST /comments/<id>/replies`. That review has the loop user as author, an empty body, and contains only the agent's own reply comments (`in_reply_to_id != null`). It carries no reviewer intent and must not trigger another cycle.
|
|
8
|
+
|
|
9
|
+
A review is a **self-loop** iff:
|
|
10
|
+
|
|
11
|
+
- `body` is empty, AND
|
|
12
|
+
- every line comment under it has `in_reply_to_id != null`
|
|
13
|
+
|
|
14
|
+
Self-loops bypass the actionable/ambiguous decision entirely. Action: advance the cursor silently. No push, no reply, no resolve-reminder, no escalation, no entry in `escalated_review_ids`. Telemetry: emit one `cycle` event with `outcome: "self-loop-skip"`.
|
|
15
|
+
|
|
16
|
+
Only reviews that survive the self-loop check proceed to classify below.
|
|
17
|
+
|
|
18
|
+
## Actionable vs ambiguous
|
|
19
|
+
|
|
5
20
|
| Class | Signal | Action |
|
|
6
21
|
| :---- | :----- | :----- |
|
|
7
22
|
| **actionable** | Review names at least one concrete change or asks an answerable question. Soft phrasing counts when there's a concrete referent. | Treat as amended requirements; run **one** implementation cycle for the whole review; reply **threaded per line comment** referencing the new SHA (top-level only when the review is body-only). |
|
|
@@ -14,7 +14,7 @@ One per address-reviews invocation, regardless of outcome.
|
|
|
14
14
|
"review_ids_ambiguous": [<int>, ...],
|
|
15
15
|
"head_sha_before": "<sha-or-null>",
|
|
16
16
|
"head_sha_after": "<sha-or-null>",
|
|
17
|
-
"outcome": "pushed" | "escalated" | "mixed" | "no-op"
|
|
17
|
+
"outcome": "pushed" | "escalated" | "mixed" | "no-op" | "self-loop-skip"
|
|
18
18
|
}
|
|
19
19
|
```
|
|
20
20
|
|
|
@@ -23,3 +23,4 @@ One per address-reviews invocation, regardless of outcome.
|
|
|
23
23
|
- `"escalated"` — all reviews were ambiguous; no push.
|
|
24
24
|
- `"mixed"` — both branches happened in the same invocation.
|
|
25
25
|
- `"no-op"` — every input id was already in the escalated set; no work.
|
|
26
|
+
- `"self-loop-skip"` — review was a synthetic wrapper around the agent's own reply (empty body + all line comments are replies). Cursor advanced silently; no work, no escalation.
|
|
@@ -27,10 +27,11 @@ The skill recognizes two modes by inspecting `$ARGUMENTS` and falling back to on
|
|
|
27
27
|
| `<pr-number>` alone | zero or multiple matches | **error:** ambiguous; list candidates and exit |
|
|
28
28
|
| empty / `help` / `?` | — | **help:** list active loops per [`output-templates/help.md`](output-templates/help.md) |
|
|
29
29
|
|
|
30
|
-
Bootstrap accepts
|
|
30
|
+
Bootstrap accepts three optional trailing flags:
|
|
31
31
|
|
|
32
32
|
- `--slug=<name>` — override the default `<repo>-pr<n>` slug
|
|
33
33
|
- `--resume` — opt in to reusing an existing session slot (default is refuse on conflict)
|
|
34
|
+
- `--forward-only` — pin cursor past existing reviews (skip history). Default is cursor 0, which processes prior submitted reviews on the first tick.
|
|
34
35
|
|
|
35
36
|
## Folder TOC
|
|
36
37
|
|
|
@@ -12,11 +12,12 @@ Bootstrap is **non-interactive**: it runs straight through, prompts the user for
|
|
|
12
12
|
|
|
13
13
|
## Input
|
|
14
14
|
|
|
15
|
-
`$ARGUMENTS = <pr-url> [--slug=<name>] [--resume]`
|
|
15
|
+
`$ARGUMENTS = <pr-url> [--slug=<name>] [--resume] [--forward-only]`
|
|
16
16
|
|
|
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 the cursor past existing reviews (skip history). Default is cursor 0 — the watcher will pick up prior submitted reviews on its first tick.
|
|
20
21
|
|
|
21
22
|
## Procedure
|
|
22
23
|
|
|
@@ -47,7 +48,8 @@ If `.muggle-do/sessions/<slug>/` exists:
|
|
|
47
48
|
|
|
48
49
|
### Step 6 — Resolve the initial cursor
|
|
49
50
|
|
|
50
|
-
|
|
51
|
+
- **Default (no `--forward-only`):** cursor is `0`. The watcher will pick up every existing submitted review on its first tick. This matches the common case where the user opened the PR, left review comments they want addressed, and is now running bootstrap.
|
|
52
|
+
- **With `--forward-only`:** fetch reviews per [`../_shared/github-cli-recipes/submitted-reviews.md`](../_shared/github-cli-recipes/submitted-reviews.md), then take `max(id)`. The watcher only acts on later submissions. Use when bootstrapping a PR with stale/already-handled prior reviews you don't want re-processed.
|
|
51
53
|
|
|
52
54
|
### Step 7 — Seed state files
|
|
53
55
|
|
|
@@ -5,7 +5,7 @@
|
|
|
5
5
|
```
|
|
6
6
|
Bootstrapped PR follow-up for <owner>/<repo>#<n>
|
|
7
7
|
Slug: <slug>
|
|
8
|
-
Cursor: review #<id> (forward-only) | empty (no prior reviews)
|
|
8
|
+
Cursor: 0 (will process <N> existing review(s) on first tick) | review #<id> (forward-only) | empty (no prior reviews)
|
|
9
9
|
Working tree: <toplevel>
|
|
10
10
|
Dispatching: /loop 1m /muggle:muggle-pr-followup <slug> <n>
|
|
11
11
|
```
|
|
@@ -54,19 +54,19 @@ Gates run per `preference-gates/README.md`.
|
|
|
54
54
|
|
|
55
55
|
Parse the user's query and explicitly confirm their expectation. There are exactly two modes:
|
|
56
56
|
|
|
57
|
-
### Mode A: Local Test Generation
|
|
57
|
+
### Mode A: Local Test Generation (default for PRs)
|
|
58
58
|
> Test impacted use cases/test cases against **localhost** using the Electron browser.
|
|
59
59
|
>
|
|
60
60
|
> Execution tool: `muggle-local-execute-test-generation`
|
|
61
61
|
|
|
62
|
-
Signs the user wants this: mentions "localhost", "local", "my machine", "dev server", "my changes locally", or just "test my changes" in a repo context.
|
|
62
|
+
Signs the user wants this: mentions "localhost", "local", "my machine", "dev server", "my changes locally", or just "test my changes" in a repo context. **Also: passing a GitHub PR/issue/repo URL (`github.com/<org>/<repo>/pull/<n>`) defaults to Local mode** — PR review almost always means checking out the branch and validating against the dev server, not testing the PR's preview deployment.
|
|
63
63
|
|
|
64
64
|
### Mode B: Remote Test Generation
|
|
65
65
|
> Ask Muggle Test's cloud to generate test scripts against a **preview/staging URL**.
|
|
66
66
|
>
|
|
67
67
|
> Execution tool: `muggle-remote-workflow-start-test-script-generation`
|
|
68
68
|
|
|
69
|
-
Signs the user wants this: mentions "preview", "staging", "deployed", "preview URL", "test on preview", "test the deployment", or provides
|
|
69
|
+
Signs the user wants this: mentions "preview", "staging", "deployed", "preview URL", "test on preview", "test the deployment", or provides an actual **deployed** preview/staging URL (e.g. `*.vercel.app`, `staging.foo.com`, custom preview domains). GitHub PR URLs do **not** count — see Mode A.
|
|
70
70
|
|
|
71
71
|
### Confirming (gated by `defaultExecutionMode`)
|
|
72
72
|
|
|
@@ -87,15 +87,23 @@ Gate `autoDetectChanges` (per `preference-gates/README.md`):
|
|
|
87
87
|
|
|
88
88
|
### Analysis (when scan is enabled)
|
|
89
89
|
|
|
90
|
-
Analyze the
|
|
90
|
+
Analyze the changes to understand what's impacted. Two sources, picked by what the user passed:
|
|
91
91
|
|
|
92
|
+
**Working directory** (default):
|
|
92
93
|
1. Run `git status` and `git diff --stat` for an overview
|
|
93
94
|
2. Run `git diff` (or `git diff --cached` if staged) to read actual diffs
|
|
94
|
-
|
|
95
|
+
|
|
96
|
+
**PR URL** (user passed `github.com/<org>/<repo>/pull/<n>`):
|
|
97
|
+
1. `gh pr diff <n> --repo <org>/<repo> --name-only` for the changed file list
|
|
98
|
+
2. `gh pr diff <n> --repo <org>/<repo>` for the actual diff
|
|
99
|
+
3. The repo lives at a sibling path (e.g. `C:\Users\stan4\Github\<repo>`) — `cd` into it and verify the PR branch is checked out before running tests; if not, ask the user to check it out (or offer to do it).
|
|
100
|
+
|
|
101
|
+
Either way:
|
|
102
|
+
1. Identify impacted feature areas:
|
|
95
103
|
- Changed UI components, pages, routes
|
|
96
104
|
- Modified API endpoints or data flows
|
|
97
105
|
- Updated form fields, validation, user interactions
|
|
98
|
-
|
|
106
|
+
2. Produce a concise **change summary** — a list of impacted features
|
|
99
107
|
|
|
100
108
|
Present:
|
|
101
109
|
> "Here's what changed: [list]. I'll scope E2E acceptance testing to these areas."
|