oficina / slides Public

fix: slide order is data too (codex 4 at slide level); export status agrees with the held bytes; docs

The deck's `slides` array is now the SET of its slides and their order
is an `order` key on each slide map — ruling 18 one level up, and the
same helper rather than a second idea (`ordered_maps` / `orderedMaps`,
`place_entry` / `placeEntry`). `move_slide` writes the key; `add_slide`,
`duplicate_slide` and `remove_slide` never rebuild the array. A slide
reordered while somebody types on it used to lose the typing for the
reason a moved block did: the slide map their text, notes and blocks all
hang off was deleted and replaced by a copy.

Tests in both implementations: two docs exchange updates, one reorders
while the other types into the slide being moved and into its notes;
both sides read the new order with the text intact. Plus the same story
over the wire in `internal/slidestest`. The view sorts by the key and
does not expose it, so no reader downstream changed — `every-block.yjs`
moved bytes and no `.view.json` moved. `changes.mjs` learned that a
slide's own `order` key is a strip re-sync rather than a stage refetch.

The export status page and the file now agree about the hour.
rastrillo/jobs forgets a finished job ten minutes after it ends and this
app holds the bytes for the hour it promised, so the page 404'd for
fifty minutes while `.pdf` at the same address still served. The page,
its polled fragment and the API's status document fall back to this
app's own record (`exportFallback`); `ForgetExportJobs` is the seam the
test uses to reach that state without waiting ten minutes.

AGENTS.md caught up with waves A and B: the write gate is `Handle.Check`
as well as `deck.Parse`, reading order has a seam of its own, ABI 2 and
both wasm artefacts are traps, offboarding is rechecked per request, and
the upload receipt has a table name. One false comment in
`fixtures/uploads.mjs` corrected — the app mints the staging key now, so
the client's hash is a claim and not an address.
Co-Authored-By: Claude Opus 5 (1M context) <noreply@anthropic.com>
claude agent, operated by paul@keymail.dev pushed by paul@keymail.dev 174a410b8a32dd3481b8f6c42141adeba1fbfc61 parent e9fe152
27 files changed, +714 −200
  • AGENTS.md +74 −19
  • core/src/check.rs +2 −2
  • core/src/layout.rs +3 −3
  • core/src/ops.rs +60 −33
  • core/src/schema.rs +34 −27
  • core/src/view.rs +6 −3
  • core/tests/ops.rs +93 −0
  • docs/api.md +8 −2
  • docs/superpowers/specs/2026-09-07-slides-design.md +32 −4
  • fixtures/changes.mjs +19 −4
  • fixtures/check.mjs +3 −3
  • fixtures/layout.mjs +3 −3
  • fixtures/ops-apply.mjs +52 −30
  • fixtures/ops-model.mjs +3 −3
  • fixtures/ops.test.mjs +36 −0
  • fixtures/stage.mjs +4 −4
  • fixtures/uploads.mjs +8 −6
  • fixtures/vectors/every-block.yjs binary
  • fixtures/view.mjs +9 −6
  • fixtures/ydoc.mjs +17 −15
  • internal/slides/core/testdata/slides_core.wasm binary
  • internal/slides/deck/deck.go +7 −0
  • internal/slides/exports.go +121 −16
  • internal/slides/static/{editor.b15cb47d0e317eee.js => editor.ea69e9f399e840e0.js} +15 −15
  • internal/slidestest/export_test.go +53 −0
  • internal/slidestest/harness_test.go +5 −2
  • internal/slidestest/integrity_test.go +47 −0

Intent

Human

<task-notification> <task-id>ab6b16b57efc291f6</task-id> <tool-use-id>toolu_012CJqiFACFc7NYUpRaF9vZ8</tool-use-id> <output-file>/home/paulca/.cache/tmp/claude-1001/-home-paulca-amadan-net-oficina/c8f62d65-b2d1-4a65-b79e-6a8e82e1e5c6/tasks/ab6b16b57efc291f6.output</output-file> <status>failed</status> <summary>Agent "Codex wave C: leftovers" failed: Agent terminated early due to an API error: You've hit your session limit · resets 7:10pm (Europe/Dublin) (error type rate_limit, HTTP 429, request id req_011CerFhjREyT3aoPm4baPUb, model sent to the API: claude-fable-5-1)</summary> <note>A task-notification fires each time this agent stops with no live background children of its own. The user can send it another message and resume it, so the same task-id may notify more than once.</note> <result>I'll start by reading the findings, wave reports, and the relevant code.</result> </task-notification>

Human

continue

Human

OK,keep going

AGENTS.md

Loading diff…

core/src/check.rs

Loading diff…

core/src/layout.rs

Loading diff…

core/src/ops.rs

Loading diff…

core/src/schema.rs

Loading diff…

core/src/view.rs

Loading diff…

core/tests/ops.rs

Loading diff…

docs/api.md

Loading diff…

docs/superpowers/specs/2026-09-07-slides-design.md

Loading diff…

fixtures/changes.mjs

Loading diff…

fixtures/check.mjs

Loading diff…

fixtures/layout.mjs

Loading diff…

fixtures/ops-apply.mjs

Loading diff…

fixtures/ops-model.mjs

Loading diff…

fixtures/ops.test.mjs

Loading diff…

fixtures/stage.mjs

Loading diff…

fixtures/uploads.mjs

Loading diff…

fixtures/vectors/every-block.yjs

Loading diff…

fixtures/view.mjs

Loading diff…

fixtures/ydoc.mjs

Loading diff…

internal/slides/core/testdata/slides_core.wasm

Loading diff…

internal/slides/deck/deck.go

Loading diff…

internal/slides/exports.go

Loading diff…

internal/slides/static/{editor.b15cb47d0e317eee.js => editor.ea69e9f399e840e0.js}

Loading diff…

internal/slidestest/export_test.go

Loading diff…

internal/slidestest/harness_test.go

Loading diff…

internal/slidestest/integrity_test.go

Loading diff…