cc-os/openspec/changes/archive/2026-07-03-add-os-adr-plugin/tasks.md

52 lines
7.2 KiB
Markdown
Raw Permalink 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.

# Tasks: add-os-adr-plugin
## 1. Plugin skeleton and eval-readiness sketches
- [x] 1.1 Sketch held-out eval scenario shapes (write-trigger + retrieval) in `docs/adr-system/06-eval-scenarios.md`; note any plugin surface they require beyond Phases 14 and fold it into this plan before proceeding
- [x] 1.2 Create `cc-os/plugins/os-adr/` skeleton: `.claude-plugin/plugin.json` (name `os-adr`), `hooks/`, `lib/`, `bin/`, `templates/`, `skills/`, `tests/`, `invariants.md` stub
- [x] 1.3 Write `templates/adr.md` — customized-Nygard template with full frontmatter (`id`, `date`, `status`, `supersedes`, `superseded-by`, `affected-paths`, `affected-components`) and body sections (Context, Decision, Consequences, Alternatives rejected)
## 2. Phase 1 — authoring core (Ruby, mechanical)
- [x] 2.1 Implement `Adr::Record` (parse/serialize one ADR file: frontmatter + sections) with unit tests
- [x] 2.2 Implement `Adr::Repository` (scan `docs/adr/`, derive next 4-digit ID from directory contents, injected root path) with unit tests including stale/missing-index cases
- [x] 2.3 Implement `Adr::Index` (full regeneration of `docs/adr/README.md` table between markers, never-hand-edited header) with golden-fixture tests including the self-heal-after-manual-edit case
- [x] 2.4 Implement `Adr::Template` + `bin/adr-new` (create templated ADR, regenerate index, mechanical supersession: set `superseded-by` + status on the superseded ADR) with tests
- [x] 2.5 Implement `bin/adr-init` (create `docs/adr/` + empty index, clear `.os-adr/suppress`) with tests
- [x] 2.6 Write `skills/create/SKILL.md` and `skills/init/SKILL.md` — skills gather decision content, then delegate all mechanical work to `bin/adr-new`/`bin/adr-init`
## 3. Phase 1 — install and register the plugin
- [x] 3.1 Symlink `~/.claude/plugins/os-adr → cc-os/plugins/os-adr/`
- [x] 3.2 Add `os-adr`/`./os-adr` to `~/.claude/plugins/.claude-plugin/marketplace.json` and enable `os-adr@local-plugins` in `settings.json`
- [x] 3.3 Run `claude plugin marketplace update local-plugins` + `claude plugin install os-adr@local-plugins`; verify with `claude plugin list` and `claude plugin details` that all skills resolve (ADR-018 failure mode check)
- [x] 3.4 Dogfood: in a scratch project, run `/os-adr:init` then `/os-adr:create` and confirm one-invocation creation with correct template, ID, and index (CLI path the skills delegate to, verified in scratchpad; skills confirmed registered via `claude plugin details` — interactive slash invocation re-checked in 4.4's fresh-session pass)
## 4. Phase 2 — SessionStart hook
- [x] 4.1 Implement `hooks/session_start.py` — deterministic existence check (`docs/adr/` + index), present→minimal usage note naming `/os-adr:create` and `/os-adr:find`, absent→init/migrate suggestion gated by `.os-adr/suppress` flag and once-per-day snooze stamp
- [x] 4.2 Write `hooks/hooks.json` (SessionStart, matcher `startup|resume`, `${CLAUDE_PLUGIN_ROOT}` command, 5s timeout); confirm no os-adr entries needed in `settings.json`
- [x] 4.3 Add hook tests: shared fixture tree asserting the Python check and Ruby `Adr::Repository` agree on existence; suppression, snooze, and present/absent output cases
- [x] 4.4 Verify in fresh sessions: present project injects the note, absent project nags once then snoozes, suppressed project stays silent (verified by invoking the hook exactly as the harness does, in fixture git projects; hook registration confirmed via `claude plugin details` — Hooks (1) SessionStart)
## 5. Phase 3 — migration
- [x] 5.1 Implement `Adr::Detector` + `bin/adr-detect` — classify existing content into the four surveyed shapes + `unrecognized` fallback (report-only), enumerate migration units, with fixture tests per shape
- [x] 5.2 Implement `Adr::Migrator` + `bin/adr-migrate` mechanical pass — heuristic-fill unambiguous fields (status/date/title/ID/provenance), emit a work manifest of fields needing LLM fill, write nothing outside `docs/adr/`, with byte-identical-source tests
- [x] 5.3 Implement flagging + report: `migration_confidence` frontmatter, not-stated-in-source markers for absent Decision/Context, and `docs/adr/migration-report.md` generation (per-file confidence, source mapping, flag rate) with tests
- [x] 5.4 Write `skills/migrate/SKILL.md` — runs detect, has the model fill only manifest-listed interpretive fields, hands results back to the core for writing, presents the report, and offers old-system deletion only as an explicit separate user-approved step
- [x] 5.5 Pilot the migration on 23 surveyed projects (viking-warrior-training-log, delta-refinery, llf-schema); record the low-confidence flag rate and threshold in each report; tighten heuristics and re-run if the rate exceeds the threshold (gate — do not proceed to broad use until passed). **Pilot 2026-07-03 (sandboxed copies, real repos untouched): threshold 25%; two tightening rounds (bulleted labels, bold-label paragraphs `**Context.**`, Why/Rationale→Context fallback at medium confidence, SETTLED/OPEN status mapping, multi-Status-no-headings→unrecognized guard). Final rates: viking 0% (6/6 high), delta-refinery 0% (12 medium), llf-schema 8.3% (1 low: the superseded 2026-06-04 index doc, legitimately lacking Decision/Context). Gate PASSED. Real-repo migration happens interactively via `/os-adr:migrate` per project.**
## 6. Phase 4 — retrieval
- [x] 6.1 Implement `Adr::Finder` + `bin/adr-find` layers 12: path/component frontmatter matching and Accepted-by-default status filter (with override flag), with tests
- [x] 6.2 Add layer 3: Graphify traversal over `graphify-out/` when present, expanding the candidate set via graph edges; graceful degradation to layers 12 when absent, with tests for both paths; resolve whether ADR frontmatter needs a tag/edge convention against the llf-schema graph. **Resolved: no tag/edge convention needed — layer 3 expands the *query* paths one hop via graph-node `source_file` attributes; ADRs never need to be graph nodes and match purely on `affected-paths` frontmatter.**
- [x] 6.3 Write `skills/find/SKILL.md` — mid-task-callable: run the deterministic CLI, apply AI judgment only over the returned candidate set, never the full corpus
- [x] 6.4 Verify retrieval end-to-end in a piloted project: query with real edited-file paths and confirm the correct Accepted ADR surfaces (llf-schema pilot copy + its real project graph: `tests/IdMinterTest.php` query surfaced the correct ADR via `graph` match; `src/IdMinter.php` via `path`; unrelated path → 0 candidates)
## 7. Wrap-up
- [x] 7.1 Fill in `invariants.md` (non-destructiveness, index-regeneration, no-LLM-in-hook, single-flag-mechanism invariants) and ensure the test suite covers each (9 invariants, each mapped to its covering tests)
- [x] 7.2 Update cc-os `CLAUDE.md` Implemented Components with the os-adr pointer and note the locked rollout order (pilot → cc-os retrofit → wider) as remaining work
- [x] 7.3 Record the build in `docs/memory-system`-style ADR log (`03-architecture-decisions.md`) if any design decision changed during implementation; keep `docs/adr-system/` docs' status lines current (ADR-020 added: 25% pilot threshold, no-graph-convention resolution, heuristic-boundary refinements; `00-README.md` status updated, `06-eval-scenarios.md` added to its doc list)