# @smithers-orchestrator/devtools — src

Dependency-free inspection utilities for Smithers runs, in three clusters:

1. **Tree utilities over `DevToolsNode`** — `buildSnapshot`, `countNodes`,
   `collectTasks`, `findNodeById`, `printTree`, `SMITHERS_NODE_ICONS` — fronted
   by the `SmithersDevToolsCore` facade.
2. **Engine-event reduction** — `DevToolsRunStore` folds `DevToolsEngineEvent`
   streams into `RunExecutionState` / `TaskExecutionState`, with FIFO retention
   caps for runs and per-run events.
3. **Snapshot wire format** — `snapshotSerialize` produces JSON-safe props;
   `diffSnapshots` / `applyDelta` / `InvalidDeltaError` operate on the seq'd
   `DevToolsSnapshotV1`.

Conventions: one export per `.js` file, named after the file; `.ts` files are
type-only sidecars; `index.d.ts` is generated by `tsup --dts-only` — never
hand-edit it. `index.js` re-exports the public surface, and its `@typedef`
block feeds the generated type exports. Every filename participates in the
package's `./*` subpath export map, so files must not be renamed casually.

Key consumers: `packages/react-reconciler` (`SmithersDevToolsCore`,
`printTree`), `packages/server` gateway routes (`diffSnapshots`,
`snapshotSerialize`), `apps/cli` `tree.js` and `packages/pi-plugin`
(`applyDelta`).

Gotchas: `DevToolsSnapshot` (`buildSnapshot` output, tree + counts) and
`DevToolsSnapshotV1` (versioned seq'd wire snapshot for diff/apply) are
different shapes. `findNodeById` matches `task.nodeId` (string), while
`applyDelta`'s internal lookup matches `DevToolsNode.id` (number).
`NodeRetrying` intentionally revives terminal-failed tasks in
`DevToolsRunStore` (backs `smithers retry-task`).
