{
  "format": "siebly-agent-implementation-manifest/v1",
  "id": "exchange-state-management",
  "title": "Exchange State Management Agent Manifest",
  "task": "exchange-state-management",
  "version": 1,
  "lastReviewed": "2026-05-12",
  "purpose": "Machine-readable implementation manifest for exchange state-management runtimes.",
  "canonicalArtifacts": {
    "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",
    "conformancePack": "https://siebly.io/.well-known/conformance/exchange-state-management/latest.json",
    "specGuide": "https://siebly.io/ai/exchange-state",
    "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."
  },
  "authorityOrder": [
    "Use this manifest before guide pages when building the runtime contract.",
    "Use the runtime kit to create the local module layout before runtime code.",
    "Use the [behavior-contract fixtures](https://siebly.io/reference/glossary#behavior-contract-fixture) and runner contract from the [conformance pack](https://siebly.io/reference/glossary#conformance-pack) to create local tests before runtime code.",
    "Use the integration kit for state machine, event routing, confirmation lifecycle, and action-family rules.",
    "Use exchange overlays for SDK methods, request fields, private topics, and rejection codes.",
    "Use installed SDK declarations and exchange docs for exact method names and request shapes."
  ],
  "requiredFirstSteps": [
    "Record the installed SDK package version and inspected SDK/API surfaces in the README before exchange calls.",
    "Create WORKFLOW_STATE_MACHINE.md, PRIVATE_EVENT_ROUTING_TABLE.md, CONFIRMATION_LIFECYCLE.md, and DURABLE_CONTEXT_LIFECYCLE.md before submitters.",
    "Create local modules from the runtime kit contracts.",
    "Generate local behavior-contract tests from the required fixture set.",
    "Keep EXECUTION_MODE=DEMO, TESTNET, or LIVE submission unavailable until required checks pass."
  ],
  "specSteps": [
    "Save this exact prompt or spec in docs/AI_PROMPT.md (or docs/SPEC.md when that is the project standard), plus the prompt manifest, workflow state machine, private-event routing table, confirmation lifecycle, durable-context lifecycle, plan, and environment example before exchange calls.",
    "Verify installed SDK/API clients, request builders, custom ID fields, private topics, filters, error shapes, reconnect hooks, and shutdown methods from installed declarations/source before coding exchange adapters.",
    "Create the exchange-state runtime modules before exchange-specific adapters. Use the runtime kit when reusable scaffolding or typed module contracts are needed.",
    "After implementation, generate or run local tests from the applicable [behavior-contract fixtures](https://siebly.io/reference/glossary#behavior-contract-fixture) in the exchange-state and selected exchange [conformance packs](https://siebly.io/reference/glossary#conformance-pack) before enabling write-capable execution modes.",
    "Implement the event-driven private-state loop (ws_symbol_side_action_gated). Private events update [Account State](https://siebly.io/reference/glossary#accountstate), record the [affected scope](https://siebly.io/reference/glossary#affected-scope), give related events a short bounded window to arrive, and one [workflow owner](https://siebly.io/reference/glossary#workflow-owner) chooses one [action family](https://siebly.io/reference/glossary#action-family). Accepted mutations stay [pending confirmation](https://siebly.io/reference/glossary#pending-confirmation) until [private confirmation](https://siebly.io/reference/glossary#private-stream-confirmation) or [scoped recovery](https://siebly.io/reference/glossary#scoped-recovery), and REST state fetches happen only at trust boundaries.",
    "Each reconciliation pass chooses one [action family](https://siebly.io/reference/glossary#action-family) only: recover uncertain state, clean up stale app-owned orders, repair/place protection, place/repair DCA, do nothing, or wait because required evidence or configuration is missing.",
    "Do not enter REST recovery just because private order, execution, fill, or position events arrived. If the private stream is healthy and [Account State](https://siebly.io/reference/glossary#accountstate) has ingested the matching order evidence plus the matching position or account evidence, continue from private-stream account state without REST hydration. For products without exchange-provided position rows, locally derived position evidence fills the same role.",
    "Plan protective SL/TP before exposure-increasing DCA for a fresh managed position. DCA runs only after protection is trusted or scoped recovery proves the account state."
  ],
  "behaviorContract": {
    "architecture": "ws_symbol_side_action_gated",
    "reusableArchitecture": "order_account_position_state_machine",
    "reusablePrimitives": [
      "custom-order-id-registry",
      "trusted-accountstate-boundary",
      "subject-level-trust-boundary",
      "position-state-update-trigger",
      "symbol-scope-auto-detect",
      "risk-geometry-validation",
      "ws-first-order-state",
      "recovery-hydrate-replan",
      "affected-scope-event-routing",
      "protective-sl-tp-dispatch",
      "mutation-confirmation-gating",
      "stale-mutation-noop-classification",
      "slot-convergence",
      "latch-lifecycle",
      "conformance-fixture-schema",
      "identity-chain-acceptance-gate"
    ],
    "managerLane": "simple_managed_slots",
    "accountStateSource": "Use the account-state layer as the in-memory account view. Feed it startup REST snapshots and private account events. Local submission outcomes are provisional coordination evidence and pending-confirmation inputs, not trusted open-order state. Do not build a second account-state reducer.",
    "subjectTrust": "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.",
    "nativePositionReplanning": "For products with exchange-provided position rows, private order/fill updates are triggers, not replacement authority. Wait for the matching position or account-state update before re-protecting, re-DCA, cleanup/noop decisions, or run scoped recovery if the stream is broken.",
    "localPositionStateForNonNativeProducts": "For products without exchange-provided position rows, define local position state from fills/executions, fees, account events, balance updates, and documented matching rules. Do not apply derivative position lifecycle rules silently to balances alone.",
    "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.",
    "defaultStrategyConfig": "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.",
    "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.",
    "slotIdentity": "Use deterministic internal SlotKey values for strategy identity. Custom order IDs are lookup keys into an order-context store. Treat ID drift as non-actionable when role, step, side, quantity, price, trigger, exit semantics, and order kind still match.",
    "customOrderIdRegistry": "[Custom Order IDs](https://siebly.io/reference/glossary#custom-order-id) are lookup keys into one order-context registry/store. Generate a unique random ID, store context before submit, send the order with that ID, and resolve exchange echoes through the store. Follow exchange-specific prefix, length, and character rules only when required. Do not encode product, symbol, role, side, step, order kind, lifecycle, generation, recovery state, or other strategy state in the ID text.",
    "startupRecovery": "On startup, reconnect, restart, or recovery, hydrate trusted state first, manage orders proven app-owned by the runtime or persisted order store, optionally clean unknown scoped orders only when explicit config enables it, then rebuild expected slots from current positions.",
    "healthyStream": "During normal private event bursts, apply every event to [Account State](https://siebly.io/reference/glossary#accountstate) immediately, then use a short [event-burst wait](https://siebly.io/reference/glossary#event-burst-wait) before planning. Do not enter REST recovery just because private order, execution, fill, or position events arrived. If the private stream is healthy and [Account State](https://siebly.io/reference/glossary#accountstate) has ingested the matching order evidence plus the matching position or account evidence, continue from private-stream account state without REST hydration. For products without exchange-provided position rows, locally derived position evidence fills the same role.",
    "restBoundary": "Use scoped REST hydration for startup, restart, reconnect, stream exception or gap, missing prerequisites such as filters, unknown submit/cancel/amend outcomes, timeouts, sync-required or not-ready state, conflicting evidence, and explicit recovery. It is not the ordinary response to every healthy private event or ordinary pending confirmation.",
    "actionFamilyGate": "Each reconciliation pass chooses one [action family](https://siebly.io/reference/glossary#action-family) only: recover uncertain state, clean up stale app-owned orders, repair/place protection, place/repair DCA, do nothing, or wait because required evidence or configuration is missing. Normal cleanup, protection, and DCA work must not run from stale or unresolved state. Recovering uncertain state means blocking normal action families, running scoped hydration and buffered replay until local state is coherent with exchange state, then requeueing the [affected scope](https://siebly.io/reference/glossary#affected-scope).",
    "protectiveDispatch": "For fresh protection, pre-register SL and TP contexts and dispatch the separate SL and TP orders concurrently by default. If serialized protective mode is configured, submit SL before TP. DCA remains gated until required protection is trusted.",
    "pendingConfirmations": "Accepted place/amend/cancel responses create [pending confirmations](https://siebly.io/reference/glossary#pending-confirmation) and duplicate-submit protection, but they do not unlock dependent action families until [private confirmation](https://siebly.io/reference/glossary#private-stream-confirmation) or [scoped recovery](https://siebly.io/reference/glossary#scoped-recovery) proves account state.",
    "submissionTimeout": "Use a configurable bounded confirmation timeout for unknown REST/WS outcomes; 5 seconds is a reasonable default for generated managers before scoped recovery. Unknown outcomes enter scoped recovery rather than duplicate submit or trusted success.",
    "slotConvergence": "When an accountstate or exchange-overlay comparison helper is available, compare NormalizedOrder-to-NormalizedOrder: convert desired slot/request objects into the accountstate NormalizedOrder shape first, mapping local managedSide/managedStrategySide to strategySide, then compare them with active normalized orders. Do not pass strategy-local DesiredManagedOrder/request objects directly or hand-roll raw exchange-object equality. Regular fixed-price TP and DCA LIMIT slots converge by slot identity, order side, quantity, and limit price after tick/lot normalization. Close-position or close-on-trigger SL slots converge by slot identity, order side, trigger price, trigger source, close-position semantics, and stop kind; hydrated quantity, price, reduce-only, and default false-like fields are diagnostic unless current exchange docs make them actionable. Exchange echo fields, generated order IDs, lifecycle counters, default booleans, omitted trigger-only fields on regular orders, and display-only precision differences must not trigger cancel/recreate churn.",
    "liveRunFailureFixtures": "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.",
    "semanticWsLogs": "Emit semantic logs for private stream ingestion and account-state application: private_ws_event_received, accountstate_event_applied, affected_scope_recorded, symbol_side_reconcile_started, action_family_selected, submission_accepted_pending_confirmation, private_ws_confirmation_applied, workflow_reconcile_complete.",
    "advancedLane": "Durable lifecycle epochs, replacement generations, and cross-process adoption belong to an advanced persistent strategy lane only when explicitly requested and tested.",
    "identityChainAcceptance": "Do not mark the implementation complete until three consecutive full identity-chain review passes produce no code, tests, fixtures, or documentation changes."
  },
  "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."
    }
  ],
  "requiredChecks": [
    "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"
  ],
  "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"
  ],
  "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."
  ],
  "exchangeOverlays": {
    "binance": "https://siebly.io/.well-known/agent-manifests/binance-position-manager/latest.json",
    "bybit": "https://siebly.io/.well-known/agent-manifests/bybit-position-manager/latest.json"
  }
}
