repo-manager/history/2026-08-09-state-hub-repo-tooling-research.md
tegwick 754d02f40e docs: research SH repo tooling, architecture blueprint, RMGR-WP-0002
Document how State Hub registers, resolves, reconciles, and mutates
repos; blueprint Stage B dual-run toward retirement; open workplan for
SH adapter writeback/reconcile without non-retirement refactors.
2026-08-09 23:04:49 +02:00

280 lines
12 KiB
Markdown
Raw Permalink Blame History

This file contains ambiguous Unicode characters

This file contains Unicode characters that might be confused with other characters. If you think that this is intentional, you can safely ignore this warning. Use the Escape button to reveal them.

# Research: How State Hub interacts with repositories
**Recorded:** 2026-08-09
**Audience:** Repo Manager + State Hub retirement
**Sources:** `state-hub` checkout (API, scripts, MCP, Makefile, docs), activity-core consumers, prior RM extraction inventory
---
## 1. Executive summary
State Hub is the **live index and agent coordination surface** for fleet
repositories. It does **not** own Git truth. It:
1. **Registers** repos (slug, domain, classification, host paths, remotes).
2. **Resolves** a checkout on the current machine via `host_paths` / `local_path`.
3. **Parses** file-backed work records (workplans, tasks, and related kinds).
4. **Reconciles** files ↔ Postgres with ADR-001 (“file wins”) via
`consistency_check` / `statehub fix-consistency`.
5. **Mutates files** for selected status writebacks (API reconciliation path +
fix-consistency writeback), then **git commit + push-seal**.
6. **Serves** agents (MCP/REST) and automation (activity-core sweep, SBOM, DoI).
Repo Managers job is to take over (1)(5) as the repository boundary while
hub-core keeps messaging, progress, and cross-domain projections.
---
## 2. Interaction model (as-built)
```text
Agents (Claude/Codex) activity-core Operators
│ │ │
│ MCP / REST │ GET /repos/ │ make / CLI
│ update_task_status │ POST sweep │ register-path
▼ ▼ ▼
┌─────────────────────────────────┐
│ State Hub API │
│ /repos /workplans /tasks │
│ /reconciliation /consistency │
│ /progress /messages … │
└───────────────┬─────────────────┘
│ Postgres (index)
┌───────────────┴─────────────────┐
│ resolve_repo_path(host_paths) │
│ parse workplans/*.md │
│ writeback + git commit/push │
└───────────────┬─────────────────┘
Git checkouts on hosts
(workstation, railiance01, …)
```
**Authority:** repository files + Git history.
**Hub DB:** rebuildable cache/index.
**Operator config:** `host_paths` (not in Git).
---
## 3. Registration and classification tooling
| Tool | Entry | What it does |
| --- | --- | --- |
| REST `POST/GET/PATCH /repos/` | API | CRUD `managed_repos` |
| `POST /repos/{slug}/paths` | API / `make register-path` | Set `host_paths[hostname]=path` |
| `POST /repos/onboard` | API | Onboarding helper |
| `scripts/register_from_classification.py` | `make register-from-classification` | Upsert from `.repo-classification.yaml` |
| `statehub register` / `register-project` | CLI / make | Scaffold INTENT/AGENTS, register, optional seed WP |
| `list_domain_repos` / `list_repos_by_classification` | MCP | Discovery |
| `register_repo` / `register_repo_from_classification` / `update_repo_path` | MCP | Agent registration |
**Classification spine:** committed `.repo-classification.yaml` (category,
domain, tags, business fields). Canon allowed vocab in the-custodian.
Domain FK on `managed_repos` derived from primary domain.
**Multi-host:** each machine registers its checkout path. Consistency uses
`host_paths[current_hostname]` then falls back to `local_path`.
**Pitfall observed:** `statehub register` seeds a bootstrap workplan with a
generic `REPO-WP-0001` style id; if a real WP already uses that prefix, **id
collision** occurs (seen on repo-manager). Prefer classification register +
hand-authored workplans for mature repos.
---
## 4. Work-record loop (files ↔ index)
### 4.1 File conventions
- `workplans/<PREFIX>-WP-NNNN-*.md` with YAML frontmatter + ````task` blocks.
- Hub UUIDs written back as `state_hub_workstream_id` / `state_hub_task_id`.
- Generated `WORK-RECORDS.md` and `.custodian-brief.md` (fix-consistency).
- Other kinds: intakes/decisions/register entries (C-31/C-32 registration).
### 4.2 Read path (agents)
| Action | Typical path |
| --- | --- |
| Orient | `get_domain_summary` / `GET /state/summary` |
| List work | `list_workplans` / `GET /workplans/?…` |
| List tasks | `list_tasks` / `GET /tasks/?workplan_id=` |
| Brief offline | `.custodian-brief.md` in each repo |
### 4.3 Write path (status)
| Action | Path | File effect |
| --- | --- | --- |
| MCP `update_task_status` | REST PATCH task | May go DB-first then consistency writeback |
| API reconciliation | `api/routers/reconciliation.py` | Classifies write-through vs deferred; may patch file via `workplan_files` |
| `statehub fix-consistency --fix` | `scripts/consistency_check.py` | File↔DB drift repair; optional git writeback commit |
| Push seal | `scripts/repo_sync.py` | After fix commits: pull-ff gates + push so local≡remote |
**Git rules (critical):**
- **C-16** behind remote → skip writes (pull first).
- **C-17** ahead + push failed → skip further writes.
- **Push-seal:** fix runs that create commits must push before return.
---
## 5. Consistency engine (primary repo tooling)
**Script:** `scripts/consistency_check.py` (large monolith).
**CLI wrappers:** `statehub fix-consistency`, `make check-consistency` /
`make fix-consistency`, MCP `check_repo_consistency`.
| Mode | Meaning |
| --- | --- |
| `--repo SLUG` | Single registered repo |
| `--here [PATH]` | Infer slug from cwd/remote |
| `--all` | All registered repos |
| `--remote --all` | Pull then fix (fleet sweep) |
| `--fix` | Apply file-wins repairs + writebacks |
| `--no-writeback` | Check/report only |
**Scheduled automation:** activity-core (or operator) →
`POST /consistency/sweep/remote-all` → remote-all sweep with wall-clock budget.
**C-rule families (repo-relevant):**
| Group | Examples | Role |
| --- | --- | --- |
| Parse/structure | C-01, C-02 | workplans/ present and parseable |
| Binding/drift | C-03C-06, C-09C-12, C-15, C-19, C-22 | UUID + status/title drift; file wins |
| Orphans | C-07, C-08, C-14 | DB without file / ghost workstreams |
| Git sync | C-16, C-17 | Protect against clobber / open-loop |
| Classification | C-24 | `.repo-classification.yaml` |
| Id hygiene | C-26, C-27 | prefix + collision |
| Work-record kinds | C-31C-33 | registry + WORK-RECORDS index |
| **Inbox (not repo)** | C-25, C-28, C-29 | messages — hub-core territory |
| Quality soft | C-34 | DoR-Ok soft warnings |
Parsers also live in `api/services/workplan_files.py` for in-process API
writeback (overlap with consistency_check — dual implementation risk).
---
## 6. REST surfaces touching repos (selected)
| Prefix / route | Purpose |
| --- | --- |
| `/repos/` | Registry list/create |
| `/repos/{slug}` PATCH/archive | Metadata / lifecycle |
| `/repos/{slug}/paths` | Host path registration |
| `/repos/{slug}/sync` | Sync trigger |
| `/repos/{slug}/doi`, `/doi/summary` | Definition of Integrated scoring |
| `/repos/todo-md-staleness` | Automation input (activity-core) |
| `/repos/scope-health` | SCOPE.md health |
| `/repos/{slug}/dispatch` | Agent dispatch orientation |
| `/workplans/`, `/tasks/` | Work index CRUD |
| `/reconciliation` | State-change + optional file write-through |
| `/consistency/sweep/remote-all` | Fleet reconcile job |
Related but **not pure repo boundary:** progress, messages, suggestions, fabric,
token events, service catalog, TPSC, capabilities (mixed hub + repo).
---
## 7. MCP tooling (repo-facing subset)
| Tool | Role |
| --- | --- |
| `register_repo` / `register_repo_from_classification` | Registration |
| `update_repo_path` | Host path |
| `list_domain_repos` / `list_repos_by_classification` | Discovery |
| `check_repo_consistency` | Wraps consistency engine |
| `validate_repo_adr` | ADR-001 checklist script |
| `ingest_sbom_tool` | SBOM ingest for a repo |
| `get_repo_goals` / `update_repo_goal` / `get_repo_dispatch` | Goals / dispatch |
| `list_workplans` / `create_workplan` / `update_workplan*` | Work index |
| `list_tasks` / `update_task_status` / bulk status | Task index + mutate |
| `get_domain_summary` / `get_state_summary` | Orientation (includes repo health) |
Sanctioned writes vs bootstrap-only are documented in `mcp_server/TOOLS.md`.
---
## 8. Adjacent tooling (repo-attached inventories)
| Tool | Makefile / script | Notes |
| --- | --- | --- |
| SBOM ingest | `make ingest-sbom`, `ingest_sbom.py` | Lockfiles + tools yaml |
| TPSC ingest | `ingest_tpsc.py` | Service declarations |
| Capabilities ingest | `ingest_capabilities.py` | Registry |
| DoI check | `check_doi.py` | Integration maturity |
| ADR validate | `validate_repo_adr.py` | File layout |
| Gitea inventory | `gitea_inventory.py` | Forge listing |
| Normalize attached WPs | `normalize_attached_repo_workplans.py` | Fleet hygiene |
| Edge outbox | `api/edge/outbox.py` | Offline queue when hub unreachable |
These are **repo-scoped jobs** but not the core ADR-001 consistency loop.
---
## 9. Downstream consumers
| Consumer | Interaction |
| --- | --- |
| **All agent AGENTS.md templates** | Session start brief; end with fix-consistency |
| **activity-core** | `GET /repos/`, todo-md-staleness, SBOM bulk, remote sweep, context resolvers |
| **ops-bridge** | Tunnels to API/MCP (`:8000` / `:18000`) |
| **Dashboard** | Observable pages over REST |
| **wise-validator / agentic-resources** | Progress and legacy field callers (historical) |
---
## 10. Strengths of the established tooling
1. **File-first doctrine is operational**, not only documented (C-rules + writeback).
2. **Multi-host path registry** enables workstation + cluster workers on one slug.
3. **Push-seal** closed the open-loop commit pile-up class of bugs.
4. **Classification spine** unifies discovery without hard-coding domain folders.
5. **MCP + REST + CLI** give agents and humans the same coordination surface.
6. **Fleet sweep** exists for unattended reconcile (activity-core / remote-all).
---
## 11. Failure modes and technical debt (retirement-relevant)
| Issue | Impact |
| --- | --- |
| Monolithic `consistency_check.py` | Hard to own outside state-hub; extract unit is large |
| Dual parsers (API vs script) | Drift risk between writeback paths |
| Bootstrap WP id collisions | `statehub register` unsafe on repos with real WP-0001 |
| Topic spine residual | `topic_id` still on models; classification is future spine |
| Inbox C-rules in consistency | Couples messaging to “repo fix” |
| Index mixed with hub concerns | Progress/messages/catalogs in same service as repo authority |
| Ghost workstreams from MCP create_* | Bootstrap-only tools still create DB-first risk if misused |
| Scheduled sweep fragility | Cluster notes: sweeps paused/gaps after cutovers |
---
## 12. Mapping to Repo Manager (current)
| State Hub capability | RM status (2026-08-09) |
| --- | --- |
| Observe + parse workplans | **Partial**`rmgr observe/reconcile` (JSON index) |
| Task status writeback + git | **Partial**`rmgr update-task-status` |
| Full C-rules / push-seal | **Not yet** — still SH |
| Registry + host_paths as system of record | **Still SH** |
| MCP / FastAPI / Postgres index | **Still SH** |
| Dual-run adapter for retirement | **Missing** — blocks clean strangler |
See also: `docs/state-hub-extraction-inventory_v0.1.md`,
`docs/observation-command-contracts_v0.1.md`.
---
## 13. Conclusion for retirement sequencing
The **retirement-critical path** is not a better CLI UX or a prettier model.
It is:
1. Make Repo Manager the **authoritative executor** of reconcile + file writeback
for at least one production command path agents already use.
2. Keep State Hub as a **strangler facade** (MCP/REST) until meters show zero
direct need for SH to touch checkouts.
3. Only then move registry/host_paths and drop SH repo mutation.
That sequence is elaborated in `specs/ArchitectureBlueprint.md` and the next
workplan **RMGR-WP-0002**.