@molecule/api-ai-tools 1.8.2 → 1.9.1

This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
package/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-17T02:50:55.123Z
6
+ Generated: 2026-10-17T07:58:25.504Z
7
7
  -->
8
8
 
9
9
  # @molecule/api-ai-tools
@@ -115,6 +115,24 @@ interface LocatedCommandSegment {
115
115
  * inside a nested `sh -c` string, for the same reason as {@link start}.
116
116
  */
117
117
  assignmentOffset: number | null
118
+ /**
119
+ * The offset in the command one past the statement's last word — where an option of this
120
+ * statement's program belongs, before whatever closes it. Null inside a nested `sh -c` string.
121
+ */
122
+ end: number | null
123
+ /**
124
+ * The offset in the command of the word in command position — the program, once every wrapper
125
+ * in front of it is taken away (`npx --prefix /app <here>playwright test`). Null inside a
126
+ * nested `sh -c` string, and for a statement that only sets variables.
127
+ */
128
+ programOffset: number | null
129
+ /**
130
+ * The separator the shell split at immediately before this statement — `|`, `||`, `&&`, `;`,
131
+ * a newline or `&` — or '' when it is the first statement of the command. It is the parse's own
132
+ * answer, so it is known even where the offsets are not, and a caller deciding whether two
133
+ * statements are one pipeline (`|`, never `;`) asks it instead of reading the text between them.
134
+ */
135
+ separator: string
118
136
  }
119
137
  ```
120
138
 
@@ -179,6 +197,23 @@ interface CutRun {
179
197
  }
180
198
  ```
181
199
 
200
+ #### `RunFailureClass`
201
+
202
+ One failure a runner printed, classified by the layer that failed.
203
+
204
+ ```typescript
205
+ interface RunFailureClass {
206
+ /** The layer that failed. */
207
+ kind: RunFailureKind
208
+ /** For a `connection` failure, what the transport did. */
209
+ connection?: ConnectionFailureKind
210
+ /** How long the request waited before the transport gave up, in seconds, when printed. */
211
+ seconds?: number
212
+ /** The `file:line` the runner printed for the failure, when it printed one. */
213
+ at?: string
214
+ }
215
+ ```
216
+
182
217
  #### `NormalizableSchema`
183
218
 
184
219
  The JSON-Schema-ish shape every tool in this package declares.
@@ -235,6 +270,19 @@ interface ToolSchema {
235
270
  }
236
271
  ```
237
272
 
273
+ #### `LeadingSleep`
274
+
275
+ The leading `sleep` a command opens with, and the command that follows it.
276
+
277
+ ```typescript
278
+ interface LeadingSleep {
279
+ /** How many seconds the statement would have slept (GNU sleep sums its operands). */
280
+ seconds: number
281
+ /** What follows the leading statement, trimmed — '' when the sleep was the whole command. */
282
+ rest: string
283
+ }
284
+ ```
285
+
238
286
  #### `SuiteRunInFlight`
239
287
 
240
288
  One suite run, as the rule that decides whether a second may start beside it reads it.
@@ -258,6 +306,20 @@ interface SuiteRunInFlight {
258
306
  }
259
307
  ```
260
308
 
309
+ #### `InstalledPackageFacts`
310
+
311
+ What the filesystem says about a write target under `node_modules` — the half
312
+ of the decision a path's spelling cannot make.
313
+
314
+ ```typescript
315
+ interface InstalledPackageFacts {
316
+ /** Whether the `node_modules` entry the path goes through is a symbolic link. */
317
+ readonly symlink: boolean
318
+ /** Whether a package is really installed there: a `package.json` resolves under the entry. */
319
+ readonly installed: boolean
320
+ }
321
+ ```
322
+
261
323
  #### `TraceRequest`
262
324
 
263
325
  One request a traced page made, as `*.network` records it.
