@molecule/api-ai-tools 1.14.4 → 1.14.6
This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
- package/README.md +236 -190
- 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 +98 -69
- package/dist/trace-artifacts.d.ts +64 -65
- package/dist/trace-artifacts.d.ts.map +1 -1
- package/dist/trace-artifacts.js +73 -75
- package/dist/types.d.ts +5 -5
- package/dist/utilities.d.ts +107 -91
- package/dist/utilities.d.ts.map +1 -1
- package/dist/utilities.js +191 -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-26T04:22:08.815Z
|
|
7
7
|
-->
|
|
8
8
|
|
|
9
9
|
# @molecule/api-ai-tools
|
|
@@ -64,7 +64,7 @@ A browser launch bound to a variable, proven to have no cleanup path.
|
|
|
64
64
|
|
|
65
65
|
```typescript
|
|
66
66
|
interface BrowserProbeLeak {
|
|
67
|
-
/** The variable the launched browser is bound to (`browser` in the
|
|
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
|
|
@@ -2253,7 +2254,9 @@ Whether every one of the classified failures is a connection failure — the onl
|
|
|
2253
2254
|
no response the app produced was measured.
|
|
2254
2255
|
|
|
2255
2256
|
```typescript
|
|
2256
|
-
function allConnectionFailures(
|
|
2257
|
+
function allConnectionFailures(
|
|
2258
|
+
failures: ReadonlyArray<RunFailureClass | null>,
|
|
2259
|
+
): failures is ReadonlyArray<RunFailureClass & { kind: 'connection' }>
|
|
2257
2260
|
```
|
|
2258
2261
|
|
|
2259
2262
|
- `failures` — The run's classifications, in printed order.
|
|
@@ -2369,7 +2372,13 @@ tools built outside this package get the same treatment as the ones built
|
|
|
2369
2372
|
inside it.
|
|
2370
2373
|
|
|
2371
2374
|
```typescript
|
|
2372
|
-
function guardAITool
|
|
2375
|
+
function guardAITool<
|
|
2376
|
+
T extends {
|
|
2377
|
+
name: string
|
|
2378
|
+
parameters?: unknown
|
|
2379
|
+
execute: (input: unknown, ...rest: never[]) => Promise<unknown>
|
|
2380
|
+
},
|
|
2381
|
+
>(tool: T, options?: GuardOptions): T
|
|
2373
2382
|
```
|
|
2374
2383
|
|
|
2375
2384
|
- `tool` — The tool to guard.
|
|
@@ -2407,7 +2416,7 @@ A runner counts only where a shell would RUN it ({@link commandSegments}): the w
|
|
|
2407
2416
|
position of a segment, after its wrapper prefixes. A runner named in an argument is not an
|
|
2408
2417
|
invocation — `head -30 run-api-tests-hurl.sh` and `grep -n playwright e2e/README.md` name a
|
|
2409
2418
|
file to read, and a `--list` written inside a file the command writes is not a flag anyone runs
|
|
2410
|
-
with
|
|
2419
|
+
with.
|
|
2411
2420
|
|
|
2412
2421
|
A command that invokes no runner is NOT one of these (false): "the command runs no test" is
|
|
2413
2422
|
then true for `ls`, which is not the question any caller is asking. The question is whether
|
|
@@ -2449,7 +2458,7 @@ function outputFilterAfterRunner(
|
|
|
2449
2458
|
|
|
2450
2459
|
- `command` — The command as the executor sent it.
|
|
2451
2460
|
- `runs` — Whether a segment is the runner this run is about (the caller knows its own kind: {@link CommandSegment.program} is the program, once wrapper words like `timeout 280` and `npx` are taken away).
|
|
2452
|
-
- `occurrence` — Which runner invocation the output belongs to, 1-based. A command can run the same runner more than once (
|
|
2461
|
+
- `occurrence` — Which runner invocation the output belongs to, 1-based. A command can run the same runner more than once (the suite bare, then with `HOST=…`), and each invocation carries its OWN pipe; a reader judging the second walk must name the second walk's cut, never the first's.
|
|
2453
2462
|
|
|
2454
2463
|
**Returns:** The filter and the unfiltered command, or null.
|
|
2455
2464
|
|
|
@@ -2725,7 +2734,7 @@ it already names one, or starts no Playwright run.
|
|
|
2725
2734
|
The flag rides the same statement the runner does: a `cd`, an env prefix and a `timeout` before
|
|
2726
2735
|
it are left exactly as they were, and so is everything chained after the run (`| tail -50`).
|
|
2727
2736
|
|
|
2728
|
-
|
|
2737
|
+
A fix-round re-run dropped the
|
|
2729
2738
|
`--config playwright.conduit.config.ts` both earlier runs had carried, so Playwright started with
|
|
2730
2739
|
NO base URL and all 10 failures were `page.goto: Cannot navigate to invalid URL` — a failure list
|
|
2731
2740
|
that says nothing about the app. The platform composes commands back to the executor too (the
|
|
@@ -2746,21 +2755,21 @@ function withSuiteConfig(command: string, config: string | null | undefined): st
|
|
|
2746
2755
|
The whole-suite command made scoped to the tests it should re-run instead: the same
|
|
2747
2756
|
invocation — same launcher, same settings — with the named `file:line`s in place of every
|
|
2748
2757
|
positional selection the run carried (a spec file, a suite directory or a regex filter),
|
|
2749
|
-
`--last-failed` dropped (it re-runs the tests that never ran too
|
|
2758
|
+
`--last-failed` dropped (it re-runs the tests that never ran too) and
|
|
2750
2759
|
`--retries=0` set (a re-run of a known failure does not need to pay for retries) — except the
|
|
2751
2760
|
re-run of a run against a DEPLOYED URL, which keeps the suite's own retries and tracing
|
|
2752
2761
|
(`options.suiteSettings`).
|
|
2753
2762
|
|
|
2754
2763
|
The re-run keeps the run's `> <file>` redirect only in the sense of keeping its OUTPUT there:
|
|
2755
2764
|
the target is rewritten to a fresh sibling ({@link redirectRunnerOutputsToFreshFiles}), so a
|
|
2756
|
-
re-run never overwrites the log the run itself is the evidence for
|
|
2757
|
-
and the setup around the run keeps its own file writes untouched
|
|
2765
|
+
re-run never overwrites the log the run itself is the evidence for —
|
|
2766
|
+
and the setup around the run keeps its own file writes untouched. A
|
|
2758
2767
|
`tail`/`head`/`cat`/`grep` chained after the run that reads that exact log is shown the fresh
|
|
2759
|
-
sibling instead, so the re-run displays the run it performed
|
|
2768
|
+
sibling instead, so the re-run displays the run it performed.
|
|
2760
2769
|
|
|
2761
2770
|
`config` is the config the run was measured under ({@link withSuiteConfig}): the narrowed re-run
|
|
2762
2771
|
carries it whenever the command itself does not, so a run that dropped `--config` cannot be
|
|
2763
|
-
handed back a command with the same defect (
|
|
2772
|
+
handed back a command with the same defect (every failing test was
|
|
2764
2773
|
`Cannot navigate to invalid URL` because the re-run loaded no base URL).
|
|
2765
2774
|
|
|
2766
2775
|
```typescript
|
|
@@ -2777,23 +2786,23 @@ function scopedRerunCommand(
|
|
|
2777
2786
|
|
|
2778
2787
|
- `command` — The whole-suite run's command.
|
|
2779
2788
|
- `locations` — The failing `file:line`s to re-run, as the run's own log printed them. A location the reporter printed relative to the runner's own directory (`../../fixtures/…`, which no absolute path contains) is resolved here ({@link playwrightLocations}), so the command this returns is one Playwright can match.
|
|
2780
|
-
- `excluded` — The test titles the request carves out. They are inverted out (`--grep-invert`) so a re-run of the failing locations cannot report one of them again —
|
|
2789
|
+
- `excluded` — The test titles the request carves out. They are inverted out (`--grep-invert`) so a re-run of the failing locations cannot report one of them again — a re-run of the whole 139-test suite spends ~4 minutes to be told about a test the request had already said does not count.
|
|
2781
2790
|
- `config` — The config the run loaded, when the caller knows it; added when the command does not name one.
|
|
2782
2791
|
- `cwd` — The directory `exec_command` was given, when it was; the base a location is resolved against when the command does not `cd` anywhere.
|
|
2783
|
-
- `env` — The settings the REQUEST requires of the suite and this run left out ({@link withRunEnv}): the re-run carries them, so a re-run of a run measured in the wrong mode is not measured in that mode again
|
|
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
|
|
2792
|
+
- `env` — The settings the REQUEST requires of the suite and this run left out ({@link withRunEnv}): the re-run carries them, so a re-run of a run measured in the wrong mode is not measured in that mode again.
|
|
2793
|
+
- `options` — `suiteSettings` for the re-run of a run against a DEPLOYED URL: it keeps the suite's own retries and tracing instead of the diagnosis ones. The graded measurement is the suite's own settings, and a retry is what leaves a failing test's trace there; the platform's `--retries=0` and its `--trace=retain-on-failure` are both a stricter measurement than the one that was graded, and the recording alone turned three budget-bound deployed tests into timeouts.
|
|
2785
2794
|
|
|
2786
2795
|
**Returns:** The scoped command, or the command unchanged when it runs no Playwright suite.
|
|
2787
2796
|
|
|
2788
2797
|
#### `withRunEnv(command, settings)`
|
|
2789
2798
|
|
|
2790
2799
|
The command with the request's required settings put in front of its RUN statement — the ONE
|
|
2791
|
-
place every composed re-run gets them
|
|
2800
|
+
place every composed re-run gets them.
|
|
2792
2801
|
|
|
2793
2802
|
The settings are written at the statement's own assignment offset, never in front of the whole
|
|
2794
2803
|
command: a shell binds an assignment there to the statement's program, while one in front of the
|
|
2795
2804
|
whole command is the environment of its FIRST statement alone (`APP_BASE=… cd app && npx
|
|
2796
|
-
playwright test` sets the variable for `cd
|
|
2805
|
+
playwright test` sets the variable for `cd`). A name the command
|
|
2797
2806
|
gives a different value is replaced, and one it already gives the required value is left as
|
|
2798
2807
|
written. When the parse cannot place the statement (a run inside a nested `sh -c '…'`), the
|
|
2799
2808
|
settings become `export`s, which no statement boundary can swallow.
|
|
@@ -2817,7 +2826,10 @@ rows — the failures one causes the other cannot be told from real ones. A run
|
|
|
2817
2826
|
suite is never in the way, and neither is one the candidate command stops first.
|
|
2818
2827
|
|
|
2819
2828
|
```typescript
|
|
2820
|
-
function suiteRunInTheWay
|
|
2829
|
+
function suiteRunInTheWay<T extends SuiteRunInFlight>(
|
|
2830
|
+
candidate: { target: string },
|
|
2831
|
+
inFlight: readonly T[],
|
|
2832
|
+
): T | null
|
|
2821
2833
|
```
|
|
2822
2834
|
|
|
2823
2835
|
- `candidate` — The run about to start, by the app and database it would measure ({@link suiteCommandTarget}).
|
|
@@ -2850,10 +2862,10 @@ disagree:
|
|
|
2850
2862
|
({@link ./utilities.js} `streamingBackgroundCommand`) — a diagnosis walks each failure once,
|
|
2851
2863
|
while the run the suite is judged by keeps the suite's own retries; and
|
|
2852
2864
|
- the platform's own notes (molecule-dev's `suite-cli-override.ts`), which must not tell the
|
|
2853
|
-
executor to drop the `--retries=0` the platform itself has just added —
|
|
2854
|
-
|
|
2865
|
+
executor to drop the `--retries=0` the platform itself has just added — a contradiction
|
|
2866
|
+
filed three times.
|
|
2855
2867
|
|
|
2856
|
-
Until
|
|
2868
|
+
Until then they were a regex and a predicate that only LOOKED alike, and the
|
|
2857
2869
|
gap was exactly the run the platform had asked for: its `testRunNote` says "run the whole suite
|
|
2858
2870
|
once with `--max-failures=0`", and the rewriter read that cap flag as a capped diagnosis and
|
|
2859
2871
|
stripped the suite's retries from the uncapped proof run that follows a deploy — the one run the
|
|
@@ -2936,11 +2948,10 @@ The command that stops a running background task, read from the sandbox's own pi
|
|
|
2936
2948
|
|
|
2937
2949
|
THE one builder for it, so every note that hands the executor a way to stop a run hands over the
|
|
2938
2950
|
same pid-only form: a `pkill -f <something>` matches the shell running it (its argv IS the
|
|
2939
|
-
command), and `molecule-dev/api/src/ai/pattern-kill-guard.ts` holds exactly that —
|
|
2940
|
-
|
|
2941
|
-
|
|
2942
|
-
|
|
2943
|
-
process under it.
|
|
2951
|
+
command), and `molecule-dev/api/src/ai/pattern-kill-guard.ts` holds exactly that — a stuck note
|
|
2952
|
+
that suggested `kill $(cat /tmp/<id>.pid) 2>/dev/null; pkill -f <id>.sh` was refused by the
|
|
2953
|
+
platform's own guard, and the same shape costs a refused call every time. The pid tree is the
|
|
2954
|
+
whole of what the pattern was for: the detached shell and every process under it.
|
|
2944
2955
|
|
|
2945
2956
|
```typescript
|
|
2946
2957
|
function taskStopCommand(backend: ExecutionBackend, taskId: string): Promise<string>
|
|
@@ -2956,8 +2967,8 @@ function taskStopCommand(backend: ExecutionBackend, taskId: string): Promise<str
|
|
|
2956
2967
|
The steer attached to a SUCCESSFUL read of a package's built output. The ENOENT
|
|
2957
2968
|
redirect below fires only when the read FAILS, so a model that knows the hoisted
|
|
2958
2969
|
layout reads `node_modules/@molecule/<pkg>/dist/*.js` happily and never learns the
|
|
2959
|
-
documented API is one call away (
|
|
2960
|
-
|
|
2970
|
+
documented API is one call away (24 such reads in 57 s, with no note on any of
|
|
2971
|
+
them). Carried as `distNote` rather than merged into `note` so a host that
|
|
2961
2972
|
has read_molecule_doc (molecule-dev's cadence note, which also names the functions)
|
|
2962
2973
|
can supersede it without string-matching.
|
|
2963
2974
|
|
|
@@ -2979,7 +2990,7 @@ The task id is the ownership: it is the handle `wait_for_task` returned, `/tmp/$
|
|
|
2979
2990
|
the log this platform's launcher writes for it, and the redirect target is the file this
|
|
2980
2991
|
process's own launch registered for that id — never a path parsed out of a command by the
|
|
2981
2992
|
caller. A diagnosis that reads a running walk must not build a `/tmp` path of its own
|
|
2982
|
-
(
|
|
2993
|
+
(a wait's DISPLAY gets diagnosed as if it were the log).
|
|
2983
2994
|
|
|
2984
2995
|
```typescript
|
|
2985
2996
|
function registeredTaskLogCommand(taskId: string): string | null
|
|
@@ -3012,17 +3023,17 @@ when the path is not under `node_modules` or nothing is installed there.
|
|
|
3012
3023
|
|
|
3013
3024
|
`node_modules` is not the project's code: nothing written there survives the
|
|
3014
3025
|
next install, no deploy carries it, and a sandbox whose dependency tree is
|
|
3015
|
-
shared (the pre-installed superset) breaks every other run through it.
|
|
3016
|
-
|
|
3017
|
-
`node_modules/@molecule/api-resource-comment/dist/numbers.d.ts
|
|
3018
|
-
the package's declarations
|
|
3026
|
+
shared (the pre-installed superset) breaks every other run through it. A
|
|
3027
|
+
`write_file` on
|
|
3028
|
+
`node_modules/@molecule/api-resource-comment/dist/numbers.d.ts`, made while
|
|
3029
|
+
reading the package's declarations, clobbered its runtime module a call later
|
|
3019
3030
|
(`module.exports = {}` over the ESM handler its own code imports) — the write
|
|
3020
3031
|
answered `ok: true`, and 18 s went to noticing, `npm pack`-ing the package and
|
|
3021
3032
|
putting the file back. Reading these files stays allowed (that is how the
|
|
3022
3033
|
declarations above are read at all).
|
|
3023
3034
|
|
|
3024
3035
|
What is protected is the INSTALL, not the spelling: the decision comes from
|
|
3025
|
-
{@link InstalledPackageFacts}, never from the path alone (
|
|
3036
|
+
{@link InstalledPackageFacts}, never from the path alone (see the symlink case above). Three
|
|
3026
3037
|
things are the run's own to remove or replace —
|
|
3027
3038
|
|
|
3028
3039
|
- a `node_modules` that is a SYMLINK: `rm`/`unlink` removes the link, never the
|
|
@@ -3032,6 +3043,7 @@ things are the run's own to remove or replace —
|
|
|
3032
3043
|
|
|
3033
3044
|
A path INSIDE the link is still decided by what resolves there: a link into a
|
|
3034
3045
|
real tree is refused, because removing or writing through it reaches the
|
|
3046
|
+
install.
|
|
3035
3047
|
|
|
3036
3048
|
_(description truncated — read the full text in `node_modules/@molecule/api-ai-tools/dist/tools.d.ts`.)_
|
|
3037
3049
|
|
|
@@ -3125,7 +3137,7 @@ function isStaticAssetRequest(request: TraceRequest): boolean
|
|
|
3125
3137
|
Whether a trace recorded a failed response or a request error other than cancellation.
|
|
3126
3138
|
|
|
3127
3139
|
A 404 on a static asset is excepted: `/sw.js` and `/fonts/*` 404 on an app that never shipped
|
|
3128
|
-
them, and naming one as a failure sent
|
|
3140
|
+
them, and naming one as a failure sent a run into writing the caching worker it had asked about.
|
|
3129
3141
|
A 5xx on an asset, or a network error, still counts. A request error alone does not locate
|
|
3130
3142
|
the cause in the server: the browser or network may have rejected the request.
|
|
3131
3143
|
|
|
@@ -3141,7 +3153,7 @@ function failedRequest(request: TraceRequest): boolean
|
|
|
3141
3153
|
|
|
3142
3154
|
Whether a trace recorded no response and no error other than cancellation. The request may
|
|
3143
3155
|
have been pending or cancelled when recording ended; the trace does not establish whether
|
|
3144
|
-
the endpoint stalled. A shell request is not evidence about the step
|
|
3156
|
+
the endpoint stalled. A shell request is not evidence about the step.
|
|
3145
3157
|
|
|
3146
3158
|
```typescript
|
|
3147
3159
|
function unansweredRequest(request: TraceRequest): boolean
|
|
@@ -3158,12 +3170,12 @@ other asset the page itself loads, with no response and no error text — still
|
|
|
3158
3170
|
the navigation timed out.
|
|
3159
3171
|
|
|
3160
3172
|
The page shell's own incidental requests (`/sw.js`, the manifest, a favicon, a font) are
|
|
3161
|
-
excepted for the reason {@link isStaticAssetRequest} documents:
|
|
3162
|
-
|
|
3163
|
-
|
|
3164
|
-
|
|
3165
|
-
|
|
3166
|
-
|
|
3173
|
+
excepted for the reason {@link isStaticAssetRequest} documents: an aborted `/sw.js` once sent a
|
|
3174
|
+
run to write a caching service worker. A pending `/assets/*.css` is different — the navigation
|
|
3175
|
+
blocks on it, so it is the reason `page.goto` ran out of time rather than one of the app's API
|
|
3176
|
+
calls (three deployed `page.goto` timeouts on tests that pass locally, one 88 KB stylesheet
|
|
3177
|
+
fetch measured at 27 s, and the failing tests' traces each holding the never-answered CSS while
|
|
3178
|
+
the note said "the cause is in the page").
|
|
3167
3179
|
|
|
3168
3180
|
```typescript
|
|
3169
3181
|
function stalledDocumentSubresource(request: TraceRequest): boolean
|
|
@@ -3181,7 +3193,7 @@ endpoint — as opposed to a protected resource that presents one.
|
|
|
3181
3193
|
This is the path half of {@link isCredentialExchange}, exported so a caller holding only a
|
|
3182
3194
|
`METHOD path` reads the same classification: a Hurl failing entry says
|
|
3183
3195
|
`POST /api/users/login` and nothing about the body, and the whole-suite note must not explain
|
|
3184
|
-
a wrong-password login that answered 200 as a cookie-jar effect
|
|
3196
|
+
a wrong-password login that answered 200 as a cookie-jar effect.
|
|
3185
3197
|
|
|
3186
3198
|
```typescript
|
|
3187
3199
|
function isCredentialExchangePath(path: string, authEndpoints?: readonly string[]): boolean
|
|
@@ -3197,7 +3209,7 @@ function isCredentialExchangePath(path: string, authEndpoints?: readonly string[
|
|
|
3197
3209
|
The sentence a "hidden" visibility failure earns when the trace proved WHY the box is empty.
|
|
3198
3210
|
|
|
3199
3211
|
Playwright calls an element with a zero-size box hidden even when it is painted, so the answer
|
|
3200
|
-
is in the element's children. `a.navbar-brand`
|
|
3212
|
+
is in the element's children. An `a.navbar-brand` was 0×4 px because its
|
|
3201
3213
|
only child was `<img src="/conduit-logo.svg" height="26">`: an SVG with a `viewBox` and no
|
|
3202
3214
|
width/height has no intrinsic size, and the `height` attribute loses to Tailwind's preflight
|
|
3203
3215
|
(`img { max-width: 100%; height: auto }`), which the scaffold's own `index.css` imports. The
|
|
@@ -3217,7 +3229,7 @@ function hiddenBoxNote(items: readonly TraceArtifact[]): string | null
|
|
|
3217
3229
|
The row's sentence for a failing count assertion: the locator, both numbers, and the elements
|
|
3218
3230
|
the failure snapshot held.
|
|
3219
3231
|
|
|
3220
|
-
|
|
3232
|
+
A `comments.spec.ts:86` row printed only `Expected: 3 / Received: 4`. The
|
|
3221
3233
|
helper counted `.card:not(.comment-form) .card-block`, and the app's comment form was a
|
|
3222
3234
|
`.comment-form` wrapper around a plain `.card`, so the form's own `.card-block` was the fourth
|
|
3223
3235
|
match. The trace held the selector and the four elements; the note held neither.
|
|
@@ -3258,14 +3270,15 @@ The three kinds are kept apart, because they mean different things. A FAILED req
|
|
|
3258
3270
|
a network error with Playwright's own text) is a cause. A request with NO RESPONSE RECORDED —
|
|
3259
3271
|
Playwright's `-1`, no error text — was still in flight when the test ended (the page closed under
|
|
3260
3272
|
it); listing it as a failure sent a run hunting an API that never answered anything wrong
|
|
3261
|
-
|
|
3273
|
+
The rest are the page's last answered requests.
|
|
3262
3274
|
|
|
3263
3275
|
A 4xx request carries what the page SENT beside its status, so a wrapped body is visible in one
|
|
3264
3276
|
line rather than inferred from the status; when one of those bodies is an object whose only key
|
|
3265
|
-
is `data`, the note names the call shape that produces it
|
|
3277
|
+
is `data`, the note names the call shape that produces it.
|
|
3266
3278
|
|
|
3267
3279
|
Every row opens with the test's LAST user action before the failing assertion and the requests
|
|
3268
3280
|
that action caused ({@link TraceArtifact.lastAction}) — started after it, before the assertion,
|
|
3281
|
+
the app's own API calls first, each with its status and the first 200 characters of its response,
|
|
3269
3282
|
|
|
3270
3283
|
_(description truncated — read the full text in `node_modules/@molecule/api-ai-tools/dist/trace-artifacts.d.ts`.)_
|
|
3271
3284
|
|
|
@@ -3293,7 +3306,7 @@ Whether a Playwright config records traces for the tests that fail.
|
|
|
3293
3306
|
|
|
3294
3307
|
Only `on` and `retain-on-failure` keep a `trace.zip` for a failure whatever the retries do: the
|
|
3295
3308
|
two retry modes need a retry to happen at all, and a diagnosis run is given `--retries=0`
|
|
3296
|
-
(`streamingBackgroundCommand`), so
|
|
3309
|
+
(`streamingBackgroundCommand`), so a run's own
|
|
3297
3310
|
`trace: 'on-first-retry'` recorded nothing — which is what left the failing tests' network log
|
|
3298
3311
|
unreadable. A config that sets no `trace:` at all records nothing either (Playwright's default
|
|
3299
3312
|
is off); so does one that cannot be read.
|
|
@@ -3332,14 +3345,15 @@ decide its own `--trace`, and whose config keeps no trace for its failures.
|
|
|
3332
3345
|
|
|
3333
3346
|
A run that can serve as PROOF is the exception: the graded measurement is the suite's own
|
|
3334
3347
|
settings, so it keeps its own tracing and retries. That was measured, not assumed — on one
|
|
3335
|
-
sandbox
|
|
3348
|
+
sandbox the same build ran a three-test deployed
|
|
3336
3349
|
subset 3/3 timed out under this flag (17.6–17.9 s against a 15 s per-test budget) and the whole
|
|
3337
3350
|
file passed 14/14 without it (10.9–12.1 s). `retain-on-failure` RETAINS only a failing test's
|
|
3338
3351
|
trace (Playwright's `_shouldAbandonTrace` unlinks a passing test's), but it RECORDS every
|
|
3339
3352
|
action of every test, and for a test near its per-test budget that recording is the difference
|
|
3340
|
-
between passing and timing out.
|
|
3353
|
+
between passing and timing out. This flag was added for exactly that failure: its
|
|
3341
3354
|
deployed proof run left only an `error-context.md` because the suite traces
|
|
3342
3355
|
`on-first-retry` and the run had no retries. That need is met without the flag — the graded
|
|
3356
|
+
deployed run keeps the suite's own retries, so a failing test leaves its retry's trace — and
|
|
3343
3357
|
|
|
3344
3358
|
_(description truncated — read the full text in `node_modules/@molecule/api-ai-tools/dist/trace-artifacts.d.ts`.)_
|
|
3345
3359
|
|
|
@@ -3543,7 +3557,7 @@ function outputIsWithheldUntilExit(command: string): boolean
|
|
|
3543
3557
|
The file a command sends its own output to, when it redirects it (`> out.txt`,
|
|
3544
3558
|
`>> log`, `&> run.log`, `| tee [-a] file`), or null. A background command that does
|
|
3545
3559
|
this leaves its task log empty, so the log is the wrong place to look and an empty
|
|
3546
|
-
log proves nothing
|
|
3560
|
+
log proves nothing.
|
|
3547
3561
|
|
|
3548
3562
|
Which redirect counts is decided by the command's own shell structure, from the same
|
|
3549
3563
|
parse every other command reader uses: a redirect written in a BACKGROUNDED statement
|
|
@@ -3551,7 +3565,7 @@ parse every other command reader uses: a redirect written in a BACKGROUNDED stat
|
|
|
3551
3565
|
the command's. The platform's own preview launch is exactly that — the preview server is
|
|
3552
3566
|
started with `>/tmp/mol-preview-4173.log 2>&1 &` inside the build/serve prelude, and the
|
|
3553
3567
|
suite's foreground command follows it — so a reader that took the last `>` in the whole
|
|
3554
|
-
text
|
|
3568
|
+
text tells a run its output went to the PREVIEW's log.
|
|
3555
3569
|
|
|
3556
3570
|
The target comes back without its shell quotes: `> '/tmp/x.log'` is `/tmp/x.log`, and
|
|
3557
3571
|
the callers resolve a relative one against the command's cwd.
|
|
@@ -3569,7 +3583,7 @@ function outputRedirectTarget(command: string): string | null
|
|
|
3569
3583
|
Rewrite a command about to run in the background so its log grows while it
|
|
3570
3584
|
runs. Two shapes left the log empty until exit, and an empty log is what
|
|
3571
3585
|
`wait_for_task` reads as "stuck", so working suites were reported stuck and
|
|
3572
|
-
killed (
|
|
3586
|
+
killed (one run lost 20 of its 60 minutes this way):
|
|
3573
3587
|
|
|
3574
3588
|
- a trailing `| tail -N`, which holds everything back until the command ends.
|
|
3575
3589
|
It is dropped: `wait_for_task` already returns the end of the log.
|
|
@@ -3577,7 +3591,7 @@ killed (X1 run flash-m15 lost 20 of its 60 minutes this way, 2026-10-15):
|
|
|
3577
3591
|
failing test's own error and leaves the pipeline's exit status — the filter's — as the run's.
|
|
3578
3592
|
Every such stage is dropped from EVERY suite run in the command, not only the last
|
|
3579
3593
|
({@link stripTrailingSuiteFilters}); `wait_for_task` already returns the end of the full log,
|
|
3580
|
-
and a run whose tally shows a failure must never report 0
|
|
3594
|
+
and a run whose tally shows a failure must never report 0.
|
|
3581
3595
|
- `playwright test` with no `--reporter`, which runs the config's reporter —
|
|
3582
3596
|
often `html`, which prints nothing per test. `--reporter=list` is added
|
|
3583
3597
|
when the playwright run is the command's last step, piped or not: it writes each result as
|
|
@@ -3594,11 +3608,16 @@ function streamingBackgroundCommand(
|
|
|
3594
3608
|
command: string,
|
|
3595
3609
|
context?: DiagnosisRunContext,
|
|
3596
3610
|
reportPath?: string,
|
|
3597
|
-
): {
|
|
3611
|
+
): {
|
|
3612
|
+
command: string
|
|
3613
|
+
changes: string[]
|
|
3614
|
+
reportPath?: string
|
|
3615
|
+
error?: string
|
|
3616
|
+
}
|
|
3598
3617
|
```
|
|
3599
3618
|
|
|
3600
3619
|
- `command` — The command as the executor sent it.
|
|
3601
|
-
- `context` — What the caller knows beyond the command: the tests the person's request excludes by name, and whether this command IS the platform's graded proof ({@link DiagnosisRunContext}). A `--grep-invert` of exactly those exclusions is the request's own scope, not a diagnosis, so it keeps the suite's retries on a deployed proof
|
|
3620
|
+
- `context` — What the caller knows beyond the command: the tests the person's request excludes by name, and whether this command IS the platform's graded proof ({@link DiagnosisRunContext}). A `--grep-invert` of exactly those exclusions is the request's own scope, not a diagnosis, so it keeps the suite's retries on a deployed proof — and a proof the platform itself composed and launched keeps them whatever its scope, targeted set included.
|
|
3602
3621
|
- `reportPath` — Where this run should write Playwright's standard `json` report, when the caller keeps one ({@link ./playwright-report.js}). The reporter is added to the run's own reporter set, never in place of one, and its output goes to that file through `PLAYWRIGHT_JSON_OUTPUT_FILE` — so the log, the executors' own reporters and every verdict stay exactly as they are. Omitted, or a run whose reporter set is not this function's to place (already names `json`, sets the variable itself, or whose runner cannot be located), leaves the command untouched and the result's `reportPath` unset.
|
|
3603
3622
|
|
|
3604
3623
|
**Returns:** The command to run, one sentence per change made (empty when none), and the report path when one was actually wired — or `error` when the command starts the suite more than once.
|
|
@@ -3670,7 +3689,7 @@ function isSuiteRunCommand(command: string): boolean
|
|
|
3670
3689
|
Refuse only a command made entirely of identical suite invocations.
|
|
3671
3690
|
|
|
3672
3691
|
Mixed shell commands execute as written. Rebuilding their prefix or suffix can lose writes,
|
|
3673
|
-
break heredoc delimiters or turn an && guard into unconditional work
|
|
3692
|
+
break heredoc delimiters or turn an && guard into unconditional work. Different args
|
|
3674
3693
|
or environments may select different suites or targets; they are not known duplicates either.
|
|
3675
3694
|
This is an optimization, so uncertainty always allows the original command.
|
|
3676
3695
|
|
|
@@ -3688,8 +3707,8 @@ A command with the supplied suite's own settings written back onto its runner as
|
|
|
3688
3707
|
flags, and the flags that could not be placed.
|
|
3689
3708
|
|
|
3690
3709
|
The grader walks the suite under its OWN budget, so a run whose runner config sets a different
|
|
3691
|
-
timeout or worker count measures a run the grader never sees (
|
|
3692
|
-
|
|
3710
|
+
timeout or worker count measures a run the grader never sees (a 60 s wrapper config produced
|
|
3711
|
+
a green local proof the official 15 s grader then failed). Playwright
|
|
3693
3712
|
lets a command-line flag win over every config file, so the suite's values are put on the
|
|
3694
3713
|
runner's own arguments — written where {@link statementArgumentEnd} places them, never after a
|
|
3695
3714
|
pipe, redirect or group closer. Only the command's LAST suite step is touched: that is the run
|
|
@@ -3747,10 +3766,13 @@ bound that was lifted.
|
|
|
3747
3766
|
Used where the platform moves a run to the background: the executor wrote the bound to fit this
|
|
3748
3767
|
tool's foreground ceiling, and in the background that ceiling no longer applies — the task is
|
|
3749
3768
|
bounded by `wait_for_task` and the turn's deadline — so the prefix only kills the walk
|
|
3750
|
-
({@link withoutTimeoutWrapper}
|
|
3769
|
+
({@link withoutTimeoutWrapper}).
|
|
3751
3770
|
|
|
3752
3771
|
```typescript
|
|
3753
|
-
function withoutSuiteTimeout(command: string): {
|
|
3772
|
+
function withoutSuiteTimeout(command: string): {
|
|
3773
|
+
command: string
|
|
3774
|
+
seconds: number | null
|
|
3775
|
+
}
|
|
3754
3776
|
```
|
|
3755
3777
|
|
|
3756
3778
|
- `command` — The shell command.
|
|
@@ -3763,7 +3785,7 @@ Whether a command starts a Playwright run — a `playwright test` in command pos
|
|
|
3763
3785
|
that runs something.
|
|
3764
3786
|
|
|
3765
3787
|
`npx playwright test --list` matched every `\bplaywright\s+test\b` test in the platform and was
|
|
3766
|
-
then treated as a run: held (
|
|
3788
|
+
then treated as a run: held (a config check), backgrounded for a run that outlasts
|
|
3767
3789
|
the tool's ceiling, and rewritten with `--reporter`. A list takes two seconds, prints its lines
|
|
3768
3790
|
and exits, so it is none of those; {@link commandRunsNoTests} is what decides.
|
|
3769
3791
|
|
|
@@ -3799,8 +3821,8 @@ Where the suite runner's exit code comes from: the runner itself, or a stage pip
|
|
|
3799
3821
|
code a finished run reports is its LAST pipeline stage's, so a stage after the runner makes the
|
|
3800
3822
|
code the stage's — but only when such a stage EXISTS. The platform used to report "piped" for
|
|
3801
3823
|
any run whose statements it could not place in the text, which one heredoc body was enough to
|
|
3802
|
-
cause:
|
|
3803
|
-
|
|
3824
|
+
cause: a config written in the same `exec_command` made the run come back with no exit code
|
|
3825
|
+
at all, and the note under it claimed a stage after the
|
|
3804
3826
|
runner that was not there. The parse now places every statement (`locatedCommandSegments`), so
|
|
3805
3827
|
"unplaced" is the rare, named case rather than a guess dressed as an answer.
|
|
3806
3828
|
|
|
@@ -3832,10 +3854,9 @@ Start a background suite run at lower CPU and IO priority, so the sandbox it
|
|
|
3832
3854
|
shares with everything else stays responsive to what the executor does next.
|
|
3833
3855
|
|
|
3834
3856
|
A whole-suite Playwright run saturates the one container the app's Vite
|
|
3835
|
-
server, its API process and every other command also live in:
|
|
3836
|
-
the
|
|
3837
|
-
|
|
3838
|
-
measured on the chat payload and on the live-stream follower independently.
|
|
3857
|
+
server, its API process and every other command also live in: a backgrounded 139-test run
|
|
3858
|
+
has left the two-word shell command sent next — tick its plan file — returning nothing for
|
|
3859
|
+
2 min 40 s, measured on the chat payload and on the live-stream follower independently.
|
|
3839
3860
|
The backgrounding note is right that the executor should go do other work;
|
|
3840
3861
|
what it cannot promise is that the sandbox will let it.
|
|
3841
3862
|
|
|
@@ -3866,8 +3887,8 @@ Check if a command is blocked for security reasons. Returns error message or nul
|
|
|
3866
3887
|
The first check reads the commands the shell actually RUNS — the statements, a `sh -c`
|
|
3867
3888
|
string's body, and every command substitution ({@link executedCommands}) — so a `|` inside a
|
|
3868
3889
|
quoted grep alternation is data, not a pipeline: `grep -E "USER CALLS|ENV|BUTTON|passed|failed"
|
|
3869
|
-
app.log` prints log lines, and the `ENV` in its pattern
|
|
3870
|
-
|
|
3890
|
+
app.log` prints log lines, and the `ENV` in its pattern starts nothing — a text
|
|
3891
|
+
match would block exactly that call as an environment dump, twice over. What the
|
|
3871
3892
|
shell DOES run stays visible through the same walk: `ls | env`, `bash -c 'env'`,
|
|
3872
3893
|
`echo "$(printenv)"` and a nested `sh -c 'x; env'` are all commands, and so is `env` itself
|
|
3873
3894
|
when nothing follows it.
|
|
@@ -3901,8 +3922,7 @@ Whether a tool path points outside the project root once normalized (an
|
|
|
3901
3922
|
absolute path elsewhere, or a `..` that climbs out). {@link resolvePath}
|
|
3902
3923
|
clamps such a path to the root; a file tool must refuse it instead of
|
|
3903
3924
|
answering about the root — a `list_files /tmp/x` used to return the
|
|
3904
|
-
workspace listing as if it were `/tmp/x
|
|
3905
|
-
2026-10-14).
|
|
3925
|
+
workspace listing as if it were `/tmp/x`.
|
|
3906
3926
|
|
|
3907
3927
|
```typescript
|
|
3908
3928
|
function isOutsideRoot(path: string, projectRoot: string): boolean
|
|
@@ -3913,6 +3933,34 @@ function isOutsideRoot(path: string, projectRoot: string): boolean
|
|
|
3913
3933
|
|
|
3914
3934
|
**Returns:** True when the path leaves the root.
|
|
3915
3935
|
|
|
3936
|
+
#### `commandStartsWithCdInto(command, directory, projectRoot)`
|
|
3937
|
+
|
|
3938
|
+
Whether a command's FIRST statement already changes into `directory`.
|
|
3939
|
+
|
|
3940
|
+
`exec_command` refuses a `cwd` outside the workspace, and that refusal tells
|
|
3941
|
+
the caller to drop `cwd` and start the command with `cd <path> && `. When the
|
|
3942
|
+
command ALREADY starts that way the advice describes what was just sent, so
|
|
3943
|
+
the command runs as written with the backend's working directory at the root
|
|
3944
|
+
instead (`{cwd: "/tmp", command: "cd /tmp && …"}` was refused with "start the command with
|
|
3945
|
+
`cd /tmp && `"; the same command resent with `cwd: "/workspace"` then passes).
|
|
3946
|
+
|
|
3947
|
+
Only the leading statement counts, only when the shell's own parse puts it in
|
|
3948
|
+
the caller's shell — a `( cd … )` group or a `sh -c '…'` runs in its own
|
|
3949
|
+
directory and moves nothing — and only when it ends the way a following
|
|
3950
|
+
command needs (`&&`, `;`, a newline, or nothing after it). `cd … | cat` is a
|
|
3951
|
+
pipeline, so its `cd` runs in a subshell, and `&` backgrounds it: neither
|
|
3952
|
+
leaves the caller's directory changed.
|
|
3953
|
+
|
|
3954
|
+
```typescript
|
|
3955
|
+
function commandStartsWithCdInto(command: string, directory: string, projectRoot: string): boolean
|
|
3956
|
+
```
|
|
3957
|
+
|
|
3958
|
+
- `command` — The shell command as the tool received it.
|
|
3959
|
+
- `directory` — The `cwd` the caller asked for.
|
|
3960
|
+
- `projectRoot` — The project root a relative path is resolved against.
|
|
3961
|
+
|
|
3962
|
+
**Returns:** True when the command's first statement `cd`s into `directory`.
|
|
3963
|
+
|
|
3916
3964
|
#### `isValidGlob(pattern)`
|
|
3917
3965
|
|
|
3918
3966
|
Validate that a glob/include pattern is safe (no shell metacharacters that could
|
|
@@ -3943,8 +3991,8 @@ expanded pattern.
|
|
|
3943
3991
|
Neither search tool expands braces itself: `grep --include` and `find` take
|
|
3944
3992
|
the pattern as a single shell-quoted argument, so no shell ever sees it.
|
|
3945
3993
|
`find_files {pattern:"*.{ts,tsx}"}` and `search_files {include:"*.{ts,tsx}"}`
|
|
3946
|
-
were both refused outright
|
|
3947
|
-
|
|
3994
|
+
were both refused outright, costing a round trip and pushing the agent to a narrower
|
|
3995
|
+
search. The group is expanded here
|
|
3948
3996
|
instead — `search_files` passes one `--include` per alternative and
|
|
3949
3997
|
`find_files` ORs one `-name`/`-path` predicate per alternative.
|
|
3950
3998
|
|
|
@@ -3967,8 +4015,8 @@ The `find` predicate for a `find_files` pattern.
|
|
|
3967
4015
|
|
|
3968
4016
|
`find -name` compares a pattern against a file's BASENAME, so a pattern
|
|
3969
4017
|
containing a slash (`helpers/*`, `e2e/*.spec.ts`, `src` + `**` + `/App.tsx`)
|
|
3970
|
-
can never match and the tool answers `[]` (
|
|
3971
|
-
|
|
4018
|
+
can never match and the tool answers `[]` (twice in one run). Such a pattern is matched
|
|
4019
|
+
with `-path` instead: an fnmatch
|
|
3972
4020
|
glob over the whole printed path, whose `*` crosses `/` — the rule
|
|
3973
4021
|
`.gitignore` uses, and the reason a bare `helpers/*` means "a `helpers/`
|
|
3974
4022
|
directory anywhere below the root". The pattern is anchored with a leading
|
|
@@ -4019,14 +4067,14 @@ anchor ({@link findPatternArgs}), so `find` visits every entry below the
|
|
|
4019
4067
|
search root. Handed `/workspace/node_modules` and
|
|
4020
4068
|
`@molecule/api-resource-user/dist/*.d.ts` — a directory named outright —
|
|
4021
4069
|
`find` walked the sandbox's entire dependency tree and hit the tool's 10 s
|
|
4022
|
-
deadline without printing a result (
|
|
4023
|
-
|
|
4070
|
+
deadline without printing a result (the one directory the model meant answered a `list_files`
|
|
4071
|
+
in 0 s). The literal prefix is that
|
|
4024
4072
|
directory, and rooting the search at it is what keeps the call instant.
|
|
4025
4073
|
|
|
4026
4074
|
A BARE first segment (`helpers/*`, `bonds/*`, `e2e/*.spec.ts`) is NOT one:
|
|
4027
4075
|
`helpers/*` means "a `helpers/` directory anywhere below the root", which the
|
|
4028
|
-
tool documents and a live run relied on (
|
|
4029
|
-
|
|
4076
|
+
tool documents and a live run relied on (a path pattern is not anchored to one depth).
|
|
4077
|
+
Rooting those at
|
|
4030
4078
|
`<root>/helpers` would answer with a SUBSET, silently: the nested
|
|
4031
4079
|
`api/src/helpers/` matches would disappear, and a missing file reads as
|
|
4032
4080
|
"no such file". So a prefix is returned only when it names a path of two or
|
|
@@ -4055,7 +4103,7 @@ The E2B SDK answers a timed-out `exec` with its generic text —
|
|
|
4055
4103
|
`[deadline_exceeded] the operation timed out: … It can be modified by passing
|
|
4056
4104
|
'timeoutMs' when making the request. Use '0' to disable the timeout.` — which
|
|
4057
4105
|
names an option the executor cannot set and says nothing about the search
|
|
4058
|
-
that died. Handing that sentence to the model is what
|
|
4106
|
+
that died. Handing that sentence to the model is what a run
|
|
4059
4107
|
read after `find_files` spent 10 s walking `node_modules`; the tool answers
|
|
4060
4108
|
the deadline in its own words instead (see {@link searchTimeoutError}).
|
|
4061
4109
|
|
|
@@ -4116,8 +4164,8 @@ shape a truncated provider stream leaves behind.
|
|
|
4116
4164
|
|
|
4117
4165
|
The path message is the wrong reading of it: "requires a non-empty path
|
|
4118
4166
|
argument" says the call was understood and the path was left out, so the model
|
|
4119
|
-
retries the call it just made instead of sending the whole call again (
|
|
4120
|
-
|
|
4167
|
+
retries the call it just made instead of sending the whole call again (`edit_file {}` loses
|
|
4168
|
+
one round). An empty object and a
|
|
4121
4169
|
missing `path` are different failures and deserve different sentences.
|
|
4122
4170
|
|
|
4123
4171
|
```typescript
|
|
@@ -4282,9 +4330,8 @@ The shell command whose stdout is the interesting part of a log that is still be
|
|
|
4282
4330
|
the failure lines so far (capped at {@link RUNNING_FAILURE_LINES}), then the end of the log.
|
|
4283
4331
|
|
|
4284
4332
|
A Playwright `list` run prints one line per test as it finishes, so the LAST bytes of a running
|
|
4285
|
-
log are its least informative part —
|
|
4286
|
-
|
|
4287
|
-
make anyway. A background run also carries each failure's own error as it fails
|
|
4333
|
+
log are its least informative part — the last 3 000 bytes of a 139-test walk are the skip
|
|
4334
|
+
list, and all 61 failures were above them, which costs the run the grep it has to make anyway. A background run also carries each failure's own error as it fails
|
|
4288
4335
|
({@link PLAYWRIGHT_FAILURES_INLINE_ENV}), and {@link RUNNING_FAILURE_LINE_RE} already matches
|
|
4289
4336
|
those blocks' headers and their `Error:` lines, so this slice shows the causes too.
|
|
4290
4337
|
|
|
@@ -4322,11 +4369,11 @@ function runningCauseCommand(log: string, own?: string): string
|
|
|
4322
4369
|
The shell command whose stdout is a bounded CONTIGUOUS read of a running task's own log: the
|
|
4323
4370
|
log's byte size, then its last {@link RUNNING_LOG_READ_BYTES} bytes.
|
|
4324
4371
|
|
|
4325
|
-
{@link runningOutputSliceCommand} is the wrong read for a diagnosis
|
|
4372
|
+
{@link runningOutputSliceCommand} is the wrong read for a diagnosis: it
|
|
4326
4373
|
stitches the first 40 grep-selected failure lines to the last 1 000 bytes with a blank line
|
|
4327
4374
|
between, so the tail is DISJOINT from the headers above it. Read as one log, the last numbered
|
|
4328
|
-
header absorbs whatever the tail starts with — a clipped skipped-test title
|
|
4329
|
-
a genuine failure
|
|
4375
|
+
header absorbs whatever the tail starts with — a clipped skipped-test title becomes the cause
|
|
4376
|
+
of a genuine failure. A contiguous window can only ever hold real
|
|
4330
4377
|
neighbouring lines of one log.
|
|
4331
4378
|
|
|
4332
4379
|
The size rides along so a caller can say when the window is only the log's end
|
|
@@ -4370,11 +4417,12 @@ log does NOT carry.
|
|
|
4370
4417
|
|
|
4371
4418
|
Either way the point is the same: a suite whose failures repeat one cause spends its whole
|
|
4372
4419
|
runtime proving that one cause, and the executor watching it can be told so at the third
|
|
4373
|
-
failure instead of at the last.
|
|
4420
|
+
failure instead of at the last. Fifteen tests walked in 4.0 minutes where 15.6 s
|
|
4374
4421
|
each was the test timeout and one missing `navigate('/')` was the cause of all of them.
|
|
4375
4422
|
|
|
4376
4423
|
The quorum is of DISTINCT tests — {@link REPEATING_FAILURE_MIN} of them — because a log that
|
|
4377
|
-
prints each failure twice (a second reporter, a retry)
|
|
4424
|
+
prints each failure twice (a second reporter, a retry) has told a run that four of its
|
|
4425
|
+
tests failed the same way when two had, so the executor stopped a 139-test walk at test 21
|
|
4378
4426
|
|
|
4379
4427
|
_(description truncated — read the full text in `node_modules/@molecule/api-ai-tools/dist/utilities.d.ts`.)_
|
|
4380
4428
|
|
|
@@ -4406,8 +4454,7 @@ is one the reporter printed inline.
|
|
|
4406
4454
|
A body for a test the request EXCLUDES is not that evidence: its failure does not count for
|
|
4407
4455
|
this request ({@link matchingExcludedTitles}), so a wait that handed it over as the diagnostic
|
|
4408
4456
|
spent a model round trip and 8 k of partial log on a test the same result says to ignore —
|
|
4409
|
-
|
|
4410
|
-
walking.
|
|
4457
|
+
which a run has done twice while the platform's proof was still walking.
|
|
4411
4458
|
|
|
4412
4459
|
With `finalOnly`, only a failure the run has FINISHED with counts; a pending retry waits.
|
|
4413
4460
|
|
|
@@ -4431,8 +4478,8 @@ How many test FILES a Playwright run's own command narrows it to, or null when i
|
|
|
4431
4478
|
whole suite (or its selection cannot be read).
|
|
4432
4479
|
|
|
4433
4480
|
{@link universalCause}'s file threshold is written for a whole-suite run, which a narrowed run
|
|
4434
|
-
can never reach.
|
|
4435
|
-
|
|
4481
|
+
can never reach. A run that re-ran ONE spec file against a hand-started `vite preview` the
|
|
4482
|
+
browser could not reach had every test in it fail `page.goto: Timeout` —
|
|
4436
4483
|
but one file is below {@link UNIVERSAL_CAUSE_FILES}, so the wait sat out its entire 280 s
|
|
4437
4484
|
budget on a run that had already measured all it could.
|
|
4438
4485
|
|
|
@@ -4459,7 +4506,7 @@ The test is: the cause accounts for every failure the log names, it has hit the
|
|
|
4459
4506
|
threshold, and nothing has passed since its first failure. The threshold is
|
|
4460
4507
|
{@link UNIVERSAL_CAUSE_FILES} for a whole-suite run but the number of files the command
|
|
4461
4508
|
SELECTED for a narrowed one ({@link specFilesSelected}): a one-file run can never span three,
|
|
4462
|
-
and
|
|
4509
|
+
and a run can wait out its whole budget on exactly that shape. An app
|
|
4463
4510
|
that is not up, a 5xx on every request, or a selector that is missing on every page all look
|
|
4464
4511
|
like that, and every remaining test will fail the same way — so the run's remaining minutes
|
|
4465
4512
|
measure nothing. A CONNECTION-class cause ({@link CONNECTION_CAUSE}) needs no file span at all:
|
|
@@ -4468,8 +4515,8 @@ case however few files the run walks.
|
|
|
4468
4515
|
|
|
4469
4516
|
Anything less is NOT this: a cause that stops at one file of a multi-file run, or that leaves
|
|
4470
4517
|
other tests passing, or that shares the run with failures of another shape, leaves the run with
|
|
4471
|
-
something to say, and the run is the only thing that will say it.
|
|
4472
|
-
|
|
4518
|
+
something to say, and the run is the only thing that will say it. Stopping runs at their first
|
|
4519
|
+
repeating cause has burned eight local runs over 14.5 minutes without finishing
|
|
4473
4520
|
one; three of its deploys each fixed a single cause that a finished run would have listed
|
|
4474
4521
|
alongside the others.
|
|
4475
4522
|
|
|
@@ -4498,16 +4545,17 @@ Both halves are load-bearing, each of them learned from a run that lost minutes
|
|
|
4498
4545
|
spec-file threshold — {@link UNIVERSAL_CAUSE_FILES}, or the files a narrowed run's own
|
|
4499
4546
|
command selects, or {@link CONNECTION_CAUSE_TESTS} tests of an app that never answered — with
|
|
4500
4547
|
nothing passing since the first. That is the
|
|
4501
|
-
dont-stop-runs rule.
|
|
4502
|
-
|
|
4548
|
+
dont-stop-runs rule. Stopping runs at their first repeating cause has burned eight local
|
|
4549
|
+
runs in 14.5 minutes without finishing one, and a run that still has other causes
|
|
4503
4550
|
left to name is the only thing that will name them.
|
|
4504
4551
|
- **A PROVEN cause** is an error repeated VERBATIM. A shared DURATION is a LEAD, never a cause:
|
|
4505
4552
|
a suite whose config sets a timeout spends that timeout on every failure that waits for
|
|
4506
4553
|
anything, so three unrelated tests timing out together look exactly like one broken run
|
|
4507
|
-
(`~7 s` is a property of the CONFIG, not of the cause — {@link normalizedSignature}).
|
|
4508
|
-
|
|
4554
|
+
(`~7 s` is a property of the CONFIG, not of the cause — {@link normalizedSignature}). A run
|
|
4555
|
+
told `status: 'repeating_failure'` twice on that
|
|
4509
4556
|
shape — three `url-navigation.spec.ts` tests at ~16.2 s, one `timeout: 15_000` plus teardown
|
|
4510
4557
|
— read the early return as "stop waiting, edit now", and voided a run that was still walking;
|
|
4558
|
+
the second cost a 224 s wait that ended with no result at all.
|
|
4511
4559
|
|
|
4512
4560
|
_(description truncated — read the full text in `node_modules/@molecule/api-ai-tools/dist/utilities.d.ts`.)_
|
|
4513
4561
|
|
|
@@ -4532,12 +4580,11 @@ The request quotes a test's own title (`… except "should require login to post
|
|
|
4532
4580
|
extracted by molecule-dev's `excludedTestTitles`) while a run's heading carries more of it
|
|
4533
4581
|
(`comments.spec.ts › Comments › should require login to post comment`), so containment is the
|
|
4534
4582
|
comparison. Whitespace is normalised and case is ignored: a brief may wrap the title across a
|
|
4535
|
-
line
|
|
4583
|
+
line, and the reporter's own casing never has to match the brief's.
|
|
4536
4584
|
|
|
4537
4585
|
Two readers used to answer this separately — the causes note (which therefore asked the
|
|
4538
4586
|
executor to fix a test the same result said not to) and molecule-dev's exclusion notes — and
|
|
4539
|
-
|
|
4540
|
-
test).
|
|
4587
|
+
a run paid for the gap (a turn and an edit spent on the excluded test).
|
|
4541
4588
|
|
|
4542
4589
|
```typescript
|
|
4543
4590
|
function matchingExcludedTitles(heading: string, excluded: readonly string[]): string[]
|
|
@@ -4555,7 +4602,7 @@ tests it hit.
|
|
|
4555
4602
|
|
|
4556
4603
|
The point is that ONE run yields EVERY cause. A Playwright report prints its failures one
|
|
4557
4604
|
after another with no statement of which of them share a cause, so a run of 19 failures is 19
|
|
4558
|
-
bodies to read;
|
|
4605
|
+
bodies to read; three deploys (6.7 minutes) each fixed a
|
|
4559
4606
|
single cause, two of them found by runs stopped before they walked the rest.
|
|
4560
4607
|
|
|
4561
4608
|
The signature is the cause itself where the log carries the failures' bodies (a finished run, a
|
|
@@ -4567,8 +4614,8 @@ proven cause. A test the log printed twice, or failed twice, is one test.
|
|
|
4567
4614
|
A test the request EXCLUDES by name is not a cause to fix: its failure does not count for
|
|
4568
4615
|
this request ({@link matchingExcludedTitles}), so it is dropped here rather than handed to the
|
|
4569
4616
|
executor as work — a result that names it beside "it does not count" is the contradiction
|
|
4570
|
-
|
|
4571
|
-
|
|
4617
|
+
a run filed (the model spent a turn and an edit on the excluded test, on a page that was
|
|
4618
|
+
passing).
|
|
4572
4619
|
|
|
4573
4620
|
```typescript
|
|
4574
4621
|
function failuresByCause(log: string, excluded?: readonly string[]): FailureCause[]
|
|
@@ -4597,7 +4644,7 @@ function requiredLandmark(selector: string): RequiredLandmark | null
|
|
|
4597
4644
|
The sentence for a run whose navigational elements are all missing from pages that otherwise
|
|
4598
4645
|
painted — the missing shared header the executor must check BEFORE rewriting auth.
|
|
4599
4646
|
|
|
4600
|
-
|
|
4647
|
+
A run had four failures on `/` — `a[href="/profile/…"]`,
|
|
4601
4648
|
`a.navbar-brand`, `nav a[href="/"]`, `nav .user-pic` — while every `error-context.md` snapshot
|
|
4602
4649
|
showed the feed, sidebar and footer with no navigation at all. `Home.tsx` imported and
|
|
4603
4650
|
re-exported `Navbar` but never rendered it, and `App.tsx` mounted `<Home />` in a bare route.
|
|
@@ -4691,7 +4738,7 @@ function rerunOfRunningSuite(
|
|
|
4691
4738
|
): string | null
|
|
4692
4739
|
```
|
|
4693
4740
|
|
|
4694
|
-
- `run` — The run in flight: the command it was started with, as it was run, the directory that command ran in, the config it loaded when the caller knows it, and the settings the request required and the run left out (`env`) — the re-run carries them, so it never reproduces the configuration the run was measured under by mistake
|
|
4741
|
+
- `run` — The run in flight: the command it was started with, as it was run, the directory that command ran in, the config it loaded when the caller knows it, and the settings the request required and the run left out (`env`) — the re-run carries them, so it never reproduces the configuration the run was measured under by mistake.
|
|
4695
4742
|
- `locations` — The failing `file:line`s to re-run, as the run's log printed them.
|
|
4696
4743
|
- `excluded` — The test titles the request carves out: the re-run inverts them out (`--grep-invert`) so it cannot report them again.
|
|
4697
4744
|
|
|
@@ -4708,17 +4755,18 @@ tests, so the note never names one or two tests as a cause.
|
|
|
4708
4755
|
The note names the cause early so the executor can START FIXING while the run keeps walking,
|
|
4709
4756
|
and it hands a stop command over only when {@link earlyReturnCause} says so — the SAME
|
|
4710
4757
|
predicate the wait uses to decide whether to return early, so a finding the wait keeps waiting
|
|
4711
|
-
on is a finding this note never asks to stop for.
|
|
4758
|
+
on is a finding this note never asks to stop for. One run spent 4.0 minutes
|
|
4712
4759
|
walking 15 tests whose one cause was certain at the third, 47 s in, and the note answers
|
|
4713
|
-
exactly that;
|
|
4760
|
+
exactly that; another stopped eight runs at their first repeating cause in 14.5
|
|
4714
4761
|
minutes and never finished one, so the note must not say to stop when the run still has other
|
|
4715
|
-
causes to name.
|
|
4762
|
+
causes to name. The third shape: a shared duration is
|
|
4716
4763
|
not a cause at all, so a lead reaches the executor as a note on a result it is still waiting
|
|
4717
4764
|
for — never as a verdict with a stop command in it.
|
|
4718
4765
|
|
|
4719
4766
|
The run is STILL WALKING while this note is written — both callers produce it mid-run — so a
|
|
4720
4767
|
re-run of one of its tests is a second run against the same app and database, and the platform
|
|
4721
4768
|
refuses that ({@link suiteRunInTheWay}, the same rule its overlap hold answers with):
|
|
4769
|
+
an executor read *"Start on them now, while the run keeps walking.
|
|
4722
4770
|
|
|
4723
4771
|
_(description truncated — read the full text in `node_modules/@molecule/api-ai-tools/dist/utilities.d.ts`.)_
|
|
4724
4772
|
|
|
@@ -4920,7 +4968,7 @@ Python WSGI server. Matched against a command segment's own text, and against a
|
|
|
4920
4968
|
when the command only names the script file — but NEVER against an inline program's code
|
|
4921
4969
|
(`node -e …`, `python3 -c …`), where this text is the user's program rather than a file being
|
|
4922
4970
|
run: `require('…/node_modules/vite')` imports a module, it does not start a dev server
|
|
4923
|
-
(
|
|
4971
|
+
(refused as "node starts a server" for exactly that line).
|
|
4924
4972
|
|
|
4925
4973
|
```typescript
|
|
4926
4974
|
const SERVER_PROGRAM: RegExp
|
|
@@ -4956,7 +5004,7 @@ this package's own input normalization, keep symbol-keyed properties, so the hos
|
|
|
4956
5004
|
survives the real launch path.
|
|
4957
5005
|
|
|
4958
5006
|
```typescript
|
|
4959
|
-
const PLATFORM_PROOF:
|
|
5007
|
+
const PLATFORM_PROOF: unique symbol
|
|
4960
5008
|
```
|
|
4961
5009
|
|
|
4962
5010
|
#### `SPLIT_WORK_ADVICE`
|
|
@@ -4974,14 +5022,13 @@ The closing advice on an over-budget message for a command that IS a suite run
|
|
|
4974
5022
|
(Playwright, Vitest, a `hurl` run — {@link isSuiteRunCommand}): its files are not
|
|
4975
5023
|
a bigger unit to break up.
|
|
4976
5024
|
|
|
4977
|
-
|
|
4978
|
-
|
|
4979
|
-
|
|
4980
|
-
|
|
4981
|
-
|
|
4982
|
-
|
|
4983
|
-
|
|
4984
|
-
300 s default per request holding the file, ten seconds past this tool's budget.
|
|
5025
|
+
The wrong advice here is "run a smaller unit": it is the wrong direction for a
|
|
5026
|
+
suite, and measurably so — a run stopped here reports NO tally, so nothing in
|
|
5027
|
+
the result says which test or request hung. The run has to be sent again in the
|
|
5028
|
+
background (off this budget, its output written to a log that can be read
|
|
5029
|
+
mid-run) or, when a consumer knows the runner's per-request limit, with each
|
|
5030
|
+
request bounded. One Hurl run lost 4.8 minutes to a single unanswered request
|
|
5031
|
+
held by hurl's 300 s default per request, ten seconds past this tool's budget.
|
|
4985
5032
|
|
|
4986
5033
|
```typescript
|
|
4987
5034
|
const SUITE_OVER_BUDGET_ADVICE: string
|
|
@@ -5048,7 +5095,7 @@ const MAX_TRACE_NOTE_REQUESTS: 4
|
|
|
5048
5095
|
|
|
5049
5096
|
How many times ONE test may send the same method+path before the note calls it a render loop.
|
|
5050
5097
|
|
|
5051
|
-
|
|
5098
|
+
An Editor effect with `[seeded, slug, t]` in its
|
|
5052
5099
|
dependency list re-fetched `GET /api/articles/<slug>` 2,106 times in one test. The trace reader
|
|
5053
5100
|
caps and de-duplicates its request list, so the note printed four identical `→ 200` lines and
|
|
5054
5101
|
the run patched the component's seeding, rebuilt and re-ran before unzipping the trace by hand.
|
|
@@ -5112,8 +5159,8 @@ reporter still prints each failure exactly once.
|
|
|
5112
5159
|
Every background command is given this (see {@link streamingBackgroundCommand}), so a suite the
|
|
5113
5160
|
executor starts through its own wrapper is covered too — the wrapper passes the environment on
|
|
5114
5161
|
to the Playwright process it spawns. Without it the log's only failure lines are `✘` rows:
|
|
5115
|
-
|
|
5116
|
-
|
|
5162
|
+
A run told to `grep -n -A 20 '<test name>'` the log got nothing back through four greps,
|
|
5163
|
+
inferred causes from the spec prose instead, and
|
|
5117
5164
|
edited `app/src` while the run was still walking — which voids the run.
|
|
5118
5165
|
|
|
5119
5166
|
```typescript
|
|
@@ -5198,9 +5245,8 @@ place, keeping ~30 KB of each end. A batched read that crossed it lost its
|
|
|
5198
5245
|
MIDDLE — the cut lands between two `"content"` values, so whole files fell
|
|
5199
5246
|
out and the note in their place said only "N characters cut here" — while
|
|
5200
5247
|
this tool's own note had promised each of those files that it "fits in one
|
|
5201
|
-
call, so it is not paged":
|
|
5202
|
-
|
|
5203
|
-
further calls (52,908 chars).
|
|
5248
|
+
call, so it is not paged": one batched read of ten e2e specs (121,467 chars) lost the
|
|
5249
|
+
middle six and bought them again in six further calls (52,908 chars).
|
|
5204
5250
|
|
|
5205
5251
|
So the CALL gets the ceiling the request gives it. Whole files are returned
|
|
5206
5252
|
up to it; the paths that did not fit are named in `note` and listed in
|
|
@@ -5247,7 +5293,7 @@ const MAX_READ_RETURN_CHARS: number
|
|
|
5247
5293
|
|
|
5248
5294
|
A file this small is returned whole on a second window of it (paging it costs a call each).
|
|
5249
5295
|
The same bound as {@link MAX_READ_RETURN_CHARS}: the windowed-read note promises that a
|
|
5250
|
-
file under it "fits in ONE call", and a smaller bound here
|
|
5296
|
+
file under it "fits in ONE call", and a smaller bound here breaks that promise.
|
|
5251
5297
|
|
|
5252
5298
|
```typescript
|
|
5253
5299
|
const SMALL_FILE_WHOLE_CHARS: number
|
|
@@ -5262,11 +5308,11 @@ an HTML read is almost never worth it.
|
|
|
5262
5308
|
An entry document is boilerplate the reader rarely needs in full: meta tags,
|
|
5263
5309
|
stylesheet and preload links, a `<style>` block, and a handful of `<script>`
|
|
5264
5310
|
tags. The parts an executor acts on — the body's structure, where a script is
|
|
5265
|
-
loaded — are all visible in an outline of one line per tag.
|
|
5266
|
-
63,735 chars
|
|
5311
|
+
loaded — are all visible in an outline of one line per tag. One such read paid
|
|
5312
|
+
63,735 chars: ~60 KB of it was the IDE's own preview bridges,
|
|
5267
5313
|
and the read pushed the transcript past its context cap, so the e2e specs the
|
|
5268
5314
|
executor had just read were trimmed to summaries and it read the whole suite
|
|
5269
|
-
again — twice
|
|
5315
|
+
again — twice. The scaffold now keeps those
|
|
5270
5316
|
bridges in separate files, but a template's own head is still ~5-12 KB, and a
|
|
5271
5317
|
static-site or SSR entry can be far more.
|
|
5272
5318
|
|
|
@@ -5396,8 +5442,8 @@ const TOOL_RESULT_CHARS: 8000
|
|
|
5396
5442
|
|
|
5397
5443
|
#### `FAILURE_CAUSES_CHARS`
|
|
5398
5444
|
|
|
5399
|
-
The characters a finished run's cause list may use of {@link TOOL_RESULT_CHARS}.
|
|
5400
|
-
|
|
5445
|
+
The characters a finished run's cause list may use of {@link TOOL_RESULT_CHARS}. A measured
|
|
5446
|
+
recap was `12 failures, 8 causes`: one cause line is
|
|
5401
5447
|
~200 chars and ~80 more with its two body lines, so 8 causes is ~2.3 k against the 8 k cap —
|
|
5402
5448
|
the old 5-cause cap withheld 3 causes that the same result had room for.
|
|
5403
5449
|
|
|
@@ -5447,7 +5493,7 @@ How many tests a run must have walked — with nothing passing since its first f
|
|
|
5447
5493
|
THREE, and the number is the cost of the alternative. The old floor of 15 was chosen when the
|
|
5448
5494
|
reading was only offered at a completed run; once it STOPS the walk, every test waited for is
|
|
5449
5495
|
a test whose result is thrown away, and a blank page costs its per-test budget each time
|
|
5450
|
-
(
|
|
5496
|
+
(18 tests, ~4.2 minutes, on a page whose thrown error was visible in the first
|
|
5451
5497
|
`pageerror`). Three is the smallest count that is not one page's own bug: the cause additionally
|
|
5452
5498
|
needs three DISTINCT spec files (`UNIVERSAL_CAUSE_FILES`, or the files a narrowed run selected),
|
|
5453
5499
|
no failure showing a locator RESOLVING ({@link ELEMENT_FOUND} — a blank page cannot resolve
|
|
@@ -5509,7 +5555,7 @@ Peer dependencies:
|
|
|
5509
5555
|
ceiling the request side puts on a single tool result: whole files are
|
|
5510
5556
|
returned up to it and every path past that is named in `note` and listed as
|
|
5511
5557
|
`not returned`, so a file is never handed back in part — the shape that lost
|
|
5512
|
-
the middle of a ten-file batch to the request-side cut
|
|
5558
|
+
the middle of a ten-file batch to the request-side cut. Each
|
|
5513
5559
|
entry carries its own content or its own error, so one bad path never fails
|
|
5514
5560
|
the batch.
|
|
5515
5561
|
- **`edit_file` shows the result, so the model need not re-read.** A
|
|
@@ -5535,7 +5581,7 @@ Peer dependencies:
|
|
|
5535
5581
|
added or removed and nothing else, the edit can only move text across lines —
|
|
5536
5582
|
joining the next line onto the replaced text, or pushing the rest of the line
|
|
5537
5583
|
down — which is what a weak model does by accident when it repeats a line it
|
|
5538
|
-
means to keep
|
|
5584
|
+
means to keep. The
|
|
5539
5585
|
replacement is skipped, the rest of the batch is applied, and the result
|
|
5540
5586
|
carries `skippedNote`: one line naming the replacement, what applying it would
|
|
5541
5587
|
have done, and how to say it on purpose (include the next line in `old_string`).
|