the-custodian/workplans/CUST-WP-0074-qualified-wait-states.md
codex 5fc4ab07a1
Some checks are pending
CI Smoke / host-smoke (push) Waiting to run
CI Smoke / container-smoke (push) Waiting to run
CUST-WP-0074-T05: slices R3/R5/R8 and the R1 root qualified; FLEX-WP-0020 cycle finding
Co-Authored-By: Claude Fable 5.1 <noreply@anthropic.com>
2026-09-28 23:51:35 +02:00

13 KiB
Raw Blame History

id type title domain repo status owner topic_slug flavor created updated related origin origin_ref state_hub_workstream_id
CUST-WP-0074 workplan Qualify task wait states: external commitment versus human gate infotech the-custodian active the-custodian custodian planning 2026-09-28 2026-09-28
CUST-WP-0072
STATE-WP-0092
COORDINATION-WP-0005
RAIL-FAB-WP-0029
CUST-WP-0071
analysis the-custodian/history/20260928-blocked-workplan-graph.md a442e062-9c91-5ac6-8f1d-35f2117b7069

Qualify task wait states: external commitment versus human gate

Why

On 2026-09-28 the hub held 105 blocked workplans (retired slugs excluded) with 220 wait tasks between them. The blocker was recorded as prose in the task text. Only 7 dependency edges existed in workplan_dependencies across all open workplans, and only 5 of the 220 wait tasks set needs_human. Nothing could answer "which of these only Bernd can unblock" or "which clear on their own when FLEX-WP-0020 finishes" without reading every task.

Reading them shows two different kinds of wait:

  • Case A — external commitment. The task waits for another repo's workplan or task to reach a terminal state. It clears by itself; the waiting side only needs to observe. Example: five workplans wait on the flex-auth → access-engine rename (FLEX-WP-0020).
  • Case B — human gate. The task waits for a decision, an approval, an attended privileged action, or a credential provisioned by an operator. Nothing in the fleet clears it; a person does. Example: about 25 workplans sit behind one attended OpenBao provisioning session (CCR-2026-0004 and the per-lane scoped applies).

Both are wait today. Founder decision 2026-09-28: keep wait as the stored status and qualify it, deriving two visible states from the qualifier. This follows the existing convention that stalled and needs_review are derived labels, not stored statuses (.claude/rules/workplan-convention.md). Two new stored statuses were rejected: every consumer (hub enum, fix-consistency rank logic, Fabric OPEN_TASK, ralph-workplan, dashboards) would have to change at once across 1465 workplans, whereas a qualifier is additive and a WARN drives migration one workplan at a time.

Analysis, gate roots and the extracted graph: history/20260928-blocked-workplan-graph.md.

The shape

No new keys. Three keys that task blocks already carry become meaningful together:

# Case A — external commitment → derived state: waiting-external
status: wait
depends_on: [FLEX-WP-0020]            # workplan id or task id (KEY-WP-0035-T02)
blocking_reason: "access-engine rename must land first"

# Case B — human gate → derived state: needs-human
status: wait
needs_human: true
blocking_reason: "operator must provision NC_WEBDAV/AGE creds to OpenBao"
decision_id: CCR-2026-0004            # optional, when a tracked decision exists

Rules:

  1. A wait task carries depends_on (Case A), needs_human: true (Case B), or both. Neither → consistency WARN.
  2. blocking_reason stays required for wait (the hub API already refuses wait without it).
  3. Case A is satisfied when every depends_on target is done, finished or archived — the coordination-model v0.2 commitment rule. A task still wait past satisfaction → consistency WARN.
  4. Case B is satisfied by a resolved decision or by the human's recorded action in the task text; when decision_id is set, resolution of that decision triggers the same WARN.
  5. Workplan blocked stays stored. The hub derives blocked-external when all its wait tasks are Case A, blocked-human when any is Case B, so "everything waiting on a person" is one query.
  6. A wait on a repo that has no workplan id yet stays Case A with the repo named in blocking_reason and the workplan-level blocked_on: field (C-25). Upgrade to a depends_on id as soon as the owner returns one. Revised during T05 (2026-09-28): the task block carries blocked_on: message-from:<agent> instead; C-39 accepts it, the hub read model does not yet (reports unqualified) — follow-up in T02.

The workplan-level depends_on (C-20) is unchanged. Task-level depends_on is the new commitment surface; related: stays context.

Write the standard and update the convention

id: CUST-WP-0074-T01
status: done
priority: high
state_hub_task_id: "82e9522b-bb69-52f4-b182-13ddfa8cd56e"

Owner: the-custodian.

