@glubean/cli 0.7.0 → 0.8.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.
@@ -0,0 +1,54 @@
1
+ import type { LoadArtifact } from "@glubean/sdk/load";
2
+ /** A filesystem-safe result filename for a runner id. */
3
+ export declare function loadResultFileName(runnerId: string): string;
4
+ /** One plan's run outcome. */
5
+ export interface LoadRunOutcome {
6
+ file: string;
7
+ runnerId: string;
8
+ artifact: LoadArtifact;
9
+ }
10
+ /** A per-file failure (e.g. an unimportable load file). */
11
+ export interface LoadFileError {
12
+ file: string;
13
+ message: string;
14
+ }
15
+ /** Result of running a set of load files — completed outcomes + per-file errors. */
16
+ export interface RunLoadFilesResult {
17
+ outcomes: LoadRunOutcome[];
18
+ errors: LoadFileError[];
19
+ }
20
+ /**
21
+ * Run each load file's plans in a CHILD PROCESS (`runLoadFileInSubprocess`) so the
22
+ * harness and the user file co-resolve one `@glubean/sdk`, and collect the
23
+ * artifacts. A single file's import failure (or a crash) is recorded as a per-file
24
+ * error and the rest still run — completed artifacts are never discarded because a
25
+ * LATER file is broken. The raw `{ vars, secrets }` flow to the child, which
26
+ * applies the process.env fallback. Free of fs writes / process exit / printing.
27
+ */
28
+ export declare function runLoadFiles(files: string[], opts: {
29
+ vars: Record<string, string>;
30
+ secrets: Record<string, string>;
31
+ /** Project root the child runs in — drives runner resolution + bare imports. */
32
+ cwd: string;
33
+ }): Promise<RunLoadFilesResult>;
34
+ /** Write each outcome's artifact to `<glubeanDir>/<runnerId>.load.result.json`,
35
+ * disambiguating ids that sanitize to the same filename so no artifact is lost. */
36
+ export declare function writeLoadResults(outcomes: LoadRunOutcome[], glubeanDir: string): Promise<string[]>;
37
+ /** Print a one-plan summary line block. The top `iterations` line is the
38
+ * end-to-end (whole-transaction) view; when a scenario calls
39
+ * `ctx.report.primaryComplete()` the artifact also carries a primary/end-to-end
40
+ * phase split, surfaced as an extra line so an async-job run shows submit latency
41
+ * vs full latency. (Exported for display tests.) */
42
+ export declare function printOutcome(o: LoadRunOutcome): void;
43
+ /** Options for the `load` command. */
44
+ export interface LoadCommandOptions {
45
+ /** Env file basename (default: the active env, else `.env`). */
46
+ envFile?: string;
47
+ }
48
+ /**
49
+ * `glubean load [target]` — discover + run load plans under `target` (a file,
50
+ * directory, or glob; defaults to the cwd), write results, and exit non-zero if
51
+ * any plan fails.
52
+ */
53
+ export declare function loadCommand(target: string | undefined, options?: LoadCommandOptions): Promise<void>;
54
+ //# sourceMappingURL=load.d.ts.map
@@ -0,0 +1 @@
1
+ {"version":3,"file":"load.d.ts","sourceRoot":"","sources":["../../src/commands/load.ts"],"names":[],"mappings":"AAqBA,OAAO,KAAK,EAAE,YAAY,EAAE,MAAM,mBAAmB,CAAC;AA0BtD,yDAAyD;AACzD,wBAAgB,kBAAkB,CAAC,QAAQ,EAAE,MAAM,GAAG,MAAM,CAG3D;AAED,8BAA8B;AAC9B,MAAM,WAAW,cAAc;IAC7B,IAAI,EAAE,MAAM,CAAC;IACb,QAAQ,EAAE,MAAM,CAAC;IACjB,QAAQ,EAAE,YAAY,CAAC;CACxB;AAED,2DAA2D;AAC3D,MAAM,WAAW,aAAa;IAC5B,IAAI,EAAE,MAAM,CAAC;IACb,OAAO,EAAE,MAAM,CAAC;CACjB;AAED,oFAAoF;AACpF,MAAM,WAAW,kBAAkB;IACjC,QAAQ,EAAE,cAAc,EAAE,CAAC;IAC3B,MAAM,EAAE,aAAa,EAAE,CAAC;CACzB;AAED;;;;;;;GAOG;AACH,wBAAsB,YAAY,CAChC,KAAK,EAAE,MAAM,EAAE,EACf,IAAI,EAAE;IACJ,IAAI,EAAE,MAAM,CAAC,MAAM,EAAE,MAAM,CAAC,CAAC;IAC7B,OAAO,EAAE,MAAM,CAAC,MAAM,EAAE,MAAM,CAAC,CAAC;IAChC,gFAAgF;IAChF,GAAG,EAAE,MAAM,CAAC;CACb,GACA,OAAO,CAAC,kBAAkB,CAAC,CAa7B;AAED;oFACoF;AACpF,wBAAsB,gBAAgB,CACpC,QAAQ,EAAE,cAAc,EAAE,EAC1B,UAAU,EAAE,MAAM,GACjB,OAAO,CAAC,MAAM,EAAE,CAAC,CAsBnB;AA2CD;;;;qDAIqD;AACrD,wBAAgB,YAAY,CAAC,CAAC,EAAE,cAAc,GAAG,IAAI,CAkFpD;AAED,sCAAsC;AACtC,MAAM,WAAW,kBAAkB;IACjC,gEAAgE;IAChE,OAAO,CAAC,EAAE,MAAM,CAAC;CAClB;AAED;;;;GAIG;AACH,wBAAsB,WAAW,CAC/B,MAAM,EAAE,MAAM,GAAG,SAAS,EAC1B,OAAO,GAAE,kBAAuB,GAC/B,OAAO,CAAC,IAAI,CAAC,CA8Df"}
@@ -0,0 +1,270 @@
1
+ /**
2
+ * `glubean load [target]` — run performance plans (M4-c).
3
+ *
4
+ * Discovers `loadRunner()` exports in `.load.ts` files, runs each through the
5
+ * closed-model orchestrator (`@glubean/runner` `runLoad`) IN A CHILD PROCESS,
6
+ * writes each finalized `LoadArtifact` to `.glubean/<runnerId>.load.result.json`,
7
+ * prints a per-plan summary, and exits non-zero if any plan's `summary.pass` is
8
+ * false (a crash or a breached threshold). This is the dedicated load path —
9
+ * separate from `glubean run` (the per-test ProjectRunner), since load's
10
+ * execution model differs.
11
+ *
12
+ * Each `.load.ts` runs via `runLoadFileInSubprocess`, which spawns the
13
+ * project-local runner harness (as `glubean run` does) so the harness and the
14
+ * user file co-resolve one `@glubean/sdk` — no split-brain when a globally
15
+ * installed CLI runs against a project with its own non-deduped sdk.
16
+ */
17
+ import { resolve, dirname } from "node:path";
18
+ import { stat, readdir, writeFile, mkdir } from "node:fs/promises";
19
+ import { existsSync } from "node:fs";
20
+ import { glob } from "node:fs/promises";
21
+ import { loadProjectEnv, runLoadFileInSubprocess } from "@glubean/runner";
22
+ import { resolveEnvFileName } from "../lib/active_env.js";
23
+ import { findProjectConfig } from "./run.js";
24
+ const colors = {
25
+ reset: "\x1b[0m",
26
+ bold: "\x1b[1m",
27
+ dim: "\x1b[2m",
28
+ green: "\x1b[32m",
29
+ red: "\x1b[31m",
30
+ yellow: "\x1b[33m",
31
+ blue: "\x1b[34m",
32
+ cyan: "\x1b[36m",
33
+ };
34
+ // Mirror the run command's skip list (+ .glubean output) so a compiled `build/`
35
+ // dir isn't walked — otherwise a built `.load.js` could double-run a plan.
36
+ const SKIP_DIRS = new Set(["node_modules", ".git", "dist", "build", ".glubean"]);
37
+ // Directory/glob discovery matches SOURCE `.load.ts` only (like `glubean run`'s
38
+ // `.ts`-only discovery), so a compiled `.load.js`/`.mjs` alongside it isn't run
39
+ // twice. An explicit file target still runs whatever the user named.
40
+ function isLoadSourceFile(name) {
41
+ return name.endsWith(".load.ts");
42
+ }
43
+ /** A filesystem-safe result filename for a runner id. */
44
+ export function loadResultFileName(runnerId) {
45
+ const safe = runnerId.replace(/[^a-zA-Z0-9._-]/g, "_").replace(/^_+|_+$/g, "");
46
+ return `${safe || "load"}.load.result.json`;
47
+ }
48
+ /**
49
+ * Run each load file's plans in a CHILD PROCESS (`runLoadFileInSubprocess`) so the
50
+ * harness and the user file co-resolve one `@glubean/sdk`, and collect the
51
+ * artifacts. A single file's import failure (or a crash) is recorded as a per-file
52
+ * error and the rest still run — completed artifacts are never discarded because a
53
+ * LATER file is broken. The raw `{ vars, secrets }` flow to the child, which
54
+ * applies the process.env fallback. Free of fs writes / process exit / printing.
55
+ */
56
+ export async function runLoadFiles(files, opts) {
57
+ const outcomes = [];
58
+ const errors = [];
59
+ for (const file of files) {
60
+ const res = await runLoadFileInSubprocess(file, {
61
+ vars: opts.vars,
62
+ secrets: opts.secrets,
63
+ cwd: opts.cwd,
64
+ });
65
+ for (const o of res.outcomes)
66
+ outcomes.push({ file, runnerId: o.runnerId, artifact: o.artifact });
67
+ for (const e of res.errors)
68
+ errors.push({ file, message: e.message });
69
+ }
70
+ return { outcomes, errors };
71
+ }
72
+ /** Write each outcome's artifact to `<glubeanDir>/<runnerId>.load.result.json`,
73
+ * disambiguating ids that sanitize to the same filename so no artifact is lost. */
74
+ export async function writeLoadResults(outcomes, glubeanDir) {
75
+ await mkdir(glubeanDir, { recursive: true });
76
+ // Track collisions case-INSENSITIVELY: on macOS/Windows, "Checkout" and
77
+ // "checkout" are the same directory entry, so an exact-string check would let
78
+ // the second overwrite the first.
79
+ const used = new Set();
80
+ const written = [];
81
+ for (const o of outcomes) {
82
+ let name = loadResultFileName(o.runnerId);
83
+ if (used.has(name.toLowerCase())) {
84
+ // Ids collapsed to the same filename — append `-N` so both survive.
85
+ const base = name.replace(/\.load\.result\.json$/, "");
86
+ let n = 2;
87
+ while (used.has(`${base}-${n}.load.result.json`.toLowerCase()))
88
+ n += 1;
89
+ name = `${base}-${n}.load.result.json`;
90
+ }
91
+ used.add(name.toLowerCase());
92
+ const path = resolve(glubeanDir, name);
93
+ await writeFile(path, JSON.stringify(o.artifact, null, 2), "utf-8");
94
+ written.push(path);
95
+ }
96
+ return written;
97
+ }
98
+ /** Recursively collect `.load.ts` files under a directory. */
99
+ async function walkLoadFiles(dir, out) {
100
+ for (const entry of await readdir(dir, { withFileTypes: true })) {
101
+ if (entry.isDirectory()) {
102
+ if (!SKIP_DIRS.has(entry.name))
103
+ await walkLoadFiles(resolve(dir, entry.name), out);
104
+ }
105
+ else if (entry.isFile() && isLoadSourceFile(entry.name)) {
106
+ out.push(resolve(dir, entry.name));
107
+ }
108
+ }
109
+ }
110
+ /** Resolve a file / directory / glob target to a sorted, deduped `.load.ts` list. */
111
+ async function resolveLoadFiles(target) {
112
+ const abs = resolve(target);
113
+ try {
114
+ const s = await stat(abs);
115
+ if (s.isFile())
116
+ return [abs];
117
+ if (s.isDirectory()) {
118
+ const files = [];
119
+ await walkLoadFiles(abs, files);
120
+ files.sort();
121
+ return files;
122
+ }
123
+ }
124
+ catch {
125
+ // not a path — try glob below
126
+ }
127
+ const files = [];
128
+ for await (const entry of glob(target, { cwd: process.cwd() })) {
129
+ const full = resolve(process.cwd(), entry);
130
+ if (!isLoadSourceFile(full))
131
+ continue;
132
+ const s = await stat(full).catch(() => null);
133
+ if (s?.isFile())
134
+ files.push(full);
135
+ }
136
+ files.sort();
137
+ return [...new Set(files)];
138
+ }
139
+ function pct(fraction) {
140
+ return `${(fraction * 100).toFixed(2)}%`;
141
+ }
142
+ /** Print a one-plan summary line block. The top `iterations` line is the
143
+ * end-to-end (whole-transaction) view; when a scenario calls
144
+ * `ctx.report.primaryComplete()` the artifact also carries a primary/end-to-end
145
+ * phase split, surfaced as an extra line so an async-job run shows submit latency
146
+ * vs full latency. (Exported for display tests.) */
147
+ export function printOutcome(o) {
148
+ const s = o.artifact.summary;
149
+ const verdict = s.pass
150
+ ? `${colors.green}PASS${colors.reset}`
151
+ : `${colors.red}FAIL${colors.reset}`;
152
+ console.log(`${colors.bold}${o.runnerId}${colors.reset} ${verdict}`);
153
+ console.log(`${colors.dim} iterations ${s.totalIterations} (ok ${s.successfulIterations}, failed ${s.failedIterations})` +
154
+ ` errorRate ${pct(s.errorRate)} p95 ${Math.round(s.latency.p95)}ms` +
155
+ ` throughput ${s.throughputPerSec.toFixed(1)}/s${colors.reset}`);
156
+ // Phase split (M5): the line above is end-to-end; show the primary phase (up to
157
+ // the primaryComplete boundary). `completed/started` indicates primary coverage —
158
+ // when fewer iterations complete primary than started, some failed before the
159
+ // boundary (a branch/error path); precise boundary coverage lands with M6.
160
+ if (s.primary) {
161
+ console.log(`${colors.dim} primary (to boundary) p95 ${Math.round(s.primary.latency.p95)}ms` +
162
+ ` throughput ${s.primary.throughputPerSec.toFixed(1)}/s` +
163
+ ` completed ${s.primary.completed}/${s.primary.started}${colors.reset}`);
164
+ if (s.primary.completed < s.primary.started) {
165
+ console.log(`${colors.yellow} ⚠ ${s.primary.started - s.primary.completed} iteration(s) did not reach the primary boundary` +
166
+ ` (failed before it, or a branch skipped it)${colors.reset}`);
167
+ }
168
+ }
169
+ // Continuation / producer-release subsystem (M6): present once any iteration engaged
170
+ // release (released / rejected / duplicate / still pending). Show the slot model, how
171
+ // many slots were released, the backlog peak + back-pressure, then surface rejections,
172
+ // drain-timeout aborts, and coverage gaps as warnings.
173
+ const c = s.continuation;
174
+ if (c) {
175
+ console.log(`${colors.dim} continuation (${o.artifact.runtime.slotModel}) released ${c.releasedProducerSlots}` +
176
+ ` backlog max ${c.maxBacklog}` +
177
+ (c.backpressureMs ? ` backpressure p95 ${Math.round(c.backpressureMs.p95)}ms` : "") +
178
+ `${colors.reset}`);
179
+ if (c.rejectedReleaseSignals > 0) {
180
+ console.log(`${colors.yellow} ⚠ ${c.rejectedReleaseSignals} release(s) rejected (backlog full, drain bound, or run deadline)${colors.reset}`);
181
+ }
182
+ if (c.abortedByDrainTimeout > 0) {
183
+ console.log(`${colors.yellow} ⚠ ${c.abortedByDrainTimeout} continuation(s) aborted by the drain timeout` +
184
+ ` (still in flight at finalize)${colors.reset}`);
185
+ }
186
+ if (c.duplicateReleaseSignals > 0) {
187
+ console.log(`${colors.yellow} ⚠ ${c.duplicateReleaseSignals} duplicate release signal(s)` +
188
+ ` (one producer-release boundary per iteration)${colors.reset}`);
189
+ }
190
+ // Coverage gaps: only SOME iterations reached a primary boundary (a branch/error path
191
+ // skipped it), so the producer-release stats above reflect just that subset — warn,
192
+ // since `releaseCoverage` alone can read 100% while boundary coverage is partial.
193
+ if (c.primaryBoundaryCoverage < 1) {
194
+ console.log(`${colors.yellow} ⚠ only ${pct(c.primaryBoundaryCoverage)} of iterations reached a primary boundary` +
195
+ ` — producer-release stats cover that subset${colors.reset}`);
196
+ }
197
+ if (c.releaseCoverage < 1) {
198
+ console.log(`${colors.dim} release coverage ${pct(c.releaseCoverage)} of primary boundaries${colors.reset}`);
199
+ }
200
+ }
201
+ for (const t of s.thresholds) {
202
+ const mark = t.pass ? `${colors.green}✓${colors.reset}` : `${colors.red}✗${colors.reset}`;
203
+ const where = t.target ? `${t.scope}[${t.target}]` : t.scope;
204
+ console.log(`${colors.dim} ${mark} ${where}.${t.metric} ${t.expression} (actual ${t.actual})${colors.reset}`);
205
+ }
206
+ // Non-fatal run-shape advisories (M6-d), e.g. a long tail poll that held the producer
207
+ // slot with no release.
208
+ for (const a of s.advisories ?? []) {
209
+ console.log(`${colors.yellow} ⓘ ${a}${colors.reset}`);
210
+ }
211
+ }
212
+ /**
213
+ * `glubean load [target]` — discover + run load plans under `target` (a file,
214
+ * directory, or glob; defaults to the cwd), write results, and exit non-zero if
215
+ * any plan fails.
216
+ */
217
+ export async function loadCommand(target, options = {}) {
218
+ console.log(`\n${colors.bold}${colors.blue}⚡ Glubean Load${colors.reset}\n`);
219
+ const files = await resolveLoadFiles(target ?? process.cwd());
220
+ if (files.length === 0) {
221
+ console.log(`${colors.yellow}No .load.ts files found${target ? ` for "${target}"` : ` in ${process.cwd()}`}.${colors.reset}`);
222
+ process.exit(1);
223
+ }
224
+ // Derive the project root from the discovered file (not the shell cwd) so a
225
+ // targeted run outside cwd uses the load file's project for runner resolution /
226
+ // env / `.glubean` output.
227
+ const { rootDir } = await findProjectConfig(dirname(files[0]));
228
+ // An EXPLICIT --env-file that's missing is an error (mirrors `glubean run`) —
229
+ // silently running with empty env could send load to the wrong target / run
230
+ // without credentials. Validate the env file up front so a missing one fails
231
+ // fast. A resolved default/active env file may be absent.
232
+ const userSpecifiedEnvFile = options.envFile !== undefined;
233
+ const envFileName = userSpecifiedEnvFile ? options.envFile : await resolveEnvFileName(rootDir);
234
+ if (userSpecifiedEnvFile && !existsSync(resolve(rootDir, envFileName))) {
235
+ console.log(`${colors.red}Error: env file '${envFileName}' not found in ${rootDir}${colors.reset}`);
236
+ process.exit(1);
237
+ }
238
+ // Plugin bootstrap happens INSIDE each subprocess (the harness registers
239
+ // matchers / protocol adapters before importing the load file), so the CLI no
240
+ // longer bootstraps here.
241
+ const { vars, secrets } = await loadProjectEnv(rootDir, envFileName);
242
+ // A single file's import failure (or crash) is collected (not thrown) so
243
+ // earlier/later files still produce + persist results. Pass the raw resolved
244
+ // env — the child re-applies the process.env fallback (a Proxy can't cross the
245
+ // process boundary), so shell/CI-supplied vars/secrets still resolve.
246
+ const { outcomes, errors } = await runLoadFiles(files, { vars, secrets, cwd: rootDir });
247
+ // Persist every completed artifact FIRST — a later broken file must not discard
248
+ // an expensive successful plan's result.
249
+ const written = await writeLoadResults(outcomes, resolve(rootDir, ".glubean"));
250
+ console.log();
251
+ let anyFail = false;
252
+ for (const o of outcomes) {
253
+ printOutcome(o);
254
+ if (!o.artifact.summary.pass)
255
+ anyFail = true;
256
+ }
257
+ for (const e of errors) {
258
+ console.log(`${colors.red}✗ ${e.message}${colors.reset}`);
259
+ }
260
+ if (written.length > 0) {
261
+ console.log(`\n${colors.dim}Wrote ${written.length} result file(s) to .glubean/${colors.reset}`);
262
+ }
263
+ if (outcomes.length === 0 && errors.length === 0) {
264
+ console.log(`${colors.yellow}No loadRunner() exports found in ${files.length} file(s).${colors.reset}`);
265
+ }
266
+ // Fail if any plan failed, any file errored, or nothing ran at all.
267
+ if (anyFail || errors.length > 0 || outcomes.length === 0)
268
+ process.exit(1);
269
+ }
270
+ //# sourceMappingURL=load.js.map
@@ -0,0 +1 @@
1
+ {"version":3,"file":"load.js","sourceRoot":"","sources":["../../src/commands/load.ts"],"names":[],"mappings":"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"}
@@ -1,3 +1,4 @@
1
+ import type { GlubeanFileKind } from "@glubean/scanner";
1
2
  interface RunOptions {
2
3
  filter?: string;
3
4
  pick?: string;
@@ -108,6 +109,10 @@ interface RunOptions {
108
109
  */
109
110
  thresholds?: import("@glubean/sdk").ThresholdConfig;
110
111
  }
112
+ export declare function findProjectConfig(startDir: string): Promise<{
113
+ rootDir: string;
114
+ configPath?: string;
115
+ }>;
111
116
  /**
112
117
  * Map a file path to its Glubean kind by extension.
113
118
  * - `.test.ts` → "test"
@@ -120,7 +125,7 @@ interface RunOptions {
120
125
  * Returns undefined for non-Glubean files. The suite.kinds filter in
121
126
  * resolveTestFiles uses this to keep only files whose kind matches.
122
127
  */
123
- export type GlubeanFileKind = "test" | "contract" | "flow" | "bootstrap";
128
+ export type { GlubeanFileKind };
124
129
  export declare function classifyGlubeanFile(filePath: string): GlubeanFileKind | undefined;
125
130
  /**
126
131
  * Per-suite resolution helper exposed for main.ts. Resolves a suite's
@@ -174,6 +179,7 @@ export declare function discoverTests(filePath: string): Promise<DiscoveredTest[
174
179
  export declare const __testing: {
175
180
  matchesTags: (testItem: DiscoveredTest, tags: string[], mode?: "or" | "and" | undefined) => boolean;
176
181
  matchesExcludeTags: (testItem: DiscoveredTest, excludeTags: string[]) => boolean;
182
+ isGlubeanTestFile: (name: string) => boolean;
177
183
  };
178
184
  declare function matchesTags(testItem: DiscoveredTest, tags: string[], mode?: "or" | "and"): boolean;
179
185
  /**
@@ -183,5 +189,4 @@ declare function matchesTags(testItem: DiscoveredTest, tags: string[], mode?: "o
183
189
  */
184
190
  declare function matchesExcludeTags(testItem: DiscoveredTest, excludeTags: string[]): boolean;
185
191
  export declare function runCommand(target: string | string[], options?: RunOptions): Promise<void>;
186
- export {};
187
192
  //# sourceMappingURL=run.d.ts.map
@@ -1 +1 @@
1
- {"version":3,"file":"run.d.ts","sourceRoot":"","sources":["../../src/commands/run.ts"],"names":[],"mappings":"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"}
1
+ {"version":3,"file":"run.d.ts","sourceRoot":"","sources":["../../src/commands/run.ts"],"names":[],"mappings":"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"}
@@ -9,7 +9,7 @@ import { shouldSkipTest } from "../lib/skip.js";
9
9
  import { CLI_VERSION } from "../version.js";
10
10
  import { redactMetadataForUpload } from "../lib/redact-metadata.js";
11
11
  import { extractContractCases, extractFromSource } from "@glubean/scanner/static";
12
- import { extractContractFromFile, findTemplateMatch, loadProjectOverlays, matchesTemplateFilter, } from "@glubean/scanner";
12
+ import { buildSuffixes, classifyByStem, extractContractFromFile, findTemplateMatch, GLUBEAN_KINDS, loadProjectOverlays, matchesTemplateFilter, } from "@glubean/scanner";
13
13
  import { applyEnvTemplating } from "@glubean/runner";
14
14
  // ANSI color codes for pretty output
15
15
  const colors = {
@@ -28,7 +28,7 @@ const CLOUD_MEMORY_LIMITS = {
28
28
  pro: 700,
29
29
  };
30
30
  const MEMORY_WARNING_THRESHOLD_MB = CLOUD_MEMORY_LIMITS.free * 0.67;
31
- async function findProjectConfig(startDir) {
31
+ export async function findProjectConfig(startDir) {
32
32
  let dir = startDir;
33
33
  while (dir !== "/") {
34
34
  try {
@@ -77,13 +77,12 @@ function isGlob(target) {
77
77
  // calls execute and register overlays before discovery runs (attachment-
78
78
  // model §7.4). `discoverTests()` is responsible for distinguishing
79
79
  // bootstrap-only files from runnable-emitting ones.
80
- const TEST_FILE_SUFFIXES = [
81
- ".test.ts",
82
- ".contract.ts",
83
- ".workflow.ts",
84
- ".flow.ts",
85
- ".bootstrap.ts",
86
- ];
80
+ // CLI target resolution for `glubean run` recognizes only `.ts` files across the
81
+ // test-runner kinds (including bootstrap), derived from the canonical kind
82
+ // registry (scanner/kinds.ts). `load` is EXCLUDED here: load plans run through
83
+ // the dedicated `glubean load` command + the closed-model orchestrator, not the
84
+ // per-test ProjectRunner, so `glubean run ./dir` must not sweep in `.load.ts`.
85
+ const TEST_FILE_SUFFIXES = GLUBEAN_KINDS.filter((k) => k.kind !== "load").flatMap((k) => buildSuffixes(k.stems, [".ts"]));
87
86
  function isGlubeanTestFile(name) {
88
87
  return TEST_FILE_SUFFIXES.some((suffix) => name.endsWith(suffix));
89
88
  }
@@ -93,17 +92,9 @@ function isGlubeanTestFile(name) {
93
92
  // the static test path — a `.workflow.` substring would mis-route it into
94
93
  // contract extraction (which ignores `test()` exports), silently dropping its
95
94
  // tests (codex 0.6 P2).
96
- const RUNTIME_ARTIFACT_SUFFIXES = [
97
- ".contract.ts",
98
- ".contract.js",
99
- ".contract.mjs",
100
- ".workflow.ts",
101
- ".workflow.js",
102
- ".workflow.mjs",
103
- ".flow.ts",
104
- ".flow.js",
105
- ".flow.mjs",
106
- ];
95
+ // Contract/workflow/flow artifact files (NOT bootstrap), all extensions —
96
+ // derived from the canonical kind registry (scanner/kinds.ts).
97
+ const RUNTIME_ARTIFACT_SUFFIXES = GLUBEAN_KINDS.filter((k) => k.runtimeArtifact && k.kind !== "bootstrap").flatMap((k) => buildSuffixes(k.stems));
107
98
  function isRuntimeExtractableArtifact(name) {
108
99
  return RUNTIME_ARTIFACT_SUFFIXES.some((suffix) => name.endsWith(suffix));
109
100
  }
@@ -125,15 +116,8 @@ async function walkTestFiles(dir, result) {
125
116
  }
126
117
  }
127
118
  export function classifyGlubeanFile(filePath) {
128
- if (filePath.endsWith(".test.ts"))
129
- return "test";
130
- if (filePath.endsWith(".contract.ts"))
131
- return "contract";
132
- if (filePath.endsWith(".workflow.ts") || filePath.endsWith(".flow.ts"))
133
- return "flow";
134
- if (filePath.endsWith(".bootstrap.ts"))
135
- return "bootstrap";
136
- return undefined;
119
+ // `.ts`-only classification, by stem, from the canonical kind registry.
120
+ return classifyByStem(filePath, [".ts"]);
137
121
  }
138
122
  async function resolveSingleTarget(target) {
139
123
  const abs = resolve(target);
@@ -450,6 +434,7 @@ function matchesFilter(testItem, filter) {
450
434
  export const __testing = {
451
435
  matchesTags: (...args) => matchesTags(...args),
452
436
  matchesExcludeTags: (...args) => matchesExcludeTags(...args),
437
+ isGlubeanTestFile: (name) => isGlubeanTestFile(name),
453
438
  };
454
439
  function matchesTags(testItem, tags, mode = "or") {
455
440
  if (!testItem.meta.tags?.length)