Establishes the tasks/architecture/ blocker-task half of the Safe Exit protocol. Each deferred OQ now has an external-trigger tracker task representing its unblocking condition, and the OQ's Blocked on field names the tracker task ID — closing the gap where the deferral field existed but the task-graph half was unenforced. Changes: - Add 6 external-trigger tracker tasks for the deferred OQs (OQ-09, 10, 32, 41, 44, 46) under tasks/architecture/, tagged [external-trigger, deferred-oq] - Add structured Blocked on field to OQ-09 and OQ-10 (previously used legacy 'deferred' status with the reason in the Resolution prose); index now surfaces all 6 deferred OQs with concrete conditions, no placeholders - Document the architecture-task level mapping (level: implementation for ADRs/specs, decomposition for spec-to-ADR breakdown, planning for backlog seeding, research/review direct fits) and the deferred-OQ blocker-task pattern in docs/sdd_process.md - Mark architecture/safe-exit-blocker-task-mechanism and architecture/oq-09-10-blocking-conditions completed (implemented by this pass) - Fix 4 pre-existing ADR-050 implementation tasks: status: done → completed (taskgraph enum is 'completed', not 'done') — taskgraph validate now passes for all 100 tasks
4.7 KiB
id, name, status, depends_on, scope, risk, impact, level, tags
| id | name | status | depends_on | scope | risk | impact | level | tags | |
|---|---|---|---|---|---|---|---|---|---|
| architecture/safe-exit-blocker-task-mechanism | Establish the tasks/architecture/ blocker-task half of the Safe Exit protocol | completed | moderate | low | project | planning |
|
Description
During the open-questions.md decompose (July 2026), I found that the role
spec's Safe Exit protocol says "create a blocker task in tasks/architecture/
that names the dependency" when deferring a decision — but that directory has
never existed. The four deferred(scope) OQs in the current file (OQ-32,
OQ-41, OQ-44, OQ-46) carry a Blocked on: field but no corresponding blocker
task files anywhere in the repo.
So the deferral field exists (the visibility half), but the task half of the safe-exit mechanism is unenforced/unused. This task is about establishing the convention so future deferrals create the corresponding blocker task, and backfilling the existing deferred OQs.
Context
The project's broader pattern (per the July 2026 discussion): questions often
lead to decisions which lead to tasks — a graph not unlike how implementation
tasks are modeled as a DAG. The tasks/architecture/ directory is where the
"this decision is blocked on X" blocker tasks live, so that:
- A deferred OQ has a visible
Blocked on:condition in the index (the open-questions.md "Deferred / Blocked" section — already in place after the decompose). - A deferred OQ has a corresponding blocker task that names the dependency and can itself be depended on by downstream work that needs the decision resolved.
The two halves serve different audiences: the index section is for the architect ("what's currently parked and why"), the blocker task is for the implementation agent / planner ("what unblocks this, and what's waiting on it").
Work
- Confirm the task file format (YAML frontmatter:
id,name,status,depends_on,scope,risk,impact,level) is the right shape for architecture blocker tasks, or adjust if the architecture workflow needs different fields (e.g., ablocks:field pointing back at the OQ). - Backfill blocker tasks for the four existing
deferred(scope)OQs:- OQ-32 (Multi-Hop Federation) — blocked on a concrete multi-hop use case
- OQ-41 (Stream Operators Library) — blocked on a handler needing operators beyond existing combinators
- OQ-44 (Terminal Modes) — blocked on a concrete mode-control use case
- OQ-46 (Runner API Surface) — blocked on a concrete runner-policy use case
- Document the convention (one line in
docs/sdd_process.mdor the architect role spec) so future deferrals create the blocker task as part of the Safe Exit step.
Summary
Completed in the July 2026 architecture-task pass. Decisions:
- Format: adopted the existing taskgraph frontmatter verbatim — no new
blocks:field. One edge type (depends_on) keeps the graph simple; the reverse lookup usestaskgraph dependents. The OQ'sBlocked on:text is the human-readable pointer; the taskdepends_onis the machine-readable edge. They serve different audiences (architect vs. planner/agent). - External-trigger tasks: the four
deferred(scope)OQs (32, 41, 44, 46) plus the two legacydeferredOQs (09, 10) each got an external-trigger tracker task undertasks/architecture/tagged[external-trigger, deferred-oq]. These represent the external condition (a use case arriving, a crate being specced) that would unblock the OQ — they are not actionable work, sorisk: trivialandlevel: research. - OQ-09/10 backfill: added a structured
Blocked on:field to both (previously they used legacydeferredstatus with the reason in the Resolution prose). Theopen-questions.mdindex now surfaces all six deferred OQs with concrete blocking conditions in the Deferred/Blocked section — no more "(no explicit blocking condition recorded)" placeholders. - Convention doc: the
docs/sdd_process.mdTask File Format section is updated with the architecture-task level mapping and the Safe Exit blocker-task pattern (separate edit).
Out of scope
- The DB-backed backend (no manual links, vector/text search) — that's a future evolution that this file-based pattern informs, not something to build now.
- Re-resolving any of the deferred OQs — this is about the tracking mechanism, not the decisions themselves.
Verification
tasks/architecture/contains one external-trigger task per deferred OQ (six total: OQ-09, 10, 32, 41, 44, 46).- Each OQ's
Blocked on:field names its tracker task ID, and theopen-questions.mdDeferred/Blocked section surfaces the condition inline. taskgraph validatepasses fortasks/architecture/.docs/sdd_process.mdreferences the convention.