orthonym.metrics.abstention#
Note
Internal API. Names and behaviour may change between releases.
Typed abstention limit-codes (Task 0.1).
Orthonym’s fail-closed paths all collapse into one descriptive fallback
string, which is right for the naming contract but blind for measurement:
the coverage program needs to know which mechanism abstained so the
recoverable buckets can be counted before any coverage engine is scoped
(the census in scripts/abstention_census.py, Task 0.2).
This module is a per-top-level-naming-session telemetry slot, deliberately side-effect-only:
record_abstentionnever raises and never touches the name string — the instrumentation is proven byte-identical on the naming suites.Two-stage precedence. GENERATION-stage codes (
NO_PARENT,BRANCH_UNNAMEABLE) are first-writer-wins: the site closest to the root cause records first. POST-GENERATION sites (COVERAGE_DOWNGRADE,GATE_SUPPRESSED) record viarecord_suppressionwith the candidate they rejected in hand: when that candidate is a REAL name (not failure-marked), its existence PROVES generation completed, so any speculative generation-stage record from an exploratory dead path is overridden. When the candidate itself embeds the failure marker (e.g.'unknownacetic acid'), the earlier branch record IS the root cause and is kept. Post-generation codes never override each other (first-wins), so a gate suppressing a downgrade’s decomposition fallback keeps theCOVERAGE_DOWNGRADEattribution.The slot is only meaningful for a FAILED naming:
abstention_code_forreturns None unless the result is the failure sentinel (errors.is_failure_name), so speculative codes recorded during a naming that ultimately succeeds never surface.
The codes complement (do not replace) errors.OrthonymLimitError:
limit codes classify the molecule shape post-hoc; abstention codes
classify the pipeline site that declined.
- class orthonym.metrics.abstention.AbstentionCode(*values)#
Bases:
str,EnumWhich pipeline mechanism abstained (str-valued for JSON artifacts).
- NO_PARENT = 'NO_PARENT'#
The parent structure itself was refused at the top level (e.g. the G0 UNSUPPORTED_RING_SYSTEM fail-closed refusal).
- BRANCH_UNNAMEABLE = 'BRANCH_UNNAMEABLE'#
A substituent branch / fragment could not be named while the parent could (the presumptive recursive-substituent-namer bucket).
- GATE_SUPPRESSED = 'GATE_SUPPRESSED'#
A fully generated candidate name was suppressed by a correctness gate (OPSIN validity, P10 structure-conservation, the organometallic/oxoacid source vetoes).
- COVERAGE_DOWNGRADE = 'COVERAGE_DOWNGRADE'#
The >15-HA GENERAL quality/atom-coverage downgrade machinery rejected the assembled name (the P2.1 re-emission lever bucket).
- OTHER = 'OTHER'#
the naming failed without any instrumented site recording a more specific code.
- Type:
Residual
- class orthonym.metrics.abstention.AbstentionRecord(code, detail)#
Bases:
NamedTuple- code: AbstentionCode#
Alias for field number 0
- detail: str | None#
Alias for field number 1
- orthonym.metrics.abstention.abstention_code_for(result_name)#
The abstention code for the naming call that produced
result_name.Returns None when
result_nameis a real name (speculative codes from exploratory paths never surface for a successful naming). For a failure sentinel, returns the recorded code, defaulting toOTHERwhen no instrumented site fired.
- orthonym.metrics.abstention.clear_abstention()#
Reset the slot. Called at the START of every top-level naming call (never by nested/fragment naming, which shares the parent’s session).
- orthonym.metrics.abstention.peek_abstention()#
Raw slot contents (or None). For tests / census detail dumps; most consumers want
abstention_code_forinstead.
- orthonym.metrics.abstention.record_abstention(code, detail=None)#
Tag the current naming session with an abstention code.
First-writer-wins: if a code is already recorded for this session the call is a no-op, so the earliest (closest-to-root-cause) site keeps the attribution. Never raises; never alters naming output.
- orthonym.metrics.abstention.record_suppression(code, detail=None, candidate=None)#
Tag from a POST-GENERATION site (downgrade gate / correctness gate) that is rejecting
candidate.When
candidateis a real name (not failure-marked), generation provably completed, so a speculative generation-stage record from an exploratory dead path is overridden bycode. A failure-marked candidate (the branch marker got glued into the name) keeps the earlier generation-stage attribution. Post-generation records are never overridden (first-wins among themselves). Never raises.