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>
This commit is contained in:
parent
87ae78c56a
commit
cfc1b75157
18 changed files with 1204 additions and 1 deletions
48
agent_harness/taskspec.py
Normal file
48
agent_harness/taskspec.py
Normal file
|
|
@ -0,0 +1,48 @@
|
|||
"""Task specification the worker consumes.
|
||||
|
||||
MVP source is a JSON file matching what the activity-core issue-core sink
|
||||
emits per rule action (task_template/description/target_repo/labels), plus
|
||||
executor-specific fields. A future source polls issue-core directly.
|
||||
"""
|
||||
|
||||
from __future__ import annotations
|
||||
|
||||
import json
|
||||
from dataclasses import dataclass, field
|
||||
from pathlib import Path
|
||||
|
||||
|
||||
class TaskSpecError(ValueError):
|
||||
pass
|
||||
|
||||
|
||||
@dataclass
|
||||
class TaskSpec:
|
||||
title: str
|
||||
description: str
|
||||
target_repo: Path
|
||||
agent: str = "coach"
|
||||
labels: list[str] = field(default_factory=list)
|
||||
hub_task_id: str | None = None
|
||||
completion_event_type: str = "executor_run"
|
||||
timeout_seconds: int = 900
|
||||
|
||||
@classmethod
|
||||
def from_file(cls, path: str | Path) -> "TaskSpec":
|
||||
raw = json.loads(Path(path).read_text())
|
||||
missing = {"title", "description", "target_repo"} - set(raw)
|
||||
if missing:
|
||||
raise TaskSpecError(f"task spec missing field(s): {', '.join(sorted(missing))}")
|
||||
target = Path(raw["target_repo"]).expanduser()
|
||||
if not (target / ".git").is_dir():
|
||||
raise TaskSpecError(f"target_repo is not a git repository: {target}")
|
||||
return cls(
|
||||
title=str(raw["title"]),
|
||||
description=str(raw["description"]),
|
||||
target_repo=target,
|
||||
agent=str(raw.get("agent", "coach")),
|
||||
labels=[str(label) for label in raw.get("labels", [])],
|
||||
hub_task_id=raw.get("hub_task_id"),
|
||||
completion_event_type=str(raw.get("completion_event_type", "executor_run")),
|
||||
timeout_seconds=int(raw.get("timeout_seconds", 900)),
|
||||
)
|
||||
Loading…
Add table
Add a link
Reference in a new issue