Bridge Campaign DAG Validation
The bridge campaign DAG validation component surfaces the public bridge_campaign_dag bundle and checks, over bounded public fixtures, that a fan-in campaign graph is well formed: unique labels, existing dependency edges, acyclicity, exactly one synthesis reaching a probe, barrier alignment, and a worker count within the provider safe-parallelism ceiling.
The write-up
Bridge campaign fans
A bridge campaign fans parallel reads into one synthesis step, and this component recomputes the plan's structure to accept or reject it before anything runs, never dispatching or executing. A bridge campaign is a small plan that fans several parallel reads into one synthesis step. This component reads such a plan and decides whether it is well formed before anything runs. It does not dispatch agents and it does not execute the campaign. It reads the plan, recomputes its structure, and returns an accept or reject decision with the rule id that fired.
Result is metadata-only
The result is a metadata-only record of status, per-case rows, and rejecting rule ids, accepting two clean plans and rejecting two broken ones over the shipped fixtures. The result is a metadata-only record: a status, per-case rows, and the rule ids that rejected each malformed plan. Over the shipped fixtures it accepts two clean plans and rejects two broken ones.
Purpose
Late structural faults waste a whole run
A structurally broken campaign is expensive to discover late, so the honest question is which rule fired rather than trusting an ok field that can lie. A structurally broken campaign is expensive to discover late. A dependency loop, two synthesis steps, or a step that depends on a name that does not exist will each waste a whole run before the fault surfaces. Trusting a plan because it carries an "ok" field does not help: the field can lie. The honest question is "which rule fired," not "is the plan valid."
Recomputing the graph from the plan
The check recomputes the graph from the plan itself, deriving cycles, single-synthesis, and reaches-a-probe from node roles rather than a summary, so passing requires every recomputed rule to hold. So the check recomputes the graph from the plan itself. Cycle detection runs over the declared edges. Single-synthesis and reaches-a-probe are derived from the node roles and dependencies, not read from a summary. A malformed plan cannot pass, because passing requires every recomputed rule to hold.
How it works
Validator bundle and component runner
Two source files carry the mechanism: the engine bundle bridge_campaign_dag.py is the validator, and the component runner drives it over the fixtures and writes the records. Two source files carry the mechanism. The engine bundle src/microcosm_core/engine_room/bridge_campaign_dag.py is the validator. The component runner src/microcosm_core/organs/bridge_campaign_dag_validation.py drives it over the fixtures and writes the records.
validate_campaign conjoins every rule outcome
validate_campaign builds a ValidationResult and adds each rule's outcome, where any reject flips ok false, so the final ok is the conjunction of every CR/VR rule. validate_campaign takes one plan, a provider name, and a worker count. It builds a ValidationResult and calls result.add(rule_id, outcome, target, message) for each rule. An outcome of reject flips ok to false and appends the formatted decision to the error list, so the final ok is the conjunction of every rule. The rule families mirror the private source CR/VR ids over a subset:
| Rule | Check |
|---|---|
| CR001 to CR005 | schema version, kind, kebab-case campaign_id, intent, and a public plan_path |
| CR017 | node labels are unique and non-empty |
| CR015, CR016, CR020 | known input_mode, a rationale when the mode is not result records-only, a valid role |
| CR010, CR011 | every depends_on names a real node; reducer and synthesis nodes depend on something |
| CR012 | the node graph is acyclic |
| CR013, CR006, CR014 | exactly one synthesis node; the barrier names it; it transitively reaches a probe |
| CR007 to CR009 | barrier description, continuation packet schema, bounded next action |
| VR005 | requested workers stay within the provider ceiling |
Cycle detection, reachability, and worker caps
_cycle_labels marks cycles with a depth-first back-edge check, _reachable_dependencies walks the closure from the synthesis node for CR014, and VR005 caps workers per provider via SAFE_PARALLELISM. Cycle detection lives in _cycle_labels. It runs a depth-first walk with a visiting set and a visited set; a back-edge into a node still on the stack marks a cycle. _reachable_dependencies walks the dependency closure from the single synthesis node so CR014 can ask whether any reachable node is a probe. VR005 reads SAFE_PARALLELISM, which caps workers per provider: chatgpt 8, claude 2, gemini 3, local 4.
The runner turns fixtures into records
The runner loads each fixture, evaluates it against validate_campaign, and aggregates a pass only when every positive validated, every negative was rejected as expected, and both planted ids fired. The runner turns fixtures into records. _fixture_cases loads every JSON file under the input directory. _evaluate_case calls validate_campaign for one case, reads the reject rule ids with _reject_codes, and decides observed_ok. A positive case passes when the plan validated and matched its expected_ok. A negative case passes only when the plan was rejected and its expected rule ids from EXPECTED_NEGATIVE_CASES are among the firing rejections. build_result aggregates the rows: the overall status is pass only if there is at least one positive and one negative case, all positive cases validated, all negative cases were rejected as expected, and both planted negative ids are present. run writes the result, a compact card from result_card, and a validation record, each with body_in_receipt set to false.
Diagram source & refs
flowchart TD Spec["Campaign plan nodes, deps, barrier, provider, workers"] Identity["Identity and schema CR001 to CR005"] Labels["Unique labels, roles, real dependency edges"] Cycle["Acyclicity CR012 depth-first"] Synth["One synthesis reaches a probe, CR013 CR014"] Ceiling["Worker ceiling VR005"] Verdict["Accept or reject with the rule id"] Spec --> Identity --> Labels --> Cycle --> Synth --> Ceiling --> VerdictNegative cases
Two planted rejections and two clean plans
The fixtures plant cycle_rejected firing CR012 and two_synthesis_rejected firing CR013 against two clean plans, and a rejection counts only when it names the exact rule it broke. The fixtures plant two malformed plans, both rejected by recomputation. cycle_rejected has a dependency loop and must fire CR012. two_synthesis_rejected declares two synthesis nodes and must fire CR013. The two accepted plans are linear_chain_ok, a probe to reducer to synthesis chain, and fan_in_ok, three probes into one reducer into one synthesis. A negative case counts as handled only when the plan was rejected and its named rule id appears in the rejections, so a rejection always names the rule it broke.
Prior Art Grounding
Ordinary graph engineering and the coverage contract
The engine bundle is a source-faithful refactor of ordinary graph engineering, claiming no external citation, its local prior art being the Plectis coverage contract requiring a scope limit and result record path. The engine bundle is a source-faithful public refactor of the private bridge campaign contract layer and its provider ceiling rule. The lineage is ordinary software engineering: schema validation, depth-first cycle detection on a directed graph, reachability over a dependency closure, and fixture-scoped regression cases. No external citation is claimed. The local prior art is the Plectis coverage contract, which requires each reader page to publish a scope limit, a grounding note, and a result record path rather than letting a generated structured source record stand in for the source.
Validation Result record Path
Run the component over its fixtures and write the records:
What a pass means and how to confirm
A pass means both clean plans validated and both broken plans were rejected with their expected rule ids, confirmed against the bundle by the coverage contract and corpus check. A pass means both clean plans validated and both broken plans were rejected with their expected rule ids. From the repository root, the coverage contract and the paper-module corpus check confirm this page against its bundle:
PYTHONPATH=src ./repo-pytest tests/test_plectis_paper_module_coverage_contract.py -q --tb=short
PYTHONPATH=src ./repo-python scripts/build_doctrine_projection.py --check-paper-module-corpus
Scope boundary
Scope limit
Proof boundary and scope limit
A green run shows well-formed plans validated and malformed ones rejected with the rule they broke over bounded fixtures, while the component neither dispatches, executes, nor authorizes launch. A green run shows that well-formed plans validated and malformed ones were rejected, each with the rule it broke, over the bounded public fixtures in this checkout. That is the strongest claim here, and it is the proof boundary. The scope limit: this component does not dispatch agents, execute campaigns, prove provider correctness or safety, or claim whole-system equivalence. It excludes launch, public sharing, external model access, or source-file changes. It reads a plan and returns a decision.
Context & evidence
In short Bridge Campaign DAG Validation is the public agent-orchestration replay for a fan-in campaign graph. It validates each campaign spec against a subset of the source CR/VR rule families: schema and identity, unique node labels, dependency edges that reference existing nodes, DFS acyclicity, exactly one synthesis node that reaches a probe, a barrier naming that synthesis, and a requested worker count within the provider safe-parallelism ceiling. It accepts a linear chain and a three-way fan-in, and self-falsifies: a cyclic campaign is rejected with CR012 and a two-synthesis campaign with CR013. It writes metadata-only result records and surfaces microcosm_core.engine_room.bridge_campaign_dag without dispatching agents or calling providers.
Scope limit Public fixture and result record evidence only; it validates campaign DAG structure and does not dispatch agents, execute campaigns, prove provider correctness or safety, and is not launch-scope decision or publishing-scope decision.
Covers Bridge Campaign DAG Validation
Source
Source Source module: src/microcosm_core/organs/bridge_campaign_dag_validation.py · Source module: src/microcosm_core/engine_room/bridge_campaign_dag.py · Design note · Source registry