@muggleai/works 4.12.0 → 4.12.1
This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
- 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/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
|
@@ -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.1",
|
|
5
5
|
"author": {
|
|
6
6
|
"name": "Muggle AI",
|
|
7
7
|
"email": "support@muggle-ai.com"
|
|
@@ -2,7 +2,7 @@
|
|
|
2
2
|
"name": "muggle",
|
|
3
3
|
"displayName": "Muggle AI",
|
|
4
4
|
"description": "Ship quality products with AI-powered end-to-end (E2E) acceptance testing that validates your web app like a real user — from Claude Code and Cursor to PR.",
|
|
5
|
-
"version": "4.12.
|
|
5
|
+
"version": "4.12.1",
|
|
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.
|
|
@@ -1,7 +1,7 @@
|
|
|
1
1
|
{
|
|
2
|
-
"release": "4.12.
|
|
3
|
-
"buildId": "run-
|
|
4
|
-
"commitSha": "
|
|
5
|
-
"buildTime": "2026-05-
|
|
2
|
+
"release": "4.12.1",
|
|
3
|
+
"buildId": "run-39-1",
|
|
4
|
+
"commitSha": "e69fef56f40ab4b9c47ea9fa90c2237ab9ca62eb",
|
|
5
|
+
"buildTime": "2026-05-21T22:26:42Z",
|
|
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.1",
|
|
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.92",
|
|
45
|
+
"downloadBaseUrl": "https://github.com/multiplex-ai/muggle-ai-works/releases/download",
|
|
46
|
+
"runtimeTargetDefault": "production",
|
|
47
|
+
"checksums": {
|
|
48
|
+
"darwin-arm64": "26fbcadb2e43a708fc424cf85c30dad99d9dff4b1013c6101de6f9c8233fc928",
|
|
49
|
+
"darwin-x64": "80fa0d2f00ce2f1209c5d9ba421d6c9fe39baba97aa1390a4d04616302fed693",
|
|
50
|
+
"linux-x64": "9898c5df678d19a2fcf07733caccd26b35953286b43d722f3bf7d8bafda21a51",
|
|
51
|
+
"win32-x64": "994c637547f12d1e9c57acba324946b54f1c36631fe314e6f8e1043e1c1afedf"
|
|
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.1",
|
|
5
5
|
"author": {
|
|
6
6
|
"name": "Muggle AI",
|
|
7
7
|
"email": "support@muggle-ai.com"
|
|
@@ -2,7 +2,7 @@
|
|
|
2
2
|
"name": "muggle",
|
|
3
3
|
"displayName": "Muggle AI",
|
|
4
4
|
"description": "Ship quality products with AI-powered end-to-end (E2E) acceptance testing that validates your web app like a real user — from Claude Code and Cursor to PR.",
|
|
5
|
-
"version": "4.12.
|
|
5
|
+
"version": "4.12.1",
|
|
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.
|