Skip to content

Search asks the corpus, and an install cannot go missing - #141

Merged
wschenk merged 2 commits into
mainfrom
claude/desktop-feature-deploy-loop-sqwp25
Aug 5, 2026
Merged

Search asks the corpus, and an install cannot go missing#141
wschenk merged 2 commits into
mainfrom
claude/desktop-feature-deploy-loop-sqwp25

Conversation

@wschenk

@wschenk wschenk commented Aug 4, 2026

Copy link
Copy Markdown
Contributor

Summary

Two reports from the same message: search finding nothing, and the install banner showing "just a stupid stylized box" instead of a real prompt.

Search asks the corpus, not just this device

The mechanism worked — I tested it at phone width and results, snippets, and report-only matches all render. What it searched was the problem.

The desk searches what it holds, and what it holds is what it cached. A report the phone never opened is not in that, so the same query answers differently on two devices of one walker — and on a phone used mostly for capturing, it answers with almost nothing.

/api/search asks the server, which has every Capture and every report. Results the device already found are dropped; the rest render under "Found on the server" with the line they matched on. A corpus that cannot be reached — offline, or a failing query — leaves the device's own search exactly as it was.

Substring matching, deliberately. It finds the words you type. Nothing here embeds the query; this is not semantic search, and the embedding index is not consulted.

Answers carry the query that asked for them, so the previous query's hits never flash under the current one — and nothing has to be cleared in an effect.

The manifest pins the app's identity

Follow-up detail from the walker: Chrome says it is installed, but no shortcut reached the launcher. That is the whole explanation for the "stylized box" — Chrome never fires beforeinstallprompt for an app it believes is already installed, so the component only ever had its fallback copy to show. The banner was not broken; it was correct about a browser that had stopped offering.

The served manifest had no id. Without one, Chrome derives app identity from start_url, so anything that changes how the app is reached can strand it holding a record of an app that is installed while the launcher has no icon for it. id: "/" pins it — matching the current start_url, so existing installs keep the identity they already have.

This does not repair a device already in that state; Chrome's record is its own. So the fallback copy now says how to get out of it: uninstall through Android Settings → Apps, then clear the site under Chrome → Settings → Site settings.

No-ticket: true

Test plan

  • tests/desk-search-corpus.spec.ts (pixel-9) — a Thread only the server knows about appears with its title, snippet, and link; a Thread the device already found is never listed twice; a corpus that 500s leaves the local results untouched
  • tests/foundation.spec.ts — 4 passed; the start_url: "/" pin still holds with id added
  • pnpm typecheck clean; pnpm test — 348 passed, 1 failed (trash-repository.spec.ts, Neon-backed, pre-existing), 10 skipped
  • pnpm lint — 7 errors, identical to main; none added

What I did not do, and why

I also changed start_url from / to /offline, because / answers 307 → /sign-in for a signed-out browser, and the service worker refuses to cache a redirected response. I reverted it. tests/foundation.spec.ts pins start_url: "/" as a deliberate contract, and I had no evidence that a same-origin redirect is what stops Chrome firing beforeinstallprompt — changing a pinned decision on a guess is not a fix. The redirect is still worth a look on its own merits (an installed app launching at a URL the SW cannot cache will fail offline), but that is a separate, evidenced change.

Everything else about installability checks out from here: /manifest.webmanifest serves 200 with purpose: "any" icons at 192 and 512; both icons are real PNGs of exactly those dimensions and serve 200; /sw.js serves 200 and registers at scope / with a fetch handler; and the install step is already defensive about redirected shell entries.

The desk searches what it holds, and what it holds is what it cached. A
report the phone never opened is not in that, so the same query answers
differently on two devices of one walker — and on a phone that has mostly
been used for capturing, it answers with almost nothing. That is the
whole reason search looks empty.

/api/search asks the server, which has every Capture and every report.
Results the device already found are dropped; the rest render under
"Found on the server" with the line they matched on. A corpus that
cannot be reached — offline, or a query that fails — leaves the device's
own search exactly as it was.

Substring matching, deliberately: it finds the words the walker types.
Nothing here embeds the query, and it is not semantic search.

Answers carry the query that asked for them, so the last query's hits
never flash under this one, and nothing has to be cleared in an effect.

No-ticket: true
@vercel

vercel Bot commented Aug 4, 2026

Copy link
Copy Markdown

The latest updates on your projects. Learn more about Vercel for GitHub.

Project Deployment Actions Updated (UTC)
walking-thoughts Ready Ready Preview Aug 5, 2026 9:04am

Request Review

Reported: Chrome says Walking Thoughts is installed, but no icon reached
the launcher — and the install banner shows its manual fallback forever,
because Chrome never fires beforeinstallprompt for an app it believes is
already there.

The manifest had no `id`, so Chrome derived the app's identity from
start_url. Anything that changes how the app is reached can then leave
Chrome holding a record of an app that is installed while Android has no
icon for it, with no way back through the browser. `id: "/"` states the
identity outright, matching the current start_url so existing installs
keep the one they already have.

This does not repair a device already in that state — Chrome's record is
its own — so the banner's fallback now says how to get out of it:
uninstall through Android Settings, then clear the site in Chrome.

No-ticket: true
@wschenk wschenk changed the title Search asks the corpus, not just this device Search asks the corpus, and an install cannot go missing Aug 5, 2026
@wschenk
wschenk merged commit 9bb3908 into main Aug 5, 2026
4 checks passed
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.

2 participants