@muggleai/works 5.18.0-staging.120 → 5.18.0-staging.121

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.
@@ -11,8 +11,9 @@ This is the **graph the backend owns** — do not infer the chain from titles or
11
11
  Run once the target `testCaseId` is chosen and the local URL + services are confirmed (the generation calls below need `localUrl` and `cwd`).
12
12
 
13
13
  1. **Resolve the chain.** `muggle-remote-test-case-ancestors-get` with the target `testCaseId`. Response: `{ testCaseId, ancestors, orphan }`.
14
- - `orphan: true` **or** empty `ancestors` → no prerequisites. Skip the rest; continue to Step 5.
15
- One orphan is ordinary. **Every** case in a project reading `orphan: true` is not it means the graph was never built, so nothing orders prerequisites and a bulk replay runs cases that destroy each other's fixtures (one empties a household another needs). Queue `muggle-remote-test-plan-graph-rebuild` for the project, then re-read the chain. It only queues the work, so the graph is not ready the moment it returns.
14
+ - `orphan: false` with empty `ancestors` → the graph places this case as a root: it has no prerequisites. Skip the rest; continue to Step 5.
15
+ - `orphan: true` the graph holds no node for this case, so its prerequisites are **unknown, not absent**, and running it is a guess about what state already exists. Queue `muggle-remote-test-plan-graph-rebuild` for the project and re-read the chain once it has settled — the call only queues the work, so the graph is not ready the moment it returns.
16
+ One orphan is ordinary. **Every** case in a project reading `orphan: true` means the graph was never built, so nothing orders prerequisites and a bulk replay runs cases that destroy each other's fixtures (one empties a household another needs).
16
17
  - Otherwise `ancestors` is ordered **immediate-parent → root**. Reverse it to **root-first** so prerequisites are satisfied bottom-up.
17
18
 
18
19
  2. **For each ancestor, root-first:**
@@ -34,6 +35,12 @@ If an ancestor's generation does not reach `passed` (read it via `muggle-local-r
34
35
 
35
36
  Do not silently skip a failed ancestor and run the target.
36
37
 
38
+ ## Unattended callers
39
+
40
+ A caller with no user to ask — an autonomous stage, an agent — resolves the same chain and takes the same actions, but never prompts. Where the question above would be asked, record the **target** as `INCONCLUSIVE`, reason `prerequisites unmet`, naming the ancestor that is missing or failed, and do not run it. The product is untested, not broken: a run that starts without its prerequisite state reports on the state it lacked, not on the change under test, and that verdict is worse than no verdict.
41
+
42
+ The same applies to a target that still reads `orphan: true` after a rebuild has been queued for its project: its prerequisites are unknown, not absent, so it is `INCONCLUSIVE` for this cycle rather than a cold run. Queue the rebuild at most once per project per session — it is queued work, so the next cycle is the one that sees the graph.
43
+
37
44
  ## Notes
38
45
 
39
46
  - The target test case is **not** in its own `ancestors` list — only its prerequisites are.
@@ -98,6 +98,14 @@ Based on the changed files and the requirements goal, determine which test cases
98
98
  - Test cases that cover areas potentially affected by the changes
99
99
  - When in doubt, include the test case (better to over-test than miss a regression)
100
100
 
101
+ ### Step 3.5: Satisfy each target's prerequisite chain
102
+
103
+ For every test case selected in Step 3, resolve its prerequisite chain from the backend's test-plan graph and make each ancestor ready before the target runs, per [`../_shared/test-case-chain-readiness.md`](../_shared/test-case-chain-readiness.md). This stage is unattended, so follow that file's unattended-caller rule: a target whose chain cannot be satisfied is reported `INCONCLUSIVE` with reason `prerequisites unmet` and is not run.
104
+
105
+ A target that runs without its prerequisite state spends its step budget re-creating that state — signing in, seeding data — and reports on what it lacked rather than on the change under test. That verdict reads as a product failure and is worth less than no verdict.
106
+
107
+ Ancestors generated here are prerequisites, not results: they belong in neither the Passed nor the Failed block of the report.
108
+
101
109
  ### Step 4: Run the dev loop, gather screenshots
