Skip to content

feat(node): three-node HF demo topology — implementation (F2)#151

Merged
brownjuly2003-code merged 6 commits into
mainfrom
feat/f2-three-node-topology
Jul 4, 2026
Merged

feat(node): three-node HF demo topology — implementation (F2)#151
brownjuly2003-code merged 6 commits into
mainfrom
feat/f2-three-node-topology

Conversation

@brownjuly2003-code

Copy link
Copy Markdown
Owner

Implements the three-node demo topology per ADR 0012 and the build contract docs/three-node-demo-topology.md (F2 of plan_endgame_02_07_26.md). One image, three roles differentiated purely by environment; the standalone demo Space stays byte-identical.

The actual Hugging Face publish + live-verify remain the owner gate — this PR is the implementation + committed deploy artifacts only.

What's here (6 commits, one per build-contract step)

  1. Node config seam (src/serving/node/config.py) — resolves/validates AGENTFLOW_NODE_* once at boot; unset role = standalone (strict superset); fail-fast on an edge with no center URL/token or an unknown branch.
  2. Center ingest POST /v1/node/events — token-auth (constant-time, distinct from demo-key), applies each event via the existing local_pipeline._process_event (no new serving logic), tags the originating branch on the pipeline_events journal (new branch column), idempotent by event_id. 404 off-center, hidden from public OpenAPI.
  3. Edge emitter — slow generator → local-apply → forward the same canonical dict to the center; tolerant of a cold/asleep hub (bounded retries, drop, never raise).
  4. Branch-scoped seed — deterministic per-branch journal baseline under a distinct node.baseline topic (center = all branches, edge = its own, standalone = none).
  5. Cross-branch view GET /v1/node/branches — per-branch baseline / live-delta / last-seen from the journal; silent branches degrade to waking, never error.
  6. Deploy artifacts — per-role Space READMEs + DEPLOY.md runbook under deploy/hf-space/three-node/ (same image ×3; env in Space Settings).

Honesty boundary (stated in every node README)

Demonstrates branch distribution / event federation, not horizontal scaling. Three substitutions are stated plainly so the artifact never over-claims: HTTPS POST stands in for Kafka→Flink (transport only); single-replica embedded control plane, not the multi-replica PostgreSQL profile; the federated live layer is ephemeral (resets on hub restart).

Tests — machine-checkable invariants N1–N12

tests/unit/test_node_{config,emitter,seed,view,deploy_artifacts}.py + tests/integration/test_node_topology.py.

Verification (local, no-Docker)

  • Full unit: 1662 passed, 1 skipped
  • Full integration (no-Docker): 263 passed, 56 skipped
  • ruff + ruff format --check + mypy (strict, src/, 124 files) + export_openapi.py --check — all green (no OpenAPI drift; the node routes are include_in_schema=False)

🤖 Generated with Claude Code

JuliaEdom and others added 6 commits July 4, 2026 11:31
Three-node demo topology (ADR 0012). New src/serving/node/ resolves and
validates AGENTFLOW_NODE_* once at boot: unset/empty role == standalone
(byte-identical to today's demo, N1); center/edge fully validated with
fail-fast on a missing center URL, missing token, or unknown branch.
Lifespan stores node_config/role/branch on app.state; the ingest endpoint
and edge emitter (later steps) hang off this single seam.

N1/N2 config + standalone-unchanged tests (unit + integration).

Co-Authored-By: Claude Opus 4.8 (1M context) <noreply@anthropic.com>
Center-only node federation ingest (ADR 0012 §3). An edge pushes a batch of
the same canonical events; the center applies each via
local_pipeline._process_event — no new serving logic — and tags the
originating branch on the pipeline_events journal (new branch column, NULL
for in-process events).

Auth ladder: role gate (404 off-center, even with a valid token) → bearer
constant-time compare vs AGENTFLOW_NODE_TOKEN (401 missing / 403 wrong) →
body shape (422, unknown origin_branch rejected by Literal). Demo-guard
allow-list + auth-middleware exempt let the token call through while the
public demo-key still fails; endpoint hidden from public OpenAPI. Idempotent
by event_id (re-POST does not double-count). N3/N4/N5/N12 tests.

Co-Authored-By: Claude Opus 4.8 (1M context) <noreply@anthropic.com>
Edge-role background task (ADR 0012 §6). A slow generator produces the same
canonical events the in-process pipeline makes; each is stamped with the
edge's branch, applied to the edge's own read surface, and forwarded
unchanged to the center's POST /v1/node/events with the node token (N7).

Cold-center tolerance (N9): bounded retries with backoff, drop + log on
give-up, never raised into the loop — the edge stays up when the hub is
asleep, which is what makes the push-on-activity sleep choreography
self-healing. Started in lifespan only for edge role (off in center/
standalone; AGENTFLOW_NODE_EMITTER_ENABLED=false disables for tests).

Co-Authored-By: Claude Opus 4.8 (1M context) <noreply@anthropic.com>
Boot baseline for the cross-branch view (ADR 0012 §7). The demo entity tables
are a shared catalog with no branch column, so branch attribution lives on the
pipeline_events journal: a deterministic per-branch baseline under a distinct
topic (node.baseline). Center seeds all three branches, an edge seeds only its
own (N6), standalone seeds none — byte-identical to today's demo (N1). Pure
function of the branch, cleared-then-relaid, so a restart yields the same
baseline (N11). The distinct topic keeps the rows inert to every existing
journal scan and separable from the live delta.

N6/N11 unit + integration tests.

Co-Authored-By: Claude Opus 4.8 (1M context) <noreply@anthropic.com>
GET /v1/node/branches (center-only, 404 off-center). Composes a per-branch
summary purely from the pipeline_events journal — no new store: seeded
baseline, live delta this lifecycle, and last-seen timestamp. A silent branch
(asleep / just booted) shows baseline + null last-seen + a waking status,
never an error (N8) — the sleep behaviour is visible by design. Includes the
UI hint directing visitors to open a branch Space.

N8 unit + integration tests (incl. the N4 "metric moved" end: an ingested
spb event lifts the spb live delta and sets last-seen).

Co-Authored-By: Claude Opus 4.8 (1M context) <noreply@anthropic.com>
…cts)

Per-role Hugging Face Space artifacts for the three-node deploy (ADR 0012 §11):
center/edge-spb/edge-ekb READMEs (Space frontmatter + role env matrix + the
honesty boundary stated plainly) and a DEPLOY.md runbook (same image x3, env in
Space Settings, center-first bring-up, verify-live §12). The shared image is the
existing deploy/hf-space/Dockerfile.

The actual HF publish + live-verify remain the OWNER GATE — these are the
committed artifacts only. Frontmatter guard test included.

Co-Authored-By: Claude Opus 4.8 (1M context) <noreply@anthropic.com>
@github-actions

github-actions Bot commented Jul 4, 2026

Copy link
Copy Markdown

DORA Metrics

  • Window: last 30 days
  • Branch: main
  • Deployment frequency: 127 total / 29.63 per week
  • Lead time for changes: avg 0.42h / median 0.0h
  • Change failure rate: 74.02% (94/127)
  • MTTR: 0.29h across 2 incident(s)

@brownjuly2003-code brownjuly2003-code merged commit 934a10b into main Jul 4, 2026
23 checks passed
@brownjuly2003-code brownjuly2003-code deleted the feat/f2-three-node-topology branch July 4, 2026 09:37
Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment

Labels

None yet

Projects

None yet

Development

Successfully merging this pull request may close these issues.

2 participants