rein-aharness/workplans/HARNESS-WP-0002-rename-and-glas-harness-alignment.md
tegwick a3fc75ced1 Close HARNESS-WP-0002-T04 per glas-harness ADR-003
Co-Authored-By: Claude Sonnet 5 <noreply@anthropic.com>
2026-07-26 14:52:01 +02:00

156 lines
7.2 KiB
Markdown
Raw Blame History

This file contains ambiguous Unicode characters

This file contains Unicode characters that might be confused with other characters. If you think that this is intentional, you can safely ignore this warning. Use the Escape button to reveal them.

---
id: HARNESS-WP-0002
title: "Rename completion and glas-harness alignment"
status: active
state_hub_workstream_id: "c53fe489-845b-42b3-8e7f-c7e4e6f16b25"
---
Follow-up to HARNESS-WP-0001 (done) and glas-harness
`docs/adr/ADR-001-rein-harness-family.md`. This repo (formerly
agent-harness) is now the `rein-aharness` rein: the Claude-Code-CLI-driven
harness for governed, unattended/scheduled tenant work, consumed through
glas-harness's router once GLAS-WP-0001 lands. This workplan finishes the
rename and prepares the repo to be called *as* a rein rather than run
standalone.
## Task: Repo-identity rename (this session)
Local directory (`~/agent-harness``~/rein-aharness`), git remote
(`coulomb/agent-harness.git``coulomb/rein-aharness.git`, already
renamed on Forgejo by the operator), `pyproject.toml` `[project].name`,
and self-referencing prose in `README.md`/`INTENT.md`. Does **not**
touch the CLI command name, Python package name, or deploy artifacts —
see next task.
```task
id: HARNESS-WP-0002-T01
status: done
priority: high
state_hub_task_id: "bf04ed50-cbe2-4f8f-9876-d06c579d19e6"
```
## Task: Deploy/package rename (deliberate follow-up, needs a maintenance window)
Rename the parts of this repo that a mechanical identity rename would
otherwise silently break, because they touch a *live* Railiance
deployment: the `agent-harness` CLI command, the `agent_harness` Python
package directory, the Docker image tag, the k8s namespace/labels/
ConfigMap names, the Railiance host directory, and
`deploy/scripts/railiance-smoke.sh`'s env var and paths.
**Code/config side done (2026-07-26):**
- `agent_harness/``rein_aharness/` (`git mv` + all internal imports)
- `pyproject.toml`: `[project.scripts]` → `rein-aharness =
"rein_aharness.cli:main"`; wheel package name
- `Containerfile`: `COPY rein_aharness`, `ENTRYPOINT ["rein-aharness"]`
- `Makefile`: `IMAGE`/`TAR` → `rein-aharness:railiance01` /
`rein-aharness-railiance01.tar`; `deploy-rsync` target path
- `deploy/k8s/railiance/*.yaml`: namespace/labels/names/image all
`rein-aharness`
- `deploy/scripts/railiance-smoke.sh`: `AGENT_HARNESS_ROOT` →
`REIN_AHARNESS_ROOT`, default checkout path, AppRole env source path
(SSH host alias for Forgejo left untouched — that's an external
`~/.ssh/config` entry, not owned by this repo)
- In-repo identity strings updated too: `hub.py`'s `source` field,
`metrics.py`'s `harness` field default, `intake.py`'s
`DEFAULT_ASSIGNEE`, `cli.py`'s `argparse` prog name, commit
author identity in `smoke.py`/`tenant_onboard_runs.py`
- Verified: 47/47 tests pass, `rein-aharness` CLI runs correctly from a
fresh venv, `docker build` succeeds and the built image runs
(`ENTRYPOINT`/`CMD` dispatch correctly)
- `deploy/README.md` gained an explicit **rename cutover checklist**
for the parts this session cannot safely do unattended: moving the
host-side secrets dir (`~/.local/agent-harness` → `~/.local/rein-aharness`)
and checkout (`~/agent-harness` → `~/rein-aharness`) on railiance01
itself, and not deleting the old k8s namespace until the new one is
confirmed working
**Still open — the actual live cutover:** running the checklist on
railiance01, rebuilding+importing the image there, applying the renamed
k8s manifests, and running the host smoke script against the live
deployment. Not attempted from this session — real production surgery
on `binky-control`'s live automation, needs the operator present for
the actual host-side moves and a confirmed rollback point.
```task
id: HARNESS-WP-0002-T02
status: progress
priority: medium
state_hub_task_id: "7c5d23cd-d7fd-4c79-8847-448b83feb673"
```
## Task: Implement the glas-harness rein contract
Once `glas-harness` GLAS-WP-0001-T01 defines the harness contract
(`start_session`/`dispatch_tool`/`end_session` or equivalent), adapt this
repo's `runner.py`/`adapter.py` to expose it, so glas-harness can call
into `rein-aharness` instead of `rein-aharness` only running itself via
its own CLI/poll loop.
**Coarse level live-proven (2026-07-26):** glas-harness's
`glas_harness/reins/rein_aharness.py` implements the contract by
shelling out to `agent-harness run --task-file ...` as one opaque
`dispatch_tool` call — proven live end-to-end (real `ext.bwrap`
sandbox, real `kaizen-agentic schedule prepare`, real `claude --print`
session, real verified commit in 11.4s).
**Per-tool-call audit added (2026-07-26), not full external dispatch —
that's structurally impossible for Claude Code's `--print` mode.**
Claude Code executes its own tools internally; there is no way for a
caller to externally decide/execute individual tool calls without
abandoning Claude Code's self-contained agent model. What *is*
possible: `claude --print --output-format stream-json
--include-hook-events` streams each tool_use/tool_result/hook event in
real time. Added:
- `adapter.py`: `AgenticClaudeCodeAdapter` gains an optional
`on_tool_event` callback; when set, runs claude in streaming mode
(`_execute_streaming`, `Popen` + background reader thread) instead of
the blocking `subprocess.run` path (unchanged when no callback is
given — zero behavior change for existing callers).
- `runner.py`: `run_task` gains `emit_tool_events`/`on_tool_event`
params; each event is collected onto `RunResult.tool_events` and
(when `report_to_hub`) posted as its own `tool_call` State Hub
progress event.
- `cli.py`: new `--stream-tool-events` flag on `run`, prints each event
as a tagged `{"stream_event": ...}` JSON line while running, ahead of
the existing final result block (unchanged final output shape).
- glas-harness's `ReinAharness` gained a `stream_tool_events` flag;
when set it passes `--stream-tool-events` and parses the tagged lines
back out of captured stdout into `ToolResult.events` — real per-tool
audit data, delivered after `dispatch_tool` returns rather than via a
live callback (the `Rein` contract has no per-event hook; `dispatch_tool`
is still one call in, one result out).
Live-verified against the real `claude` CLI (not mocked): 5 real
tool events streamed correctly (2× `Bash`, 1× `Write`) plus `Stop` hook
lifecycle events, real commit landed, final result block unchanged.
13 new tests in rein-aharness (`test_adapter.py` + 2 in
`test_runner.py`), 2 new tests in glas-harness (`test_rein_aharness.py`)
— all passing, all mocked except the one live CLI run above.
```task
id: HARNESS-WP-0002-T03
status: done
priority: high
state_hub_task_id: "228e999c-807b-4456-a286-4e3ab4fc8e90"
```
## Task: Decide scheduling/blueprint coupling boundary
Resolved in `glas-harness/docs/adr/ADR-003-scheduling-and-blueprint-sourcing-stay-rein-local.md`:
**stays rein-local.** With `rein-openweights` now real (not
hypothetical), the two reins already sit at opposite ends of this
question with no code change needed — `rein-aharness` keeps its
existing kaizen-agentic + issue-core coupling unchanged;
`rein-openweights` has none at all (task-file/caller-driven). glas-harness
does not become a task source or scheduler, consistent with its own
INTENT.md boundary ("Not a scheduler... activity-core" already listed
under "What it is not").
```task
id: HARNESS-WP-0002-T04
status: done
priority: low
state_hub_task_id: "31e2b763-8f04-4523-bd2b-ce4506b55700"
```