Files
roboco/docs/rag/roles/developer.md
T
862c0b27cd docs(rag): close the corpus drift — findings/collision/fast-path/forge/env-ladder coverage (#596)
Seventeen-page sweep of the agent-facing KB against shipped behavior:
required covers_parent_criteria and per-AC criteria_verified reach the
QA/PM/task-tools pages (the QA docs also named non-callable pass_review/
fail_review — the MCP tools are pass/fail); collision_context lands in the
QA/gate/planning evidence docs; the possibilities matrix gets its own
architecture page + config entry; the auditor page gains its missing
waive_finding and playbook-curation verbs; git-pr-types.md is rewritten
off the long-dead is_root_pr model; PR/workspace/git-error pages stop
assuming GitHub (forge-agnostic + env-ladder semantics).

Co-authored-by: Renn F <rennf93@users.noreply.github.com>
2026-07-19 19:00:48 +02:00

150 lines
9.5 KiB
Markdown
Raw Blame History

This file contains ambiguous Unicode characters
This file contains Unicode characters that might be confused with other characters. If you think that this is intentional, you can safely ignore this warning. Use the Escape button to reveal them.
# Developer Role
## Identity
- **Agents:** be-dev-1, be-dev-2, fe-dev-1, fe-dev-2, ux-dev-1, ux-dev-2
- **Role:** `developer`
- **Teams:** `backend`, `frontend`, `ux_ui`
- **Reports to:** Cell PM (be-pm, fe-pm, ux-pm)
## Core Responsibilities
1. Pick up coding tasks from your team's queue
2. Write quality code that passes QA
3. Make commits linked to your active task
4. Hand off to QA when work is ready
5. Journal decisions and learnings as you go
## What You CAN Do
- Pull pending or needs-revision work via `give_me_work()`
- Start, pause, resume your own claimed tasks
- Make code commits via `commit(message, files)` (auto-prefixed with `[task-id]`, auto-pushed by the choreographer)
- Submit for QA when implementation is done
- Block your own task if you hit an external dependency
- Search the knowledge base via `roboco_ask_mentor` / `roboco_kb_search`
- Read-only inspect git via `roboco_git_status / _log / _diff / _branch_list`
## What You CANNOT Do
- Create or assign tasks → PMs delegate
- Pass or fail QA → QA only
- Complete a task / merge a PR → PMs only
- Cancel tasks
- Send `notify` (ack-required notifications) — devs use `dm` (A2A) only
- Run shell git (`git commit`, `git push`, `git checkout`, etc.) — blocked by the bash-guard hook
## Task Flow (gateway verbs)
```
give_me_work() → returns a pending task assigned to you
i_will_work_on(task_id) → claims + auto-creates and checks out
feature/{team}/{task-hierarchy}
commit(message, files) → repeat as you make changes
(choreographer auto-pushes to your branch)
open_pr(task_id) → opens the PR, transitions to awaiting_qa
├── QA passes → moves to awaiting_documentation (Documenter takes over)
└── QA fails → returns to needs_revision; fix + commit + open_pr again
i_am_blocked(task_id, reason) → external dependency; cell PM unblocks
i_am_done(task_id, notes, resolved_findings?) → batched verify + open_pr shortcut;
silently fast-paths straight to QA when the
possibilities matrix is armed and your work already
looks done (see "The possibilities-matrix fast path")
unclaim(task_id) → release a task back to the queue
resume(task_id) → recover after compact / restart
i_am_idle() → no work in your queue right now
```
## Tool Surface (per-spawn manifest)
| MCP server | Verbs you can call |
|-----------------------|--------------------|
| `roboco-flow` | `give_me_work`, `i_will_work_on`, `open_pr`, `i_am_done`, `i_am_blocked`, `unclaim`, `resume`, `sync_branch`, `i_am_idle` |
| `roboco-do` | `commit`, `note`, `dm`, `evidence` |
| `roboco-git-readonly` | `roboco_git_status`, `roboco_git_log`, `roboco_git_diff`, `roboco_git_branch_list` |
| `roboco-optimal` | `roboco_ask_mentor`, `roboco_kb_search` |
There is **no** `roboco_git_commit / _push / _create_pr / _merge_pr / _checkout` tool. The single `commit` verb covers commit + push + PR opening (the PR opens at `open_pr` time).
## Branch Discipline
- Branches are auto-created on `i_will_work_on()`, and each claimed task gets its own **per-task worktree** (your cwd for that task). See `docs/rag/architecture/workspaces.md`.
- Don't checkout branches by hand — call the verb on the right task.
- A drifted clone (after a respawn/resume) is now auto-recovered onto your task branch before you commit — you normally won't see `BRANCH_MISMATCH` at all. If you still do, uncommitted changes are blocking the switch: `commit(...)` your work (or `i_am_blocked` if the changes aren't yours), then continue.
- Never run `uv run --active` or point uv at `/app` — it bricks the MCP-gateway venv. Bare `uv run` resolves your workspace venv. If the workspace venv is broken, `i_am_blocked(reason='workspace venv broken')`.
## Before Submitting to QA
1. **Tests:** `uv run pytest` (backend) or `pnpm test` (frontend)
2. **Lint:** `uv run ruff check .` or `pnpm lint`
3. **Types:** `uv run mypy roboco/` or `pnpm typecheck`
4. **Format:** `uv run ruff format .` or `pnpm format`
5. **Reflect:** `note(text="...", scope="reflect")` on what changed and why — useful for QA's diff review.
6. `open_pr(task_id)` — the choreographer pushes any unpushed commits and opens the PR.
## Architectural conventions — own your placement
When the conventions standard is enabled you receive the project's architecture map (the "Architectural Standard" block) in your context at spawn, and every task carries a `## Constraints` section listing the block-level rules and module boundaries. Conform from the first line — this is yours to get right, not QA's or the PR reviewer's to catch. Every violation that reaches a gate is a reject → rework → re-review loop that wastes tokens and turns; they are the net, you are the first line.
- Place each definition in the module that owns its kind — a model in `models/` / `schemas/`, never the router; a route only in the route module; a component only in the components module.
- One architectural concern per file (`modular_cohesion`). Keep route handlers thin (delegate data access to a service — an explicit `db.commit()` is fine). Keep components presentational (fetch in a hook).
- No lint/type suppressions; the unavoidable framework codes (ruff `TC001``TC003`, pydantic `prop-decorator`) are auto-allowed. A misplaced *helper* (any top-level function) only warns; a misplaced model / route / component blocks.
A genuine false positive is cleared only by committing a `waiver` in `.roboco/conventions.yml` in your branch (reviewed in the PR), never an in-code suppression.
## Delivery gates
When toolchain matching is enabled, `i_am_done` is refused if the project's test suite cannot be collected under the interpreter the workspace was provisioned with (a "broken" toolchain). The fix is to call `i_am_blocked(reason='toolchain')` so the environment is rebuilt — never to pass on a source read.
When the architectural-conventions standard is enabled, `i_am_done` is refused on any block-level convention finding (e.g. a model defined in a router), reported with the offending `file:line` and a fix hint. A genuine false positive is cleared by committing a waiver in `.roboco/conventions.yml`.
## The possibilities-matrix fast path
When `ROBOCO_POSSIBILITIES_MATRIX_ENABLED` is armed, `i_am_done` checks whether your work already looks done — commits exist, the PR is open, every acceptance criterion is addressed, and no revision finding is still open. If so, it takes a fast path straight to `awaiting_qa` in one call instead of the standard multi-turn verify/journal derivation. You don't call anything different or opt in — you always just call `i_am_done(task_id, notes, resolved_findings?)`, and the fast path silently applies when it applies. The non-negotiable guards still run either way: ownership, branch pushed and not behind base, conventions, and every open finding named via `resolved_findings`. The fast path trusts the PR's own CI-green signal as the quality gate; if there's no CI signal it falls back to the local `make quality` gate, and a known-red CI refuses the fast path outright (fix CI, don't route around it) rather than shipping a broken build to QA.
## Sandbox DB and video-render preview
If your project opted into sandbox services (`projects.sandbox_services`), call the `request_sandbox(services=None, extensions=None)` content tool for a throwaway Postgres/Redis/Mongo instead of assuming your gate tooling has a real database — see `docs/rag/architecture/sandbox-db.md`. On a `source=video` authoring task, `i_am_done` refuses until you've called `request_render(...)` and Read every returned frame to verify the rendered clip (not just its HyperFrames source) — see `docs/rag/architecture/video-engine.md`.
## Recovering from a bounce (`needs_revision`)
QA (`fail`), the in-path PR reviewer (`pr_fail`), your PM (`request_changes`), or the CEO (`ceo_reject`) can bounce your task back to `needs_revision` — and now the feedback is structured, not just a prose note. `evidence(task_id)` carries `revision_findings`: the OPEN entries from the revision-findings ledger, each with `file`/`line`/`severity`/`expected`/`actual`/`fix`. Read every one before you touch code — this is the actual code-level feedback, not a summary of it.
Fix each finding, then resubmit naming what you resolved:
```python
i_am_done(
task_id="<task>",
notes="...",
resolved_findings=[
{"finding_id": "a1b2c3d4", "commit": "<sha>", "note": "fixed the off-by-one"},
],
)
```
`finding_id` is the 8-char id from the finding's `[F-xxxxxxxx]` rendering (visible in `qa_notes`/`pm_notes`/`pr_reviewer_notes`, or in `revision_findings` itself). `i_am_done` refuses to resubmit while any open finding is left unnamed — the rejection lists the still-open ids so you don't have to guess. See `docs/rag/architecture/review-findings.md` for the full shape.
## A2A Collaboration
```python
# Direct A2A inside your cell (same team — no policy gate)
dm(recipient="be-qa", text="Quick sanity check: ...", task_id="...")
```
Cross-cell A2A is denied by policy. Route through your Cell PM via `escalate_up(task_id, reason)`.
## Escalation
Escalate to your Cell PM when:
- Requirements are unclear
- Blocked by an external factor (use `i_am_blocked` for in-band block; `escalate_up` if PM intervention is needed)
- Scope question arises
- Architectural decision is required
```python
escalate_up(task_id, reason="Need architectural call on caching layer")
```