{
  "format": "siebly-conformance-pack/v1",
  "id": "exchange-state-management",
  "title": "Exchange State Management Conformance Pack",
  "lastReviewed": "2026-05-12",
  "canonicalArtifacts": {
    "specGuide": "https://siebly.io/ai/exchange-state",
    "manifest": "https://siebly.io/.well-known/agent-manifests/exchange-state-management/latest.json",
    "runtimeKit": "https://siebly.io/.well-known/runtime-kits/exchange-state-management/v1/index.json",
    "runtimeTypes": "https://siebly.io/.well-known/runtime-kits/exchange-state-management/v1/types.ts",
    "integrationKit": "https://siebly.io/.well-known/integration-kits/exchange-state-management/latest.json",
    "recipe": "https://siebly.io/.well-known/recipes/exchange-state-management.json",
    "schema": "https://siebly.io/.well-known/conformance/exchange-state-management/v1/schema.json",
    "fixtures": "https://siebly.io/.well-known/conformance/exchange-state-management/v1/fixtures.json",
    "runner": "https://siebly.io/.well-known/conformance/exchange-state-management/v1/runner.ts"
  },
  "primarySpec": {
    "id": "exchange-state-management-spec",
    "title": "Exchange State Management",
    "href": "https://siebly.io/ai/exchange-state",
    "purpose": "Exchange-neutral runtime spec for private account, order, and position state workflows, including DCA/TP/SL managers.",
    "architecture": {
      "reusable": "order_account_position_state_machine",
      "lane": "ws_symbol_side_action_gated"
    },
    "role": "Primary implementation spec. Other artifacts support, specialize, or test this workflow; they do not replace it."
  },
  "runnerContract": {
    "language": "typescript",
    "fixtureSource": "JSON fixture set with a TypeScript runner contract for local executable tests",
    "entrypoint": "https://siebly.io/.well-known/conformance/exchange-state-management/v1/runner.ts",
    "exportedTypes": [
      "ExchangeStateFixture",
      "ExchangeStateFixtureStep",
      "ExchangeStateFixtureExpectation",
      "ExchangeStateHarness",
      "ExchangeStateFixtureReport",
      "runExchangeStateManagementFixtures"
    ],
    "requiredFixtureFields": [
      "name",
      "intent",
      "scope",
      "initial",
      "steps",
      "expect",
      "forbid"
    ],
    "expectationSemantics": [
      "Object expectations are partial matches.",
      "Array expectations are containment matches that consume one observed item per expected item; an empty expected array requires an empty observed array.",
      "Primitive expectations are exact matches after stable JSON normalization.",
      "Forbidden actions are read from observed.forbiddenObserved and matched against fixture.forbid."
    ]
  },
  "subjectTrust": {
    "subjects": [
      "order trust",
      "position trust",
      "filter trust",
      "context trust",
      "readiness trust"
    ],
    "rules": [
      "Split trust by subject: order trust, position trust, filter trust, context trust, and readiness trust.",
      "A TP/SL/DCA order update proves only order trust; it does not prove position trust, position size, entry/cost basis, exposure, or replacement eligibility.",
      "For products with exchange-provided position rows, order/fill events are triggers; replacement planning waits for matching position trust from private position or account updates or scoped recovery.",
      "For products without exchange-provided position rows, derive local position state from fills/executions, fees, account events, balance updates, and documented matching rules before managed exits, exposure changes, or re-hedging."
    ]
  },
  "symbolScope": [
    "If configuredSymbols is blank, absent, or empty, auto-detect eligible open positions.",
    "When symbols are configured, treat them as an allowlist: manage matching detected positions only and ignore or log out-of-scope private events without mutation.",
    "Sample symbols from docs, tests, prompts, or quickstarts are examples only; never use them as runtime defaults."
  ],
  "riskGeometry": [
    "For broad TP/SL/DCA position managers, use percentage-based strategy inputs by default: derive TP, DCA, and SL prices plus DCA size from trusted entry and position size before order planning.",
    "Absolute TP/DCA/SL prices or DCA quantities are advanced per-symbol operator overrides, not the primary config model. If allowed, they must be explicit, scoped, compatible with percentage defaults, and validated through the same filters and risk geometry.",
    "Startup validation rejects missing, invalid, contradictory, or non-finite strategy inputs before private clients, WebSocket subscriptions, hydration, or exchange mutation.",
    "Validate risk geometry before exchange mutation: for long positions, TP is above entry, DCA is below entry, and SL is below DCA; for short positions, TP is below entry, DCA is above entry, and SL is above DCA.",
    "Reject missing or invalid TP/DCA/SL strategy outputs before order placement. After derivation or override, quantize prices and quantities with hydrated exchange filters before final validation.",
    "After quantization, revalidate risk geometry, min/max, and notional rules; reject only if the quantized TP/DCA/SL values are equal, crossed, or otherwise violate geometry or filters before [EXECUTION_MODE](https://siebly.io/reference/glossary#execution-mode)=DRY_RUN_PRIVATE, DEMO, TESTNET, or LIVE order placement.",
    "Risk geometry validation uses the trusted entry price or explicit operator override, hydrated tick/lot filters, and the managed side before any place/amend/cancel request."
  ],
  "identityChainReview": {
    "cleanPassesRequired": 3,
    "chain": [
      "config scope",
      "product/environment/account",
      "symbol",
      "position mode",
      "managed side",
      "exchange position identity",
      "accountstate position state (native or locally derived)",
      "planner scope",
      "slot scope",
      "custom order ID",
      "durable context",
      "exchange request",
      "REST acceptance",
      "private order/execution/position event",
      "trusted active order",
      "subject trust state",
      "confirmation tracker",
      "recovery scope",
      "cleanup/protective/DCA replanning"
    ],
    "requiredRule": "Do not mark the implementation complete until three consecutive full identity-chain review passes produce no code, tests, fixtures, or documentation changes.",
    "passMustTrace": "Trace mismatched, stale, missing, contradictory, duplicated, late, recovered, and flat identities across every runtime boundary."
  },
  "liveRunFailureFixtures": [
    {
      "name": "context_write_failure_blocks_submission",
      "purpose": "A failed durable order-context write must block exchange submission.",
      "expected": "The planner records the context write failure, submits no order, creates no pending confirmation, and leaves the scope blocked or recovery-ready."
    },
    {
      "name": "private_confirmation_before_rest_accept_is_consumed",
      "purpose": "A private confirmation can arrive before the REST submit promise resolves.",
      "expected": "The early private confirmation is retained, matched to the later accepted submit response, and does not leave stale pending state or duplicate submission."
    },
    {
      "name": "side_flip_cleans_old_side_before_new_side_work",
      "purpose": "A one-way side flip cleans old-side app-owned orders before new-side protection or DCA.",
      "expected": "Cleanup for the old managed side settles first; new-side protective and DCA work stays blocked until the cleanup confirmation is trusted."
    },
    {
      "name": "pending_place_blocks_duplicate_place",
      "purpose": "A pending place confirmation blocks another place for the same slot.",
      "expected": "The planner emits no duplicate place intent while the matching place confirmation is still pending."
    },
    {
      "name": "pending_cancel_blocks_duplicate_cancel",
      "purpose": "A pending cancel confirmation blocks another cancel for the same target.",
      "expected": "The planner emits no duplicate cancel intent while the matching cancel confirmation is still pending."
    },
    {
      "name": "decimal_and_default_equivalent_active_order_does_not_replace",
      "purpose": "Equivalent active orders do not churn because of display precision or hydrated defaults.",
      "expected": "Desired-vs-active comparison normalizes decimals and non-actionable exchange defaults by order kind, then suppresses cancel/recreate when actionable slot fields match."
    }
  ],
  "finalAcceptanceGate": [
    "Trace the full identity chain: config scope -> product/environment/account -> symbol -> position mode -> managed side -> exchange position identity -> accountstate position state (native or locally derived) -> planner scope -> slot scope -> custom order ID -> durable context -> exchange request -> REST acceptance -> private order/execution/position event -> trusted active order -> subject trust state -> confirmation tracker -> recovery scope -> cleanup/protective/DCA replanning.",
    "Do not mark the implementation complete until three consecutive full identity-chain review passes produce no code, tests, fixtures, or documentation changes.",
    "Trace mismatched, stale, missing, contradictory, duplicated, late, recovered, and flat identities across every runtime boundary.",
    "Every accepted lifecycle claim needs an executable fixture; behaviors without fixtures must be listed as unsupported or unverified.",
    "Core [behavior-contract fixtures](https://siebly.io/reference/glossary#behavior-contract-fixture) cover context write failure before submit, early private confirmation before REST accept, one-way side flips, pending duplicate place/cancel guards, and decimal/default-equivalent active-order convergence.",
    "The [EXECUTION_MODE](https://siebly.io/reference/glossary#execution-mode)=DEMO, TESTNET, or LIVE submission paths are implemented for order-capable projects where supported, but they remain disabled until the required identity-chain, subject-trust, symbol-scope, and risk-geometry fixtures exist and pass."
  ],
  "requiredChecks": [
    {
      "name": "startup_hydrated_position_queues_work_before_service_ready",
      "purpose": "REST-hydrated open positions queue work before service readiness.",
      "expected": "Hydration records affected scopes and a reconciliation pass runs before service_ready."
    },
    {
      "name": "private_event_records_scope_and_schedules_reconcile",
      "purpose": "Private event ingestion leads to scoped workflow scheduling.",
      "expected": "The event applies to accountstate, records the precise or bounded affected scope, and schedules reconciliation."
    },
    {
      "name": "private_event_burst_waits_for_related_events",
      "purpose": "Account State ingestion is immediate while workflow execution briefly waits for related events in the same burst.",
      "expected": "Multiple related events update accountstate immediately, then produce one reconciliation pass after related events have had a short bounded chance to arrive."
    },
    {
      "name": "custom_order_id_registry_routes_exchange_echoes",
      "purpose": "Exchange-visible custom IDs are lookup keys into one order-context store.",
      "expected": "Private order echoes map to slot, scope, role, and pending action through the registry without parsing the ID string."
    },
    {
      "name": "pending_confirmation_does_not_unlock_dependent_action_family",
      "purpose": "Accepted mutation responses are provisional and cannot unlock dependent action families.",
      "expected": "Dependent action families wait for trusted private stream state or scoped recovery hydration."
    },
    {
      "name": "context_write_failure_blocks_submission",
      "purpose": "A failed durable order-context write must block exchange submission.",
      "expected": "The planner records the context write failure, submits no order, creates no pending confirmation, and leaves the scope blocked or recovery-ready."
    },
    {
      "name": "private_confirmation_before_rest_accept_is_consumed",
      "purpose": "A private confirmation can arrive before the REST submit promise resolves.",
      "expected": "The early private confirmation is retained, matched to the later accepted submit response, and does not leave stale pending state or duplicate submission."
    },
    {
      "name": "side_flip_cleans_old_side_before_new_side_work",
      "purpose": "A one-way side flip cleans old-side app-owned orders before new-side protection or DCA.",
      "expected": "Cleanup for the old managed side settles first; new-side protective and DCA work stays blocked until the cleanup confirmation is trusted."
    },
    {
      "name": "pending_place_blocks_duplicate_place",
      "purpose": "A pending place confirmation blocks another place for the same slot.",
      "expected": "The planner emits no duplicate place intent while the matching place confirmation is still pending."
    },
    {
      "name": "pending_cancel_blocks_duplicate_cancel",
      "purpose": "A pending cancel confirmation blocks another cancel for the same target.",
      "expected": "The planner emits no duplicate cancel intent while the matching cancel confirmation is still pending."
    },
    {
      "name": "decimal_and_default_equivalent_active_order_does_not_replace",
      "purpose": "Equivalent active orders do not churn because of display precision or hydrated defaults.",
      "expected": "Desired-vs-active comparison normalizes decimals and non-actionable exchange defaults by order kind, then suppresses cancel/recreate when actionable slot fields match."
    },
    {
      "name": "terminal_event_during_cancel_or_amend_is_benign_race",
      "purpose": "Terminal private evidence can make later missing-target cancel/amend errors benign.",
      "expected": "The target is terminalized and no duplicate recovery loop starts when proof exists."
    },
    {
      "name": "reconnect_queues_known_scopes_for_recovery_even_when_quiet",
      "purpose": "Reconnect schedules recovery even without a later private event.",
      "expected": "Known active scopes enter scoped hydration and replan from trusted state before new exposure resumes."
    },
    {
      "name": "slot_filter_failures_are_blocked_not_silent_or_retried",
      "purpose": "Exchange filters and local sizing gates produce explicit blocks.",
      "expected": "Min quantity, min notional, zero-size, or missing-filter cases log a block reason and do not spin retries."
    },
    {
      "name": "flat_position_cleans_app_owned_orders",
      "purpose": "A flat position cleans remaining managed orders.",
      "expected": "Only app-owned orders in the affected scope are cancelled or terminalized; unowned orders are untouched."
    }
  ],
  "completeRequiredChecks": [
    "startup_hydrated_position_queues_work_before_service_ready",
    "private_event_records_scope_and_schedules_reconcile",
    "private_event_burst_waits_for_related_events",
    "custom_order_id_registry_routes_exchange_echoes",
    "pending_confirmation_does_not_unlock_dependent_action_family",
    "context_write_failure_blocks_submission",
    "private_confirmation_before_rest_accept_is_consumed",
    "side_flip_cleans_old_side_before_new_side_work",
    "pending_place_blocks_duplicate_place",
    "pending_cancel_blocks_duplicate_cancel",
    "decimal_and_default_equivalent_active_order_does_not_replace",
    "terminal_event_during_cancel_or_amend_is_benign_race",
    "reconnect_queues_known_scopes_for_recovery_even_when_quiet",
    "slot_filter_failures_are_blocked_not_silent_or_retried",
    "flat_position_cleans_app_owned_orders",
    "rest_acceptance_does_not_downgrade_trusted_private_order",
    "terminal_order_status_is_not_open_order_confirmation",
    "execution_fill_is_not_open_order_confirmation",
    "default_dca_active_order_does_not_advance_next_step",
    "startup_adopts_active_contexts_and_prunes_absent_contexts",
    "ambiguous_event_routes_bounded_fallback_then_exact_scope",
    "pending_confirmation_timeout_enters_scoped_recovery",
    "recovery_hydration_blocks_normal_actions_until_trust_restored",
    "blank_symbols_auto_detects_open_positions",
    "absent_symbols_auto_detects_open_positions",
    "blank_symbols_no_positions_noops_without_mutation",
    "symbol_allowlist_manages_matching_detected_positions_only",
    "sample_symbol_not_used_as_runtime_default",
    "configured_symbol_allowlist_blocks_out_of_scope_events",
    "order_confirmation_does_not_imply_position_trust",
    "native_position_dca_fill_waits_for_position_update",
    "native_position_tp_sl_fill_waits_for_position_update",
    "spot_local_position_state_substitutes_for_native_position_rows",
    "long_dca_equal_sl_rejected",
    "short_dca_equal_sl_rejected",
    "dry_run_status_doctor_cannot_submit_live_orders"
  ],
  "exchangeOverlays": {
    "binance": "https://siebly.io/.well-known/conformance/binance-position-manager/latest.json",
    "bybit": "https://siebly.io/.well-known/conformance/bybit-position-manager/latest.json"
  }
}
