@molecule/api-ai-tools 1.7.0 → 1.8.2
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 +324 -25
- package/dist/command-position.d.ts +42 -0
- package/dist/command-position.d.ts.map +1 -1
- package/dist/command-position.js +271 -41
- package/dist/cut-run.d.ts +98 -8
- package/dist/cut-run.d.ts.map +1 -1
- package/dist/cut-run.js +182 -29
- package/dist/suite-overlap.d.ts +5 -1
- package/dist/suite-overlap.d.ts.map +1 -1
- package/dist/suite-overlap.js +16 -2
- package/dist/tools.d.ts.map +1 -1
- package/dist/tools.js +78 -13
- package/dist/trace-artifacts.d.ts.map +1 -1
- package/dist/trace-artifacts.js +45 -1
- package/dist/types.d.ts +13 -0
- package/dist/types.d.ts.map +1 -1
- package/dist/utilities.d.ts +121 -8
- package/dist/utilities.d.ts.map +1 -1
- package/dist/utilities.js +482 -41
- package/package.json +1 -1
package/README.md
CHANGED
|
@@ -3,7 +3,7 @@ AUTO-GENERATED — DO NOT EDIT THIS FILE.
|
|
|
3
3
|
Generated by `mlcl sync-docs` from the package's src/index.ts JSDoc + mlcl/registry.json.
|
|
4
4
|
Edits here are overwritten on the next commit (molecule's pre-commit hook regenerates).
|
|
5
5
|
To change this document, edit the module-level JSDoc in src/index.ts.
|
|
6
|
-
Generated: 2026-10-
|
|
6
|
+
Generated: 2026-10-17T02:50:55.123Z
|
|
7
7
|
-->
|
|
8
8
|
|
|
9
9
|
# @molecule/api-ai-tools
|
|
@@ -81,6 +81,72 @@ interface CommandSegment {
|
|
|
81
81
|
}
|
|
82
82
|
```
|
|
83
83
|
|
|
84
|
+
#### `LocatedCommandSegment`
|
|
85
|
+
|
|
86
|
+
One statement of a shell command, with where it sits and the variables it sets for itself.
|
|
87
|
+
|
|
88
|
+
`commandSegments` answers WHAT runs; this answers where, and what the shell binds to it — the
|
|
89
|
+
two things a caller that WRITES into a command needs. The platform composes a run from the
|
|
90
|
+
executor's own command in more than one place, and a value written for the runner belongs in
|
|
91
|
+
the runner's own statement: `APP_BASE=https://… cd app && npx playwright test` sets the variable
|
|
92
|
+
for `cd` alone, so the Playwright config falls back to the local app while the command line
|
|
93
|
+
still names the deployed host (xr-molecule-flash-m103 +28:08).
|
|
94
|
+
|
|
95
|
+
```typescript
|
|
96
|
+
interface LocatedCommandSegment {
|
|
97
|
+
/**
|
|
98
|
+
* What the statement runs, or null when it only sets variables (`BASE=http://…` on its own):
|
|
99
|
+
* that shape persists in the shell, so a caller following assignments across `;`/`&&` has to
|
|
100
|
+
* see it.
|
|
101
|
+
*/
|
|
102
|
+
segment: CommandSegment | null
|
|
103
|
+
/** The statement's own leading `NAME=value` words, as written (`TEST_MODE=fullstack`). */
|
|
104
|
+
assignments: readonly string[]
|
|
105
|
+
/**
|
|
106
|
+
* The offset in the command of the statement's first word, or null for a segment inside a
|
|
107
|
+
* nested `sh -c '<command>'` string — its positions are offsets in THAT string, not in this
|
|
108
|
+
* command, so nothing may be spliced at them.
|
|
109
|
+
*/
|
|
110
|
+
start: number | null
|
|
111
|
+
/**
|
|
112
|
+
* The offset in the command just before the word the statement runs — after its own leading
|
|
113
|
+
* `NAME=value` words and their whitespace. A `NAME=value` written here is in the environment of
|
|
114
|
+
* the program the statement runs (`… TEST_MODE=fullstack <here>npx playwright test`). Null
|
|
115
|
+
* inside a nested `sh -c` string, for the same reason as {@link start}.
|
|
116
|
+
*/
|
|
117
|
+
assignmentOffset: number | null
|
|
118
|
+
}
|
|
119
|
+
```
|
|
120
|
+
|
|
121
|
+
#### `SuiteSummary`
|
|
122
|
+
|
|
123
|
+
What a runner's own closing summary reports, and whether it accounts for the whole run.
|
|
124
|
+
|
|
125
|
+
A summary is not by itself proof that the run finished. Playwright prints one when its process
|
|
126
|
+
is stopped too (SIGTERM/SIGINT), listing only the tests it reached — so a run killed at 36 of
|
|
127
|
+
139 tests ends with the same `36 passed (2.5m)` line as a run that walked all 139. The only
|
|
128
|
+
thing that separates them is the total the runner announced before it started
|
|
129
|
+
(`Running 139 tests using 1 worker`), which {@link suiteSummary} reconciles the summary against.
|
|
130
|
+
|
|
131
|
+
```typescript
|
|
132
|
+
interface SuiteSummary {
|
|
133
|
+
/**
|
|
134
|
+
* The total the runner announced before its first test, or null when it announced none (Hurl
|
|
135
|
+
* announces nothing; Vitest's own summary line carries its total in parentheses).
|
|
136
|
+
*/
|
|
137
|
+
announced: number | null
|
|
138
|
+
/**
|
|
139
|
+
* Every test the summary accounts for — the ones it passed, failed, marked flaky, timed out,
|
|
140
|
+
* interrupted, skipped or left "did not run". This is how far the walk got, which is what a
|
|
141
|
+
* stopped run's sentence says; a summary that accounts for fewer than {@link announced} was
|
|
142
|
+
* printed by a process that stopped early.
|
|
143
|
+
*/
|
|
144
|
+
accounted: number
|
|
145
|
+
/** Whether the summary accounts for every test the runner announced. */
|
|
146
|
+
finished: boolean
|
|
147
|
+
}
|
|
148
|
+
```
|
|
149
|
+
|
|
84
150
|
#### `CutRun`
|
|
85
151
|
|
|
86
152
|
A run a budget stopped, as its result reports it.
|
|
@@ -96,9 +162,15 @@ interface CutRun {
|
|
|
96
162
|
* the pipeline's filter (`… | tail`) rather than to the run — the case that read as success.
|
|
97
163
|
*/
|
|
98
164
|
exitCode: number | null
|
|
99
|
-
/**
|
|
165
|
+
/**
|
|
166
|
+
* How far the run got, as its own output counts it — the files that finished, or the tests its
|
|
167
|
+
* summary accounts for — or null when the output says nothing.
|
|
168
|
+
*/
|
|
100
169
|
ran: number | null
|
|
101
|
-
/**
|
|
170
|
+
/**
|
|
171
|
+
* How many the run was walking: the total its runner announced (`Running 139 tests`), or
|
|
172
|
+
* Playwright's `[n/K]`, whichever the output carries; null when neither does.
|
|
173
|
+
*/
|
|
102
174
|
total: number | null
|
|
103
175
|
/** The noun the runner counts in. */
|
|
104
176
|
noun: 'files' | 'tests'
|
|
@@ -376,6 +448,20 @@ interface ToolBuildConfig {
|
|
|
376
448
|
*/
|
|
377
449
|
outlineLargeHtml?: () => boolean
|
|
378
450
|
|
|
451
|
+
/**
|
|
452
|
+
* The test titles the person's request EXCLUDES by name (molecule-dev's `excludedTestTitles`),
|
|
453
|
+
* asked when a finished suite run's cause note is built. Their failures are not causes to fix:
|
|
454
|
+
* the note drops them, says so at the end, and inverts them out of the narrowed re-run it hands
|
|
455
|
+
* over — a result must never name a test beside "it does not count" (xr-molecule-flash-m101
|
|
456
|
+
* +12:00, where the executor spent a turn and an edit on the excluded test).
|
|
457
|
+
*
|
|
458
|
+
* A getter, not an array, because the request is read per turn while the tool set is built
|
|
459
|
+
* once. Unset means no test is excluded.
|
|
460
|
+
*
|
|
461
|
+
* @returns The quoted titles the request carves out.
|
|
462
|
+
*/
|
|
463
|
+
excludedTestTitles?: () => readonly string[]
|
|
464
|
+
|
|
379
465
|
/** Post-write hook (e.g. auto-format via Prettier/ESLint). Called after every write_file/edit_file. */
|
|
380
466
|
onAfterWrite?: (path: string) => Promise<void>
|
|
381
467
|
|
|
@@ -454,6 +540,19 @@ interface PromptContext {
|
|
|
454
540
|
}
|
|
455
541
|
```
|
|
456
542
|
|
|
543
|
+
#### `SuiteFilterStrip`
|
|
544
|
+
|
|
545
|
+
A command with the output filters after its suite runner removed.
|
|
546
|
+
|
|
547
|
+
```typescript
|
|
548
|
+
interface SuiteFilterStrip {
|
|
549
|
+
/** The command to run. */
|
|
550
|
+
command: string
|
|
551
|
+
/** The pipeline stages dropped, as written (`| grep … | tail -20`), or '' when none were. */
|
|
552
|
+
dropped: string
|
|
553
|
+
}
|
|
554
|
+
```
|
|
555
|
+
|
|
457
556
|
#### `FailedTest`
|
|
458
557
|
|
|
459
558
|
One failed test, as a running suite's log names it.
|
|
@@ -514,6 +613,12 @@ interface FailureCause {
|
|
|
514
613
|
seconds: number | null
|
|
515
614
|
/** The distinct tests it hit, in the order the log named them. */
|
|
516
615
|
tests: FailedTest[]
|
|
616
|
+
/**
|
|
617
|
+
* The FIRST failure's two most useful body lines — the values that differ, or the locator from
|
|
618
|
+
* its `Call log` ({@link failureEvidence}) — so a fix round needs no re-read of the log. Empty
|
|
619
|
+
* for a duration group, whose blocks carried no bodies.
|
|
620
|
+
*/
|
|
621
|
+
evidence: string[]
|
|
517
622
|
}
|
|
518
623
|
```
|
|
519
624
|
|
|
@@ -532,7 +637,17 @@ type CommandRunState = 'ran' | typeof CUT_AT_BUDGET
|
|
|
532
637
|
What stopped a run.
|
|
533
638
|
|
|
534
639
|
```typescript
|
|
535
|
-
type CutBy =
|
|
640
|
+
type CutBy =
|
|
641
|
+
/** This tool's own budget (the backend's `timeout`, just past it). */
|
|
642
|
+
| 'tool-budget'
|
|
643
|
+
/** The `timeout <N>` the command itself carried. */
|
|
644
|
+
| 'command-timeout'
|
|
645
|
+
/**
|
|
646
|
+
* Something outside the run: the runner's summary does not account for the total it announced,
|
|
647
|
+
* and neither of the two bounds above had fired — the process was killed by something this
|
|
648
|
+
* platform does not own (the sandbox's own process supervisor, the box going away, a signal).
|
|
649
|
+
*/
|
|
650
|
+
| 'process-stop'
|
|
536
651
|
```
|
|
537
652
|
|
|
538
653
|
#### `DiscoveredSkill` _(deprecated)_
|
|
@@ -608,6 +723,20 @@ function commandSegments(command: string): CommandSegment[]
|
|
|
608
723
|
|
|
609
724
|
**Returns:** One entry per statement or pipeline stage that runs something, in order.
|
|
610
725
|
|
|
726
|
+
#### `locatedCommandSegments(command)`
|
|
727
|
+
|
|
728
|
+
Every statement of a command, with its own assignments and where it sits — assignment-only
|
|
729
|
+
statements included, because the variables those persist are exactly what a later statement of
|
|
730
|
+
the same command reads.
|
|
731
|
+
|
|
732
|
+
```typescript
|
|
733
|
+
function locatedCommandSegments(command: string): LocatedCommandSegment[]
|
|
734
|
+
```
|
|
735
|
+
|
|
736
|
+
- `command` — The shell command.
|
|
737
|
+
|
|
738
|
+
**Returns:** One entry per statement or pipeline stage, in order.
|
|
739
|
+
|
|
611
740
|
#### `commandTimeoutSeconds(command)`
|
|
612
741
|
|
|
613
742
|
The bound a command puts on its own run: the largest `timeout <N>` any of its segments runs
|
|
@@ -662,9 +791,29 @@ function commandRunState(result: unknown): CommandRunState
|
|
|
662
791
|
|
|
663
792
|
**Returns:** The state the result records.
|
|
664
793
|
|
|
794
|
+
#### `suiteSummary(text)`
|
|
795
|
+
|
|
796
|
+
What the runner's closing summary accounts for, or null when it printed none.
|
|
797
|
+
|
|
798
|
+
Three runners' summaries are read, each by its own wording: Playwright's per-status lines
|
|
799
|
+
(reconciled against its `Running N tests` announcement), Vitest's single `Tests …` line (its own
|
|
800
|
+
parenthesised total), and Hurl's `Executed files:` block (which it prints only at the end, and
|
|
801
|
+
which announces no total — so it is a finish by construction).
|
|
802
|
+
|
|
803
|
+
```typescript
|
|
804
|
+
function suiteSummary(text: string): SuiteSummary | null
|
|
805
|
+
```
|
|
806
|
+
|
|
807
|
+
- `text` — The run's stdout and stderr, RAW (a truncated copy can lose the announcement).
|
|
808
|
+
|
|
809
|
+
**Returns:** The summary, or null when the text carries none.
|
|
810
|
+
|
|
665
811
|
#### `suiteTally(text)`
|
|
666
812
|
|
|
667
|
-
Whether text carries a runner's closing summary
|
|
813
|
+
Whether text carries a runner's closing summary.
|
|
814
|
+
|
|
815
|
+
A summary is NOT a finish on its own — a stopped Playwright run prints one too. Use
|
|
816
|
+
{@link suiteSummary} and its `finished` for that.
|
|
668
817
|
|
|
669
818
|
```typescript
|
|
670
819
|
function suiteTally(text: string): boolean
|
|
@@ -674,13 +823,39 @@ function suiteTally(text: string): boolean
|
|
|
674
823
|
|
|
675
824
|
**Returns:** True when the runner's own end-of-run summary is there.
|
|
676
825
|
|
|
677
|
-
#### `
|
|
826
|
+
#### `suiteRunExitCode(exitCode, output, piped)`
|
|
827
|
+
|
|
828
|
+
The exit code a finished suite run may report.
|
|
829
|
+
|
|
830
|
+
The code in a background result is the code of the command's LAST pipeline stage. When a stage
|
|
831
|
+
after the suite runner still consumes its output (`| tee run.log`, or a filter the platform could
|
|
832
|
+
not prove output-only), that stage produced the code, not the run — and `… | grep … | tail -20`
|
|
833
|
+
exited 0 for a run with a failure in it (xr-molecule-flash-m101 +25:54). No code is reported
|
|
834
|
+
then: the log's own tally decides.
|
|
835
|
+
|
|
836
|
+
The same reading covers a code of 0 beside a tally that names a failure: whatever ended the
|
|
837
|
+
pipeline, a run whose log counts a failure did not pass.
|
|
838
|
+
|
|
839
|
+
```typescript
|
|
840
|
+
function suiteRunExitCode(exitCode: number | null, output: string, piped: boolean): number | null
|
|
841
|
+
```
|
|
842
|
+
|
|
843
|
+
- `exitCode` — The code the pipeline reported (null when it has none).
|
|
844
|
+
- `output` — The run's full log.
|
|
845
|
+
- `piped` — Whether a pipeline stage after the suite runner still consumes its output.
|
|
846
|
+
|
|
847
|
+
**Returns:** The code the run may report, or null when the code is the filter's or contradicts the tally.
|
|
848
|
+
|
|
849
|
+
#### `commandCutRun(command, result, elapsedMs, budgetSeconds, rawOutput)`
|
|
678
850
|
|
|
679
851
|
The run a command's result records as stopped by a budget, or null when the result is a run that
|
|
680
852
|
ended (or says nothing about a run).
|
|
681
853
|
|
|
682
854
|
Evidence, in order — never a guess:
|
|
683
855
|
|
|
856
|
+
- the runner's own summary, when it printed one: it is a finish only if it accounts for the total
|
|
857
|
+
the runner announced. A summary that accounts for fewer is a walk a process stopped early, and
|
|
858
|
+
falls through to the branches below with its own counts ({@link suiteSummary}).
|
|
684
859
|
- `timeout`'s own 124 (the code the backend's wrapper returns whenever the TOOL's budget fired,
|
|
685
860
|
whatever the pipeline ended with) — and, when the clock says the command's own smaller bound
|
|
686
861
|
ran out first and less than the budget, that bound instead.
|
|
@@ -689,6 +864,8 @@ Evidence, in order — never a guess:
|
|
|
689
864
|
killed at its own bound. Its exit code, when the pipeline handed one back, is the filter's.
|
|
690
865
|
- the run used this tool's whole budget behind a filter that withheld its output, and printed no
|
|
691
866
|
closing summary: the budget stopped it, and no code in the result is the run's.
|
|
867
|
+
- a summary that does not account for its announced total, with neither bound fired: something
|
|
868
|
+
outside this platform stopped the process ({@link CutBy} `process-stop`).
|
|
692
869
|
|
|
693
870
|
```typescript
|
|
694
871
|
function commandCutRun(
|
|
@@ -696,6 +873,7 @@ function commandCutRun(
|
|
|
696
873
|
result: unknown,
|
|
697
874
|
elapsedMs: number,
|
|
698
875
|
budgetSeconds?: number,
|
|
876
|
+
rawOutput?: string,
|
|
699
877
|
): CutRun | null
|
|
700
878
|
```
|
|
701
879
|
|
|
@@ -703,6 +881,7 @@ function commandCutRun(
|
|
|
703
881
|
- `result` — Its result.
|
|
704
882
|
- `elapsedMs` — How long the command ran, in ms.
|
|
705
883
|
- `budgetSeconds` — This tool's foreground budget, in seconds (0 when it has none).
|
|
884
|
+
- `rawOutput` — The run's output BEFORE truncation, when the caller has it: the announcement a summary is reconciled against is the first line a long run prints, which is exactly what a size cap drops. Detection reads this; the sentence's last line still comes from `result`.
|
|
706
885
|
|
|
707
886
|
**Returns:** The stopped run, or null.
|
|
708
887
|
|
|
@@ -726,12 +905,14 @@ function cutRunFacts(result: unknown): CutRun | null
|
|
|
726
905
|
|
|
727
906
|
#### `cutRunSentence(run)`
|
|
728
907
|
|
|
729
|
-
The first line of a stopped run's result: how
|
|
730
|
-
|
|
908
|
+
The first line of a stopped run's result: how far it got, what stopped it, the last thing it
|
|
909
|
+
printed, and what the reader must do next.
|
|
731
910
|
|
|
732
911
|
Written to be quotable by the model in one sentence and to leave no room for "nearly passing":
|
|
733
912
|
the counts come from the runner's own output ({@link runProgress}), and a `total` the caller
|
|
734
|
-
read elsewhere (the suite's own file count) fills in the "
|
|
913
|
+
read elsewhere (the suite's own file count) fills in the "of N" it can then state. The sentence
|
|
914
|
+
says how many tests the stop left unrun — a number a reader cannot round up to "the suite
|
|
915
|
+
passed" — and hands over the one move that survives a long run: run it in the background.
|
|
735
916
|
|
|
736
917
|
```typescript
|
|
737
918
|
function cutRunSentence(run: CutRun): string
|
|
@@ -880,7 +1061,7 @@ function suiteCommandTarget(command: string): string
|
|
|
880
1061
|
|
|
881
1062
|
**Returns:** The target key.
|
|
882
1063
|
|
|
883
|
-
#### `scopedRerunCommand(command, locations)`
|
|
1064
|
+
#### `scopedRerunCommand(command, locations, excluded)`
|
|
884
1065
|
|
|
885
1066
|
The whole-suite command made scoped to the tests it should re-run instead: the same
|
|
886
1067
|
invocation — same directory, same settings — with the named `file:line`s in place of the whole
|
|
@@ -888,11 +1069,16 @@ suite, `--last-failed` dropped (it re-runs the tests that never ran too, X1 flas
|
|
|
888
1069
|
`--retries=0` set (a re-run of a known failure does not need to pay for retries).
|
|
889
1070
|
|
|
890
1071
|
```typescript
|
|
891
|
-
function scopedRerunCommand(
|
|
1072
|
+
function scopedRerunCommand(
|
|
1073
|
+
command: string,
|
|
1074
|
+
locations: readonly string[],
|
|
1075
|
+
excluded?: readonly string[],
|
|
1076
|
+
): string
|
|
892
1077
|
```
|
|
893
1078
|
|
|
894
1079
|
- `command` — The whole-suite run's command.
|
|
895
1080
|
- `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
|
+
- `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.
|
|
896
1082
|
|
|
897
1083
|
**Returns:** The scoped command, or the command unchanged when it runs no Playwright suite.
|
|
898
1084
|
|
|
@@ -1331,19 +1517,19 @@ killed (X1 run flash-m15 lost 20 of its 60 minutes this way, 2026-10-15):
|
|
|
1331
1517
|
|
|
1332
1518
|
- a trailing `| tail -N`, which holds everything back until the command ends.
|
|
1333
1519
|
It is dropped: `wait_for_task` already returns the end of the log.
|
|
1520
|
+
- any output-only filter piped after a SUITE runner (`| grep … | tail -20`), which hides the
|
|
1521
|
+
failing test's own error and leaves the pipeline's exit status — the filter's — as the run's.
|
|
1522
|
+
Every such stage is dropped ({@link stripTrailingSuiteFilters}); `wait_for_task` already
|
|
1523
|
+
returns the end of the full log, and a run whose tally shows a failure must never report 0
|
|
1524
|
+
(xr-molecule-flash-m101 +25:54).
|
|
1334
1525
|
- `playwright test` with no `--reporter`, which runs the config's reporter —
|
|
1335
1526
|
often `html`, which prints nothing per test. `--reporter=list` is added
|
|
1336
|
-
when the playwright run is the command's last step
|
|
1337
|
-
|
|
1338
|
-
shape the platform reads a background suite back in.
|
|
1527
|
+
when the playwright run is the command's last step, piped or not: it writes each result as
|
|
1528
|
+
it finishes, and it is the shape the platform reads a background suite back in.
|
|
1339
1529
|
|
|
1340
1530
|
The run ends up with exactly ONE reporter that prints each failure — `list`. A run that names
|
|
1341
1531
|
any other printing reporter has it REPLACED, never joined: two of them write every test result
|
|
1342
1532
|
into the log twice, which on X1 flash-m83 (2026-10-16) made a `--reporter=list,line` run (its
|
|
1343
|
-
`line` added by this function one run earlier) report two distinct failures as "4 of this run's
|
|
1344
|
-
tests have already failed the same way", and the executor stopped a 139-test walk at test 21
|
|
1345
|
-
with a single cause in hand. `line` alone is no use either: it writes `[n/N] <title>` with no
|
|
1346
|
-
✓/✘ mark and no duration, so on X1 flash-m62 an 8.3-minute walk of one suite could never trip
|
|
1347
1533
|
|
|
1348
1534
|
_(description truncated — read the full text in `node_modules/@molecule/api-ai-tools/dist/utilities.d.ts`.)_
|
|
1349
1535
|
|
|
@@ -1393,6 +1579,47 @@ function isPlaywrightRunCommand(command: string): boolean
|
|
|
1393
1579
|
|
|
1394
1580
|
**Returns:** True when the command starts a Playwright run.
|
|
1395
1581
|
|
|
1582
|
+
#### `stripTrailingSuiteFilters(command)`
|
|
1583
|
+
|
|
1584
|
+
Drop the output-only filters piped after the command's suite runner.
|
|
1585
|
+
|
|
1586
|
+
A filter after the runner is not "the end of the log" the executor asked for: it hides the
|
|
1587
|
+
failing test's own error (it usually matches none of `✘|passed|failed`), and the pipeline's exit
|
|
1588
|
+
status becomes the FILTER's, so `… 2>&1 | grep -E "✘|passed|failed|skipped" | tail -20` came back
|
|
1589
|
+
`exitCode: 0` for a run with a failure in it (xr-molecule-flash-m101 +25:54). The tool returns
|
|
1590
|
+
the end of the full log anyway, so the filter only costs diagnosability.
|
|
1591
|
+
|
|
1592
|
+
Only a contiguous suffix of the stages after the runner is cut, and only stages the parse proves
|
|
1593
|
+
are output-only ({@link isOutputOnlyFilter}): a `| tee` or `| xargs` keeps its place, and a
|
|
1594
|
+
caller that reports the run's exit code must then treat it as unknown
|
|
1595
|
+
({@link suiteRunPipedAfterRunner}).
|
|
1596
|
+
|
|
1597
|
+
```typescript
|
|
1598
|
+
function stripTrailingSuiteFilters(command: string): SuiteFilterStrip
|
|
1599
|
+
```
|
|
1600
|
+
|
|
1601
|
+
- `command` — The shell command.
|
|
1602
|
+
|
|
1603
|
+
**Returns:** The rewritten command and the stages dropped.
|
|
1604
|
+
|
|
1605
|
+
#### `suiteRunPipedAfterRunner(command)`
|
|
1606
|
+
|
|
1607
|
+
Whether the command's last step runs a suite whose output still passes through a stage after
|
|
1608
|
+
the runner — one {@link stripTrailingSuiteFilters} could not prove is output-only (`| tee log`,
|
|
1609
|
+
`| xargs …`). The pipeline's exit status is that stage's, not the run's.
|
|
1610
|
+
|
|
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
|
+
```typescript
|
|
1616
|
+
function suiteRunPipedAfterRunner(command: string): boolean
|
|
1617
|
+
```
|
|
1618
|
+
|
|
1619
|
+
- `command` — The shell command, after the streaming rewrite when one was applied.
|
|
1620
|
+
|
|
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.
|
|
1622
|
+
|
|
1396
1623
|
#### `suiteRunPriorityLaunch(command, launch)`
|
|
1397
1624
|
|
|
1398
1625
|
Start a background suite run at lower CPU and IO priority, so the sandbox it
|
|
@@ -1938,7 +2165,32 @@ function earlyReturnCause(
|
|
|
1938
2165
|
|
|
1939
2166
|
**Returns:** The cause to stop the run over, or null — in which case nothing may be stopped, the wait keeps going, and the finding rides the run's result as a note.
|
|
1940
2167
|
|
|
1941
|
-
#### `
|
|
2168
|
+
#### `matchingExcludedTitles(heading, excluded)`
|
|
2169
|
+
|
|
2170
|
+
The titles a request excludes that a test's heading names — the ONE matcher for "is this
|
|
2171
|
+
failure one the request does not count?".
|
|
2172
|
+
|
|
2173
|
+
The request quotes a test's own title (`… except "should require login to post comment"`,
|
|
2174
|
+
extracted by molecule-dev's `excludedTestTitles`) while a run's heading carries more of it
|
|
2175
|
+
(`comments.spec.ts › Comments › should require login to post comment`), so containment is the
|
|
2176
|
+
comparison. Whitespace is normalised and case is ignored: a brief may wrap the title across a
|
|
2177
|
+
line (`xr-molecule-flash-m44`), and the reporter's own casing never has to match the brief's.
|
|
2178
|
+
|
|
2179
|
+
Two readers used to answer this separately — the causes note (which therefore asked the
|
|
2180
|
+
executor to fix a test the same result said not to) and molecule-dev's exclusion notes — and
|
|
2181
|
+
xr-molecule-flash-m101 paid for the gap (+12:00: a turn and an edit spent on the excluded
|
|
2182
|
+
test).
|
|
2183
|
+
|
|
2184
|
+
```typescript
|
|
2185
|
+
function matchingExcludedTitles(heading: string, excluded: readonly string[]): string[]
|
|
2186
|
+
```
|
|
2187
|
+
|
|
2188
|
+
- `heading` — The text to match against: a test's title, its whole `file › describe › title` path, or (for a note that only has the run's output) the run's text.
|
|
2189
|
+
- `excluded` — The titles the request carves out, if the caller knows them.
|
|
2190
|
+
|
|
2191
|
+
**Returns:** The excluded titles this heading names, in the request's order.
|
|
2192
|
+
|
|
2193
|
+
#### `failuresByCause(log, excluded)`
|
|
1942
2194
|
|
|
1943
2195
|
Every failure a run names, grouped by the cause behind it — one group per cause, with the
|
|
1944
2196
|
tests it hit.
|
|
@@ -1954,15 +2206,22 @@ background `list` run — whose failures print as they fail — or a `line` repo
|
|
|
1954
2206
|
they took where it does not, which is why a duration group is labelled as a duration and not as a
|
|
1955
2207
|
proven cause. A test the log printed twice, or failed twice, is one test.
|
|
1956
2208
|
|
|
2209
|
+
A test the request EXCLUDES by name is not a cause to fix: its failure does not count for
|
|
2210
|
+
this request ({@link matchingExcludedTitles}), so it is dropped here rather than handed to the
|
|
2211
|
+
executor as work — a result that names it beside "it does not count" is the contradiction
|
|
2212
|
+
xr-molecule-flash-m101 filed (+12:00: the model spent a turn and an edit on the excluded test,
|
|
2213
|
+
on a page that was passing).
|
|
2214
|
+
|
|
1957
2215
|
```typescript
|
|
1958
|
-
function failuresByCause(log: string): FailureCause[]
|
|
2216
|
+
function failuresByCause(log: string, excluded?: readonly string[]): FailureCause[]
|
|
1959
2217
|
```
|
|
1960
2218
|
|
|
1961
2219
|
- `log` — The log of a finished or running run.
|
|
2220
|
+
- `excluded` — The test titles the request carves out, if the caller knows them.
|
|
1962
2221
|
|
|
1963
2222
|
**Returns:** The causes, the one with the most tests first.
|
|
1964
2223
|
|
|
1965
|
-
#### `failureCausesNote(log)`
|
|
2224
|
+
#### `failureCausesNote(log, excluded, run)`
|
|
1966
2225
|
|
|
1967
2226
|
The one-line-per-cause summary of a finished run's failures, or null when the run named fewer
|
|
1968
2227
|
than two of them.
|
|
@@ -1971,15 +2230,26 @@ This is what makes a run worth finishing: every cause the run found, in the resu
|
|
|
1971
2230
|
executor reads, so one round of fixes covers all of them rather than the one cause a run
|
|
1972
2231
|
stopped early happened to reach.
|
|
1973
2232
|
|
|
2233
|
+
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.
|
|
2237
|
+
|
|
1974
2238
|
```typescript
|
|
1975
|
-
function failureCausesNote(
|
|
2239
|
+
function failureCausesNote(
|
|
2240
|
+
log: string,
|
|
2241
|
+
excluded?: readonly string[],
|
|
2242
|
+
run?: { command: string; cwd?: string; log?: string },
|
|
2243
|
+
): string | null
|
|
1976
2244
|
```
|
|
1977
2245
|
|
|
1978
2246
|
- `log` — The finished run's output.
|
|
2247
|
+
- `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.
|
|
1979
2249
|
|
|
1980
2250
|
**Returns:** The note, or null.
|
|
1981
2251
|
|
|
1982
|
-
#### `rerunOfRunningSuite(run, locations)`
|
|
2252
|
+
#### `rerunOfRunningSuite(run, locations, excluded)`
|
|
1983
2253
|
|
|
1984
2254
|
The command that re-runs the tests at `locations` the way the run IN FLIGHT ran them: the same
|
|
1985
2255
|
invocation, in the same directory, narrowed to those tests — or null when the running command
|
|
@@ -1996,11 +2266,13 @@ the same app and database, and that is exactly what is refused while the run wal
|
|
|
1996
2266
|
function rerunOfRunningSuite(
|
|
1997
2267
|
run: { command: string; cwd?: string },
|
|
1998
2268
|
locations: readonly string[],
|
|
2269
|
+
excluded?: readonly string[],
|
|
1999
2270
|
): string | null
|
|
2000
2271
|
```
|
|
2001
2272
|
|
|
2002
2273
|
- `run` — The run in flight: the command it was started with, as it was run, and the directory that command ran in.
|
|
2003
2274
|
- `locations` — The failing `file:line`s to re-run, as the run's log printed them.
|
|
2275
|
+
- `excluded` — The test titles the request carves out: the re-run inverts them out (`--grep-invert`) so it cannot report them again.
|
|
2004
2276
|
|
|
2005
2277
|
**Returns:** The re-run command, or null when there is no suite to narrow.
|
|
2006
2278
|
|
|
@@ -2479,12 +2751,39 @@ How many of a repeating cause's failures the note lists before it says "and N mo
|
|
|
2479
2751
|
const REPEATING_FAILURE_LISTED: 5
|
|
2480
2752
|
```
|
|
2481
2753
|
|
|
2754
|
+
#### `TOOL_RESULT_CHARS`
|
|
2755
|
+
|
|
2756
|
+
The platform's cap on one tool result's text: `MAX_TOOL_OUTPUT_CHARS` in molecule-dev's
|
|
2757
|
+
`api/src/ai/chat-handler.ts`, which cuts a longer string field's MIDDLE. A finished run's
|
|
2758
|
+
stdout is cut to it, so the cause list must not depend on reading the log back — and must
|
|
2759
|
+
itself fit inside it, or the cut lands in the list.
|
|
2760
|
+
|
|
2761
|
+
```typescript
|
|
2762
|
+
const TOOL_RESULT_CHARS: 8000
|
|
2763
|
+
```
|
|
2764
|
+
|
|
2765
|
+
#### `FAILURE_CAUSES_CHARS`
|
|
2766
|
+
|
|
2767
|
+
The characters a finished run's cause list may use of {@link TOOL_RESULT_CHARS}. The recap
|
|
2768
|
+
measured by xr-molecule-flash-m102 (+12:43) was `12 failures, 8 causes`: one cause line is
|
|
2769
|
+
~200 chars and ~80 more with its two body lines, so 8 causes is ~2.3 k against the 8 k cap —
|
|
2770
|
+
the old 5-cause cap withheld 3 causes that the same result had room for.
|
|
2771
|
+
|
|
2772
|
+
The rest of the cap is left to the header, the narrowed re-run command and the exclusion
|
|
2773
|
+
line, which ride the same note.
|
|
2774
|
+
|
|
2775
|
+
```typescript
|
|
2776
|
+
const FAILURE_CAUSES_CHARS: number
|
|
2777
|
+
```
|
|
2778
|
+
|
|
2482
2779
|
#### `FAILURE_CAUSES_LISTED`
|
|
2483
2780
|
|
|
2484
|
-
How many causes a finished run's summary lists
|
|
2781
|
+
How many causes a finished run's summary lists at most. The character budget above is the
|
|
2782
|
+
bound that must hold (it is what keeps the note on the surviving side of the tool-result
|
|
2783
|
+
cut); this is the bound past which a list stops being read at all.
|
|
2485
2784
|
|
|
2486
2785
|
```typescript
|
|
2487
|
-
const FAILURE_CAUSES_LISTED:
|
|
2786
|
+
const FAILURE_CAUSES_LISTED: 12
|
|
2488
2787
|
```
|
|
2489
2788
|
|
|
2490
2789
|
#### `FAILURE_CAUSE_TESTS_LISTED`
|
|
@@ -58,6 +58,48 @@ export declare function durationSeconds(word: string): number | null;
|
|
|
58
58
|
* @returns One entry per statement or pipeline stage that runs something, in order.
|
|
59
59
|
*/
|
|
60
60
|
export declare function commandSegments(command: string): CommandSegment[];
|
|
61
|
+
/**
|
|
62
|
+
* One statement of a shell command, with where it sits and the variables it sets for itself.
|
|
63
|
+
*
|
|
64
|
+
* `commandSegments` answers WHAT runs; this answers where, and what the shell binds to it — the
|
|
65
|
+
* two things a caller that WRITES into a command needs. The platform composes a run from the
|
|
66
|
+
* executor's own command in more than one place, and a value written for the runner belongs in
|
|
67
|
+
* the runner's own statement: `APP_BASE=https://… cd app && npx playwright test` sets the variable
|
|
68
|
+
* for `cd` alone, so the Playwright config falls back to the local app while the command line
|
|
69
|
+
* still names the deployed host (xr-molecule-flash-m103 +28:08).
|
|
70
|
+
*/
|
|
71
|
+
export interface LocatedCommandSegment {
|
|
72
|
+
/**
|
|
73
|
+
* What the statement runs, or null when it only sets variables (`BASE=http://…` on its own):
|
|
74
|
+
* that shape persists in the shell, so a caller following assignments across `;`/`&&` has to
|
|
75
|
+
* see it.
|
|
76
|
+
*/
|
|
77
|
+
segment: CommandSegment | null;
|
|
78
|
+
/** The statement's own leading `NAME=value` words, as written (`TEST_MODE=fullstack`). */
|
|
79
|
+
assignments: readonly string[];
|
|
80
|
+
/**
|
|
81
|
+
* The offset in the command of the statement's first word, or null for a segment inside a
|
|
82
|
+
* nested `sh -c '<command>'` string — its positions are offsets in THAT string, not in this
|
|
83
|
+
* command, so nothing may be spliced at them.
|
|
84
|
+
*/
|
|
85
|
+
start: number | null;
|
|
86
|
+
/**
|
|
87
|
+
* The offset in the command just before the word the statement runs — after its own leading
|
|
88
|
+
* `NAME=value` words and their whitespace. A `NAME=value` written here is in the environment of
|
|
89
|
+
* the program the statement runs (`… TEST_MODE=fullstack <here>npx playwright test`). Null
|
|
90
|
+
* inside a nested `sh -c` string, for the same reason as {@link start}.
|
|
91
|
+
*/
|
|
92
|
+
assignmentOffset: number | null;
|
|
93
|
+
}
|
|
94
|
+
/**
|
|
95
|
+
* Every statement of a command, with its own assignments and where it sits — assignment-only
|
|
96
|
+
* statements included, because the variables those persist are exactly what a later statement of
|
|
97
|
+
* the same command reads.
|
|
98
|
+
*
|
|
99
|
+
* @param command - The shell command.
|
|
100
|
+
* @returns One entry per statement or pipeline stage, in order.
|
|
101
|
+
*/
|
|
102
|
+
export declare function locatedCommandSegments(command: string): LocatedCommandSegment[];
|
|
61
103
|
/**
|
|
62
104
|
* The bound a command puts on its own run: the largest `timeout <N>` any of its segments runs
|
|
63
105
|
* under (`timeout 280 hurl --test …` → 280), or null when it carries none.
|
|
@@ -1 +1 @@
|
|
|
1
|
-
{"version":3,"file":"command-position.d.ts","sourceRoot":"","sources":["../src/command-position.ts"],"names":[],"mappings":"AAAA;;;;;;;;;;;;;;;;;;;;;;;;;;;GA2BG;AAEH,uFAAuF;AACvF,MAAM,WAAW,cAAc;IAC7B;;;OAGG;IACH,OAAO,EAAE,MAAM,CAAA;IACf,qFAAqF;IACrF,IAAI,EAAE,SAAS,MAAM,EAAE,CAAA;IACvB,4FAA4F;IAC5F,IAAI,EAAE,MAAM,CAAA;IACZ;;;OAGG;IACH,cAAc,EAAE,MAAM,GAAG,IAAI,CAAA;CAC9B;
|
|
1
|
+
{"version":3,"file":"command-position.d.ts","sourceRoot":"","sources":["../src/command-position.ts"],"names":[],"mappings":"AAAA;;;;;;;;;;;;;;;;;;;;;;;;;;;GA2BG;AAEH,uFAAuF;AACvF,MAAM,WAAW,cAAc;IAC7B;;;OAGG;IACH,OAAO,EAAE,MAAM,CAAA;IACf,qFAAqF;IACrF,IAAI,EAAE,SAAS,MAAM,EAAE,CAAA;IACvB,4FAA4F;IAC5F,IAAI,EAAE,MAAM,CAAA;IACZ;;;OAGG;IACH,cAAc,EAAE,MAAM,GAAG,IAAI,CAAA;CAC9B;AA2MD;;;;;GAKG;AACH,wBAAgB,eAAe,CAAC,IAAI,EAAE,MAAM,GAAG,MAAM,GAAG,IAAI,CAM3D;AAkVD;;;;;;GAMG;AACH,wBAAgB,eAAe,CAAC,OAAO,EAAE,MAAM,GAAG,cAAc,EAAE,CAIjE;AAED;;;;;;;;;GASG;AACH,MAAM,WAAW,qBAAqB;IACpC;;;;OAIG;IACH,OAAO,EAAE,cAAc,GAAG,IAAI,CAAA;IAC9B,0FAA0F;IAC1F,WAAW,EAAE,SAAS,MAAM,EAAE,CAAA;IAC9B;;;;OAIG;IACH,KAAK,EAAE,MAAM,GAAG,IAAI,CAAA;IACpB;;;;;OAKG;IACH,gBAAgB,EAAE,MAAM,GAAG,IAAI,CAAA;CAChC;AAED;;;;;;;GAOG;AACH,wBAAgB,sBAAsB,CAAC,OAAO,EAAE,MAAM,GAAG,qBAAqB,EAAE,CAE/E;AAqDD;;;;;;;;;;;;GAYG;AACH,wBAAgB,qBAAqB,CAAC,OAAO,EAAE,MAAM,GAAG,MAAM,GAAG,IAAI,CAOpE;AAED;;;;;;;;;;;GAWG;AACH,wBAAgB,qBAAqB,CAAC,OAAO,EAAE,MAAM,EAAE,OAAO,EAAE,MAAM,GAAG,OAAO,CAK/E"}
|