@molecule/api-ai-tools 1.14.4 → 1.14.6

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.
Files changed (45) hide show
  1. package/README.md +236 -190
  2. package/dist/browser-probe.d.ts +4 -4
  3. package/dist/browser-probe.d.ts.map +1 -1
  4. package/dist/browser-probe.js +5 -5
  5. package/dist/command-position.d.ts +15 -16
  6. package/dist/command-position.d.ts.map +1 -1
  7. package/dist/command-position.js +21 -23
  8. package/dist/cut-run.d.ts +9 -9
  9. package/dist/cut-run.js +6 -6
  10. package/dist/failure-kind.d.ts +6 -6
  11. package/dist/failure-kind.js +6 -6
  12. package/dist/index.d.ts +2 -2
  13. package/dist/index.js +2 -2
  14. package/dist/inline-script.d.ts +5 -5
  15. package/dist/inline-script.js +6 -6
  16. package/dist/line-diff.d.ts +2 -3
  17. package/dist/line-diff.d.ts.map +1 -1
  18. package/dist/line-diff.js +2 -3
  19. package/dist/no-test-run.d.ts +5 -5
  20. package/dist/no-test-run.d.ts.map +1 -1
  21. package/dist/no-test-run.js +9 -8
  22. package/dist/output-filter.d.ts +2 -2
  23. package/dist/output-filter.js +2 -2
  24. package/dist/pipeline-exit-note.d.ts +1 -1
  25. package/dist/pipeline-exit-note.js +1 -1
  26. package/dist/playwright-report.d.ts +1 -1
  27. package/dist/playwright-report.js +1 -1
  28. package/dist/server-command.d.ts +2 -2
  29. package/dist/server-command.js +2 -2
  30. package/dist/sleep-peek.d.ts +1 -1
  31. package/dist/sleep-peek.js +1 -1
  32. package/dist/suite-overlap.d.ts +24 -25
  33. package/dist/suite-overlap.d.ts.map +1 -1
  34. package/dist/suite-overlap.js +41 -43
  35. package/dist/tools.d.ts +26 -28
  36. package/dist/tools.d.ts.map +1 -1
  37. package/dist/tools.js +98 -69
  38. package/dist/trace-artifacts.d.ts +64 -65
  39. package/dist/trace-artifacts.d.ts.map +1 -1
  40. package/dist/trace-artifacts.js +73 -75
  41. package/dist/types.d.ts +5 -5
  42. package/dist/utilities.d.ts +107 -91
  43. package/dist/utilities.d.ts.map +1 -1
  44. package/dist/utilities.js +191 -143
  45. package/package.json +2 -2
package/README.md CHANGED
@@ -3,7 +3,7 @@ AUTO-GENERATED — DO NOT EDIT THIS FILE.
3
3
  Generated by `mlcl sync-docs` from the package's src/index.ts JSDoc + mlcl/registry.json.
