mirror of
https://github.com/rennf93/roboco.git
synced 2026-08-03 07:23:24 +02:00
Two structural issues flagged by the CEO:
1. Task technical-depth dilution — intake's rich analysis (file:line
targets, code examples, rationale) was getting lost as it traveled
umbrella -> root-subtask -> cell -> dev. The detail IS preserved in
Task.description; the dilution was in delegation (PMs re-authoring)
and the intake prompt not demanding depth.
Fixes:
- evidence_repo: ancestor_context_for_task walks the parent chain
(cycle-guarded, depth-capped 16, desc-clipped 1500) and surfaces it
as parent_context in the evidence payload, so a leaf dev finally
sees the upstream intake analysis instead of a bare title.
- evidence_builder: Task.description now rides in the payload;
EvidencePayload gains description + parent_context (omit-when-empty
so no null noise).
- orchestrator: _description_body (capped 4000) injects the
description into the dev spawn prompt + SessionStart briefing.
- role prompts (main_pm/cell_pm/developer/prompter): teach pass-the-
torch, don't-dim-it; prompter now demands file:line/code-examples
in the_work/notes (reconciled with the no-code-level-ACs-on-roots
rule). main_pm's brief-not-a-spec scoped: not-a-spec applies to the
solution only, facts forward verbatim.
2. PR-review/QA scope too narrow — they only checked the AC checklist,
not whether the change is coherent with project structure/intent.
Fixes:
- qa.md + pr_reviewer.md: Coherence & intent rule (intent via
description+parent_context, coherence with project patterns,
standards). Criterion-less major findings allowed for intent drift
(Finding.criterion is optional).
- parent_context + description wired into the gate/QA/inbound-PR
evidence builders (fail-open, logged).
Skipped per YAGNI: a technical_spec JSONB column (detail is already in
description) and a criterion_kind enum (criterion is already optional).
All gates green: ruff, mypy (1152), pytest (12883 passed, 94.82% cov),
xenon, vulture, bandit, pip-audit, deptry, alembic, import-linter,
foundation-check.
Co-authored-by: Renn F <rennf93@users.noreply.github.com>
35 lines
1.4 KiB
Python
35 lines
1.4 KiB
Python
"""``AgentOrchestrator._description_body`` — the bounded description block for
|
|
the dev spawn prompt + SessionStart briefing. Pure static helper, no fixtures."""
|
|
|
|
from __future__ import annotations
|
|
|
|
from roboco.runtime.orchestrator import AgentOrchestrator
|
|
|
|
_PLACEHOLDER = "(none — ask the PM before proceeding)"
|
|
|
|
|
|
class TestDescriptionBody:
|
|
def test_empty_returns_placeholder(self) -> None:
|
|
assert AgentOrchestrator._description_body("") == _PLACEHOLDER
|
|
assert AgentOrchestrator._description_body(None) == _PLACEHOLDER
|
|
assert AgentOrchestrator._description_body(" \n ") == _PLACEHOLDER
|
|
|
|
def test_short_description_returned_verbatim(self) -> None:
|
|
desc = "edit prompter.py:412 — thread task_id through update_live_batch"
|
|
assert AgentOrchestrator._description_body(desc) == desc
|
|
|
|
def test_long_description_capped_with_omitted_marker(self) -> None:
|
|
cap = 4000
|
|
desc = "x" * (cap + 1500)
|
|
body = AgentOrchestrator._description_body(desc)
|
|
assert body.startswith("x" * cap)
|
|
assert "chars omitted" in body
|
|
assert "evidence() carries" in body
|
|
# The kept prefix is exactly the cap; the marker follows.
|
|
assert len(body.split("\n… ", 1)[0]) == cap
|
|
|
|
def test_custom_cap_respected(self) -> None:
|
|
body = AgentOrchestrator._description_body("x" * 50, cap=10)
|
|
assert body.startswith("x" * 10)
|
|
assert "chars omitted" in body
|