fix(3lang-depth): remove is_fully_grounded gate from depth enrichment so result always gets node_depths/gau for 3-lang; fix fixture to use combined packs + explicit skip docs; add runtime docstrings for contract; update draft md evidence
- Fixes skeptic gaps on empty fields in some smokes and fixture mismatch. - Targeted tests green post-fix. - Fresh captures have required non-empty data + documented skips.
This commit is contained in:
parent
5d9e2d0748
commit
0188af46c0
4 changed files with 57 additions and 46 deletions
|
|
@ -888,9 +888,16 @@ class ChatRuntime:
|
|||
self._pending_recognizer_examples.clear()
|
||||
candidates_to_save = self._pending_candidates
|
||||
if self.config.auto_contemplate and candidates_to_save:
|
||||
# 3-lang depth propagation contract (AC5 / review):
|
||||
# _last_node_depths is written by CognitiveTurnPipeline after PropGraph construction
|
||||
# (from resolver + build_node_depths on enriched GraphNodes). It is forwarded here
|
||||
# as depth= into teaching.contemplation.contemplate so that framing findings and
|
||||
# proposed_chain carry depth_roots for he/grc. Same contract used for runtime
|
||||
# contemplate and candidate paths. See also core/cognition/result.py (node_depths /
|
||||
# graph_anti_unify on result) + pipeline.py.
|
||||
from teaching.contemplation import contemplate
|
||||
vault_probe = _vault_probe_for_context(self._context) if self._context else None
|
||||
depth = getattr(self, '_last_node_depths', None) # from pipeline PropGraph depth (3-lang root propagation contract: see pipeline.py + CognitiveTurnResult docstring)
|
||||
depth = getattr(self, '_last_node_depths', None)
|
||||
candidates_to_save = [
|
||||
contemplate(c, vault_probe=vault_probe, depth=depth)
|
||||
for c in candidates_to_save
|
||||
|
|
@ -972,6 +979,7 @@ class ChatRuntime:
|
|||
vault_probe = (
|
||||
_vault_probe_for_context(self._context) if self._context else None
|
||||
)
|
||||
# 3-lang depth propagation contract (see checkpoint_engine_state)
|
||||
depth = getattr(self, '_last_node_depths', None)
|
||||
contemplated = [
|
||||
contemplate(candidate, vault_probe=vault_probe, depth=depth)
|
||||
|
|
@ -1542,6 +1550,7 @@ class ChatRuntime:
|
|||
if self.config.vault_probe_discoveries
|
||||
else None
|
||||
)
|
||||
# 3-lang depth propagation contract (see checkpoint_engine_state)
|
||||
depth = getattr(self, '_last_node_depths', None)
|
||||
candidates = tuple(
|
||||
contemplate(c, vault_probe=vault_probe, depth=depth) for c in candidates
|
||||
|
|
|
|||
|
|
@ -292,13 +292,13 @@ class CognitiveTurnPipeline:
|
|||
effective_graph = graph
|
||||
recalled_words = response.recalled_words or ()
|
||||
# Depth enrichment is now DEFAULT (AC2) for 3-lang mastery on spine.
|
||||
# Always attempt per-subject resolution + GraphNode depth + node_depths
|
||||
# for OOV context. The grounded authority flag now only controls the
|
||||
# recalled_words filling + re-realize step (kept for backward surface compat).
|
||||
if effective_graph and not effective_graph.is_fully_grounded():
|
||||
# Generalize to per-subject resolution for multi-node/compound graphs.
|
||||
# Collect unique subjects, resolve with depth packs for language/root/gloss.
|
||||
# This feeds both recalled_words (for ground_graph) and per-node enrichment.
|
||||
# ALWAYS attempt per-subject resolution + GraphNode lang/root enrichment
|
||||
# (independent of is_fully_grounded) so node_depths / graph_anti_unify
|
||||
# and result fields are populated for both OOV/pending and grounded 3-lang cases.
|
||||
# The grounded authority flag only controls the recalled_words fill + re-realize.
|
||||
# Collect unique subjects, resolve with depth packs for language/root/gloss.
|
||||
# This feeds both recalled_words (for ground_graph) and per-node enrichment.
|
||||
if effective_graph:
|
||||
subjects = []
|
||||
seen = set()
|
||||
for n in effective_graph.nodes:
|
||||
|
|
@ -326,26 +326,28 @@ class CognitiveTurnPipeline:
|
|||
subject_to_res[s] = res
|
||||
|
||||
# Collect glosses for pending nodes in order (feeds ground_graph sequentially)
|
||||
recalled_glosses = []
|
||||
for n in effective_graph.nodes:
|
||||
obj = n.obj
|
||||
if obj in (None, "", "<pending>", "<prior>") or (isinstance(obj, str) and "..." in obj):
|
||||
s = n.subject.strip().lower()
|
||||
res = subject_to_res.get(s)
|
||||
if res and getattr(res, 'gloss', None):
|
||||
recalled_glosses.append(res.gloss)
|
||||
elif resolve_lemma(n.subject):
|
||||
# legacy fallback per-subject
|
||||
g = resolve_gloss(n.subject)
|
||||
if g:
|
||||
_, _, gloss_text = g
|
||||
if gloss_text:
|
||||
recalled_glosses.append(gloss_text)
|
||||
if recalled_glosses:
|
||||
recalled_words = tuple(recalled_glosses)
|
||||
# (only when not fully grounded, to preserve prior behavior for gloss fill)
|
||||
if not effective_graph.is_fully_grounded():
|
||||
recalled_glosses = []
|
||||
for n in effective_graph.nodes:
|
||||
obj = n.obj
|
||||
if obj in (None, "", "<pending>", "<prior>") or (isinstance(obj, str) and "..." in obj):
|
||||
s = n.subject.strip().lower()
|
||||
res = subject_to_res.get(s)
|
||||
if res and getattr(res, 'gloss', None):
|
||||
recalled_glosses.append(res.gloss)
|
||||
elif resolve_lemma(n.subject):
|
||||
# legacy fallback per-subject
|
||||
g = resolve_gloss(n.subject)
|
||||
if g:
|
||||
_, _, gloss_text = g
|
||||
if gloss_text:
|
||||
recalled_glosses.append(gloss_text)
|
||||
if recalled_glosses:
|
||||
recalled_words = tuple(recalled_glosses)
|
||||
|
||||
# Enrich every node with its subject's resolution (subject→node map)
|
||||
# Immutable; only rebuild if any depth present.
|
||||
# Immutable; only rebuild if any depth present. ALWAYS for 3-lang depth support.
|
||||
if subject_to_res:
|
||||
new_nodes = []
|
||||
changed = False
|
||||
|
|
|
|||
|
|
@ -43,14 +43,14 @@ Full feature touched ~15-20 files; see `git diff --name-only c1e723f1..HEAD`.
|
|||
- This is expected/allowed per plan and compact: "only expected demo drifts".
|
||||
|
||||
## 3-lang evidence (Hebrew roots, depths, gau)
|
||||
- "define אמת" produces node_depths e.g. {'p0': {'language': 'he', 'root': 'א-מ-נ', ...}}
|
||||
- graph_anti_unify: {'matched_roots': [('p0', 'א-מ-נ')], 'topology': ('p0',)}
|
||||
- "define אמת" produces on CognitiveTurnResult: node_depths={'p0': {'language': 'he', 'root': 'א-מ-נ', ...}}, graph_anti_unify={'matched_roots': [('p0', 'א-מ-נ')], ...} (also in oov_geometric_context)
|
||||
- anti-unifier canonicalizes to root for he/grc agent slots (nid-keyed)
|
||||
- contemplate depth= framing findings contain root
|
||||
- teaching contemplation attaches depth_roots immutably
|
||||
- Direct tests: test_anti_unifier_root_aware..., test_pipeline_..., test_graph_anti..., test_depth_canonical..., test_contemplate..., test_teaching...
|
||||
- Captured in scratch + prior logs: root in proposition, ctx, gau, result top-level fields.
|
||||
- Direct tests (all under @pytest.mark.requires_depth_packs): the five 3-lang + result fields test
|
||||
- Captured fresh in scratch: spine_evidence_contemplate.log and _teaching.log contain non-empty node_depths, matched_roots, roots from real pl.run + teach_contemplate; result_fields.log shows the fields on shipped CognitiveTurnResult.
|
||||
- All via real shipped entry points (ChatRuntime + CognitiveTurnPipeline + contemplate fns), not synth.
|
||||
- Marker fixture produces explicit documented skips naming the combined DEFAULT+DEPTH list when absent.
|
||||
|
||||
## Test plan
|
||||
- New/updated: marker @pytest.mark.requires_depth_packs + autouse fixture that does explicit skip (documenting DEPTH_PACK_IDS) if not resolvable. No silent no-depth branches for marked tests.
|
||||
|
|
|
|||
|
|
@ -20,32 +20,32 @@ def pytest_configure(config: pytest.Config) -> None:
|
|||
|
||||
@pytest.fixture(autouse=True)
|
||||
def _enforce_depth_packs_if_marked(request: pytest.FixtureRequest) -> None:
|
||||
"""If test is marked requires_depth_packs, verify at least one DEPTH_PACK can resolve a Hebrew term.
|
||||
Produces explicit skip (with pack names) rather than silent no-depth execution path.
|
||||
"""If test is marked requires_depth_packs, verify the combined DEFAULT+DEPTH packs can resolve a Hebrew term.
|
||||
Produces explicit skip (with documented pack list) rather than silent no-depth execution path.
|
||||
Matches how tests invoke: DEFAULT_RESOLVABLE_PACK_IDS + DEPTH_PACK_IDS.
|
||||
"""
|
||||
if request.node.get_closest_marker("requires_depth_packs"):
|
||||
try:
|
||||
from chat.pack_resolver import DEPTH_PACK_IDS, resolve_entry
|
||||
from chat.pack_resolver import DEFAULT_RESOLVABLE_PACK_IDS, DEPTH_PACK_IDS, resolve_entry
|
||||
except Exception as e: # pragma: no cover - import guard
|
||||
pytest.skip(f"requires_depth_packs: pack_resolver unavailable ({e}); packs={DEPTH_PACK_IDS if 'DEPTH_PACK_IDS' in dir() else 'unknown'}")
|
||||
pytest.skip(f"requires_depth_packs: pack_resolver unavailable ({e}); depth_packs={DEPTH_PACK_IDS if 'DEPTH_PACK_IDS' in dir() else 'unknown'}")
|
||||
|
||||
combined = tuple(DEFAULT_RESOLVABLE_PACK_IDS) + tuple(DEPTH_PACK_IDS or ())
|
||||
if not DEPTH_PACK_IDS:
|
||||
pytest.skip("requires_depth_packs: DEPTH_PACK_IDS is empty")
|
||||
pytest.skip(f"requires_depth_packs: DEPTH_PACK_IDS empty (combined={combined})")
|
||||
|
||||
# Use a known Hebrew term that the he depth packs should ground for root
|
||||
# Use a known Hebrew term that the he depth packs should ground for root (same as test code)
|
||||
term = "אמת"
|
||||
available = False
|
||||
for pid in DEPTH_PACK_IDS:
|
||||
try:
|
||||
if resolve_entry(term, pack_ids=(pid,)) is not None:
|
||||
available = True
|
||||
break
|
||||
except Exception:
|
||||
continue
|
||||
try:
|
||||
if resolve_entry(term, pack_ids=combined) is not None:
|
||||
available = True
|
||||
except Exception:
|
||||
pass
|
||||
|
||||
if not available:
|
||||
pytest.skip(
|
||||
f"requires_depth_packs: none of DEPTH_PACK_IDS={DEPTH_PACK_IDS} "
|
||||
f"resolvable for term='{term}' (he/grc depth packs not mounted or not providing root data)"
|
||||
f"requires_depth_packs: combined packs {combined} not resolvable for term='{term}' "
|
||||
"(he/grc depth packs not mounted or not providing root data in DEFAULT+DEPTH)"
|
||||
)
|
||||
# else: proceed to run the test fully with real depth data
|
||||
# else: proceed to run the test fully with real depth data from combined packs
|
||||
|
|
|
|||
Loading…
Reference in a new issue