Skip to content

Specs

Design specs written before (or while) a feature was built — the reasoning behind non-obvious decisions, worked examples, and the divergences section each one keeps up to date when the built feature departs from what's written here. These are reference material, not onboarding reading: start with the Usage guide, Features or Technical instead, and come here when you need the why behind a specific piece.

How this folder is organised

By build status, one subfolder each:

Folder Means
implemented/ Built and in use. Read these to understand something that exists
in-progress/ Partly built — some of it is running, some isn't. Read the spec's own status line for which
not-started/ Nothing built. These are proposals and plans
archived/ Will not be built: superseded or dropped. Kept for their reasoning

Citing a spec

A spec's status folder is not part of its identity. Filenames are unique across all four folders, and that is what lets a spec change status without breaking every reference to it.

Citing from Write
Anywhere outside sage-docs — code comments, CLAUDE.md files, READMEs sage-docs/docs/specs/.../<name>-spec.md
Inside sage-docs The real path, e.g. implemented/<name>-spec.md — mkdocs has to resolve it

The ... stands in for whichever status folder the spec is in today. It keeps the reference correct forever, still greps by filename, and avoids */, which would terminate the /** */ block comments these references sit in.

Moving a spec between folders

Because of the rule above, this is confined to sage-docs:

  1. git mv it into the new folder.
  2. Update its own status line — the folder is filing, the spec is the record.
  3. Update this index, and the READMEs of both the folder it left and the one it joined.
  4. Update mkdocs.yml's nav.
  5. Fix any real markdown link to it — grep -rn "<name>-spec.md" docs/. A link from another folder needs ../<folder>/.
  6. Add a MINOR entry to the changelog and bump the version in mkdocs.yml.

Nothing outside sage-docs should need touching. If a grep of the other three repos turns up a folder-qualified path, that reference is the bug — rewrite it to the ... form rather than repointing it.


Implemented

The site

  • Site engine — the code the site's pages copied by hand (the live channel, the score and attendance clients, the rules, and the second Tournament Hub inside Control Center) is now shared ES modules at /lib/v1/, with no build step and no framework. Event pages are thin shells that read their settings from events.json, the rules have unit tests, and a harness proves nothing visible changed except the differences the owner approved. Merged 2026-10-06. Phase 8 of the architecture spec.

Sync & live data

  • Runtime-fetched sync config — why event-data/config/events.json is fetched at runtime instead of committed to sage-tools-api.
  • Sync script configuration — why sheets-sync.gs keeps its per-workbook config in Script Properties, and the validation the setup dialog runs before saving it.
  • sage-tools-api test suite — unit and integration tests (and an opt-in PDF end-to-end) that pin what the service does today, against an in-memory fake of GitHub, Google Sheets and the live Worker, built with no production change. Kept current: every API change updates its tests in the same commit, enforced by guard tests and a pre-push hook. The gate for the architecture spec, which is now open.
  • sage-tools-api architecture hardening — revised against 2.8.0. Phases 1–5 are merged and deployed as 3.0.0 (the /v3 API), Phase 6's code is merged and the masters carry it, and Phases 7 and 8 are done. Its fresh-master check, production acceptance and Cloud Build filter were not run. The service moves to ports-and-adapters, checked against SOLID. The conflict retry is written once, behind two delivery strategies and a SnapshotPublisher selector. There is one error handler, one auth-middleware module, and a validated config with a composition root that the tests share. Outbound clients and the event registry get their own folders. Release 3.0.0 adds one REST surface, /v3, with a twin of every route (legacy and /v1), and every client moves onto it. Every existing URL is kept, frozen. /ping is unchanged.
  • Immediate sync — every sync measured from the edit, a sync that loses a GitHub commit race re-read and retried instead of dropped, and Apps Script syncing straight from the edit under a document lock instead of a delayed trigger. Both delivery specs build on it.
  • Live push delivery — a Cloudflare Durable Object that pushes each snapshot to open pages over WebSockets, with GitHub kept as archive and fallback. In use since the two events of 3 October 2026.
  • Plain-language explainer — the same, without the implementation detail.

Control Center

  • Match Control console — the central operator console (written before it was renamed Control Center).
  • Awards tab — podium finishers and image export.
  • Schedule screen — the venue wall display.
  • Facility progress — matches done, matches left and estimated finish per facility, on Live Matches and in Mission Control.
  • Score entry and scorer links — click a match in Match Finder, enter the scores, review (the winner named in large text), save. The API writes the match's two SCHEDULE score cells, refuses if the sheet changed meanwhile, and publishes at once. Scorer staff use the same dialog on a per-event scorer page, through 24-hour links that a Mission Control switch can stop.
  • Link attribution — desk and scorer links say who they were issued to, with a note, and the workbook records it: a markedBy column in ATTENDANCE, and a note on each edited score cell listing its last five edits.

Scoresheet Generator

  • Event picker — sourcing the matches CSV from a published event-data snapshot instead of a file upload.

Tournament Calculator

  • Dual-meet fixes — the calculator's dual-meet-specific timing math.
  • PWA — installable, offline setup.

Bracket Generator

  • Bracket Generator — promoting the per-event bracket draw page into one evergreen tool, with an optional event name.
  • Verifiable draw — proving a draw wasn't rigged: a seed, a hash sort anyone can re-check on any SHA-256 site, and a plain-language How it works dialog.
  • Bracket draw name import — uploading the tool's text exports into a generated workbook, so each category's rosters and its STEP 3 codes come from the verifiable draw instead of being typed and hand-shuffled. Also carries the workbook's menu route into the tool (§11) and a dual meet's in-sheet roster shuffle (§12). Replaces the retired Bracket Generator workbook handoff spec.
  • Keep-apart groups — keeping chosen pairs out of the same bracket while the draw stays checkable from the seed.

