Part of #5.
The check measures the wrong subject, and it does so precisely when something is wrong.
What is there today
runChecks prefers the watcher's heartbeat, but when the heartbeat is missing or older than two
minutes (app/Uplink/doctor.ts#L51, #L97) it falls back to opening chat.db from the doctor process
itself and, on success, reports
{ name: 'Reading Messages', ok: true, detail: 'this process can read chat.db ...' }
(app/Uplink/doctor.ts#L109).
That fallback fires exactly when the service is not running or not beating, which is exactly when
something is wrong. And the subject is Terminal, not Uplink.app: the README tells people to grant Full
Disk Access to their terminal for buddy uplink:watch (README.md#L104), so on a developer's Mac the
fallback almost always passes while the app itself may have no grant at all.
There is a second, smaller version of the same problem in the same file. ClaudeEngine deliberately
removes an empty CLAUDE_CODE_OAUTH_TOKEN from the environment, with the reason in a comment at
app/Uplink/engine.ts#L89: a .env copied from .env.example carries CLAUDE_CODE_OAUTH_TOKEN= and
an empty token must not stand in for the CLI's own login. claudeAuth does not do this: it spawns with
no env option at all (app/Uplink/doctor.ts#L61), so it inherits the empty value verbatim. That is
the default state of a fresh install, because prepareApp copies .env.example to .env
(app/Commands/Uplink.ts#L54).
Proposal
- When there is no fresh heartbeat, say that. "The watcher is not running, so this was not checked" is honest; a green tick earned by the wrong process is not.
- If the fallback read is kept as useful information, label it as what it is: this process can read
chat.db, which says nothing about Uplink.app. Do not let it set
ok: trueon the check the person reads as "Uplink can read Messages". - Apply the same empty-token sanitization
ClaudeEnginedoes, inclaudeAuth.
Requirements
- A check's subject must be the thing that will do the work. The heartbeat is the only witness to what the watcher can read.
- Do not make the doctor useless when the service is down. Report the service as the problem, and say what to run.
- The empty-token fix must match the engine's behaviour exactly, so the doctor and a real run agree.
Acceptance
- With the service stopped and Terminal holding Full Disk Access, the check does not report green.
- With a fresh
.envfrom.env.exampleand a logged-in CLI, the Claude check passes. - The dashboard, which shares these checks (
app/Uplink/dashboard.ts), shows the same answer.