Plectis
This page

Paper module

Engine Room Bridge Campaign DAG

Staged Engine Room component: pre-dispatch bridge-campaign DAG validator for typed nodes, acyclicity, synthesis reachability, and provider fan-out ceilings.

Contains 23 sections · 1 diagram · 4 references

The write-up

Component is validator

This component is a validator that reads a bridge campaign graph and decides, before dispatch, whether it is safe to run, never calling a provider, worker, or reducer. A bridge campaign fans one piece of work out across several agent providers, then folds their results back into a single conclusion. This component reads the graph that describes such a campaign and decides, before anything runs, whether the graph is safe to dispatch. It is a validator. It never calls a provider, never dispatches a worker, and never runs a reducer.

Takes json campaign

It takes one JSON campaign spec and returns a ValidationResult of typed rule decisions with errors and warnings, so a rejection names exactly which rule failed and why. The code lives in src/microcosm_core/engine_room/bridge_campaign_dag.py. It takes one JSON campaign spec and returns a ValidationResult: a list of typed rule decisions, plus the errors and warnings those decisions produced. Each decision carries a rule id, the target it looked at, and a plain reason. The whole point is that when a graph is rejected, the result says exactly which rule rejected it and why.

Engine room demo

The Engine Room demo admits this component as a staged target, so the fixtures a reader runs here are the same ones audit_controller_coverage and run_demo audit. The Engine Room demo at src/microcosm_core/engine_room/demo.py admits this component as one of its staged bundle targets, so the same fixtures a reader can run here are the ones the demo audits under audit_controller_coverage and run_demo.

Purpose

Malformed graphs are paid for after dispatch

A cycle, an evidence-free synthesis, or an over-large fan-out costs the most after dispatch, since a run-it-and-see approach only discovers it at runtime across live external model access. The cost of a malformed campaign graph is paid after dispatch, when it is expensive. A dependency cycle never terminates. A synthesis step that depends on nothing but other conclusions summarises no gathered evidence. A fan-out that asks one provider for more parallel workers than it can take gets throttled or rejected downstream. A loose "run it and see" approach discovers all of this at runtime, across live external model access.

Move the checks before dispatch

This component moves those checks before dispatch, where only a rejected JSON file is at stake, asking whether the graph is well formed enough to be worth running. This component moves those checks to before dispatch, where the only thing at stake is a rejected JSON file. It asks one question. Is this campaign graph well formed enough to be worth running?

Reachability: a conclusion must trace to evidence

The key check is reachability: an acyclic, well-typed graph is still rejected when its synthesis traces back to no probe, so a conclusion must be traceable to gathered evidence. The check worth pausing on is reachability. An acyclic graph with valid node types can still be wrong: the single synthesis node might trace back only to a reducer with no probe behind it. That graph looks like a campaign but concludes over nothing the campaign actually gathered. The validator rejects it. A conclusion has to be traceable to evidence.

How it works

validate_campaign appends one decision per rule

validate_campaign takes a campaign mapping, provider, and worker count, then appends one decision per rule with no side effects, mirroring the private bridge contract's CR and VR families. validate_campaign does the work. It takes one campaign mapping plus a provider name, a worker count, and optional filesystem-preflight flags. It builds an empty ValidationResult and appends one decision per rule. It performs no side effects. The rule ids mirror the private bridge contract's CR and VR families, so this public component carries a faithful subset of the same checks without carrying the runtime.

The rules run in this order over one spec:

Rule groupWhat it checksRejects when
CR001-CR009envelope: schema_version is 1.0, kind is bridge_campaign, kebab-case campaign_id (via CAMPAIGN_ID_RE), non-empty intent, a public plan_path, barrier binding, and a bounded continuation packetany envelope field is missing or out of shape
CR010, CR015-CR020nodes: labels are unique and non-empty, every role is one of VALID_NODE_ROLES (probe, reducer, synthesis), input modes are known, and every depends_on entry names a real nodea role is unknown or a dependency points nowhere
CR011reducer and synthesis nodes each depend on at least one upstream nodea reducer or synthesis has no upstream
CR012the graph is acyclic, computed by _cycle_labelsany node sits on a dependency cycle
CR013, CR006there is exactly one synthesis node, and the barrier's group_label names itzero or many synthesis nodes, or a mismatched barrier
CR014the synthesis node transitively reaches at least one probe, computed by _reachable_dependenciessynthesis traces back to no probe
VR005the requested workers count is within the provider's ceiling in SAFE_PARALLELISMthe count exceeds the ceiling

Cycle, reachability, and parallelism helpers

_cycle_labels names the members of any cycle, _reachable_dependencies walks edges from the synthesis for CR014, and SAFE_PARALLELISM caps workers per provider for VR005. _cycle_labels runs a depth-first walk with a visiting set and returns the labels caught on a back-edge, so a cycle names its members rather than just failing. _reachable_dependencies walks depends_on edges transitively from the synthesis label; CR014 then checks whether any reached node has role probe. SAFE_PARALLELISM is a small fixed table: chatgpt 8, claude 2, gemini 3, local 4. A provider not in the table, or a worker count above its ceiling, fails VR005.

ValidationResult.add turns decisions into outcomes

ValidationResult.add makes a reject set ok false with an error line, a warn record a warning, and an ok just log, while to_dict serialises the whole result. ValidationResult.add is where a decision becomes an outcome: a reject sets ok to false and records a formatted error line, a warn records a warning, an ok just logs the decision. to_dict serialises the whole result for a machine reader.

Three file wrappers replay fixtures

