LandfallDocs
Reference · Canvas

Canvas widgets

The war room's canvas is built by the investigator agent from what it reads. Every card is one of the widget types below, rendered from validated data, and every query-backed card re-reads its source for the window you choose.

Widget types

The same catalog drives the agent's add_widget tool, the bridge's share_with_room widget argument, the hosted connector's describe_widget_types read and the canvas renderer. Adding a type anywhere means adding it here.

Stat tile stat

One current number with its direction and baseline, for a headline metric.

  • current error rate
  • p99 latency now
  • healthy host count
  • requests per second
  • any single KPI

Can be backed by a signed query that re-reads live. Follows the canvas time window.

War room · Canvas · Stat tile
The Stat tile widget as it renders on the canvas.

Data shape

{ value: number, unit?, decimals?, delta?: number, deltaLabel?, trend?: "up"|"down"|"flat", tone?: "good"|"warning"|"serious"|"critical"|"neutral", baseline?: number, baselineLabel?, spark?: number[] }

Example

{
  "value": 6.7,
  "unit": "%",
  "decimals": 1,
  "delta": 6.4,
  "deltaLabel": "↑ 22×",
  "trend": "up",
  "tone": "critical",
  "baseline": 0.3,
  "baselineLabel": "baseline 0.3%",
  "spark": [
    0.3,
    0.3,
    0.4,
    0.3,
    2.1,
    5.8,
    6.4,
    6.7
  ]
}

Time series chart

One or more metrics over time on a shared clock axis, with optional thresholds and deploy markers.

  • error rate over the incident
  • latency trend
  • traffic volume
  • one metric split by region, zone or service
  • comparing a metric before and after a change

Can be backed by a signed query that re-reads live. Follows the canvas time window. Up to 8 series; the rest fold into one "other".

War room · Canvas · Time series
The Time series widget as it renders on the canvas.

Data shape

{ series: [{ label, unit?, decimals?, points: [{ t: ISO-8601, v: number }] }] (max 8), yAxis?: { min?, max?, unit?, label? }, thresholds?: [{ value, label?, tone? }], markers?: [{ t: ISO-8601, label, kind? }] }

Example

{
  "series": [
    {
      "label": "eu-west-1",
      "unit": "%",
      "points": [
        {
          "t": "2026-09-04T14:00:00Z",
          "v": 0.3
        },
        {
          "t": "2026-09-04T14:15:00Z",
          "v": 0.3
        },
        {
          "t": "2026-09-04T14:30:00Z",
          "v": 0.4
        },
        {
          "t": "2026-09-04T14:35:00Z",
          "v": 9.8
        },
        {
          "t": "2026-09-04T14:45:00Z",
          "v": 12.4
        }
      ]
    },
    {
      "label": "us-east-1",
      "unit": "%",
      "points": [
        {
          "t": "2026-09-04T14:00:00Z",
          "v": 0.3
        },
        {
          "t": "2026-09-04T14:15:00Z",
          "v": 0.3
        },
        {
          "t": "2026-09-04T14:30:00Z",
          "v": 0.4
        },
        {
          "t": "2026-09-04T14:35:00Z",
          "v": 0.4
        },
        {
          "t": "2026-09-04T14:45:00Z",
          "v": 0.4
        }
      ]
    }
  ],
  "thresholds": [
    {
      "value": 5,
      "label": "alert · 5%",
      "tone": "warning"
    }
  ],
  "markers": [
    {
      "t": "2026-09-04T14:32:00Z",
      "label": "deploy #4127",
      "kind": "deploy"
    }
  ]
}

Table table

Ranked rows with typed columns: status codes as pills, shares as bars, numbers aligned.

  • top error URLs
  • slowest endpoints
  • hosts by error count
  • targets and their health
  • anything ranked

Can be backed by a signed query that re-reads live. Follows the canvas time window.

War room · Canvas · Table
The Table widget as it renders on the canvas.

Data shape

{ columns: [{ key, label, type: "string"|"number"|"time"|"status"|"share" }], rows: [{ [key]: string | number | { v, tone? } }], highlightKey? }

Example

{
  "columns": [
    {
      "key": "path",
      "label": "Path",
      "type": "string"
    },
    {
      "key": "code",
      "label": "Code",
      "type": "status"
    },
    {
      "key": "count",
      "label": "Count 5m",
      "type": "number"
    },
    {
      "key": "share",
      "label": "Share",
      "type": "share"
    }
  ],
  "rows": [
    {
      "path": "/api/checkout/session",
      "code": 502,
      "count": 4812,
      "share": 18.2
    },
    {
      "path": "/api/cart",
      "code": 502,
      "count": 3109,
      "share": 14.7
    }
  ]
}

Log view logView

Raw log lines in the window, colored by level, with timestamps.

  • origin error lines
  • the first errors after a deploy
  • a filtered stream from one service

Can be backed by a signed query that re-reads live. Follows the canvas time window.

War room · Canvas · Log view
The Log view widget as it renders on the canvas.

Data shape

{ lines: [{ t?: ISO-8601, level?: "error"|"warn"|"info"|"debug", message, fields? }], truncated?: boolean }

Example

{
  "lines": [
    {
      "t": "2026-09-04T14:33:02Z",
      "level": "error",
      "message": "CloudFront origin 502 Bad Gateway path=/api/checkout edge=eu-west-1"
    },
    {
      "t": "2026-09-04T14:33:05Z",
      "level": "warn",
      "message": "target i-0a1 draining (2/6 healthy)"
    }
  ]
}

