Work log — 2026-04-03
What shipped today
The biggest feature was manual briefing mode (#661) — a prospect-driven request that landed fully in one pass. Users can now toggle between auto and manual briefing in settings. In manual mode, the articles page shows checkboxes on each card with a “generate briefing” button that queues a briefing from the selected articles. The engine’s briefing_generate handler accepts optional article_ids in the payload and skips the auto-scoring query when present. Selection state persists in localStorage across page navigation.
Three onboarding improvements shipped from the decomposition of #660. File upload (#663) lets users upload .txt or .docx files on onboarding step 1 — text files are read client-side via FileReader, Word documents are sent to a server action using mammoth for extraction. Both append to the interests textarea. LinkedIn profile URL (#665) added a simple URL field stored in preferences JSONB, visible in the admin user detail page for manual Claude cowork review. Both avoid database migrations by using the existing preferences JSONB column.
Housekeeping: the engine/uv.lock drift (#662) that had been carrying over for 3 sessions was finally committed — 387 lines of MCP server dependencies that were clearly intentional but never staged.
Also set up Slack bot posting: the Eli bot token is now in .env and tested. Read via MCP plugin (Paul’s account), write via bot token (Eli bot identity).
Completed
- #661 — Re-add curated hand-picked briefing option alongside auto briefing
- #662 — Commit or reset engine/uv.lock drift
- #663 — Onboarding: file upload (text/docx) to populate interest profile
- #665 — Onboarding: LinkedIn profile field for manual review
- #660 — Onboarding: upload existing content or review LinkedIn to populate profile (decomposed into #663, #664, #665)
Carry-over
- needs-clarification (2): #664 (URL import — architecture question about AI summarization without engine), #659 (white-label briefings — needs product direction on what “white-label” means technically)
- backlog (7): Sentry errors (#593, #546), future product ideas (#484, #482, #481, #480, #471, #64)
Risks
None new. The mammoth dependency adds ~1MB to the web bundle but is dynamically imported (server-side only), so no client impact.
Flags and watch-outs
- #664 surfaced an architectural gap: the web app has no AI calling infrastructure. All Claude calls go through the engine’s async command pipeline. Any feature needing synchronous AI responses from the web layer will hit this — it’s a design decision, not a bug.
- The Sentry issues #593 and #546 are still in backlog with real production events. Worth a scout pass to investigate.
- Slack bot token (
SLACK_BOT_TOKEN) is in.env— remember to add it to Vercel env vars if Eli needs to post from production.
Next session
- Run /scout — all queues are empty and milestones complete, good time for a deep sweep
- Investigate Sentry #593 and #546 — carried over from last session, real production errors worth diagnosing
- Check #664 and #659 — Paul may have responded with product direction on the URL import architecture and white-label spec
Why customer tools are organized wrong
This article reveals a fundamental flaw in how customer support tools are designed—organizing by interaction type instead of by customer—and explains why this fragmentation wastes time and obscures the full picture you need to help users effectively.
Infrastructure shapes thought
The tools you build determine what kinds of thinking become possible. On infrastructure, friction, and building deliberately for thought rather than just throughput.
Server-side dashboard architecture: Why moving data fetching off the browser changes everything
How choosing server-side rendering solved security, CORS, and credential management problems I didn't know I had.
The work of being available now
A book on AI, judgment, and staying human at work.
The practice of work in progress
Practical essays on how work actually gets done.
The inbox nobody reads is the one that matters
Every organization has a monitoring system that works perfectly and reports to nobody. The gap between having information and acting on it is where most failures actually live.
The best customers are the first ones you turn against
Every subscription makes a bet that most customers won't use what they're paying for. The customer who closes that gap becomes a problem to be managed.
Delegation without comprehension is just prayer
The organizations that survive won't be the ones that automated the most. They'll be the ones that figured out what to stop delegating.