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

52 lines
7.2 KiB
Markdown
Raw Permalink Normal View History

# 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)