From 7dae5955265d44fc57c448b143edec6f6070006e Mon Sep 17 00:00:00 2001 From: jared Date: Fri, 10 Jul 2026 10:08:17 -0400 Subject: [PATCH] openspec: archive completed add-os-status-plugin change, sync specs to main Co-Authored-By: Claude Fable 5 Claude-Session: https://claude.ai/code/session_018Mb3V8NNzAuns7vgX9A2jU --- .../.openspec.yaml | 0 .../design.md | 0 .../proposal.md | 0 .../specs/status-banner/spec.md | 0 .../specs/status-checks/spec.md | 0 .../2026-07-10-add-os-status-plugin}/tasks.md | 0 openspec/specs/status-banner/spec.md | 51 ++++++++++++ openspec/specs/status-checks/spec.md | 79 +++++++++++++++++++ 8 files changed, 130 insertions(+) rename openspec/changes/{add-os-status-plugin => archive/2026-07-10-add-os-status-plugin}/.openspec.yaml (100%) rename openspec/changes/{add-os-status-plugin => archive/2026-07-10-add-os-status-plugin}/design.md (100%) rename openspec/changes/{add-os-status-plugin => archive/2026-07-10-add-os-status-plugin}/proposal.md (100%) rename openspec/changes/{add-os-status-plugin => archive/2026-07-10-add-os-status-plugin}/specs/status-banner/spec.md (100%) rename openspec/changes/{add-os-status-plugin => archive/2026-07-10-add-os-status-plugin}/specs/status-checks/spec.md (100%) rename openspec/changes/{add-os-status-plugin => archive/2026-07-10-add-os-status-plugin}/tasks.md (100%) create mode 100644 openspec/specs/status-banner/spec.md create mode 100644 openspec/specs/status-checks/spec.md diff --git a/openspec/changes/add-os-status-plugin/.openspec.yaml b/openspec/changes/archive/2026-07-10-add-os-status-plugin/.openspec.yaml similarity index 100% rename from openspec/changes/add-os-status-plugin/.openspec.yaml rename to openspec/changes/archive/2026-07-10-add-os-status-plugin/.openspec.yaml diff --git a/openspec/changes/add-os-status-plugin/design.md b/openspec/changes/archive/2026-07-10-add-os-status-plugin/design.md similarity index 100% rename from openspec/changes/add-os-status-plugin/design.md rename to openspec/changes/archive/2026-07-10-add-os-status-plugin/design.md diff --git a/openspec/changes/add-os-status-plugin/proposal.md b/openspec/changes/archive/2026-07-10-add-os-status-plugin/proposal.md similarity index 100% rename from openspec/changes/add-os-status-plugin/proposal.md rename to openspec/changes/archive/2026-07-10-add-os-status-plugin/proposal.md diff --git a/openspec/changes/add-os-status-plugin/specs/status-banner/spec.md b/openspec/changes/archive/2026-07-10-add-os-status-plugin/specs/status-banner/spec.md similarity index 100% rename from openspec/changes/add-os-status-plugin/specs/status-banner/spec.md rename to openspec/changes/archive/2026-07-10-add-os-status-plugin/specs/status-banner/spec.md diff --git a/openspec/changes/add-os-status-plugin/specs/status-checks/spec.md b/openspec/changes/archive/2026-07-10-add-os-status-plugin/specs/status-checks/spec.md similarity index 100% rename from openspec/changes/add-os-status-plugin/specs/status-checks/spec.md rename to openspec/changes/archive/2026-07-10-add-os-status-plugin/specs/status-checks/spec.md diff --git a/openspec/changes/add-os-status-plugin/tasks.md b/openspec/changes/archive/2026-07-10-add-os-status-plugin/tasks.md similarity index 100% rename from openspec/changes/add-os-status-plugin/tasks.md rename to openspec/changes/archive/2026-07-10-add-os-status-plugin/tasks.md diff --git a/openspec/specs/status-banner/spec.md b/openspec/specs/status-banner/spec.md new file mode 100644 index 0000000..cb3ba2d --- /dev/null +++ b/openspec/specs/status-banner/spec.md @@ -0,0 +1,51 @@ +# status-banner — SessionStart aggregation, silence rules, snooze/suppress state + +## ADDED Requirements + +### Requirement: Single aggregated banner +The os-status SessionStart hook SHALL run all registered checks in-process and emit at most +one warning banner per session, containing one short line per `warn` result with its +corrective action. `note` results SHALL be emitted as individual near-zero-token lines outside +the banner. When every check returns `ok` (and no `note`s exist), the hook SHALL emit nothing. + +#### Scenario: All checks ok +- **WHEN** every registered check returns `ok` +- **THEN** the hook produces no output + +#### Scenario: Multiple warns aggregate +- **WHEN** two or more checks return `warn` +- **THEN** exactly one banner is emitted containing one line per warning + +#### Scenario: Note passes through without banner +- **WHEN** one check returns `note` and all others return `ok` +- **THEN** the note line is emitted and no warning banner appears + +### Requirement: Per-project snooze and suppress for warns +`warn` output SHALL be governed by per-project state in a gitignored `.cc-os/` directory: +each warning is emitted at most once per day (snooze), and a permanent suppress marker +silences a given check's warnings in that project until removed. `note` results SHALL NOT be +subject to snooze or suppress. Outside a git project, project-scoped checks SHALL be skipped +and no state SHALL be written. + +#### Scenario: Warn snoozed same day +- **WHEN** a check's warning was already emitted today in this project +- **THEN** the warning is not emitted again and the banner omits it + +#### Scenario: Permanent suppress +- **WHEN** `.cc-os/` contains a suppress marker for a check +- **THEN** that check's warnings are never emitted in this project while the marker exists + +#### Scenario: Not a git project +- **WHEN** the session starts outside a git project +- **THEN** project-scoped checks are skipped, environment-scoped checks still run, and no + `.cc-os/` directory is created + +### Requirement: Hook safety envelope +The SessionStart hook SHALL complete within its configured timeout, SHALL exit 0 even when +checks warn or fail internally, and SHALL never write to any file outside the project's +`.cc-os/` state directory. + +#### Scenario: Internal failure stays safe +- **WHEN** the checks module itself fails to import or crash-loops +- **THEN** the hook exits 0 with either no output or a single generic warning line, and the + session starts normally diff --git a/openspec/specs/status-checks/spec.md b/openspec/specs/status-checks/spec.md new file mode 100644 index 0000000..0b36338 --- /dev/null +++ b/openspec/specs/status-checks/spec.md @@ -0,0 +1,79 @@ +# status-checks — in-process check contract + initial checks + +## ADDED Requirements + +### Requirement: Uniform in-process check contract +Every status check SHALL be a Python function in the os-status plugin with the signature +`check(ctx) -> CheckResult`, where `ctx` provides the project root (or None outside a git +project) and per-project config, and `CheckResult` carries `status` (`ok` | `note` | `warn`) +and `message` (empty for `ok`). Checks SHALL be registered in a single registry list; adding +a check SHALL require only the function and one registry entry. + +#### Scenario: Check returns ok +- **WHEN** a registered check finds its precondition satisfied and has no informational output +- **THEN** it returns `status: ok` and contributes no output to the session + +#### Scenario: Check failure is isolated +- **WHEN** a registered check raises an exception or exceeds the per-check time budget +- **THEN** the runner records it as `warn` with a generic message naming the check, continues + running the remaining checks, and never blocks or fails the session + +### Requirement: ADR system check preserves os-adr behavior +The `adr_system_present` check SHALL reproduce os-adr's SessionStart behavior: in a git +project with `docs/adr/` present it returns `note` with the existing Eval-B-tuned usage-note +wording verbatim; with `docs/adr/` absent it returns `warn` suggesting init/migrate at most +once per day, permanently silenced by `.os-adr/suppress`; outside a git project it returns +`ok`. + +#### Scenario: ADR system present +- **WHEN** the session starts in a git project containing `docs/adr/` +- **THEN** the check returns `note` whose message is byte-identical to os-adr's current + PRESENT_NOTE wording + +#### Scenario: ADR system absent, not suppressed +- **WHEN** the session starts in a git project without `docs/adr/` and no `.os-adr/suppress` + exists and no suggestion was emitted today +- **THEN** the check returns `warn` naming `/os-adr:init` and `/os-adr:migrate` + +#### Scenario: ADR suggestion suppressed +- **WHEN** `.os-adr/suppress` exists in the project +- **THEN** the check returns `ok` + +### Requirement: Vault hub-note check +The `vault_hub_note_present` check SHALL determine whether the current project has a hub note +in the SecondBrain vault, preferring an explicit hub slug from per-project config over +inference by `project/` facet tag. Missing hub note in a git project SHALL yield `warn` +naming the corrective action; present SHALL yield `ok` with no context injection. + +#### Scenario: Hub note missing +- **WHEN** the session starts in a git project with no matching hub note in the vault +- **THEN** the check returns `warn` telling the user which skill to run to create one + +#### Scenario: Hub note present +- **WHEN** a hub note matching the project exists in the vault +- **THEN** the check returns `ok` and injects nothing + +### Requirement: Subagent model env-override check +The `subagent_model_env_override` check SHALL return `warn` when `CLAUDE_CODE_SUBAGENT_MODEL` +is set in the process environment or present in the `env` block of `~/.claude/settings.json`, +identifying where it was found; otherwise `ok`. This check SHALL run regardless of whether the +cwd is a git project. + +#### Scenario: Override set in settings.json +- **WHEN** `~/.claude/settings.json` contains `CLAUDE_CODE_SUBAGENT_MODEL` in its `env` block +- **THEN** the check returns `warn` naming the variable, its value, and the file it was found in + +#### Scenario: No override +- **WHEN** the variable is absent from both the environment and settings.json +- **THEN** the check returns `ok` + +### Requirement: os-adr SessionStart hook removed atomically +In the same change that ships the `adr_system_present` check, os-adr's own SessionStart hook +entry SHALL be removed from `plugins/os-adr/hooks/hooks.json`, and the cutover SHALL be +verified against the refreshed plugin cache (not only source), such that exactly one component +emits the ADR status per session. + +#### Scenario: No double emission after cutover +- **WHEN** a fresh session starts after `bin/refresh-plugins` with os-status and os-adr both + installed +- **THEN** the ADR usage note or suggestion appears exactly once