{
 "service": "rok-advisor-staging",
 "mission": "M07 intake L0-L2 (PROJECT_SCOPE 6.5)",
 "routes": {
  "GET /healthz": "health check (open)",
  "GET /": "the intake page (HTML)",
  "GET /static/{intake.css,intake.js}": "the page's assets",
  "GET /api": "this",
  "POST /extract": "one image -> a vision read; requires ROK_STAGING_TOKEN (and ANTHROPIC_API_KEY on the service)",
  "POST /intake": "intake ladder L0-L2; requires ROK_STAGING_TOKEN (X-ROK-Token) AND a signed-in session: the __Host-sow_session cookie (with Origin == APP_ORIGIN) or Authorization: Bearer <Supabase access token>",
  "GET /signin, /signup, /reset, /account, /auth/confirm": "first-party sign-in pages (A2); GET /auth/confirm makes no Supabase call",
  "GET /auth/session": "{signed_in, email} for the current session",
  "POST /auth/{signup,signin,signout,reset-request,confirm,update-password}": "first-party sign-in; requires ROK_STAGING_TOKEN; every Supabase call is server-side",
  "POST /ask": "M09 three-layer why (why.l1/l2/l3) over any of four serving paths; requires ROK_STAGING_TOKEN"
 },
 "intake_body": {
  "kingdom_number": "int  -- L0 on its own",
  "spend": "number -- USD per month; the C-3245 band is derived from it. With power -> L1. The page sends a band's anchor_usd_per_month from spend_bands below",
  "power": "int|str",
  "screenshot_read": "obj  -- fields a vision adapter already read (POST /extract produces one); -> L2",
  "entered": "obj  -- {field: value} the user TAPPED IN. Merged as source=declared; outranks a machine read; a hard-tier field is accepted here and never from the model",
  "today": "YYYY-MM-DD (optional, for deterministic replay)",
  "capture_ref": "str (optional)",
  "user_id": "NOT READ FROM THE BODY. Every correction is filed under the id of the verified session (Authorization: Bearer). A body user_id naming anyone else is a 403; one naming the caller is ignored (G-SEC-INTAKE-AUTHID-1)"
 },
 "extract_body": {
  "content-type": "one of image/png, image/jpeg, image/gif, image/webp",
  "body": "the raw image bytes, at most 5242880",
  "returns": "{vision_read: {fields}, audit, model_calls} -- feed vision_read to POST /intake as screenshot_read"
 },
 "ask_body": {
  "kind": "one of cell, advise, rank, build (default `cell`). `cell` is the POPULATION-MEASURED path over the recorded-battle dataset -- the only one that can carry an evidence floor, because the pair models carry no n. `advise` and `rank` are the pair models (they render KIT-MATH by their own label). `build` is the solver synthesis",
  "role": "required for cell/advise/rank. R192: ordinal WITHIN a role only, so there is no all-roles ranking and the field is not optional",
  "primary": "commander name. For kind=cell it is OPTIONAL -- omitted, you get the role's floored pick; supplied with `secondary`, you get THAT ordered cell, which is how a sub-floor abstention is reachable",
  "secondary": "commander name. Order matters and is not relaxed: the reverse order is a different cell with its own n",
  "pairs": "[[primary, secondary], ...] -- kind=rank only",
  "troop": "str (optional) -- kind=build only",
  "context": "str (optional) -- the role's own frame/target/enemy",
  "lang": "one of en, es (default en). Names resolve through the localization NameMap; why.l3 is language-neutral by ruling and is byte-identical across languages",
  "returns": "{why: {l1, l2, l3, lang}, raw: the engine's own verdict unchanged, kind, lang, role}. A render the three-layer contract REFUSES comes back 422 with the refusal quoted -- the refusal is the correct answer, not a failure"
 },
 "ask_roles": {
  "dataset": {
   "version": "v0_3",
   "harvest_date": "2026-08-22",
   "ranked_pairs": 56,
   "file": "execution/data/ROK_RokBattles_DRASTC_v0_3.json"
  },
  "floors": {
   "serving": 100,
   "holdout": 12
  },
  "roles": {
   "rally": {
    "cell": "rally",
    "recorded": 38,
    "clears_serving_floor": 9,
    "below_holdout_floor": 13
   },
   "garrison": {
    "cell": "garrison",
    "recorded": 49,
    "clears_serving_floor": 22,
    "below_holdout_floor": 10
   },
   "swarm": {
    "cell": "swarming",
    "recorded": 56,
    "clears_serving_floor": 55,
    "below_holdout_floor": 0
   },
   "openfield": {
    "cell": "open_field",
    "recorded": 56,
    "clears_serving_floor": 56,
    "below_holdout_floor": 0
   }
  }
 },
 "build": {
  "commit": "db645c1e7d622ede819a39101efe06cc8496ec10",
  "short": "db645c1",
  "source": "render runtime (RENDER_GIT_COMMIT)",
  "branch": "main"
 },
 "spend_bands": [
  {
   "band": "f2p",
   "usd_floor": 0,
   "usd_ceiling": 0,
   "anchor_usd_per_month": 0,
   "binding_constraint": "money IS the constraint",
   "guidance": "Never let a purchase BE the answer. Lead with the free path; the paid option is a labelled alternative, never the recommendation.",
   "source": "Joseph GT 2026-08-10 (C-3245)"
  },
  {
   "band": "low",
   "usd_floor": 1,
   "usd_ceiling": 99,
   "anchor_usd_per_month": 1,
   "binding_constraint": "money IS the constraint",
   "guidance": "Single-purchase decisions. Value-per-dollar dominates; the cheap tiers ARE the answer. Joseph: 'under $50-100/month' -- the 50-100 zone is fuzzy, ask if it matters.",
   "source": "Joseph GT 2026-08-10 (C-3245)"
  },
  {
   "band": "mid",
   "usd_floor": 100,
   "usd_ceiling": 400,
   "anchor_usd_per_month": 101,
   "binding_constraint": "money IS the constraint",
   "guidance": "Value-per-dollar engine + deadline awareness. Budget is REAL and FIXED -- never present a plan that quietly exceeds it.",
   "source": "Joseph GT 2026-08-10 (C-3245)"
  },
  {
   "band": "high",
   "usd_floor": 401,
   "usd_ceiling": 1000,
   "anchor_usd_per_month": 401,
   "binding_constraint": "TRANSITIONAL -- ask the goal",
   "guidance": "The flip zone. Value still matters but tempo begins to. Do NOT assume either; ask what they are trying to achieve and let the goal pick the metric.",
   "source": "Joseph GT 2026-08-10 (C-3245)"
  },
  {
   "band": "whale",
   "usd_floor": 1001,
   "usd_ceiling": 3500,
   "anchor_usd_per_month": 1001,
   "binding_constraint": "money is likely NOT the constraint",
   "guidance": "Tempo starts to outrank value-per-dollar. State BOTH and let them choose -- lead with the recommendation, keep the value note attached.",
   "source": "Joseph GT 2026-08-10 (C-3245)"
  },
  {
   "band": "kraken",
   "usd_floor": 3501,
   "usd_ceiling": null,
   "anchor_usd_per_month": 3701,
   "binding_constraint": "money is NOT the constraint -- TEMPO is",
   "guidance": "DOMINANCE is the goal and it does not need asking. Optimise TEMPO. Lead with the recommendation; the value-per-dollar caution is a FOOTNOTE, never the answer. Nobody spends this casually. Baseline $3,500-$5,000/mo, but SPIKING to $15,000+ in heavy months -- see SPEND_IS_SPIKY.",
   "source": "Joseph GT 2026-08-10 (C-3245)"
  }
 ],
 "persistence": {
  "gap": "G-M07-SUPABASE-WIRE-1",
  "what": "intake corrections and screenshot objects are not persisted; a one-tap correction is live in this response and does not survive a restart of this service",
  "missing_env": [
   "SUPABASE_URL",
   "SUPABASE_SERVICE_ROLE_KEY"
  ],
  "fill_path": "apply supabase/migrations/0003_intake_l0_l2.sql to the project, then set SUPABASE_URL and SUPABASE_SERVICE_ROLE_KEY on the service (Render -> Environment) and redeploy. See JOSEPH_STEPS_SUPABASE.md.",
  "still_available": "L0, L1 and L2 all answer normally; only the durability of a correction is affected"
 },
 "note": "L3 is out of scope for M07 by mission ruling."
}