orthonym.metrics.provenance#
Note
Internal API. Names and behaviour may change between releases.
: per-call naming provenance (tier derivation inputs).
Observation-only contextvars — the default naming path’s BEHAVIOR is untouched; sites merely record where the shipped name came from.
- orthonym.metrics.provenance.GATE_OUTCOME_NOT_RUN = 'not_run'#
no gate call was recorded for this naming session (the default).
- orthonym.metrics.provenance.GATE_OUTCOME_BYPASSED = 'bypassed'#
an outcome WAS recorded, but for a different string than the one shipped (e.g. _apply_trivial_fallback ships a retained name the gate never saw).
- orthonym.metrics.provenance.GATE_OUTCOME_DISABLED = 'gate_disabled'#
_DISABLE_VALIDITY_GATE (env) or _disable_opsin_validity_gate (instance).
- orthonym.metrics.provenance.GATE_OUTCOME_UNAVAILABLE = 'unavailable'#
jar absent / transient OPSIN failure — the gate failed OPEN.
- orthonym.metrics.provenance.GATE_OUTCOME_DESCRIPTIVE_FALLBACK = 'descriptive_fallback'#
the name handed to the gate was already a descriptive-fallback sentinel, so the gate skipped it (nothing was verified).
- orthonym.metrics.provenance.GATE_OUTCOME_SUPPRESSED = 'suppressed'#
the gate suppressed a candidate to the descriptive fallback.
- orthonym.metrics.provenance.GATE_OUTCOME_AMBIGUOUS_SUPPRESSED = 'opsin_ambiguous_suppressed'#
the gate suppressed a candidate that OPSIN parsed to the input but read as ambiguous (warning
APPEARS_AMBIGUOUS,validation.opsin_ambiguity); the name is named once more with every locant cited before it is withdrawn.
- orthonym.metrics.provenance.GATE_OUTCOME_SELF01 = 'self_consistency_verified'#
OPSIN parsed the FULL name and returned verdict “ok”. The ONE state that may claim a bare.
- orthonym.metrics.provenance.GATE_OUTCOME_SELF01_CONSTITUTION_ONLY = 'self_consistency_constitution_only'#
judged the stereo-STRIPPED parse, so the CONSTITUTION is verified and the stereo layer is NOT.
- Type:
the OPSIN-validity stereo carve-out
- orthonym.metrics.provenance.GATE_OUTCOME_SELF01_INCONCLUSIVE = 'self_consistency_inconclusive'#
ran and could not compare (fail-OPEN) — nothing was proven.
- orthonym.metrics.provenance.GATE_OUTCOME_SELF01_SKIPPED = 'self_consistency_skipped'#
was a no-op (_SC_MODE == “off”, or no input SMILES to compare to).
- orthonym.metrics.provenance.GATE_OUTCOME_SELF01_WARN_MISMATCH = 'self_consistency_warn_mismatch'#
PROVED a different molecule but _SC_MODE == “warn” shipped it.
- orthonym.metrics.provenance.GATE_OUTCOME_STEREO_RECOMPOSED = 'stereo_omission_full_key_recomposed'#
the general-fallback stereo-OMISSION reclaim COMPOSED the input’s dropped stereo back onto a constitution-verified flat name and re-verified that the composed name recomputes to the input’s FULL InChIKey. That check is strictly STRONGER than (it compares the full stereo layer, not just the skeleton), so this is a genuine VERIFIED state — not a by-design carve-out that ships unproven. (It used to be recorded as
carveout:stereo_omission_reanchor, which mislabels a full-key-verified name asunverified— a review -P2 F3.)
- orthonym.metrics.provenance.GATE_OUTCOME_CARVEOUT_PREFIX = 'carveout:'#
prefix for the ten by-design return name carve-outs: carveout:<slug>.
- orthonym.metrics.provenance.GATE_OUTCOME_FULL_KEY_VERIFIED = 'full_key_round_trip_verified'#
at a general tier,
name_tieredchecked the shipped string itself because no verified outcome was recorded for it (an offer the pool picked after the gate had seen another string, or an outcome recorded for a different string): OPSIN read the name and the FULL InChIKey of what it read equals the input’s. That is the round trip the paper claims for every shown name, and stronger than, so it claims the plain “verified” label.- Type:
claims conformance (2026-09-27)
- orthonym.metrics.provenance.GATE_OUTCOME_TWIN_PREFIX = 'twin_verified:'#
OPSIN has no grammar for the name, and it reads a twin spelling of the same structure (
validation.twin_spellings) to the input’s FULL InChIKey. The producer owns the spelling; the twin proves the structure.- Type:
prefix of
twin_verified:<rule ids>
- orthonym.metrics.provenance.GATE_OUTCOME_ACID_SPLIT_PREFIX = 'acid_split_verified:'#
OPSIN has no grammar for the name (a di- or poly-anhydride), and it reads each acid the name cites, to the structures a poly-anhydride built from those acids has the input’s FULL InChIKey and descriptors of (
validation.anhydride_acids). OPSIN never reads the name, or a spelling of it.- Type:
prefix of
acid_split_verified:<rule>
- orthonym.metrics.provenance.VERIFIED_OPSIN_LABELS = ('verified', 'verified_twin', 'verified_acid_split')#
the name itself, its twin spelling, or the acids of a poly-anhydride name
- Type:
the
opsinlabels of a name that was read back to the input’s full structure
- orthonym.metrics.provenance.VERIFIED_FIELD_BY_OPSIN_LABEL = {'verified': 'opsin', 'verified_acid_split': 'opsin_acids', 'verified_constitution_only': 'opsin_constitution', 'verified_twin': 'opsin_twin'}#
the
verifiedfield of a row by theopsinlabel of its gate outcome
- orthonym.metrics.provenance.VERIFIED_FIELD_FOR_TIER = ('opsin', 'opsin_twin', 'opsin_acids', 'identity')#
a read-back of the name, or of its twin spelling, of the acids of a poly-anhydride name, or the exact-match list identity
- Type:
the values of
verifiedthat earn a tier named “verified”
- orthonym.metrics.provenance.note_touched(*names)#
Public: record that
nameswere written by a path that bypasses the setter functions (a replay-memo HIT writes the ContextVars directly). Lets an enclosing touched-log still capture them.
- orthonym.metrics.provenance.push_touched_log()#
Arm a fresh touched-var log for the current nested call and return it. Pair with:func:pop_touched_log in a try/finally (LIFO).
- orthonym.metrics.provenance.pop_touched_log()#
Disarm the innermost touched-var log and return it (LIFO).
- orthonym.metrics.provenance.push_non_pin_log()#
Arm a fresh record-call log; pair with:func:pop_non_pin_log (LIFO).
- orthonym.metrics.provenance.pop_non_pin_log()#
Disarm the innermost record-call log and return it (LIFO).
- orthonym.metrics.provenance.clear_provenance()#
- orthonym.metrics.provenance.append_missing(base, extra)#
basefollowed by the items ofextrathatbasedoes not hold, in order: the mergerestore_provenancemakes of a snapshot and the live value of an accumulating record, and the merge a memo hit makes of the record its fresh call left. The records only grow within a naming call, so a giant molecule’s tuples hold thousands of names; the membership test is a set lookup, not a scan ofbasefor each item (that scan made every merge quadratic in the length of the record).
- orthonym.metrics.provenance.restore_provenance(snapshot)#
Re-set every provenance ContextVar from a
get_provenancedict.The inverse of:func:get_provenance. A caller that speculatively runs a producer which records provenance (
record_sourceet al.) and then REJECTS its candidate must restore the pre-attempt provenance, otherwise the kept emission carries the rejected producer’s label. Used by the Engine-3 NP→von-Baeyer downgrade, whose_try_general_engine_recoveryprobe stampssource="general_engine"before the RT gate can decline it.The name-scoped non-PIN record (
record_non_pin_fragment) is the one exception: it only grows within a naming call (clear_provenanceresets it at a call boundary), so a restore keeps the fragments recorded since the snapshot. A rejected attempt leaves cache entries behind – the scope memo (assembly.memo.cache_or_compute) and the fragment cache return a stored string without the record its computation made – so dropping the record let a later cache hit ship a recorded non-PIN spelling as if none had been recorded, and the result then depended onORTHONYM_MEMO(branch review, 2026-09-28: ‘C[C@@H](CN(C[C@@H]1CCC=CC1)C)O’ was named at the PIN tier with the memo on and abstained with it off, through the ‘(R)-(cyclohex-3-en-1-yl)meth’ record thatrules.pin_vocabulary.promote_at_pin_tierrolled back). A kept record only demotes a name that CONTAINS the recorded spelling.
- class orthonym.metrics.provenance.isolated_provenance#
Bases:
objectContext manager: every provenance variable, the name-scoped records included, is exactly what it was on entry when the body exits, and the record calls the body made are taken out of the armed record-call logs again.
For a check that names prefixes only to compare two parents (
perception.chains.chain_parent_prefix_seniority) and whose own verdict is recorded after it, outside the body. Unlike:func:restore_provenance, the non-PIN records the body made are dropped too: the body’s namings run throughname_substituent_for_ordering, whose memo and fragment-cache writes are discarded on exit (memo.push_sandbox,speculative_fragment_naming), so no later cache hit can return a string whose record was dropped; a record kept from such a body would lower the label of a name the real naming built by another route only because the check ran. A provenance read in the body stays in the logs (PROVENANCE_READ), so an enclosing memo still declines to store a call whose path read provenance. Only a variable the body changed is written back.
- orthonym.metrics.provenance.record_source(source, opsin=None)#
- orthonym.metrics.provenance.producer_record()#
The producer record of the call so far:
(source, opsin)asrecord_source()left them. Pair with:func:restore_producer_record around an attempt whose name may be discarded. The value read is only written back to the record, never used to build a name, so the read is not logged as a provenance read (PROVENANCE_READ).
- orthonym.metrics.provenance.restore_producer_record(record)#
Re-set
sourceandopsintorecord(a:func:producer_record value). A variable that already holds its value is not written, so a call that left the record unchanged touches nothing.
- orthonym.metrics.provenance.record_stereo_unexpressed(flag)#
T6.4: mark the current emission as constitution-only (stereo defined on the input but not expressed in the name). Set at the flagged best-effort ship site; read by
name_tiered.
- orthonym.metrics.provenance.record_suffix_free_prefix_name(flag)#
: mark the current emission as citing the principal characteristic group as a PREFIX with no suffix – ill-formed per (see the ContextVar comment). Set only at the PG-suppressed assembly site; read by
name_tieredand surfaced per row so can enumerate the debt.
- orthonym.metrics.provenance.record_gate_outcome(outcome, name)#
T1: record what _final_opsin_validity_gate DID, and for WHICH string. Called at every return of the gate (and of _self_consistency_decision, which owns the gate’s exits).
namemust be the string the gate is about to RETURN, not the one it was handed — on a suppression those differ, and the outcome belongs to what actually ships.
- orthonym.metrics.provenance.carveout_outcome(slug)#
carveout:<slug>— a by-design return name carve-out. The name is shipped deliberately despite an OPSIN coverage gap; it is NOT verified.
- orthonym.metrics.provenance.twin_outcome(rules)#
twin_verified:<rule ids>— the name ships on its construction, and a twin spelling OPSIN reads round-trips to the input’s full InChIKey.
- orthonym.metrics.provenance.acid_split_outcome(rule)#
acid_split_verified:<rule>— the name ships on its construction, and the acids it cites, read by OPSIN, build a structure that is the input’s (see:data:GATE_OUTCOME_ACID_SPLIT_PREFIX).
- orthonym.metrics.provenance.resolve_gate_outcome(outcome, outcome_name, shipped_name)#
The outcome that applies to
shipped_name— deny-by-default.A recorded outcome only counts for the exact string it was recorded for. Paths that ship a name the gate never saw (_apply_trivial_fallback returns a retained name only AFTER the gate has suppressed the systematic candidate, so the recorded outcome then belongs to a DIFFERENT string) get
bypassed, never the previous name’s verdict.
- orthonym.metrics.provenance.opsin_label_for_gate_outcome(outcome)#
verified/verified_constitution_only/verified_twin/verified_acid_split/unverified.Allowlist, so it fails closed: any outcome not explicitly listed — including a state that does not exist yet — reports
unverified.
- orthonym.metrics.provenance.gate_token_for_gate_outcome(outcome)#
The gates_passed token this outcome earns, or None if it earns none.
- orthonym.metrics.provenance.record_general_ring_prefix()#
-T1c: mark that a PIN-path (
composer) name contains a ring substituent prefix that only the GENERAL tier could produce.Tier and
is_pinare decided fromsourcealone (namer.py:2728), and every composer emission reportssource='pin_path'->T1,is_pin=True. A systematic replacement / von Baeyer substituent form is a VALID name but not the PREFERRED one, so shipping it under that label would assert PIN status for a non-PIN name – measured onOC(=O)CC12CC3CC(O)(CC(C3)C1)C2, whose ring PIN is the retained name adamantane, nottricyclo[3.3.1.1^3,7]decane.This flag lets
name_tiereddemote exactly those emissions to the general tier while leaving every other composer emission untouched. It is deliberately one-way (never cleared) for the duration of a naming call.
- orthonym.metrics.provenance.record_pin_promotion_rerun()#
Mark the name about to ship as built by the PIN tier’s promotion re-run (see
_PIN_PROMOTION_RERUN): labelled pin_unverified, never pin_verified. Only when a breadth piece the re-run kept (record_breadth_promotion) is part of the name: a name whose every piece a strict producer built (assembly.strict_ring_prefix) is the strict path’s own name. A piece kept in a route the re-run then left does not count (the label would depend on the input atom order); with no name to read the whole call is flagged.
- orthonym.metrics.provenance.record_breadth_promotion(name)#
Record a name
promote_at_pin_tierkept: a piece a best-effort producer built (see_BREADTH_PROMOTED_NAMES).
- orthonym.metrics.provenance.record_non_pin_fragment(fragment)#
Record a name fragment that a producer built and that is valid (the whole name is still round-trip verified) but is never part of a PIN – e.g. a carbon-substituted N+ cited as ‘trimethylazaniumyl’, whose PIN form ‘…methanaminiumyl’ cannot be verified.
Unlike
record_general_ring_prefixthis is NAME-SCOPED:name_tiereddemotes the shipped name only if it CONTAINS a recorded fragment. A producer that runs speculatively (a // sort key naming a prefix) or whose candidate is discarded (a later gate rejects it and another path names the molecule) therefore cannot demote a name that does not carry its fragment.
- orthonym.metrics.provenance.record_non_pin_label(fragment, rule=None, detail='')#
Record
fragmentas a LABEL-ONLY non-PIN part (see_NON_PIN_LABELS): a shipped name that contains it is labelled below the PIN; the PIN tier’s promotion re-run still ships it.rule(a Blue Book rule id, withdetailsaying how) is the reason the fragment is not the PIN form: the row of a name the record lowers lists it inspelling_failures(seenon_pin_label_rule_failures).
- orthonym.metrics.provenance.record_uncertified_pin_name(name)#
Record
nameas a PIN-form name whose preferred status the Blue Book leaves open (see_UNCERTIFIED_PIN_NAMES): a shipped name that contains it is labelled pin_unverified, is_pin False.
- orthonym.metrics.provenance.record_verified_through_split(name)#
Record that
namewas read back to the drawing of the input without its dative bonds (assembly.metal_offer), not to the drawing as written.verified_fieldthen reportsopsin_splitfor the name in place ofopsin.
- orthonym.metrics.provenance.verified_field(verified, prov, name)#
The
verifiedfield of a row:opsinbecomesopsin_splitfor a name recorded byrecord_verified_through_split()(OPSIN read the whole name back to the drawing of the input without its dative bonds, whose standard InChIKey is the reference, and an independent count of atoms and charges ties that drawing to the input); every other value is unchanged.
- orthonym.metrics.provenance.record_derived_uncertified_pin_name(source, derived)#
Record
derivedas an uncertified PIN-form name whensourcecontains a recorded one: a name built fromsourceby a splice that leaves every locant ofsourceas it is (an isotopic descriptor that needs no locant) keeps the status ofsource, since the recorded string does not survive the splice.
- orthonym.metrics.provenance.record_derived_non_pin_fragment(source, derived, _item=None)#
Record
derivedas a non-PIN fragment whensourcecontains a recorded one: a form built from a non-PIN name by a string conversion (an acid name turned into its acyl prefix) keeps the source’s status, since the recorded substring does not survive the conversion.The call is logged as it was made (
('D', source, derived)), and the record it makes when it fires is not: a replay of the call decides again against the record of the replay, where a replay of the record would addderivedalso when the record holds no fragment ofsource. A replay passes the stored item as_item, so the logs share it.
- orthonym.metrics.provenance.compact_non_pin_log(items, cap=None)#
The record-call log
itemsof a call, as an equivalent tuple with the no-op repeats removed: its replay (replay_non_pin_log()) leaves any record as the replay ofitemsleaves it; None when the call read provenance (PROVENANCE_READ) or the result holds a derived call and more thancapitems (NON_PIN_LOG_CAP; a log of plain items is stored whatever its length, as it always was). The record only grows under a replay, so an item is left out when it changes nothing after the items kept before it:a fragment recorded before (
record_non_pin_fragmentadds it whatever the record holds);a derived call whose
derivedis such a fragment (it adds that or nothing);a repeat of a derived call, unless a kept item since its last kept occurrence adds a fragment that is a substring of its
source: with none, the record holds a fragment ofsourceat the repeat only if it held one at the earlier call, which then addedderivedalready. Dropping every repeat would lose thederivedof a call that found no fragment ofsourcethe first time and finds one that a later item recorded.
Each kept item is tested once against each derived call, and a log with a derived call stops at the cap, so the cost is bounded by the square of the cap.
- orthonym.metrics.provenance.replay_non_pin_log(items)#
Make the record calls of a stored log again, in order, into every armed log: a plain item through:func:record_non_pin_fragment, a derived call through
record_derived_non_pin_fragment().
- orthonym.metrics.provenance.name_carries_non_pin_part(prov, name, *, label_forms=True)#
True when
namemust not be labelled a PIN: the whole-callgeneral_ring_prefixflag, the whole-callpin_promotion_rerunflag (the PIN tier’s promotion re-run built the name), or a recorded non-PIN fragment it contains.label_formsis passed torules.pin_vocabulary. non_pin_vocabulary.
- orthonym.metrics.provenance.non_pin_label_rule_failures(prov, name)#
The reasons of the label-only records that
namecontains and that name a rule (record_non_pin_label(..., rule=...)), asspelling_failuresentries{"rule":..., "detail":...}in record order, one per rule and detail.
- orthonym.metrics.provenance.get_provenance()#