@pipelex/mthds-ui 0.12.0 → 0.14.0
This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
- package/README.md +22 -0
- package/dist/chunk-GS2KODND.js +163 -0
- package/dist/chunk-GS2KODND.js.map +1 -0
- package/dist/chunk-LJQS5ZNA.js +1 -0
- package/dist/{chunk-R34J4GFM.js → chunk-V4FKGLKA.js} +113 -144
- package/dist/chunk-V4FKGLKA.js.map +1 -0
- package/dist/graph/index.d.ts +38 -4
- package/dist/graph/index.js +40 -22
- package/dist/graph/react/graph-core.css +105 -2
- package/dist/graph/react/index.css +165 -0
- package/dist/graph/react/index.css.map +1 -1
- package/dist/graph/react/index.d.ts +60 -3
- package/dist/graph/react/index.js +705 -269
- package/dist/graph/react/index.js.map +1 -1
- package/dist/graph/react/viewer/GraphToolbar.css +201 -0
- package/dist/index.d.ts +2 -2
- package/dist/index.js +40 -22
- package/dist/standalone/graph-standalone.html +317 -12
- package/dist/standalone/graph-viewer.css +306 -2
- package/dist/standalone/graph-viewer.js +11 -10
- package/dist/static-graph/index.d.ts +121 -0
- package/dist/static-graph/index.js +1287 -0
- package/dist/static-graph/index.js.map +1 -0
- package/dist/{types-B3nefYpV.d.ts → types-CIH1Ae16.d.ts} +93 -4
- package/package.json +7 -2
- package/dist/chunk-L24K3TZU.js +0 -1
- package/dist/chunk-R34J4GFM.js.map +0 -1
- /package/dist/{chunk-L24K3TZU.js.map → chunk-LJQS5ZNA.js.map} +0 -0
|
@@ -0,0 +1 @@
|
|
|
1
|
+
{"version":3,"sources":["../../src/static-graph/types.ts","../../src/static-graph/conceptRefs.ts","../../src/static-graph/parseMthdsBundle.ts","../../src/static-graph/normalizePipe.ts","../../src/static-graph/mergeBundles.ts","../../src/static-graph/buildStaticGraphSpec.ts","../../src/static-graph/validationIssues.ts"],"sourcesContent":["// ─── Static method-graph module: domain types ───────────────────────────────\n// Pure TypeScript, no React. This module parses raw `.mthds` TOML text into\n// blueprint-shaped bundles, reusing the `Pipe*Blueprint` registry types from\n// `@graph/types` so the parsed entries can feed a GraphSpec `pipe_registry`\n// directly. Parsing is lenient: half-written bundles produce partial results\n// plus non-fatal diagnostics, never exceptions.\n\nimport type { ConceptInfo, PipeBlueprintUnion } from \"@graph/types\";\n\n// ─── Diagnostics ─────────────────────────────────────────────────────────────\n\nexport type DiagnosticSeverity = \"error\" | \"warning\";\n\nexport type DiagnosticCode =\n | \"toml-parse-error\"\n | \"missing-domain\"\n | \"invalid-bundle-shape\"\n | \"invalid-concept-entry\"\n | \"invalid-pipe-entry\"\n | \"unknown-pipe-type\"\n | \"invalid-concept-ref\"\n | \"missing-pipe-output\"\n | \"invalid-sub-pipe\"\n | \"incomplete-batch-spec\"\n | \"duplicate-concept\"\n | \"duplicate-pipe\"\n | \"unresolved-pipe-ref\"\n | \"cyclic-pipe-ref\"\n | \"missing-main-pipe\"\n | \"no-entry-pipe\"\n | \"conflicting-input-concept\";\n\n/**\n * A non-fatal note collected while parsing or merging. `error` means a whole\n * unit could not be interpreted (unparseable TOML, a skipped pipe); `warning`\n * means something was tolerated with a fallback (missing output, bad ref).\n */\nexport interface Diagnostic {\n severity: DiagnosticSeverity;\n code: DiagnosticCode;\n message: string;\n /** TOML-style locator for the offending entry, e.g. `pipe.analyze_candidate.output`. */\n path?: string;\n}\n\n// ─── Parsed bundle ───────────────────────────────────────────────────────────\n\n/**\n * One `.mthds` file, parsed and normalized. Pipes are narrowed to the same\n * `PipeBlueprintUnion` shapes the pipelex runtime serializes into GraphSpec\n * `pipe_registry`, and concepts to `ConceptInfo` — no parallel type universe.\n * Field names mirror the TOML bundle header keys.\n */\nexport interface ParsedBundle {\n domain: string | null;\n description: string | null;\n main_pipe: string | null;\n system_prompt: string | null;\n /** Concepts declared in this bundle, keyed by bare concept code. */\n concepts: Record<string, ConceptInfo>;\n /** Pipes declared in this bundle, keyed by bare pipe code. */\n pipes: Record<string, PipeBlueprintUnion>;\n}\n\nexport interface ParseMthdsBundleResult {\n bundle: ParsedBundle;\n diagnostics: Diagnostic[];\n}\n\n// ─── Merged method set ───────────────────────────────────────────────────────\n\n/** Namespace of one domain after merging bundles: concepts and pipes by bare code. */\nexport interface DomainNamespace {\n domain: string;\n concepts: Record<string, ConceptInfo>;\n pipes: Record<string, PipeBlueprintUnion>;\n}\n\n/**\n * The merged namespace of a method package: every parsed bundle grouped by\n * domain, with duplicate codes resolved keep-first (plus a diagnostic).\n * `mainDomain` / `mainPipe` come as a pair from the first bundle declaring\n * `main_pipe` (falling back to the first domained bundle when none does) —\n * the walk entry point for the static graph builder. `description` comes from\n * the first bundle that declares it.\n */\nexport interface MergedMethodSet {\n domains: Record<string, DomainNamespace>;\n mainDomain: string | null;\n mainPipe: string | null;\n description: string | null;\n diagnostics: Diagnostic[];\n}\n\n/** Namespace used for bundles that declare no `domain` (a legal WIP state). */\nexport const UNKNOWN_DOMAIN = \"unknown\";\n\n// ─── Narrowing helpers (shared by the parsing modules) ───────────────────────\n\n/**\n * True for plain tables only — rejects arrays, class instances and dates\n * (smol-toml emits `TomlDate` objects for TOML datetime values).\n */\nexport function isPlainObject(value: unknown): value is Record<string, unknown> {\n if (typeof value !== \"object\" || value === null) return false;\n const proto: unknown = Object.getPrototypeOf(value);\n return proto === Object.prototype || proto === null;\n}\n\nexport function strOrNull(value: unknown): string | null {\n return typeof value === \"string\" && value.length > 0 ? value : null;\n}\n\nexport function intOrNull(value: unknown): number | null {\n return typeof value === \"number\" && Number.isInteger(value) ? value : null;\n}\n\nexport function boolOrNull(value: unknown): boolean | null {\n return typeof value === \"boolean\" ? value : null;\n}\n","// ─── Concept reference parsing and resolution ────────────────────────────────\n// A concept ref in MTHDS TOML is `Code`, `domain.Code`, optionally suffixed\n// with a multiplicity marker: `Code[]` (many) or `Code[N]` (exactly N).\n// Resolution follows the spec's namespace rules: bare refs resolve in the\n// current bundle first, then the native domain; qualified refs name their\n// domain explicitly. Anything unresolved becomes a best-effort stub — this\n// module never throws on content.\n\nimport type { ConceptInfo, StuffSpecInfo } from \"@graph/types\";\n\nexport const NATIVE_DOMAIN = \"native\";\n\n/**\n * The native concept catalog (mirrors pipelex `NativeConceptCode`). Descriptions\n * are display-only stand-ins — the runtime's exact wording is not part of the\n * contract. Structure class names follow the runtime's `<Code>Content` rule.\n */\nconst NATIVE_CONCEPT_DESCRIPTIONS: Record<string, string> = {\n Dynamic: \"Dynamically typed content\",\n Text: \"A text\",\n Image: \"An image\",\n Document: \"A document\",\n Html: \"HTML content\",\n TextAndImages: \"A text with images\",\n Number: \"A number\",\n Page: \"The content of a page of a document\",\n JSON: \"JSON content\",\n SearchResult: \"A search result\",\n Anything: \"Anything\",\n Composite: \"A named composition of multiple contents\",\n};\n\nexport const NATIVE_CONCEPT_CODES: ReadonlySet<string> = new Set(\n Object.keys(NATIVE_CONCEPT_DESCRIPTIONS),\n);\n\n// ─── Ref parsing ─────────────────────────────────────────────────────────────\n\nexport interface ConceptRefParts {\n /** Explicit domain qualifier (`recruitment` in `recruitment.Profile`), or null for bare refs. */\n domain: string | null;\n code: string;\n /** `[]` → true (many), `[N]` → N, no suffix → null (single). */\n multiplicity: number | boolean | null;\n}\n\nconst CONCEPT_REF_RE = /^(?:([A-Za-z0-9_][A-Za-z0-9_.]*)\\.)?([A-Za-z0-9_]+)(?:\\[(\\d*)\\])?$/;\n\n/** Parse a concept ref string into its parts. Returns null when the ref is not interpretable. */\nexport function parseConceptRef(raw: unknown): ConceptRefParts | null {\n if (typeof raw !== \"string\") return null;\n const match = CONCEPT_REF_RE.exec(raw.trim());\n if (!match) return null;\n const [, domain, code, multiplicity] = match;\n return {\n domain: domain ?? null,\n code,\n multiplicity:\n multiplicity === undefined\n ? null\n : multiplicity === \"\"\n ? true\n : Number.parseInt(multiplicity, 10),\n };\n}\n\n// ─── Resolution to ConceptInfo ───────────────────────────────────────────────\n\n/**\n * Synthetic structure class name for a non-native concept, mirroring the\n * runtime's `make_qualified_structure_class_name`: dots in hierarchical\n * domain codes are replaced with interpuncts (·) to keep the name a valid,\n * collision-free identifier (`a.b` → `a·b`, distinct from `a_b`).\n */\nexport function qualifiedStructureClassName(domain: string, code: string): string {\n return `${domain.replaceAll(\".\", \"·\")}__${code}`;\n}\n\nexport function nativeConceptInfo(code: string): ConceptInfo {\n return {\n code,\n domain_code: NATIVE_DOMAIN,\n description: NATIVE_CONCEPT_DESCRIPTIONS[code] ?? code,\n structure_class_name: `${code}Content`,\n refines: null,\n };\n}\n\n/**\n * Best-effort info for a concept that is referenced but not declared in the\n * material at hand — an implicit concept, a WIP ref, or a cross-bundle ref\n * that `mergeBundles` may still enrich later.\n */\nfunction stubConceptInfo(code: string, domain: string): ConceptInfo {\n return {\n code,\n domain_code: domain,\n description: \"\",\n structure_class_name: qualifiedStructureClassName(domain, code),\n refines: null,\n };\n}\n\n/**\n * Resolve parsed ref parts against the current bundle. `localConcepts` holds\n * the bundle's declared concepts keyed by bare code.\n */\nexport function resolveConceptInfo(\n parts: ConceptRefParts,\n currentDomain: string,\n localConcepts: Record<string, ConceptInfo>,\n): ConceptInfo {\n if (parts.domain === NATIVE_DOMAIN) {\n return NATIVE_CONCEPT_CODES.has(parts.code)\n ? nativeConceptInfo(parts.code)\n : stubConceptInfo(parts.code, NATIVE_DOMAIN);\n }\n if (parts.domain !== null && parts.domain !== currentDomain) {\n return stubConceptInfo(parts.code, parts.domain);\n }\n const local = localConcepts[parts.code];\n if (local) return local;\n if (parts.domain === null && NATIVE_CONCEPT_CODES.has(parts.code)) {\n return nativeConceptInfo(parts.code);\n }\n return stubConceptInfo(parts.code, currentDomain);\n}\n\n/** Resolve a raw concept ref string straight to a `StuffSpecInfo`, or null when unparseable. */\nexport function resolveStuffSpec(\n raw: unknown,\n currentDomain: string,\n localConcepts: Record<string, ConceptInfo>,\n): StuffSpecInfo | null {\n const parts = parseConceptRef(raw);\n if (parts === null) return null;\n return {\n concept: resolveConceptInfo(parts, currentDomain, localConcepts),\n multiplicity: parts.multiplicity,\n };\n}\n","// ─── parseMthdsBundle: `.mthds` TOML text → ParsedBundle ─────────────────────\n// The single entry point for turning one raw `.mthds` string into a\n// blueprint-shaped bundle. Lenient in the `validateGraphSpec` house style but\n// inverted: instead of failing loudly on contract violations, it tolerates\n// missing or partial sections, skips what it cannot interpret, and records\n// non-fatal diagnostics — the whole point is rendering methods while they are\n// being written. It never throws on content; even unparseable TOML becomes an\n// `error` diagnostic with an empty bundle.\n\nimport { parse as parseToml } from \"smol-toml\";\n\nimport type { ConceptInfo, PipeBlueprintUnion } from \"@graph/types\";\n\nimport {\n NATIVE_CONCEPT_CODES,\n NATIVE_DOMAIN,\n parseConceptRef,\n qualifiedStructureClassName,\n} from \"./conceptRefs\";\nimport { normalizePipe } from \"./normalizePipe\";\nimport type { Diagnostic, ParseMthdsBundleResult, ParsedBundle } from \"./types\";\nimport { isPlainObject, strOrNull, UNKNOWN_DOMAIN } from \"./types\";\n\n// ─── Concept structure → JSON schema (display-only, best-effort) ─────────────\n\nconst FIELD_TYPE_TO_JSON: Record<string, Record<string, unknown>> = {\n text: { type: \"string\" },\n integer: { type: \"integer\" },\n number: { type: \"number\" },\n boolean: { type: \"boolean\" },\n date: { type: \"string\", format: \"date-time\" },\n list: { type: \"array\" },\n dict: { type: \"object\" },\n concept: { type: \"object\" },\n};\n\nfunction fieldSchema(spec: Record<string, unknown>): Record<string, unknown> {\n const typeName = strOrNull(spec.type) ?? \"text\";\n const schema: Record<string, unknown> = {\n ...(FIELD_TYPE_TO_JSON[typeName] ?? { type: \"string\" }),\n };\n const description = strOrNull(spec.description);\n if (description !== null) schema.description = description;\n if (typeName === \"list\") {\n const itemType = strOrNull(spec.item_type);\n schema.items = itemType !== null ? { ...(FIELD_TYPE_TO_JSON[itemType] ?? {}) } : {};\n }\n if (Array.isArray(spec.choices)) {\n schema.enum = spec.choices.filter((choice) => typeof choice === \"string\");\n }\n if (spec.default_value !== undefined && spec.default_value !== null) {\n schema.default = spec.default_value;\n }\n return schema;\n}\n\n/**\n * Derive a lightweight JSON schema from a `[concept.X.structure]` table so\n * concept detail panels have fields to show. Deliberately simpler than the\n * pydantic-generated schema the runtime emits (no anyOf-null wrapping, no\n * per-field titles) — this is presentation data, not a contract.\n */\nfunction deriveJsonSchema(\n structure: unknown,\n title: string,\n description: string,\n): Record<string, unknown> | undefined {\n if (!isPlainObject(structure)) return undefined;\n const properties: Record<string, unknown> = {};\n const required: string[] = [];\n for (const [name, spec] of Object.entries(structure)) {\n if (typeof spec === \"string\") {\n properties[name] = { type: \"string\", description: spec };\n continue;\n }\n if (!isPlainObject(spec)) continue;\n properties[name] = fieldSchema(spec);\n if (spec.required === true) required.push(name);\n }\n return {\n title,\n type: \"object\",\n description,\n properties,\n ...(required.length > 0 ? { required } : {}),\n };\n}\n\n// ─── Concept table parsing ───────────────────────────────────────────────────\n\n/** Qualify a `refines` ref the way the runtime registry does (`Text` → `native.Text`). */\nfunction qualifyRefines(\n raw: unknown,\n domain: string,\n declaredCodes: ReadonlySet<string>,\n): string | null {\n const parts = parseConceptRef(raw);\n if (parts === null) return null;\n if (parts.domain !== null) return `${parts.domain}.${parts.code}`;\n if (!declaredCodes.has(parts.code) && NATIVE_CONCEPT_CODES.has(parts.code)) {\n return `${NATIVE_DOMAIN}.${parts.code}`;\n }\n return `${domain}.${parts.code}`;\n}\n\nfunction parseConcepts(\n raw: unknown,\n domain: string,\n diagnostics: Diagnostic[],\n): Record<string, ConceptInfo> {\n const concepts: Record<string, ConceptInfo> = {};\n if (raw === undefined) return concepts;\n if (!isPlainObject(raw)) {\n diagnostics.push({\n severity: \"warning\",\n code: \"invalid-bundle-shape\",\n message: \"concept section is not a table — ignored\",\n path: \"concept\",\n });\n return concepts;\n }\n const declaredCodes: ReadonlySet<string> = new Set(Object.keys(raw));\n for (const [code, entry] of Object.entries(raw)) {\n if (typeof entry === \"string\") {\n // Shorthand form: `Concept = \"description\"`.\n concepts[code] = {\n code,\n domain_code: domain,\n description: entry,\n structure_class_name: qualifiedStructureClassName(domain, code),\n refines: null,\n };\n continue;\n }\n if (!isPlainObject(entry)) {\n diagnostics.push({\n severity: \"warning\",\n code: \"invalid-concept-entry\",\n message: `concept \"${code}\" is neither a table nor a description string — skipped`,\n path: `concept.${code}`,\n });\n continue;\n }\n const description = strOrNull(entry.description) ?? \"\";\n // A `structure = \"ClassName\"` string names an existing structure class;\n // the table form gets the runtime's `<domain>__<Code>` synthetic name.\n const structureClassName =\n strOrNull(entry.structure) ?? qualifiedStructureClassName(domain, code);\n concepts[code] = {\n code,\n domain_code: domain,\n description,\n structure_class_name: structureClassName,\n refines: qualifyRefines(entry.refines, domain, declaredCodes),\n json_schema: deriveJsonSchema(entry.structure, structureClassName, description),\n };\n }\n return concepts;\n}\n\n// ─── Bundle parsing ──────────────────────────────────────────────────────────\n\nfunction emptyBundle(): ParsedBundle {\n return {\n domain: null,\n description: null,\n main_pipe: null,\n system_prompt: null,\n concepts: {},\n pipes: {},\n };\n}\n\n/**\n * Parse one `.mthds` TOML string. Returns whatever could be interpreted plus\n * the diagnostics collected along the way — never throws.\n */\nexport function parseMthdsBundle(tomlText: string): ParseMthdsBundleResult {\n const diagnostics: Diagnostic[] = [];\n let root: Record<string, unknown>;\n try {\n root = parseToml(tomlText);\n } catch (error) {\n diagnostics.push({\n severity: \"error\",\n code: \"toml-parse-error\",\n message: error instanceof Error ? error.message : String(error),\n });\n return { bundle: emptyBundle(), diagnostics };\n }\n\n const bundle = emptyBundle();\n bundle.domain = strOrNull(root.domain);\n bundle.description = strOrNull(root.description);\n bundle.main_pipe = strOrNull(root.main_pipe);\n bundle.system_prompt = strOrNull(root.system_prompt);\n if (bundle.domain === null) {\n diagnostics.push({\n severity: \"warning\",\n code: \"missing-domain\",\n message: `bundle declares no domain — using \"${UNKNOWN_DOMAIN}\"`,\n path: \"domain\",\n });\n }\n const domain = bundle.domain ?? UNKNOWN_DOMAIN;\n\n bundle.concepts = parseConcepts(root.concept, domain, diagnostics);\n\n const pipeTable = root.pipe;\n if (pipeTable !== undefined) {\n if (!isPlainObject(pipeTable)) {\n diagnostics.push({\n severity: \"warning\",\n code: \"invalid-bundle-shape\",\n message: \"pipe section is not a table — ignored\",\n path: \"pipe\",\n });\n } else {\n const ctx = { domain, concepts: bundle.concepts, diagnostics };\n for (const [code, entry] of Object.entries(pipeTable)) {\n if (!isPlainObject(entry)) {\n diagnostics.push({\n severity: \"error\",\n code: \"invalid-pipe-entry\",\n message: `pipe \"${code}\" is not a table — skipped`,\n path: `pipe.${code}`,\n });\n continue;\n }\n const pipe: PipeBlueprintUnion | null = normalizePipe(code, entry, ctx);\n if (pipe !== null) bundle.pipes[code] = pipe;\n }\n }\n }\n\n return { bundle, diagnostics };\n}\n","// ─── Pipe normalization: authored TOML shape → registry blueprint shape ─────\n// The authoring surface (mthds_schema.json, checked in under data/schema/)\n// and the runtime-serialized registry shape (`PipeBlueprintUnion` in\n// `@graph/types`) name things differently: `steps` vs `sequential_sub_pipes`,\n// `model` vs `llm_choices`, `prompt` vs `prompt_blueprint`, … This module maps\n// the former to the latter, leniently: uninterpretable pieces are skipped with\n// a diagnostic, and only a pipe without a usable `type` is dropped entirely.\n\nimport type {\n ConceptInfo,\n PipeBlueprintUnion,\n PipeComposeConstructBlueprint,\n PipeComposeConstructField,\n PipeType,\n StuffSpecInfo,\n SubPipeSpec,\n TemplateBlueprint,\n} from \"@graph/types\";\nimport { KNOWN_PIPE_TYPES } from \"@graph/types\";\n\nimport { NATIVE_DOMAIN, nativeConceptInfo, resolveStuffSpec } from \"./conceptRefs\";\nimport type { Diagnostic } from \"./types\";\nimport { boolOrNull, intOrNull, isPlainObject, strOrNull } from \"./types\";\n\nexport interface NormalizePipeContext {\n domain: string;\n /** The bundle's declared concepts, keyed by bare code. */\n concepts: Record<string, ConceptInfo>;\n diagnostics: Diagnostic[];\n}\n\n// ─── Small shared builders ───────────────────────────────────────────────────\n\nfunction makeTemplate(template: string, category: string): TemplateBlueprint {\n return { template, templating_style: null, category, extra_context: null };\n}\n\n/**\n * Extract a display string from a model choice, which the authoring surface\n * allows as a plain handle (`\"gpt-5\"`), an inline setting (`{ model = … }`),\n * or a model reference (`{ name = … }`).\n */\nfunction modelToString(value: unknown): string | null {\n if (typeof value === \"string\") return strOrNull(value);\n if (isPlainObject(value)) {\n return strOrNull(value.model) ?? strOrNull(value.raw) ?? strOrNull(value.name);\n }\n return null;\n}\n\nfunction stringArrayOrNull(value: unknown): string[] | null {\n if (!Array.isArray(value)) return null;\n return value.filter((item): item is string => typeof item === \"string\");\n}\n\n// ─── IO normalization ────────────────────────────────────────────────────────\n\nfunction normalizeInputs(\n raw: unknown,\n pipeCode: string,\n ctx: NormalizePipeContext,\n): Record<string, StuffSpecInfo> {\n const inputs: Record<string, StuffSpecInfo> = {};\n if (raw === undefined || raw === null) return inputs;\n if (!isPlainObject(raw)) {\n ctx.diagnostics.push({\n severity: \"warning\",\n code: \"invalid-pipe-entry\",\n message: `pipe \"${pipeCode}\": inputs is not a table — ignored`,\n path: `pipe.${pipeCode}.inputs`,\n });\n return inputs;\n }\n for (const [name, ref] of Object.entries(raw)) {\n const spec = resolveStuffSpec(ref, ctx.domain, ctx.concepts);\n if (spec === null) {\n ctx.diagnostics.push({\n severity: \"warning\",\n code: \"invalid-concept-ref\",\n message: `pipe \"${pipeCode}\": input \"${name}\" has an uninterpretable concept ref — skipped`,\n path: `pipe.${pipeCode}.inputs.${name}`,\n });\n continue;\n }\n inputs[name] = spec;\n }\n return inputs;\n}\n\nfunction normalizeOutput(raw: unknown, pipeCode: string, ctx: NormalizePipeContext): StuffSpecInfo {\n const spec = resolveStuffSpec(raw, ctx.domain, ctx.concepts);\n if (spec !== null) return spec;\n ctx.diagnostics.push({\n severity: \"warning\",\n code: \"missing-pipe-output\",\n message: `pipe \"${pipeCode}\": missing or uninterpretable output — assuming native.Anything`,\n path: `pipe.${pipeCode}.output`,\n });\n return { concept: nativeConceptInfo(\"Anything\"), multiplicity: null };\n}\n\n// ─── Sub-pipe normalization (sequence steps, parallel branches) ──────────────\n\nfunction normalizeSubPipe(\n raw: unknown,\n pipeCode: string,\n path: string,\n ctx: NormalizePipeContext,\n): SubPipeSpec | null {\n if (!isPlainObject(raw) || strOrNull(raw.pipe) === null) {\n ctx.diagnostics.push({\n severity: \"warning\",\n code: \"invalid-sub-pipe\",\n message: `pipe \"${pipeCode}\": sub-pipe entry without a \"pipe\" ref — skipped`,\n path,\n });\n return null;\n }\n const batchOver = strOrNull(raw.batch_over);\n const batchAs = strOrNull(raw.batch_as);\n let batchParams: SubPipeSpec[\"batch_params\"] = null;\n if (batchOver !== null && batchAs !== null) {\n batchParams = { input_list_stuff_name: batchOver, input_item_stuff_name: batchAs };\n } else if (batchOver !== null || batchAs !== null) {\n ctx.diagnostics.push({\n severity: \"warning\",\n code: \"incomplete-batch-spec\",\n message:\n `pipe \"${pipeCode}\": sub-pipe \"${raw.pipe as string}\" sets only one of ` +\n `batch_over/batch_as — batching ignored`,\n path,\n });\n }\n // Mirrors the runtime SubPipeFactory: explicit nb_output wins, then\n // multiple_output, and a batched step is implicitly multiple.\n let outputMultiplicity: SubPipeSpec[\"output_multiplicity\"] =\n intOrNull(raw.nb_output) ?? (raw.multiple_output === true ? true : null);\n if (batchParams !== null && outputMultiplicity === null) outputMultiplicity = true;\n return {\n pipe_code: raw.pipe as string,\n output_name: strOrNull(raw.result),\n output_multiplicity: outputMultiplicity,\n batch_params: batchParams,\n };\n}\n\nfunction normalizeSubPipeList(\n raw: unknown,\n pipeCode: string,\n key: string,\n ctx: NormalizePipeContext,\n): SubPipeSpec[] {\n if (!Array.isArray(raw)) {\n if (raw !== undefined) {\n ctx.diagnostics.push({\n severity: \"warning\",\n code: \"invalid-pipe-entry\",\n message: `pipe \"${pipeCode}\": ${key} is not an array — treated as empty`,\n path: `pipe.${pipeCode}.${key}`,\n });\n }\n return [];\n }\n return raw\n .map((entry, index) =>\n normalizeSubPipe(entry, pipeCode, `pipe.${pipeCode}.${key}[${index}]`, ctx),\n )\n .filter((entry): entry is SubPipeSpec => entry !== null);\n}\n\n// ─── Compose construct normalization ─────────────────────────────────────────\n\nfunction normalizeConstructField(value: unknown): PipeComposeConstructField | null {\n if (\n typeof value === \"string\" ||\n typeof value === \"number\" ||\n typeof value === \"boolean\" ||\n Array.isArray(value)\n ) {\n return { method: \"fixed\", fixed_value: value };\n }\n if (isPlainObject(value)) {\n if (typeof value.from === \"string\") {\n return {\n method: \"from_var\",\n from_path: value.from,\n list_to_dict_keyed_by: strOrNull(value.list_to_dict_keyed_by),\n };\n }\n if (typeof value.template === \"string\") {\n return { method: \"template\", template: value.template };\n }\n const nested = normalizeConstruct(value);\n if (nested !== null) return { method: \"nested\", nested };\n }\n return null;\n}\n\nfunction normalizeConstruct(raw: unknown): PipeComposeConstructBlueprint | null {\n if (!isPlainObject(raw)) return null;\n const fields: Record<string, PipeComposeConstructField> = {};\n for (const [name, value] of Object.entries(raw)) {\n const field = normalizeConstructField(value);\n if (field !== null) fields[name] = field;\n }\n return Object.keys(fields).length > 0 ? { fields } : null;\n}\n\n// ─── Per-type normalization ──────────────────────────────────────────────────\n\n/**\n * Normalize one `[pipe.<code>]` table to its registry blueprint shape.\n * Returns null (with a diagnostic) only when the `type` is missing or not a\n * known pipe class — everything else degrades field-by-field.\n */\nexport function normalizePipe(\n code: string,\n raw: Record<string, unknown>,\n ctx: NormalizePipeContext,\n): PipeBlueprintUnion | null {\n const typeValue = raw.type;\n if (typeof typeValue !== \"string\" || !KNOWN_PIPE_TYPES.has(typeValue)) {\n ctx.diagnostics.push({\n severity: \"error\",\n code: \"unknown-pipe-type\",\n message: `pipe \"${code}\": unknown pipe type ${JSON.stringify(typeValue)} — pipe skipped`,\n path: `pipe.${code}.type`,\n });\n return null;\n }\n const type = typeValue as PipeType;\n const base = {\n code,\n domain_code: ctx.domain,\n description: strOrNull(raw.description) ?? \"\",\n inputs: normalizeInputs(raw.inputs, code, ctx),\n output: normalizeOutput(raw.output, code, ctx),\n };\n\n switch (type) {\n case \"PipeSequence\":\n return {\n ...base,\n type,\n pipe_category: \"PipeController\",\n sequential_sub_pipes: normalizeSubPipeList(raw.steps, code, \"steps\", ctx),\n };\n case \"PipeParallel\":\n return {\n ...base,\n type,\n pipe_category: \"PipeController\",\n parallel_sub_pipes: normalizeSubPipeList(raw.branches, code, \"branches\", ctx),\n add_each_output: raw.add_each_output === true,\n combined_output: strOrNull(raw.combined_output),\n };\n case \"PipeCondition\": {\n const outcomeMap: Record<string, string> = {};\n if (isPlainObject(raw.outcomes)) {\n for (const [outcome, pipeRef] of Object.entries(raw.outcomes)) {\n if (typeof pipeRef === \"string\" && pipeRef.length > 0) {\n outcomeMap[outcome] = pipeRef;\n } else {\n ctx.diagnostics.push({\n severity: \"warning\",\n code: \"invalid-pipe-entry\",\n message: `pipe \"${code}\": outcome \"${outcome}\" is not a pipe ref — skipped`,\n path: `pipe.${code}.outcomes.${outcome}`,\n });\n }\n }\n }\n return {\n ...base,\n type,\n pipe_category: \"PipeController\",\n expression: strOrNull(raw.expression) ?? strOrNull(raw.expression_template) ?? \"\",\n outcome_map: outcomeMap,\n default_outcome: strOrNull(raw.default_outcome) ?? \"\",\n add_alias_from_expression_to: strOrNull(raw.add_alias_from_expression_to),\n };\n }\n case \"PipeBatch\": {\n const branchPipeCode = strOrNull(raw.branch_pipe_code);\n if (branchPipeCode === null) {\n ctx.diagnostics.push({\n severity: \"warning\",\n code: \"invalid-pipe-entry\",\n message: `pipe \"${code}\": PipeBatch without branch_pipe_code`,\n path: `pipe.${code}.branch_pipe_code`,\n });\n }\n return {\n ...base,\n type,\n pipe_category: \"PipeController\",\n branch_pipe_code: branchPipeCode ?? \"\",\n batch_params: {\n input_list_stuff_name: strOrNull(raw.input_list_name) ?? \"\",\n input_item_stuff_name: strOrNull(raw.input_item_name) ?? \"\",\n },\n };\n }\n case \"PipeLLM\": {\n const systemPrompt = strOrNull(raw.system_prompt);\n const prompt = strOrNull(raw.prompt);\n return {\n ...base,\n type,\n pipe_category: \"PipeOperator\",\n llm_prompt_spec: {\n templating_style: null,\n system_prompt_blueprint:\n systemPrompt === null ? null : makeTemplate(systemPrompt, \"llm_prompt\"),\n prompt_blueprint: prompt === null ? null : makeTemplate(prompt, \"llm_prompt\"),\n user_image_references: null,\n user_document_references: null,\n system_image_references: null,\n system_document_references: null,\n },\n llm_choices: {\n for_text: modelToString(raw.model),\n for_object: modelToString(raw.model_to_structure),\n },\n structuring_method: strOrNull(raw.structuring_method),\n output_multiplicity: null,\n };\n }\n case \"PipeStructure\": {\n const inputNames = Object.keys(base.inputs);\n const llmChoice = isPlainObject(raw.model) ? raw.model : strOrNull(raw.model);\n return {\n ...base,\n type,\n pipe_category: \"PipeOperator\",\n llm_choice: llmChoice,\n text_input_name: inputNames[0] ?? \"text\",\n output_multiplicity: null,\n };\n }\n case \"PipeExtract\": {\n // Mirrors the runtime PipeExtractFactory: the (single) input is either\n // image-like or document-like, and exactly one of the two stuff names is\n // set. Statically, \"compatible with native.Image\" approximates to the\n // concept being Image or refining it; anything else counts as a document.\n const isImageLike = (spec: StuffSpecInfo): boolean =>\n (spec.concept.domain_code === NATIVE_DOMAIN && spec.concept.code === \"Image\") ||\n spec.concept.refines === `${NATIVE_DOMAIN}.Image`;\n const inputEntries = Object.entries(base.inputs);\n const imageInput = inputEntries.find(([, spec]) => isImageLike(spec));\n const documentInput = imageInput === undefined ? inputEntries[0] : undefined;\n return {\n ...base,\n type,\n pipe_category: \"PipeOperator\",\n extract_choice: modelToString(raw.model),\n should_caption_images: raw.page_image_captions === true,\n max_page_images: intOrNull(raw.max_page_images),\n should_include_page_views: raw.page_views === true,\n page_views_dpi: intOrNull(raw.page_views_dpi),\n render_js: boolOrNull(raw.render_js),\n include_raw_html: boolOrNull(raw.include_raw_html),\n image_stuff_name: imageInput?.[0] ?? null,\n document_stuff_name: documentInput?.[0] ?? null,\n };\n }\n case \"PipeSearch\":\n return {\n ...base,\n type,\n pipe_category: \"PipeOperator\",\n search_choice: modelToString(raw.model),\n prompt_blueprint: makeTemplate(strOrNull(raw.prompt) ?? \"\", \"basic\"),\n include_images_override: boolOrNull(raw.include_images),\n max_results_override: intOrNull(raw.max_results),\n from_date: strOrNull(raw.from_date),\n to_date: strOrNull(raw.to_date),\n include_domains: stringArrayOrNull(raw.include_domains),\n exclude_domains: stringArrayOrNull(raw.exclude_domains),\n is_structured_output: false,\n };\n case \"PipeImgGen\": {\n const prompt = strOrNull(raw.prompt);\n const negativePrompt = strOrNull(raw.negative_prompt);\n const seed = intOrNull(raw.seed) ?? (raw.seed === \"auto\" ? \"auto\" : null);\n return {\n ...base,\n type,\n pipe_category: \"PipeOperator\",\n img_gen_prompt_blueprint: {\n prompt_blueprint: prompt === null ? null : makeTemplate(prompt, \"img_gen_prompt\"),\n negative_prompt_blueprint:\n negativePrompt === null ? null : makeTemplate(negativePrompt, \"img_gen_prompt\"),\n image_references: null,\n },\n img_gen_choice: modelToString(raw.model),\n aspect_ratio: strOrNull(raw.aspect_ratio),\n is_raw: boolOrNull(raw.is_raw),\n seed,\n background: strOrNull(raw.background),\n output_format: strOrNull(raw.output_format),\n output_multiplicity:\n typeof base.output.multiplicity === \"number\" ? base.output.multiplicity : 1,\n };\n }\n case \"PipeCompose\": {\n const rawTemplate = raw.template;\n let template: string | null = null;\n let templatingStyle: string | null = null;\n let category = \"basic\";\n let extraContext: Record<string, unknown> | null = null;\n if (typeof rawTemplate === \"string\") {\n template = rawTemplate;\n } else if (isPlainObject(rawTemplate)) {\n template = strOrNull(rawTemplate.template);\n templatingStyle = strOrNull(rawTemplate.templating_style);\n category = strOrNull(rawTemplate.category) ?? category;\n extraContext = isPlainObject(rawTemplate.extra_context) ? rawTemplate.extra_context : null;\n }\n return {\n ...base,\n type,\n pipe_category: \"PipeOperator\",\n template,\n templating_style: templatingStyle,\n category,\n extra_context: extraContext,\n construct_blueprint: normalizeConstruct(raw.construct),\n };\n }\n case \"PipeFunc\":\n return { ...base, type, pipe_category: \"PipeOperator\" };\n case \"PipeSignature\": {\n const signatureFor = strOrNull(raw.signature_for);\n return {\n ...base,\n type,\n pipe_category: null,\n signature_for:\n signatureFor !== null && KNOWN_PIPE_TYPES.has(signatureFor)\n ? (signatureFor as PipeType)\n : null,\n };\n }\n default: {\n const _exhaustive: never = type;\n return _exhaustive;\n }\n }\n}\n","// ─── mergeBundles: ParsedBundle[] → MergedMethodSet ──────────────────────────\n// A method package may span several `.mthds` files; files sharing a domain\n// merge into one namespace. Duplicate codes keep the first declaration and\n// record a diagnostic. After merging, io concept stubs are re-pointed at the\n// declarations that other files contributed (a pipe in file A can reference a\n// concept declared in file B).\n\nimport type { PipeBlueprintUnion, StuffSpecInfo } from \"@graph/types\";\n\nimport type { Diagnostic, DomainNamespace, MergedMethodSet, ParsedBundle } from \"./types\";\nimport { UNKNOWN_DOMAIN } from \"./types\";\n\nfunction enrichPipeConcepts(\n pipe: PipeBlueprintUnion,\n domains: Record<string, DomainNamespace>,\n): PipeBlueprintUnion {\n const enrichSpec = (spec: StuffSpecInfo): StuffSpecInfo => {\n const declared = domains[spec.concept.domain_code]?.concepts[spec.concept.code];\n return declared !== undefined && declared !== spec.concept\n ? { ...spec, concept: declared }\n : spec;\n };\n const inputs: Record<string, StuffSpecInfo> = {};\n for (const [name, spec] of Object.entries(pipe.inputs)) {\n inputs[name] = enrichSpec(spec);\n }\n return { ...pipe, inputs, output: enrichSpec(pipe.output) };\n}\n\n/**\n * Merge parsed bundles into one namespace per domain. Order matters: on\n * duplicate codes the first bundle wins. `mainDomain` and `mainPipe` are taken\n * together from the first bundle declaring `main_pipe`, so a bare entry ref\n * always resolves in its declaring bundle's namespace; when no bundle declares\n * one, `mainDomain` falls back to the first domained bundle. `description`\n * comes from the first bundle that declares it.\n */\nexport function mergeBundles(bundles: ParsedBundle[]): MergedMethodSet {\n const diagnostics: Diagnostic[] = [];\n const domains: Record<string, DomainNamespace> = {};\n let mainDomain: string | null = null;\n let mainPipe: string | null = null;\n let description: string | null = null;\n\n for (const bundle of bundles) {\n const domain = bundle.domain ?? UNKNOWN_DOMAIN;\n const namespace = (domains[domain] ??= { domain, concepts: {}, pipes: {} });\n if (mainDomain === null && bundle.domain !== null) mainDomain = bundle.domain;\n if (mainPipe === null && bundle.main_pipe !== null) {\n mainPipe = bundle.main_pipe;\n // A bare main_pipe must resolve in the namespace of the bundle declaring\n // it, not whichever bundle happened to come first.\n mainDomain = domain;\n }\n if (description === null && bundle.description !== null) description = bundle.description;\n\n for (const [code, concept] of Object.entries(bundle.concepts)) {\n if (code in namespace.concepts) {\n diagnostics.push({\n severity: \"warning\",\n code: \"duplicate-concept\",\n message: `concept \"${domain}.${code}\" declared more than once — keeping the first declaration`,\n path: `concept.${code}`,\n });\n continue;\n }\n namespace.concepts[code] = concept;\n }\n for (const [code, pipe] of Object.entries(bundle.pipes)) {\n if (code in namespace.pipes) {\n diagnostics.push({\n severity: \"warning\",\n code: \"duplicate-pipe\",\n message: `pipe \"${domain}.${code}\" declared more than once — keeping the first declaration`,\n path: `pipe.${code}`,\n });\n continue;\n }\n namespace.pipes[code] = pipe;\n }\n }\n\n for (const namespace of Object.values(domains)) {\n for (const [code, pipe] of Object.entries(namespace.pipes)) {\n namespace.pipes[code] = enrichPipeConcepts(pipe, domains);\n }\n }\n\n return { domains, mainDomain, mainPipe, description, diagnostics };\n}\n","// ─── Static graph builder: MergedMethodSet → GraphSpec ──────────────────────\n// The static walk from the design doc (wip/static-graph-design.md): walk pipe\n// *invocations* starting at the entry pipe, maintaining a scope (the static\n// mirror of working memory), and emit a GraphSpec with `meta.mode: \"static\"`\n// that the existing GraphViewer renders unchanged.\n//\n// Identity is deterministic: node ids are invocation paths\n// (`screening.process_cv/step_2/...`) and stuff digests are the raw strings\n// `<producer_node_id>:<name>` (external inputs: `input:<name>`). The UI treats\n// digests as opaque unique keys, so the raw string — collision-free by\n// construction and readable in snapshots — is preferred over a hash.\n//\n// Everything is best-effort: unresolvable refs skip the child, cycles render\n// as leaves, dependency-alias refs (`alias->pipe`) render as opaque leaf\n// cards. This module never throws on content.\n\nimport type {\n ConceptInfo,\n GraphSpec,\n GraphSpecEdge,\n GraphSpecEdgeKind,\n GraphSpecNode,\n GraphSpecNodeIoItem,\n PipeBatchBlueprint,\n PipeBlueprintUnion,\n PipeConditionBlueprint,\n PipeParallelBlueprint,\n PipeSequenceBlueprint,\n PipeType,\n SubPipeSpec,\n} from \"@graph/types\";\n\nimport { nativeConceptInfo } from \"./conceptRefs\";\nimport { mergeBundles } from \"./mergeBundles\";\nimport { parseMthdsBundle } from \"./parseMthdsBundle\";\nimport type { Diagnostic, DomainNamespace, MergedMethodSet } from \"./types\";\n\n// ─── Public API ──────────────────────────────────────────────────────────────\n\nexport interface StaticGraphOptions {\n /**\n * Pipe ref to walk from (`code` or `domain.code`). Defaults to the merged\n * set's `main_pipe`, falling back to a root heuristic (first pipe no other\n * pipe references) when none is declared.\n */\n entryPipe?: string;\n}\n\nexport interface StaticGraphResult {\n spec: GraphSpec;\n diagnostics: Diagnostic[];\n}\n\n/** Build a static GraphSpec from an already-parsed, merged method set. */\nexport function buildStaticGraphSpec(\n set: MergedMethodSet,\n options: StaticGraphOptions = {},\n): StaticGraphResult {\n const diagnostics: Diagnostic[] = [];\n const ctx: WalkCtx = {\n set,\n nodes: [],\n edges: [],\n pipeRegistry: {},\n conceptRegistry: {},\n stuffByDigest: new Map(),\n diagnostics,\n stack: [],\n edgeSeq: 0,\n };\n\n // Registries carry every parsed entry (the dry-run path often ships them\n // empty — populating them is what makes detail panels rich). Registered\n // before the walk so synthetic entries minted during it never clobber a\n // declared one.\n for (const namespace of Object.values(set.domains)) {\n for (const concept of Object.values(namespace.concepts)) registerConcept(ctx, concept);\n for (const pipe of Object.values(namespace.pipes)) {\n ctx.pipeRegistry[`${pipe.domain_code}.${pipe.code}`] = pipe;\n for (const spec of Object.values(pipe.inputs)) registerConcept(ctx, spec.concept);\n registerConcept(ctx, pipe.output.concept);\n }\n }\n\n const entry = pickEntryPipe(set, options.entryPipe ?? null, diagnostics);\n if (entry !== null) {\n walkPipe(ctx, entry.code, entry.domain, `${entry.domain}.${entry.code}`, null, new Map(), {\n resultName: null,\n outputMultiplicity: null,\n });\n }\n\n const spec: GraphSpec = {\n nodes: ctx.nodes,\n edges: ctx.edges,\n meta: { format: \"mthds\", mode: \"static\" },\n pipe_registry: ctx.pipeRegistry,\n concept_registry: ctx.conceptRegistry,\n };\n if (entry !== null) {\n spec.pipeline_ref = { domain: entry.domain, main_pipe: entry.code };\n }\n return { spec, diagnostics };\n}\n\n/**\n * Convenience wrapper: parse one or more `.mthds` TOML strings, merge them,\n * and build the static GraphSpec. Diagnostics from all three stages are\n * concatenated in order (parse, merge, build).\n */\nexport function buildStaticGraphSpecFromToml(\n tomlTexts: string | string[],\n options: StaticGraphOptions = {},\n): StaticGraphResult {\n const texts = Array.isArray(tomlTexts) ? tomlTexts : [tomlTexts];\n const parsed = texts.map((text) => parseMthdsBundle(text));\n const merged = mergeBundles(parsed.map((result) => result.bundle));\n const built = buildStaticGraphSpec(merged, options);\n return {\n spec: built.spec,\n diagnostics: [\n ...parsed.flatMap((result) => result.diagnostics),\n ...merged.diagnostics,\n ...built.diagnostics,\n ],\n };\n}\n\n// ─── Walk state ──────────────────────────────────────────────────────────────\n\n/** A scope entry — the static mirror of a working-memory stuff. */\ninterface StuffRecord {\n digest: string;\n name: string;\n concept: ConceptInfo;\n multiplicity: number | boolean | null;\n}\n\ntype Scope = Map<string, StuffRecord>;\n\ninterface WalkCtx {\n set: MergedMethodSet;\n nodes: GraphSpecNode[];\n edges: GraphSpecEdge[];\n pipeRegistry: Record<string, PipeBlueprintUnion>;\n conceptRegistry: Record<string, ConceptInfo>;\n stuffByDigest: Map<string, StuffRecord>;\n diagnostics: Diagnostic[];\n /** Qualified refs (`domain.code`) on the recursion stack — the cycle guard. */\n stack: string[];\n edgeSeq: number;\n}\n\n/** How a pipe is being invoked — the step/branch/outcome context. */\ninterface Invocation {\n /** The enclosing step's `result` name — names the operator's output stuff. */\n resultName: string | null;\n /** The enclosing step's `nb_output`/`multiple_output` override. */\n outputMultiplicity: SubPipeSpec[\"output_multiplicity\"];\n /** Set on condition children: the outcome value that routes here. */\n outcomeValue?: string;\n}\n\ninterface WalkResult {\n nodeId: string;\n /** Primary output stuff — what a sequence step's `result` binds to. */\n output: StuffRecord | null;\n /** Extra bindings a parallel with `add_each_output` exposes to the enclosing scope. */\n eachOutputs: [string, StuffRecord][];\n}\n\n// ─── Entry pipe selection ────────────────────────────────────────────────────\n\ntype PipeResolution =\n | { kind: \"resolved\"; blueprint: PipeBlueprintUnion; domain: string; code: string }\n | { kind: \"opaque\" }\n | { kind: \"unresolved\" };\n\n/**\n * Resolve a pipe ref against the merged set: bare refs in the current domain\n * (same-domain files are already merged into one namespace), `domain.code`\n * refs in the named domain. `alias->…` dependency refs are opaque in phase 1.\n */\nfunction resolvePipeRef(set: MergedMethodSet, ref: string, currentDomain: string): PipeResolution {\n if (ref.includes(\"->\")) return { kind: \"opaque\" };\n const dot = ref.lastIndexOf(\".\");\n const domain = dot === -1 ? currentDomain : ref.slice(0, dot);\n const code = dot === -1 ? ref : ref.slice(dot + 1);\n const blueprint = set.domains[domain]?.pipes[code];\n if (blueprint === undefined) return { kind: \"unresolved\" };\n return { kind: \"resolved\", blueprint, domain, code };\n}\n\n/** Sub-pipe refs appearing anywhere in a namespace — used by the root heuristic. */\nfunction referencedPipeCodes(namespace: DomainNamespace): Set<string> {\n const refs = new Set<string>();\n // Refs are authored strings: bare (`helper`) or qualified (`domain.helper`).\n // Reduce them to bare codes in this namespace, mirroring resolvePipeRef —\n // cross-domain and `alias->` refs can't name a pipe here, so they're dropped.\n const add = (ref: string): void => {\n if (ref === \"\" || ref.includes(\"->\")) return;\n const dot = ref.lastIndexOf(\".\");\n if (dot === -1) refs.add(ref);\n else if (ref.slice(0, dot) === namespace.domain) refs.add(ref.slice(dot + 1));\n };\n for (const pipe of Object.values(namespace.pipes)) {\n switch (pipe.type) {\n case \"PipeSequence\":\n for (const sub of pipe.sequential_sub_pipes) add(sub.pipe_code);\n break;\n case \"PipeParallel\":\n for (const sub of pipe.parallel_sub_pipes) add(sub.pipe_code);\n break;\n case \"PipeCondition\":\n for (const target of Object.values(pipe.outcome_map)) add(target);\n add(pipe.default_outcome);\n break;\n case \"PipeBatch\":\n add(pipe.branch_pipe_code);\n break;\n default:\n break;\n }\n }\n return refs;\n}\n\nfunction pickEntryPipe(\n set: MergedMethodSet,\n explicitRef: string | null,\n diagnostics: Diagnostic[],\n): { domain: string; code: string } | null {\n const domainsInOrder = Object.keys(set.domains);\n const fallbackDomain = set.mainDomain ?? domainsInOrder[0];\n if (fallbackDomain === undefined) {\n diagnostics.push({\n severity: \"error\",\n code: \"no-entry-pipe\",\n message: \"no bundles to build a graph from\",\n });\n return null;\n }\n\n const resolveEntry = (ref: string): { domain: string; code: string } | null => {\n const resolution = resolvePipeRef(set, ref, fallbackDomain);\n return resolution.kind === \"resolved\"\n ? { domain: resolution.domain, code: resolution.code }\n : null;\n };\n\n if (explicitRef !== null) {\n const entry = resolveEntry(explicitRef);\n if (entry === null) {\n diagnostics.push({\n severity: \"error\",\n code: \"unresolved-pipe-ref\",\n message: `entry pipe \"${explicitRef}\" not found in the method set`,\n });\n }\n return entry;\n }\n\n if (set.mainPipe !== null) {\n const entry = resolveEntry(set.mainPipe);\n if (entry !== null) return entry;\n diagnostics.push({\n severity: \"warning\",\n code: \"unresolved-pipe-ref\",\n message: `main_pipe \"${set.mainPipe}\" not found — falling back to a root heuristic`,\n });\n } else {\n diagnostics.push({\n severity: \"warning\",\n code: \"missing-main-pipe\",\n message: \"no main_pipe declared — falling back to a root heuristic\",\n });\n }\n\n // Root heuristic: the first pipe (declaration order) that no other pipe in\n // its domain references; else the first pipe. Keeps half-written bundles\n // rendering something sensible.\n const domainWithPipes = [fallbackDomain, ...domainsInOrder].find(\n (domain) => Object.keys(set.domains[domain]?.pipes ?? {}).length > 0,\n );\n if (domainWithPipes === undefined) {\n diagnostics.push({\n severity: \"error\",\n code: \"no-entry-pipe\",\n message: \"no pipes found in any bundle\",\n });\n return null;\n }\n const namespace = set.domains[domainWithPipes];\n const referenced = referencedPipeCodes(namespace);\n const codes = Object.keys(namespace.pipes);\n const root = codes.find((code) => !referenced.has(code)) ?? codes[0];\n return { domain: domainWithPipes, code: root };\n}\n\n// ─── Small helpers ───────────────────────────────────────────────────────────\n\n/** `CamelCase` concept code → `snake_case` stuff name (the runtime's fallback naming). */\nfunction snakeCase(code: string): string {\n return code\n .replace(/([A-Z]+)([A-Z][a-z0-9])/g, \"$1_$2\")\n .replace(/([a-z0-9])([A-Z])/g, \"$1_$2\")\n .toLowerCase();\n}\n\nfunction registerConcept(ctx: WalkCtx, concept: ConceptInfo): void {\n ctx.conceptRegistry[`${concept.domain_code}.${concept.code}`] ??= concept;\n}\n\n/**\n * Mint (or return the already-minted) stuff for a digest. First mint wins —\n * matching how the UI's stuff registry keeps the first occurrence per digest.\n */\nfunction mintStuff(\n ctx: WalkCtx,\n digest: string,\n name: string,\n concept: ConceptInfo,\n multiplicity: number | boolean | null,\n): StuffRecord {\n const existing = ctx.stuffByDigest.get(digest);\n if (existing !== undefined) return existing;\n const record: StuffRecord = { digest, name, concept, multiplicity };\n ctx.stuffByDigest.set(digest, record);\n registerConcept(ctx, concept);\n return record;\n}\n\n/**\n * An io item for `stuff`, optionally exposed under a *slot name* — the name\n * the invoking step binds it to (`result = \"x\"`). The runtime names a\n * controller's transparent output by its slot, while the producing operator\n * keeps the local name; the UI's stuff registry is first-occurrence-wins and\n * controllers are emitted before their children, so the slot name is what\n * renders (verified against the dry fixtures).\n */\nfunction ioItem(stuff: StuffRecord, slotName?: string | null): GraphSpecNodeIoItem {\n return { name: slotName ?? stuff.name, digest: stuff.digest, concept: stuff.concept.code };\n}\n\nfunction addEdge(\n ctx: WalkCtx,\n kind: GraphSpecEdgeKind,\n source: string,\n target: string,\n extras?: { label?: string; sourceStuff?: string; targetStuff?: string },\n): void {\n // Namespaced ids: the rendering pipeline synthesizes its own dataflow edges\n // named `edge_<n>` (graphBuilders.ts), so bare `edge_<n>` here would collide\n // in the ReactFlow key space.\n const edge: GraphSpecEdge = { id: `static:edge_${ctx.edgeSeq++}`, source, target, kind };\n if (extras?.label !== undefined) edge.label = extras.label;\n if (extras?.sourceStuff !== undefined) edge.source_stuff_digest = extras.sourceStuff;\n if (extras?.targetStuff !== undefined) edge.target_stuff_digest = extras.targetStuff;\n ctx.edges.push(edge);\n}\n\nfunction addNodeTag(node: GraphSpecNode, key: string, value: string): void {\n node.tags = { ...(node.tags ?? {}), [key]: value };\n}\n\nfunction formatBatchMultiplicity(multiplicity: number | boolean | null | undefined): string {\n if (typeof multiplicity === \"number\") return `x${multiplicity}`;\n if (multiplicity === true) return \"xmany\";\n return \"x?\";\n}\n\n/**\n * Working-memory name matching: exact name first, then dotted-prefix — an\n * input `a.b` is satisfied by a binding for `a`.\n */\nfunction lookupScope(scope: Scope, name: string): StuffRecord | undefined {\n let candidate = name;\n for (;;) {\n const found = scope.get(candidate);\n if (found !== undefined) return found;\n const dot = candidate.lastIndexOf(\".\");\n if (dot <= 0) return undefined;\n candidate = candidate.slice(0, dot);\n }\n}\n\nfunction conceptKey(concept: ConceptInfo): string {\n return `${concept.domain_code}.${concept.code}`;\n}\n\n/**\n * Bind the invoked pipe's declared inputs from the caller's scope. A name the\n * scope cannot satisfy is a *dangling* input: mint an input stuff\n * (`input:<name>`) with the declared concept — at the method root these are\n * exactly the method's external inputs, and the UI classifies producer-less\n * stuff as role `input`. The `input:` digest namespace is method-global on\n * purpose: an unbound name means the same missing working-memory entry\n * wherever it is read, so all its consumers share one stuff. When two\n * consumers declare *different* concepts for that shared name, the first\n * mint wins and a diagnostic surfaces the authoring inconsistency.\n *\n * Minted dangling inputs are written into `scope`: working memory is one flat\n * namespace shared down the walk (see the scope model note on `walkPipe`), so\n * later readers of the same name bind the same record.\n */\nfunction bindInputs(\n ctx: WalkCtx,\n blueprint: PipeBlueprintUnion,\n scope: Scope,\n): GraphSpecNodeIoItem[] {\n const ioInputs: GraphSpecNodeIoItem[] = [];\n for (const [name, spec] of Object.entries(blueprint.inputs)) {\n let bound = lookupScope(scope, name);\n if (bound === undefined) {\n bound = mintStuff(ctx, `input:${name}`, name, spec.concept, spec.multiplicity);\n scope.set(name, bound);\n if (conceptKey(bound.concept) !== conceptKey(spec.concept)) {\n ctx.diagnostics.push({\n severity: \"warning\",\n code: \"conflicting-input-concept\",\n message:\n `pipe \"${blueprint.code}\": dangling input \"${name}\" is declared as ` +\n `${conceptKey(spec.concept)} here but was first seen as ` +\n `${conceptKey(bound.concept)} — keeping the first`,\n path: `pipe.${blueprint.code}.inputs.${name}`,\n });\n }\n }\n ioInputs.push(ioItem(bound));\n }\n return ioInputs;\n}\n\nfunction emitNode(\n ctx: WalkCtx,\n args: {\n id: string;\n kind: \"controller\" | \"operator\";\n pipeCode: string;\n pipeType: PipeType;\n description: string;\n domainCode: string;\n ioInputs: GraphSpecNodeIoItem[];\n parentId: string | null;\n inv: Invocation;\n },\n): GraphSpecNode {\n const node: GraphSpecNode = {\n id: args.id,\n kind: args.kind,\n pipe_code: args.pipeCode,\n pipe_type: args.pipeType,\n // validateGraphSpec requires a non-empty description; WIP pipes may lack one.\n description: args.description.length > 0 ? args.description : args.pipeCode,\n domain_code: args.domainCode,\n status: \"scheduled\",\n io: { inputs: args.ioInputs, outputs: [] },\n };\n if (args.inv.outcomeValue !== undefined) node.tags = { outcome: args.inv.outcomeValue };\n ctx.nodes.push(node);\n if (args.parentId !== null) {\n addEdge(\n ctx,\n \"contains\",\n args.parentId,\n args.id,\n args.inv.outcomeValue !== undefined ? { label: args.inv.outcomeValue } : undefined,\n );\n }\n return node;\n}\n\n// ─── The walk ────────────────────────────────────────────────────────────────\n\n/**\n * Walk one pipe *invocation*: resolve the ref, emit the node (and its\n * `contains` edge), bind inputs from the caller's scope, recurse per\n * controller type, and report the invocation's output stuff.\n *\n * Scope model — the static mirror of the runtime's working memory, which is\n * ONE flat namespace shared across the whole run (verified against the dry\n * fixtures: a result produced inside a nested sub-sequence is consumed by a\n * later step of an ancestor sequence). So: sequence steps see and mutate the\n * caller's scope *object*; parallel/batch branches and condition outcome\n * children each get a *copy* — branches because the runtime forks memory per\n * branch and merges back only the declared outputs, condition outcomes\n * because they are mutually exclusive alternatives (only one runs, so no\n * branch's writes may be visible to its siblings or, beyond the condition's\n * representative output, to the caller).\n */\nfunction walkPipe(\n ctx: WalkCtx,\n ref: string,\n currentDomain: string,\n nodeId: string,\n parentId: string | null,\n scope: Scope,\n inv: Invocation,\n): WalkResult | null {\n const resolution = resolvePipeRef(ctx.set, ref, currentDomain);\n if (resolution.kind === \"unresolved\") {\n ctx.diagnostics.push({\n severity: \"warning\",\n code: \"unresolved-pipe-ref\",\n message: `pipe ref \"${ref}\" cannot be resolved — node skipped`,\n path: nodeId,\n });\n return null;\n }\n if (resolution.kind === \"opaque\") {\n return emitOpaqueLeaf(ctx, ref, currentDomain, nodeId, parentId, inv);\n }\n\n const { blueprint, domain, code } = resolution;\n const qualified = `${domain}.${code}`;\n const ioInputs = bindInputs(ctx, blueprint, scope);\n const node = emitNode(ctx, {\n id: nodeId,\n kind: blueprint.pipe_category === \"PipeController\" ? \"controller\" : \"operator\",\n pipeCode: code,\n pipeType: blueprint.type,\n description: blueprint.description,\n domainCode: blueprint.domain_code,\n ioInputs,\n parentId,\n inv,\n });\n\n if (ctx.stack.includes(qualified)) {\n ctx.diagnostics.push({\n severity: \"warning\",\n code: \"cyclic-pipe-ref\",\n message: `pipe \"${qualified}\" is invoked recursively — rendered as a leaf`,\n path: nodeId,\n });\n return finishLeaf(ctx, node, blueprint, nodeId, inv);\n }\n\n ctx.stack.push(qualified);\n try {\n switch (blueprint.type) {\n case \"PipeSequence\":\n return finishSequence(ctx, node, blueprint, nodeId, scope, inv);\n case \"PipeParallel\":\n return finishParallel(ctx, node, blueprint, nodeId, scope, inv);\n case \"PipeCondition\":\n return finishCondition(ctx, node, blueprint, nodeId, scope, inv);\n case \"PipeBatch\":\n return finishBatch(ctx, node, blueprint, nodeId, scope, inv);\n default:\n return finishLeaf(ctx, node, blueprint, nodeId, inv);\n }\n } finally {\n ctx.stack.pop();\n }\n}\n\n/**\n * A step (or branch) invocation: a step carrying inline `batch_over`/`batch_as`\n * becomes a synthetic PipeBatch node wrapping the invoked pipe — mirroring the\n * runtime, which materializes `<pipe>_batch` controllers for inline batching.\n */\nfunction walkSubPipe(\n ctx: WalkCtx,\n sub: SubPipeSpec,\n domain: string,\n nodeId: string,\n parentId: string,\n scope: Scope,\n): WalkResult | null {\n if (sub.batch_params !== null) {\n return walkInlineBatch(ctx, sub, domain, nodeId, parentId, scope);\n }\n return walkPipe(ctx, sub.pipe_code, domain, nodeId, parentId, scope, {\n resultName: sub.output_name,\n outputMultiplicity: sub.output_multiplicity,\n });\n}\n\n// ─── Leaf (operators, signatures, cyclic refs) ───────────────────────────────\n\nfunction finishLeaf(\n ctx: WalkCtx,\n node: GraphSpecNode,\n blueprint: PipeBlueprintUnion,\n nodeId: string,\n inv: Invocation,\n): WalkResult {\n const name = inv.resultName ?? snakeCase(blueprint.output.concept.code);\n const multiplicity =\n typeof inv.outputMultiplicity === \"number\" || inv.outputMultiplicity === true\n ? inv.outputMultiplicity\n : blueprint.output.multiplicity;\n const output = mintStuff(ctx, `${nodeId}:${name}`, name, blueprint.output.concept, multiplicity);\n node.io.outputs = [ioItem(output)];\n return { nodeId, output, eachOutputs: [] };\n}\n\n/** Phase-1 policy for `alias->…` dependency refs: an opaque leaf card. */\nfunction emitOpaqueLeaf(\n ctx: WalkCtx,\n ref: string,\n currentDomain: string,\n nodeId: string,\n parentId: string | null,\n inv: Invocation,\n): WalkResult {\n const alias = ref.slice(0, ref.indexOf(\"->\"));\n const tail = ref.slice(ref.lastIndexOf(\"->\") + 2);\n const codeTail = tail.slice(tail.lastIndexOf(\".\") + 1);\n const node = emitNode(ctx, {\n id: nodeId,\n kind: \"operator\",\n pipeCode: codeTail.length > 0 ? codeTail : ref,\n pipeType: \"PipeSignature\",\n description: `External pipe from dependency \"${alias}\"`,\n domainCode: alias.length > 0 ? alias : currentDomain,\n ioInputs: [],\n parentId,\n inv,\n });\n const name = inv.resultName ?? \"output\";\n const output = mintStuff(ctx, `${nodeId}:${name}`, name, nativeConceptInfo(\"Anything\"), null);\n node.io.outputs = [ioItem(output)];\n return { nodeId, output, eachOutputs: [] };\n}\n\n// ─── Controllers ─────────────────────────────────────────────────────────────\n\nfunction finishSequence(\n ctx: WalkCtx,\n node: GraphSpecNode,\n blueprint: PipeSequenceBlueprint,\n nodeId: string,\n scope: Scope,\n inv: Invocation,\n): WalkResult {\n let lastOutput: StuffRecord | null = null;\n blueprint.sequential_sub_pipes.forEach((sub, index) => {\n const result = walkSubPipe(\n ctx,\n sub,\n blueprint.domain_code,\n `${nodeId}/step_${index + 1}`,\n nodeId,\n scope,\n );\n if (result === null) return;\n if (result.output !== null) {\n if (sub.output_name !== null) scope.set(sub.output_name, result.output);\n lastOutput = result.output;\n }\n for (const [name, stuff] of result.eachOutputs) scope.set(name, stuff);\n });\n // Controller transparency: the sequence's output IS its last producing\n // step's stuff — same digest, so downstream consumers wire to the real\n // producer (the UI only takes producers from non-controller nodes).\n node.io.outputs = lastOutput === null ? [] : [ioItem(lastOutput, inv.resultName)];\n return { nodeId, output: lastOutput, eachOutputs: [] };\n}\n\nfunction finishParallel(\n ctx: WalkCtx,\n node: GraphSpecNode,\n blueprint: PipeParallelBlueprint,\n nodeId: string,\n scope: Scope,\n inv: Invocation,\n): WalkResult {\n const branchResults: { sub: SubPipeSpec; result: WalkResult }[] = [];\n blueprint.parallel_sub_pipes.forEach((sub, index) => {\n // Branches are independent: each gets its own copy of the inherited scope.\n const result = walkSubPipe(\n ctx,\n sub,\n blueprint.domain_code,\n `${nodeId}/branch_${index + 1}`,\n nodeId,\n new Map(scope),\n );\n if (result !== null) branchResults.push({ sub, result });\n });\n\n const eachOutputs: [string, StuffRecord][] = [];\n if (blueprint.add_each_output) {\n for (const { sub, result } of branchResults) {\n if (sub.output_name !== null && result.output !== null) {\n eachOutputs.push([sub.output_name, result.output]);\n }\n }\n }\n\n const combinedName =\n blueprint.combined_output ?? inv.resultName ?? snakeCase(blueprint.output.concept.code);\n const combined = mintStuff(\n ctx,\n `${nodeId}:${combinedName}`,\n combinedName,\n blueprint.output.concept,\n blueprint.output.multiplicity,\n );\n for (const { result } of branchResults) {\n if (result.output !== null) {\n addEdge(ctx, \"parallel_combine\", result.nodeId, nodeId, {\n sourceStuff: result.output.digest,\n targetStuff: combined.digest,\n });\n }\n }\n node.io.outputs = [ioItem(combined, inv.resultName)];\n return { nodeId, output: combined, eachOutputs };\n}\n\nfunction finishCondition(\n ctx: WalkCtx,\n node: GraphSpecNode,\n blueprint: PipeConditionBlueprint,\n nodeId: string,\n scope: Scope,\n inv: Invocation,\n): WalkResult {\n const conditionScope: Scope = new Map(scope);\n if (blueprint.add_alias_from_expression_to !== null) {\n const alias = blueprint.add_alias_from_expression_to;\n // The alias points at whatever the expression evaluates to at run time —\n // statically typed as native.Dynamic.\n conditionScope.set(\n alias,\n mintStuff(ctx, `${nodeId}:${alias}`, alias, nativeConceptInfo(\"Dynamic\"), null),\n );\n }\n\n // One child node per distinct *target pipe*, not per outcome value —\n // mirroring the runtime tracer. Outcomes routing to the same pipe (often\n // one value plus `default_outcome`) merge into a single child carrying all\n // its routing values. `fail` / `continue` are outcome actions, not refs.\n // The default route is tracked as a flag, never as a value string — an\n // *authored* outcome value literally named \"default\" must not collide with\n // the synthetic default sentinel (node ids and primary selection key on it).\n interface RouteEntry {\n values: string[];\n ref: string;\n viaDefault: boolean;\n }\n const targets: RouteEntry[] = [];\n const byRef = new Map<string, RouteEntry>();\n const addRoute = (value: string, ref: string, isDefault: boolean): void => {\n if (ref === \"\" || ref === \"fail\" || ref === \"continue\") return;\n const existing = byRef.get(ref);\n if (existing !== undefined) {\n existing.values.push(value);\n existing.viaDefault ||= isDefault;\n return;\n }\n const entry = { values: [value], ref, viaDefault: isDefault };\n byRef.set(ref, entry);\n targets.push(entry);\n };\n for (const [value, target] of Object.entries(blueprint.outcome_map)) {\n addRoute(value, target, false);\n }\n addRoute(\"default\", blueprint.default_outcome, true);\n\n const results: { entry: RouteEntry; result: WalkResult }[] = [];\n for (const entry of targets) {\n const idSegment =\n entry.viaDefault && entry.values.length === 1 ? \"default\" : `outcome_${entry.values[0]}`;\n const result = walkPipe(\n ctx,\n entry.ref,\n blueprint.domain_code,\n `${nodeId}/${idSegment}`,\n nodeId,\n new Map(conditionScope),\n {\n // The runtime stores whichever branch runs under the condition's own\n // slot name, so every branch's output carries it (dry-run parity).\n resultName: inv.resultName,\n outputMultiplicity: null,\n outcomeValue: entry.values.join(\" | \"),\n },\n );\n if (result !== null) results.push({ entry, result });\n }\n\n // Statically all outcomes exist; pick one representative output for the\n // controller (the default route when present, else the first producing\n // outcome) so downstream consumers wire to a real producer.\n const primary =\n results.find(({ entry, result }) => entry.viaDefault && result.output !== null)?.result\n .output ??\n results.find(({ result }) => result.output !== null)?.result.output ??\n null;\n node.io.outputs = primary === null ? [] : [ioItem(primary, inv.resultName)];\n return { nodeId, output: primary, eachOutputs: [] };\n}\n\nfunction finishBatch(\n ctx: WalkCtx,\n node: GraphSpecNode,\n blueprint: PipeBatchBlueprint,\n nodeId: string,\n scope: Scope,\n inv: Invocation,\n): WalkResult {\n const params = blueprint.batch_params;\n\n let listStuff: StuffRecord | null = null;\n if (params.input_list_stuff_name !== \"\") {\n const bound = lookupScope(scope, params.input_list_stuff_name);\n if (bound !== undefined) {\n listStuff = bound;\n } else {\n // The list name is not among the declared inputs (sloppy but legal WIP\n // state): mint it as a dangling input and surface it on the node's io.\n listStuff = mintStuff(\n ctx,\n `input:${params.input_list_stuff_name}`,\n params.input_list_stuff_name,\n nativeConceptInfo(\"Anything\"),\n true,\n );\n node.io.inputs.push(ioItem(listStuff));\n }\n }\n\n let itemStuff: StuffRecord | null = null;\n const branchScope: Scope = new Map(scope);\n if (params.input_item_stuff_name !== \"\" && listStuff !== null) {\n // The item is one element of the list: same concept, single multiplicity.\n itemStuff = mintStuff(\n ctx,\n `${nodeId}:${params.input_item_stuff_name}`,\n params.input_item_stuff_name,\n listStuff.concept,\n null,\n );\n branchScope.set(params.input_item_stuff_name, itemStuff);\n }\n\n const batchMultiplicity = formatBatchMultiplicity(listStuff?.multiplicity);\n addNodeTag(node, \"batch_multiplicity\", batchMultiplicity);\n\n // One representative branch, not N — this is a method view, not a run trace.\n let branchResult: WalkResult | null = null;\n if (blueprint.branch_pipe_code !== \"\") {\n branchResult = walkPipe(\n ctx,\n blueprint.branch_pipe_code,\n blueprint.domain_code,\n `${nodeId}/batch_branch`,\n nodeId,\n branchScope,\n { resultName: null, outputMultiplicity: null },\n );\n const branchNode = ctx.nodes.find((candidate) => candidate.id === branchResult?.nodeId);\n if (branchNode !== undefined) {\n addNodeTag(branchNode, \"batch_multiplicity\", batchMultiplicity);\n }\n }\n\n const aggConcept = branchResult?.output?.concept ?? blueprint.output.concept;\n const aggName = inv.resultName ?? snakeCase(aggConcept.code);\n const aggregate = mintStuff(ctx, `${nodeId}:${aggName}`, aggName, aggConcept, true);\n\n if (branchResult !== null && listStuff !== null && itemStuff !== null) {\n addEdge(ctx, \"batch_item\", nodeId, branchResult.nodeId, {\n sourceStuff: listStuff.digest,\n targetStuff: itemStuff.digest,\n });\n }\n if (branchResult?.output != null) {\n addEdge(ctx, \"batch_aggregate\", branchResult.nodeId, nodeId, {\n sourceStuff: branchResult.output.digest,\n targetStuff: aggregate.digest,\n });\n }\n\n node.io.outputs = [ioItem(aggregate)];\n return { nodeId, output: aggregate, eachOutputs: [] };\n}\n\n/** Synthesize the PipeBatch node the runtime materializes for an inline `batch_over` step. */\nfunction walkInlineBatch(\n ctx: WalkCtx,\n sub: SubPipeSpec,\n domain: string,\n nodeId: string,\n parentId: string,\n scope: Scope,\n): WalkResult {\n const params = sub.batch_params as NonNullable<SubPipeSpec[\"batch_params\"]>;\n // Bare code of the branch ref: strip a dependency alias (`helpers->clean`)\n // and a domain qualifier (`lib.clean`) so the synthetic code reads cleanly.\n const aliasIdx = sub.pipe_code.lastIndexOf(\"->\");\n const refTail = aliasIdx === -1 ? sub.pipe_code : sub.pipe_code.slice(aliasIdx + 2);\n const branchTail = refTail.slice(refTail.lastIndexOf(\".\") + 1);\n const branchResolution = resolvePipeRef(ctx.set, sub.pipe_code, domain);\n const branchBlueprint = branchResolution.kind === \"resolved\" ? branchResolution.blueprint : null;\n\n const listBinding = lookupScope(scope, params.input_list_stuff_name);\n const listConcept =\n listBinding?.concept ??\n branchBlueprint?.inputs[params.input_item_stuff_name]?.concept ??\n nativeConceptInfo(\"Anything\");\n const outputSpec = branchBlueprint?.output ?? {\n concept: nativeConceptInfo(\"Anything\"),\n multiplicity: null,\n };\n\n // Registry key: the detail panel resolves blueprints by `domain.pipe_code`,\n // so every distinct inline batch needs its own entry. Reuse the code only\n // when it already points at this exact batch (same branch, same params);\n // otherwise disambiguate with a numeric suffix (`x_batch`, `x_batch_2`, …).\n const baseCode = `${branchTail}_batch`;\n let code = baseCode;\n for (let suffix = 2; ; suffix++) {\n const existing = ctx.pipeRegistry[`${domain}.${code}`];\n if (\n existing === undefined ||\n (existing.type === \"PipeBatch\" &&\n existing.branch_pipe_code === sub.pipe_code &&\n existing.batch_params.input_list_stuff_name === params.input_list_stuff_name &&\n existing.batch_params.input_item_stuff_name === params.input_item_stuff_name)\n ) {\n break;\n }\n code = `${baseCode}_${suffix}`;\n }\n const blueprint: PipeBatchBlueprint = {\n type: \"PipeBatch\",\n pipe_category: \"PipeController\",\n code,\n domain_code: domain,\n description: `Batch processing for ${branchTail}`,\n inputs: { [params.input_list_stuff_name]: { concept: listConcept, multiplicity: null } },\n output: { concept: outputSpec.concept, multiplicity: null },\n branch_pipe_code: sub.pipe_code,\n batch_params: params,\n };\n ctx.pipeRegistry[`${domain}.${code}`] ??= blueprint;\n\n const ioInputs = bindInputs(ctx, blueprint, scope);\n const inv: Invocation = {\n resultName: sub.output_name,\n outputMultiplicity: sub.output_multiplicity,\n };\n const node = emitNode(ctx, {\n id: nodeId,\n kind: \"controller\",\n pipeCode: code,\n pipeType: \"PipeBatch\",\n description: blueprint.description,\n domainCode: domain,\n ioInputs,\n parentId,\n inv,\n });\n return finishBatch(ctx, node, blueprint, nodeId, scope, inv);\n}\n","// Bridge from static-analysis diagnostics to the viewer's validation panel.\n\nimport type { ValidationIssue } from \"@graph/types\";\nimport type { Diagnostic } from \"./types\";\n\n/**\n * Derive the viewer targeting fields from a diagnostic's TOML-style `path`.\n *\n * - A walk-phase path is a GraphSpec node id and contains `/` (e.g.\n * `demo.main_flow/step_2`) → `nodeId`. Checked first: node ids embed the\n * domain, so a prefix test alone could misread them.\n * - A declaration path `pipe.<code>[...]` → `pipeCode`.\n * - Everything else (concept paths, bare section paths like `pipe`, root\n * entry-pipe ids without `/`, missing paths) has no graph target — those\n * issues stay panel-only.\n */\nfunction targetFromPath(path: string | undefined): Pick<ValidationIssue, \"pipeCode\" | \"nodeId\"> {\n if (!path) return {};\n if (path.includes(\"/\")) return { nodeId: path };\n if (path.startsWith(\"pipe.\")) {\n const code = path.split(\".\")[1];\n if (code) return { pipeCode: code };\n }\n return {};\n}\n\n/**\n * Project static-graph {@link Diagnostic}s onto the viewer's presentation shape\n * so a host can feed them straight into `GraphViewer`'s `validationIssues`.\n * The TOML-style `path` becomes the locator chip; `origin: \"static\"` lets the\n * panel (and the host's issue policy) distinguish them from validator verdicts.\n * When the path identifies a pipe declaration or a precise invocation, the\n * targeting fields (`pipeCode` / `nodeId`) are filled so the viewer can\n * decorate the affected graph nodes.\n */\nexport function staticDiagnosticsToValidationIssues(diagnostics: Diagnostic[]): ValidationIssue[] {\n return diagnostics.map((diagnostic) => ({\n severity: diagnostic.severity,\n message: diagnostic.message,\n context: diagnostic.path,\n origin: \"static\",\n ...targetFromPath(diagnostic.path),\n }));\n}\n"],"mappings":"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","names":["spec","_a","_b"]}
|
|
@@ -4,6 +4,21 @@ type PipeType = PipeOperatorType | PipeControllerType;
|
|
|
4
4
|
/** Every pipe class name pipelex emits as `pipe_type`. Used by validateGraphSpec. */
|
|
5
5
|
declare const KNOWN_PIPE_TYPES: ReadonlySet<string>;
|
|
6
6
|
type PipeStatus = "succeeded" | "failed" | "running" | "scheduled" | "skipped" | "canceled";
|
|
7
|
+
declare const GRAPH_SPEC_MODE: {
|
|
8
|
+
readonly DRY: "dry";
|
|
9
|
+
readonly LIVE: "live";
|
|
10
|
+
readonly STATIC: "static";
|
|
11
|
+
};
|
|
12
|
+
type GraphSpecMode = (typeof GRAPH_SPEC_MODE)[keyof typeof GRAPH_SPEC_MODE];
|
|
13
|
+
interface GraphSpecMeta {
|
|
14
|
+
format: "mthds";
|
|
15
|
+
/**
|
|
16
|
+
* Missing mode is a legacy runtime graph. Static UI behavior must key only on
|
|
17
|
+
* `mode === "static"` and never infer it from absent runtime fields.
|
|
18
|
+
*/
|
|
19
|
+
mode?: GraphSpecMode;
|
|
20
|
+
[key: string]: unknown;
|
|
21
|
+
}
|
|
7
22
|
declare const NODE_TYPE_PIPE_CARD: "pipeCard";
|
|
8
23
|
declare const NODE_TYPE_STUFF: "default";
|
|
9
24
|
declare const NODE_TYPE_CONTROLLER: "controllerGroup";
|
|
@@ -204,7 +219,7 @@ interface PipeExtractBlueprint extends PipeBlueprintBase {
|
|
|
204
219
|
render_js: boolean | null;
|
|
205
220
|
include_raw_html: boolean | null;
|
|
206
221
|
image_stuff_name: string | null;
|
|
207
|
-
document_stuff_name: string;
|
|
222
|
+
document_stuff_name: string | null;
|
|
208
223
|
}
|
|
209
224
|
interface PipeSearchBlueprint extends PipeBlueprintBase {
|
|
210
225
|
type: "PipeSearch";
|
|
@@ -291,10 +306,13 @@ interface GraphSpec {
|
|
|
291
306
|
};
|
|
292
307
|
nodes: GraphSpecNode[];
|
|
293
308
|
edges: GraphSpecEdge[];
|
|
294
|
-
meta?:
|
|
309
|
+
meta?: GraphSpecMeta;
|
|
295
310
|
pipe_registry?: Record<string, PipeBlueprintUnion>;
|
|
296
311
|
concept_registry?: Record<string, ConceptInfo>;
|
|
297
312
|
}
|
|
313
|
+
declare function graphSpecMode(spec: Pick<GraphSpec, "meta"> | null | undefined): GraphSpecMode | undefined;
|
|
314
|
+
declare function isStaticGraphSpec(spec: Pick<GraphSpec, "meta"> | null | undefined): boolean;
|
|
315
|
+
declare function isDryGraphSpec(spec: Pick<GraphSpec, "meta"> | null | undefined): boolean;
|
|
298
316
|
interface DataflowAnalysis {
|
|
299
317
|
readonly stuffRegistry: Readonly<Record<string, {
|
|
300
318
|
name: string;
|
|
@@ -394,6 +412,65 @@ type ToolbarSide = "left" | "center" | "right";
|
|
|
394
412
|
* — exactly like {@link toolbarOrientation}.
|
|
395
413
|
*/
|
|
396
414
|
declare function toolbarSide(position: ToolbarPosition): ToolbarSide;
|
|
415
|
+
/**
|
|
416
|
+
* State of the toolbar's validation widget. The widget itself is opt-in: it
|
|
417
|
+
* renders only when the host passes a `validationState` to `GraphViewer` —
|
|
418
|
+
* `undefined` (the default) keeps it hidden entirely. The states describe the
|
|
419
|
+
* host's validation lifecycle, not the static analyzer's: `validating` while a
|
|
420
|
+
* verdict is being produced, `valid`/`invalid` once one exists, and `error`
|
|
421
|
+
* when no verdict could be produced at all (validator unavailable, timeout…).
|
|
422
|
+
*/
|
|
423
|
+
declare const VALIDATION_STATE: {
|
|
424
|
+
readonly VALIDATING: "validating";
|
|
425
|
+
readonly VALID: "valid";
|
|
426
|
+
readonly INVALID: "invalid";
|
|
427
|
+
readonly ERROR: "error";
|
|
428
|
+
};
|
|
429
|
+
type ValidationState = (typeof VALIDATION_STATE)[keyof typeof VALIDATION_STATE];
|
|
430
|
+
/**
|
|
431
|
+
* One issue row in the validation panel. Mostly presentation: the host decides
|
|
432
|
+
* which issues to show for each state (its validator's errors, the static
|
|
433
|
+
* analyzer's diagnostics, or a mix) and handles navigation on row click. The
|
|
434
|
+
* only fields the viewer interprets are the optional targeting fields
|
|
435
|
+
* (`pipeCode` / `nodeId`), which drive node decorations on the graph.
|
|
436
|
+
*/
|
|
437
|
+
interface ValidationIssue {
|
|
438
|
+
severity: "error" | "warning";
|
|
439
|
+
message: string;
|
|
440
|
+
/** Short locator chip, e.g. `pipe.analyze_candidate` or a TOML path. */
|
|
441
|
+
context?: string;
|
|
442
|
+
/** Owning-file basename, when the issue lives in a specific file. */
|
|
443
|
+
file?: string;
|
|
444
|
+
/** Human-readable suggested fix, when the validator derived one. */
|
|
445
|
+
suggestedFix?: string;
|
|
446
|
+
/** Which analyzer produced the issue: the host's validator or the static parser. */
|
|
447
|
+
origin?: "validator" | "static";
|
|
448
|
+
/**
|
|
449
|
+
* Pipe code this issue targets — decorates every rendered node invoking that
|
|
450
|
+
* pipe (a pipe can be invoked from several places in the graph).
|
|
451
|
+
*/
|
|
452
|
+
pipeCode?: string;
|
|
453
|
+
/**
|
|
454
|
+
* Precise invocation this issue targets — a GraphSpec node id (e.g.
|
|
455
|
+
* `demo.main_flow/step_2`). Takes precedence over `pipeCode` when both are
|
|
456
|
+
* set. Issues with neither targeting field stay panel-only.
|
|
457
|
+
*/
|
|
458
|
+
nodeId?: string;
|
|
459
|
+
}
|
|
460
|
+
/**
|
|
461
|
+
* Aggregated validation decoration for one rendered node — derived from the
|
|
462
|
+
* targeted `ValidationIssue`s by `buildValidationDecorations` (worst severity
|
|
463
|
+
* wins, folded controllers roll up their hidden descendants' issues). Rendered
|
|
464
|
+
* as a severity ring + count badge on the node, with `lines` as the tooltip.
|
|
465
|
+
*/
|
|
466
|
+
interface NodeValidationSummary {
|
|
467
|
+
/** Worst severity among the node's issues (`error` wins over `warning`). */
|
|
468
|
+
severity: "error" | "warning";
|
|
469
|
+
/** Number of issue hits on the node (a multi-instance pipe counts per invocation). */
|
|
470
|
+
count: number;
|
|
471
|
+
/** Tooltip lines: each issue's message, followed by a `Fix: …` line when present. */
|
|
472
|
+
lines: string[];
|
|
473
|
+
}
|
|
397
474
|
interface GraphConfig {
|
|
398
475
|
direction?: GraphDirection;
|
|
399
476
|
showControllers?: boolean;
|
|
@@ -440,6 +517,7 @@ interface PipeCardPayload {
|
|
|
440
517
|
pipeType: PipeType;
|
|
441
518
|
description?: string;
|
|
442
519
|
status: PipeStatus;
|
|
520
|
+
graphMode?: GraphSpecMode;
|
|
443
521
|
inputs: {
|
|
444
522
|
name: string;
|
|
445
523
|
concept: string;
|
|
@@ -448,12 +526,18 @@ interface PipeCardPayload {
|
|
|
448
526
|
name: string;
|
|
449
527
|
concept: string;
|
|
450
528
|
}[];
|
|
529
|
+
/** Authored/static annotations and runtime tags carried by the GraphSpec node. */
|
|
530
|
+
tags?: Record<string, string>;
|
|
451
531
|
/** Layout direction — injected by the layout engine */
|
|
452
532
|
direction?: "LR" | "TB";
|
|
453
533
|
/** When set, the card renders an unfold button that invokes this callback. */
|
|
454
534
|
onExpand?: (options?: FoldToggleOptions) => void;
|
|
535
|
+
/** Validation decoration (severity ring + count badge), stamped by GraphViewer. */
|
|
536
|
+
validation?: NodeValidationSummary;
|
|
537
|
+
/** Badge click handler (opens the validation panel), stamped alongside `validation`. */
|
|
538
|
+
onValidationBadgeClick?: () => void;
|
|
455
539
|
}
|
|
456
|
-
type StuffRole = "input" | "output";
|
|
540
|
+
type StuffRole = "input" | "output" | "combined";
|
|
457
541
|
interface GraphNodeData extends Record<string, unknown> {
|
|
458
542
|
labelDescriptor?: LabelDescriptor;
|
|
459
543
|
label?: unknown;
|
|
@@ -464,11 +548,16 @@ interface GraphNodeData extends Record<string, unknown> {
|
|
|
464
548
|
labelText: string;
|
|
465
549
|
pipeCode?: string;
|
|
466
550
|
pipeType?: PipeType;
|
|
551
|
+
graphMode?: GraphSpecMode;
|
|
467
552
|
pipeCardData?: PipeCardPayload;
|
|
468
553
|
/** For stuff nodes: "input" (no producer), "output" (no consumer), or undefined (intermediate). */
|
|
469
554
|
stuffRole?: StuffRole;
|
|
470
555
|
/** For stuff nodes: the digest used to build the node ID. */
|
|
471
556
|
stuffDigest?: string;
|
|
557
|
+
/** Validation decoration (severity ring + count badge), stamped by GraphViewer. */
|
|
558
|
+
validation?: NodeValidationSummary;
|
|
559
|
+
/** Badge click handler (opens the validation panel), stamped alongside `validation`. */
|
|
560
|
+
onValidationBadgeClick?: () => void;
|
|
472
561
|
}
|
|
473
562
|
interface GraphNode {
|
|
474
563
|
id: string;
|
|
@@ -519,4 +608,4 @@ declare const ARROW_CLOSED_MARKER = "arrowclosed";
|
|
|
519
608
|
declare function nodeWidth(n: GraphNode): number;
|
|
520
609
|
declare function nodeHeight(n: GraphNode): number;
|
|
521
610
|
|
|
522
|
-
export { type
|
|
611
|
+
export { type PipeBlueprintBase as $, ARROW_CLOSED_MARKER as A, GRAPH_DIRECTION as B, type ConceptInfo as C, type DataflowAnalysis as D, EDGE_TYPE as E, type FoldMode as F, type GraphSpec as G, GRAPH_SPEC_MODE as H, GRAPH_THEME as I, GRAPH_THEME_MODE as J, type GraphSpecEdge as K, type LabelDescriptor as L, type GraphSpecEdgeKind as M, type NodeValidationSummary as N, type GraphSpecMeta as O, type PipeBlueprintUnion as P, type GraphSpecNodeError as Q, type GraphSpecNodeIo as R, type GraphSpecNodeTiming as S, type ToolbarPosition as T, KNOWN_PIPE_TYPES as U, type ValidationIssue as V, NODE_TYPE_CONTROLLER as W, NODE_TYPE_PIPE_CARD as X, NODE_TYPE_STUFF as Y, type NodeKind as Z, type PipeBatchBlueprint as _, type GraphNodeData as a, type PipeComposeBlueprint as a0, type PipeComposeConstructBlueprint as a1, type PipeComposeConstructField as a2, type PipeConditionBlueprint as a3, type PipeExtractBlueprint as a4, type PipeFuncBlueprint as a5, type PipeImgGenBlueprint as a6, type PipeLLMBlueprint as a7, type PipeParallelBlueprint as a8, type PipeSearchBlueprint as a9, type PipeSequenceBlueprint as aa, type PipeSignatureBlueprint as ab, type PipeStructureBlueprint as ac, STUFF_ID_PREFIX as ad, type StuffRole as ae, type StuffSpecInfo as af, type SubPipeSpec as ag, TOOLBAR_POSITION as ah, type TemplateBlueprint as ai, type ToolbarOrientation as aj, type ToolbarSide as ak, VALIDATION_STATE as al, graphSpecMode as am, isDryGraphSpec as an, isStaticGraphSpec as ao, isStuffNodeId as ap, nodeHeight as aq, nodeWidth as ar, stuffDigestFromId as as, stuffNodeId as at, toolbarOrientation as au, toolbarSide as av, type GraphEdge as b, type GraphNode as c, type GraphConfig as d, type GraphDirection as e, type GraphThemeMode as f, type GraphTheme as g, type PipeStatus as h, type ValidationState as i, type PipeControllerType as j, type FoldToggleOptions as k, type PipeType as l, type GraphSpecMode as m, type GraphSpecNode as n, type GraphSpecNodeIoItem as o, type PipeOperatorType as p, type PipeCallNode as q, type GraphData as r, type PipeCardPayload as s, type LayoutConfig as t, CONTROLLER_PADDING_BOTTOM as u, CONTROLLER_PADDING_TOP as v, CONTROLLER_PADDING_X as w, type EdgeType as x, FOLD_MODE as y, type FieldResolution as z };
|
package/package.json
CHANGED
|
@@ -1,6 +1,6 @@
|
|
|
1
1
|
{
|
|
2
2
|
"name": "@pipelex/mthds-ui",
|
|
3
|
-
"version": "0.
|
|
3
|
+
"version": "0.14.0",
|
|
4
4
|
"description": "Shared graph rendering logic for MTHDS method visualization",
|
|
5
5
|
"license": "MIT",
|
|
6
6
|
"repository": {
|
|
@@ -39,6 +39,10 @@
|
|
|
39
39
|
"./shiki": {
|
|
40
40
|
"import": "./dist/shiki/index.js",
|
|
41
41
|
"types": "./dist/shiki/index.d.ts"
|
|
42
|
+
},
|
|
43
|
+
"./static-graph": {
|
|
44
|
+
"import": "./dist/static-graph/index.js",
|
|
45
|
+
"types": "./dist/static-graph/index.d.ts"
|
|
42
46
|
}
|
|
43
47
|
},
|
|
44
48
|
"files": [
|
|
@@ -65,7 +69,8 @@
|
|
|
65
69
|
"dependencies": {
|
|
66
70
|
"@xyflow/react": "^12",
|
|
67
71
|
"dompurify": "^3.3.3",
|
|
68
|
-
"elkjs": "^0.11.1"
|
|
72
|
+
"elkjs": "^0.11.1",
|
|
73
|
+
"smol-toml": "^1.7.0"
|
|
69
74
|
},
|
|
70
75
|
"peerDependencies": {
|
|
71
76
|
"react": "^19",
|
package/dist/chunk-L24K3TZU.js
DELETED
|
@@ -1 +0,0 @@
|
|
|
1
|
-
//# sourceMappingURL=chunk-L24K3TZU.js.map
|