* feat(packs): ethics ×3, anchor-lens ×3, relations-v3, register ×2
Group 1 — Ethics domain packs (ADR-0044 sibling)
legal_ethics_v1: 6 commitments covering no-legal-advice, no-outcome-prediction,
jurisdiction-disclosure, privilege-disclosure, conflict-disclosure, refer-to-counsel
engineering_ethics_v1: 6 commitments covering safety-primacy, standard-disclosure,
no-sign-off, uncertainty-surface, public-welfare-priority, refer-to-pe
research_ethics_v1: 6 commitments covering no-fabrication, no-plagiarism,
irb-disclosure, conflict-of-interest-disclosure, data-integrity, reproducibility-hedge
ratify_ethics_pack.py: PACK_IDS extended with all three new ids
Group 2 — Anchor lens packs (grc cognition atoms, ADR-0073c)
grc_sophia_v1: atom logos.sophia.wisdom via grc-core-cog-008 (cross_lang.logos.sophia
edge weight 0.88); cognitive mode wisdom-practical
grc_epignosis_v1: atom logos.epignosis.experiential via grc-core-cog-007 (weight 0.78,
en_collapse edge documented); cognitive mode experiential-knowledge
grc_episteme_v1: atom logos.episteme.systematic via grc-core-cog-021 (weight 0.72,
en_collapse edge documented); cognitive mode systematic-knowledge
ratify_anchor_lens_packs.py: LENS_IDS extended with all three new ids
Group 3 — en_core_relations_v3 (social + part-whole extension of v2 kinship)
7 new lemmas: colleague, mentor, neighbor, component, member, instance, peer
manifest.json: new pack with checksum placeholder (operator must recompute after
ratify run — same pattern as other packs)
Group 4 — Register packs formal_v1 + socratic_v1
formal_v1: standard depth, drop_provenance_tag=true + drop_articles=true;
no markers; ratifies under known_key_overrides_invariant_grounding
socratic_v1: pedagogical depth, append_semantic_domain_clause=true; markers scaffold
question-and-response rhythm (openings×4, transitions×3, closings×4)
ratify_register_packs.py: REGISTER_IDS extended with formal_v1, socratic_v1
* fix(anchor_lens): loader v1/v2 dual-schema compat — resolves blocker 1 of #48
Refactor AnchorLens to use v2 schema fields and normalize legacy fields. Update validation and loading functions for improved clarity and functionality.
* fix(ratify): restore default_unanchored_v1 + full LENS_IDS (17) — resolves blocker 2 of #48
Added new lens IDs for the he substrate and updated the order of lens IDs.
* chore(packs): migrate 8 legacy anchor-lens packs to v2 schema [1/8 default_unanchored_v1]
Updated the default unanchored lens JSON structure with new fields and modified descriptions.
* chore(packs): migrate grc_logos_v1 to v2 schema [2/8]
Updated the description and added new fields for cognitive mode, atom, and source entry ID.
* chore(packs): migrate grc_aletheia_v1 to v2 schema [3/8]
Updated the description and added new fields related to cognitive mode and atom.
* chore(packs): migrate grc_zoe_v1 to v2 schema [4/8]
Updated the description and added new fields for cognitive mode, atom, and source entry ID.
* chore(packs): migrate grc_arche_v1 to v2 schema [5/8]
Updated the description and added new fields for cognitive mode, atom, and source entry ID.
* chore(packs): migrate he_logos_v1 to v2 schema [6/8]
Updated the Hebrew-substrate anchor lens JSON structure with new fields and modified descriptions.
* chore(packs): migrate he_dabar_v1 to v2 schema [7/8]
Updated the description and added new fields for cognitive mode and source entry.
* chore(packs): migrate he_chayyim_v1 to v2 schema [8/8] — resolves blocker 3 of #48
Updated the description and added new fields for cognitive mode and source entry ID.
* fix(anchor-lens): complete v1→v2 migration + back-compat shims
Resolves blockers B4/B5/B6/B7 left by the initial round-2 schema rewrite:
B4: restore UNANCHORED module constant, is_null_lens() alias,
and verify_anchor_lens_seal() (all were dropped from loader.py;
chat/pack_grounding.py and several tests still imported them).
AnchorLens.unanchored() returns the in-memory sentinel with
lens_id='__unanchored__' as before (distinct from disk pack).
B5: add v1 attribute properties on AnchorLens (primary_substrate,
semantic_domain_preferences, cognitive_mode_label) so consumers
not yet on v2 (chat/pack_grounding.py engagement reads, several
tests) continue to work via read-only views over the canonical
v2 fields. Zero changes needed to chat/pack_grounding.py.
B6: re-derive source_entry_id by atom-in-lexicon lookup for 6 of 8
legacy packs that were positionally mis-mapped during migration.
B7: fix two new-pack atoms that didn't exist in the lexicon
(logos.episteme.systematic -> logos.episteme.systematic_knowledge,
logos.epignosis.experiential -> logos.epignosis.knowledge).
Loader hardening (recovered from v1 rewrite):
- _validate_lens_id_for_fs: reject path-traversal / slash / empty
- companion-SHA mismatch check in load_anchor_lens when require_ratified
- atom must be non-empty when substrate != 'none'
- available_anchor_lens_packs returns summary dicts (was list[str])
Ratify script special-cases substrate='none' so the null sentinel
default_unanchored_v1 keeps its self-seal (ADR-0073b invariant).
Test suite migrated to v2 schema: dropped obsolete list-shape gates
(duplicates, too-many-preferences — v2 has scalar atom), updated error
match strings, added a v1->v2 normalisation back-compat test.
All 11 round-2 packs ratified. 102/102 anchor-lens tests pass.
Cognition eval byte-identical (100/100/91.7/100).
anchor-lens-tour + register-tour both green.
Umbrella ADR-0073 ratified (Accepted); L1.1 content phase
(ADR-0073a) landed. Pure pack enrichment — no runtime code, no
composer change, no test of behaviour. Substrate prerequisite for
the L1.2–L1.4 phases.
Greek additions (grc_logos_cognition_v1, 20 → 29 entries)
Knowledge family (English collapses to `knowledge`):
- ἐπιστήμη logos.episteme.systematic_knowledge
- σύνεσις logos.synesis.insight
(γνῶσις at grc-core-cog-007 unchanged — treated as the
experiential variant by the L1.3 lens config)
Love family (English collapses to `love`):
- ἀγάπη logos.agape.covenant_love
- φιλία logos.philia.companion_love
- ἔρως logos.eros.passionate_love
- στοργή logos.storge.familial_love
Time family (English collapses to `time`):
- αἰών logos.aion.age_era
- χρόνος logos.chronos.clock_time
- καιρός logos.kairos.opportune_moment
Hebrew additions (he_core_cognition_v1, 20 → 23 entries)
- חסד logos.chesed.covenant_loyalty
- שלום logos.shalom.wholeness_peace
- צδק logos.tzedek.right_order
Alignment.jsonl on both cognition-tier packs (previously only the
micro packs carried alignment)
- grc_logos_cognition_v1/alignment.jsonl — 20 edges: three-way core
dyads (word / truth / light / life / beginning / wisdom),
knowledge-family → en collapse, ἀγάπη↔חסד covenant-love pairing
(weight 0.86, Septuagintal), `cross_lang.no_english_collapse`
annotations for love + time families pointing at
`en-collapse-<family>` sentinel ids (weight 0.0).
- he_core_cognition_v1/alignment.jsonl — 7 edges: core dyads to en,
חסד↔ἀγάπη covenant pairing, no-english-collapse annotations for
חסד / שלום / צδק.
Manifest checksums refreshed per CLAUDE.md doctrine
- grc_logos_cognition_v1: b45bcf581cee… → 0f9436675707…
- he_core_cognition_v1: dee1e8c6ad9a… → 22145d008185…
Design decisions
- Existing 20 + 20 lemma atoms untouched — downstream tests /
composers / teaching chains keep referencing the same atoms.
Only new lemmas carry the distinguishing atoms.
- `cross_lang.no_english_collapse` edges are metadata not data
(sentinel target ids, weight 0.0). Their purpose is letting the
alignment graph answer "does English split this family?" without
forcing an artificial English lemma.
- Every new entry carries `adr-0073a:hand_authored:2026-05-19` in
its `provenance_ids` so future audits can find the L1.1 cohort
deterministically.
Verification
- python -m language_packs verify grc_logos_cognition_v1 → OK
- python -m language_packs verify he_core_cognition_v1 → OK
- python -m language_packs compile <both> → 29 / 23
manifold points; spot-check confirms καιρός / צδק resolve.
- python -m core.cli eval cognition → public
100 / 100 / 91.7 / 100 byte-identical (new lemmas sit on disk but
no composer references them yet).
- python -m core.cli test --suite cognition → 120/1 pass
- python -m core.cli test --suite smoke → 67/0 pass
- python -m core.cli test --suite full → 2632 passed
/ 4 skipped / 1 pre-existing failure (test_all_preamble_explains_
combined_run rename drift, unrelated).
- core demo register-tour → exit 0
(R5 seam still holds; L1.1 doesn't touch register pathway).
What L1.1 deliberately does NOT do
- No AnchorLens class (that's L1.2 / ADR-0073b).
- No composer wiring (L1.3 / ADR-0073c).
- No --anchor-lens CLI flag or demo (L1.4 / ADR-0073d).
- No teaching corpus in non-English (post-L1).
Phase C of the gloss feature. Lands the natural-language gloss
content that the resolver (Phase B2) and the runtime composer
(Phase B3) were prepared for. This is the user-visible payoff:
cold-start DEFINITION / RECALL prompts on pack-resident lemmas now
emit fluent grounded sentences instead of dotted-domain disclosure.
Authoring: five parallel subagents in ONE message block (a single
parallel dispatch, ~20s wall-clock vs ~95s sequential). Each
subagent received its pack's complete lemma + POS list and a strict
JSON-shape exemplar. Total returned: 326 raw gloss entries.
Assembly (this commit): the raw entries were partitioned by
lexicon-residency lookup (the resolve_gloss invariant enforced at
storage time), deduplicated within pack, sorted by lemma, written
to ``language_packs/data/<pack>/glosses.jsonl``, and each pack's
manifest received a new ``glosses_checksum`` field. 323 glosses
landed clean; 0 rejected.
Per-pack distribution:
en_core_cognition_v1 78 glosses
en_core_meta_v1 72 glosses
en_core_attitude_v1 40 glosses
en_core_temporal_v1 28 glosses
en_core_action_v1 26 glosses
en_core_quantitative_v1 24 glosses
en_core_spatial_v1 24 glosses
en_core_polarity_v1 16 glosses
en_core_causation_v1 15 glosses
Live-probe lift (fresh ChatRuntime per prompt):
BEFORE:
truth — pack-grounded (en_core_cognition_v1):
cognition.truth; logos.core; epistemic.ground.
No session evidence yet.
AFTER:
Truth is a claim or state grounded by evidence and coherent
judgment. pack-grounded (en_core_cognition_v1).
Same provenance. Same audit-trail content (the dotted domains are
still in lexicon.jsonl, the resolver can still read them, the
candidate object carries them verbatim). But the user-facing
surface is a sentence the user can actually read.
Eval-lane lift:
deterministic_fluency BEFORE AFTER
no_dotted_inventory_rate 0.3333 → 1.0000
no_provenance_only_rate 1.0000 → 1.0000 (held)
no_placeholder_rate 1.0000 → 1.0000 (held)
complete_punctuation_rate 1.0000 → 1.0000 (held)
finite_predicate_shape 1.0000 → 1.0000 (held)
surface_provenance_match 1.0000 → 1.0000 (held)
cold_start_grounding all metrics held at 1.0
warmed_session_consistency no_placeholder + telemetry_match held at 1.0
(warm_grounding_stability still 0 — separate fix)
cognition eval public 100 / 100 / 91.7 / 100 (BYTE-IDENTICAL)
cognition eval holdout 100 / 100 / 83.3 / 100 (BYTE-IDENTICAL)
The cognition eval bytes-identity holds because the eval checks
substring containment (case-insensitive after the format change).
Every lemma still appears in its fluent surface.
Hardening this commit enforces:
Lexicon-residency at storage time
tests/test_pack_glosses_content.py::test_every_gloss_lemma_is_lexicon_resident
walks every glosses.jsonl and asserts every lemma is present in
the same pack's lexicon.jsonl. Drift in glosses (an unratified
lemma sneaking in) fails the lane immediately.
Dual-checksum discipline
tests/test_pack_glosses_content.py::test_every_glossed_pack_has_matching_checksum
re-hashes glosses.jsonl bytes-on-disk and compares against the
manifest's glosses_checksum. Any tampering fails.
Immutable-lexicon invariant
tests/test_pack_glosses_content.py::test_lexicon_checksum_unchanged_by_gloss_landing
re-hashes lexicon.jsonl and compares against the manifest's
(original) checksum. Proves that adding glosses did NOT perturb
the lexicon seal.
High-freq lemma resolution
32 of the most-common conversational lemmas (truth, doubt,
fact, idea, self, true, important, now, place, make, effect,
always, ...) all resolve to a fluent surface end-to-end.
Test-suite drift this commit absorbed:
- tests/test_pack_grounding.py — three substring assertions
updated to be case-insensitive (gloss-backed surfaces capitalize
lemmas at sentence start, dotted-disclosure surfaces don't).
"No session evidence yet" assertion replaced with the
common-substring "pack-grounded" marker that BOTH forms emit.
- tests/test_pack_resolver_glosses.py — the back-compat test
pivots from en_core_cognition_v1 (now glossed) to en_minimal_v1
(deliberately unglossed). A new test pins the glossed case.
Files added:
language_packs/data/<pack>/glosses.jsonl (9 files, 323 entries)
tests/test_pack_glosses_content.py (9 contract tests)
Files modified:
language_packs/data/<pack>/manifest.json (9 files, glosses_checksum field)
chat/pack_grounding.py (lowercase "pack-grounded" tag)
tests/test_pack_grounding.py (3 substring assertions relaxed)
tests/test_pack_resolver_glosses.py (back-compat test pivoted)
Verification:
127/127 affected tests green.
9/9 new gloss-content tests green.
All three eval lanes report the lift documented above.
Cognition eval byte-identical.
Lands the gloss-loader scaffolding from feat/pack-glosses-wip onto
main, with every hardening item from the 2026-05-19 design review
built in from the start. No glosses ship in this commit — only the
infrastructure that will consume them safely.
Hardening items (each pinned by a test):
1. Lexicon-residency check in resolve_gloss()
chat/pack_resolver.py — resolve_gloss now requires the lemma to be
present in the same pack's lexicon.jsonl BEFORE consulting
glosses.jsonl. Without this, glosses.jsonl would become a parallel
surface-authoring channel that bypasses the lexicon's checksum
seal: someone could ship a gloss for a lemma the pack never
ratified, and the runtime would emit it as if it were pack content.
Test: TestLexiconResidencyEnforced::test_gloss_for_unratified_lemma_is_rejected
authors a gloss for ``gamma`` (a lemma not in the lexicon) and
asserts resolve_gloss returns None.
2. Dual-checksum manifest support
language_packs/schema.py — LanguagePackManifest gains an OPTIONAL
``glosses_checksum: str | None`` field. Glosses are an additive
overlay; bumping the glosses_checksum does NOT perturb the
immutable lexicon checksum.
language_packs/compiler.py — _load_pack_cached now verifies
bytes-on-disk of glosses.jsonl against the manifest's
glosses_checksum when present. Missing field on legacy packs is
back-compat (no verification, no raise). Mismatch raises
ValueError exactly like the lexicon checksum gate.
Tests:
test_matching_glosses_checksum_loads_clean — happy path
test_checksum_mismatch_raises — tampered file rejected
test_missing_glosses_checksum_is_back_compat — legacy packs OK
3. clear_resolver_cache() clears BOTH lexicon AND glosses LRU caches
Previously only cleared _pack_lexicon_for, so test fixtures that
wrote glosses.jsonl mid-process would see stale (empty) gloss data
on subsequent resolve_gloss calls.
Test: TestClearResolverCacheClearsBoth proves the issue exists
without the clear, then proves the new code fixes it.
4. Malformed JSONL lines silently skipped
A single bad line in glosses.jsonl must not break resolution for
the rest of the pack. Same defensive parsing as _pack_lexicon_for.
Entries missing required fields (lemma, gloss, or empty values)
are also skipped.
Tests:
test_malformed_line_skipped — invalid JSON between valid lines
test_entry_missing_required_field_skipped — 4 bad shapes filtered
5. Missing glosses.jsonl is back-compat
_pack_glosses_for returns an empty dict when the file is absent.
resolve_gloss returns None. No exception. All 9 currently-
ratified English packs ship with no glosses.jsonl — they must
continue to load cleanly.
Tests:
test_pack_with_no_glosses_returns_empty
test_resolve_gloss_on_lemma_without_gloss_file_returns_none
Files:
chat/pack_resolver.py
+ _pack_glosses_for (cached loader)
+ resolve_gloss (lexicon-residency-gated lookup)
* clear_resolver_cache now clears both caches
language_packs/schema.py
+ LanguagePackManifest.glosses_checksum field (optional)
language_packs/compiler.py
+ dual-checksum verification block in _load_pack_cached
+ glosses_checksum field passed through to the manifest dataclass
tests/test_pack_resolver_glosses.py
11 tests covering all five hardening items
Verification:
11/11 new tests green.
Full cognition eval byte-identical.
All currently-ratified packs continue to load without glosses.
Workstream 1 eighth pack. Closes the polarity-marker + frequency-
adverb gap. Common conversational markers (yes/no/maybe/always/never)
had zero coverage in any prior pack.
Pack composition (16 entries — 2 INTJ / 14 ADV):
polarity.affirm.* yes indeed surely definitely
polarity.negate.* no hardly
polarity.uncertain.* maybe perhaps
polarity.frequency.* always sometimes often rarely never
usually occasionally frequently
``certain``/``certainly``/``uncertain`` deliberately excluded — those
remain in en_core_attitude_v1 (epistemic.certainty/uncertainty).
Regression test pins the invariant.
tests/test_correction_topic_lemma.py:
Three fixtures swapped from "No that is wrong" to "Nope that is
wrong". ``no`` is now correctly pack-resident in en_core_polarity_v1
(polarity.negate.dissent), so the "no pack-resident lemma" contract
these tests pin needed a fixture where every content token is
genuinely OOV. ``nope`` is OOV across all 10 mounted packs; ``wrong``
remains OOV (collision with attitude's ``right`` blocked spatial-
direction ``right`` but did not add ``wrong``).
Authoring:
Three parallel subagents — affirm / negate+uncertain / frequency.
Workstream 1 sixth pack. Closes the spatial-vocabulary gap. Prior
packs had zero coverage of here/there, location nouns, or spatial
prepositions.
Pack composition (24 entries — 7 ADV / 8 ADP / 9 NOUN):
spatial.deictic.* here there (2 ADV)
spatial.direction.* forward backward left up down (5 ADV)
spatial.relation.* near far above below inside outside
between beyond (8 ADP)
spatial.noun.* place location area region space
end top bottom side (9 NOUN)
``right`` was deliberately omitted — en_core_attitude_v1 already owns
it as evaluative.positive, and first-match-wins resolution preserves
that claim. A regression test pins this invariant explicitly.
Files: lexicon.jsonl / manifest.json + 12 contract tests.
Verification: full lane 2204 passed / 2 skipped / 0 failed.
Cognition eval byte-identical both splits.
Workstream 1 fifth pack. Closes the quantifier + basic-numeric gap.
Prior packs had zero coverage of universal / existential / comparative
quantifiers — queries about *all*, *some*, *many*, *more*, *most* all
fell through to OOV.
Pack composition (24 entries — mixed POS, 18 DET / 3 NUM / 2 ADJ / 1 NOUN):
quantitative.universal.* (6 DET) all every each both none neither
quantitative.existential.* (6 DET) some any several few many much
quantitative.comparative.* (6 DET) more less fewer most least enough
quantitative.numeric.* (3 NUM) one two three
quantitative.unit.* (3 mix) single (ADJ) half (NOUN) whole (ADJ)
The composer is POS-agnostic; surface composition uses
``semantic_domains`` rather than POS, so DET/NUM/ADJ/NOUN entries all
surface identically.
Files:
language_packs/data/en_core_quantitative_v1/
lexicon.jsonl — 24 entries, SHA-256 checksum-sealed
manifest.json — operational_base / D0
chat/pack_resolver.py
Appended to DEFAULT_RESOLVABLE_PACK_IDS after action.
core/config.py
Added to RuntimeConfig.input_packs default mount.
tests/test_en_core_quantitative_v1_pack.py
11 contract tests (load / POS-dist / namespace / no-collision /
contiguous-ids / mount / resolver-order / routing / invariance).
Authoring:
Three parallel subagents — universal+existential / comparative /
numeric. Strict exemplar + forbidden-lemma list against all 7
prior packs.
Verification:
Full lane: 2192 passed, 2 skipped, 0 failed.
Cognition eval byte-identical on both splits.
Workstream 1 fourth pack. Closes the common-action verb gap. Prior
packs covered reasoning (cognition), speech/perception (meta), and
adjectives (attitude); this pack covers what an agent *does*.
Pack composition (26 VERB entries):
action.doing.perform do perform execute carry conduct
action.doing.make make
action.doing.achieve achieve accomplish
action.creating.originate create build form produce generate develop
action.changing.transform change transform
action.moving.translate move
action.moving.depart_arrive go come
action.moving.transfer send receive
action.possessing.acquire get take
action.possessing.transfer give
action.possessing.retain keep
action.possessing.deploy use
Files:
language_packs/data/en_core_action_v1/
lexicon.jsonl — 26 entries, SHA-256 checksum-sealed
manifest.json — operational_base / D0
chat/pack_resolver.py
Appended to DEFAULT_RESOLVABLE_PACK_IDS after temporal.
core/config.py
Added to RuntimeConfig.input_packs default mount.
tests/test_en_core_action_v1_pack.py
11 contract tests covering load / POS / namespace / no-collision /
contiguous-ids / mounted-by-default / resolver-order / routing /
prior-pack invariance.
tests/test_procedure_surface.py
Swapped two test fixtures from "do stuff" to "fix bugs". ``do``
is now correctly pack-resident in en_core_action_v1 (semantically
correct — "How do I do stuff?" should ground on ``do``), so the
"no pack lemma exists" contract needed a fixture where both verb
and noun are genuinely OOV. ``fix bugs`` satisfies this across
all 7 mounted packs.
Authoring:
Three parallel subagents — doing / creating / moving+possessing.
Strict exemplar + forbidden-lemma list against all 6 prior packs.
Verification:
Cognition eval byte-identical on both splits (100/100/91.7/100 and
100/100/83.3/100).
All 70 pack tests pass (cognition + meta + attitude + temporal +
action + quant tests run together).
Live composer probes confirm every action lemma surfaces
deterministically from en_core_action_v1.
Workstream 1 third pack. Closes the temporal-vocabulary gap — prior
to this pack zero time/sequence/aspect terms existed in any mounted
English pack, so queries about *when*, *before*, *after*, *now*,
*future*, *past* all fell through to OOV.
Pack composition (28 entries, mixed POS — 12 ADV / 9 NOUN / 5 ADP /
1 SCONJ / 1 ADJ):
temporal.deictic.* (10 ADV) now today tomorrow yesterday soon
later recently eventually currently
formerly
temporal.relative.* (9 mix) before after during while until since
ago prior henceforth
temporal.noun.* (9 NOUN) moment period duration instant era
future past present time
The pack composer is POS-agnostic — surface composition uses the
ratified ``semantic_domains`` list rather than the POS tag. Mixed-POS
entries surface identically to noun/verb entries.
Files:
language_packs/data/en_core_temporal_v1/
lexicon.jsonl — 28 entries, SHA-256 checksum-sealed
manifest.json — operational_base / D0 / checksum-verified
chat/pack_resolver.py
Appended to DEFAULT_RESOLVABLE_PACK_IDS after attitude.
core/config.py
Added to RuntimeConfig.input_packs default mount.
tests/test_en_core_temporal_v1_pack.py
11 contract tests: checksum, POS-distribution invariant, primary-
domain namespace, no-collision regression gate against all 5 prior
packs, contiguous entry_ids, mounted-by-default, resolver-order
invariant, routing correctness, and prior-pack resolution unchanged.
Authoring:
Three parallel subagents — deictic / relative / nouns. Strict
exemplar + forbidden-lemma list against all 5 prior packs.
Verification:
Full lane: 2170 passed, 2 skipped, 0 failed (+11 new tests).
Cognition eval byte-identical on both splits.
Live composer probes confirm every temporal lemma surfaces
deterministically from en_core_temporal_v1.
Workstream 1 second pack. Closes the ADJ POS gap — prior to this pack
zero adjectives existed in any mounted English content pack, so the
runtime could not emit grounded surfaces for predicative queries like
"What is true?" or "What is important?".
Pack composition (40 ADJ entries):
attitude.truth_value.* (8) true false valid invalid accurate
inaccurate factual sound
attitude.evaluative.* (6) good bad right better worse best
attitude.epistemic.* (10) certain uncertain possible impossible
likely unlikely probable clear obscure
evident
attitude.modal.* (4) necessary sufficient required optional
attitude.importance.* (6) important essential relevant central
primary useful
attitude.scope.* (6) general specific broad narrow universal
particular
Files:
language_packs/data/en_core_attitude_v1/
lexicon.jsonl — 40 entries, SHA-256 checksum-sealed
manifest.json — operational_base / D0 / checksum-verified
chat/pack_resolver.py
Appended to DEFAULT_RESOLVABLE_PACK_IDS after cognition + meta.
core/config.py
Added to RuntimeConfig.input_packs default mount.
tests/test_en_core_attitude_v1_pack.py
11 contract tests: checksum, POS=ADJ uniformity, primary-domain
namespace, no-collision regression gate against all 4 prior packs,
contiguous entry_ids, mounted-by-default, resolver-order invariant,
routing correctness, and cognition+meta resolution unchanged.
Authoring:
Three parallel subagents (1 per cluster) — truth/eval, epistemic/modal,
importance/scope. Strict exemplar + forbidden-lemma list against all
prior packs. Main pass assembled, validated, sealed.
Verification:
Full lane: 2159 passed, 2 skipped, 0 failed (+11 new tests over the
previous 2148 baseline).
Cognition eval byte-identical on both splits:
public 100 / 100 / 91.7 / 100
holdout 100 / 100 / 83.3 / 100
Live composer probes: every ADJ lemma emits a deterministic
pack-grounded surface from en_core_attitude_v1.
Workstream 1 (pack content scale-up) first load-bearing step.
Adds a new ratified content pack covering the conversational vocabulary
en_core_cognition_v1 deliberately omits — speech acts, mental states,
perception, self-reference, and discourse-object nouns. These are the
lemmas that show up in nearly every model response and that previously
fell through to the OOV invitation surface.
Pack composition (73 entries, 49 VERB + 24 NOUN):
meta.speech_act.* (20 verbs) say tell speak reply claim state
describe express name mention note
observe declare assert deny confirm
suggest propose articulate respond
meta.mental_state.* (18 verbs) know believe think suppose assume
expect hope want prefer doubt wonder
guess recognize realize consider intend
decide hold
meta.perception.* (11 verbs) see hear feel sense perceive watch
look listen find detect notice
meta.self_reference.* (10 nouns) self mind view perspective position
role agent model system speaker
meta.discourse.* (14 nouns) response reply statement fact idea
point argument proposal suggestion
case instance example kind type
Files:
language_packs/data/en_core_meta_v1/
lexicon.jsonl — 73 entries, SHA-256 checksum-sealed
manifest.json — operational_base / D0 / checksum-verified
chat/pack_resolver.py
Appended en_core_meta_v1 to DEFAULT_RESOLVABLE_PACK_IDS after
en_core_cognition_v1 so cognition lemma resolution stays first-
match-wins on any future collision (preserves cognition-lane
byte-identity invariant).
core/config.py
Added en_core_meta_v1 to RuntimeConfig.input_packs default mount.
tests/test_en_core_meta_v1_pack.py
11 contract tests: checksum-verified load, POS split, primary-
domain namespace, no-collision-with-cognition-v1 regression gate,
pack registration order, resolver routing, and cognition-lemma
resolution unchanged.
tests/test_procedure_surface.py
Swapped two test fixtures from "claim" to "hypothesis". ``claim``
is now correctly pack-resident (meta.speech_act.claim) so the
procedure composer's object-first selector picks it over the verb
— the new behavior is semantically correct. ``hypothesis`` is
genuinely OOV across all mounted packs and preserves the verb-
fallback contract these tests pin.
Authoring methodology:
Four parallel subagents authored one cluster each from a strict
exemplar + word list + forbidden-lemma list (every en_core_cognition_v1
lemma listed explicitly to prevent collision). Each subagent wrote
only its cluster JSONL; the main pass assembled, validated, computed
the SHA-256 over bytes-on-disk, and wrote the manifest.
Verification:
Full lane: 2148 passed, 2 skipped, 0 failed (+11 new tests).
Cognition eval byte-identical on both splits:
public 100 / 100 / 91.7 / 100
holdout 100 / 100 / 83.3 / 100
Live runtime probes: fresh ChatRuntime() for "What is X?" with
X ∈ {fact, doubt, statement, model, self} all emit a
pack-grounded sentence from en_core_meta_v1.
OOV path still honest for genuinely-unknown terms (e.g. hypothesis).
Scope note:
This is one pack of ~70 lemmas, not "the model now articulates
open-domain English." The architecturally-honest articulation
story still requires more pack and teaching-chain content; this
pack moves the conversational-substrate boundary forward by ~70
lemmas in one ratifiable, replay-stable step.
Per teaching_order.md §5 — pick one commercial domain and run the
full 1→4 progression inside it before opening a second. Kinship is
the doctrinally classic starter: tight DAG, well-bounded primitives,
and orthogonal to the cognition pack.
Lemmas (8): parent, child, sibling, family, ancestor, descendant,
spouse, offspring. Each carries ≥2 semantic_domains under a
deterministic taxonomy (kinship.*, lineage.*, biology.*, social.*).
Deliberate exclusions:
- `person` — lives in en_core_cognition_v1; orthogonality test
pins that boundary.
- Specializations (mother/father/son/daughter/grandparent/...) —
derived from v1 primitives; land in v2 after v1 produces
reviewed chains.
- Quantifiers (one/two/many) — separate domain
(en_core_quantification_v1); cross-domain triples come last.
- Verbs of relation (begets/marries/...) — separate composer
work; no relations_chains_v1.jsonl yet.
Engagement is opt-in:
- Pack is NOT in RuntimeConfig.input_packs defaults.
- Programmatic mount via RuntimeConfig(input_packs=(..., "en_core_relations_v1")).
- CLI: core chat --pack en_core_relations_v1 (existing surface).
- Default-not-mounted preserves the cognition lane unchanged
until cross-pack teaching-grounded composition exists.
- language_packs/data/en_core_relations_v1/lexicon.jsonl
— 8 entries, JSONL format matching en_core_cognition_v1.
- language_packs/data/en_core_relations_v1/manifest.json
— pack_id, language, role=operational_base, checksum
(SHA-256 of lexicon bytes per CLAUDE.md pack-discipline),
version 1.0.0, determinism_class D0, oov_policy tagged_fallback.
- tests/test_en_core_relations_v1_pack.py — 6 tests pin:
checksum-match load, lemma roster, per-lemma primary domain,
≥2 domains/lemma (composer headroom), zero collision with
cognition pack (kinship DAG stays orthogonal), pack-not-in-
default-input-packs (opt-in engagement contract).
- docs/curriculum/relations_pack_v1.md — full pack log:
rationale per included/excluded lemma, opt-in engagement path,
4-step ADR roadmap (cross-pack composition → first kinship
chains → pronoun v2 → cross-domain triples).
Mounted-manifold sanity check (en_core_cognition_v1 +
en_core_relations_v1): 93 lemmas combined, no collisions, both
packs' surfaces individually addressable.
Lanes (regression): smoke 67 / packs 6 / algebra 132 / relations-pack 6.
The non-negotiable field invariant (versor_condition < 1e-6) is
unaffected: this is pure pack data + a contract test.
0xC0_RELOG0 contained non-hex digits (R, L, G) producing a SyntaxError
at module import, which made core pulse unable to load the GloVe-backed
manifold. Replace the wordplay constant with the equivalent integer
literal from the comment (3236855408) so the deterministic seed is
preserved and the import path is restored.
Audit of the one-mutation-path invariant (ADR-0021 §3) found three leaks
where pack authority or session-state writes could substitute for coherence
judgment. All three landed fixes or partial closures in this push.
Leaks closed:
- Leak A: pack vocab defaulted to COHERENT — flipped to SPECULATIVE in
language_packs/{compiler,schema}.py; docstring corrected to align with
ADR-0021 (it was rationalizing the leak).
- Leak B: vault.recall was epistemic-blind — VaultStore.store() now stamps
every entry with EpistemicStatus (default SPECULATIVE); recall(min_status=)
filters to admissible-as-evidence tier. All 4 vault-write sites updated.
- Leak C (write-side): generate/proposition.py:198 stored articulated
propositions unmarked — now stamps SPECULATIVE, breaking the
fabrication-feedback loop in principle. Read-side audit of 5 call sites
is the residual.
New architectural invariants (tests/test_architectural_invariants.py):
- INV-21: one-mutation-path allowlist (caught Leak C on first run)
- INV-22: pack lexicon default is SPECULATIVE (Leak A guard)
- INV-23: vault recall epistemic-aware (Leak B guard)
New eval lanes:
- teaching_injection_resistance — ships GREEN at 1.00/1.00/0 (the
structural anti-injection claim is real and measurable)
- refusal_calibration — honest gap: 0% refusal, 0% fabrication
- contradiction_detection — honest gap: 50% flag via versor-delta heuristic,
100% false-positive; motivates the proper coherence-checker
- articulation_of_status — honest gap: 0% speculative articulation, 60%
false certainty; output-side leak surface
New benchmarks:
- benchmarks/footprint.py — total deployed runtime is 7.06 MiB
(109,358x smaller than Llama 3.1 405B, runs offline, no GPU)
- benchmarks/learning_curve.py — monotonic + replay-deterministic curve
per lane
Documentation:
- docs/truth_seeking_schema.md — foundational architectural commitment,
five rules, mapped to human failure modes, leaks published openly
- evals/CLAIMS.md — five-tier public claims doc; Tier 4.5 publishes
known gaps with named fixes; verification contract at top
- README.md — new pillar between algebraic substrate and language pillar
Includes in-flight formation pipeline scaffolding (formation/, tests/formation/,
docs/formation_pipeline_plan.md) and minor CLI/contracts/gitignore edits
that were already in the working tree at session start.
Verification: 798 passed, 2 skipped, 1 deselected (pre-existing pack-count
test drift unrelated to schema changes).
ADR-0021 v1 schema land. epistemic_status is a position in the revision
graph, not a source-trust tier — coherence is the only admission signal.
Surfaces:
- teaching/epistemic.py: EpistemicStatus enum (COHERENT, CONTESTED,
SPECULATIVE, FALSIFIED); ADMISSIBLE_AS_EVIDENCE = {COHERENT}.
- PackMutationProposal.epistemic_status (default SPECULATIVE) + immutable
with_status() updater.
- ReviewedTeachingExample.epistemic_status (default SPECULATIVE);
orthogonal to acceptance per ADR §Schema impact.
- LexicalEntry.epistemic_status (default "coherent" for seed; absent in
JSONL is treated as the seed default — no retroactive tagging).
- compute_trace_hash + trace_hash_from_result + pipeline.py fold the
load-bearing proposal's epistemic_status into the trace hash so
replay detects different epistemic frames.
Non-hardening invariant (ADR-0021 §2): tests/test_epistemic_invariants.py
asserts no final/frozen/axiom/permanent flag on PackMutationProposal or
ReviewedTeachingExample, and EpistemicStatus contains no source-trust
tier names.
Docs: docs/runtime_contracts.md gains an Epistemic surface section.
Lanes green: smoke 27/27, teaching 10/10, packs 6/6, runtime 19/19,
cognition eval 100%.
Adds 15 lexical entries (071-085) extending the cognition pack with
rhetoric, metaphor, narrative, and writing-style vocabulary. Layer 1
of the work plan recorded in evals/compositionality/gaps.md and
evals/cross_domain_transfer/gaps.md: lexical scaffolding only, no
new operators. Building first-class metaphor / narrative / style
support remains correctly downstream of the cross-domain-transfer
literal case working (now closed in commit 57a6174).
New entries:
071 metaphor 076 voice 081 figure
072 simile 077 style 082 symbol
073 analogy 078 register 083 image
074 narrative 079 tone 084 discourse
075 story 080 rhetoric 085 account
Each entry follows the existing pack convention: NOUN pos, four
semantic_domains, morphology_tags=["noun"], seed provenance. The
domains anchor on rhetoric.*, language.figure/discourse/style,
cognition.*, and meaning.* clusters that integrate with the
existing pack vocabulary.
Pack-level updates:
- manifest.json checksum recomputed against the bytes actually
written to disk (per CLAUDE.md Semantic Pack Discipline).
- version bump 1.1.0 -> 1.2.0.
- test_core_semantic_seed_pack.py last-entry assertion updated
from 070 to 085.
Verification: probe "What is X?" against the new vocabulary grounds
cleanly in the pipeline (narrative 7 hits, style 9, rhetoric 8,
analogy 9 vault matches; metaphor produces a coherent surface
despite zero vault hits, consistent with the field-geometry
characterisation in the adversarial-identity calibration probe).
CLI suites packs / smoke / cognition / teaching / runtime all pass;
no regression.
What this does NOT do (deferred by design):
- No metaphor / simile / narrative operator at the proposition-
graph layer. ADR-0018 forbids building operators ahead of
eval evidence; these become a Phase 3 v3 (or Phase 4) candidate
once cross-domain transfer with selectivity has its own eval
lane.
- No first-class is_like(A,B) relation distinct from is(A,B).
Same reasoning - downstream of compositionality engineering.
- No persona/style work on the output side. That belongs in
persona/motor.py per the cross_domain_transfer/gaps.md
architectural sketch.
The entries serve as substrate for future eval lanes that probe
these capabilities specifically (metaphor-comprehension,
narrative-coherence, register-control). When those lanes are
authored, the vocabulary needed for the probes is already grounded.
- grammatical-coverage holdout v1: 52 cases across all 13 constructions, 100% pass
- zero-code-domain-acquisition lane: contract + 3 surprise domains (kinship,
calendar, color) with vocabulary, relations, axioms, teaching examples,
and dev prompts; pack closure verified for all three domains
- he_core_cognition_v1: 20 entries in Hebrew script with morphology decomposition
(triliteral roots, binyanim, aspect/person/gender/number); depth_root role
with fail_closed OOV policy
- grc_logos_cognition_v1: 20 entries in polytonic Greek with morphology
decomposition (stems, prefix/suffix chains, declension class, tense/voice/
mood/person); depth_relation role with fail_closed OOV policy
Implements the English Supervised Seeding Epoch (V1):
- language_packs/en_seeder.py: downloads GloVe-6B-50d, projects each
token embedding through a CGA lift into Cl(4,1) via construction_seed_versor,
validates the versor invariant, and registers the word in VocabManifold.
- scripts/run_pulse.py: replaces the mock 10-word hash vault with the
live VocabManifold. Injection now uses TextProjectionHead.project()
against the seeded vocab; vault_recall queries VocabManifold.nearest().
Hash fallback retained for words absent from GloVe (OOV tagged fallback).
The CGA lift preserves semantic neighbourhood: words close in GloVe
cosine space map to versors that are geometrically proximate in Cl(4,1)
inner product space, so nearest() returns semantically coherent results
rather than hash-proximity artefacts."
Add RuntimeConfig with English default output policy, wire output language through runtime/frame selection/generation/CLI, preserve language metadata in mounted manifolds, and add runtime/CLI policy tests.
* Make core CLI help robust and intuitive
* Package runtime support modules for core CLI
* Add CLI help and doctor tests
* Fix CLI trace help and pack listing
* Export language pack listing helper
* Bootstrap repo root for console runtime imports
* Align trace formatter with Proposition schema
* Cover real trace payload formatting
Compile language-pack features into even-grade rotors, apply canonicalization after alignment nudges. Preserves holonomy parity across token counts. 231 tests passing.
Root was 0.17, stem 0.10 — not heavy enough to anchor same-root forms
against the diverging suffix rotor (ים landing on a different axis).
New hierarchy:
triliteral root 0.13 → 0.22 (shared identity, strongest anchor)
root 0.17 → 0.30 (primary root geometry)
stem 0.10 → 0.18 (secondary, same-root forms cluster here)
inflection role 0.02 → 0.015 (key label, minimal)
inflection value 0.05 → 0.03 (number/gender/etc, perturbation only)
prefix 0.05 → 0.03 (per-position decay preserved)
suffix 0.04 → 0.02 (per-position decay preserved)
This ensures דבר and דברים both orbit the D-B-R root point closely
enough that cga_inner(singular, plural) > cga_inner(singular, unrelated),
while still encoding morphological distinctions as measurable offsets.
- VocabManifold.update(): replace a stored versor in-place (grade-norm
enforced, KeyError if word missing)
- compile_entries_to_manifold() now also returns entry_id->surface map
as a second return value; callers that only need the manifold use [0]
- _alignment_nudge_rotor(): slerp-style rotor that rotates source toward
target by edge.weight * ALIGNMENT_NUDGE_STRENGTH (0.06) — small enough
to preserve intra-pack geometry, large enough to pull cross-lang pairs
into proximity
- load_pack(): after both manifolds are built, loads alignment.jsonl,
resolves entry_id->surface on each side, applies nudge to source versor
using the already-compiled target versor as the attractor
- _is_hebrew_root() guard retained; _triliteral_root() Hebrew-only
- Guard _triliteral_root() rotor to Hebrew-script roots only; Greek/other
scripts now use the root: rotor alone (0.17) — no spurious uppercase
Unicode blade collision from the romanization fallback path
- test_structured_morphology_improves_same_root_hebrew_resonance: replace
tag_only baseline (now empty since legacy tags stripped) with no_morphology
baseline (domain+pos+lemma+surface only), which is the honest comparison
for what structured morphology contributes post-migration
- Strip root: tags from all 7 grc_logos_micro_v1 lexicon entries
- Refresh grc_logos_micro_v1 manifest checksum
- Remove _uses_legacy_root_tags() and _apply_morphology_tags() from compiler
- _entry_to_coordinate() now has a single morphology path: structured when
morphology_id resolves, tag fallback only for packs with no morphology data
- load_pack() registry loading made unconditional for packs with morphology.jsonl
These were the pre-rename originals superseded by he_logos_micro_v1 and
grc_logos_micro_v1. Their manifests have checksum mismatches (visible via
`python -m language_packs list`) because the lexicon content was updated
without re-checksumming before the rename.
No tests reference these pack IDs. No code loads them. Leaving broken
packs in data/ creates false noise in `list` output and risks a future
agent loading the wrong pack by prefix match.
Three subcommands:
compile <pack_id> — compile a pack, verify checksum, print manifold stats
verify <pack_id> — checksum-only verification without full compilation
list — list all available packs with role and entry count
Checksum rule (AGENTS.md) is enforced by design: the CLI reads bytes from
disk via read_bytes() as the single source of truth, never from in-memory
strings. This makes the compiler an auditable D0 instrument — not just an
importable function.
Exit codes: 0 = success, 1 = checksum mismatch or pack not found.
Permanent lesson: checksums must be computed from bytes-on-disk after
git writes the file (unicode-escaped JSON lines), not from in-memory
Python strings before serialization. The compiler CLI must do:
checksum = hashlib.sha256(Path(lexicon_path).read_bytes()).hexdigest()
after writing the file, not before.
he_logos_micro_v1: ea1ac85d...
grc_logos_micro_v1: 1fea9d9c...
Root cause: all 7 Logos words shared 'logos.core' as first domain, making
them cluster into a single blob. The misaligned triple (word ↔ ראשית,
word ↔ πνεῦμα, דבר ↔ ἀρχή) scored 0.379 vs aligned 0.299 because
cross-language 'spirit' and 'beginning' were geometrically indistinguishable
from 'word' when logos.core dominated the rotor composition.
Fix: each Logos word now has a UNIQUE leaf domain as its FIRST (highest-
weight) domain that it shares ONLY with its cross-language counterparts:
word/דבר/λόγος → logos.utterance.word
beginning/ראשית/ἀρχή → logos.genesis.origin
light/אור/φῶς → logos.illumination.photon
life/חיים/ζωή → logos.vitality.animate
truth/אמת/ἀλήθεια → logos.aletheia.verity
spirit/רוח/πνεῦμα → logos.pneuma.breath
create/ברא/κτίζω → logos.ktizo.formation
logos.core retained as second domain (background cohesion, lower weight).
divine.revelation removed from spirit/רוח/πνεῦμא (was polluting alignment).
Packs renamed: he_logos_v1 → he_logos_micro_v1, grc_logos_v1 → grc_logos_micro_v1
(test expects *_micro_* IDs).
All three manifests updated with correct D0 checksums.
- manifest checksum updated to match actual bytes-on-disk
(eca36a3d... — line endings differ between Python serialization and git)
- probe/repl.py: add sys.path.insert so it resolves language_packs
from repo root when run directly