mirror of
https://github.com/rennf93/roboco.git
synced 2026-08-03 07:23:24 +02:00
Wave 1: PR-gate turn cut, task search, trace timestamps, Secretary edits + e2e scenarios 2–3 (#295)
* feat(tests): e2e scenario 2 — the PM merge chain through the PR gate
Shared arcs extracted (arcs.py: canonical-company seeding + dev/qa/doc
segments); scenario 2 seeds a root->cell->dev hierarchy mid-flight, rides
the child through the scenario-1 arc into the cell branch (real squash
via the fake GitHub), then submit_up -> claim_gate_review/pr_pass ->
dispatcher re-claim (mirrored) -> PM complete merging cell->root. This is
the exact PM->reviewer->PM turn sequence the wave-1 turn cut shortens —
the BEFORE-net. Learned seams scripted: commit-subject validator (>=20
chars), reviewer learning-note gate, pr_pass clears ownership by design.
* feat(runtime): PR-gate turn cut — assembled parents auto-submit to the reviewer
When every child of an assembled parent is terminal, the closure
dispatcher now runs the real submit_up/submit_root through the internal
API as the owning PM (_try_auto_submit) instead of spawning the PM for
that turn — the submit's substance is deterministic gate code. Any gate
refusal falls back to the classic PM closure spawn; pr_fail routing and
the PM's final merge turn are unchanged; umbrellas never auto-submit.
ROBOCO_PR_GATE_AUTO_SUBMIT_ENABLED default-on; task.auto_submitted audit
row per cut. Proven by e2e scenario 2b (real API, real gates, real git)
against scenario 2 as the before-net.
* feat(notes): structured note sections carry a written_at trace stamp
Sections are overwrite-in-place, so without a stamp there was no way to
reconstruct WHEN a dev/qa/doc/reviewer note landed (CEO reMarkable item:
trace TIMESTAMPS). apply_structured_note stamps ISO written_at beside
the model fields; the panel notes tab renders it next to each card
title (pre-stamp rows render nothing). Progress updates, commits, and
journal entries already carried timestamps — this was the one gap.
* feat(tasks): server-side task search — title, details, and id prefix
The task list's search box only matched titles client-side, and the
trimmed summary payload deliberately carries no description — so
keyword/details/id search was impossible in the browser by design.
GET /tasks/summary gains q (ILIKE over title+description, id-prefix
match, composed with team/status and the view-permission scoping);
the panel debounces the box into the summary fetch and drops the
title-only client filter that would have hidden description matches.
* feat(wave-1): trace timestamps, real task search, Secretary task edits
- apply_structured_note stamps written_at per section; the panel notes
tab shows it (the one trace surface without a timestamp).
- GET /tasks/summary?q= searches title+description+id-prefix server-side
(summaries carry no description by design); panel debounces into the
fetch and drops the title-only client filter.
- Secretary control_task gains a CEO-gated edit action over the content
allowlist, and GET /secretary/tasks?q= resolves task names to ids for
the chat. PM-side expansion deferred per the CEO's 'not that much'.
* fix(workspace): dep-update probe scrubs the inherited venv pin
Under uv run the orchestrator's process tree carries VIRTUAL_ENV, and a
uv-based dep_update_command in the throwaway probe clone would target
that venv instead of the clone's — the same hazard _uv_subprocess_env
already guards on the install path.
* build: private per-repo uv cache — isolate from machine-wide uvx servers
Root cause of the recurring rich/pip/bandit rot, with evidence: uv cache
clean timed out on the ~/.cache/uv lock ('is another uv process
running?') — three uvx mcp-server-fetch processes (Claude Code fetch MCP,
one alive since Wednesday) share that cache and race repo syncs on it;
poisoned entries then survive venv rebuilds because rm -rf .venv never
touches the cache, and every re-link reproduces the breakage. UV_CACHE_DIR
now pins <repo>/.uv-cache (gitignored). The earlier UV_NO_SYNC
serialization stays as defense-in-depth but was not the whole story.
* feat(tests): e2e scenario 3 — pr_fail revision loop + root→CEO chain
3a: reviewer pr_fail with a concrete issue -> needs_revision ->
i_will_plan re-entry (full plan gates) -> real fix lands on the cell
branch (the unchanged-PR hard gate refuses resubmit until it does) ->
clean second pass -> merge. 3b: submit_root -> gate -> Main PM complete
escalates the root to the CEO -> the REAL approve-and-merge endpoint
squash-merges to the origin's master. Harness gains the tasks router, a
seeded CEO identity, origin_commit, and a fake GitHub whose head.sha is
recomputed live (real-GitHub semantics the unchanged gate reads). Seeds
now encode the real shape: delivery roots are team=main_pm and
planning-typed.
---------
Co-authored-by: Renn F <rennf93@users.noreply.github.com>
This commit is contained in:
@@ -4,6 +4,17 @@ All notable changes to RoboCo are documented in this file.
|
||||
|
||||
The format is based on [Keep a Changelog](https://keepachangelog.com/en/1.1.0/), and this project adheres to [Semantic Versioning](https://semver.org/spec/v2.0.0.html).
|
||||
|
||||
## [Unreleased]
|
||||
|
||||
### Added
|
||||
|
||||
- **The PR-gate turn cut — assembled parents auto-submit to the reviewer.** When every child of an assembled parent is terminal, the orchestrator used to spawn the PM just to call `submit_up`/`submit_root` — a whole agent turn whose substance (freshness rebase, integrity check, PR open) is deterministic gate code. The closure dispatcher now runs the REAL submit verb through the internal API as the owning PM (`_try_auto_submit`); the task lands in `awaiting_pr_review` and the reviewer dispatch takes it with no PM turn spent. Every gate is intact: a submit rejection (freshness/integrity — the case that genuinely needs judgment) falls back to the classic PM closure spawn, `pr_fail` still routes `needs_revision` to the PM, and the PM keeps the final merge turn. Branchless coordination parents (MegaTask umbrellas) never auto-submit. Gated by `ROBOCO_PR_GATE_AUTO_SUBMIT_ENABLED` (default **on**); each auto-submit leaves a `task.auto_submitted` audit row.
|
||||
- **Task search that actually searches.** The task list's search box only matched titles client-side — and the trimmed summary payload deliberately carries no description, so keyword/details/id search was impossible in the browser by design. `GET /tasks/summary` gains `q` (ILIKE over title + description, id-prefix match, composed with team/status filters and view-permission scoping); the panel debounces the box into the fetch and drops the title-only client filter that would have hidden description matches.
|
||||
- **Trace timestamps on structured notes.** Note sections (dev/qa/doc/reviewer/handoff) are overwrite-in-place with no stamp, so there was no way to reconstruct WHEN a note landed. `apply_structured_note` now stamps ISO `written_at` beside the model fields and the panel notes tab renders it next to each card title. Progress updates, commits, and journal entries already carried timestamps — this closed the one gap.
|
||||
- **The Secretary can modify tasks (CEO-gated).** The `control_task` directive gains an `edit` action restricted to the content allowlist (title, description, acceptance criteria, priority) — status/ownership/git fields keep their own audited paths — and `GET /secretary/tasks?q=` resolves task NAMES to ids (Secretary/CEO only), so a CEO chat instruction like "sharpen the greeting task's title" can target the right task without a UUID.
|
||||
- **e2e scenario 3 — the pr_fail revision loop and the root → CEO chain.** 3a walks the honest revision loop: the reviewer `pr_fail`s the assembled cell PR with a concrete issue → `needs_revision` → the PM re-enters via `i_will_plan` (full plan gates), real fix work lands on the cell branch (the 0.14.0 unchanged-PR hard gate correctly refuses resubmission until it does), and the second gate pass rides through to the merge. 3b closes the whole company loop with no LLM anywhere: `submit_root` opens the root→master PR, the reviewer gate-passes it, the Main PM's `complete` escalates the root parent to the CEO, and the REAL `POST /tasks/{id}/approve-and-merge` endpoint squash-merges to the origin's master. The fake GitHub now recomputes `head.sha` live from the branch (real-GitHub semantics the unchanged-PR gate depends on).
|
||||
- **e2e scenarios 2 + 2b — the PM merge chain, before and after the cut.** Shared scripted-agent arcs (`tests/e2e_smoke/arcs.py`) drive a root→cell→dev hierarchy: the child lands via the scenario-1 arc (real squash through the fake GitHub), then scenario 2 walks the classic PM `submit_up` → reviewer `pr_pass` → dispatcher re-claim → PM merge chain, and scenario 2b proves the turn cut end-to-end — no agent calls submit; `_try_auto_submit` drives the real verb through the real API and the reviewer→PM tail runs unchanged, landing the child's file on the root branch.
|
||||
|
||||
## [0.16.0] - 2026-07-02
|
||||
|
||||
### Added
|
||||
|
||||
Reference in New Issue
Block a user