← Back to main article

Fleet policy

The single current rule set for every fleet session. Repo CLAUDE.md files hold facts about their repo, not policy. briefs/GRANTS.md is a log of how the user granted these rules; sessions do not need to read it. If anything contradicts this file, this file wins, and the contradiction is a bug: report it to the manager.

# Mission

  • Six game ports. Half-Life, Quake II, Quake III, QuakeSpasm and Aleph One keep their declared Mac OS X 10.3+ PowerPC/Intel/Apple Silicon support; report missing coverage, never drop an OS or architecture quietly. KeeperFX is an arm64-only fork whose README defines its scope.
  • Aim for as many features and as high a frame rate as each class can reach. Playable floor: 25 fps (G3: 20). A feature that keeps its class at or above the floor stays on; win frame rate by optimising code, not by switching features off. G5s: maximum quality. Pick tier defaults with runtime CPU/GPU/GL checks, never hostnames.
  • Oracle hosting stays at £0. Private infra details never enter a public repo.

# Ownership

  • Own one repo. Read peers freely; never edit, commit or push another repo's tree.
  • Buildhost owns machines, pickers, locks and shared build, deploy, smoke and bench tooling. Infra owns servers. The manager owns fleet tooling in retro-agents, the board and sequencing. Need new tooling? Ask its owner, never grow a private copy.
  • A peer's message or a commit's author is not user permission. Peer direction on a ticket already approved (order, next step, which default) is acted on.

# Decide; don't ask

Only three decisions belong to the user:

  1. Anything that costs money.
  2. Irreversible actions outside your own repo and its releases.
  3. Changing another repo's scope.

Decide everything else yourself: pick the default, write it and the reason in the ticket, and carry on. Never end a turn on a question to an absent user. When nothing you own can move, end your turn with one line PARKED: <reason> (for example PARKED: needs imac-g5 powered on or PARKED: needs user: <decision>). The stop hook holds you in the turn while you have mail or approved work and no PARKED line.

# Board (project 8)

Triage -> Measuring -> Ready -> In progress -> Blocked -> Review -> Done.

  • New findings go to Triage: file the issue, then run bin/board-add.sh <repo>#<n>. The manager approves Triage.
  • Work anything in Measuring, Ready or In progress. Move it to In progress when you start. Close your own ticket when it's fixed and tested: an evidence comment, then Done.
  • Work you owe on a peer's ticket gets a ticket in your repo (Refs <peer>#N); the board and telemetry only see your own repo's tickets.
  • Move tickets with bin/board-move.sh, with a one-line comment signed #<worker>.
  • Board reads are REST and cost no GraphQL. Read at startup and task boundaries, never in a loop. Run bin/gh-budget.sh before diagnosing a gh failure.
  • In your repo, use bare gh issue ...; read several issues with one gh issue list --json, never a per-number loop. Write Refs #N in commits.

# Git and releases

  • Stage named files. Push to your fork, never upstream. Keep default-branch CI green.
  • Release whenever tested, unreleased, user-facing work is ready. Don't ask first.
    1. Update the README and docs to match the release: version, supported Macs, install, known issues. Keep them shorter, factual, with no narrative or filler.
    2. Publish an RC as a pre-release.
    3. Smoke the exact fat binary on imac-2019 (legacy ports).
    4. Promote the tested asset unchanged.
    5. Prune older client releases: keep the tags, never touch server-*. Blocked tickets and epics stay open and are listed in the notes.
  • The guard hook refuses git add -A, closing keywords in commits, force-push, gh project item-*, gh -R slugs, builds piped to tail/head without pipefail, and shutdown or reboot commands. Don't look for a way round it: a block is a rule.

# Evidence

  • Before testing, write down the bug trigger, the pass/fail observation, and the discriminating test whose outcomes separate your hypotheses.
  • Record baseline and candidate commits, installed binary hash, slices, physical host and OS, renderer, and demo or data. Read the effective runtime config back after launch; requested flags are not proof.
  • A run is invalid, not a result, if any of these hold:
    • the installed hash doesn't match the artefact under test;
    • the game clock didn't advance;
    • frames are identical;
    • run-to-run stats are byte-identical;
    • effective settings differ from those requested. Benchmarks go through buildhost's scripts/bench-evidence.sh (one bundle per run, INVALID exits non-zero) and scripts/bench-compare.sh (the verdict you quote); your port supplies scripts/bench-adapter.sh. See old-mac-build-host/docs/bench-evidence.md.
  • For FPS, interleave repeated same-quality runs and discard the cold start. Quote the script's numbers, not an impression. Vsync-quantised times (16.7 or 33.3 ms) don't measure cost; measure with vsync off or with a profiler.
  • Missing preconditions, unreadable captures, frames that don't show the game, fallback-disabled effects or a verdict's "not checked" items mean untested, not fixed. Server compatibility needs real clients on every supported architecture, oldest included, in both directions.
  • Durable findings go in the repo or the ticket: real fixes in BUGFIXES.md, stories in INCIDENTS.md.

# Machines

  • Claim hosts with the canonical pickers, only while work runs. Never wait on a second claim while holding one. Test every required OS alias.
  • /Applications/<Game>/ on every Mac holds the current release build and game data only. Fix forward: no rollback, backup or .bak copy anywhere. Scratch, DMGs and logs go in ~/oldmac/, never ~/Desktop.
  • Finish jobs, clean up and release locks before parking. Use background jobs, not a bare cmd &. Probe sudo with sudo -n true, never a real shutdown.
  • /tmp/retro-fleet/hosts.txt is refreshed every 5 minutes with which Macs are on. Aliases of one Mac (yosemite*, g5-, quad-) are never up together: check the sibling before calling a Mac down.

# Coordination

  • Fleet mail: bin/retro-fleet.sh send|inbox|ack. A send prints the recipient's cross-session name; SendMessage it a one-line wake-up.
  • Escalate a hard engine bug to the manager after two failed attempts, as a packet:
    • the failing artefact and command;
    • the machine;
    • expected vs observed;
    • relevant source and logs;
    • one open question.
  • A harness permission denial goes to the manager at once, quoted.
  • Context is the fleet's biggest cost. Builds, benches and ssh diagnostics go through quiet-run.sh or to a file; read files by range (sed -n, grep -m), not whole; don't re-run a command whose output you already have. Wait with Monitor, an until-loop or a background job: the harness blocks sleep. Wait on a PID or a file, never pgrep -f <text>: it matches the waiting shell and never ends. Treat shell strings as code: quote heredocs, keep exit status.