Commit Graph
17 Commits
Author SHA1 Message Date
60c64c70e8 fix(run-hardening): break PM decision-gate, stale-agent, and empty-diff loops (#255)
Forensic triage of a 24h run reconstructed the dominant gateway.rejected
loops from the audit_log. After earlier deploys fixed the i_will_plan crash
and the open_pr push-gap, three real, recurring-capable burn loops remained.
This fixes them at the architecture level, not by prompt-nagging.

journal:decision write-then-gate (the dominant completion-path blocker):
PM decision-point verbs required a separate note(scope='decision') call
before the verb, which loaded/weak models forget to chain — so complete and
unblock hit a tracing_gap (journal:decision missing) and respawn-looped,
stranding finished tasks forever. Each verb now auto-records its OWN
rationale as the journal:decision before the gate runs (the proven
i_am_blocked -> write_struggle pattern), so the gate passes off real,
persisted reasoning. unblock gains a required `reason` (threaded MCP tool ->
request schema -> routes -> choreographer); delegate derives the decision
from its title + description; complete/submit_up/submit_root/escalate_up/
escalate_to_ceo reuse their existing notes/reason. The gate still runs as
defense-in-depth; the auto-record is idempotent within the decision window
and best-effort. Adds JournalService.write_decision and
Choreographer._ensure_pm_decision.

open_pr empty-diff 422: an overlapping-decomposition leaf with zero commits
vs its base makes GitHub 422 "No commits between ...". The generic
invalid_state "retry" looped the dev 15x on one task. open_pr now steers to a
terminal i_am_blocked hand-off so the PM completes or cancels the redundant
leaf.

owns_task stale-agent loop (41x): a superseded agent (task reassigned away)
calling i_am_done/open_pr got a PRECONDITION_OWNERSHIP tracing_gap it read as
a fixable precondition and retried forever. Both verbs now short-circuit with
the clear not_authorized "no longer yours -> give_me_work" steer that
resume/unclaim already use.

RAG docs updated for the new unblock(reason) signature; CHANGELOG entries
added under 0.11.0 (unreleased). open_pr refactored into
_open_pr_preflight_rejection + _open_pr_failure_env to stay within the
return-count and complexity budgets.

Co-authored-by: Renn F <rennf93@users.noreply.github.com>
2026-06-25 01:07:05 +02:00
Renn F f1b197def0 docs(conventions): dev-first framing + flag-enable + accuracy sweep
The conventions standard is dev-first by design — the developer receives the
architecture map + per-task constraints at spawn and owns conforming code from
the start; QA and the PR reviewer are the downstream net. Make that explicit in
the developer prompt and add a dedicated conventions section to the RAG
developer doc (it previously only mentioned the gate, reactively).

Also reconcile the docs with the hardened behavior: env-reference now shows the
flag is off by config default but on in the compose orchestrator block (left off
in the registry), mirroring toolchain matching; and the RAG standard's example
comment no longer implies a misplaced helper blocks (it warns).
2026-06-22 21:20:42 +02:00
Renn F 71f068ea6c docs: refresh user-facing docs for the features shipped since 0.8.0
Documentation had drifted behind the post-0.8.0 work. Adds a CHANGELOG [Unreleased] section, documents the three new feature flags in the config reference (and removes the retired ROBOCO_RAG_USE_HYDE), a new Architectural Conventions Standard page, the provider-overload break in CLAUDE.md, the >=3.13 Python floor + feature flags in the README, and the toolchain/conventions delivery gates + structured-note model across the developer / QA / PR-reviewer role docs and the task-model doc.
2026-06-22 13:42:38 +02:00
5fe1e6df58 feat: in-path PR-review gate — per-cell + main reviewers (#229)
* feat(lifecycle): add the in-path PR-review gate status + reviewer verbs

Insert awaiting_pr_review between the assembled-PR submit and the PM merge,
giving the merge level the rejection capability it structurally lacks — today
only qa_fail and ceo_reject ever reach needs_revision, so a PM review is a
merge button with no teeth.

- New Status awaiting_pr_review + submit_for_review / pr_pass / pr_fail actions
  (pr_pass -> awaiting_pm_review, pr_fail -> needs_revision, mirroring the QA gate).
- Reviewer verbs claim_gate_review / pr_pass / pr_fail, and a main-PM submit_root
  verb (the root analogue of the cell PM's submit_up; opens the root->master PR).
- Extend the self-review-symmetry validator to the new sign-off actions.
- Mirror the value into the ORM TaskStatus enum + the A2A state map, and add the
  postgres taskstatus enum value (migration 040, forward-only like 037).
- Regenerate the per-role verb tables; add gate spec tests.

Spec surface only; the gateway methods + dispatch are wired in follow-ups, so the
verbs are advertised but dormant (flow_server tolerates unregistered verbs).

* feat(identity): add the three cell PR-review-gate reviewers

The in-path gate needs a reviewer per cell so each cell's assembled cell->root
PR is reviewed by a stack-specialized agent, while pr-reviewer-1 serves the
root->master gate (and keeps doing inbound external PRs).

- be/fe/ux-pr-reviewer: PR_REVIEWER role, team-scoped (so dispatch routes each
  cell's gate to its own reviewer); seeded identities + ROLE_TEAM_RULES + names.
  AI agent count 22 -> 25.
- They reuse the existing roboco-agent-pr-reviewer image (AGENT_IMAGES maps the
  three slugs to it, as be-dev-1/-2 share one image) — no new image.
- Tracing table: pr_pass/pr_fail require a learning entry (parity with
  post_pr_review), submit_root mirrors submit_up, claim_gate_review is waived
  (its tracing applies on pr_pass/pr_fail) — completes the verb surface added
  in the prior commit.
- Update the roster-pinning identity tests.

* feat(gateway): wire the in-path PR-review gate end to end

Make the assembled-PR review gate operational across the choreographer, the
TaskService transitions, and the v1 flow surface.

- TaskService: submit_for_review (in_progress→awaiting_pr_review), pr_gate_claim
  (no-transition reviewer claim), pr_pass (→awaiting_pm_review), pr_fail
  (→needs_revision); mirror qa_pass/qa_fail (clear claim, actor-mismatch warn,
  issues appended for the PM's revision). VerbRunner gains the matching atomic
  handlers + a create_root_pr side effect.
- Repoint submit_up to compose submit_for_review (cell→root PR enters the gate),
  and add a main-PM submit_root verb (opens the root→master PR, enters the gate).
- Split main_pm_complete: a code root must pass the gate first (requires
  awaiting_pm_review; rejects an in_progress code root toward submit_root and no
  longer reopens the PR), while a branchless coordination root still walks
  straight through, ungated.
- PRGateMixin (claim_gate_review / pr_pass / pr_fail) composed onto the
  Choreographer; flow_server forwarders + v1 routes (pr_reviewer + main_pm) +
  request schemas.
- Tests: gate spec + the updated submit_up / main_pm_complete expectations + new
  real-DB integration tests driving submit_for_review→pr_gate_claim→pr_pass and
  pr_fail through the real enforcement layer.

* feat(orchestrator): dispatch the in-path PR-review gate

Make the gate live in the dispatch loop.

- _dispatch_pr_gate_work: route awaiting_pr_review tasks to reviewers by level —
  a cell→root task to its cell reviewer (be/fe/ux-pr-reviewer), the root→master
  task to pr-reviewer-1. The reviewer self-claims via claim_gate_review (no
  pre-claim, mirroring the external-PR dispatcher); registered in
  _dispatch_all_work. _select_agent_for_cell learns the pr_reviewer role.
- _build_pr_gate_prompt: anchors the reviewer to the parent objective + full
  acceptance criteria + the FE<->BE contract, then pr_pass / pr_fail.
- _readiness_check_role_for_status: awaiting_pr_review -> pr_reviewer.
- Fail routing: pr_fail reassigns the failed assembled task to its PM
  (_revision_pm_for_task: cell PM for a cell team, Main PM for the root), and the
  revision dispatcher is generalized from coordination-roots-only to any
  PM-owned needs_revision task so the gate-failed task is re-coordinated instead
  of deadlocking.

* docs: document the in-path PR-review gate + the cell reviewers (22→25)

Reflect the shipped gate across the canonical + RAG docs.

- CLAUDE.md: agent count 22→25, the cell reviewers in the org chart, an
  awaiting_pr_review state + the gate transitions + a gate note in the lifecycle
  section, and submit_root / claim_gate_review / pr_pass / pr_fail in the verb
  surface table.
- docs/rag/architecture: org-structure (count, cell-reviewer roster, cells
  table), agent-uuids (be/fe/ux-pr-reviewer rows), agent-model (role + team
  rows).
- docs/rag/roles/pr-reviewer: the in-path gate section + the gate verbs.
- Wrap reviewer.id with UUID(str(...)) in the gate DB tests for mypy.

* docs: finish the gate doc sweep across README + RAG + generated artifacts

Catch the remaining surfaces beyond the canonical docs.

- README + how-to: agent count 22→25, the 6-agent cells (+ PR Reviewer), the
  main reviewer's root→master gate role.
- RAG: permissions + tool-permissions + task-tools list the gate verbs
  (claim_gate_review / pr_pass / pr_fail) for pr_reviewer; regenerate the
  lifecycle artifacts (intent-verbs, status-transitions, the per-role
  lifecycle-*.md prompts, panel lifecycle.json) from the spec via
  build_lifecycle_artifacts.py so they carry the new status + verbs.

* fix(migration): shorten the 040 revision id to fit alembic_version VARCHAR(32)

The revision id '040_taskstatus_awaiting_pr_review' is 33 chars; alembic's
alembic_version.version_num column is VARCHAR(32), so recording the migration on
a real 'alembic upgrade head' failed with 'value too long for type character
varying(32)' (surfaced on the NAS deploy). The test suite missed it: the test DB
is built via Base.metadata.create_all and the parity test only renders SQL
offline, so nothing actually applied the migration chain.

- Rename to '040_awaiting_pr_review' (22 chars).
- Add a guard test asserting every revision id fits the VARCHAR(32) column.
- Verified by applying the full chain 001->040 against real Postgres: it now
  reaches head and records '040_awaiting_pr_review' without truncation.

* fix(migration): land the actual 040 revision-id shortening + guard test

The prior commit captured only the file rename (git add aborted on the deleted
old path), leaving the long revision id and missing the guard test. This commit
carries the real content: revision id '040_awaiting_pr_review' (22 chars) and the
revision-id length guard. Re-verified against real Postgres — the full chain
reaches head and records the short id without truncation.

* fix(product): flush cell deletes before inserts when re-mapping projects

Editing a product's cell->project map (PATCH /api/products/{id}) 409'd with
'duplicate key value violates unique constraint uq_product_projects_product_team'
whenever a team already had a mapping. _replace_cells clears the old rows and
appends the new ones, but within a single flush SQLAlchemy orders INSERTs before
DELETEs for the same table, so the new (product_id, team) rows collided with the
not-yet-deleted old ones. Flush the deletes first.

Pre-existing bug (unrelated to the PR-review gate); surfaced on the NAS. New
real-Postgres regression test re-maps all three cells to different projects —
it fails with the unique violation without the fix and passes with it. The
existing update test only changed WHICH team was mapped, so it never collided.

* fix(gateway): let main_pm submit_root past the shared submit-up guard

submit_root reused the cell PM's _submit_up_ownership_guard, which
hardcoded agent.role != cell_pm and rejected the Main PM with
"submit_up is reserved for cell_pm". A branch-bearing code root could
then never close: submit_root bounced to complete, while complete
required awaiting_pm_review (reachable only via submit_root) and bounced
back — a circular rejection.

Both callers already run the spec gate (can_invoke_intent), which
enforces submit_up→cell_pm and submit_root→main_pm, so the guard's role
re-check was redundant for submit_up and wrong for submit_root. Broaden
it to accept either PM role as a defense-in-depth non-PM reject.

Adds the first choreographer-level submit_root test (the gap that let
this ship).

* fix(gateway): proactively steer both PMs to their bubble-up verb

The submit_root deadlock had a sibling steering gap: nothing told a PM
which verb opens the gate. The delegate next-hint said only 'i_am_idle
when done', and complete's in_progress rejection named submit_root for
the Main PM but left the Cell PM with a bare 'not ready for completion'
— no submit_up pointer, the same guess-the-verb trap.

- delegate hint now names the role-correct verb (root → submit_root,
  cell parent → submit_up) proactively, before any rejection.
- cell_pm_complete's in_progress rejection now steers to submit_up,
  mirroring the Main PM's submit_root gate hint.

Tests cover both the cell-PM steer and the role-aware delegate hint.

* docs: correct who-merges-which-PR across the gate docs + complete description

Audit of the gate docs found the merge actors mis-stated in several
places — the exact ambiguity that risks 'the reviewer/PM merges the root
PR' confusion:

- complete IntentSpec description said 'Main PM merges root PR' — false;
  main_pm_complete escalates and the CEO merges root→master. Corrected
  (propagated to intent-verbs.md, lifecycle.json, generated role prompts
  via build_lifecycle_artifacts.py).
- task-tools.md: submit_up target was awaiting_pm_review (should be
  awaiting_pr_review); Main PM flow had no submit_root — added it.
- README.md: lifecycle diagram now shows the awaiting_pr_review gate.
- cell-pm.md / main-pm.md: dropped the stale 'submit_up hands work to the
  Main PM who merges your cell branch' model — the cell PM merges its own
  gated cell→root PR; the Main PM owns the root + submit_root; the CEO
  merges master. Added submit_root to the main-pm manifest.
- git-commits.md, pr-creation.md, tool-permissions.md, git-tools.md:
  stopped attributing root→master PR opening to complete (it's submit_root).

No behavior change; verb wiring + state machine verified gap-free this
session (the pr_fail→needs_revision→PM respawn loop closes correctly).

* fix(orchestrator): stop closure respawn waiting the reaper window

A PM that finished its subtasks and idled left its parent 'paused' with a
fresh last_heartbeat_at. _is_recently_paused gated closure respawn on
_claim_heartbeat_ttl — the REAPER window (stale_claim_reap_seconds: 600s
default, 1800s on the NAS) — so the parent sat untouched for up to 10-30
minutes before its PM was respawned to close it. The whole chain stalled
behind it.

The race that guard actually protects against (i_am_idle auto-pauses, then
the agent is marked IDLE + its container tears down) is seconds, and the
live-session case is already covered by _is_agent_active. Introduce a
dedicated short debounce (pm_closure_recently_paused_seconds, default 45s)
and gate closure on that instead.

The existing test fixture masked this by setting _claim_heartbeat_ttl to
claim_stale_seconds (180s), not the production reaper value. Fixture now
mirrors production; adds a regression test that a parent paused past the
debounce but within the reaper window respawns immediately.

* feat(gate): post the in-path review verdict on the assembled PR

The in-path gate previously left no trace on the PR it gated — pr_pass /
pr_fail were pure status transitions. Now each verdict is posted as a
GitHub review on the assembled PR itself (server-side, bot account), so
the decision is visible on the very PR the PM merges.

- pr_pass → APPROVE, pr_fail → REQUEST_CHANGES on a cell→root PR.
- The root→master PR ALWAYS gets a plain COMMENT, never APPROVE/REQUEST_
  CHANGES: only the CEO acts on master, so the gate must never leave an
  approval that could satisfy branch protection (letting someone else
  merge) nor a blocking review that could impede the CEO's merge.
- Best-effort and AFTER the DB transition — a GitHub failure is logged,
  never rolls back the gate decision. Reuses git.post_pr_review's existing
  self-review→COMMENT downgrade for the org's own PRs.

Adds _project_slug_for to the ChoreographerHelpers protocol (mypy) and a
unit suite covering event selection, the master-bound COMMENT rule, the
no-PR skip, and failure-swallowing. Docs updated (pr-reviewer, task-tools).

---------

Co-authored-by: Renn F <rennf93@users.noreply.github.com>
2026-06-20 09:27:29 +02:00
Renn F 68094d5f2a docs(0.7.0): document Grok provider, self-heal, PR-reviewer across the RAG + how-to docs
Close the doc gaps the audit found in the agent knowledge base and the human
walkthrough:
- config-reference: add the Grok provider env table (host ~/.grok subscription
  mount, grok-build, idle-kill, cost cap) and the Self-Healing CI loop toggles.
- agent-model: provider-aware Model Configuration (ANTHROPIC default / GROK) +
  add the pr_reviewer / prompter / secretary roles to the Roles table.
- tool-permissions: 'three' -> five MCP servers (roboco-optimal, roboco-docs) +
  PR Reviewer / Prompter / Secretary tool sections.
- new roles/pr-reviewer.md (the 22nd agent had no role doc); permissions +
  agent-uuids + task-tools 'PR Reviewer flow' all gain the role.
- api-endpoints: drop the removed USAGE_UPDATE event (only USAGE_SNAPSHOT exists).
- how-to: self-healing CI loop + Company Scorecard (ch.5), inbound external-PR
  review + CEO Supersede/Dismiss queue (ch.4).

Every claim verified against current code by the audit (grok model grok-build,
auth ~/.grok, no metered API; opencode fully removed).
2026-06-19 10:50:58 +02:00
Renn F b278c55c64 docs(rag): fix PM delegate signature + cross-link cell-pm ↔ main-pm
The cell-pm role doc showed delegate with a nonexistent nested body={...}
and omitted covers_parent_criteria, so an agent following it would make a
malformed call and burn turns rediscovering the real shape. Both PM docs now
match the actual flow_server.delegate signature (flat keywords, with
covers_parent_criteria; the subtask inherits the parent's project — resolved
from the product cell→project map for coordination roots, never passed).

Also document reassign (cell PM could call it but it was undocumented) and
cross-link the two roles: cell-pm explains submit_up hands finished work to
Main PM; main-pm explains the receiving side — the integration-branch chain,
that its complete on the root opens the master PR, and that only Main PM and
the CEO act on master.
2026-06-17 17:21:50 +02:00
Renn F f48106cbb6 docs: reflow hard-wrapped prose to one line per paragraph
Markdown and editors soft-wrap on their own, so the manual ~75-char line
breaks across the docs added nothing but noise. Join wrapped prose, list
items, and paragraphs into single lines across 67 docs — README, CLAUDE.md,
deployment, usage, the RAG knowledge base, and the agent role prompts.
Whitespace-only: code fences, tables, and blockquote alerts are byte-identical
and the change is token-verified (no content altered). Applied with a
deterministic reflow tool (committed separately).

Also lands two doc edits that were awaiting commit: the measured under-load
resource numbers in usage.md and the pr_reviewer additions to the
org-structure RAG doc.
2026-06-16 23:18:55 +02:00
Renn F 568ae7a25d docs(rag): add prompter/secretary role docs + refresh guardrails surface
The agents' runtime KB had drifted three releases behind the gateway. Add the
two missing role docs (prompter, secretary — both live-session SDK chat roles,
human-only) and fold the AC/decomposition guardrails and per-dev code queues
into the high-traffic PM docs:

- task-model: acceptance_criteria_ids + parent_ac_refs fields and how the
  child->parent AC link works.
- task-planning: covers_parent_criteria on delegate, the parent_ac_coverage /
  unclaimed_parent_acs briefing fields, the decomposition-floor and roll-up
  gates (safe-by-construction), and per-dev sequenced code queues.
- task-tools: same coverage note + correct stale verbs — QA is
  pass_review/fail_review (not pass/fail), cell_pm gains reassign, and main_pm
  no longer claims submit_up/reassign it does not have.
2026-06-16 09:11:27 +02:00
Renn F ecea593a51 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.
2026-06-05 17:20:36 +02:00
Renn F 73e1e96851 Many fixes and cleanups 2026-05-09 03:15:09 +02:00
Renn F 0023c25d60 Added git workflow + fixing some issues 2026-04-19 16:13:42 +02:00
Renn F 9deb23ec3d General fixes mainly around git integration into task lifecycle 2026-01-11 06:15:54 +01:00
Renn F 955455d704 Git integration and Project workspace fixes 2026-01-08 16:45:25 +01:00
Renn F f1c5b7958c Add Project & Workspace MCP System with role-based permissions
- Add roboco_project_* tools (list, get, create, update) with CEO bypass
  - Add roboco_workspace_* tools (ensure, status, list) for workspace management
  - Add project_slug and requires_git fields to TaskCreateInput schema
  - Validate project exists and cell matches when creating git-enabled tasks
  - Register project MCP server in orchestrator with proper permissions

  Workspace permissions by role:
  - Developer: Write to own workspace only
  - QA: Read-only access to all cell workspaces
  - Documenter: Write to all cell workspaces (add docs to dev branches)
  - Cell PM: Write to own workspace, project_update for own cell
  - Main PM: Full project access (create, update all, workspace_list all)
  - CEO: Full bypass on all permission checks

  Also includes:
  - Git templates for commits, branches, PRs (separation of concerns)
  - Updated blueprints with project/workspace tools documentation
  - Updated RAG docs with project tools reference
2026-01-07 22:45:42 +01:00
Renn F c621710ae6 A2A wiring up 2026-01-06 00:59:09 +01:00
Renn F aeb3aea55e Documenter MCP tools and general support + improved workflow 2026-01-04 03:03:45 +01:00
Renn F 1d173a5203 NOW RAG is actually usable... might switch to gemma3:4b from glm-4.6 cloud for expenses reasons but we'll see 2026-01-03 05:07:45 +01:00