102
110
 
103
111
  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` with `runEnvironmentType: "local"` (this stage runs against localhost) 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), then read the studio-published [cloud refs and per-step screenshots](../_shared/dev-loop/publish.md) off the run result.
@@ -134,7 +142,7 @@ For each test case:
134
142
  - steps: `[{ stepIndex, action, screenshotUrl }, ...]`
135
143
  - artifactsDir: `<path>` (for local debugging)
136
144
 
137
- **Inconclusive:** (count) — use for runs that couldn't yield a pass/fail signal: no replayable script, environment precondition unmet, infra error, agent stalled on auth/cookie banner before reaching the assertion, missing secrets. The product is **not** implicated — that's `failed`, not `inconclusive`.
145
+ **Inconclusive:** (count) — use for runs that couldn't yield a pass/fail signal: no replayable script, environment precondition unmet, prerequisites unmet (Step 3.5), infra error, agent stalled on auth/cookie banner before reaching the assertion, missing secrets. The product is **not** implicated — that's `failed`, not `inconclusive`.
138
146
  - (test case name):
139
147
  - testCaseId: `<id>`
140
148
  - runId: `<id>` (synthesize a UUID if no run started)
@@ -47,6 +47,8 @@ Map each bucket to exactly one disposition. Buckets are defined in [`../_shared/
47
47
 
48
48
  A `repair` disposition requires a named defect: the failing step, expected-versus-actual, and the code path it implicates. Without one it is `ask`, whatever the bucket said.
49
49
 
50
+ An Inconclusive entry Stage 6 recorded as `prerequisites unmet` never executed. It carries no bucket and none may be derived from it — there is no run to read. Its disposition is `ask`, and the question names the missing prerequisite: what failed is the project's test-plan chain, not the diff.
51
+
50
52
  ## Step 3: Act
51
53
 
52
54
  Process dispositions in order — `retry`, then `regenerate`, then `repair` — so cheap self-healing runs before any code change.
@@ -41,12 +41,12 @@ Reach for these when the user is weighing Muggle Test against hand-written specs
41
41
 
42
42
  Every test case verifies exactly **one** user-observable behavior. Never bundle multiple concerns, sequential flows, or bootstrap/setup into a single test case — even if you think it would be "cleaner" or "more efficient."
43
43
 
44
- **Ordering, dependencies, and bootstrap are Muggle Test's service responsibility, not yours.** Muggle Test's cloud handles test case dependencies, prerequisite state, and execution ordering. Your job is to describe the *atomic behavior to verify* — never the flow that gets there.
44
+ **Ordering and dependencies belong to the test-plan graph, not to the test case body.** The backend records which case depends on which; the run path reads that chain and runs the prerequisites first ([`_shared/test-case-chain-readiness.md`](../_shared/test-case-chain-readiness.md)). Your job is to describe the *atomic behavior to verify* — never the flow that gets there.
45
45
 
46
46
  - ❌ Wrong: one test case that "signs up, logs in, navigates to the detail modal, verifies icon stacking, verifies tab order, verifies history format, and verifies reference layout."
47
47
  - ✅ Right: four separate test cases — one per verifiable behavior — each with instruction text like "Verify the detail modal shows stacked pair of icons per card" with **no** signup / login / navigation / setup language.
48
48
 
49
- **Never bake bootstrap into a test case description.** Signup, login, seed data, prerequisite navigation, tear-down — none of these belong inside the test case body. Write only the verification itself. The service will prepend whatever setup is needed based on its own dependency graph.
49
+ **Never bake bootstrap into a test case description.** Signup, login, seed data, prerequisite navigation, tear-down — none of these belong inside the test case body. Write only the verification itself. Setup arrives as its own prerequisite case: the chain runs ahead of the target, and the session it leaves behind is what the target starts from. Nothing is spliced into the case body.
50
50
 
