2.4 KiB
2.4 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).
- Single banner. At most one
systemMessagewarning banner per session, containing one short line per survivingwarn. Multiple warns never produce multiple banners. - Notes are never suppressed.
noteresults bypass snooze and suppress entirely and are emitted asadditionalContext, not inside the banner. This exists so os-adr's Eval-B-tuned usage note survives conversion unchanged (design D2). - 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.
- Failure isolation. A check that raises or blows its time budget becomes a generic
warnnaming the check; it never hides other checks' results and never leaks exception text into the banner. - 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, never code: the sharedconfigfile at.cc-os/config(ADR-026), and os-status's ownsnooze-<check>/suppress-<check>markers under.cc-os/status/(ADR-027). Reads fall back to the pre-ADR-027 top-level location; the first write migrates and removes the legacy files. Add.cc-os/to the project's.gitignore(one entry covers every cc-os plugin's state). - PRESENT_NOTE / ABSENT_NOTE byte-identical to os-adr.
checks.pycarries verbatim copies of the wording inplugins/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). - Legacy suppress honored. The
adr-system-presentcheck returnsokwhen.os-adr/suppressexists, so projects silenced under the old os-adr hook stay silent. - Convention-shaped seam. Every check keeps the uniform signature
check(ctx) -> CheckResult(status, message)with registration inchecks.REGISTRYonly — so later extraction to per-plugin subprocess checks stays mechanical (design D1).