--- id: GLAS-WP-0002 title: "Observability and composability follow-ups" status: active state_hub_workstream_id: "ec0777ff-18ce-4666-abaf-5bd2ff0fd4b9" --- Four items surfaced as open-but-not-urgent while closing out `GLAS-WP-0001`/`HARNESS-WP-0002`/`SAND-WP-0013`/`REIN-OW-WP-0001` — none blocking, all worth doing. Bundled into one workplan since three of the four are glas-harness-scoped and the fourth needs glas-harness coordination either way. ## Task: Design composable reins as middleware Resolve ADR-002 part 2 (deliberately deferred): should monitoring/evaluation/optimization become their own composable reins — middleware that wraps or observes a base rein's `dispatch_tool` calls — rather than each being a complete alternative harness backend the way `rein-aharness`/`rein-openweights` are? At the time of ADR-002 there was only one candidate capability (llm-connect's optional Functional-layer modules) to generalize from; that's still true today, so this task is a **design decision first, implementation only if it clearly pays for itself** — don't build a `Middleware`/`ReinWrapper` abstraction on spec. Concretely: draft the `Middleware` shape in `docs/harness-contract.md` (a chain-of-responsibility around `dispatch_tool`, distinct from `Rein`), record the decision as an ADR addendum, and only write code if a real middleware candidate (e.g. a monitoring rein) is scoped alongside it in this same task — not before. **Done (2026-07-26), stays deferred.** `docs/adr/ADR-004-composable-reins-stay-deferred.md` checked this against the two observability additions that landed since ADR-002 (rein-aharness's tool-event stream, glas-harness's own gateway hub event, both `HARNESS-WP-0002-T03`/`GLAS-WP-0002-T03`) — both turned out simpler as direct implementations, neither needed a wrapping middleware layer. Still zero real candidates for *this* shape, so no code written. `docs/harness-contract.md` now carries the `Middleware` ABC sketch for future reference, explicitly marked don't-build-yet. ```task id: GLAS-WP-0002-T01 status: done priority: medium state_hub_task_id: "2de6074e-b72b-4eb7-b454-6b849011348c" ``` ## Task: Live-verify rein-openweights's OpenBao credential path The live proof in `REIN-OW-WP-0001` used the `OPENROUTER_API_KEY` env-var short-circuit in `rein_openweights/credentials.py` — the AppRole/vault path (`_acquire_token`, `resolve_openrouter_api_key`'s `bao kv get` branch) is only unit-tested against mocked `bao` calls, never exercised against a real OpenBao instance. Set up a real (or realistic sandboxed) OpenBao AppRole for `rein-openweights` — mirroring `rein-aharness`'s existing `binky-mail` AppRole pattern — and run one live task through it with `OPENROUTER_API_KEY` unset, confirming the vault round trip actually works end to end. Coordinate with `rein-openweights` directly; this task's outcome should be recorded in both repos. **Blocked (checked 2026-07-26):** `bao token lookup` from this workstation returns `403 permission denied` — no usable vault session here. Provisioning a new AppRole (`auth/approle/role/...`) and a KV secret for `rein-openweights`, mirroring `rein-aharness`'s `binky-mail` lane, needs vault-admin access this session doesn't have. Needs the operator to provision the AppRole (or provide an ambient token with enough privilege) before this can be exercised for real. ```task id: GLAS-WP-0002-T02 status: wait priority: medium state_hub_task_id: "74b4f35b-9cdd-4228-aeed-e0eec458c0bf" ``` ## Task: Wire glas-harness's own State Hub reporting from the gateway Both live runs so far passed `--no-hub` through to the rein's own CLI — each rein reports its own events, but `run_task_through_rein` itself never posts a session-level event under glas-harness's own actor attribution. Add a State Hub progress event (and, where meaningful, a token event) emitted by `gateway.py` around sandbox create/destroy and rein dispatch, distinct from whatever the rein itself reports — this is what makes the *gateway's* audit trail exist independent of which rein ran, matching the "observable by default" design principle in `INTENT.md`. **Done (2026-07-26).** `src/glas_harness/hub.py` (mirrors the two reins' hub.py under `author: agt-glas-harness`); `gateway.py`'s `run_task_through_rein` gains `report_to_hub: bool = True`, posting one `gateway_run` progress event from a `finally` block — fires on both success and failure (a raised exception still leaves an audit trail), with `ok`/`rein`/`sandbox_id`/`sandbox_profile`/`project`/`result`/ `error` in the detail. `cli.py` gained a matching `--no-hub` flag. Live verified: ran a real task through `ReinOpenWeights` with hub reporting enabled, confirmed the `gateway_run` event landed in State Hub with the correct detail (`author: agt-glas-harness`, real commit sha in `result`). Token events skipped for now — `ToolResult` doesn't carry a uniform token count across reins, and it wasn't worth forcing one just for this task. 4 new tests (success/failure/disabled paths), 23/23 passing. ```task id: GLAS-WP-0002-T03 status: done priority: high state_hub_task_id: "76462175-4a85-4552-a6c1-af871cc1b8d3" ``` ## Task: First slice of glas-harness's remaining charter pillars `INTENT.md` describes four pillars: (1) unified harness API, (2) profile catalog, (3) extension platform (channels, memory/skills), (4) observability/governance. Only slices of (1), (2), and (4) exist today (contract, two harness profiles, the per-tool audit stream). Channels and memory/skills are entirely unbuilt. This task is **not** "build all of it" — it's picking and scoping the smallest real slice worth doing next (most likely candidate: a CLI channel extension, since one already exists implicitly via `glas_harness.cli`; formalizing it as the first of possibly several channel extensions clarifies the channel contract before a second channel is attempted). Produce a scoped follow-up workplan (`GLAS-WP-0003` or later) rather than expanding this task indefinitely. **Done (2026-07-26).** Scoped as `workplans/GLAS-WP-0003-first-channel-extension.md`: formalize the CLI as the first `Channel` extension (contract + refactor + tests + second-channel documentation), explicitly not building a second channel now — same discipline as ADR-002/ADR-004. ```task id: GLAS-WP-0002-T04 status: done priority: low state_hub_task_id: "98d4be61-5923-4445-b1f8-5135ada13ad9" ```