Doctrine
Conditional follow-ons go to backlog, not feed
Conditional follow-ons go to backlog, not feed
The rule (amends §16 Dying Well — FOLLOW-ONS LINE)
Executable follow-ons go to the feed as AWAITING_CLAIM. Conditional follow-ons go to the lane backlog with a trigger condition.
A follow-on is executable when all of:
- The work it describes can start NOW — no prerequisite ticket is unstarted or in-progress
- The code/schema/infra it touches EXISTS — no dependency on a merge that hasn't landed
- A seat with warm context could claim it this turn
A follow-on is conditional when any of:
- It is blocked on work that isn't
IN_PROGRESSyet ("after X lands, do Y") - It describes speculative improvement ("if we later need Z, consider W")
- It depends on a decision that hasn't been rendered
- It names a trigger that may never fire ("if users report X, investigate Y")
Where each goes
| Type | Destination | Required fields |
|---|---|---|
| Executable | FLEET_FEED.md via feed-append --kind actionable | ITEM, LANE, STATE=AWAITING_CLAIM, OWNER, QUEUE |
| Conditional | Lane backlog (<LANE>_WORK_BACKLOG.md) | ITEM, trigger condition, original context |
Backlog entry format for conditional follow-ons
### CMB-XXXX: <title>
**Status:** CONDITIONAL
**Trigger:** <specific, verifiable condition that makes this executable>
**Context:** <3-5 sentences — what the completing seat knew that the future seat needs>
**Filed-by:** <seat name>
**Filed-from:** <parent ticket ID>
**Filed:** <date>
The trigger must be mechanically verifiable — not "when it makes sense" but "when CMB-1908 merges" or "when bt_writes_audit has 0 production-targeted rows for 7 consecutive days." A trigger that can't be checked by grep/SQL/git-log is not a trigger — it's a wish.
What this changes in §16 Dying Well
The FOLLOW-ONS LINE at end of DONE posts now has three forms:
1. FOLLOW-ONS: CMB-XXXX claimed (self), CMB-XXXY AWAITING_CLAIM — executable, on feed 2. FOLLOW-ONS: CMB-XXXZ → CAMBER_WORK_BACKLOG (trigger: CMB-1908 merged) — conditional, on backlog 3. FOLLOW-ONS: none
The GENERATIVE TEST still counts conditional backlog entries. Filing to the backlog IS generative — it creates order. The difference is WHERE the order lives: executable order goes to the active queue; conditional order goes to the waiting room.
Queue health metric
Healthy feed: <30 BLOCKED items at any time. BLOCKED is now reserved for items that WERE executable but hit an unexpected blocker mid-work — not items that were always conditional.
Healthy backlog: any size. Backlogs are long-lived planning surfaces, not active queues. Items are promoted to the feed (via feed-append) when their trigger fires.
Trigger scanning
STRAT shepherd ticks MUST scan lane backlogs for fired triggers. Per-tick checklist addition:
- BACKLOG TRIGGER SCAN: For each lane, check CONDITIONAL items. If trigger condition is now met, promote to feed as
AWAITING_CLAIM. Cite the backlog entry when promoting.
This is the mechanism that prevents conditional follow-ons from rotting in the backlog.
Migration
Existing BLOCKED items in FLEET_FEED.md that are conditional (blocked on unstarted work, speculative, decision-dependent) will be migrated to lane backlogs. Items that are genuinely blocked mid-execution (waiting on a specific unblock action) stay in the feed.
What this doctrine kills
- Queue bloat from speculative follow-ons: 741 BLOCKED items in a feed designed for active work. The feed becomes unreadable,
fleet-active-queuebecomes slow, and seats can't find claimable work. - "One child policy" risk: Suppressing generative follow-ons is wrong — the fleet's generative instinct is valuable. The fix is routing, not throttling. File MORE follow-ons, but file them to the RIGHT surface.
- Phantom blockers: Items sitting BLOCKED in the feed on work that nobody has started. These aren't blocked — they're premature. A CONDITIONAL backlog entry is the honest representation.
- Shepherd overhead: STRAT spending cycles triaging 200+ BLOCKED items that can't be unblocked because their prerequisites don't exist yet.
Evidence
- 2026-04-26: 741 BLOCKED items in FLEET_FEED.md. 275 open items in
fleet-active-queue. ~174 are conditional (blocked on unstarted work). Feed is 74% blocked — designed capacity is <10% blocked. - Generative ratio was 35x on prompted seats (ORA-2026-0015 test, 2026-04-18). Suppressing follow-ons would destroy this. Routing them preserves it.
- Chad directive 2026-04-26: "looks like we are filing too many follow-ons. how to fix this without a 'one child policy' mistake."
Review cadence
- Next review: 2026-05-26 (30 days)
- Review triggers: (a) backlog items rot without trigger scanning, (b) executable items mistakenly routed to backlog, causing dropped work, (c) feed BLOCKED count doesn't decrease after migration