feat: add fast forge work-record reconciliation
All checks were successful
CI Smoke / host-smoke (push) Successful in 0s
CI Smoke / container-smoke (push) Successful in 1s
Build and Publish Multi-Context Image / build-and-push (push) Successful in 24s

Assistant: codex
Assistant-Model: gpt-5.6-sol
Assistant-Session: 01a053ff-1d6f-7fe2-ac1c-a6eb40a42a0c
This commit is contained in:
tegwick 2026-08-30 22:38:54 +02:00
parent a65cef02cf
commit 34f5cb3fc3
22 changed files with 799 additions and 162 deletions

View file

@ -64,8 +64,9 @@ then run consistency sync.
All services bind to `127.0.0.1` only — nothing exposed to the network.
**Production:** the primary State Hub API runs on coulombcore-k3s. Workstation
port `8000` reaches it through the ops-bridge `state-hub-primary` tunnel. See
**Production:** the primary State Hub API runs in the railiance01-hosted k3s
cluster. Workstation port `8000` reaches it through the ops-bridge
`state-hub-primary` tunnel. See
[`docs/cluster-operating-model.md`](docs/cluster-operating-model.md) for access,
rollback, backups, and pragmatic limitations.
@ -82,7 +83,11 @@ Repository rename operations use the phased, UUID-preserving workflow in
- Python 3.12+ with `uv` (`pip install uv`)
- Node.js 18+ (dashboard only)
### First-time
### First-time local development setup
The local database and API are retained for development and disaster fallback.
They are not the normal production access path and conflict with the production
tunnel on port `8000`.
```bash
cd /home/worsch/state-hub
@ -92,27 +97,51 @@ make install # uv sync
make db # docker compose up postgres
make migrate # alembic upgrade head
make seed # insert 6 canonical topics
make api # db + migrate + uvicorn :8000 (restarts if running)
make api # LOCAL fallback: db + migrate + uvicorn :8000
```
### Dashboard
For a dashboard against that deliberate local backend, use
`make dashboard-local`.
### Production dashboard (normal operation)
The dashboard remains a workstation process, but its API is the primary State
Hub on railiance01. Start the tunnel first, then start the dashboard:
```bash
make dashboard # installs dashboard deps if needed, then Observable dev server on :3000
make dashboard-check # installs deps if needed, then runs Observable build
make bridges # connect workstation :8000 to primary/railiance01
make dashboard # verify the primary identity, then serve http://127.0.0.1:3000
```
### Start Everything
`make dashboard` refuses to start if port `8000` is unreachable or identifies
itself as anything other than `primary/railiance01`. This prevents the empty
local fallback database from being mistaken for production.
To start all the infrastructure on separate consoles do:
The MCP adapter is optional and is not required by the dashboard:
```bash
make db # docker compose up postgres
make mcp-http # start state-hub mcp service
make dashboard # Observable dev server on :3000
make bridges # Set up ssh bridges for cross machines access
make mcp-http # optional local SSE adapter on :8001
```
### Fast work-record synchronization
Workplan files remain authoritative. Repo Manager assigns missing UUIDv5
identifiers locally, pushes the file commit, and asks the primary State Hub to
derive that exact commit from Forgejo in one transactional request:
```bash
make bridges
make sync
```
The sync refuses an uncommitted or behind branch and will not write to a local
empty database: the API must identify itself as `primary/railliance01`. If the
primary is unavailable, Repo Manager writes an explicit pending receipt under
the checkout's local `.git/repo-manager/` state; rerunning `make sync` safely
replays the current pushed state.
Use `statehub fix-consistency` only for the broader consistency/quality audit.
It is no longer the normal registration and task-update path.
### CLI
@ -130,17 +159,22 @@ custodian register-project # register cwd as a Custodian project
|--------|-------------|
| `make install` | `uv sync` — install Python deps + entry points |
| `make install-cli` | Symlink `custodian` to `~/.local/bin` |
| `make db` | Start postgres container |
| `make start` | Print the production UI and local fallback startup paths |
| `make bridges` | Connect managed tunnels, including workstation `:8000` to the railiance01 primary |
| `make db` | Start the local fallback/development Postgres container |
| `make db-tools` | Start postgres + pgadmin (http://127.0.0.1:5050) |
| `make migrate` | `alembic upgrade head` |
| `make seed` | Insert 6 canonical topics (legacy bootstrap) |
| `make register-from-classification REPO=slug` | Upsert repo from `.repo-classification.yaml` |
| `make register-from-classification-all` | Bulk reclassify all repos with classification files |
| `make api` | `db` + wait + `migrate` + `uvicorn` (restarts if running) |
| `make api` | Start the local fallback API; replaces the production tunnel on `:8000` |
| `make dashboard-install` | Install dashboard npm deps from `dashboard/package-lock.json` |
| `make dashboard-check` | Build the Observable dashboard as a smoke/regression check |
| `make dashboard` | Install deps if needed, then start Observable dev server (restarts if running) |
| `make check` | `curl /state/health` |
| `make dashboard` | Verify `primary/railiance01`, then start the Observable dashboard |
| `make dashboard-local` | Start the dashboard against an intentional local/fallback API |
| `make sync` | Push missing deterministic IDs and reconcile this repo from the exact Forgejo commit |
| `make check` | Require a healthy `primary/railiance01` on workstation `:8000` |
| `make check-local` | Print `/state/health` without enforcing production identity |
| `make test` | Python test suite plus `make dashboard-check` |
| `make register-project DOMAIN=x PROJECT_PATH=y` | Register a project |
| `make clean` | `docker compose down -v` (destroys DB volume) |
@ -288,7 +322,7 @@ Prints API health, totals, and any blocking decisions.
### What `register-project` does
1. Verifies the API is reachable (fails fast with `make api` hint)
1. Verifies the API is reachable
2. Looks up the topic ID for the domain via `/topics/?status=active`
3. Checks that `state-hub` is in `~/.claude.json`
4. Writes `$PROJECT_PATH/CLAUDE.md` from `scripts/project_claude_md.template`