cc-os/plugins/os-status/invariants.md

2.1 KiB

os-status behavioral invariants

Reversion protection for the SessionStart status hook. Any change that breaks one of these is a regression, not a refactor. Enforced by tests/hook_test.py (model-free; python3 tests/hook_test.py).

  1. Single banner. At most one systemMessage warning banner per session, containing one short line per surviving warn. Multiple warns never produce multiple banners.
  2. Notes are never suppressed. note results bypass snooze and suppress entirely and are emitted as additionalContext, not inside the banner. This exists so os-adr's Eval-B-tuned usage note survives conversion unchanged (design D2).
  3. Exit 0, always. The hook exits 0 on every path — checks warning, checks raising, the checks module failing to import, malformed settings.json, no git project. A session is never blocked by os-status.
  4. Failure isolation. A check that raises or blows its time budget becomes a generic warn naming the check; it never hides other checks' results and never leaks exception text into the banner.
  5. State only in .cc-os/. The hook writes nothing outside the project's .cc-os/ directory, and writes nothing at all outside a git project. .cc-os/ holds state (config, snooze-<check>, suppress-<check>), never code. Add .cc-os/ to the project's .gitignore.
  6. PRESENT_NOTE / ABSENT_NOTE byte-identical to os-adr. checks.py carries verbatim copies of the wording in plugins/os-adr/hooks/session_start.py (the wording source of record, tuned by the Eval B campaign and validated by Eval C). Never paraphrase; if the wording changes there, copy it here byte-for-byte (the test compares the two files).
  7. Legacy suppress honored. The adr-system-present check returns ok when .os-adr/suppress exists, so projects silenced under the old os-adr hook stay silent.
  8. Convention-shaped seam. Every check keeps the uniform signature check(ctx) -> CheckResult(status, message) with registration in checks.REGISTRY only — so later extraction to per-plugin subprocess checks stays mechanical (design D1).