feat: rich route-aware Thingtime link previews - #607
Conversation
🤖 Lopu live PR updateStatus: ✅ Resolver attempt finished Current phase: GitHub mergeability refresh is still pending; the detailed result is posted Estimated completion: Done — no further active-work ETA. Time conversion (UTC source)
Los Angeles and Melbourne use their real IANA time zones, so PDT/PST and AEST/AEDT offsets change automatically. Lopu queue and PR pulse
Related PR context
Exact branch pair: Timeline
Technical run details — optional; this comment is the human-facing source of truth. |
|
🤝 Merged No AI resolution was needed by merge time; the branch was updated with a plain merge commit.
Please review the merge commit before relying on it. |
Lopu-Conflict-Resolution: run=33878695508 pr=607
Structural `graphify update` completed (graphify 0.9.4, no semantic credential available). Refreshed by the resolve-pr-conflicts workflow: https://github.com/lopugit/thingtime/actions/runs/33878695508 Lopu-Conflict-Resolution: run=33878695508 pr=607
|
🤖 Branch status still computing. The base branch moved, and GitHub had not finished recomputing whether this PR conflicts or is behind after the detector waited 500s — so no branch update was started this round. The next push or the twice-hourly scheduled sweep (minutes :02/:32) re-checks automatically. Posted by the conflict detector at 07:10 UTC, 2026-09-05; this notice is edited in place on re-checks. |
|
Lopu — reviewed
I made one change — Two things I'd like your call on, neither blocking:
Validation: focused suite 24/24 (twice, with the real Full detail in the review report. |
|
Lopu review — PR #607 (head This head is one commit past Checks are green (build + typecheck ratchet, API suite, CodeQL). I found two things earlier passes missed, and fixed both. 1. I split the post-shaped projection into 2. One preview branch skipped the module's own truncation convention. In Considered and deliberately left alone: Security claims I traced rather than took at face value: the image loader only ever fetches the presigned URL from Validation: The two open questions from my last pass (the Lovely piece of work. The strongest part is that the anonymous projection is shared between the text tags and the image, so the two can't drift, and the comments explain why on the non-obvious calls. Nice to see — Lopu 🦄 |
|
🦄 Lopu review — PR #607 (head Sixth pass on this branch. Rather than restate the previous five, I re-derived the security boundary from source and then went looking only at ground they hadn't covered. Checks: 20 pass / 63 skipping / 3 pending / 0 failing. Nothing to diagnose — the Two changes, both worth defending: 1. While hoisting the shared headers I kept the failure path's deliberately shorter 2. Removed Traced rather than trusted: the anonymous attachment path genuinely fails closed — Left alone deliberately: Validation: Still yours to call, none blocking:
The design decision this all rests on — one anonymous projection shared by the text tags and the image, so the two can't drift — is the right one, and the non-obvious calls all explain why in place. Nice to see — Lopu 🦄 |
|
Lopu review — rich route-aware link previews I compared What I verified rather than assumed
Findings — none blocking
Validation I ran
Nicely done — the suite pins real defect classes (blank cards, tofu glyphs, pill overflow, unbounded bodies) rather than restating the implementation, and the comments carry the reasoning that usually gets lost. The space→tab reformat of |
🤖 Lopu review —
|
|
Lopu — repository review of Read the whole preview stack against No failing checks — everything completed is green; One real defect, fixed in the worktree
Measured on the real renderer — mean RGB-sum of the panel's bottom-right quadrant (>740 ≈ white panel):
Three photos is an ordinary post, so this shipped a visible white square on a real share shape. Fix is a tall-left / stacked-right collage mirroring the existing Worth your call, not blocking
Nice work — the measured-width layout and the pixel-level font assertions are the right way to test this, and they're why the fontless-deploy defect can't come back. |
|
Lopu review — PR #607 (head Ninth pass. Checks are green (nothing failing or cancelled — the Rather than restate the eight passes before me, I re-derived the safety boundary from source and then went hunting on ground they hadn't covered. I found one real defect, with two faces, and it's fixed on this branch. Unrenderable values were taking the slot of renderable onesThe card strips everything the bundled Liberation face can't draw, so resvg never paints a
Both reproduced against the real renderer first. Fixed by choosing from what survives the strip — Deliberately confined to the card: the preview model still carries the emoji, because the OG/Twitter text tags are drawn by the unfurler with its own fonts. Only the PNG is limited to the face we ship — exactly the split your comment at the top of the file already describes. Validation
Verified rather than assumed (no change needed)
Still open from earlier passes (your call, not mine to patch)
This remains lovely work — the suite pins real defect classes rather than restating the implementation, and the comments carry the reasoning that usually evaporates. The bug I found is the kind you only get because the emoji strip exists; it's the seam between it and the layout, not the strip itself. Lopu · Thingtime PR manager · Claude Opus 5 |
|
Lopu review — PR #607 (head Eleventh pass. Checks are green — 23 pass, 63 skipping, 0 failing; the Rather than restate the ten passes before me, I went looking on ground they hadn't covered — the cost of a card rather than its correctness or its ACL. I found one real defect, I measured it, and I deliberately did not patch it. Reasoning below; I'd like your call. A 436 KB attachment costs 1.09 GB of RAM to draw
Measured on this branch's own
Reachability is ordinary rather than exotic: upload that PNG to your own public post. What makes me confident this is a gap rather than a judgement call: Why I left it for you instead of fixing itThe natural fix is a Adding a native dependency to that function is the exact trace hazard this PR already added When you land it, I'd suggest either:
Smaller things, none blocking
What I re-derived from source and accept
ValidationFrom the PR worktree at
No code changes on this branch. 🦄 |
|
Lopu review — Nice piece of work: the shared anonymous projection between the OG tags and the card is the right shape, and the authorization path holds up — One real defect, fixed in the worktree. Decompression bomb → OOM in the public card renderer
Reproduced with a PNG of uniform pixels; both inputs pass every guard in the loader:
Fix:
Same 40000×40000 input, before → after: 7.89 GiB / 20.5 s → 66 MiB / 25 ms. For AVIF I walk the box tree and take the largest Validation: 30 passing / 0 failing on Three for you to judge — I changed none of them
No CodeQL alerts open on this head. No failing checks — the |
|
Lopu review — head I read the full diff and traced every path where this PR turns an unauthenticated request into a data read, an outbound fetch, or a decode. No blocking defect — no change made, and the worktree is left clean. CI is green on this exact head SHA ( What held up under scrutiny
Non-blocking, for a follow-up
ValidationRan the new Nice work — this is unusually well-defended code, and the comments explaining why each bound exists are the reason the review was quick. |
|
Lopu review — Approve. I read every non-generated file in the diff, plus the code the new paths Checks are clean — 22 pass / 63 skipping / 1 pending, and the pending entry is What I verified holds
The tests are the best part — asserting drawn ink instead of PNG magic bytes is Four follow-ups, none blocking — I made no changes
Validation I ran
— Lopu |
🤖 Lopu live PR updateStatus: ✅ Lopu finished — this PR is mergeable Current phase: GitHub verified the published branch result Estimated completion: Done — no further active-work ETA. Time conversion (UTC source)
Los Angeles and Melbourne use their real IANA time zones, so PDT/PST and AEST/AEDT offsets change automatically. Lopu queue and PR pulse
Related PR context
Exact branch pair: Timeline
Technical run details — optional; this comment is the human-facing source of truth. |
|
🤝 Merged No AI resolution was needed by merge time; the branch was updated with a plain merge commit.
Please review the merge commit before relying on it. |
Lopu-Conflict-Resolution: run=34088829197 pr=607 # Conflicts: # graphify-out/snapshots/v1/5ade579f61c50115e225aec6f7fd58535bbe56111ee8a830bceba7f295a448a6/d434f49a12523783144e6eff947d75b2f6c4a1ae0bfc949a759af35ad006814d/GRAPH_REPORT.md # graphify-out/snapshots/v1/5ade579f61c50115e225aec6f7fd58535bbe56111ee8a830bceba7f295a448a6/d434f49a12523783144e6eff947d75b2f6c4a1ae0bfc949a759af35ad006814d/cost.json # graphify-out/snapshots/v1/5ade579f61c50115e225aec6f7fd58535bbe56111ee8a830bceba7f295a448a6/d434f49a12523783144e6eff947d75b2f6c4a1ae0bfc949a759af35ad006814d/graph.json # graphify-out/snapshots/v1/5ade579f61c50115e225aec6f7fd58535bbe56111ee8a830bceba7f295a448a6/d434f49a12523783144e6eff947d75b2f6c4a1ae0bfc949a759af35ad006814d/manifest.json # graphify-out/snapshots/v1/94433d17c176f2bdac5c0a3e90f71417ae106a476d7bd861d5d9b811b7fa25aa/a72fe54e341fcdc9153402f7ce761c58d7f7269bd5a972f94ac68e85ffc25a27/GRAPH_REPORT.md # graphify-out/snapshots/v1/94433d17c176f2bdac5c0a3e90f71417ae106a476d7bd861d5d9b811b7fa25aa/a72fe54e341fcdc9153402f7ce761c58d7f7269bd5a972f94ac68e85ffc25a27/cost.json # graphify-out/snapshots/v1/94433d17c176f2bdac5c0a3e90f71417ae106a476d7bd861d5d9b811b7fa25aa/a72fe54e341fcdc9153402f7ce761c58d7f7269bd5a972f94ac68e85ffc25a27/graph.json # graphify-out/snapshots/v1/94433d17c176f2bdac5c0a3e90f71417ae106a476d7bd861d5d9b811b7fa25aa/a72fe54e341fcdc9153402f7ce761c58d7f7269bd5a972f94ac68e85ffc25a27/manifest.json # graphify-out/snapshots/v1/f7e629902b574fb823945c6fdf643102dc6d2d2a45d808e682ff1d6e0309ad29/9fdf09c60851ff3f5884a59af3930c059b5c85d70b1265a35aab688e61ae68c0/GRAPH_REPORT.md # graphify-out/snapshots/v1/f7e629902b574fb823945c6fdf643102dc6d2d2a45d808e682ff1d6e0309ad29/9fdf09c60851ff3f5884a59af3930c059b5c85d70b1265a35aab688e61ae68c0/cost.json # graphify-out/snapshots/v1/f7e629902b574fb823945c6fdf643102dc6d2d2a45d808e682ff1d6e0309ad29/9fdf09c60851ff3f5884a59af3930c059b5c85d70b1265a35aab688e61ae68c0/graph.json # graphify-out/snapshots/v1/f7e629902b574fb823945c6fdf643102dc6d2d2a45d808e682ff1d6e0309ad29/9fdf09c60851ff3f5884a59af3930c059b5c85d70b1265a35aab688e61ae68c0/manifest.json
Structural `graphify update` completed (graphify 0.9.4, no semantic credential available). Refreshed by the resolve-pr-conflicts workflow: https://github.com/lopugit/thingtime/actions/runs/34088829197 Lopu-Conflict-Resolution: run=34088829197 pr=607
🤖 Lopu live PR updateStatus: 🛠️ Lopu is actively working Current phase: Rebuilding Graphify structure and semantic context Estimated completion: around 08:48 UTC (~10 minutes; adjusted as work moves). Next automatic check-in: within 10 minutes, or sooner when the phase changes. You can stay on this PR; there is no need to find the Actions run. Time conversion (UTC source)
Los Angeles and Melbourne use their real IANA time zones, so PDT/PST and AEST/AEDT offsets change automatically. Lopu queue and PR pulse
Related PR context
Exact branch pair: Timeline
Technical run details — optional; this comment is the human-facing source of truth. |
|
🤝 Merged No AI resolution was needed by merge time; the branch was updated with a plain merge commit.
Please review the merge commit before relying on it. |
Lopu-Conflict-Resolution: run=34097120597 pr=607
Structural `graphify update` completed (graphify 0.9.4, no semantic credential available). Refreshed by the resolve-pr-conflicts workflow: https://github.com/lopugit/thingtime/actions/runs/34097120597 Lopu-Conflict-Resolution: run=34097120597 pr=607
✅ Develop S3 preview ready
ada510cbdevelopThe alias passed the develop bucket CORS preflight and a final live PR/SHA fence.
Generic Vercel Preview deployments use the shared development runtime; this controller adds the stable exact-SHA alias and marker-scoped cleanup.
Summary
Safety
Validation
Note