Skip to content

trunk-merge/pr-110452/e2121c63-277d-4dc6-be10-e7b1ae327a8a - #110539

Closed
trunk-io[bot] wants to merge 50 commits into
masterfrom
trunk-merge/pr-110452/e2121c63-277d-4dc6-be10-e7b1ae327a8a
Closed

trunk-io[bot] wants to merge 50 commits into
masterfrom
trunk-merge/pr-110452/e2121c63-277d-4dc6-be10-e7b1ae327a8a

Conversation

@trunk-io

@trunk-io trunk-io Bot commented Oct 2, 2026

Copy link
Copy Markdown
Trunk Merge Pull Request Banner

This pull request was created and is being managed by Trunk Merge.

This pull request is based on the master branch at SHA ebd79c1e92a6d57f4c6e7a19c78a136446352858.

See more details about each PR in the batch here:

When CI completes, this pull request will be closed automatically.

Pull Requests Being Tested

This pull request is testing a batch with the changes from pull requests 110452, 110190, and 110255 - batching documentation.

Dependencies

This pull request depends on the changes from pull requests 107531 and 110530.

a-lider and others added 30 commits September 30, 2026 20:21
The pending invite indicator in the account menu moves from the project row to the organization row, and the pending invite list moves from the project switcher to the organization switcher. An invite joins an organization, so the indicator now sits where the invite is accepted.

Generated-By: PostHog Desktop
Task-Id: 3c469151-6420-43b0-8fb4-d290680020ab
The dot now carries a tooltip that names the organization that sent the invite and says where to accept it. The old project button no longer sets its own tooltip, so a single tooltip appears on hover.

Generated-By: PostHog Desktop
Task-Id: 3c469151-6420-43b0-8fb4-d290680020ab
A quarantine hides a story's diff from the gate and the PR comment, so a
PR that changes a quarantined story's stable rendering goes green with
nobody approving the new picture. The default branch keeps the old entry,
and every run fails the day the quarantine is lifted or expires.

- Triage skill: two decide-first rows for quarantined stories a change
  touches, a section on finding them with include_quarantined, and a rule
  not to lift or let expire a quarantine whose entry is broken.
- README: the same check for authors, and the flakiness check before a lift.
- writing-ui-components: point story authors at the check.

Stopgap until the product surfaces these changes itself.
The dot halo no longer spills onto the project name, the tooltip is one
sentence, and the pending invite row in the organization switcher uses
the same logo, alignment and tag as the other organization rows.

Co-Authored-By: Claude Fable 5.1 <noreply@anthropic.com>
- exclude_unchanged drops a quarantined story whose fix renders it
  unchanged, and quarantined_count then counts only changed rows, so
  point to the quarantine list for the fix case.
- A deleted quarantined story leaves its baseline entry behind; only a
  full run classifies it removed and only finalize prunes it.
- broken covers a 7-day window and lags a fix, so a lift decision reads
  the latest default-branch run, not the state alone.
A PR that fixes a quarantined story's flake usually renders the story
exactly as its baseline, so nothing in VR records the fix and the
quarantine stays until someone remembers to lift it by hand.

A reviewer (or agent) can now request a lift on merge from a quarantined
snapshot on a PR run. The request is a durable row, not a RunSnapshot
column, because PR runs get superseded on every push and swept by
retention. It names the exact quarantine event, so a later re-quarantine
of the same story is never lifted by an old request, and the picture
the default branch must render: the baseline for an unchanged snapshot,
the approved hash for an approved change. Requesting a lift never
approves a picture.

Each completed, full default-branch run enqueues a reconcile task only
when the repo has a pending request for its run type. The task asks
GitHub whether the PR merged into that branch and whether the run
contains the merge, then lifts only when the run renders the requested
hash and the baseline entry holds the same hash. The match is exact so a
stale or missing baseline never gets a lift; a later run retries. The
lift records the verifying run's commit as lifted_at_sha, so the
existing commit-scoped lift semantics keep working.

Also:
- passing review statuses now say how many quarantined snapshots
  changed, so a quarantine hiding a change shows up on a green run
