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:
@@ -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.
|
||||||
|
|||||||
@@ -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).
|
||||||
|
|||||||
@@ -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
|
||||||
|
|||||||
148
workplans/CUST-WP-0034-scope-md-delegation-prep.md
Normal file
148
workplans/CUST-WP-0034-scope-md-delegation-prep.md
Normal 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.
|
||||||
311
workplans/CUST-WP-0035-task-flow-engine.md
Normal file
311
workplans/CUST-WP-0035-task-flow-engine.md
Normal 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.
|
||||||
Reference in New Issue
Block a user