Reading copy of lichen.page.review: one PR per unit, product changes only

ONE-DOOR unit 1: every site change goes through one entry, with one settings editor #64

targeting base/one-door-unit-1 from view/one-door-unit-1
Open opened by and assigned to notplants-bot.bsky.social
targeting base/one-door-unit-1 from view/one-door-unit-1

After a site's files change, every writer now goes through one entry, runtime.changed(Change), and settings are written by one editor.

  • One entry for the follow-ups. Once a write commits, Change itself runs the follow-up steps: synchronous settings invalidation, storage recount, the save announcement, the publication request and room reconciliation. Callers no longer write these out by hand. A settings save requests only its own awaited publication, committed writes are built through Change::saved, and debug builds refuse the call while a tree or room guard is held. Room reconciliation and runtime PDS setup use the same effects, with weak event and rebuild senders so an idle actor cannot keep the runtime alive.
  • One settings editor. API, frontend/plugin pin writers, site creation and credential migration all use the transactional settings editor (formatting, closure results and source-conflict refusals preserved; only initialization callers can create an absent file). Invite generation replaces the server configuration atomically. The old raw readers and writers are deleted.
  • One typed browser stream. Each runtime joins its settings and plugin notifications into one typed channel; a lagged browser refreshes current settings, plugins and the filetree. Wire event names do not change.
  • Accounting. Conflict and recovery artifacts are recounted even when a save fails or autosave is off, apart from successful-save events.
  • Removed: the obsolete PDS setup wrappers, the asynchronous settings invalidation listener and its startup wrapper, and the context-free invalidation fallback.

ONE-DOOR, unit 1 (subunits 1a, 1b, 1c, 1d, 1e, 1f combined, replacing their per-subunit PRs). Plan: https://tangled.org/notplants-bot.bsky.social/lichen-orchestrator/blob/main/machine-docs/plans/ONE-DOOR-2026-10-30.md

This is a reading copy: only this PR's product changes, applied in order on its base. Nothing here is to be merged.

Source PRs on lichen.page.review (product), in order, with their original descriptions #

  • #3443 s/815-od-u1a-settings-product — Share transactional settings edits

    API settings and frontend/plugin pin writers use one transactional settings editor. It preserves formatting, closure results and source-conflict refusals. Only initialization callers can create an absent file.

  • #3446 s/818-od-u1b-prelaunch-product — Share prelaunch settings edits and atomically save invites

    Site creation uses the transactional settings editor. Credential migration uses its pure document editor, retaining bounded reads and skipping absent or malformed input. Unchanged credentials cause no write. Invite generation atomically replaces server configuration, preserving its mode. Obsolete raw settings helpers are removed.

  • #3448 s/820-od-u1c1-change-product — Centralize immediate runtime change effects

    Runtime save callers share synchronous settings invalidation, storage recount and the durable-save announcement. The operation refuses held tree or room guards in debug builds. Package-update failures keep their cleanup recount without announcing a save.

  • #3450 s/822-od-u1c2a-context-product — Share weak change context with room reconciliation

    Room reconciliation uses the same committed-change effects as runtime callers. The context retains cache and quota handles, with weak event and rebuild senders; an idle actor cannot keep the runtime channels or build lane alive.

  • #3452 s/824-od-u1c2b1-git-product — Apply shared change effects to runtime PDS setup

    Runtime PDS setup applies the shared committed-change effects, including cache invalidation and storage recount before save notification. Existing no-op and failure outcomes remain silent.

  • #3454 s/826-od-u1c2b2-remove-product — Remove obsolete PDS notification entry points

    Remove the two obsolete PDS setup wrappers after every caller and test migrated to the runtime entry. PDS durable-save announcements now use the shared change effects.

  • #3456 s/828-od-u1c3a-publication-product — Request one publication per settings save

    Settings saves request only their awaited publication, avoiding a duplicate background request. Runtime settings notification is shared by saves and PDS setup; settings writes still acknowledge after the publication attempt, even when it fails.

  • #3458 s/830-od-u1c3b1-payload-product — Construct committed changes through one entry

    Construct committed writes through Change::saved so the change payload can grow without callers depending on its current field layout. Existing settings flags and messages are preserved.

  • #3460 s/832-od-u1c3b2-effects-product — shared committed change effects

    Centralize post-commit invalidation, accounting, notifications, publication requests and room reconciliation behind Change, with weak actor references and synchronous enqueue before the returned receipt.

  • #3462 s/834-od-u1c3b3-listener-product — remove duplicate settings invalidation

    Remove the asynchronous settings invalidation listener, its unused startup wrapper and test windows now that committed changes invalidate synchronously.

  • #3466 s/838-od-u1d2-stream-product — Join typed browser events once per runtime

    Each runtime joins settings and plugin notifications into one typed browser channel. Lagged browsers refresh current settings, plugins and the filetree. Publication and peer event names stay unchanged.

  • #3468 s/840-od-u1e-ownership-product — Remove the unused settings invalidation fallback

    Runtime reconciliation invalidates settings through the shared change context. Remove the context-free fallback and its unused Settings method.

  • #3470 s/842-od-u1f-artifacts-product — Account for preserved files before failed acknowledgements

    Recount conflict and recovery artifacts even when the requested save fails or autosave is disabled. Keep these refreshes separate from successful-save events and publication.

Commits #

  • e3db32d20 ONE-DOOR unit 1: subunit 1a
  • 1ebc6c97f ONE-DOOR unit 1: subunit 1b
  • 2ec28a375 ONE-DOOR unit 1: subunit 1c
  • a6e1f5bf4 ONE-DOOR unit 1: subunit 1d
  • b591dcbf9 ONE-DOOR unit 1: subunit 1e
  • 19e657edc ONE-DOOR unit 1: subunit 1f

Count and shas #

count-product-code-lines b012f4db8eaf..19e657edc8a8: NET -3 · counted +671 -674 · moved out of the counted set +0 · comment-only deletions flagged 3 · macros flagged 0 · tests-folder code flagged 0

Base b012f4db8eaf15c21c81a363d0023baefade863a (tip of s/814-hx-u6-standard-e2e-fixups-tests). Head 19e657edc8a8b1d6cf39b4cde085de9dc59fdb41. 32 files changed.

Check #

Every changed file is a file one of the product PRs changed, and each is identical at the head to the same file at the last product branch s/842-od-u1f-artifacts-product.

No file here was changed by any tests PR of this unit.

Commits 0