2026-08-13: The Window That Wasn't LinkedIn

The tab looked like a phishing site. The host was xn-- plus a percent-encoded space plus https. The path was a Google search glued to /sorry. Someone who has spent a year teaching agents not to open random windows is allowed a second of genuine alarm.
It was Jocasta. She was looking for a founder photo. She is not allowed to do that any more.
What the desktop saw
Section titled “What the desktop saw”vc.work.jocastacouncil is a KeepAlive LaunchAgent on the satellite. Every six hours it asks Exa for gaming and spatial-computing funding news, sends each headline to the local 27B through proxyd, and if the score clears seventy it writes a note to Affinity. She is not the Jocasta MCP that reads local SQLite. This job hunts new names.
The photo step was a later idea. Google for {founder} {studio} site:linkedin.com/in/. Parse a profile URL out of the results. Open LinkedIn headed, “to bypass bot detection,” on the Default profile. Save a JPEG that DuckDB never stored.
Google answered with /sorry. The eval output was two lines: the original search, a space, the CAPTCHA URL. Both lines still contained the substring linkedin.com/in/, because that string lived in the query. The agent treated the whole blob as a profile and called agent-browser --headed open on it. Chromium parsed a leading space plus https:// as a punycode host. The window that landed on the desk was Chrome for Testing, not Safari, not the LinkedIn extension.
Same lesion, same day, more than once. The log is a metronome: search, sorry, headed open, Affinity sync anyway.
What failed, and what did not
Section titled “What failed, and what did not”The deal score was fine. Exa news search was fine. Affinity create still ran. The LinkedIn extension did not open anything.
Three checks were missing, and they are the whole bug.
| Check | What the old code did | What it needed |
|---|---|---|
| Is this a URL we asked for? | "linkedin.com/in/" in text | urlparse, host in {linkedin.com, www.linkedin.com}, first path segment in, a slug |
| Did Google actually answer? | Two-second wait, take stdout | A 200 search page is not a /sorry page |
| Does a background job get a window? | --headed on Default | Never |
A substring test against a query you yourself wrote is not a parser. It is a mirror.
The Apple path
Section titled “The Apple path”Background work is invisible. If you cannot see the founder without stealing the screen, you do not see the founder.
portco_sync.py already knew this. Company pages go through Exa with includeDomains: ["linkedin.com"]. No Google. No window. Dealflow now uses the same door for people.
parse_linkedin_profile_url(raw) # https://www.linkedin.com/in/<slug> or Nonefind_founder_linkedin(name, company) # Exa, then parseparse_linkedin_profile_url fails closed on spaces, xn--, any host that is not LinkedIn, and any path that is not /in/<slug>. The sorry-page string from this incident is a unit test. It returns None.
A live Exa call for the founder who triggered the popup returned https://www.linkedin.com/in/<slug> with no browser. That URL is what Affinity gets as linkedin_url. If Exa misses, the person is still created. There is no second try through Chrome.
The JPEG path is gone. The photo was never in the CRM row.
How to operate it
Section titled “How to operate it”| Piece | Value |
|---|---|
| Code | ~/Projects/jocasta-council/dealflow_agent.py |
| Agent | vc.work.jocastacouncil |
| Cadence | six hours, KeepAlive |
| LinkedIn lookup | Exa includeDomains=["linkedin.com"] |
| Allowlist | https://www.linkedin.com/in/<slug> only |
| Eval seat | council-code via proxyd mTLS |
| Affinity | find-or-create, exact name |
| Browser | none |
python3 ~/Projects/jocasta-council/test_linkedin_url.pylaunchctl print gui/$(id -u)/vc.work.jocastacouncilpgrep -lf agent-browser # must be empty while she scansWhat is still honest
Section titled “What is still honest”The eval seat is council-code through proxyd mTLS (canary client cert). Five JSON fields do not get the 27B. A missing work-lane Affinity key (work-affinity-api-key) logs and skips CRM writes; it does not open a window. portco_sync no longer invents linkedin.com/company/{slug} when Exa misses — it skips. One DuckDB row and one Affinity note per company per calendar day. Org and person are find-or-create on exact name.
Jocasta can keep reading the news. She does not get the glass.