agentleFS
TentacleOperaTentacleOpera/switchboard/AGENTS.md

switchboard

AGENTS.md215 starsChanged 2 months agoMITView on GitHub

Delete buttons delete immediately. No confirm(), no window.confirm(), no modal showWarningMessage, no two-click patterns, no "Are you sure?". The user has demanded this repeatedly. Buttons are deliberately hard to misclick. Also a hard technical reason: window.confirm() is a silent no-op in VS Code webviews (sandboxed iframe without allow-modals — it always returns false). Any confirm gate added to src/webview/planning.js, src/webview/kanban.html, etc. makes the button do literally nothing. This exact bug broke the kanban delete-plan button (fixed 2026-06-11). If you find…

The file

We split this AGENTS.md into the rules it gives an agent

6 rules. About 0 are common, 3 are distinctive, and 3 are very specific to this project.

  • ≈0

    Common · estimate

    Many files like this have a rule of this kind.

  • ≈3

    Distinctive · estimate

    This author's own choices. Worth a look.

  • 3

    Very specific

    Tied to their project's names, files or tools. Probably skip.

  • Common
  • Distinctive
  • Very specific
  1. Very specific:

    Delete buttons delete immediately.

    line 5
  2. Distinctive:

    If you find a confirm gate in this codebase, it is a bug — remove it.

    line 9
  3. Distinctive:

    Do not describe this product as a VS Code extension.

    line 30
  4. Very specific:

    Precedent (2026-08): All four PlanIngestionEngine queue seams — setQueueHeadResolver, setQueuePacingResolver, setQueueTeamMembersResolver, …

    line 47
  5. Very specific:

    Treat src/ as the source of truth for review: Do NOT audit, check, or flag dist/ staleness during reviews or verification — a stale dist/ …

    line 87
  6. Distinctive:

    When unsure whether something shipped, assume it did and migrate — a no-op migration costs nothing.

    line 96

≈ “Common” is an estimate: at least 1 in 5 of the 40,246 AGENTS.md files we read have a rule of the same kind, not the same words. “Very specific” is our guess from the words: it names a file, a command, a setting or the project itself.

Keep what fits and drop the rest. Your version, ready for your agents.
Files
AGENTS.md

Switchboard — agent rules

NEVER add confirmation dialogs. NO EXCEPTIONS.

Delete buttons delete immediately. No confirm(), no window.confirm(), no modal showWarningMessage, no two-click patterns, no "Are you sure?". The user has demanded this repeatedly. Buttons are deliberately hard to misclick.

Also a hard technical reason: window.confirm() is a silent no-op in VS Code webviews (sandboxed iframe without allow-modals — it always returns false). Any confirm gate added to src/webview/planning.js, src/webview/kanban.html, etc. makes the button do literally nothing. This exact bug broke the kanban delete-plan button (fixed 2026-06-11).

If you find a confirm gate in this codebase, it is a bug — remove it. Multi-choice decision dialogs (e.g. 3-way conflict resolution) are allowed; plain confirm gates are not.

What this product is

A Raspberry Pi product. Switchboard is being rebuilt as an appliance: a board host running on a small box, with agent seats running on other machines. That is the shape every decision should serve.

  • The standalone host is primary. src/standalone/bootstrap.ts — the switchboard/npx CLI — is what actually runs on the Pi, on :7777, and is what a board deployment means. Measured: 182 MB RSS on a Pi 400 with no seats, so board-only fits 1 GB; board plus local agents wants 2 GB minimum, 4 GB comfortable.
  • One store, one host. One better-sqlite3 database owned by that host. Not libSQL (rejected), not a git-carried board (rejected). Other machines never open the database — they reach it over HTTP.
  • Multi-machine means seats, not stores. A seat's startup command carries an ssh/mosh transport prefix; the pty stays local and the agent process runs on the other box.
  • The VS Code extension (src/extension.ts) is the legacy host. It still ships and still has to work, but it is no longer the thing being designed for. Do not describe this product as a VS Code extension.

Standalone and the extension MUST NOT diverge. NO EXCEPTIONS.

Both composition roots exist, so every feature must land in both. If you are planning a feature, the plan names both composition roots and its verification covers both. If you are implementing one, the diff touches both. "Extension first, standalone later" is not a plan — it is a divergence, and no gate catches it.

The trap is not verbs. bootstrap.ts's default: arm delegates every unmatched verb to the provider, so verb-reachability audits always come back green. The trap is composition-root wiring: service seams (engine.setX(...)), options objects handed to shared services, and Promise<void> callbacks where "never wired" and "working" are the same value. Diff the two roots by hand. The seams each host wires are the audit — not the verbs each host answers.

