Symptom

On an LLM node, EditLLM → Sources tab behaved as if read-only: checkboxes (“Invoked By”) and radio buttons (NodeAction) would not toggle, and picking a source via “Add Source” did not add it. The same tab worked for every other node type. Only LLM reproduced it.

Root cause

NodeMetaData.withWiring(...) in shared/.../node/NodeMetaDataSourceWiring.kt is the single write path the centralized SourcesTab uses for all ~25 targeting node types. It guards on this !is TargetingNodeMetaData (LLM passes — LLMMetaData does implement TargetingNodeMetaData), then dispatches on a per-subtype when that must call each concrete data class’s copy(...). LLMMetaData was never added to that when, so it fell through to else -> this and returned the metadata unchanged. Every edit persisted a no-op, so the UI snapped back to the unchanged state and looked read-only. The sibling helper withParentSourceDefault(...) had the identical gap. LLMMetaData was added in the SDK (verb-driven LLM work) but never wired into these two repo-local when blocks — exactly the failure mode the function’s own doc comment warns about (“added to both arms or its wiring will silently be uneditable”).

Fix

Added is LLMMetaData -> copy(sources = ..., executionSource = ..., nodeAction = ...) arms to both withWiring and withParentSourceDefault, plus the krill.zone.shared.krillapp.server.llm.* import. Verified by a new TDD test (NodeMetaDataWithWiringTest."llm meta round-trips wiring") that failed before the fix and passes after, and by a programmatic diff of all SDK TargetingNodeMetaData implementors against the when arms (empty — LLM was the only gap).

Prevention

The two when blocks are hand-maintained mirrors of the SDK’s TargetingNodeMetaData hierarchy, and the compiler cannot enforce exhaustiveness against an external sealed-elsewhere set, so a new SDK targeting type silently degrades to else -> this. Best guard: a unit test that asserts withWiring actually mutates (not === this) for every targeting type — or, better, an exhaustiveness check that fails CI when an SDK TargetingNodeMetaData subtype is absent from both arms. Until that exists, treat “add a targeting node type” as requiring edits to both arms of NodeMetaDataSourceWiring.kt and a round-trip test.