Summary
In v0.34.4.0 (also reproduced reading master at 0c6fcab), gbrain doctor emits a multi_source_drift recommendation that references two CLI surfaces that don't exist, which can lead an operator to delete the wrong row.
The doctor message
src/commands/doctor.ts:1134-1140 (current master):
N page slug(s) appear at 'default' but NOT at the intended source (e.g., <samples>). Two possible causes: (1) pre-v0.30.3 putPage misroutes; (2) source X never completed initial sync and the default page is unrelated. Verify with 'gbrain sources status', then either re-sync with 'gbrain sync --source <id> --full' or 'gbrain delete <slug>' if the default-source row is the misroute. (A 'gbrain sources rehome' cleanup command is tracked for v0.32.0.)
Two gaps in that advice
1. gbrain delete <slug> has no --source flag
The delete_page op in src/core/operations.ts:897-928 declares only slug as a param. The handler does use ctx.sourceId, but that gets resolved through the 6-tier resolveSourceId chain in makeContext (src/cli.ts:490-507). For an operator running gbrain delete <slug> against a multi-source brain to target the default row specifically, they'd need to know to set GBRAIN_SOURCE=default, drop a .gbrain-source file, chdir to a path-mapped dir, or activate a brain whose default source is default. None of that is mentioned in the doctor message — it reads as if gbrain delete <slug> will target the default-source row by itself.
An operator following the literal advice on a brain whose active source is one of the intended sources will soft-delete the correctly-routed row instead of the misrouted default one.
2. gbrain sources rehome doesn't exist
The parenthetical "(A 'gbrain sources rehome' cleanup command is tracked for v0.32.0.)" — rehome isn't in src/commands/sources.ts subcommand switch (add/list/remove/rename/default/attach/detach/federate/unfederate/archive/restore/purge/archived) on current master, nor in any 0.32.x / 0.34.x / 0.35.x release. So the forward-pointer is stale.
What actually works today
On a fortiumclaw brain reporting 45 drift rows across two isolated sources, running:
gbrain sync --source <intended-source-A> --full
gbrain sync --source <intended-source-B> --full
reconciled all 45 drift rows with 0 hard deletes (the multi_source_drift check went from warn 45 to ok 0). That's the path the doctor's first option points at, and it's the one that worked cleanly — but the second half of the message (gbrain delete / sources rehome) sent us looking for surfaces that didn't exist.
Suggested fixes (any of these would close the gap)
- Option A (docs-only): rewrite the doctor message to drop the
gbrain delete second-option and the sources rehome parenthetical, since the sync --source <id> --full path is sufficient in practice. Add a note that any leftover default rows after re-sync need engine-level intervention.
- Option B (small CLI): add
--source <id> to delete_page's params + cliHints so gbrain delete <slug> --source default works as the message implies, then keep the message as-is.
- Option C (full): implement
gbrain sources rehome <slug> --from default --to <intended> as the parenthetical promises.
Happy to send a PR for Option A or B if it's useful — wanted to file this first so the design call is yours.
Repro context
- gbrain v0.34.4.0, Bun runtime, Debian-stable container
- Multi-source brain, two sources isolated from
default
gbrain doctor reports multi_source_drift warn N referencing the two surfaces above
gbrain delete --help / gbrain sources --help show no --source flag on delete, no rehome subcommand
- Caught while validating a v0.31.3 → v0.34.4.0 upgrade
Summary
In v0.34.4.0 (also reproduced reading
masterat 0c6fcab),gbrain doctoremits amulti_source_driftrecommendation that references two CLI surfaces that don't exist, which can lead an operator to delete the wrong row.The doctor message
src/commands/doctor.ts:1134-1140(current master):Two gaps in that advice
1.
gbrain delete <slug>has no--sourceflagThe
delete_pageop insrc/core/operations.ts:897-928declares onlyslugas a param. The handler does usectx.sourceId, but that gets resolved through the 6-tierresolveSourceIdchain inmakeContext(src/cli.ts:490-507). For an operator runninggbrain delete <slug>against a multi-source brain to target thedefaultrow specifically, they'd need to know to setGBRAIN_SOURCE=default, drop a.gbrain-sourcefile, chdir to a path-mapped dir, or activate a brain whose default source isdefault. None of that is mentioned in the doctor message — it reads as ifgbrain delete <slug>will target the default-source row by itself.An operator following the literal advice on a brain whose active source is one of the intended sources will soft-delete the correctly-routed row instead of the misrouted
defaultone.2.
gbrain sources rehomedoesn't existThe parenthetical "(A 'gbrain sources rehome' cleanup command is tracked for v0.32.0.)" —
rehomeisn't insrc/commands/sources.tssubcommand switch (add/list/remove/rename/default/attach/detach/federate/unfederate/archive/restore/purge/archived) on current master, nor in any 0.32.x / 0.34.x / 0.35.x release. So the forward-pointer is stale.What actually works today
On a fortiumclaw brain reporting 45 drift rows across two isolated sources, running:
reconciled all 45 drift rows with 0 hard deletes (the multi_source_drift check went from
warn 45took 0). That's the path the doctor's first option points at, and it's the one that worked cleanly — but the second half of the message (gbrain delete/sources rehome) sent us looking for surfaces that didn't exist.Suggested fixes (any of these would close the gap)
gbrain deletesecond-option and thesources rehomeparenthetical, since thesync --source <id> --fullpath is sufficient in practice. Add a note that any leftoverdefaultrows after re-sync need engine-level intervention.--source <id>todelete_page'sparams+cliHintssogbrain delete <slug> --source defaultworks as the message implies, then keep the message as-is.gbrain sources rehome <slug> --from default --to <intended>as the parenthetical promises.Happy to send a PR for Option A or B if it's useful — wanted to file this first so the design call is yours.
Repro context
defaultgbrain doctorreportsmulti_source_drift warn Nreferencing the two surfaces abovegbrain delete --help/gbrain sources --helpshow no--sourceflag on delete, norehomesubcommand