glas_harness/reins/rein_openweights.py implements the Rein ABC by shelling out to `rein-openweights run --task-file ... --no-hub [--model ...]`, mirroring reins/rein_aharness.py exactly. Factored the duplicated git_head/write_task_file logic into reins/_shared.py, used by both adapters now. registry/reins/rein-openweights.yaml flipped to status: implemented. 8 new tests (mocked subprocess), 18/18 passing. Co-Authored-By: Claude Sonnet 5 <noreply@anthropic.com>
5.8 KiB
| id | title | status | state_hub_workstream_id |
|---|---|---|---|
| GLAS-WP-0001 | Harness router foundation: contract + first two reins | active | 4b8740d9-9ea8-4c11-abfc-af9e9ac1c2df |
Turn glas-harness from a charter into the actual harness router per
docs/adr/ADR-001-rein-harness-family.md. Define the contract concrete
harness backends ("reins") implement, register the first two
(rein-aharness, rein-openweights), and stand up a minimal gateway
that can run a session through either. No channel work, no memory/skills
layer yet — this workplan is the sand-boxer-extension-model equivalent
for harnesses: contract + registry + one working round trip.
Task: Define the harness contract
Specify the interface a rein implements: session start/resume/end, tool
dispatch + policy check, actor attribution (adm/agt/atm), sandbox
policy resolution (mode/scope/workspaceAccess) handed to sand-boxer, and
the audit envelope reported to State Hub. Mirror sand-boxer's
SandboxExtension ABC shape (provision/wait_ready/teardown) at the
harness level: something like start_session/dispatch_tool/
end_session. Document in docs/harness-contract.md.
id: GLAS-WP-0001-T01
status: done
priority: high
state_hub_task_id: "e4e6e7e4-ad30-42b7-a278-39d24ec5cecc"
Task: Rein registry
A named, versioned registry of reins (registry/reins/rein-aharness.yaml,
registry/reins/rein-openweights.yaml) analogous to sand-boxer's
extensions/ext.*.yaml — each entry declares its capabilities (e.g.
unattended/interactive, model-class: frontier|open-weight,
credential-source) and a handler reference. Extend
registry/indexes/capabilities.yaml with a capability.platform. glas-harness entry per the registry-first-reuse principle.
id: GLAS-WP-0001-T02
status: done
priority: medium
state_hub_task_id: "c09e617b-a2d1-42c4-8c90-47ab0056c09c"
Task: Harness profile catalog seed
First harness profile, harness.agent-dev, paired with sand-boxer's
profile.agent-dev (existing docs/integrations/glas-harness.md contract
in sand-boxer already assumes this pairing — verify it still matches).
Add a second profile, harness.agent-dev-local, paired with sand-boxer's
forthcoming profile.bwrap-local (SAND-WP-0013) once that lands, for
fast local iteration without an SSH hop.
id: GLAS-WP-0001-T03
status: done
priority: medium
state_hub_task_id: "e599f276-a010-4284-bddd-a5a121b57de9"
Task: Minimal CLI gateway — prove the contract against rein-aharness
Implement just enough of the harness contract to run one existing
rein-aharness run (task-file path) through glas-harness: resolve
harness.agent-dev, request a sandbox from sand-boxer, dispatch to
rein-aharness's adapter, verify commit, report to State Hub. This is the
parity proof gating any later "retire agent-harness as a standalone
concern" conversation — deliberately not attempted until this exists.
Wiring is built and unit-tested: src/glas_harness/gateway.py +
reins/rein_aharness.py implement start_session/dispatch_tool/
end_session, tested against a real local git repo and a mocked
SandboxManager/agent-harness subprocess (tests/test_gateway.py,
tests/test_rein_aharness.py). Not yet done: an actual live run
(glas-harness run --sandbox-profile profile.bwrap-local ...) against
the real Claude Code CLI — that spends real API credits/credentials and
was deliberately left for a human-triggered run rather than executed
autonomously. State Hub reporting from the gateway itself is also not
wired yet (only rein-aharness's own --no-hub path was exercised).
id: GLAS-WP-0001-T04
status: progress
priority: high
state_hub_task_id: "cdcacf98-62a1-47ae-92b9-e0320968ac1f"
Task: Charter and bootstrap rein-openweights
Turn the ~/rein-openweights scaffold into a working minimal rein: an
agentic tool-use loop (plan → tool call → observe → repeat) driving an
open-weight model via OpenRouter, implementing the GLAS-WP-0001-T01
contract. Start with the same tool surface as rein-aharness's
green-commit-only profile (Read/Write/Edit/Glob/Grep + local git) so
it's directly comparable. Needs its own Forgejo remote before anything
is pushed — coordinate repo creation with the operator.
rein-openweights/REIN-OW-WP-0001 (T01-T04) is done: standalone agentic
loop, own OpenRouter client (not llm-connect — see that workplan's T01
for why), tool surface, credential acquisition, commit-verified success
- hub reporting, 26 tests.
glas_harness/reins/rein_openweights.py now implements the Rein ABC
by shelling out to rein-openweights run --task-file ... --no-hub [--model ...], mirroring reins/rein_aharness.py exactly (both now
share reins/_shared.py for git_head/write_task_file — the
duplication was real, so it got factored out). registry/reins/ rein-openweights.yaml flipped to status: implemented. 8 new tests,
all mocked.
id: GLAS-WP-0001-T05
status: done
priority: high
state_hub_task_id: "84fa62ae-3b34-42fd-a263-f65c35e87586"
Task: Decide credential-brokering ownership for rein-openweights
Resolved in docs/adr/ADR-002-credential-brokering-and-composable-reins.md:
Option B — rein-openweights acquires its OpenRouter credential
directly (OpenBao/ops-warden), consistent with rein-aharness's own
credential-holder principle. glas-harness does not broker LLM-provider
credentials. Confirmed llm-connect itself never brokers credentials
either (resolve_api_key() only reads an already-materialized key) —
the earlier "does using llm-connect impose a credential model" concern
does not apply. A separate, deliberately deferred question (composable
reins as middleware for monitoring/eval/optimization) is recorded in the
same ADR as open, not blocking this task or T05.
id: GLAS-WP-0001-T06
status: done
priority: medium
state_hub_task_id: "b4e775d6-ad81-40a4-9fd0-974ba27182fd"