Reference in New Issue
Block a user
Delete Branch "fix/72-73-load-crash-and-set-loss"
Deleting a branch is permanent. Although the deleted branch may continue to exist for a short time before it actually gets removed, it CANNOT be undone in most cases. Continue?
Two silent-failure bugs found auditing the v1.3.0 features. Both are in the "quietly does the wrong thing" class rather than the "throws something you can act on" class.
Closes #72
Closes #73
#72 — non-object server value crashed the load
extract_serverscalleddict()on every server value. A config that's valid JSON but holds a non-object server takes the app down:Three things made it worse than a normal parse error:
_load_profile's try/except — unhandled traceback, withcurrent_profilealready reassigned butserversnot.That last point is the one that bothered me: a file that's valid JSON but structurally off is precisely what this project exists to handle gracefully.
Fix. Malformed values are preserved verbatim on
ServerEntry.rawand written back untouched on Save, so nothing is silently deleted — the cardinal rule holds.lint_serversnames the offending entry instead of the app dying.rawuses aNO_RAWsentinel rather than defaulting toNone. My first pass usedNoneand my own test caught it:{"mcpServers": {"foo": null}}is legal JSON and a genuine malformed-entry case, soNonehas to mean "the config said null", not "there was nothing here."datastays a dict for every consumer;set_data()retires the raw value when the user edits, so that can't be forgotten at a call site.extract_serversalso moved inside the load guard as defence in depth — a load failure should leave the previous profile intact rather than half-swapping the window.#73 — Merge & save silently discarded named server sets
The stale-file Merge & save path reloads from disk and re-applies the user's servers:
Named sets live under
_bccServerSetsin that same file.apply_serversdoesn't write them, so a set saved during the session was dropped from disk and then from memory — no warning, on the path the user picks because it sounds like the safe one. Same class as the #8 drag-and-drop overwrite.Fix. BCC-authored keys are declared in
BCC_OWNED_KEYSand carried over bycarry_owned_keys, which returns genuinely contested keys so the status line can say "kept your_bccServerSets(the file on disk had a different copy)" rather than picking a side in silence.Declaring the keys in one tuple is the actual fix — the bug was structural, and the next BCC-authored key would have reintroduced it.
One deliberate asymmetry: a key absent locally is left alone on disk. We can't distinguish "user deleted their last set" from "user never had sets and another machine just added some," and silently deleting someone else's data is the worse of the two failures. Documented in the docstring and covered by a test.
Tests
374 passed, 1 skipped (+16 new). Ruff check and format clean.
New coverage: every non-dict shape (
str,int,list,None,bool,float) survives load; only the bad entry is flagged; malformed values round-trip through Save unchanged; editing retiresraw; lint reports malformed alongside normal warnings;carry_owned_keyscarries, detects conflict, deep-copies, and stays one-directional; plus an end-to-end merge test asserting the set survives and unrelated external keys are preserved.Review notes
import copyadded tobcc_corefor the deep copy incarry_owned_keys— without it, later edits to the in-memory set would leak into the written config.bcc.pyneeded aruff formatpass after the edit.