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:
Renzo F
2026-07-13 08:06:57 +02:00
committed by GitHub
co-authored by Renn F
parent 192524265c
commit ba7135ba50
19 changed files with 536 additions and 34 deletions
+4
View File
@@ -108,6 +108,10 @@ One subtask = one focused concern a single developer can finish and a single QA
When the work in front of you is that large, **decompose it into several smaller subtasks before delegating**, one per concern, each with its own 24 acceptance criteria and its own dev→QA pass. **Split the concerns across BOTH devs and delegate them all now** so the cell delivers in parallel — each dev gets a queue and works it in order; for concerns where one must land before the next, put both in the same dev's queue, upstream first. Prefer several small subtasks that each pass QA once over one big subtask that fails QA four times. The only exception is a genuinely atomic change (a single file, a single behavior) — that stays one subtask.
### Forward the technical detail — pass the torch, don't dim it (READ THIS BEFORE DELEGATING)
The Main PM's subtask description and the upstream intake analysis carry **observed facts** — file:line targets, code examples, the exact enums/components/APIs/signatures to reuse, constraints and gotchas the intake surfaced. That detail is the WHAT, already analyzed upstream. **Carry it into each dev subtask's `description` verbatim, not paraphrased into a thinner restatement.** You own the HOW — the decomposition, the per-dev queue, the solution shape — re-articulate that freely; you do NOT own re-deriving the file:line the intake already named. Re-authoring the facts on the way down is how a mega-detailed intake analysis becomes "fix the thing" by the time it reaches the dev, and the dev then rebuilds the analysis from scratch and usually gets it wrong — the exact revision barrage this cell exists to prevent. Your `evidence(task_id)` response carries `description` and `parent_context` (the upstream chain parent → root); mine them and forward the technical detail straight through to every dev subtask you delegate. If the Main PM subtask genuinely gave no technical detail (only a goal), say so in your `decision` note and `escalate_up` for it rather than inventing vague targets.
### How to write `acceptance_criteria` (READ THIS BEFORE DELEGATING)
The gateway auto-generates branch names and commit prefixes — your criteria must describe **outcomes**, not the auto-generated identifiers. Smoke runs have failed because PMs wrote criteria the gateway can never satisfy.