{
  "format": "siebly-agent-recipe/v1",
  "id": "binance-spot-candle-close-pipeline",
  "title": "Candle-Close Pipeline with Binance APIs & WebSockets",
  "lastReviewed": "2026-05-12",
  "package": {
    "ecosystem": "npm",
    "name": "binance",
    "docs": "https://siebly.io/sdk/binance/javascript",
    "repository": "https://github.com/tiagosiebler/binance"
  },
  "scope": {
    "runtime": "Node.js LTS",
    "language": "TypeScript",
    "product": "Binance Spot",
    "defaultSymbol": "BTCUSDT",
    "defaultInterval": "1m",
    "credentials": "public endpoints only"
  },
  "requiredSources": [
    "https://siebly.io/ai/historical-live-data-pipeline",
    "https://siebly.io/.well-known/recipes/historical-live-data-pipeline-core.json",
    "https://siebly.io/.well-known/conformance/historical-live-data/latest.json",
    "https://siebly.io/.well-known/conformance/historical-live-data/v1/schema.json",
    "https://siebly.io/.well-known/conformance/historical-live-data/v1/fixtures.json",
    "https://siebly.io/.well-known/conformance/historical-live-data/v1/runner.ts",
    "https://siebly.io/ai/candle-pipeline/binance",
    "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",
    "https://github.com/tiagosiebler/binance",
    "https://github.com/sieblyio/crypto-api-examples/tree/master/examples/Binance"
  ],
  "verifyBeforeUse": [
    "Current kline subscription helper for the selected Binance product group. For Spot, this is expected to include subscribeSpotKline(...).",
    "Current REST candle method for the selected Binance product group. For Spot, this is expected to include MainClient.getKlines(...).",
    "Current formatted kline type guard, expected to include isWsFormattedKline(...)",
    "Current final-candle field, expected to include data.kline.final",
    "Current [subscription acknowledgement](https://siebly.io/reference/glossary#subscription-acknowledgement) event, expected to be response for SUBSCRIBE acknowledgement",
    "Current reconnect hook, expected to include reconnected",
    "Current shutdown method, expected to include closeAll()"
  ],
  "workflow": [
    "Create public REST and WebSocket clients without API keys.",
    "Open the public WebSocket and send the selected product group kline subscription before REST backfill.",
    "Wait for the real exchange [subscription acknowledgement](https://siebly.io/reference/glossary#subscription-acknowledgement) path. Do not treat socket open or subscribe() return as acknowledgement.",
    "Buffer live kline events while REST backfill is running.",
    "Backfill recent candles over REST into an in-memory store keyed by symbol, interval, and candle open time.",
    "Replay buffered events in deterministic order, skipping stale or duplicate records.",
    "Do not run strategy, indicator, signal generation, optional external alert, [order-intent](https://siebly.io/reference/glossary#order-intent), or account-decision workflows until [subscription acknowledgement](https://siebly.io/reference/glossary#subscription-acknowledgement), backfill, replay, and [readiness](https://siebly.io/reference/glossary#readiness-gate) are complete.",
    "If the data type has a finality signal, run strategy, indicator, signal generation, optional external alert, [order-intent](https://siebly.io/reference/glossary#order-intent), or account-decision workflows only after that final/closed/terminal signal.",
    "After reconnect, pause workflow readiness, resync over REST, replay buffered events, then re-enable candle-close processing.",
    "Handle process signals and close SDK WebSocket connections before exit."
  ],
  "lifecycleChain": [
    "config scope",
    "product/symbol/stream identity",
    "SDK REST/read method",
    "SDK WebSocket subscription",
    "subscription acknowledgement",
    "buffered live event",
    "historical REST/read row",
    "normalized store key",
    "dedupe or replay decision",
    "readiness state",
    "downstream side effect",
    "reconnect/resync boundary"
  ],
  "validationFixtures": [
    "candle_startup_requires_subscription_ack_backfill_replay_before_downstream_workflows",
    "open_candle_updates_store_without_downstream_signal",
    "final_candle_runs_downstream_once_after_replay",
    "duplicate_final_candle_after_reconnect_is_ignored",
    "out_of_order_candle_buffer_replays_by_candle_time_then_receive_time",
    "malformed_or_wrong_symbol_candle_is_logged_and_skipped",
    "reconnect_resync_blocks_candle_close_workflow_until_complete",
    "public_only_pipeline_has_no_private_clients_or_order_endpoints"
  ],
  "completionGate": "Do not mark the pipeline complete until three consecutive full data-lifecycle review passes produce no code, tests, fixtures, or documentation changes.",
  "stateGates": [
    {
      "state": "transport_open",
      "source": "WebSocket open event",
      "requiredBeforeWorkflow": false
    },
    {
      "state": "subscription_acknowledged",
      "source": "Package-specific [subscription acknowledgement](https://siebly.io/reference/glossary#subscription-acknowledgement) event",
      "requiredBeforeWorkflow": true
    },
    {
      "state": "rest_backfill_complete",
      "source": "REST candle backfill result",
      "requiredBeforeWorkflow": true
    },
    {
      "state": "buffered_replay_complete",
      "source": "Local replay of buffered live events",
      "requiredBeforeWorkflow": true
    },
    {
      "state": "live_processing_enabled",
      "source": "Local readiness flag after reconciliation",
      "requiredBeforeWorkflow": true
    }
  ],
  "safety": [
    "No API keys are required.",
    "Do not add private clients, account reads, order placement, cancellation, or amendment.",
    "Open candles may update local state, but cannot trigger strategy, indicator, signal generation, optional external alert, [order-intent](https://siebly.io/reference/glossary#order-intent), or account-decision workflows.",
    "Reconnects must not create duplicate candles or duplicate workflow executions.",
    "Do not mark the pipeline complete until three consecutive full data-lifecycle 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."
  }
}
