SWITCHBOARD
WINDOW
PERIOD SPEND / CAP
{{ spendNow }} / {{ spendCap }}
STATE
DR
dana-reyes
human · via switchboard-auth
FLEET PAUSED No identity will be dispatched. Matched events are recorded and dropped, not queued.
PARTIAL Lane 1 is incomplete. 3 of 412 deliveries in this window failed to parse, so their downstream paths are missing. delivery 7f31c9a2-4d18-11ef-9b3e
SIGNAL MAP · {{ org }}

No webhook deliveries in this window.

The map is built from deliveries, not from configuration. It stays empty until an app you operate is installed on a repository and an injection point matches an event. Here is the shape it will take.

{{ e.num }} {{ e.label }}
{{ e.body }}
{{ e.hint }}
Last delivery received: never · webhook endpoint verified 2026-08-11 09:14Z
01 SOURCES {{ srcMeta }}
group · data
Deliveries present but unparseable: payload schema mismatch on workflow_run.completed.
delivery 7f31c9a2-4d18-11ef-9b3e
hook_id 481920377 · attempt 3/3
{{ r.name }} {{ r.d }}
02 TRIGGERS {{ trigMeta }}
{{ t.ev }} {{ t.n }}
@MENTION {{ t.rule }}
{{ t.cond }}
03 IDENTITIES {{ identMeta }}
{{ a.handle }} [bot] {{ a.stLabel }}
{{ a.station }}
{{ s.k }}
{{ s.v }}
04 OUTCOMES {{ outMeta }}
{{ o.label }} {{ o.n }}
{{ o.sub }}
SIGNAL LIST
Below 1080px the four lanes lose the horizontal room they need to stay legible, so the map degrades to the same paths ranked by volume. Filters, the drawer, and replay all still apply.
{{ tStart }} {{ tMid }} {{ tEnd }}
{{ replayPos }} · {{ replayT }}
{{ replayLine }}
REPLAY IDLE
{{ eventTotal }} events · press PLAY to step through

Identities

{{ identMeta }} · one separately installed GitHub App per row

Square glyph = an app you operate. Round avatar = a human. Handles are canonical and case-sensitive in mention matching.

