chore(consistency): sync task status from DB [auto]

Updated by fix-consistency on 2026-05-01:
  - update .custodian-brief.md for the-custodian
This commit is contained in:
2026-05-01 00:55:53 +02:00
parent ffa3809e95
commit f99d77d539
5 changed files with 466 additions and 8 deletions

View File

@@ -1,15 +1,12 @@
<!-- custodian-brief: generated by fix-consistency — do not edit manually --> <!-- custodian-brief: generated by fix-consistency — do not edit manually -->
# Custodian Brief — the-custodian # Custodian Brief — the-custodian
**Domain:** railiance **Domain:** custodian
**Last synced:** 2026-04-30 22:40 UTC **Last synced:** 2026-04-30 22:55 UTC
**State Hub:** http://127.0.0.1:8000 *(adjust if running on a remote machine)* **State Hub:** http://127.0.0.1:8000 *(adjust if running on a remote machine)*
## Active Workstreams ## Active Workstreams
### Cross-Repo E2E Sandbox Framework
Progress: 8/8 done | workstream_id: `b68de20b-e397-4f97-b1be-ad30711fc2a6`
### Task-Flow-Engine — Declarative Workstation and Requisite Model ### Task-Flow-Engine — Declarative Workstation and Requisite Model
Progress: 0/6 done | workstream_id: `781e519b-0dd7-451b-b63c-fad50f999c9c` Progress: 0/6 done | workstream_id: `781e519b-0dd7-451b-b63c-fad50f999c9c`
@@ -22,13 +19,14 @@ Progress: 0/6 done | workstream_id: `781e519b-0dd7-451b-b63c-fad50f999c9c`
- · T06: Extraction boundary and future repo scope `b9242cb4` - · T06: Extraction boundary and future repo scope `b9242cb4`
### SCOPE.md Delegation — Custodian Preparation ### SCOPE.md Delegation — Custodian Preparation
Progress: 0/4 done | workstream_id: `bf94b5e9-2bc3-4c09-88cd-233849d4d86c` Progress: 0/5 done | workstream_id: `bf94b5e9-2bc3-4c09-88cd-233849d4d86c`
**Open tasks:** **Open tasks:**
- · T01: Upgrade DOI engine C5 — content structure validation `7d31bbea` - · T01: Upgrade DOI engine C5 — content structure validation `7d31bbea`
- · T02: Surface SCOPE.md health in repo dispatch `243280c7` - · T02: Surface SCOPE.md health in repo dispatch `243280c7`
- · T03: Register capability routes for scope generation `042c54d4` - · T03: Register capability routes for scope generation `042c54d4`
- · T04: Update scope-analyst kaizen agent `b6d64844` - · T04: Update scope-analyst kaizen agent `b6d64844`
- · T05 — Expose structured SCOPE.md health for repo-scoping refresh `b5d5a1f2`
### Interactive — the-custodian ### Interactive — the-custodian
Progress: 4/4 done | workstream_id: `370c2481-6806-41eb-a917-f8874f03184f` Progress: 4/4 done | workstream_id: `370c2481-6806-41eb-a917-f8874f03184f`
@@ -87,6 +85,6 @@ Progress: 0/9 done | workstream_id: `9cc32158-2f5c-4ef6-9713-aacce4623d5e`
## MCP Orientation (when available) ## MCP Orientation (when available)
If the state-hub MCP server is reachable, call: If the state-hub MCP server is reachable, call:
`get_domain_summary("railiance")` `get_domain_summary("custodian")`
This provides richer cross-domain context. This provides richer cross-domain context.
If the MCP call fails, use this file as your orientation source. If the MCP call fails, use this file as your orientation source.

View File

@@ -73,6 +73,7 @@ VALID_TASK_PRIORITIES = {"low", "medium", "high", "critical"}
# and before PATCHing, so "done" vs "completed" is never flagged as C-04 drift. # and before PATCHing, so "done" vs "completed" is never flagged as C-04 drift.
FILE_TO_DB_WORKSTREAM_STATUS: dict[str, str] = { FILE_TO_DB_WORKSTREAM_STATUS: dict[str, str] = {
"done": "completed", "done": "completed",
"todo": "active", # workplan not yet started → active workstream in DB
} }
# Ordinal ranking for task statuses used by the no-regress rule (T01/C-15). # Ordinal ranking for task statuses used by the no-regress rule (T01/C-15).

View File

