@muggleai/works 5.0.4 → 5.1.0
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/README.md +2 -3
- package/dist/{chunk-XO5BQZM3.js → chunk-2BHC6TQR.js} +3 -4
- package/dist/{chunk-KDRSEHK5.js → chunk-MOHR7QUN.js} +197 -291
- 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/ensure-electron-app.sh +1 -1
- package/dist/plugin/scripts/guardrails.mjs +4 -2
- package/dist/plugin/skills/_shared/dev-loop/publish.md +4 -8
- package/dist/plugin/skills/_shared/pr-followup-helpers/allow-list.md +1 -1
- package/dist/plugin/skills/_shared/pr-followup-helpers/echo-skip.md +1 -1
- package/dist/plugin/skills/_shared/resolve-e2e-validation-context.md +1 -1
- package/dist/plugin/skills/_shared/test-case-chain-readiness.md +1 -2
- package/dist/plugin/skills/_shared/vcs/CLAUDE.md +9 -0
- package/dist/plugin/skills/_shared/vcs/detect-vcs.md +28 -0
- package/{plugin/skills/_shared/github-cli-recipes → dist/plugin/skills/_shared/vcs/github}/unresolved-threads.md +1 -1
- package/{plugin/skills/_shared/github-cli-recipes → dist/plugin/skills/_shared/vcs/github}/verify-working-tree.md +1 -1
- package/dist/plugin/skills/_shared/vcs/github.md +21 -0
- package/dist/plugin/skills/_shared/vcs/gitlab/loop-user-identity.md +9 -0
- package/dist/plugin/skills/_shared/vcs/gitlab/mr-create.md +11 -0
- package/dist/plugin/skills/_shared/vcs/gitlab/mr-discussions.md +18 -0
- package/dist/plugin/skills/_shared/vcs/gitlab/mr-edit.md +8 -0
- package/dist/plugin/skills/_shared/vcs/gitlab/mr-metadata.md +22 -0
- package/dist/plugin/skills/_shared/vcs/gitlab/mr-note.md +7 -0
- package/dist/plugin/skills/_shared/vcs/gitlab/mr-pipeline.md +27 -0
- package/dist/plugin/skills/_shared/vcs/gitlab/reply-discussion.md +9 -0
- package/dist/plugin/skills/_shared/vcs/gitlab/resolve-discussion.md +10 -0
- package/dist/plugin/skills/_shared/vcs/gitlab/unresolved-discussions.md +18 -0
- package/dist/plugin/skills/_shared/vcs/gitlab.md +24 -0
- package/dist/plugin/skills/do/address-reviews.md +10 -6
- package/dist/plugin/skills/do/e2e-acceptance.md +4 -4
- package/dist/plugin/skills/do/fix-ci.md +1 -1
- package/dist/plugin/skills/do/input-routing.md +4 -4
- package/dist/plugin/skills/do/open-prs/forward.md +6 -4
- package/dist/plugin/skills/do/open-prs/update.md +8 -6
- package/dist/plugin/skills/do/per-comment-replies.md +22 -13
- package/dist/plugin/skills/do/resolve-conflicts.md +1 -1
- package/dist/plugin/skills/do/resolve-reminder.md +8 -6
- package/dist/plugin/skills/muggle-browser-task/SKILL.md +1 -1
- package/dist/plugin/skills/muggle-do/SKILL.md +2 -2
- package/dist/plugin/skills/muggle-feedback/ops/submit.md +4 -4
- package/dist/plugin/skills/muggle-pr-followup/CLAUDE.md +2 -2
- package/dist/plugin/skills/muggle-pr-followup/bootstrap.md +13 -11
- package/dist/plugin/skills/muggle-pr-followup/contract.md +13 -9
- package/dist/plugin/skills/muggle-pr-followup/finalize.md +1 -1
- package/dist/plugin/skills/muggle-pr-followup/reconcile.md +1 -1
- package/dist/plugin/skills/muggle-pr-followup/state-schemas.md +4 -1
- package/dist/plugin/skills/muggle-pr-visual-walkthrough/e2e-report-assembly.md +13 -13
- package/dist/plugin/skills/muggle-preferences/ops/configure.md +2 -2
- package/dist/plugin/skills/muggle-test/SKILL.md +23 -126
- package/dist/plugin/skills/muggle-test/execute-local.md +60 -0
- package/dist/plugin/skills/muggle-test/execute-remote.md +49 -0
- package/dist/plugin/skills/muggle-test/reference.md +1 -2
- package/dist/plugin/skills/muggle-test-feature-local/SKILL.md +5 -5
- package/dist/release-manifest.json +4 -4
- package/dist/{src-2O5UH4FA.js → src-SS2AL3O7.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/ensure-electron-app.sh +1 -1
- package/plugin/scripts/guardrails.mjs +4 -2
- package/plugin/skills/_shared/dev-loop/publish.md +4 -8
- package/plugin/skills/_shared/pr-followup-helpers/allow-list.md +1 -1
- package/plugin/skills/_shared/pr-followup-helpers/echo-skip.md +1 -1
- package/plugin/skills/_shared/resolve-e2e-validation-context.md +1 -1
- package/plugin/skills/_shared/test-case-chain-readiness.md +1 -2
- package/plugin/skills/_shared/vcs/CLAUDE.md +9 -0
- package/plugin/skills/_shared/vcs/detect-vcs.md +28 -0
- package/{dist/plugin/skills/_shared/github-cli-recipes → plugin/skills/_shared/vcs/github}/unresolved-threads.md +1 -1
- package/{dist/plugin/skills/_shared/github-cli-recipes → plugin/skills/_shared/vcs/github}/verify-working-tree.md +1 -1
- package/plugin/skills/_shared/vcs/github.md +21 -0
- package/plugin/skills/_shared/vcs/gitlab/loop-user-identity.md +9 -0
- package/plugin/skills/_shared/vcs/gitlab/mr-create.md +11 -0
- package/plugin/skills/_shared/vcs/gitlab/mr-discussions.md +18 -0
- package/plugin/skills/_shared/vcs/gitlab/mr-edit.md +8 -0
- package/plugin/skills/_shared/vcs/gitlab/mr-metadata.md +22 -0
- package/plugin/skills/_shared/vcs/gitlab/mr-note.md +7 -0
- package/plugin/skills/_shared/vcs/gitlab/mr-pipeline.md +27 -0
- package/plugin/skills/_shared/vcs/gitlab/reply-discussion.md +9 -0
- package/plugin/skills/_shared/vcs/gitlab/resolve-discussion.md +10 -0
- package/plugin/skills/_shared/vcs/gitlab/unresolved-discussions.md +18 -0
- package/plugin/skills/_shared/vcs/gitlab.md +24 -0
- package/plugin/skills/do/address-reviews.md +10 -6
- package/plugin/skills/do/e2e-acceptance.md +4 -4
- package/plugin/skills/do/fix-ci.md +1 -1
- package/plugin/skills/do/input-routing.md +4 -4
- package/plugin/skills/do/open-prs/forward.md +6 -4
- package/plugin/skills/do/open-prs/update.md +8 -6
- package/plugin/skills/do/per-comment-replies.md +22 -13
- package/plugin/skills/do/resolve-conflicts.md +1 -1
- package/plugin/skills/do/resolve-reminder.md +8 -6
- package/plugin/skills/muggle-browser-task/SKILL.md +1 -1
- package/plugin/skills/muggle-do/SKILL.md +2 -2
- package/plugin/skills/muggle-feedback/ops/submit.md +4 -4
- package/plugin/skills/muggle-pr-followup/CLAUDE.md +2 -2
- package/plugin/skills/muggle-pr-followup/bootstrap.md +13 -11
- package/plugin/skills/muggle-pr-followup/contract.md +13 -9
- package/plugin/skills/muggle-pr-followup/finalize.md +1 -1
- package/plugin/skills/muggle-pr-followup/reconcile.md +1 -1
- package/plugin/skills/muggle-pr-followup/state-schemas.md +4 -1
- package/plugin/skills/muggle-pr-visual-walkthrough/e2e-report-assembly.md +13 -13
- package/plugin/skills/muggle-preferences/ops/configure.md +2 -2
- package/plugin/skills/muggle-test/SKILL.md +23 -126
- package/plugin/skills/muggle-test/execute-local.md +60 -0
- package/plugin/skills/muggle-test/execute-remote.md +49 -0
- package/plugin/skills/muggle-test/reference.md +1 -2
- package/plugin/skills/muggle-test-feature-local/SKILL.md +5 -5
- package/dist/plugin/skills/_shared/github-cli-recipes.md +0 -21
- package/dist/plugin/skills/muggle-preferences/preference-gates/autoPublishLocalResults.md +0 -11
- package/plugin/skills/_shared/github-cli-recipes.md +0 -21
- package/plugin/skills/muggle-preferences/preference-gates/autoPublishLocalResults.md +0 -11
- /package/dist/plugin/skills/_shared/{github-cli-recipes → vcs/github}/line-comments-for-review.md +0 -0
- /package/dist/plugin/skills/_shared/{github-cli-recipes → vcs/github}/loop-user-identity.md +0 -0
- /package/dist/plugin/skills/_shared/{github-cli-recipes → vcs/github}/pr-checks.md +0 -0
- /package/dist/plugin/skills/_shared/{github-cli-recipes → vcs/github}/pr-edit.md +0 -0
- /package/dist/plugin/skills/_shared/{github-cli-recipes → vcs/github}/pr-metadata.md +0 -0
- /package/dist/plugin/skills/_shared/{github-cli-recipes → vcs/github}/push-to-branch.md +0 -0
- /package/dist/plugin/skills/_shared/{github-cli-recipes → vcs/github}/reply-line-comment.md +0 -0
- /package/dist/plugin/skills/_shared/{github-cli-recipes → vcs/github}/submitted-reviews.md +0 -0
- /package/dist/plugin/skills/_shared/{github-cli-recipes → vcs/github}/top-level-comment.md +0 -0
- /package/plugin/skills/_shared/{github-cli-recipes → vcs/github}/line-comments-for-review.md +0 -0
- /package/plugin/skills/_shared/{github-cli-recipes → vcs/github}/loop-user-identity.md +0 -0
- /package/plugin/skills/_shared/{github-cli-recipes → vcs/github}/pr-checks.md +0 -0
- /package/plugin/skills/_shared/{github-cli-recipes → vcs/github}/pr-edit.md +0 -0
- /package/plugin/skills/_shared/{github-cli-recipes → vcs/github}/pr-metadata.md +0 -0
- /package/plugin/skills/_shared/{github-cli-recipes → vcs/github}/push-to-branch.md +0 -0
- /package/plugin/skills/_shared/{github-cli-recipes → vcs/github}/reply-line-comment.md +0 -0
- /package/plugin/skills/_shared/{github-cli-recipes → vcs/github}/submitted-reviews.md +0 -0
- /package/plugin/skills/_shared/{github-cli-recipes → vcs/github}/top-level-comment.md +0 -0
|
@@ -7,7 +7,7 @@ description: "Change-driven E2E acceptance testing with Muggle AI: detect the us
|
|
|
7
7
|
|
|
8
8
|
> Telemetry first step: see [`_shared/telemetry-emit.md`](../_shared/telemetry-emit.md). Use `skillName: "muggle-test"`.
|
|
9
9
|
|
|
10
|
-
A router skill that detects code changes, resolves impacted test cases, executes them locally or remotely,
|
|
10
|
+
A router skill that detects code changes, resolves impacted test cases, executes them locally or remotely, reads the cloud results from the Muggle AI dashboard (local runs are published by the studio during execution; remote runs publish cloud-side), and posts E2E acceptance summaries to the PR. The user can invoke this at any moment, in any state.
|
|
11
11
|
|
|
12
12
|
## UX Guidelines — Minimize Typing
|
|
13
13
|
|
|
@@ -42,11 +42,10 @@ Gates run per `preference-gates/README.md`.
|
|
|
42
42
|
|------------|------|-------------------|
|
|
43
43
|
| `autoLogin` | 3 | Reuse saved credentials when auth is required |
|
|
44
44
|
| `autoSelectProject` | 4 | Reuse last-used Muggle Test project for this repo |
|
|
45
|
-
| `autoSelectLocalHost` |
|
|
45
|
+
| `autoSelectLocalHost` | execute-local | Reuse last-used local dev server URL for this repo |
|
|
46
46
|
| `autoDetectChanges` | 2 | Scan local git changes and map to affected test cases |
|
|
47
47
|
| `defaultExecutionMode` | 1 | Default to local or remote test execution |
|
|
48
|
-
| `
|
|
49
|
-
| `showElectronBrowser` | 7A | Show the Electron browser window during local test execution (vs. run headless) |
|
|
48
|
+
| `showElectronBrowser` | execute-local | Show the Electron browser window during local test execution (vs. run headless) |
|
|
50
49
|
| `postPRVisualWalkthrough` | 9 | Post visual walkthrough to PR after results are available |
|
|
51
50
|
| `autoCreatePR` | 9 (if no PR) | Auto-create the PR when posting the walkthrough has no PR to target |
|
|
52
51
|
| `autoWatchPR` | 9.5 (if a PR exists) | Start a `muggle-pr-followup` watcher on the PR after the run |
|
|
@@ -235,139 +234,37 @@ Then show the per-case decision in one `AskUserQuestion`:
|
|
|
235
234
|
|
|
236
235
|
If the user picks "Override one or more", let them flip the mode for any test case via a second multi-select `AskUserQuestion`. Emit a follow-up `pre-execution-classification` event with `userAction` set whenever the user overrides.
|
|
237
236
|
|
|
238
|
-
## Step
|
|
237
|
+
## Step 7: Execute
|
|
239
238
|
|
|
240
|
-
###
|
|
239
|
+
### Fetch test case details (both modes)
|
|
241
240
|
|
|
242
|
-
|
|
241
|
+
Hydrate every selected test case **once**, before dispatch: issue **all** `muggle-remote-test-case-get` calls in parallel (single message, multiple tool calls). Both paths consume the result — never re-fetch inside a path.
|
|
243
242
|
|
|
244
|
-
###
|
|
243
|
+
### Dispatch by mode
|
|
245
244
|
|
|
246
|
-
|
|
247
|
-
- **Read the cache**: `Muggle Test Last Host: <url>` session-context line, or `muggle-local-last-host-get`. Pass as `{lastHost}` substitution.
|
|
248
|
-
- **Auto-detect a suggested URL**: `lsof -iTCP -sTCP:LISTEN -nP | grep -E ':(3000|3001|4200|5173|8080)'`. Pass as `{suggestedHost}`.
|
|
249
|
-
- **Save the cache**: call `muggle-local-last-host-set` after the user picks (the gate file requires this on every pick).
|
|
245
|
+
Run the path matching the mode confirmed in Step 1. Each path owns its own process and returns a **uniform runs list** — `[{ testCaseId, mode, runId | runtimeId, status, viewUrl? }]` — that Steps 7C–10 consume mode-agnostically.
|
|
250
246
|
|
|
251
|
-
|
|
252
|
-
|
|
253
|
-
### Pre-flight visibility (gated by `showElectronBrowser`)
|
|
254
|
-
|
|
255
|
-
Gate `showElectronBrowser` (per `preference-gates/README.md`). Resolve once; apply same `showUi` to every test case.
|
|
256
|
-
- `always` → omit `showUi` (defaults visible).
|
|
257
|
-
- `never` → pass `showUi: false`.
|
|
258
|
-
- `ask` → run Picker 1 from `preference-gates/showElectronBrowser.md` via `AskUserQuestion`; map the answer back to one of the actions above.
|
|
259
|
-
|
|
260
|
-
### Fetch test case details (in parallel)
|
|
261
|
-
|
|
262
|
-
Before execution, fetch full test case details for all selected test cases by issuing **all** `muggle-remote-test-case-get` calls in parallel (single message, multiple tool calls).
|
|
263
|
-
|
|
264
|
-
### Run the dev loop
|
|
265
|
-
|
|
266
|
-
Execute each selected test case via the shared loop in [`../_shared/dev-loop/run.md`](../_shared/dev-loop/run.md): [sequential replay/regen](../_shared/dev-loop/run.md), [`actionScript` as-is](../_shared/dev-loop/action-script.md), [`freshSession`](../_shared/dev-loop/fresh-session.md), and [`timeoutMs`](../_shared/dev-loop/timeouts.md).
|
|
267
|
-
|
|
268
|
-
Caller glue:
|
|
269
|
-
- `mode` per test case comes from Step 6f; `localUrl` from the pre-flight question; `showUi` from the `showElectronBrowser` resolution.
|
|
270
|
-
- `cwd` = the PR-branch worktree from Step 2 if one was created, else the user's repo root — it drives the cross-worktree single-flight lock so concurrent muggle-test runs from different branches serialize.
|
|
271
|
-
- On a failed run, continue the batch and route it through Step 7C after completion.
|
|
272
|
-
|
|
273
|
-
### Collect results
|
|
274
|
-
|
|
275
|
-
Fetch every `runId` per [`../_shared/dev-loop/failures.md`](../_shared/dev-loop/failures.md), reading structured fields and [interpreting failures](../_shared/dev-loop/failures.md) — never `execute`'s stdout tail. Issue the `muggle-local-run-result-get` calls in parallel; use `Error` as the headline for failures and route through Step 7C.
|
|
276
|
-
|
|
277
|
-
### Publish each run to cloud (gated by `autoPublishLocalResults`)
|
|
278
|
-
|
|
279
|
-
Gate `autoPublishLocalResults` (per `preference-gates/README.md`):
|
|
280
|
-
- `always` → proceed to publish logic below.
|
|
281
|
-
- `never` → skip to report summary; tell user Steps 8/9 and per-step screenshots are unavailable without publishing.
|
|
282
|
-
- `ask` → run Picker 1 from `preference-gates/autoPublishLocalResults.md` via `AskUserQuestion`; map the answer back to one of the actions above.
|
|
283
|
-
|
|
284
|
-
### Publish logic (when publishing is enabled)
|
|
285
|
-
|
|
286
|
-
Publish every completed run per [`../_shared/dev-loop/publish.md`](../_shared/dev-loop/publish.md) — parallel `muggle-local-publish-test-script` with the zero-step `muggle-remote-local-run-upload` fallback. Store every `viewUrl`, `testScriptId`, `actionScriptId` — used in the next steps.
|
|
287
|
-
|
|
288
|
-
### Report summary
|
|
289
|
-
|
|
290
|
-
```
|
|
291
|
-
Test Case Status Duration Steps View Steps on Muggle AI
|
|
292
|
-
─────────────────────────────────────────────────────────────────────────
|
|
293
|
-
Login with valid creds PASSED 12.3s 8 https://www.muggle-ai.com/...
|
|
294
|
-
Login with invalid creds PASSED 9.1s 6 https://www.muggle-ai.com/...
|
|
295
|
-
Checkout flow FAILED 15.7s 12 https://www.muggle-ai.com/...
|
|
296
|
-
─────────────────────────────────────────────────────────────────────────
|
|
297
|
-
Total: 3 tests | 2 passed | 1 failed | 37.1s
|
|
298
|
-
```
|
|
299
|
-
|
|
300
|
-
For failures, don't hand-write a verdict in the summary — route each through the debug path (Step 7C).
|
|
301
|
-
|
|
302
|
-
## Step 7B: Execute — Remote Mode
|
|
303
|
-
|
|
304
|
-
### Ask for target URL
|
|
305
|
-
|
|
306
|
-
> "What's the preview/staging URL to test against?"
|
|
307
|
-
|
|
308
|
-
### Fetch test case details (in parallel)
|
|
309
|
-
|
|
310
|
-
Issue all `muggle-remote-test-case-get` calls in parallel (single message, multiple tool calls) to hydrate the test case bodies.
|
|
311
|
-
|
|
312
|
-
### Trigger remote workflows (in parallel)
|
|
313
|
-
|
|
314
|
-
Branch each test case on the mode chosen in Step 6f, then issue **all** workflow-start calls in parallel — never loop them sequentially. Mix regen and replay starts in the same parallel batch.
|
|
315
|
-
|
|
316
|
-
**Regen-mode test case** — `muggle-remote-workflow-start-test-script-generation`:
|
|
317
|
-
|
|
318
|
-
- `projectId`: The project ID
|
|
319
|
-
- `useCaseId`: The use case ID
|
|
320
|
-
- `testCaseId`: The test case ID
|
|
321
|
-
- `name`: `"muggle-test: {test case title}"`
|
|
322
|
-
- `url`: The preview/staging URL
|
|
323
|
-
- `goal`: From the test case
|
|
324
|
-
- `precondition`: From the test case (use `"None"` if empty)
|
|
325
|
-
- `instructions`: From the test case
|
|
326
|
-
- `expectedResult`: From the test case
|
|
327
|
-
|
|
328
|
-
**Replay-mode test case** — `muggle-remote-workflow-start-test-script-replay` against the latest replayable script for that test case (resolve via `muggle-remote-test-script-list` if not already in hand from Step 6f). Tag results with `mode: "replay"` so Step 7C can route failures correctly.
|
|
329
|
-
|
|
330
|
-
Store each returned workflow runtime ID along with its mode tag.
|
|
331
|
-
|
|
332
|
-
### Monitor and report (in parallel)
|
|
333
|
-
|
|
334
|
-
Issue all `muggle-remote-wf-get-ts-gen-latest-run` calls in parallel, one per runtime ID.
|
|
335
|
-
|
|
336
|
-
```
|
|
337
|
-
Test Case Workflow Status Runtime ID
|
|
338
|
-
────────────────────────────────────────────────────────
|
|
339
|
-
Login with valid creds RUNNING rt-abc123
|
|
340
|
-
Login with invalid creds COMPLETED rt-def456
|
|
341
|
-
Checkout flow QUEUED rt-ghi789
|
|
342
|
-
```
|
|
247
|
+
- **Mode A (Local)** → [`execute-local.md`](execute-local.md). Inputs: the hydrated test cases, per-case `mode` from Step 6f, and `cwd` (the PR-branch worktree from Step 2 if one exists, else the repo root).
|
|
248
|
+
- **Mode B (Remote)** → [`execute-remote.md`](execute-remote.md). Inputs: the hydrated test cases, per-case `mode` from Step 6f, `projectId` / `useCaseId`.
|
|
343
249
|
|
|
344
250
|
## Step 7C: Route every failed run through the debug path
|
|
345
251
|
|
|
346
|
-
For every run with `status: "failed"` (or any non-passing terminal state)
|
|
252
|
+
For every run with `status: "failed"` (or any non-passing terminal state) returned by Step 7 (either path), route through [`_shared/debug-failed-run.md`](../_shared/debug-failed-run.md). This is **mandatory** — a failure is never reported without it. The debug path gathers evidence (attempted steps + reasoning + screenshot), diagnoses via [`_shared/failure-mode-handling.md`](../_shared/failure-mode-handling.md) (§B replay / §C regen), shows the debug card, and presents the guaranteed selection in which **"give feedback & rerun"** is always an option and "skip" is never the default.
|
|
347
253
|
|
|
348
|
-
Pass it per failed run: the `runId` (local) or workflow runtime id (remote), the `mode` that failed, `testCaseId`, `projectId`, and the execution handle (local:
|
|
254
|
+
Pass it per failed run: the `runId` (local) or workflow runtime id (remote), the `mode` that failed, `testCaseId`, `projectId`, and the execution handle (local: [`execute-local.md`](execute-local.md); remote: [`execute-remote.md`](execute-remote.md)) so a rerun re-enters the same path. Process failures one at a time so the user isn't drowning in pickers.
|
|
349
255
|
|
|
350
256
|
## Step 8: Open Results in Browser
|
|
351
257
|
|
|
352
|
-
After execution
|
|
353
|
-
|
|
354
|
-
### Mode A (Local) — open each published viewUrl
|
|
355
|
-
|
|
356
|
-
For each published run's `viewUrl`:
|
|
357
|
-
```bash
|
|
358
|
-
open "https://www.muggle-ai.com/muggleTestV0/dashboard/projects/{projectId}/scripts?modal=script-details&testCaseId={testCaseId}"
|
|
359
|
-
```
|
|
360
|
-
|
|
361
|
-
If there are many runs (>3), open just the project-level runs page instead of individual tabs:
|
|
362
|
-
```bash
|
|
363
|
-
open "https://www.muggle-ai.com/muggleTestV0/dashboard/projects/{projectId}/runs"
|
|
364
|
-
```
|
|
365
|
-
|
|
366
|
-
### Mode B (Remote) — open the project runs page
|
|
258
|
+
After execution, open the Muggle AI dashboard so the user can inspect results and screenshots. The studio published every local run during execution, so each run result already carries its `viewUrl` (read it from `muggle-local-run-result-get`). Key off the uniform runs list:
|
|
367
259
|
|
|
368
|
-
|
|
369
|
-
|
|
370
|
-
|
|
260
|
+
- **Runs carry a `viewUrl` and there are ≤3** — open each:
|
|
261
|
+
```bash
|
|
262
|
+
open "https://www.muggle-ai.com/muggleTestV0/dashboard/projects/{projectId}/scripts?modal=script-details&testCaseId={testCaseId}"
|
|
263
|
+
```
|
|
264
|
+
- **Otherwise** (more than 3 runs, or a run with no `viewUrl`) — open the project runs page:
|
|
265
|
+
```bash
|
|
266
|
+
open "https://www.muggle-ai.com/muggleTestV0/dashboard/projects/{projectId}/runs"
|
|
267
|
+
```
|
|
371
268
|
|
|
372
269
|
Tell the user:
|
|
373
270
|
> "I've opened the Muggle AI dashboard in your browser — you can see the test results, step-by-step screenshots, and action scripts there."
|
|
@@ -379,7 +276,7 @@ After reporting results:
|
|
|
379
276
|
1. Fire [`postPRVisualWalkthrough`](../muggle-preferences/preference-gates/postPRVisualWalkthrough.md). On skip → Step 9.5.
|
|
380
277
|
2. `gh pr view --json number,title,url 2>/dev/null` — find the PR.
|
|
381
278
|
3. If no PR: fire [`autoCreatePR`](../muggle-preferences/preference-gates/autoCreatePR.md). On skip → Step 9.5.
|
|
382
|
-
4. Assemble the `E2eReport` — see [`../muggle-pr-visual-walkthrough/e2e-report-assembly.md`](../muggle-pr-visual-walkthrough/e2e-report-assembly.md). Include all runs from Step
|
|
279
|
+
4. Assemble the `E2eReport` — see [`../muggle-pr-visual-walkthrough/e2e-report-assembly.md`](../muggle-pr-visual-walkthrough/e2e-report-assembly.md). Include all runs from Step 7 (passed and failed).
|
|
383
280
|
5. Invoke [`../muggle-pr-visual-walkthrough/SKILL.md`](../muggle-pr-visual-walkthrough/SKILL.md) Mode A with the `E2eReport`.
|
|
384
281
|
|
|
385
282
|
## Step 9.5: Offer to watch the PR for review follow-ups
|
|
@@ -414,6 +311,6 @@ Each rule below is covered in-step above; these are the ones this skill most oft
|
|
|
414
311
|
- **PR URLs run in a dedicated worktree** — never switch the user's main checkout; pass that worktree as `cwd`.
|
|
415
312
|
- **Every selection uses `AskUserQuestion`** — never ask the user to type a number; the user picks the project (never auto-select).
|
|
416
313
|
- **Parallelize independent cloud jobs**; the only sequential loop is local Electron execution (one browser).
|
|
417
|
-
- **
|
|
314
|
+
- **Read cloud refs off the run result** (the studio published during execution) and delegate PR posting to `muggle-pr-visual-walkthrough` — never inline the walkthrough or call `gh pr comment` here.
|
|
418
315
|
|
|
419
316
|
Phase→tool map and multi-agent (acceptance-tester) dispatch: [`reference.md`](reference.md).
|
|
@@ -0,0 +1,60 @@
|
|
|
1
|
+
# Muggle Test — Local Execution Path (Mode A)
|
|
2
|
+
|
|
3
|
+
> The Local execution process for the `muggle-test` router: run the selected test cases against localhost via the Electron browser and collect results. The studio publishes each run to the cloud during execution, so the run result already carries the cloud refs. Returns a uniform runs list to the router. Per-test-case mechanics are shared with [`../_shared/dev-loop/run.md`](../_shared/dev-loop/run.md).
|
|
4
|
+
|
|
5
|
+
## Inputs (the router passes these in)
|
|
6
|
+
|
|
7
|
+
- The hydrated test cases (fetched once by the router before dispatch).
|
|
8
|
+
- Per-case `mode` — `replay` or `regen`, chosen during replay-vs-regen classification.
|
|
9
|
+
- `cwd` — the PR-branch worktree if one exists, else the repo root.
|
|
10
|
+
|
|
11
|
+
## Local environment readiness
|
|
12
|
+
|
|
13
|
+
Before anything else, invoke [`muggle-test-prepare`](../muggle-test-prepare/SKILL.md) — the readiness/service-start owner (idempotent; halt on what it surfaces). The URL gate below only *selects* the target; prepare is what guarantees something is listening and compiled.
|
|
14
|
+
|
|
15
|
+
## Pre-flight question — Local URL (gated by `autoSelectLocalHost`)
|
|
16
|
+
|
|
17
|
+
Skill responsibilities (the rest is in `preference-gates/autoSelectLocalHost.md`):
|
|
18
|
+
- **Read the cache**: `Muggle Test Last Host: <url>` session-context line, or `muggle-local-last-host-get`. Pass as `{lastHost}` substitution.
|
|
19
|
+
- **Auto-detect a suggested URL**: `lsof -iTCP -sTCP:LISTEN -nP | grep -E ':(3000|3001|4200|5173|8080)'`. Pass as `{suggestedHost}`.
|
|
20
|
+
- **Save the cache**: call `muggle-local-last-host-set` after the user picks (the gate file requires this on every pick).
|
|
21
|
+
|
|
22
|
+
Gate `autoSelectLocalHost` per `preference-gates/README.md` + `preference-gates/autoSelectLocalHost.md`.
|
|
23
|
+
|
|
24
|
+
## Pre-flight visibility (gated by `showElectronBrowser`)
|
|
25
|
+
|
|
26
|
+
Gate `showElectronBrowser` (per `preference-gates/README.md`). Resolve once; apply same `showUi` to every test case.
|
|
27
|
+
- `always` → omit `showUi` (defaults visible).
|
|
28
|
+
- `never` → pass `showUi: false`.
|
|
29
|
+
- `ask` → run Picker 1 from `preference-gates/showElectronBrowser.md` via `AskUserQuestion`; map the answer back to one of the actions above.
|
|
30
|
+
|
|
31
|
+
## Run the dev loop
|
|
32
|
+
|
|
33
|
+
Execute each test case via the shared loop in [`../_shared/dev-loop/run.md`](../_shared/dev-loop/run.md): [sequential replay/regen](../_shared/dev-loop/run.md), [`actionScript` as-is](../_shared/dev-loop/action-script.md), [`freshSession`](../_shared/dev-loop/fresh-session.md), and [`timeoutMs`](../_shared/dev-loop/timeouts.md).
|
|
34
|
+
|
|
35
|
+
Caller glue:
|
|
36
|
+
- `mode` per test case is the input from the router; `localUrl` from the pre-flight question; `showUi` from the `showElectronBrowser` resolution.
|
|
37
|
+
- `cwd` is the input from the router — it drives the cross-worktree single-flight lock so concurrent muggle-test runs from different branches serialize.
|
|
38
|
+
- On a failed run, continue the batch; the router routes failures through the debug path after this path returns.
|
|
39
|
+
|
|
40
|
+
## Collect results
|
|
41
|
+
|
|
42
|
+
Fetch every `runId` per [`../_shared/dev-loop/failures.md`](../_shared/dev-loop/failures.md), reading structured fields and [interpreting failures](../_shared/dev-loop/failures.md) — never `execute`'s stdout tail. Issue the `muggle-local-run-result-get` calls in parallel; use `Error` as the headline for failures. The studio already published each run, so the same call surfaces `viewUrl` / `cloudTestScriptId` / `cloudActionScriptId` — retain them per [`../_shared/dev-loop/publish.md`](../_shared/dev-loop/publish.md) for the dashboard and walkthrough.
|
|
43
|
+
|
|
44
|
+
## Report summary
|
|
45
|
+
|
|
46
|
+
```
|
|
47
|
+
Test Case Status Duration Steps View Steps on Muggle AI
|
|
48
|
+
─────────────────────────────────────────────────────────────────────────
|
|
49
|
+
Login with valid creds PASSED 12.3s 8 https://www.muggle-ai.com/...
|
|
50
|
+
Login with invalid creds PASSED 9.1s 6 https://www.muggle-ai.com/...
|
|
51
|
+
Checkout flow FAILED 15.7s 12 https://www.muggle-ai.com/...
|
|
52
|
+
─────────────────────────────────────────────────────────────────────────
|
|
53
|
+
Total: 3 tests | 2 passed | 1 failed | 37.1s
|
|
54
|
+
```
|
|
55
|
+
|
|
56
|
+
For failures, don't hand-write a verdict — the router routes each through the debug path.
|
|
57
|
+
|
|
58
|
+
## Output
|
|
59
|
+
|
|
60
|
+
Return the uniform runs list the router consumes: `[{ testCaseId, mode, runId, status, viewUrl?, cloudTestScriptId?, cloudActionScriptId? }]`. The studio published each run during execution, so `viewUrl` / `cloudTestScriptId` / `cloudActionScriptId` come straight off the run result (`muggle-local-run-result-get`).
|
|
@@ -0,0 +1,49 @@
|
|
|
1
|
+
# Muggle Test — Remote Execution Path (Mode B)
|
|
2
|
+
|
|
3
|
+
> The Remote execution process for the `muggle-test` router: trigger cloud test-script generation/replay against a preview/staging URL and monitor. Returns a uniform runs list to the router.
|
|
4
|
+
|
|
5
|
+
## Inputs (the router passes these in)
|
|
6
|
+
|
|
7
|
+
- The hydrated test cases (fetched once by the router before dispatch).
|
|
8
|
+
- Per-case `mode` — `replay` or `regen`, chosen during replay-vs-regen classification.
|
|
9
|
+
- `projectId`, `useCaseId`.
|
|
10
|
+
|
|
11
|
+
## Ask for target URL
|
|
12
|
+
|
|
13
|
+
> "What's the preview/staging URL to test against?"
|
|
14
|
+
|
|
15
|
+
## Trigger remote workflows (in parallel)
|
|
16
|
+
|
|
17
|
+
Branch each test case on its `mode`, then issue **all** workflow-start calls in parallel — never loop them sequentially. Mix regen and replay starts in the same parallel batch.
|
|
18
|
+
|
|
19
|
+
**Regen-mode test case** — `muggle-remote-workflow-start-test-script-generation`:
|
|
20
|
+
|
|
21
|
+
- `projectId`: The project ID
|
|
22
|
+
- `useCaseId`: The use case ID
|
|
23
|
+
- `testCaseId`: The test case ID
|
|
24
|
+
- `name`: `"muggle-test: {test case title}"`
|
|
25
|
+
- `url`: The preview/staging URL
|
|
26
|
+
- `goal`: From the test case
|
|
27
|
+
- `precondition`: From the test case (use `"None"` if empty)
|
|
28
|
+
- `instructions`: From the test case
|
|
29
|
+
- `expectedResult`: From the test case
|
|
30
|
+
|
|
31
|
+
**Replay-mode test case** — `muggle-remote-workflow-start-test-script-replay` against the latest replayable script for that test case (resolve via `muggle-remote-test-script-list` if not already in hand from the classification step). Tag results with `mode: "replay"` so the router routes failures correctly.
|
|
32
|
+
|
|
33
|
+
Store each returned workflow runtime ID along with its mode tag.
|
|
34
|
+
|
|
35
|
+
## Monitor and report (in parallel)
|
|
36
|
+
|
|
37
|
+
Issue all `muggle-remote-wf-get-ts-gen-latest-run` calls in parallel, one per runtime ID.
|
|
38
|
+
|
|
39
|
+
```
|
|
40
|
+
Test Case Workflow Status Runtime ID
|
|
41
|
+
────────────────────────────────────────────────────────
|
|
42
|
+
Login with valid creds RUNNING rt-abc123
|
|
43
|
+
Login with invalid creds COMPLETED rt-def456
|
|
44
|
+
Checkout flow QUEUED rt-ghi789
|
|
45
|
+
```
|
|
46
|
+
|
|
47
|
+
## Output
|
|
48
|
+
|
|
49
|
+
Return the uniform runs list the router consumes: `[{ testCaseId, mode, runtimeId, status }]`.
|
|
@@ -23,9 +23,8 @@ Lookup material pulled out of `SKILL.md` to keep the always-loaded body lean. Ev
|
|
|
23
23
|
| Execute (regen) | `muggle-remote-workflow-start-test-script-generation` | Remote |
|
|
24
24
|
| Execute (replay) | `muggle-remote-workflow-start-test-script-replay` | Remote |
|
|
25
25
|
| Failure-mode telemetry | `muggle-local-telemetry-event-emit` | Both |
|
|
26
|
-
| Results | `muggle-local-run-result-get` | Local |
|
|
26
|
+
| Results + cloud refs (studio-published `viewUrl` / `cloudTestScriptId` / `cloudActionScriptId`) | `muggle-local-run-result-get` | Local |
|
|
27
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
28
|
| Per-step screenshots (for walkthrough) | `muggle-remote-test-script-get` | Both |
|
|
30
29
|
| Browser | `open` (shell command) | Both |
|
|
31
30
|
| PR walkthrough | `muggle-pr-visual-walkthrough` (shared skill) | Both |
|
|
@@ -12,7 +12,7 @@ description: Run a real-browser end-to-end (E2E) acceptance test against localho
|
|
|
12
12
|
| Scope | MCP tools |
|
|
13
13
|
| :---- | :-------- |
|
|
14
14
|
| Cloud (projects, cases, scripts, auth) | `muggle-remote-*` |
|
|
15
|
-
| Local (Electron run,
|
|
15
|
+
| Local (Electron run, results — the studio publishes during the run) | `muggle-local-*` |
|
|
16
16
|
| Create new entities (preview / create) | `muggle-remote-project-create`, `muggle-remote-use-case-prompt-preview`, `muggle-remote-use-case-create-from-prompts`, `muggle-remote-test-case-generate-from-prompt`, `muggle-remote-test-case-create` |
|
|
17
17
|
|
|
18
18
|
The local URL only changes where the browser opens; it does not change the remote project or test definitions.
|
|
@@ -158,11 +158,11 @@ Gate `showElectronBrowser` (per `preference-gates/README.md`). Reuse the choice
|
|
|
158
158
|
|
|
159
159
|
`showUi` is only ever omitted or `false` — never pass `showUi: true`.
|
|
160
160
|
|
|
161
|
-
### 8.
|
|
161
|
+
### 8. Open the run on the dashboard (`viewUrl` gated by `openTestResultsAfterRun`)
|
|
162
162
|
|
|
163
|
-
|
|
163
|
+
The studio publishes every completed run — pass or fail — to the cloud during execution, so the run result already carries the cloud refs. Failed runs are published too, so reviewers get the per-step screenshots, not just a generic "failed" link.
|
|
164
164
|
|
|
165
|
-
-
|
|
165
|
+
- Read the cloud refs per [`../_shared/dev-loop/publish.md`](../_shared/dev-loop/publish.md): `viewUrl` / `cloudTestScriptId` / `cloudActionScriptId` from `muggle-local-run-result-get`.
|
|
166
166
|
- Gate `openTestResultsAfterRun` (per `preference-gates/README.md`):
|
|
167
167
|
- `always` → open `viewUrl` automatically (`open "<viewUrl>"` on macOS or OS equivalent).
|
|
168
168
|
- `never` → print the URL only.
|
|
@@ -172,7 +172,7 @@ Upload pass-or-fail. Failed runs still need cloud-hosted screenshots and per-ste
|
|
|
172
172
|
|
|
173
173
|
Read the run record per [`../_shared/dev-loop/failures.md`](../_shared/dev-loop/failures.md) and [failure interpretation](../_shared/dev-loop/failures.md) — never diagnose from `execute`'s stdout tail.
|
|
174
174
|
|
|
175
|
-
- Include in the report: status, duration, pass/fail summary, per-step summary (passed runs), artifact paths, errors if failed, and
|
|
175
|
+
- Include in the report: status, duration, pass/fail summary, per-step summary (passed runs), artifact paths, errors if failed, and the `viewUrl` from the run result.
|
|
176
176
|
|
|
177
177
|
### 9a. Route a failed run through the debug path
|
|
178
178
|
|
|
@@ -1,7 +1,7 @@
|
|
|
1
1
|
{
|
|
2
|
-
"release": "5.0
|
|
3
|
-
"buildId": "run-
|
|
4
|
-
"commitSha": "
|
|
5
|
-
"buildTime": "2026-06-
|
|
2
|
+
"release": "5.1.0",
|
|
3
|
+
"buildId": "run-53-1",
|
|
4
|
+
"commitSha": "3a0e7525c2c606afb9a64c2d78baffa5b400cf50",
|
|
5
|
+
"buildTime": "2026-06-11T20:57:59Z",
|
|
6
6
|
"serviceName": "muggle-ai-works-mcp"
|
|
7
7
|
}
|
|
@@ -1 +1 @@
|
|
|
1
|
-
export { DEFAULT_PREFERENCES, PREFERENCES_FILE_NAME, PREFERENCES_PROJECT_DIR_NAME, PREFERENCES_SCHEMA, PREFERENCES_VERSION, PREFERENCE_ALLOWED_VALUES, PreferenceKey, PreferenceValue, buildElectronAppChecksumsUrl, buildElectronAppReleaseAssetUrl, buildElectronAppReleaseTag, calculateFileChecksum, createApiKeyWithToken, createChildLogger, deleteApiKeyData, deleteCredentials, e2e_exports as e2e, formatPreferencesOneLiner, getApiKey, getApiKeyFilePath, getAuthService, getBundledElectronAppVersion, getCallerCredentials, getCallerCredentialsAsync, getChecksumForPlatform, getConfig, getCredentialsFilePath, getDataDir, getDownloadBaseUrl, getElectronAppChecksums, getElectronAppDir, getElectronAppVersion, getElectronAppVersionSource, getLocalQaTools, getLogger, getPlatformKey, getQaTools, getValidApiKeyData, getValidCredentials, hasApiKey, isElectronAppInstalled, isFirstRun, loadApiKeyData, loadCredentials, local_exports as localQa, mcp_exports as mcp, openBrowserUrl, performLogin, performLogout, pollDeviceCode, e2e_exports as qa, readGlobalPreferences, readProjectPreferences, resetConfig, resetLogger, resetPreference, resolveElectronAppPathOrNull, resolvePreferences, saveApiKey, saveApiKeyData, saveCredentials, startDeviceCodeFlow, toolRequiresAuth, validatePreference, verifyFileChecksum, writePreferences } from './chunk-
|
|
1
|
+
export { DEFAULT_PREFERENCES, PREFERENCES_FILE_NAME, PREFERENCES_PROJECT_DIR_NAME, PREFERENCES_SCHEMA, PREFERENCES_VERSION, PREFERENCE_ALLOWED_VALUES, PreferenceKey, PreferenceValue, buildElectronAppChecksumsUrl, buildElectronAppReleaseAssetUrl, buildElectronAppReleaseTag, calculateFileChecksum, createApiKeyWithToken, createChildLogger, deleteApiKeyData, deleteCredentials, e2e_exports as e2e, formatPreferencesOneLiner, getApiKey, getApiKeyFilePath, getAuthService, getBundledElectronAppVersion, getCallerCredentials, getCallerCredentialsAsync, getChecksumForPlatform, getConfig, getCredentialsFilePath, getDataDir, getDownloadBaseUrl, getElectronAppChecksums, getElectronAppDir, getElectronAppVersion, getElectronAppVersionSource, getLocalQaTools, getLogger, getPlatformKey, getQaTools, getValidApiKeyData, getValidCredentials, hasApiKey, isElectronAppInstalled, isFirstRun, loadApiKeyData, loadCredentials, local_exports as localQa, mcp_exports as mcp, openBrowserUrl, performLogin, performLogout, pollDeviceCode, e2e_exports as qa, readGlobalPreferences, readProjectPreferences, resetConfig, resetLogger, resetPreference, resolveElectronAppPathOrNull, resolvePreferences, saveApiKey, saveApiKeyData, saveCredentials, startDeviceCodeFlow, toolRequiresAuth, validatePreference, verifyFileChecksum, writePreferences } from './chunk-MOHR7QUN.js';
|
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.0
|
|
4
|
+
"version": "5.1.0",
|
|
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",
|
|
@@ -41,14 +41,14 @@
|
|
|
41
41
|
"test:watch": "vitest"
|
|
42
42
|
},
|
|
43
43
|
"muggleConfig": {
|
|
44
|
-
"electronAppVersion": "1.
|
|
44
|
+
"electronAppVersion": "1.4.0",
|
|
45
45
|
"downloadBaseUrl": "https://github.com/multiplex-ai/muggle-ai-works/releases/download",
|
|
46
46
|
"runtimeTargetDefault": "production",
|
|
47
47
|
"checksums": {
|
|
48
|
-
"darwin-arm64": "
|
|
49
|
-
"darwin-x64": "
|
|
50
|
-
"linux-x64": "
|
|
51
|
-
"win32-x64": "
|
|
48
|
+
"darwin-arm64": "9dd7ac0a378a1d5db908a102aec4f596741e943572a7d55b08e2a62f336981bc",
|
|
49
|
+
"darwin-x64": "70c9c6df21e03ad1529682e6cf8150ddfef306e1019e4b3bd2a4e7d025a98d64",
|
|
50
|
+
"linux-x64": "14ee27b3c22988bf72f13f3734e1594dcbb0fb94f699d5ad789ea8cf452dc7a1",
|
|
51
|
+
"win32-x64": "9e059917ba4605527b47d23b43bd78438cf59e7df38c4c9698f6b9487ed64a97"
|
|
52
52
|
}
|
|
53
53
|
},
|
|
54
54
|
"dependencies": {
|
|
@@ -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.0
|
|
4
|
+
"version": "5.1.0",
|
|
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.0
|
|
5
|
+
"version": "5.1.0",
|
|
6
6
|
"author": {
|
|
7
7
|
"name": "Muggle AI",
|
|
8
8
|
"email": "support@muggle-ai.com"
|
|
@@ -104,7 +104,7 @@ if [ -f "$prefs_global_file" ]; then
|
|
|
104
104
|
const defaults = {
|
|
105
105
|
autoLogin:'ask', autoSelectProject:'ask', autoSelectLocalHost:'ask',
|
|
106
106
|
showElectronBrowser:'ask', openTestResultsAfterRun:'ask',
|
|
107
|
-
defaultExecutionMode:'ask',
|
|
107
|
+
defaultExecutionMode:'ask',
|
|
108
108
|
suggestRelatedUseCases:'ask', suggestRelatedTestCases:'ask', autoDetectChanges:'ask',
|
|
109
109
|
postPRVisualWalkthrough:'ask', autoCreatePR:'ask',
|
|
110
110
|
checkForUpdates:'ask', verboseOutput:'ask',
|
|
@@ -27,14 +27,16 @@ function markPrHandled(sessionId2, prUrl, dirOverride) {
|
|
|
27
27
|
|
|
28
28
|
// src/guardrails/prOpened.ts
|
|
29
29
|
var PR_URL = /https:\/\/github\.com\/[^/\s]+\/[^/\s]+\/pull\/\d+/;
|
|
30
|
+
var MR_URL = /https?:\/\/[^/\s]+\/[^\s]+\/-\/merge_requests\/\d+/;
|
|
30
31
|
var CREATE_CMD = /\bgh\s+pr\s+(create|ready)\b/;
|
|
32
|
+
var MR_CREATE_CMD = /\bglab\s+mr\s+create\b|\bglab\s+mr\s+update\b.*--ready\b/;
|
|
31
33
|
function detectPrOpened(input2) {
|
|
32
34
|
if (input2.tool_name !== "Bash") return null;
|
|
33
35
|
const cmd = input2.tool_input?.command ?? "";
|
|
34
|
-
if (!CREATE_CMD.test(cmd)) return null;
|
|
36
|
+
if (!CREATE_CMD.test(cmd) && !MR_CREATE_CMD.test(cmd)) return null;
|
|
35
37
|
const out = `${input2.tool_response?.stdout ?? ""}
|
|
36
38
|
${input2.tool_response?.output ?? ""}`;
|
|
37
|
-
const m = out.match(PR_URL);
|
|
39
|
+
const m = out.match(PR_URL) ?? out.match(MR_URL);
|
|
38
40
|
return m ? m[0] : null;
|
|
39
41
|
}
|
|
40
42
|
|
|
@@ -1,13 +1,9 @@
|
|
|
1
|
-
# Dev Loop —
|
|
1
|
+
# Dev Loop — Cloud Refs & Screenshots
|
|
2
2
|
|
|
3
|
-
##
|
|
3
|
+
## Cloud refs
|
|
4
4
|
|
|
5
|
-
|
|
6
|
-
|
|
7
|
-
`muggle-local-publish-test-script` with `runId` and `cloudTestCaseId`. Retain `testScriptId`, `actionScriptId`, `viewUrl`. Batch publishes in parallel.
|
|
8
|
-
|
|
9
|
-
If publish rejects with `has no generated actionScript steps to publish` (a true zero-step run), fall back to `muggle-remote-local-run-upload` with whatever exists (`summaryStep`, `errorMessage`, empty `actionScript`); capture `actionScriptId` and `viewUrl` the same way.
|
|
5
|
+
The studio publishes every completed run — pass or fail — to the cloud during execution. There is no publish step to run. The run result already carries the cloud identifiers: read `viewUrl`, `cloudTestScriptId`, and `cloudActionScriptId` from `muggle-local-run-result-get` for the run. (`cloudTestScriptId` is absent for a failed generation — the backend records the action script and `viewUrl` but no test script.)
|
|
10
6
|
|
|
11
7
|
## Screenshots
|
|
12
8
|
|
|
13
|
-
Per
|
|
9
|
+
Per run, `muggle-remote-test-script-get` with the `cloudTestScriptId` from the run result → per step `operation.screenshotUrl` and `operation.action`. Retain `{ stepIndex, action, screenshotUrl }`. Batch in parallel. These feed the `E2eReport` consumed by [`../../muggle-pr-visual-walkthrough/SKILL.md`](../../muggle-pr-visual-walkthrough/SKILL.md) — the dev loop does not post to the PR.
|
|
@@ -2,7 +2,7 @@
|
|
|
2
2
|
|
|
3
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
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. Self-loop is prevented at the watcher's filter layer rather than here: `POST /pulls/<n>/comments/<id>/replies` does create an implicit review under the loop user's identity, and the watcher drops it via the loop-echo clause in [`../github
|
|
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. Self-loop is prevented at the watcher's filter layer rather than here: `POST /pulls/<n>/comments/<id>/replies` does create an implicit review under the loop user's identity, and the watcher drops it via the loop-echo clause in [`../vcs/github/submitted-reviews.md`](../vcs/github/submitted-reviews.md) — matched by the loop signature ([`loop-signature.md`](loop-signature.md)), so the author's *genuine* reviews and thread replies still get through. Including the PR author in this allow-list is therefore safe.
|
|
6
6
|
|
|
7
7
|
## Step 1: requested reviewers
|
|
8
8
|
|
|
@@ -5,6 +5,6 @@ When `/muggle-do` posts a threaded reply to a review comment, GitHub surfaces th
|
|
|
5
5
|
Under the thread-state dispatch trigger this is **intrinsic** — there is no "advance past the echo" step to get wrong:
|
|
6
6
|
|
|
7
7
|
- **Line-comment threads.** A thread is actionable only when its newest comment lacks the loop marker `<!-- muggle-do:bot -->` (see [`loop-signature.md`](loop-signature.md)). After the loop replies, the newest comment is the loop's own and carries the marker, so the thread drops out of the actionable set on its own.
|
|
8
|
-
- **Body-only reviews.** A loop reply always carries a line comment, so it is never body-only; the body-only check (no line comments, `id > lastBodyReviewId` — see [`../github
|
|
8
|
+
- **Body-only reviews.** A loop reply always carries a line comment, so it is never body-only; the body-only check (no line comments, `id > lastBodyReviewId` — see [`../vcs/github/submitted-reviews.md`](../vcs/github/submitted-reviews.md)) excludes echoes structurally.
|
|
9
9
|
|
|
10
10
|
Classify by the marker, never by `author.login` — under a shared account the loop posts as the PR author, so the login cannot tell echo from human.
|
|
@@ -53,4 +53,4 @@ Write to `state.md` under a `## Pre-flight answers` block:
|
|
|
53
53
|
- `Auth status: <ok | re-authed | N/A>`
|
|
54
54
|
- `Working tree: <path>` — the verified checkout the cycle runs against
|
|
55
55
|
|
|
56
|
-
|
|
56
|
+
Once the strategy is `local-e2e`, missing any of its required fields (`Local URL`, `Muggle Test project`) is a seeding bug — escalate with the session path and halt; don't silently downgrade a chosen `local-e2e` to a skip. But `unit-only` and `skip` are valid first-class strategies for a PR with no testable surface — they need none of those fields, and a session seeded with no block at all is itself a clean skip.
|
|
@@ -19,8 +19,7 @@ Run once the target `testCaseId` is chosen and the local URL + services are conf
|
|
|
19
19
|
- Not ready → **generate its script only (never replay):**
|
|
20
20
|
1. `muggle-remote-test-case-get` for the ancestor.
|
|
21
21
|
2. Determine `freshSession` for that ancestor from its own content — same rules as Step 6.
|
|
22
|
-
3. `muggle-local-execute-test-generation` with the ancestor test case, `localUrl`, `cwd`, and a long `timeoutMs` (see Step 6's timeout guidance). Do **not** call `muggle-local-execute-replay`.
|
|
23
|
-
4. `muggle-local-publish-test-script` (`runId`, `cloudTestCaseId` = ancestor) so the generated script is promoted as that ancestor's canonical replay script — it now reads as ready for any case downstream.
|
|
22
|
+
3. `muggle-local-execute-test-generation` with the ancestor test case, `localUrl`, `cwd`, and a long `timeoutMs` (see Step 6's timeout guidance). Do **not** call `muggle-local-execute-replay`. The studio publishes the generated run during execution, promoting its script as that ancestor's canonical replay script — it now reads as ready for any case downstream (confirm via `muggle-local-run-result-get` carrying a `cloudActionScriptId`).
|
|
24
23
|
|
|
25
24
|
3. **All ancestors ready** → continue to Step 5 for the target test case.
|
|
26
25
|
|
|
@@ -0,0 +1,9 @@
|
|
|
1
|
+
# VCS provider recipes
|
|
2
|
+
|
|
3
|
+
Provider-agnostic seam for the watcher and dev-cycle skills. A caller resolves one provider token via [`detect-vcs.md`](detect-vcs.md) — `github` (`gh`) or `gitlab` (`glab`) — then loads the matching provider's recipe for each agnostic step. The two recipe sets mirror each other call-for-call; callers branch on the token, never fork procedure.
|
|
4
|
+
|
|
5
|
+
## Index
|
|
6
|
+
|
|
7
|
+
- [`detect-vcs.md`](detect-vcs.md) — resolve `github` | `gitlab` from a URL argument or the origin remote.
|
|
8
|
+
- [`github.md`](github.md) — `gh` / `git` recipe TOC; per-recipe files in [`github/`](github/).
|
|
9
|
+
- [`gitlab.md`](gitlab.md) — `glab` / `git` recipe TOC; per-recipe files in [`gitlab/`](gitlab/).
|
|
@@ -0,0 +1,28 @@
|
|
|
1
|
+
# Detect VCS provider
|
|
2
|
+
|
|
3
|
+
Resolve a single provider token — `github` or `gitlab` — before a caller picks its recipe set. GitHub uses `gh`; GitLab uses `glab`. Auth errors from either surface verbatim.
|
|
4
|
+
|
|
5
|
+
## Resolution order
|
|
6
|
+
|
|
7
|
+
1. **From a URL argument**, if one was passed:
|
|
8
|
+
- `github.com/<owner>/<repo>/pull/<n>` → `github`.
|
|
9
|
+
- `<host>/<group>/<project>/-/merge_requests/<iid>` → `gitlab`. The `/-/merge_requests/` segment is the tell, on any host.
|
|
10
|
+
|
|
11
|
+
2. **From the repo**, when no URL — parse the origin remote:
|
|
12
|
+
|
|
13
|
+
```bash
|
|
14
|
+
git remote get-url origin
|
|
15
|
+
```
|
|
16
|
+
|
|
17
|
+
- Host `github.com` → `github`.
|
|
18
|
+
- Host `gitlab.com`, **or** any other host where `glab auth status` succeeds → `gitlab`.
|
|
19
|
+
|
|
20
|
+
## GitLab wrinkles
|
|
21
|
+
|
|
22
|
+
- **Nested namespaces.** The path between host and `/-/` can be `group/subgroup/project`, any depth. Do not assume two segments — split on `/-/`, the project path is everything before it.
|
|
23
|
+
- **The `/-/` segment** separates the project path from the resource (`/-/merge_requests/<iid>`). GitHub has no equivalent; its `/pull/<n>` sits directly under `<owner>/<repo>`.
|
|
24
|
+
- **Self-hosted hosts.** GitLab is not just `gitlab.com` — `git.acme.com`, `gitlab.internal`, etc. Resolve the host from the remote and confirm it against `glab`'s configured host (`GITLAB_HOST`, or `glab auth status`'s active host). A remote host that matches `glab`'s host → `gitlab`, even when unknown to this doc.
|
|
25
|
+
|
|
26
|
+
## Output
|
|
27
|
+
|
|
28
|
+
The bare token `github` or `gitlab` — nothing else.
|
|
@@ -28,7 +28,7 @@ query($owner: String!, $name: String!, $number: Int!) {
|
|
|
28
28
|
}'
|
|
29
29
|
```
|
|
30
30
|
|
|
31
|
-
Filter client-side to `isResolved == false`. Walk each thread's comments in `createdAt` order and classify by the loop marker (see [
|
|
31
|
+
Filter client-side to `isResolved == false`. Walk each thread's comments in `createdAt` order and classify by the loop marker (see [`../../pr-followup-helpers/loop-signature.md`](../../pr-followup-helpers/loop-signature.md)), not by `author.login` — the login is ambiguous under a shared account:
|
|
32
32
|
|
|
33
33
|
- **Addressed, awaiting resolve** — the **newest** comment carries the loop marker `<!-- muggle-do:bot -->`. The loop has replied and nothing newer is waiting. → resolve-reminder.
|
|
34
34
|
- **Unaddressed human comment** — the newest comment lacks the marker and is newer than the thread's newest loop-marked comment (or the thread has no loop comment yet). → actionable: the round should address it. The **watcher's dispatch trigger** additionally requires `isOutdated == false` — a thread whose anchored line has since changed is skipped, since re-surfacing a stale anchor risks answering a concern the change already mooted. The resolve-reminder stage ignores `isOutdated`.
|
|
@@ -14,4 +14,4 @@ Accept any remote URL form for `<owner>/<repo>` (with or without trailing `.git`
|
|
|
14
14
|
- `git@github.com:<owner>/<repo>`
|
|
15
15
|
- `ssh://git@github.com/<owner>/<repo>`
|
|
16
16
|
|
|
17
|
-
Any mismatch → bootstrap aborts using the wrong-checkout template in [
|
|
17
|
+
Any mismatch → bootstrap aborts using the wrong-checkout template in [`../../../muggle-pr-followup/output-templates/bootstrap.md`](../../../muggle-pr-followup/output-templates/bootstrap.md).
|
|
@@ -0,0 +1,21 @@
|
|
|
1
|
+
# GitHub CLI Recipes
|
|
2
|
+
|
|
3
|
+
Reusable `gh` / `git` snippets used by `muggle-pr-followup` (watcher + bootstrap) and `/muggle-do` (address-reviews + open-prs). Each recipe is one file — load only what you need.
|
|
4
|
+
|
|
5
|
+
Skills assume a working `gh auth status`. Auth errors surface verbatim from `gh`.
|
|
6
|
+
|
|
7
|
+
## Index
|
|
8
|
+
|
|
9
|
+
| Recipe | Use case |
|
|
10
|
+
| :----- | :------- |
|
|
11
|
+
| [`pr-metadata`](github/pr-metadata.md) | Snapshot PR state, head SHA, branch, conflict + `behind_by` out-of-date detection — watcher + bootstrap. |
|
|
12
|
+
| [`submitted-reviews`](github/submitted-reviews.md) | Fetch a review by id / watcher's body-only-review check. |
|
|
13
|
+
| [`pr-checks`](github/pr-checks.md) | Check-run rollup for the head SHA — watcher's CI poll. |
|
|
14
|
+
| [`line-comments-for-review`](github/line-comments-for-review.md) | Pull a review's line comments — `/muggle-do` per-comment routing. |
|
|
15
|
+
| [`unresolved-threads`](github/unresolved-threads.md) | GraphQL unresolved-thread state — watcher's dispatch trigger + resolve-reminder. |
|
|
16
|
+
| [`reply-line-comment`](github/reply-line-comment.md) | POST a threaded reply on a line comment. |
|
|
17
|
+
| [`top-level-comment`](github/top-level-comment.md) | POST a top-level PR comment — resolve-reminder + overflow. |
|
|
18
|
+
| [`push-to-branch`](github/push-to-branch.md) | Push + capture new SHA after address-reviews work. |
|
|
19
|
+
| [`verify-working-tree`](github/verify-working-tree.md) | Three checks bootstrap runs before seeding state. |
|
|
20
|
+
| [`pr-edit`](github/pr-edit.md) | Refresh title or body when address-reviews mode flips state. |
|
|
21
|
+
| [`loop-user-identity`](github/loop-user-identity.md) | Resolve the GitHub login of the loop user. |
|