mirror of
https://github.com/rennf93/roboco.git
synced 2026-08-03 07:23:24 +02:00
chore(release): 0.11.1
Patch release bundling the post-0.11.0 run-hardening + PR-gate fixes: - PMs can re-claim needs_revision coordination roots (runtime/spec claim parity) - finished merges don't respawn-loop when the target branch is gone from origin - no phantom re-delegation from text-vs-id acceptance-criteria ref mismatch - PRECONDITION_OWNERSHIP surfaces as not_authorized, not a tracing gap - the spawn gate suppresses respawns for every parked provider, not just Grok - the Claude session limit is detected from the agent transcript so the park fires - the in-path PR-review gate lands its verdict on product-scoped (root->master) PRs - the gate persists its verdict to notes_structured.pr_review (no stale "passed") Bumps all canonical version refs (pyproject / uv.lock / panel package.json / __init__ / config.app_version + README / deployment / agent-image-tag examples).
This commit is contained in:
@@ -6,6 +6,26 @@ The format is based on [Keep a Changelog](https://keepachangelog.com/en/1.1.0/),
|
||||
|
||||
## [Unreleased]
|
||||
|
||||
## [0.11.1] - 2026-06-25
|
||||
|
||||
### Fixed
|
||||
|
||||
- **A PM no longer respawn-loops on its own coordination root after it is bounced back for revision.** The lifecycle spec lets a cell/main PM re-claim a `needs_revision` coordination root — so a root rejected by `pr_fail` / `qa_fail` / `ceo_reject` can be re-planned and re-delegated via `i_will_plan` — but the runtime's claim-status map omitted `needs_revision` for the PM roles. The spec gate allowed the verb while the composed `claim()` underneath rejected it, returned nothing, and surfaced as a cryptic `INVALID_STATE`: the PM could neither plan nor idle its own rejected root and respawn-looped (one live run logged ~143 such rejections across 11 PM sessions — the tail of the 2026-06-24/25 firefight). The runtime claim statuses now include `needs_revision` for the PM roles, and a parity test locks the runtime map to the lifecycle spec so the two can't drift apart again.
|
||||
|
||||
- **A finished merge no longer respawn-loops the PM when its target branch has been deleted from origin.** When an integration (cell/root) branch is removed from origin — e.g. a sibling cell→root merge that strands a late straggler leaf — the post-merge `_sync_target_branch` ran `git fetch origin <branch>` and raised "couldn't find remote ref". But `pr_merge` only reaches that sync *after* the authoritative GitHub merge has already succeeded, so refreshing the local copy of the now-gone target branch is purely cosmetic — yet the raise surfaced as a retryable `SERVICE_ERROR`, so `complete()` re-blocked the task and respawn-looped the PM on an already-landed merge (observed live blocking a cell PM's `complete()` for 5+ cycles). The post-merge sync is now best-effort (it logs and returns instead of raising); the CEO merge path keeps the strict sync, since its target is the always-present default branch.
|
||||
|
||||
- **A PM no longer re-delegates already-finished work as an empty phantom subtask.** A parent's acceptance-criteria coverage is matched by stable criterion id, but a PM may declare `covers_parent_criteria` on a child by *either* the criterion's id or its full text (both happen in practice), and the coverage matcher only counted id matches. So a completed child that had declared its coverage by text was invisible to the roll-up: the criterion read "uncovered", the gate refused to close the parent, and the PM re-delegated the already-merged work as a brand-new empty subtask (zero commits, no PR) that can never close — looping for hours and burning tokens (observed live: a parent's work completed and merged via one child, then re-delegated two hours later as an empty phantom). Every child ref is now normalized to the criterion id (text → id via the parent's own criteria) before counting, so coverage is recognized however it was declared; an unknown ref still matches nothing, exactly as before.
|
||||
|
||||
- **An ownership failure now reads as an authorization error instead of a fixable tracing gap.** A `PRECONDITION_OWNERSHIP` rejection (a non-owner invoking an owner-only verb) was dispatched as a generic `tracing_gap` — which looks like a *recoverable* missing-artifact precondition, so a superseded agent kept retrying the same verb instead of fetching new work. Preconditions now carry a `rejection_kind`, and `PRECONDITION_OWNERSHIP` is tagged `not_authorized`, so an ownership failure surfaces as the clear identity/role boundary it is (and the choreographer and lifecycle spec now agree on the kind across the parity suite). This generalizes, at the spec layer, the same `not_authorized` steer the reassigned-developer `i_am_done` / `open_pr` short-circuit already gives.
|
||||
|
||||
- **The spawn gate now suppresses respawns for every parked provider, not just Grok.** When a provider is parked — a rate-limit 429, a persistent overload, or the Claude session limit — the dispatcher must stop launching new agent containers until it recovers, or it just re-spawns agents every tick straight back into the wall. That guard was Grok-only, so an Anthropic park still let the dispatcher churn. The spawn gate now consults the rate-limit tracker for *every* provider (failing open if the tracker itself errors), so any provider's park actually quiets dispatch.
|
||||
|
||||
- **A Claude session-limit hit is now detected from the agent's transcript, so the park actually fires.** Parking the workforce on the Claude "5-hour" session limit (added in 0.11.0) read the session-limit 429 markers from the agent container's `docker logs` — but the Claude SDK server writes its runtime output to a log file *inside* the container, so those markers never reached docker logs and the detector silently missed them, letting the whole fleet crash-respawn back into the limit. The detector now also reads the tail of the newest durable Claude transcript as a fallback, so a session-limit exit parks the provider and the background probe loop auto-revives the agents when the window resets.
|
||||
|
||||
- **A failed in-path PR-review gate now actually leaves its verdict on the PR.** The gate posts its pass/fail review to the assembled PR so the decision is visible where the PM (or CEO) merges — but it could only resolve the PR's repo from the task's `project_id`, and a Main-PM coordination root (the only task a root→master PR ever sits on) usually carries just a `product_id` (the cell→repo map) and no project of its own. So the slug resolved to nothing and the post silently no-op'd: a root→master PR could be failed back to `needs_revision` with no comment on the PR explaining why. The gate — and the external-PR reviewer's read-only diff fetch — now fall through to the product's repo when the task has no direct project, so the verdict reaches the PR.
|
||||
|
||||
- **A task's PR-reviewer notes no longer show "passed" after the gate failed it.** `pr_pass` / `pr_fail` only threaded their notes through the tracing-gate check and posted to GitHub — neither wrote the task's structured `pr_review` slot. So a task passed once and later failed kept displaying `verdict: passed` (green card and all) while its real transition was `pr_fail` → `needs_revision`. The gate now authors the canonical `pr_review` note on every decision — `pr_pass` records *passed*, `pr_fail` records *failed* with the issues — so the panel's PR-Reviewer card always matches the actual outcome (best-effort: a malformed note is skipped, never rolling back the gate decision).
|
||||
|
||||
## [0.11.0] - 2026-06-24
|
||||
|
||||
### Added
|
||||
|
||||
@@ -129,7 +129,7 @@ Choose the registry and version with two env vars (defaults shown):
|
||||
|
||||
```bash
|
||||
ROBOCO_REGISTRY=ghcr.io/rennf93 # or docker.io/renzof93
|
||||
ROBOCO_VERSION=latest # or a pinned release, e.g. 0.11.0
|
||||
ROBOCO_VERSION=latest # or a pinned release, e.g. 0.11.1
|
||||
```
|
||||
|
||||
The orchestrator spawns the matching pre-built agent images on demand — no build toolchain or source compile on your host.
|
||||
|
||||
@@ -30,7 +30,7 @@ Two variables choose what you pull (defaults shown):
|
||||
|
||||
```bash
|
||||
ROBOCO_REGISTRY=ghcr.io/rennf93 # or docker.io/renzof93
|
||||
ROBOCO_VERSION=latest # or a pinned release, e.g. 0.11.0
|
||||
ROBOCO_VERSION=latest # or a pinned release, e.g. 0.11.1
|
||||
```
|
||||
|
||||
The orchestrator then spawns the **matching** pre-built agent images on demand (it reads `ROBOCO_AGENT_IMAGE_REGISTRY` / `ROBOCO_AGENT_IMAGE_TAG`, which the registry compose wires to the same registry and version). Pin `ROBOCO_VERSION` to a release tag in production so an upstream `latest` push can't silently change your fleet.
|
||||
|
||||
+1
-1
@@ -1,6 +1,6 @@
|
||||
{
|
||||
"name": "roboco-panel",
|
||||
"version": "0.11.0",
|
||||
"version": "0.11.1",
|
||||
"private": true,
|
||||
"packageManager": "pnpm@10.25.0",
|
||||
"scripts": {
|
||||
|
||||
+1
-1
@@ -1,6 +1,6 @@
|
||||
[project]
|
||||
name = "roboco"
|
||||
version = "0.11.0"
|
||||
version = "0.11.1"
|
||||
description = "AI Agents Company - A virtual organization of AI agents functioning as a software development workforce"
|
||||
authors = [
|
||||
{name = "Renzo Franceschini", email = "rennf93@users.noreply.github.com"}
|
||||
|
||||
+1
-1
@@ -5,7 +5,7 @@ A virtual organization of 25 AI agents + 1 human CEO,
|
||||
designed to operate as a complete software development workforce.
|
||||
"""
|
||||
|
||||
__version__ = "0.11.0"
|
||||
__version__ = "0.11.1"
|
||||
|
||||
# Core exports
|
||||
from roboco.config import settings
|
||||
|
||||
+2
-2
@@ -28,7 +28,7 @@ class Settings(BaseSettings):
|
||||
# ==========================================================================
|
||||
# Application
|
||||
# ==========================================================================
|
||||
app_version: str = "0.11.0"
|
||||
app_version: str = "0.11.1"
|
||||
debug: bool = False
|
||||
environment: str = Field(
|
||||
default="development", pattern="^(development|staging|production)$"
|
||||
@@ -548,7 +548,7 @@ class Settings(BaseSettings):
|
||||
agent_image_tag: str = Field(
|
||||
default="",
|
||||
description=(
|
||||
"Tag for pre-built agent images (e.g. 'latest' or '0.11.0'). Empty "
|
||||
"Tag for pre-built agent images (e.g. 'latest' or '0.11.1'). Empty "
|
||||
"leaves the tag implicit (':latest'); only meaningful with "
|
||||
"agent_image_registry set."
|
||||
),
|
||||
|
||||
Reference in New Issue
Block a user