Dual Meet Sheet Generator

Standard Tournament Generator

  • Standard Tournament Master — the dual-meet generator's counterpart for open-entry tournaments: one workbook per facility per day, uneven round-robin brackets, and a forward-propagating single-elimination ladder.

Events & templates

  • Event site templates — the dual-meet and standard-tournament templates new events are instantiated from.
  • Team tournament event-site template — _templates/team-tournament-template/, with everything the other two templates give an event: a Hub and a schedule board as shells on the site engine, the scorer and desk pages working on team data, and the team checks in the dry-run runbook. S.A.G.E.-themed, with pair labels per event from events.json (display.pairs).
  • Pickle & Friends × 1Bataan United Picklers dual meet — the event that drove the dual-meet template's first real run.
  • Event attendance — a staff check-in page writing each player's arrival into the venue workbook through an Apps Script web app; Pickle for Sight first.
  • Attendance for every event — staff check-in for any event, marked in Control Center or on a desk page, one check-in per person. sage-tools-api writes each workbook's ATTENDANCE tab as a service account and keeps the roster current after every sync. In use at Piggleball and PickleDrive.
  • Push for attendance — a check-in on one device reaches the other desks and Control Center within a second or two. The live Worker relays a data-free nudge (this facility's list changed) on its own object per day, and each page re-reads the list from the API with its own token. Nothing polls. sage-tools-api 3.4.0; the Worker deployed 2026-10-18. The owner's checks P1–P7 were not run.
  • Team tournament — a third event type for team events: named teams, four-match matchups, group stage then playoffs. PickleDrive Club One Year Celebration ran on 3 October 2026 on the hand-built prototype. The template and the workbook generator are separate specs under Not started.
  • Team workbook recalculation — why PickleDrive's workbook took 10–58 s to read on event day, and the by-hand fix applied on 2026-10-05: a hidden, non-volatile StackCache tab the named functions read instead of rebuilding SCHEDULE's stacks thousands of times per edit, a matchup family that reads MatchLookup's rows, and the unused functions removed.
  • CLSO Pickle for Sight — the first standard-template event site: one day across two venues (PCPH Main and Annex), three divisions × three events. Ran 27 September 2026.
  • Piggleball Chairman's Cup — the event site for NATFED's 1st Piggleball Chairman's Cup, part of the Pig Sports Festival: one venue (Centro Atletico, 3 courts), Novice Open Doubles plus Intermediate Men's and Mixed Doubles. Standard template, re-skinned from the pubmat. Ran 3 October 2026.

The docs

  • Usage guide and docs restructure — Features & Usage split in two: a Usage tab that trains a new operator from planning to the day of, and Features as a per-tool reference. Merged as docs 2.0.0, with the site repo's checklist fixes. The newcomer read-through was not done.

In progress

  • Code and access protection — a free to-do list (Viewer-only sharing of the masters, GitHub org settings within the free plan, least-privilege credentials, where the docs are hosted, licence notices) and two designs: facility workbooks closed to link access (the server reads as its service account, the desk page and Control Center read the roster through the API), and two small fixes to the played/series rules' server copy. The code, runbook and docs are built and deployed; the owner's checks and the Google, GitHub and Cloud settings are left. Records why the site is not obfuscated and the draw stays in the browser.

  • Millennium Invitational — the site for Millennium Pickleball Club's charity team tournament on 24 October 2026: eight colour teams in one round robin, then a Bronze and a Final. Its teams score games won, so it adds an opt-in teamScoring: "games" to the engine's team rules, then instantiates the team template with the club's colours. The engine change, the pages and the events.json entry are pushed; the short link, the workbook fixes, sync setup and the dry run are left.


Not started

  • Site test suite — Control Center, the current event pages and the attendance desk pages tested in a real browser on fixture data. No page changes. It provides the dry run's rendering layer. To be revised first: the site engine built its _tests/ runner, fixtures and unit tests.
  • Calculator team format — a third Format option in the Tournament Calculator: one team competition planned in matchups, with the group stage, quarterfinal-to-final playoffs, slots and finish time worked out from teams, groups and courts.
  • Team Tournament Master — the workbook generator for team events, phased, starting from the optimised workbook.
  • Automated dry run — idea only: run the Control Center runbook's rehearsal with one command, including Puppeteer editing the real facility sheet so the onEdit trigger is tested too. Its rendering checks come from the site test suite.
  • Court Control from Control Center — outline only: an operator puts a match on a court, or clears it, from Live Matches, through the same write-then-publish path as score entry. Waits for score entry's real-workbook checks.
  • Hub player experience — eight independent proposals for the owner to keep or drop, to make where and when do I play next? quicker on a phone. A search scrolls to its results, the banner is shorter on phones, a "Your next match" card tops a pair's results, and the Hub's tickets show names without codes. Then four extras: the tabs along the bottom, a provisional-standings line, a rules link and following more than one pair. Engine Hub and templates only; no new sections.

Archived

  • Fast data delivery — replacing the GitHub Pages build step in the live data path with Cloudflare R2, and full-payload polling with pointer polling. Superseded by Live push delivery, which was built instead; it will not be built.
  • Plain-language explainer — the same, without the implementation detail.