{{ det.handle }} [bot] {{ det.stLabel }}
{{ det.charter }}
{{ det.appId }} · {{ det.verLive }} {{ det.label }}
{{ det.stLabel }} {{ det.stHead }}
{{ det.stBody }}
{{ det.stRef }}
{{ s.k }}
{{ s.v }}
SUCCESS RATE
{{ det.success }}
SPEND · 14 PERIODS · DASHED LINE IS THE IDENTITY CAP {{ det.spendStr }} / {{ det.capStr }} · Aug 1 – 13
PRIMARY TRIGGER {{ det.primaryTrigger }} MODEL ROUTE {{ det.route }} CANONICAL HANDLE {{ det.mention }}
RUNSHAREPO · PRCONCLUSIONDURCOSTCONFIG
{{ v.id }} {{ v.label }} {{ v.note }} {{ v.when }}
Versions are immutable. A label is a movable pointer to exactly one version, so a rollback repoints the label and edits nothing.
{{ k.v }} {{ k.blast }}
{{ k.who }}
Blast radius is the point of this tab: a skill bundle pinned by several identities means one promotion changes several agents' behaviour at once.
SPENT · Aug 1–13
{{ det.spendStr }}
of {{ det.capStr }} identity cap
FORECAST · Aug 31
{{ det.forecast }}
at the current rate
ENFORCEMENT RUNG
{{ det.ladderRung }}
REST requests · this installation · current hour{{ det.rest }}
GraphQL points · metered separately{{ det.gql }}
PERMISSION SCOPES GRANTED TO THIS APP
{{ sc.v }} {{ sc.why }}
CREDENTIAL · REFERENCED, NEVER STORED
{{ det.app.smLabel }} {{ det.app.secretRef }}
FINGERPRINT {{ det.app.fingerprint }} RESOLVED AT {{ det.app.resolvedAt }} ROTATION {{ det.app.rotated }} · {{ det.app.rotLabel }} TOKEN TTL {{ det.app.ttl }}
The key body is never sent to SWITCHBOARD. It holds a reference, resolves it at mint time, and shows you the fingerprint so you can confirm which key is in play without seeing it.
{{ ip.name }} {{ ip.stateLabel }} published {{ ip.pubVer }} → draft {{ ip.draftVer }}
INJECTION POINTS · {{ injCount }}
PANE 1 TRIGGER
{{ ip.question }}
·
{{ s.v }}
RECURSION fired by {{ ip.recursive }}
An agent's own button click is a trigger. Multi-step work composes out of single-turn runs: the run posts an action, a human clicks it, GitHub delivers check_run.requested_action carrying the identifier, and this injection point wakes the next turn.
PANE 2 CONDITIONS matched {{ ip.matchN }} of the last {{ ip.matchOf }} pull requests
ALL OF
PAIRED GLOB changed X without changing Y {{ p.hit }}
CHANGED {{ p.a }} WITHOUT {{ p.b }}
{{ c.i }} {{ c.op }} {{ c.val }} {{ c.hit }}
MENTION MATCH First-class condition, not a regex you maintain.
GitHub does not deliver mention notifications to apps and does not offer app handles in autocomplete, and @name[bot] does not render as a mention link. SWITCHBOARD subscribes to the comment webhook and parses the body for the canonical handles below, tolerating a leading @, the [bot] suffix, and code-fence exclusion.
{{ t.handle }}
MATCH PREVIEW · LAST 3 COMMENT BODIES
{{ p.verdict }} {{ p.body }} {{ p.why }}
DRY RUN {{ dry.repo }} #{{ dry.pr }} {{ dry.sha }} nothing was posted
CONDITION EVALUATION
{{ d.label }} {{ d.verdict }}
{{ pp.v }}
PROJECTED COST
{{ dry.cost }}
PROJECTED LATENCY
{{ dry.latency }}
TOKENS
{{ dry.tokens }}
WOULD HAVE POSTED
{{ dry.summary }}
{{ dry.meta }}
BATCH DRY RUN · LAST 20 PULL REQUESTS {{ batch.fired }} would fire · {{ batch.total }} projected
PRREPO · TITLEVERDICTCOSTLATENCY
#{{ b.pr }} {{ b.repo }} {{ b.title }} {{ b.verdict }} {{ b.cost }} {{ b.lat }}
PANE 3 BINDING
{{ ip.handle }} [bot]
{{ ip.charter }}
CONFIG
{{ ip.ver }} {{ ip.label }} {{ ip.labelNote }}
MODEL ROUTE {{ ip.route }} COST CEILING {{ ip.ceiling }} per invocation TOOL ALLOWLIST
{{ t.v }}
GITHUB PREVIEW what the check run will render as
{{ ip.checkName }}
{{ ip.handle }}[bot] · status completed
{{ ip.conclusion }}
{{ ip.summaryTitle }}
{{ ip.summary }}
ANNOTATIONS {{ ip.annCount }} of 50 per API request
{{ a.level }}
{{ a.path }}
{{ a.msg }}
ACTIONS {{ ip.actCount }} of 3 max
{{ a.desc }}
id {{ a.id }} {{ a.idLen }}/20 label {{ a.labLen }}/20 desc {{ a.descLen }}/40
CONCLUSION · SETTABLE BY AN APP
STALE Rendered on historical runs but never offered here — only GitHub sets it. startup_failure is not a check run conclusion at all; it belongs to check suites and workflow runs.

Runs

{{ runsMeta }}
RUNIDENTITYREPO · SHA · PRCONCLUSIONDURCOSTCONFIGWHEN

Budgets

