@muggleai/works 4.12.1 → 4.12.3
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-I4VLYJ7M.js → chunk-CPF6AR2I.js} +499 -147
- package/dist/{chunk-2DVZ2LYO.js → chunk-JNI7INIO.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/skills/_shared/dev-server-readiness.md +39 -0
- package/dist/plugin/skills/_shared/failure-mode-handling.md +19 -4
- package/dist/plugin/skills/_shared/pr-branch-worktree.md +31 -0
- 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 +20 -8
- package/dist/plugin/skills/muggle-test-feature-local/SKILL.md +6 -1
- package/dist/plugin/skills/muggle-test-prepare/SKILL.md +40 -256
- package/dist/plugin/skills/muggle-test-prepare/steps/check-running.md +31 -0
- package/dist/plugin/skills/muggle-test-prepare/steps/env-file.md +18 -0
- package/dist/plugin/skills/muggle-test-prepare/steps/fresh-install.md +20 -0
- package/dist/plugin/skills/muggle-test-prepare/steps/identify-services.md +28 -0
- package/dist/plugin/skills/muggle-test-prepare/steps/readiness-report.md +26 -0
- package/dist/plugin/skills/muggle-test-prepare/steps/rebase-check.md +3 -0
- package/dist/plugin/skills/muggle-test-prepare/steps/scope.md +11 -0
- package/dist/plugin/skills/muggle-test-prepare/steps/smoke-test.md +26 -0
- package/dist/plugin/skills/muggle-test-prepare/steps/start-commands.md +29 -0
- package/dist/plugin/skills/muggle-test-prepare/steps/start-services.md +21 -0
- package/dist/plugin/skills/muggle-test-prepare/steps/viability-check.md +21 -0
- package/dist/release-manifest.json +4 -4
- package/dist/{src-ARTTHWNP.js → src-YR5UKLPC.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/skills/_shared/dev-server-readiness.md +39 -0
- package/plugin/skills/_shared/failure-mode-handling.md +19 -4
- package/plugin/skills/_shared/pr-branch-worktree.md +31 -0
- 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 +20 -8
- package/plugin/skills/muggle-test-feature-local/SKILL.md +6 -1
- package/plugin/skills/muggle-test-prepare/SKILL.md +40 -256
- package/plugin/skills/muggle-test-prepare/steps/check-running.md +31 -0
- package/plugin/skills/muggle-test-prepare/steps/env-file.md +18 -0
- package/plugin/skills/muggle-test-prepare/steps/fresh-install.md +20 -0
- package/plugin/skills/muggle-test-prepare/steps/identify-services.md +28 -0
- package/plugin/skills/muggle-test-prepare/steps/readiness-report.md +26 -0
- package/plugin/skills/muggle-test-prepare/steps/rebase-check.md +3 -0
- package/plugin/skills/muggle-test-prepare/steps/scope.md +11 -0
- package/plugin/skills/muggle-test-prepare/steps/smoke-test.md +26 -0
- package/plugin/skills/muggle-test-prepare/steps/start-commands.md +29 -0
- package/plugin/skills/muggle-test-prepare/steps/start-services.md +21 -0
- package/plugin/skills/muggle-test-prepare/steps/viability-check.md +21 -0
|
@@ -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.3",
|
|
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.3",
|
|
6
6
|
"author": {
|
|
7
7
|
"name": "Muggle AI",
|
|
8
8
|
"email": "support@muggle-ai.com"
|
|
@@ -49,6 +49,45 @@ netstat -ano | findstr /R /C:":3000 " /C:":3001 " /C:":4200 " /C:":5173 " /C:":8
|
|
|
49
49
|
|
|
50
50
|
If the app declares a backend URL in its env file, probe the backend's health endpoint before treating the dev server as usable. 5xx or unreachable → halt; the frontend may render but its data layer is dead, so any query against it is meaningless.
|
|
51
51
|
|
|
52
|
+
## Body sniff patterns
|
|
53
|
+
|
|
54
|
+
A `200 OK` can still be a build-error overlay or stack trace. Search the response body (case-insensitive) for broken-build markers — a match means unhealthy regardless of status.
|
|
55
|
+
|
|
56
|
+
| Stack | Pattern (regex) |
|
|
57
|
+
|:------|:----------------|
|
|
58
|
+
| Next.js | `__next_error__\|Failed to compile\|webpack-internal://` |
|
|
59
|
+
| Vite | `vite-error-overlay\|Internal server error\|\[plugin:` |
|
|
60
|
+
| Node / Express | `MODULE_NOT_FOUND\|Cannot find module\|npm ERR!\|Cannot GET /\|Cannot POST /\|Error: ENOENT\|EACCES\|EADDRINUSE` |
|
|
61
|
+
| Django | `TemplateSyntaxError\|ProgrammingError at /\|<h1>Server Error \(500\)</h1>` |
|
|
62
|
+
| Flask | `Werkzeug Debugger\|werkzeug-debug` |
|
|
63
|
+
| FastAPI / Python | `Traceback \(most recent call last\)\|ModuleNotFoundError\|ImportError` |
|
|
64
|
+
| Rails | `Better Errors\|ActionController::RoutingError\|<title>Action Controller:` |
|
|
65
|
+
| Spring Boot | `Whitelabel Error Page` |
|
|
66
|
+
| Tomcat | `HTTP Status 500.*Apache Tomcat` |
|
|
67
|
+
| Laravel / PHP | `Whoops\\\\|<b>Fatal error</b>\|Parse error:\|Stack trace:` |
|
|
68
|
+
| JS stack frame | `at .*\(.*\.[jt]sx?:\d+:\d+\)` |
|
|
69
|
+
| Java stack frame | `at \w+(\.\w+)+\(\w+\.java:\d+\)` |
|
|
70
|
+
| Python stack frame | `File ".*", line \d+, in ` |
|
|
71
|
+
| Ruby stack frame | `\.rb:\d+:in ` |
|
|
72
|
+
|
|
73
|
+
The bash/PowerShell snippets below use the union of all patterns above. Trim per-stack when you know the target.
|
|
74
|
+
|
|
75
|
+
#### bash/zsh
|
|
76
|
+
|
|
77
|
+
```bash
|
|
78
|
+
BODY=$(curl -sS -L --max-redirs 1 --max-time 3 "$URL")
|
|
79
|
+
PATTERN='__next_error__|Failed to compile|webpack-internal://|vite-error-overlay|Internal server error|MODULE_NOT_FOUND|Cannot find module|Cannot GET /|npm ERR!|Error: ENOENT|EACCES|EADDRINUSE|TemplateSyntaxError|Werkzeug Debugger|Traceback \(most recent call last\)|ModuleNotFoundError|ImportError|Better Errors|ActionController::RoutingError|Whitelabel Error Page|Apache Tomcat|Whoops|<b>Fatal error</b>|Parse error:|Stack trace:|at .*\(.*\.[jt]sx?:[0-9]+:[0-9]+\)|at \w+(\.\w+)+\(\w+\.java:[0-9]+\)|File ".*", line [0-9]+, in |\.rb:[0-9]+:in '
|
|
80
|
+
echo "$BODY" | grep -qiE "$PATTERN" && { echo "BODY-SNIFF FAIL"; echo "$BODY" | grep -iE "$PATTERN" | head -3; exit 1; }
|
|
81
|
+
```
|
|
82
|
+
|
|
83
|
+
#### PowerShell
|
|
84
|
+
|
|
85
|
+
```powershell
|
|
86
|
+
$body = (Invoke-WebRequest -Uri $url -TimeoutSec 3 -MaximumRedirection 1 -ErrorAction Stop).Content
|
|
87
|
+
$pattern = '__next_error__|Failed to compile|webpack-internal://|vite-error-overlay|Internal server error|MODULE_NOT_FOUND|Cannot find module|Cannot GET /|npm ERR!|Error: ENOENT|EACCES|EADDRINUSE|TemplateSyntaxError|Werkzeug Debugger|Traceback \(most recent call last\)|ModuleNotFoundError|ImportError|Better Errors|ActionController::RoutingError|Whitelabel Error Page|Apache Tomcat|Whoops|<b>Fatal error</b>|Parse error:|Stack trace:|at .*\(.*\.[jt]sx?:\d+:\d+\)|at \w+(\.\w+)+\(\w+\.java:\d+\)|File ".*", line \d+, in |\.rb:\d+:in '
|
|
88
|
+
if ($body -imatch $pattern) { Write-Host "BODY-SNIFF FAIL"; [regex]::Matches($body, $pattern, 'IgnoreCase') | Select-Object -First 3 | ForEach-Object { $_.Value }; exit 1 }
|
|
89
|
+
```
|
|
90
|
+
|
|
52
91
|
## Two-stage readiness — after starting a dev server
|
|
53
92
|
|
|
54
93
|
Network reachability is necessary but not sufficient. Many dev servers bind to a port before build/startup work is complete. Wait for **both** network readiness and application readiness before issuing requests.
|
|
@@ -109,9 +109,15 @@ Triggered when `muggle-local-execute-replay` returns `status: "failed"` (or non-
|
|
|
109
109
|
| **stale-script** | The test script no longer matches the live UI (selectors moved, label paths changed, page renamed). The product still works; the script is out of date. |
|
|
110
110
|
| **product-defect** | The script and infra are fine; the user's app actually misbehaved (assertion failure on previously-passing step, unexpected error, wrong page after action). This is the failure mode acceptance testing exists to catch. |
|
|
111
111
|
|
|
112
|
-
###
|
|
112
|
+
### Where to read signals
|
|
113
|
+
|
|
114
|
+
Call `muggle-local-run-result-get` (local) or the remote equivalent and read **structured fields**, not `execute`'s response stdout tail (it's a truncated display excerpt and routinely cuts off mid-sentence). Order:
|
|
113
115
|
|
|
114
|
-
|
|
116
|
+
1. `Status` + `Error` — the verdict and the one-line cause.
|
|
117
|
+
2. `Artifacts` section, when present — opens `artifactsDir`. Read `results.md` (step-by-step + screenshot links) for the per-step verdict, then `action-script.json` for what the agent attempted.
|
|
118
|
+
3. `stdout.log` / `stderr.log` only when the Artifacts section is absent or `results.md` doesn't exist (e.g. early Electron failure).
|
|
119
|
+
|
|
120
|
+
### Initial signal heuristics
|
|
115
121
|
|
|
116
122
|
- **infra** signals: `electron-crash`, `chromium-error`, `click-no-effect-on-clickable-element`, `timeout-on-trivial-wait`, `internal-error-in-mcp-output`.
|
|
117
123
|
- **stale-script** signals: `element-not-found`, `selector-timeout`, `label-path-mismatch`, `nav-target-404`, `aria-label-changed`.
|
|
@@ -189,9 +195,18 @@ Triggered when `muggle-local-execute-test-generation` (or the remote equivalent)
|
|
|
189
195
|
| **agent-course** | The generation agent went down a wrong path (chose the wrong button, misread the goal, looped on a blocking modal). The product is fine and the test case is fine — the agent's *course* needs steering. |
|
|
190
196
|
| **product-uxux** | The product itself blocks the test (broken page, missing element, server error). Agent can't proceed because the feature doesn't actually work. |
|
|
191
197
|
|
|
192
|
-
###
|
|
198
|
+
### Where to read signals
|
|
193
199
|
|
|
194
|
-
|
|
200
|
+
Same rule as section B: read **structured fields** from `muggle-local-run-result-get`, not `execute`'s response stdout tail. The `Artifacts` section is present on failed regen too — `action-script.json` is included when generation reached the step-emission stage (typical for `goal_not_achievable`: the agent's attempted steps + halt summary). `results.md` and per-step screenshots are absent on failure (electron-app emits those only on the successful completion path).
|
|
201
|
+
|
|
202
|
+
Order:
|
|
203
|
+
|
|
204
|
+
1. `Status` + `Error` — the verdict and one-line cause. `Error: Electron exited with code 26` typically means `goal_not_achievable`.
|
|
205
|
+
2. `action-script.json` in `artifactsDir` when present — read the steps the agent attempted and the `summaryStep` (halt reason, goal-not-achievable verdict).
|
|
206
|
+
3. `stdout.log` / `stderr.log` at `artifactsDir/` — last 100 lines is usually enough; look for the final structured summary the generation agent emitted (it appears near the end as a JSON-ish block, not in the truncated execute tail).
|
|
207
|
+
4. Remote regen — fetch the workflow run with `muggle-remote-wf-get-ts-gen-latest-run`; signals live in `summaryStep` and the per-step list there.
|
|
208
|
+
|
|
209
|
+
### Initial signal heuristics
|
|
195
210
|
|
|
196
211
|
- **transient**: `network-error`, `llm-rate-limit`, `single-tool-call-error`, run had partial progress then died.
|
|
197
212
|
- **infra**: `electron-mcp-handler-crash`, `internal-validation-error`, `pipeline-stuck`, identical failure repeated more than twice.
|
|
@@ -0,0 +1,31 @@
|
|
|
1
|
+
# PR-Branch Worktree — Shared Reference
|
|
2
|
+
|
|
3
|
+
> Source of truth for materializing a PR's branch in an isolated worktree so the user's main checkout is never disturbed. Used by `muggle-test` (and any future skill that takes a GitHub PR URL). Skills MUST link here rather than restate the steps.
|
|
4
|
+
|
|
5
|
+
## When this applies
|
|
6
|
+
|
|
7
|
+
A skill receives a GitHub PR URL of the form `github.com/<org>/<repo>/pull/<n>` and needs the PR's branch checked out to test against it locally.
|
|
8
|
+
|
|
9
|
+
## Steps
|
|
10
|
+
|
|
11
|
+
1. **Resolve the PR's head branch:**
|
|
12
|
+
`gh pr view <n> --repo <org>/<repo> --json headRefName -q .headRefName`
|
|
13
|
+
2. **Sanitize the branch name** for filesystem use — replace `/` and other path separators with `-`. Example: `claude/regen-test-replay-flow-ZSScQ` → `claude-regen-test-replay-flow-ZSScQ`.
|
|
14
|
+
3. **Build the target worktree path:** `<repo>/.claude/worktrees/<sanitized-branch>`.
|
|
15
|
+
4. **Materialize the worktree:**
|
|
16
|
+
- If the target path does NOT exist:
|
|
17
|
+
- `git -C <repo> fetch origin <branch>`
|
|
18
|
+
- `git -C <repo> worktree add <target-path> <branch>`
|
|
19
|
+
- If the target path EXISTS (reused from a prior run):
|
|
20
|
+
- `git -C <target-path> fetch`
|
|
21
|
+
- `git -C <target-path> reset --hard origin/<branch>` — picks up new pushes, drops any local cruft.
|
|
22
|
+
5. **Use the worktree path as the working directory** for the rest of the run, including:
|
|
23
|
+
- Passing it as the **`cwd` parameter** to `muggle-local-execute-test-generation` and `muggle-local-execute-replay`. This is required, not optional — see `_shared/failure-mode-handling.md` and the lock identity discussion in those tools' MCP source.
|
|
24
|
+
- Resolving any `npm install` / dev-server start commands inside the worktree (it has its own `node_modules/` and `.env*` files).
|
|
25
|
+
6. **Tell the user** where the worktree lives so they can clean it up later with `git -C <repo> worktree remove <target-path>`.
|
|
26
|
+
|
|
27
|
+
## Invariants
|
|
28
|
+
|
|
29
|
+
- **Never switch the user's main checkout.** The whole point of this flow is isolation; `git checkout <branch>` on the main checkout is forbidden.
|
|
30
|
+
- **Never share `node_modules/` via symlink** across worktrees. Each worktree runs its own `npm install` (or `pnpm install`) — webpack's `resolve.symlinks: true` rewrites paths and breaks asset-identity tracking.
|
|
31
|
+
- **`.env*` files do not propagate.** A freshly created worktree has no env files unless the repo commits them. If the parent skill's dev server fails to boot, check whether `.env.local` (or framework equivalent) needs to be copied from the main checkout before launching.
|
|
@@ -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. Materialize the PR branch in a dedicated worktree per [`_shared/pr-branch-worktree.md`](../_shared/pr-branch-worktree.md). Use that worktree path as the `cwd` for the rest of the run (including the `cwd` parameter on local execute tools).
|
|
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."
|
|
@@ -265,6 +273,7 @@ Execution itself **must** be sequential because there is only one local Electron
|
|
|
265
273
|
1. Call `muggle-local-execute-test-generation`:
|
|
266
274
|
- `testCase`: Full test case object from the parallel fetch above
|
|
267
275
|
- `localUrl`: User's local URL from the pre-flight question
|
|
276
|
+
- `cwd`: Absolute path of the active working directory — the PR-branch worktree if one was created in Step 2, otherwise the user's repo root. Drives the cross-worktree single-flight lock so concurrent muggle-test runs from different branches serialize.
|
|
268
277
|
- `showUi`: from the `showElectronBrowser` resolution — omit (default visible) for `always`, pass `false` for `never`
|
|
269
278
|
- `freshSession`: `true` if the test case requires a clean browser state (see above), omit otherwise
|
|
270
279
|
2. Store the returned `runId` and tag the result `mode: "regen"`.
|
|
@@ -274,14 +283,16 @@ Execution itself **must** be sequential because there is only one local Electron
|
|
|
274
283
|
2. Call `muggle-local-execute-replay`:
|
|
275
284
|
- `testScript`: from `muggle-remote-test-script-get`
|
|
276
285
|
- `actionScript`: from `muggle-remote-action-script-get`
|
|
277
|
-
- `localUrl`, `showUi`, `freshSession`: same resolution as regen
|
|
286
|
+
- `localUrl`, `cwd`, `showUi`, `freshSession`: same resolution as regen
|
|
278
287
|
3. Store the returned `runId` and tag the result `mode: "replay"`.
|
|
279
288
|
|
|
280
289
|
If a run fails, log it and continue to the next — do not abort the batch. Failures are routed through Step 7C's post-failure handler after the batch completes.
|
|
281
290
|
|
|
282
291
|
### Collect results (in parallel)
|
|
283
292
|
|
|
284
|
-
For every `runId`, issue all `muggle-local-run-result-get` calls in parallel. Extract
|
|
293
|
+
For every `runId`, issue all `muggle-local-run-result-get` calls in parallel. Extract from the **structured response only** (not from `execute`'s stdout tail, which is a truncated display excerpt): `Status`, `Error`, `Duration`, and the `Artifacts` section (always present after a run completes — names `artifactsDir` and lists the files actually on disk).
|
|
294
|
+
|
|
295
|
+
For passed runs, `results.md` inside `artifactsDir` is the step-by-step verdict — read it before summarizing. For failed runs, `stdout.log` + `stderr.log` are always present and `action-script.json` is present when generation reached the step-emission stage (typical for `goal_not_achievable`); use `Error` as the headline verdict and route through Step 7C.
|
|
285
296
|
|
|
286
297
|
### Publish each run to cloud (gated by `autoPublishLocalResults`)
|
|
287
298
|
|
|
@@ -451,6 +462,7 @@ This is a suggestion, not automatic invocation. Skip silently if every test pass
|
|
|
451
462
|
## Guardrails
|
|
452
463
|
|
|
453
464
|
- **Always confirm intent first** — never assume local vs remote without asking
|
|
465
|
+
- **PR URLs always run in a dedicated worktree** — never switch the user's main checkout. Create or reuse `<repo>/.claude/worktrees/<sanitized-branch>` and pass that path as the `cwd` parameter to local execute tools. The cross-worktree single-flight lock relies on this to serialize concurrent runs from different branches.
|
|
454
466
|
- **User MUST select project** — present clickable options via `AskUserQuestion`, wait for explicit choice, never auto-select
|
|
455
467
|
- **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.
|
|
456
468
|
- **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.
|
|
@@ -195,8 +195,12 @@ If publish rejects with `has no generated actionScript steps to publish` (true z
|
|
|
195
195
|
|
|
196
196
|
### 9. Report
|
|
197
197
|
|
|
198
|
+
**Do not diagnose from `execute`'s response stdout tail.** That tail is a truncated excerpt for human display and routinely cuts off mid-sentence. The only ground truth is the run record.
|
|
199
|
+
|
|
198
200
|
- `muggle-local-run-result-get` with the run id from execute.
|
|
199
|
-
-
|
|
201
|
+
- **Read in this order:** `Status` → `Error` → **`Artifacts` section** (always present after a run completes; names `artifactsDir` and lists the files actually on disk: `action-script.json`, `results.md`, `screenshots/`, `stdout.log`, `stderr.log`). On a `passed` run, `results.md` is the step-by-step verdict with screenshot links — read it before summarizing.
|
|
202
|
+
- **On failure**, the `Artifacts` section is still present. `stdout.log` + `stderr.log` are always there. `action-script.json` is there when generation got far enough to emit it (typical for `goal_not_achievable` / mid-progress crashes — the file holds the agent's attempted steps + halt summary). `results.md` and per-step screenshots are absent on failure (electron-app only emits those on the successful completion path) — don't hunt elsewhere on disk for them.
|
|
203
|
+
- Include in the report: status, duration, pass/fail summary, per-step summary (passed runs), artifact paths, errors if failed, and script view URL when publishing ran.
|
|
200
204
|
|
|
201
205
|
### 9a. Route failures through the failure-mode handler
|
|
202
206
|
|
|
@@ -242,6 +246,7 @@ After reporting results:
|
|
|
242
246
|
|
|
243
247
|
- No silent auth skip.
|
|
244
248
|
- **Never prompt for Electron launch approval** before execution — invoking this skill is the approval. Just run.
|
|
249
|
+
- **Never diagnose a failed run from `execute`'s response stdout tail.** Always call `muggle-local-run-result-get` first; classify only from its structured fields and (when present) the artifacts it names. The execute tail is an excerpt and routinely truncates the failure cause.
|
|
245
250
|
- If replayable scripts exist, do not default to generation without user choice.
|
|
246
251
|
- No hiding failures: surface errors and artifact paths.
|
|
247
252
|
- **Always offer the agent-guidance reminder after every Electron run** (Step 9b) — pass or fail — unless 9a already routed the user into `muggle-feedback`. Never silently end a run without giving the user a one-click path to flag what was wrong.
|