feat(#102): in-app sidecar TOML editor (stacked on #101) #104

Merged
the_og merged 2 commits from feat/102 into main 2026-08-13 00:55:21 -04:00
2 Commits
Author SHA1 Message Date
Cowork SupervisorandClaude Opus 4.8 66b0101dea feat(#102): GUI — in-app sidecar editor (pick-lists + raw fallback)
CI / Lint (ruff) (pull_request) Successful in 7s
CI / Tests (py3.10 / ubuntu-latest) (pull_request) Successful in 12s
CI / Tests (py3.12 / windows-latest) (pull_request) Successful in 22s
CI / Tests (py3.12 / ubuntu-latest) (pull_request) Successful in 11s
CI / Tests (py3.13 / ubuntu-latest) (pull_request) Successful in 11s
CI / Catalog signature (pull_request) Successful in 7s
Reached via a new "Edit config…" button beside the sidecar advisory,
shown whenever the selected server has a resolvable sidecar (even before
the file exists, so it can be created from BCC).

SidecarEditorDialog — a minimal, reviewable first pass:
- A section picker (from core.toml_sections), defaulting to [server].
- Pick-lists for the schema enum fields (auth/approvalMode/role) and a
  range-bounded spinner for port — a layperson can't type auth="sshkey".
- A raw-TOML editor showing the full file: the always-available fallback
  for anything the form doesn't model.
- Save applies ONLY the fields the user changed, surgically on top of the
  raw text (core.update_toml), so comments/unknown keys/other sections
  round-trip; validates the changed managed values; writes through
  core.write_sidecar (atomic + backup + chmod 0600). Never touches
  apply_servers. On success it re-runs the read-only advisories (the same
  path #101's watcher uses) so "args inert"/permission advisories update
  live, and confirms the backup + 0600.

All decision logic is in bcc_core (unit-tested); this is thin wiring,
smoke-tested headlessly (QT_QPA_PLATFORM=offscreen): dialog build,
section detection, changed-field diff, surgical save with comment
preserved, 0600 applied, and Edit-button visibility (shown for ssh-mcp,
hidden for plain stdio + remote).

Co-Authored-By: Claude Opus 4.8 (1M context) <noreply@anthropic.com>
2026-08-13 00:21:52 -04:00
Cowork SupervisorandClaude Opus 4.8 c5a6bdd1d1 feat(#102): core — stdlib TOML read/validate/surgical-write + atomic sidecar writer
The pure, fully-tested half of the in-app sidecar editor. No new runtime
dependency: CI's test job installs only `pytest cryptography` (not
requirements.txt) and the catalog-signature job imports bcc_core with only
cryptography, and the workflow is off-limits — so a top-level TOML import is
impossible and any pip TOML dep would leave this code untested/red on CI.

- read_toml_section() — lenient, section-aware scalar reader (string/int/
  float/bool); values it can't confidently decode are omitted (the writer
  preserves them regardless).
- toml_sections() — ordered profile/section groups for the editor's picker.
- set_toml_value() / update_toml() — SURGICAL writer: rewrites only the one
  key it's asked to, so comments, formatting, ordering and unknown keys/tables
  round-trip untouched (strictly safer than parse->dict->reserialize, which
  tomli-w wouldn't comment-preserve either). CRLF-preserving; correct scalar
  quoting/escaping; creates a missing section; deletes on value=None.
- validate_sidecar_values() — enum/port validation against ServerSpec.schema
  for the MANAGED fields only; unknown keys pass through (preserved, never a
  save-blocker) — reconciles "reject out-of-enum" with "preserve unknown keys".
- write_sidecar() — atomic temp-write + os.replace + rotating backup (reuses
  the extracted _atomic_write_text + _make_backup) then chmod 0600/0700 via
  #93's fix_permissions. Never routes through apply_servers (cardinal rule).
- _make_backup() generalised to the file's own suffix (JSON naming unchanged),
  so a .toml sidecar and a .json config keep separate backup pools.

Co-Authored-By: Claude Opus 4.8 (1M context) <noreply@anthropic.com>
2026-08-13 00:18:41 -04:00