Public entry point for @causl/devtools.

I won't make the engine "live" by bolting a devtools panel onto the side. The engine is inspectable through its own primitives: graph.explain(node) returns another node — a derived view of the dependency lineage that can itself be subscribed to, displayed, drilled into. The transaction log is a Behavior [Commit] — queryable by the same API as any other graph value. A REPL connected to a running graph can mutate, replace, and replay derivations without restarting the host process. Devtools become a UI rendered on top of those primitives, not a parallel system. If I cannot demo "edit a derivation while it's running, watch the change propagate," I have not earned the comparison to spreadsheets.

This package re-exports those primitives in UI-friendly shapes: a commit-log buffer, node inspector, statechart configuration view, lineage explainers (whyUpdated / whyNotUpdated), live-derivation REPL handles, and snapshot export/import. Each export is a thin surface over @causl/core so a devtools UI can render directly on top of the engine without a parallel state model.

@causl/devtools

Inspection primitives for Causl.

Transactional state for tangled dependency graphs.

Shipped as of v0.9.0. Sits on top of @causl/causl-wasm-ts. The animating principle is that the engine should be inspectable through its own primitives, not through a parallel devtools panel sitting next to it. So this package surfaces the things a non-programmer would expect of a spreadsheet: see a value change, drill into why, edit a derivation while it runs: by composing the same derived / subscribe API every consumer already uses.

All seven primitives listed under Surface are implemented and exercised by the package's test suite. The inspector UI that consumes them lives in @causl/devtools-bridge (read-only host channel using the narrow capability slice Pick<Graph, 'read' | 'subscribeCommits' | 'now' | 'commitLog' | 'snapshotAt' | 'readAt' | 'dependencies' | 'dependents'>, per SPEC §13: no commit, no hydrate, JUMP is view-only).

Exports mirror src/index.ts. Every primitive is a thin wrapper over @causl/causl-wasm-ts; nothing here is a parallel state model.

  • inspect(graph, node) / watchInspect(graph, node, observer): current value, deps, dependents (each itself a derived node), with watchInspect emitting a fresh view on every commit that touches the node. The README's earlier nodeInspector binding never shipped; this is the surface.
  • whyUpdated(graph, node) / whyNotUpdated(graph, node): last-commit lineage of changes, and the same for non-recompute deltas (an equality cutoff fired, a dep was unchanged, etc.). Both return a DerivedNode<WhyResult> per §11 ("the engine is its own observer"): subscribe to the returned node and the engine pushes a fresh classification on the same commit that produced it (Phase F.5, post-commitLog refresh). Memoised per (graph, node) so repeated calls share identity. Pair with renderWhy for a UI-ready string.
  • liveDerived(graph, id, compute) / replaceMany(graph, edits): REPL-style swap of compute closures without restarting the host process. This is the §11 "edit a derivation while it's running, watch the change propagate" commitment; without it the comparison to spreadsheets is unearned.
  • statechart(graph) / renderStatechartMermaid(config): current Engine-region state (Idle | Committing) for UI rendering, plus a Mermaid renderer for the same composite chart drawn in docs/lifecycle.md §1.
  • exportSnapshot(graph, options) / importSnapshot(graph, snapshot, options): structured snapshot of input values at the current GraphTime, replay onto a fresh graph. Derived values are not serialised: per the §3 denotational definition they are pure functions of their inputs at the same t and are reconstructed on import. The envelope is versioned (Snapshot.schema) and bumps fail loudly on mismatch. exportSnapshotJson / importSnapshotJson are the string-shaped variants for transport across processes or storage.
  • commitLog(graph, options?): bounded, most-recent-first projection of the engine's commit stream as a DerivedNode<readonly Commit[]>. The canonical transaction log lives on @causl/causl-wasm-ts itself as graph.commitLog: DerivedNode<readonly Commit[]> (SPEC §12.2 / EPIC #283). The devtools wrapper is sugar: a capped, reverse-chronological view registered through graph.commitMetadataDerived so subscribers fire on the same commit that produced the entry (Phase F.5). Memoised per (graph, id). Reach for graph.commitLog first; use this wrapper when bounded memory or newest-first ordering is the actual requirement.

Devtools UI lives downstream; this package is the data layer that the UI is rendered on top of, rather than a parallel system.

Interfaces

CommitLogOptions
ExportOptions
ImportOptions
LiveDerivedHandle
NodeInspectorView
Snapshot
StatechartConfiguration
WhyResult

Type Aliases

CommitLogGraph
EngineState
InspectorGraph
SnapshotReadGraph
StatechartGraph
WhyGraph
WhyNotUpdatedResult
WhyReason
WhyUpdatedResult

Variables

VERSION

Functions

commitLog
exportSnapshot
exportSnapshotJson
importSnapshot
importSnapshotJson
inspect
liveDerived
renderStatechartMermaid
renderWhy
replaceMany
statechart
watchInspect
whyNotUpdated
whyUpdated