3.4 KiB
os-adr invariants
Behavioral invariants of the plugin. Changing any of these requires explicit human approval and
a matching update to the tests named beside it. Suite entry points: ruby tests/all.rb and
python3 tests/hook_test.py (both model-free).
-
Non-destructiveness (migration). Migration writes only new files under
docs/adr/; existing source content is never deleted, moved, or edited by any tooling path. Old-system removal is a separate, explicit, user-approved step (skill-mediated, never automatic). —migrator_test.rb#test_sources_stay_byte_identical, pilot sha256 checks. -
Index regeneration, never accretion.
docs/adr/README.md's table is regenerated in full from directory contents on every ADR write; it is never appended to or hand-edited, and self-heals after manual edits. Content outside the markers is preserved. —index_test.rb(golden fixture, self-heal, prose preservation, generated-header cases). -
IDs come from the directory, never the index. Next ID = max existing filename ID + 1, derived by scanning
docs/adr/; a stale or missing index never influences numbering. —repository_test.rb#test_next_id_ignores_{missing,stale}_index. -
No LLM in the hook. The SessionStart hook is a pure function of filesystem state (ADR dir, index, suppression state, snooze stamp) — no model call, no network, no Ruby spin-up; always exits 0; emits nothing (and creates no state) outside a git project. Its existence rule is identical to
Adr::Repository#exists?. —hook_test.py(all cases;PythonRubyAgreementTestpins the shared rule). -
Single uncertainty-flagging mechanism. Migration uncertainty surfaces only via
migration_confidence: low|medium|highfrontmatter plusdocs/adr/migration-report.md. No scattered inline uncertainty comments. —migrator_test.rb#test_report_lists_files_confidence_sources_and_flag_rate. -
Core fields are never invented. A Decision or Context absent from a migration source is written as
_not stated in source_and flags the file low-confidence; LLM fills apply only to pending-marker fields (enforced structurally byapply_fills!— a stray fill key is a no-op), and an LLM-filled file stays flagged (≤ medium). —migrator_test.rb#test_missing_core_fields_*,#test_apply_fills_only_touches_pending_fields. -
Unrecognized content is reported, never auto-converted. Content matching no known shape — including multi-decision files without mechanically splittable unit headings — is listed in the report for manual handling only. —
detector_test.rb#test_multi_decision_file_without_unit_headings_is_unrecognized,migrator_test.rb#test_unrecognized_content_is_reported_never_converted. -
Deterministic-first retrieval.
adr-findnarrows by frontmatter path/component match, then Accepted-only status filter (explicit override), then optional one-hop graph expansion that degrades gracefully (absent or corrupt graph → layers 1–2). AI judgment happens only in thefindskill, only over the CLI's returned candidates. —finder_test.rb(all cases, including both degradation paths). -
Skills delegate mechanics to
bin/CLIs. Numbering, templating, indexing, supersession bookkeeping, detection, conversion, and retrieval filtering are never re-implemented in prompt instructions. — by construction ofskills/*/SKILL.md;cli_test.rbpins the CLI contracts.