2026-09-28: proposal committed — standard 11e6202 (status proposed), convention edit in the same commit, ralph-workplan spec abea4cc. Founder accepted 2026-09-28; standard set to accepted, revision accepted-1.

  • canon/standards/task-wait-qualifiers_v0.1.md: the shape above, the six rules, the derived-state names, and the satisfaction rule cross- referenced to coordination-engine/spec/coordination-model-v0.2.md §5.
  • .claude/rules/workplan-convention.md: extend the task-block template and the status-progression paragraph; state that wait without a qualifier is a WARN once T02 ships.
  • ~/ralph-workplan/workplan-spec.md: same template extension, so the loop's "all tasks done" check is unaffected and it never picks up a needs_human task.
  • Human-gated: canon goes through proposal-then-review. Commit the proposal, then record the founder's acceptance here.

Hand off enforcement and indexing to state-hub

id: CUST-WP-0074-T02
status: progress
priority: high
state_hub_task_id: "e5a05f83-1db5-59a7-8cae-095237f50b7d"

2026-09-28 — implemented in state-hub, three commits on main, not pushed, 907 tests pass: b9997d6 (read model: wait_kind on /tasks/, blocked_kind on /workplans/, decision_id on tasks, from_task_id on dependency rows, migration e8f9a0b1c2d3), 00c6e7a (checks C-39 unqualified wait, C-40 blocker satisfied, C-41 qualifier drift file→hub; C-20 indexes task-block depends_on with the task as from side), and a follow-up that skips closed plans/tasks in task-scope C-20. Check-only run on this repo: C-39 and C-40 found real drift in CUST-WP-0071/0073, fixed in the files. Remaining for done: deploy the migration to the primary, then one --fix run so C-20/C-41 write through (held until the primary has the columns — a --fix before that would PATCH fields the API rejects).

Owner: state-hub. Founder 2026-09-28: implement directly from this plan, no delegated STATE-WP workplan — keep the layer count down while getting a grip on exactly this. Receipt (commits, checks, tests) is recorded here.

Requested:

  • C-20 reads task-block depends_on (workplan and task ids) and writes workplan_dependencies rows with the waiting task as the from side — the table has to_task_id; check whether a from_task_id column is needed or whether from_workplan_id plus description suffices.
  • New check (next free C-id): wait task with neither task-block depends_on nor needs_human: true → WARN, not fixable.
  • New check: wait task whose every depends_on target is terminal, or whose decision_id is resolved → WARN "blocker satisfied", not fixable.
  • needs_human, blocking_reason and decision_id written from file to hub on sync (columns exist; decision_id may need one).
  • GET /tasks/ and GET /workplans/ expose a derived wait_kind / blocked_kind field per rule 5. Read model only — no new write route.

Acceptance: the four checks run green against this repo, and the derived fields answer for CUST-WP-0074-T05 below.

Hand off the ontology addendum to coordination-engine

id: CUST-WP-0074-T03
status: done
priority: medium
state_hub_task_id: "87711ade-f9f8-5e7f-9c15-025e5c235b35"

Owner: coordination-engine.

Done 2026-09-28 (founder: implement directly, no delegated workplan). Spec edits committed in coordination-engine 354e800, not pushed: coordination-model-v0.2.md §5 gains kind: decision and task-scope depends_on; cross-owner-wait-mode-v0.1.md entry 1 now keys on task-block depends_on, prose is a fallback until T05, and the Act section states that a human gate is never leased or woken.

  • spec/coordination-model-v0.2.md §5 gains commitment kind: decision for Case B, obligor = the named human or decision id, satisfaction = decision resolved. Case A is the existing kind: completion.
  • spec/cross-owner-wait-mode-v0.1.md entry condition 1 changes from "names another repo, owner, or workplan id" in prose to task-block depends_on; the prose form remains a fallback until the T05 backfill is complete.
  • Human-gate cases must never be leased to a worker; make that explicit in the Act section.

Hand off the view to railiance-fabric

id: CUST-WP-0074-T04
status: done
priority: medium
state_hub_task_id: "aaf60a09-ba58-578d-ba26-480d874c6b97"

Owner: railiance-fabric, under RAIL-FAB-WP-0029.

