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_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.
```python
# CORRECT - Use slug
roboco_task_create(assigned_to="be-dev-1", ...)
# CORRECT - Use slug (PMs delegate work)
delegate(assigned_to="be-dev-1", ...)
# 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)
@@ -73,9 +73,11 @@ roboco_task_create(assigned_to="00000000-0000-0000-0001-000000000001", ...)
## 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
roboco_task_claim(task_id) # task_id is UUID
roboco_journal_read_team("be-dev-1") # slug works
roboco_journal_read_team("00000000-0000-0000-0001-000000000001") # UUID works
i_will_work_on(task_id) # task_id is a UUID
dm(recipient="be-qa", text="...", task_id="...") # slug recipient
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 |
|------|------|---------|
| `main-pm-board` | Main PM & Board | main-pm, product-owner, head-marketing, auditor |
| `board-private` | Board Private | product-owner, head-marketing, auditor, ceo |
| `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 (read/write) + main-pm (read-only) |
## Special Channels
@@ -35,7 +35,7 @@ All available channels with their slugs and access rules.
## Auditor Silent Access
Auditor has silent read access to:
Auditor has silent read access (in these channels' `silent_roles`) to:
- `backend-cell`
- `frontend-cell`
- `uxui-cell`
@@ -44,28 +44,34 @@ Auditor has silent read access to:
- `pm-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
These roles bypass normal membership checks:
- **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
## Using Channels
```python
# Send message to your cell
roboco_message_send({
channel: "backend-cell",
content: "Starting work on task",
task_id: task_id
})
# List the channel slugs you can read / write (call this first if unsure of
# a slug — inventing slugs returns "Channel not found")
channels() # -> {writable: [...], readable: [...]}
# Read channel history
roboco_channel_history("backend-cell", limit=50)
# Send a message to your cell
say(
channel="backend-cell",
text="Starting work on task",
task_id=task_id,
)
# List available channels
roboco_channel_list()
# Direct agent-to-agent message (same-cell only)
dm(recipient="be-qa", text="Quick sanity check before QA", task_id=task_id)
```
+30 -11
View File
@@ -30,8 +30,12 @@
| Channel | Members |
|---------|---------|
| #main-pm-board | Main PM, Board |
| #board-private | Board only |
| #main-pm-board | Main PM, Product Owner, Head Marketing, Auditor |
| #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
@@ -42,11 +46,18 @@
## 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
- Cannot send messages
- Cannot send messages there
- 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
| Role | Own Cell | Cross-Cell | Management |
@@ -54,17 +65,25 @@ Auditor has **silent read access** to ALL channels:
| Developer | Read/Write | Read/Write | - |
| QA | 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 |
| Board | - | - | Read/Write |
| Auditor | Silent Read | Silent Read | Silent Read |
| Auditor | Silent Read | Silent Read | Read/Write |
## Messaging
Agents post to channels with the `say` content tool (there is no
`roboco_message_send` tool):
```python
roboco_message_send({
channel: "backend-cell",
content: "Starting work on rate limiting",
task_id: task_id
})
say(
channel="backend-cell",
text="Starting work on rate limiting",
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
```python
roboco_task_escalate(
escalate_up(
task_id="uuid-here",
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
roboco_task_escalate_to_ceo(
escalate_to_ceo(
task_id="uuid-here",
notes="Major feature ready for approval"
reason="Major feature ready for approval"
)
```
Requirements:
- Task in `awaiting_pm_review`
- 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
+42 -21
View File
@@ -19,16 +19,26 @@ What each role can do in the system.
|--------|-----|-------|---------|---------|---------|-----|----|----|
| View All | Yes | Yes | Yes | Yes | - | - | - | - |
| View Own | - | - | - | - | Yes | Yes | Yes | Yes |
| Create | Yes | Yes | Yes | Yes | Yes | - | - | - |
| Assign | Yes | Yes | Yes | Yes | Yes | - | - | - |
| Cancel | - | Yes | - | Yes | Yes | - | - | - |
| Close | Yes | Yes | Yes | Yes | Yes | Yes | - | Yes |
| Create (`delegate`) | - | - | - | Yes | Yes | - | - | - |
| Assign | - | - | - | Yes | Yes | - | - | - |
| Cancel | Yes | - | - | Yes | Yes | - | - | - |
| Complete (`complete`) | - | - | - | Yes | Yes | - | - | - |
| Claim | - | - | - | Yes | Yes | Yes | Yes | Yes |
| Pass QA | - | - | - | - | - | - | Yes | - |
| Fail QA | - | - | - | - | - | - | Yes | - |
| Docs Complete | - | - | - | - | - | - | - | Yes |
| Pass QA (`pass`) | - | - | - | - | - | - | Yes | - |
| Fail QA (`fail`) | - | - | - | - | - | - | 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
@@ -45,36 +55,47 @@ Note: Board (Product Owner, Head Marketing) can only index docs, not code.
## 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 |
| product_owner | Yes | Management chain |
| head_marketing | Yes | Management chain |
| auditor | Yes | All |
| auditor | No | - (silent observer) |
| main_pm | Yes | All |
| cell_pm | Yes | Own cell |
| developer | No | - |
| qa | 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:
- `ceo`
- `product_owner`
- `head_marketing`
## Task-Creator Roles
These roles can create/assign tasks (`create_subtask`, `delegate` — PM-only
per `lifecycle.py`):
- `main_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
These roles can cancel tasks:
- `product_owner`
- `head_marketing`
- `main_pm`
These roles can cancel tasks (the `cancel` action's `allowed_roles` in
`lifecycle.py` = PM roles + CEO):
- `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
+10 -17
View File
@@ -55,21 +55,13 @@ ROBOCO_WORKSPACE_CLONE_TIMEOUT=300
3. **Branch Flexibility**: Different branches simultaneously
4. **Clean State**: Fresh clone if needed
## MCP Tools
## No Workspace Tools — It's Automatic
| Tool | Purpose |
|------|---------|
| `roboco_workspace_ensure` | Create workspace if needed |
| `roboco_workspace_status` | Check workspace state |
| `roboco_workspace_list` | List all workspaces (PM only) |
```python
# Ensure workspace exists (auto-clones if needed)
roboco_workspace_ensure(project_slug="roboco")
# Check status
roboco_workspace_status(project_slug="roboco")
```
There are **no** agent-facing workspace tools. Workspaces are created and
cloned for you by the orchestrator (`WorkspaceService`) before your
container starts. You never `ensure`, `clone`, or `checkout` a workspace
by hand — your repo is already on disk at the path below, and the gateway
verbs (`i_will_work_on`, `claim_review`, ...) check out the right branch.
## 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 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.
PMs use `roboco_project_update(slug, git_token="...")` to set credentials.
**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
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
2. Quality oversight
3. Report issues to CEO
3. Record findings privately
4. No interference with workflow
## What You CAN Do
- View ALL tasks (organization-wide)
- View ALL channels (silent observer)
- Search and query knowledge base
- View KB statistics
- Create tasks (for reporting findings)
- Assign tasks (to escalate issues)
- Triage / view tasks in your scope via `triage()` (read-only)
- Discover and read channels via `channels()`
- See your inbox via `notify_list()` / `notify_get(notification_id)`
- Record private observations via `note(text="...", scope="reflect")`
- Attach evidence via `evidence(task_id)`
- Search the knowledge base via `roboco_ask_mentor` / `roboco_kb_search`
## What You CANNOT Do
- Claim tasks
- Update tasks
- Clear KB indexes
- Write to most channels (silent observer)
- Cancel tasks
- Claim, create, assign, complete, or cancel tasks
- Pass or fail QA
- Escalate (`triage` is your only flow verb besides `i_am_idle`)
- Post to channels (`say`), DM agents (`dm`), or send `notify`
- Acknowledge notifications (silent observer — `notify_ack` is not yours)
- Write to project docs, write code, or run git write operations
## Silent Observer Mode
The Auditor has **silent read access** to all channels:
- Can read all channel history
- Does NOT appear in member lists
- Cannot send messages (except to CEO)
- Observations logged privately
The Auditor has **silent read access** across the org:
- Reads task state, channels, and the knowledge base
- Cannot send messages outward — there is no `say` / `dm` / `notify`
- Observations are recorded privately via `note(scope="reflect")`
## Observation Areas
@@ -48,57 +48,34 @@ Monitor for:
- Unusual patterns
- 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
# Create task for CEO attention
roboco_task_create({
title: "Audit Finding: [Issue]",
description: "Details of finding",
team: "board",
assigned_to: "ceo"
})
note(
text="Audit finding: be-dev-1 skipped tests on task X; AC #3 unverified.",
scope="reflect",
)
evidence(task_id="...") # attach the evidence trail to the finding
```
## 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 |
|---------|---------|
| `roboco_git_status/log/diff` | All `Write/Edit` |
| `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 |
**Read-only observer.** No `say`, `dm`, `notify`, `commit`, or any write
verb is in your manifest. All `Write/Edit` and native git commands are
blocked.
## Communication
The Auditor primarily observes and reports. Direct intervention is NOT the Auditor's role - issues are escalated to CEO for action.
## A2A
```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)`
The Auditor observes and records — it does not intervene. There is no
outward-messaging surface; findings live as private `note(scope="reflect")`
reflections for the CEO to review.
+29 -48
View File
@@ -4,7 +4,7 @@
- **Agent**: ceo (Renzo - Human)
- **Role**: `ceo`
- **Team**: executive
- **Team**: board
- **Reports to**: N/A (top of hierarchy)
## Core Responsibilities
@@ -14,69 +14,50 @@
3. Set strategic direction
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
- Approve/reject tasks in `awaiting_ceo_approval`
- Force complete tasks with cancelled subtasks
- Send notifications to anyone
- Full access to 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.
- Approve or reject tasks in `awaiting_ceo_approval`
- Cancel tasks (CEO is one of the cancel-authorized roles)
- Set strategic direction
- Read all channels
## 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
# Task arrives in awaiting_ceo_approval
# CEO reviews and decides:
- **Approve** — merges the PR, task → `completed` (lifecycle `ceo_approve`)
- **Request changes** — task → `needs_revision` (lifecycle `ceo_reject`)
# Approve and complete
roboco_task_ceo_approve(task_id, notes="Approved. Great work!")
# 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`.
Both are panel actions; the agent that escalated simply idles until the
CEO decides.
## Escalation
CEO is the final escalation target. Issues escalate:
The CEO is the final escalation target:
```
Developer → Cell PM → Main PM → Product Owner → CEO
```
## A2A
```python
roboco_agent_request("product-owner", "clarification", "...", task_id)
roboco_a2a_check() # Check inbox
```
Only `main_pm`, `product_owner`, and `head_marketing` can escalate a task
to the CEO (via `escalate_to_ceo`).
## Communication
CEO has access to all channels including:
The CEO has read access to all channels, including:
- #board-private
- #announcements (write)
- #announcements
- 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
- Claim tasks in `awaiting_documentation` status
- Claim `pending` tasks (direct documentation tasks from PM)
- Complete documentation (`docs_complete`)
- Claim tasks in `awaiting_documentation` status via `claim_doc_task(task_id)`
- Claim `pending` documentation tasks via `give_me_work()`
- Signal docs complete via `i_documented(task_id, notes, files)`
- 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
- Claim developer tasks
- Index code (developer/PM only)
- Create or assign tasks (PM only)
- Pass or fail QA (QA only)
- Cancel tasks
- Send notifications
- Complete tasks (only submits for PM review)
- Send `notify` (ack-required notifications) — docs use `say` (channel)
and `dm` (A2A) only
- Complete tasks (only submits for PM review via `i_documented`)
- Document your own development work (self-documentation prevention)
## Task Flow
## Task Flow (gateway verbs)
```
awaiting_documentation → claim → start → write docs_complete
awaiting_pm_review
awaiting_documentation → claim_doc_task → write docs → i_documented
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 |
|---------|---------|
| `roboco_docs_*` | `Write/Edit` outside `/app/docs/` |
| `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 |
**Write access limited to docs.** `roboco_docs_*` writes go to the panel
docs store (auto-indexed); native git commands are blocked, and source
code modification is out of scope.
## Gather Context First
Before writing documentation:
```python
# Read developer's journey (REQUIRED)
roboco_journal_read_team(original_developer, task_id=task_id)
# Check existing docs
# Read the developer's reasoning trail — their notes / decisions are on
# the task evidence and in the KB
evidence(task_id="...")
roboco_kb_search("similar documentation")
# Read channel discussions
roboco_channel_history("backend-cell")
# Read channel discussion for this cell
channels() # discover the cell channel slug, then read its history
```
## Writing Documentation
Use `roboco_docs_write()` - handles paths and deduplication automatically:
Use `roboco_docs_write()` handles paths and deduplication automatically:
```python
roboco_docs_write({
@@ -102,44 +93,48 @@ roboco_docs_write({
## Completing Documentation
```python
roboco_task_docs_complete(task_id)
i_documented(task_id, notes="<what you documented>", files=["feature-api.md"])
```
This:
- Sets `docs_complete=True` on task
- Advances to `awaiting_pm_review` (if PR also created)
- Sends notification to PM
- Sets `docs_complete=True` on the task
- Advances to `awaiting_pm_review` (the PR is already open from pre-QA)
- The PM picks it up for review + merge
## Parallel Execution
In `awaiting_documentation`, two things happen in parallel:
| Agent | Action | Flag Set |
|-------|--------|----------|
| Documenter | Write docs | `docs_complete=True` |
| Developer | Create PR | `pr_created=True` |
Task advances to `awaiting_pm_review` only when BOTH are done.
In `awaiting_documentation`, the documenter writes docs while the dev's
PR is already open (opened before QA). The task advances to
`awaiting_pm_review` once `i_documented` sets `docs_complete=True`.
## Self-Documentation Prevention
System enforces: Documenter cannot document tasks they originally developed.
If documenter == original_developer, the claim is FORBIDDEN.
If documenter == original_developer, the claim is rejected.
## Before Completing
1. Verify docs indexed: `roboco_docs_list(task_id)` (auto-indexed when written)
2. Journal your work: `roboco_journal_entry({type: "documentation"})`
3. Write reflection: `roboco_journal_reflect()`
2. Reflect on your work: `note(text="...", scope="learning")`
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
```python
roboco_agent_request("be-dev-1", "clarification", "Need context on...", task_id)
roboco_a2a_check() # Check inbox
# Direct A2A inside your cell (same team — no policy gate)
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
Escalate to Cell PM when:
@@ -147,4 +142,6 @@ Escalate to Cell PM when:
- Scope unclear
- 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
- View ALL tasks organization-wide
- Create and assign tasks
- Cancel tasks
- Send notifications
- Index documentation
- Access management channels
- Triage actionable tasks in your scope via `triage()`
- Escalate tasks to the CEO via `escalate_to_ceo(task_id, reason)`
- Communicate: `say` (channel), `dm` (A2A), `notify` (ack-required signal)
- Open strategic sessions via `open_session`
- Read project docs via `roboco_docs_read` / `roboco_docs_list`
- Search the knowledge base via `roboco_ask_mentor` / `roboco_kb_search`
## What You CANNOT Do
- Claim tasks (board observes/approves)
- Clear/refresh KB indexes
- Claim tasks (the Board observes and approves — it does not execute work)
- 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
| Permission | Access |
|------------|--------|
| VIEW_ALL tasks | Yes |
| CREATE tasks | Yes |
| ASSIGN tasks | Yes |
| CANCEL tasks | Yes |
| CLOSE tasks | Yes |
| INDEX_DOCS | Yes |
Your flow surface is deliberately narrow: the Board steers and approves,
it does not claim, create, or complete tasks.
## Escalation
@@ -50,11 +51,17 @@ Escalates directly to 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
```python
roboco_agent_request("product-owner", "market_analysis", "...", task_id)
roboco_a2a_check() # Check inbox
dm(recipient="product-owner", text="Market analysis for the launch — ...", task_id="...")
channels() # discover channels you can post to
```
Skills: market_analysis
@@ -66,4 +73,4 @@ Access to:
- #board-private
- #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
3. Handle cross-cell dependencies
4. Monitor organization-wide progress
5. Escalate to Board when needed
5. Escalate to Board / CEO when needed
## What You CAN Do
Everything Cell PM can do, PLUS:
- Access ALL cells' tasks
- Clear and refresh KB indexes
- Triage tasks across ALL cells via `triage_all()`
- 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
When receiving work from Board/CEO:
When receiving an initiative from the Board / CEO:
```python
# 1. Claim the initiative
roboco_task_claim(initiative_id)
roboco_task_start(initiative_id)
# 1. Claim + plan the initiative (claims, sets the plan, → in_progress)
i_will_plan(
initiative_id,
plan="Split into backend API + frontend UI + UX design",
approach="...",
)
# 2. Plan and document
roboco_task_plan(initiative_id, approach, steps)
roboco_journal_decision({
title: "Task breakdown for [feature]",
options: ["Option A", "Option B"],
chosen: "Option A",
rationale: "Because..."
})
# 2. Record the decision as you go
note(
text="Chose Option A over B because ...",
scope="decision",
title="Task breakdown for [feature]",
)
# 3. Create subtasks for each cell
roboco_task_create({
title: "Backend: Implement API",
team: "backend",
parent_task_id: initiative_id,
status: "backlog",
assigned_to: "be-pm"
})
# 3. Delegate a subtask to each cell PM (parent must be in_progress)
delegate(
parent_task_id=initiative_id,
title="Backend: Implement API",
description="...",
assigned_to="be-pm",
team="backend",
task_type="planning",
nature="...",
estimated_complexity="...",
acceptance_criteria=["..."],
project_id="<project-uuid>",
)
# 4. Create session for coordination
roboco_session_create_for_tasks({
title: "Feature X Implementation",
task_ids: [subtask_1_id, subtask_2_id]
})
# 4. Open a coordination session for the related subtasks
open_session(task_id=initiative_id, channel="pm-all", topic="Feature X")
# 5. Activate and notify Cell PMs
roboco_task_activate(subtask_id)
roboco_notify_send({
recipient: "be-pm",
type: "task_assignment",
task_id: subtask_id
})
# 5. Notify the Cell PMs (ack-required signal)
notify(target="be-pm", text="New initiative assigned — see task", 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
Monitor via:
```python
# Check all cells
roboco_task_scan() # No team filter = all teams
# PM channel discussions
roboco_channel_history("pm-all")
# Read Cell PM journals
roboco_journal_read_team("be-pm")
roboco_journal_read_team("fe-pm")
triage_all() # actionable tasks across all teams (Main PM only)
channels() # discover the pm-all channel, then read its history
```
## 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 |
|---------|---------|
| `roboco_git_*` | Native `Bash(git:*)` |
| `roboco_docs_*` | - |
| `roboco_notify_send` | - |
| All task management | - |
Native `git` commands are blocked by the bash-guard hook — use the
read-only git views and let the choreographer handle PR merges on
`complete`.
See: `roboco_kb_search("tool permissions")`
## Projects and Git Tokens
## Key Tools
| Tool | Purpose |
|------|---------|
| `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
)
```
Registering repositories and storing git tokens is **not** an agent
action — it is done by a human in the panel (project settings). Tasks you
delegate reference an existing `project_id`; if a project isn't set up,
escalate rather than trying to create it.
## Handling Cell PM Escalations
When Cell PM escalates:
1. ACK immediately
2. Review cross-cell impact
3. Coordinate with other Cell PMs if needed
4. Make decision or escalate to Board
When a Cell PM escalates:
1. Review cross-cell impact
2. Coordinate with other Cell PMs if needed
3. Make the decision (`unblock`, `complete`) or escalate up
## A2A
```python
roboco_agent_request("be-pm", "coordination", "...", task_id)
roboco_a2a_check() # Check inbox
dm(recipient="be-pm", text="Coordinating the API contract — ...", task_id="...")
channels() # discover channels you can post to
```
## Escalation
Escalate to Product Owner when:
Escalate to the CEO when:
- Strategic direction needed
- Major scope change
- Resource constraints
- 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
2. Clarify requirements
3. Approve feature implementations
4. Handle escalations from Main PM
3. Review and approve feature direction
4. Handle escalations from Main PM, escalate to CEO
## What You CAN Do
- View ALL tasks organization-wide
- Create and assign tasks
- Cancel tasks
- Send notifications
- Index documentation
- Access management channels
- Triage actionable tasks in your scope via `triage()`
- Escalate tasks to the CEO via `escalate_to_ceo(task_id, reason)`
- Communicate: `say` (channel), `dm` (A2A), `notify` (ack-required signal)
- Open strategic sessions via `open_session`
- Read project docs via `roboco_docs_read` / `roboco_docs_list`
- Search the knowledge base via `roboco_ask_mentor` / `roboco_kb_search`
## What You CANNOT Do
- Claim tasks (board observes/approves)
- Clear/refresh KB indexes
- Claim tasks (the Board observes and approves — it does not execute work)
- 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
| Permission | Access |
|------------|--------|
| VIEW_ALL tasks | Yes |
| CREATE tasks | Yes |
| ASSIGN tasks | Yes |
| CANCEL tasks | Yes |
| CLOSE tasks | Yes |
| INDEX_DOCS | Yes |
Your flow surface is deliberately narrow: the Board steers and approves,
it does not claim, create, or complete tasks.
## Escalation
Receives escalations from Main PM.
Escalates to CEO for final authority.
Receives escalations from Main PM. Escalates to CEO for final authority.
```
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
```python
roboco_agent_request("main-pm", "coordination", "...", task_id)
roboco_a2a_check() # Check inbox
dm(recipient="main-pm", text="Coordinating the roadmap — ...", task_id="...")
channels() # discover channels you can post to
```
Skills: requirements_clarification, feature_approval
@@ -68,4 +74,4 @@ Access to:
- #board-private
- #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
## 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.
**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.
## Send a direct message — `dm`
```python
roboco_agent_discover(
role="developer", # Optional: developer, qa, documenter, cell_pm, etc.
team="backend", # Optional: backend, frontend, ux_ui
skill="code_review" # Optional: specific capability
dm(
recipient="be-qa", # target agent slug
text="Please review my changes",
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
roboco_agent_request(
target_agent="be-qa",
skill="code_review",
message="Please review my changes",
task_id="abc123...", # REQUIRED
options={"urgent": False} # Optional: priority queue
)
channels() # -> {"writable": [...], "readable": [...]}
say(channel="backend-cell", text="Anyone hit Y before? Starting task X.")
```
**Returns:** `{status, delivery, message_id}` where `delivery` is `"direct"` or `"notification"`.
## Receive incoming messages
### roboco_a2a_check
Poll your inbox for incoming A2A messages.
Incoming A2A and @mentions land in your notify inbox. When `i_am_idle()`
soft-blocks on unread items, drain the inbox:
```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 |
|------|--------|
| Code review | `roboco_agent_request("be-qa", "code_review", "...", task_id)` |
| Clarification | `roboco_agent_request("be-pm", "clarification", "...", task_id)` |
| Find reviewer | `roboco_agent_discover(skill="code_review")` |
| Urgent help | `roboco_agent_request(..., options={"urgent": True})` |
## 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
| Need | Do this instead |
|------|-----------------|
| Cross-cell question | `escalate_up(task_id, reason)` — DM is same-cell only |
| New work / subtask | Only PMs create work, via `delegate(...)`; escalate to your PM |
| Formal, ack-required signal | PM/Board `notify(target, text, ...)` |
| Cell-wide broadcast | `say(channel=..., text=...)` |
+89 -60
View File
@@ -1,92 +1,121 @@
# 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 |
|------|---------|
| `roboco_journal_entry` | General entry |
| `roboco_journal_decision` | Decision log |
| `roboco_journal_learning` | Learning capture |
| `roboco_journal_struggle` | Problem/solution |
| `roboco_journal_reflect` | Task reflection |
```python
note(
text: str, # always: one-paragraph summary
scope: str = "note", # note | decision | reflect | learning | struggle
task_id: str | None = None, # auto-filled from your active task if omitted
title: str | None = None,
# 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
```python
roboco_journal_entry({
type: "learning",
title: "Redis SCAN vs KEYS",
content: "SCAN is better for large datasets",
task_id: task_id,
tags: ["redis", "performance"]
})
note(
text="SCAN is better than KEYS for large datasets",
scope="learning",
title="Redis SCAN vs KEYS",
task_id=task_id,
)
```
Entry types: `task_reflection`, `decision_log`, `learning`, `struggle`, `general`
## Decision Log
```python
roboco_journal_decision({
title: "Session storage choice",
context: "Need fast session lookups",
options: ["PostgreSQL", "Redis"],
chosen: "Redis",
rationale: "Sub-ms reads, ephemeral data"
})
note(
text="Chose Redis for session storage over PostgreSQL.",
scope="decision",
title="Session storage choice",
context="Need fast session lookups",
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
```python
roboco_journal_learning({
content: "asyncio.gather for parallel calls",
how_applied: "Reduced latency 50%",
category: "performance",
tags: ["async"]
})
note(
text="asyncio.gather for parallel calls — reduced latency 50%",
scope="learning",
title="Parallel async calls",
)
```
## Struggle (Problem/Solution)
## Struggle (Problem / Blocker)
```python
roboco_journal_struggle({
task_id: task_id,
problem: "Tests failing intermittently",
attempts: ["Timeout increase", "Retry logic"],
resolution: "Race condition in setup"
})
note(
text=(
"Tests failing intermittently — tried timeout increase and retry "
"logic; root cause was a 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
roboco_journal_reflect({
task_id: task_id,
what_done: "Implemented rate limiting",
what_learned: "Lua scripts for atomicity",
what_struggled: "Testing concurrency"
})
note(
text="Implemented rate limiting with a Redis-backed sliding window.",
scope="reflect",
task_id=task_id,
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
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
# Search your journal
roboco_journal_search("rate limiting", top_k=5)
# Semantic search over indexed notes/decisions/learnings
roboco_kb_search(query="rate limiting", index_types=["journals", "decisions"])
# Recent entries
roboco_journal_recent(limit=10)
# 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()
# Conversational lookup with follow-up context
roboco_ask_mentor(question="What did we decide about session storage?")
```
+54 -58
View File
@@ -1,84 +1,80 @@
# 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
roboco_message_send({
channel: "backend-cell",
content: "Starting work on rate limiting",
task_id: task_id
})
say(channel="backend-cell", text="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
# Read channel history
roboco_channel_history(
channel="backend-cell",
limit=50
)
channels() # -> {"writable": [...], "readable": [...]}
```
## 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
roboco_notify_send({
recipient: "be-dev-1",
type: "task_assignment",
task_id: task_id,
message: "Task ready for you"
})
dm(recipient="be-qa", text="Quick sanity check: ...", task_id=task_id)
```
### 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
# List notifications
notifications = roboco_notify_list()
# Acknowledge
roboco_notify_ack(notification_id)
notify(target="be-dev-1", text="Task ready for you", priority="normal", task_id=task_id)
```
### Notification Types
`priority` is `normal | high | urgent`. `task_id` auto-injects from the
active task when omitted.
| Type | Purpose |
|------|---------|
| `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 |
## Receiving notifications
## Sessions
Every role with an inbox gets these (so `i_am_idle()` doesn't soft-block
on unread items):
```python
# Create session for tasks
roboco_session_create_for_tasks({
title: "Feature X Implementation",
task_ids: [task_1_id, task_2_id]
})
# Start collaborative session
roboco_session_start(
channel="backend-cell",
session_type="collaborative",
task_id=task_id
)
notify_list(unread_only=True, limit=20) # your inbox
notify_get(notification_id) # read one (marks it read)
notify_ack(notification_id) # acknowledge after handling
```
## 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 |
|------|---------|
| `reasoning` | Thought process |
| `dialogue` | Discussion |
| `decision` | Decisions made |
| `action` | Actions taken |
| `blocker` | Blocking issues |
| `technical` | Technical details |
## Sessions (PM-or-up only)
Devs / QA / docs participate via channels and DMs and do **not** open
sessions. PMs and the Board link discussion threads to tasks:
```python
open_session(task_id, channel="backend-cell", topic="Feature X kickoff",
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
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
roboco_project_list() # All accessible projects
roboco_project_list(cell="backend") # Filter by cell
roboco_git_status(project_slug="roboco")
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
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).
## Create Project (PM+ Only)
```python
# 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.
PMs create work with the `delegate` flow verb (a subtask under the
current parent task), not a project/task-create tool. `delegate` takes an
optional `project_id`; the parent task's project is inherited when you
omit it. There is no agent-facing standalone project- or task-create
tool.
+107 -86
View File
@@ -1,111 +1,132 @@
# 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 |
|------|---------|
| `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 |
The verbs below are grouped by who calls them.
## Task Retrieval
## Developer flow
```python
# Get specific task
task = roboco_task_get(task_id)
# Scan for available tasks
tasks = roboco_task_scan(
team="backend", # Optional filter
status="pending" # Optional filter
)
give_me_work() # returns your most-actionable pending task
i_will_work_on(task_id, plan="...")
# claims + sets plan + starts; auto-creates and
# checks out feature/{team}/{task-hierarchy}
commit(message, files=None) # content tool — repeat per change (auto-pushed)
open_pr(task_id) # pushes branch + opens the PR
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
# Claim task
roboco_task_claim(task_id)
# Release if you shouldn't work on it
roboco_task_unclaim(task_id)
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)
give_me_work() # returns an awaiting_qa task
claim_review(task_id) # claim for review (auto-checks-out dev branch)
pass(task_id, notes) # awaiting_qa -> awaiting_documentation
fail(task_id, issues=[...]) # awaiting_qa -> needs_revision (dev gets it back)
unclaim(task_id) / resume(task_id) / i_am_idle()
```
## 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
# Submit for verification
roboco_task_submit_verification(task_id)
# Submit for QA
roboco_task_submit_qa(task_id, notes)
# 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)
give_me_work() # returns an awaiting_documentation task
claim_doc_task(task_id) # claim the doc phase
commit(message, files) # commit the doc files you write
i_documented(task_id, notes, files)
# awaiting_documentation -> awaiting_pm_review
```
## PM Operations
Documentation tasks are **not** delegated — the lifecycle auto-creates
the doc phase after a code task passes QA.
## Cell PM flow
```python
# Create SUBTASK (most common)
roboco_task_create({
title: "Implement auth endpoint",
parent_task_id: my_task_id, # REQUIRED for subtasks
team: "backend",
assigned_to: "be-dev-1" # Use SLUG
})
# Create standalone task (rare)
roboco_task_create({
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)
triage() # list actionable tasks in your cell
i_will_plan(task_id, plan, approach)
# claim + plan + start a parent task
delegate(parent_task_id, title, description, assigned_to, team,
task_type, nature, estimated_complexity, acceptance_criteria)
# 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
complete(task_id, notes) # awaiting_pm_review -> completed (merges leaf PR)
escalate_up(task_id, reason) # escalate to your escalation target
```
**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
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**:
| Action | Allowed Roles |
|--------|---------------|
| Create task | PM, Board |
| Cancel task | PM |
| Create / delegate task | PM only (Cell PM, Main PM) |
| Cancel task | PM, CEO |
| Pass/fail QA | QA only |
| Complete docs | Documenter only |
| Complete task | PM only |
| Send notification | PM, Board |
| Send notification (`notify`) | PM, Board |
**Solution**: Request appropriate role to perform action
@@ -42,22 +42,23 @@
3. Already acknowledged
**Solutions**:
- Check `roboco_notify_list()` for all notifications
- Check `notify_list()` for all notifications
- Verify sender has PM/Board role
- Check if already in `acked_by`
- Check if already acknowledged via `notify_get(notification_id)`
## Escalation Not Routing
**Problem**: Escalation went to wrong person
**Cause**: Escalation auto-routes to your escalation target
**Cause**: `escalate_up` auto-routes to your escalation target
**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
@@ -123,21 +124,25 @@ roboco_docs_write({
## A2A Message Not Delivered
**Problem**: Sent A2A message but no response
**Problem**: Sent a `dm` but no response
**Check**:
1. Did you include `task_id`? (required)
2. Check delivery status in response: `"direct"` or `"notification"`
3. If `"notification"` - target was offline, will be spawned
1. Is the recipient in your **own cell**? Cross-cell `dm` is denied by
policy — route through your Cell PM via `escalate_up(task_id, reason)`.
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**:
- Direct delivery: Target should check `roboco_a2a_check()`
- Notification delivery: Wait for target to be spawned
- Same-cell peer: `dm(recipient="be-qa", text="...", task_id="...")`
- 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
**Solutions**:
- Check task status: `roboco_task_get(task_id)`
- Verify your role can claim from current status
- Check what's actionable for you: `give_me_work()` (or `triage()` for PMs)
- Verify your role can claim from the task's current status
- Contact PM if task needs reassignment
**Claimable Status by Role**:
| Role | Can Claim From |
|------|----------------|
| Developer | pending, needs_revision |
| QA | awaiting_qa |
| Documenter | awaiting_documentation |
| Role | Can Claim From | Verb |
|------|----------------|------|
| Developer | pending, needs_revision | `i_will_work_on(task_id)` |
| QA | awaiting_qa | `claim_review(task_id)` |
| Documenter | pending, awaiting_documentation | `claim_doc_task(task_id)` |
| Cell PM / Main PM | pending | `i_will_plan(task_id)` |
## Cannot Start Task
@@ -30,7 +31,9 @@
2. Task in wrong status
**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
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
**Solution**: Another QA must handle this task. Self-review prevention applies to:
- Claiming the task
- Passing QA (`roboco_task_qa_pass`)
- Failing QA (`roboco_task_qa_fail`)
- Claiming the task (`claim_review`)
- Passing QA (`pass`)
- Failing QA (`fail`)
## 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`
**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
# Get the parent task ID
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(task_id=parent_id, reason="...")
```
`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
@@ -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
**Solution**: The error message includes which subtask IDs are blocking. Either:
1. Complete the blocking subtasks first
2. Cancel them if no longer needed: `roboco_task_cancel(subtask_id, reason)`
1. Complete the blocking subtasks first (drive them through QA → docs →
`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
+41 -46
View File
@@ -2,73 +2,68 @@
## 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
```
1. Discover → roboco_agent_discover(role, team, skill)
2. Request → roboco_agent_request(target, skill, message, task_id)
3. Check → roboco_a2a_check() polls your inbox (auto-notified via hook)
4. Respond → Work on task or reply via roboco_agent_request
1. Discover → channels() lists the channels visible to you
2. Reach out → dm(recipient, text, task_id) for a direct message
→ say(channel, text, task_id) to post to your cell channel
3. Receive → notify_list() / notify_get(id) to read your inbox
```
## Delivery
| Target State | Delivery | Creates Notification? |
|--------------|----------|----------------------|
| Online | Direct HTTP to SDK | NO |
| Offline | Fallback via API | YES (spawns target) |
## Example
## Direct Messages (same cell only)
```python
# Request code review for task ABC123
result = roboco_agent_request(
target_agent="be-qa",
skill="code_review",
message="Please review my changes",
task_id="ABC123"
# Direct A2A inside your cell (same team — no policy gate)
dm(
recipient="be-qa",
text="Quick sanity check on the rate-limit boundary before I open the PR?",
task_id="<task>",
)
# 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
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
| Role | Skills |
|------|--------|
| Developer | `code_review`, `implementation`, `debugging`, `revision` |
| QA | `code_review`, `testing`, `qa_review` |
| Documenter | `documentation`, `api_docs` |
| PM | `task_planning`, `coordination`, `clarification` |
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.
## 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:
1. Escalate: `roboco_task_escalate(task_id, "Needs subtask for X")`
2. PM decides whether to create subtask
If a conversation surfaces work that needs a new task:
1. Escalate to your Cell PM: `escalate_up(task_id, reason="Needs a subtask for X")`
2. The PM decides whether to `delegate` a subtask
## Permissions
All agents can:
- Discover other agents
- Send A2A requests (must include task_id)
- Check request status
Most roles can `dm` (same-cell) and `say` to their channels, plus read
their inbox with `notify_list` / `notify_get`.
All agents CANNOT:
- Create tasks via A2A (no automatic task creation)
- Send A2A without a task_id
The **Auditor** is a silent observer: it can read (`notify_list`,
`notify_get`, `channels`) but has **no** `say`, `dm`, or `notify` — it
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
Product Owner
Product Owner / Head of Marketing (Board)
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
roboco_task_escalate(
task_id="uuid-here",
reason="Need clarification on API contract"
escalate_up(
task_id="<task>",
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
@@ -35,47 +42,51 @@ Auto-routes to your escalation target (you cannot choose).
| Blocked by external factor | Cell PM |
| Blocked by another task | 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` |
| **Block** | Waiting on another task | `roboco_task_block` |
| **Pause** | Temporarily stop work | `roboco_task_pause` |
| **Escalate** | Need a decision / help from above | `escalate_up` |
| **Block** | Can't proceed on an external dependency | `i_am_blocked` |
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
```python
# Block on another task
roboco_task_block(
task_id="uuid-here",
blocker_task_id="blocker-uuid",
reason="Waiting for auth service"
i_am_blocked(
task_id="<task>",
reason="Waiting for the auth service to land",
blocker_type="external",
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:
```python
roboco_task_escalate_to_ceo(
task_id="uuid-here",
notes="Major feature ready for final review"
escalate_to_ceo(
task_id="<task>",
reason="Major feature ready for final review",
)
```
Requirements:
- Task must be in `awaiting_pm_review`
- PR must exist
- Only PMs can do this
- **PARENT TASKS ONLY** - Subtasks cannot be escalated to CEO
- Only Main PM, Product Owner, or Head of Marketing can call it
- **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
@@ -88,10 +99,11 @@ Include:
## Handling Escalations (PM)
1. ACK immediately: `roboco_notify_ack(notification_id)`
2. Investigate: Read task, journals, messages
3. Decide or escalate further
4. Communicate decision
5. Unblock if needed: `roboco_task_unblock(task_id)`
1. ACK the notification: `notify_ack(notification_id)`
2. Investigate: read the task, journals, and channel messages
3. Decide, or escalate further with `escalate_up`
4. Communicate the decision (`say` / `dm` / `notify`)
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
4. Required before key transitions
## Entry Types
## The Tool
| Type | Use For |
|------|---------|
| `task_reflection` | End of task summary |
| `decision_log` | Architectural decisions |
Journaling is a single content tool: `note(text, scope, ...)` on the
`roboco-do` MCP server. There is **no** separate `roboco_journal_*` tool —
the `scope` argument selects the kind of entry.
| `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 |
| `struggle` | Problems and solutions |
| `general` | Other observations |
## Creating Entries
```python
# General entry
roboco_journal_entry({
type: "learning",
title: "Redis SCAN vs KEYS",
content: "SCAN is better for large datasets",
task_id: task_id,
tags: ["redis", "performance"]
})
note(
text="SCAN is better than KEYS for large Redis datasets",
scope="learning",
task_id=task_id,
)
# Decision log
roboco_journal_decision({
title: "Session storage choice",
context: "Need fast session lookups",
options: ["PostgreSQL", "Redis", "In-memory"],
chosen: "Redis",
rationale: "Sub-millisecond reads, ephemeral data"
})
# Decision log`decision` scope uses the structured fields
note(
text="Chose Redis for session storage",
scope="decision",
task_id=task_id,
context="Need fast session lookups, 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)
roboco_journal_struggle({
task_id: task_id,
problem: "Tests failing intermittently",
attempts: ["Increased timeout", "Added retry"],
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"]
})
note(
text="Tests failing intermittently; root cause was a setup race condition",
scope="struggle",
task_id=task_id,
)
```
`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
Before submitting for QA or completing:
Before submitting for QA or completing, write a `reflect` entry:
```python
roboco_journal_reflect({
task_id: task_id,
what_done: "Implemented rate limiting with Redis",
what_learned: "Lua scripts for atomic operations",
what_struggled: "Testing concurrent requests"
})
note(
text="Implemented rate limiting with Redis",
scope="reflect",
task_id=task_id,
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
```python
# Semantic search your journal
roboco_journal_search("rate limiting patterns", top_k=5)
Journal entries are indexed into the knowledge base. Search them through
the `roboco-optimal` RAG tools (there is no dedicated journal-search verb):
# Search team journals (if permitted)
roboco_journal_read_team("be-dev-1", task_id=task_id)
```python
# 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
1. **Journal as you go** - Don't wait until end
2. **Be specific** - Generic entries are less searchable
3. **Use tags** - Helps categorization
4. **Record failures** - They're valuable learning
3. **Record failures** - They're valuable learning (`scope="struggle"`)
4. **Use the right scope** - `decision` / `reflect` light up the panel views
5. **Include context** - Future searchers need it
+3 -2
View File
@@ -83,8 +83,9 @@ roboco_ask_mentor(
Always search first:
```python
roboco_kb_search("implementing rate limiter")
roboco_journal_search("rate limit decisions")
roboco_kb_search(query="implementing rate limiter")
# 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:
+33 -32
View File
@@ -2,27 +2,33 @@
## Who Can Claim What
| Role | Can Claim From Status |
|------|----------------------|
| Developer | `pending`, `needs_revision` |
| QA | `awaiting_qa` |
| Documenter | `awaiting_documentation`, `pending` |
| PM | `pending`, `backlog` |
| Role | Claim verb | Can Claim From Status |
|------|------------|----------------------|
| Developer | `i_will_work_on` | `pending`, `needs_revision` |
| QA | `claim_review` | `awaiting_qa` |
| Documenter | `claim_doc_task` | `awaiting_documentation`, `pending` |
| PM | `triage` / `give_me_work` | `pending` |
## Claiming a Task
```python
# 1. Find available tasks
roboco_task_scan(team="backend")
# 1. Get a task assigned to you (returns a pending/awaiting task)
give_me_work()
# 2. Claim the task
roboco_task_claim(task_id)
# 2. Claim it. The claim verb is role-specific:
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:
# - status: claimed
# - status: claimed (then in_progress)
# - 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
1. Check you have capacity (one task at a time recommended)
@@ -31,17 +37,16 @@ roboco_task_claim(task_id)
## After Claiming
1. Start work: `roboco_task_start(task_id)`
2. Announce to cell: `roboco_message_send({channel, content, task_id})`
3. Get proactive context: `roboco_get_proactive_context(task_id)`
4. Search KB for similar work: `roboco_kb_search()`
1. Announce to your cell: `say(channel="backend-cell", text="...", task_id=task_id)`
2. Get proactive context: `roboco_get_proactive_context(task_id)`
3. Search the KB for similar work: `roboco_kb_search(query="...")`
## Claiming Rules
- **One at a time**: Don't claim multiple in_progress tasks
- **Self-review prevention**: QA cannot claim tasks they developed
- **One at a time**: Don't claim multiple in-progress tasks
- **Self-review prevention**: QA cannot `claim_review` 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
@@ -49,35 +54,31 @@ If you claimed a task but realize you shouldn't work on it, use `unclaim`:
```python
# Release back to pool
roboco_task_unclaim(task_id)
# Hand off to specific agent
roboco_task_unclaim(task_id, hand_off_to="be-dev-2")
unclaim(task_id)
# Result:
# - status: pending
# - assigned_to: None (or hand_off_to agent)
# - assigned_to: None
# - 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:**
- Task is out of your team's scope
- Task requires a different role
- You need to prioritize other work
- 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
```
pending → claimed (Developer/PM)
needs_revision → claimed (Developer)
awaiting_qa → claimed (QA)
awaiting_documentation → claimed (Documenter)
pending → claimed (Developer via i_will_work_on / PM)
needs_revision → claimed (Developer via i_will_work_on)
awaiting_qa → claimed (QA via claim_review)
awaiting_documentation → claimed (Documenter via claim_doc_task)
```
## Cannot Claim
+50 -34
View File
@@ -2,47 +2,63 @@
## Overview
Planning is **required** before starting work. The workflow enforces:
```
CLAIM → PLAN → START → EXECUTE
```
## 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
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
then fan the work out into subtasks with `delegate`.
```
roboco_task_plan(task_id, {
"approach": "High-level implementation strategy",
"sub_tasks": [
{"title": "Step 1", "description": "First action"},
{"title": "Step 2", "description": "Second action"}
triage / give_me_work → i_will_plan → delegate (one per subtask) → i_am_idle
```
Developers do not have a separate planning verb — they pass a short
`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"],
"open_questions": ["Clarifications needed from PM"]
})
technical_considerations=["Reuse the existing config service"],
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:
- Error code: `NO_PLAN`
- Message: "Cannot start without a plan"
- Hint: Submit plan first
```python
delegate(
parent_task_id="<task>",
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
All tasks follow the git workflow:
- **Branches are auto-created when you claim the task**
- Root tasks: branch created from default branch (main/master)
- Subtasks: branch forked from parent's branch
- No manual `roboco_git_create_branch()` needed
All code tasks follow the git workflow:
- **Branches are auto-created when a developer claims the task** via
`i_will_work_on` — no manual branch creation
- Root tasks: branch created from the default branch (main/master)
- 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
```
awaiting_qa → claimed → in_progress → pass/fail
pass: awaiting_documentation
fail: needs_revision
awaiting_qa → claimed (claim_review) → pass/fail
pass: awaiting_documentation
fail: needs_revision
```
### Documenter Flow
```
awaiting_documentation → claimed → in_progress → awaiting_pm_review
awaiting_documentation → claimed (claim_doc_task) → awaiting_pm_review
```
### PM Activation
```
backlog → pending (via roboco_task_activate)
backlog → pending (a PM activates the task during `triage`)
```
## 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_ceo_approval → completed` | 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
@@ -73,7 +73,8 @@ backlog → pending (via roboco_task_activate)
## Checking State
```python
task = roboco_task_get(task_id)
# task.status contains current state
```
You don't poll task state directly — every flow verb returns a
standardized envelope whose `status` and `next` fields tell you the
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)`.