@@ -268,8 +330,43 @@ interface TraceRequest {
268
330
  method: string
269
331
  /** The request's path (`/api/articles/x/favorite`), or the whole URL when it is cross-origin. */
270
332
  path: string
271
- /** The response status, or 0 when the request never got a response. */
333
+ /**
334
+ * The response status as the trace recorded it. Playwright writes `-1` when a request was never
335
+ * answered (its HAR entry starts at `-1` and only a response event overwrites it); `0` is the
336
+ * same absence when the snapshot carried no response at all. Neither is a server failure.
337
+ */
272
338
  status: number
339
+ /**
340
+ * Playwright's own error text for a request that failed WITHOUT a response
341
+ * (`net::ERR_CONNECTION_REFUSED`) — a real failure. A request that got no response and recorded
342
+ * no text was aborted or still in flight when the test ended (the page closed under it), so it
343
+ * says nothing about the server (xr-molecule-flash-m112 +30:45).
344
+ */
345
+ failure?: string
346
+ /**
347
+ * What the page SENT, for a 4xx answered by the app's own API — bounded (see
348
+ * {@link MAX_TRACED_BODY_CHARS}). A body wrapped as `{"data":{…}}` is visible here in one line:
349
+ * app-http's verbs take the body as their second argument, so a helper that passes
350
+ * `{ data: body }` there ships the wrapper (xr-molecule-flash-m111 +11:36).
351
+ */
352
+ sent?: string
353
+ /** What came back for that 4xx, bounded the same way — the API's own error body. */
354
+ got?: string
355
+ }
356
+ ```
357
+
358
+ #### `TraceAction`
359
+
360
+ One action the traced page performed, with the trace's own timing for it.
361
+
362
+ ```typescript
363
+ interface TraceAction {
364
+ /** The Playwright API the entry names: `Frame.goto`, `Locator.fill`, `Locator.click`. */
365
+ api: string
366
+ /** When the action started, on the trace's own monotonic clock (ms). */
367
+ start: number
368
+ /** When it finished, or null when the run ended before it did. */
369
+ end: number | null
273
370
  }
274
371
  ```
275
372
 
@@ -287,6 +384,12 @@ interface TraceArtifact {
287
384
  requests: TraceRequest[]
288
385
  /** The console errors and page errors the page raised. */
289
386
  console: string[]
387
+ /**
388
+ * The page's own actions in the order the trace recorded them, bounded — what a test that ran
389
+ * out of a per-test budget spends its time on. A test that repeats one action prints it once per
390
+ * repeat, so the gap between two starts is one repeat's measured cost.
391
+ */
392
+ actions: TraceAction[]
290
393
  }
291
394
  ```
292
395
 
@@ -553,6 +656,27 @@ interface SuiteFilterStrip {
553
656
  }
554
657
  ```
555
658
 
659
+ #### `SuiteRunPipelinePlacement`
660
+
661
+ Whether a finished run's exit code belongs to a stage after the suite runner.
662
+
663
+ ```typescript
664
+ interface SuiteRunPipelinePlacement {
665
+ /**
666
+ * True when a pipe this tool must not drop still follows the suite runner: the code in the
667
+ * result is that stage's, not the run's.
668
+ */
669
+ piped: boolean
670
+ /**
671
+ * True when the suite (or a stage of its pipeline) sits inside a nested `sh -c '<command>'`
672
+ * string, so the parse cannot place it in the command's own text. The caller then says so
673
+ * plainly instead of implying a stage it can point at — and keeps the command's own code when
674
+ * no pipe follows the runner, because on that command the pipeline's last stage IS the run.
675
+ */
676
+ unplaced: boolean
677
+ }
678
+ ```
679
+
556
680
  #### `FailedTest`
557
681
 
558
682
  One failed test, as a running suite's log names it.
@@ -619,6 +743,20 @@ interface FailureCause {
619
743
  * for a duration group, whose blocks carried no bodies.
620
744
  */
621
745
  evidence: string[]
746
+ /**
747
+ * The suite's own per-test budget in ms, when the cause is the test-budget kill
748
+ * (`Test timeout of 15000ms exceeded`). The signature normalizes the number away
749
+ * ({@link normalizedSignature}) so equal causes group, and that number is the one fact that
750
+ * predicts a test spending its budget on a repeated action (xr-molecule-flash-m110 +20:44).
751
+ */
752
+ budgetMs?: number
753
+ /**
754
+ * The layer the failure came from ({@link classifyRunFailure}). A `connection` cause never
755
+ * reached the app, so it is NOT a cause the app's code can fix: the note says to re-run it
756
+ * once and read the app's log on a repeat, instead of sending a fix at a handler
757
+ * (xr-molecule-flash-m110 +18:42 rewrote a CORS middleware for a 20 s connection timeout).
758
+ */
759
+ kind: RunFailureKind
622
760
  }
623
761
  ```
