5.1 KiB
Delta: lifecycle-rulebook (calibrate-assessment-inventory)
MODIFIED Requirements
Requirement: Rulebook Locations and Envelope
The plugin SHALL ship a global rulebook at
plugins/os-doc-hygiene/rulebook.json, resolved relative to plugin scripts,
present in every project. A project MAY additionally provide a committed
repo-root .dochygiene-rules.json override. Both files SHALL use the
envelope {"schema_version": 1, "rules": [...]}. The project file MAY
additionally carry a top-level nominations key (see the Nominations Memory
requirement); the loader SHALL ignore unknown top-level keys, so the key is
additive to schema_version 1. The per-project override SHALL NOT live under
gitignored .cc-os/ — it SHALL be a committed, reviewable dotfile.
Scenario: Global rulebook is always present
- WHEN the rulebook loader runs in any project
- THEN it loads
plugins/os-doc-hygiene/rulebook.jsonresolved relative to the plugin scripts directory
Scenario: Per-project override is optional and committed
- WHEN a project has no
.dochygiene-rules.jsonat its repo root - THEN the loader proceeds using only the global rulebook, and when the file is present it is read as a committed, reviewable file, never from
.cc-os/
Scenario: Both files share one envelope shape
- WHEN either the global rulebook or a project override is loaded
- THEN it is validated against the envelope
{"schema_version": 1, "rules": [...]}
Scenario: A nominations key does not disturb the v1 loader
- WHEN a project
.dochygiene-rules.jsoncarries a top-levelnominationskey alongsiderules - THEN
rulebook.pyloads therulesarray exactly as before, ignoring the unknown top-level key without warning or error
ADDED Requirements
Requirement: Nominations Memory Lives in the Project Rules File
The project .dochygiene-rules.json MAY carry a top-level nominations key
holding exactly two lists: consults (open questions — entries with glob,
question, evidence, cluster_key, asked_on, and deliberately NO
lifetime) and rejected (settled "no" answers — entries with glob,
lifetime, why, optional consider_instead, rejected_by ("judge" or
"human"), judged_on). The nominations key SHALL never affect which
files the rulebook governs — only entries in rules decide that.
rulebook.py SHALL remain nomination-unaware; only the calibrate helpers
read the key, and the calibrate reader SHALL warn on unrecognized nomination
fields, mirroring the rules array's unknown-field discipline. Rejected
entries and exact-path singleton keep rules SHALL exit only by hand-deletion
(removals stay HITL with recorded reasoning); no automated revisit path
SHALL exist.
Scenario: Nominations never filter files
- WHEN the scanner or rulebook resolves the governing rule for a path that only a
nominationsentry's glob matches - THEN the path is treated as unmatched/unmanaged — nominations carry no lifecycle authority
Scenario: Consult entries carry no lifetime
- WHEN a consult entry is written to
nominations.consults - THEN it records
glob,question,evidence,cluster_key,asked_onand no lifetime field — presence in the list means open, with no status field
Scenario: Unrecognized nomination fields warn in the calibrate reader
- WHEN the calibrate helpers read a nominations entry containing an unknown field
- THEN a warning is emitted and the field is preserved, never silently dropped
Scenario: A rejection leaves only by hand-deletion
- WHEN a calibration pass runs against a rules file containing a stale rejection
- THEN no automated path removes or expires the entry; it is removed only by explicit human edit
Requirement: Canonical Writer-Enforced Ordering
Every code path that serializes .dochygiene-rules.json SHALL write through
one canonical writer that emits: rules grouped by lifetime tier in the
order delete-once-served, temporary, keep, glob-sorted within each group;
nominations after rules; consults before rejected, each glob-sorted.
The writer SHALL be idempotent (canonicalizing an already-canonical file is a
no-op) and SHALL round-trip unknown fields with a warning rather than
dropping them. Ordering SHALL NOT be enforced by any hook; hand edits
re-canonicalize on the next write.
Scenario: Writes are grouped and sorted canonically
- WHEN the writer serializes a rules file containing rules of all three tiers plus nominations
- THEN the output orders rules delete-once-served → temporary → keep with globs sorted within each group, and nominations follows rules with consults before rejected, each list glob-sorted
Scenario: Canonicalization is idempotent
- WHEN the writer serializes a file it previously wrote, unchanged
- THEN the output is byte-identical
Scenario: A hand-edited file re-canonicalizes on the next write
- WHEN a human appends a rule out of tier order and a later calibrate run persists a new entry
- THEN the whole file is rewritten in canonical order in that write, with no hook involved in the interim