4.6 KiB
4.6 KiB
T10.8 — Orchestrator reference service
| Field | Value |
|---|---|
| Phase | P10 — Orchestration |
| Size | M — 1 to 3 days |
| Status | Not started |
| Flags | — |
| Spec | inlined below |
| Blocks | — |
Goal
Reference process that consumes .events, invokes the registered
Reconciler for goal-tagged terminal transitions, and publishes decisions
to .dispatch — never spawns a run itself.
Facts (inlined — no spec read needed)
- The orchestrator embeds poimen only via the HTTP API (T10.4) /
poimen-sdk, exactly like any other external embedder — no special kernel access. - Its entire job: consume
.events, filter for goal-taggedVerified/Graded/Ungraded, callReconciler(T10.2), publish the resultingSpawnNextdecision to.dispatch.Stop/Retrydecisions are recorded but do not publish a dispatch message. - The default
Reconcilerimplementation may itself be another poimen run (aModelstep + aToolstep) — the orchestrator's job is identical regardless of whether the boundReconcileris LLM-backed or a hand-written Rust impl. - Never publishes a run directly, never calls
POST /v1/runsitself — that would reintroduce the bypass T10.7's inbox relay exists to prevent. Its only write is to.dispatch.
Steps
- Consume
.events, filter to records with aGoalIdand a terminal run state (Verified/Graded/Ungraded). - For each, build
ReconcileCtx(T10.2) and call theReconcilerbound to that goal. - On
SpawnNext: publish{workflow_ref, input, goal_id, dispatch_key}to.dispatch—dispatch_keyderived from the decision id so redelivery is naturally deduped downstream (T10.3). - On
Retry/Stop: record the decision (WorkEventprovenance per T10.2), publish nothing. - Own failure domain: separate process, own consumer group, own
retry/backoff on
Reconciler-call failure — aReconcilererror does not crash the orchestrator, it skips and retries on next poll or leaves the goal stalled with a visible metric. - Emit reconcile-latency and goal-stall metrics.
- Test the full loop against a stub
Reconciler: events in, dispatch out, verified end to end including a two-hop goal chain (run A → reconcile → run B → reconcile → stop).
Acceptance
- A two-run goal chain (A completes → reconcile → B spawns → B completes →
reconcile →
Stop) completes end to end through real Kafka topics, with the orchestrator never calling spawn directly. Reconcilerfailure on one goal does not block reconciliation of other goals.
Verify
Harness: real Kafka (or the board's chosen fault-injection substrate),
stub Reconciler with scripted decisions, T10.7's inbox relay running
alongside.
Integration test — tests/it_orchestrator_e2e.rs:
- Spawn run A with
goal_id=G, nodispatch_key. Drive toVerified{pass}. - Assert orchestrator calls
Reconcilerexactly once for A; stub returnsSpawnNextfor run B. - Assert a message lands on
.dispatch, and via T10.7's relay, run B is spawned withgoal_id=G. - Drive run B to
Graded. AssertReconcilercalled again; stub returnsStop. - Assert no further
.dispatchmessage is published; goal G's chain shows exactly[A, B]via T10.1'sGoalView. - Instrument
POST /v1/runs; assert zero calls originate from the orchestrator process — only from the inbox relay. - Second goal G2 with a
Reconcilerthat always errors; assert G2 stalls (visible via goal-stall metric) while G's chain, run concurrently, proceeds unaffected.
Command: cargo test -p orchestration orchestrator_e2e -- --test-threads=1
False pass:
- Step 6 omitted: an orchestrator that takes a shortcut and spawns directly under test-only conditions would still pass steps 1-5.
- Testing only a single-hop chain (A →
Stop) — the two-hop case is what proves goal-chain provenance actually threads throughGoalViewcorrectly across a full reconcile-dispatch-relay-spawn cycle.
Traps
- Orchestrator holding an admission-layer shortcut "to save a network hop." Collapses the exact boundary T10.7 was built to enforce.
- Coupling
Reconcilerfailure handling to a single global retry policy. One broken goal'sReconcilershould not starve reconciliation for every other goal in the tenant.
Background (not required to do this task): T10.1-goalid-and-goal-scoped-query.md · T10.2-reconciler-port.md · T10.7-kafka-topics-and-inbox-relay.md