624
762
 
@@ -650,6 +788,23 @@ type CutBy =
650
788
  | 'process-stop'
651
789
  ```
652
790
 
791
+ #### `RunFailureKind`
792
+
793
+ The layer a failure came from: the transport (no answer at all), the response's status, or an
794
+ assertion over a response that arrived.
795
+
796
+ ```typescript
797
+ type RunFailureKind = 'connection' | 'status' | 'assertion'
798
+ ```
799
+
800
+ #### `ConnectionFailureKind`
801
+
802
+ What the transport did when a request never got an answer.
803
+
804
+ ```typescript
805
+ type ConnectionFailureKind = 'timeout' | 'refused' | 'reset' | 'dns' | 'tls' | 'empty'
806
+ ```
807
+
653
808
  #### `DiscoveredSkill` _(deprecated)_
654
809
 
655
810
  Re-export SkillEntry as DiscoveredSkill for backwards compatibility.
@@ -658,6 +813,19 @@ Re-export SkillEntry as DiscoveredSkill for backwards compatibility.
658
813
  type DiscoveredSkill = SkillEntry
659
814
  ```
660
815
 
816
+ #### `InstalledPackageProbe`
817
+
818
+ Looks at the filesystem for {@link InstalledPackageFacts}.
819
+
820
+ The guard cannot `stat` the path itself: the tools act through a backend (a
821
+ sandbox over the network for the fleet), so the caller — which holds that
822
+ backend — supplies the look. {@link shellInstalledPackageProbe} builds one
823
+ from any shell runner.
824
+
825
+ ```typescript
826
+ type InstalledPackageProbe = (path: string) => Promise<InstalledPackageFacts>
827
+ ```
828
+
661
829
  ### Classes
662
830
 
663
831
  #### `ToolInputError`
@@ -922,6 +1090,36 @@ function cutRunSentence(run: CutRun): string
922
1090
 
923
1091
  **Returns:** The sentence.
924
1092
 
1093
+ #### `classifyRunFailure(text)`
1094
+
1095
+ Classify ONE failure's text — a Hurl `error:` block, or a Playwright failure message/body.
1096
+
1097
+ The transport is read first: a block that carries a connection error AND an assertion is a
1098
+ request whose assertion never ran, so it is a connection failure. Only a block that carries no
1099
+ failure signature at all answers null — unknown is never a connection failure, because a
1100
+ misread transport hides a real app failure behind "just re-run it".
1101
+
1102
+ ```typescript
1103
+ function classifyRunFailure(text: string): RunFailureClass | null
1104
+ ```
1105
+
1106
+ - `text` — One failure's text, as the runner printed it.
1107
+
1108
+ **Returns:** The classification, or null when the text carries no failure this reads.
1109
+
1110
+ #### `allConnectionFailures(failures)`
1111
+
1112
+ Whether every one of the classified failures is a connection failure — the only shape in which
1113
+ no response the app produced was measured.
1114
+
1115
+ ```typescript
1116
+ function allConnectionFailures(failures: readonly (RunFailureClass | null)[]): boolean
1117
+ ```
1118
+
1119
+ - `failures` — The run's classifications, in printed order.
1120
+
1121
+ **Returns:** True when there is at least one and none of them is the app's.
1122
+
925
1123
  #### `normalizeToolInput(schema, raw)`
926
1124
 
927
1125
  Move known aliases onto the declared parameter names and report what is still
@@ -1029,6 +1227,26 @@ function commandRunsNoTests(command: string): boolean
1029
1227
 
1030
1228
  **Returns:** True when the command invokes a runner only to print.
1031
1229
 
1230
+ #### `leadingSleepPeek(command)`
1231
+
1232
+ The leading `sleep` of a command, when the first statement is one and it asks for at least
1233
+ {@link MIN_PEEK_SLEEP_SECONDS}.
1234
+
1235
+ The statement is read by {@link locatedCommandSegments} — the same parse every other command
1236
+ classifier uses — so only a `sleep` in command position of the FIRST statement counts. The end
1237
+ of that statement is then found by walking forward from its own start: the statement is
1238
+ `sleep <duration>`, whose words carry no quotes and open no substitution, so the first unquoted
1239
+ `;`, newline or `&` ends it. A `|` is refused: dropping the left side of a pipeline would hand
1240
+ the right side its stdin instead, and a `||` fallback would run on a success that never did.
1241
+
1242
+ ```typescript
1243
+ function leadingSleepPeek(command: string): LeadingSleep | null
1244
+ ```
1245
+
1246
+ - `command` — The shell command the executor sent.
1247
+
1248
+ **Returns:** The seconds and the remaining command, or null when the command does not open with a long `sleep`.
1249
+
1032
1250
  #### `withoutHeredocs(command)`
