Conloca is a visual CMS for Astro sites: editors change pages in the browser and the content is committed to Git. In October Ultra / Mextner delivered fixes across the editor, invites and sign-in, content and media handling, and the production site.
The documentation theme picker is implemented and checked but awaits team review, so it is shown separately below.
397.6 → 0 px
How it works image movement during delayed hydration, in the browser test of #342
33.6 MB
snapshot that now imports in bounded parts of at most 16 MiB (#259)
409
answer to a write from an editor tab whose repository, branch or site differs, given before any billing, storage or Git work (#192, #224)
What we delivered
Editor and page actions
Dragging blocks into a page, Undo after adding a block and the Dashboard New Page button now work. A disabled Preview button explains why it is unavailable. Never-published pages read Draft in the Pages list and on the Dashboard. A route or schema error shows a CMS error page or notice instead of the developer screen, and the branch-name field formats as you type. These were everyday actions that did nothing or showed the wrong state.
Owner request (excerpt)
Original request (RU)
все баги которые никто не делает и почини по tdd в параллельных ворктри и влей через gh ship Важны максимально реалистичные е2е тесты В задачи поставь меня исполнителем Приложи пруфами скриншоты до и после
English translation
all the bugs nobody is working on, and fix them with TDD in parallel worktrees and merge through gh ship. Maximally realistic e2e tests are important. Put me as the assignee in the tasks. Attach screenshots from before and after as proof.
Source. Ultra / Mextner · Ultra's omp prompt history, project conloca · no message id · 22 October 2026, 10:39 UTC. Sender: the owner's own prompt history; it has no per-message author field, so attribution is by account. Full-message SHA-256 1ea5051957cda4839152034111af4c51789e7761deb61386ab53bc2627c82c4d.
Inferred link. The instruction under which the October editor bugs were taken from the team's bug database. It names no single pull request.
The opening words of the message and the link to the private bug database are left out.
Owner request (excerpt)
Original request (RU)
И параллельно в новом вт почини
English translation
And in parallel, in a new worktree, fix [the linked bug-database entry “Dashboard New page button bug”].
Source. Ultra / Mextner · Ultra's omp prompt history, project conloca · no message id · 22 October 2026, 18:09 UTC. Sender: the owner's own prompt history; it has no per-message author field, so attribution is by account. Full-message SHA-256 7669ba062bc44797708bedd3cc4b6cbc332f79d389145bf379003cdf2ee20979.
Inferred link. By the title in the link's address (the Dashboard New Page fix, #302). The link itself is not republished.
Owner request (excerpt)
Original request (RU)
еще задача: Cannot drag blocks onto an empty page. no block is added and the canvas remains empty. No error messages or guidance is displayed.
English translation
one more task: [English bug text, as pasted from the bug database:] Cannot drag blocks onto an empty page. no block is added and the canvas remains empty. No error messages or guidance is displayed.
Source. Ultra / Mextner · Ultra's omp prompt history, project conloca · no message id · 22 October 2026, 23:45 UTC. Sender: the owner's own prompt history; it has no per-message author field, so attribution is by account. Full-message SHA-256 e3869c29e076499fd4a50480adf8214b79b44f05f6143248f2f1db6ae57f3d9f.
Inferred link. By topic (the empty-page drag fix, #299). Only «еще задача:» is the owner's wording; the English after it is bug text pasted from the bug database.
Owner request (excerpt)
Original request (RU)
и еще одна: Pages - Status badges don’t reflect real status. All pages are always showing published. Even when I just created one.
English translation
and one more: [English bug text, as pasted from the bug database:] Pages - Status badges don’t reflect real status. All pages are always showing published. Even when I just created one.
Source. Ultra / Mextner · Ultra's omp prompt history, project conloca · no message id · 22 October 2026, 23:46 UTC. Sender: the owner's own prompt history; it has no per-message author field, so attribution is by account. Full-message SHA-256 f2437f51dc49ba9358e730e76d4e740c178b5d078d72d5653d554744d4a7d06c.
Inferred link. By topic (the Draft status fix, #296 and #307). Only «и еще одна:» is the owner's wording; the English after it is pasted bug text.
New branch field: original request and production recording
Owner request (excerpt)
Original request (RU)
и вот эту возьми: New branch - Branch name formatting problem. Problem:
SPACE can’t be used in a branch name, but we still allow users to type it and then show error.
Solution:
We need to automatically format the user inputed text like following: enforce lowercase, automatically type - when user uses SPACE.
English translation
and take this one too: [English bug text, as pasted from the bug database:] New branch - Branch name formatting problem. Problem: SPACE can’t be used in a branch name, but we still allow users to type it and then show error. Solution: We need to automatically format the user inputed text like following: enforce lowercase, automatically type - when user uses SPACE.
Source. Ultra / Mextner · Ultra's omp prompt history, project conloca · no message id · 22 October 2026, 23:51 UTC. Sender: the owner's own prompt history; it has no per-message author field, so attribution is by account. Full-message SHA-256 fdf731854e8a0dd58796a4e33ebfdc825f582d5f60d945a7fed1d64f4b204e3a.
Inferred link. By topic (the branch-name formatting fix, #297 and #316). Only «и вот эту возьми:» is the owner's wording; the English after it is pasted bug text. A screenshot attached to the message was not recovered.
The recording is footage of the production CMS made by the team and attached to pull request #316. This page shows a cropped copy of the New branch form. It checks only that the caret stays in place while the text is formatted.
Recorded production browser checkNew branch field keeps the caret while formatting. Footage recorded by the team on the production site and attached to the pull request. It is not a CI or end-to-end test run and not full acceptance. MP4 file
Page
the New branch form in the production CMS
Pull request
#316 (merged), the original recording shows a signed-in workspace and stays in the private repository; this page shows a cropped copy of the New branch form only
Recorded
29 October 2026, 15:00 UTC (attached to the pull request on 3 November), 10 seconds; real Chrome against the production CMS, signed in; the form was exercised without submitting
What it shows
Typing in the Branch name field while the caret sits after a Greek sigma. The pull request reports five DOM-backed checks passing for this scenario. It is not branch creation or release sign-off.
File
600×460, 10.05 s, 100 frames, no audio. MP4 SHA-256 175ed0005255fa6b785d89339335211cda5760fd74ba0f45ecd38630a0455a8d, WebM alternate SHA-256 8f160203355c2076ac9eedc6b893fc30effaf35460d3a51e2aa58565ccffae71. This is a derived copy: the original recording is not republished; it was cropped to the form (region 300×230 px at 182,40, scaled ×2). Original SHA-256 ce25011c07367aff2de27d53927b8212f55af2815cf55b72c731146268f84c86.
Sign-in divider in the dark theme
Merged, pull request #220 Single capture: after only.
Frame of the recording Frame at 3.9 s of the production recording below: the sign-in divider in the dark theme. Full-size original (1280×800 PNG)
The divider lines and the word “or” are visible against the dark card.
A frame of the production recording of pull request #220 shown below, at 3.9 seconds, 1280×800. The recording has no before capture.
Sign-in divider: production browser checks, desktop and phone width
Footage of the production sign-in page made by the team and attached to pull request #220. Each clip starts in the light theme and switches to the dark theme.
Recorded production browser checkSign-in divider, desktop, light then dark. Footage recorded by the team on the production site and attached to the pull request. It is not a CI or end-to-end test run and not full acceptance. MP4 file
Page
the production sign-in page
Pull request
#220 (merged), attached to the pull request in the private repository conloca/private (access required)
Recorded
3 November 2026 (comment date), 4.1 seconds; real Chrome against production, 1280×800, no account signed in
What it shows
The divider colour in the light and then the dark theme. It is not an accessibility audit and not a pixel baseline.
Recorded production browser checkSign-in divider, phone width, light then dark. Footage recorded by the team on the production site and attached to the pull request. It is not a CI or end-to-end test run and not full acceptance. MP4 file
Page
the production sign-in page
Pull request
#220 (merged), attached to the pull request in the private repository conloca/private (access required)
Recorded
3 November 2026 (comment date), 4.1 seconds; real Chrome against production, 390×844, no account signed in
What it shows
The divider colour in the light and then the dark theme at phone width.
Puck ignores a press on a real <button>, so the block-list item is a div role="button" again, and an empty page says how to add a block (#299). Undo and Redo remove and restore a block added by drag or double-click (#306).
The Dashboard New Page button opens the create-page dialog in place (#302). One pageStatusOf() and a LocaleVersion.unpublished marker decide page status, and saving a new translation keeps a never-published page a draft (#296, #307).
A route that fails to render shows RouteErrorPage, and a site schema that is not a generated host schema shows a notice instead of crashing the CMS (#301, #293, #295). The disabled Preview button shows its explanation when clicked (#262).
The New branch field lowercases, hyphenates and keeps the caret in place as you type (#297, #316). The editor opens pages with no English variant (#196), and draft previews parse records with each collection’s schema so dates and defaults match the build (#248).
Frontmatter keys such as __proto__.polluted cannot mutate Object.prototype, while own-data keys, including legitimate constructor and prototype names, are kept (#239). The sign-in divider is readable in dark mode; login-theme.spec.ts checks light and dark at 390 and 1280 px (#220).
Accepting an invite lands in the invited workspace, from both the in-app button and the emailed link. Each editor tab sends its repository, branch and site with every write, and the server rejects a mismatch with a 409 instead of writing to the wrong place. Tabs of one browser origin that refresh at the same moment share one token rotation instead of revoking the whole token family.
Owner request
Original request (RU)
Задача: When inviting someone to a workspace, they don't always get redirected to the invited workspace when clicking accept invite in a received mail
English translation
Task: [English bug text, as pasted from the bug database:] When inviting someone to a workspace, they don't always get redirected to the invited workspace when clicking accept invite in a received mail
Source. Ultra / Mextner · Ultra's omp prompt history, project conloca · no message id · 22 October 2026, 13:27 UTC. Sender: the owner's own prompt history; it has no per-message author field, so attribution is by account. Full-message SHA-256 59a3431d16bdddc2b358f19a80548dfcf20b9e974aeed17282ce6a3d534902aa.
Inferred link. By topic (the invite-landing fixes, #288, #289 and #305). Only «Задача:» is the owner's wording; the English after it is pasted bug text.
Technical detail
Mutations carry X-Conloca-Editor-Repo, -Branch and -Site headers. The worker answers 409 workspace-mismatch before any billing, storage or Git work, and the tab re-enters its own branch and retries once (#192, #224).
Accept waits at most 5 seconds for the membership flush and the Org Durable Object’s alarm delivers the rest; an invite screen that would stay on “accepting” is released after 20 seconds (#292, #305). A deployed-stage proof, invite-landing.spec.ts, covers an invitee who already has a workspace (#294).
A second use of a refresh cookie within 10 seconds gets the live token from the rotation chain, and the browser refreshes under a Web Lock so same-origin tabs send one request per rotation (#240). An OAuth failure shows its failure screen instead of looping (#225).
Splitting the sign-in and Members screens into props-only views fixed a double submit that requested two sign-in links and a double click that sent two invitations (#253, #223).
Cloudflare Access configuration fails closed with 401 when only one of its two settings is present (#191). Overlay rows for pages deleted in Git are pruned (#188). Workspace and flag types are narrowed instead of cast (#222).
Scoped content commits, safe asset moves and correct write-back
CMS commits include only content files, so other people’s staged work is left out, and an asset move claims its destination instead of overwriting an existing file. Draft images render in the canvas before Publish, and a docs-root page is written back to the file it was read from. The hosted preview shows pages committed after its build, and a site snapshot over Cloudflare’s 32 MiB call limit imports in bounded parts.
Technical detail
CMS commits build their tree in a private index seeded from HEAD and move HEAD by compare-and-swap with update-ref, so a concurrent commit is not reverted. Asset moves run one at a time and claim the destination with a hard link. Tests use real temporary repositories: foreign staged files, two concurrent instances, a held index.lock and concurrent moves racing for one name (#197).
Draft images are served from /api/v1/assets/draft/<folder>/<file> while stored data keeps the canonical /assets/... reference (#243). A docs-root MDX page used to be written to a shadow file; mdx-pages-root.test.ts covers edit, delete, create-after-delete and a collision (#235).
The hosted preview records its own buildCommit and sends it as ?build=; the worker diffs that commit against the branch head and matches entries by blob id. A deployed-stage test commits a title without redeploying and expects the new heading (#247, spec change #228).
The depth-1 snapshot of one pull request packs to about 33.6 MB, over the 32 MiB RPC limit. It now lands in parts of at most 16 MiB with the tree and commit last, and a live check against github.com imported the full closure of 4,836 objects (#259). A missing base tree is fetched by object id instead of failing the import (#256).
Org import now always retries the tracker reconcile when a ref already matches upstream, so a stale preview session recovers (#177). Only three of Ultra’s 29 commits in #177 are credited: the repair, its at-head regression test and the browser publication proof. The vocabulary sample stays off the Git lookup behind the unpublished marker (#308).
The production How it works page uses the completed design: a four-step flow with MDX, JSON and editor visuals, twelve responsive images and an install banner that survives 200% text. The design is by Saba; our work is the integration into the production site and its checks. In the pull request’s delayed-hydration test, images moved 397.6 px before the fix and 0 px after it.
How it works on production: browser check
Footage of the production page made by the team and attached to pull request #342. The page is public. There is no before footage.
Recorded production browser checkHow it works page on production. Footage recorded by the team on the production site and attached to the pull request. It is not a CI or end-to-end test run and not full acceptance. MP4 file
Page
https://conloca.com/how-it-works
Pull request
#342 (merged 27 October 2026), attached to the pull request in the private repository conloca/private (access required)
Recorded
28 October 2026, 20:14 to 20:15 UTC; real Chrome against production, viewport 1348×936, no cuts or speed changes
What it shows
Hero, the four-step flow, the layered visual, the cards, the install banner, the pnpm, npm and bun tab selection, and the footer Docs link, on desktop only.
The twelve PNGs were imported byte for byte, with SHA-256 and byte lengths checked on the preview. Existing routes, app links, docs links and install tabs are kept, and text is darkened where the original failed contrast (#342).
The test measured 397.587 px of movement before and 0 px across 53 frames after. Twenty-one website targets and 50 browser checks were rerun.
The merge to the main branch ran Validate, deployed-stage browser tests and Deploy Production, all successful. Locally, the split-port development stack redirects backend landings to the app and keeps published media on local origins (#231).
The CMS and the app each build a static Storybook catalogue in CI, and state stories cover save, sync and workspace status, the page list and the conflict dialogs. Deployed-stage browser tests walk every CMS route, create a branch through the Branch menu, confirm a new page reads Draft and check that typed text survives reopening the editor in both themes. CI keeps the proof folder of every deployed-stage run.
Technical detail
State stories render the real components with fixtures that stop at HostClient and the content API fetch, so nothing reaches the network. Counts: SaveSlot 6 plus phone, SyncStatusSlot 8 plus phone, WorkspaceStatusSlot 8 plus phone, CmsHostPlaceholder 9 (#244). CI saves a screenshot of every story at 1280 × 800 and 390 × 844. The app Storybook runner now compiles Tailwind, because classes such as max-sm:hidden were missing from all app examples.
A flaky failure in the Several Locales scenario, caused by a viewport resize landing mid-play, is gone: resizes during play went from 30 and 11 to 0 and 0 in the probe runs (#257).
The deployed-stage job keeps its proof folder on every run and the Playwright report on failed runs (#320). A manual staging proof workflow adds two new legs (#261), and the emitted billing deploy bundle runs in CI (#238).
Real-engine and typed tests for Git paths, billing identity mapping, workspace recovery and memory behaviour were added or made deterministic (#198, #234, #221, #236, #201, #254). Branch creation and the Draft check are in #229 and #309, and the editor-reopen check is in #226.
A pull-request stage environment that keeps working
Pull-request stages are cleaned up on a schedule with capacity reporting and stage leases, which brought the Cloudflare namespace count to 386 of 500 after the first eviction run. Each stage uses one Durable Object namespace fewer, and each deployment attempt gets its own preview fixture without resetting drafts. Before this, Deploy Stage was failing account-wide with Cloudflare error 10067 after about 170 namespaces leaked from closed pull requests.
Technical detail
A scheduled workflow runs every six hours, reports capacity and fails above 400 of 500 namespaces. Drafts hold a stage for 24 hours and ready pull requests for 72 hours; keep-stage and evict-stage override that. tooling/pr-stage-gc.test.ts checks that only closed same-repo pull requests are selected (#200).
Deleting the unused EventLogDO takes each stage from 10 namespaces to 9, which the pull request estimates moves live capacity from about 48 to about 53 stages (#241).
Readiness rejects dirty overlays and divergent session heads, and older attempt orgs are retired after 24 hours (#169). A read-only inventory of legacy preview resources deletes nothing (#155). A Deploy Production failure on a missing generated contracts module was fixed (#258), and E2E runs leave branches clean (#193).
Project validation moved from hand-written Zod schemas to validators generated from the TypeScript types with Typia. The editor builds its forms from the generated schema metadata, and the loader reports field paths. We adapted the existing generated-contract work to the editor, loader, CLI and sites.
Technical detail
Site schemas become HostSchema<T>: a generated validator with JSON Schema metadata. The editor builds its forms from that metadata, and the loader reports field paths. content-api drops zod and conformance rule A76 forbids it in every workspace package (#251).
Key pull request: #251 · 28 pull requests in this group, most of them build, test and CI changes, all in the source record
Before and after in numbers
Each row compares the state before the change with the state after it. Figures are taken from the pull request named in the last column.
Measure
Before
After
Source
Image movement on How it works during delayed hydration (browser test)
Opened in November and separate from the October merges above. Implemented and checked, not merged.
IMPLEMENTED · NOT MERGED
Documentation theme picker
The documentation site’s native Auto dropdown is replaced by Light, Dark and System controls with a visible selection, keyboard navigation and touch targets. The head of the pull request passed its deployed-stage browser tests, and the preview site is live. The change awaits team review.
The theme control on production and on the pull request #489 preview, both captured at 1440 px on 5 November. Each crop cuts the header where the control sits. Click a crop to open the full capture. The before image is production and the after image is the preview of an open pull request that is not merged.
Documentation theme control
Open pull request, not merged Before and after: same window, same region, same scale.
Before · production Production conloca.com, captured 5 November 2026: the theme control is a native select. Full-size original (1440×1000 PNG)
It is a native select that opens an operating-system menu.
After · PR preview Pull request #489 preview stage, same page, viewport and crop: Light, Dark and System as a visible control. Full-size original (1440×1000 PNG)
Three visible choices; the active one, System, is highlighted.
Same page (getting-started), viewport 1440×1000 and crop, captured two seconds apart on 5 November 2026. The before image is production conloca.com. The after image is the pull request #489 preview stage, a different deployment of an open pull request.
Proof
Recordings. The four clips on this page are production browser checks recorded by the team and attached to pull requests. They are not CI or end-to-end test runs and not full acceptance. The repository’s CI keeps no video or trace artifact, and a CI job page is not a recording, so none is presented as one.
Owner priority (excerpt)
Original request (RU)
Полностью рабочая конлока в нашем продукте, подтвержденная е2е тестами и скриншотами
English translation
A fully working Conloca in our product, confirmed by e2e tests and screenshots.
Source. Ultra / Mextner · Telegram, private chat between Ultra and the assistant bot · Telegram message id 180834 · 18 August 2026, 17:54 UTC. Sender: incoming Telegram message from the owner's account (not the assistant, not another person). Full-message SHA-256 d65be6db2be49447aa7b6467294c830b9bbc2c0007f3f48de41a7a4d7ccf4618.
Inferred link. Context for the proof below, not for one outcome: the owner's standing priority for Conloca as stated in a message about the day's work.
18 August 2026, before the October period of this report; kept because it states the owner's standing priority.
Hosted CI runs for the final commit of each pull request, or for the merge commit where noted.
Work by Ultra / Mextner (GitHub alex-mextner, Alex Ultra). Pull requests merged 1 to 31 October 2026 are credited by commit authorship, and 92 merged pull requests are counted, one of them for named commits only. Status checked 6 November. Source links may require repository access.
Attribution: every commit in these pull requests is by Ultra, except #177. #167, #168 and #169 were opened from the smoothbricker account and merged by alex-mextner. #177 is credited only for three of Ultra’s 29 commits there: the stale preview-session repair, its at-head regression test and the browser publication proof. Pull requests whose commits are by other authors are counted only in aggregate in the source record.
All merged pull requests counted here are listed with their authors and merge commits in the source record.
+
Conloca: October 2026
Editor fixes, workspace safety, content integrity, the production How it works page
Conloca is a visual CMS for Astro sites: editors change pages in the browser and the content is committed to Git. In October Ultra / Mextner delivered fixes across the editor, invites and sign-in, content and media handling, and the production site.
The documentation theme picker is implemented and checked but awaits team review, so it is shown separately below.
397.6 → 0 px
How it works image movement during delayed hydration, in the browser test of #342
33.6 MB
snapshot that now imports in bounded parts of at most 16 MiB (#259)
409
answer to a write from an editor tab whose repository, branch or site differs, given before any billing, storage or Git work (#192, #224)
What we delivered
Editor and page actions
Dragging blocks into a page, Undo after adding a block and the Dashboard New Page button now work. A disabled Preview button explains why it is unavailable. Never-published pages read Draft in the Pages list and on the Dashboard. A route or schema error shows a CMS error page or notice instead of the developer screen, and the branch-name field formats as you type. These were everyday actions that did nothing or showed the wrong state.
Owner request (excerpt)
Original request (RU)
все баги которые никто не делает и почини по tdd в параллельных ворктри и влей через gh ship Важны максимально реалистичные е2е тесты В задачи поставь меня исполнителем Приложи пруфами скриншоты до и после
English translation
all the bugs nobody is working on, and fix them with TDD in parallel worktrees and merge through gh ship. Maximally realistic e2e tests are important. Put me as the assignee in the tasks. Attach screenshots from before and after as proof.
Source. Ultra / Mextner · Ultra's omp prompt history, project conloca · no message id · 22 October 2026, 10:39 UTC. Sender: the owner's own prompt history; it has no per-message author field, so attribution is by account. Full-message SHA-256 1ea5051957cda4839152034111af4c51789e7761deb61386ab53bc2627c82c4d.
Inferred link. The instruction under which the October editor bugs were taken from the team's bug database. It names no single pull request.
The opening words of the message and the link to the private bug database are left out.
Owner request (excerpt)
Original request (RU)
И параллельно в новом вт почини
English translation
And in parallel, in a new worktree, fix [the linked bug-database entry “Dashboard New page button bug”].
Source. Ultra / Mextner · Ultra's omp prompt history, project conloca · no message id · 22 October 2026, 18:09 UTC. Sender: the owner's own prompt history; it has no per-message author field, so attribution is by account. Full-message SHA-256 7669ba062bc44797708bedd3cc4b6cbc332f79d389145bf379003cdf2ee20979.
Inferred link. By the title in the link's address (the Dashboard New Page fix, #302). The link itself is not republished.
Owner request (excerpt)
Original request (RU)
еще задача: Cannot drag blocks onto an empty page. no block is added and the canvas remains empty. No error messages or guidance is displayed.
English translation
one more task: [English bug text, as pasted from the bug database:] Cannot drag blocks onto an empty page. no block is added and the canvas remains empty. No error messages or guidance is displayed.
Source. Ultra / Mextner · Ultra's omp prompt history, project conloca · no message id · 22 October 2026, 23:45 UTC. Sender: the owner's own prompt history; it has no per-message author field, so attribution is by account. Full-message SHA-256 e3869c29e076499fd4a50480adf8214b79b44f05f6143248f2f1db6ae57f3d9f.
Inferred link. By topic (the empty-page drag fix, #299). Only «еще задача:» is the owner's wording; the English after it is bug text pasted from the bug database.
Owner request (excerpt)
Original request (RU)
и еще одна: Pages - Status badges don’t reflect real status. All pages are always showing published. Even when I just created one.
English translation
and one more: [English bug text, as pasted from the bug database:] Pages - Status badges don’t reflect real status. All pages are always showing published. Even when I just created one.
Source. Ultra / Mextner · Ultra's omp prompt history, project conloca · no message id · 22 October 2026, 23:46 UTC. Sender: the owner's own prompt history; it has no per-message author field, so attribution is by account. Full-message SHA-256 f2437f51dc49ba9358e730e76d4e740c178b5d078d72d5653d554744d4a7d06c.
Inferred link. By topic (the Draft status fix, #296 and #307). Only «и еще одна:» is the owner's wording; the English after it is pasted bug text.
New branch field: original request and production recording
Owner request (excerpt)
Original request (RU)
и вот эту возьми: New branch - Branch name formatting problem. Problem:
SPACE can’t be used in a branch name, but we still allow users to type it and then show error.
Solution:
We need to automatically format the user inputed text like following: enforce lowercase, automatically type - when user uses SPACE.
English translation
and take this one too: [English bug text, as pasted from the bug database:] New branch - Branch name formatting problem. Problem: SPACE can’t be used in a branch name, but we still allow users to type it and then show error. Solution: We need to automatically format the user inputed text like following: enforce lowercase, automatically type - when user uses SPACE.
Source. Ultra / Mextner · Ultra's omp prompt history, project conloca · no message id · 22 October 2026, 23:51 UTC. Sender: the owner's own prompt history; it has no per-message author field, so attribution is by account. Full-message SHA-256 fdf731854e8a0dd58796a4e33ebfdc825f582d5f60d945a7fed1d64f4b204e3a.
Inferred link. By topic (the branch-name formatting fix, #297 and #316). Only «и вот эту возьми:» is the owner's wording; the English after it is pasted bug text. A screenshot attached to the message was not recovered.
The recording is footage of the production CMS made by the team and attached to pull request #316. This page shows a cropped copy of the New branch form. It checks only that the caret stays in place while the text is formatted.
Recorded production browser checkNew branch field keeps the caret while formatting. Footage recorded by the team on the production site and attached to the pull request. It is not a CI or end-to-end test run and not full acceptance. MP4 file
Page
the New branch form in the production CMS
Pull request
#316 (merged), the original recording shows a signed-in workspace and stays in the private repository; this page shows a cropped copy of the New branch form only
Recorded
29 October 2026, 15:00 UTC (attached to the pull request on 3 November), 10 seconds; real Chrome against the production CMS, signed in; the form was exercised without submitting
What it shows
Typing in the Branch name field while the caret sits after a Greek sigma. The pull request reports five DOM-backed checks passing for this scenario. It is not branch creation or release sign-off.
File
600×460, 10.05 s, 100 frames, no audio. MP4 SHA-256 175ed0005255fa6b785d89339335211cda5760fd74ba0f45ecd38630a0455a8d, WebM alternate SHA-256 8f160203355c2076ac9eedc6b893fc30effaf35460d3a51e2aa58565ccffae71. This is a derived copy: the original recording is not republished; it was cropped to the form (region 300×230 px at 182,40, scaled ×2). Original SHA-256 ce25011c07367aff2de27d53927b8212f55af2815cf55b72c731146268f84c86.
Sign-in divider in the dark theme
Merged, pull request #220 Single capture: after only.
Frame of the recording Frame at 3.9 s of the production recording below: the sign-in divider in the dark theme. Full-size original (1280×800 PNG)
The divider lines and the word “or” are visible against the dark card.
A frame of the production recording of pull request #220 shown below, at 3.9 seconds, 1280×800. The recording has no before capture.
Sign-in divider: production browser checks, desktop and phone width
Footage of the production sign-in page made by the team and attached to pull request #220. Each clip starts in the light theme and switches to the dark theme.
Recorded production browser checkSign-in divider, desktop, light then dark. Footage recorded by the team on the production site and attached to the pull request. It is not a CI or end-to-end test run and not full acceptance. MP4 file
Page
the production sign-in page
Pull request
#220 (merged), attached to the pull request in the private repository conloca/private (access required)
Recorded
3 November 2026 (comment date), 4.1 seconds; real Chrome against production, 1280×800, no account signed in
What it shows
The divider colour in the light and then the dark theme. It is not an accessibility audit and not a pixel baseline.
Recorded production browser checkSign-in divider, phone width, light then dark. Footage recorded by the team on the production site and attached to the pull request. It is not a CI or end-to-end test run and not full acceptance. MP4 file
Page
the production sign-in page
Pull request
#220 (merged), attached to the pull request in the private repository conloca/private (access required)
Recorded
3 November 2026 (comment date), 4.1 seconds; real Chrome against production, 390×844, no account signed in
What it shows
The divider colour in the light and then the dark theme at phone width.
Puck ignores a press on a real <button>, so the block-list item is a div role="button" again, and an empty page says how to add a block (#299). Undo and Redo remove and restore a block added by drag or double-click (#306).
The Dashboard New Page button opens the create-page dialog in place (#302). One pageStatusOf() and a LocaleVersion.unpublished marker decide page status, and saving a new translation keeps a never-published page a draft (#296, #307).
A route that fails to render shows RouteErrorPage, and a site schema that is not a generated host schema shows a notice instead of crashing the CMS (#301, #293, #295). The disabled Preview button shows its explanation when clicked (#262).
The New branch field lowercases, hyphenates and keeps the caret in place as you type (#297, #316). The editor opens pages with no English variant (#196), and draft previews parse records with each collection’s schema so dates and defaults match the build (#248).
Frontmatter keys such as __proto__.polluted cannot mutate Object.prototype, while own-data keys, including legitimate constructor and prototype names, are kept (#239). The sign-in divider is readable in dark mode; login-theme.spec.ts checks light and dark at 390 and 1280 px (#220).
Accepting an invite lands in the invited workspace, from both the in-app button and the emailed link. Each editor tab sends its repository, branch and site with every write, and the server rejects a mismatch with a 409 instead of writing to the wrong place. Tabs of one browser origin that refresh at the same moment share one token rotation instead of revoking the whole token family.
Owner request
Original request (RU)
Задача: When inviting someone to a workspace, they don't always get redirected to the invited workspace when clicking accept invite in a received mail
English translation
Task: [English bug text, as pasted from the bug database:] When inviting someone to a workspace, they don't always get redirected to the invited workspace when clicking accept invite in a received mail
Source. Ultra / Mextner · Ultra's omp prompt history, project conloca · no message id · 22 October 2026, 13:27 UTC. Sender: the owner's own prompt history; it has no per-message author field, so attribution is by account. Full-message SHA-256 59a3431d16bdddc2b358f19a80548dfcf20b9e974aeed17282ce6a3d534902aa.
Inferred link. By topic (the invite-landing fixes, #288, #289 and #305). Only «Задача:» is the owner's wording; the English after it is pasted bug text.
Technical detail
Mutations carry X-Conloca-Editor-Repo, -Branch and -Site headers. The worker answers 409 workspace-mismatch before any billing, storage or Git work, and the tab re-enters its own branch and retries once (#192, #224).
Accept waits at most 5 seconds for the membership flush and the Org Durable Object’s alarm delivers the rest; an invite screen that would stay on “accepting” is released after 20 seconds (#292, #305). A deployed-stage proof, invite-landing.spec.ts, covers an invitee who already has a workspace (#294).
A second use of a refresh cookie within 10 seconds gets the live token from the rotation chain, and the browser refreshes under a Web Lock so same-origin tabs send one request per rotation (#240). An OAuth failure shows its failure screen instead of looping (#225).
Splitting the sign-in and Members screens into props-only views fixed a double submit that requested two sign-in links and a double click that sent two invitations (#253, #223).
Cloudflare Access configuration fails closed with 401 when only one of its two settings is present (#191). Overlay rows for pages deleted in Git are pruned (#188). Workspace and flag types are narrowed instead of cast (#222).
Scoped content commits, safe asset moves and correct write-back
CMS commits include only content files, so other people’s staged work is left out, and an asset move claims its destination instead of overwriting an existing file. Draft images render in the canvas before Publish, and a docs-root page is written back to the file it was read from. The hosted preview shows pages committed after its build, and a site snapshot over Cloudflare’s 32 MiB call limit imports in bounded parts.
Technical detail
CMS commits build their tree in a private index seeded from HEAD and move HEAD by compare-and-swap with update-ref, so a concurrent commit is not reverted. Asset moves run one at a time and claim the destination with a hard link. Tests use real temporary repositories: foreign staged files, two concurrent instances, a held index.lock and concurrent moves racing for one name (#197).
Draft images are served from /api/v1/assets/draft/<folder>/<file> while stored data keeps the canonical /assets/... reference (#243). A docs-root MDX page used to be written to a shadow file; mdx-pages-root.test.ts covers edit, delete, create-after-delete and a collision (#235).
The hosted preview records its own buildCommit and sends it as ?build=; the worker diffs that commit against the branch head and matches entries by blob id. A deployed-stage test commits a title without redeploying and expects the new heading (#247, spec change #228).
The depth-1 snapshot of one pull request packs to about 33.6 MB, over the 32 MiB RPC limit. It now lands in parts of at most 16 MiB with the tree and commit last, and a live check against github.com imported the full closure of 4,836 objects (#259). A missing base tree is fetched by object id instead of failing the import (#256).
Org import now always retries the tracker reconcile when a ref already matches upstream, so a stale preview session recovers (#177). Only three of Ultra’s 29 commits in #177 are credited: the repair, its at-head regression test and the browser publication proof. The vocabulary sample stays off the Git lookup behind the unpublished marker (#308).
The production How it works page uses the completed design: a four-step flow with MDX, JSON and editor visuals, twelve responsive images and an install banner that survives 200% text. The design is by Saba; our work is the integration into the production site and its checks. In the pull request’s delayed-hydration test, images moved 397.6 px before the fix and 0 px after it.
How it works on production: browser check
Footage of the production page made by the team and attached to pull request #342. The page is public. There is no before footage.
Recorded production browser checkHow it works page on production. Footage recorded by the team on the production site and attached to the pull request. It is not a CI or end-to-end test run and not full acceptance. MP4 file
Page
https://conloca.com/how-it-works
Pull request
#342 (merged 27 October 2026), attached to the pull request in the private repository conloca/private (access required)
Recorded
28 October 2026, 20:14 to 20:15 UTC; real Chrome against production, viewport 1348×936, no cuts or speed changes
What it shows
Hero, the four-step flow, the layered visual, the cards, the install banner, the pnpm, npm and bun tab selection, and the footer Docs link, on desktop only.
The twelve PNGs were imported byte for byte, with SHA-256 and byte lengths checked on the preview. Existing routes, app links, docs links and install tabs are kept, and text is darkened where the original failed contrast (#342).
The test measured 397.587 px of movement before and 0 px across 53 frames after. Twenty-one website targets and 50 browser checks were rerun.
The merge to the main branch ran Validate, deployed-stage browser tests and Deploy Production, all successful. Locally, the split-port development stack redirects backend landings to the app and keeps published media on local origins (#231).
The CMS and the app each build a static Storybook catalogue in CI, and state stories cover save, sync and workspace status, the page list and the conflict dialogs. Deployed-stage browser tests walk every CMS route, create a branch through the Branch menu, confirm a new page reads Draft and check that typed text survives reopening the editor in both themes. CI keeps the proof folder of every deployed-stage run.
Technical detail
State stories render the real components with fixtures that stop at HostClient and the content API fetch, so nothing reaches the network. Counts: SaveSlot 6 plus phone, SyncStatusSlot 8 plus phone, WorkspaceStatusSlot 8 plus phone, CmsHostPlaceholder 9 (#244). CI saves a screenshot of every story at 1280 × 800 and 390 × 844. The app Storybook runner now compiles Tailwind, because classes such as max-sm:hidden were missing from all app examples.
A flaky failure in the Several Locales scenario, caused by a viewport resize landing mid-play, is gone: resizes during play went from 30 and 11 to 0 and 0 in the probe runs (#257).
The deployed-stage job keeps its proof folder on every run and the Playwright report on failed runs (#320). A manual staging proof workflow adds two new legs (#261), and the emitted billing deploy bundle runs in CI (#238).
Real-engine and typed tests for Git paths, billing identity mapping, workspace recovery and memory behaviour were added or made deterministic (#198, #234, #221, #236, #201, #254). Branch creation and the Draft check are in #229 and #309, and the editor-reopen check is in #226.
A pull-request stage environment that keeps working
Pull-request stages are cleaned up on a schedule with capacity reporting and stage leases, which brought the Cloudflare namespace count to 386 of 500 after the first eviction run. Each stage uses one Durable Object namespace fewer, and each deployment attempt gets its own preview fixture without resetting drafts. Before this, Deploy Stage was failing account-wide with Cloudflare error 10067 after about 170 namespaces leaked from closed pull requests.
Technical detail
A scheduled workflow runs every six hours, reports capacity and fails above 400 of 500 namespaces. Drafts hold a stage for 24 hours and ready pull requests for 72 hours; keep-stage and evict-stage override that. tooling/pr-stage-gc.test.ts checks that only closed same-repo pull requests are selected (#200).
Deleting the unused EventLogDO takes each stage from 10 namespaces to 9, which the pull request estimates moves live capacity from about 48 to about 53 stages (#241).
Readiness rejects dirty overlays and divergent session heads, and older attempt orgs are retired after 24 hours (#169). A read-only inventory of legacy preview resources deletes nothing (#155). A Deploy Production failure on a missing generated contracts module was fixed (#258), and E2E runs leave branches clean (#193).
Project validation moved from hand-written Zod schemas to validators generated from the TypeScript types with Typia. The editor builds its forms from the generated schema metadata, and the loader reports field paths. We adapted the existing generated-contract work to the editor, loader, CLI and sites.
Technical detail
Site schemas become HostSchema<T>: a generated validator with JSON Schema metadata. The editor builds its forms from that metadata, and the loader reports field paths. content-api drops zod and conformance rule A76 forbids it in every workspace package (#251).
Key pull request: #251 · 28 pull requests in this group, most of them build, test and CI changes, all in the source record
Before and after in numbers
Each row compares the state before the change with the state after it. Figures are taken from the pull request named in the last column.
Measure
Before
After
Source
Image movement on How it works during delayed hydration (browser test)
Opened in November and separate from the October merges above. Implemented and checked, not merged.
IMPLEMENTED · NOT MERGED
Documentation theme picker
The documentation site’s native Auto dropdown is replaced by Light, Dark and System controls with a visible selection, keyboard navigation and touch targets. The head of the pull request passed its deployed-stage browser tests, and the preview site is live. The change awaits team review.
The theme control on production and on the pull request #489 preview, both captured at 1440 px on 5 November. Each crop cuts the header where the control sits. Click a crop to open the full capture. The before image is production and the after image is the preview of an open pull request that is not merged.
Documentation theme control
Open pull request, not merged Before and after: same window, same region, same scale.
Before · production Production conloca.com, captured 5 November 2026: the theme control is a native select. Full-size original (1440×1000 PNG)
It is a native select that opens an operating-system menu.
After · PR preview Pull request #489 preview stage, same page, viewport and crop: Light, Dark and System as a visible control. Full-size original (1440×1000 PNG)
Three visible choices; the active one, System, is highlighted.
Same page (getting-started), viewport 1440×1000 and crop, captured two seconds apart on 5 November 2026. The before image is production conloca.com. The after image is the pull request #489 preview stage, a different deployment of an open pull request.
Native stage proof, 7 November
Dated 7 November 2026 and separate from the October results above: it is not counted in any October number.
The deployed-stage checks of that run passed: 53 end-to-end tests against the deployed stage, and 4 Storybook checks (sign-in, readiness and two catalogue journeys). They are not the four product journeys and not full product acceptance. No trace, replay or visual diff was produced.
Recordings. That run recorded two WebM videos of the deployed stage, a desktop view of the CMS dashboard and a 390 px view of the app, with four PNG captures and provenance files. They sit in a private CI artifact, a download that needs GitHub access to the repository. Label: ACCESS-RESTRICTED and temporary, it expires on 2026-11-21 and is not a permanent video archive. Nothing is embedded or rehosted on this page. The CI run page is the stable link and is not a recording.
Technical detail
Pull request head 9d469170dbe5504704dae7b6a32d4825cdb11765, stage build ce4948f9558870dce11f07102a643e2807c73395, run 42375596312, artifact 13576130686.
Both case records name the same head and build before and after the recording; that is identity, not a before and after of the interface. Verified 7 November 2026 by downloading the artifact and decoding both videos in full. Record: native-stage-proof.json. Human browser approval and a permanent main stage are not verified.
Proof
Recordings. The four clips on this page are production browser checks recorded by the team and attached to pull requests. They are not CI or end-to-end test runs and not full acceptance. They predate the November native-stage check below, whose two CI recordings are linked there. A CI job page is not a recording, and the run page is never presented as one.
Owner priority (excerpt)
Original request (RU)
Полностью рабочая конлока в нашем продукте, подтвержденная е2е тестами и скриншотами
English translation
A fully working Conloca in our product, confirmed by e2e tests and screenshots.
Source. Ultra / Mextner · Telegram, private chat between Ultra and the assistant bot · Telegram message id 180834 · 18 August 2026, 17:54 UTC. Sender: incoming Telegram message from the owner's account (not the assistant, not another person). Full-message SHA-256 d65be6db2be49447aa7b6467294c830b9bbc2c0007f3f48de41a7a4d7ccf4618.
Inferred link. Context for the proof below, not for one outcome: the owner's standing priority for Conloca as stated in a message about the day's work.
18 August 2026, before the October period of this report; kept because it states the owner's standing priority.
Hosted CI runs for the final commit of each pull request, or for the merge commit where noted.
Work by Ultra / Mextner (GitHub alex-mextner, Alex Ultra). Pull requests merged 1 to 31 October 2026 are credited by commit authorship, and 92 merged pull requests are counted, one of them for named commits only. Status checked 6 November. Source links may require repository access.
Attribution: every commit in these pull requests is by Ultra, except #177. #167, #168 and #169 were opened from the smoothbricker account and merged by alex-mextner. #177 is credited only for three of Ultra’s 29 commits there: the stale preview-session repair, its at-head regression test and the browser publication proof. Pull requests whose commits are by other authors are counted only in aggregate in the source record.
All merged pull requests counted here are listed with their authors and merge commits in the source record.
diff --git a/reports/conloca-2026-10/native-stage-proof.json b/reports/conloca-2026-10/native-stage-proof.json
new file mode 100644
index 0000000..604ca85
--- /dev/null
+++ b/reports/conloca-2026-10/native-stage-proof.json
@@ -0,0 +1,37 @@
+{
+ "purpose": "Verification record for the 7 November native-stage proof block of the Conloca October report; a private temporary artifact, not a public rehost.",
+ "verifiedAt": "2026-11-07T13:45:00Z",
+ "head": "9d469170dbe5504704dae7b6a32d4825cdb11765",
+ "build": "ce4948f9558870dce11f07102a643e2807c73395",
+ "stageUrls": [
+ "https://site.pr404.conloca.com/",
+ "https://app.pr404.conloca.com/",
+ "https://storybook.pr404.conloca.com/"
+ ],
+ "runUrl": "https://github.com/conloca/private/actions/runs/42375596312",
+ "runId": 42375596312,
+ "artifactId": 13576130686,
+ "artifactUrl": "https://github.com/conloca/private/actions/runs/42375596312/artifacts/13576130686",
+ "artifactSha256": "85cef4edb76cfb7f3292c93c060e57e1e9cdb6625ea5738be4cc5d5ce1859cf5",
+ "artifactSize": 519359,
+ "artifactExpiresAt": "2026-11-21T13:18:03Z",
+ "videos": [
+ {
+ "id": "cms",
+ "width": 1280,
+ "height": 800,
+ "durationSeconds": 5.6,
+ "frames": 140,
+ "sha256": "7c7739c6526730c3ea906b852e7f2ce7a0d7df39d218a6147954b6cea2257f2a"
+ },
+ {
+ "id": "app",
+ "width": 390,
+ "height": 844,
+ "durationSeconds": 4.88,
+ "frames": 122,
+ "sha256": "1fcf67580aec5acd7bd74c70b20d565b229f5d1f9c9f92ea53e2baa181105e00"
+ }
+ ],
+ "kind": "private-temporary-ci-artifact-not-embedded"
+}
diff --git a/scripts/ci/check-media-report.py b/scripts/ci/check-media-report.py
index 6cbdbac..5fe5f5f 100644
--- a/scripts/ci/check-media-report.py
+++ b/scripts/ci/check-media-report.py
@@ -429,7 +429,7 @@ def test_public_record_and_pages_hold_no_private_identifiers(self):
self.assertNotIn(b, blob, b)
def test_links_on_the_pages_stay_on_allowed_origins(self):
- allowed = ("https://github.com/", "https://tasks.glide.vc/", "https://conloca.com", "https://site.pr489.conloca.com/", "https://linear.app/")
+ allowed = ("https://github.com/", "https://tasks.glide.vc/", "https://conloca.com", "https://site.pr489.conloca.com/", "https://site.pr404.conloca.com/", "https://app.pr404.conloca.com/", "https://storybook.pr404.conloca.com/", "https://linear.app/")
for key, page in self.pages.items():
for url in Links(page).urls:
if url.startswith("http"):
diff --git a/scripts/ci/check-native-stage-proof.py b/scripts/ci/check-native-stage-proof.py
new file mode 100644
index 0000000..e1b2eba
--- /dev/null
+++ b/scripts/ci/check-native-stage-proof.py
@@ -0,0 +1,104 @@
+"""Contract for the 7 November native-stage proof block on the Conloca October report.
+
+The block and reports/conloca-2026-10/native-stage-proof.json must agree. The October period and the
+October counts stay untouched; the November addendum is a separate, dated block.
+
+Run: python3 scripts/ci/check-native-stage-proof.py
+"""
+
+import json
+import re
+import sys
+import unittest
+from pathlib import Path
+
+sys.path.insert(0, str(Path(__file__).resolve().parent))
+from _report_html import Links, VisibleText # noqa: E402
+
+ROOT = Path(__file__).resolve().parents[2]
+DIR = ROOT / "reports/conloca-2026-10"
+HEAD = "9d469170dbe5504704dae7b6a32d4825cdb11765"
+RUN = "https://github.com/conloca/private/actions/runs/42375596312"
+ARTIFACT = "https://github.com/conloca/private/actions/runs/42375596312/artifacts/13576130686"
+STAGES = ["https://site.pr404.conloca.com/", "https://app.pr404.conloca.com/", "https://storybook.pr404.conloca.com/"]
+
+
+class NativeStageProof(unittest.TestCase):
+ @classmethod
+ def setUpClass(cls):
+ cls.raw = (DIR / "index.html").read_text(encoding="utf-8")
+ cls.rec = json.loads((DIR / "native-stage-proof.json").read_text(encoding="utf-8"))
+ cls.block = cls.raw.split('id="native-stage-proof"', 1)[1].split("", 1)[0]
+ cls.text = VisibleText(cls.block).raw
+
+ def test_three_direct_stage_links_and_nothing_else_for_stages(self):
+ urls = [u for u in Links(self.block).urls if "pr404.conloca.com" in u]
+ self.assertEqual(urls, STAGES)
+ self.assertEqual(self.rec["stageUrls"], STAGES)
+ for label in ("Landing", "CMS app", "Storybook"):
+ self.assertIn(label, self.text)
+
+ def test_run_and_artifact_links_are_distinct_and_exact(self):
+ urls = Links(self.block).urls
+ self.assertIn(RUN, urls)
+ self.assertIn(ARTIFACT, urls)
+ self.assertNotEqual(self.rec["runUrl"], self.rec["artifactUrl"])
+ self.assertEqual((self.rec["runUrl"], self.rec["artifactUrl"]), (RUN, ARTIFACT))
+ self.assertEqual(self.rec["runId"], 42375596312)
+ self.assertEqual(self.rec["artifactId"], 13576130686)
+ self.assertIn("https://github.com/conloca/private/pull/404", urls)
+
+ def test_artifact_is_labelled_private_and_temporary_and_not_embedded(self):
+ low = self.text.casefold()
+ for word in ("access-restricted", "temporary", "2026-11-21", "not full product acceptance", "deployed on pr404; not merged"):
+ self.assertIn(word, low)
+ self.assertIn("not a permanent video archive", low)
+ self.assertNotRegex(self.block, r"