@particle-academy/fancy-flow 0.59.0 → 0.63.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 (63) hide show
  1. package/dist/{HumanPrompt-Bw09OyS3.d.ts → HumanPrompt-BKThiyjB.d.ts} +1 -1
  2. package/dist/{HumanPrompt-DV5-xnDa.d.cts → HumanPrompt-Bpp3JiVH.d.cts} +1 -1
  3. package/dist/{chunk-M7M6GLFV.js → chunk-5H54OTKT.js} +3 -3
  4. package/dist/{chunk-M7M6GLFV.js.map → chunk-5H54OTKT.js.map} +1 -1
  5. package/dist/{chunk-MX4SJDNI.js → chunk-EO6444T2.js} +4 -4
  6. package/dist/{chunk-MX4SJDNI.js.map → chunk-EO6444T2.js.map} +1 -1
  7. package/dist/{chunk-HBE4LVPX.js → chunk-JF6WCRBU.js} +9 -7
  8. package/dist/chunk-JF6WCRBU.js.map +1 -0
  9. package/dist/{chunk-LGLOBK6Q.js → chunk-MBVX4ZRB.js} +3 -3
  10. package/dist/{chunk-LGLOBK6Q.js.map → chunk-MBVX4ZRB.js.map} +1 -1
  11. package/dist/{chunk-FGYG5JVW.js → chunk-MEIDPBKE.js} +3 -3
  12. package/dist/{chunk-FGYG5JVW.js.map → chunk-MEIDPBKE.js.map} +1 -1
  13. package/dist/{chunk-A3TLZS5B.js → chunk-RIAFHQT5.js} +3 -3
  14. package/dist/{chunk-A3TLZS5B.js.map → chunk-RIAFHQT5.js.map} +1 -1
  15. package/dist/{chunk-BHM5HGXH.js → chunk-UM4C46AF.js} +38 -14
  16. package/dist/chunk-UM4C46AF.js.map +1 -0
  17. package/dist/connectors.d.cts +1 -1
  18. package/dist/connectors.d.ts +1 -1
  19. package/dist/durable.cjs +7 -5
  20. package/dist/durable.cjs.map +1 -1
  21. package/dist/durable.js +2 -2
  22. package/dist/engine.cjs +138 -29
  23. package/dist/engine.cjs.map +1 -1
  24. package/dist/engine.d.cts +3 -2
  25. package/dist/engine.d.ts +3 -2
  26. package/dist/engine.js +6 -5
  27. package/dist/engine.js.map +1 -1
  28. package/dist/expr-BfXDrs4H.d.cts +149 -0
  29. package/dist/expr-BfXDrs4H.d.ts +149 -0
  30. package/dist/fields/react-fancy.d.cts +2 -2
  31. package/dist/fields/react-fancy.d.ts +2 -2
  32. package/dist/index.cjs +44 -16
  33. package/dist/index.cjs.map +1 -1
  34. package/dist/index.d.cts +7 -84
  35. package/dist/index.d.ts +7 -84
  36. package/dist/index.js +12 -12
  37. package/dist/index.js.map +1 -1
  38. package/dist/registry/index.d.cts +3 -3
  39. package/dist/registry/index.d.ts +3 -3
  40. package/dist/{registry-1qhmRtvC.d.cts → registry-CntAdUcY.d.cts} +1 -1
  41. package/dist/{registry-D2qocEsY.d.ts → registry-DYoV-MQi.d.ts} +1 -1
  42. package/dist/registry.cjs +7 -5
  43. package/dist/registry.cjs.map +1 -1
  44. package/dist/registry.js +2 -2
  45. package/dist/runtime.cjs +7 -5
  46. package/dist/runtime.cjs.map +1 -1
  47. package/dist/runtime.js +3 -3
  48. package/dist/schema.cjs +7 -5
  49. package/dist/schema.cjs.map +1 -1
  50. package/dist/schema.js +2 -2
  51. package/dist/screens.cjs +7 -5
  52. package/dist/screens.cjs.map +1 -1
  53. package/dist/screens.js +4 -4
  54. package/dist/{types-CLSUZW8c.d.ts → types-Ckhz-YwC.d.ts} +7 -2
  55. package/dist/{types-BLVpNNLN.d.cts → types-D71SKA5A.d.cts} +7 -2
  56. package/dist/ux.cjs +7 -5
  57. package/dist/ux.cjs.map +1 -1
  58. package/dist/ux.d.cts +1 -1
  59. package/dist/ux.d.ts +1 -1
  60. package/dist/ux.js +1 -1
  61. package/package.json +2 -2
  62. package/dist/chunk-BHM5HGXH.js.map +0 -1
  63. package/dist/chunk-HBE4LVPX.js.map +0 -1
package/dist/engine.d.cts CHANGED
@@ -2,8 +2,9 @@ export { R as RunOptions, a as RunResult, r as runFlow } from './run-flow-2XsHBw
2
2
  import { F as FlowGraph, R as RunEvent, N as NodeExecutor } from './types-JFYjPJAG.cjs';
3
3
  export { A as ActionNodeData, B as BaseNodeData, D as DecisionNodeData, E as ExecutorRegistry, d as FlowEdge, a as FlowNode, e as FlowNodeData, f as FlowNodeKind, g as NodeRunStatus, h as NoteNodeData, O as OutputNodeData, P as PortDescriptor, b as RunIdentity, c as RunIdentityJson, S as SubgraphNodeData, T as TriggerNodeData, i as escapeSegment } from './types-JFYjPJAG.cjs';
4
4
  export { C as CohortGuard, a as CohortOptions, b as CohortPolicy, c as CohortResult, r as runCohort } from './run-cohort-CBRAUj-z.cjs';
