Three load-bearing pieces:
1. ADR-0086 — UNKNOWN-intent pack-resident token surface
New deterministic composer `pack_grounded_unknown_surface` in
chat/pack_grounding.py. When intent classification returns UNKNOWN
but the prompt contains pack-resident lemmas (via cross-pack
resolver), surface those lemmas with their semantic_domains
instead of falling to the bare _UNKNOWN_DOMAIN_SURFACE. Wired
into chat/runtime.py::_maybe_pack_grounded_surface as the
last typed-intent branch before the OOV fallback. Null-lift
invariant pinned: fully-OOV prompts still emit the universal
disclosure byte-identically. Closes four cognition-eval term
misses: unknown_logos_019 (public), unknown_evidence_042 (dev),
unknown_spirit_041 + unknown_word_018 (holdout). Side effect:
evals/results/phase2_pack_measurements.json refusal_rate drops
from 0.25 → 0.125 across all three identity packs (no longer
refusing on these prompts).
2. ADR-0087 — PROCEDURE selector + trailing-clause subject echo
Two coupled changes in chat/pack_grounding.py:
(a) Numeric-determiner downrank in _extract_procedure_topic_lemma:
tokens whose primary semantic_domain starts with
"quantitative.numeric." are demoted; non-numeric resident
candidates always win. So "compare two terms" anchors on
`compare` not `two`.
(b) Trailing clause echoes the full normalized subject_text
rather than just the selected lemma, so OOV head nouns like
"terms" reach the surface even when only the procedure verb
is pack-resident. Closes procedure_compare_011.
3. 100-register catalog
New packs/register/_catalog.json — canonical machine-readable
spec for all 100 registers (7 currently-ratified + 93 drafted)
organized into 9 voice groups (depth/tone/stance/posture/domain/
cultural/affective/functional/composite). Each entry is a
complete production input — realizer_overrides, marker palettes
(openings/transitions/closings), depth_preference, description,
author_notes. All realizer_overrides use only legal keys per
scripts/ratify_register_packs.py::_KNOWN_OVERRIDE_KEYS.
Companion packs/register/CATALOG.md documents the production
loop: materialize → widen REGISTER_IDS → ratify → smoke.
Cognition-eval lifts (all three splits):
public: term_capture 91.7% → 100.0% (+8.3pp)
holdout: term_capture 83.3% → 100.0% (+16.7pp)
dev: term_capture 78.6% → 100.0% (+21.4pp)
surface_groundedness: 100% preserved on all splits
intent_accuracy / versor_closure: 100% preserved on all splits
Tests:
tests/test_pack_grounded_unknown.py — 14 tests (composer
direct + runtime engagement + null-lift invariant)
tests/test_adr_0087_procedure_selector.py — 12 tests (selector
numeric downrank + trailing-clause echo + regression guard)
Existing test suites unaffected — cognition lane 120 passed / 1
skipped both before and after. Full lane net −3 failures vs
pristine main (39 → 36 — none introduced).
4.2 KiB
4.2 KiB
Register pack catalog — production guide
packs/register/_catalog.json is the canonical, machine-readable spec for the
100-register catalog. Each entry is a complete production input — an author
or content pipeline materializes packs/register/<register_id>.json from it
mechanically and re-runs ratification.
| Group | Count | Voice |
|---|---|---|
| A — Depth ladder | 6 | Varies disclosure_domain_count + structural booleans. No markers. |
| B — Tone | 16 | Affective marker palettes. Default knobs. |
| C — Stance | 12 | Epistemic posture — assertive, hedged, exploratory, etc. |
| D — Posture | 10 | Social role — peer, mentor, scholar, etc. |
| E — Domain | 12 | Academic, technical, legal, scientific, philosophical, etc. |
| F — Cultural | 12 | Plainspoken, cosmopolitan, classic, lyrical, etc. |
| G — Affective | 10 | Cheerful, somber, wry, gentle, etc. |
| H — Functional | 10 | Documentary, instructional, persuasive, etc. |
| I — Composite | 12 | Combine knobs from multiple groups. |
| Total | 100 | 7 ratified + 93 drafted |
Production loop
For each entry whose status == "drafted":
- Materialize
packs/register/<register_id>.jsonfrom the catalog entry. Required fields:register_id,version(set to"1.0.0"),description,schema_version("1.0.0"),mastery_report_sha256(leave""— the ratify script will fill it),display_name,depth_preference,realizer_overrides,discourse_markers. - Widen
scripts/ratify_register_packs.py::REGISTER_IDSto include the newregister_id. - Ratify:
python scripts/ratify_register_packs.py. Idempotent; re-runs produce byte-identical files. - Test: the ratification script writes the
.mastery_report.jsoncompanion and updatesmastery_report_sha256in the pack file. Runpython -m pytest tests/test_register_loader.py -qto confirm the loader self-seal check passes. - Smoke:
core chat "Test prompt" --register <register_id>should produce a surface whosegrounding_sourceandtrace_hashare byte-identical to the same prompt underdefault_neutral_v1(ADR-0072 register invariant). Only the surface text varies.
Trust boundaries
realizer_overridesis restricted to the allow-list inscripts/ratify_register_packs.py::_KNOWN_OVERRIDE_KEYS:disclosure_domain_count(1, 2, or 3),compress_gloss,drop_articles,drop_provenance_tag,append_semantic_domain_clause, plusper_intentnested block keyed byIntentTagnames. Any other key fails ratification.discourse_markershas exactly three buckets:openings,transitions,closings. Each is a list of strings. An empty string""inside a bucket is a legal entry — the seeded selector (ADR-0071) treats it as "no marker this turn", enabling natural variation.
Author guidance
- Keep each marker palette small (3–5 entries per non-empty bucket). Larger palettes are not better — the seeded selector wants a tight bounded space so per-turn variation is felt without being noisy.
- Include
""inopeningsandclosingsfor ~20–30% of registers so the system has a "land plainly" option per turn. - Markers may contain Unicode em-dash (—), ASCII punctuation, and standard English contractions. Avoid emoji and non-English script unless the register's purpose is explicitly multilingual.
- For composite registers (group I), the
descriptionfield should name the two constituent voices it combines.
Invariants pinned by ADR-0072 / ADR-0071
Every register in this catalog must satisfy, on every prompt:
grounding_sourceis byte-identical todefault_neutral_v1.trace_hashis byte-identical todefault_neutral_v1.aggregate metrics(cognition eval lane) are byte-identical.- Only the surface text varies.
The core demo register-tour runner exists to assert this. New registers
should be added to its sweep once authored.
Next steps after authoring
- Update the cognition eval's register-invariance test fixtures to include the new register ids (sweep, no per-register code change).
- Optional follow-up: add a
register_distribution_liftbenchmark (ADR-0072 variant) that measures surface-variance across the full 100-register sweep for a fixed prompt corpus.