A reconciliation kernel for development work
Source article for ambientagents.net regeneration. Author: Jeff Sylvan. Technical design document. Items marked [FILL] or [CONFIRM] must be resolved before publishing.
The claim
The orchestrator is a control loop over a plan graph. Not a workflow engine that runs a plan, but a controller that keeps the plan itself correct while a heterogeneous fleet executes it. Two loops, decoupled by a queue. The planner consumes deltas and emits DAG mutations. The executor watches for ready nodes and dispatches them to workers. Everything below is a consequence of taking that claim seriously on top of Temporal.
The DAG is data, not workflow code
The tempting design is to express the plan as a Temporal workflow: nodes as activities, edges as control flow. It fails immediately, because Temporal workflows are deterministic code and this plan must mutate at runtime in response to external events.
So the plan graph lives as versioned data. Nodes carry task specs and state (pending, ready, dispatched, blocked-on-human, done, stale). Edges are dependencies. Missions are subtrees with their own budgets and gates. A long-lived orchestrator workflow interprets the graph rather than embodying it. External deltas arrive as Temporal signals and updates. Signal-with-start means an inbound event either wakes the standing orchestrator or creates it, which collapses the cold-start case. Continue-as-new bounds event history on anything long-lived, because a reconciler that runs for months will otherwise drown in its own history.
The queue contract
Webhook delivery is at-least-once, so the delta queue enforces idempotency and order at ingestion. Every delta carries a provenance envelope: source, actor identity, delivery id, trigger lineage, and the plan epoch it was observed against. Dedup keys come from delivery ids. Ordering is per aggregate (per repository, per mission), not global, because global ordering is neither achievable nor needed.
Actor identity and lineage are not bookkeeping. They are the loop-safety mechanism, covered below.
In-flight mutation is a fencing problem
Here's the part I didn't expect to reuse. Mutating a DAG while workers execute against it is the same problem as mutating partition ownership while nodes serve traffic, and Black Skies already solves that with epoch-based lease fencing. Same discipline, different substrate.
The plan graph carries a version number per subtree. Treat versions as epochs. Every dispatched worker is stamped with the epoch it launched under. When a delta invalidates a subtree, the epoch bumps. Results arriving from stale-epoch workers are not errors; they're handled by per-node policy:
- Drain: let the worker finish and accept the result if the node survived the mutation.
- Preempt: stop the worker, refund remaining node budget to the mission.
- Quarantine: capture the partial output for salvage review instead of discarding it, because stale work is frequently half right.
One consistency discipline, instantiated twice: once to keep 10,000 players coherent in a persistent battle space, once to keep a fleet of coding agents coherent under a changing plan.
Mutation classes
Not all deltas cost the same, so the planner distinguishes five mutation classes. Append: new issue, new PR, new task; cheap, additive, safe to apply eagerly. Amend: a node's spec changes without invalidating its subtree. Reprioritize: ordering and budget shifts only. Invalidate: a subtree is wrong now; destructive and expensive. Retract: work must be undone, not just stopped; rarest and most expensive.
Appends run on cheap heuristics. Invalidations and retractions are exactly where an adversarial review gate earns its place: before the system preempts paid-for work, a cross-family panel reviews the invalidation set and captures dissent. In v1, that's the only place the gate is mandatory.
Gates consume evidence, not vibes
A review gate is only as good as the artifacts in front of it. The council doesn't judge a diff in the abstract; it judges a diff plus what the change demonstrably does. So every worker class carries an evidence contract, and the evidence generators are adopted, never built, per the non-goals below. Browser and UI verification comes from Playwright-driven agentic checking (playwright-mcp, gsd-browse) attached to the review node. Cloud agent runtimes already produce screencast demos of completed work; those attach as evidence instead of being rebuilt. CI results stay the boring, primary evidence class for anything with tests. And for Black Skies specifically, load-simulation output is the evidence class that decides arguments. The kernel's job is routing the right evidence to the right gate and holding a merge when the evidence contract isn't met. [FILL: v1 evidence contracts per worker class]
Loop safety
Two ambient systems can retrigger each other indefinitely. My orchestrator reacts to GitHub events. Cursor Automations react to GitHub events. A PR comment written by one is an event to the other. Without guards this converges to two vendor bots arguing in a PR thread at my expense.
The guards: actor-identity filters at ingestion, lineage tags propagated onto every event the system emits, cycle detection over lineage chains, and per-trigger budgets so that even an undetected loop exhausts a bounded allowance and parks for human review instead of running open-ended.
Thrash, and the planner as economic scheduler
A constantly fresh plan can oscillate and never finish anything. Damping is a first-class requirement: minimum work quanta before a node is eligible for preemption, damping windows that batch low-priority deltas, and cost-of-change accounting on every proposed mutation. Preempting a node wastes its sunk spend plus restart and context-rebuild cost; the planner weighs that against the cost of finishing stale work.
The quiet consequence is that budget machinery stops being a bolt-on. Spend caps, refunds, and kill authority become planner inputs, and the planner becomes an economic scheduler optimizing freshness against cost under a mission budget.
Termination semantics
Continuous deltas dissolve "done" unless you define it. Two campaign types with different contracts. Standing reconcilers never finish and are governed by SLOs instead: delta-to-plan-updated latency, issue-to-triaged time [FILL: targets]. Bounded campaigns must finish and carry a protected critical path that freshness is not allowed to starve; done means the spec is satisfied at the current epoch, not at the epoch the campaign started under.
v1 scope
The January dogfood [CONFIRM: January 2] ships exactly three delta classes. An issue opened appends a triage node. A PR event appends a review node. A ratified design-document change invalidates its mapped subtree. The third one is the demo that proves the thesis: a design decision lands, and the fleet visibly re-plans around it without me touching the DAG.
Transport is GitHub webhooks plus schedules, nothing proprietary. Worker classes: [CONFIRM: Claude Code sessions plus one cloud agent class]. Council gates fire only on invalidations. Everything else is observed and logged, not gated, because a v1 that gates everything is a v1 nobody waits for.
Non-goals
No event transport (GitHub webhooks and EventBridge exist). No agent hosting (the cloud agent platforms exist and are good). No browser automation or test framework (Playwright, its agentic wrappers, and CI exist; the kernel consumes their output as evidence). No IDE, no editor plugin, no new agent framework. The product is the seat above those things, and the discipline is refusing to rebuild anything that already has a vendor.