feat(logging)!: make C5 session logging opt-in #89

Merged
rootiest merged 1 commits from feat/c5-logging-opt-in into main 2026-07-27 23:31:12 +00:00
Owner

Summary

Session logging (C5) is the one opinionated category that writes a persistent record of terminal output to disk, and those logs can contain secrets. Silent-by-default is the wrong posture for it.

__fish_config_op_logging now defaults to off. Capture requires an explicit truthy value; the master switch (__fish_config_opinionated) cannot enable it on its own — it remains a master off switch only.

Design spec: docs/superpowers/specs/2026-07-27-c5-logging-default-off-design.md

Implementation

The behavioral change is one branch in functions/__fish_config_op_enabled.fish, placed after the explicit-truthy / explicit-falsy early returns and before the master-switch fallthrough:

# C5 logging is opt-in: it writes terminal output to disk, so an unset or
# unrecognized value means off — the master switch cannot enable it.
if test "$argv[1]" = __fish_config_op_logging
    return 1
end

All five capture components, the .logging_disabled sentinel, the paru/yay wrappers, the Kitty watcher, and the config-settings TUI already route through this guard, so nothing else needed code changes.

Two consequences fall out for free:

  • conf.d/logging-events.fish already runs __fish_config_sync_logging at every shell start, so the first shell after upgrading creates the sentinel and removes the generated ~/.local/bin/paru / ~/.local/bin/yay wrappers. No migration code.
  • conf.d/kitty-watcher-reminder.fish exits early when C5 is off, so fresh installs no longer nag about installing a watcher for a disabled feature. The reminder appears the first time someone opts in — when it's actually useful.

Decisions

  • Guard special case, not a default value set in conf.d. Setting the variable at startup would make it look explicitly disabled in set -U/config-settings, would leave the TUI's three-state OFF/DEFAULT/ON model with no reachable DEFAULT, and would need ordering care against local.fish.
  • Garbage values follow unset. An unrecognized value is not consent, so status 3 lands on off rather than deferring to the master.
  • No config-settings UI change. DEFAULT still means "no variable set; built-in default applies" — that default is just off for this row.
  • No first-run prompt or startup notice. A blocking question in a startup path, or a banner for a one-time event, both outlive their usefulness.

