section-02: author and finalize the 8 rules
Goal
Write the 8 grounded rules into .claude/rules/impl-hygiene.md (exact catalog format)
and the matching subcats into .claude/rules/finding-categories.md, as one atomic
id-assignment pass, then verify catalog integrity.
Implementation Sketch
Re-verify next-available ids at write time — SPEC-66 / COVER-32 were the max as of
this plan’s authoring; re-check before writing, since impl-hygiene.md may have grown.
Assign all 8 ids (COVER-33, COVER-34, SPEC-67..SPEC-72) in a SINGLE atomic pass
per the Step 8B consensus finding — never interleave with an unrelated edit that could
shift the max between assignment and write.
Each rule text follows the exact
- PREFIX-NN (was CATEGORY:subcat): directive (Severity); cure; pin via ... format of
its sibling rules (SPEC-45, SPEC-62..66, COVER-26).
Rule bodies (final text, corrected per both /tp-help consensus rounds):
- COVER-33
(was COMPILER:ablation-toggle-untested): everyORI_DISABLE_*/ORI_FORCE_*toggle needs a negative-pin test proving it reproduces its documented bisected behavior. States explicitly it SPECIALIZESSPEC-63(env-var doc+test) for the ablation-toggle subset — not a duplicate. CitesBUG-07-005(resolved: orphan env vars read in source but not registered indebug_flags.rs) as the concrete Ori precedent for what an unverified toggle costs. - COVER-34
(was COMPILER:dead-instrumentation-dependency): a crate declaringtracing/logneeds call-site volume proportional to its pipeline role. Zero call sites (ori_patterns) = Critical; disproportionate near-zero (ori_parse) = Major. Cure is BIDIRECTIONAL per the Step 8B correction: default is REMOVE the dead dependency (NAME-11), OR add proportional instrumentation — decided per-crate by whether the crate’s pipeline role genuinely warrants observability, recorded as adecisions/NN-*.mdADR when it is a genuine tradeoff call.BUG-07-009(resolved: thetracing-treeTRANSITIVE dependency always compiled intooricregardless ofORI_LOG_TREEusage) is the same failure shape one level up — noted as adjacent precedent; COVER-34’s wording targets in-crate call-site volume, not transitive deps, soBUG-07-009’s exact shape stays out of this rule’s literal scope. - SPEC-67
(was COMPILER:eager-trace-side-effect): bans a side-effecting or non-O(1) expression as a directtrace!/debug!/etc macro argument — forward-looking only (gates new code). Cure cites rustc’s realEnteredTraceSpan::or_if_tracing_disabledmarker-trait dual-dispatch pattern (rustc_const_eval/src/interpret/util.rs:56-75) and the?field/%fieldlazy-capture idiom, contrasted against the allowedori_parse/src/grammar/expr/mod.rstrace!(pos=.., kind=..)cheap-field-access shape. - SPEC-68
(was COMPILER:nondeterministic-dump-output): a dump/trace/remark serializer iterating aHashMap/HashSetwithout canonicalizing order breaks diff-based bisection. Concrete pin:dump_orchestrator.rs’s unifiedDumpPhasesurface (the golden-baseline CONTRACT indump_orchestrator_baseline.rs’s module doc,ORI_BLESS=1to regenerate) +rc-stats.sh’s diff-driven contract. Cites the CONTRACT, not the current pass/fail state —BUG-04-252(open) has one baseline leg (ori_dump_after_llvm_pins_llvm_ir_driver_block) presently red; the rule governs the mechanism’s shape, andBUG-04-252is the mechanism catching its own regression exactly as designed, not evidence against it. - SPEC-69
(was COMPILER:trace-target-naming-drift): bans an explicit tracingtarget:override diverging from the owning crate::module path. Grounded againstoric/src/tracing_setup.rs’s realtracing_subscriberfilter setup. - SPEC-70
(was COMPILER:cycle-recovery-untraced): the ONEcycle_recovery_strategyclosureSPEC-62reserves for a genuinely-fixpoint case must trace-log the recovered query chain, distinguishing it fromSPEC-62’s banned silent-masking case at incident time. States explicitly (per Step 8B correction) that the trace-log is OBSERVATIONAL, not a memoized Salsa input — purity-exempt fromSPEC-34/SPEC-35— and is a strict LAYER onSPEC-62’s carve-out, never a second path reopening the banned case. Grounding is entirely FORWARD-LOOKING (no livecycle_recovery_strategyusage anywhere incompiler/today — confirmed by grep) — rests onSPEC-62’s existing text plus rust#119321 (“query cycles could be handled more like ICEs”), which sits at the intel graph’s 100th-percentile pain+controversy score, the sharpest available cross-repo corroboration that silent cycle recovery is a chronic, high-friction failure mode worth preventing before Ori grows its own instance. - SPEC-71
(was COMPILER:trace-target-central-registry): every crate-leveltracingtarget/span-name string must be declared in ONE central enumeration artifact, verified by a parse-check script — mirroring the PATTERN (not the path) of the REALdebug_flags.rs+check-debug-flags.shpairing (an enumeration file plus an external verifier), corrected per Step 8B from an earlier “macro-enforced registry” framing that mischaracterizeddebug_flags.rs(theflags!macro only emits name-mirrored consts;check-debug-flags.shis the actual enforcement) and would have demanded unbuildable runtime-registration infrastructure. Worded pattern-first, never path-first —check-debug-flags.shis claimed restructuring territory of the not-starteddiagnostics-splitplan; the rule must survive that relocation. The registry MUST enumerate every independent reader of a shared env var, not just the first one found —ORI_DUMP_AFTER_ARChas TWO independent readers (dump_orchestrator::dump_arcat the driver level, plusori_llvm::codegen::function_compiler::define_phase::dump_arc_if_requestedinside codegen itself) and both must appear in the enumeration. Second cross-repo precedent beyond Lean4’sregisterTraceClass: rustc’srustc_data_structures::profiling::EVENT_FILTERS_BY_NAMEnamed per-event filter table. Distinct failure mode fromSPEC-69: an un-enumerated-but-correctly-named target vs an incorrectly-named one. Even Lean4’s own reference registry has had real registration-completeness incidents (lean4#4151“fix: add missing registerTraceClass”,lean4#4369“chore: missing registerTraceClass”, found via/intel-package’s section-02 pass) — corroborating evidence that “referenced but not registered” is a recurring failure mode, not a hypothetical one. - SPEC-72
(was COMPILER:ablation-verdict-tracing): a firedORI_DISABLE_*/ORI_FORCE_*toggle must emit a structured trace event (naming the toggle + what it changed) at the point it takes effect — mirrors TypeScript’s realtracing.instant(Phase, eventName, {fields})use-site-event pattern (reference_repos/lang_repos/typescript/src/compiler/checker.ts:22892). Distinct fromCOVER-33(CI-time proof) — this is runtime visibility for whoever is actively bisecting with the flag set.
Matching finding-categories.md COMPILER subcats (one bullet per rule, Detection
column per the category’s existing convention) land in the SAME commit as the rule
text.
Spec References
N/A.
Work Items
- Re-verify next-available
SPEC-NN/COVER-NNids against.claude/rules/impl-hygiene.mdHEAD; author all 8 rules (exact text above) into the catalog in one atomic pass. - Append the 8 matching
COMPILER:*subcats to.claude/rules/finding-categories.md’s COMPILER category block, AND update that block’s trailing citation line (“See impl-hygiene.md §SPEC (SPEC-62/SPEC-63) + §COVER (COVER-26).”) to include the 8 new rule ids, and itsDflt:/severity line to reflect COVER-34’s zero-call-site Critical carve-out (per/intel-package§3H — appending only the bullets without updating the citation line leaves it stale). - Verify catalog integrity: a mechanical assertion the final catalog holds
8 net-new uniquely-numbered entries (no intra-batch id collision); run
python -m scripts.plan_corpus check,python3 scripts/prose-lint.py .claude/rules/impl-hygiene.md .claude/rules/finding-categories.md, THENpython -m scripts.finding_categories freeze(regeneratesscripts/finding_categories/tokens.json—finding-categories.md’s SECOND frozen SSOT projection thatcategory_tokens()reads instead of live-parsing the.md;/intel-packagefound nothing wires this automatically for either target file, and a desync here is the exact BUG-07-229 failure class) followed bypython3 -m pytest scripts/finding_categories/tests/ -q, THEN./test-all.sh(regression canary) — all clean before close; commit the regeneratedtokens.jsonin the SAME commit as the two.mdedits.
Fresh intel (regenerated)
This section’s real terrain is NOT the compiler code the 14-pattern synthesis discusses - it is TWO rule-catalog files and the machinery that keeps them internally consistent. The sibling dossier (research-grounding--s-156cd240.intel.md) already did the exhaustive code-graph recon on debug_flags.rs/dump_orchestrator.rs/tracing_setup.rs and independently re-verified every citation section-02 will use - this dossier does NOT re-run that recon (cite it, per methodology §7.1 “interrogate, never duplicate”). What this dossier found NEW, specific to the write-target itself:
- The JSON-SSOT/generator path for this exact catalog was already tried and reverted. Commit
e19204709(2026-06-23,--bypass) deleted.claude/rules/impl-hygiene-rules.json+.schema.json, madeimpl-hygiene.md“the hand-authored SSOT” again, and extractedfinding-categories.mdas its own file in the SAME commit.plans/completed/impl-hygiene-rules-as-data/is the full record of the tried-and-abandoned generator architecture. Section-02’s plan (hand-edit both files directly) is the CORRECT, current-architecture path - do not propose a generator/JSON-SSOT alternative, it is a confirmed dead end for this exact file pair. §2/§4/§6. .claude/rules/finding-categories.mdhas a SECOND, independently-frozen SSOT projection -scripts/finding_categories/tokens.json- and NOTHING mechanically re-syncs it for this section’s edit.category_tokens()(the live API/tpr-review’sreviewer_history.py,verify_tpr_runtime, and acommit_pushparity test all consume) reads the FROZENtokens.json, not a live parse of the.md.python -m scripts.finding_categories freeze --checkcurrently passes (259 tokens, in sync) but is wired into NEITHERlefthook.ymlNORscripts/pre_push_test_scope.py’s path-to-test mapping for either target file - confirmed empty output for both paths. Appending the 8COMPILER:*subcats without runningpython -m scripts.finding_categories freezeafterward silently desyncstokens.json, degrading/tpr-review’s reviewer category-awareness exactly the way BUG-07-229 (resolved) already did once for a different desync cause. §3D/§4/§9/§10 - the plan’s ownw-b2bed01cverification list (plan_corpus check+prose-lint.py+test-all.sh) does NOT cover this; it needs one more command.- The current catalog max ids match the plan’s own claim exactly - live grep confirms
SPEC-66/COVER-32are still the maximum-numbered entries inimpl-hygiene.mdand thefinding-categories.mdCOMPILER block still carries exactly 3 subcats (salsa-dependency-cycle,env-var-undocumented,config-flag-hygiene) matchingSPEC-62/SPEC-63/COVER-26. The re-verify-before-write instruction in the section body is satisfied as of this dossier’s generation - re-run the grep at actual write time regardless (§2/§10), since other sessions can land rules concurrently. - No plan or bug currently collides with this section’s write target.
plan-status tracing-observability-hygieneshows 0 blockers, 0 open bugs;symbol-plans impl_hygiene/finding_categoriesshow every OTHER referencing plan/bug alreadycompleted/resolved(none in-progress against these two files right now). §6.
DIG DEEPER
python -m scripts.plan_corpus.read plans/tracing-observability-hygiene
git -C /home/eric/projects/ori_lang log --oneline -1 e19204709
python -m scripts.finding_categories freeze --check
(full dossier: author-and-finalize—s-5ecbb585.intel.md)