Step 3 of the discourse-planner sequencing. Adds
generate/grounding_accessors.py:
* pack_grounded_facts(lemma) -> tuple[GroundedFact, ...]
* teaching_grounded_chains(lemma) -> tuple[GroundedFact, ...]
* cross_pack_grounded_chains(lemma) -> tuple[GroundedFact, ...]
* grounding_bundle_for(lemma) -> GroundingBundle
All four reuse the existing data substrate (chat.pack_resolver,
chat.teaching_grounding._all_chains_index, chat.cross_pack_grounding
chain accessors) — no new loader, no new I/O, no string composer
touched. Pack facts emit one `is_defined_as` per gloss + one
`belongs_to` per semantic_domain; teaching/cross-pack chains emit
verbatim (subject, connective, object) triples; everything sorted by
GroundedFact.sort_key for canonical determinism.
21 new tests pin: pack/teaching/cross-pack accessor shape, canonical
sort order, verbatim object invariant (no synthesis), source_id
points back into real artifact, bundle composition combines all three
sources with pack-first priority, and doctrine invariants (no
*_grounded_surface composer imported, no chat.runtime imported).
Verification:
* 21/21 new accessor tests pass.
* smoke suite 67/67.
* cognition eval byte-identical:
public 100/100/91.7/100, holdout 100/100/83.3/100.