@molecule/api-ai-tools 1.14.3 → 1.14.5
This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
- package/README.md +243 -189
- package/dist/browser-probe.d.ts +4 -4
- package/dist/browser-probe.d.ts.map +1 -1
- package/dist/browser-probe.js +5 -5
- package/dist/command-position.d.ts +15 -16
- package/dist/command-position.d.ts.map +1 -1
- package/dist/command-position.js +21 -23
- package/dist/cut-run.d.ts +9 -9
- package/dist/cut-run.js +6 -6
- package/dist/failure-kind.d.ts +6 -6
- package/dist/failure-kind.js +6 -6
- package/dist/index.d.ts +2 -2
- package/dist/index.js +2 -2
- package/dist/inline-script.d.ts +5 -5
- package/dist/inline-script.js +6 -6
- package/dist/line-diff.d.ts +2 -3
- package/dist/line-diff.d.ts.map +1 -1
- package/dist/line-diff.js +2 -3
- package/dist/no-test-run.d.ts +5 -5
- package/dist/no-test-run.d.ts.map +1 -1
- package/dist/no-test-run.js +9 -8
- package/dist/output-filter.d.ts +2 -2
- package/dist/output-filter.js +2 -2
- package/dist/pipeline-exit-note.d.ts +1 -1
- package/dist/pipeline-exit-note.js +1 -1
- package/dist/playwright-report.d.ts +1 -1
- package/dist/playwright-report.js +1 -1
- package/dist/server-command.d.ts +2 -2
- package/dist/server-command.js +2 -2
- package/dist/sleep-peek.d.ts +1 -1
- package/dist/sleep-peek.js +1 -1
- package/dist/suite-overlap.d.ts +24 -25
- package/dist/suite-overlap.d.ts.map +1 -1
- package/dist/suite-overlap.js +41 -43
- package/dist/tools.d.ts +26 -28
- package/dist/tools.d.ts.map +1 -1
- package/dist/tools.js +114 -72
- package/dist/trace-artifacts.d.ts +73 -65
- package/dist/trace-artifacts.d.ts.map +1 -1
- package/dist/trace-artifacts.js +76 -77
- package/dist/types.d.ts +5 -5
- package/dist/utilities.d.ts +128 -92
- package/dist/utilities.d.ts.map +1 -1
- package/dist/utilities.js +298 -143
- 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-
|
|
6
|
+
Generated: 2026-10-25T20:03:24.838Z
|
|
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
|
|
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
|
|
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
|
|
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
|
|
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
|
|
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
|
|
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 (
|
|
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
|
|
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
|
-
*
|
|
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
|
|
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 (
|
|
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 (
|
|
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
|
-
(
|
|
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.
|
|
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 (
|
|
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.
|
|
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 (
|
|
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:
|
|
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
|
|
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
|
-
|
|
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 —
|
|
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
|
|
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
|
|
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
|
|
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 (
|
|
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
|
|
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
|
-
* (
|
|
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 (
|
|
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.
|
|
1091
|
-
|
|
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 (
|
|
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" (
|
|
1361
|
-
*
|
|
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 (
|
|
1376
|
-
*
|
|
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
|
|
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
|
|
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
|
-
* (
|
|
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:
|
|
1637
|
-
*
|
|
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
|
|
1919
|
-
|
|
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
|
|
1958
|
-
model off the platform's runner shape
|
|
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
|
-
(
|
|
1990
|
-
|
|
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:
|
|
2045
|
-
|
|
2046
|
-
|
|
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
|
-
|
|
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
|
|
@@ -2407,7 +2408,7 @@ A runner counts only where a shell would RUN it ({@link commandSegments}): the w
|
|
|
2407
2408
|
position of a segment, after its wrapper prefixes. A runner named in an argument is not an
|
|
2408
2409
|
invocation — `head -30 run-api-tests-hurl.sh` and `grep -n playwright e2e/README.md` name a
|
|
2409
2410
|
file to read, and a `--list` written inside a file the command writes is not a flag anyone runs
|
|
2410
|
-
with
|
|
2411
|
+
with.
|
|
2411
2412
|
|
|
2412
2413
|
A command that invokes no runner is NOT one of these (false): "the command runs no test" is
|
|
2413
2414
|
then true for `ls`, which is not the question any caller is asking. The question is whether
|
|
@@ -2449,7 +2450,7 @@ function outputFilterAfterRunner(
|
|
|
2449
2450
|
|
|
2450
2451
|
- `command` — The command as the executor sent it.
|
|
2451
2452
|
- `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 (
|
|
2453
|
+
- `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
2454
|
|
|
2454
2455
|
**Returns:** The filter and the unfiltered command, or null.
|
|
2455
2456
|
|
|
@@ -2725,7 +2726,7 @@ it already names one, or starts no Playwright run.
|
|
|
2725
2726
|
The flag rides the same statement the runner does: a `cd`, an env prefix and a `timeout` before
|
|
2726
2727
|
it are left exactly as they were, and so is everything chained after the run (`| tail -50`).
|
|
2727
2728
|
|
|
2728
|
-
|
|
2729
|
+
A fix-round re-run dropped the
|
|
2729
2730
|
`--config playwright.conduit.config.ts` both earlier runs had carried, so Playwright started with
|
|
2730
2731
|
NO base URL and all 10 failures were `page.goto: Cannot navigate to invalid URL` — a failure list
|
|
2731
2732
|
that says nothing about the app. The platform composes commands back to the executor too (the
|
|
@@ -2746,21 +2747,21 @@ function withSuiteConfig(command: string, config: string | null | undefined): st
|
|
|
2746
2747
|
The whole-suite command made scoped to the tests it should re-run instead: the same
|
|
2747
2748
|
invocation — same launcher, same settings — with the named `file:line`s in place of every
|
|
2748
2749
|
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
|
|
2750
|
+
`--last-failed` dropped (it re-runs the tests that never ran too) and
|
|
2750
2751
|
`--retries=0` set (a re-run of a known failure does not need to pay for retries) — except the
|
|
2751
2752
|
re-run of a run against a DEPLOYED URL, which keeps the suite's own retries and tracing
|
|
2752
2753
|
(`options.suiteSettings`).
|
|
2753
2754
|
|
|
2754
2755
|
The re-run keeps the run's `> <file>` redirect only in the sense of keeping its OUTPUT there:
|
|
2755
2756
|
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
|
|
2757
|
-
and the setup around the run keeps its own file writes untouched
|
|
2757
|
+
re-run never overwrites the log the run itself is the evidence for —
|
|
2758
|
+
and the setup around the run keeps its own file writes untouched. A
|
|
2758
2759
|
`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
|
|
2760
|
+
sibling instead, so the re-run displays the run it performed.
|
|
2760
2761
|
|
|
2761
2762
|
`config` is the config the run was measured under ({@link withSuiteConfig}): the narrowed re-run
|
|
2762
2763
|
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 (
|
|
2764
|
+
handed back a command with the same defect (every failing test was
|
|
2764
2765
|
`Cannot navigate to invalid URL` because the re-run loaded no base URL).
|
|
2765
2766
|
|
|
2766
2767
|
```typescript
|
|
@@ -2777,23 +2778,23 @@ function scopedRerunCommand(
|
|
|
2777
2778
|
|
|
2778
2779
|
- `command` — The whole-suite run's command.
|
|
2779
2780
|
- `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 —
|
|
2781
|
+
- `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
2782
|
- `config` — The config the run loaded, when the caller knows it; added when the command does not name one.
|
|
2782
2783
|
- `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
|
|
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
|
|
2784
|
+
- `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.
|
|
2785
|
+
- `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
2786
|
|
|
2786
2787
|
**Returns:** The scoped command, or the command unchanged when it runs no Playwright suite.
|
|
2787
2788
|
|
|
2788
2789
|
#### `withRunEnv(command, settings)`
|
|
2789
2790
|
|
|
2790
2791
|
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
|
|
2792
|
+
place every composed re-run gets them.
|
|
2792
2793
|
|
|
2793
2794
|
The settings are written at the statement's own assignment offset, never in front of the whole
|
|
2794
2795
|
command: a shell binds an assignment there to the statement's program, while one in front of the
|
|
2795
2796
|
whole command is the environment of its FIRST statement alone (`APP_BASE=… cd app && npx
|
|
2796
|
-
playwright test` sets the variable for `cd
|
|
2797
|
+
playwright test` sets the variable for `cd`). A name the command
|
|
2797
2798
|
gives a different value is replaced, and one it already gives the required value is left as
|
|
2798
2799
|
written. When the parse cannot place the statement (a run inside a nested `sh -c '…'`), the
|
|
2799
2800
|
settings become `export`s, which no statement boundary can swallow.
|
|
@@ -2850,10 +2851,10 @@ disagree:
|
|
|
2850
2851
|
({@link ./utilities.js} `streamingBackgroundCommand`) — a diagnosis walks each failure once,
|
|
2851
2852
|
while the run the suite is judged by keeps the suite's own retries; and
|
|
2852
2853
|
- 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 —
|
|
2854
|
-
|
|
2854
|
+
executor to drop the `--retries=0` the platform itself has just added — a contradiction
|
|
2855
|
+
filed three times.
|
|
2855
2856
|
|
|
2856
|
-
Until
|
|
2857
|
+
Until then they were a regex and a predicate that only LOOKED alike, and the
|
|
2857
2858
|
gap was exactly the run the platform had asked for: its `testRunNote` says "run the whole suite
|
|
2858
2859
|
once with `--max-failures=0`", and the rewriter read that cap flag as a capped diagnosis and
|
|
2859
2860
|
stripped the suite's retries from the uncapped proof run that follows a deploy — the one run the
|
|
@@ -2936,11 +2937,10 @@ The command that stops a running background task, read from the sandbox's own pi
|
|
|
2936
2937
|
|
|
2937
2938
|
THE one builder for it, so every note that hands the executor a way to stop a run hands over the
|
|
2938
2939
|
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 —
|
|
2940
|
-
|
|
2941
|
-
|
|
2942
|
-
|
|
2943
|
-
process under it.
|
|
2940
|
+
command), and `molecule-dev/api/src/ai/pattern-kill-guard.ts` holds exactly that — a stuck note
|
|
2941
|
+
that suggested `kill $(cat /tmp/<id>.pid) 2>/dev/null; pkill -f <id>.sh` was refused by the
|
|
2942
|
+
platform's own guard, and the same shape costs a refused call every time. The pid tree is the
|
|
2943
|
+
whole of what the pattern was for: the detached shell and every process under it.
|
|
2944
2944
|
|
|
2945
2945
|
```typescript
|
|
2946
2946
|
function taskStopCommand(backend: ExecutionBackend, taskId: string): Promise<string>
|
|
@@ -2956,8 +2956,8 @@ function taskStopCommand(backend: ExecutionBackend, taskId: string): Promise<str
|
|
|
2956
2956
|
The steer attached to a SUCCESSFUL read of a package's built output. The ENOENT
|
|
2957
2957
|
redirect below fires only when the read FAILS, so a model that knows the hoisted
|
|
2958
2958
|
layout reads `node_modules/@molecule/<pkg>/dist/*.js` happily and never learns the
|
|
2959
|
-
documented API is one call away (
|
|
2960
|
-
|
|
2959
|
+
documented API is one call away (24 such reads in 57 s, with no note on any of
|
|
2960
|
+
them). Carried as `distNote` rather than merged into `note` so a host that
|
|
2961
2961
|
has read_molecule_doc (molecule-dev's cadence note, which also names the functions)
|
|
2962
2962
|
can supersede it without string-matching.
|
|
2963
2963
|
|
|
@@ -2979,7 +2979,7 @@ The task id is the ownership: it is the handle `wait_for_task` returned, `/tmp/$
|
|
|
2979
2979
|
the log this platform's launcher writes for it, and the redirect target is the file this
|
|
2980
2980
|
process's own launch registered for that id — never a path parsed out of a command by the
|
|
2981
2981
|
caller. A diagnosis that reads a running walk must not build a `/tmp` path of its own
|
|
2982
|
-
(
|
|
2982
|
+
(a wait's DISPLAY gets diagnosed as if it were the log).
|
|
2983
2983
|
|
|
2984
2984
|
```typescript
|
|
2985
2985
|
function registeredTaskLogCommand(taskId: string): string | null
|
|
@@ -3012,17 +3012,17 @@ when the path is not under `node_modules` or nothing is installed there.
|
|
|
3012
3012
|
|
|
3013
3013
|
`node_modules` is not the project's code: nothing written there survives the
|
|
3014
3014
|
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.
|
|
3016
|
-
|
|
3017
|
-
`node_modules/@molecule/api-resource-comment/dist/numbers.d.ts
|
|
3018
|
-
the package's declarations
|
|
3015
|
+
shared (the pre-installed superset) breaks every other run through it. A
|
|
3016
|
+
`write_file` on
|
|
3017
|
+
`node_modules/@molecule/api-resource-comment/dist/numbers.d.ts`, made while
|
|
3018
|
+
reading the package's declarations, clobbered its runtime module a call later
|
|
3019
3019
|
(`module.exports = {}` over the ESM handler its own code imports) — the write
|
|
3020
3020
|
answered `ok: true`, and 18 s went to noticing, `npm pack`-ing the package and
|
|
3021
3021
|
putting the file back. Reading these files stays allowed (that is how the
|
|
3022
3022
|
declarations above are read at all).
|
|
3023
3023
|
|
|
3024
3024
|
What is protected is the INSTALL, not the spelling: the decision comes from
|
|
3025
|
-
{@link InstalledPackageFacts}, never from the path alone (
|
|
3025
|
+
{@link InstalledPackageFacts}, never from the path alone (see the symlink case above). Three
|
|
3026
3026
|
things are the run's own to remove or replace —
|
|
3027
3027
|
|
|
3028
3028
|
- a `node_modules` that is a SYMLINK: `rm`/`unlink` removes the link, never the
|
|
@@ -3032,6 +3032,7 @@ things are the run's own to remove or replace —
|
|
|
3032
3032
|
|
|
3033
3033
|
A path INSIDE the link is still decided by what resolves there: a link into a
|
|
3034
3034
|
real tree is refused, because removing or writing through it reaches the
|
|
3035
|
+
install.
|
|
3035
3036
|
|
|
3036
3037
|
_(description truncated — read the full text in `node_modules/@molecule/api-ai-tools/dist/tools.d.ts`.)_
|
|
3037
3038
|
|
|
@@ -3125,7 +3126,7 @@ function isStaticAssetRequest(request: TraceRequest): boolean
|
|
|
3125
3126
|
Whether a trace recorded a failed response or a request error other than cancellation.
|
|
3126
3127
|
|
|
3127
3128
|
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
|
|
3129
|
+
them, and naming one as a failure sent a run into writing the caching worker it had asked about.
|
|
3129
3130
|
A 5xx on an asset, or a network error, still counts. A request error alone does not locate
|
|
3130
3131
|
the cause in the server: the browser or network may have rejected the request.
|
|
3131
3132
|
|
|
@@ -3141,7 +3142,7 @@ function failedRequest(request: TraceRequest): boolean
|
|
|
3141
3142
|
|
|
3142
3143
|
Whether a trace recorded no response and no error other than cancellation. The request may
|
|
3143
3144
|
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
|
|
3145
|
+
the endpoint stalled. A shell request is not evidence about the step.
|
|
3145
3146
|
|
|
3146
3147
|
```typescript
|
|
3147
3148
|
function unansweredRequest(request: TraceRequest): boolean
|
|
@@ -3158,12 +3159,12 @@ other asset the page itself loads, with no response and no error text — still
|
|
|
3158
3159
|
the navigation timed out.
|
|
3159
3160
|
|
|
3160
3161
|
The page shell's own incidental requests (`/sw.js`, the manifest, a favicon, a font) are
|
|
3161
|
-
excepted for the reason {@link isStaticAssetRequest} documents:
|
|
3162
|
-
|
|
3163
|
-
|
|
3164
|
-
|
|
3165
|
-
|
|
3166
|
-
|
|
3162
|
+
excepted for the reason {@link isStaticAssetRequest} documents: an aborted `/sw.js` once sent a
|
|
3163
|
+
run to write a caching service worker. A pending `/assets/*.css` is different — the navigation
|
|
3164
|
+
blocks on it, so it is the reason `page.goto` ran out of time rather than one of the app's API
|
|
3165
|
+
calls (three deployed `page.goto` timeouts on tests that pass locally, one 88 KB stylesheet
|
|
3166
|
+
fetch measured at 27 s, and the failing tests' traces each holding the never-answered CSS while
|
|
3167
|
+
the note said "the cause is in the page").
|
|
3167
3168
|
|
|
3168
3169
|
```typescript
|
|
3169
3170
|
function stalledDocumentSubresource(request: TraceRequest): boolean
|
|
@@ -3181,7 +3182,7 @@ endpoint — as opposed to a protected resource that presents one.
|
|
|
3181
3182
|
This is the path half of {@link isCredentialExchange}, exported so a caller holding only a
|
|
3182
3183
|
`METHOD path` reads the same classification: a Hurl failing entry says
|
|
3183
3184
|
`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
|
|
3185
|
+
a wrong-password login that answered 200 as a cookie-jar effect.
|
|
3185
3186
|
|
|
3186
3187
|
```typescript
|
|
3187
3188
|
function isCredentialExchangePath(path: string, authEndpoints?: readonly string[]): boolean
|
|
@@ -3197,7 +3198,7 @@ function isCredentialExchangePath(path: string, authEndpoints?: readonly string[
|
|
|
3197
3198
|
The sentence a "hidden" visibility failure earns when the trace proved WHY the box is empty.
|
|
3198
3199
|
|
|
3199
3200
|
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`
|
|
3201
|
+
is in the element's children. An `a.navbar-brand` was 0×4 px because its
|
|
3201
3202
|
only child was `<img src="/conduit-logo.svg" height="26">`: an SVG with a `viewBox` and no
|
|
3202
3203
|
width/height has no intrinsic size, and the `height` attribute loses to Tailwind's preflight
|
|
3203
3204
|
(`img { max-width: 100%; height: auto }`), which the scaffold's own `index.css` imports. The
|
|
@@ -3217,7 +3218,7 @@ function hiddenBoxNote(items: readonly TraceArtifact[]): string | null
|
|
|
3217
3218
|
The row's sentence for a failing count assertion: the locator, both numbers, and the elements
|
|
3218
3219
|
the failure snapshot held.
|
|
3219
3220
|
|
|
3220
|
-
|
|
3221
|
+
A `comments.spec.ts:86` row printed only `Expected: 3 / Received: 4`. The
|
|
3221
3222
|
helper counted `.card:not(.comment-form) .card-block`, and the app's comment form was a
|
|
3222
3223
|
`.comment-form` wrapper around a plain `.card`, so the form's own `.card-block` was the fourth
|
|
3223
3224
|
match. The trace held the selector and the four elements; the note held neither.
|
|
@@ -3258,14 +3259,15 @@ The three kinds are kept apart, because they mean different things. A FAILED req
|
|
|
3258
3259
|
a network error with Playwright's own text) is a cause. A request with NO RESPONSE RECORDED —
|
|
3259
3260
|
Playwright's `-1`, no error text — was still in flight when the test ended (the page closed under
|
|
3260
3261
|
it); listing it as a failure sent a run hunting an API that never answered anything wrong
|
|
3261
|
-
|
|
3262
|
+
The rest are the page's last answered requests.
|
|
3262
3263
|
|
|
3263
3264
|
A 4xx request carries what the page SENT beside its status, so a wrapped body is visible in one
|
|
3264
3265
|
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
|
|
3266
|
+
is `data`, the note names the call shape that produces it.
|
|
3266
3267
|
|
|
3267
3268
|
Every row opens with the test's LAST user action before the failing assertion and the requests
|
|
3268
3269
|
that action caused ({@link TraceArtifact.lastAction}) — started after it, before the assertion,
|
|
3270
|
+
the app's own API calls first, each with its status and the first 200 characters of its response,
|
|
3269
3271
|
|
|
3270
3272
|
_(description truncated — read the full text in `node_modules/@molecule/api-ai-tools/dist/trace-artifacts.d.ts`.)_
|
|
3271
3273
|
|
|
@@ -3293,7 +3295,7 @@ Whether a Playwright config records traces for the tests that fail.
|
|
|
3293
3295
|
|
|
3294
3296
|
Only `on` and `retain-on-failure` keep a `trace.zip` for a failure whatever the retries do: the
|
|
3295
3297
|
two retry modes need a retry to happen at all, and a diagnosis run is given `--retries=0`
|
|
3296
|
-
(`streamingBackgroundCommand`), so
|
|
3298
|
+
(`streamingBackgroundCommand`), so a run's own
|
|
3297
3299
|
`trace: 'on-first-retry'` recorded nothing — which is what left the failing tests' network log
|
|
3298
3300
|
unreadable. A config that sets no `trace:` at all records nothing either (Playwright's default
|
|
3299
3301
|
is off); so does one that cannot be read.
|
|
@@ -3306,6 +3308,20 @@ function suiteRecordsTraces(configText: string): boolean
|
|
|
3306
3308
|
|
|
3307
3309
|
**Returns:** True when the config records traces for failures.
|
|
3308
3310
|
|
|
3311
|
+
#### `namesNoRetries(command)`
|
|
3312
|
+
|
|
3313
|
+
Whether the run itself pins `--retries=0` (either spelling): a run that cannot retry records no
|
|
3314
|
+
retry trace, so it still needs one recorded for it. A running wait reads the same proof to know
|
|
3315
|
+
a first failure's body is already final (`wait_for_task`'s diagnostic yield).
|
|
3316
|
+
|
|
3317
|
+
```typescript
|
|
3318
|
+
function namesNoRetries(command: string): boolean
|
|
3319
|
+
```
|
|
3320
|
+
|
|
3321
|
+
- `command` — The shell command.
|
|
3322
|
+
|
|
3323
|
+
**Returns:** True when the run allows no retry.
|
|
3324
|
+
|
|
3309
3325
|
#### `diagnosisTraceCommand(args)`
|
|
3310
3326
|
|
|
3311
3327
|
The command a Playwright run needs to leave a readable trace behind, when the suite's config
|
|
@@ -3318,14 +3334,15 @@ decide its own `--trace`, and whose config keeps no trace for its failures.
|
|
|
3318
3334
|
|
|
3319
3335
|
A run that can serve as PROOF is the exception: the graded measurement is the suite's own
|
|
3320
3336
|
settings, so it keeps its own tracing and retries. That was measured, not assumed — on one
|
|
3321
|
-
sandbox
|
|
3337
|
+
sandbox the same build ran a three-test deployed
|
|
3322
3338
|
subset 3/3 timed out under this flag (17.6–17.9 s against a 15 s per-test budget) and the whole
|
|
3323
3339
|
file passed 14/14 without it (10.9–12.1 s). `retain-on-failure` RETAINS only a failing test's
|
|
3324
3340
|
trace (Playwright's `_shouldAbandonTrace` unlinks a passing test's), but it RECORDS every
|
|
3325
3341
|
action of every test, and for a test near its per-test budget that recording is the difference
|
|
3326
|
-
between passing and timing out.
|
|
3342
|
+
between passing and timing out. This flag was added for exactly that failure: its
|
|
3327
3343
|
deployed proof run left only an `error-context.md` because the suite traces
|
|
3328
3344
|
`on-first-retry` and the run had no retries. That need is met without the flag — the graded
|
|
3345
|
+
deployed run keeps the suite's own retries, so a failing test leaves its retry's trace — and
|
|
3329
3346
|
|
|
3330
3347
|
_(description truncated — read the full text in `node_modules/@molecule/api-ai-tools/dist/trace-artifacts.d.ts`.)_
|
|
3331
3348
|
|
|
@@ -3529,7 +3546,7 @@ function outputIsWithheldUntilExit(command: string): boolean
|
|
|
3529
3546
|
The file a command sends its own output to, when it redirects it (`> out.txt`,
|
|
3530
3547
|
`>> log`, `&> run.log`, `| tee [-a] file`), or null. A background command that does
|
|
3531
3548
|
this leaves its task log empty, so the log is the wrong place to look and an empty
|
|
3532
|
-
log proves nothing
|
|
3549
|
+
log proves nothing.
|
|
3533
3550
|
|
|
3534
3551
|
Which redirect counts is decided by the command's own shell structure, from the same
|
|
3535
3552
|
parse every other command reader uses: a redirect written in a BACKGROUNDED statement
|
|
@@ -3537,7 +3554,7 @@ parse every other command reader uses: a redirect written in a BACKGROUNDED stat
|
|
|
3537
3554
|
the command's. The platform's own preview launch is exactly that — the preview server is
|
|
3538
3555
|
started with `>/tmp/mol-preview-4173.log 2>&1 &` inside the build/serve prelude, and the
|
|
3539
3556
|
suite's foreground command follows it — so a reader that took the last `>` in the whole
|
|
3540
|
-
text
|
|
3557
|
+
text tells a run its output went to the PREVIEW's log.
|
|
3541
3558
|
|
|
3542
3559
|
The target comes back without its shell quotes: `> '/tmp/x.log'` is `/tmp/x.log`, and
|
|
3543
3560
|
the callers resolve a relative one against the command's cwd.
|
|
@@ -3555,7 +3572,7 @@ function outputRedirectTarget(command: string): string | null
|
|
|
3555
3572
|
Rewrite a command about to run in the background so its log grows while it
|
|
3556
3573
|
runs. Two shapes left the log empty until exit, and an empty log is what
|
|
3557
3574
|
`wait_for_task` reads as "stuck", so working suites were reported stuck and
|
|
3558
|
-
killed (
|
|
3575
|
+
killed (one run lost 20 of its 60 minutes this way):
|
|
3559
3576
|
|
|
3560
3577
|
- a trailing `| tail -N`, which holds everything back until the command ends.
|
|
3561
3578
|
It is dropped: `wait_for_task` already returns the end of the log.
|
|
@@ -3563,7 +3580,7 @@ killed (X1 run flash-m15 lost 20 of its 60 minutes this way, 2026-10-15):
|
|
|
3563
3580
|
failing test's own error and leaves the pipeline's exit status — the filter's — as the run's.
|
|
3564
3581
|
Every such stage is dropped from EVERY suite run in the command, not only the last
|
|
3565
3582
|
({@link stripTrailingSuiteFilters}); `wait_for_task` already returns the end of the full log,
|
|
3566
|
-
and a run whose tally shows a failure must never report 0
|
|
3583
|
+
and a run whose tally shows a failure must never report 0.
|
|
3567
3584
|
- `playwright test` with no `--reporter`, which runs the config's reporter —
|
|
3568
3585
|
often `html`, which prints nothing per test. `--reporter=list` is added
|
|
3569
3586
|
when the playwright run is the command's last step, piped or not: it writes each result as
|
|
@@ -3584,7 +3601,7 @@ function streamingBackgroundCommand(
|
|
|
3584
3601
|
```
|
|
3585
3602
|
|
|
3586
3603
|
- `command` — The command as the executor sent it.
|
|
3587
|
-
- `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
|
|
3604
|
+
- `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.
|
|
3588
3605
|
- `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.
|
|
3589
3606
|
|
|
3590
3607
|
**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.
|
|
@@ -3656,7 +3673,7 @@ function isSuiteRunCommand(command: string): boolean
|
|
|
3656
3673
|
Refuse only a command made entirely of identical suite invocations.
|
|
3657
3674
|
|
|
3658
3675
|
Mixed shell commands execute as written. Rebuilding their prefix or suffix can lose writes,
|
|
3659
|
-
break heredoc delimiters or turn an && guard into unconditional work
|
|
3676
|
+
break heredoc delimiters or turn an && guard into unconditional work. Different args
|
|
3660
3677
|
or environments may select different suites or targets; they are not known duplicates either.
|
|
3661
3678
|
This is an optimization, so uncertainty always allows the original command.
|
|
3662
3679
|
|
|
@@ -3674,8 +3691,8 @@ A command with the supplied suite's own settings written back onto its runner as
|
|
|
3674
3691
|
flags, and the flags that could not be placed.
|
|
3675
3692
|
|
|
3676
3693
|
The grader walks the suite under its OWN budget, so a run whose runner config sets a different
|
|
3677
|
-
timeout or worker count measures a run the grader never sees (
|
|
3678
|
-
|
|
3694
|
+
timeout or worker count measures a run the grader never sees (a 60 s wrapper config produced
|
|
3695
|
+
a green local proof the official 15 s grader then failed). Playwright
|
|
3679
3696
|
lets a command-line flag win over every config file, so the suite's values are put on the
|
|
3680
3697
|
runner's own arguments — written where {@link statementArgumentEnd} places them, never after a
|
|
3681
3698
|
pipe, redirect or group closer. Only the command's LAST suite step is touched: that is the run
|
|
@@ -3733,7 +3750,7 @@ bound that was lifted.
|
|
|
3733
3750
|
Used where the platform moves a run to the background: the executor wrote the bound to fit this
|
|
3734
3751
|
tool's foreground ceiling, and in the background that ceiling no longer applies — the task is
|
|
3735
3752
|
bounded by `wait_for_task` and the turn's deadline — so the prefix only kills the walk
|
|
3736
|
-
({@link withoutTimeoutWrapper}
|
|
3753
|
+
({@link withoutTimeoutWrapper}).
|
|
3737
3754
|
|
|
3738
3755
|
```typescript
|
|
3739
3756
|
function withoutSuiteTimeout(command: string): { command: string; seconds: number | null }
|
|
@@ -3749,7 +3766,7 @@ Whether a command starts a Playwright run — a `playwright test` in command pos
|
|
|
3749
3766
|
that runs something.
|
|
3750
3767
|
|
|
3751
3768
|
`npx playwright test --list` matched every `\bplaywright\s+test\b` test in the platform and was
|
|
3752
|
-
then treated as a run: held (
|
|
3769
|
+
then treated as a run: held (a config check), backgrounded for a run that outlasts
|
|
3753
3770
|
the tool's ceiling, and rewritten with `--reporter`. A list takes two seconds, prints its lines
|
|
3754
3771
|
and exits, so it is none of those; {@link commandRunsNoTests} is what decides.
|
|
3755
3772
|
|
|
@@ -3785,8 +3802,8 @@ Where the suite runner's exit code comes from: the runner itself, or a stage pip
|
|
|
3785
3802
|
code a finished run reports is its LAST pipeline stage's, so a stage after the runner makes the
|
|
3786
3803
|
code the stage's — but only when such a stage EXISTS. The platform used to report "piped" for
|
|
3787
3804
|
any run whose statements it could not place in the text, which one heredoc body was enough to
|
|
3788
|
-
cause:
|
|
3789
|
-
|
|
3805
|
+
cause: a config written in the same `exec_command` made the run come back with no exit code
|
|
3806
|
+
at all, and the note under it claimed a stage after the
|
|
3790
3807
|
runner that was not there. The parse now places every statement (`locatedCommandSegments`), so
|
|
3791
3808
|
"unplaced" is the rare, named case rather than a guess dressed as an answer.
|
|
3792
3809
|
|
|
@@ -3818,10 +3835,9 @@ Start a background suite run at lower CPU and IO priority, so the sandbox it
|
|
|
3818
3835
|
shares with everything else stays responsive to what the executor does next.
|
|
3819
3836
|
|
|
3820
3837
|
A whole-suite Playwright run saturates the one container the app's Vite
|
|
3821
|
-
server, its API process and every other command also live in:
|
|
3822
|
-
the
|
|
3823
|
-
|
|
3824
|
-
measured on the chat payload and on the live-stream follower independently.
|
|
3838
|
+
server, its API process and every other command also live in: a backgrounded 139-test run
|
|
3839
|
+
has left the two-word shell command sent next — tick its plan file — returning nothing for
|
|
3840
|
+
2 min 40 s, measured on the chat payload and on the live-stream follower independently.
|
|
3825
3841
|
The backgrounding note is right that the executor should go do other work;
|
|
3826
3842
|
what it cannot promise is that the sandbox will let it.
|
|
3827
3843
|
|
|
@@ -3852,8 +3868,8 @@ Check if a command is blocked for security reasons. Returns error message or nul
|
|
|
3852
3868
|
The first check reads the commands the shell actually RUNS — the statements, a `sh -c`
|
|
3853
3869
|
string's body, and every command substitution ({@link executedCommands}) — so a `|` inside a
|
|
3854
3870
|
quoted grep alternation is data, not a pipeline: `grep -E "USER CALLS|ENV|BUTTON|passed|failed"
|
|
3855
|
-
app.log` prints log lines, and the `ENV` in its pattern
|
|
3856
|
-
|
|
3871
|
+
app.log` prints log lines, and the `ENV` in its pattern starts nothing — a text
|
|
3872
|
+
match would block exactly that call as an environment dump, twice over. What the
|
|
3857
3873
|
shell DOES run stays visible through the same walk: `ls | env`, `bash -c 'env'`,
|
|
3858
3874
|
`echo "$(printenv)"` and a nested `sh -c 'x; env'` are all commands, and so is `env` itself
|
|
3859
3875
|
when nothing follows it.
|
|
@@ -3887,8 +3903,7 @@ Whether a tool path points outside the project root once normalized (an
|
|
|
3887
3903
|
absolute path elsewhere, or a `..` that climbs out). {@link resolvePath}
|
|
3888
3904
|
clamps such a path to the root; a file tool must refuse it instead of
|
|
3889
3905
|
answering about the root — a `list_files /tmp/x` used to return the
|
|
3890
|
-
workspace listing as if it were `/tmp/x
|
|
3891
|
-
2026-10-14).
|
|
3906
|
+
workspace listing as if it were `/tmp/x`.
|
|
3892
3907
|
|
|
3893
3908
|
```typescript
|
|
3894
3909
|
function isOutsideRoot(path: string, projectRoot: string): boolean
|
|
@@ -3899,6 +3914,34 @@ function isOutsideRoot(path: string, projectRoot: string): boolean
|
|
|
3899
3914
|
|
|
3900
3915
|
**Returns:** True when the path leaves the root.
|
|
3901
3916
|
|
|
3917
|
+
#### `commandStartsWithCdInto(command, directory, projectRoot)`
|
|
3918
|
+
|
|
3919
|
+
Whether a command's FIRST statement already changes into `directory`.
|
|
3920
|
+
|
|
3921
|
+
`exec_command` refuses a `cwd` outside the workspace, and that refusal tells
|
|
3922
|
+
the caller to drop `cwd` and start the command with `cd <path> && `. When the
|
|
3923
|
+
command ALREADY starts that way the advice describes what was just sent, so
|
|
3924
|
+
the command runs as written with the backend's working directory at the root
|
|
3925
|
+
instead (`{cwd: "/tmp", command: "cd /tmp && …"}` was refused with "start the command with
|
|
3926
|
+
`cd /tmp && `"; the same command resent with `cwd: "/workspace"` then passes).
|
|
3927
|
+
|
|
3928
|
+
Only the leading statement counts, only when the shell's own parse puts it in
|
|
3929
|
+
the caller's shell — a `( cd … )` group or a `sh -c '…'` runs in its own
|
|
3930
|
+
directory and moves nothing — and only when it ends the way a following
|
|
3931
|
+
command needs (`&&`, `;`, a newline, or nothing after it). `cd … | cat` is a
|
|
3932
|
+
pipeline, so its `cd` runs in a subshell, and `&` backgrounds it: neither
|
|
3933
|
+
leaves the caller's directory changed.
|
|
3934
|
+
|
|
3935
|
+
```typescript
|
|
3936
|
+
function commandStartsWithCdInto(command: string, directory: string, projectRoot: string): boolean
|
|
3937
|
+
```
|
|
3938
|
+
|
|
3939
|
+
- `command` — The shell command as the tool received it.
|
|
3940
|
+
- `directory` — The `cwd` the caller asked for.
|
|
3941
|
+
- `projectRoot` — The project root a relative path is resolved against.
|
|
3942
|
+
|
|
3943
|
+
**Returns:** True when the command's first statement `cd`s into `directory`.
|
|
3944
|
+
|
|
3902
3945
|
#### `isValidGlob(pattern)`
|
|
3903
3946
|
|
|
3904
3947
|
Validate that a glob/include pattern is safe (no shell metacharacters that could
|
|
@@ -3929,8 +3972,8 @@ expanded pattern.
|
|
|
3929
3972
|
Neither search tool expands braces itself: `grep --include` and `find` take
|
|
3930
3973
|
the pattern as a single shell-quoted argument, so no shell ever sees it.
|
|
3931
3974
|
`find_files {pattern:"*.{ts,tsx}"}` and `search_files {include:"*.{ts,tsx}"}`
|
|
3932
|
-
were both refused outright
|
|
3933
|
-
|
|
3975
|
+
were both refused outright, costing a round trip and pushing the agent to a narrower
|
|
3976
|
+
search. The group is expanded here
|
|
3934
3977
|
instead — `search_files` passes one `--include` per alternative and
|
|
3935
3978
|
`find_files` ORs one `-name`/`-path` predicate per alternative.
|
|
3936
3979
|
|
|
@@ -3953,8 +3996,8 @@ The `find` predicate for a `find_files` pattern.
|
|
|
3953
3996
|
|
|
3954
3997
|
`find -name` compares a pattern against a file's BASENAME, so a pattern
|
|
3955
3998
|
containing a slash (`helpers/*`, `e2e/*.spec.ts`, `src` + `**` + `/App.tsx`)
|
|
3956
|
-
can never match and the tool answers `[]` (
|
|
3957
|
-
|
|
3999
|
+
can never match and the tool answers `[]` (twice in one run). Such a pattern is matched
|
|
4000
|
+
with `-path` instead: an fnmatch
|
|
3958
4001
|
glob over the whole printed path, whose `*` crosses `/` — the rule
|
|
3959
4002
|
`.gitignore` uses, and the reason a bare `helpers/*` means "a `helpers/`
|
|
3960
4003
|
directory anywhere below the root". The pattern is anchored with a leading
|
|
@@ -3995,7 +4038,7 @@ function findPathArgs(pattern: string): string
|
|
|
3995
4038
|
|
|
3996
4039
|
**Returns:** One or more `-path '…'` alternatives, ORed inside parens when there is more than one.
|
|
3997
4040
|
|
|
3998
|
-
#### `literalDirPrefix(pattern)`
|
|
4041
|
+
#### `literalDirPrefix(pattern, root)`
|
|
3999
4042
|
|
|
4000
4043
|
The directory a GLOB pattern spells out, when it spells one out: everything
|
|
4001
4044
|
before the pattern's first glob character, trimmed back to the last `/`.
|
|
@@ -4005,25 +4048,31 @@ anchor ({@link findPatternArgs}), so `find` visits every entry below the
|
|
|
4005
4048
|
search root. Handed `/workspace/node_modules` and
|
|
4006
4049
|
`@molecule/api-resource-user/dist/*.d.ts` — a directory named outright —
|
|
4007
4050
|
`find` walked the sandbox's entire dependency tree and hit the tool's 10 s
|
|
4008
|
-
deadline without printing a result (
|
|
4009
|
-
|
|
4051
|
+
deadline without printing a result (the one directory the model meant answered a `list_files`
|
|
4052
|
+
in 0 s). The literal prefix is that
|
|
4010
4053
|
directory, and rooting the search at it is what keeps the call instant.
|
|
4011
4054
|
|
|
4012
4055
|
A BARE first segment (`helpers/*`, `bonds/*`, `e2e/*.spec.ts`) is NOT one:
|
|
4013
4056
|
`helpers/*` means "a `helpers/` directory anywhere below the root", which the
|
|
4014
|
-
tool documents and a live run relied on (
|
|
4015
|
-
|
|
4057
|
+
tool documents and a live run relied on (a path pattern is not anchored to one depth).
|
|
4058
|
+
Rooting those at
|
|
4016
4059
|
`<root>/helpers` would answer with a SUBSET, silently: the nested
|
|
4017
4060
|
`api/src/helpers/` matches would disappear, and a missing file reads as
|
|
4018
4061
|
"no such file". So a prefix is returned only when it names a path of two or
|
|
4019
4062
|
more segments (`@molecule/api-resource-user/dist`), which is the shape that
|
|
4020
4063
|
is a directory rather than a directory name.
|
|
4021
4064
|
|
|
4065
|
+
An npm SCOPE as the first segment, under a `node_modules` root, is the one
|
|
4066
|
+
exception that parameter `root` enables: npm installs a scope only directly
|
|
4067
|
+
|
|
4068
|
+
_(description truncated — read the full text in `node_modules/@molecule/api-ai-tools/dist/utilities.d.ts`.)_
|
|
4069
|
+
|
|
4022
4070
|
```typescript
|
|
4023
|
-
function literalDirPrefix(pattern: string): string | null
|
|
4071
|
+
function literalDirPrefix(pattern: string, root?: string): string | null
|
|
4024
4072
|
```
|
|
4025
4073
|
|
|
4026
4074
|
- `pattern` — A pattern already accepted by {@link isValidGlob}.
|
|
4075
|
+
- `root` — The resolved search root, when one is already known; a scope-first prefix is returned only when this ends in a `node_modules` segment (and the pattern has more path after the scope).
|
|
4027
4076
|
|
|
4028
4077
|
**Returns:** The literal directory prefix, without a trailing slash, or null when the pattern has no glob character, no `/`, or only a bare name before one.
|
|
4029
4078
|
|
|
@@ -4035,7 +4084,7 @@ The E2B SDK answers a timed-out `exec` with its generic text —
|
|
|
4035
4084
|
`[deadline_exceeded] the operation timed out: … It can be modified by passing
|
|
4036
4085
|
'timeoutMs' when making the request. Use '0' to disable the timeout.` — which
|
|
4037
4086
|
names an option the executor cannot set and says nothing about the search
|
|
4038
|
-
that died. Handing that sentence to the model is what
|
|
4087
|
+
that died. Handing that sentence to the model is what a run
|
|
4039
4088
|
read after `find_files` spent 10 s walking `node_modules`; the tool answers
|
|
4040
4089
|
the deadline in its own words instead (see {@link searchTimeoutError}).
|
|
4041
4090
|
|
|
@@ -4096,8 +4145,8 @@ shape a truncated provider stream leaves behind.
|
|
|
4096
4145
|
|
|
4097
4146
|
The path message is the wrong reading of it: "requires a non-empty path
|
|
4098
4147
|
argument" says the call was understood and the path was left out, so the model
|
|
4099
|
-
retries the call it just made instead of sending the whole call again (
|
|
4100
|
-
|
|
4148
|
+
retries the call it just made instead of sending the whole call again (`edit_file {}` loses
|
|
4149
|
+
one round). An empty object and a
|
|
4101
4150
|
missing `path` are different failures and deserve different sentences.
|
|
4102
4151
|
|
|
4103
4152
|
```typescript
|
|
@@ -4262,9 +4311,8 @@ The shell command whose stdout is the interesting part of a log that is still be
|
|
|
4262
4311
|
the failure lines so far (capped at {@link RUNNING_FAILURE_LINES}), then the end of the log.
|
|
4263
4312
|
|
|
4264
4313
|
A Playwright `list` run prints one line per test as it finishes, so the LAST bytes of a running
|
|
4265
|
-
log are its least informative part —
|
|
4266
|
-
|
|
4267
|
-
make anyway. A background run also carries each failure's own error as it fails
|
|
4314
|
+
log are its least informative part — the last 3 000 bytes of a 139-test walk are the skip
|
|
4315
|
+
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
|
|
4268
4316
|
({@link PLAYWRIGHT_FAILURES_INLINE_ENV}), and {@link RUNNING_FAILURE_LINE_RE} already matches
|
|
4269
4317
|
those blocks' headers and their `Error:` lines, so this slice shows the causes too.
|
|
4270
4318
|
|
|
@@ -4302,11 +4350,11 @@ function runningCauseCommand(log: string, own?: string): string
|
|
|
4302
4350
|
The shell command whose stdout is a bounded CONTIGUOUS read of a running task's own log: the
|
|
4303
4351
|
log's byte size, then its last {@link RUNNING_LOG_READ_BYTES} bytes.
|
|
4304
4352
|
|
|
4305
|
-
{@link runningOutputSliceCommand} is the wrong read for a diagnosis
|
|
4353
|
+
{@link runningOutputSliceCommand} is the wrong read for a diagnosis: it
|
|
4306
4354
|
stitches the first 40 grep-selected failure lines to the last 1 000 bytes with a blank line
|
|
4307
4355
|
between, so the tail is DISJOINT from the headers above it. Read as one log, the last numbered
|
|
4308
|
-
header absorbs whatever the tail starts with — a clipped skipped-test title
|
|
4309
|
-
a genuine failure
|
|
4356
|
+
header absorbs whatever the tail starts with — a clipped skipped-test title becomes the cause
|
|
4357
|
+
of a genuine failure. A contiguous window can only ever hold real
|
|
4310
4358
|
neighbouring lines of one log.
|
|
4311
4359
|
|
|
4312
4360
|
The size rides along so a caller can say when the window is only the log's end
|
|
@@ -4350,11 +4398,12 @@ log does NOT carry.
|
|
|
4350
4398
|
|
|
4351
4399
|
Either way the point is the same: a suite whose failures repeat one cause spends its whole
|
|
4352
4400
|
runtime proving that one cause, and the executor watching it can be told so at the third
|
|
4353
|
-
failure instead of at the last.
|
|
4401
|
+
failure instead of at the last. Fifteen tests walked in 4.0 minutes where 15.6 s
|
|
4354
4402
|
each was the test timeout and one missing `navigate('/')` was the cause of all of them.
|
|
4355
4403
|
|
|
4356
4404
|
The quorum is of DISTINCT tests — {@link REPEATING_FAILURE_MIN} of them — because a log that
|
|
4357
|
-
prints each failure twice (a second reporter, a retry)
|
|
4405
|
+
prints each failure twice (a second reporter, a retry) has told a run that four of its
|
|
4406
|
+
tests failed the same way when two had, so the executor stopped a 139-test walk at test 21
|
|
4358
4407
|
|
|
4359
4408
|
_(description truncated — read the full text in `node_modules/@molecule/api-ai-tools/dist/utilities.d.ts`.)_
|
|
4360
4409
|
|
|
@@ -4366,7 +4415,7 @@ function repeatingFailure(log: string): RepeatingFailure | null
|
|
|
4366
4415
|
|
|
4367
4416
|
**Returns:** The repeating cause, or null when no signature has {@link REPEATING_FAILURE_MIN} distinct tests behind it.
|
|
4368
4417
|
|
|
4369
|
-
#### `logShowsInlineFailureBodies(log, excluded)`
|
|
4418
|
+
#### `logShowsInlineFailureBodies(log, excluded, options)`
|
|
4370
4419
|
|
|
4371
4420
|
Whether the log read so far carries a failure's own body under a `✘` row — the evidence that a
|
|
4372
4421
|
run prints each failure's error as that test fails ({@link PLAYWRIGHT_FAILURES_INLINE_ENV}).
|
|
@@ -4386,17 +4435,23 @@ is one the reporter printed inline.
|
|
|
4386
4435
|
A body for a test the request EXCLUDES is not that evidence: its failure does not count for
|
|
4387
4436
|
this request ({@link matchingExcludedTitles}), so a wait that handed it over as the diagnostic
|
|
4388
4437
|
spent a model round trip and 8 k of partial log on a test the same result says to ignore —
|
|
4389
|
-
|
|
4390
|
-
|
|
4438
|
+
which a run has done twice while the platform's proof was still walking.
|
|
4439
|
+
|
|
4440
|
+
With `finalOnly`, only a failure the run has FINISHED with counts; a pending retry waits.
|
|
4391
4441
|
|
|
4392
4442
|
```typescript
|
|
4393
|
-
function logShowsInlineFailureBodies(
|
|
4443
|
+
function logShowsInlineFailureBodies(
|
|
4444
|
+
log: string,
|
|
4445
|
+
excluded?: readonly string[],
|
|
4446
|
+
options?: { finalOnly?: boolean; noRetries?: boolean },
|
|
4447
|
+
): boolean
|
|
4394
4448
|
```
|
|
4395
4449
|
|
|
4396
4450
|
- `log` — A log, or the slice of one a wait reads.
|
|
4397
4451
|
- `excluded` — The test titles the request carves out, if the caller knows them.
|
|
4452
|
+
- `options` — `finalOnly` reads only a failure the run has finished with; `noRetries` says the command proves the run cannot retry (`--retries=0`), so its first failure is final.
|
|
4398
4453
|
|
|
4399
|
-
**Returns:** True when a `✘` row's own test, outside the request's exclusions, has a failure body under it.
|
|
4454
|
+
**Returns:** True when a `✘` row's own test, outside the request's exclusions, has a failure body under it — and, with `finalOnly`, that failure is final in the log read so far.
|
|
4400
4455
|
|
|
4401
4456
|
#### `specFilesSelected(command)`
|
|
4402
4457
|
|
|
@@ -4404,8 +4459,8 @@ How many test FILES a Playwright run's own command narrows it to, or null when i
|
|
|
4404
4459
|
whole suite (or its selection cannot be read).
|
|
4405
4460
|
|
|
4406
4461
|
{@link universalCause}'s file threshold is written for a whole-suite run, which a narrowed run
|
|
4407
|
-
can never reach.
|
|
4408
|
-
|
|
4462
|
+
can never reach. A run that re-ran ONE spec file against a hand-started `vite preview` the
|
|
4463
|
+
browser could not reach had every test in it fail `page.goto: Timeout` —
|
|
4409
4464
|
but one file is below {@link UNIVERSAL_CAUSE_FILES}, so the wait sat out its entire 280 s
|
|
4410
4465
|
budget on a run that had already measured all it could.
|
|
4411
4466
|
|
|
@@ -4432,7 +4487,7 @@ The test is: the cause accounts for every failure the log names, it has hit the
|
|
|
4432
4487
|
threshold, and nothing has passed since its first failure. The threshold is
|
|
4433
4488
|
{@link UNIVERSAL_CAUSE_FILES} for a whole-suite run but the number of files the command
|
|
4434
4489
|
SELECTED for a narrowed one ({@link specFilesSelected}): a one-file run can never span three,
|
|
4435
|
-
and
|
|
4490
|
+
and a run can wait out its whole budget on exactly that shape. An app
|
|
4436
4491
|
that is not up, a 5xx on every request, or a selector that is missing on every page all look
|
|
4437
4492
|
like that, and every remaining test will fail the same way — so the run's remaining minutes
|
|
4438
4493
|
measure nothing. A CONNECTION-class cause ({@link CONNECTION_CAUSE}) needs no file span at all:
|
|
@@ -4441,8 +4496,8 @@ case however few files the run walks.
|
|
|
4441
4496
|
|
|
4442
4497
|
Anything less is NOT this: a cause that stops at one file of a multi-file run, or that leaves
|
|
4443
4498
|
other tests passing, or that shares the run with failures of another shape, leaves the run with
|
|
4444
|
-
something to say, and the run is the only thing that will say it.
|
|
4445
|
-
|
|
4499
|
+
something to say, and the run is the only thing that will say it. Stopping runs at their first
|
|
4500
|
+
repeating cause has burned eight local runs over 14.5 minutes without finishing
|
|
4446
4501
|
one; three of its deploys each fixed a single cause that a finished run would have listed
|
|
4447
4502
|
alongside the others.
|
|
4448
4503
|
|
|
@@ -4471,16 +4526,17 @@ Both halves are load-bearing, each of them learned from a run that lost minutes
|
|
|
4471
4526
|
spec-file threshold — {@link UNIVERSAL_CAUSE_FILES}, or the files a narrowed run's own
|
|
4472
4527
|
command selects, or {@link CONNECTION_CAUSE_TESTS} tests of an app that never answered — with
|
|
4473
4528
|
nothing passing since the first. That is the
|
|
4474
|
-
dont-stop-runs rule.
|
|
4475
|
-
|
|
4529
|
+
dont-stop-runs rule. Stopping runs at their first repeating cause has burned eight local
|
|
4530
|
+
runs in 14.5 minutes without finishing one, and a run that still has other causes
|
|
4476
4531
|
left to name is the only thing that will name them.
|
|
4477
4532
|
- **A PROVEN cause** is an error repeated VERBATIM. A shared DURATION is a LEAD, never a cause:
|
|
4478
4533
|
a suite whose config sets a timeout spends that timeout on every failure that waits for
|
|
4479
4534
|
anything, so three unrelated tests timing out together look exactly like one broken run
|
|
4480
|
-
(`~7 s` is a property of the CONFIG, not of the cause — {@link normalizedSignature}).
|
|
4481
|
-
|
|
4535
|
+
(`~7 s` is a property of the CONFIG, not of the cause — {@link normalizedSignature}). A run
|
|
4536
|
+
told `status: 'repeating_failure'` twice on that
|
|
4482
4537
|
shape — three `url-navigation.spec.ts` tests at ~16.2 s, one `timeout: 15_000` plus teardown
|
|
4483
4538
|
— read the early return as "stop waiting, edit now", and voided a run that was still walking;
|
|
4539
|
+
the second cost a 224 s wait that ended with no result at all.
|
|
4484
4540
|
|
|
4485
4541
|
_(description truncated — read the full text in `node_modules/@molecule/api-ai-tools/dist/utilities.d.ts`.)_
|
|
4486
4542
|
|
|
@@ -4505,12 +4561,11 @@ The request quotes a test's own title (`… except "should require login to post
|
|
|
4505
4561
|
extracted by molecule-dev's `excludedTestTitles`) while a run's heading carries more of it
|
|
4506
4562
|
(`comments.spec.ts › Comments › should require login to post comment`), so containment is the
|
|
4507
4563
|
comparison. Whitespace is normalised and case is ignored: a brief may wrap the title across a
|
|
4508
|
-
line
|
|
4564
|
+
line, and the reporter's own casing never has to match the brief's.
|
|
4509
4565
|
|
|
4510
4566
|
Two readers used to answer this separately — the causes note (which therefore asked the
|
|
4511
4567
|
executor to fix a test the same result said not to) and molecule-dev's exclusion notes — and
|
|
4512
|
-
|
|
4513
|
-
test).
|
|
4568
|
+
a run paid for the gap (a turn and an edit spent on the excluded test).
|
|
4514
4569
|
|
|
4515
4570
|
```typescript
|
|
4516
4571
|
function matchingExcludedTitles(heading: string, excluded: readonly string[]): string[]
|
|
@@ -4528,7 +4583,7 @@ tests it hit.
|
|
|
4528
4583
|
|
|
4529
4584
|
The point is that ONE run yields EVERY cause. A Playwright report prints its failures one
|
|
4530
4585
|
after another with no statement of which of them share a cause, so a run of 19 failures is 19
|
|
4531
|
-
bodies to read;
|
|
4586
|
+
bodies to read; three deploys (6.7 minutes) each fixed a
|
|
4532
4587
|
single cause, two of them found by runs stopped before they walked the rest.
|
|
4533
4588
|
|
|
4534
4589
|
The signature is the cause itself where the log carries the failures' bodies (a finished run, a
|
|
@@ -4540,8 +4595,8 @@ proven cause. A test the log printed twice, or failed twice, is one test.
|
|
|
4540
4595
|
A test the request EXCLUDES by name is not a cause to fix: its failure does not count for
|
|
4541
4596
|
this request ({@link matchingExcludedTitles}), so it is dropped here rather than handed to the
|
|
4542
4597
|
executor as work — a result that names it beside "it does not count" is the contradiction
|
|
4543
|
-
|
|
4544
|
-
|
|
4598
|
+
a run filed (the model spent a turn and an edit on the excluded test, on a page that was
|
|
4599
|
+
passing).
|
|
4545
4600
|
|
|
4546
4601
|
```typescript
|
|
4547
4602
|
function failuresByCause(log: string, excluded?: readonly string[]): FailureCause[]
|
|
@@ -4570,7 +4625,7 @@ function requiredLandmark(selector: string): RequiredLandmark | null
|
|
|
4570
4625
|
The sentence for a run whose navigational elements are all missing from pages that otherwise
|
|
4571
4626
|
painted — the missing shared header the executor must check BEFORE rewriting auth.
|
|
4572
4627
|
|
|
4573
|
-
|
|
4628
|
+
A run had four failures on `/` — `a[href="/profile/…"]`,
|
|
4574
4629
|
`a.navbar-brand`, `nav a[href="/"]`, `nav .user-pic` — while every `error-context.md` snapshot
|
|
4575
4630
|
showed the feed, sidebar and footer with no navigation at all. `Home.tsx` imported and
|
|
4576
4631
|
re-exported `Navbar` but never rendered it, and `App.tsx` mounted `<Home />` in a bare route.
|
|
@@ -4664,7 +4719,7 @@ function rerunOfRunningSuite(
|
|
|
4664
4719
|
): string | null
|
|
4665
4720
|
```
|
|
4666
4721
|
|
|
4667
|
-
- `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
|
|
4722
|
+
- `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.
|
|
4668
4723
|
- `locations` — The failing `file:line`s to re-run, as the run's log printed them.
|
|
4669
4724
|
- `excluded` — The test titles the request carves out: the re-run inverts them out (`--grep-invert`) so it cannot report them again.
|
|
4670
4725
|
|
|
@@ -4681,17 +4736,18 @@ tests, so the note never names one or two tests as a cause.
|
|
|
4681
4736
|
The note names the cause early so the executor can START FIXING while the run keeps walking,
|
|
4682
4737
|
and it hands a stop command over only when {@link earlyReturnCause} says so — the SAME
|
|
4683
4738
|
predicate the wait uses to decide whether to return early, so a finding the wait keeps waiting
|
|
4684
|
-
on is a finding this note never asks to stop for.
|
|
4739
|
+
on is a finding this note never asks to stop for. One run spent 4.0 minutes
|
|
4685
4740
|
walking 15 tests whose one cause was certain at the third, 47 s in, and the note answers
|
|
4686
|
-
exactly that;
|
|
4741
|
+
exactly that; another stopped eight runs at their first repeating cause in 14.5
|
|
4687
4742
|
minutes and never finished one, so the note must not say to stop when the run still has other
|
|
4688
|
-
causes to name.
|
|
4743
|
+
causes to name. The third shape: a shared duration is
|
|
4689
4744
|
not a cause at all, so a lead reaches the executor as a note on a result it is still waiting
|
|
4690
4745
|
for — never as a verdict with a stop command in it.
|
|
4691
4746
|
|
|
4692
4747
|
The run is STILL WALKING while this note is written — both callers produce it mid-run — so a
|
|
4693
4748
|
re-run of one of its tests is a second run against the same app and database, and the platform
|
|
4694
4749
|
refuses that ({@link suiteRunInTheWay}, the same rule its overlap hold answers with):
|
|
4750
|
+
an executor read *"Start on them now, while the run keeps walking.
|
|
4695
4751
|
|
|
4696
4752
|
_(description truncated — read the full text in `node_modules/@molecule/api-ai-tools/dist/utilities.d.ts`.)_
|
|
4697
4753
|
|
|
@@ -4893,7 +4949,7 @@ Python WSGI server. Matched against a command segment's own text, and against a
|
|
|
4893
4949
|
when the command only names the script file — but NEVER against an inline program's code
|
|
4894
4950
|
(`node -e …`, `python3 -c …`), where this text is the user's program rather than a file being
|
|
4895
4951
|
run: `require('…/node_modules/vite')` imports a module, it does not start a dev server
|
|
4896
|
-
(
|
|
4952
|
+
(refused as "node starts a server" for exactly that line).
|
|
4897
4953
|
|
|
4898
4954
|
```typescript
|
|
4899
4955
|
const SERVER_PROGRAM: RegExp
|
|
@@ -4947,14 +5003,13 @@ The closing advice on an over-budget message for a command that IS a suite run
|
|
|
4947
5003
|
(Playwright, Vitest, a `hurl` run — {@link isSuiteRunCommand}): its files are not
|
|
4948
5004
|
a bigger unit to break up.
|
|
4949
5005
|
|
|
4950
|
-
|
|
4951
|
-
|
|
4952
|
-
|
|
4953
|
-
|
|
4954
|
-
|
|
4955
|
-
|
|
4956
|
-
|
|
4957
|
-
300 s default per request holding the file, ten seconds past this tool's budget.
|
|
5006
|
+
The wrong advice here is "run a smaller unit": it is the wrong direction for a
|
|
5007
|
+
suite, and measurably so — a run stopped here reports NO tally, so nothing in
|
|
5008
|
+
the result says which test or request hung. The run has to be sent again in the
|
|
5009
|
+
background (off this budget, its output written to a log that can be read
|
|
5010
|
+
mid-run) or, when a consumer knows the runner's per-request limit, with each
|
|
5011
|
+
request bounded. One Hurl run lost 4.8 minutes to a single unanswered request
|
|
5012
|
+
held by hurl's 300 s default per request, ten seconds past this tool's budget.
|
|
4958
5013
|
|
|
4959
5014
|
```typescript
|
|
4960
5015
|
const SUITE_OVER_BUDGET_ADVICE: string
|
|
@@ -5021,7 +5076,7 @@ const MAX_TRACE_NOTE_REQUESTS: 4
|
|
|
5021
5076
|
|
|
5022
5077
|
How many times ONE test may send the same method+path before the note calls it a render loop.
|
|
5023
5078
|
|
|
5024
|
-
|
|
5079
|
+
An Editor effect with `[seeded, slug, t]` in its
|
|
5025
5080
|
dependency list re-fetched `GET /api/articles/<slug>` 2,106 times in one test. The trace reader
|
|
5026
5081
|
caps and de-duplicates its request list, so the note printed four identical `→ 200` lines and
|
|
5027
5082
|
the run patched the component's seeding, rebuilt and re-ran before unzipping the trace by hand.
|
|
@@ -5085,8 +5140,8 @@ reporter still prints each failure exactly once.
|
|
|
5085
5140
|
Every background command is given this (see {@link streamingBackgroundCommand}), so a suite the
|
|
5086
5141
|
executor starts through its own wrapper is covered too — the wrapper passes the environment on
|
|
5087
5142
|
to the Playwright process it spawns. Without it the log's only failure lines are `✘` rows:
|
|
5088
|
-
|
|
5089
|
-
|
|
5143
|
+
A run told to `grep -n -A 20 '<test name>'` the log got nothing back through four greps,
|
|
5144
|
+
inferred causes from the spec prose instead, and
|
|
5090
5145
|
edited `app/src` while the run was still walking — which voids the run.
|
|
5091
5146
|
|
|
5092
5147
|
```typescript
|
|
@@ -5171,9 +5226,8 @@ place, keeping ~30 KB of each end. A batched read that crossed it lost its
|
|
|
5171
5226
|
MIDDLE — the cut lands between two `"content"` values, so whole files fell
|
|
5172
5227
|
out and the note in their place said only "N characters cut here" — while
|
|
5173
5228
|
this tool's own note had promised each of those files that it "fits in one
|
|
5174
|
-
call, so it is not paged":
|
|
5175
|
-
|
|
5176
|
-
further calls (52,908 chars).
|
|
5229
|
+
call, so it is not paged": one batched read of ten e2e specs (121,467 chars) lost the
|
|
5230
|
+
middle six and bought them again in six further calls (52,908 chars).
|
|
5177
5231
|
|
|
5178
5232
|
So the CALL gets the ceiling the request gives it. Whole files are returned
|
|
5179
5233
|
up to it; the paths that did not fit are named in `note` and listed in
|
|
@@ -5220,7 +5274,7 @@ const MAX_READ_RETURN_CHARS: number
|
|
|
5220
5274
|
|
|
5221
5275
|
A file this small is returned whole on a second window of it (paging it costs a call each).
|
|
5222
5276
|
The same bound as {@link MAX_READ_RETURN_CHARS}: the windowed-read note promises that a
|
|
5223
|
-
file under it "fits in ONE call", and a smaller bound here
|
|
5277
|
+
file under it "fits in ONE call", and a smaller bound here breaks that promise.
|
|
5224
5278
|
|
|
5225
5279
|
```typescript
|
|
5226
5280
|
const SMALL_FILE_WHOLE_CHARS: number
|
|
@@ -5235,11 +5289,11 @@ an HTML read is almost never worth it.
|
|
|
5235
5289
|
An entry document is boilerplate the reader rarely needs in full: meta tags,
|
|
5236
5290
|
stylesheet and preload links, a `<style>` block, and a handful of `<script>`
|
|
5237
5291
|
tags. The parts an executor acts on — the body's structure, where a script is
|
|
5238
|
-
loaded — are all visible in an outline of one line per tag.
|
|
5239
|
-
63,735 chars
|
|
5292
|
+
loaded — are all visible in an outline of one line per tag. One such read paid
|
|
5293
|
+
63,735 chars: ~60 KB of it was the IDE's own preview bridges,
|
|
5240
5294
|
and the read pushed the transcript past its context cap, so the e2e specs the
|
|
5241
5295
|
executor had just read were trimmed to summaries and it read the whole suite
|
|
5242
|
-
again — twice
|
|
5296
|
+
again — twice. The scaffold now keeps those
|
|
5243
5297
|
bridges in separate files, but a template's own head is still ~5-12 KB, and a
|
|
5244
5298
|
static-site or SSR entry can be far more.
|
|
5245
5299
|
|
|
@@ -5369,8 +5423,8 @@ const TOOL_RESULT_CHARS: 8000
|
|
|
5369
5423
|
|
|
5370
5424
|
#### `FAILURE_CAUSES_CHARS`
|
|
5371
5425
|
|
|
5372
|
-
The characters a finished run's cause list may use of {@link TOOL_RESULT_CHARS}.
|
|
5373
|
-
|
|
5426
|
+
The characters a finished run's cause list may use of {@link TOOL_RESULT_CHARS}. A measured
|
|
5427
|
+
recap was `12 failures, 8 causes`: one cause line is
|
|
5374
5428
|
~200 chars and ~80 more with its two body lines, so 8 causes is ~2.3 k against the 8 k cap —
|
|
5375
5429
|
the old 5-cause cap withheld 3 causes that the same result had room for.
|
|
5376
5430
|
|
|
@@ -5420,7 +5474,7 @@ How many tests a run must have walked — with nothing passing since its first f
|
|
|
5420
5474
|
THREE, and the number is the cost of the alternative. The old floor of 15 was chosen when the
|
|
5421
5475
|
reading was only offered at a completed run; once it STOPS the walk, every test waited for is
|
|
5422
5476
|
a test whose result is thrown away, and a blank page costs its per-test budget each time
|
|
5423
|
-
(
|
|
5477
|
+
(18 tests, ~4.2 minutes, on a page whose thrown error was visible in the first
|
|
5424
5478
|
`pageerror`). Three is the smallest count that is not one page's own bug: the cause additionally
|
|
5425
5479
|
needs three DISTINCT spec files (`UNIVERSAL_CAUSE_FILES`, or the files a narrowed run selected),
|
|
5426
5480
|
no failure showing a locator RESOLVING ({@link ELEMENT_FOUND} — a blank page cannot resolve
|
|
@@ -5482,7 +5536,7 @@ Peer dependencies:
|
|
|
5482
5536
|
ceiling the request side puts on a single tool result: whole files are
|
|
5483
5537
|
returned up to it and every path past that is named in `note` and listed as
|
|
5484
5538
|
`not returned`, so a file is never handed back in part — the shape that lost
|
|
5485
|
-
the middle of a ten-file batch to the request-side cut
|
|
5539
|
+
the middle of a ten-file batch to the request-side cut. Each
|
|
5486
5540
|
entry carries its own content or its own error, so one bad path never fails
|
|
5487
5541
|
the batch.
|
|
5488
5542
|
- **`edit_file` shows the result, so the model need not re-read.** A
|
|
@@ -5508,7 +5562,7 @@ Peer dependencies:
|
|
|
5508
5562
|
added or removed and nothing else, the edit can only move text across lines —
|
|
5509
5563
|
joining the next line onto the replaced text, or pushing the rest of the line
|
|
5510
5564
|
down — which is what a weak model does by accident when it repeats a line it
|
|
5511
|
-
means to keep
|
|
5565
|
+
means to keep. The
|
|
5512
5566
|
replacement is skipped, the rest of the batch is applied, and the result
|
|
5513
5567
|
carries `skippedNote`: one line naming the replacement, what applying it would
|
|
5514
5568
|
have done, and how to say it on purpose (include the next line in `old_string`).
|