4
4
  Edits here are overwritten on the next commit (molecule's pre-commit hook regenerates).
5
5
  To change this document, edit the module-level JSDoc in src/index.ts.
6
- Generated: 2026-10-25T03:47:31.740Z
6
+ Generated: 2026-10-26T04:22:08.815Z
7
7
  -->
8
8
 
9
9
  # @molecule/api-ai-tools
@@ -64,7 +64,7 @@ A browser launch bound to a variable, proven to have no cleanup path.
64
64
 
65
65
  ```typescript
66
66
  interface BrowserProbeLeak {
67
- /** The variable the launched browser is bound to (`browser` in the m257 probe). */
67
+ /** The variable the launched browser is bound to (`browser` in the probe above). */
68
68
  readonly variable: string
69
69
  }
70
70
  ```
@@ -136,7 +136,7 @@ two things a caller that WRITES into a command needs. The platform composes a ru
136
136
  executor's own command in more than one place, and a value written for the runner belongs in
137
137
  the runner's own statement: `APP_BASE=https://… cd app && npx playwright test` sets the variable
138
138
  for `cd` alone, so the Playwright config falls back to the local app while the command line
139
- still names the deployed host (xr-molecule-flash-m103 +28:08).
139
+ still names the deployed host.
140
140
 
141
141
  ```typescript
142
142
  interface LocatedCommandSegment {
@@ -202,7 +202,7 @@ interface LocatedCommandSegment {
202
202
  * The file this statement sends its own output to (`> out.log`, `>> log`, `&> run.log`,
203
203
  * `| tee file`), or null. Only a redirect written at the command's own level counts: one
204
204
  * inside a `( … )` / `{ … }` group writes through that group, and one that feeds a heredoc's
205
- * file (`cat > cfg.ts <<'EOF'`) is writing a config (X1 flash-m44, flash-m136).
205
+ * file (`cat > cfg.ts <<'EOF'`) is writing a config.
206
206
  */
207
207
  redirectTarget: string | null
208
208
  }
@@ -252,7 +252,7 @@ interface CutRun {
252
252
  * ({@link commandCutRun}'s `budgetSeconds` is 0). A background run is bounded by what its own
253
253
  * command carries — so a `command-timeout` cut there is that prefix killing the walk, and the
254
254
  * executor must be told to drop the prefix, never to start the run in the background it is
255
- * already in (X1 xr-molecule-flash-m143 +24:45).
255
+ * already in.
256
256
  */
257
257
  background: boolean
258
258
  /**
@@ -277,12 +277,12 @@ interface CutRun {
277
277
  /**
278
278
  * The interpreter of an inline program that only touches local files (`python3`, `node`, …), or
279
279
  * null. Such a program is stopped by its short budget because it is stuck, never because the work
280
- * is slow, so the sentence must not send it to the background (xr-molecule-flash-m200 +03:45).
280
+ * is slow, so the sentence must not send it to the background.
281
281
  */
282
282
  inlineScript?: string | null
283
283
  /**
284
284
  * The variable a leaked standalone browser launch is bound to, when the command ran such a probe
285
- * and the cut reader could only classify it after the run (xr-molecule-flash-m257). A leaked
285
+ * and the cut reader could only classify it after the run. A leaked
286
286
  * handle is not a slow workload: the background is the one place it must not be sent, so the
287
287
  * sentence names the close instead.
288
288
  */
@@ -532,8 +532,7 @@ interface SuiteRunInFlight {
532
532
  target: string
533
533
  /**
534
534
  * Whether the command being judged STOPS this run before starting its own — a kill comes first,
535
- * so a run the command itself stops is not in the way (xr-molecule-flash-m87's
536
- * `kill 19408 … ; npx playwright test …`).
535
+ * so a run the command itself stops is not in the way (`kill 19408 … ; npx playwright test …`).
537
536
  */
538
537
  stoppedByCommand?: boolean
539
538
  }
@@ -638,7 +637,7 @@ interface TraceRequest {
638
637
  * What the page SENT, for a 4xx answered by the app's own API — bounded (see
639
638
  * {@link MAX_TRACED_BODY_CHARS}). A body wrapped as `{"data":{…}}` is visible here in one line:
640
639
  * app-http's verbs take the body as their second argument, so a helper that passes
641
- * `{ data: body }` there ships the wrapper (xr-molecule-flash-m111 +11:36).
640
+ * `{ data: body }` there ships the wrapper.
642
641
  */
643
642
  sent?: string
644
643
  /** What came back for that 4xx, bounded the same way — the API's own error body. */
@@ -662,7 +661,7 @@ interface TraceRequest {
662
661
  * A 401 cannot be read without this: the API's own body said
663
662
  * `{"errors":{"token":["is missing"]}}` while the note told the run to read the API handler,
664
663
  * when the header's absence proved the CLIENT never attached the token
665
- * (xr-molecule-flash-m148 +29:18). A header present moves the answer to the server: the API
664
+ * A header present moves the answer to the server: the API
666
665
  * refused a token it was sent.
667
666
  */
668
667
  sentAuthorization?: boolean
@@ -681,7 +680,7 @@ interface TraceRequest {
681
680
  /**
682
681
  * The trace member this request came from — the browser context Playwright numbered (`1`, `3`).
683
682
  * A test that opens a second browser context writes one trace member per context, and a test's
684
- * request is only evidence about the page it was made on (xr-molecule-flash-m160).
683
+ * request is only evidence about the page it was made on.
685
684
  */
686
685
  context?: string
687
686
  /** The page the request was made on, as the HAR entry's `pageref` records it. */
@@ -695,7 +694,7 @@ The test's LAST user action before the failing assertion, and the requests it ca
695
694
 
696
695
  An assertion after a navigation is not explained by the page's last call (`GET /api/tags` on
697
696
  whatever page the app redirected to); it is explained by what the action the test took sent and
698
- what came back (xr-molecule-flash-m148: 13 then 12 failing tests, every trace row leading with
697
+ what came back (13 then 12 failing tests, every trace row leading with
699
698
  `GET /api/tags → 200`, while the register `POST /api/users` and its answer — the fact that
700
699
  explains the signed-out page — was never shown).
701
700
 
@@ -741,7 +740,7 @@ interface TraceAction {
741
740
  /**
742
741
  * The selector a `fill`/`type`/`selectOption` acted on (`textarea[name="bio"]`), from the
743
742
  * trace's own params. Kept so the note can compare what the test typed with what the page
744
- * submitted (m173: the field it typed into was sent empty).
743
+ * submitted (a field typed into and sent empty).
745
744
  */
746
745
  selector?: string
747
746
  /**
@@ -759,7 +758,7 @@ two-context test opens for its own setup.
759
758
 
760
759
  Its actions and requests belong to a different page: a request it sent is not the failing
761
760
  action's effect, and the URL it left the page on is not where the assertion's page went
762
- (xr-molecule-flash-m160: the helper context created an article in an editor page while the
761
+ (the helper context created an article in an editor page while the
763
762
  primary page moved to the profile the assertion then failed on, and the note called the
764
763
  editor page the failing page).
765
764
 
@@ -784,13 +783,13 @@ The assertion's own error names the text (a `has-text(…)` / `getByText(…)` /
784
783
  argument), and the trace's network log holds the response that contained it. That pair is the
785
784
  whole diagnosis: the API returned the value and the page dropped it before rendering, so the cut
786
785
  is in the component that maps the response onto the list — not in the API, the route or the
787
- selector. xr-molecule-flash-m169 (+13:09) spent its fix rounds on the wrong component and on a
786
+ selector. One run spent its fix rounds on the wrong component and on a
788
787
  markup detail while `GET /api/tags` was returning the missing "trending" and `PopularTags`
789
- sliced the response to its first 20 entries (the m99 top-N class, in the frontend).
788
+ sliced the response to its first 20 entries (a top-N cut, in the frontend).
790
789
 
791
790
  The text must be a value the response held, never a substring of one: a whole JSON string or
792
791
  number value, or a word bounded by non-alphanumerics. A text of 2 characters or fewer, or one
793
- made of digits only, must be a whole JSON value. xr-molecule-flash-m208's pagination assertion
792
+ made of digits only, must be a whole JSON value. A pagination assertion
794
793
  waited for "2" and the raw substring hit `pag1792394785820` in a tags response, so the note led
795
794
  with a response that had nothing to do with the failure; when no response holds the text that
796
795
  way, the field is absent and the note leads with its next finding.
@@ -808,7 +807,7 @@ interface TraceMissingText {
808
807
  * of the collection that started after the last navigation, and the text is absent from the
809
808
  * page's own failure snapshot ({@link traceArtifactsScript}).
810
809
  *
811
- * Absent when the evidence is weaker — a creation POST carried the text (m194's button failure
810
+ * Absent when the evidence is weaker — a creation POST carried the text (a button failure
812
811
  * was not a missing article), the snapshot still showed it, or the trace recorded no clock —
813
812
  * and the note then says only that a response contained the text.
814
813
  */
@@ -821,7 +820,7 @@ interface TraceMissingText {
821
820
  A write the trace recorded answering a boolean field, and a LATER GET of the same resource
822
821
  answering the opposite for that field.
823
822
 
824
- This is the pair that reads as a frontend race and is not one: xr-molecule-flash-m181's follow
823
+ This is the pair that reads as a frontend race and is not one: a follow
825
824
  test sent `POST /api/profiles/:username/follow` and the API answered
826
825
  `{"profile":{…,"following":true}}`, then a `GET /api/profiles/:username` answered
827
826
  `{"profile":{…,"following":false}}` — the READ route never saw the viewer, so it hydrated
@@ -900,7 +899,7 @@ interface TraceCountMatch {
900
899
  text?: string
901
900
  /** Its ancestors, outermost first (`body > div.comment-form > div.card`), bounded. */
902
901
  path?: string
903
- /** True when a `<form>` is one of its ancestors — the m321 extra match's shape. */
902
+ /** True when a `<form>` is one of its ancestors — the shape of an extra form-internal match. */
904
903
  inForm?: true
905
904
  }
906
905
  ```
@@ -911,7 +910,7 @@ A failing assertion that compared a LOCATOR COUNT (`expect(await locator.count()
911
910
  `expect(locator).toHaveCount(n)`), with the locator the trace recorded and, when the failure
912
911
  snapshot can supply them, the elements it matched.
913
912
 
914
- xr-molecule-flash-m321's `comments.spec.ts:86` sat on `Expected: 3 / Received: 4` for ~30
913
+ A `comments.spec.ts:86` assertion sat on `Expected: 3 / Received: 4` for ~30
915
914
  minutes and three whole suite walks: the helper counted `.card:not(.comment-form) .card-block`,
916
915
  the app's comment form was a `.comment-form` wrapper around a plain `.card`, and the form's own
917
916
  `.card-block` made the fourth. The trace had the selector (its `Frame.queryCount` entry) and the
@@ -972,7 +971,7 @@ interface TraceArtifact {
972
971
  * action caused ({@link TraceArtifact.lastAction}), else — on a trace with no action clock — the
973
972
  * trace's LAST `fetch`/`xhr` in recording order, else its document. It leads the note's row when
974
973
  * {@link lastAction} is absent, because a click that changed nothing is explained by the request
975
- * the click sent and what came back — xr-molecule-flash-m135's Follow click sent
974
+ * the click sent and what came back — a Follow click sent
976
975
  * `DELETE /api/profiles/x/follow → 200` (its `following` state was stale) and the note listed only
977
976
  * the test's earlier, answered requests.
978
977
  *
@@ -992,7 +991,7 @@ interface TraceArtifact {
992
991
  *
993
992
  * A test that opens a second browser context writes one trace member per context, and the
994
993
  * archive does not order them by time: the last action of the concatenation may belong to the
995
- * helper's page while the assertion failed on another (xr-molecule-flash-m160). The action is
994
+ * helper's page while the assertion failed on another. The action is
996
995
  * therefore the failing page's own, and its `pageAfter` is that page's last frame snapshot.
997
996
  *
998
997
  * Absent on traces read before this field existed, on traces whose network entries recorded no
@@ -1012,13 +1011,13 @@ interface TraceArtifact {
1012
1011
  * True when the trace held more than one browser context and none of them could be tied to the
1013
1012
  * failing assertion's page. The note then makes no causal claim — no "the test's last action",
1014
1013
  * no "the page stayed at …" — rather than attributing one context's click and URL to another
1015
- * context's assertion (xr-molecule-flash-m160).
1014
+ * context's assertion.
1016
1015
  */
1017
1016
  unattributed?: true
1018
1017
  /**
1019
1018
  * The browser contexts the test opened BESIDES the failing assertion's page, with the app
1020
1019
  * requests each made. Kept apart so the note can name them as set-up work instead of printing
1021
- * their requests as the failing action's effects (xr-molecule-flash-m160).
1020
+ * their requests as the failing action's effects.
1022
1021
  *
1023
1022
  * Absent when the trace recorded one context only, when every other context made no request,
1024
1023
  * and on traces read before this field existed.
@@ -1027,8 +1026,7 @@ interface TraceArtifact {
1027
1026
  /**
1028
1027
  * The text the failing assertion waited for and a same-page API response carried, when the trace
1029
1028
  * recorded both. The note leads with it: the value reached the browser and the page did not
1030
- * render it, so the next read is where that response is mapped — never the API or the selector
1031
- * (xr-molecule-flash-m169).
1029
+ * render it, so the next read is where that response is mapped — never the API or the selector.
1032
1030
  *
1033
1031
  * Absent when the assertion waited for no text (a text-free selector, a strict-mode violation),
1034
1032
  * when no page-scoped `fetch`/`xhr` answered 2xx/3xx with the text in its body, and on traces
@@ -1037,7 +1035,8 @@ interface TraceArtifact {
1037
1035
  missingText?: TraceMissingText
1038
1036
  /**
1039
1037
  * A write's answer a later GET of the same resource contradicted — the read route does not see
1040
- * the viewer (xr-molecule-flash-m181's `following`). The note leads with it and sends the run at
1038
+ * the viewer (a `following` flag that reads as `false`). The note leads with it and sends the
1039
+ * run at
1041
1040
  * the route's middleware, not the page's state handling.
1042
1041
  *
1043
1042
  * Absent when no write and later read in the trace answered the same boolean field differently,
@@ -1048,19 +1047,19 @@ interface TraceArtifact {
1048
1047
  * A visibility failure whose locator RESOLVED into an empty box — Playwright's "hidden" — with
1049
1048
  * the element's children read from the failure snapshot ({@link TraceHiddenBox}). The note uses
1050
1049
  * it to name why the box is empty (an `<img>` with no CSS size, a textless element) instead of
1051
- * leaving the run to probe computed styles (xr-molecule-flash-m197).
1050
+ * leaving the run to probe computed styles.
1052
1051
  */
1053
1052
  hiddenBox?: TraceHiddenBox
1054
1053
  /**
1055
1054
  * A failing assertion that compared a locator count, with the locator the trace recorded and the
1056
1055
  * elements its failure snapshot matched ({@link TraceCountMismatch}). The row prints them, so a
1057
1056
  * count that is off by one names the extra element instead of leaving the run to probe for it
1058
- * (xr-molecule-flash-m321's 30-minute `Expected: 3 / Received: 4`).
1057
+ * (a 30-minute `Expected: 3 / Received: 4` hunt).
1059
1058
  */
1060
1059
  countMismatch?: TraceCountMismatch
1061
1060
  /**
1062
1061
  * The method+path groups this test's page sent {@link TRACE_NOTE_LOOP_REPEATS} times or more,
1063
- * most-repeated first — a render loop the note leads with (xr-molecule-flash-m215: 2,106
1062
+ * most-repeated first — a render loop the note leads with (2,106
1064
1063
  * `GET /api/articles/<slug>` in one test, printed as four identical `→ 200` lines). Counted over
1065
1064
  * every network entry of the failing page, not the capped {@link TraceArtifact.requests} list.
1066
1065
  *
@@ -1087,8 +1086,8 @@ interface TraceArtifact {
1087
1086
  What the runner's own report says about ONE failing test: where the test is declared, which
1088
1087
  Playwright call its failure names, and the per-test deadline the failure measured against.
1089
1088
 
1090
- A trace cannot tell a navigation that ran out of budget from a selector wait that did. On
1091
- xr-molecule-flash-m153 a 15 s `page.waitForSelector` timeout left a trace whose `Frame.goto`
1089
+ A trace cannot tell a navigation that ran out of budget from a selector wait that did. A 15 s
1090
+ `page.waitForSelector` timeout can leave a trace whose `Frame.goto`
1092
1091
  never finished (the test was cut off mid-navigation) with a `/src/components/*.tsx` module still
1093
1092
  pending when the context closed — and the note read that as an asset hang, then sent the run to
1094
1093
  re-run the same tests unchanged against the same dev server while the same result's
@@ -1136,7 +1135,7 @@ interface TraceRunReport {
1136
1135
  /**
1137
1136
  * The app source files whose code sends a repeated request, read by the caller from the
1138
1137
  * project (`app/src/**`) before this note is written. A loop's sentence names the component to
1139
- * read instead of leaving the run to search for it (xr-molecule-flash-m215's `Editor.tsx`).
1138
+ * read instead of leaving the run to search for it (the component's own file).
1140
1139
  * Empty when the caller could not read the app or no file states the path.
1141
1140
  */
1142
1141
  callSites?: readonly { method: string; path: string; file: string }[]
@@ -1357,8 +1356,8 @@ interface ToolBuildConfig {
1357
1356
  * The test titles the person's request EXCLUDES by name (molecule-dev's `excludedTestTitles`),
1358
1357
  * asked when a finished suite run's cause note is built. Their failures are not causes to fix:
1359
1358
  * the note drops them, says so at the end, and inverts them out of the narrowed re-run it hands
1360
- * over — a result must never name a test beside "it does not count" (xr-molecule-flash-m101
1361
- * +12:00, where the executor spent a turn and an edit on the excluded test).
1359
+ * over — a result must never name a test beside "it does not count" (an executor once spent a
1360
+ * turn and an edit on the excluded test).
1362
1361
  *
1363
1362
  * A getter, not an array, because the request is read per turn while the tool set is built
1364
1363
  * once. Unset means no test is excluded.
@@ -1372,8 +1371,8 @@ interface ToolBuildConfig {
1372
1371
  * `requiredRunSettings` — its mode, say), asked when the cause note composes a narrowed re-run
1373
1372
  * of a finished run's failures. A re-run composed from the executor's own command inherits what
1374
1373
  * that command set — and nothing it left out, so a run that measured the suite in `spa` handed
1375
- * back a re-run that would measure `spa` again (xr-molecule-flash-m182 +12:06: the request names
1376
- * `TEST_MODE=fullstack`, the run and its re-run both omitted it).
1374
+ * back a re-run that would measure `spa` again (the request names `TEST_MODE=fullstack`, and
1375
+ * both the run and its re-run omitted it).
1377
1376
  *
1378
1377
  * A getter, not an array: the request is read per turn while the tool set is built once, and
1379
1378
  * what the suite's own files read is the consumer's reading. Unset answers "nothing required".
@@ -1407,7 +1406,7 @@ interface ToolBuildConfig {
1407
1406
 
1408
1407
  /**
1409
1408
  * A whole walk's duration in ms, as the consumer measured it. A suite run the executor detached
1410
- * whose own `timeout` is shorter than this is lifted (m200); unset lifts only a bound no longer
1409
+ * whose own `timeout` is shorter than this is lifted; unset lifts only a bound no longer
1411
1410
  * than this tool's ceiling.
1412
1411
  *
1413
1412
  * @param command - The suite command.
@@ -1415,6 +1414,8 @@ interface ToolBuildConfig {
1415
1414
  * @returns The duration in ms, or null.
1416
1415
  */
1417
1416
  suiteRunMs?: (command: string, cwd: string) => Promise<number | null | undefined>
1417
+
1418
+ /** Post-write hook (e.g. auto-format via Prettier/ESLint). Called after every write_file/edit_file. */
1418
1419
  // … truncated — the full declaration is in node_modules/@molecule/api-ai-tools/dist/types.d.ts
1419
1420
  ```
1420
1421
 
@@ -1620,21 +1621,21 @@ interface FailureCause {
1620
1621
  * The suite's own per-test budget in ms, when the cause is the test-budget kill
1621
1622
  * (`Test timeout of 15000ms exceeded`). The signature normalizes the number away
1622
1623
  * ({@link normalizedSignature}) so equal causes group, and that number is the one fact that
1623
- * predicts a test spending its budget on a repeated action (xr-molecule-flash-m110 +20:44).
1624
+ * predicts a test spending its budget on a repeated action.
1624
1625
  */
1625
1626
  budgetMs?: number
1626
1627
  /**
1627
1628
  * The layer the failure came from ({@link classifyRunFailure}). A `connection` cause never
1628
1629
  * reached the app, so it is NOT a cause the app's code can fix: the note says to re-run it
1629
1630
  * once and read the app's log on a repeat, instead of sending a fix at a handler
1630
- * (xr-molecule-flash-m110 +18:42 rewrote a CORS middleware for a 20 s connection timeout).
1631
+ * (a CORS middleware was rewritten for a 20 s connection timeout).
1631
1632
  */
1632
1633
  kind: RunFailureKind
1633
1634
  /**
1634
1635
  * What the page itself showed at the moment of the failure, when the caller read it from
1635
1636
  * Playwright's `error-context.md` (the alert / error list). The failure's own error line names
1636
- * the symptom — `waitForURL` timed out — and never what the page was saying: xr-molecule-flash-
1637
- * m122 +23:39 grouped eight `waitForURL` timeouts under one line while the page snapshots named
1637
+ * the symptom — `waitForURL` timed out — and never what the page was saying: eight
1638
+ * `waitForURL` timeouts were grouped under one line while the page snapshots named
1638
1639
  * the cause (`email can't be blank`, `username can't be blank` — the settings form submitted
1639
1640
  * before its values had loaded). Attached to the cause so the fix needs no `cat` of the file.
1640
1641
  */
@@ -1915,8 +1916,8 @@ This is the reading a policy that asks "does this command run X" needs, and it i
1915
1916
  not a text match. The command-position parser already knows what runs and what is only quoted
1916
1917
  data ({@link commandSegments}), so a pattern never reads a `|` inside a quoted grep alternation
1917
1918
  as a pipeline: `grep -E "USER CALLS|ENV|BUTTON" app.log` prints log lines, and the `ENV` in
1918
- its pattern started nothing (X0 xr-molecule-flash-m331 blocked exactly that call as an
1919
- environment dump). What the shell DOES run stays visible through the same walk: a bare
1919
+ its pattern starts nothing — a text match would block exactly that call as an environment
1920
+ dump. What the shell DOES run stays visible through the same walk: a bare
1920
1921
  launcher (`ls | env`), a shell string (`bash -c 'env'`), a substitution
1921
1922
  (`echo "$(printenv)"`) and a nested one (`sh -c 'x; env'`) are all commands here.
1922
1923
 
@@ -1954,8 +1955,8 @@ A flag written "at the end of the command" is not the runner's: a statement can
1954
1955
  redirection (`… 2>&1`), and a statement can sit inside a group whose closer belongs to the
1955
1956
  shell, not to the words (`( … )`, `{ …; }`). Appending after that closer is a different shell
1956
1957
  word that the group has already closed — `… --config=x 2>&1) --reporter=list` is
1957
- `sh: Syntax error: word unexpected`, which killed a backgrounded walk at once and pushed the
1958
- model off the platform's runner shape (xr-molecule-flash-m129 +34:29). Write the option where
1958
+ `sh: Syntax error: word unexpected`, which kills a backgrounded walk at once and pushes the
1959
+ model off the platform's runner shape. Write the option where
1959
1960
  the program's own arguments end and the rest of the statement still parses:
1960
1961
  `… --config=x --reporter=list 2>&1)`.
1961
1962
 
@@ -1986,8 +1987,8 @@ adjacent closer to its last word because no separator comes between them: `( …
1986
1987
  parses its last stage as `tail` with the argument `-25)`. {@link LocatedCommandSegment.end}
1987
1988
  therefore says one past the `)`, and a caller cutting that stage out of the command takes the
1988
1989
  group's closer with it — the rewritten command is then `( … 2>&1`, which no shell parses
1989
- (xr-molecule-flash-m418 +23:31: a heredoc config plus a parenthesized Playwright pipeline came
1990
- back as `end of file unexpected` from the background runner).
1990
+ (a heredoc config plus a parenthesized Playwright pipeline came back as `end of file
1991
+ unexpected` from the background runner).
1991
1992
 
1992
1993
  The parse's own group depths answer which closers belong to an enclosing group: the depth a
1993
1994
  statement was written at is its first character's depth (an opener is recorded at the depth
@@ -2041,9 +2042,9 @@ largest bound that was lifted.
2041
2042
  The platform moves a run to the background precisely because its own bound cannot fit this
2042
2043
  tool's ceiling, and a background task has no ceiling — its wait is bounded by `wait_for_task`
2043
2044
  and the turn's deadline. The `timeout N` an executor wrote to fit the ceiling therefore keeps
2044
- killing the run at N in the background, where nothing needed it: X1 xr-molecule-flash-m143
2045
- (+24:45) wrote `timeout 280` for a 31-test walk, the tool backgrounded it, and the prefix stopped
2046
- the walk with no tally — then the cut sentence told the executor to "run it in the background",
2045
+ killing the run at N in the background, where nothing needed it: an executor wrote
2046
+ `timeout 280` for a 31-test walk, the tool backgrounded it, and the prefix stopped the walk
2047
+ with no tally — then the cut sentence told the executor to "run it in the background",
2047
2048
  which is where it already was.
2048
2049
 
2049
2050
  The wrapper is found by the same parse every other command reader uses ({@link commandStart}):
@@ -2136,7 +2137,7 @@ The exit code a finished suite run may report.
2136
2137
  The code in a background result is the code of the command's LAST pipeline stage. When a stage
2137
2138
  after the suite runner still consumes its output (`| tee run.log`, or a filter the platform could
2138
2139
  not prove output-only), that stage produced the code, not the run — and `… | grep … | tail -20`
2139
- exited 0 for a run with a failure in it (xr-molecule-flash-m101 +25:54). No code is reported
2140
+ can exit 0 for a run with a failure in it. No code is reported
2140
2141
  then: the log's own tally decides.
2141
2142
 
2142
2143
  The same reading covers a code of 0 beside a tally that names a failure: whatever ended the
@@ -2253,7 +2254,9 @@ Whether every one of the classified failures is a connection failure — the onl
2253
2254
  no response the app produced was measured.
2254
2255
 
2255
2256
  ```typescript
2256
- function allConnectionFailures(failures: readonly (RunFailureClass | null)[]): boolean
2257
+ function allConnectionFailures(
2258
+ failures: ReadonlyArray<RunFailureClass | null>,
2259
+ ): failures is ReadonlyArray<RunFailureClass & { kind: 'connection' }>
2257
2260
  ```
2258
2261
 
2259
2262
  - `failures` — The run's classifications, in printed order.
@@ -2369,7 +2372,13 @@ tools built outside this package get the same treatment as the ones built
2369
2372
  inside it.
2370
2373
 
2371
2374
  ```typescript
2372
- function guardAITool(tool: T, options?: GuardOptions): T
2375
+ function guardAITool<
2376
+ T extends {
2377
+ name: string
2378
+ parameters?: unknown
2379
+ execute: (input: unknown, ...rest: never[]) => Promise<unknown>
2380
+ },
2381
+ >(tool: T, options?: GuardOptions): T
2373
2382
  ```
2374
2383
 
2375
2384
  - `tool` — The tool to guard.
@@ -2407,7 +2416,7 @@ A runner counts only where a shell would RUN it ({@link commandSegments}): the w
2407
2416
  position of a segment, after its wrapper prefixes. A runner named in an argument is not an
2408
2417
  invocation — `head -30 run-api-tests-hurl.sh` and `grep -n playwright e2e/README.md` name a
2409
2418
  file to read, and a `--list` written inside a file the command writes is not a flag anyone runs
2410
- with (flash-m81).
2419
+ with.
2411
2420
 
2412
2421
  A command that invokes no runner is NOT one of these (false): "the command runs no test" is
2413
2422
  then true for `ls`, which is not the question any caller is asking. The question is whether
@@ -2449,7 +2458,7 @@ function outputFilterAfterRunner(
2449
2458
 
2450
2459
  - `command` — The command as the executor sent it.
2451
2460
  - `runs` — Whether a segment is the runner this run is about (the caller knows its own kind: {@link CommandSegment.program} is the program, once wrapper words like `timeout 280` and `npx` are taken away).
2452
- - `occurrence` — Which runner invocation the output belongs to, 1-based. A command can run the same runner more than once (xr-molecule-flash-m170: the suite bare, then with `HOST=…`), and each invocation carries its OWN pipe; a reader judging the second walk must name the second walk's cut, never the first's.
2461
+ - `occurrence` — Which runner invocation the output belongs to, 1-based. A command can run the same runner more than once (the suite bare, then with `HOST=…`), and each invocation carries its OWN pipe; a reader judging the second walk must name the second walk's cut, never the first's.
2453
2462
 
2454
2463
  **Returns:** The filter and the unfiltered command, or null.
2455
2464
 
@@ -2725,7 +2734,7 @@ it already names one, or starts no Playwright run.
2725
2734
  The flag rides the same statement the runner does: a `cd`, an env prefix and a `timeout` before
2726
2735
  it are left exactly as they were, and so is everything chained after the run (`| tail -50`).
2727
2736
 
2728
- xr-molecule-flash-m113 (+19:09): the model's fix-round re-run dropped the
2737
+ A fix-round re-run dropped the
2729
2738
  `--config playwright.conduit.config.ts` both earlier runs had carried, so Playwright started with
2730
2739
  NO base URL and all 10 failures were `page.goto: Cannot navigate to invalid URL` — a failure list
2731
2740
  that says nothing about the app. The platform composes commands back to the executor too (the
@@ -2746,21 +2755,21 @@ function withSuiteConfig(command: string, config: string | null | undefined): st
2746
2755
  The whole-suite command made scoped to the tests it should re-run instead: the same
2747
2756
  invocation — same launcher, same settings — with the named `file:line`s in place of every
2748
2757
  positional selection the run carried (a spec file, a suite directory or a regex filter),
2749
- `--last-failed` dropped (it re-runs the tests that never ran too, X1 flash-m60) and
2758
+ `--last-failed` dropped (it re-runs the tests that never ran too) and
2750
2759
  `--retries=0` set (a re-run of a known failure does not need to pay for retries) — except the
2751
2760
  re-run of a run against a DEPLOYED URL, which keeps the suite's own retries and tracing
2752
2761
  (`options.suiteSettings`).
2753
2762
 
2754
2763
  The re-run keeps the run's `> <file>` redirect only in the sense of keeping its OUTPUT there:
2755
2764
  the target is rewritten to a fresh sibling ({@link redirectRunnerOutputsToFreshFiles}), so a
2756
- re-run never overwrites the log the run itself is the evidence for (xr-molecule-flash-m173) —
2757
- and the setup around the run keeps its own file writes untouched (xr-molecule-flash-m429). A
2765
+ re-run never overwrites the log the run itself is the evidence for —
2766
+ and the setup around the run keeps its own file writes untouched. A
2758
2767
  `tail`/`head`/`cat`/`grep` chained after the run that reads that exact log is shown the fresh
2759
- sibling instead, so the re-run displays the run it performed (xr-molecule-flash-o03).
2768
+ sibling instead, so the re-run displays the run it performed.
2760
2769
 
2761
2770
  `config` is the config the run was measured under ({@link withSuiteConfig}): the narrowed re-run
2762
2771
  carries it whenever the command itself does not, so a run that dropped `--config` cannot be
2763
- handed back a command with the same defect (xr-molecule-flash-m113: every failing test was
2772
+ handed back a command with the same defect (every failing test was
2764
2773
  `Cannot navigate to invalid URL` because the re-run loaded no base URL).
2765
2774
 
2766
2775
  ```typescript
@@ -2777,23 +2786,23 @@ function scopedRerunCommand(
2777
2786
 
2778
2787
  - `command` — The whole-suite run's command.
2779
2788
  - `locations` — The failing `file:line`s to re-run, as the run's own log printed them. A location the reporter printed relative to the runner's own directory (`../../fixtures/…`, which no absolute path contains) is resolved here ({@link playwrightLocations}), so the command this returns is one Playwright can match.
2780
- - `excluded` — The test titles the request carves out. They are inverted out (`--grep-invert`) so a re-run of the failing locations cannot report one of them again — xr-molecule-flash-m101 re-ran the whole 139-test suite and spent ~4 minutes to be told about a test the request had already said does not count.
2789
+ - `excluded` — The test titles the request carves out. They are inverted out (`--grep-invert`) so a re-run of the failing locations cannot report one of them again — a re-run of the whole 139-test suite spends ~4 minutes to be told about a test the request had already said does not count.
2781
2790
  - `config` — The config the run loaded, when the caller knows it; added when the command does not name one.
2782
2791
  - `cwd` — The directory `exec_command` was given, when it was; the base a location is resolved against when the command does not `cd` anywhere.
2783
- - `env` — The settings the REQUEST requires of the suite and this run left out ({@link withRunEnv}): the re-run carries them, so a re-run of a run measured in the wrong mode is not measured in that mode again (xr-molecule-flash-m182 +12:06).
2784
- - `options` — `suiteSettings` for the re-run of a run against a DEPLOYED URL: it keeps the suite's own retries and tracing instead of the diagnosis ones. The graded measurement is the suite's own settings, and a retry is what leaves a failing test's trace there; the platform's `--retries=0` and its `--trace=retain-on-failure` are both a stricter measurement than the one that was graded, and on X1 xr-molecule-flash-h15 the recording alone turned three budget-bound deployed tests into timeouts.
2792
+ - `env` — The settings the REQUEST requires of the suite and this run left out ({@link withRunEnv}): the re-run carries them, so a re-run of a run measured in the wrong mode is not measured in that mode again.
2793
+ - `options` — `suiteSettings` for the re-run of a run against a DEPLOYED URL: it keeps the suite's own retries and tracing instead of the diagnosis ones. The graded measurement is the suite's own settings, and a retry is what leaves a failing test's trace there; the platform's `--retries=0` and its `--trace=retain-on-failure` are both a stricter measurement than the one that was graded, and the recording alone turned three budget-bound deployed tests into timeouts.
2785
2794
 
2786
2795
  **Returns:** The scoped command, or the command unchanged when it runs no Playwright suite.
2787
2796
 
2788
2797
  #### `withRunEnv(command, settings)`
2789
2798
 
2790
2799
  The command with the request's required settings put in front of its RUN statement — the ONE
2791
- place every composed re-run gets them (xr-molecule-flash-m182).
2800
+ place every composed re-run gets them.
2792
2801
 
2793
2802
  The settings are written at the statement's own assignment offset, never in front of the whole
2794
2803
  command: a shell binds an assignment there to the statement's program, while one in front of the
2795
2804
  whole command is the environment of its FIRST statement alone (`APP_BASE=… cd app && npx
2796
- playwright test` sets the variable for `cd`; xr-molecule-flash-m103 +28:08). A name the command
2805
+ playwright test` sets the variable for `cd`). A name the command
2797
2806
  gives a different value is replaced, and one it already gives the required value is left as
2798
2807
  written. When the parse cannot place the statement (a run inside a nested `sh -c '…'`), the
2799
2808
  settings become `export`s, which no statement boundary can swallow.
@@ -2817,7 +2826,10 @@ rows — the failures one causes the other cannot be told from real ones. A run
2817
2826
  suite is never in the way, and neither is one the candidate command stops first.
2818
2827
 
2819
2828
  ```typescript
2820
- function suiteRunInTheWay(candidate: { target: string }, inFlight: readonly T[]): T | null
2829
+ function suiteRunInTheWay<T extends SuiteRunInFlight>(
2830
+ candidate: { target: string },
2831
+ inFlight: readonly T[],
2832
+ ): T | null
2821
2833
  ```
2822
2834
 
2823
2835
  - `candidate` — The run about to start, by the app and database it would measure ({@link suiteCommandTarget}).
@@ -2850,10 +2862,10 @@ disagree:
2850
2862
  ({@link ./utilities.js} `streamingBackgroundCommand`) — a diagnosis walks each failure once,
2851
2863
  while the run the suite is judged by keeps the suite's own retries; and
2852
2864
  - the platform's own notes (molecule-dev's `suite-cli-override.ts`), which must not tell the
2853
- executor to drop the `--retries=0` the platform itself has just added — the contradiction X1
2854
- flash-m74 and m75 filed, and m76 filed a third time.
2865
+ executor to drop the `--retries=0` the platform itself has just added — a contradiction
2866
+ filed three times.
2855
2867
 
2856
- Until xr-molecule-flash-m89 they were a regex and a predicate that only LOOKED alike, and the
2868
+ Until then they were a regex and a predicate that only LOOKED alike, and the
2857
2869
  gap was exactly the run the platform had asked for: its `testRunNote` says "run the whole suite
2858
2870
  once with `--max-failures=0`", and the rewriter read that cap flag as a capped diagnosis and
2859
2871
  stripped the suite's retries from the uncapped proof run that follows a deploy — the one run the
@@ -2936,11 +2948,10 @@ The command that stops a running background task, read from the sandbox's own pi
2936
2948
 
2937
2949
  THE one builder for it, so every note that hands the executor a way to stop a run hands over the
2938
2950
  same pid-only form: a `pkill -f <something>` matches the shell running it (its argv IS the
2939
- command), and `molecule-dev/api/src/ai/pattern-kill-guard.ts` holds exactly that — X1
2940
- xr-molecule-flash-m87's stuck note suggested `kill $(cat /tmp/<id>.pid) 2>/dev/null; pkill -f
2941
- <id>.sh`, which the platform's own guard then refused, and the same shape cost a refused call at
2942
- +21:57. The pid tree is the whole of what the pattern was for: the detached shell and every
2943
- process under it.
2951
+ command), and `molecule-dev/api/src/ai/pattern-kill-guard.ts` holds exactly that — a stuck note
2952
+ that suggested `kill $(cat /tmp/<id>.pid) 2>/dev/null; pkill -f <id>.sh` was refused by the
2953
+ platform's own guard, and the same shape costs a refused call every time. The pid tree is the
2954
+ whole of what the pattern was for: the detached shell and every process under it.
2944
2955
 
2945
2956
  ```typescript
2946
2957
  function taskStopCommand(backend: ExecutionBackend, taskId: string): Promise<string>
@@ -2956,8 +2967,8 @@ function taskStopCommand(backend: ExecutionBackend, taskId: string): Promise<str
2956
2967
  The steer attached to a SUCCESSFUL read of a package's built output. The ENOENT
2957
2968
  redirect below fires only when the read FAILS, so a model that knows the hoisted
2958
2969
  layout reads `node_modules/@molecule/<pkg>/dist/*.js` happily and never learns the
2959
- documented API is one call away (X0 flash-m70: 24 such reads in 57 s, no note on
2960
- any of them). Carried as `distNote` rather than merged into `note` so a host that
2970
+ documented API is one call away (24 such reads in 57 s, with no note on any of
2971
+ them). Carried as `distNote` rather than merged into `note` so a host that
2961
2972
  has read_molecule_doc (molecule-dev's cadence note, which also names the functions)
2962
2973
  can supersede it without string-matching.
2963
2974
 
@@ -2979,7 +2990,7 @@ The task id is the ownership: it is the handle `wait_for_task` returned, `/tmp/$
2979
2990
  the log this platform's launcher writes for it, and the redirect target is the file this
2980
2991
  process's own launch registered for that id — never a path parsed out of a command by the
2981
2992
  caller. A diagnosis that reads a running walk must not build a `/tmp` path of its own
2982
- (xr-molecule-flash-l07: the wait's DISPLAY was diagnosed as if it were the log).
2993
+ (a wait's DISPLAY gets diagnosed as if it were the log).
2983
2994
 
2984
2995
  ```typescript
2985
2996
  function registeredTaskLogCommand(taskId: string): string | null
@@ -3012,17 +3023,17 @@ when the path is not under `node_modules` or nothing is installed there.
3012
3023
 
3013
3024
  `node_modules` is not the project's code: nothing written there survives the
3014
3025
  next install, no deploy carries it, and a sandbox whose dependency tree is
3015
- shared (the pre-installed superset) breaks every other run through it. X0
3016
- xr-molecule-flash-m91 (+04:43) called `write_file` on
3017
- `node_modules/@molecule/api-resource-comment/dist/numbers.d.ts` while reading
3018
- the package's declarations and clobbered its runtime module a call later
3026
+ shared (the pre-installed superset) breaks every other run through it. A
3027
+ `write_file` on
3028
+ `node_modules/@molecule/api-resource-comment/dist/numbers.d.ts`, made while
3029
+ reading the package's declarations, clobbered its runtime module a call later
3019
3030
  (`module.exports = {}` over the ESM handler its own code imports) — the write
3020
3031
  answered `ok: true`, and 18 s went to noticing, `npm pack`-ing the package and
3021
3032
  putting the file back. Reading these files stays allowed (that is how the
3022
3033
  declarations above are read at all).
3023
3034
 
3024
3035
  What is protected is the INSTALL, not the spelling: the decision comes from
3025
- {@link InstalledPackageFacts}, never from the path alone (m106 above). Three
3036
+ {@link InstalledPackageFacts}, never from the path alone (see the symlink case above). Three
3026
3037
  things are the run's own to remove or replace —
3027
3038
 
3028
3039
  - a `node_modules` that is a SYMLINK: `rm`/`unlink` removes the link, never the
@@ -3032,6 +3043,7 @@ things are the run's own to remove or replace —
3032
3043
 
3033
3044
  A path INSIDE the link is still decided by what resolves there: a link into a
3034
3045
  real tree is refused, because removing or writing through it reaches the
3046
+ install.
3035
3047
 
3036
3048
  _(description truncated — read the full text in `node_modules/@molecule/api-ai-tools/dist/tools.d.ts`.)_
3037
3049
 
@@ -3125,7 +3137,7 @@ function isStaticAssetRequest(request: TraceRequest): boolean
3125
3137
  Whether a trace recorded a failed response or a request error other than cancellation.
3126
3138
 
3127
3139
  A 404 on a static asset is excepted: `/sw.js` and `/fonts/*` 404 on an app that never shipped
3128
- them, and naming one as a failure sent m125 into writing the caching worker it had asked about.
3140
+ them, and naming one as a failure sent a run into writing the caching worker it had asked about.
3129
3141
  A 5xx on an asset, or a network error, still counts. A request error alone does not locate
3130
3142
  the cause in the server: the browser or network may have rejected the request.
3131
3143
 
@@ -3141,7 +3153,7 @@ function failedRequest(request: TraceRequest): boolean
3141
3153
 
3142
3154
  Whether a trace recorded no response and no error other than cancellation. The request may
3143
3155
  have been pending or cancelled when recording ended; the trace does not establish whether
3144
- the endpoint stalled. A shell request is not evidence about the step (m125 +29:33).
3156
+ the endpoint stalled. A shell request is not evidence about the step.
3145
3157
 
3146
3158
  ```typescript
3147
3159
  function unansweredRequest(request: TraceRequest): boolean
@@ -3158,12 +3170,12 @@ other asset the page itself loads, with no response and no error text — still
3158
3170
  the navigation timed out.
3159
3171
 
3160
3172
  The page shell's own incidental requests (`/sw.js`, the manifest, a favicon, a font) are
3161
- excepted for the reason {@link isStaticAssetRequest} documents: m125's run was sent to write a
3162
- caching service worker by an aborted `/sw.js`. A pending `/assets/*.css` is different — the
3163
- navigation blocks on it, so it is the reason `page.goto` ran out of time rather than one of the
3164
- app's API calls (xr-molecule-flash-m135 +34:10: three deployed `page.goto` timeouts on tests that
3165
- pass locally, one 88 KB stylesheet fetch measured at 27 s, and the failing tests' traces each
3166
- held the never-answered CSS while the note said "the cause is in the page").
3173
+ excepted for the reason {@link isStaticAssetRequest} documents: an aborted `/sw.js` once sent a
3174
+ run to write a caching service worker. A pending `/assets/*.css` is different — the navigation
3175
+ blocks on it, so it is the reason `page.goto` ran out of time rather than one of the app's API
3176
+ calls (three deployed `page.goto` timeouts on tests that pass locally, one 88 KB stylesheet
3177
+ fetch measured at 27 s, and the failing tests' traces each holding the never-answered CSS while
3178
+ the note said "the cause is in the page").
3167
3179
 
3168
3180
  ```typescript
3169
3181
  function stalledDocumentSubresource(request: TraceRequest): boolean
@@ -3181,7 +3193,7 @@ endpoint — as opposed to a protected resource that presents one.
3181
3193
  This is the path half of {@link isCredentialExchange}, exported so a caller holding only a
3182
3194
  `METHOD path` reads the same classification: a Hurl failing entry says
3183
3195
  `POST /api/users/login` and nothing about the body, and the whole-suite note must not explain
3184
- a wrong-password login that answered 200 as a cookie-jar effect (xr-molecule-flash-m176).
3196
+ a wrong-password login that answered 200 as a cookie-jar effect.
3185
3197
 
3186
3198
  ```typescript
3187
3199
  function isCredentialExchangePath(path: string, authEndpoints?: readonly string[]): boolean
@@ -3197,7 +3209,7 @@ function isCredentialExchangePath(path: string, authEndpoints?: readonly string[
3197
3209
  The sentence a "hidden" visibility failure earns when the trace proved WHY the box is empty.
3198
3210
 
3199
3211
  Playwright calls an element with a zero-size box hidden even when it is painted, so the answer
3200
- is in the element's children. `a.navbar-brand` on xr-molecule-flash-m197 was 0×4 px because its
3212
+ is in the element's children. An `a.navbar-brand` was 0×4 px because its
3201
3213
  only child was `<img src="/conduit-logo.svg" height="26">`: an SVG with a `viewBox` and no
3202
3214
  width/height has no intrinsic size, and the `height` attribute loses to Tailwind's preflight
3203
3215
  (`img { max-width: 100%; height: auto }`), which the scaffold's own `index.css` imports. The
@@ -3217,7 +3229,7 @@ function hiddenBoxNote(items: readonly TraceArtifact[]): string | null
3217
3229
  The row's sentence for a failing count assertion: the locator, both numbers, and the elements
3218
3230
  the failure snapshot held.
3219
3231
 
3220
- xr-molecule-flash-m321's `comments.spec.ts:86` printed only `Expected: 3 / Received: 4`. The
3232
+ A `comments.spec.ts:86` row printed only `Expected: 3 / Received: 4`. The
3221
3233
  helper counted `.card:not(.comment-form) .card-block`, and the app's comment form was a
3222
3234
  `.comment-form` wrapper around a plain `.card`, so the form's own `.card-block` was the fourth
3223
3235
  match. The trace held the selector and the four elements; the note held neither.
@@ -3258,14 +3270,15 @@ The three kinds are kept apart, because they mean different things. A FAILED req
3258
3270
  a network error with Playwright's own text) is a cause. A request with NO RESPONSE RECORDED —
3259
3271
  Playwright's `-1`, no error text — was still in flight when the test ended (the page closed under
3260
3272
  it); listing it as a failure sent a run hunting an API that never answered anything wrong
3261
- (xr-molecule-flash-m112 +30:45). The rest are the page's last answered requests.
3273
+ The rest are the page's last answered requests.
3262
3274
 
3263
3275
  A 4xx request carries what the page SENT beside its status, so a wrapped body is visible in one
3264
3276
  line rather than inferred from the status; when one of those bodies is an object whose only key
3265
- is `data`, the note names the call shape that produces it (xr-molecule-flash-m111 +11:36).
3277
+ is `data`, the note names the call shape that produces it.
3266
3278
 
3267
3279
  Every row opens with the test's LAST user action before the failing assertion and the requests
3268
3280
  that action caused ({@link TraceArtifact.lastAction}) — started after it, before the assertion,
3281
+ the app's own API calls first, each with its status and the first 200 characters of its response,
3269
3282
 
3270
3283
  _(description truncated — read the full text in `node_modules/@molecule/api-ai-tools/dist/trace-artifacts.d.ts`.)_
3271
3284
 
@@ -3293,7 +3306,7 @@ Whether a Playwright config records traces for the tests that fail.
3293
3306
 
3294
3307
  Only `on` and `retain-on-failure` keep a `trace.zip` for a failure whatever the retries do: the
3295
3308
  two retry modes need a retry to happen at all, and a diagnosis run is given `--retries=0`
3296
- (`streamingBackgroundCommand`), so on X1 xr-molecule-flash-m100 the run's own
3309
+ (`streamingBackgroundCommand`), so a run's own
3297
3310
  `trace: 'on-first-retry'` recorded nothing — which is what left the failing tests' network log
3298
3311
  unreadable. A config that sets no `trace:` at all records nothing either (Playwright's default
3299
3312
  is off); so does one that cannot be read.
@@ -3332,14 +3345,15 @@ decide its own `--trace`, and whose config keeps no trace for its failures.
3332
3345
 
3333
3346
  A run that can serve as PROOF is the exception: the graded measurement is the suite's own
3334
3347
  settings, so it keeps its own tracing and retries. That was measured, not assumed — on one
3335
- sandbox in X1 xr-molecule-flash-h15 (+46:53 → +49:30) the same build ran a three-test deployed
3348
+ sandbox the same build ran a three-test deployed
3336
3349
  subset 3/3 timed out under this flag (17.6–17.9 s against a 15 s per-test budget) and the whole
3337
3350
  file passed 14/14 without it (10.9–12.1 s). `retain-on-failure` RETAINS only a failing test's
3338
3351
  trace (Playwright's `_shouldAbandonTrace` unlinks a passing test's), but it RECORDS every
3339
3352
  action of every test, and for a test near its per-test budget that recording is the difference
3340
- between passing and timing out. m163 (+24:58) is the failure this flag was added for: its
3353
+ between passing and timing out. This flag was added for exactly that failure: its
3341
3354
  deployed proof run left only an `error-context.md` because the suite traces
3342
3355
  `on-first-retry` and the run had no retries. That need is met without the flag — the graded
3356
+ deployed run keeps the suite's own retries, so a failing test leaves its retry's trace — and
3343
3357
 
3344
3358
  _(description truncated — read the full text in `node_modules/@molecule/api-ai-tools/dist/trace-artifacts.d.ts`.)_
3345
3359
 
@@ -3543,7 +3557,7 @@ function outputIsWithheldUntilExit(command: string): boolean
3543
3557
  The file a command sends its own output to, when it redirects it (`> out.txt`,
3544
3558
  `>> log`, `&> run.log`, `| tee [-a] file`), or null. A background command that does
3545
3559
  this leaves its task log empty, so the log is the wrong place to look and an empty
3546
- log proves nothing (X1 flash-m29).
3560
+ log proves nothing.
3547
3561
 
3548
3562
  Which redirect counts is decided by the command's own shell structure, from the same
3549
3563
  parse every other command reader uses: a redirect written in a BACKGROUNDED statement
@@ -3551,7 +3565,7 @@ parse every other command reader uses: a redirect written in a BACKGROUNDED stat
3551
3565
  the command's. The platform's own preview launch is exactly that — the preview server is
3552
3566
  started with `>/tmp/mol-preview-4173.log 2>&1 &` inside the build/serve prelude, and the
3553
3567
  suite's foreground command follows it — so a reader that took the last `>` in the whole
3554
- text told a run its output went to the PREVIEW's log (X1 flash-m136 +18:31).
3568
+ text tells a run its output went to the PREVIEW's log.
3555
3569
 
3556
3570
  The target comes back without its shell quotes: `> '/tmp/x.log'` is `/tmp/x.log`, and
3557
3571
  the callers resolve a relative one against the command's cwd.
@@ -3569,7 +3583,7 @@ function outputRedirectTarget(command: string): string | null
3569
3583
  Rewrite a command about to run in the background so its log grows while it
3570
3584
  runs. Two shapes left the log empty until exit, and an empty log is what
3571
3585
  `wait_for_task` reads as "stuck", so working suites were reported stuck and
3572
- killed (X1 run flash-m15 lost 20 of its 60 minutes this way, 2026-10-15):
3586
+ killed (one run lost 20 of its 60 minutes this way):
3573
3587
 
3574
3588
  - a trailing `| tail -N`, which holds everything back until the command ends.
3575
3589
  It is dropped: `wait_for_task` already returns the end of the log.
@@ -3577,7 +3591,7 @@ killed (X1 run flash-m15 lost 20 of its 60 minutes this way, 2026-10-15):
3577
3591
  failing test's own error and leaves the pipeline's exit status — the filter's — as the run's.
3578
3592
  Every such stage is dropped from EVERY suite run in the command, not only the last
3579
3593
  ({@link stripTrailingSuiteFilters}); `wait_for_task` already returns the end of the full log,
3580
- and a run whose tally shows a failure must never report 0 (xr-molecule-flash-m101 +25:54).
3594
+ and a run whose tally shows a failure must never report 0.
3581
3595
  - `playwright test` with no `--reporter`, which runs the config's reporter —
3582
3596
  often `html`, which prints nothing per test. `--reporter=list` is added
3583
3597
  when the playwright run is the command's last step, piped or not: it writes each result as
@@ -3594,11 +3608,16 @@ function streamingBackgroundCommand(
3594
3608
  command: string,
3595
3609
  context?: DiagnosisRunContext,
3596
3610
  reportPath?: string,
3597
- ): { command: string; changes: string[]; reportPath?: string; error?: string }
3611
+ ): {
3612
+ command: string
3613
+ changes: string[]
3614
+ reportPath?: string
3615
+ error?: string
3616
+ }
3598
3617
  ```
3599
3618
 
3600
3619
  - `command` — The command as the executor sent it.
3601
- - `context` — What the caller knows beyond the command: the tests the person's request excludes by name, and whether this command IS the platform's graded proof ({@link DiagnosisRunContext}). A `--grep-invert` of exactly those exclusions is the request's own scope, not a diagnosis, so it keeps the suite's retries on a deployed proof (xr-molecule-flash-m170 +33:16) — and a proof the platform itself composed and launched keeps them whatever its scope, targeted set included (xr-molecule-flash-l48 +26:35).
3620
+ - `context` — What the caller knows beyond the command: the tests the person's request excludes by name, and whether this command IS the platform's graded proof ({@link DiagnosisRunContext}). A `--grep-invert` of exactly those exclusions is the request's own scope, not a diagnosis, so it keeps the suite's retries on a deployed proof — and a proof the platform itself composed and launched keeps them whatever its scope, targeted set included.
3602
3621
  - `reportPath` — Where this run should write Playwright's standard `json` report, when the caller keeps one ({@link ./playwright-report.js}). The reporter is added to the run's own reporter set, never in place of one, and its output goes to that file through `PLAYWRIGHT_JSON_OUTPUT_FILE` — so the log, the executors' own reporters and every verdict stay exactly as they are. Omitted, or a run whose reporter set is not this function's to place (already names `json`, sets the variable itself, or whose runner cannot be located), leaves the command untouched and the result's `reportPath` unset.
3603
3622
 
3604
3623
  **Returns:** The command to run, one sentence per change made (empty when none), and the report path when one was actually wired — or `error` when the command starts the suite more than once.
@@ -3670,7 +3689,7 @@ function isSuiteRunCommand(command: string): boolean
3670
3689
  Refuse only a command made entirely of identical suite invocations.
3671
3690
 
3672
3691
  Mixed shell commands execute as written. Rebuilding their prefix or suffix can lose writes,
3673
- break heredoc delimiters or turn an && guard into unconditional work (m277). Different args
3692
+ break heredoc delimiters or turn an && guard into unconditional work. Different args
3674
3693
  or environments may select different suites or targets; they are not known duplicates either.
3675
3694
  This is an optimization, so uncertainty always allows the original command.
3676
3695
 
@@ -3688,8 +3707,8 @@ A command with the supplied suite's own settings written back onto its runner as
3688
3707
  flags, and the flags that could not be placed.
3689
3708
 
3690
3709
  The grader walks the suite under its OWN budget, so a run whose runner config sets a different
3691
- timeout or worker count measures a run the grader never sees (xr-molecule-flash-m169: a 60 s
3692
- wrapper config produced a green local proof the official 15 s grader then failed). Playwright
3710
+ timeout or worker count measures a run the grader never sees (a 60 s wrapper config produced
3711
+ a green local proof the official 15 s grader then failed). Playwright
3693
3712
  lets a command-line flag win over every config file, so the suite's values are put on the
3694
3713
  runner's own arguments — written where {@link statementArgumentEnd} places them, never after a
3695
3714
  pipe, redirect or group closer. Only the command's LAST suite step is touched: that is the run
@@ -3747,10 +3766,13 @@ bound that was lifted.
3747
3766
  Used where the platform moves a run to the background: the executor wrote the bound to fit this
3748
3767
  tool's foreground ceiling, and in the background that ceiling no longer applies — the task is
3749
3768
  bounded by `wait_for_task` and the turn's deadline — so the prefix only kills the walk
3750
- ({@link withoutTimeoutWrapper}; X1 xr-molecule-flash-m143 +24:45).
3769
+ ({@link withoutTimeoutWrapper}).
3751
3770
 
3752
3771
  ```typescript
3753
- function withoutSuiteTimeout(command: string): { command: string; seconds: number | null }
3772
+ function withoutSuiteTimeout(command: string): {
3773
+ command: string
3774
+ seconds: number | null
3775
+ }
3754
3776
  ```
3755
3777
 
3756
3778
  - `command` — The shell command.
@@ -3763,7 +3785,7 @@ Whether a command starts a Playwright run — a `playwright test` in command pos
3763
3785
  that runs something.
3764
3786
 
3765
3787
  `npx playwright test --list` matched every `\bplaywright\s+test\b` test in the platform and was
3766
- then treated as a run: held (flash-m79's config check), backgrounded for a run that outlasts
3788
+ then treated as a run: held (a config check), backgrounded for a run that outlasts
3767
3789
  the tool's ceiling, and rewritten with `--reporter`. A list takes two seconds, prints its lines
3768
3790
  and exits, so it is none of those; {@link commandRunsNoTests} is what decides.
3769
3791
 
@@ -3799,8 +3821,8 @@ Where the suite runner's exit code comes from: the runner itself, or a stage pip
3799
3821
  code a finished run reports is its LAST pipeline stage's, so a stage after the runner makes the
3800
3822
  code the stage's — but only when such a stage EXISTS. The platform used to report "piped" for
3801
3823
  any run whose statements it could not place in the text, which one heredoc body was enough to
3802
- cause: on X1 xr-molecule-flash-m105 (+08:12) a config written in the same `exec_command` made
3803
- the run come back with no exit code at all, and the note under it claimed a stage after the
3824
+ cause: a config written in the same `exec_command` made the run come back with no exit code
3825
+ at all, and the note under it claimed a stage after the
3804
3826
  runner that was not there. The parse now places every statement (`locatedCommandSegments`), so
3805
3827
  "unplaced" is the rare, named case rather than a guess dressed as an answer.
3806
3828
 
@@ -3832,10 +3854,9 @@ Start a background suite run at lower CPU and IO priority, so the sandbox it
3832
3854
  shares with everything else stays responsive to what the executor does next.
3833
3855
 
3834
3856
  A whole-suite Playwright run saturates the one container the app's Vite
3835
- server, its API process and every other command also live in: on X1 flash-m75
3836
- the model backgrounded a 139-test run at +36:23 and the two-word shell
3837
- command it sent next — tick its plan file — returned nothing for 2 min 40 s,
3838
- measured on the chat payload and on the live-stream follower independently.
3857
+ server, its API process and every other command also live in: a backgrounded 139-test run
3858
+ has left the two-word shell command sent next — tick its plan file — returning nothing for
3859
+ 2 min 40 s, measured on the chat payload and on the live-stream follower independently.
3839
3860
  The backgrounding note is right that the executor should go do other work;
3840
3861
  what it cannot promise is that the sandbox will let it.
3841
3862
 
@@ -3866,8 +3887,8 @@ Check if a command is blocked for security reasons. Returns error message or nul
3866
3887
  The first check reads the commands the shell actually RUNS — the statements, a `sh -c`
3867
3888
  string's body, and every command substitution ({@link executedCommands}) — so a `|` inside a
3868
3889
  quoted grep alternation is data, not a pipeline: `grep -E "USER CALLS|ENV|BUTTON|passed|failed"
3869
- app.log` prints log lines, and the `ENV` in its pattern started nothing (X0
3870
- xr-molecule-flash-m331 blocked exactly that call as an environment dump, twice). What the
3890
+ app.log` prints log lines, and the `ENV` in its pattern starts nothing — a text
3891
+ match would block exactly that call as an environment dump, twice over. What the
3871
3892
  shell DOES run stays visible through the same walk: `ls | env`, `bash -c 'env'`,
3872
3893
  `echo "$(printenv)"` and a nested `sh -c 'x; env'` are all commands, and so is `env` itself
3873
3894
  when nothing follows it.
@@ -3901,8 +3922,7 @@ Whether a tool path points outside the project root once normalized (an
3901
3922
  absolute path elsewhere, or a `..` that climbs out). {@link resolvePath}
3902
3923
  clamps such a path to the root; a file tool must refuse it instead of
3903
3924
  answering about the root — a `list_files /tmp/x` used to return the
3904
- workspace listing as if it were `/tmp/x` (X1 runs sonnet-m17 and sol-m05,
3905
- 2026-10-14).
3925
+ workspace listing as if it were `/tmp/x`.
3906
3926
 
3907
3927
  ```typescript
3908
3928
  function isOutsideRoot(path: string, projectRoot: string): boolean
@@ -3913,6 +3933,34 @@ function isOutsideRoot(path: string, projectRoot: string): boolean
3913
3933
 
3914
3934
  **Returns:** True when the path leaves the root.
3915
3935
 
3936
+ #### `commandStartsWithCdInto(command, directory, projectRoot)`
3937
+
3938
+ Whether a command's FIRST statement already changes into `directory`.
3939
+
3940
+ `exec_command` refuses a `cwd` outside the workspace, and that refusal tells
3941
+ the caller to drop `cwd` and start the command with `cd <path> && `. When the
3942
+ command ALREADY starts that way the advice describes what was just sent, so
3943
+ the command runs as written with the backend's working directory at the root
3944
+ instead (`{cwd: "/tmp", command: "cd /tmp && …"}` was refused with "start the command with
3945
+ `cd /tmp && `"; the same command resent with `cwd: "/workspace"` then passes).
3946
+
3947
+ Only the leading statement counts, only when the shell's own parse puts it in
3948
+ the caller's shell — a `( cd … )` group or a `sh -c '…'` runs in its own
3949
+ directory and moves nothing — and only when it ends the way a following
3950
+ command needs (`&&`, `;`, a newline, or nothing after it). `cd … | cat` is a
3951
+ pipeline, so its `cd` runs in a subshell, and `&` backgrounds it: neither
3952
+ leaves the caller's directory changed.
3953
+
3954
+ ```typescript
3955
+ function commandStartsWithCdInto(command: string, directory: string, projectRoot: string): boolean
3956
+ ```
3957
+
3958
+ - `command` — The shell command as the tool received it.
3959
+ - `directory` — The `cwd` the caller asked for.
3960
+ - `projectRoot` — The project root a relative path is resolved against.
3961
+
3962
+ **Returns:** True when the command's first statement `cd`s into `directory`.
3963
+
3916
3964
  #### `isValidGlob(pattern)`
3917
3965
 
3918
3966
  Validate that a glob/include pattern is safe (no shell metacharacters that could
@@ -3943,8 +3991,8 @@ expanded pattern.
3943
3991
  Neither search tool expands braces itself: `grep --include` and `find` take
3944
3992
  the pattern as a single shell-quoted argument, so no shell ever sees it.
3945
3993
  `find_files {pattern:"*.{ts,tsx}"}` and `search_files {include:"*.{ts,tsx}"}`
3946
- were both refused outright (xr-molecule-flash-m199 and m189), costing a round
3947
- trip and pushing the agent to a narrower search. The group is expanded here
3994
+ were both refused outright, costing a round trip and pushing the agent to a narrower
3995
+ search. The group is expanded here
3948
3996
  instead — `search_files` passes one `--include` per alternative and
3949
3997
  `find_files` ORs one `-name`/`-path` predicate per alternative.
3950
3998
 
@@ -3967,8 +4015,8 @@ The `find` predicate for a `find_files` pattern.
3967
4015
 
3968
4016
  `find -name` compares a pattern against a file's BASENAME, so a pattern
3969
4017
  containing a slash (`helpers/*`, `e2e/*.spec.ts`, `src` + `**` + `/App.tsx`)
3970
- can never match and the tool answers `[]` (xr-molecule-flash-m77, on two
3971
- calls in one run). Such a pattern is matched with `-path` instead: an fnmatch
4018
+ can never match and the tool answers `[]` (twice in one run). Such a pattern is matched
4019
+ with `-path` instead: an fnmatch
3972
4020
  glob over the whole printed path, whose `*` crosses `/` — the rule
3973
4021
  `.gitignore` uses, and the reason a bare `helpers/*` means "a `helpers/`
3974
4022
  directory anywhere below the root". The pattern is anchored with a leading
@@ -4019,14 +4067,14 @@ anchor ({@link findPatternArgs}), so `find` visits every entry below the
4019
4067
  search root. Handed `/workspace/node_modules` and
4020
4068
  `@molecule/api-resource-user/dist/*.d.ts` — a directory named outright —
4021
4069
  `find` walked the sandbox's entire dependency tree and hit the tool's 10 s
4022
- deadline without printing a result (xr-molecule-flash-m94: the one directory
4023
- the model meant answered a `list_files` in 0 s). The literal prefix is that
4070
+ deadline without printing a result (the one directory the model meant answered a `list_files`
4071
+ in 0 s). The literal prefix is that
4024
4072
  directory, and rooting the search at it is what keeps the call instant.
4025
4073
 
4026
4074
  A BARE first segment (`helpers/*`, `bonds/*`, `e2e/*.spec.ts`) is NOT one:
4027
4075
  `helpers/*` means "a `helpers/` directory anywhere below the root", which the
4028
- tool documents and a live run relied on (xr-molecule-flash-m77 — a path
4029
- pattern is not anchored to one depth). Rooting those at
4076
+ tool documents and a live run relied on (a path pattern is not anchored to one depth).
4077
+ Rooting those at
4030
4078
  `<root>/helpers` would answer with a SUBSET, silently: the nested
4031
4079
  `api/src/helpers/` matches would disappear, and a missing file reads as
4032
4080
  "no such file". So a prefix is returned only when it names a path of two or
@@ -4055,7 +4103,7 @@ The E2B SDK answers a timed-out `exec` with its generic text —
4055
4103
  `[deadline_exceeded] the operation timed out: … It can be modified by passing
4056
4104
  'timeoutMs' when making the request. Use '0' to disable the timeout.` — which
4057
4105
  names an option the executor cannot set and says nothing about the search
4058
- that died. Handing that sentence to the model is what xr-molecule-flash-m94
4106
+ that died. Handing that sentence to the model is what a run
4059
4107
  read after `find_files` spent 10 s walking `node_modules`; the tool answers
4060
4108
  the deadline in its own words instead (see {@link searchTimeoutError}).
4061
4109
 
@@ -4116,8 +4164,8 @@ shape a truncated provider stream leaves behind.
4116
4164
 
4117
4165
  The path message is the wrong reading of it: "requires a non-empty path
4118
4166
  argument" says the call was understood and the path was left out, so the model
4119
- retries the call it just made instead of sending the whole call again (x0
4120
- flash-m83 +29:32: `edit_file {}`, one round lost). An empty object and a
4167
+ retries the call it just made instead of sending the whole call again (`edit_file {}` loses
4168
+ one round). An empty object and a
4121
4169
  missing `path` are different failures and deserve different sentences.
4122
4170
 
4123
4171
  ```typescript
@@ -4282,9 +4330,8 @@ The shell command whose stdout is the interesting part of a log that is still be
4282
4330
  the failure lines so far (capped at {@link RUNNING_FAILURE_LINES}), then the end of the log.
4283
4331
 
4284
4332
  A Playwright `list` run prints one line per test as it finishes, so the LAST bytes of a running
4285
- log are its least informative part — in X1 flash-m61 the last 3 000 bytes of a 139-test walk
4286
- were the skip list, and all 61 failures were above them, which cost the run the grep it had to
4287
- make anyway. A background run also carries each failure's own error as it fails
4333
+ log are its least informative part — the last 3 000 bytes of a 139-test walk are the skip
4334
+ list, and all 61 failures were above them, which costs the run the grep it has to make anyway. A background run also carries each failure's own error as it fails
4288
4335
  ({@link PLAYWRIGHT_FAILURES_INLINE_ENV}), and {@link RUNNING_FAILURE_LINE_RE} already matches
4289
4336
  those blocks' headers and their `Error:` lines, so this slice shows the causes too.
4290
4337
 
@@ -4322,11 +4369,11 @@ function runningCauseCommand(log: string, own?: string): string
4322
4369
  The shell command whose stdout is a bounded CONTIGUOUS read of a running task's own log: the
4323
4370
  log's byte size, then its last {@link RUNNING_LOG_READ_BYTES} bytes.
4324
4371
 
4325
- {@link runningOutputSliceCommand} is the wrong read for a diagnosis, and l07 is the finding: it
4372
+ {@link runningOutputSliceCommand} is the wrong read for a diagnosis: it
4326
4373
  stitches the first 40 grep-selected failure lines to the last 1 000 bytes with a blank line
4327
4374
  between, so the tail is DISJOINT from the headers above it. Read as one log, the last numbered
4328
- header absorbs whatever the tail starts with — a clipped skipped-test title became the cause of
4329
- a genuine failure (xr-molecule-flash-l07). A contiguous window can only ever hold real
4375
+ header absorbs whatever the tail starts with — a clipped skipped-test title becomes the cause
4376
+ of a genuine failure. A contiguous window can only ever hold real
4330
4377
  neighbouring lines of one log.
4331
4378
 
4332
4379
  The size rides along so a caller can say when the window is only the log's end
@@ -4370,11 +4417,12 @@ log does NOT carry.
4370
4417
 
4371
4418
  Either way the point is the same: a suite whose failures repeat one cause spends its whole
4372
4419
  runtime proving that one cause, and the executor watching it can be told so at the third
4373
- failure instead of at the last. X1 flash-m76 walked 15 tests in 4.0 minutes where 15.6 s
4420
+ failure instead of at the last. Fifteen tests walked in 4.0 minutes where 15.6 s
4374
4421
  each was the test timeout and one missing `navigate('/')` was the cause of all of them.
4375
4422
 
4376
4423
  The quorum is of DISTINCT tests — {@link REPEATING_FAILURE_MIN} of them — because a log that
4377
- prints each failure twice (a second reporter, a retry) had X1 flash-m83 told that four of its
4424
+ prints each failure twice (a second reporter, a retry) has told a run that four of its
4425
+ tests failed the same way when two had, so the executor stopped a 139-test walk at test 21
4378
4426
 
4379
4427
  _(description truncated — read the full text in `node_modules/@molecule/api-ai-tools/dist/utilities.d.ts`.)_
4380
4428
 
@@ -4406,8 +4454,7 @@ is one the reporter printed inline.
4406
4454
  A body for a test the request EXCLUDES is not that evidence: its failure does not count for
4407
4455
  this request ({@link matchingExcludedTitles}), so a wait that handed it over as the diagnostic
4408
4456
  spent a model round trip and 8 k of partial log on a test the same result says to ignore —
4409
- exactly what xr-molecule-flash-h13 (+19:06) did twice while the platform's proof was still
4410
- walking.
4457
+ which a run has done twice while the platform's proof was still walking.
4411
4458
 
4412
4459
  With `finalOnly`, only a failure the run has FINISHED with counts; a pending retry waits.
4413
4460
 
@@ -4431,8 +4478,8 @@ How many test FILES a Playwright run's own command narrows it to, or null when i
4431
4478
  whole suite (or its selection cannot be read).
4432
4479
 
4433
4480
  {@link universalCause}'s file threshold is written for a whole-suite run, which a narrowed run
4434
- can never reach. xr-molecule-flash-m119 (+42:08) re-ran ONE spec file against a hand-started
4435
- `vite preview` the browser could not reach, and every test in it failed `page.goto: Timeout` —
4481
+ can never reach. A run that re-ran ONE spec file against a hand-started `vite preview` the
4482
+ browser could not reach had every test in it fail `page.goto: Timeout` —
4436
4483
  but one file is below {@link UNIVERSAL_CAUSE_FILES}, so the wait sat out its entire 280 s
4437
4484
  budget on a run that had already measured all it could.
4438
4485
 
@@ -4459,7 +4506,7 @@ The test is: the cause accounts for every failure the log names, it has hit the
4459
4506
  threshold, and nothing has passed since its first failure. The threshold is
4460
4507
  {@link UNIVERSAL_CAUSE_FILES} for a whole-suite run but the number of files the command
4461
4508
  SELECTED for a narrowed one ({@link specFilesSelected}): a one-file run can never span three,
4462
- and xr-molecule-flash-m119 (+42:08) waited out its whole budget on exactly that shape. An app
4509
+ and a run can wait out its whole budget on exactly that shape. An app
4463
4510
  that is not up, a 5xx on every request, or a selector that is missing on every page all look
4464
4511
  like that, and every remaining test will fail the same way — so the run's remaining minutes
4465
4512
  measure nothing. A CONNECTION-class cause ({@link CONNECTION_CAUSE}) needs no file span at all:
@@ -4468,8 +4515,8 @@ case however few files the run walks.
4468
4515
 
4469
4516
  Anything less is NOT this: a cause that stops at one file of a multi-file run, or that leaves
4470
4517
  other tests passing, or that shares the run with failures of another shape, leaves the run with
4471
- something to say, and the run is the only thing that will say it. X1 flash-m83 (2026-10-16)
4472
- stopped eight local runs at their first repeating cause over 14.5 minutes and never finished
4518
+ something to say, and the run is the only thing that will say it. Stopping runs at their first
4519
+ repeating cause has burned eight local runs over 14.5 minutes without finishing
4473
4520
  one; three of its deploys each fixed a single cause that a finished run would have listed
4474
4521
  alongside the others.
4475
4522
 
@@ -4498,16 +4545,17 @@ Both halves are load-bearing, each of them learned from a run that lost minutes
4498
4545
  spec-file threshold — {@link UNIVERSAL_CAUSE_FILES}, or the files a narrowed run's own
4499
4546
  command selects, or {@link CONNECTION_CAUSE_TESTS} tests of an app that never answered — with
4500
4547
  nothing passing since the first. That is the
4501
- dont-stop-runs rule. X1 flash-m83 (2026-10-16) stopped eight local runs at their first
4502
- repeating cause in 14.5 minutes and never finished one, and a run that still has other causes
4548
+ dont-stop-runs rule. Stopping runs at their first repeating cause has burned eight local
4549
+ runs in 14.5 minutes without finishing one, and a run that still has other causes
4503
4550
  left to name is the only thing that will name them.
4504
4551
  - **A PROVEN cause** is an error repeated VERBATIM. A shared DURATION is a LEAD, never a cause:
4505
4552
  a suite whose config sets a timeout spends that timeout on every failure that waits for
4506
4553
  anything, so three unrelated tests timing out together look exactly like one broken run
4507
- (`~7 s` is a property of the CONFIG, not of the cause — {@link normalizedSignature}). X1
4508
- xr-molecule-flash-m99 (2026-10-16) was told `status: 'repeating_failure'` twice on that
4554
+ (`~7 s` is a property of the CONFIG, not of the cause — {@link normalizedSignature}). A run
4555
+ told `status: 'repeating_failure'` twice on that
4509
4556
  shape — three `url-navigation.spec.ts` tests at ~16.2 s, one `timeout: 15_000` plus teardown
4510
4557
  — read the early return as "stop waiting, edit now", and voided a run that was still walking;
4558
+ the second cost a 224 s wait that ended with no result at all.
4511
4559
 
4512
4560
  _(description truncated — read the full text in `node_modules/@molecule/api-ai-tools/dist/utilities.d.ts`.)_
4513
4561
 
@@ -4532,12 +4580,11 @@ The request quotes a test's own title (`… except "should require login to post
4532
4580
  extracted by molecule-dev's `excludedTestTitles`) while a run's heading carries more of it
4533
4581
  (`comments.spec.ts › Comments › should require login to post comment`), so containment is the
4534
4582
  comparison. Whitespace is normalised and case is ignored: a brief may wrap the title across a
4535
- line (`xr-molecule-flash-m44`), and the reporter's own casing never has to match the brief's.
4583
+ line, and the reporter's own casing never has to match the brief's.
4536
4584
 
4537
4585
  Two readers used to answer this separately — the causes note (which therefore asked the
4538
4586
  executor to fix a test the same result said not to) and molecule-dev's exclusion notes — and
4539
- xr-molecule-flash-m101 paid for the gap (+12:00: a turn and an edit spent on the excluded
4540
- test).
4587
+ a run paid for the gap (a turn and an edit spent on the excluded test).
4541
4588
 
4542
4589
  ```typescript
4543
4590
  function matchingExcludedTitles(heading: string, excluded: readonly string[]): string[]
@@ -4555,7 +4602,7 @@ tests it hit.
4555
4602
 
4556
4603
  The point is that ONE run yields EVERY cause. A Playwright report prints its failures one
4557
4604
  after another with no statement of which of them share a cause, so a run of 19 failures is 19
4558
- bodies to read; X1 flash-m83 (2026-10-16) spent three deploys (6.7 minutes) each fixing a
4605
+ bodies to read; three deploys (6.7 minutes) each fixed a
4559
4606
  single cause, two of them found by runs stopped before they walked the rest.
4560
4607
 
4561
4608
  The signature is the cause itself where the log carries the failures' bodies (a finished run, a
@@ -4567,8 +4614,8 @@ proven cause. A test the log printed twice, or failed twice, is one test.
4567
4614
  A test the request EXCLUDES by name is not a cause to fix: its failure does not count for
4568
4615
  this request ({@link matchingExcludedTitles}), so it is dropped here rather than handed to the
4569
4616
  executor as work — a result that names it beside "it does not count" is the contradiction
4570
- xr-molecule-flash-m101 filed (+12:00: the model spent a turn and an edit on the excluded test,
4571
- on a page that was passing).
4617
+ a run filed (the model spent a turn and an edit on the excluded test, on a page that was
4618
+ passing).
4572
4619
 
4573
4620
  ```typescript
4574
4621
  function failuresByCause(log: string, excluded?: readonly string[]): FailureCause[]
@@ -4597,7 +4644,7 @@ function requiredLandmark(selector: string): RequiredLandmark | null
4597
4644
  The sentence for a run whose navigational elements are all missing from pages that otherwise
4598
4645
  painted — the missing shared header the executor must check BEFORE rewriting auth.
4599
4646
 
4600
- xr-molecule-flash-m193 (+13:54 → +20:00): four failures on `/` — `a[href="/profile/…"]`,
4647
+ A run had four failures on `/` — `a[href="/profile/…"]`,
4601
4648
  `a.navbar-brand`, `nav a[href="/"]`, `nav .user-pic` — while every `error-context.md` snapshot
4602
4649
  showed the feed, sidebar and footer with no navigation at all. `Home.tsx` imported and
4603
4650
  re-exported `Navbar` but never rendered it, and `App.tsx` mounted `<Home />` in a bare route.
@@ -4691,7 +4738,7 @@ function rerunOfRunningSuite(
4691
4738
  ): string | null
4692
4739
  ```
4693
4740
 
4694
- - `run` — The run in flight: the command it was started with, as it was run, the directory that command ran in, the config it loaded when the caller knows it, and the settings the request required and the run left out (`env`) — the re-run carries them, so it never reproduces the configuration the run was measured under by mistake (m182).
4741
+ - `run` — The run in flight: the command it was started with, as it was run, the directory that command ran in, the config it loaded when the caller knows it, and the settings the request required and the run left out (`env`) — the re-run carries them, so it never reproduces the configuration the run was measured under by mistake.
4695
4742
  - `locations` — The failing `file:line`s to re-run, as the run's log printed them.
4696
4743
  - `excluded` — The test titles the request carves out: the re-run inverts them out (`--grep-invert`) so it cannot report them again.
4697
4744
 
@@ -4708,17 +4755,18 @@ tests, so the note never names one or two tests as a cause.
4708
4755
  The note names the cause early so the executor can START FIXING while the run keeps walking,
4709
4756
  and it hands a stop command over only when {@link earlyReturnCause} says so — the SAME
4710
4757
  predicate the wait uses to decide whether to return early, so a finding the wait keeps waiting
4711
- on is a finding this note never asks to stop for. X1 flash-m76 (2026-10-16) spent 4.0 minutes
4758
+ on is a finding this note never asks to stop for. One run spent 4.0 minutes
4712
4759
  walking 15 tests whose one cause was certain at the third, 47 s in, and the note answers
4713
- exactly that; X1 flash-m83 then stopped eight runs at their first repeating cause in 14.5
4760
+ exactly that; another stopped eight runs at their first repeating cause in 14.5
4714
4761
  minutes and never finished one, so the note must not say to stop when the run still has other
4715
- causes to name. X1 xr-molecule-flash-m99 (2026-10-16) is the third shape: a shared duration is
4762
+ causes to name. The third shape: a shared duration is
4716
4763
  not a cause at all, so a lead reaches the executor as a note on a result it is still waiting
4717
4764
  for — never as a verdict with a stop command in it.
4718
4765
 
4719
4766
  The run is STILL WALKING while this note is written — both callers produce it mid-run — so a
4720
4767
  re-run of one of its tests is a second run against the same app and database, and the platform
4721
4768
  refuses that ({@link suiteRunInTheWay}, the same rule its overlap hold answers with):
4769
+ an executor read *"Start on them now, while the run keeps walking.
4722
4770
 
4723
4771
  _(description truncated — read the full text in `node_modules/@molecule/api-ai-tools/dist/utilities.d.ts`.)_
4724
4772
 
@@ -4920,7 +4968,7 @@ Python WSGI server. Matched against a command segment's own text, and against a
4920
4968
  when the command only names the script file — but NEVER against an inline program's code
4921
4969
  (`node -e …`, `python3 -c …`), where this text is the user's program rather than a file being
4922
4970
  run: `require('…/node_modules/vite')` imports a module, it does not start a dev server
4923
- (xr-molecule-flash-m391 +13:13, refused as "node starts a server" for exactly that line).
4971
+ (refused as "node starts a server" for exactly that line).
4924
4972
 
4925
4973
  ```typescript
4926
4974
  const SERVER_PROGRAM: RegExp
@@ -4956,7 +5004,7 @@ this package's own input normalization, keep symbol-keyed properties, so the hos
4956
5004
  survives the real launch path.
4957
5005
 
4958
5006
  ```typescript
4959
- const PLATFORM_PROOF: typeof PLATFORM_PROOF
5007
+ const PLATFORM_PROOF: unique symbol
4960
5008
  ```
4961
5009
 
4962
5010
  #### `SPLIT_WORK_ADVICE`
@@ -4974,14 +5022,13 @@ The closing advice on an over-budget message for a command that IS a suite run
4974
5022
  (Playwright, Vitest, a `hurl` run — {@link isSuiteRunCommand}): its files are not
4975
5023
  a bigger unit to break up.
4976
5024
 
4977
- X1 flash-m36 asked for this half and the message kept saying "run a smaller unit"
4978
- for two months. It is the wrong direction for a suite, and measurably: a run
4979
- stopped here reports NO tally, so nothing in the result says which test or request
4980
- hung — the run has to be sent again in the background (off this budget, its output
4981
- written to a log that can be read mid-run) or, when a consumer knows the runner's
4982
- per-request limit, with each request bounded. xr-molecule-flash-m93 (+06:22,
4983
- 2026-10-16) lost 4.8 minutes to a Hurl run whose ONE unanswered request had hurl's
4984
- 300 s default per request holding the file, ten seconds past this tool's budget.
5025
+ The wrong advice here is "run a smaller unit": it is the wrong direction for a
5026
+ suite, and measurably so — a run stopped here reports NO tally, so nothing in
5027
+ the result says which test or request hung. The run has to be sent again in the
5028
+ background (off this budget, its output written to a log that can be read
5029
+ mid-run) or, when a consumer knows the runner's per-request limit, with each
5030
+ request bounded. One Hurl run lost 4.8 minutes to a single unanswered request
5031
+ held by hurl's 300 s default per request, ten seconds past this tool's budget.
4985
5032
 
4986
5033
  ```typescript
4987
5034
  const SUITE_OVER_BUDGET_ADVICE: string
@@ -5048,7 +5095,7 @@ const MAX_TRACE_NOTE_REQUESTS: 4
5048
5095
 
5049
5096
  How many times ONE test may send the same method+path before the note calls it a render loop.
5050
5097
 
5051
- xr-molecule-flash-m215 (+27:27 → +29:42): an Editor effect with `[seeded, slug, t]` in its
5098
+ An Editor effect with `[seeded, slug, t]` in its
5052
5099
  dependency list re-fetched `GET /api/articles/<slug>` 2,106 times in one test. The trace reader
5053
5100
  caps and de-duplicates its request list, so the note printed four identical `→ 200` lines and
5054
5101
  the run patched the component's seeding, rebuilt and re-ran before unzipping the trace by hand.
@@ -5112,8 +5159,8 @@ reporter still prints each failure exactly once.
5112
5159
  Every background command is given this (see {@link streamingBackgroundCommand}), so a suite the
5113
5160
  executor starts through its own wrapper is covered too — the wrapper passes the environment on
5114
5161
  to the Playwright process it spawns. Without it the log's only failure lines are `✘` rows:
5115
- X1 xr-molecule-flash-m99 (+19:27 → +21:00, 2026-10-16) was told to `grep -n -A 20 '<test name>'`
5116
- the log, got nothing back through four greps, inferred causes from the spec prose instead, and
5162
+ A run told to `grep -n -A 20 '<test name>'` the log got nothing back through four greps,
5163
+ inferred causes from the spec prose instead, and
5117
5164
  edited `app/src` while the run was still walking — which voids the run.
5118
5165
 
5119
5166
  ```typescript
@@ -5198,9 +5245,8 @@ place, keeping ~30 KB of each end. A batched read that crossed it lost its
5198
5245
  MIDDLE — the cut lands between two `"content"` values, so whole files fell
5199
5246
  out and the note in their place said only "N characters cut here" — while
5200
5247
  this tool's own note had promised each of those files that it "fits in one
5201
- call, so it is not paged": X0 flash-m81 (2026-10-16) read ten e2e specs in
5202
- one call (121,467 chars), lost the middle six, and bought them again in six
5203
- further calls (52,908 chars).
5248
+ call, so it is not paged": one batched read of ten e2e specs (121,467 chars) lost the
5249
+ middle six and bought them again in six further calls (52,908 chars).
5204
5250
 
5205
5251
  So the CALL gets the ceiling the request gives it. Whole files are returned
5206
5252
  up to it; the paths that did not fit are named in `note` and listed in
@@ -5247,7 +5293,7 @@ const MAX_READ_RETURN_CHARS: number
5247
5293
 
5248
5294
  A file this small is returned whole on a second window of it (paging it costs a call each).
5249
5295
  The same bound as {@link MAX_READ_RETURN_CHARS}: the windowed-read note promises that a
5250
- file under it "fits in ONE call", and a smaller bound here broke that promise (X1 flash-m67).
5296
+ file under it "fits in ONE call", and a smaller bound here breaks that promise.
5251
5297
 
5252
5298
  ```typescript
5253
5299
  const SMALL_FILE_WHOLE_CHARS: number
@@ -5262,11 +5308,11 @@ an HTML read is almost never worth it.
5262
5308
  An entry document is boilerplate the reader rarely needs in full: meta tags,
5263
5309
  stylesheet and preload links, a `<style>` block, and a handful of `<script>`
5264
5310
  tags. The parts an executor acts on — the body's structure, where a script is
5265
- loaded — are all visible in an outline of one line per tag. X0 flash-m77 paid
5266
- 63,735 chars for one such read: ~60 KB of it was the IDE's own preview bridges,
5311
+ loaded — are all visible in an outline of one line per tag. One such read paid
5312
+ 63,735 chars: ~60 KB of it was the IDE's own preview bridges,
5267
5313
  and the read pushed the transcript past its context cap, so the e2e specs the
5268
5314
  executor had just read were trimmed to summaries and it read the whole suite
5269
- again — twice (findings, +01:23 and +02:56). The scaffold now keeps those
5315
+ again — twice. The scaffold now keeps those
5270
5316
  bridges in separate files, but a template's own head is still ~5-12 KB, and a
5271
5317
  static-site or SSR entry can be far more.
5272
5318
 
@@ -5396,8 +5442,8 @@ const TOOL_RESULT_CHARS: 8000
5396
5442
 
5397
5443
  #### `FAILURE_CAUSES_CHARS`
5398
5444
 
5399
- The characters a finished run's cause list may use of {@link TOOL_RESULT_CHARS}. The recap
5400
- measured by xr-molecule-flash-m102 (+12:43) was `12 failures, 8 causes`: one cause line is
5445
+ The characters a finished run's cause list may use of {@link TOOL_RESULT_CHARS}. A measured
5446
+ recap was `12 failures, 8 causes`: one cause line is
5401
5447
  ~200 chars and ~80 more with its two body lines, so 8 causes is ~2.3 k against the 8 k cap —
5402
5448
  the old 5-cause cap withheld 3 causes that the same result had room for.
5403
5449
 
@@ -5447,7 +5493,7 @@ How many tests a run must have walked — with nothing passing since its first f
5447
5493
  THREE, and the number is the cost of the alternative. The old floor of 15 was chosen when the
5448
5494
  reading was only offered at a completed run; once it STOPS the walk, every test waited for is
5449
5495
  a test whose result is thrown away, and a blank page costs its per-test budget each time
5450
- (m177: 18 tests, ~4.2 minutes, on a page whose thrown error was visible in the first
5496
+ (18 tests, ~4.2 minutes, on a page whose thrown error was visible in the first
5451
5497
  `pageerror`). Three is the smallest count that is not one page's own bug: the cause additionally
5452
5498
  needs three DISTINCT spec files (`UNIVERSAL_CAUSE_FILES`, or the files a narrowed run selected),
5453
5499
  no failure showing a locator RESOLVING ({@link ELEMENT_FOUND} — a blank page cannot resolve
@@ -5509,7 +5555,7 @@ Peer dependencies:
5509
5555
  ceiling the request side puts on a single tool result: whole files are
5510
5556
  returned up to it and every path past that is named in `note` and listed as
5511
5557
  `not returned`, so a file is never handed back in part — the shape that lost
5512
- the middle of a ten-file batch to the request-side cut (X0 flash-m81). Each
5558
+ the middle of a ten-file batch to the request-side cut. Each
5513
5559
  entry carries its own content or its own error, so one bad path never fails
5514
5560
  the batch.
5515
5561
  - **`edit_file` shows the result, so the model need not re-read.** A
@@ -5535,7 +5581,7 @@ Peer dependencies:
5535
5581
  added or removed and nothing else, the edit can only move text across lines —
5536
5582
  joining the next line onto the replaced text, or pushing the rest of the line
5537
5583
  down — which is what a weak model does by accident when it repeats a line it
5538
- means to keep (flash-m28, m55, m62, m89, five times in the m89 run alone). The
5584
+ means to keep. The
5539
5585
  replacement is skipped, the rest of the batch is applied, and the result
5540
5586
  carries `skippedNote`: one line naming the replacement, what applying it would
5541
5587
  have done, and how to say it on purpose (include the next line in `old_string`).