@glubean/runner 0.5.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.
Files changed (83) hide show
  1. package/dist/engine-bridge.d.ts +55 -0
  2. package/dist/engine-bridge.d.ts.map +1 -0
  3. package/dist/engine-bridge.js +219 -0
  4. package/dist/engine-bridge.js.map +1 -0
  5. package/dist/executor.d.ts +70 -2
  6. package/dist/executor.d.ts.map +1 -1
  7. package/dist/executor.js +21 -226
  8. package/dist/executor.js.map +1 -1
  9. package/dist/generate_summary.d.ts +15 -0
  10. package/dist/generate_summary.d.ts.map +1 -1
  11. package/dist/generate_summary.js +52 -1
  12. package/dist/generate_summary.js.map +1 -1
  13. package/dist/harness.js +257 -21
  14. package/dist/harness.js.map +1 -1
  15. package/dist/index.d.ts +24 -0
  16. package/dist/index.d.ts.map +1 -1
  17. package/dist/index.js +24 -0
  18. package/dist/index.js.map +1 -1
  19. package/dist/load/continuation-pool.d.ts +82 -0
  20. package/dist/load/continuation-pool.d.ts.map +1 -0
  21. package/dist/load/continuation-pool.js +154 -0
  22. package/dist/load/continuation-pool.js.map +1 -0
  23. package/dist/load/execute-iteration.d.ts +126 -0
  24. package/dist/load/execute-iteration.d.ts.map +1 -0
  25. package/dist/load/execute-iteration.js +367 -0
  26. package/dist/load/execute-iteration.js.map +1 -0
  27. package/dist/load/histogram.d.ts +63 -0
  28. package/dist/load/histogram.d.ts.map +1 -0
  29. package/dist/load/histogram.js +149 -0
  30. package/dist/load/histogram.js.map +1 -0
  31. package/dist/load/orchestrator.d.ts +55 -0
  32. package/dist/load/orchestrator.d.ts.map +1 -0
  33. package/dist/load/orchestrator.js +571 -0
  34. package/dist/load/orchestrator.js.map +1 -0
  35. package/dist/load/reducer.d.ts +109 -0
  36. package/dist/load/reducer.d.ts.map +1 -0
  37. package/dist/load/reducer.js +718 -0
  38. package/dist/load/reducer.js.map +1 -0
  39. package/dist/load/route-key.d.ts +38 -0
  40. package/dist/load/route-key.d.ts.map +1 -0
  41. package/dist/load/route-key.js +107 -0
  42. package/dist/load/route-key.js.map +1 -0
  43. package/dist/load/samples.d.ts +83 -0
  44. package/dist/load/samples.d.ts.map +1 -0
  45. package/dist/load/samples.js +269 -0
  46. package/dist/load/samples.js.map +1 -0
  47. package/dist/load/sink.d.ts +127 -0
  48. package/dist/load/sink.d.ts.map +1 -0
  49. package/dist/load/sink.js +351 -0
  50. package/dist/load/sink.js.map +1 -0
  51. package/dist/load/subprocess.d.ts +83 -0
  52. package/dist/load/subprocess.d.ts.map +1 -0
  53. package/dist/load/subprocess.js +229 -0
  54. package/dist/load/subprocess.js.map +1 -0
  55. package/dist/load/threshold.d.ts +44 -0
  56. package/dist/load/threshold.d.ts.map +1 -0
  57. package/dist/load/threshold.js +197 -0
  58. package/dist/load/threshold.js.map +1 -0
  59. package/dist/load/timeline.d.ts +36 -0
  60. package/dist/load/timeline.d.ts.map +1 -0
  61. package/dist/load/timeline.js +158 -0
  62. package/dist/load/timeline.js.map +1 -0
  63. package/dist/load-harness.d.ts +2 -0
  64. package/dist/load-harness.d.ts.map +1 -0
  65. package/dist/load-harness.js +105 -0
  66. package/dist/load-harness.js.map +1 -0
  67. package/dist/resolve.d.ts +10 -11
  68. package/dist/resolve.d.ts.map +1 -1
  69. package/dist/resolve.js +28 -9
  70. package/dist/resolve.js.map +1 -1
  71. package/dist/runner-resolve.d.ts +53 -0
  72. package/dist/runner-resolve.d.ts.map +1 -0
  73. package/dist/runner-resolve.js +264 -0
  74. package/dist/runner-resolve.js.map +1 -0
  75. package/dist/workflow/event-timeline.d.ts +3 -0
  76. package/dist/workflow/event-timeline.d.ts.map +1 -0
  77. package/dist/workflow/event-timeline.js +72 -0
  78. package/dist/workflow/event-timeline.js.map +1 -0
  79. package/dist/workflow/execute.d.ts +267 -0
  80. package/dist/workflow/execute.d.ts.map +1 -0
  81. package/dist/workflow/execute.js +1475 -0
  82. package/dist/workflow/execute.js.map +1 -0
  83. package/package.json +8 -4
