runtime-gap-windsurf.md

Subject: Windsurf runtime parity on Robert's dev machine. Status: absent. Parity score is N/A, not zero. Measured: 2026-04-18.


Measured facts

Windsurf binary is not on PATH on this machine:

$ which windsurf
windsurf not found
# exit code: 1

Bootstrap report agrees:

$ jq '.runtimes[] | select(.name=="windsurf")' .bootstrap-report.json
{
  "name": "windsurf",
  "present": false,
  "decision": "absent"
}

Source: /Users/robertboulos/projects/snappy-os/.bootstrap-report.json (lines 54-58).

Why parity is N/A, not 0.0

state/log/parity.ndjson contains zero rows with runtime: "windsurf". Same rule as Cursor: a missing row is not a failed row. program.md reports this correctly in the parity table as n/a; this page exists so downstream readers stop hand-waving "probably works via the rules file."

What sync does write

The repo ships .windsurfrules at the root:

$ ls /Users/robertboulos/projects/snappy-os/.windsurfrules
.windsurfrules

Maintained by state/bin/sync-runtimes.ts sync (see program.md § Self-bootstrap → Step 4). Same content as CLAUDE.md. Windsurf, per public docs, reads this file as static session context; no hook system is documented.

What we do NOT know from this machine

  1. Whether .windsurfrules is ingested end-to-end without truncation.
  2. Whether Windsurf's Cascade agent calls state/bin/ tools correctly.
  3. Whether there is any execution-time surface analogous to Claude Code's UserPromptSubmit.

These are empirical questions, not rhetorical ones. They need a machine with Windsurf installed and a parity probe run.

How to promote this from N/A to a real number

On a machine with Windsurf installed:

cd ~/projects/snappy-os
which windsurf                            # exit 0 expected
npx snappy-os bootstrap --apply
npx tsx state/lint/parity-test.ts --runtime windsurf
# aggregate:
node -e 'const rows=require("fs").readFileSync("state/log/parity.ndjson","utf8").trim().split("\n").map(JSON.parse); const w=rows.filter(r=>r.runtime==="windsurf"); console.log("n="+w.length, "mean="+(w.reduce((a,b)=>a+b.score,0)/w.length).toFixed(3))'

Until that runs, the honest answer stays N/A.

<!-- kernel-ok: wiki page documenting runtime absence with cited measurements -->