Harness foundation: INTENT, ADR-001, architecture, prototype adoption
- INTENT.md: three-layer model (blueprint/instance/harness), single
shared runtime, never-become boundaries
- ADR-001 (accepted): DEC-2026-002 resolution — one harness repo for
all projects; instances are declarative state in consuming repos
- docs/architecture.md: components, contracts (manifest, tool
profiles, completion events, credential lanes), deployment shape
- agent_harness/: executor-worker prototype adopted and renamed
(6/6 tests green); HARNESS-WP-0001 initial workplan (7 tasks)
Co-Authored-By: Claude Fable 5 <noreply@anthropic.com>
2026-07-17 23:35:27 +02:00
|
|
|
"""One-task run orchestration.
|
|
|
|
|
|
2026-07-17 23:49:03 +02:00
|
|
|
Flow: lock target repo → resolve tool profile / budget from instance
|
|
|
|
|
manifest → snapshot HEAD → persona bundle → prompt → agentic session →
|
2026-09-04 11:25:07 +02:00
|
|
|
validate an explicit repository grant when present → metrics + hub progress
|
|
|
|
|
event (+ task close). Granted runs use durable external metrics so repository
|
|
|
|
|
acceptance remains clean. The worker never pushes; publishing is a separate,
|
|
|
|
|
explicitly-granted lane.
|
Harness foundation: INTENT, ADR-001, architecture, prototype adoption
- INTENT.md: three-layer model (blueprint/instance/harness), single
shared runtime, never-become boundaries
- ADR-001 (accepted): DEC-2026-002 resolution — one harness repo for
all projects; instances are declarative state in consuming repos
- docs/architecture.md: components, contracts (manifest, tool
profiles, completion events, credential lanes), deployment shape
- agent_harness/: executor-worker prototype adopted and renamed
(6/6 tests green); HARNESS-WP-0001 initial workplan (7 tasks)
Co-Authored-By: Claude Fable 5 <noreply@anthropic.com>
2026-07-17 23:35:27 +02:00
|
|
|
"""
|
|
|
|
|
|
|
|
|
|
from __future__ import annotations
|
|
|
|
|
|
|
|
|
|
import subprocess
|
2026-07-17 23:49:03 +02:00
|
|
|
import time
|
2026-07-26 14:49:36 +02:00
|
|
|
from dataclasses import dataclass, field
|
Harness foundation: INTENT, ADR-001, architecture, prototype adoption
- INTENT.md: three-layer model (blueprint/instance/harness), single
shared runtime, never-become boundaries
- ADR-001 (accepted): DEC-2026-002 resolution — one harness repo for
all projects; instances are declarative state in consuming repos
- docs/architecture.md: components, contracts (manifest, tool
profiles, completion events, credential lanes), deployment shape
- agent_harness/: executor-worker prototype adopted and renamed
(6/6 tests green); HARNESS-WP-0001 initial workplan (7 tasks)
Co-Authored-By: Claude Fable 5 <noreply@anthropic.com>
2026-07-17 23:35:27 +02:00
|
|
|
from pathlib import Path
|
2026-07-26 14:49:36 +02:00
|
|
|
from typing import Any, Callable
|
Harness foundation: INTENT, ADR-001, architecture, prototype adoption
- INTENT.md: three-layer model (blueprint/instance/harness), single
shared runtime, never-become boundaries
- ADR-001 (accepted): DEC-2026-002 resolution — one harness repo for
all projects; instances are declarative state in consuming repos
- docs/architecture.md: components, contracts (manifest, tool
profiles, completion events, credential lanes), deployment shape
- agent_harness/: executor-worker prototype adopted and renamed
(6/6 tests green); HARNESS-WP-0001 initial workplan (7 tasks)
Co-Authored-By: Claude Fable 5 <noreply@anthropic.com>
2026-07-17 23:35:27 +02:00
|
|
|
|
Rename package, CLI, and deploy artifacts to rein-aharness (HARNESS-WP-0002-T02)
agent_harness -> rein_aharness (package + all imports), CLI command
agent-harness -> rein-aharness, Docker image tag, k8s namespace/labels/
names, Makefile targets, deploy script env var/paths. In-repo identity
strings (hub event source, metrics harness field, default assignee,
argparse prog name, commit author identity) updated to match.
Historical documents left untouched on purpose: docs/adr/ADR-001-agent-harness-architecture.md,
docs/architecture.md (dated v0.1 snapshot), workplans/HARNESS-WP-0001
(completed under the old name), and the SSH host alias
"forgejo-agent-harness" (external ~/.ssh/config entry, not owned here).
Verified: 47/47 tests pass, CLI runs correctly from a fresh venv,
`make image` builds and the resulting container runs correctly.
deploy/README.md gained an explicit rename cutover checklist for what
this session cannot safely do unattended -- moving the host-side
secrets dir and checkout on railiance01, and not deleting the old k8s
namespace until the new one is confirmed working. The actual live
cutover (running that checklist against the real Railiance deployment)
is not attempted here -- real production surgery on binky-control's
live automation, needs the operator present.
Co-Authored-By: Claude Sonnet 5 <noreply@anthropic.com>
2026-07-26 14:22:18 +02:00
|
|
|
from rein_aharness import hub, metrics
|
2026-09-04 11:00:20 +02:00
|
|
|
from rein_aharness.execution_cancel import ExecutionCancelled
|
Rename package, CLI, and deploy artifacts to rein-aharness (HARNESS-WP-0002-T02)
agent_harness -> rein_aharness (package + all imports), CLI command
agent-harness -> rein-aharness, Docker image tag, k8s namespace/labels/
names, Makefile targets, deploy script env var/paths. In-repo identity
strings (hub event source, metrics harness field, default assignee,
argparse prog name, commit author identity) updated to match.
Historical documents left untouched on purpose: docs/adr/ADR-001-agent-harness-architecture.md,
docs/architecture.md (dated v0.1 snapshot), workplans/HARNESS-WP-0001
(completed under the old name), and the SSH host alias
"forgejo-agent-harness" (external ~/.ssh/config entry, not owned here).
Verified: 47/47 tests pass, CLI runs correctly from a fresh venv,
`make image` builds and the resulting container runs correctly.
deploy/README.md gained an explicit rename cutover checklist for what
this session cannot safely do unattended -- moving the host-side
secrets dir and checkout on railiance01, and not deleting the old k8s
namespace until the new one is confirmed working. The actual live
cutover (running that checklist against the real Railiance deployment)
is not attempted here -- real production surgery on binky-control's
live automation, needs the operator present.
Co-Authored-By: Claude Sonnet 5 <noreply@anthropic.com>
2026-07-26 14:22:18 +02:00
|
|
|
from rein_aharness.manifest import resolve_run_policy
|
|
|
|
|
from rein_aharness.persona import load_persona_bundle
|
|
|
|
|
from rein_aharness.profiles import UnknownToolProfileError, get_profile
|
2026-09-04 11:00:20 +02:00
|
|
|
from rein_aharness.repository_transaction import (
|
|
|
|
|
DirtyRepositoryError,
|
|
|
|
|
GitRepositoryError,
|
2026-09-04 11:25:07 +02:00
|
|
|
RepositoryAcceptanceError,
|
2026-09-04 11:00:20 +02:00
|
|
|
RepositoryBusyError,
|
|
|
|
|
RepositoryTransaction,
|
|
|
|
|
RepositoryTransactionError,
|
|
|
|
|
)
|
Rename package, CLI, and deploy artifacts to rein-aharness (HARNESS-WP-0002-T02)
agent_harness -> rein_aharness (package + all imports), CLI command
agent-harness -> rein-aharness, Docker image tag, k8s namespace/labels/
names, Makefile targets, deploy script env var/paths. In-repo identity
strings (hub event source, metrics harness field, default assignee,
argparse prog name, commit author identity) updated to match.
Historical documents left untouched on purpose: docs/adr/ADR-001-agent-harness-architecture.md,
docs/architecture.md (dated v0.1 snapshot), workplans/HARNESS-WP-0001
(completed under the old name), and the SSH host alias
"forgejo-agent-harness" (external ~/.ssh/config entry, not owned here).
Verified: 47/47 tests pass, CLI runs correctly from a fresh venv,
`make image` builds and the resulting container runs correctly.
deploy/README.md gained an explicit rename cutover checklist for what
this session cannot safely do unattended -- moving the host-side
secrets dir and checkout on railiance01, and not deleting the old k8s
namespace until the new one is confirmed working. The actual live
cutover (running that checklist against the real Railiance deployment)
is not attempted here -- real production surgery on binky-control's
live automation, needs the operator present.
Co-Authored-By: Claude Sonnet 5 <noreply@anthropic.com>
2026-07-26 14:22:18 +02:00
|
|
|
from rein_aharness.taskspec import TaskSpec
|
Harness foundation: INTENT, ADR-001, architecture, prototype adoption
- INTENT.md: three-layer model (blueprint/instance/harness), single
shared runtime, never-become boundaries
- ADR-001 (accepted): DEC-2026-002 resolution — one harness repo for
all projects; instances are declarative state in consuming repos
- docs/architecture.md: components, contracts (manifest, tool
profiles, completion events, credential lanes), deployment shape
- agent_harness/: executor-worker prototype adopted and renamed
(6/6 tests green); HARNESS-WP-0001 initial workplan (7 tasks)
Co-Authored-By: Claude Fable 5 <noreply@anthropic.com>
2026-07-17 23:35:27 +02:00
|
|
|
|
|
|
|
|
PROMPT_TEMPLATE = """\
|
|
|
|
|
You are an unattended executor session (agent persona below, if any).
|
|
|
|
|
Operating rules, non-negotiable:
|
|
|
|
|
- Work ONLY inside the current repository working directory.
|
|
|
|
|
- Green/Blue lane: file edits and local git add/commit only. Never push,
|
|
|
|
|
never touch the network, never run destructive commands.
|
2026-07-17 23:49:03 +02:00
|
|
|
- Tool profile for this run: {tool_profile} (lane={lane}).
|
Harness foundation: INTENT, ADR-001, architecture, prototype adoption
- INTENT.md: three-layer model (blueprint/instance/harness), single
shared runtime, never-become boundaries
- ADR-001 (accepted): DEC-2026-002 resolution — one harness repo for
all projects; instances are declarative state in consuming repos
- docs/architecture.md: components, contracts (manifest, tool
profiles, completion events, credential lanes), deployment shape
- agent_harness/: executor-worker prototype adopted and renamed
(6/6 tests green); HARNESS-WP-0001 initial workplan (7 tasks)
Co-Authored-By: Claude Fable 5 <noreply@anthropic.com>
2026-07-17 23:35:27 +02:00
|
|
|
- Bounded effort: complete the single task below, commit with a clear
|
|
|
|
|
message, then stop. If the task cannot be completed, commit nothing and
|
|
|
|
|
say why in your final output.
|
|
|
|
|
|
|
|
|
|
{persona}
|
|
|
|
|
|
|
|
|
|
## Task: {title}
|
|
|
|
|
|
|
|
|
|
{description}
|
|
|
|
|
"""
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
@dataclass
|
|
|
|
|
class RunResult:
|
|
|
|
|
ok: bool
|
|
|
|
|
committed: bool
|
|
|
|
|
head_before: str
|
|
|
|
|
head_after: str
|
|
|
|
|
persona_source: str
|
|
|
|
|
session_output: str
|
|
|
|
|
reason: str = ""
|
2026-08-21 00:21:53 +02:00
|
|
|
model: str | None = None
|
2026-07-17 23:49:03 +02:00
|
|
|
tool_profile: str = ""
|
|
|
|
|
budget_tokens: int | None = None
|
|
|
|
|
tokens_spent: int | None = None
|
|
|
|
|
execution_time_s: float = 0.0
|
2026-07-26 14:49:36 +02:00
|
|
|
# Real-time per-tool-call audit events, populated only when run_task is
|
|
|
|
|
# called with emit_tool_events=True. See adapter.py's module docstring
|
|
|
|
|
# for why this is observation, not external tool dispatch.
|
|
|
|
|
tool_events: list[dict[str, Any]] = field(default_factory=list)
|
2026-09-04 11:00:20 +02:00
|
|
|
transaction: dict[str, Any] | None = None
|
Harness foundation: INTENT, ADR-001, architecture, prototype adoption
- INTENT.md: three-layer model (blueprint/instance/harness), single
shared runtime, never-become boundaries
- ADR-001 (accepted): DEC-2026-002 resolution — one harness repo for
all projects; instances are declarative state in consuming repos
- docs/architecture.md: components, contracts (manifest, tool
profiles, completion events, credential lanes), deployment shape
- agent_harness/: executor-worker prototype adopted and renamed
(6/6 tests green); HARNESS-WP-0001 initial workplan (7 tasks)
Co-Authored-By: Claude Fable 5 <noreply@anthropic.com>
2026-07-17 23:35:27 +02:00
|
|
|
|
|
|
|
|
|
|
|
|
|
def _git(repo: Path, *args: str) -> str:
|
|
|
|
|
result = subprocess.run(
|
|
|
|
|
["git", "-C", str(repo), *args],
|
|
|
|
|
capture_output=True,
|
|
|
|
|
text=True,
|
|
|
|
|
timeout=60,
|
|
|
|
|
)
|
|
|
|
|
if result.returncode != 0:
|
|
|
|
|
raise RuntimeError(f"git {' '.join(args)} failed: {result.stderr.strip()}")
|
|
|
|
|
return result.stdout.strip()
|
|
|
|
|
|
|
|
|
|
|
2026-09-04 11:00:20 +02:00
|
|
|
def _refused_run(
|
|
|
|
|
*,
|
|
|
|
|
reason: str,
|
|
|
|
|
model: str | None = None,
|
|
|
|
|
head_before: str = "",
|
|
|
|
|
transaction: dict[str, Any] | None = None,
|
|
|
|
|
) -> RunResult:
|
|
|
|
|
return RunResult(
|
|
|
|
|
ok=False,
|
|
|
|
|
committed=False,
|
|
|
|
|
head_before=head_before,
|
|
|
|
|
head_after=head_before,
|
|
|
|
|
persona_source="none",
|
|
|
|
|
session_output="",
|
|
|
|
|
reason=reason,
|
|
|
|
|
tool_profile="",
|
|
|
|
|
budget_tokens=None,
|
|
|
|
|
model=model,
|
|
|
|
|
transaction=transaction,
|
|
|
|
|
)
|
|
|
|
|
|
|
|
|
|
|
2026-07-17 23:49:03 +02:00
|
|
|
def run_task(
|
|
|
|
|
spec: TaskSpec,
|
|
|
|
|
adapter=None,
|
|
|
|
|
report_to_hub: bool = True,
|
|
|
|
|
write_metrics: bool = True,
|
2026-07-26 14:49:36 +02:00
|
|
|
emit_tool_events: bool = False,
|
|
|
|
|
on_tool_event: Callable[[dict[str, Any]], None] | None = None,
|
2026-08-21 00:21:53 +02:00
|
|
|
model: str | None = None,
|
|
|
|
|
tool_profile_override: str | None = None,
|
|
|
|
|
budget_tokens_override: int | None = None,
|
2026-09-04 11:00:20 +02:00
|
|
|
transaction: RepositoryTransaction | None = None,
|
2026-07-17 23:49:03 +02:00
|
|
|
) -> RunResult:
|
2026-09-04 11:25:07 +02:00
|
|
|
if spec.repository_grant is not None and not write_metrics:
|
2026-09-04 11:00:20 +02:00
|
|
|
return _refused_run(
|
2026-08-23 13:23:50 +02:00
|
|
|
reason=(
|
2026-09-04 11:25:07 +02:00
|
|
|
"refused: repository_grant runs require durable external metrics; "
|
|
|
|
|
"--no-metrics is incompatible"
|
2026-08-23 13:23:50 +02:00
|
|
|
),
|
|
|
|
|
model=model,
|
|
|
|
|
)
|
2026-07-17 23:49:03 +02:00
|
|
|
try:
|
2026-07-18 11:07:10 +02:00
|
|
|
profile_name, budget_tokens, lane, blueprint = resolve_run_policy(
|
2026-07-17 23:49:03 +02:00
|
|
|
spec.target_repo, spec.agent
|
|
|
|
|
)
|
2026-08-21 00:21:53 +02:00
|
|
|
if tool_profile_override:
|
|
|
|
|
profile_name = tool_profile_override
|
|
|
|
|
if budget_tokens_override is not None:
|
|
|
|
|
budget_tokens = budget_tokens_override
|
2026-07-17 23:49:03 +02:00
|
|
|
profile = get_profile(profile_name)
|
|
|
|
|
except UnknownToolProfileError as exc:
|
2026-09-04 11:00:20 +02:00
|
|
|
return _refused_run(reason=f"refused: {exc}", model=model)
|
2026-07-17 23:49:03 +02:00
|
|
|
except Exception as exc:
|
2026-09-04 11:00:20 +02:00
|
|
|
return _refused_run(reason=f"manifest resolution failed: {exc}", model=model)
|
2026-07-17 23:49:03 +02:00
|
|
|
|
2026-07-26 14:49:36 +02:00
|
|
|
collected_events: list[dict[str, Any]] = []
|
|
|
|
|
|
|
|
|
|
def _on_event(event: dict[str, Any]) -> None:
|
|
|
|
|
collected_events.append(event)
|
|
|
|
|
if report_to_hub:
|
|
|
|
|
hub.post_progress_event(
|
|
|
|
|
summary=f"tool event: {spec.title}",
|
|
|
|
|
event_type="tool_call",
|
|
|
|
|
detail={"repo": spec.target_repo.name, "agent": spec.agent, "event": event},
|
|
|
|
|
task_id=spec.hub_task_id,
|
|
|
|
|
)
|
|
|
|
|
if on_tool_event is not None:
|
|
|
|
|
on_tool_event(event)
|
|
|
|
|
|
Harness foundation: INTENT, ADR-001, architecture, prototype adoption
- INTENT.md: three-layer model (blueprint/instance/harness), single
shared runtime, never-become boundaries
- ADR-001 (accepted): DEC-2026-002 resolution — one harness repo for
all projects; instances are declarative state in consuming repos
- docs/architecture.md: components, contracts (manifest, tool
profiles, completion events, credential lanes), deployment shape
- agent_harness/: executor-worker prototype adopted and renamed
(6/6 tests green); HARNESS-WP-0001 initial workplan (7 tasks)
Co-Authored-By: Claude Fable 5 <noreply@anthropic.com>
2026-07-17 23:35:27 +02:00
|
|
|
if adapter is None:
|
Rename package, CLI, and deploy artifacts to rein-aharness (HARNESS-WP-0002-T02)
agent_harness -> rein_aharness (package + all imports), CLI command
agent-harness -> rein-aharness, Docker image tag, k8s namespace/labels/
names, Makefile targets, deploy script env var/paths. In-repo identity
strings (hub event source, metrics harness field, default assignee,
argparse prog name, commit author identity) updated to match.
Historical documents left untouched on purpose: docs/adr/ADR-001-agent-harness-architecture.md,
docs/architecture.md (dated v0.1 snapshot), workplans/HARNESS-WP-0001
(completed under the old name), and the SSH host alias
"forgejo-agent-harness" (external ~/.ssh/config entry, not owned here).
Verified: 47/47 tests pass, CLI runs correctly from a fresh venv,
`make image` builds and the resulting container runs correctly.
deploy/README.md gained an explicit rename cutover checklist for what
this session cannot safely do unattended -- moving the host-side
secrets dir and checkout on railiance01, and not deleting the old k8s
namespace until the new one is confirmed working. The actual live
cutover (running that checklist against the real Railiance deployment)
is not attempted here -- real production surgery on binky-control's
live automation, needs the operator present.
Co-Authored-By: Claude Sonnet 5 <noreply@anthropic.com>
2026-07-26 14:22:18 +02:00
|
|
|
from rein_aharness.adapter import AgenticClaudeCodeAdapter
|
Harness foundation: INTENT, ADR-001, architecture, prototype adoption
- INTENT.md: three-layer model (blueprint/instance/harness), single
shared runtime, never-become boundaries
- ADR-001 (accepted): DEC-2026-002 resolution — one harness repo for
all projects; instances are declarative state in consuming repos
- docs/architecture.md: components, contracts (manifest, tool
profiles, completion events, credential lanes), deployment shape
- agent_harness/: executor-worker prototype adopted and renamed
(6/6 tests green); HARNESS-WP-0001 initial workplan (7 tasks)
Co-Authored-By: Claude Fable 5 <noreply@anthropic.com>
2026-07-17 23:35:27 +02:00
|
|
|
|
2026-08-21 00:21:53 +02:00
|
|
|
adapter_kwargs = {
|
|
|
|
|
"workdir": spec.target_repo,
|
|
|
|
|
"tool_profile": profile,
|
|
|
|
|
"on_tool_event": _on_event if (emit_tool_events or on_tool_event) else None,
|
|
|
|
|
}
|
|
|
|
|
if model is not None:
|
|
|
|
|
adapter_kwargs["model"] = model
|
|
|
|
|
adapter = AgenticClaudeCodeAdapter(**adapter_kwargs)
|
Harness foundation: INTENT, ADR-001, architecture, prototype adoption
- INTENT.md: three-layer model (blueprint/instance/harness), single
shared runtime, never-become boundaries
- ADR-001 (accepted): DEC-2026-002 resolution — one harness repo for
all projects; instances are declarative state in consuming repos
- docs/architecture.md: components, contracts (manifest, tool
profiles, completion events, credential lanes), deployment shape
- agent_harness/: executor-worker prototype adopted and renamed
(6/6 tests green); HARNESS-WP-0001 initial workplan (7 tasks)
Co-Authored-By: Claude Fable 5 <noreply@anthropic.com>
2026-07-17 23:35:27 +02:00
|
|
|
|
2026-09-04 11:00:20 +02:00
|
|
|
def _run_locked(tx: RepositoryTransaction) -> RunResult:
|
|
|
|
|
return _execute_locked_task(
|
|
|
|
|
spec,
|
|
|
|
|
tx,
|
|
|
|
|
adapter=adapter,
|
|
|
|
|
profile=profile,
|
|
|
|
|
blueprint=blueprint,
|
|
|
|
|
lane=lane,
|
|
|
|
|
budget_tokens=budget_tokens,
|
|
|
|
|
collected_events=collected_events,
|
|
|
|
|
report_to_hub=report_to_hub,
|
|
|
|
|
write_metrics=write_metrics,
|
|
|
|
|
model=model,
|
|
|
|
|
)
|
|
|
|
|
|
|
|
|
|
if transaction is not None:
|
|
|
|
|
return _run_locked(transaction)
|
|
|
|
|
try:
|
|
|
|
|
with RepositoryTransaction(
|
|
|
|
|
spec.target_repo,
|
|
|
|
|
correlation_id=spec.hub_task_id or spec.title,
|
|
|
|
|
) as tx:
|
|
|
|
|
return _run_locked(tx)
|
|
|
|
|
except DirtyRepositoryError as exc:
|
|
|
|
|
return _refused_run(
|
|
|
|
|
reason=f"refused: {exc}",
|
|
|
|
|
model=model,
|
|
|
|
|
head_before=exc.baseline.head,
|
|
|
|
|
transaction={"baseline": exc.baseline.evidence()},
|
|
|
|
|
)
|
|
|
|
|
except RepositoryBusyError as exc:
|
|
|
|
|
return _refused_run(reason=f"refused: {exc}", model=model)
|
|
|
|
|
except (GitRepositoryError, RepositoryTransactionError) as exc:
|
|
|
|
|
return _refused_run(reason=f"refused: {exc}", model=model)
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
def _execute_locked_task(
|
|
|
|
|
spec: TaskSpec,
|
|
|
|
|
tx: RepositoryTransaction,
|
|
|
|
|
*,
|
|
|
|
|
adapter: Any,
|
|
|
|
|
profile: Any,
|
|
|
|
|
blueprint: str,
|
|
|
|
|
lane: str | None,
|
|
|
|
|
budget_tokens: int | None,
|
|
|
|
|
collected_events: list[dict[str, Any]],
|
|
|
|
|
report_to_hub: bool,
|
|
|
|
|
write_metrics: bool,
|
|
|
|
|
model: str | None,
|
|
|
|
|
) -> RunResult:
|
|
|
|
|
assert tx.baseline is not None
|
|
|
|
|
head_before = tx.baseline.head
|
2026-07-18 11:07:10 +02:00
|
|
|
persona, persona_source = load_persona_bundle(blueprint, spec.target_repo)
|
Harness foundation: INTENT, ADR-001, architecture, prototype adoption
- INTENT.md: three-layer model (blueprint/instance/harness), single
shared runtime, never-become boundaries
- ADR-001 (accepted): DEC-2026-002 resolution — one harness repo for
all projects; instances are declarative state in consuming repos
- docs/architecture.md: components, contracts (manifest, tool
profiles, completion events, credential lanes), deployment shape
- agent_harness/: executor-worker prototype adopted and renamed
(6/6 tests green); HARNESS-WP-0001 initial workplan (7 tasks)
Co-Authored-By: Claude Fable 5 <noreply@anthropic.com>
2026-07-17 23:35:27 +02:00
|
|
|
prompt = PROMPT_TEMPLATE.format(
|
|
|
|
|
persona=persona or "(no persona bundle available for this run)",
|
|
|
|
|
title=spec.title,
|
|
|
|
|
description=spec.description,
|
2026-07-17 23:49:03 +02:00
|
|
|
tool_profile=profile.name,
|
|
|
|
|
lane=lane or profile.lane,
|
Harness foundation: INTENT, ADR-001, architecture, prototype adoption
- INTENT.md: three-layer model (blueprint/instance/harness), single
shared runtime, never-become boundaries
- ADR-001 (accepted): DEC-2026-002 resolution — one harness repo for
all projects; instances are declarative state in consuming repos
- docs/architecture.md: components, contracts (manifest, tool
profiles, completion events, credential lanes), deployment shape
- agent_harness/: executor-worker prototype adopted and renamed
(6/6 tests green); HARNESS-WP-0001 initial workplan (7 tasks)
Co-Authored-By: Claude Fable 5 <noreply@anthropic.com>
2026-07-17 23:35:27 +02:00
|
|
|
)
|
|
|
|
|
|
2026-07-17 23:49:03 +02:00
|
|
|
from llm_connect.models import BudgetTracker, RunConfig
|
|
|
|
|
|
|
|
|
|
budget_tracker = BudgetTracker(total=budget_tokens) if budget_tokens else None
|
|
|
|
|
config = RunConfig(
|
|
|
|
|
timeout_seconds=spec.timeout_seconds,
|
|
|
|
|
skip_if_exists=False,
|
|
|
|
|
budget_tracker=budget_tracker,
|
|
|
|
|
)
|
Harness foundation: INTENT, ADR-001, architecture, prototype adoption
- INTENT.md: three-layer model (blueprint/instance/harness), single
shared runtime, never-become boundaries
- ADR-001 (accepted): DEC-2026-002 resolution — one harness repo for
all projects; instances are declarative state in consuming repos
- docs/architecture.md: components, contracts (manifest, tool
profiles, completion events, credential lanes), deployment shape
- agent_harness/: executor-worker prototype adopted and renamed
(6/6 tests green); HARNESS-WP-0001 initial workplan (7 tasks)
Co-Authored-By: Claude Fable 5 <noreply@anthropic.com>
2026-07-17 23:35:27 +02:00
|
|
|
|
2026-07-17 23:49:03 +02:00
|
|
|
started = time.monotonic()
|
Harness foundation: INTENT, ADR-001, architecture, prototype adoption
- INTENT.md: three-layer model (blueprint/instance/harness), single
shared runtime, never-become boundaries
- ADR-001 (accepted): DEC-2026-002 resolution — one harness repo for
all projects; instances are declarative state in consuming repos
- docs/architecture.md: components, contracts (manifest, tool
profiles, completion events, credential lanes), deployment shape
- agent_harness/: executor-worker prototype adopted and renamed
(6/6 tests green); HARNESS-WP-0001 initial workplan (7 tasks)
Co-Authored-By: Claude Fable 5 <noreply@anthropic.com>
2026-07-17 23:35:27 +02:00
|
|
|
try:
|
|
|
|
|
response = adapter.execute_prompt(prompt, config)
|
|
|
|
|
session_output = response.content
|
2026-08-21 00:21:53 +02:00
|
|
|
resolved_model = response.model
|
Harness foundation: INTENT, ADR-001, architecture, prototype adoption
- INTENT.md: three-layer model (blueprint/instance/harness), single
shared runtime, never-become boundaries
- ADR-001 (accepted): DEC-2026-002 resolution — one harness repo for
all projects; instances are declarative state in consuming repos
- docs/architecture.md: components, contracts (manifest, tool
profiles, completion events, credential lanes), deployment shape
- agent_harness/: executor-worker prototype adopted and renamed
(6/6 tests green); HARNESS-WP-0001 initial workplan (7 tasks)
Co-Authored-By: Claude Fable 5 <noreply@anthropic.com>
2026-07-17 23:35:27 +02:00
|
|
|
session_ok = True
|
|
|
|
|
reason = ""
|
2026-09-04 11:00:20 +02:00
|
|
|
except ExecutionCancelled as exc:
|
|
|
|
|
session_output = ""
|
|
|
|
|
session_ok = False
|
|
|
|
|
reason = f"execution cancelled ({exc.reason})"
|
|
|
|
|
resolved_model = model
|
2026-07-17 23:49:03 +02:00
|
|
|
except Exception as exc: # adapter / budget failures must still be reported
|
Harness foundation: INTENT, ADR-001, architecture, prototype adoption
- INTENT.md: three-layer model (blueprint/instance/harness), single
shared runtime, never-become boundaries
- ADR-001 (accepted): DEC-2026-002 resolution — one harness repo for
all projects; instances are declarative state in consuming repos
- docs/architecture.md: components, contracts (manifest, tool
profiles, completion events, credential lanes), deployment shape
- agent_harness/: executor-worker prototype adopted and renamed
(6/6 tests green); HARNESS-WP-0001 initial workplan (7 tasks)
Co-Authored-By: Claude Fable 5 <noreply@anthropic.com>
2026-07-17 23:35:27 +02:00
|
|
|
session_output = ""
|
|
|
|
|
session_ok = False
|
|
|
|
|
reason = f"session failed: {exc}"
|
2026-08-21 00:21:53 +02:00
|
|
|
resolved_model = model
|
2026-07-17 23:49:03 +02:00
|
|
|
execution_time_s = time.monotonic() - started
|
Harness foundation: INTENT, ADR-001, architecture, prototype adoption
- INTENT.md: three-layer model (blueprint/instance/harness), single
shared runtime, never-become boundaries
- ADR-001 (accepted): DEC-2026-002 resolution — one harness repo for
all projects; instances are declarative state in consuming repos
- docs/architecture.md: components, contracts (manifest, tool
profiles, completion events, credential lanes), deployment shape
- agent_harness/: executor-worker prototype adopted and renamed
(6/6 tests green); HARNESS-WP-0001 initial workplan (7 tasks)
Co-Authored-By: Claude Fable 5 <noreply@anthropic.com>
2026-07-17 23:35:27 +02:00
|
|
|
|
|
|
|
|
head_after = _git(spec.target_repo, "rev-parse", "HEAD")
|
|
|
|
|
committed = head_after != head_before
|
2026-09-04 11:25:07 +02:00
|
|
|
if session_ok and spec.repository_grant is not None:
|
|
|
|
|
try:
|
|
|
|
|
tx.validate_acceptance(spec.repository_grant.acceptance_policy())
|
|
|
|
|
except RepositoryAcceptanceError as exc:
|
|
|
|
|
session_ok = False
|
|
|
|
|
reason = str(exc)
|
Harness foundation: INTENT, ADR-001, architecture, prototype adoption
- INTENT.md: three-layer model (blueprint/instance/harness), single
shared runtime, never-become boundaries
- ADR-001 (accepted): DEC-2026-002 resolution — one harness repo for
all projects; instances are declarative state in consuming repos
- docs/architecture.md: components, contracts (manifest, tool
profiles, completion events, credential lanes), deployment shape
- agent_harness/: executor-worker prototype adopted and renamed
(6/6 tests green); HARNESS-WP-0001 initial workplan (7 tasks)
Co-Authored-By: Claude Fable 5 <noreply@anthropic.com>
2026-07-17 23:35:27 +02:00
|
|
|
ok = session_ok and committed
|
2026-09-04 11:25:07 +02:00
|
|
|
if session_ok and not committed and spec.repository_grant is None:
|
Harness foundation: INTENT, ADR-001, architecture, prototype adoption
- INTENT.md: three-layer model (blueprint/instance/harness), single
shared runtime, never-become boundaries
- ADR-001 (accepted): DEC-2026-002 resolution — one harness repo for
all projects; instances are declarative state in consuming repos
- docs/architecture.md: components, contracts (manifest, tool
profiles, completion events, credential lanes), deployment shape
- agent_harness/: executor-worker prototype adopted and renamed
(6/6 tests green); HARNESS-WP-0001 initial workplan (7 tasks)
Co-Authored-By: Claude Fable 5 <noreply@anthropic.com>
2026-07-17 23:35:27 +02:00
|
|
|
reason = "session completed without committing"
|
|
|
|
|
|
2026-07-17 23:49:03 +02:00
|
|
|
tokens_spent = budget_tracker.spent if budget_tracker is not None else None
|
2026-09-04 11:25:07 +02:00
|
|
|
transaction_evidence = tx.evidence()
|
|
|
|
|
if spec.repository_grant is not None:
|
|
|
|
|
transaction_evidence["repository_grant"] = spec.repository_grant.evidence()
|
|
|
|
|
|
|
|
|
|
metric_metadata = {
|
|
|
|
|
"task_title": spec.title,
|
|
|
|
|
"tool_profile": profile.name,
|
|
|
|
|
"labels": list(spec.labels),
|
|
|
|
|
"completion_event_type": spec.completion_event_type,
|
|
|
|
|
}
|
|
|
|
|
if spec.repository_grant is not None:
|
|
|
|
|
metric_metadata["repository_grant_id"] = spec.repository_grant.grant_id
|
|
|
|
|
|
|
|
|
|
if write_metrics:
|
|
|
|
|
try:
|
|
|
|
|
recorder = (
|
|
|
|
|
metrics.record_external_execution
|
|
|
|
|
if spec.repository_grant is not None
|
|
|
|
|
else metrics.record_execution
|
|
|
|
|
)
|
|
|
|
|
recorder(
|
|
|
|
|
spec.target_repo,
|
|
|
|
|
spec.agent,
|
|
|
|
|
success=ok,
|
|
|
|
|
execution_time_s=execution_time_s,
|
|
|
|
|
tokens=tokens_spent,
|
|
|
|
|
committed=committed,
|
|
|
|
|
head_after=head_after,
|
|
|
|
|
reason=reason or None,
|
|
|
|
|
metadata=metric_metadata,
|
|
|
|
|
session_id=tx.transaction_id,
|
|
|
|
|
)
|
|
|
|
|
if spec.repository_grant is not None:
|
|
|
|
|
transaction_evidence["metrics"] = {
|
|
|
|
|
"storage": "external",
|
|
|
|
|
"session_id": tx.transaction_id,
|
|
|
|
|
"projection_ready": True,
|
|
|
|
|
}
|
|
|
|
|
except OSError as exc:
|
|
|
|
|
if spec.repository_grant is not None:
|
|
|
|
|
ok = False
|
|
|
|
|
reason = (
|
|
|
|
|
"required external metrics persistence failed "
|
|
|
|
|
f"({type(exc).__name__})"
|
|
|
|
|
)
|
2026-07-17 23:49:03 +02:00
|
|
|
|
Harness foundation: INTENT, ADR-001, architecture, prototype adoption
- INTENT.md: three-layer model (blueprint/instance/harness), single
shared runtime, never-become boundaries
- ADR-001 (accepted): DEC-2026-002 resolution — one harness repo for
all projects; instances are declarative state in consuming repos
- docs/architecture.md: components, contracts (manifest, tool
profiles, completion events, credential lanes), deployment shape
- agent_harness/: executor-worker prototype adopted and renamed
(6/6 tests green); HARNESS-WP-0001 initial workplan (7 tasks)
Co-Authored-By: Claude Fable 5 <noreply@anthropic.com>
2026-07-17 23:35:27 +02:00
|
|
|
result = RunResult(
|
|
|
|
|
ok=ok,
|
|
|
|
|
committed=committed,
|
|
|
|
|
head_before=head_before,
|
|
|
|
|
head_after=head_after,
|
|
|
|
|
persona_source=persona_source,
|
|
|
|
|
session_output=session_output,
|
|
|
|
|
reason=reason,
|
2026-08-21 00:21:53 +02:00
|
|
|
model=resolved_model,
|
2026-07-17 23:49:03 +02:00
|
|
|
tool_profile=profile.name,
|
|
|
|
|
budget_tokens=budget_tokens,
|
|
|
|
|
tokens_spent=tokens_spent,
|
|
|
|
|
execution_time_s=execution_time_s,
|
2026-07-26 14:49:36 +02:00
|
|
|
tool_events=collected_events,
|
2026-09-04 11:25:07 +02:00
|
|
|
transaction=transaction_evidence,
|
Harness foundation: INTENT, ADR-001, architecture, prototype adoption
- INTENT.md: three-layer model (blueprint/instance/harness), single
shared runtime, never-become boundaries
- ADR-001 (accepted): DEC-2026-002 resolution — one harness repo for
all projects; instances are declarative state in consuming repos
- docs/architecture.md: components, contracts (manifest, tool
profiles, completion events, credential lanes), deployment shape
- agent_harness/: executor-worker prototype adopted and renamed
(6/6 tests green); HARNESS-WP-0001 initial workplan (7 tasks)
Co-Authored-By: Claude Fable 5 <noreply@anthropic.com>
2026-07-17 23:35:27 +02:00
|
|
|
)
|
|
|
|
|
|
|
|
|
|
if report_to_hub:
|
|
|
|
|
detail = {
|
|
|
|
|
"repo": spec.target_repo.name,
|
|
|
|
|
"task_title": spec.title,
|
|
|
|
|
"agent": spec.agent,
|
|
|
|
|
"labels": spec.labels,
|
|
|
|
|
"persona_source": persona_source,
|
|
|
|
|
"committed": committed,
|
|
|
|
|
"head_after": head_after,
|
|
|
|
|
"ok": ok,
|
|
|
|
|
"reason": reason,
|
2026-07-17 23:49:03 +02:00
|
|
|
"tool_profile": profile.name,
|
|
|
|
|
"budget_tokens": budget_tokens,
|
|
|
|
|
"tokens_spent": tokens_spent,
|
|
|
|
|
"execution_time_s": round(execution_time_s, 3),
|
2026-09-04 11:25:07 +02:00
|
|
|
"repository_transaction": transaction_evidence,
|
Harness foundation: INTENT, ADR-001, architecture, prototype adoption
- INTENT.md: three-layer model (blueprint/instance/harness), single
shared runtime, never-become boundaries
- ADR-001 (accepted): DEC-2026-002 resolution — one harness repo for
all projects; instances are declarative state in consuming repos
- docs/architecture.md: components, contracts (manifest, tool
profiles, completion events, credential lanes), deployment shape
- agent_harness/: executor-worker prototype adopted and renamed
(6/6 tests green); HARNESS-WP-0001 initial workplan (7 tasks)
Co-Authored-By: Claude Fable 5 <noreply@anthropic.com>
2026-07-17 23:35:27 +02:00
|
|
|
}
|
|
|
|
|
hub.post_progress_event(
|
|
|
|
|
summary=f"executor run: {spec.title} ({'ok' if ok else 'failed'})",
|
|
|
|
|
event_type=spec.completion_event_type,
|
|
|
|
|
detail=detail,
|
|
|
|
|
task_id=spec.hub_task_id,
|
|
|
|
|
)
|
2026-07-17 23:49:03 +02:00
|
|
|
if tokens_spent is not None or budget_tokens is not None:
|
|
|
|
|
hub.post_token_event(
|
|
|
|
|
repo=spec.target_repo.name,
|
|
|
|
|
tokens=tokens_spent or 0,
|
|
|
|
|
budget=budget_tokens,
|
|
|
|
|
agent=spec.agent,
|
|
|
|
|
ok=ok,
|
|
|
|
|
detail={"task_title": spec.title, "tool_profile": profile.name},
|
|
|
|
|
)
|
Harness foundation: INTENT, ADR-001, architecture, prototype adoption
- INTENT.md: three-layer model (blueprint/instance/harness), single
shared runtime, never-become boundaries
- ADR-001 (accepted): DEC-2026-002 resolution — one harness repo for
all projects; instances are declarative state in consuming repos
- docs/architecture.md: components, contracts (manifest, tool
profiles, completion events, credential lanes), deployment shape
- agent_harness/: executor-worker prototype adopted and renamed
(6/6 tests green); HARNESS-WP-0001 initial workplan (7 tasks)
Co-Authored-By: Claude Fable 5 <noreply@anthropic.com>
2026-07-17 23:35:27 +02:00
|
|
|
if ok and spec.hub_task_id:
|
|
|
|
|
hub.close_task(spec.hub_task_id)
|
|
|
|
|
|
|
|
|
|
return result
|