Skip to content

fix(ui-server): commit schedule ledger steps on the write worker - #3015

Merged
schlessera merged 4 commits into
mainfrom
fix/3003-schedules-offloop-044
Oct 26, 2026
Merged

schlessera merged 4 commits into
mainfrom
fix/3003-schedules-offloop-044

Conversation

@schlessera

@schlessera schlessera commented Oct 26, 2026 •

Copy link
Copy Markdown
Owner

Closes #3003
Refs #2850 (epic)

What changed

Schedule proposals, approvals, publication, cancellation and operator reconciliation commit on the shared SQLite write worker at synchronous=FULL. Each route answers after the ledger steps it depends on have committed. Schedule refusals retain their class, code and HTTP status.

Why this shape

Follows the write-worker decision and the merged slices #2933, #2949, #2992 and #2994. Existing transaction bodies and BEGIN IMMEDIATE modes are preserved. A source inventory matches all 16 original SQL write statements.

Publication keeps its boundaries: qualify Git, commit the pending receipt and approval consumption, recheck Git and publish the approved file, then commit activation or quarantine. Cancellation commits the task/occurrence/Queue changes and receipt together before retiring the file; retirement is recorded afterward. A late publisher of a cancelled task journals retirement again. Reopening awaits restored-root adoption and reconciliation before its own transaction.

The excluded boot-time rootInfo insert remains inline. Unwired admission and cron execution are unchanged. No public API or machine-contract change; no CONTRACT: commit. Includes a patch changeset for @schlessera/brain-ui-server.

Proof

