tasks(arch): adopt taskgraph for architecture work — blocker tasks for deferred OQs, level mapping, status fixes
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
This commit is contained in:
1 parent
e6062230f9
commit
df5d04af1d
16 files changed
+440
-14
No files matched your search
@@ -1,12 +1,13 @@
|
||||
---
|
||||
id: architecture/oq-09-10-blocking-conditions
|
||||
name: Add explicit Blocked on conditions to OQ-09 (WASM) and OQ-10 (Git Adapter)
|
||||
status: pending
|
||||
status: completed
|
||||
depends_on: []
|
||||
scope: narrow
|
||||
risk: low
|
||||
impact: component
|
||||
level: decomposition
|
||||
tags: [convention]
|
||||
---
|
||||
|
||||
## Description
|
||||
@@ -39,8 +40,20 @@ Either:
|
||||
The decision content stays unchanged — this is a metadata-structure fix, not a
|
||||
re-resolution.
|
||||
|
||||
## Summary
|
||||
|
||||
Completed alongside `architecture/safe-exit-blocker-task-mechanism`. Added a
|
||||
structured `Blocked on:` field to both OQ-09 and OQ-10 in their per-OQ files,
|
||||
each pointing at its new external-trigger tracker task
|
||||
(`architecture/oq-09-wasm-server-use-case`,
|
||||
`architecture/oq-10-git-adapter-spec`). Kept the legacy `deferred` status
|
||||
rather than reframing to `deferred(scope)` — the distinction is no longer
|
||||
load-bearing now that both have explicit blocking conditions and tracker
|
||||
tasks. The `open-questions.md` Deferred/Blocked section now surfaces all six
|
||||
deferred OQs with concrete conditions inline — no placeholders remain.
|
||||
|
||||
## Verification
|
||||
|
||||
The "Deferred / Blocked" section of `docs/architecture/open-questions.md` should
|
||||
show a concrete blocking condition for OQ-09 and OQ-10 instead of the "no
|
||||
The "Deferred / Blocked" section of `docs/architecture/open-questions.md`
|
||||
shows a concrete blocking condition for OQ-09 and OQ-10 instead of the "no
|
||||
explicit blocking condition recorded" placeholder.
|
||||
@@ -0,0 +1,58 @@
|
||||
---
|
||||
id: architecture/oq-09-wasm-server-use-case
|
||||
name: External trigger — a concrete server-side WASM use case (or confirmation it stays a client-side constraint)
|
||||
status: pending
|
||||
depends_on: []
|
||||
scope: single
|
||||
risk: trivial
|
||||
impact: component
|
||||
level: research
|
||||
tags: [external-trigger, deferred-oq]
|
||||
---
|
||||
|
||||
## Description
|
||||
|
||||
External-trigger tracker for [OQ-09](../docs/architecture/questions/009-wasm-target-boundaries.md)
|
||||
(WASM Target Boundaries). This is **not actionable work** — it tracks whether
|
||||
a concrete server-side WASM use case has emerged, or whether the project
|
||||
confirms that WASM compatibility remains a *client-side* design constraint
|
||||
only (a browser can implement BiStream over WebTransport streams; the
|
||||
server-side dispatch door is a known, accepted closure per ADR-007/009).
|
||||
|
||||
## Trigger condition
|
||||
|
||||
Either:
|
||||
- **A concrete server-side WASM use case arrives** (a deployment that wants
|
||||
to run an alknet server peer compiled to WASM, which would require a
|
||||
`Connection` trait and a runtime-abstracted accept loop — currently not
|
||||
planned), or
|
||||
- **A deliberate confirmation** that WASM stays a client-side design
|
||||
constraint, at which point OQ-09 transitions from `deferred` to `resolved`
|
||||
with the accepted-closure framing already in its Resolution text.
|
||||
|
||||
The second path is the more likely one — the OQ exists mainly so the
|
||||
server-side WASM door closure is documented rather than implicit.
|
||||
|
||||
## What unblocking looks like
|
||||
|
||||
When a decision is made (either direction):
|
||||
|
||||
1. Mark this task `status: completed`.
|
||||
2. Move [OQ-09](../docs/architecture/questions/009-wasm-target-boundaries.md)
|
||||
from `deferred` to either `resolved` (client-side-only confirmed) or `open`
|
||||
(server-side use case arrives, requiring a Connection trait + WASM runtime
|
||||
abstraction ADR).
|
||||
|
||||
## Why this is a task, not just an OQ field
|
||||
|
||||
OQ-09 predates the formalized `deferred(scope)` + blocking-condition pattern
|
||||
and lacked a structured `Blocked on:` field (it used the legacy `deferred`
|
||||
status with the deferral reason in the Resolution prose). This task
|
||||
formalizes the blocking condition and gives the OQ a machine-readable
|
||||
presence in the task graph.
|
||||
|
||||
## Verification
|
||||
|
||||
This task is "completed" when either a server-side WASM use case arrives
|
||||
(move OQ-09 to `open`) or the client-side-only constraint is confirmed
|
||||
(move OQ-09 to `resolved`).
|
||||
@@ -0,0 +1,56 @@
|
||||
---
|
||||
id: architecture/oq-10-git-adapter-spec
|
||||
name: External trigger — speccing alknet-git (resolve OQ-10 when that crate is specified, not deferred past it)
|
||||
status: pending
|
||||
depends_on: []
|
||||
scope: single
|
||||
risk: trivial
|
||||
impact: component
|
||||
level: research
|
||||
tags: [external-trigger, deferred-oq]
|
||||
---
|
||||
|
||||
## Description
|
||||
|
||||
External-trigger tracker for [OQ-10](../docs/architecture/questions/010-git-adapter-scope-smart-protocol-only-or-full-server.md)
|
||||
(Git Adapter Scope — Smart Protocol Only or Full Server?). This is **not
|
||||
actionable work** — it tracks when the alknet-git crate is being specified,
|
||||
at which point OQ-10 must be resolved (not deferred past it).
|
||||
|
||||
## Trigger condition
|
||||
|
||||
The alknet-git crate is being specified. The OQ's Resolution text already
|
||||
states: "Resolve this when speccing alknet-git, not deferred past it." The
|
||||
two sub-questions:
|
||||
|
||||
1. **Git adapter scope** — start with git smart protocol over QUIC streams;
|
||||
ERC721 integration and full server capabilities are additive.
|
||||
2. **Composability fork** — whether git operations are registered in the
|
||||
`OperationRegistry` and callable via `env.invoke()`, or only available as
|
||||
raw smart protocol on `alknet/git`. The path of least resistance (raw
|
||||
smart protocol only) forecloses agent composition of git operations; to
|
||||
make git composable, a call-protocol projection (a set of
|
||||
`HandlerRegistration` bundles wrapping git operations behind the
|
||||
registry) must be built alongside or instead of the raw handler.
|
||||
|
||||
## What unblocking looks like
|
||||
|
||||
When alknet-git is specced:
|
||||
|
||||
1. Mark this task `status: completed`.
|
||||
2. Move [OQ-10](../docs/architecture/questions/010-git-adapter-scope-smart-protocol-only-or-full-server.md)
|
||||
from `deferred` to `open`, then resolve it as part of the alknet-git spec
|
||||
pass (the Resolution text is explicit: do not defer past the spec).
|
||||
|
||||
## Why this is a task, not just an OQ field
|
||||
|
||||
OQ-10 predates the formalized `deferred(scope)` + blocking-condition pattern
|
||||
and lacked a structured `Blocked on:` field (it used the legacy `deferred`
|
||||
status with the deferral reason in the Resolution prose). This task
|
||||
formalizes the blocking condition and gives the OQ a machine-readable
|
||||
presence in the task graph.
|
||||
|
||||
## Verification
|
||||
|
||||
This task is "completed" when alknet-git is being specced and OQ-10 has been
|
||||
moved to `open` (then resolved as part of that spec pass).
|
||||
@@ -0,0 +1,53 @@
|
||||
---
|
||||
id: architecture/oq-32-multihop-use-case
|
||||
name: External trigger — a concrete multi-hop federation use case
|
||||
status: pending
|
||||
depends_on: []
|
||||
scope: single
|
||||
risk: trivial
|
||||
impact: component
|
||||
level: research
|
||||
tags: [external-trigger, deferred-oq]
|
||||
---
|
||||
|
||||
## Description
|
||||
|
||||
External-trigger tracker for [OQ-32](../docs/architecture/questions/032-multi-hop-federation.md)
|
||||
(Multi-Hop Federation). This is **not actionable work** — it tracks whether a
|
||||
concrete use case for multi-hop federation has arrived. When it does, mark this
|
||||
task `completed` and the OQ moves from `deferred(scope)` to `open`.
|
||||
|
||||
## Trigger condition
|
||||
|
||||
A concrete deployment or use case that requires transitive op discovery across
|
||||
more than one hop — i.e., worker A needs to reach worker B's ops *through* the
|
||||
head, where the head is not explicitly re-exporting them. The one-hop model
|
||||
(head→worker, runner→hub) covers all current use cases.
|
||||
|
||||
## What unblocking looks like
|
||||
|
||||
When a use case arrives:
|
||||
|
||||
1. Mark this task `status: completed`.
|
||||
2. Move [OQ-32](../docs/architecture/questions/032-multi-hop-federation.md)
|
||||
from `deferred(scope)` to `open` (update the Status field + the
|
||||
`open-questions.md` index tables + Deferred/Blocked section).
|
||||
3. Create an architecture task to write the multi-hop federation ADR — the
|
||||
peer-keyed overlay model extends to multi-hop without redesign (ADR-029 §3.7),
|
||||
but path-finding (which peer reaches which op transitively) is where the
|
||||
design work lives. A graph library (petgraph) may pay off for multi-hop; for
|
||||
one-hop, a nested `HashMap<PeerId, HashMap<String, ...>>` suffices.
|
||||
|
||||
## Why this is a task, not just an OQ field
|
||||
|
||||
The OQ's `Blocked on:` field in `open-questions.md` is the human-readable
|
||||
visibility surface ("what's parked and why"). This task is the machine-readable
|
||||
half: it lives in the task graph so `taskgraph` tools can reason about it, and
|
||||
so downstream work that depends on multi-hop being resolved can declare
|
||||
`depends_on: [architecture/oq-32-multihop-use-case]`.
|
||||
|
||||
## Verification
|
||||
|
||||
This task is "completed" when a concrete multi-hop use case is documented
|
||||
(e.g., in a research finding or deployment note) and OQ-32 has been moved to
|
||||
`open`.
|
||||
@@ -0,0 +1,66 @@
|
||||
---
|
||||
id: architecture/oq-41-stream-operators-use-case
|
||||
name: External trigger — a handler that needs stream operators beyond existing combinators
|
||||
status: pending
|
||||
depends_on: []
|
||||
scope: single
|
||||
risk: trivial
|
||||
impact: component
|
||||
level: research
|
||||
tags: [external-trigger, deferred-oq]
|
||||
---
|
||||
|
||||
## Description
|
||||
|
||||
External-trigger tracker for [OQ-41](../docs/architecture/questions/041-stream-operators-library.md)
|
||||
(Stream Operators Library). This is **not actionable work** — it tracks
|
||||
whether a handler has emerged that needs stream operators (filter, map, batch,
|
||||
dedupe, window, etc. on `BoxStream<T>`) and finds the existing combinators
|
||||
insufficient. The operators library is a convenience, not a prerequisite for
|
||||
any handler.
|
||||
|
||||
## Trigger condition
|
||||
|
||||
A handler that transforms subscription streams (`BoxStream<ResponseEnvelope>`)
|
||||
and finds `Box::pin(stream::iter(...))`, `async_stream::stream!`, and
|
||||
`futures::stream` combinators insufficient — i.e., the handler code is
|
||||
demonstrably boilerplate-heavy for stream manipulation that the operators
|
||||
library would collapse. The architectural decision (stream composition is
|
||||
handler-level, not protocol-level) is already made in ADR-049; this tracks the
|
||||
*implementation* of the utility library.
|
||||
|
||||
## What unblocking looks like
|
||||
|
||||
When a handler needs the operators:
|
||||
|
||||
1. Mark this task `status: completed`.
|
||||
2. Move [OQ-41](../docs/architecture/questions/041-stream-operators-library.md)
|
||||
from `deferred(scope)` to `resolved` (the architectural decision is already
|
||||
made — ADR-049; what remains is the implementation, which is scheduling
|
||||
work). The OQ may transition directly to `resolved` rather than `open`,
|
||||
since no architecture decision remains.
|
||||
3. Implement the operators library (no ADR needed — internal utility code
|
||||
that doesn't cross crate boundaries as a contract; an ADR would be
|
||||
warranted only if the operators become part of a public API surface, e.g.,
|
||||
a handler-registration DSL that references operator names).
|
||||
|
||||
## Why this is a task, not just an OQ field
|
||||
|
||||
The OQ's `Blocked on:` field in `open-questions.md` is the human-readable
|
||||
visibility surface. This task is the machine-readable half: it lives in the
|
||||
task graph so `taskgraph` tools can reason about it, and so a handler that
|
||||
needs the operators can declare `depends_on:
|
||||
[architecture/oq-41-stream-operators-use-case]`.
|
||||
|
||||
## Prior art
|
||||
|
||||
`@alkdev/pubsub/src/operators.ts` — 13 operators (`filter`, `map`, `take`,
|
||||
`batch`, `dedupe`, `window`, `chain`, `join`, `reduce`, `groupBy`, `flat`,
|
||||
`pipe`, `toArray`) on `AsyncIterable<T>`, forked from graphql-yoga's
|
||||
subscription implementation. The Rust analogue would provide the same set on
|
||||
`BoxStream<T>` / `impl Stream<Item = T>`.
|
||||
|
||||
## Verification
|
||||
|
||||
This task is "completed" when a handler is identified that needs the operators
|
||||
and OQ-41 has been moved to `resolved`.
|
||||
@@ -0,0 +1,51 @@
|
||||
---
|
||||
id: architecture/oq-44-tty-modes-use-case
|
||||
name: External trigger — a concrete TTY mode-control use case
|
||||
status: pending
|
||||
depends_on: []
|
||||
scope: single
|
||||
risk: trivial
|
||||
impact: component
|
||||
level: research
|
||||
tags: [external-trigger, deferred-oq]
|
||||
---
|
||||
|
||||
## Description
|
||||
|
||||
External-trigger tracker for [OQ-44](../docs/architecture/questions/044-terminal-modes-tty-modes.md)
|
||||
(Terminal Modes / TTY modes). This is **not actionable work** — it tracks
|
||||
whether a concrete deployment has emerged that needs to set TTY modes (echo,
|
||||
raw, canonical, etc.) on a PTY beyond the backend's defaults.
|
||||
|
||||
## Trigger condition
|
||||
|
||||
A concrete deployment that needs to control TTY modes beyond the defaults the
|
||||
backends already provide (`portable_pty`, docker `tty: true`, russh
|
||||
`pty_request` all have defaults that work for the common terminal case). The
|
||||
`modes` field in `TerminalParams` is `serde_json::Value` (reserved as `{}` in
|
||||
v1) for when this arrives.
|
||||
|
||||
## What unblocking looks like
|
||||
|
||||
When a mode-control use case arrives:
|
||||
|
||||
1. Mark this task `status: completed`.
|
||||
2. Move [OQ-44](../docs/architecture/questions/044-terminal-modes-tty-modes.md)
|
||||
from `deferred(scope)` to `open`.
|
||||
3. Specify the `modes` JSON shape (SSH's `pty_request` carries TTY modes as a
|
||||
packed bitmask; the Rust analogue extends the `modes` field). Adding mode
|
||||
control is additive (extend the `modes` JSON shape) and does not break
|
||||
downstream — the architectural commitment is two-way-door.
|
||||
|
||||
## Why this is a task, not just an OQ field
|
||||
|
||||
The OQ's `Blocked on:` field in `open-questions.md` is the human-readable
|
||||
visibility surface. This task is the machine-readable half: it lives in the
|
||||
task graph so `taskgraph` tools can reason about it, and so downstream work
|
||||
that depends on TTY mode control can declare `depends_on:
|
||||
[architecture/oq-44-tty-modes-use-case]`.
|
||||
|
||||
## Verification
|
||||
|
||||
This task is "completed" when a concrete mode-control use case is documented
|
||||
and OQ-44 has been moved to `open`.
|
||||
@@ -0,0 +1,52 @@
|
||||
---
|
||||
id: architecture/oq-46-runner-policy-use-case
|
||||
name: External trigger — a concrete runner-policy use case that forces the API surface
|
||||
status: pending
|
||||
depends_on: []
|
||||
scope: single
|
||||
risk: trivial
|
||||
impact: component
|
||||
level: research
|
||||
tags: [external-trigger, deferred-oq]
|
||||
---
|
||||
|
||||
## Description
|
||||
|
||||
External-trigger tracker for [OQ-46](../docs/architecture/questions/046-runner-api-surface.md)
|
||||
(Runner API Surface). This is **not actionable work** — it tracks whether a
|
||||
concrete runner-policy use case has emerged that forces the API surface (job
|
||||
management, log persistence, task graph integration). The runner *mechanism*
|
||||
(pipe mode) is already in alknet-tty (ADR-054); the runner *policy* is a
|
||||
downstream crate's job.
|
||||
|
||||
## Trigger condition
|
||||
|
||||
A concrete deployment that needs runner *policy* — job management, log
|
||||
persistence, task graph integration — on top of the pipe-mode mechanism
|
||||
(`TtyParams.terminal = None` → `std::process::Command` with piped stdio →
|
||||
framed byte stream + exit code) that alknet-tty already provides.
|
||||
|
||||
## What unblocking looks like
|
||||
|
||||
When a runner-policy use case arrives:
|
||||
|
||||
1. Mark this task `status: completed`.
|
||||
2. Move [OQ-46](../docs/architecture/questions/046-runner-api-surface.md)
|
||||
from `deferred(scope)` to `open`.
|
||||
3. Decide whether a runner-policy crate (e.g., an `alknet-runner` crate that
|
||||
builds on the pipe mode + the wire format to provide job management) is
|
||||
needed, and what its API surface would be. The mechanism is preserved
|
||||
regardless of the policy decision.
|
||||
|
||||
## Why this is a task, not just an OQ field
|
||||
|
||||
The OQ's `Blocked on:` field in `open-questions.md` is the human-readable
|
||||
visibility surface. This task is the machine-readable half: it lives in the
|
||||
task graph so `taskgraph` tools can reason about it, and so downstream work
|
||||
that depends on runner policy can declare `depends_on:
|
||||
[architecture/oq-46-runner-policy-use-case]`.
|
||||
|
||||
## Verification
|
||||
|
||||
This task is "completed" when a concrete runner-policy use case is documented
|
||||
and OQ-46 has been moved to `open`.
|
||||
@@ -1,12 +1,13 @@
|
||||
---
|
||||
id: architecture/safe-exit-blocker-task-mechanism
|
||||
name: Establish the tasks/architecture/ blocker-task half of the Safe Exit protocol
|
||||
status: pending
|
||||
status: completed
|
||||
depends_on: []
|
||||
scope: moderate
|
||||
risk: low
|
||||
impact: project
|
||||
level: planning
|
||||
tags: [convention]
|
||||
---
|
||||
|
||||
## Description
|
||||
@@ -58,6 +59,30 @@ it").
|
||||
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 uses `taskgraph dependents`. The OQ's `Blocked on:` text is
|
||||
the human-readable pointer; the task `depends_on` is 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 legacy `deferred` OQs (09, 10) each got an external-trigger
|
||||
tracker task under `tasks/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, so `risk: trivial` and `level: research`.
|
||||
- **OQ-09/10 backfill**: added a structured `Blocked on:` field to both
|
||||
(previously they used legacy `deferred` status with the reason in the
|
||||
Resolution prose). The `open-questions.md` index 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.md` Task 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
|
||||
@@ -67,7 +92,9 @@ it").
|
||||
|
||||
## Verification
|
||||
|
||||
- `tasks/architecture/` contains one blocker task per `deferred(scope)` OQ
|
||||
- Each blocker task's `depends_on` names the concrete unblocking condition (or
|
||||
a task that represents it)
|
||||
- `docs/sdd_process.md` (or equivalent) references the convention
|
||||
- `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 the
|
||||
`open-questions.md` Deferred/Blocked section surfaces the condition inline.
|
||||
- `taskgraph validate` passes for `tasks/architecture/`.
|
||||
- `docs/sdd_process.md` references the convention.
|
||||
@@ -1,7 +1,7 @@
|
||||
---
|
||||
id: call/registry/access-control-ownership-check
|
||||
name: Update AccessControl::check to consult OwnershipProvider for dynamic resource ownership (ADR-050 §2)
|
||||
status: done
|
||||
status: completed
|
||||
depends_on: [core/ownership-store-trait]
|
||||
scope: moderate
|
||||
risk: medium
|
||||
|
||||
@@ -1,7 +1,7 @@
|
||||
---
|
||||
id: call/registry/dispatch-resource-id-extraction
|
||||
name: Wire dispatch path to extract resource_id from input and thread OwnershipProvider to AccessControl::check (ADR-050 §2a, §4a)
|
||||
status: done
|
||||
status: completed
|
||||
depends_on: [call/registry/operation-spec-resource-id-path, call/registry/access-control-ownership-check]
|
||||
scope: moderate
|
||||
risk: medium
|
||||
|
||||
@@ -1,7 +1,7 @@
|
||||
---
|
||||
id: call/registry/operation-spec-resource-id-path
|
||||
name: Add resource_id_path field to OperationSpec (ADR-050 §2a)
|
||||
status: done
|
||||
status: completed
|
||||
depends_on: []
|
||||
scope: single
|
||||
risk: low
|
||||
|
||||
@@ -1,7 +1,7 @@
|
||||
---
|
||||
id: core/ownership-store-trait
|
||||
name: Add OwnershipProvider (sync read) + OwnershipStore (async write) traits and InMemoryOwnershipStore (ADR-050)
|
||||
status: done
|
||||
status: completed
|
||||
depends_on: []
|
||||
scope: moderate
|
||||
risk: low
|
||||
|
||||
Reference in new issue
Block a user