sharp does the images now; ffmpeg keeps the video. each does the job it is for — sharp is libvips in-process, no process to spawn and no pipe, which is an order of magnitude less work for the common case of a folder of photographs. a video has no frame until something decodes one, and that is ffmpeg's and nobody else's. added through the procedure bunfig.toml describes, since there is no --no-frozen-lockfile flag in bun 1.3.14: package.json edited, frozenLockfile commented out for ONE command, lockfile diff read, setting put back, and a frozen install confirmed clean afterwards. WHAT THE LOCKFILE DIFF ACTUALLY SAID, because the friction is only worth anything if somebody reads it. everything is inside sharp's tree: sharp 0.33.5 -> 0.35.4 at top level, @img/colour added, and the per-platform libvips binaries moved 1.2.4 -> 1.3.3. two SHARED packages moved with it — semver 7.7.4 -> 7.8.5 and @emnapi/runtime 1.8.1 -> 1.11.3 — both forced by sharp's own ranges, and both previous consumers (next, editorconfig) kept pinned copies of what they had. next keeps its own sharp at 0.33.5 entirely. nothing outside that moved. ^0.35.3 to match what av-club declares. 0.x caret pins the minor, so ^0.33 and ^0.35 do not overlap — the plugin intersection would have resolved two native libvips trees onto one machine for no reason. THE IMAGE LIST GREW: libvips reads HEIC and SVG and ffmpeg does not, and neither is exotic — HEIC is what every recent iPhone writes, and a folder of them drawing generic file icons was the most visible gap this had. `failOn: 'none'` and `limitInputPixels: false` are both deliberate. libvips rejects a file with any warning in it, and a truncated JPEG — an interrupted copy, a phone that died mid-write — is exactly that; refusing it would make this browser stricter than the viewer somebody opens the file with. the pixel ceiling is a DoS guard for an upload endpoint, and these are the owner's own files already on the owner's own disk: a panorama is not an attack. SETUP, both halves: ffmpeg was never in the package list at all, on any of the four package managers, despite this router shelling out to it for subtitles, audio extraction and audio tracks long before thumbnails existed. it worked because every machine set up by hand already had it. now declared. sharp gets a LOAD CHECK beside node-pty's build check, and reported separately from it. same failure shape — an install that succeeds while the native module does not — but the opposite cause: node-pty compiles and can fail to, sharp downloads a libvips binary for this exact platform and arch and can fail to resolve one. a combined "native modules" verdict would send somebody to rebuild the wrong thing. loading it is the only test worth running; a directory proves nothing, and `versions.vips` proves libvips is bound. Co-Authored-By: Claude Opus 5 <noreply@anthropic.com> Officer-Session: 656f5c85-e49a-4f1f-b9f3-042a04b4d043
The documentation, triaged
2026-08-13. A map of what is in here, what it is for, and what should happen to it. Made because there are 42 documents and 13,000 lines, and no way to tell from the filenames which describe the system as it is and which are a record of an afternoon in July.
How much I verified: the classifications below are from filenames, status lines, and greps for things that changed on 2026-08-13. Where I actually read the document or checked the code, it says so. The rest is a starting point for a conversation, not a verdict.
Living — these describe the system and must stay true
| doc | state |
|---|---|
working-on-officer.md |
updated 2026-08-13. Operational guide. |
secret-store.md |
updated 2026-08-13. Built; rotation still open. |
install-variants.md |
new. The branch tree, for discussion. |
http-secure-context-audit.md |
new. What breaks over plain http. |
install-container-testing.md |
new. First container pass and its findings. |
per-user-linux-accounts.md |
partly updated. OFFICER_OS_USERS is gone; check the rest. |
navigation-audit.md |
authoritative on routing. Unverified against tonight's route removals. |
workspace-panels.md + workspace-panel-todo.md |
the panel framework. 1,300 lines combined — likely the biggest cleanup here. |
agent-coordination.md |
the north star for panel work. |
deprovision-os-account.md |
implemented; the 'disabled' stage it may mention was deleted tonight. |
Stale — describe things that changed on 2026-08-13
Each of these references something that no longer exists. Not yet corrected.
sidecar-topology.md— "ecosystem.config.cjs is the source of truth". It is generated now, and holds six processes.sidecar-app-store.md— derives the catalogue fromfull − light. Those files are gone, andcatalogue.test.tswas rewritten.sidecar-bootstrapping.md— "20 PM2 entries, 18 sidecar dirs". Six entries now.mobile-api-keys.md— partly corrected; recheck the origin-checking claims.wallet-key-custody.md—VAULT_STORE_KEYis now the per-purposewalletkey.push-notifications.md— "agreed design, 2026-07-31". Notify is a plugin and unmounted.chat-session-lifetime.md,chat-ui-walkthrough.md— referenceofficer-agent, renamed.
Historical — a record of a moment, and should stay one
Do not rewrite these to match today's code. They document how a decision was reached, and editing them destroys the reasoning. If they mislead, add a dated header pointing forward.
sidecar-audit-2026-07.md(1,377 lines)claude-sidecar-isolation.md— records theofficer-claude→officer-agentrename that preceded tonight'sofficer-agent→officer-claude-codeopen-threads-after-per-user-claude.mdtwo-agent-field-report-2026-08-12.mdapi-method-changes-2026-08-06.md
The opencode cluster — nine documents for one migration
opencode-fork-decision · -parity · -api-2-assessment · -phase0-review · -phase1-report ·
-phase1-review · -serve-migration-plan · -serve-path · -testing-checklist
The migration landed — opencode serve is in the sidecar, verified. So
opencode-serve-migration-plan.md saying "Nothing here is implemented" is false.
This is the clearest consolidation candidate in the whole directory: one document recording what was decided and what shipped, replacing nine that describe stages of getting there. I did not do it because it needs reading all nine, and deleting documents unread is not a thing to do at 4am.
The mobile-dav thread — three documents, one conversation
mobile-dav-provisioning · -feedback · -reply. A correspondence. Almost certainly one document.
Unclassified — I have not looked
design-language-interface · file-sync · jobs-unification · mobile-photo-sync-api ·
nextcloud-replacement · agent-git-identity
The plugin split, which affects most of the above
A core install is six processes. Everything else is a plugin, switched off tonight but present on disk. Most documents here were written when the estate was twenty processes and every one of them was simply "there", so they describe availability that no longer holds.
The useful rewrite is usually one line, not a rewrite: say whether the thing described is core or a plugin, and if a plugin, that it is not mounted on a fresh install.