Skip to content

feat: prove the URL path end to end, and give it a UI - #23

Merged
ralyodio merged 1 commit into
mainfrom
feat/crawl-e2e
Aug 13, 2026
Merged

ralyodio merged 1 commit into
mainfrom
feat/crawl-e2e

Conversation

@ralyodio

Copy link
Copy Markdown
Contributor

feat: prove the URL path end to end, and give it a UI

Three things: a seam test, the bug it found, and the form that makes any
of this reachable by a human.

The seam test. Every piece of the URL-first path had unit tests and none
of them proved the pieces compose, so crawl_site moves out of the
server's tick into packages/pipeline/src/crawl.ts — a seam nothing can
call is a seam nothing can test. crawl.test.ts then drives the real
queue, the real handler and the real chain, and asserts a URL goes in and
a person, a score and a recommendation come out.

The bug it found. upsertPerson deduped only on GitHub's numeric
platform id, which a crawl never has: a company page gives
github.com/alexchen, not the id. Every re-crawl of the same site
therefore created a fresh copy of everyone on it. It now matches on the
platform id first and falls back to the handle. Handles are renameable
and a freed-and-reused handle could match the wrong person, which is why
the original avoided them — but that only compares against handles
already linked to somebody with evidence, and the alternative was
guaranteed duplicates on every crawl. Corrupting the queue beats risking
it, so the fallback stays.

The UI. AddByUrl on /prospects: one URL per line up to a hundred,
posting to by-url and then polling batches/:id with a progress bar.
It lists only the failures — ninety-nine successes are noise, and the
failures are the reason anyone opens it. The GitHub handle form stays
below it for the developer-tooling wedge.

Ran live against stripe.com and vercel.com through the HTTP API on a
local stack: 202 with a batch id, the duplicate deduped by host, an
ftp:// entry rejected, both jobs claimed and completed in one tick,
Stripe and Vercel identified from json-ld and links.

Both produced zero people. That is the honest result and not a defect:
homepages describe companies rather than naming individuals, and the
model half that would read the prose is capped until 2026-09-01. The
mechanism is proven; the yield is not, and will not be until a working
key exists.

Co-Authored-By: Claude Opus 5 (1M context) noreply@anthropic.com

Three things: a seam test, the bug it found, and the form that makes any
of this reachable by a human.

The seam test. Every piece of the URL-first path had unit tests and none
of them proved the pieces compose, so `crawl_site` moves out of the
server's tick into `packages/pipeline/src/crawl.ts` — a seam nothing can
call is a seam nothing can test. `crawl.test.ts` then drives the real
queue, the real handler and the real chain, and asserts a URL goes in and
a person, a score and a recommendation come out.

The bug it found. `upsertPerson` deduped only on GitHub's numeric
platform id, which a crawl never has: a company page gives
`github.com/alexchen`, not the id. Every re-crawl of the same site
therefore created a fresh copy of everyone on it. It now matches on the
platform id first and falls back to the handle. Handles are renameable
and a freed-and-reused handle could match the wrong person, which is why
the original avoided them — but that only compares against handles
already linked to somebody with evidence, and the alternative was
guaranteed duplicates on every crawl. Corrupting the queue beats risking
it, so the fallback stays.

The UI. `AddByUrl` on /prospects: one URL per line up to a hundred,
posting to `by-url` and then polling `batches/:id` with a progress bar.
It lists only the failures — ninety-nine successes are noise, and the
failures are the reason anyone opens it. The GitHub handle form stays
below it for the developer-tooling wedge.

Ran live against stripe.com and vercel.com through the HTTP API on a
local stack: 202 with a batch id, the duplicate deduped by host, an
`ftp://` entry rejected, both jobs claimed and completed in one tick,
`Stripe` and `Vercel` identified from json-ld and links.

Both produced zero people. That is the honest result and not a defect:
homepages describe companies rather than naming individuals, and the
model half that would read the prose is capped until 2026-09-01. The
mechanism is proven; the yield is not, and will not be until a working
key exists.

Co-Authored-By: Claude Opus 5 (1M context) <noreply@anthropic.com>
@ralyodio
ralyodio merged commit 039caf4 into main Aug 13, 2026
4 checks passed
@ralyodio
ralyodio deleted the feat/crawl-e2e branch August 16, 2026 17:33
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.

1 participant