core/tests
Shay 310793a4ea feat(adr-0024): Phase 2 — honest refusal with typed evidence
Replace plain ValueError at both inner-loop exhaustion sites in
generate/stream.py with InnerLoopExhaustion, a typed ValueError
subclass carrying machine-readable refusal evidence:

  reason            : RefusalReason (INNER_LOOP_EXHAUSTION)
  region_label      : which AdmissibilityRegion blocked
  step_index        : -1 = pre-walk empty intersection;
                      >=0 = in-walk per-step exhaustion
  rejected_attempts : ordered (idx, word, score) triples

Backward-compat by construction: subclassing ValueError preserves
every pre-Phase-2 `except ValueError` handler in chat/runtime.py,
eval lanes, and tests. No edits to chat/runtime.py, field/propagate.py,
algebra/versor.py, or vault/store.py.

Trace path wired:
  - CognitiveTurnResult.refusal_reason (str, default "")
  - compute_trace_hash folds refusal_reason only when non-empty
    -> byte-identical hashes preserved for non-refused turns
  - CognitiveTurnPipeline reads via getattr from ChatResponse and
    forwards into both trace_hash and result construction

Contract documented in docs/runtime_contracts.md §"Refusal contract".

Tests (tests/test_refusal_contract.py — 10 passing):
  - InnerLoopExhaustion isinstance(ValueError) at both raise sites
  - In-walk site carries reason/region_label/step_index>=0/
    rejected_attempts with (int,str,float) triples
  - Pre-walk site uses step_index=-1 sentinel + empty
    rejected_attempts
  - Pre-walk fires even when inner_loop_admissibility=False
  - Trace hash: empty refusal_reason preserves legacy bytes;
    non-empty differs; same inputs are stable

Suite results:
  smoke: 67 passed
  cognition: 121 passed
  runtime: 19 passed
  full: 1024 passed, 2 skipped
  core eval cognition: 13/13, 100% intent accuracy, 100% versor closure

Residual silent path (documented as out-of-scope for Phase 2):
chat/runtime.respond()/arespond() still convert any ValueError to
"" for their public str return contract. So a refused turn today
produces surface == "" with refusal_reason == "" — the typed
evidence is unread between the raise site and the result. The
plumbing on result + trace + pipeline is in place so a future ADR
can wire materialisation (propagate exception to
ChatResponse.refusal_reason, or catch at the pipeline seam) without
re-deriving the contract.

Phase 1 (commit 3940290) and Phase 2 (this commit) were developed
in parallel with disjoint file scope to avoid conflicts.
2026-05-17 14:49:08 -07:00
..
formation feat(epistemic): truth-seeking schema audit — 3 leaks closed, 4 new lanes, 3 new invariants 2026-05-17 07:27:41 -07:00
__init__.py
test_achat.py
test_admissibility_trace.py feat(adr-0023): Forward Semantic Control proof evidence — Accepted 2026-05-17 12:55:19 -07:00
test_alignment_graph.py
test_architectural_invariants.py feat(epistemic): Leak C read-side audit — INV-24 callsite registry, Leak C fully closed 2026-05-17 09:48:39 -07:00
test_articulation.py
test_articulation_realizer_v2.py
test_benchmarks_profiler.py feat(benchmarks): discourse_paragraph lane + pipeline profiler + word-selection tracer 2026-05-16 21:53:46 -07:00
test_cga_inner_rust_parity.py
test_chat_runtime.py
test_cli.py
test_cli_pack_validate_security.py
test_cli_test_suites.py
test_cognitive_eval_harness.py
test_cognitive_turn_pipeline.py
test_compiler.py
test_compose_relations.py feat(compositionality): compose_relations operator lifts lane 68.8% → 100% 2026-05-16 22:44:06 -07:00
test_core_ingest.py
test_core_semantic_seed_pack.py
test_determinism_proofs.py
test_deterministic_hash.py
test_dialogue.py
test_dialogue_fluency_regression.py
test_energy.py
test_engine_loop_proof.py
test_epistemic_invariants.py
test_explain.py
test_forward_semantic_control.py feat(adr-0022): Forward Semantic Control — Accepted 2026-05-17 12:10:20 -07:00
test_generate_stream.py
test_geometric_product_rust_parity.py
test_graph_diffusion.py
test_holonomy.py
test_holonomy_resonance.py
test_identity_gate.py
test_inference_operators.py
test_inner_loop_admissibility.py feat(adr-0024): Phases 2-5 — corpus eval, v2 adversarial, threshold characterization, ADR-0025 design note 2026-05-17 14:07:50 -07:00
test_inner_loop_phase2.py feat(adr-0024): Phases 2-5 — corpus eval, v2 adversarial, threshold characterization, ADR-0025 design note 2026-05-17 14:07:50 -07:00
test_inner_loop_phase3.py feat(adr-0024): Phases 2-5 — corpus eval, v2 adversarial, threshold characterization, ADR-0025 design note 2026-05-17 14:07:50 -07:00
test_inner_loop_phase4.py feat(adr-0024): Phase 1 addendum — retire v1/dev fixture rot 2026-05-17 14:43:34 -07:00
test_intent_proposition_graph.py
test_intent_ratifier.py feat(adr-0022): Forward Semantic Control — Accepted 2026-05-17 12:10:20 -07:00
test_language_pack_cache.py feat(adr-0024): Phase 1 — wire inner-loop admissibility + determinism proof 2026-05-17 13:38:55 -07:00
test_language_pack_runtime.py
test_manifold.py
test_manifold_state.py
test_morphology_irregular.py fix(gaps): close G1+G2+G3 + identity vocab + pipeline safety-stub honour 2026-05-16 21:21:06 -07:00
test_morphology_registry.py
test_motor.py
test_null_cone.py
test_oov_grounding_cache.py
test_operator_calibration_replay.py
test_pipeline.py
test_pipeline_teaching_integration.py
test_probe_repl.py
test_proof_properties.py
test_proposition.py
test_provenance.py
test_pulse_integration.py
test_realizer_quantifier_agreement.py fix(gaps): close G1+G2+G3 + identity vocab + pipeline safety-stub honour 2026-05-16 21:21:06 -07:00
test_refusal_contract.py feat(adr-0024): Phase 2 — honest refusal with typed evidence 2026-05-17 14:49:08 -07:00
test_replay_vs_llm_benchmark.py feat(compositionality): compose_relations operator lifts lane 68.8% → 100% 2026-05-16 22:44:06 -07:00
test_reviewed_teaching_loop.py
test_rotor_power.py
test_runtime_config.py
test_rust_backend.py feat(algebra): null-preserving versor_apply path + un-skip 2 invariant tests 2026-05-16 21:40:37 -07:00
test_salience.py
test_segmenter.py
test_semantic_realizer_integration.py feat(adr-0023): Forward Semantic Control proof evidence — Accepted 2026-05-17 12:55:19 -07:00
test_sensorium_mount.py
test_session_coherence.py
test_surface.py
test_transition_rotor.py
test_unknown_token_ingest.py
test_vault_config.py
test_vault_recall.py
test_vault_recall_rust_parity.py
test_vault_recall_vectorised.py
test_vault_store.py
test_versor_apply_rust_parity.py perf(rust): versor_apply f64 parity port — 29x over Python, bit-identical 2026-05-16 20:43:01 -07:00
test_versor_closure.py feat(algebra): null-preserving versor_apply path + un-skip 2 invariant tests 2026-05-16 21:40:37 -07:00
test_versor_condition_rust_parity.py
test_vocab_manifold_invariants.py