# @smithers-orchestrator/graph — src

The framework-neutral workflow graph model. `types.ts` is the source of truth;
the one-type-per-file `.ts` sidecars (`TaskDescriptor.ts`, `GraphSnapshot.ts`,
`XmlNode.ts`, ...) exist so JSDoc `import("./Foo.ts")` references stay granular.
Implementation is JSDoc-typed `.js` — never convert `.js` <-> `.ts`.

Two extraction pipelines coexist:

- `extract.js` — the core `extractGraph` (exported from `index.js`, aliased as
  `extractFromHost`): turns a reconciler `HostNode` tree into a `WorkflowGraph`
  of `TaskDescriptor`s plus the serialized XML tree.
- `dom/extract.js` — the legacy `extractFromHost`, which additionally attaches
  runtime `computeFn` handlers to `<Subflow>`/`<Sandbox>` tasks. See its
  `TODO(migration)`: the two intentionally duplicate helpers (heartbeat
  defaults, retry config, loop scoping, ...) until it is retired.

`validateForkSources.js` and `worktree-path.js` support extraction;
`utils/tree-ids.js` provides the stable path-based ids both extractors share.

Claude Code /workflows phase plans: `buildClaudeWorkflowPhasePlan.js` is the
shared walk; `deriveClaudeWorkflowPhases.js` feeds it a live `GraphSnapshot`,
`deriveClaudeWorkflowPhasesFromFrame.js` feeds it a persisted frame row, and
`classifyClaudeWorkflowNodeKind.js` classifies descriptors into node kinds
(the engine also stamps these onto persisted frames).

Gotchas: `index.d.ts` is generated by `pnpm build` (tsup --dts-only) — do not
hand-edit. The `// @smithers-type-exports-begin/end` blocks are tool-managed
byte-for-byte. The subpaths `./constants`, `./utils/xml`, and
`./classifyClaudeWorkflowNodeKind` ship hand-written sibling `.d.ts` files
enforced by `tests/subpath-exports-types.test.js`. `types.ts` is public type
surface: driver, components, and react-reconciler deep-import
`@smithers-orchestrator/graph/types`.
