2026-09-28 20:52:02 +02:00
|
|
|
|
---
|
|
|
|
|
|
id: CUST-WP-0074
|
|
|
|
|
|
type: workplan
|
|
|
|
|
|
title: "Qualify task wait states: external commitment versus human gate"
|
|
|
|
|
|
domain: infotech
|
|
|
|
|
|
repo: the-custodian
|
2026-09-28 23:10:11 +02:00
|
|
|
|
status: active
|
2026-09-28 20:52:02 +02:00
|
|
|
|
owner: the-custodian
|
|
|
|
|
|
topic_slug: custodian
|
|
|
|
|
|
flavor: planning
|
|
|
|
|
|
created: "2026-09-28"
|
|
|
|
|
|
updated: "2026-09-28"
|
|
|
|
|
|
related:
|
|
|
|
|
|
- CUST-WP-0072
|
|
|
|
|
|
- STATE-WP-0092
|
|
|
|
|
|
- COORDINATION-WP-0005
|
|
|
|
|
|
- RAIL-FAB-WP-0029
|
|
|
|
|
|
- CUST-WP-0071
|
|
|
|
|
|
origin: analysis
|
|
|
|
|
|
origin_ref: the-custodian/history/20260928-blocked-workplan-graph.md
|
2026-09-28 20:53:17 +02:00
|
|
|
|
state_hub_workstream_id: "a442e062-9c91-5ac6-8f1d-35f2117b7069"
|
2026-09-28 20:52:02 +02:00
|
|
|
|
---
|
|
|
|
|
|
|
|
|
|
|
|
# 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:
|
|
|
|
|
|
|
|
|
|
|
|
```yaml
|
|
|
|
|
|
# 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
|
2026-09-28 23:16:48 +02:00
|
|
|
|
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.*
|
2026-09-28 20:52:02 +02:00
|
|
|
|
|
|
|
|
|
|
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
|
|
|
|
|
|
|
|
|
|
|
|
```task
|
|
|
|
|
|
id: CUST-WP-0074-T01
|
2026-09-28 23:10:11 +02:00
|
|
|
|
status: done
|
2026-09-28 20:52:02 +02:00
|
|
|
|
priority: high
|
2026-09-28 20:53:17 +02:00
|
|
|
|
state_hub_task_id: "82e9522b-bb69-52f4-b182-13ddfa8cd56e"
|
2026-09-28 20:52:02 +02:00
|
|
|
|
```
|
|
|
|
|
|
|
|
|
|
|
|
Owner: the-custodian.
|
|
|
|
|
|
|
2026-09-28 22:15:06 +02:00
|
|
|
|
2026-09-28: proposal committed — standard `11e6202` (status `proposed`),
|
|
|
|
|
|
convention edit in the same commit, ralph-workplan spec `abea4cc`.
|
2026-09-28 23:10:11 +02:00
|
|
|
|
Founder accepted 2026-09-28; standard set to `accepted`, revision `accepted-1`.
|
2026-09-28 22:15:06 +02:00
|
|
|
|
|
2026-09-28 20:52:02 +02:00
|
|
|
|
- `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
|
|
|
|
|
|
|
|
|
|
|
|
```task
|
|
|
|
|
|
id: CUST-WP-0074-T02
|
2026-09-28 22:46:18 +02:00
|
|
|
|
status: progress
|
2026-09-28 20:52:02 +02:00
|
|
|
|
priority: high
|
2026-09-28 20:53:17 +02:00
|
|
|
|
state_hub_task_id: "e5a05f83-1db5-59a7-8cae-095237f50b7d"
|
2026-09-28 20:52:02 +02:00
|
|
|
|
```
|
|
|
|
|
|
|
2026-09-28 22:46:18 +02:00
|
|
|
|
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).
|
|
|
|
|
|
|
2026-09-28 22:15:06 +02:00
|
|
|
|
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.
|
2026-09-28 20:52:02 +02:00
|
|
|
|
|
2026-09-28 22:15:06 +02:00
|
|
|
|
Requested:
|
2026-09-28 20:52:02 +02:00
|
|
|
|
|
|
|
|
|
|
- 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
|
|
|
|
|
|
|
|
|
|
|
|
```task
|
|
|
|
|
|
id: CUST-WP-0074-T03
|
2026-09-28 22:15:06 +02:00
|
|
|
|
status: done
|
2026-09-28 20:52:02 +02:00
|
|
|
|
priority: medium
|
2026-09-28 20:53:17 +02:00
|
|
|
|
state_hub_task_id: "87711ade-f9f8-5e7f-9c15-025e5c235b35"
|
2026-09-28 20:52:02 +02:00
|
|
|
|
```
|
|
|
|
|
|
|
|
|
|
|
|
Owner: coordination-engine.
|
|
|
|
|
|
|
2026-09-28 22:15:06 +02:00
|
|
|
|
**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.
|
|
|
|
|
|
|
2026-09-28 20:52:02 +02:00
|
|
|
|
- `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
|
|
|
|
|
|
|
|
|
|
|
|
```task
|
|
|
|
|
|
id: CUST-WP-0074-T04
|
2026-09-28 22:29:52 +02:00
|
|
|
|
status: done
|
2026-09-28 20:52:02 +02:00
|
|
|
|
priority: medium
|
2026-09-28 20:53:17 +02:00
|
|
|
|
state_hub_task_id: "aaf60a09-ba58-578d-ba26-480d874c6b97"
|
2026-09-28 20:52:02 +02:00
|
|
|
|
```
|
|
|
|
|
|
|
|
|
|
|
|
Owner: railiance-fabric, under `RAIL-FAB-WP-0029`.
|
|
|
|
|
|
|
2026-09-28 22:29:52 +02:00
|
|
|
|
**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.
|
|
|
|
|
|
|
2026-09-28 20:52:02 +02:00
|
|
|
|
- `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
|
|
|
|
|
|
|
|
|
|
|
|
```task
|
|
|
|
|
|
id: CUST-WP-0074-T05
|
|
|
|
|
|
status: wait
|
|
|
|
|
|
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."
|
2026-09-28 20:53:17 +02:00
|
|
|
|
state_hub_task_id: "03a9c033-470e-56cf-965f-a5b289dd71af"
|
2026-09-28 20:52:02 +02:00
|
|
|
|
```
|
|
|
|
|
|
|
|
|
|
|
|
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.
|
|
|
|
|
|
|
|
|
|
|
|
## Correct the mis-blocked workplans
|
|
|
|
|
|
|
|
|
|
|
|
```task
|
|
|
|
|
|
id: CUST-WP-0074-T06
|
|
|
|
|
|
status: todo
|
|
|
|
|
|
priority: low
|
2026-09-28 20:53:17 +02:00
|
|
|
|
state_hub_task_id: "8c51fc11-b09b-598a-8866-7cc39f3f1ada"
|
2026-09-28 20:52:02 +02:00
|
|
|
|
```
|
|
|
|
|
|
|
|
|
|
|
|
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.
|