1033
1251
 
1034
1252
  A command with its heredoc bodies removed: the runs, kills and hosts it names in a file it
@@ -1061,24 +1279,68 @@ function suiteCommandTarget(command: string): string
1061
1279
 
1062
1280
  **Returns:** The target key.
1063
1281
 
1064
- #### `scopedRerunCommand(command, locations, excluded)`
1282
+ #### `namesSuiteConfig(command)`
1283
+
1284
+ Whether a Playwright statement names its own config — the reading {@link withSuiteConfig} and
1285
+ {@link scopedRerunCommand} share, so neither adds a second `--config` to a command that has one.
1286
+
1287
+ ```typescript
1288
+ function namesSuiteConfig(command: string): boolean
1289
+ ```
1290
+
1291
+ - `command` — A command, or the Playwright statement inside it.
1292
+
1293
+ **Returns:** True when the statement loads a config of its own.
1294
+
1295
+ #### `withSuiteConfig(command, config)`
1296
+
1297
+ The command with a `--config` added to the Playwright invocation it starts — or unchanged when
1298
+ it already names one, or starts no Playwright run.
1299
+
1300
+ The flag rides the same statement the runner does: a `cd`, an env prefix and a `timeout` before
1301
+ it are left exactly as they were, and so is everything chained after the run (`| tail -50`).
1302
+
1303
+ xr-molecule-flash-m113 (+19:09): the model's fix-round re-run dropped the
1304
+ `--config playwright.conduit.config.ts` both earlier runs had carried, so Playwright started with
1305
+ NO base URL and all 10 failures were `page.goto: Cannot navigate to invalid URL` — a failure list
1306
+ that says nothing about the app. The platform composes commands back to the executor too (the
1307
+ narrowed re-run of a finished run's failures), and a command it hands back has to carry the
1308
+ config the run was measured under, never the shape that caused that finding.
1309
+
1310
+ ```typescript
1311
+ function withSuiteConfig(command: string, config: string | null | undefined): string
1312
+ ```
1313
+
1314
+ - `command` — The command as the executor sent it.
1315
+ - `config` — The config the run loads, when the caller knows it.
1316
+
1317
+ **Returns:** The command with the flag, or the command unchanged.
1318
+
1319
+ #### `scopedRerunCommand(command, locations, excluded, config)`
1065
1320
 
1066
1321
  The whole-suite command made scoped to the tests it should re-run instead: the same
1067
1322
  invocation — same directory, same settings — with the named `file:line`s in place of the whole
1068
1323
  suite, `--last-failed` dropped (it re-runs the tests that never ran too, X1 flash-m60) and
1069
1324
  `--retries=0` set (a re-run of a known failure does not need to pay for retries).
1070
1325
 
1326
+ `config` is the config the run was measured under ({@link withSuiteConfig}): the narrowed re-run
1327
+ carries it whenever the command itself does not, so a run that dropped `--config` cannot be
1328
+ handed back a command with the same defect (xr-molecule-flash-m113: every failing test was
1329
+ `Cannot navigate to invalid URL` because the re-run loaded no base URL).
1330
+
1071
1331
  ```typescript
1072
1332
  function scopedRerunCommand(
1073
1333
  command: string,
1074
1334
  locations: readonly string[],
1075
1335
  excluded?: readonly string[],
1336
+ config?: string | null,
1076
1337
  ): string
1077
1338
  ```
1078
1339
 
1079
1340
  - `command` — The whole-suite run's command.
1080
1341
  - `locations` — The failing `file:line`s to re-run, as the run's own log printed them — or, for a run that started outside the suite, the absolute form Playwright matches each file argument against.
1081
1342
  - `excluded` — The test titles the request carves out. They are inverted out (`--grep-invert`) so a re-run of the failing locations cannot report one of them again — xr-molecule-flash-m101 re-ran the whole 139-test suite and spent ~4 minutes to be told about a test the request had already said does not count.
1343
+ - `config` — The config the run loaded, when the caller knows it; added when the command does not name one.
1082
1344
 
1083
1345
  **Returns:** The scoped command, or the command unchanged when it runs no Playwright suite.
1084
1346
 
@@ -1213,10 +1475,26 @@ function moleculeDistReadNote(path: string): string | null
1213
1475
 
1214
1476
  **Returns:** The note, or null when the path is not inside a package's `dist`.
1215
1477
 
1216
- #### `installedPackageWriteRefusal(path)`
1478
+ #### `shellInstalledPackageProbe(run)`
1479
+
1480
+ Build an {@link InstalledPackageProbe} from a shell runner (a backend's
1481
+ `run`, or a sandbox's `exec`): one command reports whether the entry is a
1482
+ link and whether a `package.json` resolves under it.
1483
+
1484
+ ```typescript
1485
+ function shellInstalledPackageProbe(
1486
+ run: (command: string) => Promise<{ stdout?: string } | null | undefined>,
1487
+ ): InstalledPackageProbe
1488
+ ```
1489
+
1490
+ - `run` — Runs a command where the path lives.
1491
+
1492
+ **Returns:** The probe.
1217
1493
 
1218
- The refusal for a write whose target is inside an installed package, or null
1219
- when the path is not under a `node_modules` directory.
1494
+ #### `installedPackageWriteRefusal(path, probe)`
1495
+
1496
+ The refusal for a write whose target is inside an INSTALLED package, or null
1497
+ when the path is not under `node_modules` or nothing is installed there.
1220
1498
 
1221
1499
  `node_modules` is not the project's code: nothing written there survives the
1222
1500
  next install, no deploy carries it, and a sandbox whose dependency tree is
@@ -1229,17 +1507,29 @@ answered `ok: true`, and 18 s went to noticing, `npm pack`-ing the package and
1229
1507
  putting the file back. Reading these files stays allowed (that is how the
1230
1508
  declarations above are read at all).
1231
1509
 
1232
- The restore route is named because the model that has ALREADY clobbered a file
1233
- (this refusal is too late for it) is the one who needs it, and because the
1234
- obvious repair — `npm install <pkg>` — is itself refused in the pre-installed
1235
- sandbox. `npm pack` + a `tar` extraction over the package directory is what
1236
- m91 used, and what both guards leave alone.
1510
+ What is protected is the INSTALL, not the spelling: the decision comes from
1511
+ {@link InstalledPackageFacts}, never from the path alone (m106 above). Three
1512
+ things are the run's own to remove or replace —
1513
+
1514
+ - a `node_modules` that is a SYMLINK: `rm`/`unlink` removes the link, never the
1515
+ tree it points at, so a link the run made cannot clobber anything;
1516
+ - anything under the run's own `.mol-scratch/` directory;
1517
+ - a `node_modules` with no `package.json` under it (nothing was ever installed).
1518
+
1519
+ A path INSIDE the link is still decided by what resolves there: a link into a
1520
+ real tree is refused, because removing or writing through it reaches the
1521
+
1522
+ _(description truncated — read the full text in `node_modules/@molecule/api-ai-tools/dist/tools.d.ts`.)_
1237
1523
 
1238
1524
  ```typescript
1239
- function installedPackageWriteRefusal(path: string): string | null
1525
+ function installedPackageWriteRefusal(
1526
+ path: string,
1527
+ probe?: InstalledPackageProbe,
1528
+ ): Promise<string | null>
1240
1529
  ```
1241
1530
 
1242
1531
  - `path` — An absolute path a tool is about to write.
1532
+ - `probe` — Looks at the filesystem where the path lives.
1243
1533
 
1244
1534
  **Returns:** The one-line refusal naming the package, or null when nothing is installed there.
1245
1535
 
@@ -1268,10 +1558,17 @@ on `unzip` would make the read fail on every sandbox that has none. The zip is r
1268
1558
  central directory and `zlib.inflateRawSync` — about forty lines, and the only thing that has to
1269
1559
  be true of a `trace.zip` is that it IS one.
1270
1560
 
1271
- A request is kept over a static asset when it failed (`status >= 400`) or never answered
1272
- (`status === 0`), and over anything else when it is the page talking to the app
1273
- (`fetch`/`xhr`/`document`): a failing test's trace holds the whole page load, and the answer is
1274
- always at the end of it.
1561
+ A request is kept over a static asset when it failed — a `status >= 400`, or no response at all
1562
+ together with Playwright's own error text (`-1` plus `_failureText`, a refused connection) — and
1563
+ over anything else when it is the page talking to the app (`fetch`/`xhr`/`document`): a failing
1564
+ test's trace holds the whole page load. A request with no response and NO error text was aborted
1565
+ or still in flight when the test ended; it is kept too, but as what it is, not as a failure.
1566
+
1567
+ A request answered 4xx by the app's OWN API also keeps what the page SENT and the first of what
1568
+ came back: Playwright stores either inline (`text`) or in a resource entry (`_file`), and both
1569
+ are read. That is where a wrapped body shows: xr-molecule-flash-m111's helper passed
1570
+
1571
+ _(description truncated — read the full text in `node_modules/@molecule/api-ai-tools/dist/trace-artifacts.d.ts`.)_
1275
1572
 
1276
1573
  ```typescript
1277
1574
  function traceArtifactsScript(): string
@@ -1294,7 +1591,7 @@ function parseTraceArtifacts(stdout: string): TraceArtifact[]
1294
1591
 
1295
1592
  **Returns:** One entry per trace it printed.
1296
1593
 
1297
- #### `failureTraceNote(items, target)`
1594
+ #### `failureTraceNote(items, target, earlierFailures)`
1298
1595
 
1299
1596
  The note a failed suite run's result carries: what each failing test's page actually sent, and
1300
1597
  what came back.
@@ -1305,14 +1602,34 @@ with them: read the handler the route reaches, not the selector. It is BOUNDED t
1305
1602
  {@link MAX_TRACE_NOTE_TESTS} tests with {@link MAX_TRACE_NOTE_REQUESTS} requests each, because it
1306
1603
  rides in a result the model pays for.
1307
1604
 
1605
+ The three kinds are kept apart, because they mean different things. A FAILED request (4xx/5xx, or
1606
+ a network error with Playwright's own text) is a cause. A request with NO RESPONSE RECORDED —
1607
+ Playwright's `-1`, no error text — was still in flight when the test ended (the page closed under
1608
+ it); listing it as a failure sent a run hunting an API that never answered anything wrong
1609
+ (xr-molecule-flash-m112 +30:45). The rest are the page's last answered requests.
1610
+
1611
+ A 4xx request carries what the page SENT beside its status, so a wrapped body is visible in one
1612
+ line rather than inferred from the status; when one of those bodies is an object whose only key
1613
+ is `data`, the note names the call shape that produces it (xr-molecule-flash-m111 +11:36).
1614
+
1615
+ WHICH rows it spends is evidence, not artifact order (xr-molecule-flash-m112 +53:46): a row
1616
+ needs a recorded response, a real failure or a console error ({@link traceRowEvidence}), rows are
1617
+
1618
+ _(description truncated — read the full text in `node_modules/@molecule/api-ai-tools/dist/trace-artifacts.d.ts`.)_
1619
+
1308
1620
  ```typescript
1309
- function failureTraceNote(items: readonly TraceArtifact[], target: string): string | null
1621
+ function failureTraceNote(
1622
+ items: readonly TraceArtifact[],
1623
+ target: string,
1624
+ earlierFailures?: readonly string[],
1625
+ ): string | null
1310
1626
  ```
1311
1627
 
1312
1628
  - `items` — The traces {@link parseTraceArtifacts} read.
1313
1629
  - `target` — Where the run went — the deployed host, as the note names it.
1630
+ - `earlierFailures` — The failing `file:line`s earlier walks of this suite left, so a repeat is ranked above a one-off. Empty when the caller knows of no earlier walk.
1314
1631
 
1315
- **Returns:** The note, or null when no trace held a request or a console error.
1632
+ **Returns:** The note, or null when no trace held a recorded response, a real failure or a console error.
1316
1633
 
1317
1634
  #### `suiteRecordsTraces(configText)`
1318
1635
 
@@ -1602,23 +1919,40 @@ function stripTrailingSuiteFilters(command: string): SuiteFilterStrip
1602
1919
 
1603
1920
  **Returns:** The rewritten command and the stages dropped.
1604
1921
 
1922
+ #### `suiteRunPipelinePlacement(command)`
1923
+
1924
+ Where the suite runner's exit code comes from: the runner itself, or a stage piped after it.
1925
+
1926
+ {@link suiteRunPipedAfterRunner}'s one question, with the honest third answer kept apart. The
1927
+ code a finished run reports is its LAST pipeline stage's, so a stage after the runner makes the
1928
+ code the stage's — but only when such a stage EXISTS. The platform used to report "piped" for
1929
+ any run whose statements it could not place in the text, which one heredoc body was enough to
1930
+ cause: on X1 xr-molecule-flash-m105 (+08:12) a config written in the same `exec_command` made
1931
+ the run come back with no exit code at all, and the note under it claimed a stage after the
1932
+ runner that was not there. The parse now places every statement (`locatedCommandSegments`), so
1933
+ "unplaced" is the rare, named case rather than a guess dressed as an answer.
1934
+
1935
+ ```typescript
1936
+ function suiteRunPipelinePlacement(command: string): SuiteRunPipelinePlacement
1937
+ ```
1938
+
1939
+ - `command` — The shell command, after the streaming rewrite when one was applied.
1940
+
1941
+ **Returns:** Whether a stage follows the runner, and whether the run could be placed at all.
1942
+
1605
1943
  #### `suiteRunPipedAfterRunner(command)`
1606
1944
 
1607
1945
  Whether the command's last step runs a suite whose output still passes through a stage after
1608
1946
  the runner — one {@link stripTrailingSuiteFilters} could not prove is output-only (`| tee log`,
1609
1947
  `| xargs …`). The pipeline's exit status is that stage's, not the run's.
1610
1948
 
1611
- A command whose stages cannot be placed in the text (irregular whitespace inside the run) is
1612
- reported as piped too: whether a pipe follows the runner is then UNKNOWN, and an unknown exit
1613
- code that gets trusted is a failing run read as a pass — the failure this rule exists to stop.
1614
-
1615
1949
  ```typescript
1616
1950
  function suiteRunPipedAfterRunner(command: string): boolean
1617
1951
  ```
1618
1952
 
1619
1953
  - `command` — The shell command, after the streaming rewrite when one was applied.
1620
1954
 
1621
- **Returns:** True when a pipe this tool must not drop still follows the suite runner, or when the command runs a suite the parse cannot place.
1955
+ **Returns:** True when a pipe this tool must not drop still follows the suite runner.
1622
1956
 
1623
1957
  #### `suiteRunPriorityLaunch(command, launch)`
1624
1958
 
@@ -2231,21 +2565,28 @@ executor reads, so one round of fixes covers all of them rather than the one cau
2231
2565
  stopped early happened to reach.
2232
2566
 
2233
2567
  A test the request excludes is not one of the causes — it is dropped and named once, at the
2234
- end, so a result never asks to fix a test it also says to ignore. Where the caller knows how
2235
- the run was started, the note also hands over the narrowed re-run of exactly those tests
2236
- ({@link rerunOfRunningSuite}) instead of leaving the executor to re-run the whole suite.
2568
+ end, so a result never asks to fix a test it also says to ignore. A test the runner itself
2569
+ declared `flaky` (it failed once and passed on its config retry) is not a cause either: it is
2570
+ named apart from them, once, as what the tally called it ({@link flakyTestsDeclared}). Where
2571
+ the caller knows how the run was started, the note also hands over the narrowed re-run of
2572
+ exactly those tests ({@link rerunOfRunningSuite}) instead of leaving the executor to re-run the
2573
+ whole suite.
2574
+
2575
+ A run whose failures are ALL {@link NO_BASE_URL_ERROR} is not a set of causes at all: it is one
2576
+ configuration failure, said in one line ({@link noBaseUrlConfigNote}) rather than a list that
2577
+ reads as ten defects in the app.
2237
2578
 
2238
2579
  ```typescript
2239
2580
  function failureCausesNote(
2240
2581
  log: string,
2241
2582
  excluded?: readonly string[],
2242
- run?: { command: string; cwd?: string; log?: string },
2583
+ run?: { command: string; cwd?: string; log?: string; config?: string | null },
2243
2584
  ): string | null
2244
2585
  ```
2245
2586
 
2246
2587
  - `log` — The finished run's output.
2247
2588
  - `excluded` — The test titles the request carves out, if the caller knows them.
2248
- - `run` — How the run was started, when the caller knows it: the narrowed re-run is built from `command`/`cwd`, and `log` (the path the output was written to) is what the "left out" sentence greps when more causes exist than the result has room for.
2589
+ - `run` — How the run was started, when the caller knows it: the narrowed re-run is built from `command`/`cwd`/`config`, and `log` (the path the output was written to) is what the "left out" sentence greps when more causes exist than the result has room for.
2249
2590
 
2250
2591
  **Returns:** The note, or null.
2251
2592
 
@@ -2264,13 +2605,13 @@ the same app and database, and that is exactly what is refused while the run wal
2264
2605
 
2265
2606
  ```typescript
2266
2607
  function rerunOfRunningSuite(
2267
- run: { command: string; cwd?: string },
2608
+ run: { command: string; cwd?: string; config?: string | null },
2268
2609
  locations: readonly string[],
2269
2610
  excluded?: readonly string[],
2270
2611
  ): string | null
2271
2612
  ```
2272
2613
 
2273
- - `run` — The run in flight: the command it was started with, as it was run, and the directory that command ran in.
2614
+ - `run` — The run in flight: the command it was started with, as it was run, the directory that command ran in, and the config it loaded when the caller knows it.
2274
2615
  - `locations` — The failing `file:line`s to re-run, as the run's log printed them.
2275
2616
  - `excluded` — The test titles the request carves out: the re-run inverts them out (`--grep-invert`) so it cannot report them again.
2276
2617
 
@@ -2414,6 +2755,15 @@ Canonical tool schemas shared by the agent runtime and documentation.
2414
2755
  const TOOL_SCHEMAS: Record<string, ToolSchema>
2415
2756
  ```
2416
2757
 
2758
+ #### `MIN_PEEK_SLEEP_SECONDS`
2759
+
2760
+ The shortest leading sleep the platform drops: below it the wall clock it costs is noise, and a
2761
+ short settle (`sleep 2; curl …`) is a legitimate thing to run.
2762
+
2763
+ ```typescript
2764
+ const MIN_PEEK_SLEEP_SECONDS: 5
2765
+ ```
2766
+
2417
2767
  #### `SPLIT_WORK_ADVICE`
2418
2768
 
2419
2769
  The closing advice on an over-budget message for a command that is not a test
@@ -2466,6 +2816,22 @@ How many console errors one test's trace contributes.
2466
2816
  const MAX_TRACED_CONSOLE: 4
2467
2817
  ```
2468
2818
 
2819
+ #### `MAX_TRACED_ACTIONS`
2820
+
2821
+ How many of the page's own actions one test's trace contributes, the LAST ones.
2822
+
2823
+ ```typescript
2824
+ const MAX_TRACED_ACTIONS: 40
2825
+ ```
2826
+
2827
+ #### `MAX_TRACED_BODY_CHARS`
2828
+
2829
+ How much of a 4xx request's sent body (or its response body) the trace read keeps.
2830
+
2831
+ ```typescript
2832
+ const MAX_TRACED_BODY_CHARS: 300
2833
+ ```
2834
+
2469
2835
  #### `MAX_TRACE_NOTE_TESTS`
2470
2836
 
2471
2837
  How many tests the note in a run's result names.
@@ -2490,6 +2856,22 @@ How long a URL the note prints, before the middle is cut.
2490
2856
  const TRACE_NOTE_URL_CHARS: 96
2491
2857
  ```
2492
2858
 
2859
+ #### `TRACE_NOTE_SENT_CHARS`
2860
+
2861
+ How much of the sent body the note prints — enough to see a `{"data":…}` wrapper.
2862
+
2863
+ ```typescript
2864
+ const TRACE_NOTE_SENT_CHARS: 160
2865
+ ```
2866
+
2867
+ #### `TRACE_NOTE_GOT_CHARS`
2868
+
2869
+ How much of the response body the note prints — the API's first error line.
2870
+
2871
+ ```typescript
2872
+ const TRACE_NOTE_GOT_CHARS: 120
2873
+ ```
2874
+
2493
2875
  #### `DIAGNOSIS_TRACE_FLAG`
2494
2876
 
2495
2877
  The `--trace` flag this platform adds, and the only value it adds it with.