@molecule/api-ai-tools 1.9.19 → 1.10.0

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-18T20:46:28.562Z
6
+ Generated: 2026-10-18T22:07:04.913Z
7
7
  -->
8
8
 
9
9
  # @molecule/api-ai-tools
@@ -339,6 +339,17 @@ interface LeadingSleep {
339
339
  }
340
340
  ```
341
341
 
342
+ #### `RunEnvSetting`
343
+
344
+ One `NAME=value` the request requires of a suite run.
345
+
346
+ ```typescript
347
+ interface RunEnvSetting {
348
+ name: string
349
+ value: string
350
+ }
351
+ ```
352
+
342
353
  #### `SuiteRunInFlight`
343
354
 
344
355
  One suite run, as the rule that decides whether a second may start beside it reads it.
@@ -578,6 +589,33 @@ interface TraceMissingText {
578
589
  }
579
590
  ```
580
591
 
592
+ #### `TraceReadContradiction`
593
+
594
+ A write the trace recorded answering a boolean field, and a LATER GET of the same resource
595
+ answering the opposite for that field.
596
+
597
+ This is the pair that reads as a frontend race and is not one: xr-molecule-flash-m181's follow
598
+ test sent `POST /api/profiles/:username/follow` and the API answered
599
+ `{"profile":{…,"following":true}}`, then a `GET /api/profiles/:username` answered
600
+ `{"profile":{…,"following":false}}` — the READ route never saw the viewer, so it hydrated
601
+ `following` from nobody. The run rewrote the profile component twice, the API client once, and
602
+ added optimistic state before anyone read the route's middleware; the write itself was fine.
603
+
604
+ ```typescript
605
+ interface TraceReadContradiction {
606
+ /** The boolean field both answered (`following`, `favorited`). */
607
+ field: string
608
+ /** What the write's response said it is. */
609
+ writeValue: boolean
610
+ /** What the later read's response said it is. */
611
+ readValue: boolean
612
+ /** The write that answered it (`POST /api/profiles/x/follow`). */
613
+ write: TraceRequest
614
+ /** The later GET of the same resource (`GET /api/profiles/x`). */
615
+ read: TraceRequest
616
+ }
617
+ ```
618
+
581
619
  #### `TraceArtifact`
582
620
 
583
621
  What one trace says: the test it belongs to, the requests it made, and its console lines.
@@ -658,6 +696,15 @@ interface TraceArtifact {
658
696
  * read before this field existed.
659
697
  */
660
698
  missingText?: TraceMissingText
699
+ /**
700
+ * A write's answer a later GET of the same resource contradicted — the read route does not see
701
+ * the viewer (xr-molecule-flash-m181's `following`). The note leads with it and sends the run at
702
+ * the route's middleware, not the page's state handling.
703
+ *
704
+ * Absent when no write and later read in the trace answered the same boolean field differently,
705
+ * and on traces read before this field existed.
706
+ */
707
+ readContradiction?: TraceReadContradiction
661
708
  }
662
709
  ```
663
710
 
@@ -914,6 +961,26 @@ interface ToolBuildConfig {
914
961
  */
915
962
  excludedTestTitles?: () => readonly string[]
916
963
 
964
+ /**
965
+ * The `NAME=value` settings the person's request REQUIRES of a suite run (molecule-dev's
966
+ * `requiredRunSettings` — its mode, say), asked when the cause note composes a narrowed re-run
967
+ * of a finished run's failures. A re-run composed from the executor's own command inherits what
968
+ * that command set — and nothing it left out, so a run that measured the suite in `spa` handed
969
+ * back a re-run that would measure `spa` again (xr-molecule-flash-m182 +12:06: the request names
970
+ * `TEST_MODE=fullstack`, the run and its re-run both omitted it).
971
+ *
972
+ * A getter, not an array: the request is read per turn while the tool set is built once, and
973
+ * what the suite's own files read is the consumer's reading. Unset answers "nothing required".
974
+ *
975
+ * @param command - The command the finished run was started with.
976
+ * @param cwd - The resolved working directory it ran in.
977
+ * @returns The settings to put on a re-run of that command.
978
+ */
979
+ requiredSuiteEnv?: (
980
+ command: string,
981
+ cwd: string,
982
+ ) => Promise<readonly { name: string; value: string }[] | null | undefined>
983
+
917
984
  /**
918
985
  * The supplied suite's own budget, when the Playwright config a command would load sets
919
986
  * different settings, asked BEFORE the run executes. The consumer knows where the suite and its
@@ -1901,7 +1968,7 @@ function withSuiteConfig(command: string, config: string | null | undefined): st
1901
1968
 
1902
1969
  **Returns:** The command with the flag, or the command unchanged.
1903
1970
 
1904
- #### `scopedRerunCommand(command, locations, excluded, config, cwd)`
1971
+ #### `scopedRerunCommand(command, locations, excluded, config, cwd, env)`
1905
1972
 
1906
1973
  The whole-suite command made scoped to the tests it should re-run instead: the same
1907
1974
  invocation — same directory, same settings — with the named `file:line`s in place of the whole
@@ -1924,6 +1991,7 @@ function scopedRerunCommand(
1924
1991
  excluded?: readonly string[],
1925
1992
  config?: string | null,
1926
1993
  cwd?: string | null,
1994
+ env?: readonly RunEnvSetting[],
1927
1995
  ): string
1928
1996
  ```
1929
1997
 
@@ -1932,9 +2000,32 @@ function scopedRerunCommand(
1932
2000
  - `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.
1933
2001
  - `config` — The config the run loaded, when the caller knows it; added when the command does not name one.
1934
2002
  - `cwd` — The directory `exec_command` was given, when it was; the base a location is resolved against when the command does not `cd` anywhere.
2003
+ - `env` — The settings the REQUEST requires of the suite and this run left out ({@link withRunEnv}): the re-run carries them, so a re-run of a run measured in the wrong mode is not measured in that mode again (xr-molecule-flash-m182 +12:06).
1935
2004
 
1936
2005
  **Returns:** The scoped command, or the command unchanged when it runs no Playwright suite.
1937
2006
 
2007
+ #### `withRunEnv(command, settings)`
2008
+
2009
+ The command with the request's required settings put in front of its RUN statement — the ONE
2010
+ place every composed re-run gets them (xr-molecule-flash-m182).
2011
+
2012
+ The settings are written at the statement's own assignment offset, never in front of the whole
2013
+ command: a shell binds an assignment there to the statement's program, while one in front of the
2014
+ whole command is the environment of its FIRST statement alone (`APP_BASE=… cd app && npx
2015
+ playwright test` sets the variable for `cd`; xr-molecule-flash-m103 +28:08). A name the command
2016
+ gives a different value is replaced, and one it already gives the required value is left as
2017
+ written. When the parse cannot place the statement (a run inside a nested `sh -c '…'`), the
2018
+ settings become `export`s, which no statement boundary can swallow.
2019
+
2020
+ ```typescript
2021
+ function withRunEnv(command: string, settings?: readonly RunEnvSetting[]): string
2022
+ ```
2023
+
2024
+ - `command` — The command to carry them.
2025
+ - `settings` — The `NAME`/`value` pairs the request requires.
2026
+
2027
+ **Returns:** The command, or the command unchanged when it already carries every setting.
2028
+
1938
2029
  #### `suiteRunInTheWay(candidate, inFlight)`
1939
2030
 
1940
2031
  The run in flight that makes a second run a hazard, or null when nothing is in the way.
@@ -3415,14 +3506,20 @@ reads as ten defects in the app.
3415
3506
  function failureCausesNote(
3416
3507
  log: string,
3417
3508
  excluded?: readonly string[],
3418
- run?: { command: string; cwd?: string; log?: string; config?: string | null },
3509
+ run?: {
3510
+ command: string
3511
+ cwd?: string
3512
+ log?: string
3513
+ config?: string | null
3514
+ env?: readonly RunEnvSetting[]
3515
+ },
3419
3516
  pageErrors?: readonly CausePageErrors[],
3420
3517
  ): string | null
3421
3518
  ```
3422
3519
 
3423
3520
  - `log` — The finished run's output.
3424
3521
  - `excluded` — The test titles the request carves out, if the caller knows them.
3425
- - `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.
3522
+ - `run` — How the run was started, when the caller knows it: the narrowed re-run is built from `command`/`cwd`/`config`/`env`, 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.
3426
3523
 
3427
3524
  **Returns:** The note, or null.
3428
3525
 
@@ -3441,13 +3538,13 @@ refused while the run walks ({@link suiteRunInTheWay}).
3441
3538
 
3442
3539
  ```typescript
3443
3540
  function rerunOfRunningSuite(
3444
- run: { command: string; cwd?: string; config?: string | null },
3541
+ run: { command: string; cwd?: string; config?: string | null; env?: readonly RunEnvSetting[] },
3445
3542
  locations: readonly string[],
3446
3543
  excluded?: readonly string[],
3447
3544
  ): string | null
3448
3545
  ```
3449
3546
 
3450
- - `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.
3547
+ - `run` — The run in flight: the command it was started with, as it was run, the directory that command ran in, the config it loaded when the caller knows it, and the settings the request required and the run left out (`env`) — the re-run carries them, so it never reproduces the configuration the run was measured under by mistake (m182).
3451
3548
  - `locations` — The failing `file:line`s to re-run, as the run's log printed them.
3452
3549
  - `excluded` — The test titles the request carves out: the re-run inverts them out (`--grep-invert`) so it cannot report them again.
3453
3550
 
@@ -3486,7 +3583,7 @@ function repeatingFailureNote(
3486
3583
  log: string
3487
3584
  stop: string
3488
3585
  universal?: UniversalCause | null
3489
- run?: { command: string; cwd?: string }
3586
+ run?: { command: string; cwd?: string; env?: readonly RunEnvSetting[] }
3490
3587
  editsInvalidateRun?: boolean
3491
3588
  },
3492
3589
  ): string
