@muggleai/works 4.14.0 → 4.15.1
This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
- package/dist/plugin/.claude-plugin/plugin.json +1 -1
- package/dist/plugin/.cursor-plugin/plugin.json +1 -1
- package/dist/plugin/agents/acceptance-tester.md +2 -0
- package/dist/plugin/commands/mbt.md +7 -0
- package/dist/plugin/commands/mdo.md +3 -3
- package/dist/plugin/skills/CLAUDE.md +15 -0
- package/dist/plugin/skills/_aliases.json +1 -0
- package/dist/plugin/skills/_shared/ci-check-to-command.md +10 -0
- package/dist/plugin/skills/_shared/dev-loop/action-script.md +3 -0
- package/dist/plugin/skills/_shared/dev-loop/failures.md +14 -0
- package/dist/plugin/skills/_shared/dev-loop/fresh-session.md +10 -0
- package/dist/plugin/skills/_shared/dev-loop/publish.md +13 -0
- package/dist/plugin/skills/_shared/dev-loop/run.md +34 -0
- package/dist/plugin/skills/_shared/dev-loop/timeouts.md +6 -0
- package/dist/plugin/skills/_shared/failure-mode-handling.md +2 -2
- package/dist/plugin/skills/_shared/github-cli-recipes/pr-checks.md +22 -0
- package/dist/plugin/skills/_shared/github-cli-recipes.md +1 -0
- package/dist/plugin/skills/_shared/post-merge-cleanup.md +1 -1
- package/dist/plugin/skills/_shared/pr-branch-worktree.md +1 -1
- package/dist/plugin/skills/_shared/rebase-before-e2e.md +7 -1
- package/dist/plugin/skills/_shared/resolve-rebase-conflicts.md +60 -0
- package/dist/plugin/skills/_shared/telemetry-events/muggle-do-cycle.md +8 -1
- package/dist/plugin/skills/_shared/telemetry-events/muggle-do-escalation.md +2 -1
- package/dist/plugin/skills/_shared/telemetry-events/pr-followup-tick.md +4 -0
- package/dist/plugin/skills/_shared/use-worktrees.md +2 -1
- package/dist/plugin/skills/do/address-reviews.md +6 -0
- package/dist/plugin/skills/do/cleanup.md +14 -0
- package/dist/plugin/skills/do/e2e-acceptance.md +5 -66
- package/dist/plugin/skills/do/fix-ci.md +60 -0
- package/dist/plugin/skills/do/input-routing.md +12 -0
- package/dist/plugin/skills/do/open-prs/forward.md +1 -1
- package/dist/plugin/skills/do/pre-flight.md +3 -3
- package/dist/plugin/skills/mbt/SKILL.md +8 -0
- package/dist/plugin/skills/mdo/SKILL.md +3 -3
- package/dist/plugin/skills/{muggle-do-task → muggle-browser-task}/SKILL.md +1 -1
- package/dist/plugin/skills/muggle-do/SKILL.md +3 -10
- package/dist/plugin/skills/muggle-pr-followup/CLAUDE.md +4 -5
- package/dist/plugin/skills/muggle-pr-followup/SKILL.md +4 -1
- package/dist/plugin/skills/muggle-pr-followup/auto-track.md +5 -1
- package/dist/plugin/skills/muggle-pr-followup/contract.md +33 -16
- package/dist/plugin/skills/muggle-pr-followup/finalize.md +29 -0
- package/dist/plugin/skills/muggle-pr-followup/reconcile.md +33 -0
- package/dist/plugin/skills/muggle-pr-followup/state-schemas.md +5 -1
- package/dist/plugin/skills/muggle-preferences/preference-gates/autoResolveConflicts.md +11 -0
- package/dist/plugin/skills/muggle-test/SKILL.md +14 -45
- package/dist/plugin/skills/muggle-test-feature-local/SKILL.md +5 -42
- package/dist/release-manifest.json +4 -4
- package/package.json +6 -6
- package/plugin/.claude-plugin/plugin.json +1 -1
- package/plugin/.cursor-plugin/plugin.json +1 -1
- package/plugin/agents/acceptance-tester.md +2 -0
- package/plugin/commands/mbt.md +7 -0
- package/plugin/commands/mdo.md +3 -3
- package/plugin/skills/CLAUDE.md +15 -0
- package/plugin/skills/_aliases.json +1 -0
- package/plugin/skills/_shared/ci-check-to-command.md +10 -0
- package/plugin/skills/_shared/dev-loop/action-script.md +3 -0
- package/plugin/skills/_shared/dev-loop/failures.md +14 -0
- package/plugin/skills/_shared/dev-loop/fresh-session.md +10 -0
- package/plugin/skills/_shared/dev-loop/publish.md +13 -0
- package/plugin/skills/_shared/dev-loop/run.md +34 -0
- package/plugin/skills/_shared/dev-loop/timeouts.md +6 -0
- package/plugin/skills/_shared/failure-mode-handling.md +2 -2
- package/plugin/skills/_shared/github-cli-recipes/pr-checks.md +22 -0
- package/plugin/skills/_shared/github-cli-recipes.md +1 -0
- package/plugin/skills/_shared/post-merge-cleanup.md +1 -1
- package/plugin/skills/_shared/pr-branch-worktree.md +1 -1
- package/plugin/skills/_shared/rebase-before-e2e.md +7 -1
- package/plugin/skills/_shared/resolve-rebase-conflicts.md +60 -0
- package/plugin/skills/_shared/telemetry-events/muggle-do-cycle.md +8 -1
- package/plugin/skills/_shared/telemetry-events/muggle-do-escalation.md +2 -1
- package/plugin/skills/_shared/telemetry-events/pr-followup-tick.md +4 -0
- package/plugin/skills/_shared/use-worktrees.md +2 -1
- package/plugin/skills/do/address-reviews.md +6 -0
- package/plugin/skills/do/cleanup.md +14 -0
- package/plugin/skills/do/e2e-acceptance.md +5 -66
- package/plugin/skills/do/fix-ci.md +60 -0
- package/plugin/skills/do/input-routing.md +12 -0
- package/plugin/skills/do/open-prs/forward.md +1 -1
- package/plugin/skills/do/pre-flight.md +3 -3
- package/plugin/skills/mbt/SKILL.md +8 -0
- package/plugin/skills/mdo/SKILL.md +3 -3
- package/plugin/skills/{muggle-do-task → muggle-browser-task}/SKILL.md +1 -1
- package/plugin/skills/muggle-do/SKILL.md +3 -10
- package/plugin/skills/muggle-pr-followup/CLAUDE.md +4 -5
- package/plugin/skills/muggle-pr-followup/SKILL.md +4 -1
- package/plugin/skills/muggle-pr-followup/auto-track.md +5 -1
- package/plugin/skills/muggle-pr-followup/contract.md +33 -16
- package/plugin/skills/muggle-pr-followup/finalize.md +29 -0
- package/plugin/skills/muggle-pr-followup/reconcile.md +33 -0
- package/plugin/skills/muggle-pr-followup/state-schemas.md +5 -1
- package/plugin/skills/muggle-preferences/preference-gates/autoResolveConflicts.md +11 -0
- package/plugin/skills/muggle-test/SKILL.md +14 -45
- package/plugin/skills/muggle-test-feature-local/SKILL.md +5 -42
|
@@ -1,7 +1,7 @@
|
|
|
1
1
|
{
|
|
2
2
|
"name": "muggle",
|
|
3
3
|
"description": "Run real-browser end-to-end (E2E) acceptance tests on your web app from any AI coding agent. Generate test scripts from plain English, replay them on localhost, capture screenshots, and validate user flows like signup, checkout, and dashboards. Works across Claude Code, Cursor, Codex, and Windsurf.",
|
|
4
|
-
"version": "4.
|
|
4
|
+
"version": "4.15.1",
|
|
5
5
|
"author": {
|
|
6
6
|
"name": "Muggle AI",
|
|
7
7
|
"email": "support@muggle-ai.com"
|
|
@@ -2,7 +2,7 @@
|
|
|
2
2
|
"name": "muggle",
|
|
3
3
|
"displayName": "Muggle AI",
|
|
4
4
|
"description": "Ship quality products with AI-powered end-to-end (E2E) acceptance testing that validates your web app like a real user — from Claude Code and Cursor to PR.",
|
|
5
|
-
"version": "4.
|
|
5
|
+
"version": "4.15.1",
|
|
6
6
|
"author": {
|
|
7
7
|
"name": "Muggle AI",
|
|
8
8
|
"email": "support@muggle-ai.com"
|
|
@@ -22,6 +22,8 @@ You operate through skills — never call raw MCP tools directly.
|
|
|
22
22
|
|
|
23
23
|
Select the skill based on what the orchestrator asks you to do. If the task doesn't clearly map to one skill, ask for clarification.
|
|
24
24
|
|
|
25
|
+
The run loop these skills execute (replay/regen, timeouts, publish, screenshots) lives in [`../skills/_shared/dev-loop/run.md`](../skills/_shared/dev-loop/run.md) — you reach it through `muggle-test`, never by calling MCP tools yourself.
|
|
26
|
+
|
|
25
27
|
## Input Contract
|
|
26
28
|
|
|
27
29
|
The orchestrator provides a dispatch prompt with:
|
|
@@ -0,0 +1,7 @@
|
|
|
1
|
+
---
|
|
2
|
+
description: Run a browser automation task on a website in natural language (alias for /muggle-browser-task)
|
|
3
|
+
argument-hint: [task description and target site]
|
|
4
|
+
allowed-tools: [Skill]
|
|
5
|
+
---
|
|
6
|
+
|
|
7
|
+
Invoke the `muggle-browser-task` skill via the Skill tool. Forward `$ARGUMENTS` as the skill's `args`.
|
|
@@ -1,7 +1,7 @@
|
|
|
1
1
|
---
|
|
2
|
-
description:
|
|
3
|
-
argument-hint: [
|
|
2
|
+
description: Muggle AI autonomous workflow entry point (alias for /muggle-do)
|
|
3
|
+
argument-hint: [what to build, or a directive]
|
|
4
4
|
allowed-tools: [Skill]
|
|
5
5
|
---
|
|
6
6
|
|
|
7
|
-
Invoke the `muggle-do
|
|
7
|
+
Invoke the `muggle-do` skill via the Skill tool. Forward `$ARGUMENTS` as the skill's `args`.
|
|
@@ -0,0 +1,15 @@
|
|
|
1
|
+
# Skill authoring conventions
|
|
2
|
+
|
|
3
|
+
Rules for every skill under `plugin/skills/`. Read before adding or editing one.
|
|
4
|
+
|
|
5
|
+
## One-way dependencies — no reverse references
|
|
6
|
+
|
|
7
|
+
Skill cross-references form a one-way graph. If any file in skill **A** references skill **B** — a markdown link to B's files, or a documented dependency on B's internals — then **no file in B may reference A back**. Reference *downward*, toward the more general / lower-level skill you depend on; pass anything the other direction needs as input, not as a link.
|
|
8
|
+
|
|
9
|
+
A reverse reference (A → B and B → A) couples the depended-on skill to its caller, creates a cycle no one can reason about in isolation, and makes every edit ripple both ways. The lower-level skill must stay reusable by callers it has never heard of.
|
|
10
|
+
|
|
11
|
+
**Runtime dispatch is not a doc reference.** A dumb-pipe skill may *fire* another skill's slash command at runtime (hand off and forget) — that is an action, not a dependency. What the rule forbids is a procedure file **linking to** or **encoding the internals of** the skill it hands off to.
|
|
12
|
+
|
|
13
|
+
**Worked example.** `muggle-pr-followup` (the dumb-pipe watcher) is lower-level than `muggle-do` (the executor that orchestrates it). `muggle-do` references `muggle-pr-followup`; `muggle-pr-followup`'s files must not link back to `muggle-do`. A watcher tick still dispatches `/muggle-do …` at runtime — allowed — but no watcher file links a `do/` file or restates its steps, and shared primitives like `muggle-pr-followup/finalize.md` stay dispatch-free so any caller can reuse them.
|
|
14
|
+
|
|
15
|
+
When you feel the urge to link "up" to a caller, that is the smell — restructure so the caller passes what is needed in.
|
|
@@ -0,0 +1,10 @@
|
|
|
1
|
+
# CI check → local fix command
|
|
2
|
+
|
|
3
|
+
Map a red CI check to the local command that reproduces and fixes it. Repo-agnostic — read the repo's `package.json` scripts; never hardcode script names.
|
|
4
|
+
|
|
5
|
+
| Failing check | Local action |
|
|
6
|
+
| :------------ | :----------- |
|
|
7
|
+
| lint / format | Run the repo's lint `--fix` / formatter; restage. |
|
|
8
|
+
| typecheck | Run the typecheck script; read the errors; edit the types. |
|
|
9
|
+
| unit / test | Run the suite; read the failures; fix the code or the test. |
|
|
10
|
+
| out of scope — E2E-in-CI, build/deploy infra, flaky / non-deterministic, or unknown | Do **not** attempt; record for escalation. |
|
|
@@ -0,0 +1,3 @@
|
|
|
1
|
+
# Dev Loop — Action Script
|
|
2
|
+
|
|
3
|
+
On the replay path use the `muggle-remote-action-script-get` response **as-is** — never edit, shorten, or rebuild `actionScript`; replay needs the full `label` paths for element lookup. For batches, fan the script fetches out in parallel before the sequential execute loop.
|
|
@@ -0,0 +1,14 @@
|
|
|
1
|
+
# Dev Loop — Reading the Result
|
|
2
|
+
|
|
3
|
+
For each `runId`, call `muggle-local-run-result-get` and read **structured fields**, never `execute`'s stdout tail (a truncated display excerpt). Order: `Status` → `Error` → `Artifacts`. Retain per test case: `testCaseId`, `testScriptId` (if any), `runId`, `status`, `artifactsDir`.
|
|
4
|
+
|
|
5
|
+
## Artifacts
|
|
6
|
+
|
|
7
|
+
The `Artifacts` section is present after any completed run; it names `artifactsDir` and lists files. On pass, `results.md` is the step-by-step verdict (read it before summarizing). On failure, `stdout.log` + `stderr.log` are always present; `action-script.json` appears when generation reached step-emission (typical for `goal_not_achievable`); `results.md` and per-step screenshots are absent on the failure path — don't hunt for them.
|
|
8
|
+
|
|
9
|
+
## Common failures
|
|
10
|
+
|
|
11
|
+
- `Electron execution timed out after 300000ms` → orchestration wait too short; see [`timeouts.md`](timeouts.md).
|
|
12
|
+
- **Exit code 26** (with "LLM failed to generate / replay action script") is usually a completed exploration whose outcome was **goal not achievable** (`goal_not_achievable`, summary with `halt`) — e.g. asserting "view a completed run" on an account that has none. Read the summary; don't assume a crash. Fix the precondition: pick a project/account that already has the needed state, or narrow the goal so generation isn't forced to create resources from scratch.
|
|
13
|
+
|
|
14
|
+
Then route via [`../failure-mode-handling.md`](../failure-mode-handling.md).
|
|
@@ -0,0 +1,10 @@
|
|
|
1
|
+
# Dev Loop — Fresh Session
|
|
2
|
+
|
|
3
|
+
Pass `freshSession: true` for a test case that needs clean browser state (no prior cookies, localStorage, or login):
|
|
4
|
+
|
|
5
|
+
- Registration / sign-up.
|
|
6
|
+
- Login / authentication when the flow itself is under test (not a test that merely uses login as a prerequisite).
|
|
7
|
+
- Cookie-consent / GDPR first-visit banners.
|
|
8
|
+
- Onboarding / first-run experiences.
|
|
9
|
+
|
|
10
|
+
Otherwise omit it (defaults `false`, preserving session state). Evaluate per test case — in a batch some need it and some don't.
|
|
@@ -0,0 +1,13 @@
|
|
|
1
|
+
# Dev Loop — Publish & Screenshots
|
|
2
|
+
|
|
3
|
+
## Publish
|
|
4
|
+
|
|
5
|
+
After every completed run — pass or fail — publish: failed runs still need cloud-hosted screenshots and per-step actions for the walkthrough, and the upload `status` tells the backend whether to promote the action script as the canonical replay script (pass → promote; fail → record only).
|
|
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.
|
|
10
|
+
|
|
11
|
+
## Screenshots
|
|
12
|
+
|
|
13
|
+
Per published script, `muggle-remote-test-script-get` with the `testScriptId` from publish → 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.
|
|
@@ -0,0 +1,34 @@
|
|
|
1
|
+
# Dev Loop — Run a Test
|
|
2
|
+
|
|
3
|
+
> The local dev loop: run one test case in the browser (replay an existing script, or regenerate from the case), then record the result. Source of truth for the run mechanics; the sibling files in this folder own each invariant. Used by `muggle-test`, `muggle-test-feature-local`, `muggle-do` Stage 6 ([`../../do/e2e-acceptance.md`](../../do/e2e-acceptance.md)), and the `acceptance-tester` agent.
|
|
4
|
+
|
|
5
|
+
Not owned here — the caller resolves and passes in: which test cases to run, replay-vs-regen classification and failure routing ([`../failure-mode-handling.md`](../failure-mode-handling.md)), dev-server readiness ([`../dev-server-readiness.md`](../dev-server-readiness.md)), validation context ([`../resolve-e2e-validation-context.md`](../resolve-e2e-validation-context.md)), and PR posting ([`../../muggle-pr-visual-walkthrough/SKILL.md`](../../muggle-pr-visual-walkthrough/SKILL.md)).
|
|
6
|
+
|
|
7
|
+
## Inputs
|
|
8
|
+
|
|
9
|
+
The caller resolves these before the loop and supplies them per test case:
|
|
10
|
+
|
|
11
|
+
- `mode` — `replay` or `regen`, already chosen (by the user, or by [`../failure-mode-handling.md`](../failure-mode-handling.md) for change-driven callers).
|
|
12
|
+
- `localUrl` — local execution target. Local-only; never changes the cloud project or test definitions.
|
|
13
|
+
- `cwd` — absolute path of the active working tree (PR-branch worktree if one exists, else repo root). Drives the cross-worktree single-flight lock so concurrent runs serialize.
|
|
14
|
+
- `testCase` / `cloudTestCaseId` — the cloud test case and its id.
|
|
15
|
+
- `showUi` — from the caller's `showElectronBrowser` resolution: omit for visible, `false` for headless.
|
|
16
|
+
|
|
17
|
+
The tool boundary is fixed: cloud reads (`muggle-remote-*`) resolve definitions and scripts; local tools (`muggle-local-*`) run the browser, fetch results, and publish.
|
|
18
|
+
|
|
19
|
+
## Sequence
|
|
20
|
+
|
|
21
|
+
One local browser exists, so **execution is sequential** — one test case at a time, in the caller's order. The pre/post fetches are independent across test cases and should be issued in parallel batches around the sequential execute calls.
|
|
22
|
+
|
|
23
|
+
Per test case, branch on `mode`:
|
|
24
|
+
|
|
25
|
+
**Replay**
|
|
26
|
+
1. `muggle-remote-test-script-get` (latest replayable script) → note `actionScriptId`.
|
|
27
|
+
2. `muggle-remote-action-script-get` with that id → full `actionScript` (see [`action-script.md`](action-script.md)).
|
|
28
|
+
3. `muggle-local-execute-replay` with `testScript`, `actionScript`, `localUrl`, `cwd`, `showUi`, `freshSession` (see [`fresh-session.md`](fresh-session.md)), `timeoutMs` (see [`timeouts.md`](timeouts.md)).
|
|
29
|
+
|
|
30
|
+
**Regen**
|
|
31
|
+
1. `muggle-remote-test-case-get` → full test case object.
|
|
32
|
+
2. `muggle-local-execute-test-generation` with `testCase`, `localUrl`, `cwd`, `showUi`, `freshSession`, `timeoutMs`.
|
|
33
|
+
|
|
34
|
+
Store the returned `runId`, tagged with its `mode`. If a run fails, log it and continue the batch — never abort. Read the result per [`failures.md`](failures.md), then [`publish.md`](publish.md).
|
|
@@ -0,0 +1,6 @@
|
|
|
1
|
+
# Dev Loop — Timeouts
|
|
2
|
+
|
|
3
|
+
The MCP client default wait is **300000 ms (5 min)**. Exploratory generation (identity login, multi-step flows, many LLM iterations) routinely runs longer while the browser is still healthy.
|
|
4
|
+
|
|
5
|
+
- **Always pass `timeoutMs`** — `600000` (10 min) or `900000` (15 min) — unless the test case is known simple or the user wants a short cap.
|
|
6
|
+
- `Electron execution timed out after 300000ms` while logs show the run still progressing (steps, screenshots, LLM calls) is an **orchestration timeout, not a browser defect** — increase `timeoutMs` and retry.
|
|
@@ -1,6 +1,6 @@
|
|
|
1
1
|
# Failure-Mode Handling — Shared Reference
|
|
2
2
|
|
|
3
|
-
> Source of truth for **(a)** the pre-execution replay-vs-regen choice and **(b)** the post-execution failure router used by `muggle-test`, `muggle-test-feature-local`, `muggle-
|
|
3
|
+
> Source of truth for **(a)** the pre-execution replay-vs-regen choice and **(b)** the post-execution failure router used by `muggle-test`, `muggle-test-feature-local`, `muggle-browser-task`, and `muggle-test-regenerate-missing`. Skills MUST link here rather than restate the rules.
|
|
4
4
|
|
|
5
5
|
## The contract
|
|
6
6
|
|
|
@@ -55,7 +55,7 @@ Subagents return the verdict as part of a structured block, not free-form prose.
|
|
|
55
55
|
|
|
56
56
|
## A. Pre-execution: replay vs regen (used by `muggle-test`)
|
|
57
57
|
|
|
58
|
-
Run during change analysis, **per impacted test case**. Picks the initial execution mode before Step 7. Other skills with a single user-picked target (`muggle-test-feature-local`, `muggle-
|
|
58
|
+
Run during change analysis, **per impacted test case**. Picks the initial execution mode before Step 7. Other skills with a single user-picked target (`muggle-test-feature-local`, `muggle-browser-task`) skip this section — the user already chose.
|
|
59
59
|
|
|
60
60
|
### Inputs
|
|
61
61
|
|
|
@@ -0,0 +1,22 @@
|
|
|
1
|
+
# PR check-run rollup
|
|
2
|
+
|
|
3
|
+
Fetch the CI check state for a PR's head — what the watcher polls to detect red CI.
|
|
4
|
+
|
|
5
|
+
```bash
|
|
6
|
+
gh pr checks <pr-number> --repo <owner>/<repo> --json name,state,bucket,link
|
|
7
|
+
```
|
|
8
|
+
|
|
9
|
+
Each row:
|
|
10
|
+
|
|
11
|
+
- `name` — the check's name (e.g. `lint`, `typecheck`, `unit`, `build`).
|
|
12
|
+
- `state` — `SUCCESS` / `FAILURE` / `PENDING` / `SKIPPED` / `CANCELLED` / `NEUTRAL` (gh folds status + conclusion into one field).
|
|
13
|
+
- `bucket` — `pass` / `fail` / `pending` / `skipping` / `cancel`; the coarse rollup — filter on this.
|
|
14
|
+
- `link` — the check's details URL, for pulling logs in the fix-ci stage.
|
|
15
|
+
|
|
16
|
+
Classify for the watcher:
|
|
17
|
+
|
|
18
|
+
- **pending** — any row with `bucket == "pending"`. Checks haven't settled → idle.
|
|
19
|
+
- **red** — any row with `bucket == "fail"` (`state` FAILURE / CANCELLED / TIMED_OUT). Candidate for fix-ci.
|
|
20
|
+
- **green** — every row `pass` / `skipping`, or no rows at all.
|
|
21
|
+
|
|
22
|
+
The fix-ci dispatch carries the `name`s of the red rows. `gh pr checks` exits non-zero when any check fails — capture output regardless of exit code.
|
|
@@ -10,6 +10,7 @@ Skills assume a working `gh auth status`. Auth errors surface verbatim from `gh`
|
|
|
10
10
|
| :----- | :------- |
|
|
11
11
|
| [`pr-metadata`](github-cli-recipes/pr-metadata.md) | Snapshot PR state, head SHA, branch — watcher + bootstrap. |
|
|
12
12
|
| [`submitted-reviews`](github-cli-recipes/submitted-reviews.md) | Fetch reviews past a cursor — watcher's poll. |
|
|
13
|
+
| [`pr-checks`](github-cli-recipes/pr-checks.md) | Check-run rollup for the head SHA — watcher's CI poll. |
|
|
13
14
|
| [`line-comments-for-review`](github-cli-recipes/line-comments-for-review.md) | Pull a review's line comments — `/muggle-do` per-comment routing. |
|
|
14
15
|
| [`unresolved-threads`](github-cli-recipes/unresolved-threads.md) | GraphQL fetch of unresolved comment threads — resolve-reminder. |
|
|
15
16
|
| [`reply-line-comment`](github-cli-recipes/reply-line-comment.md) | POST a threaded reply on a line comment. |
|
|
@@ -5,6 +5,6 @@ Gated by [`autoCleanup`](../muggle-preferences/preference-gates/autoCleanup.md).
|
|
|
5
5
|
On `always`, the four steps below run as one pre-authorized sequence (no per-step prompts). Stop on the first failure; do not force.
|
|
6
6
|
|
|
7
7
|
1. `git worktree remove {worktreePath}` — only if a worktree was used.
|
|
8
|
-
2. `git branch -d {branch}`
|
|
8
|
+
2. `git branch -d {branch}` — **skip when no worktree was used**: the branch is the user's current live checkout (a bootstrap/auto-track watcher), and the checked-out branch must never be deleted. Then `git push origin --delete {branch}`.
|
|
9
9
|
3. Clear `.muggle-ai/` session folders for this branch's runs and stale `/tmp/muggle-prepare-*.log` files. Cloud results stay.
|
|
10
10
|
4. Invoke `commit-commands:clean_gone` via the `Skill` tool.
|
|
@@ -4,7 +4,7 @@
|
|
|
4
4
|
|
|
5
5
|
## When this applies
|
|
6
6
|
|
|
7
|
-
A skill receives a GitHub PR URL of the form `github.com/<org>/<repo>/pull/<n>` and needs the PR's branch checked out to test against it locally.
|
|
7
|
+
A skill receives a GitHub PR URL of the form `github.com/<org>/<repo>/pull/<n>` and needs the PR's branch checked out to test against it locally. For worktree principles (one-per-branch, port/data isolation, teardown) see [`use-worktrees.md`](use-worktrees.md) — this file owns only the materialize-an-existing-PR-branch operation.
|
|
8
8
|
|
|
9
9
|
## Steps
|
|
10
10
|
|
|
@@ -10,6 +10,12 @@ default=$(git symbolic-ref refs/remotes/origin/HEAD --short | sed 's|origin/||')
|
|
|
10
10
|
behind=$(git rev-list --count "HEAD..origin/${default}")
|
|
11
11
|
```
|
|
12
12
|
|
|
13
|
-
Pass `{behind}` and `{default}` to the picker prompts. On `always
|
|
13
|
+
Pass `{behind}` and `{default}` to the picker prompts. On `always`:
|
|
14
|
+
|
|
15
|
+
1. Capture the rollback point: `pre_rebase_sha=$(git rev-parse HEAD)`.
|
|
16
|
+
2. `git rebase origin/${default}`.
|
|
17
|
+
3. On conflict, branch by [`autoResolveConflicts`](../muggle-preferences/preference-gates/autoResolveConflicts.md):
|
|
18
|
+
- `never` (default) → `git rebase --abort`; stop and report, naming the conflicted files. Never auto-resolve.
|
|
19
|
+
- `always` → hand off to [`resolve-rebase-conflicts.md`](resolve-rebase-conflicts.md) with `pre_rebase_sha`; it resolves, runs the verify-or-rollback gate, and either proceeds or restores `pre_rebase_sha` and escalates.
|
|
14
20
|
|
|
15
21
|
Stale branches produce false failures and false greens — that's why this gate exists.
|
|
@@ -0,0 +1,60 @@
|
|
|
1
|
+
# Auto-Resolve Rebase Conflicts
|
|
2
|
+
|
|
3
|
+
The autonomous conflict-resolution body, run when a rebase onto `origin/{default}` reports conflicts **and** [`autoResolveConflicts`](../muggle-preferences/preference-gates/autoResolveConflicts.md) is `always`. Under the default `never` the caller aborts and escalates instead, and this file never runs. The caller hands off the inputs below; this file names no caller — the dependency runs one way.
|
|
4
|
+
|
|
5
|
+
Contract: never push an auto-resolved rebase that has not passed the verify gate, and always keep the branch restorable to its pre-rebase state.
|
|
6
|
+
|
|
7
|
+
## Inputs
|
|
8
|
+
|
|
9
|
+
- `pre_rebase_sha` — branch HEAD captured by the caller **before** `git rebase`; the rollback point.
|
|
10
|
+
- `default` — the branch being rebased onto.
|
|
11
|
+
- Session context: slug, PR url/number, and the persisted validation strategy (for the E2E step).
|
|
12
|
+
|
|
13
|
+
## Procedure
|
|
14
|
+
|
|
15
|
+
### Step 1 — Enumerate and classify conflicts
|
|
16
|
+
|
|
17
|
+
```bash
|
|
18
|
+
git diff --name-only --diff-filter=U
|
|
19
|
+
```
|
|
20
|
+
|
|
21
|
+
Classify each conflicted path:
|
|
22
|
+
|
|
23
|
+
- **Mechanical** — lockfiles (`package-lock.json`, `pnpm-lock.yaml`, `yarn.lock`, `Cargo.lock`, …), generated output (`dist/`, build artifacts, snapshots), or pure formatting / import-order churn.
|
|
24
|
+
- **Semantic** — anything carrying logic: source, behavior-changing config, tests.
|
|
25
|
+
|
|
26
|
+
### Step 2 — Resolve
|
|
27
|
+
|
|
28
|
+
- **Mechanical** → resolve deterministically: regenerate the lockfile with the repo's package manager; regenerate or take-incoming for generated files; run the repo's formatter. Never hand-merge a lockfile.
|
|
29
|
+
- **Semantic** → a reasoned 3-way resolution preserving the intent of **both** sides (ours = the PR's change, theirs = the new default-branch line). If intent in load-bearing logic can't be confidently reconciled, do not guess → Step 5.
|
|
30
|
+
|
|
31
|
+
Then `git add -A && git rebase --continue`, and repeat Steps 1–2 for each remaining conflicted commit until the rebase completes.
|
|
32
|
+
|
|
33
|
+
### Step 3 — Verify gate (mandatory)
|
|
34
|
+
|
|
35
|
+
Each must pass, in order:
|
|
36
|
+
|
|
37
|
+
1. **Build** — typecheck + lint on the changed surface, per [`../do/build.md`](../do/build.md).
|
|
38
|
+
2. **Unit suite** — per [`../do/unit-tests.md`](../do/unit-tests.md); record PASS.
|
|
39
|
+
3. **E2E** — per [`../do/e2e-acceptance.md`](../do/e2e-acceptance.md) and the persisted [`autoE2ETest`](../muggle-preferences/preference-gates/autoE2ETest.md) strategy. A poll-only session with no validation context reports `SKIPPED`, same as the normal cycle.
|
|
40
|
+
|
|
41
|
+
### Step 4 — Pass → proceed
|
|
42
|
+
|
|
43
|
+
Return success. The caller resumes the normal flow; the push happens downstream, so a resolved rebase ships only after it has verified.
|
|
44
|
+
|
|
45
|
+
### Step 5 — Fail → restore + escalate
|
|
46
|
+
|
|
47
|
+
On an unreconcilable semantic conflict (Step 2) or any verify failure (Step 3):
|
|
48
|
+
|
|
49
|
+
```bash
|
|
50
|
+
git rebase --abort 2>/dev/null || true
|
|
51
|
+
git reset --hard <pre_rebase_sha>
|
|
52
|
+
```
|
|
53
|
+
|
|
54
|
+
The branch is now byte-for-byte its pre-rebase state. Emit one terminal escalation per [`../muggle-pr-followup/output-templates/escalation.md`](../muggle-pr-followup/output-templates/escalation.md) naming the conflicted files and the failing step, plus the `muggle-do:escalation` event with `kind: "rebase-conflict"` ([`telemetry-events/muggle-do-escalation.md`](telemetry-events/muggle-do-escalation.md)). Do not push.
|
|
55
|
+
|
|
56
|
+
## Invariants
|
|
57
|
+
|
|
58
|
+
- A push never follows a verify failure.
|
|
59
|
+
- The branch is always restorable to `pre_rebase_sha`.
|
|
60
|
+
- This file runs only under `autoResolveConflicts = always`; `never` is the caller's unchanged abort-and-escalate path.
|
|
@@ -12,9 +12,12 @@ One per address-reviews invocation, regardless of outcome.
|
|
|
12
12
|
"review_ids_in": [<int>, ...],
|
|
13
13
|
"review_ids_actionable": [<int>, ...],
|
|
14
14
|
"review_ids_ambiguous": [<int>, ...],
|
|
15
|
+
"ci_checks_in": ["<check-name>", ...],
|
|
16
|
+
"ci_checks_fixed": ["<check-name>", ...],
|
|
17
|
+
"ci_checks_escalated": ["<check-name>", ...],
|
|
15
18
|
"head_sha_before": "<sha-or-null>",
|
|
16
19
|
"head_sha_after": "<sha-or-null>",
|
|
17
|
-
"outcome": "pushed" | "escalated" | "mixed" | "no-op" | "self-loop-skip"
|
|
20
|
+
"outcome": "pushed" | "escalated" | "mixed" | "no-op" | "self-loop-skip" | "ci-fixed" | "ci-escalated"
|
|
18
21
|
}
|
|
19
22
|
```
|
|
20
23
|
|
|
@@ -24,3 +27,7 @@ One per address-reviews invocation, regardless of outcome.
|
|
|
24
27
|
- `"mixed"` — both branches happened in the same invocation.
|
|
25
28
|
- `"no-op"` — every input id was already in the escalated set; no work.
|
|
26
29
|
- `"self-loop-skip"` — review was a synthetic wrapper around the agent's own reply (every line comment is a reply carrying the loop marker `<!-- muggle-do:bot -->`). Cursor advanced silently; no work, no escalation.
|
|
30
|
+
- `"ci-fixed"` — a watcher-dispatched fix-ci cycle pushed a fix for one or more red checks.
|
|
31
|
+
- `"ci-escalated"` — fix-ci exhausted its 3 attempts for the SHA or the failing checks were out of scope; the SHA was added to `ci_escalated_shas`. No further auto-fix on it.
|
|
32
|
+
|
|
33
|
+
For fix-ci cycles (`ci-fixed` / `ci-escalated`) the `review_ids_*` arrays are empty and the `ci_checks_*` arrays carry the data: `ci_checks_in` (red checks dispatched), `ci_checks_fixed` (made green and pushed), `ci_checks_escalated` (out-of-scope or unresolved).
|
|
@@ -9,7 +9,7 @@ Zero or one per address-reviews invocation. Fires when `/muggle-do` emits a term
|
|
|
9
9
|
"session_slug": "<slug>",
|
|
10
10
|
"repo": "<owner>/<repo>",
|
|
11
11
|
"pr_number": <int>,
|
|
12
|
-
"kind": "ambiguous-review" | "design-adjustment",
|
|
12
|
+
"kind": "ambiguous-review" | "design-adjustment" | "rebase-conflict",
|
|
13
13
|
"review_ids": [<int>, ...]
|
|
14
14
|
}
|
|
15
15
|
```
|
|
@@ -17,3 +17,4 @@ Zero or one per address-reviews invocation. Fires when `/muggle-do` emits a term
|
|
|
17
17
|
`kind`:
|
|
18
18
|
- `"ambiguous-review"` — one or more reviews classified ambiguous in this batch.
|
|
19
19
|
- `"design-adjustment"` — mid-cycle, the work surfaced a design-level conflict.
|
|
20
|
+
- `"rebase-conflict"` — an opt-in auto-rebase hit conflicts that couldn't be resolved and verified; the branch was restored to its pre-rebase SHA. `review_ids` may be empty.
|
|
@@ -11,6 +11,8 @@ One per watcher iteration (idle or not).
|
|
|
11
11
|
"pr_number": <int>,
|
|
12
12
|
"reviews_seen": <int>,
|
|
13
13
|
"dispatched_review_ids": [<int>, ...],
|
|
14
|
+
"checks_red": <int>,
|
|
15
|
+
"dispatched_ci_fix": true | false,
|
|
14
16
|
"terminal": true | false,
|
|
15
17
|
"idle": true | false,
|
|
16
18
|
"tick_duration_ms": <int>
|
|
@@ -19,5 +21,7 @@ One per watcher iteration (idle or not).
|
|
|
19
21
|
|
|
20
22
|
- `reviews_seen`: count of new submitted reviews past the cursor, **after** filtering by the escalated set.
|
|
21
23
|
- `dispatched_review_ids`: review ids handed to `/muggle-do`. Empty when idle.
|
|
24
|
+
- `checks_red`: count of failing checks on the head SHA. `0` when reviews were dispatched (reviews preempt the CI poll) or CI was green/pending.
|
|
25
|
+
- `dispatched_ci_fix`: true when this tick dispatched `/muggle-do` with a fix-ci directive.
|
|
22
26
|
- `terminal`: true when this tick observed the PR merged or closed and wrote `result.md`.
|
|
23
27
|
- `idle`: true when no reviews were dispatched this tick.
|
|
@@ -7,13 +7,14 @@ Use this for feature development, local validation, and PR iteration.
|
|
|
7
7
|
- **One worktree per branch.** Never switch branches inside a long-lived checkout.
|
|
8
8
|
- **Isolate runtime resources.** Parallel worktrees need unique ports and isolated mutable test state.
|
|
9
9
|
- **Keep worktrees disposable.** Create for focused work, remove after merge.
|
|
10
|
+
- **Existing PR branch?** Materialize it via [`pr-branch-worktree.md`](pr-branch-worktree.md) — same `<repo>/.claude/worktrees/` path scheme, checking out the existing branch instead of creating a new one.
|
|
10
11
|
|
|
11
12
|
## Start new change work
|
|
12
13
|
|
|
13
14
|
1. Update the base branch (usually `main`).
|
|
14
15
|
2. Create a new worktree and branch:
|
|
15
16
|
```bash
|
|
16
|
-
git worktree add <repo
|
|
17
|
+
git worktree add <repo>/.claude/worktrees/<sanitized-branch> -b <branch>
|
|
17
18
|
```
|
|
18
19
|
3. Install dependencies and run setup in that worktree.
|
|
19
20
|
4. Keep all edits and commits for the change in that same worktree.
|
|
@@ -27,6 +27,10 @@ Read from `~/.muggle-ai/muggle-do/sessions/<slug>/`:
|
|
|
27
27
|
|
|
28
28
|
## Procedure
|
|
29
29
|
|
|
30
|
+
### Step 0 — Track the default branch
|
|
31
|
+
|
|
32
|
+
Before assembling work, rebase onto the latest default branch so the cycle addresses reviews against current master, not a stale base. Run [`../_shared/rebase-before-e2e.md`](../_shared/rebase-before-e2e.md) — gated by [`autoRebase`](../muggle-preferences/preference-gates/autoRebase.md), fires only when `behind > 0`. Conflict handling follows [`autoResolveConflicts`](../muggle-preferences/preference-gates/autoResolveConflicts.md): the default `never` aborts and escalates (`kind: "rebase-conflict"`); `always` resolves behind the verify-or-rollback gate. If the rebase escalates, stop the cycle — do not push.
|
|
33
|
+
|
|
30
34
|
### Step 1 — Assemble the work set
|
|
31
35
|
|
|
32
36
|
Two sources, combined into one batch (dedupe by comment id):
|
|
@@ -63,6 +67,8 @@ The user clarifies on GitHub by submitting a new review. The next watcher tick p
|
|
|
63
67
|
|
|
64
68
|
If `actionable_review_ids` is empty, skip the rest of Step 4 and Step 5; proceed to Step 5.5 (resolve-reminder) then Step 6. Otherwise:
|
|
65
69
|
|
|
70
|
+
Before any edits, ensure the PR's branch workspace is the working directory. If `state.md` carries a `worktreePath` (forward-mode session), use it. Otherwise materialize the PR branch per [`../_shared/pr-branch-worktree.md`](../_shared/pr-branch-worktree.md) — the single owner of checking out a PR branch in isolation — so a bootstrap or auto-track watcher never edits the user's live checkout. If the resolved tree is dirty with unrelated work, escalate per Step 7 rather than editing it.
|
|
71
|
+
|
|
66
72
|
#### 4a. Flatten the work
|
|
67
73
|
|
|
68
74
|
The actionable reviews together carry a flat list of change items, one per line comment plus any directive in the review body. Each item is design, code logic, or test in nature; the cycle does **not** treat each item as a separate cycle iteration — it plans them together and runs the work **once** for the whole batch.
|
|
@@ -0,0 +1,14 @@
|
|
|
1
|
+
# Post-Merge Cleanup Stage
|
|
2
|
+
|
|
3
|
+
Invoked by `/muggle-do` when the watcher forwards a PR's terminal (`merged`) state. This stage only resolves the session's workspace and **delegates** teardown to the shared procedure — it does not restate the teardown steps. Never runs while the PR is open.
|
|
4
|
+
|
|
5
|
+
## Input
|
|
6
|
+
|
|
7
|
+
`$ARGUMENTS` carries the session slug as `slug=<slug>`. No PR URL, no review ids.
|
|
8
|
+
|
|
9
|
+
## Procedure
|
|
10
|
+
|
|
11
|
+
1. Read `~/.muggle-ai/muggle-do/sessions/<slug>/`: `prs.json` (PR `repo`, `number`, observed `state`) and `state.md` (`worktreePath` if a worktree was used, and the target branch `headRefName`).
|
|
12
|
+
2. Confirm `prs.json` shows the PR `merged`. If it is still open or was closed unmerged, do nothing and exit — this stage is post-merge only.
|
|
13
|
+
3. Run [`../_shared/post-merge-cleanup.md`](../_shared/post-merge-cleanup.md) with `{worktreePath}` and `{branch}`. That file owns the teardown sequence **and its safety rules** — including skipping worktree-remove and local branch deletion when no worktree was used. This stage adds no teardown logic of its own.
|
|
14
|
+
4. Append a cleanup line to the session's `followup.log`.
|
|
@@ -58,7 +58,7 @@ For a `local-e2e` block, use `localUrl`, `projectId`, and the working-tree path
|
|
|
58
58
|
|
|
59
59
|
Before launching the local runner:
|
|
60
60
|
|
|
61
|
-
1. **Dev-server + backend readiness** —
|
|
61
|
+
1. **Dev-server + backend readiness** — invoke [`muggle-test-prepare`](../muggle-test-prepare/SKILL.md), the readiness/service-start owner (idempotent fast-exit when healthy; probes via `dev-server-readiness.md`). Halt on failure.
|
|
62
62
|
2. **Auth** — `muggle-remote-auth-status` must be `authenticated`; else escalate.
|
|
63
63
|
3. **Identity tenant/domain match** — if test credentials were marked `existing`, confirm the repo's configured identity tenant/domain matches the recorded tenant/domain. Mismatch → halt.
|
|
64
64
|
|
|
@@ -96,71 +96,11 @@ Based on the changed files and the requirements goal, determine which test cases
|
|
|
96
96
|
- Test cases that cover areas potentially affected by the changes
|
|
97
97
|
- When in doubt, include the test case (better to over-test than miss a regression)
|
|
98
98
|
|
|
99
|
-
### Step 4:
|
|
99
|
+
### Step 4: Run the dev loop, publish, gather screenshots
|
|
100
100
|
|
|
101
|
-
For each relevant test case:
|
|
101
|
+
For each relevant test case, run the shared loop in [`../_shared/dev-loop/run.md`](../_shared/dev-loop/run.md): `muggle-remote-test-script-list` by `testCaseId` to pick [replay vs regen](../_shared/dev-loop/run.md), [execute with `timeoutMs`](../_shared/dev-loop/timeouts.md), [fetch the result](../_shared/dev-loop/failures.md) and [interpret failures](../_shared/dev-loop/failures.md), [publish](../_shared/dev-loop/publish.md), and gather [per-step screenshots](../_shared/dev-loop/publish.md).
|
|
102
102
|
|
|
103
|
-
|
|
104
|
-
|
|
105
|
-
2. **If a script exists** (replay path):
|
|
106
|
-
- `muggle-remote-test-script-get` with `testScriptId` → note `actionScriptId`
|
|
107
|
-
- `muggle-remote-action-script-get` with that id → full `actionScript`
|
|
108
|
-
- **Use the API response as-is.** Do not edit, shorten, or rebuild `actionScript`; replay needs full `label` paths for element lookup.
|
|
109
|
-
- `muggle-local-execute-replay` with:
|
|
110
|
-
- `testScript`: the full script object
|
|
111
|
-
- `actionScript`: the full action script object (from `muggle-remote-action-script-get`)
|
|
112
|
-
- `localUrl`: the resolved local URL
|
|
113
|
-
- `timeoutMs`: `600000` (10 min) or `900000` (15 min) for complex flows
|
|
114
|
-
|
|
115
|
-
3. **If no script exists** (generation path):
|
|
116
|
-
- `muggle-remote-test-case-get` with `testCaseId` to fetch the full test case object.
|
|
117
|
-
- `muggle-local-execute-test-generation` with:
|
|
118
|
-
- `testCase`: the full test case object
|
|
119
|
-
- `localUrl`: the resolved local URL
|
|
120
|
-
- `timeoutMs`: `600000` (10 min) or `900000` (15 min) for complex flows
|
|
121
|
-
|
|
122
|
-
4. When execution completes, call `muggle-local-run-result-get` with the `runId` returned by the execute call.
|
|
123
|
-
|
|
124
|
-
5. **Retain per test case:** `testCaseId`, `testScriptId` (if present), `runId`, `status` (passed/failed), `artifactsDir`.
|
|
125
|
-
|
|
126
|
-
### Local Execution Timeout (`timeoutMs`)
|
|
127
|
-
|
|
128
|
-
The MCP client often uses a **default wait of 300000 ms (5 minutes)**. **Exploratory script generation** (identity login, multi-step app flows, many LLM iterations) routinely **runs longer than 5 minutes** while Electron is still healthy.
|
|
129
|
-
|
|
130
|
-
- **Always pass `timeoutMs`** — `600000` (10 min) or `900000` (15 min) — unless the test case is known to be simple.
|
|
131
|
-
- If the tool reports **`Electron execution timed out after 300000ms`** but Electron logs show the run still progressing (steps, screenshots, LLM calls), treat it as **orchestration timeout**, not an Electron app defect: **increase `timeoutMs` and retry**.
|
|
132
|
-
|
|
133
|
-
### Interpreting Failures
|
|
134
|
-
|
|
135
|
-
- **`Electron execution timed out after 300000ms`:** Orchestration wait too short — see `timeoutMs` above.
|
|
136
|
-
- **Exit code 26** (and messages like **LLM failed to generate / replay action script**): Often corresponds to a completed exploration whose **outcome was goal not achievable** (`goal_not_achievable`, summary with `halt`). Use `muggle-local-run-result-get` and read the **summary / structured summary**; do not assume an Electron crash.
|
|
137
|
-
- **Fix for precondition failures:** Choose a project/account that already has the needed state, or narrow the test goal so generation does not try to create resources from scratch unless intentional.
|
|
138
|
-
|
|
139
|
-
### Step 5: Publish Test Scripts
|
|
140
|
-
|
|
141
|
-
After each test execution completes (whether pass or fail):
|
|
142
|
-
|
|
143
|
-
1. Call `muggle-local-publish-test-script` with:
|
|
144
|
-
- `runId`: the run ID from execution
|
|
145
|
-
- `cloudTestCaseId`: the test case ID
|
|
146
|
-
|
|
147
|
-
2. **Retain from publish response:**
|
|
148
|
-
- `testScriptId`: the cloud test script ID
|
|
149
|
-
- `viewUrl`: the URL to view the run on muggle-ai.com
|
|
150
|
-
|
|
151
|
-
This ensures all screenshots are uploaded to the cloud and accessible via URLs for PR comments.
|
|
152
|
-
|
|
153
|
-
### Step 6: Fetch Screenshot URLs
|
|
154
|
-
|
|
155
|
-
For each published test script:
|
|
156
|
-
|
|
157
|
-
1. Call `muggle-remote-test-script-get` with the `testScriptId` from publish.
|
|
158
|
-
|
|
159
|
-
2. Extract from the response:
|
|
160
|
-
- `steps[].operation.screenshotUrl`: cloud URL for each step's screenshot
|
|
161
|
-
- `steps[].operation.action`: the action description for each step
|
|
162
|
-
|
|
163
|
-
3. **Retain per test case:** array of `{ stepIndex, action, screenshotUrl }`.
|
|
103
|
+
Inputs to the loop: `mode` from the script-exists check, `localUrl`/project from Step 1.7, `cwd` = the working tree recorded in `state.md`.
|
|
164
104
|
|
|
165
105
|
### Step 7: Collect Results
|
|
166
106
|
|
|
@@ -216,8 +156,7 @@ For each test case:
|
|
|
216
156
|
## Non-negotiables
|
|
217
157
|
|
|
218
158
|
- No silent auth skip; always verify with `muggle-remote-auth-status` first.
|
|
219
|
-
- Replay
|
|
220
|
-
- Always pass `timeoutMs` for execution calls; do not rely on default 5-minute timeout.
|
|
159
|
+
- Replay/timeout/result discipline per [`../_shared/dev-loop/run.md`](../_shared/dev-loop/run.md) — never hand-build `actionScript`, always pass `timeoutMs`, read structured run-result fields.
|
|
221
160
|
- No hiding failures: surface errors, exit codes, and artifact paths.
|
|
222
161
|
- In `local-e2e` mode, every relevant test case must be executed — generate a new script if none exists (no skips).
|
|
223
162
|
- Always publish after execution to ensure screenshots are cloud-accessible for PR comments.
|
|
@@ -0,0 +1,60 @@
|
|
|
1
|
+
# Fix-CI (watcher-dispatched)
|
|
2
|
+
|
|
3
|
+
Resolve red CI on a PR's head — lint/format, typecheck, and failing unit tests — verifying green before re-push. A dumb-pipe dispatch like address-reviews: the executor receives a PR URL, slug, and the failing check names, and fixes them — it owns the fix, not the decision to dispatch.
|
|
4
|
+
|
|
5
|
+
## Turn preamble
|
|
6
|
+
|
|
7
|
+
```
|
|
8
|
+
**/muggle-do fix-ci** — fixing <count> red check(s) on <owner>/<repo>#<n>.
|
|
9
|
+
```
|
|
10
|
+
|
|
11
|
+
## Input
|
|
12
|
+
|
|
13
|
+
`$ARGUMENTS` carries a `github.com/.../pull/<n>` URL, `slug=<slug>`, and the failing check names (no review ids). Parse all three.
|
|
14
|
+
|
|
15
|
+
## Inputs from disk
|
|
16
|
+
|
|
17
|
+
From `~/.muggle-ai/muggle-do/sessions/<slug>/`: `prs.json` (PR + local checkout / branch), `last_seen.json` (`ci_fix_attempts`, `ci_escalated_shas`, `pushed_shas`), `state.md` (worktree path, validation strategy).
|
|
18
|
+
|
|
19
|
+
## Procedure
|
|
20
|
+
|
|
21
|
+
### Step 1 — Re-attach
|
|
22
|
+
|
|
23
|
+
Check out the PR branch in the session's working tree (per `state.md`). Capture `red_sha = prs.json[0].head_sha`.
|
|
24
|
+
|
|
25
|
+
### Step 2 — Map each failing check to a local command
|
|
26
|
+
|
|
27
|
+
Per [`../_shared/ci-check-to-command.md`](../_shared/ci-check-to-command.md). Fix the in-scope checks in the working tree; record out-of-scope checks for escalation (Step 6).
|
|
28
|
+
|
|
29
|
+
### Step 3 — Verify before push
|
|
30
|
+
|
|
31
|
+
- Build (typecheck + lint on the changed surface) + unit suite must pass.
|
|
32
|
+
- Run E2E (per [`../muggle-preferences/preference-gates/autoE2ETest.md`](../muggle-preferences/preference-gates/autoE2ETest.md)) only if the fix touched app logic; lint/format-only fixes skip E2E.
|
|
33
|
+
|
|
34
|
+
A fix that can't be made green locally is not pushed → Step 6.
|
|
35
|
+
|
|
36
|
+
### Step 4 — Commit + push
|
|
37
|
+
|
|
38
|
+
Commit per the `fix(ci): <check> — <what>` convention ([`../_shared/pr-followup-helpers/reply-routing.md`](../_shared/pr-followup-helpers/reply-routing.md)). Push. Append the new SHA to `last_seen.pushed_shas`. **No PR replies** — the fix commit is the response.
|
|
39
|
+
|
|
40
|
+
### Step 5 — Update state + respawn
|
|
41
|
+
|
|
42
|
+
- Increment `last_seen.ci_fix_attempts[red_sha]`.
|
|
43
|
+
- Respawn the watcher: `/loop 1m /muggle:muggle-pr-followup <slug> <n>`. CI on the new SHA is the verify loop — a still-red SHA returns as a fresh dispatch, bounded by the per-SHA fix budget (Step 6).
|
|
44
|
+
|
|
45
|
+
### Step 6 — Escalate (budget spent or out of scope)
|
|
46
|
+
|
|
47
|
+
When the failing checks are all out of scope, or `ci_fix_attempts[red_sha]` has reached 3 with CI still red:
|
|
48
|
+
|
|
49
|
+
1. Add `red_sha` to `last_seen.ci_escalated_shas` so the SHA is not re-fixed.
|
|
50
|
+
2. Emit one terminal message naming the unresolved checks.
|
|
51
|
+
3. Emit the cycle event with `outcome: "ci-escalated"` (Step 7). Do not loop further on this SHA.
|
|
52
|
+
|
|
53
|
+
### Step 7 — Telemetry
|
|
54
|
+
|
|
55
|
+
Emit one `muggle-do:cycle` event ([`../_shared/telemetry-events/muggle-do-cycle.md`](../_shared/telemetry-events/muggle-do-cycle.md)): `outcome: "ci-fixed"` when a fix pushed, `"ci-escalated"` when escalated — with `ci_checks_in` / `ci_checks_fixed` / `ci_checks_escalated`.
|
|
56
|
+
|
|
57
|
+
## Guardrails
|
|
58
|
+
|
|
59
|
+
- Max 3 fix attempts per SHA; out-of-scope checks escalate immediately rather than churn.
|
|
60
|
+
- No PR replies; the fix commit is the response.
|
|
@@ -0,0 +1,12 @@
|
|
|
1
|
+
# Input routing
|
|
2
|
+
|
|
3
|
+
How `/muggle-do` resolves `$ARGUMENTS` to a mode. Modes 1–3 are programmatic — dispatched by the watcher — so never ask on those. Inspect in order:
|
|
4
|
+
|
|
5
|
+
1. **Address-reviews** — a `github.com/.../pull/<n>` URL **and** one or more review ids (integers ≥ 100000000) → [`address-reviews.md`](address-reviews.md).
|
|
6
|
+
2. **Fix-CI** — a `github.com/.../pull/<n>` URL **and** a `fix ci` / `fix-ci` directive with failing check names (no review ids) → [`fix-ci.md`](fix-ci.md).
|
|
7
|
+
3. **Post-merge cleanup** — a `cleanup` token and `slug=<slug>` (no PR URL, no review ids) → [`cleanup.md`](cleanup.md).
|
|
8
|
+
4. **Empty / `help` / `menu` / `?`** → menu + session selector.
|
|
9
|
+
5. **Task automation** (perform an action on a website) → `muggle:muggle-browser-task`.
|
|
10
|
+
6. **Otherwise** → forward pipeline at Stage 1.
|
|
11
|
+
|
|
12
|
+
When in doubt between #5 and #6, ask one question.
|