Timeline timeline

Discrete events in time order, each with a kind badge; a correlated one is highlighted.

  • recent deploys and config changes
  • feature-flag flips
  • alarms as they fired
  • what changed before the incident

Can be backed by a signed query that re-reads live. Follows the canvas time window.

War room · Canvas · Timeline
The Timeline widget as it renders on the canvas.

Data shape

{ events: [{ t: ISO-8601, label, kind?: "deploy"|"config"|"flag"|"alarm"|string, detail?, correlated?: number|boolean, tone? }] }

Example

{
  "events": [
    {
      "t": "2026-09-04T14:32:00Z",
      "label": "web-edge #4127 · task def :47",
      "kind": "deploy",
      "correlated": 0.94
    },
    {
      "t": "2026-09-04T14:18:00Z",
      "label": "checkout-v2 rollout 25% → 50%",
      "kind": "flag"
    }
  ]
}

World map geo

Regions or points of presence on a world map, colored by status, to show WHERE an incident is.

  • error rate by region
  • edge locations affected
  • latency by point of presence
  • which regions are healthy
  • any value keyed by a place

Can be backed by a signed query that re-reads live. Follows the canvas time window. Up to 60 series; the rest fold into one "other".

War room · Canvas · World map
The World map widget as it renders on the canvas.

Data shape

{ points: [{ place: "eu-west-1"|"DUB"|"Frankfurt"|"Brazil"|…, label?, lat?, lon?, value?, unit?, tone?, pulse?, detail? }], unit?, legend? } — coordinates are filled from the place name when omitted

Example

{
  "unit": "%",
  "points": [
    {
      "place": "eu-west-1",
      "value": 12.4,
      "tone": "critical",
      "pulse": true,
      "label": "eu-west-1 · 12.4% 5xx"
    },
    {
      "place": "eu-central-1",
      "value": 3.2,
      "tone": "warning"
    },
    {
      "place": "us-east-1",
      "value": 0.4,
      "tone": "good",
      "label": "us-east-1 · 0.4%"
    },
    {
      "place": "ap-southeast-1",
      "value": 0.3,
      "tone": "good"
    }
  ]
}

Code finding codeFinding

A code snippet pinned to a commit, with a permalink, captured when the finding was made.

  • the exact lines a deploy changed
  • a suspicious configuration value in source
  • evidence read from a repository

Data only: captured once, never re-read.

War room · Canvas · Code finding
The Code finding widget as it renders on the canvas.

Data shape

{ codeRef: { owner, repo, ref, path?, lineStart?, lineEnd?, pullRequestNumber?, permalink }, snippet: { lines: string[], startLine } }

Example

{
  "codeRef": {
    "provider": "github",
    "owner": "acme",
    "repo": "web-edge",
    "ref": "9f3c1e2a",
    "path": "src/origin.ts",
    "lineStart": 41,
    "lineEnd": 44,
    "permalink": "https://github.com/acme/web-edge/blob/9f3c1e2a/src/origin.ts#L41-L44"
  },
  "snippet": {
    "startLine": 41,
    "lines": [
      "const ttl = 120;",
      "export const origin = alb(\"web-edge-tg\", { ttl });"
    ]
  }
}

Time windows

War room · Canvas · window and live controls
The canvas toolbar: a Window select on Incident window, the resolved window label, a Live checkbox with an interval select on every 15s, a Refresh now button, and the status line updated 3s ago with the live widget count.

One control row above the cards scopes every query-backed widget. The default is the incident window: from 30 minutes before the incident opened until now. A window can be at most 7 days; reversed or future ranges are refused with the reason.

  • Incident window (fixed start, slides while live)
  • Last 15 min (15m ending now, slides while live)
  • Last 1 hour (1h ending now, slides while live)
  • Last 3 hours (3h ending now, slides while live)
  • Last 6 hours (6h ending now, slides while live)
  • Last 24 hours (24h ending now, slides while live)
  • Custom: an absolute start and end.

An agent may give a widget its own default window (for example the five minutes it looked at); the card names it in its head and the canvas control overrides it while selected.

Live, snapshot, stale

Each card carries exactly one freshness badge, and it never claims more than it knows.

  • building: the agent requested the widget and the build is still running.
  • live · updated Ns ago: the widget is in the refresh cycle and its last read succeeded. Live refreshes every 5, 15, 30 or 60 seconds, in one request for the whole canvas, and can be turned off.
  • stale · last good: the last refresh failed; the card keeps the data it last had and says why.
  • snapshot · HH:MM: data-only widgets (shared by an edge agent, the investigation status, a code finding) captured at that time and never re-read. With Live off, every query-backed card is a snapshot of its last read.
  • no data in this window: the source answered with no points for the selected window; try the incident window.
  • failed: the read failed and nothing good was ever shown for this window; the reason is on the card.

While a refresh is in flight the previous render stays visible, dimmed; a refresh button on each query-backed card and on the toolbar re-reads immediately. Widgets survive a server restart: the durable record carries everything needed to rebuild them.

Agents

The investigator agent puts a widget on the canvas with the same source, operation, parameters and connection it read with, plus the window it looked at and a grouping hint when values split by region or zone. It picks the type from this catalog, which it can ask for at any time with describe_widget_types. Your own coding agent, connected through the bridge, shares data-only widgets of any type here with share_with_room; the bridge exposes the same catalog. The world map places regions, edge locations, cities and countries by name, so a widget only has to say eu-west-1 or DUB.