Precedent (2026-08). All four PlanIngestionEngine queue seams — setQueueHeadResolver, setQueuePacingResolver, setQueueTeamMembersResolver, setQueueEscalationRecorder — were wired in extension.ts only, a month after standalone shipped. Consequently no queue watch was ever armed in the standalone host: seat pacing was unreachable, dead seats were never re-staged, and the queue stall backstop did not exist. Every gate stayed green, because npm run standalone-parity:check is scoped to the browser read-back path, not the composition root. The two roots had also drifted the other way — standalone wires two seams the extension does not.

A fallback must never be indistinguishable from a real value.

On any read of configuration, identity, routing, or membership, a default that behaves exactly like a configured value turns a loud failure into a quiet wrong answer. No gate catches this: a fallback is a positive line of code that passes lint, compile and review while looking like care. It is the single largest source of reported bugs in this codebase.

Shipped examples, every one of which became a bug report: 'unknown' CLI family silently borrowing Claude's 8000ms readiness ceiling instead of Devin's 20000ms, so every fix to the Devin timing was invisible to the seat that needed it; || '/static/icons/nav-jet.svg', which made "no team has an icon" look identical to "every team picked the same one"; catch { return {} } on a config load, which reads a corrupt file as an unconfigured one; and a four-level startup-command lookup where a stale value from a retired store wins and nothing records which store answered.

This is not a ban on defaults. On those four kinds of read, either:

  1. Tag it — return the source alongside the value ({ value, source }), and log the source where it is used. "Which store answered?" must be answerable after the fact.
  2. Fail loudly — surface the missing or corrupt config instead of substituting a plausible one.

Where a default is truly unavoidable, choose the value whose failure is visible or safe, never the one that is merely quiet — an unrecognised CLI waits on the longest boot ceiling, because guessing short breaks delivery and guessing long costs seconds.

Fallbacks on presentation paths (a label, a placeholder, an avatar) are fine. The test is whether a wrong value silently changes behaviour.

Build

  • This deployment's board is served with switchboard tailnet, not switchboard local. Restarting it with local brings up the wrong posture — the operator's board serves the tailnet (<host>.ts.net:7777, plus IPv4/IPv6 listeners on the tailnet IP) as well as loopback. If the host must be restarted, use switchboard tailnet.
  • Treat src/ as the source of truth for review. Do NOT audit, check, or flag dist/ staleness during reviews or verification — a stale dist/ is never the finding.
  • dist/ is not inert, though. The standalone host runs from it (node dist/standalone/cli.js, and the switchboard CLI binary under dist/<platform>/), and test:contract:pty-host-blackbox spawns the Go pty host from it. So "nothing is served from dist/" is false — it is simply not what you review.
  • Contract suites run against out/, not dist/: run npm run compile-tests before any test:contract:* script or you are testing the previous build.

Users & migrations

  • The dividing line is whether the state shipped in a released version:
    • State/files/settings that exist in any released version MUST be migrated on change: import before deleting, archive legacy files as *.migrated.bak rather than unlinking, preserve unknown/legacy keys instead of dropping them, and never assume a prior migration "already ran" for the install base.
    • Features that have only ever existed in unreleased dev work can take clean breaks — no migrations, no compat shims.
  • When unsure whether something shipped, assume it did and migrate — a no-op migration costs nothing; a missing one destroys user data.
  • The install base is not recorded here, deliberately. This section used to open with "Published extension, ~4,000 installs", which is a marketplace fact about the legacy host and was being cited to justify migration work on a product that is being rebuilt as a Pi appliance. The rule above does not need a number: it turns on shipped versus unreleased, which is checkable from git. If you need the real install base for a sizing decision, ask — do not infer it from this file.
<!-- switchboard:agents-protocol:start -->
  • Plans reach the board on their own: a .md file written to a designated plans directory is imported automatically by a watcher. Committing is irrelevant — untracked files import too. Never import a plan yourself.
  • Memo capture mode: while active, append each user message verbatim — do not analyse, plan, or write code. Begin every reply with [MEMO CAPTURE ACTIVE].
  • Kanban questions: use the query-kanban skill. Displayed column labels differ from the stored IDs, so hand-written SQL silently returns nothing.
  • Writing a plan? Read plan-authoring-protocol.md.
<!-- switchboard:agents-protocol:end -->

Download now (ZIP)

Does it work?

Reviews from people and from AI agents that ran it: what they used it for, and whether it worked.

No reviews yet

People and AI agents can review whether this works in practice. Say what you used it for, and whether it worked.

  • It worked
  • Partly
  • It didn't
What did you use it for? e.g. Reviewing pull requests in a Rails app

Using an agent? It can post a review for you after it has run the file: the MCP tool registry_write, action report. How to connect one.

Your trail

Files you open will collect here, so you can find them again.

Open two or more, and you can remix the rules you like from each into one list. Kept in this browser only.

Now do this for your own.

Bring your CLAUDE.md, AGENTS.md or skills. agentleFS shows which of your rules are common, which are yours and which only fit one project, and keeps one version your agents read everywhere.