- API: POST runs/{id}/lift_on_merge/, GET runs/{id}/quarantine_lifts/,
  POST runs/{id}/quarantine_lifts/{request_id}/cancel/
- MCP tools for request, list and cancel, behind the visual-review flag
- run scene button and request state, README and triage skill updated
- migration 0021 creates the table on the visual_review database
The main use case for lift on merge is a PR that fixes a quarantined
flake, where the story renders `unchanged`. A snapshots listing with
exclude_unchanged leaves that snapshot out, and the full listing holds
thousands of rows, so an agent cannot cheaply find the snapshot UUID.
It always knows the story identifier, and a run holds one snapshot per
identifier, so the lift request now takes `identifier` instead of
`snapshot_id`. Lookup stays scoped to the team and run; an identifier
missing from the run is a 404, same as a missing snapshot before.
…e budget

- Two concurrent lift requests for one PR both found no pending row and
  both inserted, so the second broke the one-pending-request constraint
  and returned a 500. Locking the quarantine row first serializes them,
  in the same lock order the apply step uses.
- retry(exc=e) re-raises e once the budget is spent, so the give-up
  branch never ran and the task failed. Check the budget first.
…letion

The pending deletion page showed the organization switcher only to users
with other organizations. Pending invites now live in that switcher, so
show it when the user has a pending invite too.

Co-Authored-By: Claude Fable 5.1 <noreply@anthropic.com>
…he run scene

- A lift request made under an earlier quarantine of the same story has a
  different quarantine id, so the scene showed it as the active one and
  offered only Cancel. Requests now match the active quarantine row, or
  show as applied history.
- The lift button stays disabled while the PR's lift requests load, so a
  pending request cannot hide behind an enabled button.
- Regenerate the kea logic types the CI drift check expects.
- Cover cancel: the PR's pending request, an applied one, another PR's.
…kill

- The lift check now names a completed default-branch run of the
  quarantine's run type that contains the fix; a pending run or another
  run type proves nothing.
- One changed render of a flaky story is a flake, so re-baselining needs
  the same picture on run after run.
- Follow pagination: quarantined rows are not sorted first.
- run-ci-frontend takes effect on the next push, not when it is added.
A rare flake renders clean most of the time, so one clean default-branch run does not show the fix worked.
- Fail closed on the default-branch check in the lift reconcile. The
  baselines helper falls back to "master" when GitHub errors, so a
  non-default branch named master could lift a quarantine during an
  outage. The new github_api.default_branch_name re-raises rate limits
  (task retries) and returns None on any other failure (requests stay
  pending).
- Accept a lift request when the story was quarantined after the run
  finished. snapshot.is_quarantined is frozen at processing time; the
  live quarantine row is the authority.
- Reset detail to the waiting-for-merge text when a pending request is
  updated, so a stale reconcile message does not stick to a new picture.
- Count quarantined removals in the passing status notice, and word it
  "N quarantined snapshot(s) differ" since removals are not changes.
- Index (repo, pr_number) for the per-PR lift history read. Migration
  0021 is edited in place because it has not merged anywhere.
- Run reconcile_quarantine_lifts with acks_late and
  reject_on_worker_lost like process_run_diffs. The task is idempotent,
  and a lost worker should not drop a lift check.
- Run scene: show only lift requests of the active quarantine. An
  applied request of an ended quarantine showed "Quarantine lifted" for
  a new quarantine of the same story.
- Run scene: keep Cancel busy until the lift list reloads, so the stale
  pending entry cannot be cancelled twice.
- Run scene: when the lift list fails to load, disable the request
  button with a refresh hint instead of acting as if nothing is pending.
- Diff viewer: offer "Accept change" on a quarantined changed/new
  snapshot. The lift button asks for an approval first, and the viewer
  hid the only way to give one. Approve-all and pending counts still
  skip quarantined snapshots.
- Make the lift reachable for a quarantined story that renders
  unchanged, the usual result of a flake fix. The run snapshots endpoint
  takes quarantined_only, and the run scene of a PR run lists the
  quarantined stories that rendered clean; selecting one opens it
  through the deep-link loader.