org northwind-labs · {{ budget.period }} · {{ budget.periodFull }}
AXIS A MONETARY org · {{ budget.period }}
{{ budget.spent }} / {{ budget.cap }} cap {{ budget.spentPct }}
FORECAST TO Aug 31
{{ budget.fMid }}
CONE
{{ budget.fLo }} – {{ budget.fHi }}
BURN RATE
{{ budget.rate }}
{{ budget.rateNote }} · forecast lands at {{ budget.fPct }} of cap if the rate holds
AXIS B GITHUB RATE LIMIT per installation · current hour
The allowance belongs to the installation, not to a repo, and it is computed — not 5,000. REST counts requests, GraphQL spends points; summing them would be wrong, so they are separate meters.
{{ i.handle }}
{{ i.allow }}
REST{{ i.rest }} · {{ i.restPct }}
GRAPHQL pts{{ i.gql }} · {{ i.gqlPct }}
@auditor allowance {{ auditorFormula }}
PERIOD BURN-DOWN cumulative spend · forecast cone · version promotions
{{ m.who }}
{{ m.what }}
Aug 1Aug 13 · todayAug 31 · cap {{ budget.cap }}
Spend tripled on Aug 8. The promotion marker on the same day is @warden cfg_v18 -> cfg_v19, which widened the secret pattern set from 12 to 41 and moved the route from haiku to sonnet.
ENFORCEMENT LADDER
{{ l.rung }}
{{ l.at }}
{{ w.v }} none
Configured per node in the hierarchy. A child inherits its parent's ladder unless it declares its own.
BY IDENTITY · org · {{ budget.period }}
{{ b.n }}{{ b.amt }} / {{ b.cap }}
BY REPO · top 6 of 34
{{ b.n }}{{ b.amt }}
BY MODEL · routing is the cost strategy
{{ m.v }} {{ m.note }} {{ m.amt }}
HIERARCHY · org → repo → identity → injection point → invocation
SCOPECAPSPENTFORECASTENFORCEMENT
{{ t.name }} {{ t.kind }}
{{ t.cap }} {{ t.spent }} {{ t.forecast }} {{ t.enf }}
ANOMALY FEED
{{ a.kind }}
{{ a.head }}
{{ a.body }}
{{ a.ref }}
INVOCATIONS 40 of 50,000 rendered · windowed · org · {{ budget.period }}

Apps & Keys

7 operated apps · 1 sign-in app · no key material is rendered anywhere in this product
SIGN-IN APP · AUTHENTICATES YOU · DOES NOT DO WORK
SB
{{ signIn.name }} {{ signIn.appId }} ROUND AVATAR · NOT AN OPERATED APP
CAN {{ signIn.can }} CANNOT {{ signIn.cannot }}
{{ sc }}
OPERATED APPS · SQUARE GLYPH · THESE DO THE WORK
{{ a.display }} {{ a.handle }}[bot] {{ a.appId }} · {{ a.installs }}
{{ a.charter }}
{{ sc.v }}
WEBHOOK DELIVERIES · 24H
{{ a.hookLabel }}
REST HEADROOM
{{ a.rest }} per hr
{{ a.smLabel }} {{ a.secretRef }}
FINGERPRINT {{ a.fingerprint }}
ROTATED {{ a.rotated }} · {{ a.rotLabel }}
TOKEN TTL {{ a.ttl }} minted {{ a.lastMint }}
LAST AUTH FAILURE {{ a.authFail }}
ADD APP 4 steps · nothing is stored until step 4
{{ w.n }} {{ w.title }} {{ w.badge }}
{{ w.body }}
{{ w.detail }}
FAILURE MODE {{ w.fail }}
RESOLVE AND VERIFY · POSSIBLE OUTCOMES
{{ v.v }} {{ v.body }}

Versions

immutable numbered versions · labels are movable pointers to exactly one version
DEPLOYMENT TIMELINE · Aug 1 – 13 the same markers overlay the budget burn-down and the Signal Map
{{ t.when }}
{{ t.what }}
{{ t.kind }}
VERSIONED ENTITIES
{{ vers.selName }} {{ vers.selType }} {{ vers.selOwner }} affects {{ vers.affects }}
VERSIONAUTHORWHENCHANGE SUMMARYLABELS · ACTIONS
{{ r.id }} {{ r.author }} {{ r.when }} {{ r.summary }}
{{ l.v }}
PROMPT DIFF · WORD LEVEL · cfg_v18 → cfg_v19
cfg_v18
{{ vers.diffA }}
cfg_v19 · production
{{ vers.diffB }}
INLINE
{{ d.t }}
CANARY Two labels plus a split rule the router owns.
A label resolves to exactly one version, so a percentage cannot live on a label. The traffic percentage is a property of the route: the router reads both pointers and picks per invocation.
{{ p.label }} {{ p.ver }}
{{ p.pct }} of route traffic
COMPARISON · production vs canary
METRICv19 prodv20 canary
{{ c.k }} {{ c.a }} {{ c.b }}
v20 is 54% more expensive per invocation and 22% faster, and raises the action_required rate. On 40 sampled invocations that is a signal, not a conclusion.
{{ confirm.title }}
{{ confirm.body }}
{{ confirm.impact }}