5
- export { d as defaultConfigFor, g as getNodeKind, k as kindIds, l as listNodeKinds, r as registerNodeKind, a as resolveKindId, v as validateConfig } from './registry-1qhmRtvC.cjs';
6
- export { b as CapabilityRequirement, C as ConfigField, E as EmitsRelation, M as ManifestProblem, c as ManifestValidation, d as NODE_MANIFEST_SCHEMA_VERSION, a as NodeCategory, N as NodeKindDefinition, e as NodePackageManifest, f as NodeRuntimeId, g as NodeRuntimeSpec, O as OutputField, h as OutputShape, P as PortSpec, S as SideEffects, i as checkCapabilities, j as checkRuntimeSupport, s as satisfiesRange, v as validateNodeManifest } from './types-BLVpNNLN.cjs';
5
+ export { d as defaultConfigFor, g as getNodeKind, k as kindIds, l as listNodeKinds, r as registerNodeKind, a as resolveKindId, v as validateConfig } from './registry-CntAdUcY.cjs';
6
+ export { b as CapabilityRequirement, C as ConfigField, E as EmitsRelation, M as ManifestProblem, c as ManifestValidation, d as NODE_MANIFEST_SCHEMA_VERSION, a as NodeCategory, N as NodeKindDefinition, e as NodePackageManifest, f as NodeRuntimeId, g as NodeRuntimeSpec, O as OutputField, h as OutputShape, P as PortSpec, S as SideEffects, i as checkCapabilities, j as checkRuntimeSupport, s as satisfiesRange, v as validateNodeManifest } from './types-D71SKA5A.cjs';
7
+ export { E as EvaluateOptions, a as ExprContext, b as ExprValue, R as Resolution, U as UnresolvedPathError, c as UnresolvedPolicy, e as evaluateConfig, d as evaluateExpression, r as resolvePath, t as text, f as truthy, g as tryResolvePath } from './expr-BfXDrs4H.cjs';
7
8
  import { P as PauseAwaiting } from './pause-9iT4tCEV.cjs';
8
9
  export { L as LEGACY_PAUSE_PREFIXES, a as PAUSE_PREFIX, b as PauseSignal, d as decodePause, e as encodePause, i as isPause, p as pauseForHuman } from './pause-9iT4tCEV.cjs';
9
10
  import { W as WorkflowResolver } from './capabilities-BYa5p5jw.cjs';
package/dist/engine.d.ts CHANGED
@@ -2,8 +2,9 @@ export { R as RunOptions, a as RunResult, r as runFlow } from './run-flow-D7AOCc
2
2
  import { F as FlowGraph, R as RunEvent, N as NodeExecutor } from './types-JFYjPJAG.js';
3
3
  export { A as ActionNodeData, B as BaseNodeData, D as DecisionNodeData, E as ExecutorRegistry, d as FlowEdge, a as FlowNode, e as FlowNodeData, f as FlowNodeKind, g as NodeRunStatus, h as NoteNodeData, O as OutputNodeData, P as PortDescriptor, b as RunIdentity, c as RunIdentityJson, S as SubgraphNodeData, T as TriggerNodeData, i as escapeSegment } from './types-JFYjPJAG.js';
4
4
  export { C as CohortGuard, a as CohortOptions, b as CohortPolicy, c as CohortResult, r as runCohort } from './run-cohort-C1nRh_mi.js';
5
- export { d as defaultConfigFor, g as getNodeKind, k as kindIds, l as listNodeKinds, r as registerNodeKind, a as resolveKindId, v as validateConfig } from './registry-D2qocEsY.js';
6
- export { b as CapabilityRequirement, C as ConfigField, E as EmitsRelation, M as ManifestProblem, c as ManifestValidation, d as NODE_MANIFEST_SCHEMA_VERSION, a as NodeCategory, N as NodeKindDefinition, e as NodePackageManifest, f as NodeRuntimeId, g as NodeRuntimeSpec, O as OutputField, h as OutputShape, P as PortSpec, S as SideEffects, i as checkCapabilities, j as checkRuntimeSupport, s as satisfiesRange, v as validateNodeManifest } from './types-CLSUZW8c.js';
5
+ export { d as defaultConfigFor, g as getNodeKind, k as kindIds, l as listNodeKinds, r as registerNodeKind, a as resolveKindId, v as validateConfig } from './registry-DYoV-MQi.js';
6
+ export { b as CapabilityRequirement, C as ConfigField, E as EmitsRelation, M as ManifestProblem, c as ManifestValidation, d as NODE_MANIFEST_SCHEMA_VERSION, a as NodeCategory, N as NodeKindDefinition, e as NodePackageManifest, f as NodeRuntimeId, g as NodeRuntimeSpec, O as OutputField, h as OutputShape, P as PortSpec, S as SideEffects, i as checkCapabilities, j as checkRuntimeSupport, s as satisfiesRange, v as validateNodeManifest } from './types-Ckhz-YwC.js';
7
+ export { E as EvaluateOptions, a as ExprContext, b as ExprValue, R as Resolution, U as UnresolvedPathError, c as UnresolvedPolicy, e as evaluateConfig, d as evaluateExpression, r as resolvePath, t as text, f as truthy, g as tryResolvePath } from './expr-BfXDrs4H.js';
7
8
  import { P as PauseAwaiting } from './pause-9iT4tCEV.js';
8
9
  export { L as LEGACY_PAUSE_PREFIXES, a as PAUSE_PREFIX, b as PauseSignal, d as decodePause, e as encodePause, i as isPause, p as pauseForHuman } from './pause-9iT4tCEV.js';
9
10
  import { W as WorkflowResolver } from './capabilities-COOXRiNL.js';
package/dist/engine.js CHANGED
@@ -1,8 +1,9 @@
1
- export { runCohort } from './chunk-A3TLZS5B.js';
1
+ export { runCohort } from './chunk-RIAFHQT5.js';
2
+ export { UnresolvedPathError, evaluateConfig, evaluateExpression, resolvePath, text, truthy, tryResolvePath } from './chunk-UM4C46AF.js';
2
3
  import { decodePause } from './chunk-UEOE6B52.js';
3
4
  export { LEGACY_PAUSE_PREFIXES, PAUSE_PREFIX, decodePause, encodePause, isPause, pauseForHuman } from './chunk-UEOE6B52.js';
4
- import { runFlow, getNodeKind, resolveNodePorts } from './chunk-HBE4LVPX.js';
5
- export { RunIdentity, defaultConfigFor, escapeSegment, getNodeKind, kindIds, listNodeKinds, registerNodeKind, resolveKindId, runFlow, validateConfig } from './chunk-HBE4LVPX.js';
5
+ import { runFlow, getNodeKind, resolveNodePorts } from './chunk-JF6WCRBU.js';
6
+ export { RunIdentity, defaultConfigFor, escapeSegment, getNodeKind, kindIds, listNodeKinds, registerNodeKind, resolveKindId, runFlow, validateConfig } from './chunk-JF6WCRBU.js';
6
7
  import './chunk-F5RPRB7A.js';
