@muggleai/works 5.20.0-staging.140 → 5.20.0-staging.142
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/scripts/guardrails.mjs +3 -3
- package/dist/plugin/scripts/pr-watch-arm.sh +10 -10
- package/dist/plugin/scripts/pr-watch-events.sh +12 -0
- package/dist/plugin/scripts/pr-watch-loop.sh +11 -11
- package/dist/release-manifest.json +3 -3
- package/package.json +1 -1
- package/plugin/.claude-plugin/plugin.json +1 -1
- package/plugin/.cursor-plugin/plugin.json +1 -1
- package/plugin/scripts/guardrails.mjs +3 -3
- package/plugin/scripts/pr-watch-arm.sh +10 -10
- package/plugin/scripts/pr-watch-events.sh +12 -0
- package/plugin/scripts/pr-watch-loop.sh +11 -11
|
@@ -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": "5.20.0-staging.
|
|
4
|
+
"version": "5.20.0-staging.142",
|
|
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": "5.20.0-staging.
|
|
5
|
+
"version": "5.20.0-staging.142",
|
|
6
6
|
"author": {
|
|
7
7
|
"name": "Muggle AI",
|
|
8
8
|
"email": "support@muggle-ai.com"
|
|
@@ -10,7 +10,7 @@ import { execFileSync } from 'child_process';
|
|
|
10
10
|
var GH_PR_MERGED_LINE = /\b(?:Merged|Squashed and merged|Rebased and merged) pull request [\w./-]*#(\d+)/;
|
|
11
11
|
var GH_PR_CLOSED_LINE = /\bClosed pull request [\w./-]*#(\d+)/;
|
|
12
12
|
var GH_PR_REOPENED_LINE = /\bReopened pull request [\w./-]*#(\d+)/;
|
|
13
|
-
var PR_MONITOR_TERMINAL_LINE = /\bTERMINAL pr=(\d+)
|
|
13
|
+
var PR_MONITOR_TERMINAL_LINE = /\bTERMINAL pr=(\d+)(?: state=|: )(MERGED|CLOSED)\b/;
|
|
14
14
|
var MAX_PR_TERMINAL_BLOCKS = 3;
|
|
15
15
|
var SHELL_TOOL_NAMES = ["Bash", "PowerShell"];
|
|
16
16
|
var MAX_WATCH_BLOCKS = 3;
|
|
@@ -50,7 +50,7 @@ var CALL_FAILURE_SIGNALS = [
|
|
|
50
50
|
/"isError"\s*:\s*true/
|
|
51
51
|
];
|
|
52
52
|
var FORGE_TERMINAL_CMD = /\b(?:gh\s+pr\s+(?:merge|close|reopen)|glab\s+mr\s+(?:merge|close|reopen))\b/;
|
|
53
|
-
var
|
|
53
|
+
var WATCH_TERMINAL_CMD = /pr-watch-(?:loop|arm)\.sh/;
|
|
54
54
|
|
|
55
55
|
// src/guardrails/store/fileLock.ts
|
|
56
56
|
function isProcessAlive(pid) {
|
|
@@ -180,7 +180,7 @@ function terminalProvenance(input2) {
|
|
|
180
180
|
if (command === void 0) return { acceptsForgeLine: true, acceptsMonitorLine: true };
|
|
181
181
|
return {
|
|
182
182
|
acceptsForgeLine: FORGE_TERMINAL_CMD.test(command),
|
|
183
|
-
acceptsMonitorLine:
|
|
183
|
+
acceptsMonitorLine: WATCH_TERMINAL_CMD.test(command)
|
|
184
184
|
};
|
|
185
185
|
}
|
|
186
186
|
function detectPrTerminal(input2) {
|
|
@@ -59,16 +59,16 @@ if [ -z "$state_line" ]; then
|
|
|
59
59
|
exit 1
|
|
60
60
|
fi
|
|
61
61
|
|
|
62
|
-
|
|
63
|
-
pr_state="${
|
|
64
|
-
head_sha="${
|
|
65
|
-
base_sha="${
|
|
66
|
-
mergeable="${
|
|
67
|
-
latest_review="${
|
|
68
|
-
latest_comment="${
|
|
69
|
-
unresolved_threads="${
|
|
70
|
-
pending_checks="${
|
|
71
|
-
failed_checks="${
|
|
62
|
+
watch_read_state_fields "$state_line"
|
|
63
|
+
pr_state="${STATE_FIELDS[0]-}"
|
|
64
|
+
head_sha="${STATE_FIELDS[1]-}"
|
|
65
|
+
base_sha="${STATE_FIELDS[2]-}"
|
|
66
|
+
mergeable="${STATE_FIELDS[3]-}"
|
|
67
|
+
latest_review="${STATE_FIELDS[4]-}"
|
|
68
|
+
latest_comment="${STATE_FIELDS[5]-}"
|
|
69
|
+
unresolved_threads="${STATE_FIELDS[6]-}"
|
|
70
|
+
pending_checks="${STATE_FIELDS[7]-}"
|
|
71
|
+
failed_checks="${STATE_FIELDS[8]-}"
|
|
72
72
|
|
|
73
73
|
if [ "$pr_state" = "MERGED" ] || [ "$pr_state" = "CLOSED" ]; then
|
|
74
74
|
echo "TERMINAL pr=$pr_number state=$pr_state — nothing to arm"
|
|
@@ -31,6 +31,18 @@ watch_split_state() {
|
|
|
31
31
|
printf '%s\n' "$1" | awk -F'\t' '{for (i = 1; i <= NF; i++) print $i}'
|
|
32
32
|
}
|
|
33
33
|
|
|
34
|
+
# Loads a state line's fields into the array STATE_FIELDS, empty fields kept.
|
|
35
|
+
# Read line by line rather than with `mapfile`, which bash 3.2 lacks — and 3.2
|
|
36
|
+
# is the system bash on macOS, where a missing builtin left every field empty
|
|
37
|
+
# and the watch unable to see a review, a red check, or a merge.
|
|
38
|
+
watch_read_state_fields() {
|
|
39
|
+
local field
|
|
40
|
+
STATE_FIELDS=()
|
|
41
|
+
while IFS= read -r field; do
|
|
42
|
+
STATE_FIELDS+=("$field")
|
|
43
|
+
done < <(watch_split_state "$1")
|
|
44
|
+
}
|
|
45
|
+
|
|
34
46
|
# A submitted review newer than the floor. Monotonic ids, so `>` is the whole
|
|
35
47
|
# test. PENDING (unsubmitted) reviews are excluded by the caller's query — they
|
|
36
48
|
# are the reviewer's own drafts and are not feedback until submitted.
|
|
@@ -149,17 +149,17 @@ while :; do
|
|
|
149
149
|
continue
|
|
150
150
|
fi
|
|
151
151
|
|
|
152
|
-
|
|
153
|
-
pr_state="${
|
|
154
|
-
head_sha="${
|
|
155
|
-
base_sha="${
|
|
156
|
-
mergeable="${
|
|
157
|
-
latest_review="${
|
|
158
|
-
latest_comment="${
|
|
159
|
-
unresolved_threads="${
|
|
160
|
-
pending_checks="${
|
|
161
|
-
failed_checks="${
|
|
162
|
-
ci_digest="${
|
|
152
|
+
watch_read_state_fields "$state_line"
|
|
153
|
+
pr_state="${STATE_FIELDS[0]-}"
|
|
154
|
+
head_sha="${STATE_FIELDS[1]-}"
|
|
155
|
+
base_sha="${STATE_FIELDS[2]-}"
|
|
156
|
+
mergeable="${STATE_FIELDS[3]-}"
|
|
157
|
+
latest_review="${STATE_FIELDS[4]-}"
|
|
158
|
+
latest_comment="${STATE_FIELDS[5]-}"
|
|
159
|
+
unresolved_threads="${STATE_FIELDS[6]-}"
|
|
160
|
+
pending_checks="${STATE_FIELDS[7]-}"
|
|
161
|
+
failed_checks="${STATE_FIELDS[8]-}"
|
|
162
|
+
ci_digest="${STATE_FIELDS[9]-}"
|
|
163
163
|
|
|
164
164
|
if [ "$pr_state" = "MERGED" ] || [ "$pr_state" = "CLOSED" ]; then
|
|
165
165
|
echo "TERMINAL pr=$pr_number state=$pr_state"
|
|
@@ -1,7 +1,7 @@
|
|
|
1
1
|
{
|
|
2
2
|
"release": "5.18.0",
|
|
3
|
-
"buildId": "run-
|
|
4
|
-
"commitSha": "
|
|
5
|
-
"buildTime": "2026-
|
|
3
|
+
"buildId": "run-142-1",
|
|
4
|
+
"commitSha": "80be7d3ad2babcef518d3decbafba51c75a0ecdb",
|
|
5
|
+
"buildTime": "2026-10-01T22:19:53Z",
|
|
6
6
|
"serviceName": "muggle-ai-works-mcp"
|
|
7
7
|
}
|
package/package.json
CHANGED
|
@@ -1,7 +1,7 @@
|
|
|
1
1
|
{
|
|
2
2
|
"name": "@muggleai/works",
|
|
3
3
|
"mcpName": "io.github.multiplex-ai/muggle",
|
|
4
|
-
"version": "5.20.0-staging.
|
|
4
|
+
"version": "5.20.0-staging.142",
|
|
5
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
6
|
"type": "module",
|
|
7
7
|
"main": "dist/index.js",
|
|
@@ -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": "5.20.0-staging.
|
|
4
|
+
"version": "5.20.0-staging.142",
|
|
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": "5.20.0-staging.
|
|
5
|
+
"version": "5.20.0-staging.142",
|
|
6
6
|
"author": {
|
|
7
7
|
"name": "Muggle AI",
|
|
8
8
|
"email": "support@muggle-ai.com"
|
|
@@ -10,7 +10,7 @@ import { execFileSync } from 'child_process';
|
|
|
10
10
|
var GH_PR_MERGED_LINE = /\b(?:Merged|Squashed and merged|Rebased and merged) pull request [\w./-]*#(\d+)/;
|
|
11
11
|
var GH_PR_CLOSED_LINE = /\bClosed pull request [\w./-]*#(\d+)/;
|
|
12
12
|
var GH_PR_REOPENED_LINE = /\bReopened pull request [\w./-]*#(\d+)/;
|
|
13
|
-
var PR_MONITOR_TERMINAL_LINE = /\bTERMINAL pr=(\d+)
|
|
13
|
+
var PR_MONITOR_TERMINAL_LINE = /\bTERMINAL pr=(\d+)(?: state=|: )(MERGED|CLOSED)\b/;
|
|
14
14
|
var MAX_PR_TERMINAL_BLOCKS = 3;
|
|
15
15
|
var SHELL_TOOL_NAMES = ["Bash", "PowerShell"];
|
|
16
16
|
var MAX_WATCH_BLOCKS = 3;
|
|
@@ -50,7 +50,7 @@ var CALL_FAILURE_SIGNALS = [
|
|
|
50
50
|
/"isError"\s*:\s*true/
|
|
51
51
|
];
|
|
52
52
|
var FORGE_TERMINAL_CMD = /\b(?:gh\s+pr\s+(?:merge|close|reopen)|glab\s+mr\s+(?:merge|close|reopen))\b/;
|
|
53
|
-
var
|
|
53
|
+
var WATCH_TERMINAL_CMD = /pr-watch-(?:loop|arm)\.sh/;
|
|
54
54
|
|
|
55
55
|
// src/guardrails/store/fileLock.ts
|
|
56
56
|
function isProcessAlive(pid) {
|
|
@@ -180,7 +180,7 @@ function terminalProvenance(input2) {
|
|
|
180
180
|
if (command === void 0) return { acceptsForgeLine: true, acceptsMonitorLine: true };
|
|
181
181
|
return {
|
|
182
182
|
acceptsForgeLine: FORGE_TERMINAL_CMD.test(command),
|
|
183
|
-
acceptsMonitorLine:
|
|
183
|
+
acceptsMonitorLine: WATCH_TERMINAL_CMD.test(command)
|
|
184
184
|
};
|
|
185
185
|
}
|
|
186
186
|
function detectPrTerminal(input2) {
|
|
@@ -59,16 +59,16 @@ if [ -z "$state_line" ]; then
|
|
|
59
59
|
exit 1
|
|
60
60
|
fi
|
|
61
61
|
|
|
62
|
-
|
|
63
|
-
pr_state="${
|
|
64
|
-
head_sha="${
|
|
65
|
-
base_sha="${
|
|
66
|
-
mergeable="${
|
|
67
|
-
latest_review="${
|
|
68
|
-
latest_comment="${
|
|
69
|
-
unresolved_threads="${
|
|
70
|
-
pending_checks="${
|
|
71
|
-
failed_checks="${
|
|
62
|
+
watch_read_state_fields "$state_line"
|
|
63
|
+
pr_state="${STATE_FIELDS[0]-}"
|
|
64
|
+
head_sha="${STATE_FIELDS[1]-}"
|
|
65
|
+
base_sha="${STATE_FIELDS[2]-}"
|
|
66
|
+
mergeable="${STATE_FIELDS[3]-}"
|
|
67
|
+
latest_review="${STATE_FIELDS[4]-}"
|
|
68
|
+
latest_comment="${STATE_FIELDS[5]-}"
|
|
69
|
+
unresolved_threads="${STATE_FIELDS[6]-}"
|
|
70
|
+
pending_checks="${STATE_FIELDS[7]-}"
|
|
71
|
+
failed_checks="${STATE_FIELDS[8]-}"
|
|
72
72
|
|
|
73
73
|
if [ "$pr_state" = "MERGED" ] || [ "$pr_state" = "CLOSED" ]; then
|
|
74
74
|
echo "TERMINAL pr=$pr_number state=$pr_state — nothing to arm"
|
|
@@ -31,6 +31,18 @@ watch_split_state() {
|
|
|
31
31
|
printf '%s\n' "$1" | awk -F'\t' '{for (i = 1; i <= NF; i++) print $i}'
|
|
32
32
|
}
|
|
33
33
|
|
|
34
|
+
# Loads a state line's fields into the array STATE_FIELDS, empty fields kept.
|
|
35
|
+
# Read line by line rather than with `mapfile`, which bash 3.2 lacks — and 3.2
|
|
36
|
+
# is the system bash on macOS, where a missing builtin left every field empty
|
|
37
|
+
# and the watch unable to see a review, a red check, or a merge.
|
|
38
|
+
watch_read_state_fields() {
|
|
39
|
+
local field
|
|
40
|
+
STATE_FIELDS=()
|
|
41
|
+
while IFS= read -r field; do
|
|
42
|
+
STATE_FIELDS+=("$field")
|
|
43
|
+
done < <(watch_split_state "$1")
|
|
44
|
+
}
|
|
45
|
+
|
|
34
46
|
# A submitted review newer than the floor. Monotonic ids, so `>` is the whole
|
|
35
47
|
# test. PENDING (unsubmitted) reviews are excluded by the caller's query — they
|
|
36
48
|
# are the reviewer's own drafts and are not feedback until submitted.
|
|
@@ -149,17 +149,17 @@ while :; do
|
|
|
149
149
|
continue
|
|
150
150
|
fi
|
|
151
151
|
|
|
152
|
-
|
|
153
|
-
pr_state="${
|
|
154
|
-
head_sha="${
|
|
155
|
-
base_sha="${
|
|
156
|
-
mergeable="${
|
|
157
|
-
latest_review="${
|
|
158
|
-
latest_comment="${
|
|
159
|
-
unresolved_threads="${
|
|
160
|
-
pending_checks="${
|
|
161
|
-
failed_checks="${
|
|
162
|
-
ci_digest="${
|
|
152
|
+
watch_read_state_fields "$state_line"
|
|
153
|
+
pr_state="${STATE_FIELDS[0]-}"
|
|
154
|
+
head_sha="${STATE_FIELDS[1]-}"
|
|
155
|
+
base_sha="${STATE_FIELDS[2]-}"
|
|
156
|
+
mergeable="${STATE_FIELDS[3]-}"
|
|
157
|
+
latest_review="${STATE_FIELDS[4]-}"
|
|
158
|
+
latest_comment="${STATE_FIELDS[5]-}"
|
|
159
|
+
unresolved_threads="${STATE_FIELDS[6]-}"
|
|
160
|
+
pending_checks="${STATE_FIELDS[7]-}"
|
|
161
|
+
failed_checks="${STATE_FIELDS[8]-}"
|
|
162
|
+
ci_digest="${STATE_FIELDS[9]-}"
|
|
163
163
|
|
|
164
164
|
if [ "$pr_state" = "MERGED" ] || [ "$pr_state" = "CLOSED" ]; then
|
|
165
165
|
echo "TERMINAL pr=$pr_number state=$pr_state"
|