cc-os/plugins/os-status/skills/fix/SKILL.md

116 lines
5.8 KiB
Markdown
Raw Blame History

This file contains ambiguous Unicode characters

This file contains Unicode characters that might be confused with other characters. If you think that this is intentional, you can safely ignore this warning. Use the Escape button to reveal them.

---
description: Bring the current project up to the current cc-os approach by remediating whatever /os-status checks flag — idempotent, doubles as the update path. Invoked by /os-status:fix.
---
# fix
Unified project setup/update. Runs the same check registry the SessionStart hook
runs, then drives each failing check's remediation. Per ADR-026: `fix` orchestrates
existing per-plugin skills — it never reimplements them. Idempotent by construction:
re-running `fix` on an already-configured project is the update path, not a separate
command.
**Scope: `fix` never stages or commits.** It edits files and reports what changed —
staging and committing is always the user's call, even for mechanical remediations
like a `.gitignore` addition or a config stamp.
## Flow
1. **Get machine-readable results.** From the project root, run:
```
python3 ${CLAUDE_PLUGIN_ROOT}/hooks/checks.py --json
```
This prints a JSON array of `{name, status, message, remediation}` for every
check applicable to the current project (project-scoped checks are skipped
outside a git project, same rule the SessionStart hook uses).
2. **All `ok` (and only `note`/`ok`)?** Report "this project is up to date" and go
straight to steps 3b4 (gitignore + version stamp) — nothing else to remediate.
3a. **Ensure `.cc-os/` is gitignored.** Check the project's `.gitignore` for a
`.cc-os/` entry; add one if missing. Per ADR-027, this single entry covers every
cc-os plugin's per-project state (os-status's `.cc-os/config` + `.cc-os/status/`,
os-backlog's tracker key, etc.) — there is no separate `.os-adr/` entry to add
anymore. This step runs every `fix` invocation, not just when a check flags it.
3b. **Otherwise, walk the non-`ok` entries in this order** (mechanical → decision-
bearing, so autonomous fixes land before anything needing a human gate):
a. **`adr-system-present`** → invoke `/os-adr:init` (or `/os-adr:migrate` if the
project already has decision-log-like content the message/context suggests —
use judgment, this is mechanical either way).
b. **`vault-hub-note-present`** → either invoke `/os-vault:write` to create a hub
note (tags `type/hub` + `project/<name>`), or if the user says a hub note
already exists under a different name, set `hub = <slug>` in `.cc-os/config`
via the config-write helper (see step 4).
c. **`project-graph-present`** → invoke `/os-vault:onboard-project`.
d. **`tracker-configured`** → invoke `/os-backlog:route` directly and let it run
its own inspect → propose → confirm flow. Do NOT pre-ask the user "forgejo or
planka?" — that framing is wrong: the boundary rule uses BOTH (Planka = state,
git issues = specs; a project routinely keeps its git-issue spec chains AND a
`planka:` tracker key for new ad hoc state). The route skill owns that
decision conversation and its gates. If `/os-backlog:route` is not installed,
tell the user and skip — do not fabricate a `.cc-os/config` tracker value
yourself.
e. **`subagent-model-env-override`** → **human gate, and typically out of scope
for a project-level fix.** This is an environment/settings.json condition, not
a per-project one. Report it and ask the user to remove the env var
themselves; do not edit `~/.claude/settings.json` from this skill.
f. **`config-version-current`** → resolved automatically by step 4 below; no
separate action.
Re-run the JSON check after each remediation that plausibly changed check-registry
state (creating a hub note, running `/os-adr:init`, setting a config key), so later
steps see fresh results (e.g. don't act on a stale `vault-hub-note-present` warning
after already creating the note). Remediations that don't affect check-registry
state — step 3a's gitignore edit is the example — don't require a re-run.
Snoozed warns self-clear: whenever a check now evaluates to `ok`/`note` (whether
because this skill just fixed it or it was already fine), the next SessionStart
or `fix` run clears its stale `snooze-<check>` file automatically (state.py's
`clear_snooze`) — nothing to do here beyond re-running the JSON check per the
rule above.
4. **Stamp the config version.** Once the mechanical/human-gated fixes above are
done (or were already `ok`), write the current version into `.cc-os/config`,
preserving every other key. Use the helper:
```python
import sys
sys.path.insert(0, "${CLAUDE_PLUGIN_ROOT}/hooks")
from state import write_config_value, find_project_root
from checks import CURRENT_CONFIG_VERSION
from pathlib import Path
root = find_project_root(Path.cwd())
write_config_value(root, "version", str(CURRENT_CONFIG_VERSION))
```
(Equivalently, run it as a one-off `python3 -c "..."` from the project root.)
This is what makes `config-version-current` pass on the next run and what makes
re-running `fix` on a fully-configured project a fast, silent no-op.
5. **Report a short summary**: which checks were already `ok`, which were fixed and
how, which were skipped pending a human decision, and confirm the config version
was stamped.
## Notes
- Never edit `.cc-os/config` by hand-writing the whole file — always go through
`write_config_value` (or the equivalent read-modify-write) so unrelated keys
(`hub`, `tracker`, `vault_path`, ...) are preserved.
- Decision-bearing steps (tracker destination, anything destructive) keep their
human gate even when this skill is otherwise running autonomously. Mechanical
steps (running `/os-adr:init`, `/os-vault:onboard-project`, stamping the version)
proceed without asking.
- This skill does not touch `subagent-model-env-override` state — that's a machine
environment condition, not a per-project one, and editing global settings.json is
out of scope.