{
  "schema_version": "1.0.0",
  "bot_id": "2.9",
  "bot_name": "CancelReplaceOptimizer",
  "slug": "cancelreplaceoptimizer",
  "layer": "Execution",
  "layer_key": "exec",
  "bot_class": "Execution Utility",
  "authority": [
    "Reshape"
  ],
  "status": "planned",
  "readiness": "Spec started",
  "flagship": false,
  "is_reference": false,
  "public_export": false,
  "identity": {
    "layer": "Execution",
    "bot_class": "Execution Utility",
    "authority": "Reshape",
    "runs_before": "Order signing and CLOB V2 submission",
    "runs_after": "PartialFillHandler or strategy-driven requote signal",
    "applies_to": "Any request to modify a resting order's price or size",
    "default_mode": "shadow_only",
    "user_visible": "summary-only",
    "developer_owner": "Polytraders core \u2014 Execution pod"
  },
  "purpose": "CancelReplaceOptimizer selects the cheapest path to modify a resting order: amend-in-place if queue priority is preserved, or cancel-then-replace if the delta exceeds the amend threshold. It enforces rate-limit budgets across cancel and amend operations.",
  "why_it_matters": [
    {
      "failure": "Always using cancel-then-replace",
      "consequence": "Loses queue position on every requote, resulting in consistently worse fills on passive strategies where queue position matters."
    },
    {
      "failure": "Amend threshold set too wide",
      "consequence": "Large price changes that would trigger queue-position loss are processed as amends, causing the strategy to hold a stale order at a position that was meant to be cancelled."
    },
    {
      "failure": "Rate limit not enforced across cancels",
      "consequence": "A burst of cancel-replace operations hits the CLOB V2 rate limit, causing 429 errors and leaving orders unmodified at stale prices."
    }
  ],
  "polymarket_inputs": [
    {
      "input": "CLOB V2 amend endpoint semantics",
      "source": "clob_auth",
      "required": true,
      "use": "Determine whether amend preserves queue priority for the given price/size delta."
    },
    {
      "input": "Market tick size",
      "source": "clob_public",
      "required": true,
      "use": "Compute tick distance between current and target price for amend vs. cancel-replace decision."
    }
  ],
  "internal_inputs": [
    {
      "input": "Requote instruction with current order_id, target price, target size",
      "source": "exec.partialfillhandler or strat layer",
      "required": true,
      "use": "Receive the requested modification and current order parameters."
    },
    {
      "input": "Rate-limit budget state",
      "source": "internal rate-limit tracker",
      "required": true,
      "use": "Check remaining cancel and amend budget before issuing operations."
    }
  ],
  "raw_params": [
    "amend_threshold_ticks \u00b7 int",
    "preserve_queue_when_possible \u00b7 bool",
    "burst_max_per_s \u00b7 int",
    "fallback_strategy \u00b7 enum"
  ],
  "parameters": [
    {
      "name": "amend_threshold_ticks",
      "default": 2,
      "warning": 4,
      "hard": 8,
      "controls": "Maximum tick distance between current and target price for which an amend-in-place is preferred over cancel-then-replace.",
      "why_default_matters": "Amending within 2 ticks typically preserves queue priority on CLOB V2; larger moves force a queue-position reset anyway.",
      "threshold_logic": [
        {
          "condition": "delta_ticks <= 2",
          "action": "Amend in place (queue priority preserved)"
        },
        {
          "condition": "2 < delta_ticks <= 4",
          "action": "WARN \u2014 amend may lose queue priority; proceed"
        },
        {
          "condition": "delta_ticks > 8 (hard)",
          "action": "Always cancel-then-replace; CANCEL_REPLACE_FORCED"
        }
      ],
      "dev_check": "if deltaTicks > params.amend_threshold_ticks: cancelReplace(order)",
      "user_facing": "Your order was adjusted to improve your position in the market."
    },
    {
      "name": "preserve_queue_when_possible",
      "default": true,
      "warning": "\u2014",
      "hard": "\u2014",
      "controls": "Prefer amend-in-place over cancel-then-replace whenever the CLOB V2 amend semantics permit queue priority to be preserved.",
      "why_default_matters": "Preserving queue position is generally better for passive strategies; only disable if the strategy always wants a fresh queue position.",
      "threshold_logic": [
        {
          "condition": "preserve_queue=true AND delta within threshold",
          "action": "Amend in place"
        },
        {
          "condition": "preserve_queue=false",
          "action": "Always cancel-then-replace regardless of delta"
        }
      ],
      "dev_check": "if not params.preserve_queue_when_possible: cancelReplace(order)",
      "user_facing": "Your order's position in the queue was preserved where possible."
    },
    {
      "name": "burst_max_per_s",
      "default": 10,
      "warning": 15,
      "hard": 20,
      "controls": "Maximum number of cancel or amend operations per second across all orders.",
      "why_default_matters": "CLOB V2 rate limits restrict cancel/amend to ~20/s; staying at 10/s leaves budget for other exec operations.",
      "threshold_logic": [
        {
          "condition": "ops_per_s <= 10",
          "action": "Normal"
        },
        {
          "condition": "10 < ops_per_s <= 15",
          "action": "WARN \u2014 approaching rate limit"
        },
        {
          "condition": "ops_per_s > 20 (hard)",
          "action": "Shed requests; CANCEL_REPLACE_RATE_LIMIT_SHED"
        }
      ],
      "dev_check": "if opsThisSecond > params.burst_max_per_s: shedRequest()",
      "user_facing": "Order updates were briefly delayed to stay within exchange limits."
    },
    {
      "name": "fallback_strategy",
      "default": "cancel_replace",
      "warning": "\u2014",
      "hard": "\u2014",
      "controls": "Fallback when amend endpoint is unavailable: cancel_replace (issue cancel then new order) or hold (leave resting, no modification).",
      "why_default_matters": "cancel_replace is always possible when amend is unavailable; hold risks leaving a stale order.",
      "threshold_logic": [
        {
          "condition": "amend unavailable AND fallback=cancel_replace",
          "action": "Cancel and resubmit new order"
        },
        {
          "condition": "amend unavailable AND fallback=hold",
          "action": "Leave order resting; emit WARN"
        }
      ],
      "dev_check": "if amendFailed: cancelReplace(order) if params.fallback_strategy == 'cancel_replace'",
      "user_facing": "Your order was updated using an alternative method to keep it competitive."
    }
  ],
  "default_config": {
    "bot_id": "exec.cancelreplaceoptimizer",
    "version": "0.1.0",
    "mode": "shadow_only",
    "defaults": {
      "amend_threshold_ticks": 2,
      "preserve_queue_when_possible": true,
      "burst_max_per_s": 10,
      "fallback_strategy": "cancel_replace"
    },
    "locked": {
      "amend_threshold_ticks": {
        "max": 8
      },
      "burst_max_per_s": {
        "max": 20
      }
    }
  },
  "implementation_flow": [
    "Receive requote instruction: {order_id, current_price, target_price, target_size, market_id}.",
    "Fetch tick size from clob_public; compute delta_ticks = abs(target_price - current_price) / tick_size.",
    "Check rate-limit budget; if burst_max_per_s exceeded, shed request and emit CANCEL_REPLACE_RATE_LIMIT_SHED.",
    "If preserve_queue_when_possible and delta_ticks <= amend_threshold_ticks: attempt amend via clob_auth PATCH /order/{id}.",
    "If amend succeeds: emit ExecutionReport(AMEND_IN_PLACE); done.",
    "If amend fails or delta_ticks > amend_threshold_ticks: cancel via clob_auth DELETE /order/{id}; submit new order at target_price/target_size.",
    "Emit ExecutionReport with path_taken (amend or cancel_replace), delta_ticks, and rate_limit_budget_remaining."
  ],
  "decision_logic": {
    "approve": "Amend succeeds within amend_threshold_ticks; queue priority preserved.",
    "reshape_required": "Cancel-then-replace path: order modified at cost of queue priority.",
    "reject": "Rate limit budget exhausted; request shed. Or KillSwitch active.",
    "warning_only": "delta_ticks between warning and hard threshold; WARN emitted but amend proceeds."
  },
  "decision_output_schema": "ExecutionReport",
  "decision_output_example": {
    "report_id": "rep_4d5e6f7a8b9c0d1e",
    "trace_id": "trc_3c4d5e6f7a8b9c0d",
    "bot_id": "exec.cancelreplaceoptimizer",
    "order_id": "0xdddd4444eeee5555ffff6666aaaa7777bbbb8888cccc9999dddd0000eeee1111",
    "path_taken": "amend_in_place",
    "delta_ticks": 1,
    "original_price": 0.62,
    "target_price": 0.63,
    "collateral": "pUSD",
    "builder_code": "0x706f6c7974726164657273000000000000000000000000000000000000000000",
    "evaluated_at_ms": 1746770200000
  },
  "developer_log": {
    "order_id": "0xdddd4444eeee5555ffff6666aaaa7777bbbb8888cccc9999dddd0000eeee1111",
    "delta_ticks": 1,
    "amend_threshold_ticks": 2,
    "path_taken": "amend_in_place",
    "rate_limit_budget_remaining": 8,
    "amend_success": true
  },
  "user_explanations": [
    {
      "situation": "Order amended in place",
      "message": "Your order was updated to a new price while keeping its place in the queue."
    },
    {
      "situation": "Order cancelled and resubmitted",
      "message": "Your order price changed by more than a small amount, so it was cancelled and a new order was submitted."
    },
    {
      "situation": "Order update delayed \u2014 rate limit",
      "message": "Your order update was briefly delayed because the exchange has a limit on how many changes can be made per second."
    }
  ],
  "failure_modes": {
    "main_failure_mode": "Amend endpoint returns success but CLOB V2 actually cancels and recreates the order (losing queue position), causing the strategy to believe queue was preserved when it was not.",
    "false_positive_risk": "Amending within the tick threshold when the book has moved and queue position is already lost anyway, wasting an amend operation.",
    "false_negative_risk": "Always cancelling-and-replacing when amend would have preserved queue priority, causing systematic queue-position loss on passive strategies.",
    "safe_fallback": "If amend endpoint returns error, fall back to cancel-then-replace per fallback_strategy config. If both fail, emit WARN and leave order resting.",
    "required_dependencies": [
      "clob_auth amend/cancel endpoints",
      "clob_public tick size",
      "rate-limit budget tracker"
    ]
  },
  "acceptance_tests": {
    "unit": [
      {
        "test": "Amend chosen when delta_ticks <= amend_threshold_ticks",
        "setup": "delta_ticks=1, amend_threshold_ticks=2",
        "expected": "path_taken=amend_in_place"
      },
      {
        "test": "Cancel-replace when delta_ticks > amend_threshold_ticks",
        "setup": "delta_ticks=5, amend_threshold_ticks=2",
        "expected": "path_taken=cancel_replace"
      },
      {
        "test": "Rate-limit shed when burst_max_per_s exceeded",
        "setup": "ops_this_second=11, burst_max_per_s=10",
        "expected": "CANCEL_REPLACE_RATE_LIMIT_SHED; request dropped"
      }
    ],
    "integration": [
      {
        "test": "Amend endpoint failure \u2192 fallback to cancel-replace",
        "expected": "clob_auth PATCH returns 4xx; fallback cancel+resubmit executed; ExecutionReport path_taken=cancel_replace"
      },
      {
        "test": "Sequential amends within rate budget",
        "expected": "All amends processed within burst_max_per_s; no shedding"
      }
    ],
    "property": [
      {
        "property": "path_taken is always either amend_in_place or cancel_replace \u2014 never both",
        "required": "Always true"
      },
      {
        "property": "Target order price after modification always equals target_price rounded to tick_size",
        "required": "Always true"
      }
    ]
  },
  "checklist_overrides": {},
  "legacy_goal": "Choose the cheapest path between cancel-then-replace and amend-in-place.",
  "legacy_pm_signals": [
    "CLOB V2 amend semantics: queue-priority preserved or lost",
    "Distance between current and target price/size",
    "Rate-limit budget remaining for cancels vs. amends"
  ],
  "legacy_external_feeds": [],
  "reporting_groups": [
    "execution"
  ],
  "network": [
    "polygon"
  ],
  "api_surface": [
    "clob_auth",
    "clob_public",
    "internal"
  ],
  "version": {
    "spec": "2.0.0",
    "implementation": "0.1.0",
    "schema": "2",
    "released": null,
    "planned_release": "Q4-2026"
  },
  "migration_history": [
    {
      "date": "2026-04-28",
      "from": "n/a",
      "to": "v2-spec",
      "reason": "Spec drafted post-CLOB-V2 cutover; bot not yet implemented",
      "action_taken": "Designed against V2 schema (pUSD, builder codes, V2 EIP-712 domain)"
    }
  ],
  "polymarket_v2_compat": {
    "clob_version": "v2",
    "collateral": "pUSD",
    "eip712_domain_version": "2",
    "builder_code_aware": true,
    "negrisk_aware": false,
    "multichain_ready": false,
    "sdk_used": "py-clob-client-v2",
    "settlement_contract": "CTFExchangeV2",
    "notes": "Replacement orders carry the same builder_code bytes32 for continuous attribution. CLOB V2 amend semantics differ from V1; queue-priority preservation must be verified per V2 API docs."
  },
  "reference_implementation": {
    "pseudocode": "FUNCTION optimizeCancelReplace(instruction):\n  // 1. Fetch tick size\n  market = FETCH clob_public.GET('/markets/' + instruction.market_id)\n  tickSize = market.minimum_tick_size\n  deltaTicks = abs(instruction.target_price - instruction.current_price) / tickSize\n\n  // 2. Rate limit check\n  IF rateLimiter.opsThisSecond >= params.burst_max_per_s:\n    EMIT ExecutionReport(CANCEL_REPLACE_RATE_LIMIT_SHED, WARN)\n    RETURN\n\n  // 3. Decide path\n  IF params.preserve_queue_when_possible\n     AND deltaTicks <= params.amend_threshold_ticks:\n    // Attempt amend\n    result = clob_auth.PATCH('/order/' + instruction.order_id,\n                              {price: instruction.target_price,\n                               size: instruction.target_size})\n    IF result.ok:\n      EMIT ExecutionReport(AMEND_IN_PLACE)\n      RETURN\n    // Amend failed \u2014 fall through to cancel-replace\n\n  // 4. Cancel-then-replace\n  clob_auth.DELETE('/order/' + instruction.order_id)\n  newOrder = buildOrderTypedData({\n    price: instruction.target_price,\n    size: instruction.target_size,\n    builder: instruction.builder_code,\n    timestamp: now_ms()\n  })\n  clob_auth.POST('/order', sign(newOrder))\n  EMIT ExecutionReport(CANCEL_REPLACE_EXECUTED)",
    "sdk_calls": [
      "clob_public.GET('/markets/' + market_id)",
      "clob_auth.PATCH('/order/' + order_id, {price, size})",
      "clob_auth.DELETE('/order/' + order_id)",
      "clob_auth.POST('/order', signed_new_order)",
      "buildOrderTypedData({price, size, builder_code, timestamp})"
    ],
    "complexity": "O(1) per requote instruction"
  },
  "wire_examples": {
    "input": [
      {
        "label": "Requote instruction",
        "source": "exec.partialfillhandler",
        "payload": {
          "order_id": "0xdddd4444eeee5555ffff6666aaaa7777bbbb8888cccc9999dddd0000eeee1111",
          "market_id": "0x1a2b3c4d5e6f7a8b9c0d1e2f3a4b5c6d7e8f9a0b1c2d3e4f5a6b7c8d9e0f1a2b",
          "current_price": 0.62,
          "target_price": 0.63,
          "target_size_usd": 250,
          "builder_code": "0x706f6c7974726164657273000000000000000000000000000000000000000000",
          "collateral": "pUSD"
        }
      }
    ],
    "output": [
      {
        "label": "ExecutionReport \u2014 amend in place",
        "payload": {
          "report_id": "rep_4d5e6f7a8b9c0d1e",
          "bot_id": "exec.cancelreplaceoptimizer",
          "path_taken": "amend_in_place",
          "delta_ticks": 1,
          "original_price": 0.62,
          "target_price": 0.63,
          "collateral": "pUSD",
          "evaluated_at_ms": 1746770200000
        }
      }
    ]
  },
  "reason_codes": [
    {
      "code": "AMEND_IN_PLACE",
      "severity": "INFO",
      "meaning": "Order amended without cancelling; queue priority preserved.",
      "action": "Emit ExecutionReport; no further action.",
      "user_message": ""
    },
    {
      "code": "CANCEL_REPLACE_EXECUTED",
      "severity": "INFO",
      "meaning": "Order cancelled and resubmitted at new price/size.",
      "action": "Emit ExecutionReport.",
      "user_message": "Your order was updated to a new price."
    },
    {
      "code": "CANCEL_REPLACE_FORCED",
      "severity": "RESHAPE",
      "meaning": "Delta exceeds amend_threshold_ticks; cancel-replace forced.",
      "action": "Cancel and resubmit.",
      "user_message": "Your order price changed significantly and was resubmitted."
    },
    {
      "code": "CANCEL_REPLACE_RATE_LIMIT_SHED",
      "severity": "WARN",
      "meaning": "burst_max_per_s exceeded; request shed.",
      "action": "Drop request; emit WARN; retry on next tick.",
      "user_message": "Your order update was briefly delayed."
    },
    {
      "code": "KILL_SWITCH_ACTIVE",
      "severity": "HARD_REJECT",
      "meaning": "KillSwitch active; no cancel or amend operations.",
      "action": "Halt all operations.",
      "user_message": "Trading is currently paused."
    }
  ],
  "metrics": {
    "emitted": [
      {
        "name": "polytraders_exec_cancelreplaceoptimizer_ops_total",
        "type": "counter",
        "unit": "count",
        "labels": [
          "path_taken"
        ],
        "meaning": "Total cancel-replace operations by path (amend_in_place vs cancel_replace)."
      },
      {
        "name": "polytraders_exec_cancelreplaceoptimizer_delta_ticks",
        "type": "histogram",
        "unit": "count",
        "labels": [],
        "meaning": "Distribution of price delta in ticks on each requote instruction."
      },
      {
        "name": "polytraders_exec_cancelreplaceoptimizer_rate_limit_sheds_total",
        "type": "counter",
        "unit": "count",
        "labels": [],
        "meaning": "Total requests shed due to burst_max_per_s rate limit."
      }
    ],
    "alerts": [
      {
        "name": "CROHighRateLimitShed",
        "condition": "rate(polytraders_exec_cancelreplaceoptimizer_rate_limit_sheds_total[1m]) > 1",
        "severity": "P2",
        "runbook": "#runbook-cro-rate-limit"
      },
      {
        "name": "CROHighDeltaTicks",
        "condition": "histogram_quantile(0.95, rate(polytraders_exec_cancelreplaceoptimizer_delta_ticks_bucket[5m])) > 5",
        "severity": "P3",
        "runbook": "#runbook-cro-delta-ticks"
      }
    ]
  },
  "state": {
    "store": "in-memory rate-limit counter (rolling 1s window) + Redis for cross-instance coordination",
    "shape": "ops_this_second counter keyed by instance_id; amend success/failure stats per market_id",
    "ttl": "Rate counter resets every second; per-market stats TTL = 300s",
    "recovery": "Rate counter resets on restart; conservative: assume full burst budget used until first tick completes.",
    "size_estimate": "~50 bytes for rate counter; ~1 KB for per-market stats on 20 markets"
  },
  "concurrency": {
    "execution_model": "single-threaded rate-gated queue",
    "max_in_flight": 20,
    "idempotency_key": "order_id + target_price + target_size",
    "timeout_ms": 500,
    "backpressure": "Shed excess beyond burst_max_per_s; WARN emitted",
    "locking": "per-instance atomic counter for rate limiting"
  },
  "dependencies": {
    "depends_on": [
      {
        "bot_id": "exec.partialfillhandler",
        "why": "Primary source of requote instructions for partial remainder chasing.",
        "contract": "Receives cancel+new instruction; executes optimal path."
      }
    ],
    "emits_to": [
      {
        "bot_id": "gov.builder_attribution",
        "why": "Every new replacement order carries builder_code for attribution logging.",
        "contract": "builder_code bytes32 present on every signed replacement order."
      }
    ],
    "sibling": [],
    "external": [
      {
        "service": "CLOB V2 auth API",
        "endpoint": "https://clob.polymarket.com",
        "sla": "99.95% / 200ms p99",
        "failure_mode": "Retry amend once; fall back to cancel-replace; emit WARN on persistent failure."
      },
      {
        "service": "CLOB V2 public API",
        "endpoint": "https://clob.polymarket.com",
        "sla": "99.9% / 200ms p99",
        "failure_mode": "If tick size unavailable, use last-known tick size; emit WARN."
      }
    ]
  },
  "security_surfaces": {
    "signs_orders": true,
    "private_key_access": "signing-only",
    "abuse_vectors": [
      "Flooding with rapid requote instructions to exhaust rate limit budget and suppress legitimate order modifications",
      "Injecting a requote with a target_price far from market to trigger a forced cancel-replace that loses queue priority"
    ],
    "mitigations": [
      "burst_max_per_s enforced atomically; excess requests shed with WARN before hitting CLOB rate limit",
      "target_price validated against PriceBandValidator before requote is accepted"
    ]
  },
  "failure_injection": [
    {
      "scenario": "AMEND_ENDPOINT_UNAVAILABLE",
      "how_to_inject": "Block PATCH /order endpoint; leave DELETE and POST available",
      "expected_behaviour": "Amend fails; fallback to cancel-replace executed; CANCEL_REPLACE_EXECUTED emitted",
      "recovery": "Amend endpoint restored; subsequent requotes attempt amend first"
    },
    {
      "scenario": "BURST_RATE_LIMIT_HIT",
      "how_to_inject": "Submit 25 requote instructions in 1 second (burst_max_per_s=10)",
      "expected_behaviour": "First 10 processed; 15 shed with CANCEL_REPLACE_RATE_LIMIT_SHED",
      "recovery": "Automatic on next second"
    },
    {
      "scenario": "KILL_SWITCH_DURING_AMEND",
      "how_to_inject": "Set killswitch.active=true mid-amend sequence",
      "expected_behaviour": "In-flight amend completes; subsequent requests rejected with KILL_SWITCH_ACTIVE",
      "recovery": "Manual KillSwitch reset"
    }
  ],
  "runbook": {
    "summary": "CancelReplaceOptimizer incidents are typically rate-limit sheds (strategy generating too many requotes) or amend-endpoint failures causing unexpected cancel-replaces.",
    "oncall_actions": [
      {
        "alert": "CROHighRateLimitShed",
        "first_step": "Identify which strategy is generating excess requotes; reduce requote frequency or increase burst_max_per_s temporarily.",
        "diagnosis": "",
        "mitigation": "",
        "escalation": "Exec pod lead"
      },
      {
        "alert": "CROHighDeltaTicks",
        "first_step": "Investigate why strategies are requesting large price moves; may indicate stale quote data.",
        "diagnosis": "",
        "mitigation": "",
        "escalation": "Strategy pod lead"
      }
    ],
    "manual_overrides": [
      {
        "name": "force_cancel_replace",
        "how": "polytraders bot force-cancel-replace exec.cancelreplaceoptimizer --order <order_id> --price <price>",
        "when": "Manual cancel-replace needed when amend endpoint is persistently unavailable.",
        "command": "polytraders bot force-cancel-replace exec.cancelreplaceoptimizer --order <order_id> --price <price>",
        "effect": "Manual cancel-replace needed when amend endpoint is persistently unavailable."
      }
    ],
    "healthcheck": "GET /internal/health/cancelreplaceoptimizer \u2192 green if clob_auth reachable, rate_limit_shed_rate < 0.1/min, amend success rate > 80%; red if clob_auth unreachable, rate_limit_shed_rate > 1/min, amend success rate < 50%"
  },
  "promotion_gates": {
    "to_shadow": [
      {
        "gate": "Rate-limit enforcement unit tests pass: no more than burst_max_per_s ops processed in any 1s window",
        "how_measured": "CI test run",
        "threshold": "Zero violations"
      }
    ],
    "to_limited_live": [
      {
        "gate": "Amend success rate > 80% over 48h shadow run (when delta <= threshold)",
        "how_measured": "polytraders_exec_cancelreplaceoptimizer_ops_total by path_taken",
        "threshold": "> 80% amend_in_place"
      }
    ],
    "to_general_live": [
      {
        "gate": "Rate limit shed rate < 0.01/min over 7-day limited-live",
        "how_measured": "polytraders_exec_cancelreplaceoptimizer_rate_limit_sheds_total",
        "threshold": "< 0.01/min"
      }
    ]
  },
  "reporting": {
    "emits_kinds": [
      "ExecutionReport"
    ],
    "topics": [
      "polytraders.reports.execution"
    ],
    "partition_key": "trace_id",
    "cadence": "every-event",
    "retention_class": "7y",
    "sampling_rule": "emit-every",
    "bus_failure_action": "wal-then-retry",
    "user_visible": "yes",
    "consumes_kinds": [
      "DecisionReport"
    ]
  },
  "capital_impact": "Direct",
  "mode_support": [
    "quarantine"
  ],
  "v3_status": {
    "phase": 5,
    "phase_name": "Execution rails",
    "docs": {
      "done": 27,
      "total": 27,
      "state": "done"
    },
    "impl": {
      "done": 0,
      "total": 15,
      "state": "pending"
    },
    "runtime": {
      "done": 0,
      "total": 8,
      "state": "pending"
    },
    "overall": "pending"
  }
}