@@ -0,0 +1,264 @@
1
+ /**
2
+ * Shared runner-resolution internals — the delicate "where does the runner
3
+ * harness live + how do we spawn it" code, factored out of `executor.ts` so the
4
+ * test harness (`TestExecutor`) AND the load harness (`runLoadFileInSubprocess`)
5
+ * resolve the SAME project-local runner the SAME way.
6
+ *
7
+ * Three reused seams:
8
+ * - `resolveRunnerRoot` — the **dual-package hazard fix**: prefer the project's
9
+ * own `@glubean/runner` dist (so the spawned harness + the user file co-resolve
10
+ * the project's `@glubean/sdk`), fall back to the bundled copy with a warning.
11
+ * **Most delicate code in the package — change with care.**
12
+ * - `resolveTsxPath` — locate the tsx CLI to transform the user's TypeScript.
13
+ * - `prepareZeroProject` — scratch-mode (no node_modules) `--import` register +
14
+ * `GLUBEAN_VENDORED_ROOT` redirect + temp package.json, with a cleanup closure.
15
+ *
16
+ * Internal to `@glubean/runner` — not part of the public `index.ts` surface.
17
+ */
18
+ import { existsSync, unlinkSync, readFileSync, writeFileSync, realpathSync } from "node:fs";
19
+ import { dirname, resolve, join } from "node:path";
20
+ import { createRequire } from "node:module";
21
+ // ── Project-local runner resolution (Plan 1) ────────────────────────────────
22
+ /**
23
+ * Walk up from a starting file path looking for the first package.json
24
+ * whose `name` field matches `expectedName`. Layout-independent — works
25
+ * regardless of dist/ depth.
26
+ *
27
+ * Returns the realpath of the package root, or undefined if not found.
28
+ */
29
+ function findPackageRoot(startFile, expectedName) {
30
+ let dir = dirname(startFile);
31
+ for (let i = 0; i < 16; i++) {
32
+ const candidate = resolve(dir, "package.json");
33
+ if (existsSync(candidate)) {
34
+ try {
35
+ const pkg = JSON.parse(readFileSync(candidate, "utf-8"));
36
+ if (pkg?.name === expectedName) {
37
+ try {
38
+ return realpathSync(dir);
39
+ }
40
+ catch {
41
+ return dir;
42
+ }
43
+ }
44
+ }
45
+ catch {
46
+ // corrupt / non-json; keep walking
47
+ }
48
+ }
49
+ const parent = dirname(dir);
50
+ if (parent === dir)
51
+ return undefined;
52
+ dir = parent;
53
+ }
54
+ return undefined;
55
+ }
56
+ /**
57
+ * Compare two version strings (numeric major.minor.patch). Returns true
58
+ * if `a < b`. Tolerant of missing fields and non-numeric tails.
59
+ */
60
+ function semverLt(a, b) {
61
+ const parse = (s) => s.split(/[.\-+]/).slice(0, 3).map((p) => parseInt(p, 10) || 0);
62
+ const [aMajor, aMinor, aPatch] = parse(a);
63
+ const [bMajor, bMinor, bPatch] = parse(b);
64
+ if (aMajor !== bMajor)
65
+ return aMajor < bMajor;
66
+ if (aMinor !== bMinor)
67
+ return aMinor < bMinor;
68
+ return aPatch < bPatch;
69
+ }
70
+ /**
71
+ * Resolve the runner dist/ directory + package root.
72
+ *
73
+ * Preference: project-local `@glubean/runner` (found from `projectCwd`'s
74
+ * `node_modules` chain). Fallback: bundled (the consumer's own runner copy).
75
+ *
76
+ * Returns warnings to be yielded as `{ type: "warning", ... }` events at
77
+ * the start of every `run()` call. Always emits a warning when falling
78
+ * back to bundled (so users see why "configure() values..." errors may
79
+ * appear in a misconfigured project).
80
+ */
81
+ export function resolveRunnerRoot(projectCwd, bundledDistDir, bundledPkgRoot) {
82
+ const warnings = [];
83
+ try {
84
+ // Root `createRequire` at a stub path INSIDE the project cwd — not
85
+ // at `import.meta.url` (the workspace executor file). If we use the
86
+ // workspace URL, Node's resolver returns the workspace's own
87
+ // `@glubean/runner` via package self-reference (the `exports` field
88
+ // points back at itself), regardless of `paths: [projectCwd]`. With
89
+ // a cwd-rooted stub there's no self-reference and Node walks the
90
+ // project's node_modules chain correctly.
91
+ const req = createRequire(resolve(projectCwd, "__glubean_resolve_stub__.js"));
92
+ const mainEntry = req.resolve("@glubean/runner");
93
+ const pkgRoot = findPackageRoot(mainEntry, "@glubean/runner");
94
+ if (!pkgRoot) {
95
+ warnings.push({
96
+ code: "runner_pkg_root_not_found",
97
+ message: `Could not locate @glubean/runner's package.json above ${mainEntry}; using bundled runner.`,
98
+ });
99
+ return {
100
+ distDir: bundledDistDir,
101
+ pkgRoot: bundledPkgRoot,
102
+ source: "bundled",
103
+ pendingWarnings: warnings,
104
+ };
105
+ }
106
+ const projectDistDir = dirname(mainEntry);
107
+ if (!existsSync(resolve(projectDistDir, "harness.js"))) {
108
+ warnings.push({
109
+ code: "runner_fallback_no_dist",
110
+ message: `Project @glubean/runner at ${pkgRoot} has no built harness.js (looked in ${projectDistDir}); using bundled runner.`,
111
+ });
112
+ return {
113
+ distDir: bundledDistDir,
114
+ pkgRoot: bundledPkgRoot,
115
+ source: "bundled",
116
+ pendingWarnings: warnings,
117
+ };
118
+ }
119
+ let version;
120
+ let projectProtocol;
121
+ try {
122
+ const pkg = JSON.parse(readFileSync(resolve(pkgRoot, "package.json"), "utf-8"));
123
+ version = pkg.version;
124
+ projectProtocol = pkg.glubeanRunnerProtocol;
125
+ }
126
+ catch {
127
+ // best effort
128
+ }
129
+ // Min-protocol check: emit a warning if project's protocol is older
130
+ // than what this consumer needs, but DON'T fall back. Using project-
131
+ // local runner with an old protocol just means some new env channels
132
+ // may be silently ignored. Falling back to bundled when the project
133
+ // has its own SDK would re-introduce the dual-package hazard the
134
+ // whole fix exists to prevent. Project-local wins; missing features
135
+ // are surfaced via warning so the user knows to upgrade.
136
+ try {
137
+ const bundledPkg = JSON.parse(readFileSync(resolve(bundledPkgRoot, "package.json"), "utf-8"));
138
+ const bundledMin = bundledPkg.glubeanRunnerProtocolMinimum;
139
+ if (bundledMin && (!projectProtocol || semverLt(projectProtocol, bundledMin))) {
140
+ warnings.push({
141
+ code: "runner_protocol_old",
142
+ message: `Project @glubean/runner ${version ?? "<unknown>"} declares glubeanRunnerProtocol=${projectProtocol ?? "<unset>"}, ` +
143
+ `but this consumer was built for >= ${bundledMin}. ` +
144
+ `Using project-local runner anyway; some newer features may be silently unavailable. ` +
145
+ `Run \`npm i -D @glubean/runner@latest\` to silence.`,
146
+ });
147
+ }
148
+ }
149
+ catch {
150
+ // bundled pkg.json unreadable — skip the check; happens in test fixtures
151
+ }
152
+ return {
153
+ distDir: projectDistDir,
154
+ pkgRoot,
155
+ source: "project",
156
+ resolvedFrom: mainEntry,
157
+ version,
158
+ pendingWarnings: warnings,
159
+ };
160
+ }
161
+ catch {
162
+ // No project-local runner installed. Plan 1 AC4: emit a warning whenever
163
+ // bundled is used so users see why version-skew "configure() values..."
164
+ // errors may appear.
165
+ warnings.push({
166
+ code: "runner_fallback_no_project",
167
+ message: `No project-local @glubean/runner found at ${projectCwd}; using consumer's bundled runner. ` +
168
+ `If your tests import @glubean/sdk from this project, install runner to keep module identity ` +
169
+ `consistent: \`npm i -D @glubean/runner\`.`,
170
+ });
171
+ return {
172
+ distDir: bundledDistDir,
173
+ pkgRoot: bundledPkgRoot,
174
+ source: "bundled",
175
+ pendingWarnings: warnings,
176
+ };
177
+ }
178
+ }
179
+ // ── End of project-local resolution ─────────────────────────────────────────
180
+ // ── tsx path resolution ─────────────────────────────────────────────────────
181
+ let _tsxPath;
182
+ /** Resolve the tsx CLI entry used to transform the user's TypeScript in the
183
+ * spawned harness subprocess. Cached after the first lookup. */
184
+ export function resolveTsxPath() {
185
+ if (_tsxPath)
186
+ return _tsxPath;
187
+ const req = createRequire(import.meta.url);
188
+ _tsxPath = resolve(dirname(req.resolve("tsx/package.json")), "dist/cli.mjs");
189
+ return _tsxPath;
190
+ }
191
+ /**
192
+ * Set up zero-project (scratch) mode for a spawn rooted at `cwd`: when the cwd
193
+ * has no `@glubean/sdk` in node_modules, redirect the user file's `@glubean/*`
194
+ * imports to the resolved runner's vendored copy (via the register hook +
195
+ * `GLUBEAN_VENDORED_ROOT`) and ensure a `"type":"module"` package.json so the
196
+ * `.ts` file loads as ESM. When the cwd already has `@glubean/sdk`, this is a
197
+ * no-op (empty args/env, no-op cleanup).
198
+ *
199
+ * Pure w.r.t. instance state — both `TestExecutor` and the load spawn call it
200
+ * and own the returned `tsxArgs`/`env`/`cleanup`.
201
+ */
202
+ export function prepareZeroProject(cwd, runnerDistDir, runnerPkgRoot) {
203
+ if (existsSync(join(cwd, "node_modules", "@glubean", "sdk"))) {
204
+ return { tsxArgs: [], env: {}, cleanup: () => { } };
205
+ }
206
+ // Plan 1: relocate zero-project subpaths with the harness — if harness moved
207
+ // to project-local runner, register + vendored root must move too, otherwise
208
+ // scratch mode mixes project harness with bundled @glubean/* resolution.
209
+ const registerPath = resolve(runnerDistDir, "zero-project-register.mjs");
210
+ const tsxArgs = ["--import", registerPath];
211
+ // Use the runner package root as the synthetic parent. From there, Node's
212
+ // normal package resolution finds sibling @glubean/* packages in both
213
+ // workspace installs (packages/runner/node_modules) and published installs
214
+ // (ancestor node_modules).
215
+ const env = { GLUBEAN_VENDORED_ROOT: runnerPkgRoot };
216
+ const pkgPath = join(cwd, "package.json");
217
+ let tempPackageJson = false;
218
+ let originalPackageJson;
219
+ if (!existsSync(pkgPath)) {
220
+ try {
221
+ writeFileSync(pkgPath, '{"type":"module"}\n');
222
+ tempPackageJson = "created";
223
+ }
224
+ catch {
225
+ // Non-critical
226
+ }
227
+ }
228
+ else {
229
+ try {
230
+ const original = readFileSync(pkgPath, "utf-8");
231
+ const pkg = JSON.parse(original);
232
+ if (pkg.type !== "module") {
233
+ originalPackageJson = original;
234
+ pkg.type = "module";
235
+ writeFileSync(pkgPath, JSON.stringify(pkg, null, 2) + "\n");
236
+ tempPackageJson = "patched";
237
+ }
238
+ }
239
+ catch {
240
+ // Non-critical
241
+ }
242
+ }
243
+ return {
244
+ tsxArgs,
245
+ env,
246
+ cleanup() {
247
+ if (!tempPackageJson)
248
+ return;
249
+ try {
250
+ if (tempPackageJson === "created") {
251
+ unlinkSync(pkgPath);
252
+ }
253
+ else if (tempPackageJson === "patched" && originalPackageJson) {
254
+ writeFileSync(pkgPath, originalPackageJson);
255
+ }
256
+ }
257
+ catch {
258
+ // Non-critical
259
+ }
260
+ tempPackageJson = false;
261
+ },
262
+ };
263
+ }
264
+ //# sourceMappingURL=runner-resolve.js.map
@@ -0,0 +1 @@
1
+ {"version":3,"file":"runner-resolve.js","sourceRoot":"","sources":["../src/runner-resolve.ts"],"names":[],"mappings":"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"}
@@ -0,0 +1,3 @@
1
+ import type { GlubeanEvent } from "@glubean/sdk";
2
+ export declare function workflowEventToTimeline(ev: GlubeanEvent): Record<string, unknown> | null;
3
+ //# sourceMappingURL=event-timeline.d.ts.map
@@ -0,0 +1 @@
1
+ {"version":3,"file":"event-timeline.d.ts","sourceRoot":"","sources":["../../src/workflow/event-timeline.ts"],"names":[],"mappings":"AAaA,OAAO,KAAK,EAAE,YAAY,EAAE,MAAM,cAAc,CAAC;AAYjD,wBAAgB,uBAAuB,CAAC,EAAE,EAAE,YAAY,GAAG,MAAM,CAAC,MAAM,EAAE,OAAO,CAAC,GAAG,IAAI,CAqExF"}
@@ -0,0 +1,72 @@
1
+ import { NODE_START_EVENT, NODE_END_EVENT, POLL_ATTEMPT_EVENT, BRANCH_DECISION_EVENT, } from "./execute.js";
2
+ const NODE_STATUSES = new Set(["passed", "failed", "skipped"]);
3
+ const NODE_GRADES = new Set(["full", "partial", "trace", "opaque"]);
4
+ const POLL_OUTCOMES = new Set(["satisfied", "probe", "failed"]);
5
+ export function workflowEventToTimeline(ev) {
6
+ if (ev.type !== NODE_START_EVENT &&
7
+ ev.type !== NODE_END_EVENT &&
8
+ ev.type !== POLL_ATTEMPT_EVENT &&
9
+ ev.type !== BRANCH_DECISION_EVENT) {
10
+ return null;
11
+ }
12
+ const d = ev.data;
13
+ if (!d || typeof d.nodeId !== "string")
14
+ return null;
15
+ const attemptFields = {
16
+ ...(typeof d.attempt === "number" ? { attempt: d.attempt } : {}),
17
+ ...(typeof d.attempts === "number" ? { attempts: d.attempts } : {}),
18
+ };
19
+ if (ev.type === NODE_START_EVENT) {
20
+ return {
21
+ type: "node_start",
22
+ nodeId: d.nodeId,
23
+ kind: typeof d.kind === "string" ? d.kind : "unknown",
24
+ name: typeof d.name === "string" ? d.name : d.nodeId,
25
+ ...attemptFields,
26
+ };
27
+ }
28
+ if (ev.type === NODE_END_EVENT) {
29
+ if (typeof d.status !== "string" || !NODE_STATUSES.has(d.status))
30
+ return null;
31
+ if (typeof d.grade !== "string" || !NODE_GRADES.has(d.grade))
32
+ return null;
33
+ return {
34
+ type: "node_end",
35
+ nodeId: d.nodeId,
36
+ kind: typeof d.kind === "string" ? d.kind : "unknown",
37
+ name: typeof d.name === "string" ? d.name : d.nodeId,
38
+ status: d.status,
39
+ grade: d.grade,
40
+ durationMs: typeof d.durationMs === "number" ? d.durationMs : 0,
41
+ ...(typeof d.error === "string" ? { error: d.error } : {}),
42
+ ...attemptFields,
43
+ };
44
+ }
45
+ if (ev.type === POLL_ATTEMPT_EVENT) {
46
+ if (typeof d.attempt !== "number" ||
47
+ typeof d.outcome !== "string" ||
48
+ !POLL_OUTCOMES.has(d.outcome)) {
49
+ return null;
50
+ }
51
+ return {
52
+ type: "poll_attempt",
53
+ nodeId: d.nodeId,
54
+ attempt: d.attempt,
55
+ outcome: d.outcome,
56
+ durationMs: typeof d.durationMs === "number" ? d.durationMs : 0,
57
+ };
58
+ }
59
+ // BRANCH_DECISION_EVENT (addendum §9 — branch/switch/route taken case)
60
+ if ((d.mode !== "predicate" && d.mode !== "value") ||
61
+ (typeof d.takenIndex !== "number" && d.takenIndex !== "default")) {
62
+ return null;
63
+ }
64
+ return {
65
+ type: "branch_decision",
66
+ nodeId: d.nodeId,
67
+ mode: d.mode,
68
+ takenIndex: d.takenIndex,
69
+ ...(typeof d.takenLabel === "string" ? { takenLabel: d.takenLabel } : {}),
70
+ };
71
+ }
72
+ //# sourceMappingURL=event-timeline.js.map
@@ -0,0 +1 @@
1
+ {"version":3,"file":"event-timeline.js","sourceRoot":"","sources":["../../src/workflow/event-timeline.ts"],"names":[],"mappings":"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"}
@@ -0,0 +1,267 @@
1
+ /**
2
+ * @module workflow/execute
3
+ *
4
+ * vNext `workflow` EXECUTOR — the per-node runtime harness.
5
+ *
6
+ * GOVERNING PRINCIPLE (2026-06-09): no backward compatibility. Where `runFlow`
7
+ * (`contract-core.ts`) and the `test()` harness (`packages/runner`) diverge, this
8
+ * executor picks the ONE rule decided in the proposal §17 self-consistency corpus
9
+ * and every node obeys it. See `internal/40-discovery/proposals/contract-workflow-vnext.md`.
10
+ *
11
+ * This slice (S2.0) builds the foundation every later node type stands on:
12
+ * - a per-node derived child ctx (`makeNodeScope`) that attributes evidence to
13
+ * the node, tracks its pass/fail + structured-evidence emission, and — after
14
+ * the node settles — QUARANTINES any late evidence the body still emits (§17 #12);
15
+ * - `runNode`: brackets the node with `workflow:node_start` / `:node_end`
16
+ * events, runs the body under a per-node `AbortController`, and enforces a
17
+ * TERMINAL per-node timeout (no retry; §17 #4) that aborts the node (§17 #12).
18
+ *
19
+ * On top of it: `runWorkflow` walks setup → nodes → teardown (S2.1); `runBranch`
20
+ * runs only the taken side (S2.4a, §17 #6); `runPollNode` is the bounded
21
+ * poll-until with per-attempt quarantine (S2.4b, §17 #3). Control-flow nodes
22
+ * (branch/poll) own their bracket/bounds and are dispatched by `runNodeList`,
23
+ * not `runNode`; remaining reserved kinds throw "not implemented yet".
24
+ */
25
+ import type { TestContext, ProjectionGrade, StaticGrade, Workflow, WorkflowContext, WorkflowNode, ExtractedPredicate } from "@glubean/sdk";
26
+ /**
27
+ * Human-readable label for a declarative expect item (phase4 §7.2) — derived
28
+ * from the extracted predicate, never authored, so it cannot drift from what
29
+ * actually evaluates. Used for assertion-event messages.
30
+ */
31
+ export declare function predicateLabel(p: ExtractedPredicate): string;
32
+ /**
33
+ * Host integration point (used by @glubean/runner's http hooks): the ctx that
34
+ * observability emitted DURING a workflow node body should be attributed to,
35
+ * or undefined outside any workflow node.
36
+ */
37
+ export declare function __activeWorkflowNodeCtx(): TestContext | undefined;
38
+ /**
39
+ * Per-node boundary events ride the generic `ctx.event` channel for this slice
40
+ * (zero runner-package change — they reach the timeline as namespaced
41
+ * `GlubeanEvent`s). S2.5 decides whether to promote them to first-class
42
+ * `node_start` / `node_end` event kinds for richer Cloud rendering.
43
+ */
44
+ export declare const NODE_START_EVENT = "workflow:node_start";
45
+ export declare const NODE_END_EVENT = "workflow:node_end";
46
+ export type NodeStatus = "passed" | "failed" | "skipped";
47
+ export interface NodeStartEventData {
48
+ nodeId: string;
49
+ kind: WorkflowNode["kind"];
50
+ name: string;
51
+ /** Set on a retrying node (§17 #7): which attempt this bracket is (1-based). */
52
+ attempt?: number;
53
+ /** Set on a retrying node (§17 #7): the configured total attempts. */
54
+ attempts?: number;
55
+ [k: string]: unknown;
56
+ }
57
+ export interface NodeEndEventData {
58
+ nodeId: string;
59
+ kind: WorkflowNode["kind"];
60
+ name: string;
61
+ status: NodeStatus;
62
+ /** Runtime grade after evidence promotion (§17 #10). */
63
+ grade: ProjectionGrade;
64
+ durationMs: number;
65
+ error?: string;
66
+ /** Set on a retrying node (§17 #7): which attempt this bracket is (1-based). */
67
+ attempt?: number;
68
+ /** Set on a retrying node (§17 #7): the configured total attempts. */
69
+ attempts?: number;
70
+ [k: string]: unknown;
71
+ }
72
+ /** A node exceeded its `timeout`. TERMINAL — the node is not retried (§17 #4). */
73
+ export declare class NodeTimeoutError extends Error {
74
+ readonly nodeId: string;
75
+ readonly timeoutMs: number;
76
+ constructor(nodeId: string, timeoutMs: number);
77
+ }
78
+ /**
79
+ * A workflow phase (setup, or a node) FAILED via soft assertions/validation —
80
+ * nothing was thrown, so `runNode` has no `error` to report. The executor
81
+ * synthesizes this as the run's `cause` so teardown + the result carry a
82
+ * non-empty failure even for the pure soft-failure path (codex S2.1 P2).
83
+ */
84
+ export declare class WorkflowPhaseFailedError extends Error {
85
+ readonly workflowId: string;
86
+ readonly phase: string;
87
+ constructor(workflowId: string, phase: string);
88
+ }
89
+ /**
90
+ * A `compute` node returned a thenable — an async fn, or (the case the builder
91
+ * can't catch) a sync fn that returns a Promise. compute MUST be synchronous and
92
+ * I/O-free; the executor FAILS the node rather than committing the Promise as
93
+ * state, so async/I/O can't masquerade as a `full` pure transform (§17 #11).
94
+ */
95
+ export declare class ComputeAsyncError extends Error {
96
+ readonly nodeId: string;
97
+ constructor(nodeId: string);
98
+ }
99
+ /**
100
+ * A per-node child `TestContext` (+ `signal`). Sibling to `quarantinedCtx`
101
+ * (`contract-flow-poll.ts`): same "derive with `Object.create`, override the
102
+ * pass/fail APIs, pass observability through" technique, different policy —
103
+ * evidence emits IMMEDIATELY while the node is live, then is DROPPED once the
104
+ * node settles (`seal()`), so a body that ignores `signal` and keeps running
105
+ * after a timeout/failure cannot leak late evidence into the run (§17 #12).
106
+ *
107
+ * It also records, for the executor: whether any assertion/validate/fail FAILED
108
+ * (the node's pass/fail decision, §17 #5) and whether the node emitted ≥1 piece
109
+ * of STRUCTURED evidence — protocol `trace`, `assertion`, `schema_validation`,
110
+ * `metric` — which promotes a statically-`opaque` node to `trace` (§17 #10).
111
+ * Plain `log` / `warn` / `action` / `event` do NOT count as structured evidence.
112
+ */
113
+ export interface NodeScope {
114
+ readonly ctx: WorkflowContext;
115
+ /** True iff some assertion / error-severity validation / `fail()` recorded a failure (§17 #5). */
116
+ hasFailure(): boolean;
117
+ /** True iff the node emitted ≥1 structured evidence (drives opaque→trace, §17 #10). */
118
+ emittedStructuredEvidence(): boolean;
119
+ /** Settle the node: subsequent emissions are quarantined (dropped) (§17 #12). */
120
+ seal(): void;
121
+ }
122
+ export declare function makeNodeScope(base: TestContext, signal: AbortSignal): NodeScope;
123
+ /**
124
+ * Runtime grade = the static floor, promoted from `opaque` → `trace` iff the node
125
+ * emitted structured evidence at run time (§17 #10). `full` / `partial` are never
126
+ * promoted (they are already as good as or better than `trace`).
127
+ */
128
+ export declare function promoteGrade(staticGrade: StaticGrade, scope: NodeScope): ProjectionGrade;
129
+ export interface NodeRunResult {
130
+ status: NodeStatus;
131
+ /** Committed state. On failure this is the PRIOR state — a failed node does not
132
+ * commit its return (§17 #13). On success: the body's return, or the prior state
133
+ * when the body returned void/undefined (§17 #2).
134
+ *
135
+ * §17 #14: state is treated as IMMUTABLE, but the executor does NOT clone it
136
+ * (perf). A body that mutates the LIVE state object in place takes effect
137
+ * IMMEDIATELY and is NOT isolated or rolled back on failure/timeout — commit-on-
138
+ * success governs the RETURN VALUE, not in-place writes. A node needing rollback
139
+ * safety MUST return a new object instead of mutating in place. */
140
+ state: unknown;
141
+ /** Runtime grade after evidence promotion (§17 #10). */
142
+ grade: ProjectionGrade;
143
+ /** The error that failed the node (throw / timeout / fatal), if any. */
144
+ error?: unknown;
145
+ }
146
+ /** Attempt label for a retrying node's events (§17 #7): `n` of `of`. */
147
+ export interface AttemptInfo {
148
+ n: number;
149
+ of: number;
150
+ }
151
+ export interface RunNodeOptions {
152
+ /** Static floor grade for this node (from the projector); promoted per §17 #10. */
153
+ staticGrade: StaticGrade;
154
+ /** Per-node terminal timeout (ms). Omit / non-finite = unbounded (§17 #4). */
155
+ timeoutMs?: number;
156
+ /** Stamp this run's node_start/node_end events as attempt n of of (§17 #7). */
157
+ attempt?: AttemptInfo;
158
+ /**
159
+ * Called with the settled verdict JUST BEFORE this run's node_end event is
160
+ * emitted — the retry wrapper uses it to flush the terminal attempt's buffered
161
+ * assert/validate evidence INSIDE the attempt bracket, so timeline grouping
162
+ * holds (codex S2.4c R2 P2). Runs after the scope is sealed; anything it emits
163
+ * goes straight to the base ctx.
164
+ */
165
+ beforeNodeEnd?: (status: NodeStatus, error?: unknown) => void;
166
+ /**
167
+ * Adjust the runtime grade before it is reported — applied to BOTH the
168
+ * node_end event and the returned result, so they always agree. The retry
169
+ * wrapper uses it to tie opaque→trace promotion to HOST-VISIBLE evidence
170
+ * across attempts: the scope's structured flag cannot distinguish
171
+ * pass-through traces from buffered (possibly-discarded) assert counts, and
172
+ * an earlier attempt's promotion must survive into the terminal bracket
173
+ * (§17 #10; codex S2.5 R5 P2).
174
+ */
175
+ adjustGrade?: (computed: ProjectionGrade, info: {
176
+ structured: boolean;
177
+ status: NodeStatus;
178
+ error?: unknown;
179
+ }) => ProjectionGrade;
180
+ }
181
+ /**
182
+ * Run ONE node: bracket it with node_start/node_end, execute its body under a
183
+ * per-node child ctx + `AbortController`, enforce a TERMINAL timeout (§17 #4),
184
+ * and quarantine any late evidence after the node settles (§17 #12). Returns the
185
+ * verdict + the state to carry forward (commit-on-success, §17 #13).
186
+ */
187
+ export declare function runNode(base: TestContext, node: WorkflowNode, state: unknown, opts: RunNodeOptions): Promise<NodeRunResult>;
188
+ export interface WorkflowNodeOutcome {
189
+ id: string;
190
+ status: NodeStatus;
191
+ /** Runtime grade after evidence promotion (§17 #10). */
192
+ grade: ProjectionGrade;
193
+ }
194
+ export interface WorkflowRunResult {
195
+ /** `skipped` if the workflow opts out (meta.skip) or a node called `ctx.skip()`;
196
+ * `failed` if setup threw / soft-failed or a node failed; else `passed`. */
197
+ status: "passed" | "failed" | "skipped";
198
+ /** Last COMMITTED state — passed nodes commit, failed/skipped do not (§17 #13). */
199
+ state: unknown;
200
+ /** Per-node outcomes, authored order. */
201
+ nodes: WorkflowNodeOutcome[];
202
+ /** The primary cause that failed the run (the one teardown sees), if any. */
203
+ error?: unknown;
204
+ /** Why the run skipped: the user-authored ctx.skip(reason) (setup/node/
205
+ * branch-predicate/poll), or `meta.skip`. Only set when status === "skipped"
206
+ * (codex S2.5 R6 — the host's skipped status must keep the authored reason). */
207
+ skipReason?: string;
208
+ }
209
+ /** Branch-family decision event (§17 #9 "branch decision") — rides the generic
210
+ * ctx.event channel like node_start/node_end; the runner unwraps it into a
211
+ * first-class `branch_decision` timeline event. */
212
+ export declare const BRANCH_DECISION_EVENT = "workflow:branch_decision";
213
+ export interface BranchDecisionEventData {
214
+ nodeId: string;
215
+ mode: "predicate" | "value";
216
+ takenIndex: number | "default";
217
+ takenLabel?: string;
218
+ [k: string]: unknown;
219
+ }
220
+ /** Per-attempt timeline event (§17 #9 "poll attempt timeline"). Rides the generic
221
+ * `ctx.event` channel like node_start/node_end; emitted through the NODE scope, so
222
+ * it is observability (never promotes the grade) and is quarantined after seal. */
223
+ export declare const POLL_ATTEMPT_EVENT = "workflow:poll_attempt";
224
+ export interface PollAttemptEventData {
225
+ nodeId: string;
226
+ attempt: number;
227
+ /** `satisfied` — until held; `probe` — until not yet; `failed` — the attempt
228
+ * threw / exceeded its budget (the poll node fails). */
229
+ outcome: "satisfied" | "probe" | "failed";
230
+ durationMs: number;
231
+ /**
232
+ * Inbound polls only (design §9.4): the matcher's classification for this
233
+ * attempt — `matched`, the probe attributions (`no-delivery` /
234
+ * `type-mismatch` / `correlation-mismatch` / `schema-mismatch`), or the
235
+ * fail class that ended the poll. Diagnosis, never verdict.
236
+ */
237
+ classification?: string;
238
+ /**
239
+ * Inbound polls, satisfied attempts only: `receivedAt − pollStart` of the
240
+ * matched delivery (ms) — the measured side of `expect.within` (§9.4a #5).
241
+ * NEGATIVE when the delivery arrived before the poll started (allowed
242
+ * evidence, §9.4a #3).
243
+ */
244
+ withinDeltaMs?: number;
245
+ [k: string]: unknown;
246
+ }
247
+ /**
248
+ * A fail-class inbound classification (inbound-contract-design §9.4 rows 1–3):
249
+ * a property of the delivery CHANNEL (forgery / replay / non-JSON), never
250
+ * noise — it fails the poll node even when a later delivery in the same
251
+ * snapshot would have matched (§9.4a #4, first terminal wins).
252
+ */
253
+ export declare class InboundDeliveryFailError extends Error {
254
+ readonly classification: "signature-invalid" | "stale" | "unparseable";
255
+ constructor(classification: "signature-invalid" | "stale" | "unparseable", nodeId: string, detail?: string);
256
+ }
257
+ /**
258
+ * Execute a built `Workflow` against a host `TestContext`. setup runs INSIDE the
259
+ * protected region so teardown ALWAYS runs — even when setup throws (§17 #1, the
260
+ * opposite of runFlow). Nodes run in authored order with fail-stop: a non-passed
261
+ * node stops the rest (emitted `skipped`). A node `ctx.skip()` skips the whole
262
+ * workflow (mirrors the runner's whole-test skip); `meta.skip` opts the workflow
263
+ * out entirely (discoverable, never executed). teardown sees the last committed
264
+ * state + the failing cause; a teardown that throws is logged and never masks it.
265
+ */
266
+ export declare function runWorkflow<State = unknown>(wf: Workflow<State>, baseCtx: TestContext): Promise<WorkflowRunResult>;
267
+ //# sourceMappingURL=execute.d.ts.map
@@ -0,0 +1 @@
1
+ {"version":3,"file":"execute.d.ts","sourceRoot":"","sources":["../../src/workflow/execute.ts"],"names":[],"mappings":"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"}