5.5 KiB
WS3 — per-plugin SessionStart status-check convention + glue plugin
Created: 2026-07-06. Status: proposed. Prereq: none (parallel with WS1). See
2026-07-06-plugin-evals-overview.md.
Goal
A convention-over-configuration status system: at SessionStart, every installed cc-os plugin verifies its expected per-project artifacts exist (adr: ADR system present; vault: project hub note exists — optionally injecting it as context). All good → silent. Problem → one short banner prompting corrective action (" missing — run /os-vault:… to fix"). Plugins stay independent; new plugins get picked up automatically by following the convention; only the glue plugin is mandatory for the collection.
This is architecture → OpenSpec change + ADR (use openspec-propose; decisions land in
docs/memory-system/03-architecture-decisions.md). Do not build outside that workflow.
User's sketch (the starting design)
Per-plugin Python status scripts following a cc-os convention (naming, interface, location), living in a specific gitignored hidden directory in the project. SessionStart fires a cc-os master status script that enumerates all status scripts in that directory (excluding itself) and runs them. Adding a plugin later = drop in a conforming script; no global rewrites.
The one design tension the proposal must settle (pressure-test, don't fiat)
Where does status-check CODE live?
- Option A (user sketch): project-local dir (e.g.
.cc-os/status.d/*.py, gitignored). Pro: per-project opt-in/customization. Con: code copies drift across projects; needs an install/update step per project per plugin; the 2026-07-04 stale-cache incident shows copy-drift is a real failure class here. - Option B: plugin-source enumeration — each plugin ships
status/check.pyin its own source; the master enumerates installedos-*plugins at session start. Same modularity and zero-global-rewrite extension; no copies, no drift, no install step. Project-local.cc-os/still exists but holds STATE only (suppress files, per-project config like "this project opts out of hub-note checks"), mirroring os-adr's.os-adr/and os-doc-hygiene's.dochygiene/— consolidating those is itself a candidate scope item.
Run perspectives:simplifier and perspectives:implementer (both sonnet) against both
shapes inside the proposal. Lean: B for code, A-style dir for state.
Interface contract (draft for the proposal)
- Each check: stdin/argv gets project root + plugin config; stdout JSON
{"status": "ok"|"warn", "message": str, "context": str|null}; hard timeout (~5s); non-zero exit or timeout = treated as warn with a generic message, never blocks session. - Silent on ok — os-adr's near-zero-token SessionStart discipline is the template. Master aggregates warns into ONE short banner; per-project once-per-day snooze + permanent suppress via state dir (pattern already proven in os-adr/os-doc-hygiene).
contextfield = optional session-context injection (the "pull the hub note into context if useful" idea) — but gate it through injection-economics thinking (see the design-template skill's filter); default null.
Glue plugin scope ("cc-os collection manager")
Naming: per ~/Documents/SecondBrain/cc-os-plugin-skill-naming-convention.md (read before
naming; os-[domain], verb-first skills, NO name: frontmatter). Candidates: os-core
(lean) or os-status (narrower). Settle in the proposal.
Phase 1 (this change): master SessionStart hook + enumeration + interface contract + convert the two existing consumers:
- os-adr: refactor its existing existence-check hook into a conforming status check (it is already exactly this pattern — present→usage note, absent→once-per-day suggestion).
- os-vault: new hub-note check (project hub note exists for the current project; missing → prompt to run onboarding/creation; optionally inject on present).
- os-orchestration: env-override check — warn when
CLAUDE_CODE_SUBAGENT_MODEL(or similar model-forcing env) is set in~/.claude/settings.jsonor the environment. Added 2026-07-06: the E1 canary proved the orchestrator cannot observe resolved models at spawn time (resolvedModelis harness-side only), so silent-override protection must be deterministic, not model behavior. This check would have caught the WS1 Cluster 1 incident at SessionStart.
Phase 2 (separate change, later): collection-manager duties — verify installed cc-os
plugin caches are fresh vs source (would have auto-caught the 2026-07-04 stale-cache
incident), migrations complete, conventions followed (e.g. no name: in SKILL.md
frontmatter). Effectively an automated bin/refresh-plugins advisor.
Deliverables
- OpenSpec change (design.md resolving the tension above + specs + tasks) — via
openspec-propose. - ADR in
docs/memory-system/03-architecture-decisions.md(status-check convention + code-location decision). - Implementation via
openspec-apply-change: master hook + shared contract module (Python, matching os-vault's deep-module style: thin entry points, shared config/io modules), conforming checks for os-adr + os-vault, model-free tests (Python, mirroringtests/hook_test.pystyle) + invariants.md. bin/refresh-plugins,claude plugin detailsverification, fresh-session smoke test.
Models
Design synthesis + ADR: orchestrator. Perspective reviews: sonnet. Implementation: haiku for thin scripts/tests, sonnet for the shared contract module. No behavioral eval needed — deterministic code; invariants + model-free tests suffice (same rationale as the os-adr hook).