Forms #875 - #1281
Open
Polleps wants to merge 65 commits into
Open
Conversation
|
Bugbot is not enabled for your account, so this pull request was not reviewed. Enable Bugbot in the Cursor dashboard to get automatic reviews on future PRs. |
Polleps
force-pushed
the
forms-#875
branch
2 times, most recently
from
August 20, 2026 09:50
040d35f to
03b037f
Compare
The .po catalogs and pnpm-lock.yaml are generated artifacts; both were resolved to develop's side during the rebase, so the forms strings and the form-app/form-renderer workspace entries were missing. Re-extracted with wuchale (no AI translation run) and re-locked with pnpm install. Co-Authored-By: Claude Opus 5 (1M context) <noreply@anthropic.com>
The rights walk now consults the per-query verdict memo by subject before fetching an ancestor, and loads ancestors from materialized propvals instead of decoding their Loro snapshots. Query loops stop calling resolve_query_member after 16 consecutive denials while filling a page, so a fully-private listing no longer fetches every match. Co-authored-by: Polle Pas <polleps@gmail.com>
Each member can carry its own read grant, so a streak of private siblings must not skip later readable rows. Keep resolving until the page is full of authorized hits; the ancestor-fetch memo is what makes that cheap. Co-authored-by: Polle Pas <polleps@gmail.com>
FormCondition resources on pages, fields, and layout blocks, evaluated in document order (AND; empty = always visible). Shared fixtures keep the TS renderer and Rust submit validator in lockstep. Hidden required fields are not errors; submitted values for them are dropped. Co-authored-by: Polle Pas <polleps@gmail.com>
Co-authored-by: Polle Pas <polleps@gmail.com>
The compiler emitted a broken _w_ctx reference, which crashed the form builder as soon as the page settings pane mounted the editor. Co-authored-by: Polle Pas <polleps@gmail.com>
Wuchale rewrote "<FaPlus /> Add condition" into W_tx_ with an undefined _w_ctx_, which crashed the form builder as soon as the page pane mounted. Wrap the label in a span so it extracts as a plain string. Co-authored-by: Polle Pas <polleps@gmail.com>
The e2e server script resolved its binary as `$REPO_ROOT/target/debug/ atomic-server`. That is only where cargo puts it when nothing has moved the target dir — `CARGO_TARGET_DIR` or a `build.target-dir` in any cargo config (commonly `~/.cargo/config.toml`, to share one target dir across checkouts or park it on a faster disk) sends it elsewhere, and the repo-local path then still holds a binary from before that config existed. The suite started happily and served stale server code, failing specs for behaviour fixed weeks earlier, while `cargo build` reported success and changed nothing under test. Ask cargo instead of guessing, and keep the conventional path as the fallback for when cargo cannot answer. Two more things this turned up: - Both staleness guards counted the wuchale-generated locale catalogs as sources. Wuchale rewrites them byte-for-byte identically on every vite start, so the guards fired for anyone who had run `pnpm start` and taught you to pass `--stale-ok` reflexively — which is the flag that lets a genuinely stale build through. Exclude the generated files so the guard only fires when it means something. - `search.spec.ts`'s tag test named its tags `first-tag` / `second-tag`. The folder name was already unique per run, but the tags were not, and `tag:` search is a Tantivy query over the whole store — so every earlier run left another folder carrying those tags. Once enough runs had accumulated, `tag:first-tag` matched dozens of old folders, this run's fell outside the rendered result list, and the spec timed out looking for it. It only reproduces on a store with history, so it survives being run in isolation. Also guard `forms.spec.ts`'s sync predicate with `window.store?.`, matching the equivalent poll in `e2e.spec.ts`: a `waitForFunction` predicate that throws fails the wait outright instead of polling again, so a frame where the store has not attached yet surfaced as `Cannot read properties of undefined`. Verified on a store carrying history: the tag spec goes from failing to passing 5/5, and a full run is 176 passed / 1 failed, the remaining failure being a chatroom load flake that passes 3/3 in isolation. Co-Authored-By: Claude Opus 5 <noreply@anthropic.com>
Wuchale output from running the dev server: fills in the de/es/fr translations for the Cloud Vault, device-link and getting-started strings, and refreshes one placeholder comment in the AI tool-part message. Co-Authored-By: Claude Opus 5 <noreply@anthropic.com>
`CLAUDE.local.md` / `AGENTS.local.md` are the per-checkout, uncommitted counterparts to the tracked `CLAUDE.md` / `AGENTS.md`. Co-Authored-By: Claude Opus 5 <noreply@anthropic.com>
…make options visible in the cards
The rebase left the four catalogs disagreeing with each other: strings develop had retired (the personal -> private drive rename, `Open by URL`) came back as active entries in de/es/fr because the branch's translation commits reintroduced them, and the new entries from both sides landed in a different order per language. Rebuild de/es/fr against en's structure — same msgid sequence, same reference comments — and demote the retired strings to `#~` entries with their translations kept, so nothing translated is thrown away. A data-browser build no longer rewrites any of the four.
Pre-existing on the branch, not caused by the rebase, but they are what stands between it and a green pipeline.
`create a form, add every field type, and persist across reload` did two unrelated jobs. Adding one field of all 24 types cost ~20s of its ~44s — each add is about five sequential resource saves (property, ontology, row class, field, page) — and the regression walk it was welded to only ever touched four of those fields. Split in two. The breadth test adds all 24 and reloads; the walk adds the four it edits and keeps its sequence (creation -> property sync -> rename -> delete -> reload) intact, which is what its comment says is the point. Coverage is unchanged. Measured on forms.spec.ts at 2 workers, alternating before/after runs to cancel machine drift: 43.5/43.7s before, 34.3/34.8s after. The walk alone drops from 44.5s to 15.3s, which is the one you re-run while debugging. `test.slow()` stays on the breadth test — 33s here, and CI boxes are slower. The walk no longer needs it.
Adds `form-open-at` / `form-close-at` to the forms ontology and gates every
visitor-facing `/form/{id}` route on the resulting window: a published form
is not yet open before `form-open-at` and closed from `form-close-at`, each
with its own 410 wording (and the moment in UTC). The builder's Settings tab
gets a Schedule section, and the Publish toggle shows a Scheduled / Closed
badge so "Unpublish" is not the only signal on a form no visitor can open.
Covered by the `forms::` scheduling unit tests, `form_submission_flow`
step 7b, and the "a scheduled window opens and closes a published form" e2e.
Co-Authored-By: Claude Fable 5.1 <noreply@anthropic.com>
…m routes
Two unrelated defects behind "once a commit for a form is parked, the
server's copy never advances again".
The parked commit: class extenders shape a GET response with
`Resource::set`, which also records a Loro op on the doc decoded from the
stored snapshot, and JSON-AD serialization re-exported that doc as the
served `loroUpdate`. The Form extender did this for `form-submission-summary`
on every HTTP GET, so a builder tab hydrated over HTTP held an op the server
never persisted and its next delta, whatever the edit, depended on it.
`get_resource_extended` now pins the served `loroUpdate` to the persisted
snapshot after any extender (and the `incomplete` marker), and the Form
extender attaches the summary without touching the doc.
"Never advances again": the server had converged (the client's snapshot
recovery works), but `/form/{id}/definition` answered `410` without
`Cache-Control`, and Chromium replayed the cached `410` for every later
fetch of that URL — from the e2e probe and a console `fetch` alike. Every
form API response now carries `Cache-Control: no-store`, the e2e probe
fetches with `cache: 'no-store'`, and the trimmed reopen assertion in the
scheduled-window e2e is restored.
Regression tests: `class_extender::extended_get_serves_the_persisted_snapshot`
and `form_submission_flow` steps 1, 2 and 2b.
Co-Authored-By: Claude Fable 5.1 <noreply@anthropic.com>
This file contains hidden or bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
Sign up for free
to join this conversation on GitHub.
Already have an account?
Sign in to comment
Add this suggestion to a batch that can be applied as a single commit.This suggestion is invalid because no changes were made to the code.Suggestions cannot be applied while the pull request is closed.Suggestions cannot be applied while viewing a subset of changes.Only one suggestion per line can be applied in a batch.Add this suggestion to a batch that can be applied as a single commit.Applying suggestions on deleted lines is not supported.You must change the existing code in this line in order to create a valid suggestion.Outdated suggestions cannot be applied.This suggestion has been applied or marked resolved.Suggestions cannot be applied from pending reviews.Suggestions cannot be applied on multi-line comments.Suggestions cannot be applied while the pull request is queued to merge.Suggestion cannot be applied right now. Please check back later.
Related Issues
closes #875
Checklist