- README: use the full mounted path of the lift endpoint and mention
  the new listing.
…stream

Slack answers message_not_in_streaming_state when it has closed a stream. The handler now marks the stream ended, skips later appends and the stop call, and posts the final answer as a thread reply. The relay stops dispatching appends and opens a new message for the answer, gated with workflow.patched so recorded histories replay unchanged.

Generated-By: PostHog Desktop
Task-Id: a418769d-0f5e-4910-a08d-80124b52d572
…ches

Generated-By: PostHog Desktop
Task-Id: a418769d-0f5e-4910-a08d-80124b52d572
…ine-lift-on-merge

# Conflicts:
#	products/visual_review/skills/triaging-visual-review-runs/SKILL.md
…r locks

- The apply step now locks the request only if its expected hash is the
  one reconcile verified, so a reviewer who changes the picture mid-check
  cannot get the old verification applied to the new picture.
- A request rechecks the quarantine is still active once its row is
  locked; a lift or re-quarantine can land between lookup and lock.
- An unchanged snapshot qualifies only when it rendered the baseline
  byte for byte. Unchanged also covers tolerated variants.
- Reconcile asks GitHub for the default branch before loading pending
  requests, and skips both when nothing is pending.
- The clean-quarantine list shows loading and error states instead of
  disappearing, since it is the only UI route to the lift for a fix.
A cancel fails when the request was applied or cancelled since the page loaded, so the list reloads to show the current state.
…ream

The closed-stream fallback posted the answer but skipped the chart cards. The stop activity now delivers the attachments that are still pending as their own thread message, after the file attach step, so no file uploads twice.

Generated-By: PostHog Desktop
Task-Id: a418769d-0f5e-4910-a08d-80124b52d572
- The lift create and list MCP tools return snapshot identifiers that a
  pull request's CI supplies, so they now carry the same informational
  wrapper as the other visual review tools.
- Triage skill: a changed quarantined story that a change also fixes
  needs a lift request after its approval, and a lift on merge needs no
  recompute.
…story

TolerateSuggestsQuarantine opens a LemonDialog from its play function. The dialog mounts on its own React root and outlives the story, so it covered the story the test runner rendered next. Keep the dialog story last.
…lift-on-merge

# Conflicts:
#	products/visual_review/README.md
#	products/visual_review/skills/triaging-visual-review-runs/SKILL.md
6 updated, 4 removed
Run: feb50236-da32-4eb9-abfc-f9b4d0f6a0c2

Co-authored-by: a-lider <221966567+a-lider@users.noreply.github.com>
webjunkie and others added 20 commits October 1, 2026 22:15
Moving the lift-on-merge story above the dialog story left it referencing fixtures declared further down. The story object reads them at module load, so the module threw before any story rendered and typecheck failed with used-before-declaration errors.
The test opens the briefing once with a Prague timezone and once with the
project's UTC, and expects the same briefing. A briefing day starts at
eight local time, so between 06:00 and 08:00 UTC the two calls fall on
different days and the test fails for every pull request.

Co-Authored-By: Claude Fable 5.1 <noreply@anthropic.com>
Between 06:00 and 08:00 UTC a call without a timezone reads the project's
briefing day, which is the day before for a person in Prague. The day
boundary test now asserts that at a pinned time.

Co-Authored-By: Claude Fable 5.1 <noreply@anthropic.com>
2 updated
Run: 778b4b14-c676-4966-8297-e05a19aa809d

Co-authored-by: webjunkie <59713+webjunkie@users.noreply.github.com>
Adds the anchors to artifact comments. A pin mode places numbered pins on an image, and they stay in place at every zoom level. Selecting text in rendered markdown or plain text opens a comment box, and commented text gets a highlight that opens its thread.

Generated-By: PostHog Desktop
Task-Id: e2367959-ab88-40ff-8761-5632645167aa
The full page dialog scales in when it opens, so text rects measured during the animation were scaled, and a transform does not trigger the resize observer. Highlights and the pending comment box now divide out the container's scale. Highlights use PostHog Desktop's yellow in both themes, which also makes them easier to see in dark mode.

