docs: Add EPIC-202 and tickets for Claw-based agent build
- EPIC-202: Build Claw-Architecture Agent - TICKET-203: ToolPermissionContext - TICKET-204: ExecutionRegistry - TICKET-205: Session Persistence Replaces idle Allegro-Primus with real work capability.
This commit is contained in:
138
epics/EPIC-202-claw-agent.md
Normal file
138
epics/EPIC-202-claw-agent.md
Normal file
@@ -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.*
|
||||||
39
tickets/TICKET-203-tool-permission.md
Normal file
39
tickets/TICKET-203-tool-permission.md
Normal file
@@ -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`
|
||||||
44
tickets/TICKET-204-execution-registry.md
Normal file
44
tickets/TICKET-204-execution-registry.md
Normal file
@@ -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
|
||||||
43
tickets/TICKET-205-session-persistence.md
Normal file
43
tickets/TICKET-205-session-persistence.md
Normal file
@@ -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`
|
||||||
Reference in New Issue
Block a user