Skip to content

signals: fixes and improvements for the Signals inspector #346

Closed

Description

@erkamyaman

Context

Fixes and improvements from a code audit of the signals inspector, done in October 2026. Roadmap work lives in #340, #341, #342 and #343. Items marked (to confirm) were not reproduced; check them before fixing.

Problems

Medium

  • Write hook cost: the write hook serializes every write to every named signal, even when no panel or agent is listening and the signal is not in the reported graph. Hot signals (pointer position, animation frames, typing) pay serialize synchronously inside Angular's set path. Keep the raw value and version on write and serialize lazily in collect() only for tracks bound to graph nodes, or keep only the latest value per track per microtask (packages/devtools/src/signal-history.ts:58-63, installed in packages/devtools/src/overlay.ts:250).
  • Unnamed writes dropped silently: onWrite returns early when node.debugName is missing, so those signals get only sample history and nothing says why. Only resources show a debugName hint. Add the same hint on (unnamed) cards and on histories with only sampled entries, and say which Angular version adds names automatically (packages/devtools/src/signal-history.ts:42-43, app/src/pages/signal-inspector.ts:384, :485).

Low

  • Track eviction is FIFO, not LRU: tracks.delete(tracks.keys().next().value!) evicts the oldest created track, and existing tracks are never re-inserted on write, so a signal written constantly loses its exact history once 500 newer signals exist. Re-insert on write and prefer tracks whose WeakRef is dead (packages/devtools/src/signal-history.ts:56).
  • History owner ignores injectors: the delta owner is graph.component?.id ?? '', so switching between environment injector graphs sends a delta, and the server merges prev?.history?.[id] by node id without checking the owner. Use graph.component?.id ?? graph.injector?.id ?? '', and drop the previous history on the server when the owner changed (packages/devtools/src/overlay.ts:271, packages/devtools/src/devframe.ts:1446-1449).
  • Quadratic dependency lookups: getDependencies and getConsumers each run findIndex plus an edges filter, and the template calls them up to four times per card. Precompute a computed() map of id to deps and consumers once per graph (app/src/pages/signal-inspector.ts:498-504, :1637-1655).
  • Filter matches every resource: 'resource'.includes(q) makes queries such as e, so or our list all resources. Match the kind only on a prefix of at least 3 characters, or leave it to the kind chips (app/src/pages/signal-inspector.ts:1365).
  • Peeks only take environment injectors: toPeekRequest requires env, so inspect-signals tells agents to call pangular:highlight first, which moves the user's selection on the Signals page. Accept { id } or { selector } in SignalPeekRequest, reuse SignalTarget, and update the tool description (packages/devtools/src/signal-peek.ts:16-41, packages/devtools/src/devframe.ts:1976).
  • Live nodes not linked to source: the source-scan signals (file, line, component) only show when there is no live graph. Match live nodes to source entries by label and component class name, show file:line on the card, and show nothing when the match is ambiguous. Open in editor itself is tracked in phase 1 of 4: safe by default and wired into your workflow #340 (app/src/pages/signal-inspector.ts:283-311).
  • linkedSignal writes may skip the hook: the history relies only on setPostSignalSetFn, and no test writes to a named linkedSignal. Add a real-Angular test that asserts a write entry; if it fails, hook linkedSignal writes another way or document the limit (packages/devtools/src/signal-history.ts:190-221, packages/devtools/src/__tests__/signal-history.test.ts) (to confirm).

Improvements

  • Restore a past value from the history list once signal editing (phase 2 of 4: deeper inspection #341) lands, as a one-click undo (app/src/pages/signal-inspector.ts, packages/devtools/src/signal-history.ts).
  • Show a JSON diff between consecutive history entries instead of the full value each time (app/src/pages/signal-inspector.ts).
  • Effect run counts and durations per effect node, if Angular exposes a hook, to spot runaway effects (packages/devtools/src/signal-graph.ts, app/src/pages/signal-inspector.ts).
  • Count unnamed signals in the inspect-signals answer, so agents can suggest adding debugName (packages/devtools/src/rpc/signal-tools.ts).

Already tracked elsewhere


Generated by Claude Code

Metadata

Metadata

Assignees

No one assigned

    Labels

    bugSomething is broken or shows wrong datafeatureA feature request or a pull request that adds one

    Type

    No type

    Projects

    No projects

      Milestone

      No milestone

      Relationships

      None yet

      Development

      No branches or pull requests

      Issue actions