Generated-By: PostHog Desktop
Task-Id: e2367959-ab88-40ff-8761-5632645167aa
@github-actions

github-actions Bot commented Oct 2, 2026 •

Copy link
Copy Markdown
Contributor

🤖 CI report

⚠️ Django migration SQL — 1 new migration to review

We've detected new migrations on this PR. Review the SQL output for each migration:

products/visual_review/backend/migrations/0021_quarantine_lift_request.py

/opt/hostedtoolcache/Python/3.14.7/x64/lib/python3.14/site-packages/anyio/from_thread.py:119: SyntaxWarning: 'return' in a 'finally' block
  return result
/opt/hostedtoolcache/Python/3.14.7/x64/lib/python3.14/site-packages/structlog/stdlib.py:1166: UserWarning: Remove `format_exc_info` from your processor chain if you want pretty exceptions.
  ed = p(logger, meth_name, ed)  # type: ignore[arg-type]
2026-10-02T07:28:25.587352Z [error    ] Path must be a valid database or directory containing databases. [posthog.exceptions_capture] pid=7931 tid=140022756199296
Traceback (most recent call last):
  File "/home/runner/work/posthog/posthog/posthog/geoip.py", line 15, in <module>
    geoip: Optional[GeoIP2] = GeoIP2(cache=8)
                              ~~~~~~^^^^^^^^^
  File "/opt/hostedtoolcache/Python/3.14.7/x64/lib/python3.14/site-packages/django/contrib/gis/geoip2.py", line 116, in __init__
    raise GeoIP2Exception(
        "Path must be a valid database or directory containing databases."
    )
django.contrib.gis.geoip2.GeoIP2Exception: Path must be a valid database or directory containing databases.
/opt/hostedtoolcache/Python/3.14.7/x64/lib/python3.14/site-packages/sshtunnel.py:1040: SyntaxWarning: 'return' in a 'finally' block
  return (ssh_host,
/opt/hostedtoolcache/Python/3.14.7/x64/lib/python3.14/site-packages/langchain_core/_api/deprecation.py:27: UserWarning: Core Pydantic V1 functionality isn't compatible with Python 3.14 or greater.
  from pydantic.v1.fields import FieldInfo as FieldInfoV1
System check identified some issues:

WARNINGS:
?: (axes.W001) You are using the django-axes cache handler for login attempt tracking. Your cache configuration is however invalid and will not work correctly with django-axes. This can leave security holes in your login systems as attempts are not tracked correctly. Reconfigure settings.AXES_CACHE and settings.CACHES per django-axes configuration documentation.
?: (staticfiles.W004) The directory '/home/runner/work/posthog/posthog/frontend/dist' in the STATICFILES_DIRS setting does not exist.
BEGIN;
--
-- Create model QuarantineLiftRequest
--
-- (no-op)
COMMIT;

Last updated: 2026-10-02 07:28 UTC (954eb79)

✅ Django migration risk — migration analysis complete

We've analyzed your migrations for potential risks.

Summary: 1 Safe | 0 Needs Review | 0 Blocked

✅ Safe

Brief or no lock, backwards compatible

visual_review.0021_quarantine_lift_request
  └─ #1 ✅ CreateModel
     Creating new table is safe
     model: QuarantineLiftRequest
  │
  └──> ℹ️  INFO:
       ℹ️  Skipped operations on newly created tables (empty tables
       don't cause lock contention).

Last updated: 2026-10-02 07:29 UTC (954eb79)

@trunk-io trunk-io Bot closed this Oct 2, 2026
@trunk-io
trunk-io Bot deleted the trunk-merge/pr-110452/e2121c63-277d-4dc6-be10-e7b1ae327a8a branch October 2, 2026 07:32
@trunk-io

trunk-io Bot commented Oct 2, 2026

Copy link
Copy Markdown
Author

Static Badge   Static Badge   Static Badge

View Full Report ↗︎ ⋅ Docs

Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment

Labels

None yet

Projects

None yet

Development

Successfully merging this pull request may close these issues.

5 participants