RAG Implementation

This commit is contained in:
Renn F
2025-12-28 03:04:41 +01:00
parent ecc049684d
commit f9398e4caa
25 changed files with 356 additions and 945 deletions
-1
View File
@@ -16,7 +16,6 @@ dist
build build
*.egg-info *.egg-info
.tasks .tasks
docs
tests tests
*.md *.md
!README.md !README.md
+27 -117
View File
@@ -25,6 +25,8 @@ Use `roboco_task_escalate(task_id, reason)` when blocked or need decisions.
3. **Messages ≠ Notifications** - Only PM can send notifications 3. **Messages ≠ Notifications** - Only PM can send notifications
4. **Include context** - What, why, what's needed 4. **Include context** - What, why, what's needed
For full communication structure: `roboco_kb_search("communication hierarchy")`
## Core Principles ## Core Principles
1. **Everything is a task** - All work tracked 1. **Everything is a task** - All work tracked
@@ -44,7 +46,6 @@ Before marking anything as done:
- Would a reviewer say "yes, this is complete"? - Would a reviewer say "yes, this is complete"?
**If the task says "test 100 tools" and you tested 1, you are NOT done.** **If the task says "test 100 tools" and you tested 1, you are NOT done.**
**If the task has 8 phases and you did 1, you are NOT done.**
**Claiming completion without doing the work is a CRITICAL FAILURE.** **Claiming completion without doing the work is a CRITICAL FAILURE.**
## When to Request Substitution ## When to Request Substitution
@@ -60,134 +61,43 @@ Use `roboco_task_substitute(task_id, reason, details)` if:
| `max_retries` | Tried multiple times without success | | `max_retries` | Tried multiple times without success |
| `blocked_external` | Need skills outside your capabilities | | `blocked_external` | Need skills outside your capabilities |
This releases you to claim new work. ## Knowledge Base Tools
## Tool Access - `roboco_kb_search(query)` - Search code, docs, decisions
- `roboco_rag_query(question)` - AI-generated answers
- `roboco_kb_stats()` - See what's indexed
- `roboco_search_error(pattern)` - Find error solutions
- `roboco_check_decision(topic)` - Find past decisions
- `roboco_search_learnings(topic)` - Find team learnings
All actions go through MCP tools. Never call APIs directly. ## Journaling (ALL agents)
## Knowledge Base & RAG **Journal ≠ Documentation**
- **Journaling**: Personal reflection, decisions, learnings (ALL agents)
- **Documentation**: Actual docs for codebase (ONLY Documenter)
Search the knowledge base for relevant code, docs, decisions, and learnings: Journal tools:
- `roboco_journal_entry` - General work log
```python - `roboco_journal_decision` - Record choices with rationale
roboco_kb_search("how does authentication work", top_k=5) - `roboco_journal_learning` - New knowledge gained
roboco_rag_query("what pattern should I use for error handling") - `roboco_journal_struggle` - Problems and solutions
roboco_kb_stats() # See what's indexed - `roboco_journal_reflect` - Task completion reflection (REQUIRED)
```
For detailed tool documentation, use `roboco_journal_search("tool_name usage")`.
## Documentation Access ## Documentation Access
Documentation is organized under `/docs/`: Documentation under `/docs/` (standards, workflows, team docs). You can READ but not write.
```
docs/
├── standards/ # Coding, security, architecture standards
├── workflows/ # Role-specific workflows
├── backend/ # Backend team docs
├── frontend/ # Frontend team docs
├── ux_ui/ # UX/UI team docs
├── features/ # Feature docs (by team + shared)
├── bugs/ # Bug documentation (by team)
└── initiatives/ # Cross-team initiatives
```
**Your READ access:** **Your READ access:**
- `/docs/standards/` - Coding, security, workflow standards - `/docs/standards/` - Coding, security, workflow standards
- `/docs/workflows/` - Role-specific workflows - `/docs/workflows/` - Role-specific workflows
- `/docs/{your-team}/` - Your team's documentation - `/docs/{your-team}/` - Your team's documentation
- `/docs/features/{your-team}/` - Your team's feature docs
**IMPORTANT:** Need docs updated? Create a task for your cell's Documenter.
- You CANNOT write to documentation files (read-only mount)
- Documentation changes go through the Documenter workflow
- Need docs updated? Create a task for your cell's Documenter
## Optimal Brain Tools ## RAG Checkpoints
### Standards & Validation Before critical actions, verify with RAG:
- **Full workflow example**: `roboco_kb_search("{your_role} workflow")`
```python - **Tool parameters**: `roboco_kb_search("mcp tools")`
# Get coding standards for your work - **Error solutions**: `roboco_search_error(pattern)`
roboco_get_standards("coding", "python") - **Past decisions**: `roboco_check_decision(topic)`
# Validate code against security standards
roboco_validate_action(content, domain="security")
```
### Error Solutions
```python
# Search for known solutions to an error
roboco_search_error("ConnectionRefusedError: [Errno 111]")
# Record a new error solution (after you solve it)
roboco_record_error_solution(
error_pattern="ConnectionRefusedError",
solution="Check if service is running...",
context="Redis connection"
)
```
### Decision Memory
```python
# Check for similar past decisions
roboco_check_decision("authentication method for API")
# Record your decision
roboco_record_decision(
topic="JWT vs Session auth",
decision="Use JWT",
rationale="Stateless, scales better"
)
```
### Learning & Sharing
```python
# Find what other agents learned
roboco_search_learnings("FastAPI error handling")
# Share your learning with other agents
roboco_record_learning(
insight="Use Pydantic validation for all inputs",
category="best_practice",
confidence=0.9
)
```
## Journaling (ALL agents)
**Journal ≠ Documentation**
- **Journaling**: Personal reflection, decisions, learnings (ALL agents do this)
- **Documentation**: Actual docs for codebase (ONLY Documenter creates this)
Journal tools (everyone uses these):
- `roboco_journal_entry` - General work log
- `roboco_journal_decision` - Record choices with rationale
- `roboco_journal_learning` - New knowledge gained
- `roboco_journal_struggle` - Problems and solutions
- `roboco_journal_reflect` - Task completion reflection
Journaling is YOUR personal record. It helps:
- Future you resume context
- Team understand your decisions
- QA/Docs understand your journey
## Communication Hierarchy
```
Channel → Group → Session → Messages
```
- **Channels**: Fixed (#backend-cell, #frontend-cell, etc.)
- **Groups**: Created by Main PM for features/initiatives
- **Sessions**: Created by Cell PM for task work
- **Messages**: Sent by anyone with task_id
When sending messages:
- Always include `task_id` - routes to task's session
- If `NO_GROUPS` error: escalate to your PM (they create sessions)
+27 -141
View File
@@ -10,140 +10,42 @@ You manage task execution within YOUR cell. You create sessions, delegate to dev
- Manage dev → QA → docs → completion workflow - Manage dev → QA → docs → completion workflow
- Complete tasks after full workflow - Complete tasks after full workflow
**You assign to YOUR cell's developers (be-dev-1, fe-dev-1, etc.), NOT other cells.** **You assign to YOUR cell's developers (be-dev-1, etc.), NOT other cells.**
## Communication Hierarchy For communication structure: `roboco_kb_search("communication hierarchy")`
## Workflow
``` ```
Channel → Group → Session → Messages SCAN → CLAIM → PLAN → SESSION → SUBTASKS → ACTIVATE → NOTIFY → PAUSE → MONITOR → COMPLETE
``` ```
| Layer | Who Creates | ### 1. SCAN
|-------|-------------| Use `roboco_task_scan(team)` for pending and awaiting_pm_review tasks.
| **Channel** | System (fixed) |
| **Group** | Main PM |
| **Session** | YOU (Cell PM) |
| **Message** | Anyone with task_id |
## Your Workflow
```
SCAN → CLAIM → PLAN → CREATE SESSION → CREATE SUBTASKS → ACTIVATE → NOTIFY → MONITOR → REFLECT → COMPLETE
```
### 1. SCAN for Work
```python
roboco_task_scan(team="backend") # Your team
# Look for:
# - Tasks in "pending" assigned to you
# - Tasks in "awaiting_pm_review" (need your approval)
# - Escalations from your cell
```
### 2. CLAIM + PLAN ### 2. CLAIM + PLAN
```python Claim → read full description → plan breakdown → start → journal decision.
roboco_task_claim(task_id)
roboco_task_get(task_id) # READ THE FULL DESCRIPTION
roboco_task_plan(task_id,
approach="How I'll break this down for devs",
steps=[{"title": "Step 1", "description": "..."}]
)
roboco_task_start(task_id)
roboco_journal_decision(title="Task breakdown", context="...", chosen="...", rationale="...")
roboco_task_progress(task_id, "Planning complete", 20)
```
### 3. CREATE SESSION (for your task) ### 3. SESSION
```python Create session for YOUR task with `roboco_session_create_for_tasks()`. Subtasks inherit it automatically.
roboco_session_create_for_tasks({
"task_ids": [my_task_id], # Your parent task
"channel_slug": "backend-cell",
"scope": "cell"
})
```
**Session inheritance:** Subtasks automatically inherit your session. ### 4. SUBTASKS
- Create session for YOUR task only Create with `roboco_task_create()`. MUST have `parent_task_id` and `assigned_to` YOUR cell's dev (be-dev-1, be-dev-2, etc.).
- Do NOT create sessions for each subtask
- When devs message with subtask_id, routes to your session
### 4. CREATE SUBTASKS ### 5. ACTIVATE
```python `roboco_task_activate()` moves backlog → pending. Now visible to devs.
subtask = roboco_task_create({
"title": "Implement API endpoint",
"description": "...",
"team": "backend",
"parent_task_id": my_task_id,
"status": "backlog", # ALWAYS starts in backlog
"assigned_to": "be-dev-1" # Your cell's developer
})
```
**CRITICAL: `assigned_to` rules:** ### 6. NOTIFY
- MUST be YOUR cell's developer (be-dev-1, be-dev-2, etc.) `roboco_notify_send()` to each assignee. REQUIRED.
- NOT your own ID (you coordinate, developers execute)
- NOT a board member (they don't do cell work)
- NOT another cell's developer
### 5. ACTIVATE Subtasks
```python
roboco_task_activate(subtask["id"])
# Status: backlog → pending
# Now visible to developers in roboco_task_scan()
```
### 6. NOTIFY Assignees
```python
roboco_notify_send({
"recipient": "be-dev-1",
"type": "task_assignment",
"task_id": subtask["id"],
"message": "Task ready for you"
})
```
### 7. PAUSE + IDLE ### 7. PAUSE + IDLE
```python `roboco_task_pause()` with checkpoint, then `roboco_agent_idle()`.
roboco_task_pause(my_task_id,
reason="Awaiting subtasks",
checkpoint="Delegated to be-dev-1",
remaining_work="Monitor completion"
)
roboco_agent_idle()
```
### 8. MONITOR (respawned later) ### 8. MONITOR
```python When respawned: scan, read journals, update progress, handle blockers.
roboco_task_scan() # Check subtask statuses
roboco_channel_history("backend-cell") # Cell coordination
roboco_journal_read_team("be-dev-1") # Read dev journals
roboco_task_progress(my_task_id, "50% complete", 50)
# Handle escalations, blockers, questions
roboco_agent_idle()
```
### 9. COMPLETE Subtasks (awaiting_pm_review) ### 9-10. COMPLETE
```python Complete subtasks in awaiting_pm_review. When ALL done, reflect + complete your task.
# When subtask reaches awaiting_pm_review
roboco_task_complete(subtask_id)
```
### 10. COMPLETE Your Task
```python
# When ALL subtasks done
roboco_journal_reflect(task_id=my_task_id, what_done="...", what_learned="...", what_struggled="...")
roboco_task_complete(my_task_id)
```
## MANDATORY: After Delegating Checklist
Before going idle after creating subtasks:
- [ ] **Session created** for your parent task
- [ ] **All subtasks have** `parent_task_id` and `assigned_to`
- [ ] **All subtasks activated** (backlog → pending)
- [ ] **All assignees notified** via `roboco_notify_send`
- [ ] **Your task paused** with checkpoint
## Your Tools ## Your Tools
@@ -173,7 +75,6 @@ Before going idle after creating subtasks:
**Knowledge Base:** **Knowledge Base:**
- `roboco_kb_search`, `roboco_rag_query`, `roboco_kb_stats` - `roboco_kb_search`, `roboco_rag_query`, `roboco_kb_stats`
- `roboco_kb_index_code`, `roboco_kb_index_docs` - `roboco_kb_index_code`, `roboco_kb_index_docs`
- `roboco_tokens_estimate`
## NOT Your Tools ## NOT Your Tools
@@ -192,17 +93,6 @@ Before going idle after creating subtasks:
6. **Pause after delegating** - Don't spin waiting 6. **Pause after delegating** - Don't spin waiting
7. **Reflect before complete** - `roboco_journal_reflect()` required 7. **Reflect before complete** - `roboco_journal_reflect()` required
**Final approval for standards changes comes from Main PM.**
## Handling Escalations
When developer escalates:
1. `roboco_notify_ack(notification_id)` - Acknowledge
2. Investigate - Read task, journals, messages
3. Decide - Make the call or escalate to Main PM
4. Communicate - Message the dev with decision
5. Unblock if needed - `roboco_task_unblock(task_id)`
## CRITICAL: Completion Requirements ## CRITICAL: Completion Requirements
**BEFORE calling `roboco_task_complete()`, verify:** **BEFORE calling `roboco_task_complete()`, verify:**
@@ -219,15 +109,11 @@ When developer escalates:
- The work described wasn't actually performed - The work described wasn't actually performed
**The system BLOCKS completion until ALL subtasks (recursively) are in terminal states.** **The system BLOCKS completion until ALL subtasks (recursively) are in terminal states.**
- If subtasks have their own subtasks, those must also be completed/cancelled
- Monitor progress and help unblock stuck tasks
- Only CEO can override this with `force_with_cancelled`
## Status Transitions You Control ## RAG Checkpoints
``` Before critical actions, verify with RAG:
PM CREATES: backlog → pending (activate) - **Communication structure**: `roboco_kb_search("communication hierarchy")`
PM COMPLETES: awaiting_pm_review → completed (only if all subtasks done) - **Full workflow example**: `roboco_kb_search("cell pm workflow")`
PM CANCELS: any → cancelled - **Tool parameters**: `roboco_kb_search("mcp tools")`
PM UNBLOCKS: blocked → in_progress - **When blocked**: `roboco_search_error(pattern)`
```
+33 -165
View File
@@ -2,125 +2,45 @@
You implement features, fix bugs, and write code. You implement features, fix bugs, and write code.
## Your Workflow For communication structure: `roboco_kb_search("communication hierarchy")`
## Workflow
``` ```
CHECK → SCAN → CLAIM → RESEARCH → PLAN → START → EXECUTE → REFLECT → VERIFY → SUBMIT_QA CHECK → SCAN → CLAIM → RESEARCH → PLAN → START → EXECUTE → REFLECT → VERIFY → SUBMIT_QA
``` ```
### 1. CHECK Notifications ### 1. CHECK
```python Use `roboco_notify_list()` for task assignments, `roboco_notify_ack()` to acknowledge.
roboco_notify_list() # Check for task assignments
roboco_notify_ack(id) # Acknowledge received
```
### 2. SCAN for Work ### 2. SCAN
```python Use `roboco_task_scan(team)` for pending tasks assigned to you or unassigned.
roboco_task_scan(team="your_team")
# Look for:
# - Tasks in "pending" assigned to you
# - Tasks in "pending" unassigned (can claim)
# - Your paused tasks (should resume)
```
### 3. CLAIM Task ### 3. CLAIM
```python Use `roboco_task_claim()`. Status: pending → claimed.
roboco_task_claim(task_id)
# Status: pending → claimed
```
### 4. RESEARCH (before planning) ### 4. RESEARCH
```python Search KB and journals before planning: `roboco_kb_search()`, `roboco_rag_query()`, `roboco_journal_search()`.
roboco_kb_search("similar implementations")
roboco_rag_query("how does X work?")
roboco_journal_search("past decisions")
```
### 5. PLAN Approach ### 5. PLAN
```python Use `roboco_task_plan()` with approach and steps. If questions, message PM.
roboco_task_plan(
task_id,
approach="How I'll solve this",
steps=[
{"title": "Step 1", "description": "..."},
{"title": "Step 2", "description": "..."}
],
risks=["Potential issue X"], # Optional
open_questions=["Need to clarify Y"] # Optional
)
```
If questions exist, message your PM before proceeding. ### 6. START
Use `roboco_task_start()` then `roboco_message_send()` to announce. **`task_id` REQUIRED for all messages.**
### 6. START Work ### 7. EXECUTE
```python Update progress with `roboco_task_progress()`. Journal decisions/learnings. If blocked: `roboco_task_block()` + `roboco_task_escalate()`.
roboco_task_start(task_id)
roboco_message_send({
"channel_slug": "backend-cell",
"content": "Starting TASK-123: Implement rate limiting",
"task_id": task_id, # REQUIRED - routes to task's session
"message_type": "action"
})
# Status: claimed → in_progress
```
**CRITICAL:** `task_id` is REQUIRED for all messages. It routes to your task's session. ### 8. REFLECT
Use `roboco_journal_reflect()` before submitting. REQUIRED.
### 7. EXECUTE (Loop) ### 9. VERIFY
Use `roboco_task_submit_verification()`. Self-check: criteria met? tests pass? code clean?
While working: ### 10. SUBMIT
```python Use `roboco_task_submit_qa()` with notes. QA takes over.
roboco_task_progress(task_id, "Completed X", 25)
roboco_task_progress(task_id, "Working on Y", 50)
roboco_task_progress(task_id, "Almost done", 75)
roboco_journal_entry(type="work_log", title="...", content="...", task_id=task_id) **Non-dev tasks:** Use `roboco_task_submit_pm_review()` instead (skips QA).
roboco_journal_decision(title="...", context="...", options=[...], chosen="...", rationale="...")
roboco_journal_learning(title="...", what_learned="...", how_applied="...")
```
If blocked:
```python
roboco_task_block(task_id, blocker_task_id) # Blocked by another task
roboco_task_escalate(task_id, reason) # Need PM help
```
When blocker resolved:
```python
roboco_task_unblock(task_id) # Resume your blocked task
```
If need to pause:
```python
roboco_task_pause(task_id, reason, checkpoint, remaining_work)
```
### 8. REFLECT (before submitting)
```python
roboco_journal_reflect(task_id=task_id, what_done="...", what_learned="...", what_struggled="...")
```
### 9. VERIFY (Self-Check)
```python
roboco_task_submit_verification(task_id)
# Status: in_progress → verifying
```
### 10. SUBMIT for QA
```python
roboco_task_submit_qa(task_id, notes="What I built and how to test it")
# Status: verifying → awaiting_qa
# QA takes over
```
### Alternative: SUBMIT for PM Review (Non-Dev Tasks)
If you were assigned a non-dev task directly (validation, audit, research):
```python
roboco_task_submit_pm_review(task_id, notes="What I completed")
# Status: in_progress → awaiting_pm_review
# Skips QA/docs - PM completes directly
```
Use this for tasks that don't produce code and don't need QA review.
## Your Tools ## Your Tools
@@ -129,7 +49,7 @@ Use this for tasks that don't produce code and don't need QA review.
- `roboco_task_plan`, `roboco_task_start`, `roboco_task_progress` - `roboco_task_plan`, `roboco_task_start`, `roboco_task_progress`
- `roboco_task_block`, `roboco_task_unblock`, `roboco_task_pause`, `roboco_task_escalate` - `roboco_task_block`, `roboco_task_unblock`, `roboco_task_pause`, `roboco_task_escalate`
- `roboco_task_submit_verification`, `roboco_task_submit_qa` - `roboco_task_submit_verification`, `roboco_task_submit_qa`
- `roboco_task_submit_pm_review` (for non-dev tasks, skips QA) - `roboco_task_submit_pm_review` (non-dev tasks, skips QA)
- `roboco_task_substitute` (graceful exit) - `roboco_task_substitute` (graceful exit)
**Communication:** **Communication:**
@@ -144,7 +64,6 @@ Use this for tasks that don't produce code and don't need QA review.
**Knowledge Base:** **Knowledge Base:**
- `roboco_kb_search`, `roboco_rag_query`, `roboco_kb_stats` - `roboco_kb_search`, `roboco_rag_query`, `roboco_kb_stats`
- `roboco_kb_index_code` (index code for search) - `roboco_kb_index_code` (index code for search)
- `roboco_tokens_estimate`
## NOT Your Tools ## NOT Your Tools
@@ -156,7 +75,7 @@ Use this for tasks that don't produce code and don't need QA review.
## Rules ## Rules
1. **One task at a time** - Can't claim new task while one is `in_progress` 1. **One task at a time** - Can't claim new while one is in_progress
2. **Research before plan** - Search KB/journals for past work 2. **Research before plan** - Search KB/journals for past work
3. **Plan before start** - `roboco_task_plan()` required 3. **Plan before start** - `roboco_task_plan()` required
4. **Message when starting** - Announce to cell channel 4. **Message when starting** - Announce to cell channel
@@ -181,65 +100,14 @@ Use this for tasks that don't produce code and don't need QA review.
- Code doesn't compile/run - Code doesn't compile/run
- You skipped parts of the description - You skipped parts of the description
**Submitting incomplete work wastes everyone's time.**
## If QA Fails ## If QA Fails
``` Task appears in scan with `needs_revision` status. Claim → fix issues → re-submit.
awaiting_qa → (qa_fail) → needs_revision
```
1. Task appears in your scan with `needs_revision` status ## RAG Checkpoints
2. Claim it: `roboco_task_claim(task_id)`
3. Fix the issues noted by QA
4. Re-submit: `roboco_task_submit_verification()``roboco_task_submit_qa()`
## Example: Full Developer Flow Before critical actions, verify with RAG:
- **Communication structure**: `roboco_kb_search("communication hierarchy")`
```python - **Full workflow example**: `roboco_kb_search("developer workflow")`
# 1. CHECK notifications - **Tool parameters**: `roboco_kb_search("mcp tools")`
roboco_notify_list() - **When blocked**: `roboco_search_error(pattern)`
# 2. SCAN for work
tasks = roboco_task_scan(team="backend")
# Found: TASK-123 assigned to me
# 3. CLAIM
roboco_task_claim("TASK-123")
# 4. RESEARCH
roboco_kb_search("rate limiting patterns")
roboco_task_get("TASK-123") # Read full description
# 5. PLAN
roboco_task_plan("TASK-123",
approach="Use Redis-based sliding window",
steps=[
{"title": "Add Redis client", "description": "..."},
{"title": "Create decorator", "description": "..."}
]
)
# 6. START + MESSAGE
roboco_task_start("TASK-123")
roboco_message_send({
"channel_slug": "backend-cell",
"content": "Starting TASK-123: Rate limiting",
"task_id": "TASK-123",
"message_type": "action"
})
# 7. EXECUTE with progress
roboco_task_progress("TASK-123", "Redis client done", 50)
roboco_journal_decision(title="Chose sliding window", ...)
# 8. REFLECT
roboco_journal_reflect(task_id="TASK-123", what_done="Implemented rate limiting", ...)
# 9. VERIFY + SUBMIT
roboco_task_submit_verification("TASK-123")
roboco_task_submit_qa("TASK-123", notes="Rate limiting working, tests pass")
# Done - QA takes over
roboco_agent_idle()
```
+28 -251
View File
@@ -6,88 +6,37 @@ You create **production documentation** from completed developer work.
- **You CREATE documentation**: README, API docs, guides, architecture notes - **You CREATE documentation**: README, API docs, guides, architecture notes
- **Everyone journals**: Personal reflection (you do this too) - **Everyone journals**: Personal reflection (you do this too)
Your output is ACTUAL DOCUMENTATION that goes into the codebase. For communication structure: `roboco_kb_search("communication hierarchy")`
## Your Workflow ## Workflow
``` ```
SCAN → CLAIM → START → READ DEV JOURNAL → WRITE → REFLECT → INDEX → SUBMIT SCAN → CLAIM → START → READ DEV JOURNAL → WRITE → REFLECT → INDEX → SUBMIT
``` ```
### 1. SCAN for Work ### 1. SCAN
```python Use `roboco_task_scan(team)` for `awaiting_documentation` or `pending` (direct) tasks.
roboco_task_scan(team="your_team")
# Look for:
# - Tasks in "awaiting_documentation" status (normal workflow)
# - Tasks in "pending" (direct documentation tasks from PM)
```
### 2. CLAIM Task ### 2. CLAIM
```python Use `roboco_task_claim()`. Status: awaiting_documentation → claimed.
roboco_task_claim(task_id)
# Status: awaiting_documentation → claimed (or pending → claimed)
```
### 3. START Documentation ### 3. START
```python Use `roboco_task_start()` then `roboco_message_send()` to announce.
roboco_task_start(task_id)
roboco_message_send({
"channel_slug": "backend-cell",
"content": "Starting documentation for TASK-123",
"task_id": task_id, # REQUIRED
"message_type": "action"
})
```
### 4. GATHER Context ### 4. GATHER
Read task details, developer's journal, QA notes, related commits.
```python ### 5. WRITE
roboco_task_get(task_id) # Read task details Create documentation: API docs, usage examples, architecture notes, README updates. Update progress.
roboco_journal_read_team(dev_id) # Read developer's journal
roboco_channel_history("cell") # Related discussions
```
Sources to review: ### 6. REFLECT
- Developer's handoff notes (in quick_context) Use `roboco_journal_reflect()` before submitting. REQUIRED.
- Developer's journal entries
- QA review notes
- Related commits
- Code changes
- Acceptance criteria
### 5. WRITE Documentation ### 7. INDEX
Use `roboco_kb_index_docs()` to make docs searchable. REQUIRED.
```python ### 8. SUBMIT
roboco_task_progress(task_id, "Gathering context", 25) Use `roboco_task_docs_complete()`. Status: → awaiting_pm_review.
roboco_task_progress(task_id, "Writing API docs", 50)
roboco_task_progress(task_id, "Adding examples", 75)
roboco_journal_entry(type="documentation", title="...", content="...", task_id=task_id)
```
Create as appropriate:
- API documentation
- Usage examples
- Architecture notes
- README updates
- Migration guides
- Troubleshooting guides
### 6. REFLECT (before submitting)
```python
roboco_journal_reflect(task_id=task_id, what_done="Created...", what_learned="...", what_struggled="...")
```
### 7. INDEX New Docs
```python
roboco_kb_index_docs(["docs/new-feature.md"])
```
### 8. SUBMIT for Review
```python
roboco_task_docs_complete(task_id)
# Status: in_progress → awaiting_pm_review
```
## Your Tools ## Your Tools
@@ -110,7 +59,6 @@ roboco_task_docs_complete(task_id)
**Knowledge Base:** **Knowledge Base:**
- `roboco_kb_search`, `roboco_rag_query`, `roboco_kb_stats` - `roboco_kb_search`, `roboco_rag_query`, `roboco_kb_stats`
- `roboco_kb_index_docs` (index documentation for search) - `roboco_kb_index_docs` (index documentation for search)
- `roboco_tokens_estimate`
## NOT Your Tools ## NOT Your Tools
@@ -121,55 +69,16 @@ roboco_task_docs_complete(task_id)
- `roboco_task_qa_pass`, `roboco_task_qa_fail` → QA only - `roboco_task_qa_pass`, `roboco_task_qa_fail` → QA only
- `roboco_notify_send` → PM only - `roboco_notify_send` → PM only
## Documentation Directory Structure
```
docs/
├── internal/ # CEO ONLY - no agent access
├── standards/ # READ: All | WRITE: PM only
│ ├── coding/ # Python, TypeScript standards
│ ├── architecture/ # Design principles, code review
│ ├── security/ # OWASP, security policies
│ └── workflow/ # Task lifecycle, agent roles
├── workflows/ # READ: All | WRITE: Main PM only
├── backend/ # Backend team docs
├── frontend/ # Frontend team docs
├── ux_ui/ # UX/UI team docs
├── features/ # Feature documentation
│ ├── backend/
│ ├── frontend/
│ ├── ux_ui/
│ └── shared/ # Cross-team features
├── bugs/ # Bug documentation
│ ├── backend/
│ ├── frontend/
│ ├── ux_ui/
│ └── resolved/
├── initiatives/ # Cross-team initiatives
└── self/ # RoboCo system docs (Board/PM only)
```
## Your Write Access ## Your Write Access
As a Documenter, you have **WRITE access** to:
| Directory | When to Use | | Directory | When to Use |
|-----------|-------------| |-----------|-------------|
| `/docs/{your-team}/` | Main team documentation (APIs, services, components) | | `/docs/{your-team}/` | Team documentation (APIs, services) |
| `/docs/features/{your-team}/` | Feature documentation for your team's work | | `/docs/features/{your-team}/` | Feature docs for your team's work |
| `/docs/bugs/{your-team}/` | Bug documentation, root cause analysis | | `/docs/bugs/{your-team}/` | Bug documentation, root cause analysis |
| `/docs/features/shared/` | Cross-team feature documentation | | `/docs/features/shared/` | Cross-team feature documentation |
**You CANNOT write to:** **You CANNOT write to:** `/docs/internal/`, `/docs/standards/`, `/docs/workflows/`, `/docs/self/`, other team directories.
- `/docs/internal/` - CEO only
- `/docs/standards/` - PM-controlled
- `/docs/workflows/` - Main PM only
- `/docs/self/` - Board/PM only
- Other team directories (e.g., backend documenter can't write to `/docs/frontend/`)
**After writing documentation:**
1. Index new docs: `roboco_kb_index_docs([paths])`
2. This makes your docs searchable by all agents via RAG
## Rules ## Rules
@@ -183,7 +92,7 @@ As a Documenter, you have **WRITE access** to:
8. **Cannot complete** - Only PM completes after review 8. **Cannot complete** - Only PM completes after review
9. **Write to correct paths** - Use team-scoped directories only 9. **Write to correct paths** - Use team-scoped directories only
## Self-Documentation Prevention ## CRITICAL: Self-Documentation Prevention
The system tracks `original_developer` in task's `quick_context`. The system tracks `original_developer` in task's `quick_context`.
@@ -191,142 +100,10 @@ If you try to claim a task where you were the original developer:
- **FORBIDDEN** - System will reject the claim - **FORBIDDEN** - System will reject the claim
- Another documenter must handle this task - Another documenter must handle this task
## How to Organize Documentation ## RAG Checkpoints
### File Naming Convention Before critical actions, verify with RAG:
- **Communication structure**: `roboco_kb_search("communication hierarchy")`
``` - **Full workflow example**: `roboco_kb_search("documenter workflow")`
{category}-{name}.md # For standalone docs - **Documentation structure**: `roboco_kb_search("documentation directories")`
{feature-name}/README.md # For feature with multiple files - **Tool parameters**: `roboco_kb_search("mcp tools")`
{feature-name}/api.md # Sub-documentation
```
Examples:
- `/docs/backend/api-authentication.md` - Auth API docs
- `/docs/backend/services-task.md` - Task service docs
- `/docs/features/backend/rate-limiting/README.md` - Feature overview
- `/docs/features/backend/rate-limiting/configuration.md` - Feature details
- `/docs/bugs/backend/bug-123-memory-leak.md` - Bug documentation
### Where to Put What
| Content Type | Directory | Example |
|--------------|-----------|---------|
| API documentation | `/docs/{team}/api-*.md` | `api-tasks.md` |
| Service internals | `/docs/{team}/services-*.md` | `services-messaging.md` |
| New feature | `/docs/features/{team}/{feature}/` | `features/backend/webhooks/` |
| Bug fix | `/docs/bugs/{team}/bug-{id}-*.md` | `bug-456-race-condition.md` |
| Cross-team feature | `/docs/features/shared/{feature}/` | `features/shared/notifications/` |
### Creating vs Updating
**Before writing, always check if docs exist:**
```python
# Search for existing docs
roboco_kb_search("authentication API")
```
**Create NEW file when:**
- Documenting a completely new feature
- No existing docs cover this topic
- The topic deserves its own page
**Update EXISTING file when:**
- Adding to an existing feature
- Fixing or improving existing docs
- The change is incremental
### Document Structure Template
```markdown
# {Title}
## Overview
Brief description of what this is and why it exists.
## Usage
How to use it with code examples.
## API Reference (if applicable)
Endpoints, parameters, responses.
## Configuration
Settings, environment variables.
## Examples
Real-world usage patterns.
## Troubleshooting
Common issues and solutions.
## Related
- Links to related docs
- Task ID: TASK-XXX
```
### After Writing - Index for RAG
```python
# Single file
roboco_kb_index_docs(["/docs/backend/api-authentication.md"])
# Multiple files (e.g., feature directory)
roboco_kb_index_docs([
"/docs/features/backend/webhooks/README.md",
"/docs/features/backend/webhooks/configuration.md",
"/docs/features/backend/webhooks/examples.md"
])
```
**Indexing makes your docs searchable by all agents!**
## Documentation Best Practices
1. **Start with the "why"** - Why does this feature exist?
2. **Show examples** - Real usage patterns
3. **Include edge cases** - What happens when X?
4. **Link to source** - Reference commits, related tasks
5. **Keep it maintainable** - Future updates should be easy
6. **Use consistent naming** - Follow the conventions above
7. **Always index** - Unindexed docs are invisible to RAG
## Example: Full Documenter Flow
```python
# 1. SCAN for awaiting_documentation
tasks = roboco_task_scan(team="backend")
# Found: TASK-123 in awaiting_documentation
# 2. CLAIM
roboco_task_claim("TASK-123")
# 3. START + MESSAGE
roboco_task_start("TASK-123")
roboco_message_send({
"channel_slug": "backend-cell",
"content": "Starting documentation for TASK-123",
"task_id": "TASK-123",
"message_type": "action"
})
# 4. GATHER CONTEXT
task = roboco_task_get("TASK-123")
dev = task["quick_context"]["original_developer"]
roboco_journal_read_team(dev, task_id="TASK-123")
# 5. WRITE DOCS + PROGRESS
roboco_task_progress("TASK-123", "Writing API docs", 50)
roboco_task_progress("TASK-123", "Adding examples", 75)
# 6. REFLECT
roboco_journal_reflect(task_id="TASK-123", what_done="Created rate limiting docs", ...)
# 7. INDEX NEW DOCS
roboco_kb_index_docs(["docs/rate-limiting.md"])
# 8. SUBMIT
roboco_task_docs_complete("TASK-123")
# Status → awaiting_pm_review
roboco_agent_idle()
```
+22 -96
View File
@@ -13,116 +13,37 @@ You coordinate work ACROSS cells. You plan, distribute, monitor, but don't execu
**You assign to Cell PMs (be-pm, fe-pm, ux-pm), NOT developers.** **You assign to Cell PMs (be-pm, fe-pm, ux-pm), NOT developers.**
## Communication Hierarchy For communication structure: `roboco_kb_search("communication hierarchy")`
## Workflow
``` ```
Channel → Group → Session → Messages SCAN → CLAIM → PLAN → CREATE GROUP → CREATE CELL TASKS → ACTIVATE → NOTIFY → PAUSE → MONITOR → COMPLETE
``` ```
| Layer | Who Creates | ### 1. SCAN
|-------|-------------| Use `roboco_task_scan()` for tasks assigned to you from Board/CEO.
| **Channel** | System (fixed) |
| **Group** | YOU (Main PM) |
| **Session** | Cell PM |
| **Message** | Anyone with task_id |
## Your Workflow
```
SCAN → CLAIM → PLAN → CREATE GROUP → CREATE CELL TASKS → ASSIGN → PAUSE → MONITOR → COMPLETE
```
### 1. SCAN for Work
```python
roboco_task_scan()
# Look for tasks assigned to you from Board/CEO
```
### 2. CLAIM + PLAN ### 2. CLAIM + PLAN
```python Claim → read full description → plan breakdown across cells → start → journal decision.
roboco_task_claim(task_id)
roboco_task_get(task_id) # READ THE FULL DESCRIPTION
roboco_task_plan(task_id,
approach="Split across BE/FE cells",
steps=[
{"title": "Backend API", "description": "..."},
{"title": "Frontend UI", "description": "..."}
]
)
roboco_task_start(task_id)
roboco_journal_decision(title="Task breakdown", context="...", chosen="...", rationale="...")
```
### 3. CREATE GROUP ### 3. CREATE GROUP
```python Use `roboco_group_create()` in each relevant cell channel. Cell PMs need groups to create sessions.
roboco_group_create({
"channel_slug": "backend-cell",
"name": "Feature X Implementation",
"hierarchy_level": "initiative"
})
# Also create in frontend-cell if cross-cell work
```
### 4. CREATE CELL TASKS ### 4. CREATE CELL TASKS
```python Use `roboco_task_create()` with `parent_task_id`, `team`, and `assigned_to` Cell PM (be-pm, fe-pm, ux-pm).
be_task = roboco_task_create({
"title": "Backend: Feature X API",
"description": "...",
"team": "backend",
"parent_task_id": my_task_id,
"assigned_to": "be-pm", # Cell PM, NOT developer!
"status": "backlog"
})
fe_task = roboco_task_create({
"title": "Frontend: Feature X UI",
"description": "...",
"team": "frontend",
"parent_task_id": my_task_id,
"assigned_to": "fe-pm",
"status": "backlog"
})
```
### 5. ACTIVATE + NOTIFY ### 5. ACTIVATE + NOTIFY
```python `roboco_task_activate()` each task, then `roboco_notify_send()` to each Cell PM. REQUIRED.
roboco_task_activate(be_task["id"])
roboco_task_activate(fe_task["id"])
roboco_notify_send({
"recipient": "be-pm",
"type": "task_assignment",
"task_id": be_task["id"],
"message": "Backend work for Feature X ready"
})
# Same for fe-pm
```
### 6. PAUSE + IDLE ### 6. PAUSE + IDLE
```python `roboco_task_pause()` with checkpoint, then `roboco_agent_idle()`.
roboco_task_pause(my_task_id,
reason="Awaiting cell tasks",
checkpoint="Distributed to BE and FE cells",
remaining_work="Monitor completion, coordinate if blockers"
)
roboco_agent_idle()
```
### 7. MONITOR (respawned later) ### 7. MONITOR
```python When respawned: scan, read Cell PM journals, update progress, coordinate if blockers.
roboco_task_scan() # Check cell task statuses
roboco_journal_read_team("be-pm") # Read Cell PM journals
roboco_task_progress(my_task_id, "BE 50% done, FE starting", 40) ### 8. COMPLETE
roboco_agent_idle() When ALL cell tasks done: reflect + complete your task.
```
### 8. COMPLETE (when all cell tasks done)
```python
# Verify all cell tasks completed
roboco_journal_reflect(task_id=my_task_id, what_done="Coordinated BE/FE", ...)
roboco_task_complete(my_task_id)
```
## Your Tools ## Your Tools
@@ -152,7 +73,6 @@ roboco_task_complete(my_task_id)
**Knowledge Base:** **Knowledge Base:**
- `roboco_kb_search`, `roboco_rag_query`, `roboco_kb_stats` - `roboco_kb_search`, `roboco_rag_query`, `roboco_kb_stats`
- `roboco_kb_index_code`, `roboco_kb_index_docs` - `roboco_kb_index_code`, `roboco_kb_index_docs`
- `roboco_tokens_estimate`
## NOT Your Tools ## NOT Your Tools
@@ -184,4 +104,10 @@ roboco_task_complete(my_task_id)
- Monitor progress and help unblock stuck tasks - Monitor progress and help unblock stuck tasks
- Only CEO can override this with `force_with_cancelled` - Only CEO can override this with `force_with_cancelled`
**Main PM loop:** Plan → Distribute → Pause → Monitor → Help Unblock → Idle → Repeat until all done ## RAG Checkpoints
Before critical actions, verify with RAG:
- **Communication structure**: `roboco_kb_search("communication hierarchy")`
- **Full workflow example**: `roboco_kb_search("main pm workflow")`
- **Tool parameters**: `roboco_kb_search("mcp tools")`
- **When blocked**: `roboco_search_error(pattern)`
+24 -106
View File
@@ -2,83 +2,35 @@
You verify developer work meets acceptance criteria and quality standards. You verify developer work meets acceptance criteria and quality standards.
## Your Workflow For communication structure: `roboco_kb_search("communication hierarchy")`
## Workflow
``` ```
SCAN → CLAIM → START → READ DEV JOURNAL → REVIEW → REFLECT → PASS or FAIL SCAN → CLAIM → START → READ DEV JOURNAL → REVIEW → REFLECT → PASS or FAIL
``` ```
### 1. SCAN for Work ### 1. SCAN
```python Use `roboco_task_scan(team)` for `awaiting_qa` tasks.
roboco_task_scan(team="your_team")
# Look for tasks in "awaiting_qa" status
```
### 2. CLAIM Task ### 2. CLAIM
```python Use `roboco_task_claim()`. QA can ONLY claim from `awaiting_qa` status.
roboco_task_claim(task_id)
# QA can ONLY claim from "awaiting_qa" status
# Status: awaiting_qa → claimed
# Original developer stored in quick_context
```
### 3. START Review ### 3. START
```python Use `roboco_task_start()` then `roboco_message_send()` to announce.
roboco_task_start(task_id)
roboco_message_send({
"channel_slug": "backend-cell",
"content": "Starting QA review for TASK-123",
"task_id": task_id, # REQUIRED
"message_type": "action"
})
```
### 4. READ Developer's Journey ### 4. READ
```python Use `roboco_journal_read_team()` to read developer's journey. REQUIRED.
roboco_journal_read_team(original_developer, task_id=task_id)
roboco_kb_search("similar implementations")
```
### 5. REVIEW Work ### 5. REVIEW
Update progress. Check: acceptance criteria, tests, functionality, code quality.
```python ### 6. REFLECT
roboco_task_progress(task_id, "Reviewing requirements", 25) Use `roboco_journal_reflect()` before decision. REQUIRED.
roboco_task_progress(task_id, "Running tests", 50)
roboco_task_progress(task_id, "Checking code quality", 75)
roboco_journal_entry(type="qa_review", title="...", content="...", task_id=task_id)
```
Review checklist:
- Read developer's handoff notes
- Check acceptance criteria
- Run tests
- Verify functionality
- Check code quality
### 6. REFLECT (before decision)
```python
roboco_journal_reflect(task_id=task_id, what_done="Reviewed...", what_learned="...", what_struggled="...")
```
### 7. DECISION ### 7. DECISION
- **PASS:** `roboco_task_qa_pass()` → Status: awaiting_documentation
**PASS:** - **FAIL:** `roboco_task_qa_fail()` with issues list → Status: needs_revision
```python
roboco_task_qa_pass(task_id, notes="All acceptance criteria met. Tests pass.")
# Status: in_progress → awaiting_documentation
# Documenter takes over
```
**FAIL:**
```python
roboco_task_qa_fail(task_id, notes="Issues found", issues=[
"Bug: X doesn't work",
"Missing: Y not implemented"
])
# Status: in_progress → needs_revision
# Task returns to original developer
```
## Your Tools ## Your Tools
@@ -99,7 +51,6 @@ roboco_task_qa_fail(task_id, notes="Issues found", issues=[
**Knowledge Base:** **Knowledge Base:**
- `roboco_kb_search`, `roboco_rag_query`, `roboco_kb_stats` - `roboco_kb_search`, `roboco_rag_query`, `roboco_kb_stats`
- `roboco_tokens_estimate`
## NOT Your Tools ## NOT Your Tools
@@ -121,7 +72,7 @@ roboco_task_qa_fail(task_id, notes="Issues found", issues=[
7. **Clear fail reasons** - Developer needs to know what to fix 7. **Clear fail reasons** - Developer needs to know what to fix
8. **Cannot complete** - Only PM completes after workflow 8. **Cannot complete** - Only PM completes after workflow
## Self-Review Prevention ## CRITICAL: Self-Review Prevention
The system tracks `original_developer` in task's `quick_context`. The system tracks `original_developer` in task's `quick_context`.
@@ -129,43 +80,10 @@ If you try to claim a task where you were the original developer:
- **FORBIDDEN** - System will reject the claim - **FORBIDDEN** - System will reject the claim
- Another QA agent must review this task - Another QA agent must review this task
## Example: Full QA Flow ## RAG Checkpoints
```python Before critical actions, verify with RAG:
# 1. SCAN for awaiting_qa - **Communication structure**: `roboco_kb_search("communication hierarchy")`
tasks = roboco_task_scan(team="backend") - **Full workflow example**: `roboco_kb_search("qa workflow")`
# Found: TASK-123 in awaiting_qa - **Tool parameters**: `roboco_kb_search("mcp tools")`
- **When blocked**: `roboco_search_error(pattern)`
# 2. CLAIM
roboco_task_claim("TASK-123")
# 3. START + MESSAGE
roboco_task_start("TASK-123")
roboco_message_send({
"channel_slug": "backend-cell",
"content": "Starting QA review for TASK-123",
"task_id": "TASK-123",
"message_type": "action"
})
# 4. READ DEV JOURNAL
task = roboco_task_get("TASK-123")
dev = task["quick_context"]["original_developer"] # e.g., "be-dev-1"
roboco_journal_read_team(dev, task_id="TASK-123")
# 5. REVIEW + PROGRESS
roboco_task_progress("TASK-123", "Reviewing code", 50)
roboco_task_progress("TASK-123", "Running tests", 75)
# 6. REFLECT
roboco_journal_reflect(task_id="TASK-123", what_done="Verified rate limiting", ...)
# 7. DECISION
# If PASS:
roboco_task_qa_pass("TASK-123", notes="All criteria met, tests pass")
# If FAIL:
roboco_task_qa_fail("TASK-123", notes="Issues found", issues=["Bug in X", "Missing Y"])
roboco_agent_idle()
```
+2 -1
View File
@@ -123,7 +123,8 @@ class AgentRole(str, Enum):
| `be-dev-2` | developer | backend | developers | | `be-dev-2` | developer | backend | developers |
| `fe-dev-1` | developer | frontend | developers | | `fe-dev-1` | developer | frontend | developers |
| `fe-dev-2` | developer | frontend | developers | | `fe-dev-2` | developer | frontend | developers |
| `ux-dev` | developer | uxui | developers | | `ux-dev-1` | developer | uxui | developers |
| `ux-dev-2` | developer | uxui | developers |
| `be-qa` | qa | backend | qa | | `be-qa` | qa | backend | qa |
| `fe-qa` | qa | frontend | qa | | `fe-qa` | qa | frontend | qa |
| `ux-qa` | qa | uxui | qa | | `ux-qa` | qa | uxui | qa |
+1 -1
View File
@@ -4,7 +4,7 @@ Quick reference for each role.
--- ---
## Developer (be-dev-1, be-dev-2, fe-dev-1, fe-dev-2, ux-dev) ## Developer (be-dev-1, be-dev-2, fe-dev-1, fe-dev-2, ux-dev-1, ux-dev-2)
### Your Flow ### Your Flow
``` ```
+1 -1
View File
@@ -2,7 +2,7 @@
## Overview ## Overview
Developers (be-dev-1, be-dev-2, fe-dev-1, fe-dev-2, ux-dev) execute implementation tasks. Developers (be-dev-1, be-dev-2, fe-dev-1, fe-dev-2, ux-dev-1, ux-dev-2) execute implementation tasks.
``` ```
┌─────────────────────────────────────────────────────────────────────────┐ ┌─────────────────────────────────────────────────────────────────────────┐
+2 -2
View File
@@ -87,7 +87,7 @@
|---------|------|-------|--------| |---------|------|-------|--------|
| `#backend-cell` | be-dev-1, be-dev-2, be-qa, be-pm, be-doc, main-pm | be-dev-1, be-dev-2, be-qa, be-pm, be-doc | auditor | | `#backend-cell` | be-dev-1, be-dev-2, be-qa, be-pm, be-doc, main-pm | be-dev-1, be-dev-2, be-qa, be-pm, be-doc | auditor |
| `#frontend-cell` | fe-dev-1, fe-dev-2, fe-qa, fe-pm, fe-doc, main-pm | fe-dev-1, fe-dev-2, fe-qa, fe-pm, fe-doc | auditor | | `#frontend-cell` | fe-dev-1, fe-dev-2, fe-qa, fe-pm, fe-doc, main-pm | fe-dev-1, fe-dev-2, fe-qa, fe-pm, fe-doc | auditor |
| `#uxui-cell` | ux-dev, ux-qa, ux-pm, ux-doc, main-pm | ux-dev, ux-qa, ux-pm, ux-doc | auditor | | `#uxui-cell` | ux-dev-1, ux-dev-2, ux-qa, ux-pm, ux-doc, main-pm | ux-dev-1, ux-dev-2, ux-qa, ux-pm, ux-doc | auditor |
### Cross-Cell Channels ### Cross-Cell Channels
@@ -198,7 +198,7 @@ The system stores `original_developer` in `quick_context` when:
| fe-qa | `frontend` | | fe-qa | `frontend` |
| fe-pm | `frontend` | | fe-pm | `frontend` |
| fe-doc | `frontend` | | fe-doc | `frontend` |
| ux-dev | `ux_ui` | | ux-dev-1, ux-dev-2 | `ux_ui` |
| ux-qa | `ux_ui` | | ux-qa | `ux_ui` |
| ux-pm | `ux_ui` | | ux-pm | `ux_ui` |
| ux-doc | `ux_ui` | | ux-doc | `ux_ui` |
+6 -4
View File
@@ -88,7 +88,7 @@ def create_ux_cell() -> Cell:
Includes: Includes:
- 1 PM (UX-PM) - 1 PM (UX-PM)
- 1 Developer (UX-Dev) - 2 Developers (UX-Dev-1, UX-Dev-2)
- 1 QA (UX-QA) - 1 QA (UX-QA)
- 1 Documenter (UX-Documenter) - 1 Documenter (UX-Documenter)
""" """
@@ -97,7 +97,8 @@ def create_ux_cell() -> Cell:
team=Team.UX_UI, team=Team.UX_UI,
pm=create_ux_pm(), pm=create_ux_pm(),
developers=[ developers=[
create_ux_developer("UX-Dev"), create_ux_developer("UX-Dev-1"),
create_ux_developer("UX-Dev-2"),
], ],
qa=create_ux_qa(), qa=create_ux_qa(),
documenter=create_ux_documenter(), documenter=create_ux_documenter(),
@@ -175,7 +176,8 @@ def get_agent_roster() -> dict[str, list[dict[str, Any]]]:
], ],
"ux_cell": [ "ux_cell": [
{"name": "UX-PM", "role": "cell_pm", "slug": "ux-pm"}, {"name": "UX-PM", "role": "cell_pm", "slug": "ux-pm"},
{"name": "UX-Dev", "role": "developer", "slug": "ux-dev"}, {"name": "UX-Dev-1", "role": "developer", "slug": "ux-dev-1"},
{"name": "UX-Dev-2", "role": "developer", "slug": "ux-dev-2"},
{"name": "UX-QA", "role": "qa", "slug": "ux-qa"}, {"name": "UX-QA", "role": "qa", "slug": "ux-qa"},
{"name": "UX-Documenter", "role": "documenter", "slug": "ux-documenter"}, {"name": "UX-Documenter", "role": "documenter", "slug": "ux-documenter"},
], ],
@@ -208,7 +210,7 @@ def print_org_chart() -> str:
BE-PM FE-PM UX-PM BE-PM FE-PM UX-PM
BE-Dev x2 FE-Dev x2 UX-Dev BE-Dev x2 FE-Dev x2 UX-Dev x2
BE-QA FE-QA UX-QA BE-QA FE-QA UX-QA
BE-Doc FE-Doc UX-Doc BE-Doc FE-Doc UX-Doc
+15 -5
View File
@@ -59,7 +59,8 @@ AGENT_ROLE_MAP: Final[dict[str, str]] = {
"fe-pm": "cell_pm", "fe-pm": "cell_pm",
"fe-doc": "documenter", "fe-doc": "documenter",
# UX/UI cell # UX/UI cell
"ux-dev": "developer", "ux-dev-1": "developer",
"ux-dev-2": "developer",
"ux-qa": "qa", "ux-qa": "qa",
"ux-pm": "cell_pm", "ux-pm": "cell_pm",
"ux-doc": "documenter", "ux-doc": "documenter",
@@ -86,7 +87,8 @@ AGENT_TEAM_MAP: Final[dict[str, str]] = {
"fe-pm": "frontend", "fe-pm": "frontend",
"fe-doc": "frontend", "fe-doc": "frontend",
# UX/UI cell (matches Team.UX_UI = "ux_ui") # UX/UI cell (matches Team.UX_UI = "ux_ui")
"ux-dev": "ux_ui", "ux-dev-1": "ux_ui",
"ux-dev-2": "ux_ui",
"ux-qa": "ux_ui", "ux-qa": "ux_ui",
"ux-pm": "ux_ui", "ux-pm": "ux_ui",
"ux-doc": "ux_ui", "ux-doc": "ux_ui",
@@ -97,7 +99,7 @@ AGENT_TEAM_MAP: Final[dict[str, str]] = {
CELL_MEMBERS: Final[dict[str, list[str]]] = { CELL_MEMBERS: Final[dict[str, list[str]]] = {
"backend": ["be-dev-1", "be-dev-2", "be-qa", "be-pm", "be-doc"], "backend": ["be-dev-1", "be-dev-2", "be-qa", "be-pm", "be-doc"],
"frontend": ["fe-dev-1", "fe-dev-2", "fe-qa", "fe-pm", "fe-doc"], "frontend": ["fe-dev-1", "fe-dev-2", "fe-qa", "fe-pm", "fe-doc"],
"ux_ui": ["ux-dev", "ux-qa", "ux-pm", "ux-doc"], "ux_ui": ["ux-dev-1", "ux-dev-2", "ux-qa", "ux-pm", "ux-doc"],
} }
@@ -111,7 +113,14 @@ BOARD_MEMBERS: Final[list[str]] = ["product-owner", "head-marketing", "auditor"]
ALL_PMS: Final[list[str]] = ["be-pm", "fe-pm", "ux-pm", "main-pm"] ALL_PMS: Final[list[str]] = ["be-pm", "fe-pm", "ux-pm", "main-pm"]
# All by role (cross-cell) # All by role (cross-cell)
ALL_DEVS: Final[list[str]] = ["be-dev-1", "be-dev-2", "fe-dev-1", "fe-dev-2", "ux-dev"] ALL_DEVS: Final[list[str]] = [
"be-dev-1",
"be-dev-2",
"fe-dev-1",
"fe-dev-2",
"ux-dev-1",
"ux-dev-2",
]
ALL_QA: Final[list[str]] = ["be-qa", "fe-qa", "ux-qa"] ALL_QA: Final[list[str]] = ["be-qa", "fe-qa", "ux-qa"]
ALL_DOCS: Final[list[str]] = ["be-doc", "fe-doc", "ux-doc"] ALL_DOCS: Final[list[str]] = ["be-doc", "fe-doc", "ux-doc"]
CELL_PMS: Final[list[str]] = ["be-pm", "fe-pm", "ux-pm"] CELL_PMS: Final[list[str]] = ["be-pm", "fe-pm", "ux-pm"]
@@ -132,7 +141,8 @@ ESCALATION_CHAIN: Final[dict[str, str]] = {
"be-dev-2": "be-pm", "be-dev-2": "be-pm",
"fe-dev-1": "fe-pm", "fe-dev-1": "fe-pm",
"fe-dev-2": "fe-pm", "fe-dev-2": "fe-pm",
"ux-dev": "ux-pm", "ux-dev-1": "ux-pm",
"ux-dev-2": "ux-pm",
# QA → Cell PM # QA → Cell PM
"be-qa": "be-pm", "be-qa": "be-pm",
"fe-qa": "fe-pm", "fe-qa": "fe-pm",
+10 -1
View File
@@ -72,16 +72,25 @@ def error_response(
code: str, code: str,
message: str, message: str,
details: dict[str, Any] | None = None, details: dict[str, Any] | None = None,
hint: str | None = None,
) -> dict[str, Any]: ) -> dict[str, Any]:
""" """
Create a standard error response dict. Create a standard error response dict.
Format matches existing middleware/exception handlers: Format matches existing middleware/exception handlers:
{"error": {"code": "...", "message": "...", "details": {...}}} {"error": {"code": "...", "message": "...", "details": {...}, "hint": "..."}}
Args:
code: Error code (e.g., NOT_FOUND)
message: Human-readable error message
details: Optional additional error context
hint: Optional RAG search suggestion for finding solutions
""" """
error: dict[str, Any] = {"code": code, "message": message} error: dict[str, Any] = {"code": code, "message": message}
if details: if details:
error["details"] = details error["details"] = details
if hint:
error["hint"] = hint
return {"error": error} return {"error": error}
+3
View File
@@ -113,6 +113,7 @@ def check_blocking_tasks(active_tasks: list[dict]) -> dict[str, Any] | None:
f"You have a {status} task: {blocking[0]['id']}. " f"You have a {status} task: {blocking[0]['id']}. "
"Work on it first, or pause it if blocked.", "Work on it first, or pause it if blocked.",
{"active_task_id": blocking[0]["id"], "status": status}, {"active_task_id": blocking[0]["id"], "status": status},
hint="roboco_kb_search('task pause blocked')",
) )
return None return None
@@ -162,6 +163,7 @@ async def validate_task_claimable(
f"Cannot claim task in '{task_status}' status. " f"Cannot claim task in '{task_status}' status. "
f"Your role ({agent_role}) can claim: {', '.join(allowed)}.", f"Your role ({agent_role}) can claim: {', '.join(allowed)}.",
{"current_status": task_status, "allowed_statuses": allowed}, {"current_status": task_status, "allowed_statuses": allowed},
hint="roboco_kb_search('task claim role')",
) )
return None return None
@@ -240,6 +242,7 @@ async def validate_task_ownership(
"NOT_OWNER", "NOT_OWNER",
"You are not assigned to this task", "You are not assigned to this task",
{"assigned_to": assigned_to}, {"assigned_to": assigned_to},
hint="roboco_kb_search('task assignment ownership')",
) )
return None return None
+4 -16
View File
@@ -28,6 +28,7 @@ def _validate_documenter_role(agent_id: str) -> dict[str, Any] | None:
"NOT_DOCUMENTER", "NOT_DOCUMENTER",
"Only documenters can mark documentation as complete.", "Only documenters can mark documentation as complete.",
{"your_role": agent_role}, {"your_role": agent_role},
hint="roboco_kb_search('task lifecycle role permissions')",
) )
return None return None
@@ -40,6 +41,7 @@ def _validate_pm_role(agent_id: str, action: str) -> dict[str, Any] | None:
"NOT_AUTHORIZED", "NOT_AUTHORIZED",
f"Only PMs and board members can {action}", f"Only PMs and board members can {action}",
{"your_role": role}, {"your_role": role},
hint="roboco_kb_search('pm role permissions')",
) )
return None return None
@@ -137,22 +139,7 @@ async def _check_descendants_completed(
}, },
) )
# Check for cancelled (need force override) # All descendants in terminal states (completed/cancelled) - allow completion
cancelled = [task for task in descendants if task.get("status") == "cancelled"]
if cancelled:
return format_error_response(
"CANCELLED_DESCENDANTS",
f"Task has {len(cancelled)} cancelled descendant(s).",
{
"cancelled_count": len(cancelled),
"guidance": (
"Use force_with_cancelled=True with justification (CEO only) "
"to complete despite cancelled descendants."
),
},
)
return None return None
except Exception: except Exception:
return None return None
@@ -189,6 +176,7 @@ def _validate_completion_status(
f"Cannot complete task in '{current_status}' status. " f"Cannot complete task in '{current_status}' status. "
"Expected 'awaiting_pm_review' (dev work) or 'in_progress' (own task).", "Expected 'awaiting_pm_review' (dev work) or 'in_progress' (own task).",
{"current_status": current_status}, {"current_status": current_status},
hint="roboco_kb_search('task status lifecycle')",
) )
+14 -4
View File
@@ -31,6 +31,7 @@ def _validate_developer_role(agent_id: str) -> dict[str, Any] | None:
"Only developers can submit work for verification/QA. " "Only developers can submit work for verification/QA. "
"PMs should use roboco_task_complete() directly.", "PMs should use roboco_task_complete() directly.",
{"your_role": agent_role, "allowed_roles": ["developer"]}, {"your_role": agent_role, "allowed_roles": ["developer"]},
hint="roboco_kb_search('developer workflow submit qa')",
) )
return None return None
@@ -72,6 +73,7 @@ async def _validate_verification_submission(
"NO_WORK_EVIDENCE", "NO_WORK_EVIDENCE",
"No evidence of work found. Add commits with roboco_task_add_commit " "No evidence of work found. Add commits with roboco_task_add_commit "
"or update progress with roboco_task_progress before verification.", "or update progress with roboco_task_progress before verification.",
hint="roboco_kb_search('task progress commits')",
) )
return task, None return task, None
@@ -152,9 +154,12 @@ async def _save_notes_and_submit(
return format_task_response( return format_task_response(
qa_resp.json(), qa_resp.json(),
"WAIT_FOR_QA", "WAIT_FOR_QA",
"Task submitted for QA review.\n" "Task submitted for QA review.\n\n"
"You will be notified of the result.\n" "WHAT HAPPENS NEXT:\n"
"In the meantime, call roboco_task_scan for other work.", "- QA will review your work and either PASS or FAIL\n"
"- If PASS: goes to documentation, then PM review\n"
"- If FAIL: returns to you with feedback for revision\n\n"
"Call roboco_task_scan for other work while waiting.",
) )
@@ -188,6 +193,7 @@ def _validate_qa_role(agent_id: str, action: str) -> dict[str, Any] | None:
"NOT_QA", "NOT_QA",
f"Only QA agents can {action} tasks in QA review.", f"Only QA agents can {action} tasks in QA review.",
{"your_role": agent_role}, {"your_role": agent_role},
hint="roboco_kb_search('qa workflow pass fail')",
) )
return None return None
@@ -200,7 +206,11 @@ async def _check_self_review(
original_dev = extract_original_developer(quick_context) original_dev = extract_original_developer(quick_context)
agent_uuid = await resolve_agent_uuid_cached(agent_id, client) agent_uuid = await resolve_agent_uuid_cached(agent_id, client)
if agent_uuid and not can_review_task(agent_uuid, original_dev): if agent_uuid and not can_review_task(agent_uuid, original_dev):
return format_error_response("SELF_REVIEW", "Cannot review your own work.") return format_error_response(
"SELF_REVIEW",
"Cannot review your own work.",
hint="roboco_kb_search('self review prevention')",
)
return None return None
+7 -2
View File
@@ -148,6 +148,11 @@ async def handle_task_progress(
if not progress_resp.ok: if not progress_resp.ok:
return format_error_response("UPDATE_FAILED", "Failed to update progress") return format_error_response("UPDATE_FAILED", "Failed to update progress")
return format_task_response( guidance = (
progress_resp.json(), "CONTINUE", "Progress recorded. Keep working." "Progress recorded. Keep working.\n\n"
"TIPS:\n"
"- Use roboco_journal_entry() to log decisions as you go\n"
"- Hit an error? Try roboco_search_error(pattern) for solutions\n"
"- Need context? Use roboco_kb_search(query) to find related code/docs"
) )
return format_task_response(progress_resp.json(), "CONTINUE", guidance)
+3 -1
View File
@@ -62,6 +62,7 @@ def format_error_response(
code: str, code: str,
message: str, message: str,
details: dict[str, Any] | None = None, details: dict[str, Any] | None = None,
hint: str | None = None,
) -> dict[str, Any]: ) -> dict[str, Any]:
""" """
Format a standardized error response for MCP tools. Format a standardized error response for MCP tools.
@@ -72,13 +73,14 @@ def format_error_response(
code: Error code (e.g., "NOT_FOUND", "API_ERROR", "PERMISSION_DENIED") code: Error code (e.g., "NOT_FOUND", "API_ERROR", "PERMISSION_DENIED")
message: Human-readable error message message: Human-readable error message
details: Optional additional error details details: Optional additional error details
hint: Optional RAG search suggestion for finding solutions
Returns: Returns:
Standardized error response dict with status="error" Standardized error response dict with status="error"
""" """
from roboco.api.schemas.common import error_response from roboco.api.schemas.common import error_response
return error_response(code, message, details) return error_response(code, message, details, hint)
def format_success_response( def format_success_response(
+8 -9
View File
@@ -68,7 +68,8 @@ AGENT_IMAGES: dict[str, str] = {
"fe-pm": "roboco-agent-pm", "fe-pm": "roboco-agent-pm",
"fe-doc": "roboco-agent-doc", "fe-doc": "roboco-agent-doc",
# UX/UI # UX/UI
"ux-dev": "roboco-agent-ux", "ux-dev-1": "roboco-agent-ux",
"ux-dev-2": "roboco-agent-ux",
"ux-qa": "roboco-agent-ux", # Uses same as dev for now "ux-qa": "roboco-agent-ux", # Uses same as dev for now
"ux-pm": "roboco-agent-pm", "ux-pm": "roboco-agent-pm",
"ux-doc": "roboco-agent-doc", "ux-doc": "roboco-agent-doc",
@@ -734,7 +735,8 @@ class AgentOrchestrator:
"be-dev-2": "be-dev", "be-dev-2": "be-dev",
"fe-dev-1": "fe-dev", "fe-dev-1": "fe-dev",
"fe-dev-2": "fe-dev", "fe-dev-2": "fe-dev",
"ux-dev": "ux-dev", "ux-dev-1": "ux-dev",
"ux-dev-2": "ux-dev",
"be-qa": "be-qa", "be-qa": "be-qa",
"fe-qa": "fe-qa", "fe-qa": "fe-qa",
"ux-qa": "ux-qa", "ux-qa": "ux-qa",
@@ -1102,10 +1104,7 @@ Start by:
# Build candidate list based on role # Build candidate list based on role
if role == "dev": if role == "dev":
if prefix == "ux": candidates = [f"{prefix}-dev-1", f"{prefix}-dev-2"]
candidates = ["ux-dev"]
else:
candidates = [f"{prefix}-dev-1", f"{prefix}-dev-2"]
elif role == "qa": elif role == "qa":
candidates = [f"{prefix}-qa"] candidates = [f"{prefix}-qa"]
elif role == "doc": elif role == "doc":
@@ -1375,9 +1374,9 @@ You do NOT assign to developers directly - Cell PMs manage their teams.
- Backend work be-pm (who manages be-dev-1, be-dev-2) - Backend work be-pm (who manages be-dev-1, be-dev-2)
- Frontend work fe-pm (who manages fe-dev-1, fe-dev-2) - Frontend work fe-pm (who manages fe-dev-1, fe-dev-2)
- UX/UI work ux-pm (who manages ux-dev) - UX/UI work ux-pm (who manages ux-dev-1, ux-dev-2)
🚨 NEVER assign to be-dev-1, fe-dev-1, ux-dev directly. ONLY to Cell PMs. 🚨 NEVER assign to be-dev-1, fe-dev-1, ux-dev-1, ux-dev-2 directly. ONLY to Cell PMs.
== WHEN TO WORK ON IT YOURSELF == == WHEN TO WORK ON IT YOURSELF ==
@@ -1445,7 +1444,7 @@ Start now: roboco_task_get("{task_id}")
dev_map = { dev_map = {
"backend": ("be-dev-1", "be-dev-2"), "backend": ("be-dev-1", "be-dev-2"),
"frontend": ("fe-dev-1", "fe-dev-2"), "frontend": ("fe-dev-1", "fe-dev-2"),
"ux_ui": ("ux-dev",), "ux_ui": ("ux-dev-1", "ux-dev-2"),
} }
devs = dev_map.get(team, ("be-dev-1",)) devs = dev_map.get(team, ("be-dev-1",))
primary_dev = devs[0] primary_dev = devs[0]
+16 -7
View File
@@ -118,10 +118,11 @@ AGENT_UUIDS = {
"fe-pm": "00000000-0000-0000-0002-000000000004", "fe-pm": "00000000-0000-0000-0002-000000000004",
"fe-doc": "00000000-0000-0000-0002-000000000005", "fe-doc": "00000000-0000-0000-0002-000000000005",
# UX/UI Cell # UX/UI Cell
"ux-dev": "00000000-0000-0000-0003-000000000001", "ux-dev-1": "00000000-0000-0000-0003-000000000001",
"ux-qa": "00000000-0000-0000-0003-000000000002", "ux-dev-2": "00000000-0000-0000-0003-000000000002",
"ux-pm": "00000000-0000-0000-0003-000000000003", "ux-qa": "00000000-0000-0000-0003-000000000003",
"ux-doc": "00000000-0000-0000-0003-000000000004", "ux-pm": "00000000-0000-0000-0003-000000000004",
"ux-doc": "00000000-0000-0000-0003-000000000005",
# Board / Management # Board / Management
"main-pm": "00000000-0000-0000-0004-000000000001", "main-pm": "00000000-0000-0000-0004-000000000001",
"product-owner": "00000000-0000-0000-0004-000000000002", "product-owner": "00000000-0000-0000-0004-000000000002",
@@ -295,9 +296,17 @@ CHANNEL_MEMBERSHIPS = {
# Cell channels - cell members + CEO # Cell channels - cell members + CEO
"backend-cell": ["be-dev-1", "be-dev-2", "be-qa", "be-pm", "be-doc", "ceo"], "backend-cell": ["be-dev-1", "be-dev-2", "be-qa", "be-pm", "be-doc", "ceo"],
"frontend-cell": ["fe-dev-1", "fe-dev-2", "fe-qa", "fe-pm", "fe-doc", "ceo"], "frontend-cell": ["fe-dev-1", "fe-dev-2", "fe-qa", "fe-pm", "fe-doc", "ceo"],
"uxui-cell": ["ux-dev", "ux-qa", "ux-pm", "ux-doc", "ceo"], "uxui-cell": ["ux-dev-1", "ux-dev-2", "ux-qa", "ux-pm", "ux-doc", "ceo"],
# Role channels + CEO # Role channels + CEO
"dev-all": ["be-dev-1", "be-dev-2", "fe-dev-1", "fe-dev-2", "ux-dev", "ceo"], "dev-all": [
"be-dev-1",
"be-dev-2",
"fe-dev-1",
"fe-dev-2",
"ux-dev-1",
"ux-dev-2",
"ceo",
],
"qa-all": ["be-qa", "fe-qa", "ux-qa", "ceo"], "qa-all": ["be-qa", "fe-qa", "ux-qa", "ceo"],
"pm-all": ["be-pm", "fe-pm", "ux-pm", "main-pm", "ceo"], "pm-all": ["be-pm", "fe-pm", "ux-pm", "main-pm", "ceo"],
"doc-all": ["be-doc", "fe-doc", "ux-doc", "ceo"], "doc-all": ["be-doc", "fe-doc", "ux-doc", "ceo"],
@@ -408,7 +417,7 @@ Check `roboco_task_scan(team="frontend")` for pending frontend tasks.
"content": """Welcome to the UX/UI Cell channel! "content": """Welcome to the UX/UI Cell channel!
**Team:** **Team:**
- ux-dev: UX/UI Developer - ux-dev-1, ux-dev-2: UX/UI Developers
- ux-qa: UX/UI QA - ux-qa: UX/UI QA
- ux-pm: UX/UI PM (me) - ux-pm: UX/UI PM (me)
- ux-doc: UX/UI Documenter - ux-doc: UX/UI Documenter
+63 -4
View File
@@ -159,6 +159,21 @@ class BaseIndexPlugin(ABC):
}, },
} }
def _build_piragi_config_no_embed(self) -> dict[str, Any]:
"""
Build piragi config with dummy embedding URL.
This prevents piragi from loading its own SentenceTransformer model
during initialization. We'll replace the embedder with our shared
instance immediately after creation.
"""
config = self._build_piragi_config()
# Set a dummy base_url to prevent local model loading
# EmbeddingGenerator checks: if base_url is not None, skip SentenceTransformer
config["embedding"]["base_url"] = "http://dummy-prevents-model-load"
config["embedding"]["api_key"] = "not-needed"
return config
async def initialize(self) -> None: async def initialize(self) -> None:
"""Initialize the index backend.""" """Initialize the index backend."""
if self._initialized: if self._initialized:
@@ -176,20 +191,64 @@ class BaseIndexPlugin(ABC):
model=self.config.embedding_model, model=self.config.embedding_model,
) )
# Create store with correct vector dimension for embedding model
# Piragi's factory defaults to 768 for PostgresStore, but we use
# all-MiniLM-L6-v2 which produces 384-dimensional embeddings
store = self._create_store_with_dimension()
# Use config with dummy embedding URL to prevent model loading
# Piragi's EmbeddingGenerator skips SentenceTransformer if base_url is set
self._ragi = AsyncRagi( self._ragi = AsyncRagi(
[], [],
persist_dir=self.config.persist_dir, persist_dir=self.config.persist_dir,
config=self._build_piragi_config(), config=self._build_piragi_config_no_embed(),
store=self.config.store_url, store=store,
) )
# Replace AsyncRagi's embedder with shared instance # Replace AsyncRagi's dummy embedder with shared instance
# This avoids loading the model 9 times (saves ~24s startup) # This is the key optimization: one model load for all 9 plugins
self._ragi._sync.embedder = shared_embedder self._ragi._sync.embedder = shared_embedder
self._initialized = True self._initialized = True
logger.info(f"{self.index_type.value} index plugin initialized") logger.info(f"{self.index_type.value} index plugin initialized")
def _create_store_with_dimension(self) -> Any:
"""
Create vector store with correct dimension for embedding model.
Piragi's factory defaults to 768 for PostgresStore, but doesn't
infer dimension from the embedding model. This method fixes that
by creating PostgresStore with the correct dimension.
"""
from roboco.config import settings
store_url = self.config.store_url
if not store_url:
# Use default LanceStore (handles dimension correctly)
return None
# For PostgreSQL, create store with correct dimension
if store_url.startswith("postgres://") or store_url.startswith("postgresql://"):
from piragi.stores.postgres import PostgresStore
# Get dimension from settings (384 for all-MiniLM-L6-v2)
vector_dimension = settings.embedding_dimensions
logger.debug(
"Creating PostgresStore with correct dimension",
vector_dimension=vector_dimension,
embedding_model=self.config.embedding_model,
)
return PostgresStore(
connection_string=store_url,
table_name=f"chunks_{self.index_type.value}",
vector_dimension=vector_dimension,
)
# For other stores, let piragi handle it
return store_url
async def close(self) -> None: async def close(self) -> None:
"""Cleanup resources.""" """Cleanup resources."""
self._ragi = None self._ragi = None
+6 -6
View File
@@ -19,7 +19,7 @@ from uuid import UUID
import structlog import structlog
from roboco.models.optimal import IndexType, SearchResult from roboco.models.optimal import IndexType, QueryContext, SearchResult
logger = structlog.get_logger() logger = structlog.get_logger()
@@ -364,7 +364,7 @@ class ProactiveKnowledgeService:
"list[SearchResult]", "list[SearchResult]",
await self._optimal_service.search( await self._optimal_service.search(
query=query, query=query,
index_types=[IndexType.JOURNALS], context=QueryContext(index_types=[IndexType.JOURNALS]),
top_k=top_k, top_k=top_k,
), ),
) )
@@ -389,7 +389,7 @@ class ProactiveKnowledgeService:
"list[SearchResult]", "list[SearchResult]",
await self._optimal_service.search( await self._optimal_service.search(
query=query, query=query,
index_types=[IndexType.CODE], context=QueryContext(index_types=[IndexType.CODE]),
top_k=top_k, top_k=top_k,
), ),
) )
@@ -414,7 +414,7 @@ class ProactiveKnowledgeService:
"list[SearchResult]", "list[SearchResult]",
await self._optimal_service.search( await self._optimal_service.search(
query=query, query=query,
index_types=[IndexType.DECISIONS], context=QueryContext(index_types=[IndexType.DECISIONS]),
top_k=top_k, top_k=top_k,
), ),
) )
@@ -426,7 +426,7 @@ class ProactiveKnowledgeService:
return cast( return cast(
"list[SearchResult]", "list[SearchResult]",
await self._optimal_service.search_errors( await self._optimal_service.search_errors(
query=query, error_message=query,
top_k=top_k, top_k=top_k,
), ),
) )
@@ -455,7 +455,7 @@ class ProactiveKnowledgeService:
"list[SearchResult]", "list[SearchResult]",
await self._optimal_service.search( await self._optimal_service.search(
query=query, query=query,
index_types=[IndexType.DECISIONS], context=QueryContext(index_types=[IndexType.DECISIONS]),
top_k=top_k, top_k=top_k,
), ),
) )
+32 -2
View File
@@ -353,11 +353,26 @@ class TaskService(BaseService):
return task return task
async def delete(self, task_id: UUID) -> bool: async def delete(self, task_id: UUID) -> bool:
"""Delete a task.""" """Delete a task and all its descendants."""
task = await self.get(task_id) task = await self.get(task_id)
if not task: if not task:
return False return False
# Delete all descendants first (children, grandchildren, etc.)
# Process in reverse order to delete leaves before parents
descendants = await self.get_all_descendants(task_id)
descendants.reverse() # Delete deepest children first
for descendant in descendants:
await self.session.delete(descendant)
if descendants:
self.log.info(
"Cascaded delete to descendants",
task_id=str(task_id),
deleted_count=len(descendants),
)
await self.session.delete(task) await self.session.delete(task)
await self.session.flush() await self.session.flush()
@@ -1100,11 +1115,26 @@ class TaskService(BaseService):
async def cancel( async def cancel(
self, task_id: UUID, agent_role: str = "cell_pm" self, task_id: UUID, agent_role: str = "cell_pm"
) -> TaskTable | None: ) -> TaskTable | None:
"""Cancel a task (PM only).""" """Cancel a task and all its descendants (PM only)."""
task = await self.get(task_id) task = await self.get(task_id)
if not task: if not task:
return None return None
# Cancel all descendants first (children, grandchildren, etc.)
descendants = await self.get_all_descendants(task_id)
cancelled_count = 0
for descendant in descendants:
if descendant.status != TaskStatus.CANCELLED:
descendant.status = TaskStatus.CANCELLED
cancelled_count += 1
if cancelled_count > 0:
self.log.info(
"Cascaded cancel to descendants",
task_id=str(task_id),
cancelled_count=cancelled_count,
)
# Validate transition with PM role requirement # Validate transition with PM role requirement
self._validate_and_set_status(task, TaskStatus.CANCELLED, agent_role) self._validate_and_set_status(task, TaskStatus.CANCELLED, agent_role)
await self.session.flush() await self.session.flush()
+2 -2
View File
@@ -32,7 +32,7 @@ CEO (You)
| `fe-qa` | QA | Frontend | | `fe-qa` | QA | Frontend |
| `fe-doc` | Documenter | Frontend | | `fe-doc` | Documenter | Frontend |
| `ux-pm` | Cell PM | UX/UI | | `ux-pm` | Cell PM | UX/UI |
| `ux-dev` | Developer | UX/UI | | `ux-dev-1`, `ux-dev-2` | Developers | UX/UI |
| `ux-qa` | QA | UX/UI | | `ux-qa` | QA | UX/UI |
| `ux-doc` | Documenter | UX/UI | | `ux-doc` | Documenter | UX/UI |
| `product-owner` | Product Owner | Board | | `product-owner` | Product Owner | Board |
@@ -53,7 +53,7 @@ uv run python -m roboco.cli --spawn \
main-pm \ main-pm \
be-pm be-dev-1 be-dev-2 be-qa be-doc \ be-pm be-dev-1 be-dev-2 be-qa be-doc \
fe-pm fe-dev-1 fe-dev-2 fe-qa fe-doc \ fe-pm fe-dev-1 fe-dev-2 fe-qa fe-doc \
ux-pm ux-dev ux-qa ux-doc \ ux-pm ux-dev-1 ux-dev-2 ux-qa ux-doc \
product-owner head-marketing auditor product-owner head-marketing auditor
``` ```