@particle-academy/fancy-flow 0.27.1 → 0.29.0
This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
- package/README.md +102 -15
- package/dist/{capabilities-85Mjn4uW.d.ts → capabilities-BH7zmSQQ.d.ts} +1 -1
- package/dist/{capabilities-exVeADXz.d.cts → capabilities-BLOeLACV.d.cts} +1 -1
- package/dist/{chunk-HHFOHHAQ.js → chunk-EBE3FEAJ.js} +2 -2
- package/dist/{chunk-HHFOHHAQ.js.map → chunk-EBE3FEAJ.js.map} +1 -1
- package/dist/chunk-FKOXQP76.js +50 -0
- package/dist/chunk-FKOXQP76.js.map +1 -0
- package/dist/engine.cjs +46 -0
- package/dist/engine.cjs.map +1 -1
- package/dist/engine.d.cts +1 -1
- package/dist/engine.d.ts +1 -1
- package/dist/engine.js +1 -0
- package/dist/engine.js.map +1 -1
- package/dist/index.cjs +46 -0
- package/dist/index.cjs.map +1 -1
- package/dist/index.d.cts +2 -2
- package/dist/index.d.ts +2 -2
- package/dist/index.js +3 -2
- package/dist/index.js.map +1 -1
- package/dist/llm/prism.cjs +72 -0
- package/dist/llm/prism.cjs.map +1 -0
- package/dist/llm/prism.d.cts +68 -0
- package/dist/llm/prism.d.ts +68 -0
- package/dist/llm/prism.js +65 -0
- package/dist/llm/prism.js.map +1 -0
- package/dist/llm/vercel-ai.d.cts +1 -1
- package/dist/llm/vercel-ai.d.ts +1 -1
- package/dist/registry/index.d.cts +2 -2
- package/dist/registry/index.d.ts +2 -2
- package/dist/run-cohort-CV7EcwGG.d.ts +111 -0
- package/dist/run-cohort-DitsaYgS.d.cts +111 -0
- package/dist/runtime/index.d.cts +2 -2
- package/dist/runtime/index.d.ts +2 -2
- package/dist/runtime.cjs +46 -0
- package/dist/runtime.cjs.map +1 -1
- package/dist/runtime.js +2 -1
- package/package.json +11 -1
- package/dist/run-flow-9U-gaYVF.d.ts +0 -35
- package/dist/run-flow-AXzOR-Wq.d.cts +0 -35
package/dist/engine.js.map
CHANGED
|
@@ -1 +1 @@
|
|
|
1
|
-
{"version":3,"sources":["../src/marketplace/manifest.ts","../src/marketplace/fixtures.ts"],"names":[],"mappings":"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","file":"engine.js","sourcesContent":["/**\n * The node package manifest — what a marketplace node declares about itself.\n *\n * A node is not one artifact. It is a kind definition (palette entry, config\n * schema, ports, renderer) plus an executor for EACH runtime the consumer runs.\n * A package shipping only a TS executor is unusable to anyone executing on PHP,\n * and without a manifest that is invisible until a run fails. Requested by the\n * MOIC Suite consumer (fancy-flow#2 §2), who runs the editor in TS and executes\n * in PHP and hit exactly this.\n *\n * The manifest is data, not code: the registry, the CLI, and the MCP all read\n * it without executing anything a package author wrote.\n *\n * ## Why the engine range lives per runtime\n *\n * The first cut of this manifest carried ONE `fancyFlow` range, and it was\n * wrong: the two engines version independently, so a single range cannot say\n * \"needs npm >=0.11 AND php >=0.5\". A package supporting both runtimes would\n * install cleanly against a host whose OTHER runtime was too old — the 0.9.0\n * failure shape wearing a manifest. The range belongs inside each runtime.\n */\n\nimport type { PauseAwaiting } from \"../registry/pause\";\n\n/** The current manifest schema version. Bump only on a breaking shape change. */\nexport const NODE_MANIFEST_SCHEMA_VERSION = 1;\n\n/**\n * A runtime a node can implement.\n *\n * Open rather than a closed union — the PHP and Node twins are what exist\n * today, but the point of a manifest is that a runtime we haven't written can\n * declare itself without a release here.\n */\nexport type NodeRuntimeId = \"ts\" | \"php\" | (string & {});\n\n/**\n * How one runtime provides this node, and which engine version it needs.\n *\n * `entry` and `package` are both here because the two ecosystems install\n * differently — a module path within the package for TS, a Composer\n * requirement for PHP — and pretending otherwise just moves the problem into\n * the CLI. Exactly one is required.\n */\nexport type NodeRuntimeSpec = {\n /** Module path within the package (TS-style runtimes). */\n entry?: string;\n /** Dependency requirement resolved by that ecosystem (PHP/Composer-style). */\n package?: string;\n /** Semver range of THIS runtime's engine. Required — see the module note. */\n engine: string;\n};\n\n/**\n * Whether a capability must be wired for the node to work at all.\n *\n * `required` is checked at AUTHOR time, not run time. The failure that hurts is\n * a node that installs fine, authors fine, and silently no-ops during a run —\n * the same silence as a routing bug. An editor can grey the node and say which\n * capability the host never registered.\n */\nexport type CapabilityRequirement = \"required\" | \"optional\";\n\n/**\n * Whether a node is safe to run again.\n *\n * Durable runs RETRY. A node that writes needs to say so, or a host has to pick\n * one retry policy for every node and get it wrong somewhere.\n */\nexport type SideEffects = \"none\" | \"idempotent\" | \"unsafe-to-replay\";\n\nexport type NodePackageManifest = {\n /** Must equal `NODE_MANIFEST_SCHEMA_VERSION`. */\n schemaVersion: number;\n /** Package name, as installed (`@acme/fancy-flow-salesforce`). */\n name: string;\n /**\n * The canonical kind id this package provides — namespaced, and the string\n * that gets persisted into every document using it.\n */\n kind: string;\n /**\n * Previous ids this kind still answers to.\n *\n * Core renamed `llm_branch` to `llm_router` and kept every old id working.\n * Third-party packages will rename too, and their documents break the same\n * way core's would have — so packages get the same escape hatch, otherwise\n * only first-party nodes can rename safely.\n */\n aliases?: string[];\n /**\n * Version of this node's CONFIG shape, independent of the document schema.\n *\n * A node's config evolves on its own clock. Without a declared version, every\n * executor accretes hand-written read-fallbacks forever (MOIC carries one for\n * `routes[].key` → `routes[].port`), because nothing canonicalises old config\n * the way import canonicalises kind ids.\n */\n configVersion?: number;\n /** Per-runtime entrypoints and engine ranges. */\n runtimes: Partial<Record<NodeRuntimeId, NodeRuntimeSpec>>;\n /**\n * Host capabilities this node needs, and whether each is mandatory.\n *\n * Declared so the CLI and the editor can say what to wire BEFORE a run,\n * rather than the node silently no-opping or crashing mid-run.\n */\n capabilities?: Record<string, CapabilityRequirement>;\n /**\n * Path to this node's golden fixtures, relative to the package root.\n *\n * REQUIRED. Every runtime the package claims runs these same cases, which is\n * what makes \"behaves identically on both runtimes\" verified rather than\n * asserted. See `./fixtures`.\n */\n fixtures: string;\n /**\n * Declares the node halts for a person. Mirrors `NodeKindDefinition`.\n *\n * A host-planning fact, not a node internal: a parent that embeds workflows\n * needs to reject a child that can pause, because a paused child wedges the\n * parent — and discovering that at run time means watching a run park.\n */\n pausesForHuman?: PauseAwaiting;\n /** Whether this node is safe to replay. See `SideEffects`. */\n sideEffects?: SideEffects;\n /** One-line summary — what `search_nodes` matches against. */\n description?: string;\n /**\n * Assigned by the registry, never by the author. Present in a manifest being\n * submitted for publication, it is a claim to a trust signal the author does\n * not get to make.\n */\n verified?: boolean;\n};\n\nexport type ManifestProblem = {\n level: \"error\" | \"warning\";\n field: string;\n message: string;\n};\n\nexport type ManifestValidation = {\n /** True when there are no `error`-level problems. Warnings do not block. */\n ok: boolean;\n manifest?: NodePackageManifest;\n problems: ManifestProblem[];\n};\n\n/** Reserved for first-party packages; the registry rejects other claimants. */\nconst FIRST_PARTY_SCOPE = \"@particle-academy/\";\n\n/** `@scope/name` — the shape 0.11.0 made canonical for kind ids. */\nconst NAMESPACED_KIND = /^@[a-z0-9][a-z0-9._-]*\\/[a-z0-9][a-z0-9._-]*$/i;\n\nconst SIDE_EFFECTS: readonly string[] = [\"none\", \"idempotent\", \"unsafe-to-replay\"];\nconst REQUIREMENTS: readonly string[] = [\"required\", \"optional\"];\n\nfunction err(field: string, message: string): ManifestProblem {\n return { level: \"error\", field, message };\n}\n\nfunction warn(field: string, message: string): ManifestProblem {\n return { level: \"warning\", field, message };\n}\n\n/**\n * Validate a manifest read from disk or a registry.\n *\n * Returns every problem rather than throwing on the first, because an author\n * fixing a package wants the whole list — a validator that reveals one error\n * per run turns a five-minute fix into five round trips.\n */\nexport function validateNodeManifest(input: unknown): ManifestValidation {\n const problems: ManifestProblem[] = [];\n\n if (typeof input !== \"object\" || input === null || Array.isArray(input)) {\n return { ok: false, problems: [err(\"\", \"Manifest must be a JSON object.\")] };\n }\n\n const m = input as Record<string, unknown>;\n\n // Version first: an unknown version means every other check below is\n // guessing at a shape we do not know, so say so plainly instead of\n // half-reading it and reporting confident nonsense about the rest.\n if (m.schemaVersion !== NODE_MANIFEST_SCHEMA_VERSION) {\n if (typeof m.schemaVersion !== \"number\") {\n problems.push(err(\"schemaVersion\", `Required, and must be ${NODE_MANIFEST_SCHEMA_VERSION}.`));\n } else {\n return {\n ok: false,\n problems: [\n err(\n \"schemaVersion\",\n `Unsupported manifest version ${m.schemaVersion}; this fancy-flow understands ${NODE_MANIFEST_SCHEMA_VERSION}. Upgrade fancy-flow to install this node.`,\n ),\n ],\n };\n }\n }\n\n if (typeof m.name !== \"string\" || m.name.trim() === \"\") {\n problems.push(err(\"name\", \"Required — the package name as installed.\"));\n }\n\n validateKind(m.kind, problems);\n validateAliases(m.aliases, problems);\n\n if (m.configVersion !== undefined && (typeof m.configVersion !== \"number\" || !Number.isInteger(m.configVersion))) {\n problems.push(err(\"configVersion\", \"Must be an integer.\"));\n }\n\n // A leftover single range from the pre-per-runtime shape. Worth naming\n // explicitly rather than ignoring — it silently means \"no engine constraint\".\n if (m.fancyFlow !== undefined) {\n problems.push(\n err(\n \"fancyFlow\",\n \"A single engine range cannot express the split — it cannot say \\\"needs ts >=0.15 AND php >=0.7\\\". Move the range into each entry of `runtimes` as `engine`.\",\n ),\n );\n }\n\n validateRuntimes(m.runtimes, problems);\n\n // Fixtures: the publish gate. Cross-runtime drift does not fail loudly —\n // it completes, down one path, with no error — so it has to be caught by\n // something that runs, not by review.\n if (typeof m.fixtures !== \"string\" || m.fixtures.trim() === \"\") {\n problems.push(\n err(\"fixtures\", \"Required — path to the node's golden fixtures. Every claimed runtime runs them, which is what makes cross-runtime parity verified rather than claimed.\"),\n );\n }\n\n validateCapabilities(m.capabilities, problems);\n\n if (m.sideEffects !== undefined && !SIDE_EFFECTS.includes(m.sideEffects as string)) {\n problems.push(err(\"sideEffects\", `Must be one of: ${SIDE_EFFECTS.join(\", \")}.`));\n }\n\n if (m.verified !== undefined) {\n problems.push(\n err(\"verified\", \"Assigned by the registry, not the package. Remove it — a package cannot vouch for itself.\"),\n );\n }\n\n const ok = !problems.some((p) => p.level === \"error\");\n return ok ? { ok, manifest: m as unknown as NodePackageManifest, problems } : { ok, problems };\n}\n\nfunction validateKind(kind: unknown, problems: ManifestProblem[]): void {\n if (typeof kind !== \"string\" || kind.trim() === \"\") {\n problems.push(err(\"kind\", \"Required — the canonical kind id this package provides.\"));\n return;\n }\n if (!NAMESPACED_KIND.test(kind)) {\n // Un-namespaced ids are the one mistake that cannot be fixed after the\n // fact: the ambiguous string is already written into saved documents.\n problems.push(\n err(\"kind\", `\"${kind}\" must be namespaced as @scope/name — a bare id makes stored graphs ambiguous, and that is unfixable once documents carry it.`),\n );\n return;\n }\n if (kind.startsWith(FIRST_PARTY_SCOPE)) {\n problems.push(\n warn(\"kind\", `${FIRST_PARTY_SCOPE}* is reserved for first-party nodes; the registry will reject this unless the package is first-party.`),\n );\n }\n}\n\nfunction validateAliases(aliases: unknown, problems: ManifestProblem[]): void {\n if (aliases === undefined) return;\n\n if (!Array.isArray(aliases) || aliases.some((a) => typeof a !== \"string\" || a.trim() === \"\")) {\n problems.push(err(\"aliases\", \"Must be an array of non-empty id strings.\"));\n }\n}\n\nfunction validateRuntimes(runtimes: unknown, problems: ManifestProblem[]): void {\n if (typeof runtimes !== \"object\" || runtimes === null || Array.isArray(runtimes)) {\n problems.push(err(\"runtimes\", \"Required — an object of runtime id to { entry | package, engine }.\"));\n return;\n }\n\n const entries = Object.entries(runtimes as Record<string, unknown>);\n if (entries.length === 0) {\n problems.push(err(\"runtimes\", \"A node that implements no runtime cannot execute anywhere.\"));\n return;\n }\n\n for (const [runtime, spec] of entries) {\n if (typeof spec !== \"object\" || spec === null || Array.isArray(spec)) {\n problems.push(err(`runtimes.${runtime}`, \"Must be an object of { entry | package, engine }.\"));\n continue;\n }\n\n const s = spec as Record<string, unknown>;\n const hasEntry = typeof s.entry === \"string\" && s.entry.trim() !== \"\";\n const hasPackage = typeof s.package === \"string\" && s.package.trim() !== \"\";\n\n if (!hasEntry && !hasPackage) {\n problems.push(err(`runtimes.${runtime}`, \"Needs `entry` (a module path) or `package` (a dependency requirement).\"));\n }\n if (hasEntry && hasPackage) {\n problems.push(err(`runtimes.${runtime}`, \"Declare `entry` or `package`, not both — which one is authoritative is otherwise ambiguous.\"));\n }\n if (typeof s.engine !== \"string\" || s.engine.trim() === \"\") {\n problems.push(\n err(`runtimes.${runtime}.engine`, `Required — the semver range of the ${runtime} engine. Without it, this node installs against a ${runtime} engine too old to run it.`),\n );\n }\n }\n}\n\nfunction validateCapabilities(capabilities: unknown, problems: ManifestProblem[]): void {\n if (capabilities === undefined) return;\n\n if (typeof capabilities !== \"object\" || capabilities === null || Array.isArray(capabilities)) {\n problems.push(\n err(\"capabilities\", 'Must be an object of capability id to \"required\" | \"optional\" — a bare list cannot say whether the node works without one.'),\n );\n return;\n }\n\n for (const [id, requirement] of Object.entries(capabilities as Record<string, unknown>)) {\n if (!REQUIREMENTS.includes(requirement as string)) {\n problems.push(err(`capabilities.${id}`, `Must be \"required\" or \"optional\".`));\n }\n }\n}\n\n/**\n * Check a node against the runtimes a host executes on, and their versions.\n *\n * Two failures live here, and both are errors because the node genuinely\n * cannot run: a runtime the package does not implement at all, and a runtime\n * it implements against an engine newer than the host's.\n *\n * `engineVersions` is optional — pass what the host knows. An unchecked range\n * is reported as a warning rather than passed over silently, because \"we did\n * not check\" and \"it is fine\" must not look the same.\n */\nexport function checkRuntimeSupport(\n manifest: Pick<NodePackageManifest, \"kind\" | \"runtimes\">,\n hostRuntimes: readonly string[],\n engineVersions?: Readonly<Record<string, string>>,\n): ManifestProblem[] {\n const runtimes = manifest.runtimes ?? {};\n const provided = Object.keys(runtimes);\n const problems: ManifestProblem[] = [];\n\n const missing = hostRuntimes.filter((r) => !provided.includes(r));\n if (missing.length > 0) {\n problems.push(\n err(\n \"runtimes\",\n `${manifest.kind} implements ${provided.join(\", \") || \"no runtime\"} but this project executes on ${missing.join(\", \")}. The node would install, appear in the palette, and then fail to run.`,\n ),\n );\n }\n\n for (const runtime of hostRuntimes) {\n const spec = (runtimes as Record<string, NodeRuntimeSpec | undefined>)[runtime];\n if (!spec) continue;\n\n const hostVersion = engineVersions?.[runtime];\n if (hostVersion === undefined) {\n problems.push(\n warn(`runtimes.${runtime}.engine`, `${manifest.kind} needs ${runtime} engine ${spec.engine}; this host did not report its ${runtime} version, so the range was not checked.`),\n );\n continue;\n }\n\n if (!satisfiesRange(hostVersion, spec.engine)) {\n problems.push(\n err(`runtimes.${runtime}.engine`, `${manifest.kind} needs ${runtime} engine ${spec.engine}, but this host runs ${hostVersion}.`),\n );\n }\n }\n\n return problems;\n}\n\n/**\n * Minimal semver range check — `^x.y.z`, `~x.y.z`, `>=x.y.z`, `x.y.z`, `*`.\n *\n * Deliberately small: this runs in the CLI and in CI, and pulling a semver\n * library into the engine for one comparison is not worth the dependency. It\n * covers the forms a manifest actually uses; anything it cannot parse is\n * treated as unsatisfied rather than silently passed, so an unparseable range\n * fails loudly instead of waving a node through.\n */\nexport function satisfiesRange(version: string, range: string): boolean {\n const trimmed = range.trim();\n if (trimmed === \"*\" || trimmed === \"\") return true;\n\n const v = parseVersion(version);\n if (!v) return false;\n\n for (const clause of trimmed.split(\"||\").map((c) => c.trim())) {\n if (satisfiesClause(v, clause)) return true;\n }\n return false;\n}\n\nfunction satisfiesClause(v: [number, number, number], clause: string): boolean {\n const m = /^(\\^|~|>=|>|<=|<|=)?\\s*v?(\\d+)(?:\\.(\\d+))?(?:\\.(\\d+))?/.exec(clause);\n if (!m) return false;\n\n const op = m[1] ?? \"=\";\n const target: [number, number, number] = [Number(m[2]), Number(m[3] ?? 0), Number(m[4] ?? 0)];\n const cmp = compare(v, target);\n\n switch (op) {\n case \">=\":\n return cmp >= 0;\n case \">\":\n return cmp > 0;\n case \"<=\":\n return cmp <= 0;\n case \"<\":\n return cmp < 0;\n case \"=\":\n return cmp === 0;\n case \"~\":\n // Same major+minor, patch may rise.\n return cmp >= 0 && v[0] === target[0] && v[1] === target[1];\n case \"^\":\n // Below 1.0.0 a minor bump is breaking, so ^0.5 means 0.5.x — which is\n // the range every pre-1.0 package in this suite actually needs.\n if (target[0] === 0) return cmp >= 0 && v[0] === 0 && v[1] === target[1];\n return cmp >= 0 && v[0] === target[0];\n default:\n return false;\n }\n}\n\nfunction parseVersion(version: string): [number, number, number] | null {\n const m = /^v?(\\d+)\\.(\\d+)(?:\\.(\\d+))?/.exec(version.trim());\n return m ? [Number(m[1]), Number(m[2]), Number(m[3] ?? 0)] : null;\n}\n\nfunction compare(a: [number, number, number], b: [number, number, number]): number {\n for (let i = 0; i < 3; i++) {\n if (a[i] !== b[i]) return a[i] < b[i] ? -1 : 1;\n }\n return 0;\n}\n\n/**\n * Check that every capability a node needs is wired.\n *\n * A `required` capability that is missing is an ERROR — that is the whole point\n * of the requirement level. It is meant to be surfaced at author time, so an\n * editor can grey the node and name what the host never registered, rather than\n * the node installing cleanly and silently no-opping during a run.\n *\n * An `optional` one is a warning: the node still works, with less.\n */\nexport function checkCapabilities(\n manifest: Pick<NodePackageManifest, \"kind\" | \"capabilities\">,\n available: Readonly<Record<string, boolean>>,\n): ManifestProblem[] {\n const needed = manifest.capabilities ?? {};\n const problems: ManifestProblem[] = [];\n\n for (const [id, requirement] of Object.entries(needed)) {\n if (available[id] === true) continue;\n\n problems.push(\n requirement === \"required\"\n ? err(\"capabilities\", `${manifest.kind} requires the ${id} capability, which this host has not registered. The node cannot run here.`)\n : warn(\"capabilities\", `${manifest.kind} can use the ${id} capability, which this host has not registered. The node runs with reduced behaviour.`),\n );\n }\n\n return problems;\n}\n","/**\n * Golden fixtures — the parity guarantee, and a publishing requirement.\n *\n * Every runtime a node package claims runs these same JSON cases. That is what\n * makes \"this node behaves identically on TS and PHP\" verified rather than\n * asserted, and it is the one thing a loose collection of repos can never\n * offer.\n *\n * WHY IT IS REQUIRED RATHER THAN ENCOURAGED: cross-runtime drift does not fail\n * loudly. The 0.9.0 port-resolution divergence produced flows that routed\n * correctly in the editor and silently down one path on the server — status\n * `completed`, no error, no exception, nothing to alert on. A guarantee that\n * only holds when an author opts in is not a guarantee.\n *\n * WHAT A CASE ASSERTS, and why it matters more than it looks:\n *\n * A fixture asserts THE DOWNSTREAM NODE EXECUTED — not the port the node\n * recorded. The distinction is the whole lesson of that incident. A test\n * reading back `outputs.router.__port` stays green while no edge fires and\n * the run halts at the branch: the node faithfully recorded its choice, and\n * nothing downstream ever ran. So the runner wires a real probe to every\n * declared port and reports which probes actually executed.\n *\n * The format is plain JSON with no expressions or callbacks, so the PHP runner\n * executes byte-identical cases without an embedded JS engine.\n */\n\nimport { runFlow } from \"../runtime/run-flow\";\nimport { getNodeKind } from \"../registry/registry\";\nimport { resolveNodePorts } from \"../registry/ports\";\nimport { decodePause, type PauseAwaiting } from \"../registry/pause\";\nimport { registerLlmClient, registerWorkflowResolver } from \"../registry/capabilities\";\nimport type { FlowGraph, FlowNode, NodeExecutor, RunEvent } from \"../types\";\n\n/**\n * Deterministic stand-ins for host capabilities, declared as DATA.\n *\n * `llm_router` cannot reach a provider in CI, so a fixture has to supply a fake\n * `LlmClient`. If the stub format is not shared, each runtime stubs\n * differently and the fixtures stop being comparable — parity theatre. So the\n * fixture declares the stub's *behaviour* and both engines construct it\n * identically from the same JSON.\n */\nexport type FixtureStubs = {\n /** Canned `chooseRoute` answer for the LLM capability. */\n llm_client?: { chooseRoute: { port: string; reason?: string } };\n /** Canned workflow resolution, keyed by ref, for `subflow`. */\n workflow_resolver?: Record<string, FlowGraph | null>;\n};\n\n/** An event a case expects the run to have emitted. */\nexport type FixtureEventExpectation = {\n type: RunEvent[\"type\"];\n /** Emitting node, when it matters. */\n nodeId?: string;\n level?: \"info\" | \"warn\" | \"error\";\n /** Substring match against the message — full text is too brittle to pin. */\n messageContains?: string;\n};\n\n/** What a case expects to have happened. */\nexport type FixtureExpectation = {\n /**\n * Output ports whose downstream node must have executed — the assertion that\n * catches routing drift. Order-insensitive; the set must match exactly, so a\n * node that fires an extra port fails just as loudly as one that fires none.\n */\n ports?: string[];\n /** The value carried downstream, deep-compared when present. */\n value?: unknown;\n /** The run halted for a person. */\n pause?: { awaiting: PauseAwaiting; detail?: unknown };\n /** The run failed, and the message contains this substring. */\n error?: string;\n /**\n * Events the run must have emitted.\n *\n * Emitted events are BEHAVIOUR, not decoration. The hallucinated-port warning\n * is a contract an operator relies on to know a run took the fallback — if\n * one runtime stops emitting it, the guarantee degrades silently. Each entry\n * must match at least one emitted event.\n */\n events?: FixtureEventExpectation[];\n /**\n * The run resumed after a pause and reached this state.\n *\n * Pause/resume is the ONLY path that crosses a persistence boundary, which\n * makes it where two runtimes are most likely to drift — and it had no parity\n * coverage at all while `PausesForHuman` became public API.\n */\n afterResume?: {\n /** Delivered on the paused node's `values` input, as a host would on resume. */\n submit: unknown;\n ports?: string[];\n value?: unknown;\n error?: string;\n };\n};\n\nexport type FixtureCase = {\n /** Human-readable, and what a failure report names. */\n name: string;\n /** Config for the node under test — drives config-derived ports. */\n config?: Record<string, unknown>;\n /**\n * The node's resolved output ports, stated rather than derived.\n *\n * NOT a convenience. TS derives config-driven ports by running a JavaScript\n * function (`switch_case`'s cases, `llm_router`'s routes); PHP cannot, and\n * falls back to the kind's static declaration. Left there, the identical\n * fixture would build a DIFFERENT graph on each runtime — the fixtures would\n * silently stop comparing like with like, which is the exact failure they\n * exist to catch.\n *\n * So a case states its ports the same way an exported document does (see\n * 0.10.1, \"serialize resolved ports\"), and both runners honour it. Omit it\n * only for a node whose ports are static.\n */\n ports?: string[];\n /** Inputs delivered on the node's input ports. */\n inputs?: Record<string, unknown>;\n /**\n * Run this case against an ALIAS or an older config shape.\n *\n * What proves `aliases` and `configVersion` actually work rather than being\n * declared and rotting. A package that renames its kind should have a case\n * pinning that the old id still resolves.\n */\n legacyKind?: string;\n /** Deterministic capability stand-ins for this case. */\n stubs?: FixtureStubs;\n expect: FixtureExpectation;\n};\n\nexport type FixtureFile = {\n /** The kind under test. Must match the manifest's `kind`. */\n kind: string;\n cases: FixtureCase[];\n};\n\nexport type FixtureFailure = {\n case: string;\n message: string;\n};\n\nexport type FixtureRunResult = {\n ok: boolean;\n passed: number;\n failures: FixtureFailure[];\n};\n\nconst SUBJECT = \"subject\";\nconst TRIGGER = \"trigger\";\nconst probeId = (port: string) => `probe:${port}`;\n\n/**\n * Build the graph a case runs in: a trigger, the node under test, and one\n * probe per declared output port.\n *\n * The probes are the point. Reading the subject's return value would tell us\n * what it *recorded*; only a probe tells us what actually reached a downstream\n * node through a real edge.\n */\nfunction buildGraph(kindId: string, testCase: FixtureCase): { graph: FlowGraph; ports: string[] } {\n const subject: FlowNode = {\n id: SUBJECT,\n type: kindId,\n position: { x: 0, y: 100 },\n data: { kind: kindId, config: testCase.config ?? {} },\n } as unknown as FlowNode;\n\n const kind = getNodeKind(kindId) ?? undefined;\n // An explicitly declared port list wins, so both runtimes build the same\n // graph even where one can derive config-driven ports and the other cannot.\n const ports = testCase.ports ?? (resolveNodePorts(subject, kind).outputs ?? []).map((p) => p.id);\n const effective = ports.length ? ports : [\"out\"];\n\n const nodes: FlowNode[] = [\n { id: TRIGGER, type: \"manual_trigger\", position: { x: 0, y: 0 }, data: {} } as unknown as FlowNode,\n subject,\n ...effective.map(\n (port, i) =>\n ({\n id: probeId(port),\n type: \"@particle-academy/transform\",\n position: { x: i * 200, y: 200 },\n data: {},\n }) as unknown as FlowNode,\n ),\n ];\n\n const edges = [\n { id: `e:trigger`, source: TRIGGER, target: SUBJECT },\n ...effective.map((port) => ({\n id: `e:${port}`,\n source: SUBJECT,\n sourceHandle: port,\n target: probeId(port),\n })),\n ];\n\n return { graph: { nodes, edges } as FlowGraph, ports: effective };\n}\n\nfunction deepEqual(a: unknown, b: unknown): boolean {\n return JSON.stringify(a) === JSON.stringify(b);\n}\n\n/**\n * Install the case's capability stubs, returning a function that removes them.\n *\n * Constructed here from the fixture's JSON rather than supplied by the caller,\n * which is the whole point: both runtimes build the same stub from the same\n * data, so a fixture covering `llm_router` compares like with like instead of\n * comparing two different fakes.\n */\nfunction installStubs(stubs: FixtureStubs | undefined): () => void {\n if (!stubs) return () => {};\n\n const teardown: Array<() => void> = [];\n\n if (stubs.llm_client) {\n const answer = stubs.llm_client.chooseRoute;\n teardown.push(registerLlmClient({ chooseRoute: () => ({ ...answer }) }));\n }\n\n if (stubs.workflow_resolver) {\n const table = stubs.workflow_resolver;\n teardown.push(registerWorkflowResolver((ref) => table[ref] ?? null));\n }\n\n return () => teardown.forEach((fn) => fn());\n}\n\nfunction matchesEvent(event: RunEvent, want: FixtureEventExpectation): boolean {\n if (event.type !== want.type) return false;\n\n const e = event as Record<string, unknown>;\n if (want.nodeId !== undefined && e.nodeId !== want.nodeId) return false;\n if (want.level !== undefined && e.level !== want.level) return false;\n if (want.messageContains !== undefined && !String(e.message ?? \"\").includes(want.messageContains)) return false;\n\n return true;\n}\n\n/**\n * Re-run a paused case with a submission delivered, as a durable host would.\n *\n * The submission arrives on `values` because that is the input the builtin\n * human nodes read, and a third-party pausing node that wants fixture coverage\n * should follow the same convention rather than inventing its own.\n */\nasync function resume(\n kindId: string,\n testCase: FixtureCase,\n executor: NodeExecutor,\n pausedNodeId: string,\n submit: unknown,\n): Promise<{ ok: boolean; error?: string; fired: string[]; carried: unknown }> {\n const { graph } = buildGraph(kindId, testCase);\n const fired: string[] = [];\n let carried: unknown;\n\n const executors: Record<string, NodeExecutor> = {\n manual_trigger: () => testCase.inputs ?? {},\n \"@particle-academy/manual_trigger\": () => testCase.inputs ?? {},\n [kindId]: executor,\n };\n\n // The resumed node sees its submission, exactly as the durable runner\n // injects one.\n executors[pausedNodeId] = ((c: Parameters<NodeExecutor>[0]) =>\n executor({ ...c, inputs: { ...(c.inputs as object), values: submit } })) as NodeExecutor;\n\n for (const node of graph.nodes) {\n if (!node.id.startsWith(\"probe:\")) continue;\n const port = node.id.slice(\"probe:\".length);\n executors[node.id] = ((c: { inputs: Record<string, unknown> }) => {\n fired.push(port);\n carried = c.inputs?.in ?? c.inputs;\n return undefined;\n }) as unknown as NodeExecutor;\n }\n\n const releaseStubs = installStubs(testCase.stubs);\n const result = await runFlow(graph, executors, () => {});\n releaseStubs();\n\n return { ok: result.ok, error: result.error, fired, carried };\n}\n\n/**\n * Run one fixture file against a kind's executor.\n *\n * `executor` is the node's own; everything else in the graph is supplied here,\n * so a case exercises the node and nothing but the node.\n */\nexport async function runFixtures(\n file: FixtureFile,\n executor: NodeExecutor,\n): Promise<FixtureRunResult> {\n const failures: FixtureFailure[] = [];\n let passed = 0;\n\n for (const testCase of file.cases) {\n // A case may run against an alias or an older id, which is what proves the\n // package's `aliases` declaration is real rather than decorative.\n const kindId = testCase.legacyKind ?? file.kind;\n const { graph } = buildGraph(kindId, testCase);\n const fired: string[] = [];\n const events: RunEvent[] = [];\n let carried: unknown;\n\n const releaseStubs = installStubs(testCase.stubs);\n\n const executors: Record<string, NodeExecutor> = {\n manual_trigger: () => testCase.inputs ?? {},\n \"@particle-academy/manual_trigger\": () => testCase.inputs ?? {},\n [kindId]: executor,\n };\n\n // A probe per port, bound by NODE ID — `pickExecutor` checks that before\n // kind, so each probe reports which specific port reached it. Recording\n // here, rather than inspecting the subject's result, is what makes this\n // assert reachability instead of intent.\n for (const node of graph.nodes) {\n if (!node.id.startsWith(\"probe:\")) continue;\n const port = node.id.slice(\"probe:\".length);\n executors[node.id] = ((ctx: { inputs: Record<string, unknown> }) => {\n fired.push(port);\n carried = ctx.inputs?.in ?? ctx.inputs;\n return undefined;\n }) as unknown as NodeExecutor;\n }\n\n const result = await runFlow(graph, executors, (e) => events.push(e));\n releaseStubs();\n\n const fail = (message: string) => failures.push({ case: testCase.name, message });\n const expected = testCase.expect;\n let caseOk = true;\n\n if (expected.pause) {\n const paused = decodePause(result.error);\n if (!paused) {\n caseOk = false;\n fail(`expected a pause awaiting \"${expected.pause.awaiting}\", got ${result.ok ? \"a completed run\" : `error: ${result.error}`}`);\n } else {\n if (paused.awaiting !== expected.pause.awaiting) {\n caseOk = false;\n fail(`expected pause awaiting \"${expected.pause.awaiting}\", got \"${paused.awaiting}\"`);\n }\n if (\"detail\" in expected.pause && !deepEqual(paused.detail, expected.pause.detail)) {\n caseOk = false;\n fail(`pause detail mismatch: expected ${JSON.stringify(expected.pause.detail)}, got ${JSON.stringify(paused.detail)}`);\n }\n }\n } else if (expected.error !== undefined) {\n if (result.ok) {\n caseOk = false;\n fail(`expected an error containing \"${expected.error}\", but the run succeeded`);\n } else if (!String(result.error ?? \"\").includes(expected.error)) {\n caseOk = false;\n fail(`expected an error containing \"${expected.error}\", got \"${result.error}\"`);\n }\n } else {\n if (expected.ports !== undefined) {\n const got = [...fired].sort();\n const want = [...expected.ports].sort();\n if (!deepEqual(got, want)) {\n caseOk = false;\n // Name the failure in terms of reachability, because that is what\n // the assertion means and what a reader needs to act on.\n fail(\n `expected these ports to reach a downstream node: [${want.join(\", \")}], but [${got.join(\", \")}] did` +\n (result.ok ? \"\" : ` (run error: ${result.error})`),\n );\n }\n }\n if (\"value\" in expected && !deepEqual(carried, expected.value)) {\n caseOk = false;\n fail(`expected the value carried downstream to be ${JSON.stringify(expected.value)}, got ${JSON.stringify(carried)}`);\n }\n }\n\n // Emitted events are behaviour, not decoration — an operator relies on the\n // hallucinated-port warning to know a run took the fallback.\n for (const want of expected.events ?? []) {\n if (!events.some((e) => matchesEvent(e, want))) {\n caseOk = false;\n fail(`expected an emitted event matching ${JSON.stringify(want)}, but none of the ${events.length} emitted events did`);\n }\n }\n\n // Resume: the only path crossing a persistence boundary, and so the one\n // most likely to drift between runtimes.\n if (expected.afterResume) {\n const paused = decodePause(result.error);\n if (!paused) {\n caseOk = false;\n fail(\"expected the run to pause before resuming, but it never paused\");\n } else {\n const resumed = await resume(kindId, testCase, executor, paused.nodeId, expected.afterResume.submit);\n const want = expected.afterResume;\n\n if (want.error !== undefined) {\n if (resumed.ok || !String(resumed.error ?? \"\").includes(want.error)) {\n caseOk = false;\n fail(`after resume: expected an error containing \"${want.error}\", got ${resumed.ok ? \"success\" : `\"${resumed.error}\"`}`);\n }\n }\n if (want.ports !== undefined) {\n const got = [...resumed.fired].sort();\n const wanted = [...want.ports].sort();\n if (!deepEqual(got, wanted)) {\n caseOk = false;\n fail(`after resume: expected ports [${wanted.join(\", \")}] to reach a downstream node, but [${got.join(\", \")}] did`);\n }\n }\n if (\"value\" in want && !deepEqual(resumed.carried, want.value)) {\n caseOk = false;\n fail(`after resume: expected the value carried downstream to be ${JSON.stringify(want.value)}, got ${JSON.stringify(resumed.carried)}`);\n }\n }\n }\n\n if (caseOk) passed += 1;\n }\n\n return { ok: failures.length === 0, passed, failures };\n}\n\n/**\n * Validate a fixture file's shape before running it.\n *\n * A package that publishes an empty or malformed fixture file has satisfied the\n * letter of the requirement and none of its purpose, so this is checked at\n * publish rather than trusted.\n */\nexport function validateFixtureFile(input: unknown, expectedKind?: string): string[] {\n const problems: string[] = [];\n\n if (typeof input !== \"object\" || input === null || Array.isArray(input)) {\n return [\"Fixture file must be a JSON object.\"];\n }\n\n const f = input as Record<string, unknown>;\n\n if (typeof f.kind !== \"string\" || f.kind.trim() === \"\") {\n problems.push(\"`kind` is required — the kind these cases exercise.\");\n } else if (expectedKind && f.kind !== expectedKind) {\n problems.push(`\\`kind\\` is \"${f.kind}\" but the manifest declares \"${expectedKind}\".`);\n }\n\n if (!Array.isArray(f.cases) || f.cases.length === 0) {\n problems.push(\"`cases` must contain at least one case — an empty fixture file proves nothing.\");\n return problems;\n }\n\n // At least one case must exercise a failure.\n //\n // \"Does it fail the same way\" deserves equal weight to \"does it succeed the\n // same way\": the incident that motivated this whole mechanism was a FAILURE\n // that reported `completed` with no error. A suite that only covers happy\n // paths cannot catch a runtime that fails differently — or does not fail\n // at all.\n const coversFailure = f.cases.some((c: unknown) => {\n const expect = (c as { expect?: Record<string, unknown> })?.expect;\n return Boolean(expect && (\"error\" in expect || \"pause\" in expect));\n });\n if (!coversFailure) {\n problems.push(\n \"At least one case must assert a failure (`expect.error`) or a pause (`expect.pause`). Every case here covers a success path, and the divergence this format exists to catch reported success while doing nothing.\",\n );\n }\n\n f.cases.forEach((c: unknown, i: number) => {\n const label = `cases[${i}]`;\n if (typeof c !== \"object\" || c === null) {\n problems.push(`${label} must be an object.`);\n return;\n }\n const testCase = c as Record<string, unknown>;\n if (typeof testCase.name !== \"string\" || testCase.name.trim() === \"\") {\n problems.push(`${label}.name is required — a failure report names it.`);\n }\n if (typeof testCase.expect !== \"object\" || testCase.expect === null) {\n problems.push(`${label}.expect is required — a case that asserts nothing passes vacuously.`);\n return;\n }\n const expect = testCase.expect as Record<string, unknown>;\n if (\n expect.ports === undefined &&\n expect.value === undefined &&\n expect.pause === undefined &&\n expect.error === undefined\n ) {\n problems.push(`${label}.expect must assert at least one of: ports, value, pause, error.`);\n }\n if (expect.ports !== undefined && (!Array.isArray(expect.ports) || expect.ports.some((p) => typeof p !== \"string\"))) {\n problems.push(`${label}.expect.ports must be an array of port id strings.`);\n }\n });\n\n return problems;\n}\n"]}
|
|
1
|
+
{"version":3,"sources":["../src/marketplace/manifest.ts","../src/marketplace/fixtures.ts"],"names":[],"mappings":"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","file":"engine.js","sourcesContent":["/**\n * The node package manifest — what a marketplace node declares about itself.\n *\n * A node is not one artifact. It is a kind definition (palette entry, config\n * schema, ports, renderer) plus an executor for EACH runtime the consumer runs.\n * A package shipping only a TS executor is unusable to anyone executing on PHP,\n * and without a manifest that is invisible until a run fails. Requested by the\n * MOIC Suite consumer (fancy-flow#2 §2), who runs the editor in TS and executes\n * in PHP and hit exactly this.\n *\n * The manifest is data, not code: the registry, the CLI, and the MCP all read\n * it without executing anything a package author wrote.\n *\n * ## Why the engine range lives per runtime\n *\n * The first cut of this manifest carried ONE `fancyFlow` range, and it was\n * wrong: the two engines version independently, so a single range cannot say\n * \"needs npm >=0.11 AND php >=0.5\". A package supporting both runtimes would\n * install cleanly against a host whose OTHER runtime was too old — the 0.9.0\n * failure shape wearing a manifest. The range belongs inside each runtime.\n */\n\nimport type { PauseAwaiting } from \"../registry/pause\";\n\n/** The current manifest schema version. Bump only on a breaking shape change. */\nexport const NODE_MANIFEST_SCHEMA_VERSION = 1;\n\n/**\n * A runtime a node can implement.\n *\n * Open rather than a closed union — the PHP and Node twins are what exist\n * today, but the point of a manifest is that a runtime we haven't written can\n * declare itself without a release here.\n */\nexport type NodeRuntimeId = \"ts\" | \"php\" | (string & {});\n\n/**\n * How one runtime provides this node, and which engine version it needs.\n *\n * `entry` and `package` are both here because the two ecosystems install\n * differently — a module path within the package for TS, a Composer\n * requirement for PHP — and pretending otherwise just moves the problem into\n * the CLI. Exactly one is required.\n */\nexport type NodeRuntimeSpec = {\n /** Module path within the package (TS-style runtimes). */\n entry?: string;\n /** Dependency requirement resolved by that ecosystem (PHP/Composer-style). */\n package?: string;\n /** Semver range of THIS runtime's engine. Required — see the module note. */\n engine: string;\n};\n\n/**\n * Whether a capability must be wired for the node to work at all.\n *\n * `required` is checked at AUTHOR time, not run time. The failure that hurts is\n * a node that installs fine, authors fine, and silently no-ops during a run —\n * the same silence as a routing bug. An editor can grey the node and say which\n * capability the host never registered.\n */\nexport type CapabilityRequirement = \"required\" | \"optional\";\n\n/**\n * Whether a node is safe to run again.\n *\n * Durable runs RETRY. A node that writes needs to say so, or a host has to pick\n * one retry policy for every node and get it wrong somewhere.\n */\nexport type SideEffects = \"none\" | \"idempotent\" | \"unsafe-to-replay\";\n\nexport type NodePackageManifest = {\n /** Must equal `NODE_MANIFEST_SCHEMA_VERSION`. */\n schemaVersion: number;\n /** Package name, as installed (`@acme/fancy-flow-salesforce`). */\n name: string;\n /**\n * The canonical kind id this package provides — namespaced, and the string\n * that gets persisted into every document using it.\n */\n kind: string;\n /**\n * Previous ids this kind still answers to.\n *\n * Core renamed `llm_branch` to `llm_router` and kept every old id working.\n * Third-party packages will rename too, and their documents break the same\n * way core's would have — so packages get the same escape hatch, otherwise\n * only first-party nodes can rename safely.\n */\n aliases?: string[];\n /**\n * Version of this node's CONFIG shape, independent of the document schema.\n *\n * A node's config evolves on its own clock. Without a declared version, every\n * executor accretes hand-written read-fallbacks forever (MOIC carries one for\n * `routes[].key` → `routes[].port`), because nothing canonicalises old config\n * the way import canonicalises kind ids.\n */\n configVersion?: number;\n /** Per-runtime entrypoints and engine ranges. */\n runtimes: Partial<Record<NodeRuntimeId, NodeRuntimeSpec>>;\n /**\n * Host capabilities this node needs, and whether each is mandatory.\n *\n * Declared so the CLI and the editor can say what to wire BEFORE a run,\n * rather than the node silently no-opping or crashing mid-run.\n */\n capabilities?: Record<string, CapabilityRequirement>;\n /**\n * Path to this node's golden fixtures, relative to the package root.\n *\n * REQUIRED. Every runtime the package claims runs these same cases, which is\n * what makes \"behaves identically on both runtimes\" verified rather than\n * asserted. See `./fixtures`.\n */\n fixtures: string;\n /**\n * Declares the node halts for a person. Mirrors `NodeKindDefinition`.\n *\n * A host-planning fact, not a node internal: a parent that embeds workflows\n * needs to reject a child that can pause, because a paused child wedges the\n * parent — and discovering that at run time means watching a run park.\n */\n pausesForHuman?: PauseAwaiting;\n /** Whether this node is safe to replay. See `SideEffects`. */\n sideEffects?: SideEffects;\n /** One-line summary — what `search_nodes` matches against. */\n description?: string;\n /**\n * Assigned by the registry, never by the author. Present in a manifest being\n * submitted for publication, it is a claim to a trust signal the author does\n * not get to make.\n */\n verified?: boolean;\n};\n\nexport type ManifestProblem = {\n level: \"error\" | \"warning\";\n field: string;\n message: string;\n};\n\nexport type ManifestValidation = {\n /** True when there are no `error`-level problems. Warnings do not block. */\n ok: boolean;\n manifest?: NodePackageManifest;\n problems: ManifestProblem[];\n};\n\n/** Reserved for first-party packages; the registry rejects other claimants. */\nconst FIRST_PARTY_SCOPE = \"@particle-academy/\";\n\n/** `@scope/name` — the shape 0.11.0 made canonical for kind ids. */\nconst NAMESPACED_KIND = /^@[a-z0-9][a-z0-9._-]*\\/[a-z0-9][a-z0-9._-]*$/i;\n\nconst SIDE_EFFECTS: readonly string[] = [\"none\", \"idempotent\", \"unsafe-to-replay\"];\nconst REQUIREMENTS: readonly string[] = [\"required\", \"optional\"];\n\nfunction err(field: string, message: string): ManifestProblem {\n return { level: \"error\", field, message };\n}\n\nfunction warn(field: string, message: string): ManifestProblem {\n return { level: \"warning\", field, message };\n}\n\n/**\n * Validate a manifest read from disk or a registry.\n *\n * Returns every problem rather than throwing on the first, because an author\n * fixing a package wants the whole list — a validator that reveals one error\n * per run turns a five-minute fix into five round trips.\n */\nexport function validateNodeManifest(input: unknown): ManifestValidation {\n const problems: ManifestProblem[] = [];\n\n if (typeof input !== \"object\" || input === null || Array.isArray(input)) {\n return { ok: false, problems: [err(\"\", \"Manifest must be a JSON object.\")] };\n }\n\n const m = input as Record<string, unknown>;\n\n // Version first: an unknown version means every other check below is\n // guessing at a shape we do not know, so say so plainly instead of\n // half-reading it and reporting confident nonsense about the rest.\n if (m.schemaVersion !== NODE_MANIFEST_SCHEMA_VERSION) {\n if (typeof m.schemaVersion !== \"number\") {\n problems.push(err(\"schemaVersion\", `Required, and must be ${NODE_MANIFEST_SCHEMA_VERSION}.`));\n } else {\n return {\n ok: false,\n problems: [\n err(\n \"schemaVersion\",\n `Unsupported manifest version ${m.schemaVersion}; this fancy-flow understands ${NODE_MANIFEST_SCHEMA_VERSION}. Upgrade fancy-flow to install this node.`,\n ),\n ],\n };\n }\n }\n\n if (typeof m.name !== \"string\" || m.name.trim() === \"\") {\n problems.push(err(\"name\", \"Required — the package name as installed.\"));\n }\n\n validateKind(m.kind, problems);\n validateAliases(m.aliases, problems);\n\n if (m.configVersion !== undefined && (typeof m.configVersion !== \"number\" || !Number.isInteger(m.configVersion))) {\n problems.push(err(\"configVersion\", \"Must be an integer.\"));\n }\n\n // A leftover single range from the pre-per-runtime shape. Worth naming\n // explicitly rather than ignoring — it silently means \"no engine constraint\".\n if (m.fancyFlow !== undefined) {\n problems.push(\n err(\n \"fancyFlow\",\n \"A single engine range cannot express the split — it cannot say \\\"needs ts >=0.15 AND php >=0.7\\\". Move the range into each entry of `runtimes` as `engine`.\",\n ),\n );\n }\n\n validateRuntimes(m.runtimes, problems);\n\n // Fixtures: the publish gate. Cross-runtime drift does not fail loudly —\n // it completes, down one path, with no error — so it has to be caught by\n // something that runs, not by review.\n if (typeof m.fixtures !== \"string\" || m.fixtures.trim() === \"\") {\n problems.push(\n err(\"fixtures\", \"Required — path to the node's golden fixtures. Every claimed runtime runs them, which is what makes cross-runtime parity verified rather than claimed.\"),\n );\n }\n\n validateCapabilities(m.capabilities, problems);\n\n if (m.sideEffects !== undefined && !SIDE_EFFECTS.includes(m.sideEffects as string)) {\n problems.push(err(\"sideEffects\", `Must be one of: ${SIDE_EFFECTS.join(\", \")}.`));\n }\n\n if (m.verified !== undefined) {\n problems.push(\n err(\"verified\", \"Assigned by the registry, not the package. Remove it — a package cannot vouch for itself.\"),\n );\n }\n\n const ok = !problems.some((p) => p.level === \"error\");\n return ok ? { ok, manifest: m as unknown as NodePackageManifest, problems } : { ok, problems };\n}\n\nfunction validateKind(kind: unknown, problems: ManifestProblem[]): void {\n if (typeof kind !== \"string\" || kind.trim() === \"\") {\n problems.push(err(\"kind\", \"Required — the canonical kind id this package provides.\"));\n return;\n }\n if (!NAMESPACED_KIND.test(kind)) {\n // Un-namespaced ids are the one mistake that cannot be fixed after the\n // fact: the ambiguous string is already written into saved documents.\n problems.push(\n err(\"kind\", `\"${kind}\" must be namespaced as @scope/name — a bare id makes stored graphs ambiguous, and that is unfixable once documents carry it.`),\n );\n return;\n }\n if (kind.startsWith(FIRST_PARTY_SCOPE)) {\n problems.push(\n warn(\"kind\", `${FIRST_PARTY_SCOPE}* is reserved for first-party nodes; the registry will reject this unless the package is first-party.`),\n );\n }\n}\n\nfunction validateAliases(aliases: unknown, problems: ManifestProblem[]): void {\n if (aliases === undefined) return;\n\n if (!Array.isArray(aliases) || aliases.some((a) => typeof a !== \"string\" || a.trim() === \"\")) {\n problems.push(err(\"aliases\", \"Must be an array of non-empty id strings.\"));\n }\n}\n\nfunction validateRuntimes(runtimes: unknown, problems: ManifestProblem[]): void {\n if (typeof runtimes !== \"object\" || runtimes === null || Array.isArray(runtimes)) {\n problems.push(err(\"runtimes\", \"Required — an object of runtime id to { entry | package, engine }.\"));\n return;\n }\n\n const entries = Object.entries(runtimes as Record<string, unknown>);\n if (entries.length === 0) {\n problems.push(err(\"runtimes\", \"A node that implements no runtime cannot execute anywhere.\"));\n return;\n }\n\n for (const [runtime, spec] of entries) {\n if (typeof spec !== \"object\" || spec === null || Array.isArray(spec)) {\n problems.push(err(`runtimes.${runtime}`, \"Must be an object of { entry | package, engine }.\"));\n continue;\n }\n\n const s = spec as Record<string, unknown>;\n const hasEntry = typeof s.entry === \"string\" && s.entry.trim() !== \"\";\n const hasPackage = typeof s.package === \"string\" && s.package.trim() !== \"\";\n\n if (!hasEntry && !hasPackage) {\n problems.push(err(`runtimes.${runtime}`, \"Needs `entry` (a module path) or `package` (a dependency requirement).\"));\n }\n if (hasEntry && hasPackage) {\n problems.push(err(`runtimes.${runtime}`, \"Declare `entry` or `package`, not both — which one is authoritative is otherwise ambiguous.\"));\n }\n if (typeof s.engine !== \"string\" || s.engine.trim() === \"\") {\n problems.push(\n err(`runtimes.${runtime}.engine`, `Required — the semver range of the ${runtime} engine. Without it, this node installs against a ${runtime} engine too old to run it.`),\n );\n }\n }\n}\n\nfunction validateCapabilities(capabilities: unknown, problems: ManifestProblem[]): void {\n if (capabilities === undefined) return;\n\n if (typeof capabilities !== \"object\" || capabilities === null || Array.isArray(capabilities)) {\n problems.push(\n err(\"capabilities\", 'Must be an object of capability id to \"required\" | \"optional\" — a bare list cannot say whether the node works without one.'),\n );\n return;\n }\n\n for (const [id, requirement] of Object.entries(capabilities as Record<string, unknown>)) {\n if (!REQUIREMENTS.includes(requirement as string)) {\n problems.push(err(`capabilities.${id}`, `Must be \"required\" or \"optional\".`));\n }\n }\n}\n\n/**\n * Check a node against the runtimes a host executes on, and their versions.\n *\n * Two failures live here, and both are errors because the node genuinely\n * cannot run: a runtime the package does not implement at all, and a runtime\n * it implements against an engine newer than the host's.\n *\n * `engineVersions` is optional — pass what the host knows. An unchecked range\n * is reported as a warning rather than passed over silently, because \"we did\n * not check\" and \"it is fine\" must not look the same.\n */\nexport function checkRuntimeSupport(\n manifest: Pick<NodePackageManifest, \"kind\" | \"runtimes\">,\n hostRuntimes: readonly string[],\n engineVersions?: Readonly<Record<string, string>>,\n): ManifestProblem[] {\n const runtimes = manifest.runtimes ?? {};\n const provided = Object.keys(runtimes);\n const problems: ManifestProblem[] = [];\n\n const missing = hostRuntimes.filter((r) => !provided.includes(r));\n if (missing.length > 0) {\n problems.push(\n err(\n \"runtimes\",\n `${manifest.kind} implements ${provided.join(\", \") || \"no runtime\"} but this project executes on ${missing.join(\", \")}. The node would install, appear in the palette, and then fail to run.`,\n ),\n );\n }\n\n for (const runtime of hostRuntimes) {\n const spec = (runtimes as Record<string, NodeRuntimeSpec | undefined>)[runtime];\n if (!spec) continue;\n\n const hostVersion = engineVersions?.[runtime];\n if (hostVersion === undefined) {\n problems.push(\n warn(`runtimes.${runtime}.engine`, `${manifest.kind} needs ${runtime} engine ${spec.engine}; this host did not report its ${runtime} version, so the range was not checked.`),\n );\n continue;\n }\n\n if (!satisfiesRange(hostVersion, spec.engine)) {\n problems.push(\n err(`runtimes.${runtime}.engine`, `${manifest.kind} needs ${runtime} engine ${spec.engine}, but this host runs ${hostVersion}.`),\n );\n }\n }\n\n return problems;\n}\n\n/**\n * Minimal semver range check — `^x.y.z`, `~x.y.z`, `>=x.y.z`, `x.y.z`, `*`.\n *\n * Deliberately small: this runs in the CLI and in CI, and pulling a semver\n * library into the engine for one comparison is not worth the dependency. It\n * covers the forms a manifest actually uses; anything it cannot parse is\n * treated as unsatisfied rather than silently passed, so an unparseable range\n * fails loudly instead of waving a node through.\n */\nexport function satisfiesRange(version: string, range: string): boolean {\n const trimmed = range.trim();\n if (trimmed === \"*\" || trimmed === \"\") return true;\n\n const v = parseVersion(version);\n if (!v) return false;\n\n for (const clause of trimmed.split(\"||\").map((c) => c.trim())) {\n if (satisfiesClause(v, clause)) return true;\n }\n return false;\n}\n\nfunction satisfiesClause(v: [number, number, number], clause: string): boolean {\n const m = /^(\\^|~|>=|>|<=|<|=)?\\s*v?(\\d+)(?:\\.(\\d+))?(?:\\.(\\d+))?/.exec(clause);\n if (!m) return false;\n\n const op = m[1] ?? \"=\";\n const target: [number, number, number] = [Number(m[2]), Number(m[3] ?? 0), Number(m[4] ?? 0)];\n const cmp = compare(v, target);\n\n switch (op) {\n case \">=\":\n return cmp >= 0;\n case \">\":\n return cmp > 0;\n case \"<=\":\n return cmp <= 0;\n case \"<\":\n return cmp < 0;\n case \"=\":\n return cmp === 0;\n case \"~\":\n // Same major+minor, patch may rise.\n return cmp >= 0 && v[0] === target[0] && v[1] === target[1];\n case \"^\":\n // Below 1.0.0 a minor bump is breaking, so ^0.5 means 0.5.x — which is\n // the range every pre-1.0 package in this suite actually needs.\n if (target[0] === 0) return cmp >= 0 && v[0] === 0 && v[1] === target[1];\n return cmp >= 0 && v[0] === target[0];\n default:\n return false;\n }\n}\n\nfunction parseVersion(version: string): [number, number, number] | null {\n const m = /^v?(\\d+)\\.(\\d+)(?:\\.(\\d+))?/.exec(version.trim());\n return m ? [Number(m[1]), Number(m[2]), Number(m[3] ?? 0)] : null;\n}\n\nfunction compare(a: [number, number, number], b: [number, number, number]): number {\n for (let i = 0; i < 3; i++) {\n if (a[i] !== b[i]) return a[i] < b[i] ? -1 : 1;\n }\n return 0;\n}\n\n/**\n * Check that every capability a node needs is wired.\n *\n * A `required` capability that is missing is an ERROR — that is the whole point\n * of the requirement level. It is meant to be surfaced at author time, so an\n * editor can grey the node and name what the host never registered, rather than\n * the node installing cleanly and silently no-opping during a run.\n *\n * An `optional` one is a warning: the node still works, with less.\n */\nexport function checkCapabilities(\n manifest: Pick<NodePackageManifest, \"kind\" | \"capabilities\">,\n available: Readonly<Record<string, boolean>>,\n): ManifestProblem[] {\n const needed = manifest.capabilities ?? {};\n const problems: ManifestProblem[] = [];\n\n for (const [id, requirement] of Object.entries(needed)) {\n if (available[id] === true) continue;\n\n problems.push(\n requirement === \"required\"\n ? err(\"capabilities\", `${manifest.kind} requires the ${id} capability, which this host has not registered. The node cannot run here.`)\n : warn(\"capabilities\", `${manifest.kind} can use the ${id} capability, which this host has not registered. The node runs with reduced behaviour.`),\n );\n }\n\n return problems;\n}\n","/**\n * Golden fixtures — the parity guarantee, and a publishing requirement.\n *\n * Every runtime a node package claims runs these same JSON cases. That is what\n * makes \"this node behaves identically on TS and PHP\" verified rather than\n * asserted, and it is the one thing a loose collection of repos can never\n * offer.\n *\n * WHY IT IS REQUIRED RATHER THAN ENCOURAGED: cross-runtime drift does not fail\n * loudly. The 0.9.0 port-resolution divergence produced flows that routed\n * correctly in the editor and silently down one path on the server — status\n * `completed`, no error, no exception, nothing to alert on. A guarantee that\n * only holds when an author opts in is not a guarantee.\n *\n * WHAT A CASE ASSERTS, and why it matters more than it looks:\n *\n * A fixture asserts THE DOWNSTREAM NODE EXECUTED — not the port the node\n * recorded. The distinction is the whole lesson of that incident. A test\n * reading back `outputs.router.__port` stays green while no edge fires and\n * the run halts at the branch: the node faithfully recorded its choice, and\n * nothing downstream ever ran. So the runner wires a real probe to every\n * declared port and reports which probes actually executed.\n *\n * The format is plain JSON with no expressions or callbacks, so the PHP runner\n * executes byte-identical cases without an embedded JS engine.\n */\n\nimport { runFlow } from \"../runtime/run-flow\";\nimport { getNodeKind } from \"../registry/registry\";\nimport { resolveNodePorts } from \"../registry/ports\";\nimport { decodePause, type PauseAwaiting } from \"../registry/pause\";\nimport { registerLlmClient, registerWorkflowResolver } from \"../registry/capabilities\";\nimport type { FlowGraph, FlowNode, NodeExecutor, RunEvent } from \"../types\";\n\n/**\n * Deterministic stand-ins for host capabilities, declared as DATA.\n *\n * `llm_router` cannot reach a provider in CI, so a fixture has to supply a fake\n * `LlmClient`. If the stub format is not shared, each runtime stubs\n * differently and the fixtures stop being comparable — parity theatre. So the\n * fixture declares the stub's *behaviour* and both engines construct it\n * identically from the same JSON.\n */\nexport type FixtureStubs = {\n /** Canned `chooseRoute` answer for the LLM capability. */\n llm_client?: { chooseRoute: { port: string; reason?: string } };\n /** Canned workflow resolution, keyed by ref, for `subflow`. */\n workflow_resolver?: Record<string, FlowGraph | null>;\n};\n\n/** An event a case expects the run to have emitted. */\nexport type FixtureEventExpectation = {\n type: RunEvent[\"type\"];\n /** Emitting node, when it matters. */\n nodeId?: string;\n level?: \"info\" | \"warn\" | \"error\";\n /** Substring match against the message — full text is too brittle to pin. */\n messageContains?: string;\n};\n\n/** What a case expects to have happened. */\nexport type FixtureExpectation = {\n /**\n * Output ports whose downstream node must have executed — the assertion that\n * catches routing drift. Order-insensitive; the set must match exactly, so a\n * node that fires an extra port fails just as loudly as one that fires none.\n */\n ports?: string[];\n /** The value carried downstream, deep-compared when present. */\n value?: unknown;\n /** The run halted for a person. */\n pause?: { awaiting: PauseAwaiting; detail?: unknown };\n /** The run failed, and the message contains this substring. */\n error?: string;\n /**\n * Events the run must have emitted.\n *\n * Emitted events are BEHAVIOUR, not decoration. The hallucinated-port warning\n * is a contract an operator relies on to know a run took the fallback — if\n * one runtime stops emitting it, the guarantee degrades silently. Each entry\n * must match at least one emitted event.\n */\n events?: FixtureEventExpectation[];\n /**\n * The run resumed after a pause and reached this state.\n *\n * Pause/resume is the ONLY path that crosses a persistence boundary, which\n * makes it where two runtimes are most likely to drift — and it had no parity\n * coverage at all while `PausesForHuman` became public API.\n */\n afterResume?: {\n /** Delivered on the paused node's `values` input, as a host would on resume. */\n submit: unknown;\n ports?: string[];\n value?: unknown;\n error?: string;\n };\n};\n\nexport type FixtureCase = {\n /** Human-readable, and what a failure report names. */\n name: string;\n /** Config for the node under test — drives config-derived ports. */\n config?: Record<string, unknown>;\n /**\n * The node's resolved output ports, stated rather than derived.\n *\n * NOT a convenience. TS derives config-driven ports by running a JavaScript\n * function (`switch_case`'s cases, `llm_router`'s routes); PHP cannot, and\n * falls back to the kind's static declaration. Left there, the identical\n * fixture would build a DIFFERENT graph on each runtime — the fixtures would\n * silently stop comparing like with like, which is the exact failure they\n * exist to catch.\n *\n * So a case states its ports the same way an exported document does (see\n * 0.10.1, \"serialize resolved ports\"), and both runners honour it. Omit it\n * only for a node whose ports are static.\n */\n ports?: string[];\n /** Inputs delivered on the node's input ports. */\n inputs?: Record<string, unknown>;\n /**\n * Run this case against an ALIAS or an older config shape.\n *\n * What proves `aliases` and `configVersion` actually work rather than being\n * declared and rotting. A package that renames its kind should have a case\n * pinning that the old id still resolves.\n */\n legacyKind?: string;\n /** Deterministic capability stand-ins for this case. */\n stubs?: FixtureStubs;\n expect: FixtureExpectation;\n};\n\nexport type FixtureFile = {\n /** The kind under test. Must match the manifest's `kind`. */\n kind: string;\n cases: FixtureCase[];\n};\n\nexport type FixtureFailure = {\n case: string;\n message: string;\n};\n\nexport type FixtureRunResult = {\n ok: boolean;\n passed: number;\n failures: FixtureFailure[];\n};\n\nconst SUBJECT = \"subject\";\nconst TRIGGER = \"trigger\";\nconst probeId = (port: string) => `probe:${port}`;\n\n/**\n * Build the graph a case runs in: a trigger, the node under test, and one\n * probe per declared output port.\n *\n * The probes are the point. Reading the subject's return value would tell us\n * what it *recorded*; only a probe tells us what actually reached a downstream\n * node through a real edge.\n */\nfunction buildGraph(kindId: string, testCase: FixtureCase): { graph: FlowGraph; ports: string[] } {\n const subject: FlowNode = {\n id: SUBJECT,\n type: kindId,\n position: { x: 0, y: 100 },\n data: { kind: kindId, config: testCase.config ?? {} },\n } as unknown as FlowNode;\n\n const kind = getNodeKind(kindId) ?? undefined;\n // An explicitly declared port list wins, so both runtimes build the same\n // graph even where one can derive config-driven ports and the other cannot.\n const ports = testCase.ports ?? (resolveNodePorts(subject, kind).outputs ?? []).map((p) => p.id);\n const effective = ports.length ? ports : [\"out\"];\n\n const nodes: FlowNode[] = [\n { id: TRIGGER, type: \"manual_trigger\", position: { x: 0, y: 0 }, data: {} } as unknown as FlowNode,\n subject,\n ...effective.map(\n (port, i) =>\n ({\n id: probeId(port),\n type: \"@particle-academy/transform\",\n position: { x: i * 200, y: 200 },\n data: {},\n }) as unknown as FlowNode,\n ),\n ];\n\n const edges = [\n { id: `e:trigger`, source: TRIGGER, target: SUBJECT },\n ...effective.map((port) => ({\n id: `e:${port}`,\n source: SUBJECT,\n sourceHandle: port,\n target: probeId(port),\n })),\n ];\n\n return { graph: { nodes, edges } as FlowGraph, ports: effective };\n}\n\nfunction deepEqual(a: unknown, b: unknown): boolean {\n return JSON.stringify(a) === JSON.stringify(b);\n}\n\n/**\n * Install the case's capability stubs, returning a function that removes them.\n *\n * Constructed here from the fixture's JSON rather than supplied by the caller,\n * which is the whole point: both runtimes build the same stub from the same\n * data, so a fixture covering `llm_router` compares like with like instead of\n * comparing two different fakes.\n */\nfunction installStubs(stubs: FixtureStubs | undefined): () => void {\n if (!stubs) return () => {};\n\n const teardown: Array<() => void> = [];\n\n if (stubs.llm_client) {\n const answer = stubs.llm_client.chooseRoute;\n teardown.push(registerLlmClient({ chooseRoute: () => ({ ...answer }) }));\n }\n\n if (stubs.workflow_resolver) {\n const table = stubs.workflow_resolver;\n teardown.push(registerWorkflowResolver((ref) => table[ref] ?? null));\n }\n\n return () => teardown.forEach((fn) => fn());\n}\n\nfunction matchesEvent(event: RunEvent, want: FixtureEventExpectation): boolean {\n if (event.type !== want.type) return false;\n\n const e = event as Record<string, unknown>;\n if (want.nodeId !== undefined && e.nodeId !== want.nodeId) return false;\n if (want.level !== undefined && e.level !== want.level) return false;\n if (want.messageContains !== undefined && !String(e.message ?? \"\").includes(want.messageContains)) return false;\n\n return true;\n}\n\n/**\n * Re-run a paused case with a submission delivered, as a durable host would.\n *\n * The submission arrives on `values` because that is the input the builtin\n * human nodes read, and a third-party pausing node that wants fixture coverage\n * should follow the same convention rather than inventing its own.\n */\nasync function resume(\n kindId: string,\n testCase: FixtureCase,\n executor: NodeExecutor,\n pausedNodeId: string,\n submit: unknown,\n): Promise<{ ok: boolean; error?: string; fired: string[]; carried: unknown }> {\n const { graph } = buildGraph(kindId, testCase);\n const fired: string[] = [];\n let carried: unknown;\n\n const executors: Record<string, NodeExecutor> = {\n manual_trigger: () => testCase.inputs ?? {},\n \"@particle-academy/manual_trigger\": () => testCase.inputs ?? {},\n [kindId]: executor,\n };\n\n // The resumed node sees its submission, exactly as the durable runner\n // injects one.\n executors[pausedNodeId] = ((c: Parameters<NodeExecutor>[0]) =>\n executor({ ...c, inputs: { ...(c.inputs as object), values: submit } })) as NodeExecutor;\n\n for (const node of graph.nodes) {\n if (!node.id.startsWith(\"probe:\")) continue;\n const port = node.id.slice(\"probe:\".length);\n executors[node.id] = ((c: { inputs: Record<string, unknown> }) => {\n fired.push(port);\n carried = c.inputs?.in ?? c.inputs;\n return undefined;\n }) as unknown as NodeExecutor;\n }\n\n const releaseStubs = installStubs(testCase.stubs);\n const result = await runFlow(graph, executors, () => {});\n releaseStubs();\n\n return { ok: result.ok, error: result.error, fired, carried };\n}\n\n/**\n * Run one fixture file against a kind's executor.\n *\n * `executor` is the node's own; everything else in the graph is supplied here,\n * so a case exercises the node and nothing but the node.\n */\nexport async function runFixtures(\n file: FixtureFile,\n executor: NodeExecutor,\n): Promise<FixtureRunResult> {\n const failures: FixtureFailure[] = [];\n let passed = 0;\n\n for (const testCase of file.cases) {\n // A case may run against an alias or an older id, which is what proves the\n // package's `aliases` declaration is real rather than decorative.\n const kindId = testCase.legacyKind ?? file.kind;\n const { graph } = buildGraph(kindId, testCase);\n const fired: string[] = [];\n const events: RunEvent[] = [];\n let carried: unknown;\n\n const releaseStubs = installStubs(testCase.stubs);\n\n const executors: Record<string, NodeExecutor> = {\n manual_trigger: () => testCase.inputs ?? {},\n \"@particle-academy/manual_trigger\": () => testCase.inputs ?? {},\n [kindId]: executor,\n };\n\n // A probe per port, bound by NODE ID — `pickExecutor` checks that before\n // kind, so each probe reports which specific port reached it. Recording\n // here, rather than inspecting the subject's result, is what makes this\n // assert reachability instead of intent.\n for (const node of graph.nodes) {\n if (!node.id.startsWith(\"probe:\")) continue;\n const port = node.id.slice(\"probe:\".length);\n executors[node.id] = ((ctx: { inputs: Record<string, unknown> }) => {\n fired.push(port);\n carried = ctx.inputs?.in ?? ctx.inputs;\n return undefined;\n }) as unknown as NodeExecutor;\n }\n\n const result = await runFlow(graph, executors, (e) => events.push(e));\n releaseStubs();\n\n const fail = (message: string) => failures.push({ case: testCase.name, message });\n const expected = testCase.expect;\n let caseOk = true;\n\n if (expected.pause) {\n const paused = decodePause(result.error);\n if (!paused) {\n caseOk = false;\n fail(`expected a pause awaiting \"${expected.pause.awaiting}\", got ${result.ok ? \"a completed run\" : `error: ${result.error}`}`);\n } else {\n if (paused.awaiting !== expected.pause.awaiting) {\n caseOk = false;\n fail(`expected pause awaiting \"${expected.pause.awaiting}\", got \"${paused.awaiting}\"`);\n }\n if (\"detail\" in expected.pause && !deepEqual(paused.detail, expected.pause.detail)) {\n caseOk = false;\n fail(`pause detail mismatch: expected ${JSON.stringify(expected.pause.detail)}, got ${JSON.stringify(paused.detail)}`);\n }\n }\n } else if (expected.error !== undefined) {\n if (result.ok) {\n caseOk = false;\n fail(`expected an error containing \"${expected.error}\", but the run succeeded`);\n } else if (!String(result.error ?? \"\").includes(expected.error)) {\n caseOk = false;\n fail(`expected an error containing \"${expected.error}\", got \"${result.error}\"`);\n }\n } else {\n if (expected.ports !== undefined) {\n const got = [...fired].sort();\n const want = [...expected.ports].sort();\n if (!deepEqual(got, want)) {\n caseOk = false;\n // Name the failure in terms of reachability, because that is what\n // the assertion means and what a reader needs to act on.\n fail(\n `expected these ports to reach a downstream node: [${want.join(\", \")}], but [${got.join(\", \")}] did` +\n (result.ok ? \"\" : ` (run error: ${result.error})`),\n );\n }\n }\n if (\"value\" in expected && !deepEqual(carried, expected.value)) {\n caseOk = false;\n fail(`expected the value carried downstream to be ${JSON.stringify(expected.value)}, got ${JSON.stringify(carried)}`);\n }\n }\n\n // Emitted events are behaviour, not decoration — an operator relies on the\n // hallucinated-port warning to know a run took the fallback.\n for (const want of expected.events ?? []) {\n if (!events.some((e) => matchesEvent(e, want))) {\n caseOk = false;\n fail(`expected an emitted event matching ${JSON.stringify(want)}, but none of the ${events.length} emitted events did`);\n }\n }\n\n // Resume: the only path crossing a persistence boundary, and so the one\n // most likely to drift between runtimes.\n if (expected.afterResume) {\n const paused = decodePause(result.error);\n if (!paused) {\n caseOk = false;\n fail(\"expected the run to pause before resuming, but it never paused\");\n } else {\n const resumed = await resume(kindId, testCase, executor, paused.nodeId, expected.afterResume.submit);\n const want = expected.afterResume;\n\n if (want.error !== undefined) {\n if (resumed.ok || !String(resumed.error ?? \"\").includes(want.error)) {\n caseOk = false;\n fail(`after resume: expected an error containing \"${want.error}\", got ${resumed.ok ? \"success\" : `\"${resumed.error}\"`}`);\n }\n }\n if (want.ports !== undefined) {\n const got = [...resumed.fired].sort();\n const wanted = [...want.ports].sort();\n if (!deepEqual(got, wanted)) {\n caseOk = false;\n fail(`after resume: expected ports [${wanted.join(\", \")}] to reach a downstream node, but [${got.join(\", \")}] did`);\n }\n }\n if (\"value\" in want && !deepEqual(resumed.carried, want.value)) {\n caseOk = false;\n fail(`after resume: expected the value carried downstream to be ${JSON.stringify(want.value)}, got ${JSON.stringify(resumed.carried)}`);\n }\n }\n }\n\n if (caseOk) passed += 1;\n }\n\n return { ok: failures.length === 0, passed, failures };\n}\n\n/**\n * Validate a fixture file's shape before running it.\n *\n * A package that publishes an empty or malformed fixture file has satisfied the\n * letter of the requirement and none of its purpose, so this is checked at\n * publish rather than trusted.\n */\nexport function validateFixtureFile(input: unknown, expectedKind?: string): string[] {\n const problems: string[] = [];\n\n if (typeof input !== \"object\" || input === null || Array.isArray(input)) {\n return [\"Fixture file must be a JSON object.\"];\n }\n\n const f = input as Record<string, unknown>;\n\n if (typeof f.kind !== \"string\" || f.kind.trim() === \"\") {\n problems.push(\"`kind` is required — the kind these cases exercise.\");\n } else if (expectedKind && f.kind !== expectedKind) {\n problems.push(`\\`kind\\` is \"${f.kind}\" but the manifest declares \"${expectedKind}\".`);\n }\n\n if (!Array.isArray(f.cases) || f.cases.length === 0) {\n problems.push(\"`cases` must contain at least one case — an empty fixture file proves nothing.\");\n return problems;\n }\n\n // At least one case must exercise a failure.\n //\n // \"Does it fail the same way\" deserves equal weight to \"does it succeed the\n // same way\": the incident that motivated this whole mechanism was a FAILURE\n // that reported `completed` with no error. A suite that only covers happy\n // paths cannot catch a runtime that fails differently — or does not fail\n // at all.\n const coversFailure = f.cases.some((c: unknown) => {\n const expect = (c as { expect?: Record<string, unknown> })?.expect;\n return Boolean(expect && (\"error\" in expect || \"pause\" in expect));\n });\n if (!coversFailure) {\n problems.push(\n \"At least one case must assert a failure (`expect.error`) or a pause (`expect.pause`). Every case here covers a success path, and the divergence this format exists to catch reported success while doing nothing.\",\n );\n }\n\n f.cases.forEach((c: unknown, i: number) => {\n const label = `cases[${i}]`;\n if (typeof c !== \"object\" || c === null) {\n problems.push(`${label} must be an object.`);\n return;\n }\n const testCase = c as Record<string, unknown>;\n if (typeof testCase.name !== \"string\" || testCase.name.trim() === \"\") {\n problems.push(`${label}.name is required — a failure report names it.`);\n }\n if (typeof testCase.expect !== \"object\" || testCase.expect === null) {\n problems.push(`${label}.expect is required — a case that asserts nothing passes vacuously.`);\n return;\n }\n const expect = testCase.expect as Record<string, unknown>;\n if (\n expect.ports === undefined &&\n expect.value === undefined &&\n expect.pause === undefined &&\n expect.error === undefined\n ) {\n problems.push(`${label}.expect must assert at least one of: ports, value, pause, error.`);\n }\n if (expect.ports !== undefined && (!Array.isArray(expect.ports) || expect.ports.some((p) => typeof p !== \"string\"))) {\n problems.push(`${label}.expect.ports must be an array of port id strings.`);\n }\n });\n\n return problems;\n}\n"]}
|
package/dist/index.cjs
CHANGED
|
@@ -14671,6 +14671,51 @@ function NodePort({ side, type, id: id2, style: style2, title, className }) {
|
|
|
14671
14671
|
);
|
|
14672
14672
|
}
|
|
14673
14673
|
|
|
14674
|
+
// src/runtime/run-cohort.ts
|
|
14675
|
+
async function runCohort(flows, executors, onEvent = () => {
|
|
14676
|
+
}, options = {}) {
|
|
14677
|
+
const { policy = "serial-guarded", guard, reason, ...runOptions } = options;
|
|
14678
|
+
if (policy === "parallel") {
|
|
14679
|
+
return Promise.all(
|
|
14680
|
+
flows.map(async (flow, index2) => ({
|
|
14681
|
+
...await runFlow(flow, executors, (e) => onEvent(e, index2), runOptions),
|
|
14682
|
+
index: index2
|
|
14683
|
+
}))
|
|
14684
|
+
);
|
|
14685
|
+
}
|
|
14686
|
+
const results = [];
|
|
14687
|
+
for (const [index2, flow] of flows.entries()) {
|
|
14688
|
+
if (policy === "serial-guarded" && guard) {
|
|
14689
|
+
const why = () => reason?.(flow, index2) ?? "trigger precondition no longer holds";
|
|
14690
|
+
let passes;
|
|
14691
|
+
try {
|
|
14692
|
+
passes = await guard(flow, index2);
|
|
14693
|
+
} catch (error) {
|
|
14694
|
+
results.push({
|
|
14695
|
+
ok: false,
|
|
14696
|
+
outputs: {},
|
|
14697
|
+
index: index2,
|
|
14698
|
+
skipped: true,
|
|
14699
|
+
skippedReason: `guard could not be evaluated: ${errorText(error)}`
|
|
14700
|
+
});
|
|
14701
|
+
continue;
|
|
14702
|
+
}
|
|
14703
|
+
if (!passes) {
|
|
14704
|
+
results.push({ ok: false, outputs: {}, index: index2, skipped: true, skippedReason: why() });
|
|
14705
|
+
continue;
|
|
14706
|
+
}
|
|
14707
|
+
}
|
|
14708
|
+
results.push({
|
|
14709
|
+
...await runFlow(flow, executors, (e) => onEvent(e, index2), runOptions),
|
|
14710
|
+
index: index2
|
|
14711
|
+
});
|
|
14712
|
+
}
|
|
14713
|
+
return results;
|
|
14714
|
+
}
|
|
14715
|
+
function errorText(error) {
|
|
14716
|
+
return error instanceof Error ? error.message : String(error);
|
|
14717
|
+
}
|
|
14718
|
+
|
|
14674
14719
|
// src/index.ts
|
|
14675
14720
|
registerBuiltinKinds();
|
|
14676
14721
|
/*! Bundled license information:
|
|
@@ -14736,6 +14781,7 @@ exports.registerNodeKind = registerNodeKind;
|
|
|
14736
14781
|
exports.registerRichInputAdapter = registerRichInputAdapter;
|
|
14737
14782
|
exports.resolveNodePorts = resolveNodePorts;
|
|
14738
14783
|
exports.resolvePortSpec = resolvePortSpec;
|
|
14784
|
+
exports.runCohort = runCohort;
|
|
14739
14785
|
exports.runFlow = runFlow;
|
|
14740
14786
|
exports.useFlowEditor = useFlowEditor;
|
|
14741
14787
|
exports.useFlowEditorOptional = useFlowEditorOptional;
|