@@ -92,7 +92,7 @@ status is not `resolved`. Each entry: `id`, `title`, `change_type`,
Extend `DispatchWorkstream` schema with the new field. Update `RepoDispatch` schema. Extend `DispatchWorkstream` schema with the new field. Update `RepoDispatch` schema.
Update the `get_repo_dispatch` endpoint accordingly. Update the `get_repo_dispatch` endpoint accordingly.
Acceptance: `GET /repos/repo-registry/dispatch` returns `pending_interface_changes` Acceptance: `GET /repos/repo-scoping/dispatch` returns `pending_interface_changes`
list (empty or populated); no regression on existing dispatch tests. list (empty or populated); no regression on existing dispatch tests.
## T04: MCP tools ## T04: MCP tools

View File

@@ -0,0 +1,148 @@
---
id: CUST-WP-0034
type: workplan
title: "SCOPE.md Delegation — Custodian Preparation"
domain: custodian
repo: the-custodian
status: todo
owner: custodian
topic_slug: custodian
created: "2026-04-30"
updated: "2026-04-30"
state_hub_workstream_id: "bf94b5e9-2bc3-4c09-88cd-233849d4d86c"
---
# CUST-WP-0034 — SCOPE.md Delegation Preparation
## Goal
Prepare the custodian to delegate SCOPE.md generation and maintenance to
repo-scoping. Three concrete changes: (1) upgrade the
DOI engine's C5 check from file-presence to content-structure validation so
the custodian can detect stale or non-conforming SCOPE.md files; (2) register
a capability request route so "scope.generate" and "scope.update" requests are
formally routed to repo-scoping; (3) update the scope-analyst kaizen agent to
describe itself as a routing shim rather than a standalone analyser.
This workplan does not move any SCOPE.md generation logic — that lives in
RREG-WP-0005. It only makes the custodian aware of the delegation interface.
Depends on: none
Unblocks: RREG-WP-0005 (capability route must exist before registration), RREG-WP-0006
## T01: Upgrade DOI engine C5 — content structure validation
```task
id: CUST-WP-0034-T01
status: todo
priority: high
state_hub_task_id: "7d31bbea-cebf-486e-b622-05bc5ca141ea"
```
Replace the current file-presence check in `state-hub/api/doi_engine.py` (C5)
with a three-level content check:
- **C5a** (pass/fail): SCOPE.md present at repo root
- **C5b** (pass/warn): All 11 standard sections present as H2 headings:
`One-liner`, `Core Idea`, `In Scope`, `Out of Scope`, `Relevant When`,
`Not Relevant When`, `Current State`, `How It Fits`, `Terminology`,
`Related / Overlapping`, `Provided Capabilities`
- **C5c** (pass/warn): `## Provided Capabilities` contains at least one
fenced `capability` block that parses as valid YAML with `type` and `title`
C5b and C5c emit `warn` (not `fail`) so a stub SCOPE.md doesn't hard-fail
the DoI gate while still surfacing clearly in the dashboard.
Acceptance: `make check-doi REPO=the-custodian` reports C5a/C5b/C5c
separately; the-custodian SCOPE.md passes all three; a repo with a blank
stub SCOPE.md shows C5b and C5c as warn.
## T02: Surface SCOPE.md health in repo dispatch
```task
id: CUST-WP-0034-T02
status: todo
priority: medium
state_hub_task_id: "243280c7-3e68-4791-9243-ef9ee6b6d311"
```
Extend `GET /repos/{slug}/dispatch` with a `scope_needs_review: bool` field.
It is `true` when either C5b or C5c is `warn` or `fail` for the repo. This
ensures agents picking up a repo at session start see the signal without
needing to call the DOI engine separately.
Also add `scope_needs_review` to the MCP `get_repo_dispatch` tool output.
Acceptance: for a repo with a stub SCOPE.md, `get_repo_dispatch("that-repo")`
returns `scope_needs_review: true`; for a repo with a valid SCOPE.md it
returns `false`.
## T03: Register capability routes for scope generation
```task
id: CUST-WP-0034-T03
status: todo
priority: high
state_hub_task_id: "042c54d4-0aa6-41e1-9497-4172986d779b"
```
Register two capability routes in the custodian's capability request system
pointing to repo-scoping:
```
capability_key: scope.generate
provider_repo: repo-scoping
description: >
Generate a SCOPE.md from scratch for a given repo using its approved
characteristics profile.
input_schema: {repo_slug: string, output_path: string}
```
```
capability_key: scope.update
provider_repo: repo-scoping
description: >
Diff an existing SCOPE.md against the current characteristics profile
and write an updated version.
input_schema: {repo_slug: string, output_path: string}
```
Use `register_capability()` (MCP tool) or the `/capabilities/` API directly.
These routes are the formal contract that downstream automation (and the
scope-analyst agent) will use to trigger SCOPE.md work.
Acceptance: `list_capabilities()` returns both `scope.generate` and
`scope.update` with `provider_repo: repo-scoping`.
## T04: Update scope-analyst kaizen agent
```task
id: CUST-WP-0034-T04
status: todo
priority: medium
state_hub_task_id: "b6d64844-8a6d-4856-bdf5-3867fb49f215"
```
Update `agents/agent-scope-analyst.md`:
1. Add a short **Delegation** section at the top explaining that as of
RREG-WP-0005, the authoritative SCOPE.md generator is repo-scoping.
The scope-analyst persona is now a routing shim: it inspects the repo,
decides whether `scope.generate` or `scope.update` is appropriate, and
issues the capability request via `request_capability()`.
2. Retain the existing heuristics and template sections — they remain valid
as the spec that repo-scoping must produce to. They also serve as
fallback if repo-scoping is unavailable.
3. Add a code example showing how to issue the capability request:
```
request_capability(
capability_key="scope.generate",
requesting_repo="the-custodian",
payload={"repo_slug": "target-repo", "output_path": "/path/to/SCOPE.md"}
)
```
Acceptance: `get_kaizen_agent("scope-analyst")` returns the updated persona;
the delegation flow is clear in the first screen of the agent instructions.

