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.
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 group | What it checks | Rejects when |
|---|---|---|
CR001-CR009 | envelope: 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 packet | any envelope field is missing or out of shape |
CR010, CR015-CR020 | nodes: 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 node | a role is unknown or a dependency points nowhere |
CR011 | reducer and synthesis nodes each depend on at least one upstream node | a reducer or synthesis has no upstream |
CR012 | the graph is acyclic, computed by _cycle_labels | any node sits on a dependency cycle |
CR013, CR006 | there is exactly one synthesis node, and the barrier's group_label names it | zero or many synthesis nodes, or a mismatched barrier |
CR014 | the synthesis node transitively reaches at least one probe, computed by _reachable_dependencies | synthesis traces back to no probe |
VR005 | the requested workers count is within the provider's ceiling in SAFE_PARALLELISM | the 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 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| RNegative 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
In short Engine Room Bridge Campaign DAG binds the staged pre-dispatch campaign validator to the accepted Engine Room demo mechanism. It validates typed probe/reducer/synthesis graphs, rejects cycles, requires synthesis nodes to trace back to probe evidence, checks provider parallelism ceilings, and emits public fixture result records without dispatching providers or proving campaign execution safety.
Scope limit Component evidence for the accepted staged Engine Room demo only; no external model access, campaign execution, reducer or synthesis correctness proof, provider safety proof, launch-scope decision, whole-system equivalence, source-file changes, or whole-system correctness.
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