// What leaves your machine, and what does not

Telemetry

FULCRUMAXE can report anonymous counters back to this site. It is off until you turn it on, it sends integers and nothing else, and this page exists so you can decide with the actual message in front of you rather than a description of it.

The site has said since launch that the team’s own telemetry store never leaves the machine it runs on, and that is still true — the numbers on the long record come from this project’s own install. This is a different thing: an opt-in channel for other people’s installs, built so that turning it on costs you nothing you would mind losing.

What it never sends

There is no field for any of these, which is a stronger statement than a promise not to fill them in. The schema is a closed set; the server drops anything outside it before storage and names what it dropped in the response, so a client sending something it should not is told immediately rather than silently ignored.

Everything it would send

This is the whole message. Not a summary of it — the complete body, generated from the same file the server validates against, so this page cannot describe a field the endpoint does not accept or omit one it does.

{
  "install": "a3f91c47e2b84d60a1f5c93b7e204d8f",
  "version": "2026.09.12",
  "os": "linux",
  "window_hours": 24,
  "counts": {
    "spawns": 41,
    "prs_opened": 12,
    "prs_merged": 11,
    "gate_pass": 33,
    "gate_fail": 4,
    "sent_back": 6,
    "loop_iterations": 96,
    "discussions_filed": 5
  },
  "failures": {
    "rate_limit": 7,
    "gate_timeout": 1,
    "worktree_contamination": 1
  }
}

The counters

Integers over the reporting window, nothing else. Each is capped at 100,000; a larger value is clamped rather than believed.

FieldCounts
spawnsAgents spawned
prs_openedPull requests opened
prs_mergedPull requests merged
gate_passMerge gates passed
gate_failMerge gates failed
sent_backReviews that sent a change back
loop_iterationsLoop iterations
discussions_filedDiscussions filed

The failure kinds

A closed set. The point of this half is to learn what actually breaks on other people’s machines rather than only how often something ran — but an error string would carry paths, repository names and occasionally credentials, so a client maps its own errors onto these fixed names. Anything else is dropped by the server and named back in the response.

FieldMeans
rate_limitHit a GitHub or model rate limit
authAuthentication or token scope failure
worktree_contaminationA worktree left the checkout on the wrong branch
gate_timeoutA merge gate never reported
ci_redCI failed on the head commit
sandbox_deniedThe sandbox hook refused an action
spawn_failedAn agent could not be spawned
plane_mismatchA call went to the wrong repository plane
state_dir_missingThe external state directory was absent or broken
budget_exhaustedThe cost ceiling stopped work

And the rest of the body

What has been reported

Reading the totals…

Turning it off, and erasing it

Off is the default and stays the default; nothing is sent unless you set the dial. The install id is 32 random characters in one file — delete it and the next report is from a stranger. To remove what has already been sent, one request is enough:

curl -X DELETE https://fulcrumaxe.dev/api/telemetry \
  -H 'content-type: application/json' \
  -d '{"install": "<your id>"}'

No account, no verification, no email. Knowing the id is the only claim anyone could make to it, and asking for more would mean collecting more.

Reporting a bug from inside a run

Separate from the counters, and separate again from the form on this site: POST /api/report takes one structured bug or feature request from an install. The summary is yours to write and free text — so the endpoint refuses anything that looks like a path, a stack trace, a diff, an email address or a credential, rather than accepting it and stripping it. Left alone, the one thing an automated reporter will do is paste the error it just caught.

GET /api/telemetry and GET /api/report both return exactly what they accept, without you sending anything first. Filing one takes a single command:

curl -X POST https://fulcrumaxe.dev/api/report \
  -H 'content-type: application/json' \
  -d '{
    "kind": "bug",
    "category": "coldstart",
    "version": "2026.09.12",
    "summary": "Provisioning halts at the labels step on a repo where
                the merge-gate labels already exist, instead of treating
                them as satisfied and moving on."
  }'

category is one of ten fixed values, listed by the GET. The summary is yours — and if it contains a path, a stack trace, a diff or anything credential-shaped the request is refused rather than cleaned up, because a stripped report looks deliberate and an automated reporter’s first instinct is to paste the error it just caught.

This page is generated by tools/build-telemetry-page.py from lib/telemetry-schema.js, the file the endpoint validates against. Nothing on it is written by hand.