Repository navigation
Conversation
…a click-through found A real mouse click-through of a running FlyBot found defects no test covered. This fixes the ones that reproduce, and states the two that do not. The Details panel opened at 320px and wrapped its own controls: the Name field's label broke into Nam + e, Test connection into Test connecti + on, Main Bot's Change into Ch/an/ge. It now opens at 380px, a row's label stays on one line, a button never breaks its own words, and below 300px - the panel's floor in a narrow window - the row stacks instead of clipping. A saved width from the narrower policy is kept, not silently widened. A sidebar preview could carry the untrusted fence, or the fragment an older write left (from="User"> ... >), so a shared helper reads a stored line the same way whatever shape its fence is in: complete wraps are unwrapped, leftover marker fragments are removed until stable, and plain words are kept. A Bot chat with nothing said yet gets no header from the shell (headerBlank), so the column was blank with a composer. The dock now draws a strip on the same blank fact #998 uses for a group - never for a friend's Bot, never beside a header the shell drew. The details drawer's copy button is named for what it does and confirms the copy; a refused copy is reported rather than swallowed. The mode word beside the title no longer draws as a filled chip that looks clickable and is not. A provider failure stored as a cut-off JSON body now reads as a sentence naming the feature and where to change the model, keyed on the provider's stable code, in the chat's failure lines and in the Inbox. Not reproduced on DSH 0.2.0-rc.2 or 0.2.1-rc.3, so not changed: the trajectory toolbar left painted over Chat (it unmounts on the click, and through Inbox, Settings and a chat switch), and chat bubbles drawn above a modal (checked with elementsFromPoint and an opaque scrim at four viewports). The rate_limited flood in Feedback is #1161's retry storm, already fixed and pinned by core/test/room-ticket-seat.test.js. Fixes #1335 Co-authored-by: Danyang Chen <birfychen@gmail.com>
Co-authored-by: Danyang Chen <birfychen@gmail.com>
Co-authored-by: Danyang Chen <birfychen@gmail.com>
Co-authored-by: Danyang Chen <birfychen@gmail.com>
Birfy
marked this pull request as draft
October 27, 2026 05:29
…scrim The owner's screenshots show a right-aligned user message at full opacity across the Tasks dialog and over the Inbox scrim, with chat text readable through the columns. My earlier elementsFromPoint walk could not see it, because this is a paint-order defect rather than a DOM-order one: the walk returns the dialog as topmost while the browser still paints the bubble above it. Cause. The chat column had no stacking context of its own (position:static, z-index:auto), so nothing inside it was boxed in. Anything the browser promotes to its own composited layer -- an entrance animation's transform (bt-row-in), a filter, a will-change, a sticky box -- was ordered against the ROOT stacking context rather than against the column, and a dialog layer is just a z-index box at the root. So a promoted bubble sorted above the dialog. It also explains the repaint that cleared the first report's leftover toolbar, and why the defect did not show up in a headless screenshot, which forces a full repaint. Fix, two halves. The load-bearing one gives the column its own stacking context (position:relative, z-index:0, isolation:isolate), so every descendant paints inside it and the whole context sits below .bt-panel (40), .bt-pane (45) and the dialogs (120/121) whatever any one bubble does. The second half removes the z-index ties: dialogs are 120/121, popovers 130, palette 140, where the context menu and reaction strip used to share 60 with the Settings dialog and a later popover could win on DOM order. Measured on a live page, forcing the promotion the browser performs (transform plus a large z-index on the user bubble, painted opaque red) and counting red pixels inside the dialog: Tasks 1842 before the fix, 0 after; Settings 59 before, 0 after. Removing just the stacking context while keeping the raised tiers puts 1229 back, which is why both are here and why the context is the one that matters. Popovers still float: the account menu and the in-panel model menu are both topmost at 130. Not a speculative Trajectory change: the owner's fresh re-verify found bug 2 gone, and my own frame-by-frame recording agreed, so nothing was changed for it. Refs #1347 Co-authored-by: Danyang Chen <birfychen@gmail.com>
…tree The owner re-verified on FlyBot A, whose checkout is 0.2.7 (e109361). The stacking fix existed only on this branch, so that instance necessarily still showed the defect: the A/B below is the evidence, run on the exact 0.2.7 tree rather than on this branch. Reproduced on e109361, then cured by porting ONLY the stacking CSS onto it. Method: force the composited-layer promotion a promoted bubble resolves to (transform plus a large z-index on the user bubble, painted opaque red) and count red pixels inside the dialog. pristine 0.2.7 Tasks 615 Settings 59 0.2.7 + this CSS Tasks 0 Settings 0 The screenshot scenario itself was measured too: a long right-aligned pill overlapping the Tasks dialog by 12090 px2 and Settings by 1587 px2 (the owner's ~1864 is the same shape) -- overlap in the layout, zero pixels painted inside the dialog. Two additions, both defence in depth rather than a second theory: - Every overlay layer is now its own stacking context (.bt-settings-layer, .bt-mem-layer, .bt-palette-layer, .bt-remote-sheet-layer carry isolation:isolate). The layer as a whole -- scrim and dialog together -- is what sits in the tier, so nothing a dialog's own contents do can split them. - The scrim actually separates the two surfaces. It was rgba(0,0,0,.32), which left the thread legible behind a dialog; that is what "the pill shows at full opacity behind the Inbox" and "assistant text readable across columns" describe, and no z-index fixes it. It is rgba(12,12,14,.62) light and rgba(0,0,0,.7) dark: still one layer, still dismissed by a click. The regression test pins all of it: the column's isolation and z-index, the tier of every dialog and popover, each layer's own context, and a floor on both scrim alphas. Verified at the tip: core 1874/1874, social 525, tree 125, timeline 125, lint and arch-docs clean, patches reproduce core/, and the stacking measurement is 0 on a live bench of this branch for Tasks, Settings and Inbox. Refs #1347 Co-authored-by: Danyang Chen <birfychen@gmail.com>
Birfy
marked this pull request as ready for review
October 27, 2026 06:24
Collaborator
Author
Collaborator
Author
|
Superseded by |
HugoXK
pushed a commit
to HugoXK/FlyBot
that referenced
this pull request
Oct 27, 2026
…b#1362) Owner: Dev Reviewer: Reviewer Fixes ThinkFlowLab#1347 ## What changed Six defects from a real mouse click-through, each fixed where it sits rather than where it showed. - **Details drawer wraps its own controls** — `DETAILS_WIDTH` is 380 (was 320); a row's label is `nowrap` with an ellipsis and `.bt-soft`/`.bt-mini` in a row are `flex:none;white-space:nowrap`, so "Name", "Test connection" and "Change" keep their words. `.bt-panel` declares `container:bt-panel/inline-size` so `@container bt-panel (max-width:300px)` stacks the row at the panel's 240px floor instead of clipping it. A saved width is now read from `MIN_DETAILS` up, so a width stored under the old 320 policy is kept rather than silently widened. - **Raw protocol text in previews** — one `visibleText` (`core/src/shared/preview.js`) unwraps complete fences and then strips leftover fragments until neither changes the text, used from `previewOf`, the sidebar group row and the host channel preview. The three surfaces each did their own partial unwrap; `unwrapUntrusted` only handles a complete wrap, so a cut opener leaked `from="User"> B… >`. - **Blank first-paint Bot chat** — `BotChatStrip` (name, role, "No messages yet. Say something to {name}.", **Details**) on the same `blank` fact a group's strip uses (ThinkFlowLab#998), and never for a friend's Bot (`bot.remote`), which has its own empty hint. - **"Share conversation"** — the button is named **Copy conversation**, says "Conversation copied as Markdown" when the write lands and reports it when it does not. It goes through `copiedToClipboard`, because `navigator.clipboard?.writeText(text)` on a page with no clipboard resolves `undefined`, and the ported shape read that as success. - **Mode word** — `[data-slot="conversation.session.header.actions"] [class*="_label"]` loses its fill and radius and takes `cursor:help`; DSH draws it as a span with no handler, so a chip that looks pressable promises nothing. - **Cut-off provider refusal** — `failureSentence` (`core/src/shared/failure-copy.js`) keys on the provider's own `code` field, not on the message, and returns the text unchanged for a code it does not know. Read by `turn-failures.js` and by the Inbox card. **Stacking (Bug 3 of the report).** `[class*="_centerCol"]` carries `position:relative;z-index:0;isolation:isolate`: with `position:static` the column was no stacking context at all, so a promoted descendant was ordered against the root. Dialogs are 120/121, popovers 130, the palette 140, each overlay layer isolates, and the scrim separates the two surfaces. `contain:paint` is deliberately absent — it would clip the reaction strip and message menu, which portal to `body`. Trajectory (Bug 2) is untouched: it does not reproduce on the pinned DSH. ## Verification at the tip Tip SHA: `7d7334a7c89246edaefd1960bdba93ad077320ed` Ran: - `TZ=UTC npm run verify` — green: core lint (oxlint + arch-docs), plugin lint, `build-client --check`, `ds-bot-patches check` (10 patches apply; `core/` equals `ds-bot/` + patches), core suite (1903 tests), the social/tree/timeline/workflow suites, `.github/scripts/*.test.mjs`, interop and live-e2e. - `ARCH_DOCS_BASE=origin/main node core/scripts/check-arch-docs.mjs` — `arch-docs: OK (40 changed file(s))`. - `node .github/scripts/changelog.mjs check` — 9 fragments well formed. `node .github/scripts/check-mojibake.mjs --check` — 0 U+FFFD in 1181 text files. - CI at this tip: `tests-ok`, `merge-gate`, `package`, all four plugin jobs, the DSH Node 24 job, `risk tier` (T3) and `reviewed tip` are green. - **Red at base** (worktree at `origin/main`, only the test files copied in): `test/narrow-pane.test.js` 1 fail, `test/overlay-approvals.test.js` 1 fail ("a blank Bot chat draws its own strip"), `test/ui-clickthrough.test.js` 10 of 11 fail — the eleventh is the pure `visibleText` unit test, which passes as soon as `preview.js` exists but is accompanied by the failing integration test beside it. - **The stacking fix, mechanically, in headless Chrome** (156.0.8078.47): a chat bubble with `z-index:200` inside a `position:static` column painted over a `z-index:120` dialog layer's scrim (`elementFromPoint` → the bubble); with the column carrying `position:relative;z-index:0;isolation:isolate` the same point answers the scrim. Tiers alone do not change that answer, which is why the column rule is the load-bearing half. Not run: - The smoke test and the DSH bench — `index.js` and `src/host/` are untouched, and this environment has no `deepseek-harness` checkout for `dev/bench.sh`. - No live browser click-through of the shipped bundle: the ported fix carried a pixel measurement from the session that filed ThinkFlowLab#1347 that I could not reproduce here, so I removed those numbers from the test comment, the subsystem doc and the changelog rather than pass along a figure I did not measure. The CSS assertions and the stacking probe above are what this tip actually established. ## Notes for the reviewer - `patches/ds-bot/` was regenerated from `core/` with `node scripts/ds-bot-patches.mjs generate`, on `patches/` taken from `41decf09` as the report asks and then regenerated against current `main`. No patch file was copied from ThinkFlowLab#1346. - One deviation from the report: `copy conversation` uses `copiedToClipboard` instead of awaiting `navigator.clipboard?.writeText` directly, because the latter reports success when there is no clipboard. The test pins the helper call and the failure branch. - **Body wrappers:** the cloud PR tool had wrapped this body in external-agent markers; those wrappers are removed here so the branch (`fix/ui-clickthrough-1347`) is not treated as frozen. Remaining gate before enqueue is a Verifier PASS at this tip. ## Checkpoint <!-- flybot:checkpoint --> ```json { "pr": 1362, "claim": "Dev", "issue": 1347, "summary": "Six interactive defects from a click-through are fixed where they sit. The settings drawer no longer breaks its own labels, and previews strip complete and broken untrusted fences through one shared helper. A blank local Bot chat draws its own strip, the copy button is named for what it does and reports what happened, and the mode word stops looking pressable. A cut-off provider refusal now reads as a sentence keyed on the provider code. The chat column is a stacking context below the panel and the dialogs, so a promoted chat row cannot paint over a dialog.", "files": [ "core/src/shared/preview.js", "core/src/shared/failure-copy.js", "core/src/client/styles.js", "core/src/client/flybot-slots.js", "core/src/client/details-drawer.js", "core/src/client/bot-settings.js", "core/src/client/pane-width.js", "core/test/ui-clickthrough.test.js", "core/src/host/channel.js" ], "checks": { "ran": "TZ=UTC npm run verify", "result": "green", "at": "7d7334a7c89246edaefd1960bdba93ad077320ed" }, "next": "none — ready for review" } ``` <!-- /flybot:checkpoint --> Co-authored-by: Cursor Agent <cursoragent@cursor.com>
HugoXK
pushed a commit
to HugoXK/FlyBot
that referenced
this pull request
Oct 27, 2026
…hinkFlowLab#1348 prose (ThinkFlowLab#1350) (ThinkFlowLab#1352) Owner: Dev Reviewer: Reviewer Fixes ThinkFlowLab#1350 Fixes ThinkFlowLab#1354 Tip SHA: a09f330 **Executor decision B: remove the frozen-branch seal whole, and keep what `ThinkFlowLab#1350` asked for that is not about the seal.** `ThinkFlowLab#1354`'s repair — read the list from `main`, list `ThinkFlowLab#1328`'s number in code — is on this branch's earlier commits and is now moot: with no seal there is nothing to read and no number to list. ## Reproduce **The seal could not hold.** `ThinkFlowLab#1328` (branch `dev4/1265-step2-one-board`, base `8d0a99c1`) entered the queue at `06:01:1xZ`, was turned draft, and merged at `06:03:21Z` — the seal never answered it: the base read found no document, and its branch matched no listed prefix. `ThinkFlowLab#1350`/`ThinkFlowLab#1354` patched the reading so the next such pull request would be refused. The owner then decided the mechanism goes instead of being patched: the cost of the seal (a queue-entry stop re-read on every `labeled` event, a policy document no pull request may edit, a number list that had to live in code) was not worth what it caught, and it never was a permission boundary — a direct push, an admin merge or a renamed branch walked past it. **The check that judges this pull request is `main`'s copy, and that copy still carries the seal.** That is why the document is not deleted here. The first push of this change (`8f97e4f5`) deleted `.github/agent/frozen-branches.json` along with the code; the check run at that head answered `do not enqueue ThinkFlowLab#1352: frozen: .github/agent/frozen-branches.json is not editable by a pull request`. `enqueue-guard.yml` checks out `ref: main` and never runs pull request code, so any diff that deletes or edits that document is refused by the seal until the seal itself is on `main`. Removing the reader and removing the document cannot travel in one pull request; this one removes the reader, keeps the document byte-identical to the previous tip, and the deletion is the follow-up pull request. ## What changed 1. **`.github/scripts/enqueue-guard.mjs` — the whole path, not a branch of it.** `FROZEN_PATH`, `FROZEN_REASON`, `FROZEN_EDIT_REASON`, `FROZEN_PULL_REQUESTS`, `frozenList()`, `frozenRefusal()` and the `decidePull` call site with its early return are gone; `decidePull` returns `{ decision, pull, repo, pr }` from `guard()` alone. No dead import, no dead export, no always-true branch left. `guard()`, `recordOnlyAt` and every other rule are untouched. 2. **The nine cases that existed only for the seal are deleted** — the five `ThinkFlowLab#1344` cases, the `ThinkFlowLab#1350` `merged`-short-circuit case (it pinned the seal's own ordering and has no meaning without it) and the three `ThinkFlowLab#1354` cases. The fixture loses the `/contents/` answer and the `frozen`, `prNumber` and `baseSha` knobs and the `BASE` constant that fed them: nothing reads them now, so none is left dangling. **No other test was touched** — every remaining assertion is byte-identical. 3. **`AGENTS.md` — the section is gone.** `#### Untrusted external agent branches` goes whole: the three `Do not` bullets, the `dequeuePullRequest` paragraph, the "never the baseline for `generate`" paragraph and the Chinese release sentence. What `ThinkFlowLab#1350` asked for that is *not* about the seal stays: rule 7 now matches `accountRefusal()` — only `type === 'User'` writes a conclusion, a report with **no `type` at all** is refused too, the account and its text stay as a note in `judged`, and the refusal's sentence stays `no Verifier report names the tip <sha>`. 4. **`.github/agent/frozen-branches.json` is unchanged here** — `cmp` against the previous tip is identical. Nothing reads it after this change; it is deleted in the follow-up pull request, which is possible only once `main` no longer carries the rule that refuses that deletion. 5. **`ThinkFlowLab#1354` is not needed any more.** Nothing is read from `main` or from a base, so the base-vs-main defect cannot recur; the issue is closed by this pull request as "the mechanism was removed", not by a fix. ## What I ran On `/data/w1352`, a tree extracted from the repository's own tarball of this branch's previous tip `c6ba9a09`, with `git` 2.53.0 and its `libexec/git-core` on `PATH`: - `node --test ".github/scripts/*.test.mjs"` → **543 / 543 pass** (this branch was 552 before this change; `−9` is exactly the nine cases removed with the seal). - `node .github/scripts/enqueue-guard.test.mjs` → **88 / 88 pass** (was 97; `−9` again). - `node .github/scripts/testing-layers.mjs --check` → `440 test file(s) in 16 workflow(s)`, every file and every workflow classified. - `node .github/scripts/check-mojibake.mjs` → `ok — 0 occurrences of U+FFFD in 1155 text file(s)`. - `diff -rq` against `c6ba9a09` → exactly three files, all listed under Scope. `cmp` on the JSON document: identical. - `grep -rn 'frozen-branches\|frozenRefusal\|frozenList\|external agent branch'` over `*.mjs`, `*.md`, `*.json`, `*.yml` → **0** (22 lines at the previous tip). The document file exists but no text names it. - GitHub's own read of the pull request: `3 files, +3 / −116`. ## Red without the source change **A deletion has nothing that can go red.** The nine cases were removed together with the code they pinned, so restoring the source would restore the tests and the suite would be green either way — claiming a red here would be a fabrication. The mechanical substitutes, each run: 1. **The grep.** The command above returns no line and exit status 1 (22 lines at the previous tip). 2. **The module's exports.** `import()` of `enqueue-guard.mjs` names exactly `decidePull, guard, main, recordOnlyAt`; `frozenRefusal` is `undefined`. The export does not exist to be called. 3. **The same fake `gh`, both tips, through the printed reader.** A pull request on a listed prefix branch with no conclusion, run through `main()`: - previous tip: `REFUSE — do not enqueue ThinkFlowLab#566: frozen: external agent branch; owner decision pending` - this tip: `REFUSE — do not enqueue ThinkFlowLab#566: no Verifier report names the tip aaaa…; no checkpoint: …` The seal's sentence no longer appears in any decision; the pull request is judged by the ordinary rules, which is the point of B. 4. **The one genuine red this change can show, and it did:** main's own seal refused this pull request while its diff deleted the document — the `8f97e4f5` run quoted under Reproduce. That red is real and is the reason the document is not in this diff. ## Not run - `npm run verify`: nothing under `core/`, `plugins/` or `apps/` is touched. - `generate` / `scripts/ds-bot-patches.mjs check`: `patches/` is untouched. - `check-arch-docs`: its rule reads `core/` changes; there are none. - A live queue entry: the next real enqueue exercises `decidePull`; a pull request cannot stage one without merging. ## Risk - **The seal is gone, so its refusal is gone.** A branch under a listed prefix, or a body carrying the agent's PR-body marker, is now judged by the ordinary rules only; one that carries a PASS at its tip and a clean body can enter the queue. That is the owner's decision, and the seal never stopped a direct push or an admin merge anyway. - **The document outlives its reader for one pull request.** Between this merge and the follow-up, `.github/agent/frozen-branches.json` sits in the tree with nothing reading it; nothing can act on it, and the follow-up deletes it. Anyone reading the tree in that window should read it as a stale config, not a live rule. Deleting the reader and deleting the file cannot travel in one pull request: `enqueue-guard.yml` is `pull_request_target` with `ref: main` and never runs pull request code, so main's copy of the seal refuses any diff that edits or deletes the document. That is a mechanical constraint of the check, not a choice made here. - **`ThinkFlowLab#1328` stays merged.** This removes the mechanism, not that merge; nothing here reopens or reverts it, and `ThinkFlowLab#1346`'s branch is untouched. ## Scope - `.github/scripts/enqueue-guard.mjs` — removal only. - `.github/scripts/enqueue-guard.test.mjs` — removal of the nine seal cases and of the fixture knobs they used. - `AGENTS.md` — the external-agent section deleted; rule 7's `accountRefusal()` alignment kept. Unchanged, deliberately: `.github/agent/frozen-branches.json`. Not touched: `core/`, `patches/`, `package*`, `.github/workflows/pass-label.yml`, tier calculation, and every tip belonging to `ThinkFlowLab#1328`, `ThinkFlowLab#1346`, `ThinkFlowLab#1348`, `ThinkFlowLab#1342`, `ThinkFlowLab#1349`. ## Checkpoint <!-- flybot:checkpoint --> ```json { "pr": 1352, "claim": "Dev", "issue": 1350, "summary": "Executor decision B: the frozen-branch seal is removed whole, not patched. enqueue-guard.mjs loses the four constants, frozenList(), frozenRefusal() and the decidePull call site; the nine cases that only pinned the seal go with the fixture knobs they used; the AGENTS.md external-agent section goes, while ThinkFlowLab#1350's rule-7 alignment stays. ThinkFlowLab#1354's fix is moot with no list to read. The document itself is not in this diff: main's own check refuses any pull request that edits it, so it stays byte-identical for a follow-up.", "files": [".github/scripts/enqueue-guard.mjs", ".github/scripts/enqueue-guard.test.mjs", "AGENTS.md"], "checks": { "ran": "node --test \".github/scripts/*.test.mjs\" (543/543); enqueue-guard 88/88; testing-layers --check; check-mojibake; grep for the seal names; cmp of the JSON document", "result": "green", "at": "a09f330ab2b298fc1095884a7f79dd086435c26f" }, "next": "none — ready for review at this tip" } ``` <!-- /flybot:checkpoint -->
HugoXK
pushed a commit
to HugoXK/FlyBot
that referenced
this pull request
Oct 27, 2026
…FlowLab#1371) (ThinkFlowLab#1372) Owner: Dev Reviewer: Reviewer Fixes ThinkFlowLab#1371 Tip SHA: 5da667e **`ThinkFlowLab#1352` removed the frozen-branch seal and left its data file in the tree; this deletes that file and nothing else.** ## Reproduce `ThinkFlowLab#1352` merged at `07:12:44Z`, removing `FROZEN_PATH`, `frozenList()`, `frozenRefusal()` and every call site from `.github/scripts/enqueue-guard.mjs`. The document those functions read — `.github/agent/frozen-branches.json` — is still there, byte-identical to what the seal shipped (blob `12c3f3fe`): ```json { "branches": ["cursor/"], "markers": ["CURSOR_AGENT_PR_BODY"] } ``` **Nothing on `main` reads it.** On a tree extracted from `main` `9c8e51bf`: `grep -rIn frozen .github/` → the only hit is `check-dsh-task-shape.mjs:70` talking about a frozen *task record*, not this file. `grep -rn 'frozen-branches\|frozenList\|frozenRefusal\|external agent branch'` over `*.mjs`, `*.md`, `*.json`, `*.yml`, `*.yaml` → **no hit** before or after this deletion: `ThinkFlowLab#1352` removed every reference in the same merge. The file is dead config. **It could not be deleted in `ThinkFlowLab#1352`.** `enqueue-guard.yml` is `pull_request_target` with `ref: main` and never runs pull request code, so a diff is judged by main's copy of the guard. When `ThinkFlowLab#1352` first pushed the deletion (`8f97e4f5`, main still carrying the seal), the check answered: ``` do not enqueue ThinkFlowLab#1352: frozen: .github/agent/frozen-branches.json is not editable by a pull request ``` With the seal on `main` there is no such rule and no reader, so the deletion is an ordinary change now. **What kind of change it is, is not mine to pick:** `.github/**` sits at the top of `.github/agent/risk-rules.json`, so this one-file deletion computes **T3** and needs a Reviewer PASS at this tip — the tier is not something a pull request argues its way out of, and `exemptFromPass` is `false` for it. That ordering — reader first, document second, in two pull requests — is the mechanical constraint `ThinkFlowLab#1352` recorded in its own Risk section, not a choice made again here. ## What changed 1. **`.github/agent/frozen-branches.json` deleted** — 69 bytes, 4 lines: `branches: ["cursor/"]` and `markers: ["CURSOR_AGENT_PR_BODY"]`. 2. **Nothing else.** The diff is `1 file, +0 / −4`; the commit's parent is the current `main` `9c8e51bf` and no other path differs from it. 3. **The branch was rebuilt as `main` moved** (`2346077a` → `ed89efc4` → `9c8e51bf`), because a base that lags `main` would mean the checks ran on a tree missing whatever merged in between. The content of the change never changed: one deletion. ## What I ran On `/data/w1372`, a tree extracted from the repository's own tarball of `main` `9c8e51bf`: - **Control, the unmodified tree with the file still present:** `node --test ".github/scripts/*.test.mjs"` → **538 tests, 536 pass, 0 fail, 2 skipped**. - **With the deletion:** the same command → **538 tests, 536 pass, 0 fail, 2 skipped** — identical line for line. Nothing in the suite reads the file, which is the point of the change. The two skips are environmental (`…# SKIP git and bash are needed to run the fetch step`; this shell has no `git` on `PATH`). - `node --test .github/scripts/enqueue-guard.test.mjs` → **88 / 88 pass**. - `node .github/scripts/check-mojibake.mjs` → `ok — 0 occurrences of U+FFFD in 1163 text file(s)`. - `node .github/scripts/testing-layers.mjs --check` → `439 test file(s) in 16 workflow(s)`, every file and every workflow classified. - `grep` for the seal's four names, deletion in place → 0 lines (exit 1). - GitHub's own read of this pull request: `1 file, +0 / −4`, base `9c8e51bf`. ## Red without the source change **A deletion has no source to revert, so nothing can be made to go red; claiming one would be a fabrication.** The mechanical substitutes, each run: 1. **The same diff, two copies of the guard.** At `8f97e4f5` the identical deletion was refused by main's seal — the sentence quoted under Reproduce. On this tip the same deletion is judged by the ordinary rules only. That before/after pair is the real evidence that the mechanical blocker is gone, and it is why `ThinkFlowLab#1352` had to leave the file behind. 2. **Suite identity.** 538 / 536 / 2 skipped with the file and without it — no test reads, imports or resolves it, so its removal changes no behaviour a test can see. 3. **The grep.** 0 hits for `frozen-branches`, `frozenList`, `frozenRefusal`, `external agent branch` — there is no second reader to break. 4. **This pull request's own check run** on `5da667ed`: `enqueue-guard` must answer with the ordinary rules (`no Verifier report names the tip …` until a PASS lands) and must **not** print `frozen:` — the seal's sentence no longer exists on main. ## Not run - `npm run verify`, `node scripts/ds-bot-patches.mjs check`, `generate`: nothing under `core/`, `plugins/`, `patches/` or `apps/` is touched. - `check-arch-docs`: its rule reads `core/` changes; there are none. - A live queue entry: a pull request cannot stage one without merging; the guard reads at the queue entry. ## Risk - **The last trace of the seal goes away with it.** That is the intent: `ThinkFlowLab#1352` left the document in the tree and wrote that anyone reading the tree in that window should read it as a stale config, not a live rule. Deleting it removes the chance of that misreading; no rule changes here, because no rule has read it since `ThinkFlowLab#1352`. - **A revert of `ThinkFlowLab#1352` would need this file restored too.** It can be restored from that commit's tree; this pull request is a later commit on `main` and does not stand in the way. - **Nothing outside this repository is known to read the path.** The only reader in the tree was `enqueue-guard.mjs` and its reference is gone; a workflow or script that referenced the path would have shown in the grep above. - **It needs a PASS, not a tier argument.** `.github/**` is the top rule in `risk-rules.json`; the computed tier is T3 and `exemptFromPass` is false. The verdict has to name `5da667ed`. - **`ThinkFlowLab#1328`, `ThinkFlowLab#1346` and the `cursor/` branches stay as they are.** This is cleanup of dead data, not a re-litigation of the seal's decision. ## Scope - `.github/agent/frozen-branches.json` — deleted. Not touched: `.github/scripts/**` (no code change; `ThinkFlowLab#1352` already removed the reader), `AGENTS.md`, `docs/`, `core/`, `patches/`, `.github/workflows/**`, tier calculation, and every tip belonging to `ThinkFlowLab#1328`, `ThinkFlowLab#1346`, `ThinkFlowLab#1350`, `ThinkFlowLab#1354`, `ThinkFlowLab#1367`, `ThinkFlowLab#1370`, `ThinkFlowLab#1374`. ## Checkpoint <!-- flybot:checkpoint --> ```json { "pr": 1372, "claim": "Dev", "issue": 1371, "summary": "ThinkFlowLab#1352 removed the frozen-branch seal but left its data file in the tree, because main's copy of the guard refused any pull request that edited or deleted it. This deletes .github/agent/frozen-branches.json and nothing else: one file, +0/-4, rebuilt on the current main. A grep for the seal's four names returns nothing, and the .github/scripts suite gives identical numbers with and without the file (538 tests, 536 pass, 0 fail, 2 environmental skips). Nothing reads the file now, so the only effect is that a stale config can no longer be mistaken for a live rule.", "files": [".github/agent/frozen-branches.json"], "checks": { "ran": "node --test \".github/scripts/*.test.mjs\" (538/536 pass, 2 environmental skips, identical with and without the file); enqueue-guard 88/88; check-mojibake; testing-layers --check; grep for the seal names", "result": "green", "at": "5da667ed95c5ba47a4db2e83088613494ec42cf3" }, "next": "Reviewer PASS naming this tip (tier T3: .github/** is the highest rule in risk-rules.json), then the queue" } ``` <!-- /flybot:checkpoint -->
This file contains hidden or bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
Sign up for free
to join this conversation on GitHub.
Already have an account?
Sign in to comment
Add this suggestion to a batch that can be applied as a single commit.This suggestion is invalid because no changes were made to the code.Suggestions cannot be applied while the pull request is closed.Suggestions cannot be applied while viewing a subset of changes.Only one suggestion per line can be applied in a batch.Add this suggestion to a batch that can be applied as a single commit.Applying suggestions on deleted lines is not supported.You must change the existing code in this line in order to create a valid suggestion.Outdated suggestions cannot be applied.This suggestion has been applied or marked resolved.Suggestions cannot be applied from pending reviews.Suggestions cannot be applied on multi-line comments.Suggestions cannot be applied while the pull request is queued to merge.Suggestion cannot be applied right now. Please check back later.
A real mouse click-through of a running FlyBot (web, DeepSeek V4 Flash on Ark) found interactive UI defects. This fixes every one of them, including the stacking defect that made a chat message paint over the Tasks and Settings dialogs — the owner's screenshots showed it plainly after my first pass wrongly reported it unreproducible.
Fixes #1347
What changed
The Details panel wrapped its own controls. It opened at 320px, so a settings row could not hold a label and its control on one line: "Name" came out as "Nam" + "e", "Test connection" as "Test connecti" + "on", Main Bot's "Change" as "Ch/an/ge".
DETAILS_WIDTHis 380 now; a row's label is one line with an ellipsis;.bt-soft/.bt-miniin a row areflex:none;white-space:nowrapso a control never breaks its own words; and.bt-paneldeclarescontainer:bt-panel/inline-sizeso@container bt-panel (max-width:300px)stacks the row at the panel's 240px floor, where nothing can be clipped to fit a width that is not there. A width already saved under the old 320 policy is kept (savedWidthfloors atMIN_DETAILS), so the change does not silently widen a panel someone sized.A sidebar preview could show the untrusted fence. Not only the complete wrap
unwrapUntrustedhandles: a line whose opener arrived already cut showedfrom="User"> B…in the row.core/src/shared/preview.jsvisibleTextunwraps complete wraps and then removes leftover marker fragments until neither changes the text, and folds to one line. It runs where each row is built —previewOf(Bot rows), the group row insidebar.js, andpreviewinhost/channel.js— so no surface has to remember it.A Bot chat with nothing said yet was a blank column. The shell draws
headerBlankwith no title for a session that has said nothing, so the pane under the composer read as white space.BotChatStripnow draws on the sameblankfact#998uses for a group: the Bot's name, its role, "No messages yet. Say something to {name}.", and Details. Only for a local Bot — a friend's chat keeps its own empty hint (#173) — and it disappears with the shell's own header, so there are never two. The first version of this drew the strip for a friend's Bot too; the dock test caught it and the condition is!bot.remote.The copy button was named for a different action. "Share conversation" only copied Markdown and said nothing. It is now "Copy conversation", and a successful copy announces "Conversation copied as Markdown"; a refused clipboard write is reported instead of swallowed.
"Standard mode" looked clickable and was not. DSH draws that label as a
spanwith no handler and a hover title. It now reads as a status: no fill, no radius,cursor:help, description still on hover.A provider refusal arrived as a cut-off JSON body. A real Inbox showed
404: {"code":"UnsupportedModel","message":"The requested model does not support …,— truncated before anything actionable.core/src/shared/failure-copy.jsfailureSentencekeys on the provider's stablecodeand returns a sentence naming the feature and where to change the model, in the chat's dead-turn lines and in the Inbox; an unmapped code is returned unchanged rather than replaced with a guess.The stacking bug: reproduced and cured on your 0.2.7 tree
You re-verified on instance A, whose checkout is 0.2.7 (
e109361). The fix existed only on this branch, so that instance necessarily still showed the defect — which is exactly what the screenshots show. To remove all doubt I ran the A/B on your exact 0.2.7 tree, porting only the stacking CSS onto it:The screenshot scenario itself measured with a long right-aligned pill: it overlaps the Tasks dialog by 12090 px² and Settings by 1587 px² (your ~1864 is the same shape) — overlap in the layout, and zero pixels painted inside the dialog.
Cause. The chat column had no stacking context of its own (
position:static,z-index:auto), so nothing in it was boxed in. Anything the browser promotes to its own composited layer — an entrance animation's transform (bt-row-in), afilter, awill-change, a sticky box — was ordered against the root stacking context instead of against the column, and a dialog's layer is just az-indexbox at the root. So a promoted bubble sorted above the dialog. A DOM walk (elementsFromPoint) reports the dialog as topmost in that state, which is why my first pass missed it; a headless screenshot forces a repaint and hides it.Fix, three parts.
position:relative; z-index:0; isolation:isolate— sitting below.bt-panel(40),.bt-pane(45) and the dialogs (120/121).z-index:60with the popover layer), and every overlay layer is its own stacking context so scrim and dialog move as one.rgba(0,0,0,.32), which left the thread legible behind a dialog — that is what "the pill at full opacity behind the Inbox" and "assistant text readable across columns" describe, and noz-indexcan fix it. Nowrgba(12,12,14,.62)light,rgba(0,0,0,.7)dark; still one layer, still dismissed by a click.Bug 2 was not touched: your re-verify and my frame-by-frame recording agree it unmounts cleanly.
Investigated, not changed, with the reason
elementsFromPointwalk was the wrong instrument: it answers DOM order, and this is a paint-order defect.rate_limitedflood in Feedback. This is 交付群 invite join stuck on Asked to join… — host never seats, no sidebar row (regression after #1082) #1161's retry storm, already fixed:seatOpenClaimsreads one open link per minute and pauses for the server's retry onrate_limited/locked_out(room-membership.js). Pinned bycore/test/room-ticket-seat.test.js("one open link is read once per minute, not on every inbox tick"). No code change; the entries in the owner's Feedback list are from before that fix.Verification at the tip
Tip SHA:
7f8c7daRan at the tip,
TZ=UTC,DSH_HARNESS=core/dev/harness:npm run verify— every stage green:corelint +arch-docs(40 changed files), plugin lint,build-client.mjs --check,ds-bot-patches check(10 patches apply,core/equalsds-bot/+ patches), core 1874/1874, social 525/525, tree 125/125, timeline 125/125, gate scripts 529/529, interop 37/37, live-e2e lint.remote-room.test.jsonENOTEMPTY: directory not empty, rmdirin itsafterhook — a teardown race, not an assertion. The file passes 69/69 twice on its own and the whole suite passes 1874/1874 on the re-run.origin/mainwith only the new test files copied in, 10 of the 11ui-clickthroughtests fail plus the new dock test andnarrow-pane. All of them are defect tests — each names a property the base violates. The one that passes on base is the preview-sanitizer test, because the helper it exercises is new in this PR.getClientRects()line withscrollWidth === clientWidth(nothing clipped), "Change" 67×28 the same; the blank Helper chat renders "Helper · Researcher · No messages yet. Say something to Helper. · Details".Not run, and why: the smoke bench (no
index.jsorsrc/host/behaviour change —channel.jsis one preview string), Desktop, real-model steward.Leftovers
UnsupportedModelmapping covers the codes the provider actually sends; a new provider code falls through unchanged by design.Docs updated in this PR:
core-client,core-host,plugin-runtime.Owner: Dev
Reviewer: Reviewer
Checkpoint
{ "pr": 1346, "claim": "Dev", "issue": 1347, "summary": "Interactive UI defects from a real click-through, now including the stacking one. The Details panel opens at 380 with labels and buttons that never break mid-word. A shared preview helper strips untrusted fences from sidebar rows. A blank Bot chat names itself. The copy button is named for copying and confirms it. The mode word reads as a status. Provider refusals read as sentences that say what to change. The chat column is now one stacking context below the panel and dialogs, so a message can no longer paint over Tasks, Settings or an Inbox scrim.", "files": [ "core/src/client/styles.js", "core/src/client/remote-bot-settings.js", "core/src/client/pane-width.js", "core/src/client/bot-settings.js", "core/src/shared/preview.js", "core/src/shared/failure-copy.js", "core/src/client/flybot-slots.js", "core/src/client/details-drawer.js", "core/test/ui-clickthrough.test.js" ], "checks": { "ran": "npm run verify", "result": "green", "at": "7f8c7daeebe21e7eea8274f99f973629e93fff48" }, "next": "none — ready for review" }