Docs

  • docs/manual/index.md — CAUTION callout kept and retitled SESSION LOGGING IS OPT-IN; body now reads "this configuration can silently record…"; enable/disable bullets swapped. Verified it still renders as a Starlight <Aside> with all four bullets intact (Task #5 wrapped-list hazard avoided).
  • docs/manual/07-customization.md — Minimal Mode preamble, category table, and the whole C5 section reframed to opt-in; sentinel section notes it is present on a fresh install.
  • docs/manual/11-troubleshooting.md — §11.3 retitled Enable or Disable Session Logging, leads with enabling.
  • README.md — overview bullet, > [!CAUTION] block, Session Logging section, and Minimal Mode table/preamble.
  • docs/fish-config.index — retargeted disable-logging, added enable-logging.
  • AGENTS.md — added a "C5 is opt-in (do not 'fix' this)" rule under Opinionated Component Guards so a future agent doesn't refactor the special case back out.
  • docs/fish-config.md regenerated. python3 docs/verify-manual.py43/43 passed (the 8 missing-CATEGORY warnings are pre-existing).

⚠️ Breaking Change

Anyone relying on the previous default loses logging on their next shell start. Re-enable with:

set -U __fish_config_op_logging on

Existing logs in ~/.terminal_history are not touched — only capture stops, and the generated AUR wrappers are removed.

Manual Verification

  • Fresh default is off: set -Ue __fish_config_op_logging; __fish_config_op_enabled __fish_config_op_logging; echo $status1
  • Master cannot enable it: with C5 erased, set -U __fish_config_opinionated 1 → still 1
  • Explicit opt-in works: set -U __fish_config_op_logging on0, and ~/.config/fish/.logging_disabled disappears immediately
  • Explicit off still works: set -U __fish_config_op_logging off1, sentinel present
  • Garbage value is treated as off: set -U __fish_config_op_logging banana1
  • Other five categories unchanged: with everything erased, each returns 0
  • Migration: open a new shell from a previously-logging state → ~/.local/bin/paru and ~/.local/bin/yay are gone, sentinel exists, ~/.terminal_history untouched
  • With C5 on, wrappers regenerate in ~/.local/bin and paru --version still works
  • kitty-logging status reports C5 logging: disabled on defaults, enabled after opting in
  • config-settings Logging row shows DEFAULT on a clean state and steps DEFAULT → ON → OFF correctly, with the sentinel tracking each step
  • Inside Kitty on a fresh default, no watcher-install reminder appears; it returns after set -U __fish_config_op_logging on
  • Inside tmux with C5 on, a new tmux_*.log appears; toggling off stops the pipe-pane in every open shell
  • Docs site: the index page CAUTION renders as a caution <Aside> with all four bullets
## Summary Session logging (C5) is the one opinionated category that writes a persistent record of terminal output to disk, and those logs can contain secrets. Silent-by-default is the wrong posture for it. `__fish_config_op_logging` now defaults to **off**. Capture requires an explicit truthy value; the master switch (`__fish_config_opinionated`) cannot enable it on its own — it remains a master *off* switch only. Design spec: `docs/superpowers/specs/2026-07-27-c5-logging-default-off-design.md` ## Implementation The behavioral change is **one branch** in `functions/__fish_config_op_enabled.fish`, placed after the explicit-truthy / explicit-falsy early returns and before the master-switch fallthrough: ```fish # C5 logging is opt-in: it writes terminal output to disk, so an unset or # unrecognized value means off — the master switch cannot enable it. if test "$argv[1]" = __fish_config_op_logging return 1 end ``` All five capture components, the `.logging_disabled` sentinel, the `paru`/`yay` wrappers, the Kitty watcher, and the `config-settings` TUI already route through this guard, so nothing else needed code changes. Two consequences fall out for free: - `conf.d/logging-events.fish` already runs `__fish_config_sync_logging` at every shell start, so the first shell after upgrading **creates the sentinel** and **removes the generated `~/.local/bin/paru` / `~/.local/bin/yay` wrappers**. No migration code. - `conf.d/kitty-watcher-reminder.fish` exits early when C5 is off, so fresh installs no longer nag about installing a watcher for a disabled feature. The reminder appears the first time someone opts in — when it's actually useful. ### Decisions - **Guard special case, not a default value set in `conf.d`.** Setting the variable at startup would make it *look* explicitly disabled in `set -U`/`config-settings`, would leave the TUI's three-state OFF/DEFAULT/ON model with no reachable DEFAULT, and would need ordering care against `local.fish`. - **Garbage values follow unset.** An unrecognized value is not consent, so status 3 lands on off rather than deferring to the master. - **No `config-settings` UI change.** DEFAULT still means "no variable set; built-in default applies" — that default is just `off` for this row. - **No first-run prompt or startup notice.** A blocking question in a startup path, or a banner for a one-time event, both outlive their usefulness. ## Docs - `docs/manual/index.md` — CAUTION callout kept and retitled **SESSION LOGGING IS OPT-IN**; body now reads "this configuration *can* silently record…"; enable/disable bullets swapped. Verified it still renders as a Starlight `<Aside>` with all four bullets intact (Task #5 wrapped-list hazard avoided). - `docs/manual/07-customization.md` — Minimal Mode preamble, category table, and the whole C5 section reframed to opt-in; sentinel section notes it is present on a fresh install. - `docs/manual/11-troubleshooting.md` — §11.3 retitled *Enable or Disable Session Logging*, leads with enabling. - `README.md` — overview bullet, `> [!CAUTION]` block, Session Logging section, and Minimal Mode table/preamble. - `docs/fish-config.index` — retargeted `disable-logging`, added `enable-logging`. - `AGENTS.md` — added a **"C5 is opt-in (do not 'fix' this)"** rule under Opinionated Component Guards so a future agent doesn't refactor the special case back out. - `docs/fish-config.md` regenerated. `python3 docs/verify-manual.py` → **43/43 passed** (the 8 missing-`CATEGORY` warnings are pre-existing). ## ⚠️ Breaking Change Anyone relying on the previous default loses logging on their next shell start. Re-enable with: ```fish set -U __fish_config_op_logging on ``` Existing logs in `~/.terminal_history` are **not** touched — only capture stops, and the generated AUR wrappers are removed. ## Manual Verification - [x] Fresh default is off: `set -Ue __fish_config_op_logging; __fish_config_op_enabled __fish_config_op_logging; echo $status` → `1` - [x] Master cannot enable it: with C5 erased, `set -U __fish_config_opinionated 1` → still `1` - [x] Explicit opt-in works: `set -U __fish_config_op_logging on` → `0`, and `~/.config/fish/.logging_disabled` disappears immediately - [x] Explicit off still works: `set -U __fish_config_op_logging off` → `1`, sentinel present - [x] Garbage value is treated as off: `set -U __fish_config_op_logging banana` → `1` - [x] Other five categories unchanged: with everything erased, each returns `0` - [x] Migration: open a new shell from a previously-logging state → `~/.local/bin/paru` and `~/.local/bin/yay` are gone, sentinel exists, `~/.terminal_history` untouched - [x] With C5 on, wrappers regenerate in `~/.local/bin` and `paru --version` still works - [x] `kitty-logging status` reports `C5 logging: disabled` on defaults, `enabled` after opting in - [x] `config-settings` Logging row shows `DEFAULT` on a clean state and steps DEFAULT → ON → OFF correctly, with the sentinel tracking each step - [x] Inside Kitty on a fresh default, no watcher-install reminder appears; it returns after `set -U __fish_config_op_logging on` - [x] Inside tmux with C5 on, a new `tmux_*.log` appears; toggling off stops the pipe-pane in every open shell - [x] Docs site: the index page CAUTION renders as a caution `<Aside>` with all four bullets
rootiest added 1 commit 2026-07-27 23:20:33 +00:00
Session logging is the one opinionated category that writes a persistent
record of terminal output to disk, and those logs can contain secrets.
Silent-by-default is the wrong posture for it, so C5 now defaults to off:
__fish_config_op_logging must be set to an explicit truthy value to enable
capture, and the master switch cannot enable it on its own.

Implemented as a single special case in __fish_config_op_enabled, so all
five capture components, the sentinel file, the paru/yay wrappers, the
Kitty watcher, and the config-settings TUI pick it up with no other code
changes. The existing startup sync in conf.d/logging-events.fish
reconciles the sentinel and removes the generated wrappers on the first
shell after upgrading.

BREAKING CHANGE: users relying on the previous default must now run
`set -U __fish_config_op_logging on`. Existing logs in ~/.terminal_history
are left untouched.
rootiest merged commit a690e814eb into main 2026-07-27 23:31:12 +00:00
rootiest deleted branch feat/c5-logging-opt-in 2026-07-27 23:31:12 +00:00
Sign in to join this conversation.