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.
Technical detail
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.
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.
Technical detail
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 PR #489 preview, both captured at 1440 px on 5 November. On a phone the pictures show the header where the control sits; tap one to open the full capture.
Before: native dropdown. Production, 5 November.After: Light, Dark and System choices. PR #489 preview, 5 November.
Proof
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.
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.
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/hyper-2026-10/media-evidence.json b/reports/hyper-2026-10/media-evidence.json
new file mode 100644
index 0000000..b97ce89
--- /dev/null
+++ b/reports/hyper-2026-10/media-evidence.json
@@ -0,0 +1,2129 @@
+{
+ "report": "hyper",
+ "generatedAt": "2026-11-06",
+ "note": "Public-safe subset: hashes, crop coordinates and source labels. Private chat text outside the quoted excerpts, raw message dumps, local file paths and protected originals are not included.",
+ "originalRequests": [
+ {
+ "id": "req-hyp990-warning-with-autofix",
+ "outcome": "a3-dead-prop-refusal",
+ "report": "hyper",
+ "sourceRecord": "A1",
+ "language": "ru",
+ "ru": "Короче думаю да надо варнинг с кнопкой auto fix через ии. Ии должен проверить и задать вопрос как лучше сделать или отменить",
+ "en": "In short, I think yes: we need a warning with an Auto fix button, through AI. The AI should check and ask a question about how best to do it, or cancel.",
+ "excerptIsWholeMessage": false,
+ "excerptSha256": "5d66d8bdd6f5f86ea1ffd4dc0c1e1824c4e658b519a7340ceb8d1436d1158cc6",
+ "messageSha256": "0dec09e9a155f89651bcd1c4ed965a9f90fd9a070700943c07778d9fa32dc3ae",
+ "dateUtc": "2026-07-16T18:33:06Z",
+ "author": "Ultra / Mextner",
+ "sourceLabel": "Telegram, private chat between Ultra and the assistant bot",
+ "senderBasis": "incoming Telegram message from the owner's account (not the assistant, not another person)",
+ "messageIdentity": "tg#9034, Telegram message id 174396",
+ "ids": {
+ "tg": "tg#9034",
+ "telegramMessageId": 174396
+ },
+ "relationKind": "inferred",
+ "relation": "By topic only (HYP-990): an edit that cannot be applied must show a warning with an Auto fix action, and the pull request does not cite this message.",
+ "windowNote": "before the 6 August window; kept because it is the origin of the requirement",
+ "omitted": "The message opens by quoting an assistant status bullet; only the owner's reply is quoted here.",
+ "pastedEnglishBugText": false,
+ "permalink": null,
+ "permalinkNote": "private chat or local history: there is no public link and none is invented"
+ },
+ {
+ "id": "req-hyp990-native-notification",
+ "outcome": "a3-dead-prop-refusal",
+ "report": "hyper",
+ "sourceRecord": "A2",
+ "language": "ru",
+ "ru": "Перекрывает все, гора текста, текст слева от кнопки, куча пустоты \nКакая-то нестандартная нотификация. На ext надо чтобы стандартные испзровались для vscode а на saas стандартные для saas",
+ "en": "It covers everything, a huge amount of text, the text is to the left of the button, a lot of empty space. Some kind of non-standard notification. In the extension the standard VS Code ones should be used, and in SaaS the standard SaaS ones.",
+ "excerptIsWholeMessage": false,
+ "excerptSha256": "75965920a90f7e06b2fc259686b8102a353747d9b596e767228eacbbee71df72",
+ "messageSha256": "eb71987e04e6357ec0c85fc72a495e915490d24c8db41f695d202caf4e4ef7f9",
+ "dateUtc": "2026-07-17T06:33:18Z",
+ "author": "Ultra / Mextner",
+ "sourceLabel": "Telegram, private chat between Ultra and the assistant bot",
+ "senderBasis": "incoming Telegram message from the owner's account (not the assistant, not another person)",
+ "messageIdentity": "tg#9122, Telegram message id 174497",
+ "ids": {
+ "tg": "tg#9122",
+ "telegramMessageId": 174497
+ },
+ "relationKind": "pr",
+ "relation": "The body of pull request #665 cites “CTO tg#9122/#9125” for presenting the warning through each platform's native notification.",
+ "windowNote": "before the 6 August window; kept because it is the origin of the requirement",
+ "omitted": "The message's opening exclamation is left out; the rest is quoted exactly. The message came with a screenshot of the old in-Inspector card, which was not recovered.",
+ "pastedEnglishBugText": false,
+ "permalink": null,
+ "permalinkNote": "private chat or local history: there is no public link and none is invented"
+ },
+ {
+ "id": "req-hyp990-details-and-ai-context",
+ "outcome": "a3-dead-prop-refusal",
+ "report": "hyper",
+ "sourceRecord": "A3",
+ "language": "ru",
+ "ru": "И подумай как раскрывать длинный текст с подробностями \nЛибо разворачивать прямо с тосте либо показать ещё подробнее в баннере по клику подробнее ну и в ии нужно чтобы все подробности уходили в лютом случае",
+ "en": "And think about how to reveal the long text with details. Either expand it right in the toast, or show more in a banner when Details is clicked, and in any case the AI must receive all the details.",
+ "excerptIsWholeMessage": true,
+ "excerptSha256": "f07e16a579836f600f31a2b54f36dc693d2d8b0a67f7a9ce6b6999a07aad8e19",
+ "messageSha256": "f07e16a579836f600f31a2b54f36dc693d2d8b0a67f7a9ce6b6999a07aad8e19",
+ "dateUtc": "2026-07-17T06:36:25Z",
+ "author": "Ultra / Mextner",
+ "sourceLabel": "Telegram, private chat between Ultra and the assistant bot",
+ "senderBasis": "incoming Telegram message from the owner's account (not the assistant, not another person)",
+ "messageIdentity": "tg#9125, Telegram message id 174500",
+ "ids": {
+ "tg": "tg#9125",
+ "telegramMessageId": 174500
+ },
+ "relationKind": "pr",
+ "relation": "The body of pull request #665 says “the AI always receives the complete structured context (CTO tg#9125)”.",
+ "windowNote": "before the 6 August window; kept because it is the origin of the requirement",
+ "omitted": null,
+ "pastedEnglishBugText": false,
+ "permalink": null,
+ "permalinkNote": "private chat or local history: there is no public link and none is invented"
+ },
+ {
+ "id": "req-hyp706-fallback-is-good",
+ "outcome": "a4-css-miss-inline-floor",
+ "report": "hyper",
+ "sourceRecord": "D3",
+ "language": "ru",
+ "ru": "почему отвергнут этот фолбек? Он хороший же",
+ "en": "why was this fallback rejected? It's a good one, isn't it.",
+ "excerptIsWholeMessage": false,
+ "excerptSha256": "1172df26937ef3bb6387f782f4718f14f235bf683e2b72f339adbe78e6d410aa",
+ "messageSha256": "2840d656e9575bfc7070214edf879935e4ae957117210b789e40ff600775e8cf",
+ "dateUtc": "2026-06-11T11:05:19Z",
+ "author": "Ultra / Mextner",
+ "sourceLabel": "Ultra's Claude Code prompt history, project hyper-canvas-draft",
+ "senderBasis": "the owner's own prompt history; it has no per-message author field, so attribution is by account",
+ "messageIdentity": "no message id",
+ "ids": {},
+ "relationKind": "spec",
+ "relation": "Master spec decision D24 records this wording about the inline-style fallback.",
+ "windowNote": "11 June 2026, before the 6 August window; kept because it is the origin of the requirement",
+ "omitted": "The line above it in the same message is a pasted assistant proposal and is not attributed to the owner. The lines after it ask for explanations and are not quoted.",
+ "pastedEnglishBugText": false,
+ "permalink": null,
+ "permalinkNote": "private chat or local history: there is no public link and none is invented"
+ },
+ {
+ "id": "req-hyp722-same-file-const",
+ "outcome": "a5-fill-color-class-sync",
+ "report": "hyper",
+ "sourceRecord": "D1",
+ "language": "ru",
+ "ru": "через twMerge надо решать проблемы только с (внешними) мастер-компонентами, если же константа с заменяемым значением в том же файле, должна работать та логика что у нас и раньше всегда была, находить значение и заменять",
+ "en": "twMerge should be used to solve problems only with (external) master components; but if the constant with the replaceable value is in the same file, the logic we always had before should work: find the value and replace it.",
+ "excerptIsWholeMessage": false,
+ "excerptSha256": "a9934d5c7608051c9d71c6913b470bf4129698e7ea477c2251bd0aeb6286a9d3",
+ "messageSha256": "b1f7e6743b1bb4898765f20a46f5749c1f7557c10eab0f13dca618293080bffd",
+ "dateUtc": "2026-06-09T18:00:43Z",
+ "author": "Ultra / Mextner",
+ "sourceLabel": "Ultra's Claude Code prompt history, project hyper-canvas-draft",
+ "senderBasis": "the owner's own prompt history; it has no per-message author field, so attribution is by account",
+ "messageIdentity": "no message id",
+ "ids": {},
+ "relationKind": "spec",
+ "relation": "Master spec decision D25 records this rule (twMerge for external master components only; a same-file constant is found and replaced at its definition).",
+ "windowNote": "9 June 2026, before the 6 August window; kept because it is the origin of the requirement",
+ "omitted": "The rest of the message is about message-attachment rules of another tool and is not quoted.",
+ "pastedEnglishBugText": false,
+ "permalink": null,
+ "permalinkNote": "private chat or local history: there is no public link and none is invented"
+ },
+ {
+ "id": "req-hyp722-edit-in-place",
+ "outcome": "a5-fill-color-class-sync",
+ "report": "hyper",
+ "sourceRecord": "D2",
+ "language": "ru",
+ "ru": "пользователь должен ожидать изменение по месту",
+ "en": "the user should expect the change in place.",
+ "excerptIsWholeMessage": false,
+ "excerptSha256": "79260c9acdb75489d2a52506a86b5e37282a0dd387345c59f4a7d221bd11389c",
+ "messageSha256": "af48674468be79a94adf237688f1831d2fd477c22f9f322004ce21283060a0ed",
+ "dateUtc": "2026-06-08T14:50:47Z",
+ "author": "Ultra / Mextner",
+ "sourceLabel": "Ultra's Claude Code prompt history, project hyper-canvas-draft",
+ "senderBasis": "the owner's own prompt history; it has no per-message author field, so attribution is by account",
+ "messageIdentity": "no message id",
+ "ids": {},
+ "relationKind": "inferred",
+ "relation": "By topic (HYP-722 master-spec decision D25, in-place edits). Written about master components, the neighbouring case of the same rule.",
+ "windowNote": "8 June 2026, before the 6 August window; kept because it is the origin of the requirement",
+ "omitted": null,
+ "pastedEnglishBugText": false,
+ "permalink": null,
+ "permalinkNote": "private chat or local history: there is no public link and none is invented"
+ },
+ {
+ "id": "req-hyp1420-auto-height",
+ "outcome": "t3-layout-panel-pixel-size",
+ "report": "hyper",
+ "sourceRecord": "B1",
+ "language": "ru",
+ "ru": "а еще у кнопки Get started почему-то предлагается ручное визуальное изменение высоты хотя высота у нее Auto! разберись тоже/ причем не ad hoc чисто для одного случая и только для высоты само собой",
+ "en": "And also, for the Get started button, manual visual resizing of the height is offered for some reason, even though its height is Auto! Look into that too, and not ad hoc for just one case and, of course, not only for height.",
+ "excerptIsWholeMessage": true,
+ "excerptSha256": "28696fa4bf7ec1051da8c7256086bdab2b57a18d074f66e499f5a04e05eb74d9",
+ "messageSha256": "28696fa4bf7ec1051da8c7256086bdab2b57a18d074f66e499f5a04e05eb74d9",
+ "dateUtc": "2026-08-28T11:45:34Z",
+ "author": "Ultra / Mextner",
+ "sourceLabel": "Ultra's Claude Code prompt history, project hyperide",
+ "senderBasis": "the owner's own prompt history; it has no per-message author field, so attribution is by account",
+ "messageIdentity": "no message id",
+ "ids": {},
+ "relationKind": "task",
+ "relation": "HYP-1420 “Why” says the owner reported this with a live screenshot (the screenshot was not recovered).",
+ "windowNote": null,
+ "omitted": null,
+ "pastedEnglishBugText": false,
+ "permalink": null,
+ "permalinkNote": "private chat or local history: there is no public link and none is invented"
+ },
+ {
+ "id": "req-hyp1372-old-bug-back",
+ "outcome": "t-split-first-click",
+ "report": "hyper",
+ "sourceRecord": "C1",
+ "language": "ru",
+ "ru": "А еще вернулся старый баг \nПри клике на компонент в hyper explorer не создается Сплит",
+ "en": "And another thing: an old bug has come back. When I click a component in Hyper Explorer, a split is not created.",
+ "excerptIsWholeMessage": true,
+ "excerptSha256": "9eb8a44deb8c65e676ce2aebe44839463691ea0ab8f2bcaacf57659f6c6ccef6",
+ "messageSha256": "9eb8a44deb8c65e676ce2aebe44839463691ea0ab8f2bcaacf57659f6c6ccef6",
+ "dateUtc": "2026-08-27T20:58:43Z",
+ "author": "Ultra / Mextner",
+ "sourceLabel": "Telegram, private chat between Ultra and the assistant bot",
+ "senderBasis": "incoming Telegram message from the owner's account (not the assistant, not another person)",
+ "messageIdentity": "tg#13863, Telegram message id 182966",
+ "ids": {
+ "tg": "tg#13863",
+ "telegramMessageId": 182966
+ },
+ "relationKind": "task",
+ "relation": "HYP-1372 “Why” records this report (Telegram screenshot, Feed.tsx opened in the same group as Hyper Canvas).",
+ "windowNote": null,
+ "omitted": null,
+ "pastedEnglishBugText": false,
+ "permalink": null,
+ "permalinkNote": "private chat or local history: there is no public link and none is invented"
+ },
+ {
+ "id": "req-hyp1372-first-click",
+ "outcome": "t-split-first-click",
+ "report": "hyper",
+ "sourceRecord": "C2",
+ "language": "ru",
+ "ru": "Кстати второй подряд клик уже Сплит открывает но первый клик у меня никогда не открывает сплит/ несколько раз пробовал",
+ "en": "By the way, the second click in a row does open the split, but the first click never opens the split for me. I tried several times.",
+ "excerptIsWholeMessage": true,
+ "excerptSha256": "243c6a1cf4c5ceef03dc4860a38cc6f75fb0976479de0f1a133d61f6768fcbad",
+ "messageSha256": "243c6a1cf4c5ceef03dc4860a38cc6f75fb0976479de0f1a133d61f6768fcbad",
+ "dateUtc": "2026-08-27T21:15:43Z",
+ "author": "Ultra / Mextner",
+ "sourceLabel": "Telegram, private chat between Ultra and the assistant bot",
+ "senderBasis": "incoming Telegram message from the owner's account (not the assistant, not another person)",
+ "messageIdentity": "tg#13879, Telegram message id 182984",
+ "ids": {
+ "tg": "tg#13879",
+ "telegramMessageId": 182984
+ },
+ "relationKind": "task",
+ "relation": "Same HYP-1372 report.",
+ "windowNote": null,
+ "omitted": null,
+ "pastedEnglishBugText": false,
+ "permalink": null,
+ "permalinkNote": "private chat or local history: there is no public link and none is invented"
+ },
+ {
+ "id": "req-hyp1372-accepted",
+ "outcome": "t-split-first-click",
+ "report": "hyper",
+ "sourceRecord": "C3",
+ "language": "ru",
+ "ru": "Принимаю",
+ "en": "I accept.",
+ "excerptIsWholeMessage": false,
+ "excerptSha256": "c0a5d6e4e696d19ca9ca325106a37ae45fb430e8b7a0e15db844fe470b74a1f1",
+ "messageSha256": "098783b05319744084618099e7766e9a3cf98d245e17ebe93538a793ae1c0fff",
+ "dateUtc": "2026-08-28T08:04:58Z",
+ "author": "Ultra / Mextner",
+ "sourceLabel": "Ultra's Claude Code prompt history, project hyperide",
+ "senderBasis": "the owner's own prompt history; it has no per-message author field, so attribution is by account",
+ "messageIdentity": "bridged Telegram message tg#13924",
+ "ids": {
+ "tg": "tg#13924"
+ },
+ "relationKind": "inferred",
+ "relation": "A reply to the assistant's message tg#13906 (“After the fix: first click on a component in Ex…”). Linked by that message's text; the acceptance is the owner's, the fix claim is the assistant's.",
+ "windowNote": null,
+ "omitted": "Only the owner's one-word reply is quoted; the quoted assistant text above it is not.",
+ "pastedEnglishBugText": false,
+ "permalink": null,
+ "permalinkNote": "private chat or local history: there is no public link and none is invented"
+ },
+ {
+ "id": "req-canvas-drag-complaint",
+ "outcome": "c2-verified-move",
+ "report": "hyper",
+ "sourceRecord": "E1",
+ "language": "ru",
+ "ru": "Я потаскал элементы в hyper canvas в открытом в hyper ext проекте conloca и ужаснулся как плохо это работает.",
+ "en": "I dragged elements around in Hyper Canvas, in the Conloca project open in Hyper ext, and was horrified at how badly it works.",
+ "excerptIsWholeMessage": false,
+ "excerptSha256": "dc80962479f34d1bb2de55dd3c59d08e355a1825930a1bb38687d43ec905584a",
+ "messageSha256": "024830278cc22430b7bf6f224615db59dbc9816d3337d8f3180f490d09ab692f",
+ "dateUtc": "2026-09-02T20:36:21Z",
+ "author": "Ultra / Mextner",
+ "sourceLabel": "Ultra's Claude Code prompt history, project hyperide",
+ "senderBasis": "the owner's own prompt history; it has no per-message author field, so attribution is by account",
+ "messageIdentity": "no message id",
+ "ids": {},
+ "relationKind": "inferred",
+ "relation": "By topic and date (the Canvas drag-move work, HYP-732 and HYP-1456); the message names no ticket.",
+ "windowNote": "2 September 2026",
+ "omitted": null,
+ "pastedEnglishBugText": false,
+ "permalink": null,
+ "permalinkNote": "private chat or local history: there is no public link and none is invented"
+ },
+ {
+ "id": "req-hyp1404-wrong-instance",
+ "outcome": "open-hyp1404",
+ "report": "hyper",
+ "sourceRecord": "B2",
+ "language": "ru",
+ "ru": "кликаю на Try Demo а выделяется Get started. Мы уже много раз решали эту проблему/ реши ее с разных сторон раз и навсегда чтобы такое было невозможно в принципе",
+ "en": "I click Try Demo and Get started gets selected. We have solved this problem many times; solve it from different sides once and for all, so that it is impossible in principle.",
+ "excerptIsWholeMessage": false,
+ "excerptSha256": "dd2bd7729fd139c238730edb51df810e8d29ac66099133d94b6e41c76160ff1d",
+ "messageSha256": "013ec364d31a2f09c4268c606e11ace5235e1c1ade1ab01b6f67cde667f9aed7",
+ "dateUtc": "2026-08-28T11:44:19Z",
+ "author": "Ultra / Mextner",
+ "sourceLabel": "Ultra's Claude Code prompt history, project hyperide",
+ "senderBasis": "the owner's own prompt history; it has no per-message author field, so attribution is by account",
+ "messageIdentity": "no message id",
+ "ids": {},
+ "relationKind": "inferred",
+ "relation": "By topic (HYP-1404: a click on one of two sibling instances selects the wrong one). The message starts with the path of a screenshot that was not recovered.",
+ "windowNote": "28 August 2026",
+ "omitted": "The path of the screenshot and the instruction about which review models to use are not quoted.",
+ "pastedEnglishBugText": false,
+ "permalink": null,
+ "permalinkNote": "private chat or local history: there is no public link and none is invented"
+ },
+ {
+ "id": "req-retro-is-not-styles",
+ "outcome": "r1-retro-identity",
+ "report": "hyper",
+ "sourceRecord": "D6",
+ "language": "ru",
+ "ru": "Запомни что это ретро спек. Стили тут не причем. Про стили мастер спек.",
+ "en": "Note that this is the retro spec. Styles have nothing to do with it. Styles are in the master spec.",
+ "excerptIsWholeMessage": false,
+ "excerptSha256": "5b4a24a85558e8ad5884bd743ed06a2981c30b4ec61905d759d61f516147dbee",
+ "messageSha256": "015e6f8b0a56ecdc5e3d0d1ffce0c190cd50d879c25d401087c55fde40ebb05c",
+ "dateUtc": "2026-08-18T18:11:39Z",
+ "author": "Ultra / Mextner",
+ "sourceLabel": "Telegram, private chat between Ultra and the assistant bot",
+ "senderBasis": "incoming Telegram message from the owner's account (not the assistant, not another person)",
+ "messageIdentity": "tg#12319, Telegram message id 180850",
+ "ids": {
+ "tg": "tg#12319",
+ "telegramMessageId": 180850
+ },
+ "relationKind": "inferred",
+ "relation": "By topic: the owner separating the retro spec from the master styles spec.",
+ "windowNote": "18 August 2026",
+ "omitted": null,
+ "pastedEnglishBugText": false,
+ "permalink": null,
+ "permalinkNote": "private chat or local history: there is no public link and none is invented"
+ }
+ ],
+ "images": [
+ {
+ "id": "pr721-before-explorer",
+ "path": "media/pr721-before-explorer.png",
+ "sha256": "93537d33d98052395a7bb977edc99abada97c5d698e504b11195d9f520039891",
+ "width": 824,
+ "height": 446,
+ "bytes": 20809,
+ "role": "before",
+ "pair": "pr721-explorer",
+ "outcome": "t-explorer-empty-state",
+ "chip": "Before",
+ "alt": "HyperIDE Explorer panel in VS Code with no folder open, before the fix: the panel body under the HYPERIDE: EXPLORER title is empty",
+ "caption": "HyperIDE Explorer with no folder open, before the fix. The panel body is empty.",
+ "roi": [
+ 90,
+ 70,
+ 700,
+ 400
+ ],
+ "scale": 1.35,
+ "boxes": [
+ {
+ "n": 1,
+ "original_xyxy": [
+ 115,
+ 165,
+ 690,
+ 390
+ ],
+ "crop_xyxy": [
+ 34,
+ 128,
+ 810,
+ 432
+ ],
+ "note": "The Explorer view body is empty: no message and no action."
+ }
+ ],
+ "original": {
+ "path": "media/orig/pr721-before.png",
+ "sha256": "4a5a405a057a77084867df53d0dd164473ab072b5ffe792eb14059be17b8a5da",
+ "width": 2400,
+ "height": 1536,
+ "bytes": 398390,
+ "source": "hyperide/hyper-saas @683b016b .github/pr-screenshots/pr721-20260814-01-before-blank-panel-spinner.png"
+ }
+ },
+ {
+ "id": "pr721-after-explorer",
+ "path": "media/pr721-after-explorer.png",
+ "sha256": "4c3ce81652b17a7e98ce63ce815522130aea9af35a89c29b82984112ec789c2c",
+ "width": 824,
+ "height": 446,
+ "bytes": 108676,
+ "role": "after",
+ "pair": "pr721-explorer",
+ "outcome": "t-explorer-empty-state",
+ "chip": "After",
+ "alt": "Same Explorer panel and crop after the fix: it says No folder opened, explains that opening a folder closes all current editors, offers an add a folder link and shows an Open Folder button",
+ "caption": "Same window, fixture and crop after the merged fix, taken from the pull request's follow-up commit with the final wording.",
+ "roi": [
+ 90,
+ 70,
+ 700,
+ 400
+ ],
+ "scale": 1.35,
+ "boxes": [
+ {
+ "n": 1,
+ "original_xyxy": [
+ 118,
+ 164,
+ 676,
+ 298
+ ],
+ "crop_xyxy": [
+ 38,
+ 127,
+ 791,
+ 308
+ ],
+ "note": "Message: “No folder opened. Opening folder will close all current editors. To keep them open, add a folder instead.”"
+ },
+ {
+ "n": 2,
+ "original_xyxy": [
+ 285,
+ 314,
+ 506,
+ 382
+ ],
+ "crop_xyxy": [
+ 263,
+ 329,
+ 562,
+ 421
+ ],
+ "note": "Open Folder button."
+ }
+ ],
+ "original": {
+ "path": "media/orig/pr721-after-final.png",
+ "sha256": "db843126c805832bf876915eb9da80778cea6d6945c48428215161bda2fc1fdf",
+ "width": 2400,
+ "height": 1536,
+ "bytes": 415663,
+ "source": "hyperide/hyper-saas @4fa7dd8c .github/pr-screenshots/pr721-20260814-03-followup-exact-copy-and-two-actions.png"
+ }
+ },
+ {
+ "id": "pr721-after-interim-explorer",
+ "path": "media/pr721-after-interim-explorer.png",
+ "sha256": "7790ffcee838b189899897d4a24791098113f22d5604edbcde194310f2512077",
+ "width": 824,
+ "height": 446,
+ "bytes": 79692,
+ "role": "interim-after",
+ "pair": null,
+ "outcome": "t-explorer-empty-state",
+ "chip": "Interim after",
+ "alt": "Same Explorer panel and crop at the first fix commit: an earlier wording saying HyperIDE needs a folder open, with an Open Folder button",
+ "caption": "Interim capture at the first fix commit. A follow-up commit changed this wording, so it is not the merged copy.",
+ "roi": [
+ 90,
+ 70,
+ 700,
+ 400
+ ],
+ "scale": 1.35,
+ "boxes": [
+ {
+ "n": 1,
+ "original_xyxy": [
+ 115,
+ 168,
+ 690,
+ 250
+ ],
+ "crop_xyxy": [
+ 34,
+ 132,
+ 810,
+ 243
+ ],
+ "note": "Interim message: “HyperIDE needs a folder open to preview and edit components.”"
+ },
+ {
+ "n": 2,
+ "original_xyxy": [
+ 285,
+ 266,
+ 505,
+ 335
+ ],
+ "crop_xyxy": [
+ 263,
+ 265,
+ 560,
+ 358
+ ],
+ "note": "Open Folder button."
+ }
+ ],
+ "original": {
+ "path": "media/orig/pr721-after-interim.png",
+ "sha256": "f85b2341c4df27f1a61addffe90e8a07f4f7085e8efc9ba3d8936782abe2377d",
+ "width": 2400,
+ "height": 1536,
+ "bytes": 409560,
+ "source": "hyperide/hyper-saas @683b016b .github/pr-screenshots/pr721-20260814-02-after-empty-state.png"
+ }
+ },
+ {
+ "id": "pr721-link-clicked-explorer",
+ "path": "media/pr721-link-clicked-explorer.png",
+ "sha256": "52b84ef535aad07b5660560b3220803a6d59c2e327c66756075922e623b34018",
+ "width": 824,
+ "height": 446,
+ "bytes": 108489,
+ "role": "stage",
+ "pair": null,
+ "outcome": "t-explorer-empty-state",
+ "chip": "Stage",
+ "alt": "Same Explorer panel after the add a folder link was clicked: the link shows a focus outline",
+ "caption": "Later stage of the same run: the add a folder link after a click.",
+ "roi": [
+ 90,
+ 70,
+ 700,
+ 400
+ ],
+ "scale": 1.35,
+ "boxes": [
+ {
+ "n": 1,
+ "original_xyxy": [
+ 385,
+ 254,
+ 546,
+ 294
+ ],
+ "crop_xyxy": [
+ 398,
+ 248,
+ 616,
+ 302
+ ],
+ "note": "The add a folder link, activated: it shows the focus outline."
+ },
+ {
+ "n": 2,
+ "original_xyxy": [
+ 285,
+ 314,
+ 506,
+ 382
+ ],
+ "crop_xyxy": [
+ 263,
+ 329,
+ 562,
+ 421
+ ],
+ "note": "Open Folder button."
+ }
+ ],
+ "original": {
+ "path": "media/orig/pr721-after-link-clicked.png",
+ "sha256": "6438a78b2a9e33cfd2ccae7f9dabc05d1e50ac50c3c964c6c6a53f8498b31d7e",
+ "width": 2400,
+ "height": 1536,
+ "bytes": 415695,
+ "source": "hyperide/hyper-saas @4fa7dd8c .github/pr-screenshots/pr721-20260814-04-followup-addfolder-link-clicked.png"
+ }
+ },
+ {
+ "id": "pr827-before-canvas",
+ "path": "media/pr827-before-canvas.png",
+ "sha256": "1b5fb5b129f49f854d02e002e9a7c4653c273590691329501fa607900f146c08",
+ "width": 845,
+ "height": 216,
+ "bytes": 13350,
+ "role": "before",
+ "pair": "pr827-canvas",
+ "outcome": "s1-operation-authority-in-style-editor",
+ "chip": "Before",
+ "alt": "Canvas crop before the width write: element R is a narrow square",
+ "caption": "Canvas, element R, before the Inspector width write.",
+ "roi": [
+ 760,
+ 312,
+ 1112,
+ 402
+ ],
+ "scale": 2.4,
+ "boxes": [
+ {
+ "n": 1,
+ "original_xyxy": [
+ 768,
+ 324,
+ 824,
+ 379
+ ],
+ "crop_xyxy": [
+ 19,
+ 29,
+ 154,
+ 161
+ ],
+ "note": "Element R is the narrow square, Tailwind w-12 (3rem)."
+ }
+ ],
+ "original": {
+ "path": "media/orig/pr827-before.png",
+ "sha256": "199847407455ebf23115c639f0439f487e34fcb904137595d80de1b47cc731c2",
+ "width": 1440,
+ "height": 835,
+ "bytes": 259980,
+ "source": "hyperide/hyper-saas @57ce3969 docs/reports/evidence/style-operation-20261016/native-before.png"
+ }
+ },
+ {
+ "id": "pr827-after-canvas",
+ "path": "media/pr827-after-canvas.png",
+ "sha256": "d948af0054b08bd0c68cc2e7fabc848b7a12d9236ac0bbf5bdf1b98598fed978",
+ "width": 845,
+ "height": 216,
+ "bytes": 13466,
+ "role": "after",
+ "pair": "pr827-canvas",
+ "outcome": "s1-operation-authority-in-style-editor",
+ "chip": "After",
+ "alt": "Same canvas crop after the width write: element R is clearly wider",
+ "caption": "Same element and crop after the write.",
+ "roi": [
+ 760,
+ 312,
+ 1112,
+ 402
+ ],
+ "scale": 2.4,
+ "boxes": [
+ {
+ "n": 1,
+ "original_xyxy": [
+ 768,
+ 324,
+ 916,
+ 379
+ ],
+ "crop_xyxy": [
+ 19,
+ 29,
+ 374,
+ 161
+ ],
+ "note": "Element R is wider after the write; the pull request measures 140 px."
+ }
+ ],
+ "original": {
+ "path": "media/orig/pr827-after.png",
+ "sha256": "ffb57145c8fb2fc28e98c08797cc82a68ac2c169b67a9b91d0c120957ef692aa",
+ "width": 1440,
+ "height": 835,
+ "bytes": 260507,
+ "source": "hyperide/hyper-saas @57ce3969 docs/reports/evidence/style-operation-20261016/native-after.png"
+ }
+ },
+ {
+ "id": "pr827-before-inspector",
+ "path": "media/pr827-before-inspector.png",
+ "sha256": "233c1fdd86038e1505ac0301b7ac5ace0c81e868e77b49cbf21cc540b21405ca",
+ "width": 804,
+ "height": 132,
+ "bytes": 21197,
+ "role": "before",
+ "pair": "pr827-inspector",
+ "outcome": "s1-operation-authority-in-style-editor",
+ "chip": "Before",
+ "alt": "Inspector Layout row crop before the write: the width field reads 3rem",
+ "caption": "Inspector Layout row, width and height fields, before the write.",
+ "roi": [
+ 1150,
+ 468,
+ 1418,
+ 512
+ ],
+ "scale": 3.0,
+ "boxes": [
+ {
+ "n": 1,
+ "original_xyxy": [
+ 1156,
+ 476,
+ 1268,
+ 505
+ ],
+ "crop_xyxy": [
+ 18,
+ 24,
+ 354,
+ 111
+ ],
+ "note": "The W field reads 3rem."
+ }
+ ],
+ "original": {
+ "path": "media/orig/pr827-before.png",
+ "sha256": "199847407455ebf23115c639f0439f487e34fcb904137595d80de1b47cc731c2",
+ "width": 1440,
+ "height": 835,
+ "bytes": 259980,
+ "source": "hyperide/hyper-saas @57ce3969 docs/reports/evidence/style-operation-20261016/native-before.png"
+ }
+ },
+ {
+ "id": "pr827-after-inspector",
+ "path": "media/pr827-after-inspector.png",
+ "sha256": "58718488b7b6e7a538e9fb74feb0f0b39c51a75837157d6e43072f0591154e2a",
+ "width": 804,
+ "height": 132,
+ "bytes": 16022,
+ "role": "after",
+ "pair": "pr827-inspector",
+ "outcome": "s1-operation-authority-in-style-editor",
+ "chip": "After",
+ "alt": "Same Inspector Layout row crop after the write: the width field reads 140",
+ "caption": "Same fields after the write: width shows the new value.",
+ "roi": [
+ 1150,
+ 468,
+ 1418,
+ 512
+ ],
+ "scale": 3.0,
+ "boxes": [
+ {
+ "n": 1,
+ "original_xyxy": [
+ 1156,
+ 476,
+ 1268,
+ 505
+ ],
+ "crop_xyxy": [
+ 18,
+ 24,
+ 354,
+ 111
+ ],
+ "note": "The W field reads 140."
+ }
+ ],
+ "original": {
+ "path": "media/orig/pr827-after.png",
+ "sha256": "ffb57145c8fb2fc28e98c08797cc82a68ac2c169b67a9b91d0c120957ef692aa",
+ "width": 1440,
+ "height": 835,
+ "bytes": 260507,
+ "source": "hyperide/hyper-saas @57ce3969 docs/reports/evidence/style-operation-20261016/native-after.png"
+ }
+ },
+ {
+ "id": "pr665-after-native-warning",
+ "path": "media/pr665-after-native-warning.png",
+ "sha256": "e1df364477a43431212a6416d46814608c886893546156f9da8dc8226f6a6315",
+ "width": 950,
+ "height": 258,
+ "bytes": 41388,
+ "role": "single-after",
+ "pair": null,
+ "outcome": "a3-dead-prop-refusal",
+ "chip": "After (single capture)",
+ "alt": "Native VS Code warning notification: Style could not be applied, Badge does not forward this prop to the DOM, with Details and Auto fix via AI buttons",
+ "caption": "Native VS Code warning after a border-radius edit on a Badge component that forwards neither className nor style.",
+ "roi": [
+ 1930,
+ 1452,
+ 2880,
+ 1710
+ ],
+ "scale": 1.0,
+ "boxes": [
+ {
+ "n": 1,
+ "original_xyxy": [
+ 1975,
+ 1476,
+ 2775,
+ 1590
+ ],
+ "crop_xyxy": [
+ 45,
+ 24,
+ 845,
+ 138
+ ],
+ "note": "Warning text: Style could not be applied, and does not forward this prop to the DOM."
+ },
+ {
+ "n": 2,
+ "original_xyxy": [
+ 2515,
+ 1596,
+ 2855,
+ 1664
+ ],
+ "crop_xyxy": [
+ 585,
+ 144,
+ 925,
+ 212
+ ],
+ "note": "Details and Auto fix via AI buttons."
+ }
+ ],
+ "original": {
+ "path": "media/orig/pr665-after.png",
+ "sha256": "ac639d764c014623f3deb5681f8c4fe187cf6bf67b074c8130f9ee47cb06ad31",
+ "width": 2880,
+ "height": 1736,
+ "bytes": 568690,
+ "source": "image embedded in the body of hyperide/hyper-saas#665"
+ }
+ },
+ {
+ "id": "pr738-after-inspector-warning",
+ "path": "media/pr738-after-inspector-warning.png",
+ "sha256": "3d65de2c7371520564637bd5d7ecc77d140ed7c2ec344625dfe45cdeb4542580",
+ "width": 810,
+ "height": 716,
+ "bytes": 185949,
+ "role": "single-after",
+ "pair": null,
+ "outcome": "a2-no-style-surface-warning",
+ "chip": "After (single capture)",
+ "alt": "Inspector toast in VS Code: This component may not accept style edits, NonForwardingBadge does not appear to forward className or style to a DOM element, with an Ask AI action",
+ "caption": "Inspector after selecting a component that does not forward className or style.",
+ "roi": [
+ 2280,
+ 190,
+ 2880,
+ 720
+ ],
+ "scale": 1.35,
+ "boxes": [
+ {
+ "n": 1,
+ "original_xyxy": [
+ 2345,
+ 255,
+ 2700,
+ 640
+ ],
+ "crop_xyxy": [
+ 88,
+ 88,
+ 567,
+ 608
+ ],
+ "note": "Warning: “This component may not accept style edits”, with the reason."
+ },
+ {
+ "n": 2,
+ "original_xyxy": [
+ 2715,
+ 415,
+ 2856,
+ 490
+ ],
+ "crop_xyxy": [
+ 587,
+ 304,
+ 778,
+ 405
+ ],
+ "note": "Ask AI action."
+ }
+ ],
+ "original": {
+ "path": "media/orig/pr738-after.png",
+ "sha256": "a35de0a9f5a2431965b244f85235c5249564d88b032363c96e2c47ff4547b685",
+ "width": 2880,
+ "height": 1736,
+ "bytes": 436954,
+ "source": "image attached to hyperide/hyper-saas#738"
+ }
+ },
+ {
+ "id": "pr738-after-canvas-selection",
+ "path": "media/pr738-after-canvas-selection.png",
+ "sha256": "54138354689329d47a352dd8559e20bf3bfa252dd32a0142f188a8d314781b9f",
+ "width": 800,
+ "height": 280,
+ "bytes": 28952,
+ "role": "context",
+ "pair": null,
+ "outcome": "a2-no-style-surface-warning",
+ "chip": "Same capture",
+ "alt": "Canvas region of the same capture: the selected element has a blue selection outline",
+ "caption": "The element selected in the Canvas in the same capture.",
+ "roi": [
+ 1500,
+ 1340,
+ 1900,
+ 1480
+ ],
+ "scale": 2.0,
+ "boxes": [
+ {
+ "n": 1,
+ "original_xyxy": [
+ 1548,
+ 1388,
+ 1762,
+ 1442
+ ],
+ "crop_xyxy": [
+ 96,
+ 96,
+ 524,
+ 204
+ ],
+ "note": "The selected element, labelled “No style surface”, with a blue selection outline."
+ }
+ ],
+ "original": {
+ "path": "media/orig/pr738-after.png",
+ "sha256": "a35de0a9f5a2431965b244f85235c5249564d88b032363c96e2c47ff4547b685",
+ "width": 2880,
+ "height": 1736,
+ "bytes": 436954,
+ "source": "image attached to hyperide/hyper-saas#738"
+ }
+ },
+ {
+ "id": "pr794-before-tab",
+ "path": "media/pr794-before-tab.png",
+ "sha256": "ae04c8ded2d66fc6baecf3aab07be80994c5ca36c7d6c84152352b3f041e751b",
+ "width": 794,
+ "height": 112,
+ "bytes": 31489,
+ "role": "before",
+ "pair": "pr794-tab",
+ "outcome": "c5-edit-component-drag-undo",
+ "chip": "Before",
+ "alt": "Editor tab strip before Edit component: the active tab is App.tsx",
+ "caption": "Editor tabs before Edit component, with the Feed call-site selected inside App.",
+ "roi": [
+ 348,
+ 40,
+ 745,
+ 96
+ ],
+ "scale": 2.0,
+ "boxes": [
+ {
+ "n": 1,
+ "original_xyxy": [
+ 352,
+ 42,
+ 462,
+ 66
+ ],
+ "crop_xyxy": [
+ 8,
+ 4,
+ 228,
+ 52
+ ],
+ "note": "Active editor tab: App.tsx."
+ },
+ {
+ "n": 2,
+ "original_xyxy": [
+ 362,
+ 72,
+ 530,
+ 91
+ ],
+ "crop_xyxy": [
+ 28,
+ 64,
+ 364,
+ 102
+ ],
+ "note": "Breadcrumb ends at App.tsx."
+ }
+ ],
+ "original": {
+ "path": "media/orig/pr794-before.png",
+ "sha256": "bc1e8d9d542b8b336f930fed8fd65219affcf28eca1b082315da6457de4557d5",
+ "width": 1440,
+ "height": 1000,
+ "bytes": 264064,
+ "source": "image in the body of hyperide/hyper-saas#794 (Before)"
+ }
+ },
+ {
+ "id": "pr794-after-tab",
+ "path": "media/pr794-after-tab.png",
+ "sha256": "964e95887cc6d53adf7b7508c1e93b52b49fb233a7a513460efc24ceafe991e4",
+ "width": 794,
+ "height": 112,
+ "bytes": 39849,
+ "role": "after",
+ "pair": "pr794-tab",
+ "outcome": "c5-edit-component-drag-undo",
+ "chip": "After",
+ "alt": "Same tab strip after Edit component: the active tab is Feed.tsx and the breadcrumb reads src, components, Feed.tsx",
+ "caption": "Same crop after Edit component: the editor opened the Feed definition.",
+ "roi": [
+ 348,
+ 40,
+ 745,
+ 96
+ ],
+ "scale": 2.0,
+ "boxes": [
+ {
+ "n": 1,
+ "original_xyxy": [
+ 466,
+ 42,
+ 584,
+ 66
+ ],
+ "crop_xyxy": [
+ 236,
+ 4,
+ 472,
+ 52
+ ],
+ "note": "Active editor tab: Feed.tsx."
+ },
+ {
+ "n": 2,
+ "original_xyxy": [
+ 362,
+ 72,
+ 592,
+ 91
+ ],
+ "crop_xyxy": [
+ 28,
+ 64,
+ 488,
+ 102
+ ],
+ "note": "Breadcrumb: src › components › Feed.tsx."
+ }
+ ],
+ "original": {
+ "path": "media/orig/pr794-after.png",
+ "sha256": "0e7f863a1a9223f9addd74bcdbcecd88bd5b3b2a097cc6c2e0e1f79648e1a4fc",
+ "width": 1440,
+ "height": 1000,
+ "bytes": 352024,
+ "source": "image in the body of hyperide/hyper-saas#794 (After)"
+ }
+ },
+ {
+ "id": "pr794-before-canvas",
+ "path": "media/pr794-before-canvas.png",
+ "sha256": "b4213372739a2eec11c334fa7a46440b0969bb2a9915c78bff422b0e407d4544",
+ "width": 790,
+ "height": 580,
+ "bytes": 134483,
+ "role": "before",
+ "pair": "pr794-canvas",
+ "outcome": "c5-edit-component-drag-undo",
+ "chip": "Before",
+ "alt": "Canvas before Edit component: the whole App page with its top bar, and the Feed call-site outlined in blue",
+ "caption": "Canvas before: the whole App page, with Feed selected inside it.",
+ "roi": [
+ 745,
+ 40,
+ 1140,
+ 330
+ ],
+ "scale": 2.0,
+ "boxes": [
+ {
+ "n": 1,
+ "original_xyxy": [
+ 763,
+ 122,
+ 1016,
+ 325
+ ],
+ "crop_xyxy": [
+ 36,
+ 164,
+ 542,
+ 570
+ ],
+ "note": "Blue outline: the Feed call-site, selected inside the App page."
+ },
+ {
+ "n": 2,
+ "original_xyxy": [
+ 762,
+ 76,
+ 1132,
+ 118
+ ],
+ "crop_xyxy": [
+ 34,
+ 72,
+ 774,
+ 156
+ ],
+ "note": "App's own top bar is still part of what the Canvas renders."
+ }
+ ],
+ "original": {
+ "path": "media/orig/pr794-before.png",
+ "sha256": "bc1e8d9d542b8b336f930fed8fd65219affcf28eca1b082315da6457de4557d5",
+ "width": 1440,
+ "height": 1000,
+ "bytes": 264064,
+ "source": "image in the body of hyperide/hyper-saas#794 (Before)"
+ }
+ },
+ {
+ "id": "pr794-after-canvas",
+ "path": "media/pr794-after-canvas.png",
+ "sha256": "af3a83ee3a0c8671c41af1b881300821741ced5a75a19f39f8d2c4cdce4bb532",
+ "width": 790,
+ "height": 580,
+ "bytes": 190014,
+ "role": "after",
+ "pair": "pr794-canvas",
+ "outcome": "c5-edit-component-drag-undo",
+ "chip": "After",
+ "alt": "Same canvas crop after Edit component: the Canvas shows the Feed definition on its own, starting at the Home heading, without App's top bar",
+ "caption": "Same crop after: the Canvas switched to the Feed definition.",
+ "roi": [
+ 745,
+ 40,
+ 1140,
+ 330
+ ],
+ "scale": 2.0,
+ "boxes": [
+ {
+ "n": 1,
+ "original_xyxy": [
+ 770,
+ 78,
+ 856,
+ 114
+ ],
+ "crop_xyxy": [
+ 50,
+ 76,
+ 222,
+ 148
+ ],
+ "note": "The Canvas renders the Feed definition on its own, starting at its Home heading. App's top bar is gone."
+ }
+ ],
+ "original": {
+ "path": "media/orig/pr794-after.png",
+ "sha256": "0e7f863a1a9223f9addd74bcdbcecd88bd5b3b2a097cc6c2e0e1f79648e1a4fc",
+ "width": 1440,
+ "height": 1000,
+ "bytes": 352024,
+ "source": "image in the body of hyperide/hyper-saas#794 (After)"
+ }
+ },
+ {
+ "id": "pr794-before-tree",
+ "path": "media/pr794-before-tree.png",
+ "sha256": "e90362a291ac0b5beed42b4921c06c62a6bd6d8d33bd52c0105380a428e96fda",
+ "width": 780,
+ "height": 775,
+ "bytes": 127318,
+ "role": "before",
+ "pair": "pr794-tree",
+ "outcome": "c5-edit-component-drag-undo",
+ "chip": "Before",
+ "alt": "Elements tree before Edit component: the Feed call-site row is selected",
+ "caption": "Elements tree before: the Feed call-site row is selected.",
+ "roi": [
+ 48,
+ 664,
+ 348,
+ 962
+ ],
+ "scale": 2.6,
+ "boxes": [
+ {
+ "n": 1,
+ "original_xyxy": [
+ 56,
+ 856,
+ 340,
+ 882
+ ],
+ "crop_xyxy": [
+ 21,
+ 499,
+ 759,
+ 567
+ ],
+ "note": "Selected row: Feed, a call-site inside App."
+ }
+ ],
+ "original": {
+ "path": "media/orig/pr794-before.png",
+ "sha256": "bc1e8d9d542b8b336f930fed8fd65219affcf28eca1b082315da6457de4557d5",
+ "width": 1440,
+ "height": 1000,
+ "bytes": 264064,
+ "source": "image in the body of hyperide/hyper-saas#794 (Before)"
+ }
+ },
+ {
+ "id": "pr794-after-tree",
+ "path": "media/pr794-after-tree.png",
+ "sha256": "0da2163b58c93af9e491264d2c8eb068994a2e1eef921b0048e13609bec1612e",
+ "width": 780,
+ "height": 775,
+ "bytes": 152407,
+ "role": "after",
+ "pair": "pr794-tree",
+ "outcome": "c5-edit-component-drag-undo",
+ "chip": "After",
+ "alt": "Same Elements tree crop after Edit component: the tree is rebuilt from the Feed definition and starts at main, div, h1 Home",
+ "caption": "Same crop after: the tree is rebuilt from the Feed definition.",
+ "roi": [
+ 48,
+ 664,
+ 348,
+ 962
+ ],
+ "scale": 2.6,
+ "boxes": [
+ {
+ "n": 1,
+ "original_xyxy": [
+ 56,
+ 684,
+ 340,
+ 758
+ ],
+ "crop_xyxy": [
+ 21,
+ 52,
+ 759,
+ 244
+ ],
+ "note": "The tree now starts at the root of Feed's own source, main › div › h1 Home."
+ }
+ ],
+ "original": {
+ "path": "media/orig/pr794-after.png",
+ "sha256": "0e7f863a1a9223f9addd74bcdbcecd88bd5b3b2a097cc6c2e0e1f79648e1a4fc",
+ "width": 1440,
+ "height": 1000,
+ "bytes": 352024,
+ "source": "image in the body of hyperide/hyper-saas#794 (After)"
+ }
+ },
+ {
+ "id": "pr794-before-notice",
+ "path": "media/pr794-before-notice.png",
+ "sha256": "a1122c563e31588fb19b98bd4fe5d009344bef23ac0a9d62755b6b66360ef413",
+ "width": 790,
+ "height": 167,
+ "bytes": 40103,
+ "role": "before",
+ "pair": "pr794-notice",
+ "outcome": "c5-edit-component-drag-undo",
+ "chip": "Before",
+ "alt": "Bottom-right notices before Edit component: only the dev server notice",
+ "caption": "Notices before: only the dev server notice.",
+ "roi": [
+ 975,
+ 878,
+ 1440,
+ 976
+ ],
+ "scale": 1.7,
+ "boxes": [
+ {
+ "n": 1,
+ "original_xyxy": [
+ 982,
+ 930,
+ 1436,
+ 970
+ ],
+ "crop_xyxy": [
+ 12,
+ 88,
+ 784,
+ 156
+ ],
+ "note": "Only notice: “Dev server running at localhost”."
+ }
+ ],
+ "original": {
+ "path": "media/orig/pr794-before.png",
+ "sha256": "bc1e8d9d542b8b336f930fed8fd65219affcf28eca1b082315da6457de4557d5",
+ "width": 1440,
+ "height": 1000,
+ "bytes": 264064,
+ "source": "image in the body of hyperide/hyper-saas#794 (Before)"
+ }
+ },
+ {
+ "id": "pr794-after-notice",
+ "path": "media/pr794-after-notice.png",
+ "sha256": "92e97c5335a1546ca017aff6730450e0a3722dd9df5389533891c24f8559a459",
+ "width": 790,
+ "height": 167,
+ "bytes": 62180,
+ "role": "after",
+ "pair": "pr794-notice",
+ "outcome": "c5-edit-component-drag-undo",
+ "chip": "After",
+ "alt": "Same notices crop after Edit component: a new notice says Editing Feed and that changes to this component definition affect all its instances",
+ "caption": "Same crop after: a notice explains the scope of editing a definition.",
+ "roi": [
+ 975,
+ 878,
+ 1440,
+ 976
+ ],
+ "scale": 1.7,
+ "boxes": [
+ {
+ "n": 1,
+ "original_xyxy": [
+ 982,
+ 890,
+ 1436,
+ 920
+ ],
+ "crop_xyxy": [
+ 12,
+ 20,
+ 784,
+ 71
+ ],
+ "note": "New notice: “Editing Feed. Changes to this component definition affect all its instances.”"
+ }
+ ],
+ "original": {
+ "path": "media/orig/pr794-after.png",
+ "sha256": "0e7f863a1a9223f9addd74bcdbcecd88bd5b3b2a097cc6c2e0e1f79648e1a4fc",
+ "width": 1440,
+ "height": 1000,
+ "bytes": 352024,
+ "source": "image in the body of hyperide/hyper-saas#794 (After)"
+ }
+ },
+ {
+ "id": "pr805-step1-edit-cancelled",
+ "path": "media/pr805-step1-edit-cancelled.png",
+ "sha256": "dad2503f6001f1c48b4ea1683028b6c7dd1a4ad761300221732ced618843ebe1",
+ "width": 783,
+ "height": 551,
+ "bytes": 180827,
+ "role": "step-1",
+ "pair": "pr805-sequence",
+ "outcome": "c1-stale-context-cancellation",
+ "chip": "Step 1",
+ "alt": "Inspector panel with a message: Edit cancelled. The selected element or preview changed before this edit was applied. Select the element and try again",
+ "caption": "Step 1, Inspector: the selection changed before a delayed edit was dispatched, and the edit is refused.",
+ "roi": [
+ 1146,
+ 96,
+ 1436,
+ 300
+ ],
+ "scale": 2.7,
+ "boxes": [
+ {
+ "n": 1,
+ "original_xyxy": [
+ 1156,
+ 106,
+ 1426,
+ 284
+ ],
+ "crop_xyxy": [
+ 27,
+ 27,
+ 756,
+ 508
+ ],
+ "note": "Inspector: “Edit cancelled. The selected element or preview changed before this edit was applied. Select the element and try again. (src/ContextGuardFixture.tsx)”"
+ }
+ ],
+ "original": {
+ "path": "media/orig/pr805-edit-cancelled.png",
+ "sha256": "8af51db9f1c7f051d995a2914b55c3cb04b2c93cf5fff9d163aa6fb241be958e",
+ "width": 1440,
+ "height": 1000,
+ "bytes": 172684,
+ "source": "image in the body of hyperide/hyper-saas#805 (HYP-1480 criterion 1)"
+ }
+ },
+ {
+ "id": "pr805-step1-selection-kept",
+ "path": "media/pr805-step1-selection-kept.png",
+ "sha256": "cc023ac804c7ce2f868c5b01bf246cf87975fab2639d3880d120e113f5bcfdcf",
+ "width": 803,
+ "height": 550,
+ "bytes": 139679,
+ "role": "step-1",
+ "pair": "pr805-sequence",
+ "outcome": "c1-stale-context-cancellation",
+ "chip": "Step 1",
+ "alt": "Canvas region of the same capture: the second heading stays selected with a blue outline",
+ "caption": "Step 1, Canvas, same capture: the second heading stays selected after the cancellation.",
+ "roi": [
+ 765,
+ 70,
+ 1130,
+ 320
+ ],
+ "scale": 2.2,
+ "boxes": [
+ {
+ "n": 1,
+ "original_xyxy": [
+ 790,
+ 204,
+ 1030,
+ 244
+ ],
+ "crop_xyxy": [
+ 55,
+ 295,
+ 583,
+ 383
+ ],
+ "note": "The second heading, “Second editable heading”, stays selected."
+ }
+ ],
+ "original": {
+ "path": "media/orig/pr805-edit-cancelled.png",
+ "sha256": "8af51db9f1c7f051d995a2914b55c3cb04b2c93cf5fff9d163aa6fb241be958e",
+ "width": 1440,
+ "height": 1000,
+ "bytes": 172684,
+ "source": "image in the body of hyperide/hyper-saas#805 (HYP-1480 criterion 1)"
+ }
+ },
+ {
+ "id": "pr805-step2-next-edit-persisted",
+ "path": "media/pr805-step2-next-edit-persisted.png",
+ "sha256": "7c0e2ff68f1fd8ed20e3663b610e7f90f8cf9d31060b405223df05ae24ce7b41",
+ "width": 803,
+ "height": 550,
+ "bytes": 100104,
+ "role": "step-2",
+ "pair": "pr805-sequence",
+ "outcome": "c1-stale-context-cancellation",
+ "chip": "Step 2",
+ "alt": "Canvas region at a later stage of the same run: the first heading is almost transparent, because the next ordinary Inspector edit was applied",
+ "caption": "Step 2, same run: the next ordinary edit persisted. The test typed a near-zero opacity, so the heading is almost invisible.",
+ "roi": [
+ 765,
+ 70,
+ 1130,
+ 320
+ ],
+ "scale": 2.2,
+ "boxes": [
+ {
+ "n": 1,
+ "original_xyxy": [
+ 790,
+ 98,
+ 1000,
+ 170
+ ],
+ "crop_xyxy": [
+ 55,
+ 62,
+ 517,
+ 220
+ ],
+ "note": "The first heading is almost transparent: the next Inspector edit was applied."
+ }
+ ],
+ "original": {
+ "path": "media/orig/pr805-next-edit.png",
+ "sha256": "a1f4bbfa86041f9405149c08680eef1ab0b01155499ad62bbd2f635be167597c",
+ "width": 1440,
+ "height": 1000,
+ "bytes": 154508,
+ "source": "image in the body of hyperide/hyper-saas#805 (HYP-1480 criterion 2)"
+ }
+ },
+ {
+ "id": "pr811-before-order-row",
+ "path": "media/pr811-before-order-row.png",
+ "sha256": "5c1f6429d10732f848058707b1892834b1646143b432dc1ec842bf50a6102bfe",
+ "width": 816,
+ "height": 238,
+ "bytes": 46764,
+ "role": "before",
+ "pair": "pr811-order-row",
+ "outcome": "c2-verified-move",
+ "chip": "Before",
+ "alt": "Canvas crop before the order drop: the row of chips reads Order A, Order B, Order C",
+ "caption": "Canvas, the order row, before Order A is dropped after Order C.",
+ "roi": [
+ 1500,
+ 790,
+ 1980,
+ 930
+ ],
+ "scale": 1.7,
+ "boxes": [
+ {
+ "n": 1,
+ "original_xyxy": [
+ 1540,
+ 862,
+ 1935,
+ 912
+ ],
+ "crop_xyxy": [
+ 68,
+ 122,
+ 740,
+ 207
+ ],
+ "note": "The order row reads Order A, Order B, Order C."
+ }
+ ],
+ "original": {
+ "path": "media/orig/pr811-order-before.png",
+ "sha256": "5f6df6841c19a430a04f29b8a608dc1635f6762a12b4de5fc6fe7c81f0a8e7f8",
+ "width": 2880,
+ "height": 1736,
+ "bytes": 631230,
+ "source": "image in the body of hyperide/hyper-saas#811 (hyp732-r2-5-order-before)"
+ }
+ },
+ {
+ "id": "pr811-after-order-row",
+ "path": "media/pr811-after-order-row.png",
+ "sha256": "38037a9462ea14c31b6b7100f92a85238fb99acc1351e967f9e70aa048178434",
+ "width": 816,
+ "height": 238,
+ "bytes": 46955,
+ "role": "after",
+ "pair": "pr811-order-row",
+ "outcome": "c2-verified-move",
+ "chip": "After",
+ "alt": "Same canvas crop after the order drop: the row of chips reads Order B, Order C, Order A, with Order A outlined as selected",
+ "caption": "Same crop after the drop: the visual order is B, C, A.",
+ "roi": [
+ 1500,
+ 790,
+ 1980,
+ 930
+ ],
+ "scale": 1.7,
+ "boxes": [
+ {
+ "n": 1,
+ "original_xyxy": [
+ 1540,
+ 862,
+ 1935,
+ 912
+ ],
+ "crop_xyxy": [
+ 68,
+ 122,
+ 740,
+ 207
+ ],
+ "note": "The row now reads Order B, Order C, Order A, and Order A is selected."
+ }
+ ],
+ "original": {
+ "path": "media/orig/pr811-order-after.png",
+ "sha256": "6ddb11e8f241a44cd5ac2353b151d440c2a640dd8595b37a433c32bd6a3bcc03",
+ "width": 2880,
+ "height": 1736,
+ "bytes": 568535,
+ "source": "image in the body of hyperide/hyper-saas#811 (hyp732-r2-5-order-after)"
+ }
+ },
+ {
+ "id": "pr811-before-order-inspector",
+ "path": "media/pr811-before-order-inspector.png",
+ "sha256": "9c620df90389ceac4d587af7e2e7a8c1f11bdea37f268c71e0cdf9eb90334f61",
+ "width": 798,
+ "height": 504,
+ "bytes": 72545,
+ "role": "before",
+ "pair": "pr811-order-inspector",
+ "outcome": "c2-verified-move",
+ "chip": "Before",
+ "alt": "Inspector crop before the order drop: it reads No element selected",
+ "caption": "Inspector before the drop.",
+ "roi": [
+ 2290,
+ 120,
+ 2860,
+ 480
+ ],
+ "scale": 1.4,
+ "boxes": [
+ {
+ "n": 1,
+ "original_xyxy": [
+ 2300,
+ 330,
+ 2850,
+ 470
+ ],
+ "crop_xyxy": [
+ 14,
+ 294,
+ 784,
+ 490
+ ],
+ "note": "Inspector: “No element selected”."
+ }
+ ],
+ "original": {
+ "path": "media/orig/pr811-order-before.png",
+ "sha256": "5f6df6841c19a430a04f29b8a608dc1635f6762a12b4de5fc6fe7c81f0a8e7f8",
+ "width": 2880,
+ "height": 1736,
+ "bytes": 631230,
+ "source": "image in the body of hyperide/hyper-saas#811 (hyp732-r2-5-order-before)"
+ }
+ },
+ {
+ "id": "pr811-after-order-inspector",
+ "path": "media/pr811-after-order-inspector.png",
+ "sha256": "66ba864bd264985b790d9c672ee37fdf257394a2929a4dfe7df75442f36cca98",
+ "width": 798,
+ "height": 504,
+ "bytes": 61097,
+ "role": "after",
+ "pair": "pr811-order-inspector",
+ "outcome": "c2-verified-move",
+ "chip": "After",
+ "alt": "Same Inspector crop after the order drop: it shows Frame (div) named Order A",
+ "caption": "Same crop after the drop: the Inspector follows the moved element.",
+ "roi": [
+ 2290,
+ 120,
+ 2860,
+ 480
+ ],
+ "scale": 1.4,
+ "boxes": [
+ {
+ "n": 1,
+ "original_xyxy": [
+ 2295,
+ 215,
+ 2850,
+ 335
+ ],
+ "crop_xyxy": [
+ 7,
+ 133,
+ 784,
+ 301
+ ],
+ "note": "Inspector: Frame (div), named Order A, the moved element."
+ }
+ ],
+ "original": {
+ "path": "media/orig/pr811-order-after.png",
+ "sha256": "6ddb11e8f241a44cd5ac2353b151d440c2a640dd8595b37a433c32bd6a3bcc03",
+ "width": 2880,
+ "height": 1736,
+ "bytes": 568535,
+ "source": "image in the body of hyperide/hyper-saas#811 (hyp732-r2-5-order-after)"
+ }
+ },
+ {
+ "id": "pr811-restored-notice",
+ "path": "media/pr811-restored-notice.png",
+ "sha256": "1fad2f995bb497a710b14643e779a84c0f9650795d3963902ea878a0baf74f47",
+ "width": 940,
+ "height": 330,
+ "bytes": 81307,
+ "role": "single-after",
+ "pair": null,
+ "outcome": "c2-verified-move",
+ "chip": "After (single capture)",
+ "alt": "VS Code notice: Canvas move did not verify and was restored. The preview did not render the moved version of TestElements.tsx. The verification deadline passed. An AI recovery proposal was queued in the AI Chat panel, with an Open AI Chat button",
+ "caption": "A move whose target module throws while loading: the file is restored and the notice says so.",
+ "roi": [
+ 1940,
+ 1370,
+ 2880,
+ 1700
+ ],
+ "scale": 1.0,
+ "boxes": [
+ {
+ "n": 1,
+ "original_xyxy": [
+ 1990,
+ 1395,
+ 2800,
+ 1585
+ ],
+ "crop_xyxy": [
+ 50,
+ 25,
+ 860,
+ 215
+ ],
+ "note": "Notice: the move did not verify and was restored; an AI recovery proposal was queued."
+ },
+ {
+ "n": 2,
+ "original_xyxy": [
+ 2650,
+ 1600,
+ 2850,
+ 1655
+ ],
+ "crop_xyxy": [
+ 710,
+ 230,
+ 910,
+ 285
+ ],
+ "note": "Open AI Chat button."
+ }
+ ],
+ "original": {
+ "path": "media/orig/pr811-restored-toast.png",
+ "sha256": "3e64de85fd8681034f17d68151802a4383b4cd66ad274c268f57b578e017a93f",
+ "width": 2880,
+ "height": 1736,
+ "bytes": 611670,
+ "source": "image in the body of hyperide/hyper-saas#811 (hyp732-r2-2-restored-toast)"
+ }
+ },
+ {
+ "id": "pr823-restored-fix-with-ai",
+ "path": "media/pr823-restored-fix-with-ai.png",
+ "sha256": "071938a657a9724622ea7e29161cd89f8f884e0c07cca7f53ccba34ae4cfc6f7",
+ "width": 960,
+ "height": 230,
+ "bytes": 78162,
+ "role": "single-after",
+ "pair": null,
+ "outcome": "c3-ai-fix-on-click-only",
+ "chip": "After (single capture)",
+ "alt": "VS Code notice: Canvas couldn't apply the move and put the file back, with Fix with AI and Details buttons",
+ "caption": "After a failed move the notice offers Fix with AI as a button.",
+ "roi": [
+ 960,
+ 705,
+ 1440,
+ 820
+ ],
+ "scale": 2.0,
+ "boxes": [
+ {
+ "n": 1,
+ "original_xyxy": [
+ 988,
+ 726,
+ 1330,
+ 756
+ ],
+ "crop_xyxy": [
+ 56,
+ 42,
+ 740,
+ 102
+ ],
+ "note": "Notice: “Canvas couldn't apply the move and put the file back.”"
+ },
+ {
+ "n": 2,
+ "original_xyxy": [
+ 1280,
+ 762,
+ 1426,
+ 795
+ ],
+ "crop_xyxy": [
+ 640,
+ 114,
+ 932,
+ 180
+ ],
+ "note": "Fix with AI and Details are buttons in the notice."
+ }
+ ],
+ "original": {
+ "path": "media/orig/pr823-restored-toast.png",
+ "sha256": "122365e4b6f573229dfd6617ead6656616ce4f04f8db856a8bde22cdf0a31af2",
+ "width": 1440,
+ "height": 835,
+ "bytes": 277659,
+ "source": "hyperide/hyper-saas @a4caec76 docs/notes/canvas-proof-20261016/restored.png"
+ }
+ },
+ {
+ "id": "pr705-step1-dialog",
+ "path": "media/pr705-step1-dialog.png",
+ "sha256": "1ba03f1ca8b147b0570353db9470c638c3451d0705dbe0fcb8bdb1638011cb82",
+ "width": 793,
+ "height": 1710,
+ "bytes": 329682,
+ "role": "step-1",
+ "pair": "pr705-sequence",
+ "outcome": "t-new-component-dialog",
+ "chip": "Step 1",
+ "alt": "The guided New component dialog in VS Code: three kinds in plain words, a name field with HeroBadge and the target folder, and Create and Cancel buttons",
+ "caption": "Step 1: the guided New component dialog, opened from the Components + button.",
+ "roi": [
+ 90,
+ 260,
+ 700,
+ 1575
+ ],
+ "scale": 1.3,
+ "boxes": [
+ {
+ "n": 1,
+ "original_xyxy": [
+ 145,
+ 517,
+ 646,
+ 1084
+ ],
+ "crop_xyxy": [
+ 72,
+ 334,
+ 723,
+ 1071
+ ],
+ "note": "Three kinds in plain words: Building block, Section, Page."
+ },
+ {
+ "n": 2,
+ "original_xyxy": [
+ 140,
+ 1163,
+ 653,
+ 1259
+ ],
+ "crop_xyxy": [
+ 65,
+ 1174,
+ 732,
+ 1299
+ ],
+ "note": "Name field, filled with HeroBadge, with the target folder hint."
+ },
+ {
+ "n": 3,
+ "original_xyxy": [
+ 145,
+ 1356,
+ 646,
+ 1440
+ ],
+ "crop_xyxy": [
+ 72,
+ 1425,
+ 723,
+ 1534
+ ],
+ "note": "The Create button; Cancel sits below it."
+ }
+ ],
+ "original": {
+ "path": "media/orig/pr705-dialog.png",
+ "sha256": "ee77f190d5bbac3e30df5ed2530c912f36ce5504b3488ad62e3d52bcb9588655",
+ "width": 2880,
+ "height": 1736,
+ "bytes": 721362,
+ "source": "hyperide/hyper-saas @b901fb76 .github/pr-screenshots/20260806-hyp1184-create-dialog.png"
+ }
+ },
+ {
+ "id": "pr705-step2-created-list",
+ "path": "media/pr705-step2-created-list.png",
+ "sha256": "4bb28b1bd3e69976fc2a6d50f9dfd32d1ac1d2f8d4b47f9daae107000662a6f1",
+ "width": 793,
+ "height": 494,
+ "bytes": 122964,
+ "role": "step-2",
+ "pair": "pr705-sequence",
+ "outcome": "t-new-component-dialog",
+ "chip": "Step 2",
+ "alt": "Components list after Create: HeroBadge.tsx appears in Composite components and is selected, and the Elements tree shows its root",
+ "caption": "Step 2: after Create, the new file is listed and opened.",
+ "roi": [
+ 90,
+ 880,
+ 700,
+ 1260
+ ],
+ "scale": 1.3,
+ "boxes": [
+ {
+ "n": 1,
+ "original_xyxy": [
+ 160,
+ 904,
+ 680,
+ 962
+ ],
+ "crop_xyxy": [
+ 91,
+ 31,
+ 767,
+ 107
+ ],
+ "note": "HeroBadge.tsx now appears in Composite components, selected."
+ },
+ {
+ "n": 2,
+ "original_xyxy": [
+ 95,
+ 1196,
+ 420,
+ 1244
+ ],
+ "crop_xyxy": [
+ 6,
+ 411,
+ 429,
+ 473
+ ],
+ "note": "The Elements tree shows the new component's root."
+ }
+ ],
+ "original": {
+ "path": "media/orig/pr705-created.png",
+ "sha256": "0472c6b2aa0868b52e7980de8ba2c7989994513544b8dfeb865832d704fafe2d",
+ "width": 2880,
+ "height": 1736,
+ "bytes": 323033,
+ "source": "hyperide/hyper-saas @b901fb76 .github/pr-screenshots/20260806-hyp1184-created-in-preview.png"
+ }
+ },
+ {
+ "id": "pr705-step2-created-canvas",
+ "path": "media/pr705-step2-created-canvas.png",
+ "sha256": "a2544a2f7c5eb947914be58f8a792206b0a17057ad8f89f2621d896037031c02",
+ "width": 950,
+ "height": 190,
+ "bytes": 41815,
+ "role": "step-2",
+ "pair": "pr705-sequence",
+ "outcome": "t-new-component-dialog",
+ "chip": "Step 2",
+ "alt": "Editor tab HeroBadge.tsx and the Hyper Canvas rendering the Hero Badge component",
+ "caption": "Step 2, same capture: the new component opens in the editor and renders in the Canvas.",
+ "roi": [
+ 900,
+ 70,
+ 1850,
+ 260
+ ],
+ "scale": 1.0,
+ "boxes": [
+ {
+ "n": 1,
+ "original_xyxy": [
+ 935,
+ 76,
+ 1240,
+ 134
+ ],
+ "crop_xyxy": [
+ 35,
+ 6,
+ 340,
+ 64
+ ],
+ "note": "Editor tab HeroBadge.tsx."
+ },
+ {
+ "n": 2,
+ "original_xyxy": [
+ 1540,
+ 186,
+ 1732,
+ 238
+ ],
+ "crop_xyxy": [
+ 640,
+ 116,
+ 832,
+ 168
+ ],
+ "note": "The Canvas renders Hero Badge."
+ }
+ ],
+ "original": {
+ "path": "media/orig/pr705-created.png",
+ "sha256": "0472c6b2aa0868b52e7980de8ba2c7989994513544b8dfeb865832d704fafe2d",
+ "width": 2880,
+ "height": 1736,
+ "bytes": 323033,
+ "source": "hyperide/hyper-saas @b901fb76 .github/pr-screenshots/20260806-hyp1184-created-in-preview.png"
+ }
+ }
+ ],
+ "groups": [
+ {
+ "id": "pr721-explorer",
+ "kind": "pair",
+ "crops": [
+ "pr721-before-explorer",
+ "pr721-after-explorer",
+ "pr721-after-interim-explorer",
+ "pr721-link-clicked-explorer"
+ ]
+ },
+ {
+ "id": "pr827-write",
+ "kind": "pair",
+ "crops": [
+ "pr827-before-canvas",
+ "pr827-after-canvas",
+ "pr827-before-inspector",
+ "pr827-after-inspector"
+ ]
+ },
+ {
+ "id": "pr665-warning",
+ "kind": "single",
+ "crops": [
+ "pr665-after-native-warning"
+ ]
+ },
+ {
+ "id": "pr738-warning",
+ "kind": "single",
+ "crops": [
+ "pr738-after-inspector-warning",
+ "pr738-after-canvas-selection"
+ ]
+ },
+ {
+ "id": "pr794-edit-component",
+ "kind": "pair",
+ "crops": [
+ "pr794-before-tab",
+ "pr794-after-tab",
+ "pr794-before-canvas",
+ "pr794-after-canvas",
+ "pr794-before-tree",
+ "pr794-after-tree",
+ "pr794-before-notice",
+ "pr794-after-notice"
+ ]
+ },
+ {
+ "id": "pr805-sequence",
+ "kind": "sequence",
+ "crops": [
+ "pr805-step1-edit-cancelled",
+ "pr805-step1-selection-kept",
+ "pr805-step2-next-edit-persisted"
+ ]
+ },
+ {
+ "id": "pr811-order",
+ "kind": "pair",
+ "crops": [
+ "pr811-before-order-row",
+ "pr811-after-order-row",
+ "pr811-before-order-inspector",
+ "pr811-after-order-inspector"
+ ]
+ },
+ {
+ "id": "pr811-restored",
+ "kind": "single",
+ "crops": [
+ "pr811-restored-notice"
+ ]
+ },
+ {
+ "id": "pr823-restored",
+ "kind": "single",
+ "crops": [
+ "pr823-restored-fix-with-ai"
+ ]
+ },
+ {
+ "id": "pr705-sequence",
+ "kind": "sequence",
+ "crops": [
+ "pr705-step1-dialog",
+ "pr705-step2-created-list",
+ "pr705-step2-created-canvas"
+ ]
+ }
+ ],
+ "videos": []
+}
diff --git a/reports/hyper-2026-10/media/orig/pr665-after.png b/reports/hyper-2026-10/media/orig/pr665-after.png
new file mode 100644
index 0000000000000000000000000000000000000000..287a209913d72bfb6b5f4aeb84e86e7f283c5951
GIT binary patch
literal 568690
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