Files
roboco/agents/prompts/_generated/verbs.md
T
a9dee3b34e feat(agents): force agents to the Makefile — deny raw uv/pip/conda/poetry (CEO #15) (#518)
* fix(prompts): point agents at Makefile, drop raw uv run instructions

backend.md:23-26 literally instructed raw uv run ruff/mypy/pytest (copied from
the human-facing CLAUDE.md), so agents bypassed the Makefile's UV_NO_SYNC=1 +
private UV_CACHE_DIR venv-corruption guard. Replace with make targets across
backend/developer/qa/cell_pm + a universal rule in base.md. Regenerate verbs.md
from the updated regen script (baked instruction now make foundation-check) and
align the Makefile drift message. Ships with the bash-guard deny in the next
commit so agents don't loop fighting the guard.

* feat(bash-guard): deny raw uv/pip/conda/poetry, point at Makefile

When a Makefile is present, deny raw uv run/uv pip/uv lock/add/remove, pip/pip3
install/uninstall, conda install/create/run, poetry run/install/add and remediate
to make quality/gate/lint/test. Skipped when no Makefile (Makefile-less projects
not blocked). ROBOCO_GUARD_SKIP_PM=1 (grok path) nudges exit 0 instead of the
run-canceling exit 2. Overrides the prior bare-uv-run-allowed stance by CEO
direction; the /app-targeted blocks above keep priority.

* feat(grok): deny raw uv/pip/conda/poetry via native --deny + PM-skip nudge

Add _RAW_PM_DENY (uv run/pip install/lock/add/remove, pip/pip3 install, conda
install/create/run, poetry run/install/add) to _deny_rules so grok's graceful
native --deny blocks raw package-manager commands (model adapts to make, run
continues — unlike a hook deny which cancels the run). The bash-guard hook
keeps the compound-command fallback (cd x && uv run) and nudges exit 0 there via
ROBOCO_GUARD_SKIP_PM=1 in the grok hook env, never canceling.

* test(bash-guard): align existing tests with W1 Makefile-gate policy

Raw uv run / pip install are now Makefile-gated (W1, CEO item #15), so two
existing bash-guard invariants reverse:

- test_allows_pytest_even_if_suite_uses_requests keeps its HTTP-injection
  allow-path intent but uses bare `python -m pytest` (raw `uv run` is now
  denied); the deny case is covered by test_bash_guard_makefile_guardrail.
- test_allows_pip_install_in_workspace -> test_denies_pip_install_when_makefile_
  present: a workspace clone carries a Makefile, so bare pip install is now
  denied -> agents use `make` / `uv sync --extra dev`. Makefile-less skips
  stay covered.

Gate: 12994 passed, 439 skipped, 94.81% cov (DB env :55432 user renzof);
the lone flaky integration error passes in isolation (DB-state race, not W1).

---------

Co-authored-by: Renn F <rennf93@users.noreply.github.com>
2026-07-15 04:32:27 +02:00

18 KiB

Per-role verb shapes (autogenerated)

Run make foundation-check after changing any role config or schema. Role prompts reference this file's sections as the source of truth for verb signatures.

Driver-based roles (prompter, secretary) are intentionally omitted — their real tools live in their agent_sdk drivers, not role_config.

developer

Flow verbs

Verb Body schema
give_me_work give_me_work()
i_am_blocked `i_am_blocked(task_id: UUID, reason: str, blocker_type: str
i_am_done i_am_done(task_id: UUID, notes: str = '', resolved_findings: list[ResolvedFindingInput] = PydanticUndefined)
i_am_idle i_am_idle()
i_will_work_on `i_will_work_on(task_id: UUID, plan: str
open_pr open_pr(task_id: UUID)
resume resume(task_id: UUID)
sync_branch sync_branch(task_id: UUID, stash: bool = False)
unclaim unclaim(task_id: UUID)

Content (do) tools

Tool Body schema
commit `commit(message: str, files: list[str]
note `note(text: str, scope: str = 'note', task_id: UUID
dm `dm(recipient: str, text: str, task_id: UUID
evidence evidence(task_id: UUID)
progress `progress(task_id: UUID, message: str, plan_step: str
pr_update pr_update(see do_server)
draft_playbook `draft_playbook(title: str, problem: str, procedure: str, tags: list[str] = PydanticUndefined, source_task_id: UUID
propose_video `propose_video(composition_id: str, x_caption: str, tiktok_caption: str, platforms: list[str], input_props: str
request_sandbox `request_sandbox(services: list[str]
notify_list notify_list(unread_only: bool = True, pending_ack_only: bool = False, limit: int = 20)
notify_get notify_get(notification_id: UUID)
notify_ack notify_ack(notification_id: UUID)
read_messages read_messages()
read_a2a read_a2a(see do_server)

qa

Flow verbs

Verb Body schema
claim_review claim_review(task_id: UUID)
fail_review `fail_review(task_id: UUID, issues: list[str] = PydanticUndefined, findings: list[str
give_me_work give_me_work()
i_am_blocked `i_am_blocked(task_id: UUID, reason: str, blocker_type: str
i_am_idle i_am_idle()
pass_review `pass_review(task_id: UUID, notes: str, ac_verdicts: list[str]
resume resume(task_id: UUID)
unclaim unclaim(task_id: UUID)

Content (do) tools

Tool Body schema
note `note(text: str, scope: str = 'note', task_id: UUID
dm `dm(recipient: str, text: str, task_id: UUID
evidence evidence(task_id: UUID)
draft_playbook `draft_playbook(title: str, problem: str, procedure: str, tags: list[str] = PydanticUndefined, source_task_id: UUID
request_sandbox `request_sandbox(services: list[str]
notify_list notify_list(unread_only: bool = True, pending_ack_only: bool = False, limit: int = 20)
notify_get notify_get(notification_id: UUID)
notify_ack notify_ack(notification_id: UUID)
read_messages read_messages()
read_a2a read_a2a(see do_server)

documenter

Flow verbs

Verb Body schema
claim_doc_task claim_doc_task(task_id: UUID)
give_me_work give_me_work()
i_am_blocked `i_am_blocked(task_id: UUID, reason: str, blocker_type: str
i_am_idle i_am_idle()
i_documented i_documented(task_id: UUID, notes: str, files: list[str])
resume resume(task_id: UUID)
unclaim unclaim(task_id: UUID)

Content (do) tools

Tool Body schema
commit `commit(message: str, files: list[str]
note `note(text: str, scope: str = 'note', task_id: UUID
dm `dm(recipient: str, text: str, task_id: UUID
evidence evidence(task_id: UUID)
progress `progress(task_id: UUID, message: str, plan_step: str
pr_update pr_update(see do_server)
draft_playbook `draft_playbook(title: str, problem: str, procedure: str, tags: list[str] = PydanticUndefined, source_task_id: UUID
notify_list notify_list(unread_only: bool = True, pending_ack_only: bool = False, limit: int = 20)
notify_get notify_get(notification_id: UUID)
notify_ack notify_ack(notification_id: UUID)
read_messages read_messages()
read_a2a read_a2a(see do_server)

cell_pm

Flow verbs

Verb Body schema
complete complete(task_id: UUID, notes: str)
declare_coverage declare_coverage(task_id: UUID, criteria: list[str])
delegate `delegate(parent_task_id: UUID, title: str, description: str, assigned_to: str, team: str, task_type: str, nature: str, estimated_complexity: Complexity, acceptance_criteria: list[str], project_id: UUID
escalate_up escalate_up(task_id: UUID, reason: str)
give_me_work give_me_work()
i_am_idle i_am_idle()
i_will_plan i_will_plan(task_id: UUID, plan: str, approach: str, sub_tasks: list[SubTaskCreate] = PydanticUndefined, technical_considerations: list[str] = PydanticUndefined, risks: list[RiskCreate] = PydanticUndefined, open_questions: list[OpenQuestionCreate] = PydanticUndefined)
reassign reassign(task_id: UUID, new_assignee: str)
request_changes `request_changes(task_id: UUID, issues: list[str] = PydanticUndefined, findings: list[str
resume resume(task_id: UUID)
submit_up submit_up(task_id: UUID, notes: str, resolved_findings: list[ResolvedFindingInput] = PydanticUndefined)
triage triage()
unblock unblock(task_id: UUID, reason: str, restore: bool = True)
unclaim unclaim(task_id: UUID)

Content (do) tools

Tool Body schema
note `note(text: str, scope: str = 'note', task_id: UUID
dm `dm(recipient: str, text: str, task_id: UUID
notify `notify(target: str, text: str, priority: str = 'normal', task_id: UUID
evidence evidence(task_id: UUID)
pr_update pr_update(see do_server)
draft_playbook `draft_playbook(title: str, problem: str, procedure: str, tags: list[str] = PydanticUndefined, source_task_id: UUID
notify_list notify_list(unread_only: bool = True, pending_ack_only: bool = False, limit: int = 20)
notify_get notify_get(notification_id: UUID)
notify_ack notify_ack(notification_id: UUID)
read_messages read_messages()
read_a2a read_a2a(see do_server)

main_pm

Flow verbs

Verb Body schema
complete complete(task_id: UUID, notes: str)
declare_coverage declare_coverage(task_id: UUID, criteria: list[str])
delegate `delegate(parent_task_id: UUID, title: str, description: str, assigned_to: str, team: str, task_type: str, nature: str, estimated_complexity: Complexity, acceptance_criteria: list[str], project_id: UUID
escalate_to_ceo escalate_to_ceo(task_id: UUID, reason: str)
escalate_up escalate_up(task_id: UUID, reason: str)
give_me_work give_me_work()
i_am_idle i_am_idle()
i_will_plan i_will_plan(task_id: UUID, plan: str, approach: str, sub_tasks: list[SubTaskCreate] = PydanticUndefined, technical_considerations: list[str] = PydanticUndefined, risks: list[RiskCreate] = PydanticUndefined, open_questions: list[OpenQuestionCreate] = PydanticUndefined)
request_changes `request_changes(task_id: UUID, issues: list[str] = PydanticUndefined, findings: list[str
resume resume(task_id: UUID)
submit_root submit_root(task_id: UUID, notes: str, resolved_findings: list[ResolvedFindingInput] = PydanticUndefined)
triage triage()
triage_all triage_all()
unblock unblock(task_id: UUID, reason: str, restore: bool = True)
unclaim unclaim(task_id: UUID)

Content (do) tools

Tool Body schema
note `note(text: str, scope: str = 'note', task_id: UUID
dm `dm(recipient: str, text: str, task_id: UUID
notify `notify(target: str, text: str, priority: str = 'normal', task_id: UUID
evidence evidence(task_id: UUID)
pr_update pr_update(see do_server)
draft_playbook `draft_playbook(title: str, problem: str, procedure: str, tags: list[str] = PydanticUndefined, source_task_id: UUID
notify_list notify_list(unread_only: bool = True, pending_ack_only: bool = False, limit: int = 20)
notify_get notify_get(notification_id: UUID)
notify_ack notify_ack(notification_id: UUID)
read_messages read_messages()
read_a2a read_a2a(see do_server)

product_owner

Flow verbs

Verb Body schema
escalate_to_ceo escalate_to_ceo(task_id: UUID, reason: str)
i_am_idle i_am_idle()
triage triage()

Content (do) tools

Tool Body schema
note `note(text: str, scope: str = 'note', task_id: UUID
pitch pitch(title: str, slug: str, problem: str, proposed_solution: str, target_cells: list[str])
dm `dm(recipient: str, text: str, task_id: UUID
notify `notify(target: str, text: str, priority: str = 'normal', task_id: UUID
evidence evidence(task_id: UUID)
notify_list notify_list(unread_only: bool = True, pending_ack_only: bool = False, limit: int = 20)
notify_get notify_get(notification_id: UUID)
notify_ack notify_ack(notification_id: UUID)
read_messages read_messages()
read_a2a read_a2a(see do_server)
propose_roadmap propose_roadmap(cycle_goal: str, items: list[RoadmapItemInput])

head_marketing

Flow verbs

Verb Body schema
escalate_to_ceo escalate_to_ceo(task_id: UUID, reason: str)
i_am_idle i_am_idle()
triage triage()

Content (do) tools

Tool Body schema
note `note(text: str, scope: str = 'note', task_id: UUID
pitch pitch(title: str, slug: str, problem: str, proposed_solution: str, target_cells: list[str])
dm `dm(recipient: str, text: str, task_id: UUID
notify `notify(target: str, text: str, priority: str = 'normal', task_id: UUID
evidence evidence(task_id: UUID)
notify_list notify_list(unread_only: bool = True, pending_ack_only: bool = False, limit: int = 20)
notify_get notify_get(notification_id: UUID)
notify_ack notify_ack(notification_id: UUID)
read_messages read_messages()
read_a2a read_a2a(see do_server)
propose_feature_spotlight propose_feature_spotlight(feature_slug: str = '', feature_title: str = '', body: str = '', wants_video: bool = False, video_script: str = '', skip: bool = False, skip_reason: str = '')

auditor

Flow verbs

Verb Body schema
i_am_idle i_am_idle()
triage triage()
waive_finding waive_finding(finding_id: UUID, note: str)

Content (do) tools

Tool Body schema
note `note(text: str, scope: str = 'note', task_id: UUID
evidence evidence(task_id: UUID)
approve_playbook approve_playbook(playbook_id: UUID)
reject_playbook reject_playbook(playbook_id: UUID, reason: str)
archive_playbook archive_playbook(playbook_id: UUID)
curate_vault curate_vault(task_id: UUID, narrative: str)
notify_list notify_list(unread_only: bool = True, pending_ack_only: bool = False, limit: int = 20)
notify_get notify_get(notification_id: UUID)

pr_reviewer

Flow verbs

Verb Body schema
claim_gate_review claim_gate_review(task_id: UUID)
claim_pr_review claim_pr_review(task_id: UUID)
give_me_work give_me_work()
i_am_idle i_am_idle()
post_pr_review `post_pr_review(task_id: UUID, body: str, event: str = 'REQUEST_CHANGES', findings: list[str
pr_fail `pr_fail(task_id: UUID, issues: list[str] = PydanticUndefined, findings: list[str
pr_pass pr_pass(task_id: UUID, notes: str)
unclaim unclaim(task_id: UUID)

Content (do) tools

Tool Body schema
note `note(text: str, scope: str = 'note', task_id: UUID
evidence evidence(task_id: UUID)
notify_list notify_list(unread_only: bool = True, pending_ack_only: bool = False, limit: int = 20)
notify_get notify_get(notification_id: UUID)