Skip to content

Cascade merge engine

What it does: Merges org floor → project floor → agent overrides via strictest-wins; rejects relaxations of higher floors.

For a customer with 5 teams shipping 30 agents, the architecture works only if multiple operators can each author policy at their level without stepping on each other. Org admins author the floor; project admins add stricter rules within their project; agent owners scope per-agent. This component is the engine that merges those layers correctly — strictest wins, never weakens.

It's the algorithmic core of architecture §6 (the cascade) — small in code (~80 LOC), large in implication.

Pure function: merge(org, project, agent) -> merged + provenance. Reuses merge primitives from intent-to-policy substrate (live on main); adds floor-violation detection.

Lives at tappass/policy/cascade/. Reuses _merge_step, _merge_constraint from intent-to-policy resolver. New: validate_does_not_relax(floor, candidate) raises CascadeViolationError on attempted weakening.

  • All acceptance_criteria pass.
  • Property tests: 1000 random (org, project, agent) triples preserve order independence.
  • Violation tests: every type of relaxation attempt rejected with clear error message including the offending rule + which higher level imposed it.

With policy-to-sandbox-config-builder: the builder calls us. We are a pure function (no DB, no audit emit) so the builder owns persistence.

With intent-to-policy substrate: we extend their merge logic with cascade-level awareness. Coordinate to avoid duplicate merge code paths.

  • Authoring policies at any level (intent-to-policy + UI).
  • Persisting cascade levels (covered by projects-teams substrate + policy_store).
  • RBAC: who is allowed to author at which level (projects-teams-concept.md).