Candidate head: 7405e78084f4138eee9362df96f94dc92a3efbe0.
Merged base: 07fbce896099b87903bb994e3b6a939f232669fd (refreshed at the coordinator's request).
Initial baseline: e69ade40513eea1e1aacf636a8da27bb9bd647a1.

Main advanced to b99489b3cbe27fa739fd4d19117cab2cc78f72f3 while the last already-started UI-server run was finishing. No heavy commands remained to start. Per the coordinator's notice, these receipts remain attributed to the head/base above for overlap judgment; the newer base is not merged or qualified here. It changes inbox lifecycle procedures, app registration, citations/API reports and native-harness wiring; it does not change the schedule service files or inbox/store.ts. A fresh combined candidate remains the coordinator's responsibility.

  • Failing first against the original schedule service on 07fbce896: 11 failures with APP_CONNECTION_WRITE, no module-load error.
  • Restored focused proof: 39 tests across schedule worker/service/recovery tests, 225 assertions, zero failures.
  • Refreshed mutation receipts: individually route propose, approve, publish, activate, quarantine, retired, retireAgain, pauseDrifted, cancel, adoptRestoredRoot, and reopen to the app connection: each selected named test fails with APP_CONNECTION_WRITE (11/11). Individually lower each same procedure to synchronous=NORMAL after the worker probe is armed: each fails with SQLITE_WRITE_BELOW_FULL (11/11). All mutations restored. The quarantine test captures its refusal, so either guard surfaces at SCHEDULE_FILE_CONFLICT_CLASS_KEPT with the guard message in the received error.
  • Remove refusal revival: schedule worker refusals… fails SCHEDULE_WORKER_HTTP_REFUSAL_STATUS (503 versus 409).
  • Remove pre-journal Git qualification: schedule publication observes Git… fails SCHEDULE_GIT_CHECK_BETWEEN_COMMITS.
  • Refreshed bunx --no-install tsc --noEmit and bun run lint: pass.
  • Refreshed bun run check:pr --base origin/main through the heavy wrapper: passed, 755 tests across 29 files, 5,033 assertions, zero failures.
  • Refreshed packed-consumer smoke through the heavy wrapper: every publishable package packed, installed and passed its probes.
  • Refreshed bun run test ./tests through the heavy wrapper: passed, 1,966 tests across 179 files, 74,414 assertions, zero failures. The previously failing Claude interactive policy-boundary test passed in this complete run.
  • Refreshed bun run test packages/ui-server through the heavy wrapper: passed, 4,114 tests across 346 files, 28,465 assertions, zero failures.
  • Refreshed native hosted proof: full four-cell matrix plus verified automatic-index negative control passed under native.lock, without load (401.379 s) and under three concurrent dd bs=1M count=1024 conv=fsync writers (444.830 s; successful iterations [780, 783, 784]). Every owned fixture provided complete cleanup receipts. AppArmor is unavailable on this host; these do not qualify AppArmor enforcement.

Earlier complete receipts at head 942897313c06a31499c2509cbc3357598aaa436d remain retained: 4,096 UI-server tests across 345 files (28,404 assertions), 755 preflight tests across 29 files (5,033 assertions), packed-consumer probes, and both full native matrices passed. Its root run had 1,965 pass / 1 fail: Claude interactive AREAS_WRITABLE, expected [true, true], received [false, true]. That occurrence is recorded in #3010. The complete isolated policy-boundary file passes on both pristine 07fbce896 and this refreshed head: 19 tests and 587 assertions each. These controls establish the isolated results, not a cause or repair for the full-suite symptom. The failed receipt is preserved.

Native lag coverage: the pi UID 1000 admission cell makes no schedule requests and begins with an empty operational database. It exercises only the excluded boot root insert, so it cannot provide before/after lag attribution for this group. The separate native schedule control invokes gitCheckIgnored, not proposal/publication SQL. No latency improvement is inferred from an unexercised writer. Actual schedule commits, replay, Git ordering, cancellation/retirement races, Queue changes and HTTP refusals are covered by the real-worker tests.

Citation audit: no repository citations point to schedules/service.ts; the app wiring changes one existing line without moving cited lines. Decision documentation changes only this writer group.

Mutation test mapping (each row was run independently for both app-routing and lowered-durability mutations, exit 1 in all 22 runs):

Procedure Selected test name prefix App-routing assertion Durability assertion
propose schedule propose commits APP_CONNECTION_WRITE SQLITE_WRITE_BELOW_FULL
approve schedule approve commits APP_CONNECTION_WRITE SQLITE_WRITE_BELOW_FULL
publish schedule publish commits APP_CONNECTION_WRITE SQLITE_WRITE_BELOW_FULL
activate schedule publish commits APP_CONNECTION_WRITE SQLITE_WRITE_BELOW_FULL
quarantine schedule quarantine commits APP_CONNECTION_WRITE (captured refusal) SQLITE_WRITE_BELOW_FULL (captured refusal)
retired schedule cancel commits APP_CONNECTION_WRITE SQLITE_WRITE_BELOW_FULL
retireAgain a schedule cancelled during publication APP_CONNECTION_WRITE SQLITE_WRITE_BELOW_FULL
pauseDrifted schedule reconcile commits APP_CONNECTION_WRITE SQLITE_WRITE_BELOW_FULL
cancel schedule cancel commits APP_CONNECTION_WRITE SQLITE_WRITE_BELOW_FULL
adoptRestoredRoot schedule adopt commits APP_CONNECTION_WRITE SQLITE_WRITE_BELOW_FULL
reopen schedule reopen commits APP_CONNECTION_WRITE SQLITE_WRITE_BELOW_FULL

These tests live in packages/ui-server/tests/schedule-writes-offloop.test.ts. Restored focused command: bun run test packages/ui-server/tests/schedule-writes-offloop.test.ts packages/ui-server/tests/schedule-service.test.ts packages/ui-server/tests/schedule-recovery.test.ts. Mutations select the named test with -t; the two additional named assertions above also fail with exit 1. No mutation failed at module load.

Checklist

  • Focused local preflight/behavioral receipts and complete selected hosted proof passed; actual head/base/job checkout evidence is in Proof.
  • Acceptance criteria from the issue are all met, or the gap is named below.
  • The PR and completed/advanced issues have verified release milestones under docs/process/github.md.
  • A changeset is included, or this changes nothing a consumer can see.
  • No personal data anywhere in the diff — the leakage gate covers the whole tree.
  • The integration contract index or relevant component is updated in this same commit, or nothing in the machine surface moved.
  • Docs under docs/ reflect the change, or nothing documented moved.
  • Provider history stays append-only (docs/decisions/provider-history.md): the provider-history guard passes, or nothing on a turn's path changed.

Anything left open

Draft only. All required local proof passed on the recorded head/base. The coordinator must judge the overlap with newer main b99489b3c, refresh the branch and obtain fresh combined-candidate confirmation before ready status or merge. The earlier full-root scratch-writability failure is retained and tracked in #3010; isolated 07fbce896 and refreshed-head controls and the refreshed complete root suite pass. This does not establish a cause or repair for the earlier symptom. Native lag attribution does not cover schedule requests, as explained above.

@schlessera schlessera added this to the 0.44.0 milestone Oct 26, 2026
@schlessera schlessera added type: fix Something is broken and must behave the way it is documented. area: ui-server Hono app factory: turn coordinator, auth, session catalog, routes, cron. labels Oct 26, 2026
# Conflicts:
#	docs/decisions/sqlite-write-worker.md
Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment

Labels

area: ui-server Hono app factory: turn coordinator, auth, session catalog, routes, cron. type: fix Something is broken and must behave the way it is documented.

Projects

None yet

Development

Successfully merging this pull request may close these issues.

ui-server: schedule proposals and publication commit on the write worker

1 participant