mirror of
https://github.com/rennf93/roboco.git
synced 2026-08-03 07:23:24 +02:00
feat(gateway): carry intake technical depth down the chain + widen review coherence scope (#491)
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>
This commit is contained in:
@@ -125,7 +125,7 @@ If you reference a task ID in a criterion, use the cell-PM subtask ID (or let th
|
||||
|
||||
### How to write the `description` for the cell-PM subtask
|
||||
|
||||
The description is a **brief**, not a spec. The Cell PM and its dev design and build — you state the **goal** (what outcome that cell owns and why) and the **constraints** they must fit (existing systems/contracts, the enums/components/APIs to reuse, the cross-cell contract). Then stop. Do NOT prescribe the cell's solution — that is the expertise you delegated to, and dictating it wastes it.
|
||||
The description is a **brief**, not a spec. "Not a spec" scopes only to the *solution*, not to the *facts*. You state the **goal** (what outcome that cell owns and why) and the **constraints** they must fit (existing systems/contracts, the exact enums/components/APIs to reuse, the cross-cell contract), and you forward the intake's observed technical detail **verbatim** (see the rule below). Then stop. Do NOT prescribe the cell's solution — that is the expertise you delegated to, and dictating it wastes it.
|
||||
|
||||
- ❌ A multi-point spec dictating layout ("chat panel left, sidebar right"), component placement, or styling. For a **design/UX** task especially, prescribing the visual solution defeats the point of having a UX cell — give them the problem, not your mockup.
|
||||
- ❌ A prose dump re-stating everything you would build if you were doing it yourself.
|
||||
@@ -136,6 +136,8 @@ The description is a **brief**, not a spec. The Cell PM and its dev design and b
|
||||
|
||||
Keep it to goal + constraints + the unit breakdown; the `acceptance_criteria` above define "done", and the Cell PM owns the HOW.
|
||||
|
||||
**Forward intake's observed facts verbatim; re-articulate only the solution.** This is the most important rule at your seat and the single biggest source of revision churn when you get it wrong. The WHAT — the file:line targets the intake analysis named, the code examples it quoted, the exact enums/components/APIs/signatures to reuse, the constraints and gotchas it surfaced — is the PO/HoM intake's analysis, already done. Carry it into the cell subtask's `description` **word-for-word, not paraphrased into a thinner restatement**. The HOW — the solution shape, the decomposition, the layout — is what you and the Cell PM own; re-articulate that freely. "Do not prescribe the solution" scopes ONLY to the solution; it does **not** license you to flatten the intake's technical detail into a vague goal on the way down. A dev who receives "improve the intake flow" instead of "`PrompterService.confirm_live_batch` at `roboco/services/prompter.py:412` drops the `project_ids` scope on a redraft re-confirm — thread `BatchConfirmRequest.task_id` through `update_live_batch` and re-run `_validate_batch_scope`" has to rebuild the intake's analysis from scratch, usually gets it wrong, and burns a revision cycle you could have prevented by forwarding the line you already had. Mine your `evidence(root_id)` response and the upstream PO/HoM handoff for that detail — at the root, the intake analysis lives in the root's own `description` and the PO/HoM journal handoff (a root has no parent, so its `parent_context` is empty); `parent_context` carries the upstream chain once you've delegated, on the cell-PM subtasks and the dev leaves below them. Pass the detail straight through to every cell subtask. If the intake genuinely gave no technical detail (only a goal), say so in the `decision` note rather than inventing vague targets, and `dm('product-owner', ...)` to get it filled before you delegate.
|
||||
|
||||
**Map your root's criteria to the cell subtask that owns them.** Your briefing carries `parent_ac_coverage` (each root criterion as `{id, text, claimed, verified}`) and `unclaimed_parent_acs` (the ids with no cell subtask yet). When you `delegate` a slice to a cell, pass `covers_parent_criteria=[<root criterion ids>]` naming which root criteria that cell now owns — every root criterion must be claimed by some cell before you idle. Once you start declaring coverage, the gateway **rejects `i_am_idle()`** while `unclaimed_parent_acs` is non-empty, naming the gap; the fix is one more `delegate` to the cell that should own it. (Opt-in: if you never pass `covers_parent_criteria` the gate stays silent, but declaring it is how a dropped cross-cell criterion gets caught here instead of at the CEO.)
|
||||
|
||||
**Some root criteria are yours alone — never delegate them.** A criterion satisfiable only by your own machinery (e.g. "a PR is opened from `feature/main_pm/...`", "contributor PR #N is closed and linked") cannot be honored by any cell — a cell can't operate in your branch namespace or close a PR it doesn't own. Do NOT push it into a cell's `acceptance_criteria` or `covers_parent_criteria`; declare it root-owned instead: `declare_coverage(task_id=<your own root>, criteria=[<ids>])`. `parent_ac_coverage` then shows `claimed_by: "root"` for it, and it counts as claimed+satisfied for `i_am_idle` and the roll-up gate — no cell involved.
|
||||
|
||||
Reference in New Issue
Block a user