mirror of
https://github.com/rennf93/roboco.git
synced 2026-08-03 07:23:24 +02:00
An adversarial review of the feature found two blocking defects (both would surface the moment external_pr_enabled is turned on) plus hardening gaps: - HIGH: the enforcement legacy role-gate overlay OVERWROTE spec-derived roles, so pr_reviewer was erased from the (in_progress->completed) edge it shares with the PM self-complete gate — the review task could never complete. Fix: UNION legacy + spec roles instead of overwriting (also preserves the legacy 'add roles' intent on every shared edge). - HIGH: claim_pr_review routed claim+start through the verb runner, which hit start()'s plan gate (planless review task -> None -> crash/respawn loop) and auto-created+pushed a stray branch (violating the read-only/branchless invariant). Fix: mirror QA's claim_review — a verb-body TaskService.pr_review_claim does pending->in_progress with no plan and no branch. - MED: add the pr_reviewer Write(*)/Edit(*) deny at the permission layer (it ingests untrusted PR diffs — make read-only explicit, not implicit). - MED: regenerate the verb-table artifacts (the schemas existed but the generator had not been re-run; the agent prompt showed 'unknown' signatures). ruff + mypy clean (279 files); foundation + gateway suites green (5205 passed).
24 lines
1.1 KiB
Markdown
24 lines
1.1 KiB
Markdown
<!-- AUTOGENERATED by scripts/regenerate_verb_tables.py. -->
|
|
<!-- Per-role verb signatures, derived from Pydantic schemas. -->
|
|
|
|
## Verbs available to you (autogenerated source of truth)
|
|
|
|
### Flow verbs
|
|
|
|
| Verb | Body schema |
|
|
|------|-------------|
|
|
| `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')` |
|
|
|
|
### Content (do) tools
|
|
|
|
| Tool | Body schema |
|
|
|------|-------------|
|
|
| `note` | `note(text: str, scope: str = 'note', task_id: UUID | None = None, title: str | None = None, context: str = '', options: list[str | str] | None = None, chosen: str = '', rationale: str = '', consequences: list[str] | None = None, what_done: str = '', what_learned: str = '', what_struggled: str = '', next_steps: list[str] | None = None)` |
|
|
| `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)` |
|
|
| `channels` | `channels()` |
|