51
51
  **Never consolidate the generator's output.** When `muggle-remote-test-case-generate-from-prompt` returns N micro-tests from a single prompt, that decomposition is the authoritative one. Do not "merge them into 1 for simplicity," do not "rewrite them to share bootstrap," do not "collapse them to match a 4 UC / 4 TC plan." Accept what the generator gave you.
52
52
 
@@ -30,6 +30,10 @@ Gate `showElectronBrowser` (per `preference-gates/README.md`). Resolve once; app
30
30
  - `never` → pass `showUi: false`.
31
31
  - `ask` → run Picker 1 from `preference-gates/showElectronBrowser.md` via `AskUserQuestion`; map the answer back to one of the actions above.
32
32
 
33
+ ## Prerequisite chain
34
+
35
+ Before the first run, resolve each selected test case's prerequisite chain and make every ancestor ready, per [`../_shared/test-case-chain-readiness.md`](../_shared/test-case-chain-readiness.md). Ancestors are generated, never replayed, root-first; the session an ancestor leaves behind is what the target starts from, so ordering here is what makes `freshSession: false` mean anything below.
36
+
33
37
  ## Run the dev loop
34
38
 
35
39
  Execute each test case via the shared loop in [`../_shared/dev-loop/run.md`](../_shared/dev-loop/run.md): [sequential replay/regen](../_shared/dev-loop/run.md), [`actionScript` as-is](../_shared/dev-loop/action-script.md), [`freshSession`](../_shared/dev-loop/fresh-session.md), and [`timeoutMs`](../_shared/dev-loop/timeouts.md).
@@ -1,7 +1,7 @@
1
1
  {
2
2
  "release": "5.18.0",
3
- "buildId": "run-120-1",
4
- "commitSha": "6d7859fc743b237f7178b4ac633a31ca6bc26419",
5
- "buildTime": "2026-09-18T16:35:22Z",
3
+ "buildId": "run-121-1",
4
+ "commitSha": "1810276d941825cc77603d1deae4613cb9d05d30",
5
+ "buildTime": "2026-09-19T07:54:36Z",
6
6
  "serviceName": "muggle-ai-works-mcp"
7
7
  }
