8.7 KiB
Delta: calibrate (calibrate-assessment-inventory)
ADDED Requirements
Requirement: Deterministic Nomination Intake Filter
Between cheap-model nomination and strong-model judgment, :calibrate SHALL
run a deterministic NominationIntakeFilter (in calibrate_helpers.py, no
model — invariant #6). A nomination whose glob+lifetime exactly equals a
rejected entry SHALL be dropped before the judge and logged in the run
summary. Surviving nominations SHALL be annotated with every related
rejection, where related means the two globs' match sets intersect on the
current shortlist (deterministic, computed from the scan). The annotations
plus all open consults SHALL enter the judge prompt as its "Nominations
memory" input section; related rejections are context for the judge, never a
veto.
Scenario: Exact glob+lifetime repeat is dropped before the judge
- WHEN haiku nominates
docs/research/** -> temporaryandnominations.rejectedcontains an entry with globdocs/research/**and lifetimetemporary - THEN the nomination is dropped at intake, never reaches the judge, and the drop is logged in the run summary
Scenario: A variant flows through annotated, not blocked
- WHEN haiku nominates
docs/research/drafts/** -> temporaryandnominations.rejectedcontainsdocs/research/** -> temporary, and the two globs' match sets intersect on the current shortlist - THEN the nomination proceeds to the judge carrying the related rejection (its why and consider_instead) as context, and the judge may still confirm it
Scenario: Open consults always reach the judge prompt
- WHEN
nominations.consultsis non-empty at intake time - THEN every open consult is included in the judge prompt's "Nominations memory" section, regardless of what haiku nominated this round
Requirement: Consult Persistence and Resurfacing
Open consult verdicts SHALL persist to nominations.consults (deduped by
glob at write time) rather than dying with the run. Consults SHALL resurface
in :calibrate only — :check and :clean are unchanged — appearing in the
judge prompt and as an "Open consults" section of the rule report. A consult
SHALL exit in exactly one of three ways: (a) a human answer settles the
purpose — a normal rule is persisted and the consult entry deleted; (b) the
human deems it not rule-worthy — the entry is rewritten into rejected with
rejected_by: "human" and the human's why; (c) the human defers — the entry
stays and resurfaces next run. New rejections and consults SHALL appear in
the rule report but are not individually gated — they are memory, not
deletion authority.
Scenario: A consult survives the run and resurfaces
- WHEN a judge verdict is
consultand the run ends without a human answer - THEN the consult is written to
nominations.consults, and the next:calibraterun surfaces it in both the judge prompt and the report's "Open consults" section
Scenario: An answered consult becomes a rule and disappears
- WHEN the human answers an open consult in a way that settles the artifact's purpose
- THEN a normal rule is persisted through the standard report flow and the consult entry is deleted in the same write
Scenario: A declined consult becomes a human rejection
- WHEN the human answers that an open consult's artifact class is not rule-worthy
- THEN the consult entry is rewritten into
nominations.rejectedwithrejected_by: "human"and the stated reason
Scenario: Consults never surface outside calibrate
- WHEN
:checkor:cleanruns against a project with open consults - THEN their behavior is unchanged — consults neither appear in output nor affect any classification
MODIFIED Requirements
Requirement: Persistence Rules by Scope
Project-rulebook writes SHALL land on judge confirmation once the human has
reviewed the rule report. Global-rulebook writes (writing into
plugins/os-doc-hygiene/rulebook.json) SHALL additionally require explicit
human gating, distinct from project-rule confirmation, since it is a
cross-repo write into cc-os. Rule removals SHALL be HITL-only in all cases,
with recorded reasoning, regardless of scope. Every settled verdict SHALL
persist: judge keep verdicts become ordinary lifetime: keep rules in
rules (including exact-path singletons, per the keep-tier relaxation);
human declines at the rule report persist as rejected entries with
rejected_by: "human"; open consult verdicts persist to
nominations.consults, deduped by glob at write time. All persistence SHALL
go through the canonical rules-file writer.
Scenario: Project rule persists on judge confirmation plus report review
- WHEN the judge verdict is
confirmfor a project-scoped rule and the human has reviewed its rule report - THEN the rule is written to the project's
.dochygiene-rules.json
Scenario: Global rulebook writes require an additional explicit gate
- WHEN a proposed rule would be written to the global
rulebook.json - THEN a distinct human confirmation for the cross-repo write is required, beyond the project-rule confirmation step
Scenario: Rule removal is always HITL-only
- WHEN any rule (project or global) is proposed for removal
- THEN the removal happens only via explicit human instruction, with the reasoning recorded, never as an automatic side effect of a calibration pass
Scenario: A keep verdict persists as a plain keep rule
- WHEN the judge's settled verdict for a cluster is that the artifacts must be retained
- THEN an ordinary
lifetime: keeprule is persisted torules— removing the cluster from future calibrate pools and protecting future matches — even when the glob is an exact-path singleton
Scenario: A human decline persists as a rejection
- WHEN the human declines a judge-confirmed rule at the rule report
- THEN a
rejectedentry withrejected_by: "human"is written, so a later haiku round cannot re-nominate the identical glob+lifetime without the judge knowing
Requirement: Rule-Quality Test — Class Never Path
A proposed rule's glob SHALL name a recurring class of artifact, never an
identifier unique to a single instance. A glob that hardcodes a name
recurring by convention (e.g. PRD.md, HANDOFF-*.md,
migration-report.md) is acceptable. A glob that hardcodes a run-id, hash,
or bare timestamp unique to one instance is not acceptable. A rule that
currently matches only one file is acceptable; a rule that can, by
construction, only ever match one file is a failed generalization and SHALL
be flagged loudly rather than silently persisted. Keep-tier relaxation:
exact-path/instance globs ARE acceptable for lifetime: keep entries only —
this test exists to prevent bad deletion rules, and a singleton keep merely
protects; instance globs remain forbidden for temporary and
delete-once-served. When the near-miss boundary check reveals sibling
artifacts a glob misses, the fix SHALL be to enumerate the conventional
prefixes as separate rule entries, never to widen the glob to the containing
directory; container-claiming globs are justified ONLY when the directory is
wholly machine-owned (e.g. plugins/*/.pytest_cache/).
Scenario: A convention-recurring name is acceptable
- WHEN a proposed rule's glob is
HANDOFF-*.md - THEN it passes the class-never-path test, since
HANDOFF-*is a recurring naming convention, not a single instance
Scenario: An instance-unique identifier fails the test
- WHEN a proposed rule's glob hardcodes a specific run-id or hash string that can only ever identify one artifact
- THEN the rule fails the class-never-path test and is flagged loudly, not silently persisted
Scenario: One current match is fine; one-EVER match is not
- WHEN a proposed rule currently matches exactly one file
- THEN it is acceptable if the glob's structure could match future similarly-named files; it is flagged as a failed generalization if the glob's structure can never match any file but the one it names today
Scenario: A singleton keep passes under the keep-tier relaxation
- WHEN a proposed rule is
docs/research/clutter-pattern-inventory.md -> keep - THEN it passes despite being an exact-path instance glob, because the keep tier only protects; the same glob with lifetime
temporaryordelete-once-servedfails
Scenario: Missed siblings are enumerated, never widened to the container
- WHEN the boundary check shows
autoresearch/classic-*/misses sibling runs underautoresearch/improve-*/ - THEN the fix is a second rule entry
autoresearch/improve-*/(same cluster), never a widening toautoresearch/*/orautoresearch/**, so keep-worthy content can still live in the container without a counter-rule