docs: start CUST-WP-0025 hub-core extraction
This commit is contained in:
120
docs/hub-core-extraction-boundary.md
Normal file
120
docs/hub-core-extraction-boundary.md
Normal file
@@ -0,0 +1,120 @@
|
|||||||
|
# Hub-Core Extraction Boundary
|
||||||
|
|
||||||
|
Last reviewed: 2026-06-06
|
||||||
|
|
||||||
|
## Purpose
|
||||||
|
|
||||||
|
This note starts `CUST-WP-0025-T05` by translating the original hub-core idea
|
||||||
|
into a current implementation boundary. The State Hub implementation no longer
|
||||||
|
lives under `the-custodian/state-hub`; the authoritative source checkout is
|
||||||
|
`/home/worsch/state-hub`, and the planned package target is
|
||||||
|
`/home/worsch/hub-core`.
|
||||||
|
|
||||||
|
The extraction must preserve a clean FOS split:
|
||||||
|
|
||||||
|
- `hub-core` owns reusable hub primitives.
|
||||||
|
- `state-hub` becomes the first dev-hub implementation and keeps development
|
||||||
|
coordination concepts such as topics, workstreams, tasks, decisions,
|
||||||
|
dependencies, SBOM, token accounting, and kaizen agents.
|
||||||
|
- Future hubs such as ops-hub and fin-hub depend on `hub-core` without pulling
|
||||||
|
in dev-hub coordination tables.
|
||||||
|
|
||||||
|
## First Package Slice
|
||||||
|
|
||||||
|
Create `/home/worsch/hub-core` as a uv-managed Python package with this initial
|
||||||
|
layout:
|
||||||
|
|
||||||
|
```text
|
||||||
|
hub_core/
|
||||||
|
__init__.py
|
||||||
|
database.py
|
||||||
|
models/
|
||||||
|
__init__.py
|
||||||
|
base.py
|
||||||
|
domain.py
|
||||||
|
managed_repo.py
|
||||||
|
agent_message.py
|
||||||
|
tpsc.py
|
||||||
|
schemas/
|
||||||
|
__init__.py
|
||||||
|
domain.py
|
||||||
|
managed_repo.py
|
||||||
|
agent_message.py
|
||||||
|
tpsc.py
|
||||||
|
routers/
|
||||||
|
__init__.py
|
||||||
|
domains.py
|
||||||
|
repos.py
|
||||||
|
messages.py
|
||||||
|
tpsc.py
|
||||||
|
policy.py
|
||||||
|
```
|
||||||
|
|
||||||
|
This slice avoids the models that currently carry dev-hub foreign keys. It is
|
||||||
|
large enough to prove packaging, import style, SQLAlchemy metadata ownership,
|
||||||
|
router dependency injection, and State Hub compatibility before the more
|
||||||
|
entangled surfaces move.
|
||||||
|
|
||||||
|
## Extract Now
|
||||||
|
|
||||||
|
These State Hub files are suitable for the first extraction after import-path
|
||||||
|
rewriting and small router seams:
|
||||||
|
|
||||||
|
| Source in `/home/worsch/state-hub` | Target role |
|
||||||
|
| --- | --- |
|
||||||
|
| `api/models/base.py` | Declarative base, timestamps, UUID helper. |
|
||||||
|
| `api/models/domain.py` | Core domain identity; remove relationships to dev-hub-only models from core. |
|
||||||
|
| `api/models/managed_repo.py` | Core repo registry; make `topic_id`, SBOM, and sync timestamps extension fields or keep them in dev-hub until a second pass. |
|
||||||
|
| `api/models/agent_message.py` | Generic agent inbox and thread model. |
|
||||||
|
| `api/models/tpsc.py` | Third-party service catalog/snapshot primitives. |
|
||||||
|
| `api/schemas/domain.py` | Core domain schemas; split dev-hub counts from generic read models. |
|
||||||
|
| `api/schemas/managed_repo.py` | Core repo schemas; keep dispatch/scope-health schemas in dev-hub. |
|
||||||
|
| `api/schemas/agent_message.py` | Generic message schemas. |
|
||||||
|
| `api/schemas/tpsc.py` | Generic TPSC schemas. |
|
||||||
|
| `api/routers/messages.py` | Mostly self-contained generic router. |
|
||||||
|
| `api/routers/tpsc.py` | Generic catalog and GDPR report router. |
|
||||||
|
| `api/routers/policy.py` | Generic policy document router if policy roots become configurable. |
|
||||||
|
|
||||||
|
## Needs An Adapter Seam
|
||||||
|
|
||||||
|
These are still part of the target architecture, but the current State Hub
|
||||||
|
implementation is coupled to dev-hub concepts:
|
||||||
|
|
||||||
|
| Surface | Coupling to resolve |
|
||||||
|
| --- | --- |
|
||||||
|
| `Domain` and `domains.py` detail views | Counts topics, workstreams, extension points, and technical debt. Hub-core should expose a domain summary hook that dev-hub can implement. |
|
||||||
|
| `ManagedRepo` | Contains `topic_id`, SBOM fields, and state-sync timestamps. Keep minimal repo identity in core, then add dev-hub extensions. |
|
||||||
|
| `CapabilityRequest` | Points at workstreams and tasks. Hub-core needs generic context fields or optional extension references before extraction. |
|
||||||
|
| `ProgressEvent` | Points at topics, workstreams, tasks, and decisions. Hub-core should define event identity, type, summary, detail, author, and timestamps, with hub-specific subject references added by each hub. |
|
||||||
|
| MCP tools in `mcp_server/server.py` | Generic tools are mixed into a single dev-hub server module. T06 should create a base registration class that receives API client/config dependencies and lets dev-hub add its own tools. |
|
||||||
|
|
||||||
|
## Keep In Dev-Hub
|
||||||
|
|
||||||
|
The following State Hub areas should not move into hub-core during T05:
|
||||||
|
|
||||||
|
- Topics, workstreams, tasks, decisions, dependencies, and flow state.
|
||||||
|
- Extension points, technical debt, interface changes, SBOM, token events, and
|
||||||
|
contribution accounting.
|
||||||
|
- Dashboard-specific loaders and Observable views.
|
||||||
|
- Workplan-file parsing and consistency reconciliation.
|
||||||
|
- Kaizen agents, scope health, dispatch views, and recently-on-scope reports.
|
||||||
|
|
||||||
|
## Verification Plan
|
||||||
|
|
||||||
|
The first hub-core commit should pass these checks before State Hub is refactored
|
||||||
|
to import it:
|
||||||
|
|
||||||
|
1. `python3 -m compileall hub_core`
|
||||||
|
2. A minimal import test that imports every model, schema, and router module.
|
||||||
|
3. SQLAlchemy metadata inspection proving the initial core tables are registered.
|
||||||
|
4. A FastAPI smoke app that mounts the extracted routers with an injected
|
||||||
|
`get_session` dependency.
|
||||||
|
5. `cd /home/worsch/state-hub && make test` remains green before and after the
|
||||||
|
editable `hub-core` dependency is introduced.
|
||||||
|
|
||||||
|
## Next Step
|
||||||
|
|
||||||
|
Create the `/home/worsch/hub-core` package with only the first package slice,
|
||||||
|
commit that seed independently, then return to `/home/worsch/state-hub` for the
|
||||||
|
first import-based refactor. Do not rename State Hub to dev-hub until T05-T08
|
||||||
|
prove the shared package boundary.
|
||||||
@@ -8,7 +8,7 @@ status: active
|
|||||||
owner: custodian
|
owner: custodian
|
||||||
topic_slug: custodian
|
topic_slug: custodian
|
||||||
created: "2026-03-20"
|
created: "2026-03-20"
|
||||||
updated: "2026-03-20"
|
updated: "2026-06-06"
|
||||||
state_hub_workstream_id: "293a74fe-a85a-4ad6-8933-23d52a72fe8b"
|
state_hub_workstream_id: "293a74fe-a85a-4ad6-8933-23d52a72fe8b"
|
||||||
---
|
---
|
||||||
|
|
||||||
@@ -119,9 +119,16 @@ Document the OIDC contract as `canon/standards/iam-profile_v0.1.md`:
|
|||||||
## Phase 2 — Hub Extraction & Dev Hub Rename
|
## Phase 2 — Hub Extraction & Dev Hub Rename
|
||||||
|
|
||||||
**Goal**: Extract generic hub-core package; rename state-hub to dev-hub.
|
**Goal**: Extract generic hub-core package; rename state-hub to dev-hub.
|
||||||
**Repo**: the-custodian (extraction), hub-core (new repo)
|
**Repo**: the-custodian (governance and workplan), `/home/worsch/state-hub`
|
||||||
|
(authoritative source), `/home/worsch/hub-core` (new target repo)
|
||||||
**Runs in parallel with Phase 1.**
|
**Runs in parallel with Phase 1.**
|
||||||
|
|
||||||
|
**Current repo reality (2026-06-06):** `CUST-WP-0043` completed the State Hub
|
||||||
|
repo extraction, so this repository now keeps only the `state-hub/README.md`
|
||||||
|
pointer. Phase 2 implementation work must read and refactor the standalone
|
||||||
|
`/home/worsch/state-hub` checkout, while this workplan keeps the coordination
|
||||||
|
record in `the-custodian`.
|
||||||
|
|
||||||
### Extraction Boundary
|
### Extraction Boundary
|
||||||
|
|
||||||
**Generic hub-core (~17 MCP tools, ~6 models, ~6 routers):**
|
**Generic hub-core (~17 MCP tools, ~6 models, ~6 routers):**
|
||||||
@@ -136,19 +143,27 @@ Document the OIDC contract as `canon/standards/iam-profile_v0.1.md`:
|
|||||||
|
|
||||||
```task
|
```task
|
||||||
id: CUST-WP-0025-T05
|
id: CUST-WP-0025-T05
|
||||||
status: todo
|
status: in_progress
|
||||||
priority: high
|
priority: high
|
||||||
state_hub_task_id: "04bf480c-8847-4a89-a4f2-e7c5fc51088d"
|
state_hub_task_id: "04bf480c-8847-4a89-a4f2-e7c5fc51088d"
|
||||||
```
|
```
|
||||||
|
|
||||||
Create `hub-core` as a standalone repo with `pyproject.toml` (uv-managed).
|
Create `/home/worsch/hub-core` as a standalone repo with `pyproject.toml`
|
||||||
Extract from state-hub:
|
(uv-managed). Extract from `/home/worsch/state-hub`:
|
||||||
- Generic SQLAlchemy models (Domain, AgentMessage, CapabilityCatalog, CapabilityRequest, ManagedRepo, TPSC*, ProgressEvent)
|
- Generic SQLAlchemy models (Domain, AgentMessage, CapabilityCatalog, CapabilityRequest, ManagedRepo, TPSC*, ProgressEvent)
|
||||||
- Generic Pydantic schemas
|
- Generic Pydantic schemas
|
||||||
- Generic FastAPI routers (domains, repos, messages, capability_requests, tpsc, policy)
|
- Generic FastAPI routers (domains, repos, messages, capability_requests, tpsc, policy)
|
||||||
- Alembic migration templates for core schema
|
- Alembic migration templates for core schema
|
||||||
- Shared utilities (slug resolution, pagination, trailing-slash normalization)
|
- Shared utilities (slug resolution, pagination, trailing-slash normalization)
|
||||||
|
|
||||||
|
Implementation start (2026-06-06): reviewed the standalone State Hub source and
|
||||||
|
captured the first extraction boundary in
|
||||||
|
`docs/hub-core-extraction-boundary.md`. Several candidate "generic" models still
|
||||||
|
reference dev-hub tables (`topics`, `workstreams`, `tasks`, `decisions`), so the
|
||||||
|
initial package slice should start with base DB primitives, domains, repos,
|
||||||
|
messages, TPSC catalog/snapshots, and adapter seams for progress and capability
|
||||||
|
requests rather than a blind file copy.
|
||||||
|
|
||||||
### T06 — Hub-core FastMCP base server
|
### T06 — Hub-core FastMCP base server
|
||||||
|
|
||||||
```task
|
```task
|
||||||
@@ -193,7 +208,7 @@ priority: high
|
|||||||
state_hub_task_id: "daf1d8ac-b55a-4692-b359-2671ddf6fc8a"
|
state_hub_task_id: "daf1d8ac-b55a-4692-b359-2671ddf6fc8a"
|
||||||
```
|
```
|
||||||
|
|
||||||
Refactor the state-hub codebase:
|
Refactor the standalone `/home/worsch/state-hub` codebase:
|
||||||
- Replace generic models/routers/schemas with imports from hub-core
|
- Replace generic models/routers/schemas with imports from hub-core
|
||||||
- Keep dev-specific code (topics, workstreams, tasks, decisions, etc.) in state-hub
|
- Keep dev-specific code (topics, workstreams, tasks, decisions, etc.) in state-hub
|
||||||
- Ensure all existing tests pass with the new import structure
|
- Ensure all existing tests pass with the new import structure
|
||||||
@@ -209,13 +224,13 @@ state_hub_task_id: "2148a804-7d6a-4e26-b1a8-08da24929c88"
|
|||||||
```
|
```
|
||||||
|
|
||||||
Rename across all integration points:
|
Rename across all integration points:
|
||||||
- `state-hub/mcp_server/server.py`: name="state-hub" → "dev-hub"
|
- `/home/worsch/state-hub/mcp_server/server.py`: name="state-hub" → "dev-hub"
|
||||||
- `~/.claude/CLAUDE.md`: 3 locations (registration commands, references)
|
- `~/.claude/CLAUDE.md`: 3 locations (registration commands, references)
|
||||||
- `state-hub/scripts/register_project.sh`: validation checks
|
- `/home/worsch/state-hub/scripts/register_project.sh`: validation checks
|
||||||
- `state-hub/scripts/patch_mcp_cwd.py`: config checks
|
- `/home/worsch/state-hub/scripts/patch_mcp_cwd.py`: config checks
|
||||||
- `state-hub/custodian_cli.py`: config checks
|
- `/home/worsch/state-hub/custodian_cli.py`: config checks
|
||||||
- `state-hub/scripts/project_rules/session-protocol.template`: template text
|
- `/home/worsch/state-hub/scripts/project_rules/session-protocol.template`: template text
|
||||||
- `state-hub/api/main.py`: service metadata response
|
- `/home/worsch/state-hub/api/main.py`: service metadata response
|
||||||
|
|
||||||
### T10 — MCP config migration script
|
### T10 — MCP config migration script
|
||||||
|
|
||||||
@@ -226,7 +241,7 @@ priority: medium
|
|||||||
state_hub_task_id: "5953f129-089d-4d90-bbe5-f86da4eac1bf"
|
state_hub_task_id: "5953f129-089d-4d90-bbe5-f86da4eac1bf"
|
||||||
```
|
```
|
||||||
|
|
||||||
Create `state-hub/scripts/migrate_mcp_config.py` that:
|
Create `/home/worsch/state-hub/scripts/migrate_mcp_config.py` that:
|
||||||
- Reads `~/.claude.json`
|
- Reads `~/.claude.json`
|
||||||
- Renames `mcpServers["state-hub"]` to `mcpServers["dev-hub"]`
|
- Renames `mcpServers["state-hub"]` to `mcpServers["dev-hub"]`
|
||||||
- Preserves all other settings
|
- Preserves all other settings
|
||||||
@@ -258,7 +273,7 @@ state_hub_task_id: "e55ae544-3cea-485e-80d5-a9696ef97b96"
|
|||||||
```
|
```
|
||||||
|
|
||||||
Gate: all of the following must pass before Phase 2 is considered complete:
|
Gate: all of the following must pass before Phase 2 is considered complete:
|
||||||
- `cd state-hub && make test` — full test suite
|
- `cd /home/worsch/state-hub && make test` — full test suite
|
||||||
- `make fix-consistency REPO=the-custodian` — workplan ↔ DB sync
|
- `make fix-consistency REPO=the-custodian` — workplan ↔ DB sync
|
||||||
- `make check-consistency-all` — all registered repos
|
- `make check-consistency-all` — all registered repos
|
||||||
- Manual smoke test: start dev-hub MCP server, run get_domain_summary from a domain repo
|
- Manual smoke test: start dev-hub MCP server, run get_domain_summary from a domain repo
|
||||||
@@ -269,6 +284,14 @@ Gate: all of the following must pass before Phase 2 is considered complete:
|
|||||||
**Depends on**: Phase 2 (hub_core available), Phase 1 (identity for service auth).
|
**Depends on**: Phase 2 (hub_core available), Phase 1 (identity for service auth).
|
||||||
**Repo**: ops-hub (new standalone repo, registered under custodian domain)
|
**Repo**: ops-hub (new standalone repo, registered under custodian domain)
|
||||||
|
|
||||||
|
**Inventory-first implementation slice (2026-06-05):** `CUST-WP-0047`
|
||||||
|
carves out the minimum useful part of T14/T16/T18 before the full standalone
|
||||||
|
`ops-hub` scaffold exists: a repo-owned service inventory contract, an initial
|
||||||
|
service/location/evidence seed, and the handoff path for Inter-Hub widgets and
|
||||||
|
activity-core probes. The T13-T19 tasks below remain the long-term ops-hub
|
||||||
|
implementation; the inventory slice produces input artifacts that the eventual
|
||||||
|
ops-hub repo can ingest rather than replace.
|
||||||
|
|
||||||
### T13 — Create ops-hub repo from hub-core scaffold
|
### T13 — Create ops-hub repo from hub-core scaffold
|
||||||
|
|
||||||
```task
|
```task
|
||||||
|
|||||||
Reference in New Issue
Block a user