oficina / docs Public

Act on the whole-branch review

The Fable review found one blocking defect and a set of real
non-blocking ones. It also did the verification this branch said it
could not: it installed pypdf and fontTools and parsed the exported PDF
and its embedded subsets independently — strict mode, checksum
validation, text extraction including "café", em dashes and curly
quotes. So the Identity-H and ToUnicode construction is confirmed by
something nobody here wrote, which is the gap the PDF commit was honest
about leaving open.

BLOCKING, now fixed: the PDF export logged document content. On a
substitution it wrote Report.String() — the actual missing characters —
into the instance log, and an instance's logs reach the platform's own
store. Spec §2.1's leak list, item 5, is categorical that a handler
never interpolates document content into a log or an error, and for a
short document in an unshipped script the deduplicated set of its
characters approximates the document. It would have leaked most of one
in plaintext, out of a system whose premise is that documents are sealed
at rest, and it would have done it to exactly the people the missing
fonts already disadvantage. It now logs a count and Unicode block names
— which is what an operator can act on anyway, since blocks say which
faces to add. Report.String() keeps its behaviour and gains a comment
saying what it must not be used for.

TestPDFIsDeterministic could not see what it claimed to. It compared
with strings.EqualFold, and a PDF is mostly Flate — mostly invalid
UTF-8 — where every invalid byte decodes to U+FFFD on both sides and
compares equal. Two files with different compressed bodies passed, in
the test whose whole subject is bytes. bytes.Equal now. That is the
AGENTS.md shape appearing in the one test written to rule it out.

And the nondeterminism it was too weak to catch is real: a run carrying
two size marks — impossible through the schema, possible through raw
POST /updates bytes — picked one by ranging a map with a break, so the
same document could export differently. Fixed order, and its own test.

A list item whose first line falls on a new page lost its marker
entirely: the guard compared an offset on the old page with one on the
new. In an ordered list that is a silently missing number. The marker
now follows the line wherever it actually lands. Verified by restoring
the original logic and watching items 28 and 55 — the two page breaks —
lose their numbers.

The three toolbar selects were never disabled server-side though a
comment claimed they were, so with no JavaScript a person could change
Font to Monospace and watch the document ignore them; and the Size
control listed "Small" first, so it displayed the wrong current state
until the first sync, and forever without script. Disabled like the
buttons, enabled by the same sync, and Normal listed first.

The subset dropped cvt /fpgm/prep. Liberation's glyph programs call
functions defined in fpgm and read values from cvt , so the embedded
font was executing instructions against definitions that were not in the
file — ISO 32000-1 §9.9 requires them, and about 15KB a face is the
cheapest correctness in the package.

Smaller: Get's fallback comment said "regular serif" and returned
Liberation Mono Bold, because faces is sorted by served path — it now
asks for the face it means by name. parseCmap12 skipped rather than
stopped on a short group table, so a hostile count could spin billions
of no-op iterations in a parser whose own header advertises it is one
step from untrusted input.

toolbar.mjs was 350 lines against spec §12's 300-line cap, which this
branch's own plan promised to respect. The roving-tabindex logic is now
fixtures/toolbar-roving.mjs — a genuinely separate concern, since it
decides which control the keyboard is on and knows nothing about
ProseMirror. 273 and 86 lines. The browser drive still passes 22/22,
including all three keyboard checks.
Co-Authored-By: Claude Opus 5 (1M context) <noreply@anthropic.com>
Claude-Session: https://claude.ai/code/session_01YYB9fUAfxXNzkeC3fsFYzR
Paul Campbell pushed by paul@keymail.dev 797149b4b563ff1cc6929788d810374d274620f8 parent f0a81b3
10 files changed, +417 −116
  • fixtures/toolbar-roving.mjs +86 −0
  • fixtures/toolbar.mjs +8 −78
  • internal/docs/export.go +26 −2
  • internal/docs/static/{editor.3dbb8fa17262528b.js => editor.30d1bd8b9ffef032.js} +12 −12
  • internal/docs/views/show.html +3 −3
  • internal/export/pdf.go +122 −16
  • internal/export/pdf_test.go +66 −1
  • internal/fonts/fonts.go +15 −3
  • internal/fonts/fonts_test.go +47 −0
  • internal/fonts/truetype.go +32 −1

CI passed — run details

Intent

Human

<task-notification> <task-id>bswsetyb9</task-id> <tool-use-id>toolu_011oucwt2ZYc54inMLRe62XC</tool-use-id> <output-file>/home/paulca/.cache/tmp/claude-1001/-home-paulca-amadan-net-oficina-docs/8c293727-d922-4f5a-bfde-9457b649670f/tasks/bswsetyb9.output</output-file> <status>completed</status> <summary>Background command "Wait for CI" completed (exit code 0)</summary> </task-notification>

Human

shall we do search now, so i can find docs by title?

Attributed to this commit: 311 g CO₂e (41038715 tokens). This is an attribution, not a measurement — usage counted from this commit's own marker forward to the next one on formatting-and-export, never backward from it. A turn that produced more than one commit books all of its tokens to the last one, and a concurrent session on this branch can add to the same figure. Some of it was priced using the shared default rate, because no model-specific factor row exists yet for at least one model involved. The Carbon view has the repo total, which is never derived from this attribution.

fixtures/toolbar-roving.mjs

Loading diff…

fixtures/toolbar.mjs

Loading diff…

internal/docs/export.go

Loading diff…

internal/docs/static/{editor.3dbb8fa17262528b.js => editor.30d1bd8b9ffef032.js}

Loading diff…

internal/docs/views/show.html

Loading diff…

internal/export/pdf.go

Loading diff…

internal/export/pdf_test.go

Loading diff…

internal/fonts/fonts.go

Loading diff…

internal/fonts/fonts_test.go

Loading diff…

internal/fonts/truetype.go

Loading diff…