Chain · Hiring — the first application, not the product

Updated · View the entry on sijie.xyz ↗

L0 · Vision

boundaries — hiring is an application on the foundation, explicitly NOT the product. transaction-needs-difference — a transaction needs difference; the résumé is lossy compression into an HR-parseable format; StandMeet's job is to put the difference back. dont-repeat-myself — the job story told 5–15 times across 30–50 interviews.

L1 · Promise

In the hiring transaction, the owner's specific, provable, opinionated detail reaches the recruiter — via QR on the résumé into a role-framed conversation, and via an owner-side outbound loop.

L2 · Requirements (journeys & features)

The owner's job/resume/application journeys and the cross-actor closed loop: recruiter scans the QR → lands /<handle>?code=… → the code is absorbed and held (defer-issue: the session is only issued after the visitor picks a name — deliberately not auto-start). Feature surfaces: the Jobs tools (jobs.fetch_new, 18 source kinds — backend/internal/owner/jobs/fetch/jobfetch.go:36-63, asserted by e2e/test/admin-sources.spec.ts:26-30; six more on 2026-09-02 (7dd19527b) incl. a generic schema.org JSON-LD ingester, a generic RSS adapter + seeded default aggregators on 2026-09-04 (d235f9817)), Resume (resume.draft/update_draft/discard_draft; since 2026-09-07 a visual Puck composer on /admin/edit-resume/[id] — 756c0eb1d, app/src/components/admin/composer/PuckResumeEditor.tsx — and the PDF drawn from the same Puck config through gotenberg's Chromium at /print/application/<id> — 1b1ebed2b, backend/cmd/server/boot_pdf.go), applications.commit; each code carries its own landing path /c/<slug> (c6c54ce88, 2026-09-06, app/src/app/c/[slug]/page.tsx, access/entity/access_code.go:85) and its string can be rotated for leak recovery (codes.rotate, 505b3fc4f, access/repo/codes_rotate.go; admin modal 6ed1759bb); admin Applications (searchable by company / role / status — af263d4eb, 2026-09-05) + Sources + Listings.

L3 · Design decisions

The job-loop design (built; docs/design/job-loop.md is the record): the state/reasoning split (StandMeet = state holder, Claude = reasoning via Playwright MCP — an MCP server on the owner's Claude side, neither of our two planes, confusables); AccessCode = invitation, unified; mandatory staging (draft → preview → owner nod → commit — never "Claude sends directly"); QR top-right pointing at <public_url>/?code=<code> (jobsuc/applications.go:317-322), no /gate interstitial; history.replaceState strips ?code (app/src/lib/gate/use-absorb-code.ts); an invalid code lands on /gate (230a17025); the draft snapshots the job row. One renderer: a Typst renderer with owner-selectable templates was added 2026-09-01 (340ffabf9) and removed 2026-09-07 (1b1ebed2b) — Puck draws both the editor canvas and the PDF, so preview and print cannot diverge. IDEAS.md backlog: resume=git model (git vocabulary dropped from UI, 2026-05-28), application bundles, bullet↔wiki backlinks.

L4 · Engineering artifacts

backend/internal/owner/jobs/ — a domain module (fetch / dedup / cache / jobsuc / jobsmcp / jobsadmin / printsess), tables job_sources / job_fingerprints / resume_drafts / applications (code_bookings is gone — the booker owns per-code booking quota, b73c932bb, 2026-07-25); printsess + gotenberg (PDF, boot_pdf.go); mock-stack job-board fake upstream.

L5 · Verification

E2e [✓ applications-commit, -qr-works, -playwright-hint], [✓ qr-code-absorb], coded-landing-slug, applications-search, job-fetch-rss, the resume-composer-* / resume-pdf-render / resume-look / composer-pdf-fidelity estate (e2e/test/); booking regression suite.

Status & gaps

The job-loop phases are built (jobs / resume / applications / QR → coded landing live; no calendar hook exists — next_event_at appears nowhere in the backend at 36789537d); the mandatory-staging discipline is the chain's own safe-recursion gate — owner nod before anything leaves. Boundary risk to watch: this is the easiest chain to over-invest in against boundaries' own warning.

Related notes