KB-7E06
O8A live-execution wiring authoring (Contabo) — 03-live-adapter-design-lock
5 min read Revision 1
dieu44iu-cutterv0.6o8alive-execution-wiringauthoringsandbox-proofcontabo
O8A Report 03 — Live-adapter design lock
- macro:
v0.6-o8a-live-execution-wiring-authoring - date_utc: 2026-05-21 · host:
vmi3080463(Contabo) - gate covered: G2 live-adapter design lock
1. Adapter interface — the seam
New module cutter_agent/orchestrator/live_execution.py defines
LiveExecutionAdapter (ABC) — one method per mutating phase:
class LiveExecutionAdapter(abc.ABC):
name: str
def pre_write_backup(ctx) -> BackupResult
def cut_leg_a(ctx, *, change_set_id, cutplan_rows) -> list[IUCreateResult]
def leg_b_record(ctx, *, change_set_id) -> LegBResult
def verify_result_count_for(ctx, *, change_set_id) -> int
def write_verify(ctx, *, change_set_id) -> VerifyResult
def lifecycle_enact(ctx, *, addresses, review_decision_id,
change_set_id) -> EnactBatchResult
Result value objects (BackupResult, LegBResult, VerifyResult,
EnactBatchResult) are frozen dataclasses; cut_leg_a returns the same
IUCreateResult type the simulator returns, so phase post-processing is
mode-agnostic.
2. Transaction boundary
- One transaction per phase. Each adapter method opens exactly one
txn (
conn.execute("BEGIN")), does all its work, thenCOMMIT. - Atomic, all-or-nothing. Any error inside the txn ⇒
ROLLBACK+ re-raise (_safe_rollback); never a partial write (v0.5 G6 doctrine). - Caller-owned. The adapter — not the v0.5 recorder classes — owns
BEGIN/COMMIT/ROLLBACK, exactly as
prod_iu_adapter_canonicalrequires. cut_leg_a/lifecycle_enactfan out NSELECT fn_iu_create(...)/fn_iu_enact(...)calls inside the single txn; one bad status ⇒ whole batch rolls back.
3. Dry-run vs live separation
mutating phase body:
refuse_if_killswitch_off(ctx, phase) # 1. kill-switch gate
... approval / pin checks ...
if ctx.mode == Mode.LIVE:
adapter = require_live_adapter(db_provider, phase) # 2. adapter or refuse
result = adapter.<phase>(ctx, ...) # 3. LIVE → adapter
else: # Mode.DRYRUN
result = discoverer.simulate_<phase>(...) # DRYRUN → simulator
The simulator is reachable only on the Mode.DRYRUN branch.
Mode.LIVE reaches the adapter or fails closed — it can never fall
through to the simulator.
4. Kill-switch enforcement
Three independent locks, all reading the switch dynamically:
execution_enabled()— a function inorchestrator/__init__.py(replaces value-import of__execution_enabled__), evaluated at call time. Backing constant staysFalse.refuse_if_killswitch_off(ctx, phase)— every mutating phase calls it first;Mode.LIVE+ switch OFF ⇒ProductionExecutionNotAuthorized.ProductionLiveExecutionAdapter._assert_live_allowed— defence in depth: the adapter re-checks the switch even if a caller bypassed the phase guard.
The runner's cut() also gates Mode.LIVE: kill-switch first, then a
mandatory LiveExecutionAdapter wired as db_provider.
5. Role / credential expectation (no secret logging)
ProductionLiveExecutionAdapterconstruction never connects.- DB access via an injected
connection_provider(role) -> conn; roles arecutter_exec(cut/leg-B/enact) andcutter_verify(verify). - Backup via an injected
backup_runner(spec) -> dict. - The default collaborators all REFUSE (
ProductionExecutionNotAuthorized) — no DSN, no.env, no GPG key, no secret at module scope (mirrorsprod_iu_adapter_canonical._default_provider). - Env-var / role names may appear; values never are.
6. Rollback / compensation hooks
- Per-phase txn rollback on any error (
_safe_rollback). cut_leg_a/lifecycle_enact: a single non-created/ non-enactedstatus raises → whole batch ROLLBACK.pre_write_backupruns before any DB write — the fresh backup is the cross-phase compensation anchor.- A torn live run escalates via
SG_3to a separate sovereign compensation macro (unchanged orchestrator doctrine).
7. Design-lock verdict
G2_live_adapter_design_lock: PASS
interfaces: LiveExecutionAdapter ABC (6 methods) + 4 result types
txn_boundary: one atomic txn per phase; rollback on any error
dryrun_vs_live: simulator on Mode.DRYRUN only; never on Mode.LIVE
kill_switch: execution_enabled() fn + 3 enforcement locks
credentials: injected collaborators; defaults refuse; no secrets
production_enabled: NO — execution_enabled stays False