Three wrappers add files: load_campaign reads one JSON object, validate_campaign_file checks a spec against its declared expectation, and validate_fixture_dir folds a directory into a pass matrix. The other three callables wrap this for files. load_campaign reads one JSON object off disk and rejects anything that is not an object. validate_campaign_file loads a spec, pulls its declared provider, workers, and expected_ok, runs validate_campaign, and returns a row recording whether the observed result matched the declared expectation. validate_fixture_dir runs that over every *.json in a directory and returns a matrix with status: pass only when every case met its declared expectation. main exposes both as the validate and validate-fixtures subcommands.

Diagram of the mechanism (7 steps).
rejectrejectrejectrejectCampaign JSON specCampaign JSON specvalidate_campaignenvelope + node rulesvalidate_campaign envelope + node rules_cycle_labelsacyclicity CR012_cycle_labels acyclicity CR012_reachable_dependenciessynthesis reaches probe CR014_reachable_dependencies synthesis reaches probe CR014SAFE_PARALLELISMprovider ceiling VR005SAFE_PARALLELISM provider ceiling VR005ValidationResultok = true, decisionsValidationResult ok = true, decisionsValidationResultok = falserule id + target + reasonValidationResult ok = false rule id + target + reason
Diagram source & refs
flowchart TD A["Campaign JSON spec"] --> B["validate_campaign envelope + node rules"] B --> C["_cycle_labels acyclicity CR012"] C --> D["_reachable_dependencies synthesis reaches probe CR014"] D --> E["SAFE_PARALLELISM provider ceiling VR005"] E --> F["ValidationResult ok = true, decisions"] B -.->|reject| R["ValidationResult ok = false rule id + target + reason"] C -.->|reject| R D -.->|reject| R E -.->|reject| R

Negative cases

Four public fixtures

The four public fixtures in fixtures/first_wave/engine_room_bridge_campaign_dag/input pin the behavior with three declared failures and one pass. The four public fixtures in fixtures/first_wave/engine_room_bridge_campaign_dag/input pin the behavior with three declared failures and one pass.

valid_three_probe_campaign is the passing fixture

The passing fixture wires three probes into one reducer and then one synthesis, requesting 3 chatgpt workers against a ceiling of 8. The pass, valid_three_probe_campaign, wires three probes (prover_probe, metabolism_probe, security_probe) into one engine_room_reducer and then one engine_room_synthesis, requesting 3 chatgpt workers against a ceiling of 8.

Cycle, ceiling, and dangling-synthesis rejections

The three failures reject a cycle through CR012, a 99-worker request through VR005, and a synthesis reaching no probe through CR014, with CR011 also firing. The cycle_rejected case makes probe_a depend on the synthesis node while the synthesis depends on probe_a, so _cycle_labels finds the loop and CR012 rejects it. The provider_ceiling_rejected case asks chatgpt for 99 workers, so VR005 rejects it against the ceiling of 8. The dangling_synthesis_rejected case points the synthesis at an empty_reducer with no probe behind it, so CR014 rejects it for reaching no probe (and CR011 also fires, since the reducer has no upstream).

Prior Art Grounding

Lineage in DAG workflow orchestration

The design follows workflow orchestration's typed directed-acyclic-graph tradition, borrowing acyclicity, evidence reachability, and provider-capacity ceilings as contract-layer checks run before any campaign executes. This component follows the workflow-orchestration tradition that models work as a directed acyclic graph with typed nodes, dependency edges, fan-in, and validation before execution. Apache Airflow DAGs group tasks into a directed acyclic graph with explicit dependencies checked before a run. BPMN and related notations separate control-flow structure from the concrete execution system. The borrowed pattern is narrow: acyclicity, evidence reachability, and provider-capacity ceilings are all checked at the contract layer, before any campaign runs.

Validation Result record Path

Run the focused tests and the corpus parity check:

PYTHONPATH=src ./repo-pytest tests/test_engine_room_bridge_campaign_dag.py -q
cd microcosm-substrate && PYTHONPATH=src ../repo-python scripts/build_doctrine_projection.py --check-paper-module-corpus

Or exercise the fixtures directly:

PYTHONPATH=src python3 -m microcosm_core.engine_room.bridge_campaign_dag validate-fixtures \
  --input fixtures/first_wave/engine_room_bridge_campaign_dag/input \
  --json

What a pass proves here

A pass means the four fixtures behaved exactly as declared and the generated projection is still reproducible from source, but it does not mean a campaign ran. A pass means the four fixtures behaved exactly as declared (status: pass, case_count: 4) and the generated bundle projection is still reproducible from source. It does not mean a campaign ran.

Scope boundary

Scope limit

The strongest honest claim

At most, given a typed campaign spec the component decides before dispatch whether the envelope, nodes, dependencies, acyclicity, synthesis binding, evidence reachability, and worker ceiling all hold. The strongest honest claim: given a typed campaign spec, this component decides before dispatch whether the graph has a valid envelope, unique and typed nodes, resolvable dependencies, no cycle, exactly one synthesis node bound to the barrier, a synthesis path that reaches a probe, and a worker count within the provider ceiling. The four fixtures show each rejection firing on a real malformed graph.

What validation still refuses

Beyond that it dispatches nothing, calls no provider, proves no reducer correct, and its ceiling table claims no live quota, provider-safety authority, or launch-scope decision. It refuses everything past that line. It does not dispatch agents, use external model services, run reducers or synthesis, or prove that a reducer or synthesis is correct. Its provider ceiling is a small local table, not live quota or provider-safety authority. It is staged under Engine Room paths and is not an accepted standalone component. The proof boundary is the fixture run and the focused tests; the scope limit stops at graph-shape validation and claims no equivalence to the private bridge runtime and no launch-scope decision.

Context & evidence

Source

Source Source module: src/microcosm_core/engine_room/bridge_campaign_dag.py · Source module: src/microcosm_core/engine_room/demo.py · Design note · Source registry