diff --git a/epics/EPIC-202-claw-agent.md b/epics/EPIC-202-claw-agent.md new file mode 100644 index 0000000..e080837 --- /dev/null +++ b/epics/EPIC-202-claw-agent.md @@ -0,0 +1,138 @@ +# EPIC-202: Build Claw-Architecture Agent + +**Status:** In Progress +**Priority:** P0 +**Milestone:** M1: Core Architecture +**Created:** 2026-03-31 +**Author:** Allegro + +--- + +## Objective + +Create a NEW autonomous agent using architectural patterns from [Claw Code](http://143.198.27.163:3000/Timmy/claw-code), integrated with Gitea for real work dispatch. + +## Problem Statement + +**Allegro-Primus is IDLE.** +- Gateway running (PID 367883) but zero meaningful output +- No Gitea issues created +- No PRs submitted +- No actual work completed + +This agent will **replace** Allegro-Primus with real capabilities. + +--- + +## Claw Patterns to Adopt + +### 1. ToolPermissionContext +```python +@dataclass +class ToolPermissionContext: + deny_tools: set[str] + deny_prefixes: tuple[str, ...] + + def blocks(self, tool_name: str) -> bool: + return tool_name in self.deny_tools or \ + any(tool_name.startswith(p) for p in self.deny_prefixes) +``` + +**Why:** Fine-grained tool access control vs Hermes basic approval + +### 2. ExecutionRegistry +```python +class ExecutionRegistry: + def command(self, name: str) -> CommandHandler + def tool(self, name: str) -> ToolHandler + def execute(self, context: PermissionContext) -> Result +``` + +**Why:** Clean routing vs Hermes model-decided routing + +### 3. Session Persistence +```python +@dataclass +class RuntimeSession: + prompt: str + context: PortContext + history: HistoryLog + persisted_path: str +``` + +**Why:** JSON-based sessions vs SQLite - more portable, inspectable + +### 4. Bootstrap Graph +```python +def build_bootstrap_graph() -> Graph: + # Setup phases + # Context building + # System init messages +``` + +**Why:** Structured initialization vs ad-hoc setup + +--- + +## Implementation Plan + +### Phase 1: Core Architecture (2 days) +- [ ] Create new Hermes profile: `claw-agent` +- [ ] Implement ToolPermissionContext +- [ ] Create ExecutionRegistry +- [ ] Build Session persistence layer + +### Phase 2: Gitea Integration (2 days) +- [ ] Gitea client with issue querying +- [ ] Work scheduler for autonomous cycles +- [ ] PR creation and review assistance + +### Phase 3: Deployment (1 day) +- [ ] Telegram bot integration +- [ ] Cron scheduling +- [ ] Health monitoring + +--- + +## Success Criteria + +| Criteria | How We'll Verify | +|----------|-----------------| +| Receives Telegram tasks | Send test message, agent responds | +| Queries Gitea issues | Agent lists open P0 issues | +| Permission checks work | Blocked tool returns error | +| Session persistence | Restart agent, history intact | +| Progress reports | Agent sends Telegram updates | + +--- + +## Resource Requirements + +| Resource | Status | +|----------|--------| +| Gitea API token | ✅ Have | +| Kimi API key | ✅ Have | +| Telegram bot | ⏳ Need @BotFather | +| New profile | ⏳ Will create | + +--- + +## References + +- [Claw Code Mirror](http://143.198.27.163:3000/Timmy/claw-code) +- [Claw Issue #1 - Architecture](http://143.198.27.163:3000/Timmy/claw-code/issues/1) +- [Hermes v0.6 Profiles](../docs/profiles.md) + +--- + +## Tickets + +- #203: Implement ToolPermissionContext +- #204: Create ExecutionRegistry +- #205: Build Session Persistence +- #206: Gitea Integration +- #207: Telegram Deployment + +--- + +*This epic supersedes Allegro-Primus who has been idle.* diff --git a/tickets/TICKET-203-tool-permission.md b/tickets/TICKET-203-tool-permission.md new file mode 100644 index 0000000..822f67e --- /dev/null +++ b/tickets/TICKET-203-tool-permission.md @@ -0,0 +1,39 @@ +# TICKET-203: Implement ToolPermissionContext + +**Epic:** EPIC-202 +**Priority:** P0 +**Status:** Ready +**Assignee:** Allegro +**Estimate:** 4 hours + +## Description + +Implement the ToolPermissionContext pattern from Claw Code for fine-grained tool access control. + +## Acceptance Criteria + +- [ ] `ToolPermissionContext` dataclass created +- [ ] `deny_tools: set[str]` field +- [ ] `deny_prefixes: tuple[str, ...]` field +- [ ] `blocks(tool_name: str) -> bool` method +- [ ] Integration with Hermes tool registry +- [ ] Tests pass + +## Implementation Notes + +```python +@dataclass(frozen=True) +class ToolPermissionContext: + deny_tools: set[str] = field(default_factory=set) + deny_prefixes: tuple[str, ...] = () + + def blocks(self, tool_name: str) -> bool: + if tool_name in self.deny_tools: + return True + return any(tool_name.startswith(p) for p in self.deny_prefixes) +``` + +## References + +- Claw: `src/permissions.py` +- Hermes: `tools/registry.py` diff --git a/tickets/TICKET-204-execution-registry.md b/tickets/TICKET-204-execution-registry.md new file mode 100644 index 0000000..f8262f3 --- /dev/null +++ b/tickets/TICKET-204-execution-registry.md @@ -0,0 +1,44 @@ +# TICKET-204: Create ExecutionRegistry + +**Epic:** EPIC-202 +**Priority:** P0 +**Status:** Ready +**Assignee:** Allegro +**Estimate:** 6 hours + +## Description + +Create ExecutionRegistry for clean command/tool routing, replacing model-decided routing. + +## Acceptance Criteria + +- [ ] `ExecutionRegistry` class +- [ ] `register_command(name, handler)` method +- [ ] `register_tool(name, handler)` method +- [ ] `command(name) -> CommandHandler` lookup +- [ ] `tool(name) -> ToolHandler` lookup +- [ ] `execute(prompt, context)` routing method +- [ ] Permission context integration +- [ ] Tests pass + +## Implementation Notes + +Pattern from Claw `src/execution_registry.py`: + +```python +class ExecutionRegistry: + def __init__(self): + self._commands: dict[str, CommandHandler] = {} + self._tools: dict[str, ToolHandler] = {} + + def register_command(self, name: str, handler: CommandHandler): + self._commands[name] = handler + + def command(self, name: str) -> CommandHandler | None: + return self._commands.get(name) +``` + +## References + +- Claw: `src/execution_registry.py` +- Claw: `src/runtime.py` for usage diff --git a/tickets/TICKET-205-session-persistence.md b/tickets/TICKET-205-session-persistence.md new file mode 100644 index 0000000..98fd9c8 --- /dev/null +++ b/tickets/TICKET-205-session-persistence.md @@ -0,0 +1,43 @@ +# TICKET-205: Build Session Persistence + +**Epic:** EPIC-202 +**Priority:** P0 +**Status:** Ready +**Assignee:** Allegro +**Estimate:** 4 hours + +## Description + +Build JSON-based session persistence layer, more portable than SQLite. + +## Acceptance Criteria + +- [ ] `RuntimeSession` dataclass +- [ ] `SessionStore` class +- [ ] `save(session)` writes JSON +- [ ] `load(session_id)` reads JSON +- [ ] `HistoryLog` for turn tracking +- [ ] Sessions survive agent restart +- [ ] Tests pass + +## Implementation Notes + +Pattern from Claw `src/session_store.py`: + +```python +@dataclass +class RuntimeSession: + session_id: str + prompt: str + context: dict + history: HistoryLog + persisted_path: Path + + def save(self): + self.persisted_path.write_text(json.dumps(asdict(self))) +``` + +## References + +- Claw: `src/session_store.py` +- Claw: `src/history.py`