Design reference

one screen · tokens, scale, and the status-encoding rules
COLOUR TOKENS · SEMANTIC ROLE
{{ t.g }}
{{ r.hex }} {{ r.role }} {{ r.use }}
TYPE SCALE
{{ t.spec }} {{ t.role }} {{ t.sample }}
SPACING SCALE
{{ s.v }}
ELEVATION
flat
nodes, rows, cards. Border only, no shadow.
drawer
one directional shadow, cast inward from the edge it slid from.
modal
the only surface that dims the app behind it.
STATUS ENCODING RULES
{{ r.head }}
{{ r.body }}
RESPONSIVE
This is a desktop tool and does not pretend otherwise. Below 1080px the Signal Map degrades to a ranked path list — the lanes need horizontal room the tablet does not have — while Budgets, Runs, and the kill switch keep working at 1024px because those are the on-call surfaces.
NOTIFICATIONS {{ notifCount }} unresolved
GO esc
403 PERMISSION DENIED

Your sign-in app cannot read {{ deniedScope }}.

SWITCHBOARD authenticated you through switchboard-auth with read:user and read:org. This surface needs the operator role on northwind-labs, which is granted in the org, not here.

signed in as dana-reyes · role viewer
request id 4c19a8f0-9d21-11ef-b3ac
NOT BUILT YET

{{ stubTitle }}

{{ stubBody }}

placeholder · direct this surface next
{{ drawerKicker }}
{{ edgeFrom }} {{ edgeTo }}
{{ s.k }}
{{ s.v }}
SHA / PRCONCLUSIONDURCOSTCONFIG
{{ dIdent.handle }} [bot]
{{ dIdent.station }}
{{ dIdent.mention }}
Canonical handle. GitHub does not autocomplete app handles or notify apps of mentions — SWITCHBOARD matches the body text.
{{ dIdent.stLabel }} {{ dIdent.stHead }}
{{ dIdent.stBody }}
{{ dIdent.stRef }}
SPEND · 14 PERIODS {{ dIdent.spend }} / {{ dIdent.cap }}
{{ s.k }}
{{ s.v }}
CONFIG VERSIONS
{{ v.id }} LIVE {{ v.note }} {{ v.when }}
PERMISSION SCOPES · MODEL ROUTE
{{ s.v }}
route{{ dIdent.route }}
KEY REF {{ dIdent.keyRef }} rotated {{ dIdent.rotated }}
RECENT RUNS
{{ dRun.id }} {{ dRun.conclusion }}
{{ m.k }} {{ m.v }}
PROVENANCE exactly what was live when this answered
TIMELINE · MODEL AND TOOL CALLS
{{ t.kind }} {{ t.step }} {{ t.dur }} {{ t.cost }}
{{ t.detail }}
{{ t.note }}
OUTPUT · AS POSTED
{{ dRun.checkName }} {{ dRun.conclusion }}
{{ dRun.sTitle }}
{{ dRun.body }}
{{ a.level }}
{{ a.path }}
{{ a.msg }}
{{ a.label }} {{ a.desc }}
CLICKED {{ a.clickNote }}
{{ dRun.bodyRef }}
CONVERSATION · DISCUSSION THREAD
MENTION GRAPH
{{ n.handle }}
{{ t.who }} {{ t.kind }} {{ t.when }}
{{ t.body }}
{{ toast }}
chart unset (not declared on the worker) declared · runtime Cloudflare-Workers observed · edge CMH observed