7
8
  import { isResolutionFailure, registerLlmClient, registerWorkflowResolver } from './chunk-USL4FMFU.js';
8
9
 
@@ -377,7 +378,7 @@ async function resume(kindId, testCase, executor, pausedNodeId, submit) {
377
378
  const port = node.id.slice("probe:".length);
378
379
  executors[node.id] = ((c) => {
379
380
  fired.push(port);
380
- carried = c.inputs?.in ?? c.inputs;
381
+ carried = c.inputs && Object.prototype.hasOwnProperty.call(c.inputs, "in") ? c.inputs.in : c.inputs;
381
382
  return void 0;
382
383
  });
383
384
  }
@@ -407,7 +408,7 @@ async function runFixtures(file, executor) {
407
408
  const port = node.id.slice("probe:".length);
408
409
  executors[node.id] = ((ctx) => {
409
410
  fired.push(port);
410
- carried = ctx.inputs?.in ?? ctx.inputs;
411
+ carried = ctx.inputs && Object.prototype.hasOwnProperty.call(ctx.inputs, "in") ? ctx.inputs.in : ctx.inputs;
411
412
  return void 0;
412
413
  });
413
414
  }
@@ -1 +1 @@
1
- {"version":3,"sources":["../src/marketplace/manifest.ts","../src/marketplace/fixtures.ts","../src/analysis/subflow-cycle.ts"],"names":["version","key"],"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 * `files` are source directories, not a dependency: a node is **vendored**, so\n * `fancy-cli add node` copies them into the project the way it copies a\n * component's source. One node, one source, readable and editable in the app\n * rather than hidden in `node_modules` or `vendor`.\n *\n * This spec covers a runtime's BACKEND only. The surface lives in the\n * manifest's `ui`, because the editor is React on every host — a Laravel\n * project needs the React kind and does not need the TypeScript executor.\n */\nexport type NodeRuntimeSpec = {\n /** This backend's source directories, relative to the node. */\n files: 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\n/**\n * A Fancy suite package this node's source imports.\n *\n * Separate from a plain npm dependency because the suite is polyglot and\n * vendorable: the same capability ships as an npm package, a Composer package,\n * or source you copy in, and which of those a consumer wants depends on the\n * host — so the node names the *package*, and the CLI offers the routes that\n * exist. A bare `dependencies: [\"@particle-academy/fancy-screens\"]` can only\n * ever offer `npm install`, which is the wrong answer in a Laravel app whose\n * editor is vendored.\n *\n * ## No versions, deliberately\n *\n * Nothing here carries a range, and the validator rejects one. A pinned\n * marketplace node freezes a consumer on an old surface: the suite ships\n * additively and often, and a node that pinned `^0.4` at authoring time would\n * be holding a project back a year later for a constraint nobody revisits.\n * Compatibility is expressed where it can actually be checked — `runtimes[].engine`\n * against the *engine*, which is the contract a node really depends on.\n */\nexport type FancyDependency = {\n /** Suite slug — what `/packages/<slug>` documents. */\n package: string;\n /** npm name, when the suite ships one. */\n npm?: string;\n /** Composer name, when the suite ships one. */\n composer?: string;\n /**\n * Why the node needs it, in a few words.\n *\n * Printed at install. Without it the CLI can only present a bare name and a\n * command, which reads as an unexplained demand for a second package.\n */\n reason?: string;\n /** Whether the node fails without it, or merely does less. Defaults to required. */\n requirement?: CapabilityRequirement;\n};\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 /**\n * The node's SURFACE — its React kind — as source directories.\n *\n * Copied whichever backend the consumer picks, because the editor is React on\n * every host. Kept out of `runtimes` deliberately: fold the two together and\n * a PHP project either loses its palette entry or gains a TypeScript executor\n * it will never run.\n */\n ui?: string[];\n /** Per-runtime backend source 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 /** Fancy suite packages this node's source imports. See {@link FancyDependency}. */\n fancyDependencies?: FancyDependency[];\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 validateFancyDependencies(m.fancyDependencies, 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 { files, 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 { files, engine }.\"));\n continue;\n }\n\n const s = spec as Record<string, unknown>;\n const files = Array.isArray(s.files) ? s.files : null;\n\n if (!files || files.length === 0 || files.some((f) => typeof f !== \"string\" || f.trim() === \"\")) {\n problems.push(\n err(\n `runtimes.${runtime}`,\n \"Needs `files` — the node source directories this runtime's backend lives in, relative to the node.\",\n ),\n );\n }\n if (s.entry !== undefined || s.package !== undefined) {\n // Nodes are VENDORED, not installed: the CLI copies a node's source into\n // the project the way it copies a component's. `entry` / `package`\n // described an npm/Composer install that no longer happens, and leaving\n // them readable would let a manifest claim an install path nothing honours.\n problems.push(\n err(\n `runtimes.${runtime}`,\n \"`entry` / `package` are gone — nodes are copied into a project, not installed from a registry. Declare `files` instead.\",\n ),\n );\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\n/**\n * Anything that looks like a version range, in a field that must not carry one.\n *\n * Covers the two shapes an author actually writes: a range appended to the name\n * (`@particle-academy/fancy-screens@^0.4`, `fancy-screens:^1`) and a bare\n * `version` key alongside it.\n *\n * ## Why the operators are `(?:[\\^~>=<]+\\s*)?` and not `[\\^~>=<]*\\s*`\n *\n * The obvious spelling — `(?:@|:)\\s*[\\^~>=<]*\\s*\\d` — is a ReDoS\n * (CWE-1333, CodeQL js/polynomial-redos). Because the operator class can match\n * nothing, a run of n spaces can be divided between the two `\\s*` in n+1 ways,\n * and a value with no trailing digit makes the engine try all of them: cost is\n * O(n²), and `npm: \"@\" + \" \".repeat(32000)` measured ~730ms on one core. A\n * manifest is third-party data — read off a marketplace package or a registry\n * response, by a validator whose whole job is to be pointed at input nobody\n * here wrote — so that is reachable, not hypothetical.\n *\n * Reaching the second whitespace run only *through* a non-empty operator run\n * removes the ambiguity while matching exactly the same strings: with no\n * operators the group is skipped and a single `\\s*` consumes the gap; with\n * operators, each `\\s*` owns one distinct side of them. Equivalence was checked\n * exhaustively over every string up to length 4 in the relevant alphabet plus\n * 400k longer random ones — zero divergence. See the ReDoS test in\n * `tests/marketplace.test.ts`.\n */\nconst VERSIONED = /(?:@|:)\\s*(?:[\\^~>=<]+\\s*)?\\d/;\n\nfunction validateFancyDependencies(deps: unknown, problems: ManifestProblem[]): void {\n if (deps === undefined) return;\n\n if (!Array.isArray(deps)) {\n problems.push(err(\"fancyDependencies\", \"Must be an array of { package, npm?, composer?, reason?, requirement? }.\"));\n return;\n }\n\n deps.forEach((entry, index) => {\n const at = `fancyDependencies[${index}]`;\n\n if (typeof entry !== \"object\" || entry === null || Array.isArray(entry)) {\n problems.push(err(at, \"Must be an object naming a suite package, not a bare string — a slug alone cannot say whether the package exists on npm, on Composer, or both.\"));\n return;\n }\n\n const dep = entry as Record<string, unknown>;\n\n if (typeof dep.package !== \"string\" || dep.package.trim() === \"\") {\n problems.push(err(`${at}.package`, \"Required — the suite slug, e.g. `fancy-screens`.\"));\n }\n\n if (dep.npm === undefined && dep.composer === undefined) {\n problems.push(\n err(at, \"Needs at least one of `npm` or `composer`. Naming neither leaves the CLI with a package it cannot offer any way to install.\"),\n );\n }\n\n // Versions are rejected rather than ignored. A node that pins holds a\n // consumer on an old surface for a constraint nobody revisits, and the\n // engine range in `runtimes` is where compatibility can actually be checked.\n for (const field of [\"package\", \"npm\", \"composer\"] as const) {\n const value = dep[field];\n if (typeof value === \"string\" && VERSIONED.test(value.replace(/^@[a-z0-9._-]+\\//i, \"\"))) {\n problems.push(\n err(\n `${at}.${field}`,\n \"Must not carry a version range — the suite ships additively and a pin here freezes a consumer on an old surface. Express engine compatibility in `runtimes[].engine` instead.\",\n ),\n );\n }\n }\n\n if (dep.version !== undefined) {\n problems.push(err(`${at}.version`, \"Not a field. Fancy dependencies are unversioned — see `runtimes[].engine` for the constraint that is actually checked.\"));\n }\n\n if (dep.requirement !== undefined && !REQUIREMENTS.includes(dep.requirement as string)) {\n problems.push(err(`${at}.requirement`, `Must be \"required\" or \"optional\".`));\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\n/**\n * Structural comparison, insensitive to key ORDER.\n *\n * This was `JSON.stringify(a) === JSON.stringify(b)`, which compares key order\n * as if it were meaning. A node spreading its input before its own fields\n * (`{ ...incoming, applied: true }`) produced a different key order than the\n * fixture author wrote, and the case failed with a message showing two\n * identical-looking objects — the worst kind of failure to debug, and one that\n * says nothing about the node.\n *\n * `undefined`-valued keys are still ignored, matching what JSON did and what a\n * fixture file (which cannot express `undefined`) can round-trip.\n */\nfunction deepEqual(a: unknown, b: unknown): boolean {\n if (Object.is(a, b)) return true;\n if (a === null || b === null || typeof a !== \"object\" || typeof b !== \"object\") return false;\n\n if (Array.isArray(a) || Array.isArray(b)) {\n if (!Array.isArray(a) || !Array.isArray(b) || a.length !== b.length) return false;\n\n return a.every((item, index) => deepEqual(item, b[index]));\n }\n\n const left = definedEntries(a as Record<string, unknown>);\n const right = definedEntries(b as Record<string, unknown>);\n const keys = Object.keys(left);\n if (keys.length !== Object.keys(right).length) return false;\n\n return keys.every(\n (key) => Object.prototype.hasOwnProperty.call(right, key) && deepEqual(left[key], right[key]),\n );\n}\n\nfunction definedEntries(value: Record<string, unknown>): Record<string, unknown> {\n const out: Record<string, unknown> = {};\n for (const [key, item] of Object.entries(value)) {\n if (item !== undefined) out[key] = item;\n }\n\n return out;\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","import type { FlowGraph } from \"../types\";\nimport { isResolutionFailure, type WorkflowResolver } from \"../registry/capabilities\";\n\n/**\n * Find a `subflow` loop BEFORE the graph is saved, rather than after a run has\n * already done the work N times.\n *\n * ## Why this is not the depth cap\n *\n * `subflowExecutor` caps recursion depth at runtime, which is the correct\n * backstop and stays — it is the only thing that catches a loop created from the\n * other end, when someone edits B after A was saved. But by the time it fires,\n * every node ABOVE the subflow has run on each pass, side effects included, and\n * the author is handed an opaque failure from deep inside a run while the graph\n * that caused it is still saved and still runnable.\n *\n * The editor is where an author would most naturally be stopped, which is why\n * this lives here and not only in the PHP runtime.\n *\n * ## Why it needs a resolver\n *\n * Schema validation checks one graph in isolation and cannot see A → B → A,\n * because each graph is individually valid. Only the resolver knows what a ref\n * points at, and only the host has one.\n *\n * The chain matters more than the boolean: \"this loops\" is much less useful than\n * naming the step that closes it.\n *\n * The TS twin of `FancyFlow\\Analysis\\SubflowCycle`.\n *\n * ```ts\n * const loop = await findSubflowCycle(graph, resolver, \"Daily Planner\");\n * // [\"Daily Planner\", \"Digest\", \"Daily Planner\"] — or [] when safe\n * ```\n */\nexport async function findSubflowCycle(\n graph: FlowGraph,\n resolver: WorkflowResolver,\n rootRef?: string,\n): Promise<string[]> {\n return walk(\n graph,\n resolver,\n rootRef === undefined ? [] : [rootRef],\n rootRef === undefined ? new Set<string>() : new Set([key(rootRef, undefined)]),\n );\n}\n\nasync function walk(\n graph: FlowGraph,\n resolver: WorkflowResolver,\n path: string[],\n onPath: Set<string>,\n): Promise<string[]> {\n for (const [ref, version] of references(graph?.nodes ?? [])) {\n const k = key(ref, version);\n\n // Membership is tracked PER PATH, not globally: a diamond (two branches\n // that both call the same child) revisits a ref without looping, and\n // treating that as a cycle would refuse a perfectly good graph.\n if (onPath.has(k)) return [...path, ref];\n\n const resolved = await resolver(ref, version);\n\n // A ref that does not resolve is a different problem, reported elsewhere.\n // Refusing the save for it would block authoring a parent before its child\n // exists.\n if (!resolved || isResolutionFailure(resolved)) continue;\n\n const found = await walk(\n resolved as FlowGraph,\n resolver,\n [...path, ref],\n new Set(onPath).add(k),\n );\n if (found.length) return found;\n }\n\n return [];\n}\n\n/**\n * Every subflow reference reachable from these nodes without leaving the graph —\n * which includes those nested inside an inline `subgraph`, whose graph lives in\n * node config rather than behind a ref.\n */\nfunction references(nodes: readonly unknown[]): Array<[string, number | undefined]> {\n const found: Array<[string, number | undefined]> = [];\n\n for (const raw of nodes) {\n const n = raw as { type?: string; data?: { kind?: string; config?: Record<string, unknown> } };\n // Same precedence the runner uses to pick an executor.\n const kind = kindName(String(n?.data?.kind ?? n?.type ?? \"\"));\n const config = (n?.data?.config ?? {}) as Record<string, unknown>;\n\n if (kind === \"subflow\") {\n const ref = String(config.workflow ?? \"\").trim();\n if (ref) found.push([ref, version(config.version)]);\n continue;\n }\n\n if (kind === \"subgraph\") {\n // Cannot cycle by itself — it embeds a graph rather than naming one — but\n // a `subflow` inside it can, and a walker that only read top-level nodes\n // would never see it.\n const nested = (config.graph as { nodes?: unknown[] } | undefined)?.nodes;\n if (Array.isArray(nested)) found.push(...references(nested));\n }\n }\n\n return found;\n}\n\n/**\n * Kind ids are namespaced (`@particle-academy/subflow`) with bare aliases\n * (`subflow`), and graphs in the wild carry both. Matching one spelling would\n * silently stop seeing half of them.\n */\nfunction kindName(type: string): string {\n const slash = type.lastIndexOf(\"/\");\n return slash === -1 ? type : type.slice(slash + 1);\n}\n\n/** Mirrors the executor's pin rules; anything unusable is treated as unpinned. */\nfunction version(pin: unknown): number | undefined {\n if (pin === undefined || pin === null || pin === \"\") return undefined;\n const n = Number(pin);\n return Number.isInteger(n) ? n : undefined;\n}\n\n/**\n * A pinned ref is a DIFFERENT interface from the same ref unpinned, or from\n * another pin of it — so `A@1 → A@2` is not a loop on its own. Collapsing them\n * would refuse a legitimate \"call the previous version\" graph.\n */\nfunction key(ref: string, v: number | undefined): string {\n return v === undefined ? ref : `${ref}@${v}`;\n}\n"]}
1
+ {"version":3,"sources":["../src/marketplace/manifest.ts","../src/marketplace/fixtures.ts","../src/analysis/subflow-cycle.ts"],"names":["version","key"],"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 * `files` are source directories, not a dependency: a node is **vendored**, so\n * `fancy-cli add node` copies them into the project the way it copies a\n * component's source. One node, one source, readable and editable in the app\n * rather than hidden in `node_modules` or `vendor`.\n *\n * This spec covers a runtime's BACKEND only. The surface lives in the\n * manifest's `ui`, because the editor is React on every host — a Laravel\n * project needs the React kind and does not need the TypeScript executor.\n */\nexport type NodeRuntimeSpec = {\n /** This backend's source directories, relative to the node. */\n files: 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\n/**\n * A Fancy suite package this node's source imports.\n *\n * Separate from a plain npm dependency because the suite is polyglot and\n * vendorable: the same capability ships as an npm package, a Composer package,\n * or source you copy in, and which of those a consumer wants depends on the\n * host — so the node names the *package*, and the CLI offers the routes that\n * exist. A bare `dependencies: [\"@particle-academy/fancy-screens\"]` can only\n * ever offer `npm install`, which is the wrong answer in a Laravel app whose\n * editor is vendored.\n *\n * ## No versions, deliberately\n *\n * Nothing here carries a range, and the validator rejects one. A pinned\n * marketplace node freezes a consumer on an old surface: the suite ships\n * additively and often, and a node that pinned `^0.4` at authoring time would\n * be holding a project back a year later for a constraint nobody revisits.\n * Compatibility is expressed where it can actually be checked — `runtimes[].engine`\n * against the *engine*, which is the contract a node really depends on.\n */\nexport type FancyDependency = {\n /** Suite slug — what `/packages/<slug>` documents. */\n package: string;\n /** npm name, when the suite ships one. */\n npm?: string;\n /** Composer name, when the suite ships one. */\n composer?: string;\n /**\n * Why the node needs it, in a few words.\n *\n * Printed at install. Without it the CLI can only present a bare name and a\n * command, which reads as an unexplained demand for a second package.\n */\n reason?: string;\n /** Whether the node fails without it, or merely does less. Defaults to required. */\n requirement?: CapabilityRequirement;\n};\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 /**\n * The node's SURFACE — its React kind — as source directories.\n *\n * Copied whichever backend the consumer picks, because the editor is React on\n * every host. Kept out of `runtimes` deliberately: fold the two together and\n * a PHP project either loses its palette entry or gains a TypeScript executor\n * it will never run.\n */\n ui?: string[];\n /** Per-runtime backend source 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 /** Fancy suite packages this node's source imports. See {@link FancyDependency}. */\n fancyDependencies?: FancyDependency[];\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 validateFancyDependencies(m.fancyDependencies, 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 { files, 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 { files, engine }.\"));\n continue;\n }\n\n const s = spec as Record<string, unknown>;\n const files = Array.isArray(s.files) ? s.files : null;\n\n if (!files || files.length === 0 || files.some((f) => typeof f !== \"string\" || f.trim() === \"\")) {\n problems.push(\n err(\n `runtimes.${runtime}`,\n \"Needs `files` — the node source directories this runtime's backend lives in, relative to the node.\",\n ),\n );\n }\n if (s.entry !== undefined || s.package !== undefined) {\n // Nodes are VENDORED, not installed: the CLI copies a node's source into\n // the project the way it copies a component's. `entry` / `package`\n // described an npm/Composer install that no longer happens, and leaving\n // them readable would let a manifest claim an install path nothing honours.\n problems.push(\n err(\n `runtimes.${runtime}`,\n \"`entry` / `package` are gone — nodes are copied into a project, not installed from a registry. Declare `files` instead.\",\n ),\n );\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\n/**\n * Anything that looks like a version range, in a field that must not carry one.\n *\n * Covers the two shapes an author actually writes: a range appended to the name\n * (`@particle-academy/fancy-screens@^0.4`, `fancy-screens:^1`) and a bare\n * `version` key alongside it.\n *\n * ## Why the operators are `(?:[\\^~>=<]+\\s*)?` and not `[\\^~>=<]*\\s*`\n *\n * The obvious spelling — `(?:@|:)\\s*[\\^~>=<]*\\s*\\d` — is a ReDoS\n * (CWE-1333, CodeQL js/polynomial-redos). Because the operator class can match\n * nothing, a run of n spaces can be divided between the two `\\s*` in n+1 ways,\n * and a value with no trailing digit makes the engine try all of them: cost is\n * O(n²), and `npm: \"@\" + \" \".repeat(32000)` measured ~730ms on one core. A\n * manifest is third-party data — read off a marketplace package or a registry\n * response, by a validator whose whole job is to be pointed at input nobody\n * here wrote — so that is reachable, not hypothetical.\n *\n * Reaching the second whitespace run only *through* a non-empty operator run\n * removes the ambiguity while matching exactly the same strings: with no\n * operators the group is skipped and a single `\\s*` consumes the gap; with\n * operators, each `\\s*` owns one distinct side of them. Equivalence was checked\n * exhaustively over every string up to length 4 in the relevant alphabet plus\n * 400k longer random ones — zero divergence. See the ReDoS test in\n * `tests/marketplace.test.ts`.\n */\nconst VERSIONED = /(?:@|:)\\s*(?:[\\^~>=<]+\\s*)?\\d/;\n\nfunction validateFancyDependencies(deps: unknown, problems: ManifestProblem[]): void {\n if (deps === undefined) return;\n\n if (!Array.isArray(deps)) {\n problems.push(err(\"fancyDependencies\", \"Must be an array of { package, npm?, composer?, reason?, requirement? }.\"));\n return;\n }\n\n deps.forEach((entry, index) => {\n const at = `fancyDependencies[${index}]`;\n\n if (typeof entry !== \"object\" || entry === null || Array.isArray(entry)) {\n problems.push(err(at, \"Must be an object naming a suite package, not a bare string — a slug alone cannot say whether the package exists on npm, on Composer, or both.\"));\n return;\n }\n\n const dep = entry as Record<string, unknown>;\n\n if (typeof dep.package !== \"string\" || dep.package.trim() === \"\") {\n problems.push(err(`${at}.package`, \"Required — the suite slug, e.g. `fancy-screens`.\"));\n }\n\n if (dep.npm === undefined && dep.composer === undefined) {\n problems.push(\n err(at, \"Needs at least one of `npm` or `composer`. Naming neither leaves the CLI with a package it cannot offer any way to install.\"),\n );\n }\n\n // Versions are rejected rather than ignored. A node that pins holds a\n // consumer on an old surface for a constraint nobody revisits, and the\n // engine range in `runtimes` is where compatibility can actually be checked.\n for (const field of [\"package\", \"npm\", \"composer\"] as const) {\n const value = dep[field];\n if (typeof value === \"string\" && VERSIONED.test(value.replace(/^@[a-z0-9._-]+\\//i, \"\"))) {\n problems.push(\n err(\n `${at}.${field}`,\n \"Must not carry a version range — the suite ships additively and a pin here freezes a consumer on an old surface. Express engine compatibility in `runtimes[].engine` instead.\",\n ),\n );\n }\n }\n\n if (dep.version !== undefined) {\n problems.push(err(`${at}.version`, \"Not a field. Fancy dependencies are unversioned — see `runtimes[].engine` for the constraint that is actually checked.\"));\n }\n\n if (dep.requirement !== undefined && !REQUIREMENTS.includes(dep.requirement as string)) {\n problems.push(err(`${at}.requirement`, `Must be \"required\" or \"optional\".`));\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\n/**\n * Structural comparison, insensitive to key ORDER.\n *\n * This was `JSON.stringify(a) === JSON.stringify(b)`, which compares key order\n * as if it were meaning. A node spreading its input before its own fields\n * (`{ ...incoming, applied: true }`) produced a different key order than the\n * fixture author wrote, and the case failed with a message showing two\n * identical-looking objects — the worst kind of failure to debug, and one that\n * says nothing about the node.\n *\n * `undefined`-valued keys are still ignored, matching what JSON did and what a\n * fixture file (which cannot express `undefined`) can round-trip.\n */\nfunction deepEqual(a: unknown, b: unknown): boolean {\n if (Object.is(a, b)) return true;\n if (a === null || b === null || typeof a !== \"object\" || typeof b !== \"object\") return false;\n\n if (Array.isArray(a) || Array.isArray(b)) {\n if (!Array.isArray(a) || !Array.isArray(b) || a.length !== b.length) return false;\n\n return a.every((item, index) => deepEqual(item, b[index]));\n }\n\n const left = definedEntries(a as Record<string, unknown>);\n const right = definedEntries(b as Record<string, unknown>);\n const keys = Object.keys(left);\n if (keys.length !== Object.keys(right).length) return false;\n\n return keys.every(\n (key) => Object.prototype.hasOwnProperty.call(right, key) && deepEqual(left[key], right[key]),\n );\n}\n\nfunction definedEntries(value: Record<string, unknown>): Record<string, unknown> {\n const out: Record<string, unknown> = {};\n for (const [key, item] of Object.entries(value)) {\n if (item !== undefined) out[key] = item;\n }\n\n return out;\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 // Key PRESENCE: a port bound to null is not an absent port, and\n // only the absent one falls back to the whole map.\n carried = c.inputs && Object.prototype.hasOwnProperty.call(c.inputs, \"in\") ? 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 && Object.prototype.hasOwnProperty.call(ctx.inputs, \"in\") ? 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","import type { FlowGraph } from \"../types\";\nimport { isResolutionFailure, type WorkflowResolver } from \"../registry/capabilities\";\n\n/**\n * Find a `subflow` loop BEFORE the graph is saved, rather than after a run has\n * already done the work N times.\n *\n * ## Why this is not the depth cap\n *\n * `subflowExecutor` caps recursion depth at runtime, which is the correct\n * backstop and stays — it is the only thing that catches a loop created from the\n * other end, when someone edits B after A was saved. But by the time it fires,\n * every node ABOVE the subflow has run on each pass, side effects included, and\n * the author is handed an opaque failure from deep inside a run while the graph\n * that caused it is still saved and still runnable.\n *\n * The editor is where an author would most naturally be stopped, which is why\n * this lives here and not only in the PHP runtime.\n *\n * ## Why it needs a resolver\n *\n * Schema validation checks one graph in isolation and cannot see A → B → A,\n * because each graph is individually valid. Only the resolver knows what a ref\n * points at, and only the host has one.\n *\n * The chain matters more than the boolean: \"this loops\" is much less useful than\n * naming the step that closes it.\n *\n * The TS twin of `FancyFlow\\Analysis\\SubflowCycle`.\n *\n * ```ts\n * const loop = await findSubflowCycle(graph, resolver, \"Daily Planner\");\n * // [\"Daily Planner\", \"Digest\", \"Daily Planner\"] — or [] when safe\n * ```\n */\nexport async function findSubflowCycle(\n graph: FlowGraph,\n resolver: WorkflowResolver,\n rootRef?: string,\n): Promise<string[]> {\n return walk(\n graph,\n resolver,\n rootRef === undefined ? [] : [rootRef],\n rootRef === undefined ? new Set<string>() : new Set([key(rootRef, undefined)]),\n );\n}\n\nasync function walk(\n graph: FlowGraph,\n resolver: WorkflowResolver,\n path: string[],\n onPath: Set<string>,\n): Promise<string[]> {\n for (const [ref, version] of references(graph?.nodes ?? [])) {\n const k = key(ref, version);\n\n // Membership is tracked PER PATH, not globally: a diamond (two branches\n // that both call the same child) revisits a ref without looping, and\n // treating that as a cycle would refuse a perfectly good graph.\n if (onPath.has(k)) return [...path, ref];\n\n const resolved = await resolver(ref, version);\n\n // A ref that does not resolve is a different problem, reported elsewhere.\n // Refusing the save for it would block authoring a parent before its child\n // exists.\n if (!resolved || isResolutionFailure(resolved)) continue;\n\n const found = await walk(\n resolved as FlowGraph,\n resolver,\n [...path, ref],\n new Set(onPath).add(k),\n );\n if (found.length) return found;\n }\n\n return [];\n}\n\n/**\n * Every subflow reference reachable from these nodes without leaving the graph —\n * which includes those nested inside an inline `subgraph`, whose graph lives in\n * node config rather than behind a ref.\n */\nfunction references(nodes: readonly unknown[]): Array<[string, number | undefined]> {\n const found: Array<[string, number | undefined]> = [];\n\n for (const raw of nodes) {\n const n = raw as { type?: string; data?: { kind?: string; config?: Record<string, unknown> } };\n // Same precedence the runner uses to pick an executor.\n const kind = kindName(String(n?.data?.kind ?? n?.type ?? \"\"));\n const config = (n?.data?.config ?? {}) as Record<string, unknown>;\n\n if (kind === \"subflow\") {\n const ref = String(config.workflow ?? \"\").trim();\n if (ref) found.push([ref, version(config.version)]);\n continue;\n }\n\n if (kind === \"subgraph\") {\n // Cannot cycle by itself — it embeds a graph rather than naming one — but\n // a `subflow` inside it can, and a walker that only read top-level nodes\n // would never see it.\n const nested = (config.graph as { nodes?: unknown[] } | undefined)?.nodes;\n if (Array.isArray(nested)) found.push(...references(nested));\n }\n }\n\n return found;\n}\n\n/**\n * Kind ids are namespaced (`@particle-academy/subflow`) with bare aliases\n * (`subflow`), and graphs in the wild carry both. Matching one spelling would\n * silently stop seeing half of them.\n */\nfunction kindName(type: string): string {\n const slash = type.lastIndexOf(\"/\");\n return slash === -1 ? type : type.slice(slash + 1);\n}\n\n/** Mirrors the executor's pin rules; anything unusable is treated as unpinned. */\nfunction version(pin: unknown): number | undefined {\n if (pin === undefined || pin === null || pin === \"\") return undefined;\n const n = Number(pin);\n return Number.isInteger(n) ? n : undefined;\n}\n\n/**\n * A pinned ref is a DIFFERENT interface from the same ref unpinned, or from\n * another pin of it — so `A@1 → A@2` is not a loop on its own. Collapsing them\n * would refuse a legitimate \"call the previous version\" graph.\n */\nfunction key(ref: string, v: number | undefined): string {\n return v === undefined ? ref : `${ref}@${v}`;\n}\n"]}
@@ -0,0 +1,149 @@
1
+ /**
2
+ * `{{ }}` resolution — the TypeScript twin of `FancyFlow\Nodes\Support\Expr`.
3
+ *
4
+ * ## Why this is opt-in and not wired into `runFlow`
5
+ *
6
+ * The PHP runtime resolves expressions inside its batteries-included executors.
7
+ * The JS runtime never has: `runFlow` hands `node.data.config` to your executor
8
+ * verbatim, so every host that uses `{{ }}` today already resolves it itself.
9
+ * Turning resolution on inside `runFlow` would interpolate a second time over
10
+ * values those hosts had already substituted — silently, and only for graphs
11
+ * that happen to contain `{{` in their DATA.
12
+ *
13
+ * So this exports the semantics and changes no behaviour. Call it yourself:
14
+ *
15
+ * ```ts
16
+ * const url = evaluateExpression(node.data.config.url, inputs);
17
+ * ```
18
+ *
19
+ * ## The semantics are the PHP file's, deliberately
20
+ *
21
+ * This is not a general expression language and must not grow into one. It
22
+ * resolves a dot-path against a context and nothing else — no arithmetic, no
23
+ * comparisons, no calls. Hosts that want real expressions override the executor
24
+ * (the PHP docblock points at symfony/expression-language for the same reason).
25
+ *
26
+ * Divergence here is a correctness bug rather than a style difference: the same
27
+ * graph is authored once and may run on either runtime. `suites/shared/expr`
28
+ * in `@particle-academy/fancy-conformance` is the fixture table both sides run,
29
+ * so parity is a test result instead of a claim.
30
+ */
31
+ /** Anything a context or a resolved value can be. */
32
+ type ExprValue = unknown;
33
+ /** The context an expression resolves against — the executor's `inputs`. */
34
+ type ExprContext = Record<string, ExprValue>;
35
+ /**
36
+ * What a resolution attempt ANSWERS — did the path resolve, and to what.
37
+ *
38
+ * `resolvePath` cannot express this, and that is the defect it exists to fix:
39
+ * it returns `null` both for "this path does not exist" and for "this path
40
+ * exists and holds null". One value standing for two states.
41
+ *
42
+ * At the interpolation layer the collapse is worse, because `null` stringifies
43
+ * to `""`. A consumer put it exactly:
44
+ *
45
+ * > "An unresolvable path yields `''`, so a wrong field is indistinguishable
46
+ * > from an empty one at runtime."
47
+ *
48
+ * A misspelled field renders as an empty string, which looks precisely like a
49
+ * field that is legitimately empty. The graph runs, the node succeeds, and the
50
+ * output is quietly missing a value nobody is told about — worst on
51
+ * LLM-authored graphs, where the field name was guessed in the first place.
52
+ *
53
+ * Same shape as the four `??` collapses fixed across all four runtimes on
54
+ * 2026-08-26 (absent vs null), one layer up: **presence is the only correct
55
+ * test, and a return value that cannot express presence cannot be tested for
56
+ * it.** Hence a second return channel rather than a cleverer sentinel — every
57
+ * sentinel is a legal value for somebody.
58
+ */
59
+ interface Resolution {
60
+ /** Whether the path resolved at all. `false` means it does not exist. */
61
+ resolved: boolean;
62
+ /** The value, when `resolved`. `null` when not — do not read it blind. */
63
+ value: ExprValue;
64
+ }
65
+ /** Thrown by the `"throw"` policy when a path does not resolve. */
66
+ declare class UnresolvedPathError extends Error {
67
+ readonly path: string;
68
+ constructor(path: string);
69
+ }
70
+ /**
71
+ * What evaluation does with a path that does not resolve.
72
+ *
73
+ * - `"empty"` — today's behaviour, and the DEFAULT. Interpolates to `""`; a
74
+ * whole expression yields `null`. Unchanged so that widening this API breaks
75
+ * nobody: 40 call sites across the runtimes assume it.
76
+ * - `"keep"` — leave the `{{ … }}` text in place. The failure becomes VISIBLE
77
+ * in the output without stopping the run, which is what you want for
78
+ * human-reviewed content: a rendered `{{ in.recipient_naem }}` is self-
79
+ * diagnosing in a way an absence never is.
80
+ * - `"throw"` — refuse. For hosts that would rather fail a run than deliver a
81
+ * silently incomplete result.
82
+ *
83
+ * Opt-in before default at the request of the consumer who reported it — the
84
+ * host with the most LLM-authored graphs, and so both the biggest beneficiary
85
+ * and the right place for it to break first if it is going to.
86
+ */
87
+ type UnresolvedPolicy = "empty" | "keep" | "throw";
88
+ /** Options for {@link evaluateExpression} / {@link evaluateConfig}. */
89
+ interface EvaluateOptions {
90
+ /** What to do with a path that does not resolve. Default `"empty"`. */
91
+ onUnresolved?: UnresolvedPolicy;
92
+ }
93
+ /**
94
+ * Resolve a dot-path, reporting WHETHER it resolved.
95
+ *
96
+ * The same walk as `resolvePath` — deliberately, so the two can never disagree
97
+ * about what resolves; `resolvePath` is defined in terms of this one below.
98
+ *
99
+ * A note on JS having two absent values: a key present with the value
100
+ * `undefined` reports `resolved: false`, matching `resolvePath`'s long-standing
101
+ * behaviour. It cannot arise from graph data (JSON has no `undefined`), and
102
+ * changing it would make the two functions disagree for no reachable gain.
103
+ */
104
+ declare function tryResolvePath(path: string, context: ExprContext): Resolution;
105
+ /**
106
+ * Resolve a dot-path against the context, honouring the `$json` / `$input`
107
+ * alias.
108
+ *
109
+ * Both aliases point at the `in` port value when the context has one, and at
110
+ * the whole context otherwise — the same fallback the PHP does, which is what
111
+ * makes `{{ $json.x }}` work on a trigger node that has no upstream input.
112
+ *
113
+ * A path that does not resolve returns `null`, never `undefined`: PHP has one
114
+ * absent value and JS has two, and letting the difference leak would make the
115
+ * two runtimes disagree about `{{ missing }}` for no useful reason.
116
+ */
117
+ declare function resolvePath(path: string, context: ExprContext): ExprValue;
118
+ /**
119
+ * Evaluate a template against a context.
120
+ *
121
+ * A string that is EXACTLY one expression returns the resolved value with its
122
+ * type intact — `{{ $json.count }}` gives you a number, not `"3"`. Anything
123
+ * else interpolates each run as text. That distinction is load-bearing: it is
124
+ * what lets a config field carry either a value or a sentence.
125
+ *
126
+ * Non-string templates pass through untouched, so this is safe to map over a
127
+ * whole config object.
128
+ */
129
+ declare function evaluateExpression(template: ExprValue, context: ExprContext, options?: EvaluateOptions): ExprValue;
130
+ /**
131
+ * Truthiness for branch / switch decisions.
132
+ *
133
+ * Mirrors PHP's rules rather than JavaScript's, because the graph is authored
134
+ * once and may run on either side. The two disagree in exactly the places a
135
+ * workflow hits: `"0"` and `"false"` are truthy in JS and falsy here, and an
136
+ * empty array is truthy in JS and falsy here.
137
+ */
138
+ declare function truthy(value: ExprValue): boolean;
139
+ /** Coerce a value to text the way interpolation does. */
140
+ declare function text(value: ExprValue): string;
141
+ /**
142
+ * Resolve every string in a config object, one level of nesting at a time.
143
+ *
144
+ * The convenience most hosts actually want, and the shape their hand-rolled
145
+ * version usually takes. Opt-in like the rest of this module.
146
+ */
147
+ declare function evaluateConfig<T extends Record<string, ExprValue>>(config: T, context: ExprContext, options?: EvaluateOptions): T;
148
+
149
+ export { type EvaluateOptions as E, type Resolution as R, UnresolvedPathError as U, type ExprContext as a, type ExprValue as b, type UnresolvedPolicy as c, evaluateExpression as d, evaluateConfig as e, truthy as f, tryResolvePath as g, resolvePath as r, text as t };