Formalize the CLI as the first Channel extension (GLAS-WP-0003)
All checks were successful
CI Smoke / host-smoke (push) Successful in 0s
CI Smoke / container-smoke (push) Successful in 1s

channels/base.py: GatewayInvocation dataclass + Channel ABC
(parse_invocation/render_result), mirroring Rein one layer up -- a
channel turns an external invocation into what run_task_through_rein
needs, and turns its result back into whatever the invocation medium
expects.

channels/cli_channel.py: CLIChannel, a pure refactor of what cli.py did
inline -- argparse Namespace -> GatewayInvocation, result dict ->
json.dumps(..., indent=2). cli.py's run handler is now a thin
construct-parse-invoke-render wrapper.

docs/channel-contract.md documents the pattern and sketches (without
building) a second channel.

Found and fixed a real bug while live-testing this refactor:
ReinAharness's default cli_bin was still "agent-harness", stale from
before HARNESS-WP-0002-T02's rename.

4 new tests (27/27 passing), plus a real live run through
python3 -m glas_harness.cli against rein-aharness/real Claude Code
confirming identical output shape and a real commit.

Co-Authored-By: Claude Sonnet 5 <noreply@anthropic.com>
This commit is contained in:
tegwick 2026-07-26 22:41:51 +02:00
parent a87b924126
commit d3130162b1
9 changed files with 251 additions and 17 deletions

View file

@ -2,6 +2,7 @@
id: GLAS-WP-0003
title: "First channel extension: formalize the CLI channel contract"
status: proposed
state_hub_workstream_id: "78da8b34-27dd-4807-b7c8-321328dd2db8"
---
Scoped by `GLAS-WP-0002-T04`: of glas-harness's four charter pillars
@ -37,10 +38,15 @@ class Channel(ABC):
Document in `docs/channel-contract.md`, parallel to
`docs/harness-contract.md`.
**Done (2026-07-26).** `src/glas_harness/channels/base.py`:
`GatewayInvocation` dataclass + `Channel` ABC as sketched above.
Documented in `docs/channel-contract.md`.
```task
id: GLAS-WP-0003-T01
status: todo
status: done
priority: medium
state_hub_task_id: "f6a63483-2780-4b6c-8e0a-791e10d9c91a"
```
## Task: Refactor glas_harness.cli into a CLIChannel
@ -52,10 +58,19 @@ exactly — this is a refactor, not a behavior change). `cli.py` becomes a
thin `main()` that constructs a `CLIChannel` and calls it; existing CLI
usage and output are unchanged.
**Done (2026-07-26).** `cli.py`'s `run` handler now constructs
`CLIChannel()`, calls `parse_invocation(args)`, invokes
`run_task_through_rein` with the resulting `GatewayInvocation` fields,
and prints `channel.render_result(result)` — same shape as before.
Also fixed a real bug found while live-testing this: `ReinAharness`'s
default `cli_bin` was still `"agent-harness"`, stale from before the
rename — now `"rein-aharness"`.
```task
id: GLAS-WP-0003-T02
status: todo
status: done
priority: medium
state_hub_task_id: "f7d26f3b-0df2-4db5-be7b-33065868087c"
```
## Task: Tests + verify no behavior change
@ -64,10 +79,18 @@ Unit tests for `CLIChannel.parse_invocation`/`render_result` in
isolation, plus re-running the existing live-proof commands (both
reins) to confirm identical CLI output before/after the refactor.
**Done (2026-07-26).** `tests/test_cli_channel.py`, 4 new tests
(27/27 passing overall). Live-verified with a real run through
`python3 -m glas_harness.cli run ...` against `rein-aharness`/real
Claude Code: real commit landed, output shape unchanged,
`executor-sandbox` itself untouched (as with every prior live proof —
`ext.bwrap` only mutates its ephemeral copy).
```task
id: GLAS-WP-0003-T03
status: todo
status: done
priority: medium
state_hub_task_id: "5012c88c-0b9c-4d12-97a8-07a58b7b84c4"
```
## Task: Document the pattern for a second channel
@ -79,8 +102,13 @@ one real implementation proves it," matching the discipline applied
throughout this session's other deferred-until-a-second-example
decisions.
**Done (2026-07-26).** "Adding a second channel" section in
`docs/channel-contract.md`, sketching a Slack channel without building
one.
```task
id: GLAS-WP-0003-T04
status: todo
status: done
priority: low
state_hub_task_id: "0a06387f-c7ed-4de9-999d-a7ba50e33d50"
```