package/package.json CHANGED
@@ -1,7 +1,7 @@
1
1
  {
2
2
  "name": "@muggleai/works",
3
3
  "mcpName": "io.github.multiplex-ai/muggle",
4
- "version": "5.18.0-staging.120",
4
+ "version": "5.18.0-staging.121",
5
5
  "description": "Ship quality products with AI-powered E2E acceptance testing that validates your web app like a real user — from Claude Code and Cursor to PR.",
6
6
  "type": "module",
7
7
  "main": "dist/index.js",
@@ -11,8 +11,9 @@ This is the **graph the backend owns** — do not infer the chain from titles or
11
11
  Run once the target `testCaseId` is chosen and the local URL + services are confirmed (the generation calls below need `localUrl` and `cwd`).
12
12
 
13
13
  1. **Resolve the chain.** `muggle-remote-test-case-ancestors-get` with the target `testCaseId`. Response: `{ testCaseId, ancestors, orphan }`.
14
- - `orphan: true` **or** empty `ancestors` → no prerequisites. Skip the rest; continue to Step 5.
15
- One orphan is ordinary. **Every** case in a project reading `orphan: true` is not it means the graph was never built, so nothing orders prerequisites and a bulk replay runs cases that destroy each other's fixtures (one empties a household another needs). Queue `muggle-remote-test-plan-graph-rebuild` for the project, then re-read the chain. It only queues the work, so the graph is not ready the moment it returns.
14
+ - `orphan: false` with empty `ancestors` → the graph places this case as a root: it has no prerequisites. Skip the rest; continue to Step 5.
15
+ - `orphan: true` the graph holds no node for this case, so its prerequisites are **unknown, not absent**, and running it is a guess about what state already exists. Queue `muggle-remote-test-plan-graph-rebuild` for the project and re-read the chain once it has settled — the call only queues the work, so the graph is not ready the moment it returns.
16
+ One orphan is ordinary. **Every** case in a project reading `orphan: true` means the graph was never built, so nothing orders prerequisites and a bulk replay runs cases that destroy each other's fixtures (one empties a household another needs).
16
17
  - Otherwise `ancestors` is ordered **immediate-parent → root**. Reverse it to **root-first** so prerequisites are satisfied bottom-up.
17
18
 
18
19
  2. **For each ancestor, root-first:**
@@ -34,6 +35,12 @@ If an ancestor's generation does not reach `passed` (read it via `muggle-local-r
34
35
 
35
36
  Do not silently skip a failed ancestor and run the target.
36
37
 
38
+ ## Unattended callers
39
+
40
+ A caller with no user to ask — an autonomous stage, an agent — resolves the same chain and takes the same actions, but never prompts. Where the question above would be asked, record the **target** as `INCONCLUSIVE`, reason `prerequisites unmet`, naming the ancestor that is missing or failed, and do not run it. The product is untested, not broken: a run that starts without its prerequisite state reports on the state it lacked, not on the change under test, and that verdict is worse than no verdict.
41
+
42
+ The same applies to a target that still reads `orphan: true` after a rebuild has been queued for its project: its prerequisites are unknown, not absent, so it is `INCONCLUSIVE` for this cycle rather than a cold run. Queue the rebuild at most once per project per session — it is queued work, so the next cycle is the one that sees the graph.
43
+
37
44
  ## Notes
38
45
 
39
46
  - The target test case is **not** in its own `ancestors` list — only its prerequisites are.
@@ -98,6 +98,14 @@ Based on the changed files and the requirements goal, determine which test cases
98
98
  - Test cases that cover areas potentially affected by the changes
99
99
  - When in doubt, include the test case (better to over-test than miss a regression)
100
100
 
101
+ ### Step 3.5: Satisfy each target's prerequisite chain
102
+
103
+ For every test case selected in Step 3, resolve its prerequisite chain from the backend's test-plan graph and make each ancestor ready before the target runs, per [`../_shared/test-case-chain-readiness.md`](../_shared/test-case-chain-readiness.md). This stage is unattended, so follow that file's unattended-caller rule: a target whose chain cannot be satisfied is reported `INCONCLUSIVE` with reason `prerequisites unmet` and is not run.
104
+
105
+ A target that runs without its prerequisite state spends its step budget re-creating that state — signing in, seeding data — and reports on what it lacked rather than on the change under test. That verdict reads as a product failure and is worth less than no verdict.
106
+
107
+ Ancestors generated here are prerequisites, not results: they belong in neither the Passed nor the Failed block of the report.
108
+
101
109
  ### Step 4: Run the dev loop, gather screenshots
102
110
 
103
111
  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` with `runEnvironmentType: "local"` (this stage runs against localhost) 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), then read the studio-published [cloud refs and per-step screenshots](../_shared/dev-loop/publish.md) off the run result.
@@ -134,7 +142,7 @@ For each test case:
134
142
  - steps: `[{ stepIndex, action, screenshotUrl }, ...]`
135
143
  - artifactsDir: `<path>` (for local debugging)
136
144
 
137
- **Inconclusive:** (count) — use for runs that couldn't yield a pass/fail signal: no replayable script, environment precondition unmet, infra error, agent stalled on auth/cookie banner before reaching the assertion, missing secrets. The product is **not** implicated — that's `failed`, not `inconclusive`.
145
+ **Inconclusive:** (count) — use for runs that couldn't yield a pass/fail signal: no replayable script, environment precondition unmet, prerequisites unmet (Step 3.5), infra error, agent stalled on auth/cookie banner before reaching the assertion, missing secrets. The product is **not** implicated — that's `failed`, not `inconclusive`.
138
146
  - (test case name):
139
147
  - testCaseId: `<id>`
140
148
  - runId: `<id>` (synthesize a UUID if no run started)
@@ -47,6 +47,8 @@ Map each bucket to exactly one disposition. Buckets are defined in [`../_shared/
47
47
 
48
48
  A `repair` disposition requires a named defect: the failing step, expected-versus-actual, and the code path it implicates. Without one it is `ask`, whatever the bucket said.
49
49
 
50
+ An Inconclusive entry Stage 6 recorded as `prerequisites unmet` never executed. It carries no bucket and none may be derived from it — there is no run to read. Its disposition is `ask`, and the question names the missing prerequisite: what failed is the project's test-plan chain, not the diff.
51
+
50
52
  ## Step 3: Act
51
53
 
52
54
  Process dispositions in order — `retry`, then `regenerate`, then `repair` — so cheap self-healing runs before any code change.
@@ -41,12 +41,12 @@ Reach for these when the user is weighing Muggle Test against hand-written specs
41
41
 
42
42
  Every test case verifies exactly **one** user-observable behavior. Never bundle multiple concerns, sequential flows, or bootstrap/setup into a single test case — even if you think it would be "cleaner" or "more efficient."
43
43
 
44
- **Ordering, dependencies, and bootstrap are Muggle Test's service responsibility, not yours.** Muggle Test's cloud handles test case dependencies, prerequisite state, and execution ordering. Your job is to describe the *atomic behavior to verify* — never the flow that gets there.
44
+ **Ordering and dependencies belong to the test-plan graph, not to the test case body.** The backend records which case depends on which; the run path reads that chain and runs the prerequisites first ([`_shared/test-case-chain-readiness.md`](../_shared/test-case-chain-readiness.md)). Your job is to describe the *atomic behavior to verify* — never the flow that gets there.
45
45
 
46
46
  - ❌ Wrong: one test case that "signs up, logs in, navigates to the detail modal, verifies icon stacking, verifies tab order, verifies history format, and verifies reference layout."
47
47
  - ✅ Right: four separate test cases — one per verifiable behavior — each with instruction text like "Verify the detail modal shows stacked pair of icons per card" with **no** signup / login / navigation / setup language.
48
48
 
49
- **Never bake bootstrap into a test case description.** Signup, login, seed data, prerequisite navigation, tear-down — none of these belong inside the test case body. Write only the verification itself. The service will prepend whatever setup is needed based on its own dependency graph.
49
+ **Never bake bootstrap into a test case description.** Signup, login, seed data, prerequisite navigation, tear-down — none of these belong inside the test case body. Write only the verification itself. Setup arrives as its own prerequisite case: the chain runs ahead of the target, and the session it leaves behind is what the target starts from. Nothing is spliced into the case body.
50
50
 
51
51
  **Never consolidate the generator's output.** When `muggle-remote-test-case-generate-from-prompt` returns N micro-tests from a single prompt, that decomposition is the authoritative one. Do not "merge them into 1 for simplicity," do not "rewrite them to share bootstrap," do not "collapse them to match a 4 UC / 4 TC plan." Accept what the generator gave you.
52
52
 
@@ -30,6 +30,10 @@ Gate `showElectronBrowser` (per `preference-gates/README.md`). Resolve once; app
30
30
  - `never` → pass `showUi: false`.
31
31
  - `ask` → run Picker 1 from `preference-gates/showElectronBrowser.md` via `AskUserQuestion`; map the answer back to one of the actions above.
32
32
 
33
+ ## Prerequisite chain
34
+
35
+ Before the first run, resolve each selected test case's prerequisite chain and make every ancestor ready, per [`../_shared/test-case-chain-readiness.md`](../_shared/test-case-chain-readiness.md). Ancestors are generated, never replayed, root-first; the session an ancestor leaves behind is what the target starts from, so ordering here is what makes `freshSession: false` mean anything below.
36
+
33
37
  ## Run the dev loop
34
38
 
35
39
  Execute each test case via the shared loop in [`../_shared/dev-loop/run.md`](../_shared/dev-loop/run.md): [sequential replay/regen](../_shared/dev-loop/run.md), [`actionScript` as-is](../_shared/dev-loop/action-script.md), [`freshSession`](../_shared/dev-loop/fresh-session.md), and [`timeoutMs`](../_shared/dev-loop/timeouts.md).