{
  "format": "siebly-agent-recipe/v1",
  "id": "order-intent-chaser",
  "title": "Order Intent Chasing with Exchange APIs & WebSockets",
  "lastReviewed": "2026-05-12",
  "package": {
    "ecosystem": "npm",
    "name": "selected exchange SDK",
    "install": "Install the maintained SDK for the selected exchange",
    "docs": "https://siebly.io/sdk",
    "repository": "Use the selected SDK repository and installed package source"
  },
  "scope": {
    "runtime": "Node.js LTS",
    "language": "TypeScript",
    "products": [
      "Spot",
      "Margin",
      "Perpetuals",
      "Futures where supported by the exchange SDK"
    ],
    "defaultMode": "EXECUTION_MODE=DRY_RUN_PRIVATE chaser plan records",
    "liveExecutionDefault": false,
    "executionMode": {
      "env": "EXECUTION_MODE",
      "values": [
        "PUBLIC",
        "READ_ONLY_PRIVATE",
        "DRY_RUN_PRIVATE",
        "DEMO",
        "TESTNET",
        "LIVE"
      ],
      "exchangeWritesOnlyWhen": "EXECUTION_MODE=DEMO, TESTNET, or LIVE"
    },
    "credentials": "scoped API keys from environment variables only for READ_ONLY_PRIVATE, DRY_RUN_PRIVATE, DEMO, TESTNET, LIVE; exchange writes require EXECUTION_MODE=DEMO, TESTNET, or LIVE"
  },
  "requiredSources": [
    "https://siebly.io/ai/order-intent-chaser",
    "https://siebly.io/.well-known/recipes/order-intent-chaser.json",
    "https://siebly.io/.well-known/conformance/order-intent-chaser/latest.json",
    "https://siebly.io/.well-known/conformance/order-intent-chaser/v1/schema.json",
    "https://siebly.io/.well-known/conformance/order-intent-chaser/v1/fixtures.json",
    "https://siebly.io/.well-known/conformance/order-intent-chaser/v1/runner.ts",
    "https://siebly.io/ai/patterns",
    "https://siebly.io/ai",
    "https://siebly.io/sdk",
    "https://siebly.io/.well-known/agent-skills/siebly-crypto-exchange-api/SKILL.md",
    "https://siebly.io/reference/glossary",
    "https://siebly.io/llms.txt",
    "https://siebly.io/llms-tasks.txt",
    "https://siebly.io/llms-full.txt",
    "https://siebly.io/.well-known/siebly-sdk-catalog.json"
  ],
  "intentContract": [
    "The chaser consumes an already-approved [order intent](https://siebly.io/reference/glossary#order-intent) and does not decide whether to trade.",
    "Define a typed parent [OrderIntent](https://siebly.io/reference/glossary#order-intent) that includes id, product, symbol, side, role, quantity, price limit, max slippage, time limit, chase interval, max replace count, execution mode, risk approval.",
    "Entry intents and exit intents use the same adapter shape, but exit intents must preserve reduce-only or close-only semantics where the exchange supports them.",
    "The adapter must reject intents without market data, exchange filters, risk approval, or explicit EXECUTION_MODE=LIVE permission for exchange writes."
  ],
  "executionChain": [
    "parent intent",
    "risk approval",
    "product/symbol scope",
    "filter trust",
    "market-data trust",
    "child order candidate",
    "child custom order ID",
    "exchange request",
    "REST acceptance",
    "private order/fill event or scoped recovery",
    "remaining quantity",
    "replace, terminal, paused, or abandoned state"
  ],
  "trustRules": [
    "Risk approval proves the parent [order intent](https://siebly.io/reference/glossary#order-intent) may be attempted; it does not prove market data is fresh, filters are hydrated, or child order state is known.",
    "REST acceptance proves only that the exchange accepted the request. The child order remains pending until private order/fill evidence or scoped recovery confirms active, filled, rejected, cancelled, or absent state.",
    "Market-data trust is independent from child-order trust. A reconnect, sequence gap, stale book, or crossed book pauses new price-changing place/amend/replace decisions even if the child order is known.",
    "Durable child-order context is separate from child-order trust. For adapters with an implemented [EXECUTION_MODE](https://siebly.io/reference/glossary#execution-mode)=DEMO, TESTNET, or LIVE submission path, store parent [order intent](https://siebly.io/reference/glossary#order-intent), local generation, scope, and request context before submission; if an app-owned child order has no context, the adapter refuses mutation unless explicit adoption is configured and tested.",
    "Partial fills update remaining quantity before any amend, cancel, replace, timeout, or abandonment decision."
  ],
  "completionGate": "Do not mark a chaser with an implemented [EXECUTION_MODE](https://siebly.io/reference/glossary#execution-mode)=DEMO, TESTNET, or LIVE submission path complete until three consecutive full intent-to-child-order review passes produce no code, tests, fixtures, or documentation changes.",
  "marketDataRequirements": [
    "Hydrate exchange filters before pricing: tick size, step size, min quantity, max quantity, min notional, price bands, post-only support, and time-in-force support.",
    "Use fresh top-of-book or book-depth data before price-changing child order place, amend, or replace decisions. A cleanup cancel of a known app-owned child order may proceed from child-order state, timeout, or risk policy without waiting for fresh market data.",
    "Pause price-changing place, amend, or replace decisions on stale market data, crossed books, sequence gaps, reconnects, spread spikes, volatility spikes, or failed market-data or child-order reconciliation.",
    "Quantize every candidate price and quantity from hydrated filters before comparing against limits."
  ],
  "workflow": [
    "Keep the chaser as an execution adapter between order-intent generation and exchange submission. Strategy, signal, risk approval, and account reconciliation stay outside this class.",
    "Dry-run chaser plan records show side, role, raw target price, quantized limit price, quantity, maker/taker mode, slippage from reference, and reason.",
    "For a buy, never price above the configured price limit or max slippage cap. For a sell, never price below the configured price limit or max slippage cap.",
    "If postOnly is enabled, never cross the book; price at or behind the maker side and handle post-only rejection by repricing or pausing according to config.",
    "If taker crossing is allowed, cap the crossing price by the intent limit and slippage budget, and make that mode explicit in logs and config.",
    "Submit at most one write-capable child order per parent [order intent](https://siebly.io/reference/glossary#order-intent) at a time. Track the exchange-visible child order ID when available, local parent intent ID, local generation, remaining quantity, durable context status, and in-flight cancel/replace state.",
    "For adapters with an implemented EXECUTION_MODE=DEMO, TESTNET, or LIVE submission path, write durable child-order context before submission. Use exchange-visible [Custom Order IDs](https://siebly.io/reference/glossary#custom-order-id) to look up durable child-order context. Generate unique IDs and store parent intent ID plus replacement generation locally. Keep product, symbol, role, side, step, order kind, lifecycle, generation, recovery state, and other strategy state out of the ID text. Fail closed if an active [app-owned](https://siebly.io/reference/glossary#app-owned-order) child order lacks context unless explicit adoption is configured and fixture-tested.",
    "Do not replace on every tick. Use chase interval, minimum price movement, queue age, spread, and rate-limit budget before canceling or amending.",
    "Before canceling, amending, or replacing, verify current child order status and filled quantity from private events or trusted accountstate. Use scoped REST at startup, reconnect, timeout, unknown outcome, missing prerequisites, or conflicting evidence; do not refetch state after every healthy private event. Never assume a cancel succeeded until the exchange confirms or reconciliation proves the state.",
    "On partial fill, reduce remaining quantity, revalidate step size and min notional, and stop if the remainder is too small or the parent intent is complete.",
    "After reconnect, timeout, or conflicting evidence, restore market-data trust and child-order state before price-changing child order decisions. Cleanup cancels may proceed from trusted child-order state and explicit risk or timeout policy.",
    "On timeout, max replace count, stale data, rejection, unknown order state, or [risk-gate failure](https://siebly.io/reference/glossary#risk-gate), cancel or leave the child order according to explicit policy, then mark the parent intent abandoned, paused, or needs operator review.",
    "On shutdown, stop new replace attempts, reconcile app-owned child orders, cancel only configured transient chaser orders, and log a compact summary."
  ],
  "pricingRules": [
    "Use side-specific caps: buyLimit is the maximum acceptable price; sellLimit is the minimum acceptable price.",
    "Reference price should be explicit: best bid, best ask, mid, mark price, last trade, or strategy-provided limit.",
    "For maker chasing, candidate buy price should normally be at or below best bid; candidate sell price should normally be at or above best ask.",
    "For taker-allowed chasing, candidate price may cross the spread only inside the configured slippage and price-limit boundary.",
    "Use exchange-visible [Custom Order IDs](https://siebly.io/reference/glossary#custom-order-id) to look up durable child-order context. Generate unique IDs and store parent intent ID plus replacement generation locally. Keep product, symbol, role, side, step, order kind, lifecycle, generation, recovery state, and other strategy state out of the ID text.",
    "Durability is a runtime boundary, not an exchange ID format. Persist context by parent intent, local generation, product, symbol, side, role, and [Custom Order ID](https://siebly.io/reference/glossary#custom-order-id). Keep product, symbol, role, side, step, order kind, lifecycle, generation, recovery state, and other strategy state out of the ID text."
  ],
  "stateMachine": [
    {
      "state": "queued",
      "allowedAction": "Validate intent and execution boundary."
    },
    {
      "state": "hydrating_market",
      "allowedAction": "Fetch filters and fresh book data; no submission."
    },
    {
      "state": "pricing",
      "allowedAction": "Build a bounded dry-run child order candidate."
    },
    {
      "state": "placing",
      "allowedAction": "Submit one child order only if EXECUTION_MODE=DEMO, TESTNET, or LIVE and all [risk gates](https://siebly.io/reference/glossary#risk-gate) and execution gates pass."
    },
    {
      "state": "open",
      "allowedAction": "Wait for fill, cancel, replace trigger, timeout, or risk event."
    },
    {
      "state": "replacing",
      "allowedAction": "Cancel or amend only the app-owned child order after reconciliation."
    },
    {
      "state": "recovering",
      "allowedAction": "Hydrate scoped market and child-order state after reconnect, timeout, unknown status, or conflicting evidence."
    },
    {
      "state": "partially_filled",
      "allowedAction": "Reduce remaining quantity and revalidate filters."
    },
    {
      "state": "filled",
      "allowedAction": "Mark parent intent complete and stop chasing."
    },
    {
      "state": "paused",
      "allowedAction": "No submission until operator or reconciliation clears the reason."
    },
    {
      "state": "abandoned",
      "allowedAction": "No further exchange action except configured cleanup."
    }
  ],
  "observability": [
    "Add structured logs for parent intent ID, child order ID, generation, symbol, side, role, remaining quantity, raw and quantized price, reference price, spread, slippage budget, time remaining, and decision reason.",
    "Do not log secrets, signed URLs, listen keys, full account snapshots, or raw private payloads.",
    "Expected reprices and app-owned order updates should be info logs. Rejections, unknown order state, stale data, and risk pauses should be structured warnings or errors.",
    "Keep dry-run output copyable so operators can inspect the exact request that would be submitted."
  ],
  "validationFixtures": [
    "chaser_dry_run_buy_candidate_respects_limit_and_filters",
    "chaser_dry_run_sell_exit_preserves_reduce_or_close_semantics",
    "chaser_rest_acceptance_does_not_confirm_child_order_state",
    "chaser_private_fill_before_rest_acceptance_updates_remaining_quantity_once",
    "chaser_cancel_replace_waits_for_terminal_or_recovered_child_state",
    "chaser_stale_market_data_blocks_place_and_replace",
    "chaser_reconnect_requires_market_resync_before_replace",
    "chaser_partial_fill_below_minimum_abandons_or_pauses_by_policy",
    "chaser_duplicate_child_generation_is_blocked_before_exchange_call",
    "chaser_active_app_child_without_parent_context_refuses_mutation",
    "chaser_timeout_cleanup_follows_explicit_policy"
  ],
  "fixtureCases": [
    {
      "name": "Dry-run buy entry chaser",
      "purpose": "Proves an entry intent becomes a bounded buy limit candidate without DEMO, TESTNET, or LIVE submission.",
      "expected": "Candidate price is quantized, does not exceed the buy limit or slippage cap, and includes a child order generation."
    },
    {
      "name": "Dry-run sell exit chaser",
      "purpose": "Proves an exit intent preserves reduce-only or close-only semantics where supported.",
      "expected": "Candidate price is quantized, does not go below the sell limit or slippage cap, and never increases exposure."
    },
    {
      "name": "Post-only would cross",
      "purpose": "Proves maker-only mode does not accidentally take liquidity.",
      "expected": "The candidate is repriced behind the book or blocked locally before submission."
    },
    {
      "name": "Partial fill before replace",
      "purpose": "Proves the adapter reconciles filled quantity before canceling, amending, or replacing.",
      "expected": "Remaining quantity is reduced, revalidated against filters, and abandoned if below minimum size or notional."
    },
    {
      "name": "Cancel replace race",
      "purpose": "Proves the adapter does not submit a replacement while the previous child order state is unknown.",
      "expected": "Workflow pauses or reconciles until the cancel, amend, fill, or open state is known."
    },
    {
      "name": "REST acceptance is provisional",
      "purpose": "Proves an accepted child order request does not unlock replacement or terminal handling before private order evidence or scoped recovery.",
      "expected": "Child order state remains pending and duplicate place/replace calls are blocked until active, filled, rejected, cancelled, or absent state is known."
    },
    {
      "name": "Reconnect before replace",
      "purpose": "Proves a reconnect pauses market-data trust and child-order mutation until both market data and app-owned child state are reconciled.",
      "expected": "No cancel, amend, or replacement call is made from stale pre-reconnect data."
    },
    {
      "name": "Stale market data",
      "purpose": "Proves the chaser stops repricing when top-of-book data is not authoritative.",
      "expected": "No order is submitted or replaced until REST/WebSocket resync succeeds."
    },
    {
      "name": "Timeout with app-owned child order",
      "purpose": "Proves timeout behavior follows explicit cleanup policy.",
      "expected": "Adapter cancels, leaves, or marks the child order for review according to config and logs the final parent state."
    }
  ],
  "safety": [
    "[EXECUTION_MODE](https://siebly.io/reference/glossary#execution-mode)=DRY_RUN_PRIVATE is the default execution mode, where the adapter builds and logs bounded child order candidates without submitting to the exchange. Always handle incoming account state events to keep internal account state in sync with exchange state, so the system is ready to execute live if requested by the user. Do not simulate fills, balances, or positions unless a separate paper-trading simulator is explicitly requested.",
    "The chaser must never create an [order intent](https://siebly.io/reference/glossary#order-intent); it only executes an already-approved intent.",
    "[EXECUTION_MODE](https://siebly.io/reference/glossary#execution-mode)=DEMO, TESTNET, or LIVE execution must require explicit config, scoped credentials, exchange-rule verification, and reviewed code.",
    "Emergency exits and hard stops should not rely only on a passive chaser. A market, stop, or fail-safe path must be an explicit separate operator decision.",
    "Rate limits, max replace count, max runtime, max slippage, max notional, and [risk gates](https://siebly.io/reference/glossary#risk-gate) including a kill switch are required before live use.",
    "Do not amend or cancel unowned manual orders.",
    "Do not mark a chaser with an implemented [EXECUTION_MODE](https://siebly.io/reference/glossary#execution-mode)=DEMO, TESTNET, or LIVE submission path complete until three consecutive full intent-to-child-order review passes produce no code, tests, fixtures, or documentation changes."
  ],
  "promptFrameworkCompletionWorkflow": {
    "instruction": "Recursive completion workflow:\n1. Before implementation, save this exact prompt in docs/AI_PROMPT.md (or docs/SPEC.md when that is the project standard) and write docs/PLAN.md with phases, invariants, tests or fixtures, docs to update, and acceptance gates.\n2. Review docs/PLAN.md for missing workflows, unsafe assumptions, product/exchange-specific leakage, unclear state ownership, confirmation or recovery gaps, missing tests, and incomplete docs. Update docs/PLAN.md and repeat until one full review pass finds no actionable changes.\n3. Implement one plan phase at a time. After each phase, review changed code, tests, fixtures, docs, generated artifacts, and runtime workflows against docs/PLAN.md and this prompt. Fix gaps and repeat until that phase has no actionable changes before starting the next phase.\n4. After all phases, run a full-depth project review across every workflow, lifecycle, state transition, error path, and artifact. This is not a shallow summary pass. Fix every actionable gap and repeat until a full pass finds no further changes, then record the final review outcome in docs/PLAN.md.",
    "acceptanceRequirement": "docs/PLAN.md records the initial plan, plan-review iterations, phase review outcomes, final full-project review, validation commands, and any documented non-claims. No plan phase or project completion is accepted until the recursive review loop finds no actionable gaps, flaws, or incomplete workflows left to correct."
  }
}