View File

@@ -0,0 +1,311 @@
---
id: CUST-WP-0035
type: workplan
title: "Task-Flow-Engine — Declarative Workstation and Requisite Model"
domain: custodian
repo: the-custodian
status: todo
owner: custodian
topic_slug: custodian
created: "2026-04-30"
updated: "2026-04-30"
state_hub_workstream_id: "781e519b-0dd7-451b-b63c-fad50f999c9c"
---
# CUST-WP-0035 — Task-Flow-Engine
## Goal
Build a lightweight, declarative workflow substrate that replaces the
custodian's current hardcoded status enums and `_VALID_TRANSITIONS` dicts with
a generalised model of **workstations**, **information objects**, and
**requisite assertions**.
The core idea:
- **Information objects** are any entities that move through a lifecycle:
workstreams, tasks, contributions, capability requests, interface changes.
- **Workstations** are named positions an information object can occupy. They
are not fixed lifecycle stages — they are general nodes whose semantics are
defined by their entry and exit assertions.
- **Requisite assertions** are declarative predicates on data elements or
qualities of an information object or its environment. An assertion might
say "all child tasks have status `done`", "a human approval record exists",
or "the dependency workstream `X` is at workstation `completed`". Assertions
compose: a workstation is reachable when all its entry assertions are
satisfied; it is exitable when all its exit assertions are satisfied.
- **Transitions** are derived, not enumerated. Any workstation is reachable
from any other if the entry assertions are met. There are no hardcoded valid
transition tables. Blocked state is also derived — an object is blocked at
its current workstation when one or more exit assertions are unsatisfied, and
the engine surfaces exactly which assertions are failing and why.
This design supports the loose, flexible coupling of activities needed across
the custodian ecosystem. Work items don't march through a prescribed pipeline;
they move when their world matches what the target workstation requires.
The engine is designed to eventually live in its own repository
(`task-flow-engine`) as a reusable Python package, independent of the
state-hub. This workplan builds the first version inside the custodian, then
scopes the extraction boundary.
## T01: Design specification — workstations, assertions, flow definitions
```task
id: CUST-WP-0035-T01
status: todo
priority: high
state_hub_task_id: "25ad9022-987f-4d30-b1a1-a96c4a83889a"
```
Write `state-hub/docs/task-flow-engine-spec.md` capturing the full data model
before any code is written. The spec must cover:
**Information Object:** any entity with a current workstation label and a
bag of observable properties. The engine is not coupled to a specific DB
schema — it receives a plain dict of properties.
**WorkstationDef:** `{name: str, entry_assertions: list[AssertionDef],
exit_assertions: list[AssertionDef], description: str}`. A workstation with
no assertions is always reachable / always exitable (unconstrained).
**AssertionDef:** `{id: str, target: str, op: str, value: Any,
description: str}`.
- `target` is a dot-path into the information object's properties:
`"tasks.*.status"`, `"dependencies.all.workstation"`, `"metadata.approved_by"`
- `op` is a predicate: `all_eq`, `any_eq`, `none_eq`, `exists`, `count_gte`,
`custom` (for assertions that call back into the engine host)
- Assertions are pure — they do not mutate state
**FlowDef:** `{id: str, entity_type: str, workstations: list[WorkstationDef]}`.
A flow definition is a named graph. Multiple flows can exist per entity type
(e.g., a "lightweight" flow and a "governance" flow for workstreams).
**Transition:** not a first-class type. The engine derives valid next
workstations by evaluating entry assertions of all workstations in the flow
against the current object state. The caller sees: current workstation,
satisfied exit assertions, unsatisfied exit assertions (blocking reasons),
reachable workstations, unreachable workstations with the blocking assertion
for each.
**FlowResult:** `{current_workstation: str, exit_blocked: bool,
blocking_assertions: list[AssertionResult], reachable: list[str],
unreachable: list[{workstation: str, blocking: AssertionResult}]}`.
Acceptance: spec document exists; the model can express the full lifecycle of
workstreams, tasks, contributions, and capability requests without hardcoding
any domain knowledge into the engine itself.
## T02: Core Python library — pure engine, no FastAPI dependency
```task
id: CUST-WP-0035-T02
status: todo
priority: high
state_hub_task_id: "df5ce1f2-a0d0-4f90-9629-c28c6021b909"
```
New package at `state-hub/task_flow_engine/`:
```
task_flow_engine/
__init__.py
models.py # AssertionDef, WorkstationDef, FlowDef, FlowResult dataclasses
evaluator.py # assertion evaluation logic
engine.py # FlowEngine.evaluate(obj: dict, flow: FlowDef) -> FlowResult
builtins.py # built-in op implementations: all_eq, any_eq, exists, count_gte, …
```
Design constraints:
- No SQLAlchemy, no FastAPI, no HTTP — this is a pure computation library
- `FlowEngine.evaluate()` takes a plain `dict` (the information object's
properties) and a `FlowDef`, returns a `FlowResult`
- `FlowDef` instances can be loaded from YAML or constructed in code; the
engine does not care
- The `custom` op accepts a callable injected by the host — keeping the engine
pure while allowing host-specific assertions (e.g., "has a linked approval
decision in the DB")
Acceptance: unit tests in `state-hub/tests/test_task_flow_engine.py` cover:
- object with all assertions satisfied → correct reachable workstations
- object with one failing exit assertion → `exit_blocked: true` with the
specific assertion identified
- custom op callable invoked correctly
- empty flow def (no assertions) → all workstations reachable
- circular reference in target path → handled without infinite loop
## T03: Flow definitions for existing custodian entities
```task
id: CUST-WP-0035-T03
status: todo
priority: high
state_hub_task_id: "3d01fc77-0329-44ee-8a60-20a3de1c1d6e"
```
Write YAML flow definitions for the four entity types currently tracked in the
state-hub. Store them at `state-hub/flows/`:
**`workstream.yaml`** — replaces `WorkstreamStatus` enum:
- Workstations: `todo`, `active`, `blocked`, `completed`, `archived`
- `todo → active`: no entry assertions (planning is unconstrained)
- `active → completed`: exit assertion `tasks.all_done` = all tasks have
status `done` or `cancelled`
- `active → blocked`: exit assertion `dependencies.any_incomplete` (any
dependency workstream not yet at `completed`)
- `blocked → active`: entry assertion `dependencies.all_complete`
- `completed → archived`: no entry assertions
**`task.yaml`** — replaces the informal `todo | in_progress | blocked | done`
model:
- Workstations: `todo`, `in_progress`, `blocked`, `done`, `cancelled`
- `in_progress → blocked`: exit assertion `needs_human == false` (maps to the
existing `needs_human` flag)
- `blocked → in_progress`: entry assertion `needs_human == false`
- `in_progress → done`: no assertions beyond curator intent
**`contribution.yaml`** — replaces `_VALID_TRANSITIONS` dict in
`routers/contributions.py`:
- Workstations: `draft`, `submitted`, `acknowledged`, `accepted`, `merged`,
`rejected`, `withdrawn`
- Express the same lifecycle as the current dict but as assertion-annotated
workstation definitions, making the intent readable rather than just the
allowed edges
**`capability_request.yaml`** — replaces `_VALID_TRANSITIONS` in
`routers/capability_requests.py`
Acceptance: each YAML file loads as a valid `FlowDef`; running
`FlowEngine.evaluate()` on a representative set of existing DB entities (via
a test fixture) produces `FlowResult`s consistent with the current manual
status labels.
## T04: State-hub integration — migrate from enums to engine
```task
id: CUST-WP-0035-T04
status: todo
priority: high
state_hub_task_id: "db320d4e-cbcd-4787-a42c-e7cb109737a3"
```
**4a: Migrate `WorkstreamStatus` from SA Enum to `String(20)`**
Write an Alembic migration that alters the `workstreams.status` column from
the `WorkstreamStatus` enum type to `VARCHAR(20)`. Existing values (`active`,
`blocked`, `completed`, `archived`) are valid workstation names and survive
unchanged. Drop the `WorkstreamStatus` Python enum after migration; use plain
strings throughout. Follow the pattern already established by tasks
(`String(20)` with no SA Enum).
**4b: Replace `_VALID_TRANSITIONS` guards with engine evaluation**
In `routers/contributions.py` and `routers/capability_requests.py`: replace
the `_VALID_TRANSITIONS` dict lookup with `FlowEngine.evaluate()`. The router
loads the appropriate `FlowDef` (from the YAML files in T03), calls evaluate,
and returns 409 with a structured error body listing the failing assertions
if the target workstation is unreachable. The error body replaces the current
free-text `"transition not allowed"` message with machine-readable assertion
failures.
**4c: Derive `blocked` automatically in state summary**
In `routers/state.py`: instead of filtering `Workstream.status == 'blocked'`
directly, evaluate each active workstream against its flow definition and
surface it as effectively blocked when `exit_blocked: true`. This means the
`blocked` status on a workstream can be set automatically by the engine rather
than requiring manual `update_workstream_status("blocked")` calls.
Acceptance: existing API tests pass after migration; the state summary
`blocked_workstreams` count matches what the engine derives; a workstream
with all tasks done automatically surfaces as ready to move to `completed`.
## T05: MCP tools — flow-aware session orientation
```task
id: CUST-WP-0035-T05
status: todo
priority: medium
state_hub_task_id: "8ea7e49f-f1ad-4290-84f4-c1ee75c79786"
```
Three new tools in `mcp_server/server.py`:
- `get_flow_state(entity_type: str, entity_id: str)` — returns the
`FlowResult` for the given entity: current workstation, exit-blocking
assertions with human-readable reasons, and list of reachable workstations
- `advance_workstation(entity_type: str, entity_id: str,
target_workstation: str)` — attempts to move the entity to the target
workstation; returns the `FlowResult` on success, or a 409-equivalent with
the specific failing assertions if blocked
- `list_flow_definitions()` — returns the registered flow definitions with
their workstation names and assertion counts (orientation tool)
Update `get_state_summary()` and `get_domain_summary()` to include a
`blocked_reasons` field per blocked workstream so agents see not just that a
workstream is blocked but specifically which assertion is failing.
Acceptance: `get_flow_state("workstream", "<id>")` returns a readable result
for an existing workstream; `advance_workstation` refuses correctly when
assertions are unmet and accepts correctly when they are met.
## T06: Extraction boundary and future repo scope
```task
id: CUST-WP-0035-T06
status: todo
priority: low
state_hub_task_id: "b9242cb4-5fb4-4e9e-9f16-9a1866cedc6a"
```
Before closing this workplan, write a brief design note at
`canon/projects/custodian/task_flow_engine_scope_v0.1.md` that captures:
- What belongs in the standalone `task-flow-engine` package:
`models.py`, `evaluator.py`, `engine.py`, `builtins.py` — pure Python,
no custodian dependency
- What stays in the state-hub integration layer:
YAML flow definitions (domain-specific), DB migration, router changes, MCP
tools, custom op callables that query the DB
- The extraction path: once the engine is stable, `state-hub/task_flow_engine/`
is published as a separate pip package and re-imported as a dependency
- Register a new managed repo concept (`task-flow-engine`) in the capabilities
domain for when extraction happens
Also register an extension point:
```
ep_type: architecture
title: task-flow-engine extraction as standalone package
description: >
task_flow_engine/ is currently co-located in the state-hub. Extract to its
own repo and pip package once the API is stable after at least one non-trivial
flow definition has been running in production.
status: open
priority: low
```
Acceptance: design note file exists; extension point registered.
---
## Closing note — reference documentation cleanup
Once this workplan is complete and the task-flow-engine model is live, the
following custodian reference materials will need to be updated to reflect the
refined terminology (workstations, information objects, requisite assertions)
and to retire language that assumed fixed lifecycle enums:
- `state-hub/dashboard/src/docs/` — any page describing workstream or task
lifecycle, status values, or contribution flows
- `state-hub/policies/repo-doi.md` — references to task/workstream status
checks that assume specific enum values
- `agents/agent-scope-analyst.md` and other kaizen agents that reference
status transitions by name
- `CLAUDE.md` (global and project) — session protocol references to
`update_workstream_status()` and `update_task_status()` should be updated
to the `advance_workstation()` pattern
- `memory/MEMORY.md` entries covering the state-hub data model
This cleanup is intentionally deferred — the new terminology should stabilise
in practice before documentation is frozen. A dedicated workplan should be
opened at the close of T05 to track this.