Polytraders Dev Guide
internal
v3 spine Phase 1 · Shared contracts 9 demo-wired · 0 shadow-ready · 0 production-live · 100 pending · 109 total 15/33 infra tasks the plan status board

Guardrail template

Copy templates/guardrail-bot/ into the implementation repo. Fill in decide(). Run the fixtures.

Files

templates/guardrail-bot/
  README.md
  bot.ts
  config.schema.json
  default.config.json
  input.fixture.json
  expected.output.json
  tests.spec.ts

Bot interface bound

This template implements Bot<OrderIntent, RiskVote>. The contract is the canonical bot interface.

The only function you write

async decide(input: OrderIntent, ctx: BotContext): Promise<RiskVote> {
  // 1. Cheap rejects first
  if (ctx.killSwitchActive) {
    return reject(input.intentId, "RISK_KILL_SWITCH_ACTIVE", ctx);
  }

  // 2. Freshness check
  const snap = ctx.signal<MarketSnapshot>("market_snapshot");
  if (!snap || ctx.now() - snap.observedAt > this.config.parameters.max_market_data_age_ms) {
    return reject(input.intentId, "RISK_STALE_BOOK", ctx);
  }

  // 3. Domain check
  if (!isWithinExposureCap(input, this.portfolio)) {
    return reject(input.intentId, "RISK_PORTFOLIO_LIMIT", ctx);
  }

  // 4. Approve
  return approve(input.intentId, ctx);
}

What's already wired for you

Promotion checklist

  1. Implement decide().
  2. Run npm test — all four test classes must pass.
  3. Open a PR with the bot's spec page linked in the description.
  4. Promote through the modes ladder: stub → shadow → advisory → enforced.