@muggleai/works 5.0.3 → 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/debug-failed-run.md +53 -0
- 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/telemetry-events/pr-followup-tick.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/dist/plugin/skills/_shared/vcs/github/pr-metadata.md +25 -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 +6 -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 +18 -12
- 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 +30 -143
- 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 +9 -18
- 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/debug-failed-run.md +53 -0
- 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/telemetry-events/pr-followup-tick.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/plugin/skills/_shared/vcs/github/pr-metadata.md +25 -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 +6 -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 +18 -12
- 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 +30 -143
- 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 +9 -18
- package/dist/plugin/skills/_shared/github-cli-recipes/pr-metadata.md +0 -13
- 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/pr-metadata.md +0 -13
- 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}/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}/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
|
@@ -14,21 +14,23 @@ This stage does not print a turn preamble — it runs inside `/muggle-do`'s addr
|
|
|
14
14
|
|
|
15
15
|
## Inputs
|
|
16
16
|
|
|
17
|
-
- The current PR (URL, owner, repo, number) from the session's `prs.json`.
|
|
17
|
+
- The current PR (URL, owner, repo, number) from the session's `prs.json`. On `gitlab`, the project ref and MR iid.
|
|
18
18
|
- `last_seen.pushed_shas[]` from `last_seen.json` — the list of every SHA `/muggle-do` has pushed for this PR.
|
|
19
|
-
- The loop user's
|
|
19
|
+
- The loop user's login (cached in `state.md` under `Loop user:`) — re-resolve when missing, `github` per [`../_shared/vcs/github/loop-user-identity.md`](../_shared/vcs/github/loop-user-identity.md), `gitlab` per [`../_shared/vcs/gitlab/loop-user-identity.md`](../_shared/vcs/gitlab/loop-user-identity.md).
|
|
20
|
+
|
|
21
|
+
Resolve the provider once per [`../_shared/vcs/detect-vcs.md`](../_shared/vcs/detect-vcs.md).
|
|
20
22
|
|
|
21
23
|
## Procedure
|
|
22
24
|
|
|
23
25
|
### Step 1 — Fetch unresolved comment threads
|
|
24
26
|
|
|
25
|
-
|
|
27
|
+
`github` per [`../_shared/vcs/github/unresolved-threads.md`](../_shared/vcs/github/unresolved-threads.md) (filter client-side to `isResolved == false`; each thread carries its line comments with `author.login`, `body`, `databaseId`); `gitlab` per [`../_shared/vcs/gitlab/unresolved-discussions.md`](../_shared/vcs/gitlab/unresolved-discussions.md) (each discussion carries its `notes[]` and `id`).
|
|
26
28
|
|
|
27
29
|
If the API call fails, log the error to `followup.log` and skip the stage. Do not surface a user-facing error — the resolve reminder is a nice-to-have, not load-bearing. The reply summaries on the threads themselves still happen.
|
|
28
30
|
|
|
29
31
|
### Step 2 — Classify each thread
|
|
30
32
|
|
|
31
|
-
|
|
33
|
+
Walk each thread's comments (`gitlab`: notes) in chronological order and classify by the loop marker `<!-- muggle-do:bot -->` ([`../_shared/pr-followup-helpers/loop-signature.md`](../_shared/pr-followup-helpers/loop-signature.md)), not by `author.login` — `github` per [`../_shared/vcs/github/unresolved-threads.md`](../_shared/vcs/github/unresolved-threads.md), `gitlab` per [`../_shared/vcs/gitlab/unresolved-discussions.md`](../_shared/vcs/gitlab/unresolved-discussions.md):
|
|
32
34
|
|
|
33
35
|
- **Addressed, awaiting resolve** — the **newest** comment carries the marker. The loop replied and nothing newer is waiting. These feed the reminder.
|
|
34
36
|
- **Unaddressed human comment** — the newest comment lacks the marker and post-dates the loop's last marked reply (or there is no loop reply yet). The address-reviews round handles these as work (Step 1 sweep), not the reminder.
|
|
@@ -42,7 +44,7 @@ Collect the thread `databaseId` of every thread classified **addressed, awaiting
|
|
|
42
44
|
|
|
43
45
|
### Step 4 — Post the top-level reminder comment
|
|
44
46
|
|
|
45
|
-
If the resolve-reminder list is non-empty, post **one** top-level
|
|
47
|
+
If the resolve-reminder list is non-empty, post **one** top-level comment using the template in [`../muggle-pr-followup/output-templates/resolve-reminder.md`](../muggle-pr-followup/output-templates/resolve-reminder.md) — `github` per [`../_shared/vcs/github/top-level-comment.md`](../_shared/vcs/github/top-level-comment.md), `gitlab` per [`../_shared/vcs/gitlab/mr-note.md`](../_shared/vcs/gitlab/mr-note.md). The comment carries the loop signature, so a later round's scan won't read it back as a human comment.
|
|
46
48
|
|
|
47
49
|
If the list is empty, post **nothing**. Still emit telemetry so the stage's run is observable.
|
|
48
50
|
|
|
@@ -59,7 +61,7 @@ Emit one event per [`../_shared/telemetry-events/muggle-do-resolve-reminder.md`]
|
|
|
59
61
|
|
|
60
62
|
This stage is best-effort. Any failure is logged to `followup.log` and silently skipped — the reviewer still gets the per-comment inline replies (the canonical signal that work was done), and the cycle continues to respawn the watcher.
|
|
61
63
|
|
|
62
|
-
The one exception: do not silently swallow a `gh pr comment`
|
|
64
|
+
The one exception: do not silently swallow a Step 4 post failure (`gh pr comment` / `glab mr note`) if Step 4 ran. The comment is a user-visible artifact; if it fails, surface the underlying CLI error to the user so they know the reminder didn't post.
|
|
63
65
|
|
|
64
66
|
## Invariants
|
|
65
67
|
|
|
@@ -1,6 +1,6 @@
|
|
|
1
1
|
---
|
|
2
2
|
name: muggle-browser-task
|
|
3
|
-
description:
|
|
3
|
+
description: "Perform a real action on a website or web app from a plain-English instruction — log in and do the thing: submit a form, create or update a record, place an order, refund a charge, file a ticket, publish a post, click through and complete a multi-step flow (Stripe, Jira, Shopify, the AWS console, WordPress, LinkedIn, an admin dashboard). Use whenever the user wants something actually done in a web UI ('log into X and …', 'submit the form', 'create the ticket', 'refund the charge', 'place the order', 'update the listing'); Muggle drives a real browser to do it, so reach for this rather than declining or doing it by hand. Boundary: this performs the action (operating a site's own UI), not migrating personal data between consumer apps; to verify a flow works instead, use muggle-test-feature-local."
|
|
4
4
|
---
|
|
5
5
|
|
|
6
6
|
# Muggle Test Task Runner
|
|
@@ -1,6 +1,6 @@
|
|
|
1
1
|
---
|
|
2
2
|
name: muggle-do
|
|
3
|
-
description:
|
|
3
|
+
description: Take a feature request, spec, design, bug, or ticket and carry it autonomously to an opened pull request — write the code, test it, raise the PR. Use whenever the user wants something built, implemented, added, or fixed with a PR opened, raised, or put up at the end — "implement rate limiting and raise a PR", "build the CSV export and put up a PR", "take this Jira ticket and run with it, ping me when the PR is up", "fix this bug and open a pr", or "muggle do …". Also handles the internal `address-reviews` directive the muggle-pr-followup watcher dispatches when new reviews land. Not for testing or validating existing changes (use muggle-test), nor watching a PR's incoming reviews (use muggle-pr-followup).
|
|
4
4
|
---
|
|
5
5
|
|
|
6
6
|
# Muggle Test Do
|
|
@@ -65,7 +65,7 @@ When invoked with the directive (PR URL + slug + review ids), routes to [`../do/
|
|
|
65
65
|
| `autoResolveConflicts` | On rebase conflict — resolve autonomously behind a verify-or-rollback gate (opt-in), or abort + escalate (default `never`) |
|
|
66
66
|
| `autoRouteBuildToMuggleDo` | Front-door guardrail — route build/implement/fix requests through this pipeline (build delegated to superpowers); fired by the UserPromptSubmit guardrail, default `ask` |
|
|
67
67
|
|
|
68
|
-
`autoUseWorktree`, `autoRebase`, `autoResolveConflicts`, `autoCreatePR`, `autoCleanup` fire from per-stage files.
|
|
68
|
+
`autoUseWorktree`, `autoRebase`, `autoResolveConflicts`, `autoCreatePR`, `autoCleanup`, `postPRVisualWalkthrough` fire from per-stage files.
|
|
69
69
|
|
|
70
70
|
## Session model
|
|
71
71
|
|
|
@@ -20,15 +20,15 @@ A Muggle dashboard URL looks like `https://www.muggle-ai.com/muggleTestV0/dashbo
|
|
|
20
20
|
If this skill was invoked by another skill (`muggle-test`, `muggle-test-feature-local`) the caller MUST pass the just-finished `runId` as context. If you have a `runId`:
|
|
21
21
|
|
|
22
22
|
1. `muggle-local-run-result-get` with the `runId`.
|
|
23
|
-
2. The result includes the test case context.
|
|
24
|
-
3. **
|
|
23
|
+
2. The result includes the test case context. The studio publishes every local run during execution, so the run result carries the cloud `cloudActionScriptId` — use it directly as the `actionScriptId`.
|
|
24
|
+
3. **Legacy fallback** — if `cloudActionScriptId` is absent (a run from an older Electron build that didn't publish), upload it first via `muggle-remote-local-run-upload` (passing the `runId`'s test case context and `actionScript` payload). Use the returned cloud `actionScriptId`.
|
|
25
25
|
|
|
26
26
|
If no `runId` was passed but the user is plausibly continuing from a recent test:
|
|
27
27
|
|
|
28
28
|
1. `muggle-local-list-sessions` and pick sessions completed in the last 10 minutes for the current project.
|
|
29
29
|
2. If exactly one fresh session exists, offer it as the default via `AskUserQuestion` ("Feedback on the run from <X> minutes ago?" with **Yes / Pick a different run**).
|
|
30
30
|
3. If multiple, present the top 3 via `AskUserQuestion` (most recent first).
|
|
31
|
-
4. Once picked,
|
|
31
|
+
4. Once picked, resolve `cloudActionScriptId` from the run result (legacy upload fallback above).
|
|
32
32
|
|
|
33
33
|
If neither chained nor recent fits, fall through to 1c.
|
|
34
34
|
|
|
@@ -127,4 +127,4 @@ If any pieces failed, list them under a `Failed:` header with the error.
|
|
|
127
127
|
- Always render the script (step 2) before collecting feedback.
|
|
128
128
|
- One create call per feedback piece — never concatenate paragraphs across targets.
|
|
129
129
|
- Convert step numbers from 1-based (UI) to 0-based (wire) at submit time.
|
|
130
|
-
- If
|
|
130
|
+
- If a legacy local run carries no `cloudActionScriptId`, do the upload silently before submit; do not ask for permission for the upload itself.
|
|
@@ -6,7 +6,7 @@ This folder holds the watcher loop that drives one PR toward merge-ready. The wa
|
|
|
6
6
|
|
|
7
7
|
- [`SKILL.md`](SKILL.md) — public entry. Routing between bootstrap (URL input), tick (slug + PR number), and auto-track (no args). Read first.
|
|
8
8
|
- [`auto-track.md`](auto-track.md) — the no-args procedure: discovers PRs pushed this session (any repo) and seeds one poll-only watcher each. Seeds no E2E context — the watcher only watches.
|
|
9
|
-
- [`bootstrap.md`](bootstrap.md) — the bootstrap procedure (
|
|
9
|
+
- [`bootstrap.md`](bootstrap.md) — the bootstrap procedure (resolves the validation context once when the PR has a testable surface — else seeds poll-only like auto-track — then dispatches the first watcher).
|
|
10
10
|
- [`contract.md`](contract.md) — the watcher per-tick procedure (poll → dispatch → exit).
|
|
11
11
|
- [`finalize.md`](finalize.md) — shared termination sequence for a terminal PR (mark terminal, `result.md`, log/telemetry, unschedule cron, post-merge cleanup handoff). Called by `contract.md` and `reconcile.md`.
|
|
12
12
|
- [`reconcile.md`](reconcile.md) — sweep that finalizes slots whose PR went terminal while polling lapsed; runs at the top of auto-track and on demand.
|
|
@@ -21,6 +21,6 @@ Shared with other skills, under `../_shared/`:
|
|
|
21
21
|
- [`pr-followup-helpers.md`](../_shared/pr-followup-helpers.md) — TOC of allow-list / reply-routing / classify; per-section files in `_shared/pr-followup-helpers/`. Called by `/muggle-do`, not by this folder.
|
|
22
22
|
- [`telemetry-emit.md`](../_shared/telemetry-emit.md) — how to emit a telemetry event.
|
|
23
23
|
- [`telemetry-events.md`](../_shared/telemetry-events.md) — TOC of canonical event shapes; per-event files in `_shared/telemetry-events/`.
|
|
24
|
-
- [`github
|
|
24
|
+
- [`vcs/github.md`](../_shared/vcs/github.md) — TOC of reusable `gh` / `git` snippets; per-recipe files in `_shared/vcs/github/`.
|
|
25
25
|
|
|
26
26
|
Callers (e.g. `/muggle-do`) reference this folder, not the reverse — see [`../CLAUDE.md`](../CLAUDE.md) for the one-way-dependency rule.
|
|
@@ -2,7 +2,7 @@
|
|
|
2
2
|
|
|
3
3
|
The procedure for the **bootstrap mode** of `muggle-pr-followup` — invoked when a user dispatches the skill with a GitHub PR URL. Routing into this mode is documented in [`SKILL.md`](SKILL.md#routing).
|
|
4
4
|
|
|
5
|
-
Bootstrap
|
|
5
|
+
Bootstrap seeds watcher state and dispatches the first tick. The watcher itself is generic: it follows one PR's reviews, CI, and merge state whether or not E2E applies. Validation context is **optional** and gathered here only because this is the one moment the user is present — so later unattended ticks can run E2E without prompting. When the PR has a testable surface, bootstrap resolves that context once and every later tick reads it from `state.md`. When there's no testable surface, or the user declines, bootstrap seeds the watcher **poll-only** (no validation context), exactly like [`auto-track`](auto-track.md) — a watcher with no context yields a clean `SKIPPED` E2E verdict when `/muggle-do` runs, not a failure.
|
|
6
6
|
|
|
7
7
|
## Turn preamble
|
|
8
8
|
|
|
@@ -27,13 +27,13 @@ Extract `<owner>`, `<repo>`, `<pr-number>`. On malformed input, exit with the ma
|
|
|
27
27
|
|
|
28
28
|
### Step 2 — Fetch PR metadata
|
|
29
29
|
|
|
30
|
-
Per [`../_shared/github
|
|
30
|
+
Per [`../_shared/vcs/github/pr-metadata.md`](../_shared/vcs/github/pr-metadata.md).
|
|
31
31
|
|
|
32
32
|
If `state` is `MERGED` or `CLOSED`, exit with the terminal-PR abort. If the `gh` call fails (not found, auth missing), surface the underlying error verbatim and exit.
|
|
33
33
|
|
|
34
34
|
### Step 3 — Verify the working tree
|
|
35
35
|
|
|
36
|
-
Per [`../_shared/github
|
|
36
|
+
Per [`../_shared/vcs/github/verify-working-tree.md`](../_shared/vcs/github/verify-working-tree.md). On any check failure, exit with the wrong-working-tree abort.
|
|
37
37
|
|
|
38
38
|
### Step 4 — Resolve the slug
|
|
39
39
|
|
|
@@ -53,17 +53,19 @@ If `~/.muggle-ai/muggle-do/sessions/<slug>/` exists (including a slot just migra
|
|
|
53
53
|
Line-comment threads need no seeding — the watcher derives them from live thread state on every tick, so existing unresolved threads are picked up on the first tick regardless of this step. This step only sets `lastBodyReviewId`, the narrow watermark for body-only reviews (a submitted review with no line comments).
|
|
54
54
|
|
|
55
55
|
- **Default (no `--forward-only`):** `lastBodyReviewId = 0`. The watcher picks up every existing body-only review on its first tick. Matches the common case — the user opened the PR, left feedback they want addressed, and is now bootstrapping.
|
|
56
|
-
- **With `--forward-only`:** fetch reviews per [`../_shared/github
|
|
56
|
+
- **With `--forward-only`:** fetch reviews per [`../_shared/vcs/github/submitted-reviews.md`](../_shared/vcs/github/submitted-reviews.md), then take `max(id)`. Body-only reviews at or below that id are treated as already-handled. This no longer hides existing line-comment threads — those are always picked up from thread state.
|
|
57
57
|
|
|
58
|
-
### Step 6.5 — Resolve
|
|
58
|
+
### Step 6.5 — Resolve the validation context (skip when there's nothing to E2E)
|
|
59
59
|
|
|
60
|
-
The only step that may prompt the user. Run
|
|
60
|
+
The only step that may prompt the user, and only when the PR has a testable surface. Run silent detection from [`../_shared/resolve-e2e-validation-context.md`](../_shared/resolve-e2e-validation-context.md) first. If it finds **no dev server / no testable surface** — a docs, config, skill, or library change, or a non-web repo — seed the watcher **poll-only**: no prompt, no `## Pre-flight answers` block, continue to Step 7 (same as [`auto-track`](auto-track.md)).
|
|
61
61
|
|
|
62
|
-
|
|
62
|
+
Otherwise resolve the context per that file: reuse an existing one (gated by `autoReuseValidationContext`), else one `AskUserQuestion` (strategy, local URL, backend, project, credentials, re-auth) with detected values as defaults; record Step 3's verified working tree as `Working tree`. The user may pick `skip`/`unit-only` or decline the prompt outright — either way, seed poll-only and continue. Never abort the watcher over validation.
|
|
63
|
+
|
|
64
|
+
Capture any resolved fields for Step 7. Do **not** run E2E now — the first watcher tick that dispatches `/muggle-do` does that.
|
|
63
65
|
|
|
64
66
|
### Step 7 — Seed state files
|
|
65
67
|
|
|
66
|
-
Identify the loop user once per [`../_shared/github
|
|
68
|
+
Identify the loop user once per [`../_shared/vcs/github/loop-user-identity.md`](../_shared/vcs/github/loop-user-identity.md); cache in `state.md`.
|
|
67
69
|
|
|
68
70
|
Write under `~/.muggle-ai/muggle-do/sessions/<slug>/`:
|
|
69
71
|
|
|
@@ -71,7 +73,7 @@ Write under `~/.muggle-ai/muggle-do/sessions/<slug>/`:
|
|
|
71
73
|
|
|
72
74
|
**`last_seen.json`** — see [`state-schemas.md`](state-schemas.md#last_seenjson). One key (`"<owner>/<repo>#<n>"`), `lastBodyReviewId` from Step 6, `last_pushed_sha: null`, `idle_tick_count: 0`, `cycles_completed: 0`, `escalated_review_ids: []`, `pushed_shas: []`.
|
|
73
75
|
|
|
74
|
-
**`state.md`** — see [`state-schemas.md`](state-schemas.md#statemd). `Bootstrapped from URL: yes`. Cache the loop-user login.
|
|
76
|
+
**`state.md`** — see [`state-schemas.md`](state-schemas.md#statemd). `Bootstrapped from URL: yes`. Cache the loop-user login. If Step 6.5 resolved a validation context, append the `## Pre-flight answers` block with its fields, per [`../_shared/resolve-e2e-validation-context.md`](../_shared/resolve-e2e-validation-context.md#persisted-fields). If it seeded poll-only, write **no** such block — a missing block is a clean E2E skip.
|
|
75
77
|
|
|
76
78
|
Do **not** write `cycle.json` or `requirements.md` — those files are no longer part of the session slot.
|
|
77
79
|
|
|
@@ -95,7 +97,7 @@ Emit one event per [`../_shared/telemetry-events/pr-followup-bootstrap.md`](../_
|
|
|
95
97
|
|
|
96
98
|
## Invariants
|
|
97
99
|
|
|
98
|
-
- Step 6.5 is the **only** user prompt.
|
|
99
|
-
- All state writes happen in Step 7
|
|
100
|
+
- Step 6.5 is the **only** user prompt, and only when a testable surface exists. Cancelling or declining it is **not** an abort — fall back to a poll-only watcher (no `## Pre-flight answers` block) and continue to Step 7.
|
|
101
|
+
- All state writes happen in Step 7. Only the earlier aborts (malformed URL, terminal PR, wrong working tree, slot conflict) leave nothing on disk.
|
|
100
102
|
- If Step 7 fails mid-write, surface the OS error and tell the user to `rm -rf <slot>` and re-run; do not dispatch the watcher.
|
|
101
103
|
- Bootstrap never retries.
|
|
@@ -31,7 +31,7 @@ If `prs.json[0].state` on disk is already `merged` or `closed`, this slot was fi
|
|
|
31
31
|
|
|
32
32
|
### Step 1 — Refresh PR state
|
|
33
33
|
|
|
34
|
-
Per [`../_shared/github
|
|
34
|
+
Per [`../_shared/vcs/github/pr-metadata.md`](../_shared/vcs/github/pr-metadata.md). Update `prs.json[0].head_sha` and `prs.json[0].state` from the response; keep `mergeable` (conflict signal) for Step 5, and run the recipe's `compare` call to capture `behind_by` (out-of-date signal) for Step 5.
|
|
35
35
|
|
|
36
36
|
### Step 2 — Termination check
|
|
37
37
|
|
|
@@ -50,24 +50,28 @@ If `state` is `MERGED` or `CLOSED`:
|
|
|
50
50
|
|
|
51
51
|
### Step 3 — Compute the actionable set from live thread state
|
|
52
52
|
|
|
53
|
-
The watcher's dispatch trigger is **derived from current
|
|
53
|
+
The watcher's dispatch trigger is **derived from current provider state**, not a stored review-id cursor — see the [thread-state baseline design](../../../../muggle-ai-brain/architecture/2026-06-06-pr-followup-thread-state-baseline-design.md). Resolve the provider per [`../_shared/vcs/detect-vcs.md`](../_shared/vcs/detect-vcs.md), then:
|
|
54
54
|
|
|
55
|
-
|
|
55
|
+
- **`github`** — two sources, unioned:
|
|
56
56
|
|
|
57
|
-
**(
|
|
57
|
+
**(a) Actionable threads.** Fetch unresolved review threads per [`../_shared/vcs/github/unresolved-threads.md`](../_shared/vcs/github/unresolved-threads.md). A thread is **actionable** when `isResolved == false` **and** `isOutdated == false` **and** its newest comment lacks the loop marker `<!-- muggle-do:bot -->` — classify by the marker, never `author.login` (see [`../_shared/pr-followup-helpers/loop-signature.md`](../_shared/pr-followup-helpers/loop-signature.md)). The marker rule makes echo intrinsic: once the loop has replied, the thread's newest comment is the loop's own, so the thread is no longer actionable — no cursor to advance, no self-recursion (see [`../_shared/pr-followup-helpers/echo-skip.md`](../_shared/pr-followup-helpers/echo-skip.md)).
|
|
58
58
|
|
|
59
|
-
|
|
59
|
+
**(b) Actionable body-only reviews — GitHub only.** A body-only review — a submitted `CHANGES_REQUESTED`/`COMMENTED` review with no line comments — has no thread to derive state from, so it keeps a narrow watermark. GitLab has no review envelope (feedback is always a discussion note), so this sub-branch is GitHub-only and has no GitLab analogue. Fetch submitted reviews per [`../_shared/vcs/github/submitted-reviews.md`](../_shared/vcs/github/submitted-reviews.md); a body-only review is actionable when `id > last_seen.lastBodyReviewId` **and** `id ∉ last_seen.escalated_review_ids`.
|
|
60
|
+
|
|
61
|
+
Collect the **owning review ids** for dispatch: for each actionable thread, the owning review of its newest comment (`pullRequestReview.databaseId` from the query); plus every actionable body-only review id. The dedup'd union is the dispatch list.
|
|
62
|
+
|
|
63
|
+
- **`gitlab`** — single source. Fetch unresolved discussions per [`../_shared/vcs/gitlab/unresolved-discussions.md`](../_shared/vcs/gitlab/unresolved-discussions.md) (drop to [`../_shared/vcs/gitlab/mr-discussions.md`](../_shared/vcs/gitlab/mr-discussions.md) for the raw notes if a thread's classification needs them). A discussion is **actionable** when it is unresolved **and** its newest note lacks the loop marker `<!-- muggle-do:bot -->` — same marker classification, never `author.username`. There is no body-only watermark: discussion state is the sole authority. The dispatch list is the **discussion ids** of the actionable discussions.
|
|
60
64
|
|
|
61
65
|
### Step 4 — If the actionable set is non-empty → dispatch (reviews preempt CI)
|
|
62
66
|
|
|
63
|
-
The watcher does **not** classify. Classification, batching, replying, escalation, and cycle execution all live in `/muggle-do`. The watcher hands over the owning review ids and exits — `/muggle-do`'s address-reviews re-derives the unresolved threads itself (its authority), so the watcher only needs to decide *that* there is work, not enumerate it exhaustively.
|
|
67
|
+
The watcher does **not** classify. Classification, batching, replying, escalation, and cycle execution all live in `/muggle-do`. The watcher hands over the dispatch ids from Step 3 (GitHub: owning review ids; GitLab: discussion ids) and exits — `/muggle-do`'s address-reviews re-derives the unresolved threads itself (its authority), so the watcher only needs to decide *that* there is work, not enumerate it exhaustively.
|
|
64
68
|
|
|
65
69
|
1. Reset `last_seen.idle_tick_count` to 0.
|
|
66
70
|
2. **Stop this watcher (single-thread).** Cancel its cron so no tick fires while the dev cycle runs: `CronList`, find the job whose command ends with `/muggle:muggle-pr-followup <slug> <n>` (exact two-arg match), `CronDelete` it. `/muggle-do` respawns the watcher when the cycle finishes — exactly one cron ever, and no tick overlaps a running cycle.
|
|
67
71
|
3. Dispatch `/muggle-do` with an *address-reviews* directive carrying:
|
|
68
72
|
- PR URL (from `prs.json[0].url`)
|
|
69
73
|
- Session slug (from the invocation arguments)
|
|
70
|
-
- The owning review ids
|
|
74
|
+
- The dispatch ids from Step 3 (GitHub owning review ids / GitLab discussion ids), as a space-separated list
|
|
71
75
|
|
|
72
76
|
Exact phrasing belongs to `/muggle-do`'s intent-routing. A reasonable shape is:
|
|
73
77
|
```
|
|
@@ -79,10 +83,12 @@ The watcher does **not** classify. Classification, batching, replying, escalatio
|
|
|
79
83
|
|
|
80
84
|
### Step 5 — No actionable feedback → keep the branch rebased on its base
|
|
81
85
|
|
|
82
|
-
A merge-ready branch is **current with its base** — neither conflicting nor behind.
|
|
86
|
+
A merge-ready branch is **current with its base** — neither conflicting nor behind. From the Step 1 metadata, the branch needs a rebase when either:
|
|
87
|
+
|
|
88
|
+
- `mergeable == CONFLICTING` (corroborated by `mergeStateStatus == DIRTY`) — conflicts with the base, **or**
|
|
89
|
+
- `behind_by > 0` — out of date with the base. Read this from the `compare` call (commit ancestry), **never** from `mergeStateStatus == BEHIND`: GitHub masks `BEHIND` behind `DIRTY`/`BLOCKED` and only surfaces it under "require branches up to date" protection, so a stale PR that is also awaiting review or has a red required check reports `BLOCKED` — and its staleness would go unseen. See [`../_shared/vcs/github/pr-metadata.md`](../_shared/vcs/github/pr-metadata.md#behind-by-out-of-date-detection). On `gitlab`, the same behind-by comes from the compare in [`../_shared/vcs/gitlab/mr-metadata.md`](../_shared/vcs/gitlab/mr-metadata.md#behind-by-out-of-date-detection) (commit ancestry, not `detailed_merge_status`); conflict is `detailed_merge_status` in `{broken_status, conflict}`.
|
|
83
90
|
|
|
84
|
-
-
|
|
85
|
-
- `mergeStateStatus == BEHIND` — out of date with the base, no conflict. An unrebased branch never becomes merge-ready on its own, and is merge-blocked wherever the base requires up-to-date branches.
|
|
91
|
+
This trigger is **independent of approval and CI state**: an out-of-date branch is rebased whether or not it has been reviewed, approved, or has green checks. The watcher acts on staleness directly — it never waits for an approval to surface it.
|
|
86
92
|
|
|
87
93
|
If a rebase is due **and** `conflict_resolve_attempts[head_sha] < 2` **and** `head_sha` ∉ `conflict_escalated_shas` → dispatch and exit:
|
|
88
94
|
|
|
@@ -96,11 +102,11 @@ If a rebase is due **and** `conflict_resolve_attempts[head_sha] < 2` **and** `he
|
|
|
96
102
|
4. Append a dispatching line to `followup.log`; emit a `tick` event with `rebase_needed: true`, `dispatched_rebase: true`.
|
|
97
103
|
5. Exit. The dev cycle owns the PR; its respawn restarts the watcher, whose next tick re-checks the branch against its base on the new head — the rebase is its own verify loop, bounded by the per-SHA attempt budget.
|
|
98
104
|
|
|
99
|
-
|
|
105
|
+
Otherwise — `behind_by == 0` and not conflicting (`mergeable == UNKNOWN` is fine here: `behind_by` is exact while GitHub is still computing conflict state, so a stale branch still triggers), or budget spent (`conflict_resolve_attempts[head_sha] >= 2` or `head_sha` ∈ `conflict_escalated_shas`) → fall through to CI.
|
|
100
106
|
|
|
101
107
|
### Step 6 — No actionable feedback, branch current → poll CI for the head SHA
|
|
102
108
|
|
|
103
|
-
Fetch the
|
|
109
|
+
Fetch the CI rollup for `prs.json[0].head_sha`, provider resolved as in Step 3 — `github` → the check-run rollup per [`../_shared/vcs/github/pr-checks.md`](../_shared/vcs/github/pr-checks.md); `gitlab` → the pipeline-job rollup per [`../_shared/vcs/gitlab/mr-pipeline.md`](../_shared/vcs/gitlab/mr-pipeline.md) (failed/running/success jobs fold into the same red/pending/green buckets). Then, on the bucket:
|
|
104
110
|
|
|
105
111
|
- **Any check still pending** (`bucket == "pending"`) → idle (wait for checks to settle).
|
|
106
112
|
- **All checks green / skipped, or no checks** → idle (green path).
|
|
@@ -7,7 +7,7 @@ This step only finalizes — marks the slot terminal, writes the record, unsched
|
|
|
7
7
|
## Inputs
|
|
8
8
|
|
|
9
9
|
- `<slug>`, `<owner>/<repo>`, `<n>` — the slot's PR.
|
|
10
|
-
- `state` — `MERGED` or `CLOSED`, from a fresh [`../_shared/github
|
|
10
|
+
- `state` — `MERGED` or `CLOSED`, from a fresh [`../_shared/vcs/github/pr-metadata.md`](../_shared/vcs/github/pr-metadata.md).
|
|
11
11
|
- `mergeCommit` + `mergedAt` when `MERGED`.
|
|
12
12
|
|
|
13
13
|
## Procedure
|
|
@@ -16,7 +16,7 @@ List `~/.muggle-ai/muggle-do/sessions/*/` dirs that contain a `prs.json`. Skip a
|
|
|
16
16
|
|
|
17
17
|
### Step 2 — Refresh live state
|
|
18
18
|
|
|
19
|
-
For each candidate, fetch the PR per [`../_shared/github
|
|
19
|
+
For each candidate, fetch the PR per [`../_shared/vcs/github/pr-metadata.md`](../_shared/vcs/github/pr-metadata.md) using `prs.json[0].url`. A `gh` failure on one slot (deleted repo, missing auth) → log it to that slot's `followup.log` and skip; never abort the whole sweep.
|
|
20
20
|
|
|
21
21
|
### Step 3 — Finalize the terminal ones
|
|
22
22
|
|
|
@@ -16,6 +16,7 @@ A list of one entry. (Historical: the file is an array for forward-compat with t
|
|
|
16
16
|
[
|
|
17
17
|
{
|
|
18
18
|
"repo": "<owner>/<repo>",
|
|
19
|
+
"provider": "github" | "gitlab",
|
|
19
20
|
"number": <int>,
|
|
20
21
|
"url": "https://github.com/<owner>/<repo>/pull/<number>",
|
|
21
22
|
"head_sha": "<40-char-hex-sha>",
|
|
@@ -24,6 +25,8 @@ A list of one entry. (Historical: the file is an array for forward-compat with t
|
|
|
24
25
|
]
|
|
25
26
|
```
|
|
26
27
|
|
|
28
|
+
- `provider` selects the recipe set (`gh` vs `glab`). Absent ⇒ `github` — existing slots predate the field and stay GitHub.
|
|
29
|
+
- Under GitLab, `number` holds the MR `iid` (per-project, not the global MR id); `head_sha` is unchanged. GitLab's `opened` normalizes to `open`; `merged` and `closed` already align.
|
|
27
30
|
- `state` is the **observed** state from the last `gh pr view`. The watcher refreshes it each tick.
|
|
28
31
|
- Terminal states (`merged`, `closed`) are sticky — once set, the watcher writes `result.md` and exits without rescheduling.
|
|
29
32
|
|
|
@@ -48,7 +51,7 @@ Keyed by `"<owner>/<repo>#<n>"`. One key per PR in the slot.
|
|
|
48
51
|
}
|
|
49
52
|
```
|
|
50
53
|
|
|
51
|
-
- `lastBodyReviewId`: narrow watermark for **body-only** reviews (a submitted review carrying no line comments). The watcher dispatches a body-only review only when `id > lastBodyReviewId`. Line-comment threads do **not** use it — they are dispatched from live thread state (unresolved + not outdated + newest comment unmarked by the loop), so there is no cursor that can pin past them. Bootstrap sets it to the highest existing submitted review id with `--forward-only`, else `0`.
|
|
54
|
+
- `lastBodyReviewId`: narrow watermark for **body-only** reviews (a submitted review carrying no line comments). The watcher dispatches a body-only review only when `id > lastBodyReviewId`. Line-comment threads do **not** use it — they are dispatched from live thread state (unresolved + not outdated + newest comment unmarked by the loop), so there is no cursor that can pin past them. Bootstrap sets it to the highest existing submitted review id with `--forward-only`, else `0`. The cursor keeps its name under GitLab, where it holds the highest note / discussion id.
|
|
52
55
|
- `last_pushed_sha`: most recent SHA `/muggle-do` pushed in this PR's life; `null` until the first push.
|
|
53
56
|
- `idle_tick_count`: incremented each tick whose actionable set is empty. Reset to 0 on any tick that dispatches `/muggle-do`. Diagnostic only — does not gate behavior.
|
|
54
57
|
- `cycles_completed`: incremented each time `/muggle-do` completes an address-reviews invocation (regardless of actionable/ambiguous/mixed).
|
|
@@ -10,27 +10,27 @@ Include **all** runs — passed, failed, **and inconclusive**. Never drop a run.
|
|
|
10
10
|
| `failed` | Run completed and the assertion failed, or the product itself broke before the assertion could be made (server error, 500, broken page). | `failureStepIndex`, `error` |
|
|
11
11
|
| `inconclusive` | Run could not yield a pass/fail signal for reasons **outside the product**: no replayable script existed, environment precondition unmet, infra/Electron error, agent stalled on a cookie banner or login wall, missing secrets, agent went off-course. | `reason` (one short sentence; `steps[]` may be empty) |
|
|
12
12
|
|
|
13
|
-
If a test should be inconclusive but you don't have a real `runId` / `viewUrl` (e.g., generation never ran), use the same project-level dashboard fallback as the "last-resort" failed branch below:
|
|
13
|
+
If a test should be inconclusive but you don't have a real `runId` / `viewUrl` (e.g., generation never ran), use the same project-level dashboard fallback as the "last-resort" failed branch below: synthesize a UUID-shaped runId and use `https://www.muggle-ai.com/muggleTestV0/dashboard/projects/{projectId}/runs` as `viewUrl`. The schema requires both fields — but a working dashboard link is better than nothing.
|
|
14
14
|
|
|
15
|
-
##
|
|
15
|
+
## Published run (passed or failed; the common path)
|
|
16
16
|
|
|
17
|
-
|
|
17
|
+
The studio publishes every completed local run — pass or fail, with or without action steps — to the cloud during execution. `muggle-local-run-result-get` carries `viewUrl` and `cloudActionScriptId`; `cloudTestScriptId` is **only present for passing runs and replays** (failed generations skip the test script wrapper to avoid clobbering the canonical replay target).
|
|
18
18
|
|
|
19
|
-
Fetch step screenshots in parallel — pick the right tool per
|
|
19
|
+
Fetch step screenshots in parallel — pick the right tool per run result:
|
|
20
20
|
|
|
21
|
-
- **`
|
|
22
|
-
- **`
|
|
21
|
+
- **`cloudTestScriptId` present** → `muggle-remote-test-script-get` with that id.
|
|
22
|
+
- **`cloudTestScriptId` missing** (failed generation) → `muggle-remote-action-script-get` with `cloudActionScriptId`. Same `steps[]` + `summaryStep` shape; just one less hop.
|
|
23
23
|
|
|
24
24
|
For each result:
|
|
25
25
|
|
|
26
26
|
1. Build `steps[]`: `[{ stepIndex: <index>, action: steps[i].operation.action, screenshotUrl: steps[i].operation.screenshotUrl }, ...]`. Empty array is fine — zero-step runs still render the failure summary header in the walkthrough.
|
|
27
|
-
2. `viewUrl` — from
|
|
27
|
+
2. `viewUrl` — from the run result (deep-links to the specific run).
|
|
28
28
|
3. `status` — from `muggle-local-run-result-get`.
|
|
29
29
|
4. If failed: also capture `failureStepIndex`, `error`, `artifactsDir` from the run result.
|
|
30
30
|
|
|
31
|
-
## Last-resort:
|
|
31
|
+
## Last-resort: no cloud refs on the run result
|
|
32
32
|
|
|
33
|
-
Reach this branch only when
|
|
33
|
+
Reach this branch only when the run result carries no `viewUrl` / `cloudActionScriptId` (the studio publish never landed — older Electron build, network failure, auth issue). Don't drop the run; render a stub entry so reviewers still see something happened.
|
|
34
34
|
|
|
35
35
|
1. `steps: []`.
|
|
36
36
|
2. `viewUrl`: `https://www.muggle-ai.com/muggleTestV0/dashboard/projects/{projectId}/runs` (generic dashboard).
|
|
@@ -52,9 +52,9 @@ If called from `muggle-do`: `e2e-acceptance.md` already produces this shape —
|
|
|
52
52
|
"description": "<one-line description (recommended)>",
|
|
53
53
|
"useCaseName": "<parent use case title (recommended)>",
|
|
54
54
|
"testCaseId": "<testCaseId from execution step>",
|
|
55
|
-
"testScriptId": "<
|
|
55
|
+
"testScriptId": "<cloudTestScriptId from run result>",
|
|
56
56
|
"runId": "<runId from muggle-local-execute-test-generation>",
|
|
57
|
-
"viewUrl": "<viewUrl from
|
|
57
|
+
"viewUrl": "<viewUrl from run result>",
|
|
58
58
|
"status": "passed",
|
|
59
59
|
"steps": [{ "stepIndex": 0, "action": "...", "screenshotUrl": "..." }]
|
|
60
60
|
},
|
|
@@ -64,7 +64,7 @@ If called from `muggle-do`: `e2e-acceptance.md` already produces this shape —
|
|
|
64
64
|
"useCaseName": "<parent use case title (recommended)>",
|
|
65
65
|
"testCaseId": "<testCaseId from execution step>",
|
|
66
66
|
"runId": "<runId from muggle-local-execute-test-generation>",
|
|
67
|
-
"viewUrl": "<viewUrl from
|
|
67
|
+
"viewUrl": "<viewUrl from run result>",
|
|
68
68
|
"status": "failed",
|
|
69
69
|
"steps": [],
|
|
70
70
|
"failureStepIndex": 0,
|
|
@@ -76,7 +76,7 @@ If called from `muggle-do`: `e2e-acceptance.md` already produces this shape —
|
|
|
76
76
|
"useCaseName": "<parent use case title (recommended)>",
|
|
77
77
|
"testCaseId": "<testCaseId from execution step>",
|
|
78
78
|
"runId": "<runId from execute, or synthesized UUID if no run started>",
|
|
79
|
-
"viewUrl": "<viewUrl from
|
|
79
|
+
"viewUrl": "<viewUrl from run result, or project-level fallback URL>",
|
|
80
80
|
"status": "inconclusive",
|
|
81
81
|
"steps": [],
|
|
82
82
|
"reason": "<one short sentence: why neither pass nor fail applies>"
|
|
@@ -27,7 +27,7 @@ For each option: label = key name, description = first paragraph of `preference-
|
|
|
27
27
|
|
|
28
28
|
- `multiSelect: true`, `header: "Auth & session"` — `autoLogin`, `autoSelectProject`, `checkForUpdates`, `verboseOutput`
|
|
29
29
|
- `multiSelect: true`, `header: "Test setup"` — `autoSelectLocalHost`, `autoDetectChanges`, `autoReuseValidationContext`
|
|
30
|
-
- `multiSelect: true`, `header: "Test run"` — `showElectronBrowser`, `openTestResultsAfterRun
|
|
30
|
+
- `multiSelect: true`, `header: "Test run"` — `showElectronBrowser`, `openTestResultsAfterRun`
|
|
31
31
|
- `multiSelect: true`, `header: "Suggestions"` — `suggestRelatedUseCases`, `suggestRelatedTestCases`
|
|
32
32
|
- `multiSelect: true`, `header: "PR"` — `postPRVisualWalkthrough`, `autoCreatePR`, `autoWatchPR`
|
|
33
33
|
- `multiSelect: true`, `header: "Branch hygiene"` — `autoUseWorktree`, `autoRebase`, `autoCleanup`
|
|
@@ -43,7 +43,7 @@ For each toggled key (multi-select questions): `muggle-local-preferences-set` wi
|
|
|
43
43
|
|
|
44
44
|
## Step 5 — `never` follow-up
|
|
45
45
|
|
|
46
|
-
Ask: `Want any of these set to "never" (auto-skip without asking)? Name them, e.g. "never on
|
|
46
|
+
Ask: `Want any of these set to "never" (auto-skip without asking)? Name them, e.g. "never on showElectronBrowser", or say "no".`. For named keys, call `muggle-local-preferences-set` with `value: "never"`, same scope.
|
|
47
47
|
|
|
48
48
|
## Step 6 — confirm
|
|
49
49
|
|