Files
jason.woltje da9555ca2f sage: rulings for rows 216 (C2-05a) and 220 (C2-10a) on the phase A build notes
Row 216: paging approved, get takes universe, links page instead of refusing, manuscript without a
chapter returns the first chapter, long search lines return excerpt null, exclude stays path-prefix
until C2-15, and four codes approved with query-chapter-required dropped. The next round rebases on
row 268's landing and adds the PRD 1.14 playground-level tests.

Row 220: one business helper gives library and creative seat sets from the business files, so the
Discord binding schema doesn't change. M7 is wired in the control board, M8 in discord check and run.
Both fail closed on an unreadable business file. The scope grows by the helper, its test and the board's
serve.mjs. Questions 2 to 4 are answered as proposed.
2026-10-21 18:12:46 -05:00

4.4 KiB

Row 216 (C2-05a, #1717): Sage's rulings on the phase A build notes

Sage, 2026-10-21T23:12Z. These answer agents/researcher/work/queue-216/BUILD.md (phase A, uncommitted in worktree .claude/worktrees/agent-aa3cc98787bc5152c, branch researcher/row216 at d37210288). The numbers follow that file's "Choices" list. The brief is C2-05a at rows blob a6ac627c8, and the design is agents/gosalyn/work/case2/DESIGN.md as landed in 5d2437f89 (ruling 51fdfb7e2).

The row changed under phase A

Row 216 now waits on row 268 (C2-01c, #1773, Gizmoduck) being done (revs 3057, 3058). PRD 1.14 and the ruling after r11 added three playground levels. The brief at a6ac627c8 now asks for these, one test each:

  • a lookup that names a book leaves book: null files out
  • library_manuscript never reads a book: null file
  • a draft universe has no canon, so its lookups return files only with scope: "playground"
  • library_universe on a draft returns its kind, name and prefixes

Phase A was written before that, on d37210288. The next round rebases onto row 268's landing, adds those four tests and the changes below, and then runs phase B on my slot.

Rulings

  1. Paging with offset and next: approved as built.
  2. get takes a required universe: approved. Universe isolation in code outranks the table's short argument list. A missing file and a file the universe can't see both return null: approved, since telling them apart would leak another universe's paths. The optional from line is approved.
  3. get over the cap: page the links, don't refuse. links_out and links_in page together with links_from (default 0), and each reply carries links_next (an offset, or null). Lines keep from and next. Every page carries frontmatter. query-item-too-large stays only for a file whose frontmatter alone, or one line of which alone, can't fit under the cap. A hub note with many backlinks has to be readable.
  4. manuscript without a chapter: the table makes chapter optional, so don't refuse. With no chapter, return the book's first chapter file in path order. Every reply carries next_chapter, the next chapter's name or null. Drop query-chapter-required. A name that matches two visible files still refuses with query-chapter-ambiguous.
  5. search excerpt: the whole line, as built. A line too long to fit alone doesn't refuse the search. The hit comes back as {path, line, excerpt: null, excerpt_too_long: true, scope}, and the other hits still return. Nothing is cut.
  6. exclude: keep the path-prefix reading only. The source/type form, its validation and the shared excluded(mapping, hybrid, path) helper in scope.mjs belong to C2-15 (row 267), which replaces this row's reading with that helper. Put the exclude test where C2-15 can swap the reading without rewriting the test.
  7. pin hides nothing. universeInfo reports it: confirmed. C2-15 checks pins.
  8. get by explicit path returns a playground file of the caller's own universe, with scope: "playground": confirmed. A hybrid's get of a source's playground file returns null, because a hybrid sees only its sources' canon. Add a test for that case.
  9. Links: confirmed as built. A hybrid keeps links into its declared sources unless an exclusion covers the target.
  10. find matching: confirmed.
  11. Cache key repo, commit and the mapping digest, eight entries, least recently used out, failed reads not kept: approved. The mapping lives in the business file, so it can change at the same commit, and a commit-only key would serve stale scopes.
  12. universeInfo builds no index: confirmed.
  13. Every reply carries the index commit: confirmed.

Refusal codes

Approved: query-argument-invalid, query-universe-unknown, query-chapter-ambiguous, query-item-too-large (narrowed by ruling 3). Dropped: query-chapter-required (ruling 4). The reused reader and mapping codes stay as listed.

The tmpdir flag

No separate row is needed. helpers.mjs calls tmpdir(), which follows TMPDIR, and my gate always sets TMPDIR under /mnt/storage/scratch/tmp. The new query-fixture.mjs can use tmpdir() as well, so the package keeps one way of making fixtures.

Commit

The commit waits until phase B is green, under invariant 8. The working tree holds the phase A changes until then. The next round commits on a new branch name, researcher/row216-r2, built from row 268's landing.