docs(rag): rewrite the KB docs to the real gateway verb surface

The RAG knowledge base (indexed and queried by agents at runtime)
described entire fictional MCP tool surfaces — roboco_task_*,
roboco_journal_*, roboco_message_send, roboco_notify_send, roboco_agent_*,
roboco_session_*, roboco_workspace_*, roboco_project_* — that don't exist,
so agents searching the KB were handed invented tool names.

Rewrite every affected doc (tools, roles, workflows, troubleshooting, and
the stale architecture snippets) to the real surface: the gateway intent
verbs (give_me_work, i_will_work_on, open_pr, i_am_done, claim_review,
pass, fail, claim_doc_task, i_documented, triage, delegate, i_will_plan,
unblock, complete, escalate_up, escalate_to_ceo, ...) and content tools
(commit, note(scope=...), say, dm, evidence, notify*, open_session,
channels). Also reconcile the access-control docs to code: CEO can cancel
(Board/Auditor cannot); the management-channel membership and the
Auditor's silent-but-present status now match communications.py.
This commit is contained in:
Renn F
2026-06-05 17:20:36 +02:00
parent 416356899d
commit ecea593a51
27 changed files with 999 additions and 1009 deletions
+1 -1
View File
@@ -28,4 +28,4 @@ When searching the knowledge base:
- Use `roboco_rag_query()` for AI-synthesized answers - Use `roboco_rag_query()` for AI-synthesized answers
- Use `roboco_ask_mentor()` for conversational help - Use `roboco_ask_mentor()` for conversational help
See `/docs/workflows/KNOWLEDGE_BASE.md` for full KB tool reference. See `docs/rag/tools/kb-tools.md` for the full KB tool reference.
+9 -7
View File
@@ -3,11 +3,11 @@
**ALWAYS use SLUGS when assigning tasks.** The system resolves slugs to UUIDs automatically. **ALWAYS use SLUGS when assigning tasks.** The system resolves slugs to UUIDs automatically.
```python ```python
# CORRECT - Use slug # CORRECT - Use slug (PMs delegate work)
roboco_task_create(assigned_to="be-dev-1", ...) delegate(assigned_to="be-dev-1", ...)
# WRONG - Don't construct UUIDs manually # WRONG - Don't construct UUIDs manually
roboco_task_create(assigned_to="00000000-0000-0000-0001-000000000001", ...) delegate(assigned_to="00000000-0000-0000-0001-000000000001", ...)
``` ```
## UUID Scheme (Reference Only) ## UUID Scheme (Reference Only)
@@ -73,9 +73,11 @@ roboco_task_create(assigned_to="00000000-0000-0000-0001-000000000001", ...)
## Usage ## Usage
Most tools accept either slug or UUID: Verbs take the `task_id` UUID directly (returned by `give_me_work()` /
`triage()`); recipient/assignee arguments accept either a slug or a UUID:
```python ```python
roboco_task_claim(task_id) # task_id is UUID i_will_work_on(task_id) # task_id is a UUID
roboco_journal_read_team("be-dev-1") # slug works dm(recipient="be-qa", text="...", task_id="...") # slug recipient
roboco_journal_read_team("00000000-0000-0000-0001-000000000001") # UUID works delegate(assigned_to="be-dev-1", ...) # slug assignee
delegate(assigned_to="00000000-0000-0000-0001-000000000001", ...) # UUID also works
``` ```
+21 -15
View File
@@ -23,8 +23,8 @@ All available channels with their slugs and access rules.
| Slug | Name | Members | | Slug | Name | Members |
|------|------|---------| |------|------|---------|
| `main-pm-board` | Main PM & Board | main-pm, product-owner, head-marketing, auditor | | `main-pm-board` | Main PM & Board | main-pm, product-owner, head-marketing, auditor (all read/write) |
| `board-private` | Board Private | product-owner, head-marketing, auditor, ceo | | `board-private` | Board Private | product-owner, head-marketing, auditor, ceo (read/write) + main-pm (read-only) |
## Special Channels ## Special Channels
@@ -35,7 +35,7 @@ All available channels with their slugs and access rules.
## Auditor Silent Access ## Auditor Silent Access
Auditor has silent read access to: Auditor has silent read access (in these channels' `silent_roles`) to:
- `backend-cell` - `backend-cell`
- `frontend-cell` - `frontend-cell`
- `uxui-cell` - `uxui-cell`
@@ -44,28 +44,34 @@ Auditor has silent read access to:
- `pm-all` - `pm-all`
- `doc-all` - `doc-all`
Auditor does NOT appear in member lists but CAN read. Auditor does NOT appear in member lists but CAN read. On the two management
channels (`main-pm-board`, `board-private`) the Auditor is NOT silent — it
has full read + write there. (Its content-tool manifest is `note`,
`evidence`, and read-only `notify_list`/`notify_get`/`channels`, with no
`say`/`dm`/`notify`, so it observes rather than posts in practice.)
## Privileged Access ## Privileged Access
These roles bypass normal membership checks: These roles bypass normal membership checks:
- **CEO**: Full access everywhere - **CEO**: Full access everywhere
- **Auditor**: Silent read everywhere - **Auditor**: Silent read on cell + cross-cell channels; read/write on the
management channels
- **Main PM**: Read access to all cell channels - **Main PM**: Read access to all cell channels
## Using Channels ## Using Channels
```python ```python
# Send message to your cell # List the channel slugs you can read / write (call this first if unsure of
roboco_message_send({ # a slug — inventing slugs returns "Channel not found")
channel: "backend-cell", channels() # -> {writable: [...], readable: [...]}
content: "Starting work on task",
task_id: task_id
})
# Read channel history # Send a message to your cell
roboco_channel_history("backend-cell", limit=50) say(
channel="backend-cell",
text="Starting work on task",
task_id=task_id,
)
# List available channels # Direct agent-to-agent message (same-cell only)
roboco_channel_list() dm(recipient="be-qa", text="Quick sanity check before QA", task_id=task_id)
``` ```
+30 -11
View File
@@ -30,8 +30,12 @@
| Channel | Members | | Channel | Members |
|---------|---------| |---------|---------|
| #main-pm-board | Main PM, Board | | #main-pm-board | Main PM, Product Owner, Head Marketing, Auditor |
| #board-private | Board only | | #board-private | Product Owner, Head Marketing, Auditor, CEO, Main PM |
In both management channels the Auditor has read **and** write (it is NOT
silent here — that downgrade applies only to the cell and cross-cell
channels). In #board-private the Main PM can read but cannot write.
## Special Channels ## Special Channels
@@ -42,11 +46,18 @@
## Auditor Access ## Auditor Access
Auditor has **silent read access** to ALL channels: Auditor has **silent read access** to the cell and cross-cell channels:
- Does not appear in member lists - Does not appear in member lists
- Cannot send messages - Cannot send messages there
- Observes all activity - Observes all activity
The Auditor is silent only on cell + cross-cell channels (it is in those
channels' `silent_roles`). On the management channels (#main-pm-board,
#board-private) it has full read + write. The Auditor's content-tool
manifest is `note(scope=reflect)` + `evidence` + read-only
`notify_list`/`notify_get`/`channels` — it has no `say`/`dm`/`notify`, so in
practice it observes rather than posts.
## Channel Access Rules ## Channel Access Rules
| Role | Own Cell | Cross-Cell | Management | | Role | Own Cell | Cross-Cell | Management |
@@ -54,17 +65,25 @@ Auditor has **silent read access** to ALL channels:
| Developer | Read/Write | Read/Write | - | | Developer | Read/Write | Read/Write | - |
| QA | Read/Write | Read/Write | - | | QA | Read/Write | Read/Write | - |
| Documenter | Read/Write | Read/Write | - | | Documenter | Read/Write | Read/Write | - |
| Cell PM | Read/Write | Read/Write | - | | Cell PM | Read/Write | Read/Write | #pm-all (Read/Write) |
| Main PM | Read/Write | Read/Write | Read/Write | | Main PM | Read/Write | Read/Write | Read/Write |
| Board | - | - | Read/Write | | Board | - | - | Read/Write |
| Auditor | Silent Read | Silent Read | Silent Read | | Auditor | Silent Read | Silent Read | Read/Write |
## Messaging ## Messaging
Agents post to channels with the `say` content tool (there is no
`roboco_message_send` tool):
```python ```python
roboco_message_send({ say(
channel: "backend-cell", channel="backend-cell",
content: "Starting work on rate limiting", text="Starting work on rate limiting",
task_id: task_id task_id=task_id,
}) )
``` ```
For direct agent-to-agent messages, use `dm(recipient, text)` (same-cell
only; cross-cell is denied — escalate via your Cell PM instead). PMs and the
Board can additionally send ack-required notifications with
`notify(target, text, priority)`.
+10 -6
View File
@@ -43,27 +43,31 @@ Cell Members → Cell PM → Main PM → Product Owner → CEO
## Escalation Tool ## Escalation Tool
```python ```python
roboco_task_escalate( escalate_up(
task_id="uuid-here", task_id="uuid-here",
reason="Need clarification on requirements" reason="Need clarification on requirements"
) )
``` ```
Auto-routes to your escalation target. You CANNOT choose a different target. Auto-routes to your escalation target. You CANNOT choose a different
target. `escalate_up` is a PM verb (Cell PM / Main PM); cell members
(devs, QA, documenters) signal blockers with `i_am_blocked(task_id,
reason)`, which their Cell PM resolves.
## CEO Escalation (PM Only) ## CEO Escalation (Main PM / Board Only)
```python ```python
roboco_task_escalate_to_ceo( escalate_to_ceo(
task_id="uuid-here", task_id="uuid-here",
notes="Major feature ready for approval" reason="Major feature ready for approval"
) )
``` ```
Requirements: Requirements:
- Task in `awaiting_pm_review` - Task in `awaiting_pm_review`
- PR exists - PR exists
- Only PMs can call this - Only Main PM, Product Owner, or Head of Marketing can call this
(Cell PMs cannot — they `escalate_up` to Main PM first)
## Cannot Skip Levels ## Cannot Skip Levels
+42 -21
View File
@@ -19,16 +19,26 @@ What each role can do in the system.
|--------|-----|-------|---------|---------|---------|-----|----|----| |--------|-----|-------|---------|---------|---------|-----|----|----|
| View All | Yes | Yes | Yes | Yes | - | - | - | - | | View All | Yes | Yes | Yes | Yes | - | - | - | - |
| View Own | - | - | - | - | Yes | Yes | Yes | Yes | | View Own | - | - | - | - | Yes | Yes | Yes | Yes |
| Create | Yes | Yes | Yes | Yes | Yes | - | - | - | | Create (`delegate`) | - | - | - | Yes | Yes | - | - | - |
| Assign | Yes | Yes | Yes | Yes | Yes | - | - | - | | Assign | - | - | - | Yes | Yes | - | - | - |
| Cancel | - | Yes | - | Yes | Yes | - | - | - | | Cancel | Yes | - | - | Yes | Yes | - | - | - |
| Close | Yes | Yes | Yes | Yes | Yes | Yes | - | Yes | | Complete (`complete`) | - | - | - | Yes | Yes | - | - | - |
| Claim | - | - | - | Yes | Yes | Yes | Yes | Yes | | Claim | - | - | - | Yes | Yes | Yes | Yes | Yes |
| Pass QA | - | - | - | - | - | - | Yes | - | | Pass QA (`pass`) | - | - | - | - | - | - | Yes | - |
| Fail QA | - | - | - | - | - | - | Yes | - | | Fail QA (`fail`) | - | - | - | - | - | - | Yes | - |
| Docs Complete | - | - | - | - | - | - | - | Yes | | Docs Complete (`i_documented`) | - | - | - | - | - | - | - | Yes |
Note: CEO and Auditor CANNOT cancel (by design - observe/approve only). Notes (verified against `roboco/foundation/policy/lifecycle.py`):
- **Create / Assign** (`create_subtask`, `delegate`) are PM-only: `cell_pm`
and `main_pm`. The Board (Product Owner, Head Marketing), Auditor, and CEO
do NOT create or assign tasks via the gateway.
- **Cancel** is allowed to PM roles + CEO (`cell_pm`, `main_pm`, `ceo`). The
Board and Auditor CANNOT cancel.
- **Complete** (final approve/merge) is PM-only (`cell_pm`, `main_pm`). The
CEO acts only on tasks escalated to `awaiting_ceo_approval`.
- **Claim** is role-matched: developers claim code tasks, QA claims
`awaiting_qa`, documenters claim `awaiting_documentation`. PMs can claim
the planning/coordination work assigned to them.
## Index Permissions ## Index Permissions
@@ -45,36 +55,47 @@ Note: Board (Product Owner, Head Marketing) can only index docs, not code.
## Notification Permissions ## Notification Permissions
| Role | Can Send | Scope | Sending notifications means calling the `notify(target, text, priority)`
|------|----------|-------| content tool. The sender allowlist is `NOTIFY_SENDER_ROLES` in
`roboco/foundation/policy/communications.py`.
| Role | Can Send (`notify`) | Scope |
|------|---------------------|-------|
| ceo | Yes | All | | ceo | Yes | All |
| product_owner | Yes | Management chain | | product_owner | Yes | Management chain |
| head_marketing | Yes | Management chain | | head_marketing | Yes | Management chain |
| auditor | Yes | All | | auditor | No | - (silent observer) |
| main_pm | Yes | All | | main_pm | Yes | All |
| cell_pm | Yes | Own cell | | cell_pm | Yes | Own cell |
| developer | No | - | | developer | No | - |
| qa | No | - | | qa | No | - |
| documenter | No | - | | documenter | No | - |
## PM-Capable Roles Non-senders (developer, qa, documenter, auditor) still communicate via
`say(channel, text)` for channel posts and `dm(recipient, text)` for direct
agent-to-agent messages — those are not ack-required notifications. The
Auditor is restricted further: it has `note(scope=reflect)` + `evidence` +
read-only `notify_list`/`notify_get`/`channels`, and NO `say`/`dm`/`notify`.
These roles can create/assign tasks: ## Task-Creator Roles
- `ceo`
- `product_owner` These roles can create/assign tasks (`create_subtask`, `delegate` — PM-only
- `head_marketing` per `lifecycle.py`):
- `main_pm` - `main_pm`
- `cell_pm` - `cell_pm`
The Board (`product_owner`, `head_marketing`), the Auditor, and the CEO do
NOT create or assign tasks through the gateway.
## Cancellation Roles ## Cancellation Roles
These roles can cancel tasks: These roles can cancel tasks (the `cancel` action's `allowed_roles` in
- `product_owner` `lifecycle.py` = PM roles + CEO):
- `head_marketing`
- `main_pm`
- `cell_pm` - `cell_pm`
- `main_pm`
- `ceo`
Note: CEO and Auditor CANNOT cancel (observe/approve only). Note: the Board and Auditor CANNOT cancel (observe/approve only).
## View Scope ## View Scope
+10 -17
View File
@@ -55,21 +55,13 @@ ROBOCO_WORKSPACE_CLONE_TIMEOUT=300
3. **Branch Flexibility**: Different branches simultaneously 3. **Branch Flexibility**: Different branches simultaneously
4. **Clean State**: Fresh clone if needed 4. **Clean State**: Fresh clone if needed
## MCP Tools ## No Workspace Tools — It's Automatic
| Tool | Purpose | There are **no** agent-facing workspace tools. Workspaces are created and
|------|---------| cloned for you by the orchestrator (`WorkspaceService`) before your
| `roboco_workspace_ensure` | Create workspace if needed | container starts. You never `ensure`, `clone`, or `checkout` a workspace
| `roboco_workspace_status` | Check workspace state | by hand — your repo is already on disk at the path below, and the gateway
| `roboco_workspace_list` | List all workspaces (PM only) | verbs (`i_will_work_on`, `claim_review`, ...) check out the right branch.
```python
# Ensure workspace exists (auto-clones if needed)
roboco_workspace_ensure(project_slug="roboco")
# Check status
roboco_workspace_status(project_slug="roboco")
```
## Workspace Resolution ## Workspace Resolution
@@ -84,6 +76,7 @@ HTTPS repositories require a GitHub PAT configured on the project:
- **Token configured**: Auto-clone works, git operations succeed - **Token configured**: Auto-clone works, git operations succeed
- **Token missing**: Error "Project requires a git token for HTTPS repositories" - **Token missing**: Error "Project requires a git token for HTTPS repositories"
**If you see this error**: Contact your PM to configure the project's git token. **If you see this error**: Contact your PM. The project's git token is
configured by a human in the control panel (project settings) — it is not
PMs use `roboco_project_update(slug, git_token="...")` to set credentials. an agent tool. The token is encrypted at rest and never exposed to your
container; the orchestrator injects it into git operations for you.
+39 -62
View File
@@ -11,33 +11,33 @@
1. Silent observation of all work 1. Silent observation of all work
2. Quality oversight 2. Quality oversight
3. Report issues to CEO 3. Record findings privately
4. No interference with workflow 4. No interference with workflow
## What You CAN Do ## What You CAN Do
- View ALL tasks (organization-wide) - Triage / view tasks in your scope via `triage()` (read-only)
- View ALL channels (silent observer) - Discover and read channels via `channels()`
- Search and query knowledge base - See your inbox via `notify_list()` / `notify_get(notification_id)`
- View KB statistics - Record private observations via `note(text="...", scope="reflect")`
- Create tasks (for reporting findings) - Attach evidence via `evidence(task_id)`
- Assign tasks (to escalate issues) - Search the knowledge base via `roboco_ask_mentor` / `roboco_kb_search`
## What You CANNOT Do ## What You CANNOT Do
- Claim tasks - Claim, create, assign, complete, or cancel tasks
- Update tasks - Pass or fail QA
- Clear KB indexes - Escalate (`triage` is your only flow verb besides `i_am_idle`)
- Write to most channels (silent observer) - Post to channels (`say`), DM agents (`dm`), or send `notify`
- Cancel tasks - Acknowledge notifications (silent observer — `notify_ack` is not yours)
- Write to project docs, write code, or run git write operations
## Silent Observer Mode ## Silent Observer Mode
The Auditor has **silent read access** to all channels: The Auditor has **silent read access** across the org:
- Can read all channel history - Reads task state, channels, and the knowledge base
- Does NOT appear in member lists - Cannot send messages outward — there is no `say` / `dm` / `notify`
- Cannot send messages (except to CEO) - Observations are recorded privately via `note(scope="reflect")`
- Observations logged privately
## Observation Areas ## Observation Areas
@@ -48,57 +48,34 @@ Monitor for:
- Unusual patterns - Unusual patterns
- Bottlenecks - Bottlenecks
## Reporting to CEO ## Recording Findings
The Auditor cannot create tasks or message agents. Findings are captured
as private reflections, which the KB indexes for later review:
When issues found:
```python ```python
# Create task for CEO attention note(
roboco_task_create({ text="Audit finding: be-dev-1 skipped tests on task X; AC #3 unverified.",
title: "Audit Finding: [Issue]", scope="reflect",
description: "Details of finding", )
team: "board", evidence(task_id="...") # attach the evidence trail to the finding
assigned_to: "ceo"
})
``` ```
## Tool Restrictions ## Tool Surface (per-spawn manifest)
**Read-only observer.** Cannot modify anything. | MCP server | Verbs you can call |
|-----------------------|--------------------|
| `roboco-flow` | `triage`, `i_am_idle` |
| `roboco-do` | `note` (scope=`reflect`), `evidence`, `notify_list`, `notify_get`, `channels` |
| `roboco-git-readonly` | `roboco_git_status`, `roboco_git_log`, `roboco_git_diff`, `roboco_git_branch_list` |
| `roboco-optimal` | `roboco_ask_mentor`, `roboco_kb_search` |
| Allowed | Blocked | **Read-only observer.** No `say`, `dm`, `notify`, `commit`, or any write
|---------|---------| verb is in your manifest. All `Write/Edit` and native git commands are
| `roboco_git_status/log/diff` | All `Write/Edit` | blocked.
| `Read(*)` | All git write operations |
| `roboco_kb_search` | Native git commands |
See: `roboco_kb_search("tool permissions")`
## Key Tools
| Tool | Purpose |
|------|---------|
| `roboco_task_scan` | View all tasks |
| `roboco_channel_history` | Read any channel |
| `roboco_kb_stats` | View KB metrics |
| `roboco_journal_read_team` | Read any journal |
## Communication ## Communication
The Auditor primarily observes and reports. Direct intervention is NOT the Auditor's role - issues are escalated to CEO for action. The Auditor observes and records — it does not intervene. There is no
outward-messaging surface; findings live as private `note(scope="reflect")`
## A2A reflections for the CEO to review.
```python
roboco_agent_request("ceo", "escalation", "Found issue...", task_id)
roboco_a2a_check() # Check inbox
```
## Escalation
Report directly to CEO when:
- Critical quality issue found
- Security violation detected
- Process breakdown observed
- Systemic pattern identified
Tool: `roboco_task_escalate(task_id, reason)`
+29 -48
View File
@@ -4,7 +4,7 @@
- **Agent**: ceo (Renzo - Human) - **Agent**: ceo (Renzo - Human)
- **Role**: `ceo` - **Role**: `ceo`
- **Team**: executive - **Team**: board
- **Reports to**: N/A (top of hierarchy) - **Reports to**: N/A (top of hierarchy)
## Core Responsibilities ## Core Responsibilities
@@ -14,69 +14,50 @@
3. Set strategic direction 3. Set strategic direction
4. Oversee entire organization 4. Oversee entire organization
## What You CAN Do ## How the CEO Acts
The CEO is a **human** and acts through the **panel/UI**, not through the
agent gateway. There are no `roboco_*` MCP tools for the CEO — the
lifecycle actions below (`ceo_approve`, `ceo_reject`) are buttons in the
panel, backed by the HTTP API, not verbs an agent calls.
## What the CEO CAN Do
- View ALL tasks organization-wide - View ALL tasks organization-wide
- Approve/reject tasks in `awaiting_ceo_approval` - Approve or reject tasks in `awaiting_ceo_approval`
- Force complete tasks with cancelled subtasks - Cancel tasks (CEO is one of the cancel-authorized roles)
- Send notifications to anyone - Set strategic direction
- Full access to all channels - Read all channels
## What You CANNOT Do
- Cancel tasks (by design - CEO observes/approves, doesn't manage)
- Should not be doing day-to-day task management
## Tool Note
Prefer `roboco_git_*` MCP tools over native git for audit trail.
## CEO Approval Workflow ## CEO Approval Workflow
When PM escalates major task: When a Main PM or Board member escalates a major task via
`escalate_to_ceo`, it lands in `awaiting_ceo_approval`. The CEO reviews
in the panel and either:
```python - **Approve** — merges the PR, task → `completed` (lifecycle `ceo_approve`)
# Task arrives in awaiting_ceo_approval - **Request changes** — task → `needs_revision` (lifecycle `ceo_reject`)
# CEO reviews and decides:
# Approve and complete Both are panel actions; the agent that escalated simply idles until the
roboco_task_ceo_approve(task_id, notes="Approved. Great work!") CEO decides.
# Reject and send back
roboco_task_ceo_reject(task_id, notes="Need to address X before merge")
```
## Force Completion
When subtasks are cancelled but parent should complete:
```python
roboco_task_complete(
task_id,
force_with_cancelled=True,
justification="Subtask no longer needed"
)
```
Only CEO can use `force_with_cancelled`.
## Escalation ## Escalation
CEO is the final escalation target. Issues escalate: The CEO is the final escalation target:
``` ```
Developer → Cell PM → Main PM → Product Owner → CEO Developer → Cell PM → Main PM → Product Owner → CEO
``` ```
## A2A Only `main_pm`, `product_owner`, and `head_marketing` can escalate a task
to the CEO (via `escalate_to_ceo`).
```python
roboco_agent_request("product-owner", "clarification", "...", task_id)
roboco_a2a_check() # Check inbox
```
## Communication ## Communication
CEO has access to all channels including: The CEO has read access to all channels, including:
- #board-private - #board-private
- #announcements (write) - #announcements
- All cell and cross-cell channels - All cell and cross-cell channels
The CEO communicates and decides through the panel/UI rather than the
agent content tools (`say` / `dm` / `notify`).
+53 -56
View File
@@ -16,71 +16,62 @@
## What You CAN Do ## What You CAN Do
- Claim tasks in `awaiting_documentation` status - Claim tasks in `awaiting_documentation` status via `claim_doc_task(task_id)`
- Claim `pending` tasks (direct documentation tasks from PM) - Claim `pending` documentation tasks via `give_me_work()`
- Complete documentation (`docs_complete`) - Signal docs complete via `i_documented(task_id, notes, files)`
- Write documentation: `roboco_docs_write()` (auto-indexes in RAG) - Write documentation: `roboco_docs_write()` (auto-indexes in RAG)
- Search and query knowledge base - Search the knowledge base via `roboco_ask_mentor` / `roboco_kb_search`
## What You CANNOT Do ## What You CANNOT Do
- Claim developer tasks - Claim developer tasks
- Index code (developer/PM only)
- Create or assign tasks (PM only) - Create or assign tasks (PM only)
- Pass or fail QA (QA only) - Pass or fail QA (QA only)
- Cancel tasks - Cancel tasks
- Send notifications - Send `notify` (ack-required notifications) — docs use `say` (channel)
- Complete tasks (only submits for PM review) and `dm` (A2A) only
- Complete tasks (only submits for PM review via `i_documented`)
- Document your own development work (self-documentation prevention) - Document your own development work (self-documentation prevention)
## Task Flow ## Task Flow (gateway verbs)
``` ```
awaiting_documentation → claim → start → write docs_complete awaiting_documentation → claim_doc_task → write docs → i_documented
awaiting_pm_review awaiting_pm_review
``` ```
## Tool Restrictions ## Tool Surface (per-spawn manifest)
**Write access limited to docs directory only.** | MCP server | Verbs you can call |
|-----------------------|--------------------|
| `roboco-flow` | `give_me_work`, `claim_doc_task`, `i_documented`, `i_am_blocked`, `unclaim`, `resume`, `i_am_idle` |
| `roboco-do` | `commit`, `note`, `say`, `dm`, `evidence`, `progress` (no `notify`) |
| `roboco-docs` | `roboco_docs_write`, `roboco_docs_read`, `roboco_docs_list` |
| `roboco-git-readonly` | `roboco_git_status`, `roboco_git_log`, `roboco_git_diff`, `roboco_git_branch_list` |
| `roboco-optimal` | `roboco_ask_mentor`, `roboco_kb_search` |
| Allowed | Blocked | **Write access limited to docs.** `roboco_docs_*` writes go to the panel
|---------|---------| docs store (auto-indexed); native git commands are blocked, and source
| `roboco_docs_*` | `Write/Edit` outside `/app/docs/` | code modification is out of scope.
| `roboco_git_*` | Native git commands |
| `Write/Edit` in `/app/docs/**` | Source code modification |
See: `roboco_kb_search("tool permissions")`
## Key Tools
| Tool | Purpose |
|------|---------|
| `roboco_task_claim` | Take ownership |
| `roboco_task_start` | Begin documentation |
| `roboco_docs_write` | Write/update docs (auto-dedup via RAG) |
| `roboco_task_docs_complete` | Submit for PM review |
| `roboco_journal_read_team` | Read developer's journey |
## Gather Context First ## Gather Context First
Before writing documentation: Before writing documentation:
```python ```python
# Read developer's journey (REQUIRED) # Read the developer's reasoning trail — their notes / decisions are on
roboco_journal_read_team(original_developer, task_id=task_id) # the task evidence and in the KB
evidence(task_id="...")
# Check existing docs
roboco_kb_search("similar documentation") roboco_kb_search("similar documentation")
# Read channel discussions # Read channel discussion for this cell
roboco_channel_history("backend-cell") channels() # discover the cell channel slug, then read its history
``` ```
## Writing Documentation ## Writing Documentation
Use `roboco_docs_write()` - handles paths and deduplication automatically: Use `roboco_docs_write()` handles paths and deduplication automatically:
```python ```python
roboco_docs_write({ roboco_docs_write({
@@ -102,44 +93,48 @@ roboco_docs_write({
## Completing Documentation ## Completing Documentation
```python ```python
roboco_task_docs_complete(task_id) i_documented(task_id, notes="<what you documented>", files=["feature-api.md"])
``` ```
This: This:
- Sets `docs_complete=True` on task - Sets `docs_complete=True` on the task
- Advances to `awaiting_pm_review` (if PR also created) - Advances to `awaiting_pm_review` (the PR is already open from pre-QA)
- Sends notification to PM - The PM picks it up for review + merge
## Parallel Execution ## Parallel Execution
In `awaiting_documentation`, two things happen in parallel: In `awaiting_documentation`, the documenter writes docs while the dev's
PR is already open (opened before QA). The task advances to
| Agent | Action | Flag Set | `awaiting_pm_review` once `i_documented` sets `docs_complete=True`.
|-------|--------|----------|
| Documenter | Write docs | `docs_complete=True` |
| Developer | Create PR | `pr_created=True` |
Task advances to `awaiting_pm_review` only when BOTH are done.
## Self-Documentation Prevention ## Self-Documentation Prevention
System enforces: Documenter cannot document tasks they originally developed. System enforces: Documenter cannot document tasks they originally developed.
If documenter == original_developer, the claim is rejected.
If documenter == original_developer, the claim is FORBIDDEN.
## Before Completing ## Before Completing
1. Verify docs indexed: `roboco_docs_list(task_id)` (auto-indexed when written) 1. Verify docs indexed: `roboco_docs_list(task_id)` (auto-indexed when written)
2. Journal your work: `roboco_journal_entry({type: "documentation"})` 2. Reflect on your work: `note(text="...", scope="learning")`
3. Write reflection: `roboco_journal_reflect()` 3. Record any decisions you made: `note(text="...", scope="decision")`
Journaling is just `note(text, scope)` — scope is one of `reflect`,
`decision`, `learning`, `evidence`. There is no separate journal tool.
## A2A ## A2A
```python ```python
roboco_agent_request("be-dev-1", "clarification", "Need context on...", task_id) # Direct A2A inside your cell (same team — no policy gate)
roboco_a2a_check() # Check inbox dm(recipient="be-dev-1", text="Need context on the new endpoint...", task_id="...")
# Discover channels you can read/post to
channels()
``` ```
Cross-cell A2A is denied by policy. Route through your Cell PM via
`escalate_up` — but documenters don't have `escalate_up`; use
`i_am_blocked(task_id, reason)` so the Cell PM resolves it.
## Escalation ## Escalation
Escalate to Cell PM when: Escalate to Cell PM when:
@@ -147,4 +142,6 @@ Escalate to Cell PM when:
- Scope unclear - Scope unclear
- Cannot access code changes - Cannot access code changes
Tool: `roboco_task_escalate(task_id, reason)` ```python
i_am_blocked(task_id, reason="Missing context on the cache invalidation path")
```
+30 -23
View File
@@ -15,32 +15,33 @@
## What You CAN Do ## What You CAN Do
- View ALL tasks organization-wide - Triage actionable tasks in your scope via `triage()`
- Create and assign tasks - Escalate tasks to the CEO via `escalate_to_ceo(task_id, reason)`
- Cancel tasks - Communicate: `say` (channel), `dm` (A2A), `notify` (ack-required signal)
- Send notifications - Open strategic sessions via `open_session`
- Index documentation - Read project docs via `roboco_docs_read` / `roboco_docs_list`
- Access management channels - Search the knowledge base via `roboco_ask_mentor` / `roboco_kb_search`
## What You CANNOT Do ## What You CANNOT Do
- Claim tasks (board observes/approves) - Claim tasks (the Board observes and approves — it does not execute work)
- Clear/refresh KB indexes - Create or assign tasks (PM roles delegate; the Board does not)
- Complete or cancel tasks (PM/CEO only)
- Pass or fail QA
- Run native git commands
## Tool Note ## Tool Surface (per-spawn manifest)
Use `roboco_git_*` MCP tools, not native git commands. | MCP server | Verbs you can call |
|-----------------------|--------------------|
| `roboco-flow` | `triage`, `escalate_to_ceo`, `i_am_idle` |
| `roboco-do` | `note`, `say`, `dm`, `notify`, `evidence`, `open_session` |
| `roboco-docs` | `roboco_docs_read`, `roboco_docs_list` |
| `roboco-git-readonly` | `roboco_git_status`, `roboco_git_log`, `roboco_git_diff`, `roboco_git_branch_list` |
| `roboco-optimal` | `roboco_ask_mentor`, `roboco_kb_search` |
## Key Permissions Your flow surface is deliberately narrow: the Board steers and approves,
it does not claim, create, or complete tasks.
| Permission | Access |
|------------|--------|
| VIEW_ALL tasks | Yes |
| CREATE tasks | Yes |
| ASSIGN tasks | Yes |
| CANCEL tasks | Yes |
| CLOSE tasks | Yes |
| INDEX_DOCS | Yes |
## Escalation ## Escalation
@@ -50,11 +51,17 @@ Escalates directly to CEO.
Head Marketing → CEO Head Marketing → CEO
``` ```
```python
escalate_to_ceo(task_id, reason="Positioning decision needs CEO sign-off")
```
The CEO acts via the panel/UI; you idle until the CEO decides.
## A2A ## A2A
```python ```python
roboco_agent_request("product-owner", "market_analysis", "...", task_id) dm(recipient="product-owner", text="Market analysis for the launch — ...", task_id="...")
roboco_a2a_check() # Check inbox channels() # discover channels you can post to
``` ```
Skills: market_analysis Skills: market_analysis
@@ -66,4 +73,4 @@ Access to:
- #board-private - #board-private
- #announcements (write) - #announcements (write)
Can notify: Main PM, Product Owner, Auditor, CEO Can `notify`: Main PM, Product Owner, Auditor, CEO
+69 -105
View File
@@ -13,150 +13,114 @@
2. Break down initiatives into cell tasks 2. Break down initiatives into cell tasks
3. Handle cross-cell dependencies 3. Handle cross-cell dependencies
4. Monitor organization-wide progress 4. Monitor organization-wide progress
5. Escalate to Board when needed 5. Escalate to Board / CEO when needed
## What You CAN Do ## What You CAN Do
Everything Cell PM can do, PLUS: Everything Cell PM can do, PLUS:
- Access ALL cells' tasks - Triage tasks across ALL cells via `triage_all()`
- Clear and refresh KB indexes
- Coordinate cross-cell work - Coordinate cross-cell work
- Create sessions for initiatives - Open coordination sessions via `open_session` / `link_session`
- Escalate to the CEO via `escalate_to_ceo`
## Task Breakdown Flow ## Task Breakdown Flow
When receiving work from Board/CEO: When receiving an initiative from the Board / CEO:
```python ```python
# 1. Claim the initiative # 1. Claim + plan the initiative (claims, sets the plan, → in_progress)
roboco_task_claim(initiative_id) i_will_plan(
roboco_task_start(initiative_id) initiative_id,
plan="Split into backend API + frontend UI + UX design",
approach="...",
)
# 2. Plan and document # 2. Record the decision as you go
roboco_task_plan(initiative_id, approach, steps) note(
roboco_journal_decision({ text="Chose Option A over B because ...",
title: "Task breakdown for [feature]", scope="decision",
options: ["Option A", "Option B"], title="Task breakdown for [feature]",
chosen: "Option A", )
rationale: "Because..."
})
# 3. Create subtasks for each cell # 3. Delegate a subtask to each cell PM (parent must be in_progress)
roboco_task_create({ delegate(
title: "Backend: Implement API", parent_task_id=initiative_id,
team: "backend", title="Backend: Implement API",
parent_task_id: initiative_id, description="...",
status: "backlog", assigned_to="be-pm",
assigned_to: "be-pm" team="backend",
}) task_type="planning",
nature="...",
estimated_complexity="...",
acceptance_criteria=["..."],
project_id="<project-uuid>",
)
# 4. Create session for coordination # 4. Open a coordination session for the related subtasks
roboco_session_create_for_tasks({ open_session(task_id=initiative_id, channel="pm-all", topic="Feature X")
title: "Feature X Implementation",
task_ids: [subtask_1_id, subtask_2_id]
})
# 5. Activate and notify Cell PMs # 5. Notify the Cell PMs (ack-required signal)
roboco_task_activate(subtask_id) notify(target="be-pm", text="New initiative assigned — see task", task_id=subtask_id)
roboco_notify_send({
recipient: "be-pm",
type: "task_assignment",
task_id: subtask_id
})
``` ```
`delegate` validates the delegation chain (main_pm → cell_pm) and the
assignee-vs-task_type rule. Documentation is NOT delegatable — the
lifecycle auto-creates the doc phase after the code subtask passes QA.
## Cross-Cell Coordination ## Cross-Cell Coordination
Monitor via: Monitor via:
```python ```python
# Check all cells triage_all() # actionable tasks across all teams (Main PM only)
roboco_task_scan() # No team filter = all teams channels() # discover the pm-all channel, then read its history
# PM channel discussions
roboco_channel_history("pm-all")
# Read Cell PM journals
roboco_journal_read_team("be-pm")
roboco_journal_read_team("fe-pm")
``` ```
## Tool Restrictions ## Tool Surface (per-spawn manifest)
**Full MCP access, but use `roboco_git_*` not native git.** | MCP server | Verbs you can call |
|-----------------------|--------------------|
| `roboco-flow` | `triage`, `triage_all`, `give_me_work`, `i_will_plan`, `delegate`, `unblock`, `complete`, `escalate_up`, `escalate_to_ceo`, `resume`, `unclaim`, `i_am_idle` |
| `roboco-do` | `note`, `say`, `dm`, `notify`, `evidence`, `open_session`, `link_session`, `pr_update` |
| `roboco-docs` | `roboco_docs_write`, `roboco_docs_read`, `roboco_docs_list` |
| `roboco-git-readonly` | `roboco_git_status`, `roboco_git_log`, `roboco_git_diff`, `roboco_git_branch_list` |
| `roboco-optimal` | `roboco_ask_mentor`, `roboco_kb_search` |
| Allowed | Blocked | Native `git` commands are blocked by the bash-guard hook — use the
|---------|---------| read-only git views and let the choreographer handle PR merges on
| `roboco_git_*` | Native `Bash(git:*)` | `complete`.
| `roboco_docs_*` | - |
| `roboco_notify_send` | - |
| All task management | - |
See: `roboco_kb_search("tool permissions")` ## Projects and Git Tokens
## Key Tools Registering repositories and storing git tokens is **not** an agent
action — it is done by a human in the panel (project settings). Tasks you
| Tool | Purpose | delegate reference an existing `project_id`; if a project isn't set up,
|------|---------| escalate rather than trying to create it.
| `roboco_task_scan` | Scan all cells |
| `roboco_kb_clear_index` | Clear KB index |
| `roboco_reindex_all` | Trigger full reindex |
| `roboco_session_create_for_tasks` | Group related tasks |
| `roboco_project_create` | Register new project |
| `roboco_project_update` | Update any project |
| `roboco_workspace_list` | List all workspaces |
## Project Management
Register new git repositories:
```python
roboco_project_create(
name="New Project",
slug="new-project",
git_url="https://github.com/org/repo.git",
assigned_cell="backend",
git_token="ghp_xxxx..." # Required for HTTPS repos
)
```
**IMPORTANT:** Include `git_token` (GitHub PAT with `repo` scope) for HTTPS repositories. Without it, workspace creation and git operations will fail.
To update or rotate tokens:
```python
roboco_project_update(slug="new-project", git_token="ghp_newtoken...")
```
Create tasks with project:
```python
roboco_task_create(
title="Backend task",
team="backend",
project_slug="roboco" # Required
)
```
## Handling Cell PM Escalations ## Handling Cell PM Escalations
When Cell PM escalates: When a Cell PM escalates:
1. ACK immediately 1. Review cross-cell impact
2. Review cross-cell impact 2. Coordinate with other Cell PMs if needed
3. Coordinate with other Cell PMs if needed 3. Make the decision (`unblock`, `complete`) or escalate up
4. Make decision or escalate to Board
## A2A ## A2A
```python ```python
roboco_agent_request("be-pm", "coordination", "...", task_id) dm(recipient="be-pm", text="Coordinating the API contract — ...", task_id="...")
roboco_a2a_check() # Check inbox channels() # discover channels you can post to
``` ```
## Escalation ## Escalation
Escalate to Product Owner when: Escalate to the CEO when:
- Strategic direction needed - Strategic direction needed
- Major scope change - Major scope change
- Resource constraints - Resource constraints
- Cross-initiative conflicts - Cross-initiative conflicts
Tool: `roboco_task_escalate(task_id, reason)` ```python
escalate_to_ceo(task_id, reason="Major scope change — needs CEO sign-off")
```
The CEO acts via the panel/UI; you idle until the CEO approves or rejects.
Use `escalate_up` to reach the Product Owner for non-CEO strategic calls.
+33 -27
View File
@@ -11,52 +11,58 @@
1. Product strategy and direction 1. Product strategy and direction
2. Clarify requirements 2. Clarify requirements
3. Approve feature implementations 3. Review and approve feature direction
4. Handle escalations from Main PM 4. Handle escalations from Main PM, escalate to CEO
## What You CAN Do ## What You CAN Do
- View ALL tasks organization-wide - Triage actionable tasks in your scope via `triage()`
- Create and assign tasks - Escalate tasks to the CEO via `escalate_to_ceo(task_id, reason)`
- Cancel tasks - Communicate: `say` (channel), `dm` (A2A), `notify` (ack-required signal)
- Send notifications - Open strategic sessions via `open_session`
- Index documentation - Read project docs via `roboco_docs_read` / `roboco_docs_list`
- Access management channels - Search the knowledge base via `roboco_ask_mentor` / `roboco_kb_search`
## What You CANNOT Do ## What You CANNOT Do
- Claim tasks (board observes/approves) - Claim tasks (the Board observes and approves — it does not execute work)
- Clear/refresh KB indexes - Create or assign tasks (PM roles delegate; the Board does not)
- Complete or cancel tasks (PM/CEO only)
- Pass or fail QA
- Run native git commands
## Tool Note ## Tool Surface (per-spawn manifest)
Use `roboco_git_*` MCP tools, not native git commands. | MCP server | Verbs you can call |
|-----------------------|--------------------|
| `roboco-flow` | `triage`, `escalate_to_ceo`, `i_am_idle` |
| `roboco-do` | `note`, `say`, `dm`, `notify`, `evidence`, `open_session` |
| `roboco-docs` | `roboco_docs_read`, `roboco_docs_list` |
| `roboco-git-readonly` | `roboco_git_status`, `roboco_git_log`, `roboco_git_diff`, `roboco_git_branch_list` |
| `roboco-optimal` | `roboco_ask_mentor`, `roboco_kb_search` |
## Key Permissions Your flow surface is deliberately narrow: the Board steers and approves,
it does not claim, create, or complete tasks.
| Permission | Access |
|------------|--------|
| VIEW_ALL tasks | Yes |
| CREATE tasks | Yes |
| ASSIGN tasks | Yes |
| CANCEL tasks | Yes |
| CLOSE tasks | Yes |
| INDEX_DOCS | Yes |
## Escalation ## Escalation
Receives escalations from Main PM. Receives escalations from Main PM. Escalates to CEO for final authority.
Escalates to CEO for final authority.
``` ```
Main PM → Product Owner → CEO Main PM → Product Owner → CEO
``` ```
```python
escalate_to_ceo(task_id, reason="Strategic direction needed on the roadmap")
```
The CEO acts via the panel/UI; you idle until the CEO decides.
## A2A ## A2A
```python ```python
roboco_agent_request("main-pm", "coordination", "...", task_id) dm(recipient="main-pm", text="Coordinating the roadmap — ...", task_id="...")
roboco_a2a_check() # Check inbox channels() # discover channels you can post to
``` ```
Skills: requirements_clarification, feature_approval Skills: requirements_clarification, feature_approval
@@ -68,4 +74,4 @@ Access to:
- #board-private - #board-private
- #announcements (write) - #announcements (write)
Can notify: Main PM, Head Marketing, Auditor, CEO Can `notify`: Main PM, Head Marketing, Auditor, CEO
+37 -61
View File
@@ -1,82 +1,58 @@
# A2A (Agent-to-Agent) Tools # A2A (Agent-to-Agent) Tools
## Overview A2A is direct peer-to-peer messaging between agents. There is **no**
`roboco_agent_*` or `roboco_a2a_*` tool — A2A is the `dm` content tool on
the `roboco-do` MCP server, with `channels()` for discovery and the
notify inbox for receiving.
A2A enables direct peer-to-peer communication between agents about existing tasks. ## Send a direct message — `dm`
**Key points:**
- Direct HTTP when both agents online (no notification)
- Fallback to notification only when target offline
- All requests MUST reference an existing `task_id`
## Tools
### roboco_agent_discover
Find agents by role, team, or skill.
```python ```python
roboco_agent_discover( dm(
role="developer", # Optional: developer, qa, documenter, cell_pm, etc. recipient="be-qa", # target agent slug
team="backend", # Optional: backend, frontend, ux_ui text="Please review my changes",
skill="code_review" # Optional: specific capability task_id="abc123...", # auto-filled from your active task if omitted
skill=None, # optional skill slug to scope the conversation
) )
``` ```
### roboco_agent_request - Auto-creates the conversation; auto-resolves the skill if needed.
- **Same-cell only.** Cross-cell DM is denied by policy — route through
your Cell PM via `escalate_up(task_id, reason)`.
- The recipient sees it in their notify inbox when offline.
Send A2A message to another agent. ## Discover who/where to message — `channels`
There is no agent-directory tool. Use `channels()` to see the channels
you can read/write, and post to a channel when the audience is the whole
cell rather than one peer:
```python ```python
roboco_agent_request( channels() # -> {"writable": [...], "readable": [...]}
target_agent="be-qa", say(channel="backend-cell", text="Anyone hit Y before? Starting task X.")
skill="code_review",
message="Please review my changes",
task_id="abc123...", # REQUIRED
options={"urgent": False} # Optional: priority queue
)
``` ```
**Returns:** `{status, delivery, message_id}` where `delivery` is `"direct"` or `"notification"`. ## Receive incoming messages
### roboco_a2a_check Incoming A2A and @mentions land in your notify inbox. When `i_am_idle()`
soft-blocks on unread items, drain the inbox:
Poll your inbox for incoming A2A messages.
```python ```python
roboco_a2a_check() notify_list(unread_only=True) # list pending items
notify_get(notification_id) # read one (marks it read)
notify_ack(notification_id) # acknowledge after handling
``` ```
**Returns:** `{messages: [...], count: N}` - messages from other agents. ## When to use A2A
**Note:** A hook automatically notifies you of pending messages after tool calls. - A quick question, sanity check, or hand-off about a task you own
- Requesting code review or clarification from a same-cell peer
## Common Use Cases ## When NOT to use A2A
| Need | Action | | Need | Do this instead |
|------|--------| |------|-----------------|
| Code review | `roboco_agent_request("be-qa", "code_review", "...", task_id)` | | Cross-cell question | `escalate_up(task_id, reason)` — DM is same-cell only |
| Clarification | `roboco_agent_request("be-pm", "clarification", "...", task_id)` | | New work / subtask | Only PMs create work, via `delegate(...)`; escalate to your PM |
| Find reviewer | `roboco_agent_discover(skill="code_review")` | | Formal, ack-required signal | PM/Board `notify(target, text, ...)` |
| Urgent help | `roboco_agent_request(..., options={"urgent": True})` | | Cell-wide broadcast | `say(channel=..., text=...)` |
## When to Use A2A
- Communication about an existing task you're working on
- Requesting code review, clarification, or help
- Notifying another agent about task progress
- Urgent questions needing immediate attention
## When NOT to Use A2A
- Creating new work → Only PMs create tasks via `roboco_task_create`
- Task assignments → PM assigns via `roboco_task_assign`
- Escalations → Use `roboco_task_escalate`
- Formal notifications → Use `roboco_notify_send` (PM only)
## Task Creation Rules
Only Cell PMs and Main PM can create tasks (subtasks).
If an agent receives an A2A request that requires new work:
1. Escalate to PM: `roboco_task_escalate(task_id, "Needs subtask for...")`
2. PM decides whether to create a subtask
+89 -60
View File
@@ -1,92 +1,121 @@
# Journal Tools # Journal Tools
## Creating Entries There is **no** `roboco_journal_*` tool. Journaling is a single content
tool on the `roboco-do` MCP server: `note`. The `scope` argument selects
the entry kind; structured fields are filled per scope.
| Tool | Purpose | ```python
|------|---------| note(
| `roboco_journal_entry` | General entry | text: str, # always: one-paragraph summary
| `roboco_journal_decision` | Decision log | scope: str = "note", # note | decision | reflect | learning | struggle
| `roboco_journal_learning` | Learning capture | task_id: str | None = None, # auto-filled from your active task if omitted
| `roboco_journal_struggle` | Problem/solution | title: str | None = None,
| `roboco_journal_reflect` | Task reflection | # decision-scope fields:
context: str = "",
options=None, # list of {name, pros, cons} (a single dict is ok)
chosen: str = "",
rationale: str = "",
consequences=None, # list of strings (a single string is ok)
# reflect-scope fields:
what_done: str = "",
what_learned: str = "",
what_struggled: str = "",
next_steps=None, # list of strings (a single string is ok)
)
```
`text` is always required. Missing narrative fields default to a visible
placeholder rather than being rejected — the note is always recorded.
## Scopes
| Scope | Use For | Structured fields |
|-------|---------|-------------------|
| `note` | General entry | (just `text`) |
| `decision` | Decision log | `context`, `options`, `chosen`, `rationale`, `consequences` |
| `reflect` | Task reflection | `what_done`, `what_learned`, `what_struggled`, `next_steps` |
| `learning` | Learning capture | (just `text`) |
| `struggle` | Problem / blocker | (just `text`) |
## General Entry ## General Entry
```python ```python
roboco_journal_entry({ note(
type: "learning", text="SCAN is better than KEYS for large datasets",
title: "Redis SCAN vs KEYS", scope="learning",
content: "SCAN is better for large datasets", title="Redis SCAN vs KEYS",
task_id: task_id, task_id=task_id,
tags: ["redis", "performance"] )
})
``` ```
Entry types: `task_reflection`, `decision_log`, `learning`, `struggle`, `general`
## Decision Log ## Decision Log
```python ```python
roboco_journal_decision({ note(
title: "Session storage choice", text="Chose Redis for session storage over PostgreSQL.",
context: "Need fast session lookups", scope="decision",
options: ["PostgreSQL", "Redis"], title="Session storage choice",
chosen: "Redis", context="Need fast session lookups",
rationale: "Sub-ms reads, ephemeral data" options=[
}) {"name": "PostgreSQL", "pros": "durable", "cons": "slower reads"},
{"name": "Redis", "pros": "sub-ms reads", "cons": "ephemeral"},
],
chosen="Redis",
rationale="Sub-ms reads, ephemeral data",
consequences=["Session loss on Redis restart is acceptable"],
)
``` ```
## Learning ## Learning
```python ```python
roboco_journal_learning({ note(
content: "asyncio.gather for parallel calls", text="asyncio.gather for parallel calls — reduced latency 50%",
how_applied: "Reduced latency 50%", scope="learning",
category: "performance", title="Parallel async calls",
tags: ["async"] )
})
``` ```
## Struggle (Problem/Solution) ## Struggle (Problem / Blocker)
```python ```python
roboco_journal_struggle({ note(
task_id: task_id, text=(
problem: "Tests failing intermittently", "Tests failing intermittently — tried timeout increase and retry "
attempts: ["Timeout increase", "Retry logic"], "logic; root cause was a race condition in setup."
resolution: "Race condition in setup" ),
}) scope="struggle",
task_id=task_id,
)
``` ```
## Reflection (Required) ## Reflection
Use a `reflect`-scope note before submitting to QA — it gives QA the
"why" behind the diff.
```python ```python
roboco_journal_reflect({ note(
task_id: task_id, text="Implemented rate limiting with a Redis-backed sliding window.",
what_done: "Implemented rate limiting", scope="reflect",
what_learned: "Lua scripts for atomicity", task_id=task_id,
what_struggled: "Testing concurrency" what_done="Implemented rate limiting",
}) what_learned="Lua scripts give atomicity for the counter increment",
what_struggled="Testing concurrency deterministically",
next_steps=["Add a load test for the 100-req boundary"],
)
``` ```
## Reading Journals ## Reading Journals
Journals are written by `note` and surface through the knowledge base —
there is no separate journal-read tool. Search past notes (yours and
your team's, where permitted) via the `roboco-optimal` MCP server:
```python ```python
# Search your journal # Semantic search over indexed notes/decisions/learnings
roboco_journal_search("rate limiting", top_k=5) roboco_kb_search(query="rate limiting", index_types=["journals", "decisions"])
# Recent entries # Conversational lookup with follow-up context
roboco_journal_recent(limit=10) roboco_ask_mentor(question="What did we decide about session storage?")
# Read team journals (if permitted)
roboco_journal_read_team(
target_agent="be-dev-1",
task_id=task_id
)
# Your stats
roboco_journal_stats()
# Check access scope
roboco_journal_scope()
``` ```
+54 -58
View File
@@ -1,84 +1,80 @@
# Messaging Tools # Messaging Tools
## Sending Messages There is **no** `roboco_message_*`, `roboco_notify_send`, or
`roboco_session_*` tool. Messaging is a small set of **content tools** on
the `roboco-do` MCP server. They are role-scoped at spawn time.
## Channel post — `say`
```python ```python
roboco_message_send({ say(channel="backend-cell", text="Starting work on rate limiting", task_id=task_id)
channel: "backend-cell",
content: "Starting work on rate limiting",
task_id: task_id
})
``` ```
## Channel History - `channel` is the slug WITHOUT a leading `#`.
- `task_id` is auto-filled from your active task if omitted.
- Write access varies by role; the gateway returns `not_authorized` and
lists the channels you *can* write to.
Don't invent channel slugs. Call `channels()` first if unsure:
```python ```python
# Read channel history channels() # -> {"writable": [...], "readable": [...]}
roboco_channel_history(
channel="backend-cell",
limit=50
)
``` ```
## Notifications Valid slugs: cell channels (`backend-cell`, `frontend-cell`,
`uxui-cell`); cross-cell (`dev-all`, `qa-all`, `pm-all`, `doc-all`);
management (`main-pm-board`, `board-private`); broadcast
(`announcements`, `all-hands`).
### Sending (PM/Board only) ## Direct message (A2A) — `dm`
```python ```python
roboco_notify_send({ dm(recipient="be-qa", text="Quick sanity check: ...", task_id=task_id)
recipient: "be-dev-1",
type: "task_assignment",
task_id: task_id,
message: "Task ready for you"
})
``` ```
### Receiving - `recipient` is an agent slug (`be-pm`, `be-dev-1`, `ceo`, ...).
- Auto-creates the conversation; `task_id` auto-fills from your active task.
- Same-cell only. Cross-cell DM is denied by policy — route through your
Cell PM via `escalate_up(task_id, reason)`.
## Formal notification — `notify` (PM / Board only)
`notify` creates an ack-required notification (distinct from the informal
`say`/`dm`). Only PM roles and the Board may send it; devs / QA / docs use
`say` and `dm`.
```python ```python
# List notifications notify(target="be-dev-1", text="Task ready for you", priority="normal", task_id=task_id)
notifications = roboco_notify_list()
# Acknowledge
roboco_notify_ack(notification_id)
``` ```
### Notification Types `priority` is `normal | high | urgent`. `task_id` auto-injects from the
active task when omitted.
| Type | Purpose | ## Receiving notifications
|------|---------|
| `task_assignment` | New task assigned |
| `priority_change` | Priority updated |
| `blocker_escalation` | Task blocked |
| `review_request` | Review needed |
| `documentation_request` | Docs needed |
| `alert` | General alert |
| `broadcast` | Org-wide message |
## Sessions Every role with an inbox gets these (so `i_am_idle()` doesn't soft-block
on unread items):
```python ```python
# Create session for tasks notify_list(unread_only=True, limit=20) # your inbox
roboco_session_create_for_tasks({ notify_get(notification_id) # read one (marks it read)
title: "Feature X Implementation", notify_ack(notification_id) # acknowledge after handling
task_ids: [task_1_id, task_2_id]
})
# Start collaborative session
roboco_session_start(
channel="backend-cell",
session_type="collaborative",
task_id=task_id
)
``` ```
## Message Types When `i_am_idle()` reports unread A2A or @mentions, list -> get -> ack,
then idle again. (The Auditor gets `notify_list`/`notify_get` for inbox
visibility but does not ack.)
| Type | Use For | ## Sessions (PM-or-up only)
|------|---------|
| `reasoning` | Thought process | Devs / QA / docs participate via channels and DMs and do **not** open
| `dialogue` | Discussion | sessions. PMs and the Board link discussion threads to tasks:
| `decision` | Decisions made |
| `action` | Actions taken | ```python
| `blocker` | Blocking issues | open_session(task_id, channel="backend-cell", topic="Feature X kickoff",
| `technical` | Technical details | relationship_type="discussion")
link_session(session_id, task_id, is_primary=False)
```
`relationship_type` is `discussion | planning | review | retrospective`.
`link_session` is idempotent; you must own the task you're linking.
+47 -101
View File
@@ -1,115 +1,61 @@
# Project Tools # Project & Workspace Tools
## Overview ## Overview
Project tools manage git repositories and agent workspaces. There is **no** `roboco_project_*` or `roboco_workspace_*` agent tool.
Agents do **not** create projects, manage git tokens, or ensure
workspaces. Those are handled for you:
## List Projects - **Workspaces are auto-cloned by the orchestrator** (`WorkspaceService`).
Your per-agent clone of the project repo is created the first time you
claim work on it — you never call a workspace tool. Branches are
auto-created on `i_will_work_on()` / `claim_review()`; you don't run
`git checkout` either.
- **Project registration and git-token management are operator actions**
done through the control panel / HTTP API, not from inside an agent
container. Tokens are encrypted at rest; the agent container never sees
the PAT (it is injected into git operations server-side and scrubbed
from URLs).
## What a task already tells you
A task carries its project linkage; you don't look it up with a tool. The
task object you receive from `give_me_work()` / `triage()` includes the
`project_id` (and the branch the flow verbs check out). Acceptance
criteria and the project context come back inline on the Envelope.
## Inspecting the repo
Read-only git inspection is available through the `roboco-git-readonly`
MCP server (developers and QA):
```python ```python
roboco_project_list() # All accessible projects roboco_git_status(project_slug="roboco")
roboco_project_list(cell="backend") # Filter by cell roboco_git_log(project_slug="roboco")
roboco_git_diff(project_slug="roboco")
roboco_git_branch_list(project_slug="roboco")
``` ```
Returns projects you have access to (cell-scoped for non-PMs). There is **no** `roboco_git_commit / _push / _checkout / _create_pr /
_merge_pr` tool. Commits go through the `commit` content tool (auto-
prefixed with `[task-id]`, auto-pushed by the choreographer); PRs open at
`open_pr` time; merges are a PM `complete` operation.
## Get Project Details ## Finding project knowledge
To learn how a project's codebase is laid out or how a subsystem works,
query the knowledge base rather than a project tool:
```python ```python
roboco_project_get(slug="roboco") roboco_kb_search(query="rate limiting redis", project="roboco",
index_types=["code", "documentation"])
roboco_ask_mentor(question="How is auth wired up in this project?")
``` ```
Returns: `name`, `git_url`, `assigned_cell`, `default_branch`, `has_git_token`, `test_command`, etc. ## PM note: creating work
**Note:** `has_git_token` indicates if authentication is configured (required for HTTPS repos). PMs create work with the `delegate` flow verb (a subtask under the
current parent task), not a project/task-create tool. `delegate` takes an
## Create Project (PM+ Only) optional `project_id`; the parent task's project is inherited when you
omit it. There is no agent-facing standalone project- or task-create
```python tool.
# Example: register a separate frontend-only repo as a project.
# (The built-in RoboCo control panel lives in this same repo under
# panel/ and is NOT registered as a separate project.)
roboco_project_create(
name="Customer Portal",
slug="customer-portal",
git_url="https://github.com/org/customer-portal.git",
assigned_cell="frontend",
git_token="ghp_xxxx...", # GitHub PAT with repo scope
default_branch="main",
test_command="pnpm test",
lint_command="pnpm lint"
)
```
**Who can create:** Main PM, Board, CEO
**IMPORTANT:** `git_token` is **required** for HTTPS repositories. Without it, workspace creation and git operations will fail.
## Update Project
```python
roboco_project_update(
slug="roboco-panel",
git_token="ghp_newtoken...", # Update/rotate token
test_command="pnpm test:ci",
lint_command="pnpm lint:fix"
)
```
**Who can update:**
- CEO, Main PM: Any project
- Cell PM: Own cell's projects only
**Token rotation:** Pass `git_token` to update credentials. Pass empty string to clear.
## Workspace Tools
### Ensure Workspace
```python
roboco_workspace_ensure(project_slug="roboco")
```
Creates your workspace if it doesn't exist. Auto-clones the repository.
### Check Workspace Status
```python
roboco_workspace_status(project_slug="roboco")
```
Returns: `exists`, `branch`, `has_uncommitted`, `staged_files`, `unstaged_files`
### List Workspaces (PM Only)
```python
roboco_workspace_list(project_slug="roboco")
```
Lists all agent workspaces for a project. Cell PM sees own cell only.
## Permission Matrix
| Tool | Dev/QA/Doc | Cell PM | Main PM | CEO |
|------|------------|---------|---------|-----|
| `project_list` | Own cell | Own cell | All | All |
| `project_get` | Yes | Yes | Yes | Yes |
| `project_create` | No | No | Yes | Yes |
| `project_update` | No | Own cell | All | All |
| `workspace_ensure` | Yes | Yes | Yes | Yes |
| `workspace_status` | Yes | Yes | Yes | Yes |
| `workspace_list` | No | Own cell | All | All |
## Task Creation with Project
When creating tasks:
```python
roboco_task_create(
title="Add rate limiting",
team="backend",
project_slug="roboco", # Required - all tasks follow git workflow
)
```
Use `project_slug="roboco"` for internal RoboCo codebase work.
+107 -86
View File
@@ -1,111 +1,132 @@
# Task Management Tools # Task Management Tools
## Core Operations There is **no** `roboco_task_*` tool surface. Tasks move through the
lifecycle via **flow verbs** on the `roboco-flow` MCP server. Each verb is
role-scoped — you only see the ones your role is allowed to call (the
spawn manifest registers them per role). Every verb returns an
**Envelope** whose `next` field tells you what to call next; trust it
rather than guessing state.
| Tool | Purpose | The verbs below are grouped by who calls them.
|------|---------|
| `roboco_task_get` | Get task details |
| `roboco_task_scan` | Find available tasks |
| `roboco_task_claim` | Take ownership |
| `roboco_task_unclaim` | Release claimed task |
| `roboco_task_start` | Begin work |
## Task Retrieval ## Developer flow
```python ```python
# Get specific task give_me_work() # returns your most-actionable pending task
task = roboco_task_get(task_id) i_will_work_on(task_id, plan="...")
# claims + sets plan + starts; auto-creates and
# Scan for available tasks # checks out feature/{team}/{task-hierarchy}
tasks = roboco_task_scan( commit(message, files=None) # content tool — repeat per change (auto-pushed)
team="backend", # Optional filter open_pr(task_id) # pushes branch + opens the PR
status="pending" # Optional filter i_am_done(task_id, notes="") # verifying -> awaiting_qa (PR must already be open)
) i_am_blocked(task_id, reason) # external dependency; cell PM unblocks
unclaim(task_id) # release a claimed task back to the queue
resume(task_id) # recover a paused task after compact/restart
i_am_idle() # no work in your queue right now
``` ```
## Task Lifecycle There is no separate claim / start / pause verb — `i_will_work_on`
composes claim + set-plan + start atomically, and `i_am_done` composes
verify + submit-qa. Branches are auto-created on `i_will_work_on`; do not
checkout by hand.
## QA flow
```python ```python
# Claim task give_me_work() # returns an awaiting_qa task
roboco_task_claim(task_id) claim_review(task_id) # claim for review (auto-checks-out dev branch)
pass(task_id, notes) # awaiting_qa -> awaiting_documentation
# Release if you shouldn't work on it fail(task_id, issues=[...]) # awaiting_qa -> needs_revision (dev gets it back)
roboco_task_unclaim(task_id) unclaim(task_id) / resume(task_id) / i_am_idle()
roboco_task_unclaim(task_id, hand_off_to="be-dev-2")
# Start work (also resumes paused tasks)
roboco_task_start(task_id)
# Pause work
roboco_task_pause(task_id, reason="Waiting for clarification")
# Resume paused work (use start)
roboco_task_start(task_id) # Works on paused tasks
# Block (waiting on another task)
roboco_task_block(task_id, blocker_task_id, reason)
# Unblock (PM only)
roboco_task_unblock(task_id)
``` ```
## Submission `notes` (on pass) and `issues` (on fail) must be substantive — the
enforcement layer rejects empty or near-empty content. QA cannot review
its own dev work (self-review guard rejects on `claim_review`).
## Documenter flow
```python ```python
# Submit for verification give_me_work() # returns an awaiting_documentation task
roboco_task_submit_verification(task_id) claim_doc_task(task_id) # claim the doc phase
commit(message, files) # commit the doc files you write
# Submit for QA i_documented(task_id, notes, files)
roboco_task_submit_qa(task_id, notes) # awaiting_documentation -> awaiting_pm_review
# QA actions
roboco_task_qa_pass(task_id, {notes: "..."})
roboco_task_qa_fail(task_id, {notes: "...", issues: [...]})
# Documentation complete
roboco_task_docs_complete(task_id)
# PM complete
roboco_task_complete(task_id)
``` ```
## PM Operations Documentation tasks are **not** delegated — the lifecycle auto-creates
the doc phase after a code task passes QA.
## Cell PM flow
```python ```python
# Create SUBTASK (most common) triage() # list actionable tasks in your cell
roboco_task_create({ i_will_plan(task_id, plan, approach)
title: "Implement auth endpoint", # claim + plan + start a parent task
parent_task_id: my_task_id, # REQUIRED for subtasks delegate(parent_task_id, title, description, assigned_to, team,
team: "backend", task_type, nature, estimated_complexity, acceptance_criteria)
assigned_to: "be-dev-1" # Use SLUG # create a subtask under the current task
}) unblock(task_id) # blocked -> in_progress (PM only)
submit_up(task_id, notes) # open cell->root PR; -> awaiting_pm_review
# Create standalone task (rare) complete(task_id, notes) # awaiting_pm_review -> completed (merges leaf PR)
roboco_task_create({ escalate_up(task_id, reason) # escalate to your escalation target
title: "...",
team: "backend",
status: "backlog"
})
# Activate (backlog -> pending)
roboco_task_activate(task_id)
# Cancel
roboco_task_cancel(task_id, reason)
# Plan
roboco_task_plan(task_id, approach, steps)
# Escalate to CEO (parent tasks only)
roboco_task_escalate_to_ceo(task_id, notes)
``` ```
**CRITICAL**: When creating subtasks, ALWAYS include `parent_task_id`. Without it, you create orphan sibling tasks instead of linked subtasks. **Delegation rules** (enforced): `main_pm -> cell_pm`; `cell_pm -> its
team's devs`. Cell PMs receive planning-typed parent tasks; devs get
code/research (UX devs also design). Always create subtasks via
`delegate` with `parent_task_id` set — there is no standalone task-create
verb for agents.
**Note**: `roboco_task_escalate_to_ceo` only works on parent tasks (tasks without a `parent_task_id`). Subtasks must have their parent task escalated instead. ## Main PM flow
## Progress Updates The Main PM has the Cell PM verbs **plus**:
```python ```python
roboco_task_progress(task_id, "Implementing API", 50) triage_all() # list actionable tasks across all teams
escalate_to_ceo(task_id, reason)
# awaiting_pm_review -> awaiting_ceo_approval
give_me_work() # Main PM may also pull work directly
``` ```
`complete` for the Main PM merges the **root** PR. Only the CEO merges to
`master`; agents stop at `escalate_to_ceo`.
## Board flow (Product Owner / Head of Marketing)
```python
triage() # list actionable tasks in scope
escalate_to_ceo(task_id, reason)
i_am_idle()
```
The Board **cannot** claim, create, complete, or cancel tasks. Strategic
decisions are escalated to the CEO.
## Auditor flow
```python
triage() # read-only list of actionable tasks
i_am_idle()
```
The Auditor is a silent observer: read-only `triage`, no `say`/`dm`/
`notify`, no claim/complete/cancel.
## Cancel
Cancelling a task (any non-terminal status -> `cancelled`) is restricted
to **PM roles and the CEO**. There is no agent verb to cancel — it is a
PM/CEO operation through the lifecycle.
## Progress
Record progress against your plan with the `progress` content tool (on
`roboco-do`), not a task verb:
```python
progress(task_id, message="API skeleton landed", plan_step="2")
```
Your plan's steps are the progress checklist; the percentage is derived
from completed steps — you do not set it.
+23 -18
View File
@@ -9,12 +9,12 @@
**Check Permissions**: **Check Permissions**:
| Action | Allowed Roles | | Action | Allowed Roles |
|--------|---------------| |--------|---------------|
| Create task | PM, Board | | Create / delegate task | PM only (Cell PM, Main PM) |
| Cancel task | PM | | Cancel task | PM, CEO |
| Pass/fail QA | QA only | | Pass/fail QA | QA only |
| Complete docs | Documenter only | | Complete docs | Documenter only |
| Complete task | PM only | | Complete task | PM only |
| Send notification | PM, Board | | Send notification (`notify`) | PM, Board |
**Solution**: Request appropriate role to perform action **Solution**: Request appropriate role to perform action
@@ -42,22 +42,23 @@
3. Already acknowledged 3. Already acknowledged
**Solutions**: **Solutions**:
- Check `roboco_notify_list()` for all notifications - Check `notify_list()` for all notifications
- Verify sender has PM/Board role - Verify sender has PM/Board role
- Check if already in `acked_by` - Check if already acknowledged via `notify_get(notification_id)`
## Escalation Not Routing ## Escalation Not Routing
**Problem**: Escalation went to wrong person **Problem**: Escalation went to wrong person
**Cause**: Escalation auto-routes to your escalation target **Cause**: `escalate_up` auto-routes to your escalation target
**Chain**: **Chain**:
``` ```
Developer → Cell PM → Main PM → Product Owner → CEO Cell members → Cell PM → Main PM → Product Owner → CEO
``` ```
Cannot skip levels or choose target. Cannot skip levels or choose target. (Only Main PM / Board call
`escalate_to_ceo`; cell members and Cell PMs use `escalate_up`.)
## Tests Failing Before Submit ## Tests Failing Before Submit
@@ -123,21 +124,25 @@ roboco_docs_write({
## A2A Message Not Delivered ## A2A Message Not Delivered
**Problem**: Sent A2A message but no response **Problem**: Sent a `dm` but no response
**Check**: **Check**:
1. Did you include `task_id`? (required) 1. Is the recipient in your **own cell**? Cross-cell `dm` is denied by
2. Check delivery status in response: `"direct"` or `"notification"` policy — route through your Cell PM via `escalate_up(task_id, reason)`.
3. If `"notification"` - target was offline, will be spawned 2. Use the right slug — call `channels()` to discover valid recipients
instead of guessing.
3. Did you include `task_id`? It anchors the message to the work.
**Solutions**: **Solutions**:
- Direct delivery: Target should check `roboco_a2a_check()` - Same-cell peer: `dm(recipient="be-qa", text="...", task_id="...")`
- Notification delivery: Wait for target to be spawned - Anything cross-cell or needing PM action: `escalate_up(task_id, reason)`
- Broadcast to the cell instead of one peer: `say(channel="backend-cell", text="...")`
## A2A SDK Server Unavailable ## Cross-Cell Message Denied
**Error**: "SDK Server is not available" **Error**: A `dm` to an agent outside your cell is rejected by policy
**Cause**: SDK Server not running in container **Cause**: Direct A2A is same-cell only — there is no cross-cell `dm`
**Solution**: SDK Server starts automatically with agent container. If error persists, container may need restart. **Solution**: Escalate up the chain. Use `escalate_up(task_id, reason)`
so your Cell PM can coordinate with the other cell's PM.
+24 -20
View File
@@ -10,16 +10,17 @@
3. Wrong role for this task type 3. Wrong role for this task type
**Solutions**: **Solutions**:
- Check task status: `roboco_task_get(task_id)` - Check what's actionable for you: `give_me_work()` (or `triage()` for PMs)
- Verify your role can claim from current status - Verify your role can claim from the task's current status
- Contact PM if task needs reassignment - Contact PM if task needs reassignment
**Claimable Status by Role**: **Claimable Status by Role**:
| Role | Can Claim From | | Role | Can Claim From | Verb |
|------|----------------| |------|----------------|------|
| Developer | pending, needs_revision | | Developer | pending, needs_revision | `i_will_work_on(task_id)` |
| QA | awaiting_qa | | QA | awaiting_qa | `claim_review(task_id)` |
| Documenter | awaiting_documentation | | Documenter | pending, awaiting_documentation | `claim_doc_task(task_id)` |
| Cell PM / Main PM | pending | `i_will_plan(task_id)` |
## Cannot Start Task ## Cannot Start Task
@@ -30,7 +31,9 @@
2. Task in wrong status 2. Task in wrong status
**Solutions**: **Solutions**:
- Claim first: `roboco_task_claim(task_id)` - Claim + start in one step: `i_will_work_on(task_id, plan="...")`
(devs), `claim_review(task_id)` (QA), `claim_doc_task(task_id)` (doc),
or `i_will_plan(task_id, plan, approach)` (PMs)
- Check current status - Check current status
Note: Git branches are auto-created on claim, no waiting needed. Note: Git branches are auto-created on claim, no waiting needed.
@@ -54,9 +57,9 @@ Note: Git branches are auto-created on claim, no waiting needed.
**Cause**: QA trying to claim, pass, or fail a task they originally developed **Cause**: QA trying to claim, pass, or fail a task they originally developed
**Solution**: Another QA must handle this task. Self-review prevention applies to: **Solution**: Another QA must handle this task. Self-review prevention applies to:
- Claiming the task - Claiming the task (`claim_review`)
- Passing QA (`roboco_task_qa_pass`) - Passing QA (`pass`)
- Failing QA (`roboco_task_qa_fail`) - Failing QA (`fail`)
## Cannot Escalate Subtask to CEO ## Cannot Escalate Subtask to CEO
@@ -64,15 +67,14 @@ Note: Git branches are auto-created on claim, no waiting needed.
**Cause**: Attempting to escalate a task that has a `parent_task_id` **Cause**: Attempting to escalate a task that has a `parent_task_id`
**Solution**: Escalate the parent task instead: **Solution**: Escalate the parent task instead. Find the parent task ID
(it's on the subtask's `parent_task_id` field, surfaced in your
`give_me_work()` / `triage()` envelope), then escalate the parent:
```python ```python
# Get the parent task ID escalate_to_ceo(task_id=parent_id, reason="...")
task = roboco_task_get(subtask_id)
parent_id = task.parent_task_id
# Escalate the parent
roboco_task_escalate_to_ceo(parent_id, notes="...")
``` ```
`escalate_to_ceo` is Main PM / Board only; Cell PMs and cell members
use `escalate_up(task_id, reason)` instead.
## Git Task: Parent Branch Required ## Git Task: Parent Branch Required
@@ -91,8 +93,10 @@ roboco_task_escalate_to_ceo(parent_id, notes="...")
**Cause**: Trying to complete a parent task while subtasks are still in progress **Cause**: Trying to complete a parent task while subtasks are still in progress
**Solution**: The error message includes which subtask IDs are blocking. Either: **Solution**: The error message includes which subtask IDs are blocking. Either:
1. Complete the blocking subtasks first 1. Complete the blocking subtasks first (drive them through QA → docs →
2. Cancel them if no longer needed: `roboco_task_cancel(subtask_id, reason)` `complete(task_id, notes)`)
2. Cancel them if no longer needed (PM/CEO only — cancellation is not an
agent verb; ask your PM)
## Invalid Task Status for Operation ## Invalid Task Status for Operation
+41 -46
View File
@@ -2,73 +2,68 @@
## Overview ## Overview
Agents communicate directly via SDK Server (port 9000) for true peer-to-peer messaging. Agents collaborate directly through two content tools on the `roboco-do`
MCP server: `dm` for agent-to-agent messages and `say` for channel posts.
Use `channels()` to discover the channels you can post to.
**Key:** A2A requires `task_id` - it's about existing tasks, NOT task creation. **Key:** A2A is about *existing* tasks, NOT task creation. Pass the
`task_id` you're collaborating on so the message is linked to it.
## Flow ## Flow
``` ```
1. Discover → roboco_agent_discover(role, team, skill) 1. Discover → channels() lists the channels visible to you
2. Request → roboco_agent_request(target, skill, message, task_id) 2. Reach out → dm(recipient, text, task_id) for a direct message
3. Check → roboco_a2a_check() polls your inbox (auto-notified via hook) → say(channel, text, task_id) to post to your cell channel
4. Respond → Work on task or reply via roboco_agent_request 3. Receive → notify_list() / notify_get(id) to read your inbox
``` ```
## Delivery ## Direct Messages (same cell only)
| Target State | Delivery | Creates Notification? |
|--------------|----------|----------------------|
| Online | Direct HTTP to SDK | NO |
| Offline | Fallback via API | YES (spawns target) |
## Example
```python ```python
# Request code review for task ABC123 # Direct A2A inside your cell (same team — no policy gate)
result = roboco_agent_request( dm(
target_agent="be-qa", recipient="be-qa",
skill="code_review", text="Quick sanity check on the rate-limit boundary before I open the PR?",
message="Please review my changes", task_id="<task>",
task_id="ABC123"
) )
# result.delivery = "direct" or "notification"
# Check for incoming messages
inbox = roboco_a2a_check()
# inbox.messages = [{from, task_id, skill, message, priority}, ...]
``` ```
## Urgency Cross-cell `dm` is **denied by policy**. If you need something from
another cell, route it through your Cell PM via `escalate_up(task_id,
reason)` — the PM coordinates across cells.
## Channel Posts
```python ```python
roboco_agent_request(..., options={"urgent": True}) # Priority queue # Visible to your whole cell
say(
channel="backend-cell",
text="Started on <task> — anyone hit the Redis failover path before?",
task_id="<task>",
)
``` ```
## Agent Skills Call `channels()` first if you're unsure of the exact slug — it returns
the channels you're allowed to post to, so you don't have to guess.
| Role | Skills |
|------|--------|
| Developer | `code_review`, `implementation`, `debugging`, `revision` |
| QA | `code_review`, `testing`, `qa_review` |
| Documenter | `documentation`, `api_docs` |
| PM | `task_planning`, `coordination`, `clarification` |
## Task Creation Rules ## Task Creation Rules
**Only PMs can create tasks.** **Only PMs create tasks** (via the `delegate` verb). Regular agents
cannot create work from a `dm` or `say`.
If you receive an A2A request that needs new work: If a conversation surfaces work that needs a new task:
1. Escalate: `roboco_task_escalate(task_id, "Needs subtask for X")` 1. Escalate to your Cell PM: `escalate_up(task_id, reason="Needs a subtask for X")`
2. PM decides whether to create subtask 2. The PM decides whether to `delegate` a subtask
## Permissions ## Permissions
All agents can: Most roles can `dm` (same-cell) and `say` to their channels, plus read
- Discover other agents their inbox with `notify_list` / `notify_get`.
- Send A2A requests (must include task_id)
- Check request status
All agents CANNOT: The **Auditor** is a silent observer: it can read (`notify_list`,
- Create tasks via A2A (no automatic task creation) `notify_get`, `channels`) but has **no** `say`, `dm`, or `notify` — it
- Send A2A without a task_id never communicates outwardly.
Only PMs and the Board can send ack-required `notify` signals; regular
agents use `say` and `dm` only.
+44 -32
View File
@@ -9,23 +9,30 @@ Developer/QA/Documenter
Main PM Main PM
Product Owner Product Owner / Head of Marketing (Board)
CEO CEO
``` ```
You CANNOT skip levels in the chain. `escalate_up` walks this chain **one rung at a time** — it auto-routes to
your immediate escalation target; you cannot choose a higher level or skip
a rung.
## How to Escalate The one exception is `escalate_to_ceo`: it is a **separate** verb,
available only to Main PM and the Board (Product Owner / Head of
Marketing), that goes straight to the CEO for final approval of a major
task. It is not part of the `escalate_up` chain.
## How to Escalate (up one rung)
```python ```python
roboco_task_escalate( escalate_up(
task_id="uuid-here", task_id="<task>",
reason="Need clarification on API contract" reason="Need clarification on the API contract",
) )
``` ```
Auto-routes to your escalation target (you cannot choose). Auto-routes to your escalation target (you cannot choose it).
## When to Escalate ## When to Escalate
@@ -35,47 +42,51 @@ Auto-routes to your escalation target (you cannot choose).
| Blocked by external factor | Cell PM | | Blocked by external factor | Cell PM |
| Blocked by another task | Cell PM | | Blocked by another task | Cell PM |
| Cross-cell coordination | Main PM (via Cell PM) | | Cross-cell coordination | Main PM (via Cell PM) |
| Major feature ready | CEO (PM only) | | Major feature ready for CEO sign-off | CEO (via `escalate_to_ceo`, PM/Board only) |
## Escalation vs Block vs Pause ## Escalate vs Block
| Action | When | Tool | | Action | When | Verb |
|--------|------|------| |--------|------|------|
| **Escalate** | Need help/decision | `roboco_task_escalate` | | **Escalate** | Need a decision / help from above | `escalate_up` |
| **Block** | Waiting on another task | `roboco_task_block` | | **Block** | Can't proceed on an external dependency | `i_am_blocked` |
| **Pause** | Temporarily stop work | `roboco_task_pause` |
There is no agent-facing "pause" verb. If you need to step off a task you
claimed but haven't progressed, use `unclaim(task_id)` to return it to
the pool.
## Blocking a Task ## Blocking a Task
```python ```python
# Block on another task i_am_blocked(
roboco_task_block( task_id="<task>",
task_id="uuid-here", reason="Waiting for the auth service to land",
blocker_task_id="blocker-uuid", blocker_type="external",
reason="Waiting for auth service" what_needed="auth-service /token endpoint deployed",
) )
``` ```
PM receives notification with ACTION REQUIRED. Your Cell PM is notified and is the one who can `unblock` it.
## CEO Escalation (PM Only) ## CEO Escalation (Main PM / Board Only)
For major tasks requiring CEO approval: For major tasks requiring CEO approval:
```python ```python
roboco_task_escalate_to_ceo( escalate_to_ceo(
task_id="uuid-here", task_id="<task>",
notes="Major feature ready for final review" reason="Major feature ready for final review",
) )
``` ```
Requirements: Requirements:
- Task must be in `awaiting_pm_review` - Task must be in `awaiting_pm_review`
- PR must exist - PR must exist
- Only PMs can do this - Only Main PM, Product Owner, or Head of Marketing can call it
- **PARENT TASKS ONLY** - Subtasks cannot be escalated to CEO - **PARENT TASKS ONLY** — subtasks cannot be escalated to CEO
If you need to escalate a subtask, escalate the parent task instead. The CEO reviews the complete feature, not individual components. If you need to escalate a subtask, escalate the parent task instead. The
CEO reviews the complete feature, not individual components.
## Good Escalation Format ## Good Escalation Format
@@ -88,10 +99,11 @@ Include:
## Handling Escalations (PM) ## Handling Escalations (PM)
1. ACK immediately: `roboco_notify_ack(notification_id)` 1. ACK the notification: `notify_ack(notification_id)`
2. Investigate: Read task, journals, messages 2. Investigate: read the task, journals, and channel messages
3. Decide or escalate further 3. Decide, or escalate further with `escalate_up`
4. Communicate decision 4. Communicate the decision (`say` / `dm` / `notify`)
5. Unblock if needed: `roboco_task_unblock(task_id)` 5. Unblock if needed: `unblock(task_id)`
CRITICAL: Verbal resolution is NOT enough. You MUST call `roboco_task_unblock()`. CRITICAL: Verbal resolution is NOT enough. To clear a block you MUST call
`unblock(task_id)`.
+59 -49
View File
@@ -7,81 +7,91 @@
3. Documents decisions and learnings 3. Documents decisions and learnings
4. Required before key transitions 4. Required before key transitions
## Entry Types ## The Tool
| Type | Use For | Journaling is a single content tool: `note(text, scope, ...)` on the
|------|---------| `roboco-do` MCP server. There is **no** separate `roboco_journal_*` tool —
| `task_reflection` | End of task summary | the `scope` argument selects the kind of entry.
| `decision_log` | Architectural decisions |
| `scope` | Use For |
|---------|---------|
| `note` (default) | General observation |
| `reflect` | End-of-task summary (what done / learned / struggled) |
| `decision` | Architectural decision (context / options / chosen / rationale) |
| `learning` | New knowledge gained | | `learning` | New knowledge gained |
| `struggle` | Problems and solutions | | `struggle` | Problems and solutions |
| `general` | Other observations |
## Creating Entries ## Creating Entries
```python ```python
# General entry # General entry
roboco_journal_entry({ note(
type: "learning", text="SCAN is better than KEYS for large Redis datasets",
title: "Redis SCAN vs KEYS", scope="learning",
content: "SCAN is better for large datasets", task_id=task_id,
task_id: task_id, )
tags: ["redis", "performance"]
})
# Decision log # Decision log — `decision` scope uses the structured fields
roboco_journal_decision({ note(
title: "Session storage choice", text="Chose Redis for session storage",
context: "Need fast session lookups", scope="decision",
options: ["PostgreSQL", "Redis", "In-memory"], task_id=task_id,
chosen: "Redis", context="Need fast session lookups, ephemeral data",
rationale: "Sub-millisecond reads, ephemeral data" options=[
}) {"name": "PostgreSQL", "pros": "durable", "cons": "slower"},
{"name": "Redis", "pros": "sub-ms reads", "cons": "ephemeral"},
{"name": "In-memory", "pros": "fastest", "cons": "lost on restart"},
],
chosen="Redis",
rationale="Sub-millisecond reads; data is ephemeral by design",
consequences=["Adds Redis as a session dependency"],
)
# Struggle (problem and solution) # Struggle (problem and solution)
roboco_journal_struggle({ note(
task_id: task_id, text="Tests failing intermittently; root cause was a setup race condition",
problem: "Tests failing intermittently", scope="struggle",
attempts: ["Increased timeout", "Added retry"], task_id=task_id,
resolution: "Race condition in setup" )
})
# Learning
roboco_journal_learning({
content: "Use asyncio.gather for parallel calls",
how_applied: "Reduced endpoint latency 50%",
category: "performance",
tags: ["async", "performance"]
})
``` ```
`options`, `consequences`, and `next_steps` accept either a list or a
single value. For `decision` and `reflect` scopes the structured fields
are recommended; the note is always recorded even if some are omitted.
## Required Reflections ## Required Reflections
Before submitting for QA or completing: Before submitting for QA or completing, write a `reflect` entry:
```python ```python
roboco_journal_reflect({ note(
task_id: task_id, text="Implemented rate limiting with Redis",
what_done: "Implemented rate limiting with Redis", scope="reflect",
what_learned: "Lua scripts for atomic operations", task_id=task_id,
what_struggled: "Testing concurrent requests" what_done="Redis-backed token bucket on the API edge",
}) what_learned="Lua scripts give atomic check-and-decrement",
what_struggled="Testing concurrent requests deterministically",
next_steps=["Add a regression test for the boundary case"],
)
``` ```
## Searching Journals ## Searching Journals
```python Journal entries are indexed into the knowledge base. Search them through
# Semantic search your journal the `roboco-optimal` RAG tools (there is no dedicated journal-search verb):
roboco_journal_search("rate limiting patterns", top_k=5)
# Search team journals (if permitted) ```python
roboco_journal_read_team("be-dev-1", task_id=task_id) # Semantic search across the KB, filtered to journal entries
roboco_kb_search(query="rate limiting patterns", index_types=["journals"])
# Or ask the mentor, which searches all sources including journals
roboco_ask_mentor(question="What did we decide about rate limiting?")
``` ```
## Best Practices ## Best Practices
1. **Journal as you go** - Don't wait until end 1. **Journal as you go** - Don't wait until end
2. **Be specific** - Generic entries are less searchable 2. **Be specific** - Generic entries are less searchable
3. **Use tags** - Helps categorization 3. **Record failures** - They're valuable learning (`scope="struggle"`)
4. **Record failures** - They're valuable learning 4. **Use the right scope** - `decision` / `reflect` light up the panel views
5. **Include context** - Future searchers need it 5. **Include context** - Future searchers need it
+3 -2
View File
@@ -83,8 +83,9 @@ roboco_ask_mentor(
Always search first: Always search first:
```python ```python
roboco_kb_search("implementing rate limiter") roboco_kb_search(query="implementing rate limiter")
roboco_journal_search("rate limit decisions") # Journal entries are part of the KB — filter to them with index_types:
roboco_kb_search(query="rate limit decisions", index_types=["journals", "decisions"])
``` ```
This helps you: This helps you:
+33 -32
View File
@@ -2,27 +2,33 @@
## Who Can Claim What ## Who Can Claim What
| Role | Can Claim From Status | | Role | Claim verb | Can Claim From Status |
|------|----------------------| |------|------------|----------------------|
| Developer | `pending`, `needs_revision` | | Developer | `i_will_work_on` | `pending`, `needs_revision` |
| QA | `awaiting_qa` | | QA | `claim_review` | `awaiting_qa` |
| Documenter | `awaiting_documentation`, `pending` | | Documenter | `claim_doc_task` | `awaiting_documentation`, `pending` |
| PM | `pending`, `backlog` | | PM | `triage` / `give_me_work` | `pending` |
## Claiming a Task ## Claiming a Task
```python ```python
# 1. Find available tasks # 1. Get a task assigned to you (returns a pending/awaiting task)
roboco_task_scan(team="backend") give_me_work()
# 2. Claim the task # 2. Claim it. The claim verb is role-specific:
roboco_task_claim(task_id) i_will_work_on(task_id) # Developer — claims + auto-creates the branch
claim_review(task_id) # QA — claims + auto-checks-out the dev's branch
claim_doc_task(task_id) # Documenter
# Result: # Result:
# - status: claimed # - status: claimed (then in_progress)
# - assigned_to: your agent ID # - assigned_to: your agent ID
``` ```
The claim verb both claims and starts the task — there is no separate
`start` call. For developers, `i_will_work_on` also creates and checks
out the `feature/{team}/{task-hierarchy}` branch.
## Before Claiming ## Before Claiming
1. Check you have capacity (one task at a time recommended) 1. Check you have capacity (one task at a time recommended)
@@ -31,17 +37,16 @@ roboco_task_claim(task_id)
## After Claiming ## After Claiming
1. Start work: `roboco_task_start(task_id)` 1. Announce to your cell: `say(channel="backend-cell", text="...", task_id=task_id)`
2. Announce to cell: `roboco_message_send({channel, content, task_id})` 2. Get proactive context: `roboco_get_proactive_context(task_id)`
3. Get proactive context: `roboco_get_proactive_context(task_id)` 3. Search the KB for similar work: `roboco_kb_search(query="...")`
4. Search KB for similar work: `roboco_kb_search()`
## Claiming Rules ## Claiming Rules
- **One at a time**: Don't claim multiple in_progress tasks - **One at a time**: Don't claim multiple in-progress tasks
- **Self-review prevention**: QA cannot claim tasks they developed - **Self-review prevention**: QA cannot `claim_review` tasks they developed
- **Self-documentation prevention**: Documenter cannot claim tasks they developed - **Self-documentation prevention**: Documenter cannot claim tasks they developed
- **Branch requirement**: Branch auto-created on claim - **Branch requirement**: Branch auto-created on `i_will_work_on`
## Releasing a Claimed Task ## Releasing a Claimed Task
@@ -49,35 +54,31 @@ If you claimed a task but realize you shouldn't work on it, use `unclaim`:
```python ```python
# Release back to pool # Release back to pool
roboco_task_unclaim(task_id) unclaim(task_id)
# Hand off to specific agent
roboco_task_unclaim(task_id, hand_off_to="be-dev-2")
# Result: # Result:
# - status: pending # - status: pending
# - assigned_to: None (or hand_off_to agent) # - assigned_to: None
# - You can now claim new work # - You can now claim new work
``` ```
`unclaim` takes only the `task_id` — it returns the task to the pool for
re-pickup. To hand a specific task to a specific agent, escalate to your
PM (`escalate_up`) and let the PM re-`delegate` or reassign it.
**When to use unclaim:** **When to use unclaim:**
- Task is out of your team's scope - Task is out of your team's scope
- Task requires a different role - Task requires a different role
- You need to prioritize other work - You need to prioritize other work
- Better suited for another agent - Better suited for another agent
**Restrictions:**
- Only works on `claimed` status (not yet started)
- You must be the agent who claimed it
- If task is `in_progress`, use `roboco_task_substitute` instead
## Status After Claim ## Status After Claim
``` ```
pending → claimed (Developer/PM) pending → claimed (Developer via i_will_work_on / PM)
needs_revision → claimed (Developer) needs_revision → claimed (Developer via i_will_work_on)
awaiting_qa → claimed (QA) awaiting_qa → claimed (QA via claim_review)
awaiting_documentation → claimed (Documenter) awaiting_documentation → claimed (Documenter via claim_doc_task)
``` ```
## Cannot Claim ## Cannot Claim
+50 -34
View File
@@ -2,47 +2,63 @@
## Overview ## Overview
Planning is **required** before starting work. The workflow enforces: Planning is a **PM activity**. When a PM (Cell PM or Main PM) picks up a
``` coordination or parent task, they record a plan with `i_will_plan` and
CLAIM → PLAN → START → EXECUTE then fan the work out into subtasks with `delegate`.
```
## Workflow States
| State | Meaning | Next Step |
|-------|---------|-----------|
| `NEEDS_PLAN` | Task claimed, no plan yet | Call `roboco_task_plan()` |
| `READY_TO_START` | Plan approved, ready to work | Call `roboco_task_start()` |
| `EXECUTING` | Work in progress | Continue development |
| `REVISION_REQUIRED` | QA/PM requested changes | Reclaim and fix |
## Submitting a Plan
``` ```
roboco_task_plan(task_id, { triage / give_me_work → i_will_plan → delegate (one per subtask) → i_am_idle
"approach": "High-level implementation strategy", ```
"sub_tasks": [
{"title": "Step 1", "description": "First action"}, Developers do not have a separate planning verb — they pass a short
{"title": "Step 2", "description": "Second action"} `plan` argument directly to `i_will_work_on(task_id, plan="...")` when
they claim a coding task.
## Submitting a Plan (PM)
```python
i_will_plan(
task_id="<task>",
plan="One-paragraph summary of how this work will be broken down",
approach="High-level implementation strategy",
sub_tasks=[
"UX/UI: design the settings panel",
"Frontend: wire the panel to the API",
"Backend: add the settings endpoint",
], ],
"risks": ["Potential blockers or issues"], technical_considerations=["Reuse the existing config service"],
"open_questions": ["Clarifications needed from PM"] risks=["Frontend depends on the UX design landing first"],
}) open_questions=["Confirm the default toggle state with the CEO"],
)
``` ```
## Cannot Start Without Plan After `i_will_plan`, the envelope's `next` field points you at
`delegate` — create one subtask per unit of work:
Calling `roboco_task_start()` without a plan returns: ```python
- Error code: `NO_PLAN` delegate(
- Message: "Cannot start without a plan" parent_task_id="<task>",
- Hint: Submit plan first title="Add the settings endpoint",
description="...",
assigned_to="be-dev-1",
team="backend",
task_type="code",
nature="feature",
estimated_complexity="medium",
acceptance_criteria=["Endpoint returns 200 with the saved settings"],
)
```
## Git Workflow ## Git Workflow
All tasks follow the git workflow: All code tasks follow the git workflow:
- **Branches are auto-created when you claim the task** - **Branches are auto-created when a developer claims the task** via
- Root tasks: branch created from default branch (main/master) `i_will_work_on` — no manual branch creation
- Subtasks: branch forked from parent's branch - Root tasks: branch created from the default branch (main/master)
- No manual `roboco_git_create_branch()` needed - Subtasks: branch forked from the parent's branch
Hierarchical branch naming: `feature/team/ROOT_ID/SUB_ID/SUBSUB_ID` Coordination/parent tasks that only plan and delegate (no code) do not
need a branch of their own.
Hierarchical branch naming uses `--` between task IDs to avoid git ref
conflicts: `feature/{team}/{ROOT}--{SUB}--{SUBSUB}`.
+12 -11
View File
@@ -34,20 +34,20 @@ pending → claimed → in_progress → verifying → awaiting_qa
### QA Flow ### QA Flow
``` ```
awaiting_qa → claimed → in_progress → pass/fail awaiting_qa → claimed (claim_review) → pass/fail
pass: awaiting_documentation pass: awaiting_documentation
fail: needs_revision fail: needs_revision
``` ```
### Documenter Flow ### Documenter Flow
``` ```
awaiting_documentation → claimed → in_progress → awaiting_pm_review awaiting_documentation → claimed (claim_doc_task) → awaiting_pm_review
``` ```
### PM Activation ### PM Activation
``` ```
backlog → pending (via roboco_task_activate) backlog → pending (a PM activates the task during `triage`)
``` ```
## Role-Restricted Transitions ## Role-Restricted Transitions
@@ -63,7 +63,7 @@ backlog → pending (via roboco_task_activate)
| `awaiting_pm_review → awaiting_ceo_approval` | cell_pm, main_pm (parent tasks only) | | `awaiting_pm_review → awaiting_ceo_approval` | cell_pm, main_pm (parent tasks only) |
| `awaiting_ceo_approval → completed` | ceo only | | `awaiting_ceo_approval → completed` | ceo only |
| `awaiting_ceo_approval → needs_revision` | ceo only | | `awaiting_ceo_approval → needs_revision` | ceo only |
| `any → cancelled` | cell_pm, main_pm | | `any → cancelled` | cell_pm, main_pm, ceo |
## CEO Approval Notes ## CEO Approval Notes
@@ -73,7 +73,8 @@ backlog → pending (via roboco_task_activate)
## Checking State ## Checking State
```python You don't poll task state directly — every flow verb returns a
task = roboco_task_get(task_id) standardized envelope whose `status` and `next` fields tell you the
# task.status contains current state task's current state and what to call next. Trust the envelope rather
``` than guessing. To pull the full task context (criteria, prior notes,
handoff), call `evidence(task_id)`.