@@ -105,9 +105,34 @@ export declare function withSuiteConfig(command: string, config: string | null |
105
105
  * does not name one.
106
106
  * @param cwd - The directory `exec_command` was given, when it was; the base a location is
107
107
  * resolved against when the command does not `cd` anywhere.
108
+ * @param env - The settings the REQUEST requires of the suite and this run left out
109
+ * ({@link withRunEnv}): the re-run carries them, so a re-run of a run measured in the wrong
110
+ * mode is not measured in that mode again (xr-molecule-flash-m182 +12:06).
108
111
  * @returns The scoped command, or the command unchanged when it runs no Playwright suite.
109
112
  */
110
- export declare function scopedRerunCommand(command: string, locations: readonly string[], excluded?: readonly string[], config?: string | null, cwd?: string | null): string;
113
+ export declare function scopedRerunCommand(command: string, locations: readonly string[], excluded?: readonly string[], config?: string | null, cwd?: string | null, env?: readonly RunEnvSetting[]): string;
114
+ /** One `NAME=value` the request requires of a suite run. */
115
+ export interface RunEnvSetting {
116
+ name: string;
117
+ value: string;
118
+ }
119
+ /**
120
+ * The command with the request's required settings put in front of its RUN statement — the ONE
121
+ * place every composed re-run gets them (xr-molecule-flash-m182).
122
+ *
123
+ * The settings are written at the statement's own assignment offset, never in front of the whole
124
+ * command: a shell binds an assignment there to the statement's program, while one in front of the
125
+ * whole command is the environment of its FIRST statement alone (`APP_BASE=… cd app && npx
126
+ * playwright test` sets the variable for `cd`; xr-molecule-flash-m103 +28:08). A name the command
127
+ * gives a different value is replaced, and one it already gives the required value is left as
128
+ * written. When the parse cannot place the statement (a run inside a nested `sh -c '…'`), the
129
+ * settings become `export`s, which no statement boundary can swallow.
130
+ *
131
+ * @param command - The command to carry them.
132
+ * @param settings - The `NAME`/`value` pairs the request requires.
133
+ * @returns The command, or the command unchanged when it already carries every setting.
134
+ */
135
+ export declare function withRunEnv(command: string, settings?: readonly RunEnvSetting[]): string;
111
136
  /**
112
137
  * One suite run, as the rule that decides whether a second may start beside it reads it.
113
138
  *
@@ -1 +1 @@
1
- {"version":3,"file":"suite-overlap.d.ts","sourceRoot":"","sources":["../src/suite-overlap.ts"],"names":[],"mappings":"AAAA;;;;;;;;;;;;;;;;;;;;;;;;;;;;;GA6BG;AAQH;;;;;;;;;GASG;AACH,wBAAgB,eAAe,CAAC,OAAO,EAAE,MAAM,GAAG,MAAM,CAEvD;AAED;;;;;;;;;GASG;AACH,wBAAgB,kBAAkB,CAAC,OAAO,EAAE,MAAM,GAAG,MAAM,CAoB1D;AAKD;;;;;;GAMG;AACH,wBAAgB,gBAAgB,CAAC,OAAO,EAAE,MAAM,GAAG,OAAO,CAEzD;AAED;;;;;;;;;;;;;;;;;GAiBG;AACH,wBAAgB,eAAe,CAAC,OAAO,EAAE,MAAM,EAAE,MAAM,EAAE,MAAM,GAAG,IAAI,GAAG,SAAS,GAAG,MAAM,CAS1F;AAqCD;;;;;;;;;;;;;;;;;;;;;;;;;;;;;GA6BG;AACH,wBAAgB,kBAAkB,CAChC,OAAO,EAAE,MAAM,EACf,SAAS,EAAE,SAAS,MAAM,EAAE,EAC5B,QAAQ,GAAE,SAAS,MAAM,EAAO,EAChC,MAAM,CAAC,EAAE,MAAM,GAAG,IAAI,EACtB,GAAG,CAAC,EAAE,MAAM,GAAG,IAAI,GAClB,MAAM,CA8CR;AAkHD;;;;;;GAMG;AACH,MAAM,WAAW,gBAAgB;IAC/B,+FAA+F;IAC/F,SAAS,EAAE,OAAO,CAAA;IAClB,oFAAoF;IACpF,MAAM,EAAE,MAAM,CAAA;IACd;;;;OAIG;IACH,gBAAgB,CAAC,EAAE,OAAO,CAAA;CAC3B;AAED;;;;;;;;;;;;GAYG;AACH,wBAAgB,gBAAgB,CAAC,CAAC,SAAS,gBAAgB,EACzD,SAAS,EAAE;IAAE,MAAM,EAAE,MAAM,CAAA;CAAE,EAC7B,QAAQ,EAAE,SAAS,CAAC,EAAE,GACrB,CAAC,GAAG,IAAI,CAMV;AA2FD;;GAEG;AACH,MAAM,WAAW,mBAAmB;IAClC;;;OAGG;IACH,kBAAkB,CAAC,EAAE,SAAS,MAAM,EAAE,CAAA;CACvC;AAmCD;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;GAsCG;AACH,wBAAgB,cAAc,CAAC,OAAO,EAAE,MAAM,EAAE,OAAO,CAAC,EAAE,mBAAmB,GAAG,OAAO,CAYtF"}
1
+ {"version":3,"file":"suite-overlap.d.ts","sourceRoot":"","sources":["../src/suite-overlap.ts"],"names":[],"mappings":"AAAA;;;;;;;;;;;;;;;;;;;;;;;;;;;;;GA6BG;AAQH;;;;;;;;;GASG;AACH,wBAAgB,eAAe,CAAC,OAAO,EAAE,MAAM,GAAG,MAAM,CAEvD;AAED;;;;;;;;;GASG;AACH,wBAAgB,kBAAkB,CAAC,OAAO,EAAE,MAAM,GAAG,MAAM,CAoB1D;AAKD;;;;;;GAMG;AACH,wBAAgB,gBAAgB,CAAC,OAAO,EAAE,MAAM,GAAG,OAAO,CAEzD;AAED;;;;;;;;;;;;;;;;;GAiBG;AACH,wBAAgB,eAAe,CAAC,OAAO,EAAE,MAAM,EAAE,MAAM,EAAE,MAAM,GAAG,IAAI,GAAG,SAAS,GAAG,MAAM,CAS1F;AAqCD;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;GAgCG;AACH,wBAAgB,kBAAkB,CAChC,OAAO,EAAE,MAAM,EACf,SAAS,EAAE,SAAS,MAAM,EAAE,EAC5B,QAAQ,GAAE,SAAS,MAAM,EAAO,EAChC,MAAM,CAAC,EAAE,MAAM,GAAG,IAAI,EACtB,GAAG,CAAC,EAAE,MAAM,GAAG,IAAI,EACnB,GAAG,GAAE,SAAS,aAAa,EAAO,GACjC,MAAM,CA8CR;AAED,4DAA4D;AAC5D,MAAM,WAAW,aAAa;IAC5B,IAAI,EAAE,MAAM,CAAA;IACZ,KAAK,EAAE,MAAM,CAAA;CACd;AAmCD;;;;;;;;;;;;;;;GAeG;AACH,wBAAgB,UAAU,CAAC,OAAO,EAAE,MAAM,EAAE,QAAQ,GAAE,SAAS,aAAa,EAAO,GAAG,MAAM,CAe3F;AAkHD;;;;;;GAMG;AACH,MAAM,WAAW,gBAAgB;IAC/B,+FAA+F;IAC/F,SAAS,EAAE,OAAO,CAAA;IAClB,oFAAoF;IACpF,MAAM,EAAE,MAAM,CAAA;IACd;;;;OAIG;IACH,gBAAgB,CAAC,EAAE,OAAO,CAAA;CAC3B;AAED;;;;;;;;;;;;GAYG;AACH,wBAAgB,gBAAgB,CAAC,CAAC,SAAS,gBAAgB,EACzD,SAAS,EAAE;IAAE,MAAM,EAAE,MAAM,CAAA;CAAE,EAC7B,QAAQ,EAAE,SAAS,CAAC,EAAE,GACrB,CAAC,GAAG,IAAI,CAMV;AA2FD;;GAEG;AACH,MAAM,WAAW,mBAAmB;IAClC;;;OAGG;IACH,kBAAkB,CAAC,EAAE,SAAS,MAAM,EAAE,CAAA;CACvC;AAmCD;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;GAsCG;AACH,wBAAgB,cAAc,CAAC,OAAO,EAAE,MAAM,EAAE,OAAO,CAAC,EAAE,mBAAmB,GAAG,OAAO,CAYtF"}
@@ -179,9 +179,12 @@ function redirectToFreshFile(command) {
179
179
  * does not name one.
180
180
  * @param cwd - The directory `exec_command` was given, when it was; the base a location is
181
181
  * resolved against when the command does not `cd` anywhere.
182
+ * @param env - The settings the REQUEST requires of the suite and this run left out
183
+ * ({@link withRunEnv}): the re-run carries them, so a re-run of a run measured in the wrong
184
+ * mode is not measured in that mode again (xr-molecule-flash-m182 +12:06).
182
185
  * @returns The scoped command, or the command unchanged when it runs no Playwright suite.
183
186
  */
184
- export function scopedRerunCommand(command, locations, excluded = [], config, cwd) {
187
+ export function scopedRerunCommand(command, locations, excluded = [], config, cwd, env = []) {
185
188
  const run = playwrightStatement(command);
186
189
  if (run === null)
187
190
  return command;
@@ -223,7 +226,68 @@ export function scopedRerunCommand(command, locations, excluded = [], config, cw
223
226
  // X1 xr-molecule-flash-m157 (+14:02) was handed a re-run that still carried the chain's second
224
227
  // whole walk — 4.5 minutes measuring code it had not changed.
225
228
  const rerunTail = suiteRunStatements(tail).length > 0 ? '' : tail;
226
- return `${redirectToFreshFile(scoped)}${redirectToFreshFile(rerunTail)}`;
229
+ return withRunEnv(`${redirectToFreshFile(scoped)}${redirectToFreshFile(rerunTail)}`, env);
230
+ }
231
+ /** A `NAME=value` word in command position, optionally behind `export`/`env`. */
232
+ const ENV_WORD = /(^|[\s;&|(])(?:export[ \t]+|env[ \t]+)?([A-Za-z_][A-Za-z0-9_]*)=('[^']*'|"[^"]*"|[^\s;&|]+)/g;
233
+ /** The value a command gives a name, unquoted, or null when it sets none. */
234
+ function envValueOf(command, name) {
235
+ for (const m of command.matchAll(ENV_WORD)) {
236
+ if (m[2] !== name)
237
+ continue;
238
+ return (m[3] ?? '').replace(/^(['"])(.*)\1$/, '$2');
239
+ }
240
+ return null;
241
+ }
242
+ /** The command with one `NAME=value` word taken out, whitespace and all. */
243
+ function withoutEnvWord(command, name) {
244
+ const pattern = new RegExp(`(^|[\\s;&|(])(?:export[ \\t]+|env[ \\t]+)?${name}=('[^']*'|"[^"]*"|[^\\s;&|]+)`);
245
+ const m = pattern.exec(command);
246
+ if (!m)
247
+ return command;
248
+ const start = m.index + m[1].length;
249
+ const end = m.index + m[0].length;
250
+ const left = /[ \t]*$/.exec(command.slice(0, start))?.[0] ?? '';
251
+ const chain = /^[ \t]*(?:&&|\|\||;)[ \t]*/.exec(command.slice(end));
252
+ // A word between two chained statements takes the following operator with it, so the result is
253
+ // `a && b` and not `a && && b`.
254
+ if (chain && left.length > 0)
255
+ return command.slice(0, start) + command.slice(end + chain[0].length);
256
+ if (left.length > 0)
257
+ return command.slice(0, start - left.length) + command.slice(end);
258
+ const right = /^[ \t]*/.exec(command.slice(end))?.[0] ?? '';
259
+ return command.slice(0, start) + command.slice(end + right.length);
260
+ }
261
+ /**
262
+ * The command with the request's required settings put in front of its RUN statement — the ONE
263
+ * place every composed re-run gets them (xr-molecule-flash-m182).
264
+ *
265
+ * The settings are written at the statement's own assignment offset, never in front of the whole
266
+ * command: a shell binds an assignment there to the statement's program, while one in front of the
267
+ * whole command is the environment of its FIRST statement alone (`APP_BASE=… cd app && npx
268
+ * playwright test` sets the variable for `cd`; xr-molecule-flash-m103 +28:08). A name the command
269
+ * gives a different value is replaced, and one it already gives the required value is left as
270
+ * written. When the parse cannot place the statement (a run inside a nested `sh -c '…'`), the
271
+ * settings become `export`s, which no statement boundary can swallow.
272
+ *
273
+ * @param command - The command to carry them.
274
+ * @param settings - The `NAME`/`value` pairs the request requires.
275
+ * @returns The command, or the command unchanged when it already carries every setting.
276
+ */
277
+ export function withRunEnv(command, settings = []) {
278
+ const added = [];
279
+ let out = command;
280
+ for (const setting of settings) {
281
+ if (envValueOf(out, setting.name) === setting.value)
282
+ continue;
283
+ out = withoutEnvWord(out, setting.name);
284
+ added.push(`${setting.name}=${setting.value}`);
285
+ }
286
+ if (added.length === 0)
287
+ return command;
288
+ const at = locatedCommandSegments(out).find((entry) => entry.segment !== null && PLAYWRIGHT_RUN.test(entry.segment.text))?.assignmentOffset ?? null;
289
+ const words = added.join(' ');
290
+ return at === null ? `export ${words} && ${out}` : `${out.slice(0, at)}${words} ${out.slice(at)}`;
227
291
  }
228
292
  /** A directory a `cd` can name literally: no `~`, no variable, no glob. */
229
293
  const LITERAL_DIR = /^[A-Za-z0-9_./+-]+$/;
@@ -1 +1 @@
1
- {"version":3,"file":"tools.d.ts","sourceRoot":"","sources":["../src/tools.ts"],"names":[],"mappings":"AAAA;;;;;;;GAOG;AAIH,OAAO,KAAK,EAAE,MAAM,EAAE,MAAM,kBAAkB,CAAA;AAsK9C;;;;;;;;;;;;;;;;GAgBG;AACH,wBAAsB,eAAe,CAAC,OAAO,EAAE,gBAAgB,EAAE,MAAM,EAAE,MAAM,GAAG,OAAO,CAAC,MAAM,CAAC,CAahG;AAiSD,OAAO,KAAK,EAAE,gBAAgB,EAAE,eAAe,EAAE,MAAM,YAAY,CAAA;AAqFnE;;;GAGG;AACH,eAAO,MAAM,iBAAiB,QAEA,CAAA;AAE9B;;;;;;;;;;;;;GAaG;AACH,eAAO,MAAM,wBAAwB,QAI6C,CAAA;AAmBlF;;;;;;;;;;;GAWG;AACH,wBAAgB,oBAAoB,CAAC,IAAI,EAAE,MAAM,GAAG,MAAM,GAAG,IAAI,CAUhE;AAED;;;;;;;;;;;;GAYG;AACH,MAAM,WAAW,qBAAqB;IACpC,iFAAiF;IACjF,QAAQ,CAAC,OAAO,EAAE,OAAO,CAAA;IACzB,8FAA8F;IAC9F,QAAQ,CAAC,SAAS,EAAE,OAAO,CAAA;CAC5B;AAED;;;;;;;GAOG;AACH,MAAM,MAAM,qBAAqB,GAAG,CAAC,IAAI,EAAE,MAAM,KAAK,OAAO,CAAC,qBAAqB,CAAC,CAAA;AAoBpF;;;;;;;GAOG;AACH,wBAAgB,0BAA0B,CACxC,GAAG,EAAE,CAAC,OAAO,EAAE,MAAM,KAAK,OAAO,CAAC;IAAE,MAAM,CAAC,EAAE,MAAM,CAAA;CAAE,GAAG,IAAI,GAAG,SAAS,CAAC,GACxE,qBAAqB,CAkBvB;AAED;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;GAqCG;AACH,wBAAsB,4BAA4B,CAChD,IAAI,EAAE,MAAM,EACZ,KAAK,CAAC,EAAE,qBAAqB,GAC5B,OAAO,CAAC,MAAM,GAAG,IAAI,CAAC,CAiCxB;AA2GD;;;;;;GAMG;AACH,wBAAgB,UAAU,CAAC,OAAO,EAAE,gBAAgB,EAAE,MAAM,CAAC,EAAE,eAAe,GAAG,MAAM,EAAE,CAurFxF"}
1
+ {"version":3,"file":"tools.d.ts","sourceRoot":"","sources":["../src/tools.ts"],"names":[],"mappings":"AAAA;;;;;;;GAOG;AAIH,OAAO,KAAK,EAAE,MAAM,EAAE,MAAM,kBAAkB,CAAA;AA4K9C;;;;;;;;;;;;;;;;GAgBG;AACH,wBAAsB,eAAe,CAAC,OAAO,EAAE,gBAAgB,EAAE,MAAM,EAAE,MAAM,GAAG,OAAO,CAAC,MAAM,CAAC,CAahG;AA6ZD,OAAO,KAAK,EAAE,gBAAgB,EAAE,eAAe,EAAE,MAAM,YAAY,CAAA;AAqFnE;;;GAGG;AACH,eAAO,MAAM,iBAAiB,QAEA,CAAA;AAE9B;;;;;;;;;;;;;GAaG;AACH,eAAO,MAAM,wBAAwB,QAI6C,CAAA;AAmBlF;;;;;;;;;;;GAWG;AACH,wBAAgB,oBAAoB,CAAC,IAAI,EAAE,MAAM,GAAG,MAAM,GAAG,IAAI,CAUhE;AAED;;;;;;;;;;;;GAYG;AACH,MAAM,WAAW,qBAAqB;IACpC,iFAAiF;IACjF,QAAQ,CAAC,OAAO,EAAE,OAAO,CAAA;IACzB,8FAA8F;IAC9F,QAAQ,CAAC,SAAS,EAAE,OAAO,CAAA;CAC5B;AAED;;;;;;;GAOG;AACH,MAAM,MAAM,qBAAqB,GAAG,CAAC,IAAI,EAAE,MAAM,KAAK,OAAO,CAAC,qBAAqB,CAAC,CAAA;AAoBpF;;;;;;;GAOG;AACH,wBAAgB,0BAA0B,CACxC,GAAG,EAAE,CAAC,OAAO,EAAE,MAAM,KAAK,OAAO,CAAC;IAAE,MAAM,CAAC,EAAE,MAAM,CAAA;CAAE,GAAG,IAAI,GAAG,SAAS,CAAC,GACxE,qBAAqB,CAkBvB;AAED;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;GAqCG;AACH,wBAAsB,4BAA4B,CAChD,IAAI,EAAE,MAAM,EACZ,KAAK,CAAC,EAAE,qBAAqB,GAC5B,OAAO,CAAC,MAAM,GAAG,IAAI,CAAC,CAiCxB;AA2GD;;;;;;GAMG;AACH,wBAAgB,UAAU,CAAC,OAAO,EAAE,gBAAgB,EAAE,MAAM,CAAC,EAAE,eAAe,GAAG,MAAM,EAAE,CAguFxF"}
package/dist/tools.js CHANGED
@@ -7,7 +7,7 @@
7
7
  * @module
8
8
  */
9
9
  import { posix } from 'path';
10
- import { commandCutRun, CUT_AT_BUDGET, cutRunSentence, suiteRunExitCode } from './cut-run.js';
10
+ import { commandCutRun, CUT_AT_BUDGET, cutRunSentence, suiteRunExitCode, suiteSummary, } from './cut-run.js';
11
11
  import { addChangeSpan, changedSpan, countLines, renderEditExcerpt, renderSmallFile, } from './edit-excerpt.js';
12
12
  import { guardToolExecute, missingParamError, ToolInputError } from './input-normalizer.js';
13
13
  import { diffLineCount } from './line-diff.js';
@@ -171,6 +171,105 @@ export async function taskStopCommand(backend, taskId) {
171
171
  return fallback;
172
172
  }
173
173
  }
174
+ /**
175
+ * How often a wait re-asks whether a task whose exit file has not appeared has ended. The exit
176
+ * file is read every tick; this probe is a process test plus the task's own output, and 3 s is
177
+ * close enough that a run which ended is never waited out (m182: 281 s on a walk that ended in 20).
178
+ */
179
+ const TASK_END_LOOK_MS = 3_000;
180
+ /** How much of a task's own output the end test reads — a runner's tally is its last lines. */
181
+ const TASK_OUTPUT_END_BYTES = 4_000;
182
+ /**
183
+ * The shell probe behind {@link taskEndState}: the pid the launcher wrote, and the end of the
184
+ * file the command redirects its own output to.
185
+ *
186
+ * The pid test is the one `molecule-dev/api/src/ai/background-tasks.ts` applies in `liveness` —
187
+ * a written exit code ends the task, a live pid keeps it running, and a handle the sandbox cannot
188
+ * account for stays unknown — so this package and that one cannot disagree about whether a task
189
+ * is still walking.
190
+ *
191
+ * @param taskId - The task's `mol-bg-…` handle (format already checked by the caller).
192
+ * @param own - The file the command redirects its own output to, when the launch could tell.
193
+ * @returns The command; its first line is `MOL_TASK_STATE <alive|gone|unknown>`, the rest the tail.
194
+ */
195
+ const taskStateCommand = (taskId, own) => `P=$(cat /tmp/${taskId}.pid 2>/dev/null); ` +
196
+ `if [ -z "$P" ] || [ ! -f /tmp/${taskId}.sh ]; then echo MOL_TASK_STATE unknown; ` +
197
+ `elif kill -0 "$P" 2>/dev/null; then echo MOL_TASK_STATE alive; ` +
198
+ `else echo MOL_TASK_STATE gone; fi; ` +
199
+ (own ? `tail -c ${TASK_OUTPUT_END_BYTES} ${shellQuote(own)} 2>/dev/null` : 'true');
200
+ /**
201
+ * The ending a task's own output already records, read from the file its command redirects to.
202
+ *
203
+ * A command can put its real work in a subshell and leave the platform's wrapper waiting on
204
+ * something else — `( runner > /tmp/full-run.log; echo EXIT=$? >> /tmp/full-run.log ) &` — so
205
+ * the task log stays empty and the exit file may never appear while the run itself is over. The
206
+ * run's own file is where its outcome is: an `EXIT=<n>` line the command appended, or the
207
+ * runner's closing tally (Playwright's status lines, Vitest's `Tests …` line, Hurl's
208
+ * `Executed files:`), which is the last thing a finished run prints.
209
+ *
210
+ * @param text - The tail of the task's own output file.
211
+ * @returns Whether the output records an ending, and the code when it recorded one.
212
+ */
213
+ function outputEnding(text) {
214
+ const trimmed = text.trimEnd();
215
+ if (!trimmed)
216
+ return { ended: false, exitCode: null };
217
+ // An explicit marker the command appended is the run's own verdict, whatever precedes it.
218
+ const marker = /(?:^|\n)EXIT=(\d+)\s*$/.exec(trimmed);
219
+ if (marker)
220
+ return { ended: true, exitCode: Number(marker[1]) };
221
+ const lastLine = trimmed.slice(trimmed.lastIndexOf('\n') + 1).trim();
222
+ // A tally is an ending only as the LAST line: a second walk starts by printing its own header,
223
+ // so a file whose last line is still the first walk's tally is between the two.
224
+ const tallyLine = /^\d+\s+(?:passed|failed|flaky|skipped|interrupted|timed out|did not run)\b/.test(lastLine) ||
225
+ /^Tests\s+.+\(\d+\)$/.test(lastLine) ||
226
+ /\bExecuted files:\s*\d+/.test(lastLine);
227
+ if (!tallyLine)
228
+ return { ended: false, exitCode: null };
229
+ return { ended: suiteSummary(trimmed)?.finished ?? false, exitCode: null };
230
+ }
231
+ /**
232
+ * Whether a background task has ENDED, asked of the task itself rather than of a note about it.
233
+ *
234
+ * A missing exit file alone is not "running": the launcher writes that file from the wrapper it
235
+ * started, and a command that backgrounds its real work leaves the file missing after the run is
236
+ * over. X1 xr-molecule-flash-m182 (+30:25) waited 281 s — its whole remaining ceiling — on a walk
237
+ * that had ended in 20 s, and a `sleep 240; tail` on the same handle was answered "is live". The
238
+ * end is read the way `molecule-dev/api/src/ai/background-tasks.ts` reads it — exit file, then
239
+ * the pid — plus the one signal this package has and that tracker does not: the task's own output
240
+ * file already holding its ending.
241
+ *
242
+ * @param backend - The execution backend the task runs on.
243
+ * @param taskId - The task's `mol-bg-…` handle.
244
+ * @returns Whether it has ended, and the code its own output recorded when it recorded one.
245
+ */
246
+ async function taskEndState(backend, taskId) {
247
+ const own = outputFileByTask.get(taskId);
248
+ let stdout;
249
+ try {
250
+ const r = await backend.run(taskStateCommand(taskId, own), { timeout: 5_000 });
251
+ stdout = String(r.stdout ?? '');
252
+ }
253
+ catch (_error) {
254
+ // A sandbox that cannot answer is not evidence of an ending: the quiet failure (a wait) beats
255
+ // the loud one (a result handed back for a run that is still walking).
256
+ return { ended: false, exitCode: null };
257
+ }
258
+ const [stateLine = '', ...rest] = stdout.split('\n');
259
+ const state = /MOL_TASK_STATE (alive|gone|unknown)/.exec(stateLine)?.[1] ?? 'unknown';
260
+ const ownEnding = outputEnding(rest.join('\n'));
261
+ // The run's own output can end the task while its wrapper is still alive: the wrapper may be
262
+ // waiting on the wrong thing (m182's was blocked) while the run it started is over. An explicit
263
+ // `EXIT=<n>` is that verdict; a bare tally is trusted only once the pid is gone, because the
264
+ // instant between a walk's tally and its next walk's header reads the same.
265
+ if (ownEnding.ended && (ownEnding.exitCode !== null || state === 'gone'))
266
+ return ownEnding;
267
+ // A pid this sandbox can account for and that is gone, with no exit file: the wrapper that
268
+ // writes the exit code was killed or exited, so the task ended and has no verdict to invent.
269
+ if (state === 'gone')
270
+ return { ended: true, exitCode: null };
271
+ return { ended: false, exitCode: null };
272
+ }
174
273
  /** A millisecond span the way a model reads it: seconds under 90, else minutes. */
175
274
  function durationText(ms) {
176
275
  const s = Math.max(0, Math.round(ms / 1000));
@@ -382,17 +481,27 @@ async function backgroundTaskState(backend, command, seconds, ceilingMs) {
382
481
  const own = outputFileByTask.get(id);
383
482
  return own !== undefined && command.includes(own);
384
483
  };
484
+ // A task is only a candidate to WAIT on while it is still walking: the exit file and the same
485
+ // end test `wait_for_task` applies both say when it ended, so a sleep is never held for a handle
486
+ // whose run is already over (m182 +30:25: `sleep 240; tail /tmp/full-run.log` was answered "is
487
+ // live" for a task that had ended 20 s after it started).
488
+ const stateOf = async (id) => {
489
+ const exitCode = await exitCodeOf(id);
490
+ if (exitCode !== null)
491
+ return { id, ended: true, exitCode };
492
+ return { id, ...(await taskEndState(backend, id)) };
493
+ };
385
494
  const newestFirst = [...ids].reverse();
386
495
  const namedId = newestFirst.find(names);
387
496
  let target = namedId
388
- ? { id: namedId, exitCode: await exitCodeOf(namedId) }
497
+ ? await stateOf(namedId)
389
498
  : null;
390
499
  if (!target) {
391
500
  // Bounded: a long session can leave many finished tasks behind, and each look costs a read.
392
501
  for (const id of newestFirst.slice(0, 8)) {
393
- const exitCode = await exitCodeOf(id);
394
- if (exitCode === null) {
395
- target = { id, exitCode };
502
+ const state = await stateOf(id);
503
+ if (!state.ended) {
504
+ target = state;
396
505
  break;
397
506
  }
398
507
  }
@@ -408,7 +517,7 @@ async function backgroundTaskState(backend, command, seconds, ceilingMs) {
408
517
  // No slice: the note still says the task's state and how to get its result.
409
518
  }
410
519
  const secondsText = `Did not sleep ${Math.round(seconds)} s: background task \`${target.id}\``;
411
- if (target.exitCode === null) {
520
+ if (!target.ended) {
412
521
  const facts = waitProgressClauses({
413
522
  taskId: target.id,
414
523
  slice,
@@ -427,8 +536,12 @@ async function backgroundTaskState(backend, command, seconds, ceilingMs) {
427
536
  const counter = logProgress(slice);
428
537
  const progress = counter ? `, at ${counter.done} of ${counter.total} in its log` : '';
429
538
  const failures = slice.trim() ? '; the failures in its log are in outputSoFar' : '';
539
+ // No exit file and no code in the run's own output: it ended and there is no verdict to invent.
540
+ const verdict = target.exitCode === null
541
+ ? 'no exit code — its process is gone and its output recorded none'
542
+ : `exit code ${target.exitCode}`;
430
543
  return {
431
- note: `${secondsText} had already ended (exit code ${target.exitCode})${progress}${failures} — ` +
544
+ note: `${secondsText} had already ended (${verdict})${progress}${failures} — ` +
432
545
  `\`wait_for_task ${target.id}\` returns its result now.`,
433
546
  slice,
434
547
  };
@@ -728,7 +841,7 @@ function packageCatalog(path) {
728
841
  * @returns Array of AITool objects ready to pass to an AI provider
729
842
  */
730
843
  export function buildTools(backend, config) {
731
- const { include, exclude, pathGuards = true, symlinkGuards = false, redactSecrets: doRedact = true, blockDangerousCommands = false, blockCommand, execTimeoutMs = 120_000, commandBudgetMs, overCeilingGraceMs = OVER_CEILING_GRACE_MS, searchExcludedDirs, outlineLargeHtml, excludedTestTitles, onAfterWrite, onFileDiff, onFileChange, } = config ?? {};
844
+ const { include, exclude, pathGuards = true, symlinkGuards = false, redactSecrets: doRedact = true, blockDangerousCommands = false, blockCommand, execTimeoutMs = 120_000, commandBudgetMs, overCeilingGraceMs = OVER_CEILING_GRACE_MS, searchExcludedDirs, outlineLargeHtml, excludedTestTitles, requiredSuiteEnv, onAfterWrite, onFileDiff, onFileChange, } = config ?? {};
732
845
  const root = backend.projectRoot;
733
846
  // A host-filesystem backend with escape guards off is the combination the
734
847
  // audit flagged: `pathGuards` off lets `..` paths out of the workspace,
@@ -2900,6 +3013,8 @@ export function buildTools(backend, config) {
2900
3013
  const started = runByTask.get(taskId);
2901
3014
  let midRunNote = null;
2902
3015
  let lastCauseLookAt = startedAt - repeatingCauseLookMs();
3016
+ let lastEndLookAt = startedAt - TASK_END_LOOK_MS;
3017
+ let endedWithoutCode = false;
2903
3018
  let exitCode = await readExit();
2904
3019
  while (exitCode === null && Date.now() - startedAt < budgetMs) {
2905
3020
  await new Promise((r) => setTimeout(r, Math.min(2_000, budgetMs - (Date.now() - startedAt))));
@@ -2908,6 +3023,19 @@ export function buildTools(backend, config) {
2908
3023
  // its real result instead of a note about it.
2909
3024
  if (exitCode !== null)
2910
3025
  break;
3026
+ // A missing exit file is not "running": the launcher writes that file from its wrapper,
3027
+ // and a command that backgrounds its real work leaves it missing after the run is over.
3028
+ // The same end test the sleep peek uses answers here, before a cause look can `continue`
3029
+ // past it — m182 (+30:25) waited 281 s on a walk that had ended in 20 s.
3030
+ if (Date.now() - lastEndLookAt >= TASK_END_LOOK_MS) {
3031
+ lastEndLookAt = Date.now();
3032
+ const state = await taskEndState(backend, taskId);
3033
+ if (state.ended) {
3034
+ exitCode = state.exitCode;
3035
+ endedWithoutCode = state.exitCode === null;
3036
+ break;
3037
+ }
3038
+ }
2911
3039
  if (repeatingCauseNoted.has(taskId))
2912
3040
  continue;
2913
3041
  if (Date.now() - lastCauseLookAt < repeatingCauseLookMs())
@@ -2987,7 +3115,10 @@ export function buildTools(backend, config) {
2987
3115
  }
2988
3116
  const waitedMs = Date.now() - startedAt;
2989
3117
  waitedByTask.set(taskId, waitedBefore + waitedMs);
2990
- if (exitCode === null) {
3118
+ // A task the end test found over with no exit code is FINISHED, not still walking: its
3119
+ // result is read below from its own output. Only a task still alive (or a sandbox that
3120
+ // could not answer) reaches the running/stuck answers.
3121
+ if (exitCode === null && !endedWithoutCode) {
2991
3122
  const grownTo = await logBytes();
2992
3123
  const lastSize = logBytesByTask.get(taskId);
2993
3124
  if (grownTo !== null)
@@ -3138,12 +3269,20 @@ export function buildTools(backend, config) {
3138
3269
  // failing tests instead of leaving the executor to re-run the whole suite (xr-molecule-
3139
3270
  // flash-m101 +12:13: 139 tests, ~4 minutes, to check two fixes).
3140
3271
  const run = runByTask.get(taskId);
3272
+ // What the REQUEST requires of this suite and the run left out: the narrowed re-run below
3273
+ // is composed from the run's own command, so without these it would measure the same wrong
3274
+ // configuration again (m182: the request names `TEST_MODE=fullstack`, the run and its
3275
+ // re-run both omitted it, and the walk measured the `spa` suite). The consumer's reading,
3276
+ // asked once per finished run; a failure to read answers "nothing required".
3277
+ const requiredEnv = run && requiredSuiteEnv
3278
+ ? ((await requiredSuiteEnv(run.command, run.cwd).catch(() => [])) ?? [])
3279
+ : [];
3141
3280
  // The tests the request excludes are not causes to fix, and the re-run below inverts them
3142
3281
  // out — a result must never ask the executor to fix a test it also says does not count.
3143
3282
  // The log's own path rides along so a recap that leaves causes out can hand over the ONE
3144
3283
  // grep that prints their bodies: the stdout above is cut in the middle, so the log is where
3145
3284
  // they still are whole.
3146
- const causes = failureCausesNote(output, excludedTestTitles?.() ?? [], run ? { ...run, log: ownFile ?? log } : undefined);
3285
+ const causes = failureCausesNote(output, excludedTestTitles?.() ?? [], run ? { ...run, log: ownFile ?? log, env: requiredEnv } : undefined);
3147
3286
  // A backgrounded run is under no tool budget, and the exit file hands back the PIPELINE's
3148
3287
  // code — so a suite killed at a `timeout 280` the command carried behind a `| tail` reports
3149
3288
  // 0 here too. The run's start is in its own id ({@link taskStartedAt}), so the bound it used
@@ -3177,7 +3316,16 @@ export function buildTools(backend, config) {
3177
3316
  ? suiteRunPipelinePlacement(run.command)
3178
3317
  : { piped: false, unplaced: false };
3179
3318
  const reported = suiteRunExitCode(exitCode, output, placement.piped);
3180
- const noCodeNote = suiteExitCodeNote(placement, reported);
3319
+ // A run that ended with no code at all is not a filtered pipeline: the sentence below says
3320
+ // where its result came from, and claiming a stage after the runner would contradict it.
3321
+ const noCodeNote = endedWithoutCode ? null : suiteExitCodeNote(placement, reported);
3322
+ // The task ended and no exit file recorded a verdict: say so, and say where the result came
3323
+ // from, so the executor reads it instead of waiting on a handle that can never answer.
3324
+ const endedNote = endedWithoutCode
3325
+ ? 'It ended without writing an exit code — its process is gone' +
3326
+ (ownFile ? `, and its own output (${ownFile}) is the result below` : '') +
3327
+ '. Read that result; do not wait on this task again.'
3328
+ : null;
3181
3329
  // A FINISHED result says so, even when the code it would report is withheld: a filtered
3182
3330
  // pipeline's code is not the run's verdict ({@link FILTERED_EXIT_NOTE}), so `exitCode` alone
3183
3331
  // cannot tell a caller this is the delivered result rather than a progress return — and a
@@ -3187,8 +3335,12 @@ export function buildTools(backend, config) {
3187
3335
  status: 'completed',
3188
3336
  exitCode: reported,
3189
3337
  waitedMs,
3190
- ...(causes || noCodeNote
3191
- ? { note: [causes, noCodeNote].filter((n) => Boolean(n)).join(' ') }
3338
+ ...(causes || noCodeNote || endedNote
3339
+ ? {
3340
+ note: [causes, noCodeNote, endedNote]
3341
+ .filter((n) => Boolean(n))
3342
+ .join(' '),
3343
+ }
3192
3344
  : {}),
3193
3345
  stdout: sanitizeOutput(truncateMiddle(output, MAX_OUTPUT_SIZE)),
3194
3346
  ...(output.length > MAX_OUTPUT_SIZE ? { truncated: true, fullOutput: log } : {}),
@@ -190,6 +190,29 @@ export interface TraceMissingText {
190
190
  /** The path of the response that carried it (`/api/tags`). */
191
191
  path: string;
192
192
  }
193
+ /**
194
+ * A write the trace recorded answering a boolean field, and a LATER GET of the same resource
195
+ * answering the opposite for that field.
196
+ *
197
+ * This is the pair that reads as a frontend race and is not one: xr-molecule-flash-m181's follow
198
+ * test sent `POST /api/profiles/:username/follow` and the API answered
199
+ * `{"profile":{…,"following":true}}`, then a `GET /api/profiles/:username` answered
200
+ * `{"profile":{…,"following":false}}` — the READ route never saw the viewer, so it hydrated
201
+ * `following` from nobody. The run rewrote the profile component twice, the API client once, and
202
+ * added optimistic state before anyone read the route's middleware; the write itself was fine.
203
+ */
204
+ export interface TraceReadContradiction {
205
+ /** The boolean field both answered (`following`, `favorited`). */
206
+ field: string;
207
+ /** What the write's response said it is. */
208
+ writeValue: boolean;
209
+ /** What the later read's response said it is. */
210
+ readValue: boolean;
211
+ /** The write that answered it (`POST /api/profiles/x/follow`). */
212
+ write: TraceRequest;
213
+ /** The later GET of the same resource (`GET /api/profiles/x`). */
214
+ read: TraceRequest;
215
+ }
193
216
  /** What one trace says: the test it belongs to, the requests it made, and its console lines. */
194
217
  export interface TraceArtifact {
195
218
  /** The failure's spec file, relative to the run's directory, when the trace names one. */
@@ -266,6 +289,15 @@ export interface TraceArtifact {
266
289
  * read before this field existed.
267
290
  */
268
291
  missingText?: TraceMissingText;
292
+ /**
293
+ * A write's answer a later GET of the same resource contradicted — the read route does not see
294
+ * the viewer (xr-molecule-flash-m181's `following`). The note leads with it and sends the run at
295
+ * the route's middleware, not the page's state handling.
296
+ *
297
+ * Absent when no write and later read in the trace answered the same boolean field differently,
298
+ * and on traces read before this field existed.
299
+ */
300
+ readContradiction?: TraceReadContradiction;
269
301
  }
270
302
  /** How many traces one read reports, newest first. */
271
303
  export declare const MAX_TRACE_ARTIFACTS = 12;
@@ -491,6 +523,12 @@ export declare function isCredentialExchangePath(path: string, authEndpoints?: r
491
523
  * this on the deployed URL only, where the background session verification lands later than it
492
524
  * does locally.
493
525
  *
526
+ * A write whose response said a boolean field is true and a LATER GET of the same resource that
527
+ * said it is false leads the note first ({@link readContradictionSentence}): the read route never
528
+ * saw the viewer, so the fix is on that route's middleware, not in the page. xr-molecule-flash-m181
529
+ * spent ~8 minutes rewriting the profile component over exactly that pair — the write answered
530
+ * `{"following":true}` and the next profile GET answered `false`.
531
+ *
494
532
  * WHICH rows it spends is evidence, not artifact order (xr-molecule-flash-m112 +53:46): a row
495
533
  * needs a recorded response, a real failure or a console line ({@link traceRowEvidence}), rows are
496
534
  * deduplicated by the test's location, and they are ordered real failure → repeated from an
@@ -1 +1 @@
1
- {"version":3,"file":"trace-artifacts.d.ts","sourceRoot":"","sources":["../src/trace-artifacts.ts"],"names":[],"mappings":"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"}
1
+ {"version":3,"file":"trace-artifacts.d.ts","sourceRoot":"","sources":["../src/trace-artifacts.ts"],"names":[],"mappings":"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"}
@@ -284,6 +284,40 @@ function gotText(buf, entries, r) {
284
284
  return (websocketText(raw) || raw).slice(0, MAX_WS)
285
285
  }
286
286
 
287
+ // The boolean-valued fields a response body carries, however deeply its entity is wrapped
288
+ // ({"profile":{…,"following":true}}) — what a read of the same field can contradict.
289
+ // A body that does not parse (the trace read bounds what it keeps) names no field.
290
+ function booleanFieldsOf(text) {
291
+ let parsed
292
+ try { parsed = JSON.parse(text) } catch (e) { return null }
293
+ const out = {}
294
+ function walk(value, depth) {
295
+ if (depth > 4 || value === null || typeof value !== 'object') return
296
+ if (Array.isArray(value)) {
297
+ for (let i = 0; i < value.length; i++) walk(value[i], depth + 1)
298
+ return
299
+ }
300
+ for (const key of Object.keys(value)) {
301
+ const item = value[key]
302
+ if (typeof item === 'boolean') {
303
+ if (!Object.prototype.hasOwnProperty.call(out, key)) out[key] = item
304
+ } else walk(item, depth + 1)
305
+ }
306
+ }
307
+ walk(parsed, 0)
308
+ return Object.keys(out).length > 0 ? out : null
309
+ }
310
+
311
+ // The resource a write acts on: its last path segment is the action (follow, favorite), so
312
+ // /api/profiles/alice/follow is the resource a GET /api/profiles/alice reads.
313
+ function resourceBaseOf(path) {
314
+ const clean = String(path).split(/[?#]/)[0]
315
+ const parts = clean.split('/').filter(function (segment) { return segment !== '' })
316
+ if (parts.length === 0) return clean
317
+ parts.pop()
318
+ return '/' + parts.join('/')
319
+ }
320
+
287
321
  let origin = ''
288
322
  function pathOf(url) {
289
323
  try {
@@ -829,6 +863,66 @@ for (const one of found.slice(0, MAX_TRACES)) {
829
863
  if (got) lead.got = got
830
864
  }
831
865
  }
866
+ // A write that answered a boolean field and a LATER GET of the same resource that answered the
867
+ // opposite — the read route never saw the viewer (m181's follow: the write answered
868
+ // {"following":true}, the next profile GET answered false). Both bodies are the trace's own
869
+ // facts; the note leads with them and sends the run to the route's middleware, not the page.
870
+ function readContradictionOf() {
871
+ const writes = []
872
+ for (let i = 0; i < requests.length; i++) {
873
+ const r = requests[i]
874
+ if (!/^(?:POST|PUT|PATCH|DELETE)$/.test(r.method)) continue
875
+ if (r.status < 200 || r.status >= 300) continue
876
+ if (r.type !== 'fetch' && r.type !== 'xhr') continue
877
+ writes.push({ index: i, request: r })
878
+ }
879
+ for (let w = 0; w < writes.length; w++) {
880
+ const write = writes[w].request
881
+ const writeGot = gotText(buf, entries, write)
882
+ const writeFields = writeGot ? booleanFieldsOf(writeGot) : null
883
+ if (!writeFields) continue
884
+ const base = resourceBaseOf(write.path)
885
+ let read = null
886
+ let readFields = null
887
+ for (let j = writes[w].index + 1; j < requests.length; j++) {
888
+ const candidate = requests[j]
889
+ if (candidate.method !== 'GET') continue
890
+ if (candidate.status < 200 || candidate.status >= 300) continue
891
+ if (candidate.type !== 'fetch' && candidate.type !== 'xhr') continue
892
+ // The same page only: another context's read is not this page's answer.
893
+ if (candidate.pageId !== undefined && write.pageId !== undefined &&
894
+ candidate.pageId !== write.pageId) continue
895
+ if (candidate.context !== undefined && write.context !== undefined &&
896
+ candidate.context !== write.context) continue
897
+ // LATER, on the trace's own clock when it recorded one.
898
+ if (typeof candidate.startedAt === 'number' && typeof write.startedAt === 'number' &&
899
+ candidate.startedAt <= write.startedAt) continue
900
+ if (String(candidate.path).split(/[?#]/)[0] !== base) continue
901
+ const got = gotText(buf, entries, candidate)
902
+ const fields = got ? booleanFieldsOf(got) : null
903
+ if (!fields) continue
904
+ read = candidate
905
+ readFields = fields
906
+ break
907
+ }
908
+ if (read === null || readFields === null) continue
909
+ for (const key of Object.keys(writeFields)) {
910
+ if (!Object.prototype.hasOwnProperty.call(readFields, key)) continue
911
+ if (readFields[key] === writeFields[key]) continue
912
+ write.got = writeGot
913
+ read.got = gotText(buf, entries, read)
914
+ return {
915
+ field: key,
916
+ writeValue: writeFields[key],
917
+ readValue: readFields[key],
918
+ write: wire(write),
919
+ read: wire(read),
920
+ }
921
+ }
922
+ }
923
+ return null
924
+ }
925
+ const readContradiction = readContradictionOf()
832
926
  const failing = []
833
927
  const api = []
834
928
  const pending = []
@@ -934,6 +1028,7 @@ for (const one of found.slice(0, MAX_TRACES)) {
934
1028
  // plus the answered ones (xr-molecule-flash-m112's note listed only -1s and 200s).
935
1029
  requests: chosen.slice(0, MAX_REQUESTS),
936
1030
  ...(missingText === null ? {} : { missingText: missingText }),
1031
+ ...(readContradiction === null ? {} : { readContradiction: readContradiction }),
937
1032
  console: keptConsole.slice(0, MAX_CONSOLE).map(function (text) { return text.slice(0, 300) }),
938
1033
  actions: actions.slice(-MAX_ACTIONS),
939
1034
  ...(unattributed ? { unattributed: true } : {}),
@@ -988,6 +1083,29 @@ function parseMissingText(value) {
988
1083
  return null;
989
1084
  return { text: raw.text, method: raw.method, path: raw.path };
990
1085
  }
1086
+ /**
1087
+ * One `readContradiction` out of a `TRACE` line's json, or null when the value is not one.
1088
+ *
1089
+ * Both requests must parse and the two values must be booleans: a partial fact never becomes a
1090
+ * claim about the route.
1091
+ *
1092
+ * @param value - The line's `readContradiction`.
1093
+ * @returns The write, the later read and the field they disagree on, or null.
1094
+ */
1095
+ function parseReadContradiction(value) {
1096
+ if (typeof value !== 'object' || value === null)
1097
+ return null;
1098
+ const raw = value;
1099
+ if (typeof raw.field !== 'string' || raw.field === '')
1100
+ return null;
1101
+ if (typeof raw.writeValue !== 'boolean' || typeof raw.readValue !== 'boolean')
1102
+ return null;
1103
+ const write = parseTraceRequest(raw.write);
1104
+ const read = parseTraceRequest(raw.read);
1105
+ if (write === null || read === null)
1106
+ return null;
1107
+ return { field: raw.field, writeValue: raw.writeValue, readValue: raw.readValue, write, read };
1108
+ }
991
1109
  /**
992
1110
  * One `lastAction` out of a `TRACE` line's json, or null when the value is not one.
993
1111
  *
@@ -1034,6 +1152,7 @@ export function parseTraceArtifacts(stdout) {
1034
1152
  const lead = parseTraceRequest(raw.lead);
1035
1153
  const lastAction = parseLastAction(raw.lastAction);
1036
1154
  const missingText = parseMissingText(raw.missingText);
1155
+ const readContradiction = parseReadContradiction(raw.readContradiction);
1037
1156
  const otherContexts = Array.isArray(raw.otherContexts)
1038
1157
  ? raw.otherContexts
1039
1158
  .filter((c) => typeof c === 'object' && c !== null)
@@ -1070,6 +1189,7 @@ export function parseTraceArtifacts(stdout) {
1070
1189
  ...(otherContexts.length === 0 ? {} : { otherContexts }),
1071
1190
  ...(raw.unattributed === true ? { unattributed: true } : {}),
1072
1191
  ...(missingText === null ? {} : { missingText }),
1192
+ ...(readContradiction === null ? {} : { readContradiction }),
1073
1193
  });
1074
1194
  }
1075
1195
  catch (_error) {
@@ -2159,6 +2279,71 @@ function formResetSentence(reset) {
2159
2279
  `typing (an effect re-seeding the form from data that changed identity ran again after the ` +
2160
2280
  `test typed). Seed the form once, not every time that data changes.`);
2161
2281
  }
2282
+ /**
2283
+ * The sentence for a write whose answer a later GET of the same resource contradicted.
2284
+ *
2285
+ * It states the two recorded facts and the one inference they support — the read route never saw
2286
+ * the viewer — then the place to look: the route's middleware, not the page. It names both
2287
+ * possibilities the trace cannot separate (a missing auth/optional-auth middleware on that route,
2288
+ * or a different user), so the run checks the route instead of rewriting the component.
2289
+ *
2290
+ * @param contradiction - The write's answer and the later read's opposite one.
2291
+ * @returns The sentence the note leads with.
2292
+ */
2293
+ function readContradictionSentence(contradiction) {
2294
+ return (`The server answered \`${contradiction.field}\`: ${contradiction.writeValue} to ` +
2295
+ `${requestLabel(contradiction.write)} and \`${contradiction.field}\`: ` +
2296
+ `${contradiction.readValue} to ${requestLabel(contradiction.read)} — the read route does not ` +
2297
+ `see the viewer (a missing auth/optional-auth middleware on that route, or a different user); ` +
2298
+ `check the route's middleware, not the page.`);
2299
+ }
2300
+ /**
2301
+ * Chromium's webfont decode failure: the URL it fetched, and OTS's reason.
2302
+ *
2303
+ * A page that serves its SPA fallback for a missing `.woff` produces exactly this line — the
2304
+ * browser downloads `index.html` and OTS rejects the first four bytes.
2305
+ */
2306
+ const FONT_DECODE_FAILURE = /Failed to decode downloaded font:\s*(\S+)\s*\|\s*OTS parsing error:\s*(.+?)\s*$/i;
2307
+ /**
2308
+ * Whether an OTS `invalid sfntVersion: <n>` number is four ASCII bytes that start an HTML
2309
+ * document (`<!do` — `0x3C21646F` is the doctype's first four bytes).
2310
+ *
2311
+ * @param reason - The OTS reason text after `OTS parsing error:`.
2312
+ * @returns True when the codec read an HTML signature instead of a font signature.
2313
+ */
2314
+ function sfntVersionIsHtml(reason) {
2315
+ const raw = /invalid sfntVersion:\s*(\d+)/i.exec(reason)?.[1];
2316
+ if (raw === undefined)
2317
+ return false;
2318
+ const value = Number(raw);
2319
+ if (!Number.isInteger(value) || value < 0 || value > 0xffffffff)
2320
+ return false;
2321
+ const magic = String.fromCharCode((value >>> 24) & 0xff, (value >>> 16) & 0xff, (value >>> 8) & 0xff, value & 0xff);
2322
+ return magic.startsWith('<');
2323
+ }
2324
+ /**
2325
+ * One line of a failure row's `console:` list, with the webfont-decode signature explained.
2326
+ *
2327
+ * `Failed to decode downloaded font: <url> | OTS parsing error: invalid sfntVersion: 1008821359`
2328
+ * is not a font to debug: the URL answered HTML (the app's `index.html`, the SPA fallback), so
2329
+ * the file the `@font-face` names is not there. xr-molecule-flash-m186's page fetched
2330
+ * `/fonts/ionicons.woff`, got the index document, and the note printed the raw decode error
2331
+ * while the model went looking elsewhere.
2332
+ *
2333
+ * @param text - The console line, as the trace recorded it.
2334
+ * @returns The line to print, naming the URL that served HTML when it is that failure.
2335
+ */
2336
+ function consoleLine(text) {
2337
+ const normalized = text.replace(/\s+/g, ' ').trim();
2338
+ const failure = FONT_DECODE_FAILURE.exec(normalized);
2339
+ if (!failure)
2340
+ return normalized;
2341
+ const [, url, reason] = failure;
2342
+ if (!sfntVersionIsHtml(reason))
2343
+ return normalized;
2344
+ return (`${url} answered the app's index.html, not a font — the file is missing from ` +
2345
+ `\`app/public/\` (or the asset import); copy/import it`);
2346
+ }
2162
2347
  /**
2163
2348
  * The note a failed suite run's result carries: what each failing test's page actually sent, and
2164
2349
  * what came back.
@@ -2206,6 +2391,12 @@ function formResetSentence(reset) {
2206
2391
  * this on the deployed URL only, where the background session verification lands later than it
2207
2392
  * does locally.
2208
2393
  *
2394
+ * A write whose response said a boolean field is true and a LATER GET of the same resource that
2395
+ * said it is false leads the note first ({@link readContradictionSentence}): the read route never
2396
+ * saw the viewer, so the fix is on that route's middleware, not in the page. xr-molecule-flash-m181
2397
+ * spent ~8 minutes rewriting the profile component over exactly that pair — the write answered
2398
+ * `{"following":true}` and the next profile GET answered `false`.
2399
+ *
2209
2400
  * WHICH rows it spends is evidence, not artifact order (xr-molecule-flash-m112 +53:46): a row
2210
2401
  * needs a recorded response, a real failure or a console line ({@link traceRowEvidence}), rows are
2211
2402
  * deduplicated by the test's location, and they are ordered real failure → repeated from an
@@ -2468,7 +2659,7 @@ export function failureTraceNote(items, target, earlierFailures = [], apiPrefixe
2468
2659
  if (item.console.length > 0)
2469
2660
  parts.push(`console: ${item.console
2470
2661
  .slice(0, 2)
2471
- .map((text) => text.replace(/\s+/g, ' ').trim().slice(0, 160))
2662
+ .map((text) => consoleLine(text).slice(0, 160))
2472
2663
  .join(' | ')}`);
2473
2664
  // A request from another browser context the test opened is not the failing action's effect:
2474
2665
  // it is set-up work on a different page, and it is named as such rather than merged into the
@@ -2566,6 +2757,24 @@ export function failureTraceNote(items, target, earlierFailures = [], apiPrefixe
2566
2757
  const missingTextLead = missingTexts.length === 0
2567
2758
  ? ''
2568
2759
  : `${missingTexts.slice(0, 2).map(missingTextSentence).join(' ')}\n\n`;
2760
+ // A write whose answer a later GET of the same resource contradicted: the read route does not
2761
+ // see the viewer (m181's `following` — the write answered true, the next profile GET answered
2762
+ // false). It reads as a frontend race and is not one, so it leads the note before any row and
2763
+ // before the form-reset reading.
2764
+ const readContradictions = [
2765
+ ...new Map(traced
2766
+ .filter((item) => item.readContradiction !== undefined)
2767
+ .map((item) => {
2768
+ const contradiction = item.readContradiction;
2769
+ return [
2770
+ `${contradiction.field}\u0000${contradiction.write.method} ${contradiction.write.path}`,
2771
+ contradiction,
2772
+ ];
2773
+ })).values(),
2774
+ ];
2775
+ const readContradictionLead = readContradictions.length === 0
2776
+ ? ''
2777
+ : `${readContradictions.slice(0, 2).map(readContradictionSentence).join(' ')}\n\n`;
2569
2778
  // A field the test typed and the page submitted empty: the form re-seeded itself after the
2570
2779
  // typing (m173's Settings race — the deployed URL lands the background session verification
2571
2780
  // later than a local run, and its new user object re-ran the form's seeding effect between the
@@ -2577,7 +2786,8 @@ export function failureTraceNote(items, target, earlierFailures = [], apiPrefixe
2577
2786
  .map((reset) => [`${reset.request.method} ${reset.request.path}\u0000${reset.field}`, reset])).values(),
2578
2787
  ];
2579
2788
  const formResetLead = formResets.length === 0 ? '' : `${formResets.slice(0, 2).map(formResetSentence).join(' ')}\n\n`;
2580
- return (formResetLead +
2789
+ return (readContradictionLead +
2790
+ formResetLead +
2581
2791
  missingTextLead +
2582
2792
  transportLead +
2583
2793
  setupOriginLead +
package/dist/types.d.ts CHANGED
@@ -164,6 +164,25 @@ export interface ToolBuildConfig {
164
164
  * @returns The quoted titles the request carves out.
165
165
  */
166
166
  excludedTestTitles?: () => readonly string[];
167
+ /**
168
+ * The `NAME=value` settings the person's request REQUIRES of a suite run (molecule-dev's
169
+ * `requiredRunSettings` — its mode, say), asked when the cause note composes a narrowed re-run
170
+ * of a finished run's failures. A re-run composed from the executor's own command inherits what
171
+ * that command set — and nothing it left out, so a run that measured the suite in `spa` handed
172
+ * back a re-run that would measure `spa` again (xr-molecule-flash-m182 +12:06: the request names
173
+ * `TEST_MODE=fullstack`, the run and its re-run both omitted it).
174
+ *
175
+ * A getter, not an array: the request is read per turn while the tool set is built once, and
176
+ * what the suite's own files read is the consumer's reading. Unset answers "nothing required".
177
+ *
178
+ * @param command - The command the finished run was started with.
179
+ * @param cwd - The resolved working directory it ran in.
180
+ * @returns The settings to put on a re-run of that command.
181
+ */
182
+ requiredSuiteEnv?: (command: string, cwd: string) => Promise<readonly {
183
+ name: string;
184
+ value: string;
185
+ }[] | null | undefined>;
167
186
  /**
168
187
  * The supplied suite's own budget, when the Playwright config a command would load sets
169
188
  * different settings, asked BEFORE the run executes. The consumer knows where the suite and its
@@ -1 +1 @@
1
- {"version":3,"file":"types.d.ts","sourceRoot":"","sources":["../src/types.ts"],"names":[],"mappings":"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"}
1
+ {"version":3,"file":"types.d.ts","sourceRoot":"","sources":["../src/types.ts"],"names":[],"mappings":"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"}
@@ -5,7 +5,7 @@
5
5
  * @module
6
6
  */
7
7
  import { type RunFailureKind } from './failure-kind.js';
8
- import { type DiagnosisRunContext } from './suite-overlap.js';
8
+ import { type DiagnosisRunContext, type RunEnvSetting } from './suite-overlap.js';
9
9
  /**
10
10
  * Shell-safe quoting using single quotes. Unlike JSON.stringify (double quotes),
11
11
  * single-quoted strings prevent command substitution ($(), backticks) and variable expansion.
@@ -1169,8 +1169,8 @@ export declare function failuresByCause(log: string, excluded?: readonly string[
1169
1169
  * @param log - The finished run's output.
1170
1170
  * @param excluded - The test titles the request carves out, if the caller knows them.
1171
1171
  * @param run - How the run was started, when the caller knows it: the narrowed re-run is built
1172
- * from `command`/`cwd`/`config`, and `log` (the path the output was written to) is what the
1173
- * "left out" sentence greps when more causes exist than the result has room for.
1172
+ * from `command`/`cwd`/`config`/`env`, and `log` (the path the output was written to) is what
1173
+ * the "left out" sentence greps when more causes exist than the result has room for.
1174
1174
  * @returns The note, or null.
1175
1175
  */
1176
1176
  export declare function failureCausesNote(log: string, excluded?: readonly string[], run?: {
@@ -1178,6 +1178,7 @@ export declare function failureCausesNote(log: string, excluded?: readonly strin
1178
1178
  cwd?: string;
1179
1179
  log?: string;
1180
1180
  config?: string | null;
1181
+ env?: readonly RunEnvSetting[];
1181
1182
  }, pageErrors?: readonly CausePageErrors[]): string | null;
1182
1183
  /**
1183
1184
  * The command that re-runs the tests at `locations` the way the run IN FLIGHT ran them: the same
@@ -1192,7 +1193,9 @@ export declare function failureCausesNote(log: string, excluded?: readonly strin
1192
1193
  * refused while the run walks ({@link suiteRunInTheWay}).
1193
1194
  *
1194
1195
  * @param run - The run in flight: the command it was started with, as it was run, the directory
1195
- * that command ran in, and the config it loaded when the caller knows it.
1196
+ * that command ran in, the config it loaded when the caller knows it, and the settings the
1197
+ * request required and the run left out (`env`) — the re-run carries them, so it never
1198
+ * reproduces the configuration the run was measured under by mistake (m182).
1196
1199
  * @param locations - The failing `file:line`s to re-run, as the run's log printed them.
1197
1200
  * @param excluded - The test titles the request carves out: the re-run inverts them out
1198
1201
  * (`--grep-invert`) so it cannot report them again.
@@ -1202,6 +1205,7 @@ export declare function rerunOfRunningSuite(run: {
1202
1205
  command: string;
1203
1206
  cwd?: string;
1204
1207
  config?: string | null;
1208
+ env?: readonly RunEnvSetting[];
1205
1209
  }, locations: readonly string[], excluded?: readonly string[]): string | null;
1206
1210
  /**
1207
1211
  * The sentence that names a cause repeating among a running suite's failures, mid-run.
@@ -1248,6 +1252,7 @@ export declare function repeatingFailureNote(found: RepeatingFailure, o: {
1248
1252
  run?: {
1249
1253
  command: string;
1250
1254
  cwd?: string;
1255
+ env?: readonly RunEnvSetting[];
1251
1256
  };
1252
1257
  editsInvalidateRun?: boolean;
1253
1258
  }): string;
@@ -1 +1 @@
1
- {"version":3,"file":"utilities.d.ts","sourceRoot":"","sources":["../src/utilities.ts"],"names":[],"mappings":"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"}
1
+ {"version":3,"file":"utilities.d.ts","sourceRoot":"","sources":["../src/utilities.ts"],"names":[],"mappings":"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"}
package/dist/utilities.js CHANGED
@@ -2980,8 +2980,8 @@ function noBaseUrlConfigNote(causes, run, excluded) {
2980
2980
  * @param log - The finished run's output.
2981
2981
  * @param excluded - The test titles the request carves out, if the caller knows them.
2982
2982
  * @param run - How the run was started, when the caller knows it: the narrowed re-run is built
2983
- * from `command`/`cwd`/`config`, and `log` (the path the output was written to) is what the
2984
- * "left out" sentence greps when more causes exist than the result has room for.
2983
+ * from `command`/`cwd`/`config`/`env`, and `log` (the path the output was written to) is what
2984
+ * the "left out" sentence greps when more causes exist than the result has room for.
2985
2985
  * @returns The note, or null.
2986
2986
  */
2987
2987
  export function failureCausesNote(log, excluded = [], run, pageErrors = []) {
@@ -3181,7 +3181,9 @@ function omittedCausesRecap(omitted, run, excluded) {
3181
3181
  * refused while the run walks ({@link suiteRunInTheWay}).
3182
3182
  *
3183
3183
  * @param run - The run in flight: the command it was started with, as it was run, the directory
3184
- * that command ran in, and the config it loaded when the caller knows it.
3184
+ * that command ran in, the config it loaded when the caller knows it, and the settings the
3185
+ * request required and the run left out (`env`) — the re-run carries them, so it never
3186
+ * reproduces the configuration the run was measured under by mistake (m182).
3185
3187
  * @param locations - The failing `file:line`s to re-run, as the run's log printed them.
3186
3188
  * @param excluded - The test titles the request carves out: the re-run inverts them out
3187
3189
  * (`--grep-invert`) so it cannot report them again.
@@ -3193,7 +3195,7 @@ export function rerunOfRunningSuite(run, locations, excluded = []) {
3193
3195
  // The run's own directory is the base a relative failure location resolves against: the
3194
3196
  // reporter prints it from where the runner started, and Playwright matches file arguments
3195
3197
  // against absolute paths (xr-molecule-flash-m118 +16:34, m124 +18:38).
3196
- const scoped = scopedRerunCommand(run.command, locations, excluded, run.config, run.cwd);
3198
+ const scoped = scopedRerunCommand(run.command, locations, excluded, run.config, run.cwd, run.env ?? []);
3197
3199
  if (scoped === run.command)
3198
3200
  return null;
3199
3201
  if (!run.cwd || commandSegments(withoutHeredocs(run.command)).some((s) => s.program === 'cd'))
package/package.json CHANGED
@@ -1,6 +1,6 @@
1
1
  {
2
2
  "name": "@molecule/api-ai-tools",
3
- "version": "1.9.19",
3
+ "version": "1.10.0",
4
4
  "description": "Shared AI agent tools with backend abstraction for sandbox and local execution",
5
5
  "type": "module",
6
6
  "main": "dist/index.js",