glas-harness/docs/adr/ADR-004-composable-reins-stay-deferred.md
tegwick 9bbff9d336
All checks were successful
CI Smoke / host-smoke (push) Successful in 0s
CI Smoke / container-smoke (push) Successful in 1s
ADR-004: composable reins as middleware stays deferred (GLAS-WP-0002-T01)
Checked ADR-002 part 2's deferred question against the two observability
additions that landed since (rein-aharness's tool-event stream,
glas-harness's own gateway hub event) -- both turned out simpler as
direct implementations, neither needed a wrapping middleware layer.
Still zero real candidates for that shape. docs/harness-contract.md
gains the Middleware ABC as a documented, unimplemented sketch for if a
real third case ever appears -- no code written now.

Also flagged GLAS-WP-0002-T02 (live OpenBao verification) as blocked:
`bao token lookup` from this workstation returns 403, no usable vault
session to provision a new AppRole with. Needs the operator.

Co-Authored-By: Claude Sonnet 5 <noreply@anthropic.com>
2026-07-26 20:22:55 +02:00

3.1 KiB

ADR-004: Composable reins as middleware — stay deferred

  • Status: accepted
  • Date: 2026-07-26
  • Deciders: Bernd Worsch

Context

ADR-002 part 2 raised the idea, left deliberately open: could monitoring/evaluation/optimization become their own composable reins — middleware wrapping or observing a base rein's dispatch_tool calls, rather than each being a complete alternative harness backend? At the time there was exactly one candidate capability to generalize from (llm-connect's optional Functional-layer modules: diagnostics, replay, budget tracking), and the rule set then was: don't build the abstraction until a second real candidate shows up.

Since then, two more observability additions landed:

  1. rein-aharness's per-tool-call audit stream (HARNESS-WP-0002-T03) — AgenticClaudeCodeAdapter gained an on_tool_event callback, parsing claude's stream-json output.
  2. glas-harness's own gateway hub event (GLAS-WP-0002-T03) — run_task_through_rein posts a gateway_run progress event under its own actor attribution, independent of whatever the rein reports.

Both are exactly the kind of thing the middleware idea was reaching for: cross-cutting observability layered on top of a rein's tool dispatch. Worth checking, now that two real examples exist, whether they should have been built as Middleware wrapping a Rein, per the sketch in docs/harness-contract.md.

Decision

They shouldn't have been, and composable-reins-as-middleware stays deferred — sketch recorded, no code.

Both additions turned out to be simpler as direct implementations than a wrapping-middleware abstraction would have been:

  • Item 1 lives inside rein-aharness's own adapter, because the thing being observed (Claude Code's internal tool execution) is only visible from inside that adapter's process boundary in the first place — no external wrapper could intercept it, wrapping-middleware or otherwise.
  • Item 2 lives in glas-harness's own gateway, because it's reporting on the gateway's own actions (sandbox lifecycle, dispatch call), not wrapping a rein's internals — there's nothing here a Middleware layer would add over just... doing it in the gateway.

Neither is evidence for the original idea (a rein-shaped monitoring/eval/ optimization layer sitting between glas-harness and a base rein). The original candidate — llm-connect's optional modules — remains untouched and unintegrated into either rein. Two additions still isn't two candidates for this specific shape; it's zero candidates plus two observations that the direct-implementation path keeps winning on its own merits.

Consequences

  • docs/harness-contract.md keeps the Middleware ABC as a documented, unimplemented sketch — reachable if a real third case appears, not built speculatively.
  • GLAS-WP-0002-T01 closes on this ADR; no code follows from it.
  • Future observability needs should default to "implement directly where the data actually is" (as both examples here did) unless a genuine cross-rein reuse case forces the composition question — don't reach for Middleware reflexively just because it's now documented.