diff --git a/Containerfile b/Containerfile index 292ca17..3a54d0b 100644 --- a/Containerfile +++ b/Containerfile @@ -1,5 +1,5 @@ -# agent-harness — shared unattended agent runtime (Railiance / local). -# Build: docker build -f Containerfile -t agent-harness:local . +# rein-aharness — shared unattended agent runtime (Railiance / local). +# Build: docker build -f Containerfile -t rein-aharness:local . # Optional llm-connect sibling: docker build --build-arg WITH_LLM_CONNECT=1 ... FROM python:3.12-slim @@ -17,7 +17,7 @@ RUN apt-get update \ && useradd -u 10001 -g 10001 -m -s /usr/sbin/nologin harness COPY pyproject.toml README.md ./ -COPY agent_harness ./agent_harness +COPY rein_aharness ./rein_aharness # Populated by `make image` from ../llm-connect when present. COPY llm_connect_vendor ./llm_connect_vendor @@ -31,5 +31,5 @@ RUN pip install --no-cache-dir "httpx>=0.27" "PyYAML>=6.0" \ USER 10001:10001 # No long-running HTTP API yet — image is invoked as CLI (run / smoke / validate). -ENTRYPOINT ["agent-harness"] +ENTRYPOINT ["rein-aharness"] CMD ["profiles"] diff --git a/Makefile b/Makefile index 227fa55..1af464d 100644 --- a/Makefile +++ b/Makefile @@ -1,8 +1,8 @@ .PHONY: test image image-export deploy-rsync help UV ?= $(shell command -v uv 2>/dev/null || echo uv) -IMAGE ?= agent-harness:railiance01 -TAR ?= /tmp/agent-harness-railiance01.tar +IMAGE ?= rein-aharness:railiance01 +TAR ?= /tmp/rein-aharness-railiance01.tar help: ## Show targets @grep -Eh '^[a-zA-Z_-]+:.*?##' $(MAKEFILE_LIST) | \ @@ -26,8 +26,8 @@ image-export: image ## Save image tar for k3s import docker save -o $(TAR) $(IMAGE) @ls -lh $(TAR) -deploy-rsync: ## Rsync tree to railiance01:~/agent-harness +deploy-rsync: ## Rsync tree to railiance01:~/rein-aharness rsync -az --delete \ --exclude '.git' --exclude '__pycache__' --exclude '.pytest_cache' \ --exclude 'llm_connect_vendor' --exclude '*.egg-info' \ - ./ railiance01:agent-harness/ + ./ railiance01:rein-aharness/ diff --git a/README.md b/README.md index 6abe9d2..bcebf1f 100644 --- a/README.md +++ b/README.md @@ -14,14 +14,17 @@ tenants that need governed cron-style agent runs. See [glas-harness ADR-001](../glas-harness/docs/adr/ADR-001-rein-harness-family.md) for how it relates to other reins (e.g. `rein-openweights`). -The CLI command (`agent-harness`), Python package (`agent_harness`), and -deploy artifacts (Docker image tag, k8s namespace, Railiance host paths) -still use the old name — that rename is tracked separately in -[workplans/REIN-A-WP-0002](workplans/REIN-A-WP-0002-rename-and-glas-harness-alignment.md) -because it touches a live Railiance deployment. +The CLI command (`rein-aharness`) and Python package (`rein_aharness`) are +renamed. Deploy artifacts (Docker image tag, k8s namespace, Railiance host +paths) are renamed in this repo too, but the live Railiance cutover itself +(moving the host-side checkout + secrets dir, redeploying) is a separate, +deliberate step — tracked in +[workplans/HARNESS-WP-0002](workplans/HARNESS-WP-0002-rename-and-glas-harness-alignment.md) +and [deploy/README.md](deploy/README.md)'s rename cutover checklist. - Why and boundaries: [INTENT.md](INTENT.md) -- Decision + architecture: [docs/adr/ADR-001](docs/adr/ADR-001-agent-harness-architecture.md), +- Decision + architecture: [docs/adr/ADR-001](docs/adr/ADR-001-agent-harness-architecture.md) + (kept under its original filename — it documents the pre-rename decision), [docs/architecture.md](docs/architecture.md) - Current work: [workplans/](workplans/) @@ -29,33 +32,33 @@ because it touches a live Railiance deployment. ``` # Validate a consuming repo's instance manifest (.kaizen/schedule.yml) -agent-harness validate --target ~/binky-control -agent-harness validate --target ~/binky-control --strict # require harness fields +rein-aharness validate --target ~/binky-control +rein-aharness validate --target ~/binky-control --strict # require harness fields # List named tool profiles -agent-harness profiles +rein-aharness profiles # Run exactly one task (local JSON task-file path — dev) -agent-harness run --task-file examples/task-hello-sandbox.json [--no-hub] [--no-metrics] +rein-aharness run --task-file examples/task-hello-sandbox.json [--no-hub] [--no-metrics] # Production intake: poll issue-core (activity-core emissions), claim, run, close export ISSUE_CORE_URL=http://127.0.0.1:8765 ISSUE_CORE_API_KEY=… -agent-harness poll -agent-harness run --from-issue-core +rein-aharness poll +rein-aharness run --from-issue-core # Deterministic mailbox scan (no LLM session) -agent-harness mail-scan --target-repo ~/binky-control +rein-aharness mail-scan --target-repo ~/binky-control # Mail triage via llm-connect HTTP (OpenRouter behind the service; no Claude CLI) export LLM_CONNECT_URL=http://llm-connect.activity-core.svc.cluster.local:8080 -agent-harness mail-triage --target-repo ~/binky-control +rein-aharness mail-triage --target-repo ~/binky-control # Daily brief via llm-connect (structured JSON → briefs/YYYY-MM-DD-daily-brief.md) -agent-harness brief-daily --target-repo ~/binky-control +rein-aharness brief-daily --target-repo ~/binky-control # Railiance packaging smoke (commit + optional push + hub; no Claude required) -agent-harness smoke --work-dir ~/work/executor-sandbox +rein-aharness smoke --work-dir ~/work/executor-sandbox ``` Railiance deploy: [deploy/README.md](deploy/README.md). diff --git a/WORK-RECORDS.md b/WORK-RECORDS.md index ec77ac3..cf18423 100644 --- a/WORK-RECORDS.md +++ b/WORK-RECORDS.md @@ -20,7 +20,7 @@ | task | HARNESS-WP-0001-T07 | done | — | workplans/HARNESS-WP-0001-harness-foundation.md | | task | HARNESS-WP-0002-T01 | done | — | workplans/HARNESS-WP-0002-rename-and-glas-harness-alignment.md | | task | HARNESS-WP-0002-T02 | todo | — | workplans/HARNESS-WP-0002-rename-and-glas-harness-alignment.md | -| task | HARNESS-WP-0002-T03 | todo | — | workplans/HARNESS-WP-0002-rename-and-glas-harness-alignment.md | +| task | HARNESS-WP-0002-T03 | progress | — | workplans/HARNESS-WP-0002-rename-and-glas-harness-alignment.md | | task | HARNESS-WP-0002-T04 | todo | — | workplans/HARNESS-WP-0002-rename-and-glas-harness-alignment.md | | task | REIN-A-0001-T01 | todo | — | workplans/REIN-A-0001-statehub-bootstrap.md | | task | REIN-A-0001-T02 | todo | — | workplans/REIN-A-0001-statehub-bootstrap.md | diff --git a/deploy/README.md b/deploy/README.md index f383914..90b0726 100644 --- a/deploy/README.md +++ b/deploy/README.md @@ -3,6 +3,25 @@ Single shared harness instance on **railiance01**. Secrets stay on the host (Lanes 2–3); the container image is the portable runtime package. +> **Renamed from agent-harness (HARNESS-WP-0002-T02).** Image tag, k8s +> namespace/labels, CLI command, and Python package are all renamed in +> this repo already. The commands below assume the **rename cutover +> checklist** just below has been done on railiance01 first — this is a +> live production deployment for `binky-control`, so the cutover itself +> is deliberately not automated from a workstation session. + +## Rename cutover checklist (do this on railiance01 before redeploying) + +1. Move the host-side secrets dir: `mv ~/.local/agent-harness ~/.local/rein-aharness` + (or symlink, if anything else still reads the old path). +2. Move/rename the checkout: `mv ~/agent-harness ~/rein-aharness` (or a fresh + `deploy-rsync` to the new path — see Makefile). +3. Verify no other host cron/systemd unit still references + `~/agent-harness` or the `agent-harness` command directly. +4. Once the above is done, `kubectl delete namespace agent-harness` **after** + confirming the new `rein-aharness` namespace deploys and smokes clean — + don't delete the old one first, in case cutover needs a rollback. + ## Layout | Path | Role | @@ -10,31 +29,31 @@ Single shared harness instance on **railiance01**. Secrets stay on the host | `Containerfile` | Image: Python CLI + git + openssh; optional vendored llm-connect | | `deploy/k8s/railiance/` | Namespace, ConfigMap, Deployment, smoke Job | | `deploy/scripts/railiance-smoke.sh` | Host e2e: clone sandbox → commit → push → hub | -| `agent-harness smoke` | Deterministic smoke (no Claude Code required) | +| `rein-aharness smoke` | Deterministic smoke (no Claude Code required) | -## Prerequisites (done 2026-07-17) +## Prerequisites (done 2026-07-17, paths renamed per checklist above) - Lane 2 deploy key on host + Forgejo write on `coulomb/executor-sandbox` -- Lane 3 AppRole under `~/.local/agent-harness/approle-binky-mail` -- `source ~/.local/agent-harness/env` +- Lane 3 AppRole under `~/.local/rein-aharness/approle-binky-mail` +- `source ~/.local/rein-aharness/env` - Hub: `http://127.0.0.1:18000` (ops-bridge) or in-cluster `state-hub.state-hub.svc` ## Build & load image (workstation → railiance01) ```bash -# from agent-harness repo root -make image # tags agent-harness:railiance01 -make image-export # /tmp/agent-harness-railiance01.tar -scp /tmp/agent-harness-railiance01.tar railiance01:/tmp/ -ssh railiance01 sudo k3s ctr images import /tmp/agent-harness-railiance01.tar +# from rein-aharness repo root +make image # tags rein-aharness:railiance01 +make image-export # /tmp/rein-aharness-railiance01.tar +scp /tmp/rein-aharness-railiance01.tar railiance01:/tmp/ +ssh railiance01 sudo k3s ctr images import /tmp/rein-aharness-railiance01.tar ``` ## Apply k8s ```bash -rsync -a deploy/k8s/railiance/ railiance01:agent-harness/deploy/k8s/railiance/ -ssh railiance01 kubectl apply -k agent-harness/deploy/k8s/railiance/ -ssh railiance01 kubectl -n agent-harness rollout status deploy/agent-harness +rsync -a deploy/k8s/railiance/ railiance01:rein-aharness/deploy/k8s/railiance/ +ssh railiance01 kubectl apply -k rein-aharness/deploy/k8s/railiance/ +ssh railiance01 kubectl -n rein-aharness rollout status deploy/rein-aharness ``` ## Host smoke (authoritative e2e gate) @@ -42,7 +61,7 @@ ssh railiance01 kubectl -n agent-harness rollout status deploy/agent-harness Full path uses the host deploy key and hub bridge: ```bash -ssh railiance01 'bash ~/agent-harness/deploy/scripts/railiance-smoke.sh' +ssh railiance01 'bash ~/rein-aharness/deploy/scripts/railiance-smoke.sh' ``` Expect: local commit + push to `executor-sandbox`, hub event `harness_smoke`, diff --git a/deploy/k8s/railiance/00-namespace.yaml b/deploy/k8s/railiance/00-namespace.yaml index 93375a3..dac0910 100644 --- a/deploy/k8s/railiance/00-namespace.yaml +++ b/deploy/k8s/railiance/00-namespace.yaml @@ -1,7 +1,7 @@ apiVersion: v1 kind: Namespace metadata: - name: agent-harness + name: rein-aharness labels: - app.kubernetes.io/part-of: agent-harness - app.kubernetes.io/name: agent-harness + app.kubernetes.io/part-of: rein-aharness + app.kubernetes.io/name: rein-aharness diff --git a/deploy/k8s/railiance/configmap.yaml b/deploy/k8s/railiance/configmap.yaml index 6de25b2..02a0e0f 100644 --- a/deploy/k8s/railiance/configmap.yaml +++ b/deploy/k8s/railiance/configmap.yaml @@ -1,10 +1,10 @@ apiVersion: v1 kind: ConfigMap metadata: - name: agent-harness-config - namespace: agent-harness + name: rein-aharness-config + namespace: rein-aharness labels: - app.kubernetes.io/name: agent-harness + app.kubernetes.io/name: rein-aharness data: # In-cluster State Hub (production). Host-level smoke may override to # http://127.0.0.1:18000 (ops-bridge reverse tunnel to workstation hub). diff --git a/deploy/k8s/railiance/deployment.yaml b/deploy/k8s/railiance/deployment.yaml index d62b8ec..06b6b00 100644 --- a/deploy/k8s/railiance/deployment.yaml +++ b/deploy/k8s/railiance/deployment.yaml @@ -3,32 +3,32 @@ apiVersion: apps/v1 kind: Deployment metadata: - name: agent-harness - namespace: agent-harness + name: rein-aharness + namespace: rein-aharness labels: - app.kubernetes.io/name: agent-harness - app.kubernetes.io/part-of: agent-harness + app.kubernetes.io/name: rein-aharness + app.kubernetes.io/part-of: rein-aharness spec: replicas: 1 selector: matchLabels: - app.kubernetes.io/name: agent-harness + app.kubernetes.io/name: rein-aharness template: metadata: labels: - app.kubernetes.io/name: agent-harness - app.kubernetes.io/part-of: agent-harness + app.kubernetes.io/name: rein-aharness + app.kubernetes.io/part-of: rein-aharness spec: securityContext: fsGroup: 10001 containers: - - name: agent-harness - image: agent-harness:railiance01 + - name: rein-aharness + image: rein-aharness:railiance01 imagePullPolicy: Never command: ["sleep", "infinity"] envFrom: - configMapRef: - name: agent-harness-config + name: rein-aharness-config resources: requests: cpu: 25m diff --git a/deploy/k8s/railiance/job-smoke.yaml b/deploy/k8s/railiance/job-smoke.yaml index 08ba245..fd518cf 100644 --- a/deploy/k8s/railiance/job-smoke.yaml +++ b/deploy/k8s/railiance/job-smoke.yaml @@ -4,10 +4,10 @@ apiVersion: batch/v1 kind: Job metadata: - name: agent-harness-smoke - namespace: agent-harness + name: rein-aharness-smoke + namespace: rein-aharness labels: - app.kubernetes.io/name: agent-harness + app.kubernetes.io/name: rein-aharness app.kubernetes.io/component: smoke spec: ttlSecondsAfterFinished: 600 @@ -15,7 +15,7 @@ spec: template: metadata: labels: - app.kubernetes.io/name: agent-harness + app.kubernetes.io/name: rein-aharness app.kubernetes.io/component: smoke spec: restartPolicy: Never @@ -23,13 +23,13 @@ spec: fsGroup: 10001 containers: - name: smoke - image: agent-harness:railiance01 + image: rein-aharness:railiance01 imagePullPolicy: Never args: - "profiles" envFrom: - configMapRef: - name: agent-harness-config + name: rein-aharness-config resources: requests: cpu: 50m diff --git a/deploy/k8s/railiance/kustomization.yaml b/deploy/k8s/railiance/kustomization.yaml index e9dbf38..baee3a8 100644 --- a/deploy/k8s/railiance/kustomization.yaml +++ b/deploy/k8s/railiance/kustomization.yaml @@ -1,6 +1,6 @@ apiVersion: kustomize.config.k8s.io/v1beta1 kind: Kustomization -namespace: agent-harness +namespace: rein-aharness resources: - 00-namespace.yaml - configmap.yaml diff --git a/deploy/scripts/railiance-smoke.sh b/deploy/scripts/railiance-smoke.sh index 09adc88..75d63a4 100755 --- a/deploy/scripts/railiance-smoke.sh +++ b/deploy/scripts/railiance-smoke.sh @@ -1,17 +1,22 @@ #!/usr/bin/env bash -# Host-level Railiance smoke for agent-harness (HARNESS-WP-0001-T06). +# Host-level Railiance smoke for rein-aharness (HARNESS-WP-0001-T06). # Run on railiance01 after install. Uses deploy key + AppRole env + hub :18000. +# +# HARNESS-WP-0002-T02 rename: ROOT default and the AppRole env path below +# changed from agent-harness to rein-aharness. Both must exist under the +# NEW name on the host (checkout dir + ~/.local/rein-aharness/) before this +# script is deployed — see deploy/README.md "Rename cutover checklist". set -euo pipefail -ROOT="${AGENT_HARNESS_ROOT:-$HOME/agent-harness}" +ROOT="${REIN_AHARNESS_ROOT:-$HOME/rein-aharness}" # shellcheck disable=SC1090 -source "${HOME}/.local/agent-harness/env" +source "${HOME}/.local/rein-aharness/env" export STATE_HUB_URL="${STATE_HUB_URL:-http://127.0.0.1:18000}" export PATH="${HOME}/.local/bin:${PATH}" export PYTHONPATH="${ROOT}:${HOME}/llm-connect${PYTHONPATH:+:$PYTHONPATH}" cd "$ROOT" -if ! command -v agent-harness >/dev/null 2>&1; then +if ! command -v rein-aharness >/dev/null 2>&1; then python3 -m pip install --user -e . -q fi @@ -19,6 +24,6 @@ echo "STATE_HUB_URL=$STATE_HUB_URL" curl -sS -m 5 "$STATE_HUB_URL/state/health" || curl -sS -m 5 "${STATE_HUB_URL%/}/" || true echo -agent-harness smoke \ +rein-aharness smoke \ --work-dir "${HOME}/work/executor-sandbox" \ --remote "ssh://git@forgejo-agent-harness/coulomb/executor-sandbox.git" diff --git a/docs/instance-manifest.md b/docs/instance-manifest.md index fc0df58..3d398a2 100644 --- a/docs/instance-manifest.md +++ b/docs/instance-manifest.md @@ -10,7 +10,7 @@ ``` **Same file as ADR-005.** kaizen-agentic owns the base schedule keys; -agent-harness owns the extension keys below. A sibling file is reserved +rein-aharness owns the extension keys below. A sibling file is reserved only if kaizen owners later prefer hard separation — until then, one manifest keeps cadence and runtime policy colocated. @@ -18,8 +18,8 @@ Validate: ```bash kaizen-agentic schedule validate --target # base ADR-005 keys -agent-harness validate --target # base + harness extensions -agent-harness validate --target --strict # require harness fields on enabled agents +rein-aharness validate --target # base + harness extensions +rein-aharness validate --target --strict # require harness fields on enabled agents ``` ## Schema @@ -39,12 +39,12 @@ agent-harness validate --target --strict # require harness fields on e | `agents..budget` | harness | no | int | Token cap per run (positive) | | `agents..harness` | harness | no | int | Per-agent major pin; overrides top-level | -\* Required for enabled agents under `agent-harness validate --strict`. +\* Required for enabled agents under `rein-aharness validate --strict`. ## Example (tenant-ready) ```yaml -# .kaizen/schedule.yml — ADR-005 + agent-harness extensions +# .kaizen/schedule.yml — ADR-005 + rein-aharness extensions version: "1" timezone: Europe/Berlin harness: 0 @@ -75,7 +75,7 @@ agents: ## Tool profiles -Defined **only** in agent-harness (see `agent_harness/profiles.py`). +Defined **only** in rein-aharness (see `rein_aharness/profiles.py`). Manifests reference them by name; unknown names refuse to run. | Name | Lane | Session tools | @@ -99,7 +99,7 @@ deliberate. ## Relationship to task files -Local development may still use JSON task files (`agent-harness run +Local development may still use JSON task files (`rein-aharness run --task-file …`). When the target repo has a matching agent entry, the runner resolves `tool_profile`, `budget`, and `lane` from the manifest; otherwise it defaults to `green-commit-only` with no budget cap. diff --git a/docs/task-intake.md b/docs/task-intake.md index 2179efa..ed94d02 100644 --- a/docs/task-intake.md +++ b/docs/task-intake.md @@ -1,13 +1,13 @@ # Task intake (HARNESS-WP-0001-T03) activity-core emits tasks via IssueSink → `POST /issues/` on **issue-core**. -agent-harness **consumes** them by polling the same service: +rein-aharness **consumes** them by polling the same service: ``` activity-core (cron/rule) → IssueCoreRestSink POST /issues/ → issue-core backend (sqlite / gitea) - → agent-harness poll/claim GET+PATCH /issues/ + → rein-aharness poll/claim GET+PATCH /issues/ → run_task (profile + budget + persona + session) → PATCH close + hub progress + .kaizen/metrics ``` @@ -17,8 +17,8 @@ activity-core (cron/rule) ## Mail path (server / Railiance) ``` -agent-harness mail-scan # deterministic IMAP (AppRole) -agent-harness mail-triage # llm-connect HTTP → JSON → apply mail-log + commit +rein-aharness mail-scan # deterministic IMAP (AppRole) +rein-aharness mail-triage # llm-connect HTTP → JSON → apply mail-log + commit ``` Requires `LLM_CONNECT_URL` (e.g. in-cluster @@ -45,14 +45,14 @@ export ISSUE_CORE_API_KEY=… export AGENT_HARNESS_REPO_MAP='{"binky-control":"/home/tegwick/binky-control"}' # Peek / claim without executing -agent-harness poll -agent-harness poll --no-claim +rein-aharness poll +rein-aharness poll --no-claim # Claim → run → close (or reopen on failure) -agent-harness run --from-issue-core +rein-aharness run --from-issue-core # Local dev (unchanged) -agent-harness run --task-file examples/task-hello-sandbox.json --no-hub +rein-aharness run --task-file examples/task-hello-sandbox.json --no-hub ``` ## Label filter diff --git a/examples/schedule.harness.yml b/examples/schedule.harness.yml index d02de89..4ae383a 100644 --- a/examples/schedule.harness.yml +++ b/examples/schedule.harness.yml @@ -1,7 +1,7 @@ -# Example instance manifest (ADR-005 + agent-harness extensions). +# Example instance manifest (ADR-005 + rein-aharness extensions). # Copy keys into a consuming repo's .kaizen/schedule.yml. # Validate with: -# agent-harness validate --target --strict +# rein-aharness validate --target --strict version: "1" timezone: Europe/Berlin harness: 0 diff --git a/pyproject.toml b/pyproject.toml index b6310b0..285f4a7 100644 --- a/pyproject.toml +++ b/pyproject.toml @@ -9,7 +9,7 @@ dependencies = [ ] [project.scripts] -agent-harness = "agent_harness.cli:main" +rein-aharness = "rein_aharness.cli:main" [tool.uv.sources] llm-connect = { path = "../llm-connect", editable = true } @@ -23,4 +23,4 @@ requires = ["hatchling"] build-backend = "hatchling.build" [tool.hatch.build.targets.wheel] -packages = ["agent_harness"] +packages = ["rein_aharness"] diff --git a/agent_harness/__init__.py b/rein_aharness/__init__.py similarity index 100% rename from agent_harness/__init__.py rename to rein_aharness/__init__.py diff --git a/agent_harness/adapter.py b/rein_aharness/adapter.py similarity index 98% rename from agent_harness/adapter.py rename to rein_aharness/adapter.py index 8b17a40..1697646 100644 --- a/agent_harness/adapter.py +++ b/rein_aharness/adapter.py @@ -20,7 +20,7 @@ from llm_connect.claude_code import ClaudeCodeAdapter from llm_connect.exceptions import LLMSubprocessError, LLMTimeoutError from llm_connect.models import LLMResponse, RunConfig -from agent_harness.profiles import ToolProfile, get_profile +from rein_aharness.profiles import ToolProfile, get_profile # Backward-compatible alias for the seed profile allow-list string. ALLOWED_TOOLS = get_profile("green-commit-only").allowed_tools diff --git a/agent_harness/brief_daily.py b/rein_aharness/brief_daily.py similarity index 99% rename from agent_harness/brief_daily.py rename to rein_aharness/brief_daily.py index ee730df..89346e4 100644 --- a/agent_harness/brief_daily.py +++ b/rein_aharness/brief_daily.py @@ -16,8 +16,8 @@ from pathlib import Path from typing import Any, Callable from zoneinfo import ZoneInfo -from agent_harness import hub -from agent_harness.llm_connect_client import ( +from rein_aharness import hub +from rein_aharness.llm_connect_client import ( LLMConnectClient, LLMConnectError, get_llm_connect_client, diff --git a/agent_harness/cli.py b/rein_aharness/cli.py similarity index 95% rename from agent_harness/cli.py rename to rein_aharness/cli.py index 566a70d..83fb207 100644 --- a/agent_harness/cli.py +++ b/rein_aharness/cli.py @@ -7,15 +7,15 @@ import json import sys from pathlib import Path -from agent_harness.manifest import ( +from rein_aharness.manifest import ( ManifestError, load_manifest_for_repo, manifest_path, validate_manifest, ) -from agent_harness.profiles import list_profiles -from agent_harness.runner import run_task -from agent_harness.taskspec import TaskSpec, TaskSpecError +from rein_aharness.profiles import list_profiles +from rein_aharness.runner import run_task +from rein_aharness.taskspec import TaskSpec, TaskSpecError def _cmd_validate(args: argparse.Namespace) -> int: @@ -69,7 +69,7 @@ def _cmd_profiles(_args: argparse.Namespace) -> int: def _cmd_poll(args: argparse.Namespace) -> int: - from agent_harness.intake import IntakeError, IssueCoreClient, poll_next + from rein_aharness.intake import IntakeError, IssueCoreClient, poll_next try: client = IssueCoreClient() @@ -100,7 +100,7 @@ def _cmd_poll(args: argparse.Namespace) -> int: def _cmd_run(args: argparse.Namespace) -> int: - from agent_harness.intake import IntakeError, IssueCoreClient, poll_next + from rein_aharness.intake import IntakeError, IssueCoreClient, poll_next issue_id: str | None = None client: IssueCoreClient | None = None @@ -171,7 +171,7 @@ def _cmd_run(args: argparse.Namespace) -> int: def main(argv: list[str] | None = None) -> int: - parser = argparse.ArgumentParser(prog="agent-harness") + parser = argparse.ArgumentParser(prog="rein-aharness") sub = parser.add_subparsers(dest="command", required=True) run = sub.add_parser( @@ -305,7 +305,7 @@ def main(argv: list[str] | None = None) -> int: return _cmd_run(args) if args.command == "smoke": - from agent_harness.smoke import ensure_sandbox_clone, run_smoke + from rein_aharness.smoke import ensure_sandbox_clone, run_smoke if args.target_repo: repo = Path(args.target_repo).expanduser().resolve() @@ -348,7 +348,7 @@ def main(argv: list[str] | None = None) -> int: return 0 if ok else 1 if args.command == "mail-triage": - from agent_harness.mail_triage import run_mail_triage + from rein_aharness.mail_triage import run_mail_triage triage_result = run_mail_triage( target_repo=Path(args.target_repo).expanduser(), @@ -377,7 +377,7 @@ def main(argv: list[str] | None = None) -> int: if args.command == "brief-daily": from datetime import date as date_cls - from agent_harness.brief_daily import run_brief_daily + from rein_aharness.brief_daily import run_brief_daily day = None if args.date: @@ -408,7 +408,7 @@ def main(argv: list[str] | None = None) -> int: return 0 if brief_result.ok else 1 if args.command == "mail-scan": - from agent_harness.mailscan import run_mail_scan + from rein_aharness.mailscan import run_mail_scan result = run_mail_scan( target_repo=Path(args.target_repo).expanduser(), diff --git a/agent_harness/hub.py b/rein_aharness/hub.py similarity index 98% rename from agent_harness/hub.py rename to rein_aharness/hub.py index edcbad2..1f88f7b 100644 --- a/agent_harness/hub.py +++ b/rein_aharness/hub.py @@ -71,7 +71,7 @@ def post_token_event( payload: dict[str, Any] = { "repo": repo, "tokens": tokens, - "source": "agent-harness", + "source": "rein-aharness", "ok": ok, } if budget is not None: diff --git a/agent_harness/intake.py b/rein_aharness/intake.py similarity index 97% rename from agent_harness/intake.py rename to rein_aharness/intake.py index 7eb4876..5add966 100644 --- a/agent_harness/intake.py +++ b/rein_aharness/intake.py @@ -8,11 +8,11 @@ Environment: ISSUE_CORE_URL default http://127.0.0.1:8765 ISSUE_CORE_API_KEY required for live poll AGENT_HARNESS_INTAKE_LABELS comma list; issue must have ALL (default: automated) - AGENT_HARNESS_ASSIGNEE claim assignee (default: agent-harness) + AGENT_HARNESS_ASSIGNEE claim assignee (default: rein-aharness) AGENT_HARNESS_REPO_MAP JSON object name→path, e.g. {"binky-control":"~/binky-control"} AGENT_HARNESS_REPO_ROOTS colon-separated search roots (default: ~:~/work) -Local development still uses `agent-harness run --task-file …`. +Local development still uses `rein-aharness run --task-file …`. """ from __future__ import annotations @@ -25,11 +25,11 @@ from typing import Any import httpx -from agent_harness.taskspec import TaskSpec, TaskSpecError +from rein_aharness.taskspec import TaskSpec, TaskSpecError DEFAULT_ISSUE_CORE_URL = "http://127.0.0.1:8765" DEFAULT_INTAKE_LABELS = ("automated",) -DEFAULT_ASSIGNEE = "agent-harness" +DEFAULT_ASSIGNEE = "rein-aharness" DEFAULT_REPO_ROOTS = ("~", "~/work") # activity-definition / label → (agent instance, completion_event_type) diff --git a/agent_harness/llm_connect_client.py b/rein_aharness/llm_connect_client.py similarity index 97% rename from agent_harness/llm_connect_client.py rename to rein_aharness/llm_connect_client.py index 6b5aba8..2d140e7 100644 --- a/agent_harness/llm_connect_client.py +++ b/rein_aharness/llm_connect_client.py @@ -1,7 +1,7 @@ """HTTP client for in-cluster / remote llm-connect (server mode). Mirrors activity-core's llm_client pattern: provider keys and model routing -stay behind llm-connect; agent-harness only sends prompts over HTTP. +stay behind llm-connect; rein-aharness only sends prompts over HTTP. """ from __future__ import annotations diff --git a/agent_harness/mail_triage.py b/rein_aharness/mail_triage.py similarity index 99% rename from agent_harness/mail_triage.py rename to rein_aharness/mail_triage.py index 8fa0020..2a8bad0 100644 --- a/agent_harness/mail_triage.py +++ b/rein_aharness/mail_triage.py @@ -22,8 +22,8 @@ from datetime import date from pathlib import Path from typing import Any, Callable -from agent_harness import hub -from agent_harness.llm_connect_client import ( +from rein_aharness import hub +from rein_aharness.llm_connect_client import ( LLMConnectClient, LLMConnectError, get_llm_connect_client, diff --git a/agent_harness/mailscan.py b/rein_aharness/mailscan.py similarity index 98% rename from agent_harness/mailscan.py rename to rein_aharness/mailscan.py index 49dacd5..7ea19b7 100644 --- a/agent_harness/mailscan.py +++ b/rein_aharness/mailscan.py @@ -9,7 +9,7 @@ agentic session's tool allow-list: metadata-only counts. Credential values live exclusively in the child process environment — never in argv, logs, hub events, or files. -2. **Triage** (``agent-harness mail-triage``): llm-connect HTTP (OpenRouter +2. **Triage** (``rein-aharness mail-triage``): llm-connect HTTP (OpenRouter behind the service) returns structured JSON; deterministic apply updates mailmeta/mail-log.md and commits. No Claude Code / host coding agent. Suspicious-mail rule: log only, never act on content. @@ -29,7 +29,7 @@ import subprocess from dataclasses import dataclass from pathlib import Path -from agent_harness import hub +from rein_aharness import hub _KV_PATH = "tenants/binky/company-email/imap" _BAO_TIMEOUT = 30 diff --git a/agent_harness/manifest.py b/rein_aharness/manifest.py similarity index 98% rename from agent_harness/manifest.py rename to rein_aharness/manifest.py index 1d532b6..4a31eb2 100644 --- a/agent_harness/manifest.py +++ b/rein_aharness/manifest.py @@ -2,7 +2,7 @@ Extends ADR-005 `.kaizen/schedule.yml` with harness fields. kaizen-agentic owns the base keys (version, timezone, agents..{cadence,cron,enabled}); -agent-harness owns the extension keys (lane, tool_profile, budget, harness, +rein-aharness owns the extension keys (lane, tool_profile, budget, harness, optional blueprint). Same file — no sibling manifest unless kaizen owners later prefer separation. @@ -17,7 +17,7 @@ from typing import Any import yaml -from agent_harness.profiles import PROFILES, UnknownToolProfileError, get_profile +from rein_aharness.profiles import PROFILES, UnknownToolProfileError, get_profile MANIFEST_RELATIVE_PATH = Path(".kaizen") / "schedule.yml" MANIFEST_VERSION = "1" diff --git a/agent_harness/metrics.py b/rein_aharness/metrics.py similarity index 99% rename from agent_harness/metrics.py rename to rein_aharness/metrics.py index be18cf6..4e5fcc5 100644 --- a/agent_harness/metrics.py +++ b/rein_aharness/metrics.py @@ -33,7 +33,7 @@ class ExecutionRecord: committed: bool | None = None head_after: str | None = None reason: str | None = None - harness: str = "agent-harness" + harness: str = "rein-aharness" def to_json_line(self) -> str: data = asdict(self) diff --git a/agent_harness/persona.py b/rein_aharness/persona.py similarity index 100% rename from agent_harness/persona.py rename to rein_aharness/persona.py diff --git a/agent_harness/profiles.py b/rein_aharness/profiles.py similarity index 100% rename from agent_harness/profiles.py rename to rein_aharness/profiles.py diff --git a/agent_harness/runner.py b/rein_aharness/runner.py similarity index 95% rename from agent_harness/runner.py rename to rein_aharness/runner.py index 7248f01..c9d9e4a 100644 --- a/agent_harness/runner.py +++ b/rein_aharness/runner.py @@ -15,11 +15,11 @@ import time from dataclasses import dataclass from pathlib import Path -from agent_harness import hub, metrics -from agent_harness.manifest import resolve_run_policy -from agent_harness.persona import load_persona_bundle -from agent_harness.profiles import UnknownToolProfileError, get_profile -from agent_harness.taskspec import TaskSpec +from rein_aharness import hub, metrics +from rein_aharness.manifest import resolve_run_policy +from rein_aharness.persona import load_persona_bundle +from rein_aharness.profiles import UnknownToolProfileError, get_profile +from rein_aharness.taskspec import TaskSpec PROMPT_TEMPLATE = """\ You are an unattended executor session (agent persona below, if any). @@ -104,7 +104,7 @@ def run_task( ) if adapter is None: - from agent_harness.adapter import AgenticClaudeCodeAdapter + from rein_aharness.adapter import AgenticClaudeCodeAdapter adapter = AgenticClaudeCodeAdapter( workdir=spec.target_repo, diff --git a/agent_harness/smoke.py b/rein_aharness/smoke.py similarity index 93% rename from agent_harness/smoke.py rename to rein_aharness/smoke.py index b8ca122..233858d 100644 --- a/agent_harness/smoke.py +++ b/rein_aharness/smoke.py @@ -12,8 +12,8 @@ from dataclasses import dataclass from datetime import datetime, timezone from pathlib import Path -from agent_harness.runner import RunResult, run_task -from agent_harness.taskspec import TaskSpec +from rein_aharness.runner import RunResult, run_task +from rein_aharness.taskspec import TaskSpec @dataclass @@ -35,7 +35,7 @@ class _CommittingSmokeAdapter: self.prompts.append(prompt) path = self.repo / "SMOKE.md" path.write_text( - f"# agent-harness smoke\n\nstamp: {self.stamp}\n", + f"# rein-aharness smoke\n\nstamp: {self.stamp}\n", encoding="utf-8", ) subprocess.run(["git", "add", "SMOKE.md"], cwd=self.repo, check=True) @@ -43,9 +43,9 @@ class _CommittingSmokeAdapter: [ "git", "-c", - "user.email=agent-harness@railiance.local", + "user.email=rein-aharness@railiance.local", "-c", - "user.name=agent-harness", + "user.name=rein-aharness", "commit", "-qm", f"harness smoke: {self.stamp}", diff --git a/agent_harness/taskspec.py b/rein_aharness/taskspec.py similarity index 100% rename from agent_harness/taskspec.py rename to rein_aharness/taskspec.py diff --git a/scripts/tenant_onboard_runs.py b/scripts/tenant_onboard_runs.py index 1f129d8..7eb5df5 100644 --- a/scripts/tenant_onboard_runs.py +++ b/scripts/tenant_onboard_runs.py @@ -19,8 +19,8 @@ _ROOT = Path(__file__).resolve().parents[1] if str(_ROOT) not in sys.path: sys.path.insert(0, str(_ROOT)) -from agent_harness.runner import run_task -from agent_harness.taskspec import TaskSpec +from rein_aharness.runner import run_task +from rein_aharness.taskspec import TaskSpec class EvidenceAdapter: @@ -47,9 +47,9 @@ class EvidenceAdapter: [ "git", "-c", - "user.email=agent-harness@local", + "user.email=rein-aharness@local", "-c", - "user.name=agent-harness", + "user.name=rein-aharness", "commit", "-qm", f"harness onboard: {self.slug}", diff --git a/tests/test_brief_daily.py b/tests/test_brief_daily.py index c57b31d..67816a4 100644 --- a/tests/test_brief_daily.py +++ b/tests/test_brief_daily.py @@ -5,7 +5,7 @@ import subprocess from datetime import date from pathlib import Path -from agent_harness import brief_daily +from rein_aharness import brief_daily def _git_repo(tmp_path: Path) -> Path: diff --git a/tests/test_intake.py b/tests/test_intake.py index 6abedca..780a15d 100644 --- a/tests/test_intake.py +++ b/tests/test_intake.py @@ -7,7 +7,7 @@ from unittest.mock import MagicMock, patch import pytest -from agent_harness.intake import ( +from rein_aharness.intake import ( EmittedIssue, IntakeConfig, IssueCoreClient, @@ -16,7 +16,7 @@ from agent_harness.intake import ( poll_next, resolve_target_repo, ) -from agent_harness.taskspec import TaskSpecError +from rein_aharness.taskspec import TaskSpecError def _make_repo(tmp_path: Path, name: str = "binky-control") -> Path: @@ -110,7 +110,7 @@ def test_client_list_claim_close() -> None: base_url="http://issue-core.test", api_key="k", require_labels=("automated",), - assignee="agent-harness", + assignee="rein-aharness", ) client = IssueCoreClient(cfg) @@ -126,11 +126,11 @@ def test_client_list_claim_close() -> None: "activity_definition_id": "binky-daily-rhythm", } ] - claim_body = {**list_body[0], "state": "in_progress", "assignee": "agent-harness"} + claim_body = {**list_body[0], "state": "in_progress", "assignee": "rein-aharness"} close_body = {**claim_body, "state": "closed"} - with patch("agent_harness.intake.httpx.get") as get_mock, patch( - "agent_harness.intake.httpx.patch" + with patch("rein_aharness.intake.httpx.get") as get_mock, patch( + "rein_aharness.intake.httpx.patch" ) as patch_mock: get_resp = MagicMock() get_resp.raise_for_status = MagicMock() diff --git a/tests/test_mail_triage.py b/tests/test_mail_triage.py index 83b15c6..ad50d69 100644 --- a/tests/test_mail_triage.py +++ b/tests/test_mail_triage.py @@ -6,8 +6,8 @@ from pathlib import Path import pytest -from agent_harness import mail_triage -from agent_harness.llm_connect_client import LLMConnectClient, LLMConnectError +from rein_aharness import mail_triage +from rein_aharness.llm_connect_client import LLMConnectClient, LLMConnectError def _git_repo(tmp_path: Path) -> Path: @@ -166,7 +166,7 @@ def test_run_mail_triage_no_report(tmp_path: Path, monkeypatch) -> None: def test_llm_connect_client_complete(monkeypatch) -> None: - import agent_harness.llm_connect_client as mod + import rein_aharness.llm_connect_client as mod class FakeResp: def raise_for_status(self) -> None: @@ -190,6 +190,6 @@ def test_llm_connect_client_complete(monkeypatch) -> None: def test_get_client_requires_env(monkeypatch) -> None: monkeypatch.delenv("LLM_CONNECT_URL", raising=False) with pytest.raises(LLMConnectError, match="LLM_CONNECT_URL"): - from agent_harness.llm_connect_client import get_llm_connect_client + from rein_aharness.llm_connect_client import get_llm_connect_client get_llm_connect_client() diff --git a/tests/test_mailscan.py b/tests/test_mailscan.py index 3d476a1..6889a49 100644 --- a/tests/test_mailscan.py +++ b/tests/test_mailscan.py @@ -5,7 +5,7 @@ from pathlib import Path import pytest -from agent_harness import mailscan +from rein_aharness import mailscan class FakeCompleted: diff --git a/tests/test_manifest.py b/tests/test_manifest.py index 11b56a5..4b78c68 100644 --- a/tests/test_manifest.py +++ b/tests/test_manifest.py @@ -5,8 +5,8 @@ from pathlib import Path import pytest import yaml -from agent_harness.cli import main -from agent_harness.manifest import ( +from rein_aharness.cli import main +from rein_aharness.manifest import ( HARNESS_MAJOR, ManifestError, load_manifest, @@ -14,7 +14,7 @@ from agent_harness.manifest import ( resolve_run_policy, validate_manifest, ) -from agent_harness.profiles import UnknownToolProfileError, get_profile, list_profiles +from rein_aharness.profiles import UnknownToolProfileError, get_profile, list_profiles def _write_manifest(tmp_path: Path, data: dict) -> Path: diff --git a/tests/test_metrics.py b/tests/test_metrics.py index 171849e..24c2369 100644 --- a/tests/test_metrics.py +++ b/tests/test_metrics.py @@ -3,7 +3,7 @@ from __future__ import annotations import json from pathlib import Path -from agent_harness.metrics import record_execution, regenerate_summary +from rein_aharness.metrics import record_execution, regenerate_summary def test_record_execution_writes_jsonl_and_summary(tmp_path: Path) -> None: @@ -25,7 +25,7 @@ def test_record_execution_writes_jsonl_and_summary(tmp_path: Path) -> None: assert rec["agent"] == "coach" assert rec["success"] is True assert rec["tokens"] == 100 - assert rec["harness"] == "agent-harness" + assert rec["harness"] == "rein-aharness" assert rec["metadata"]["task_title"] == "hello" summary = json.loads( diff --git a/tests/test_runner.py b/tests/test_runner.py index 89774eb..da6e805 100644 --- a/tests/test_runner.py +++ b/tests/test_runner.py @@ -7,9 +7,9 @@ from pathlib import Path import pytest import yaml -from agent_harness.manifest import HARNESS_MAJOR -from agent_harness.runner import RunResult, run_task -from agent_harness.taskspec import TaskSpec, TaskSpecError +from rein_aharness.manifest import HARNESS_MAJOR +from rein_aharness.runner import RunResult, run_task +from rein_aharness.taskspec import TaskSpec, TaskSpecError def _make_repo(tmp_path: Path) -> Path: diff --git a/tests/test_smoke.py b/tests/test_smoke.py index 4352cdd..c7becdc 100644 --- a/tests/test_smoke.py +++ b/tests/test_smoke.py @@ -3,7 +3,7 @@ from __future__ import annotations import subprocess from pathlib import Path -from agent_harness.smoke import run_smoke +from rein_aharness.smoke import run_smoke def _make_repo(tmp_path: Path) -> Path: diff --git a/workplans/HARNESS-WP-0002-rename-and-glas-harness-alignment.md b/workplans/HARNESS-WP-0002-rename-and-glas-harness-alignment.md index 0476d5e..725fbf6 100644 --- a/workplans/HARNESS-WP-0002-rename-and-glas-harness-alignment.md +++ b/workplans/HARNESS-WP-0002-rename-and-glas-harness-alignment.md @@ -33,19 +33,48 @@ state_hub_task_id: "bf04ed50-cbe2-4f8f-9876-d06c579d19e6" 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 (`pyproject.toml -[project.scripts]`, `agent_harness/cli.py` entry point), the -`agent_harness` Python package directory, the Docker image tag -(`agent-harness:railiance01`), the k8s namespace/labels/ConfigMap names -(`deploy/k8s/railiance/*.yaml`), the Railiance host directory -(`~/agent-harness/deploy/...`), and `deploy/scripts/railiance-smoke.sh`'s -`AGENT_HARNESS_ROOT` env var and SSH remote alias. Do this as one -reviewed change with a Railiance re-deploy and smoke-test run -immediately after, not as incidental cleanup. +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: todo +status: progress priority: medium state_hub_task_id: "7c5d23cd-d7fd-4c79-8847-448b83feb673" ```