Files
roboco/docs/rag/roles/developer.md
T
cea3e56628 feat(lifecycle): revision findings ledger — structured failure feedback, persisted and delivered down the chain (#486)
* feat(lifecycle): revision findings ledger — structured QA/PR/PM/CEO failure feedback, persisted and delivered down the chain

Every bounce used to survive only as flattened prose: rounds overwrote each
other in notes_structured, request_changes persisted nothing, two raw
dev_notes appends were silently destroyed by the next handoff note, and the
dev prompt pointed at fields (qa_notes via evidence(), pm_notes) the API
never delivered. Agents re-interpreted and re-discovered every failure
before they could start fixing it.

- task_review_findings (migration 071, append-only): file/line/severity/
  criterion(AC-id-validated)/expected/actual/fix/evidence per finding, with
  origin (qa|pr_gate|pm|ceo), round, and an open->addressed->verified
  lifecycle (waived reserved); new tasks.pm_notes + PmReviewContent give
  request_changes a structured home
- producers: fail_review/pr_fail/request_changes take findings=[...] (prose
  issues shimmed+merged for one release, deprecation-logged); ceo_reject
  validates its reason (no 500), lands an origin=ceo finding, and bumps
  round+audit on branchless coordination roots; guardrails at the verb
  chokepoint (nudge >5, hard reject >10, field caps, traversal-safe file);
  the dev_notes data-loss appends are removed; new task.request_changes +
  task.ceo_reject audit events close rework attribution
- delivery: qa_notes/pr_reviewer_notes/pm_notes carry the deterministic
  [F-id8] rendering; claim briefings, evidence(), the REVISION_REQUIRED
  spawn prompt, PM triage bounced-blocks, and A2A bodies deliver open
  findings; round-N+1 QA and gate reviewers get the full prior ledger;
  panel Findings tab + bounced-xN chip; metrics pm_rejects/ceo_rejects +
  findings counts; vault task notes render a Findings section (fail-open)
- resolution closes for every origin: i_am_done and submit_up/submit_root
  take resolved_findings gated by FINDINGS_ADDRESSED (owner-gated so a
  stale non-owner PM can never mutate the ledger); pass_review/pr_pass/
  complete verify-stamp same-transaction; ceo_approve stamps best-effort
- 24 real-DB integration tests drive the full loop through the real
  choreographer; full suite 12856 green

* docs: revision findings ledger sweep — CLAUDE.md, map, RAG corpus

- CLAUDE.md: new ledger section + corrected request_changes row
- docs/map/review-findings.md (new subsystem map) + surgical updates to
  task-service/pr-gate-review/metrics-observability/vault/panel maps
- docs/rag: producers' findings contract across qa/pr-reviewer/developer/
  cell-pm/main-pm/ceo role docs (the PM docs were missing request_changes
  entirely), verb references, and a new architecture/review-findings.md
  disambiguating ledger findings from convention findings

* test(e2e): resubmit resolves the pr_fail finding per the ledger contract

The scripted pr_fail revision loop resubmitted submit_up without
resolved_findings — correctly rejected now that FINDINGS_ADDRESSED gates
the PM resubmit verbs (green locally, red only in CI since the e2e suite
skips without ROBOCO_E2E_SMOKE=1). The scripted PM now reads the open
ledger row pr_fail persisted (new open_finding_ids arc helper) and
resolves it on resubmit, asserting the open set drains — exercising the
coordinator half of the new contract end to end.

---------

Co-authored-by: Renn F <rennf93@users.noreply.github.com>
2026-07-11 22:54:42 +02:00

7.7 KiB
Raw Blame History

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
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 TC001TC003, 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.

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:

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

# 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
escalate_up(task_id, reason="Need architectural call on caching layer")