Skip to content

streams: installing the streams plugin does not wire its env into dependent services (install order silently changes behaviour) #1067

Description

@rickylabs

Summary

Installing the streams plugin does not wire its environment into the services that depend on it.
Every other plugin surface behaves as though it does, so agents and developers reasonably assume
netscript plugin install stream is sufficient — and then producers silently fail to deliver.

Two independent wave-four agents hit this from opposite directions in the same night.

Evidence 1 — install order silently changes the result (run 1, Claude Fable 5)

Plugins installed in the order workers → sagas → streams. The streams install did not
retro-wire PluginReferences: ["streams"] into the already-installed sagas-api / workers-api
entries in appsettings.json, so those services had no route to the durable-stream transport.

The symptom was not an error. POST /api/v1/sagas/publish blocked instead of failing:

[DurableStreamProducer] Could not connect to stream "/sagas/instances": Durable streams URL not
found. Expected DURABLE_STREAMS_URL or services__streams__http__0 ... Writes will be dropped
until reconnect.

That hint appears in the startup log of a different process, two hops from where the request
hangs. Cost: ~25 minutes, and it presented as a bug in the agent's own service handler.

Fixed by hand-adding the references, re-running netscript service generate, and restarting.

Evidence 2 — a capability was abandoned because of it (run 2, Grok 4.5)

From its published article, unprompted:

"I did not build full durable-stream SSE hydration in the island. Producers needed
DURABLE_STREAMS_URL / Aspire streams env that was easy to miss; the board refetches on an
interval and still shows motion. That is a deferred edge, said plainly."

So the framework's live-update story — one of the four capabilities the demo brief is built around —
was replaced with interval polling because the wiring was easy to miss. The agent did not
consider this a framework bug; it took the blame itself and shipped a downgrade.

That is the more damaging outcome of the two: no drift entry, no issue, just a quieter product.

Expected

netscript plugin install stream should wire the streams environment into dependent services the
way the rest of the plugin surface behaves — regardless of install order. Concretely, at least
one of:

  • The streams install patches PluginReferences on already-installed dependent services, or
  • Service generation resolves stream references at generate time rather than install time, so order
    cannot matter, or
  • A producer with no reachable streams URL fails fast and loudly at startup in the dependent
    service, naming the missing reference and the fix — instead of a warning in another process's log
    followed by dropped writes and a blocking publish.

The current behaviour fails all three: order matters, nothing retro-wires, and the failure is silent
in the place it actually manifests.

Acceptance

  • Installing plugins in any order produces the same wiring; workers → sagas → streams and
    streams → sagas → workers yield identical appsettings.json references
  • A service that produces to a durable stream with no reachable streams URL fails at startup
    with an actionable message, or the producer call errors — it never blocks indefinitely and
    never silently drops writes
  • An E2E case covers install-order permutations for a stream-dependent plugin
  • Docs state the dependency explicitly if any manual step genuinely remains

Why this is worth prioritising above its apparent severity

It does not just cost debugging time — it silently degrades products. One agent lost 25 minutes;
the other lost the live-update capability entirely and shipped polling in its place, believing the
gap was its own. A defect that makes competent users quietly build the worse version of your product
is more expensive than one that stops them.

Provenance

Wave four, 2026-08-03. Run 1 drift finding #5 (/home/codex/repos/wave4-fable/.llm/run/drift.md);
run 2 article and product/nightbell/apps/nightbell/islands/IncidentBoard.tsx.
Repos: https://github.com/rickylabs/vigil · https://github.com/rickylabs/nightbell
Related: #1064 (the same fog contributed to the publish-hang diagnosis).

Metadata

Metadata

Assignees

No one assigned

    Projects

    No projects

    Relationships

    None yet

    Development

    No branches or pull requests

    Issue actions