Done 2026-09-28 (implemented directly; railiance-fabric 9dbb8f0 on main, not pushed; 87 tests pass, node --check on the inline script OK). Task nodes carry wait_kind, workplan nodes blocked_kind (hub value wins, derived otherwise); task-level depends_on becomes edge_kind: commitment edges counted in chokepoint in-degree; human gates are a humanGate node marker (rose #be123c; commitment cyan #0891b2). Filter: needs_human=true on the UI checkbox, server route and export --format coordination --needs-human. Caveat: the view reads /state/deps stubs, not per-workplan dependency rows, so task-scope edges appear once T02's indexing is deployed on the primary.

  • coordination_graph.py reads task-block depends_on for edges and the derived wait_kind for colour: external commitment versus human gate.
  • Chokepoint sizing already uses in-degree; add a filter for needs-human only, so the operator's queue is one view.
  • Fabric remains a read of State Hub. No authoring.

Backfill the open wait tasks

id: CUST-WP-0074-T05
status: progress
priority: high
needs_human: false
depends_on: [CUST-WP-0074-T01, CUST-WP-0074-T02]
blocking_reason: "Standard must be accepted (T01) and the unqualified-wait WARN must exist (T02) before touching foreign workplan files."
state_hub_task_id: "03a9c033-470e-56cf-965f-a5b289dd71af"

Owner: the-custodian, following the CUST-WP-0072 backfill pattern: edit files in each repo, commit, run fix-consistency, never patch the hub directly.

  • Start with the gate roots in the history record (R1–R8): qualifying those roughly 60 tasks turns the largest fan-outs into real edges.
  • Case B tasks: set needs_human: true; attach decision_id where a CCR or hub decision exists (CCR-2026-0004 covers the offsite-backup lane).
  • Case A tasks: convert the referenced id in the prose to depends_on.
  • Leave flavor: residual workplans alone.
  • Done when the unqualified-wait WARN count for open workplans is zero.

Slice R1 done 2026-09-28 — FLEX-WP-0020 dependents: NK-WP-0039-T03/T04 (70bdc4a), USER-WP-0034-T02 (b08b2d7), RCLK-WP-0002-T01–T04 (82c6784), each synced through fix-consistency. RAIL-FAB-WP-0031 and REUSE-WP-0023 are flavor: residual and were left alone. Rule 6 was revised on contact: owner-return waits use task-block blocked_on: message-from:<agent>. Queue for the next slices is C-39 output per repo; seen so far: net-kingdom 8, user-engine 8, railiance-clock 8 (all R2/R3/R8 roots).

Slice R2 done 2026-09-28 — credential-provisioning root, 41 tasks in secrets-engine ccd057a, ops-mason 0d2fe45, sand-boxer 6fca6de, glas-harness 9f04c42, intelligence-radar 9bcc20e, railiance-platform 360cc5c, ops-warden dda65ef; all synced. Left unqualified on purpose: WARDEN-WP-0040-T01 (no external gate stated in the file — owner decides), WARDEN-WP-0039 (residual). C-40 now flags RPF-WP-0035-T02/T06/T08: every external target terminal, human part remains — the intended signal. Hub migration still queued behind a fluid-core CI build; task edges parked.

Slices R3, R5, R8 and the R1 root done 2026-09-28 — R3 audit-core returns: flex-auth 912dfcb, net-kingdom a705961, info-tech-canon 8a5b9b2. R5 ArgoCD lane: railiance-platform 98e0c3a (RPF-WP-0036-T03 left for its owner: no gate stated). R8 identity custody: hub-core 77b664c (HUB-WP-0012's prose blocked_on moved to blocking_reason), user-engine 0d554dc, net-kingdom 2a004a7, plus HUB-WP-0006-T06 and NK-WP-0022/0027. R1 root: flex-auth 23c93bb qualifies FLEX-WP-0020-T04..T11 and FLEX-WP-0027-T03. Finding: FLEX-WP-0020-T04 waits on the downstream owners' handoffs, which are the very plans (NK-WP-0039, USER-WP-0034, RAIL-FAB-WP-0031, REUSE-WP-0023) that wait on FLEX-WP-0020 — a cycle that was invisible as prose; T04 looks satisfiable. Route to flex-auth in T06. Residuals left untouched: HUB-WP-0011, APPROVAL-WP-0002, TEN-WP-0012, WARDEN-WP-0039, RAIL-FAB-WP-0031, REUSE-WP-0023.

Correct the mis-blocked workplans

id: CUST-WP-0074-T06
status: todo
priority: low
state_hub_task_id: "8c51fc11-b09b-598a-8866-7cc39f3f1ada"

Owner: the-custodian coordinates; each repo owner edits.

Six blocked workplans have no wait task at all (fluid-wp-0008, fluid-wp-0009, ft-wp-0001, glas-wp-0015, key-wp-0013, three-phoenix-ha-cluster); the FEP-WP-0002/0003/0004/0006/0008 chain is self-ordering inside one repo; testdrive-jsui-publication waits on a submodule init. Message each owner with the finding and the qualifier rule. Do not edit their files or reassign their tasks. Record the outcome per workplan here.