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).
205 lines
7 KiB
Python
205 lines
7 KiB
Python
"""Stage 5 — Compile. ``CourseYAML`` -> ``FormationPlan``.
|
|
|
|
The plan is a deterministic, content-addressed sequence of ``PlanStep``
|
|
objects. Each step carries the typed payload the Runner needs to issue a
|
|
single ``CognitiveTurnPipeline.run()`` invocation.
|
|
|
|
Same ``CourseYAML`` -> same ``FormationPlan`` -> same ``plan_sha256``. This
|
|
property is load-bearing for replay determinism and the ratify gates.
|
|
"""
|
|
|
|
from __future__ import annotations
|
|
|
|
from typing import Any
|
|
|
|
import yaml
|
|
|
|
from formation.course import CourseYAML, FormationPlan, PlanStep
|
|
from formation.hashing import sha256_of
|
|
|
|
|
|
def compile_course(course: CourseYAML) -> FormationPlan:
|
|
"""Convert a ``CourseYAML`` to a deterministic ``FormationPlan``."""
|
|
body = yaml.safe_load(course.yaml_bytes)
|
|
if not isinstance(body, dict):
|
|
raise ValueError("compile_course: course body must be a mapping")
|
|
# The Definition template emits course fields at the top level; we accept
|
|
# either a wrapped ``course:`` mapping (future templates) or the bare form.
|
|
course_block = body.get("course") if "course" in body else body
|
|
if not isinstance(course_block, dict):
|
|
raise ValueError("compile_course: course payload must be a mapping")
|
|
|
|
steps: list[PlanStep] = []
|
|
steps.extend(_seed_concept_steps(course_block))
|
|
steps.extend(_introduce_relation_steps(course_block))
|
|
steps.extend(_walk_step_steps(course_block))
|
|
steps.extend(_adversarial_probe_steps(course_block))
|
|
steps.extend(_replay_assertion_steps(course_block))
|
|
|
|
plan_sha = sha256_of({
|
|
"course_id": course.course_id,
|
|
"course_sha256": course.course_sha256,
|
|
"steps": [
|
|
{"step_type": s.step_type, "payload": _canonicalize(s.payload)}
|
|
for s in steps
|
|
],
|
|
})
|
|
return FormationPlan(
|
|
course_id=course.course_id,
|
|
course_sha256=course.course_sha256,
|
|
steps=tuple(steps),
|
|
plan_sha256=plan_sha,
|
|
)
|
|
|
|
|
|
# ---------- per-phase extractors ----------
|
|
|
|
|
|
def _seed_concept_steps(course: dict[str, Any]) -> list[PlanStep]:
|
|
phase = course.get("phase_1_ontological_seeding", {}) or {}
|
|
items = phase.get("concepts", []) or []
|
|
out: list[PlanStep] = []
|
|
for c in items:
|
|
if not isinstance(c, dict):
|
|
continue
|
|
term = str(c.get("canonical_term", ""))
|
|
definition = str(c.get("definition", ""))
|
|
if not term:
|
|
continue
|
|
out.append(PlanStep(
|
|
step_type="seed_concept",
|
|
payload={
|
|
"canonical_term": term,
|
|
"definition": definition,
|
|
"utterance": f"What is {term}?",
|
|
},
|
|
))
|
|
return out
|
|
|
|
|
|
def _introduce_relation_steps(course: dict[str, Any]) -> list[PlanStep]:
|
|
phase = course.get("phase_2_axiomatic_rotor_scaffolding", {}) or {}
|
|
items = phase.get("relations", []) or []
|
|
out: list[PlanStep] = []
|
|
for r in items:
|
|
if not isinstance(r, dict):
|
|
continue
|
|
head = str(r.get("head", ""))
|
|
relation = str(r.get("relation", ""))
|
|
tail = str(r.get("tail", ""))
|
|
if not head or not relation or not tail:
|
|
continue
|
|
out.append(PlanStep(
|
|
step_type="introduce_relation",
|
|
payload={
|
|
"head": head,
|
|
"relation": relation,
|
|
"tail": tail,
|
|
"utterance": f"{head} {relation.replace('_', ' ')} {tail}.",
|
|
},
|
|
))
|
|
return out
|
|
|
|
|
|
def _walk_step_steps(course: dict[str, Any]) -> list[PlanStep]:
|
|
phase = course.get("phase_3_holonomic_syllabus_walk", {}) or {}
|
|
# Accept the Definition template's ``walks:`` key as well as the future
|
|
# ``ordered_walks:`` form proposed in the plan doc.
|
|
walks = phase.get("walks") or phase.get("ordered_walks") or []
|
|
out: list[PlanStep] = []
|
|
for walk in walks:
|
|
if not isinstance(walk, dict):
|
|
continue
|
|
edges = walk.get("steps") or walk.get("edges") or []
|
|
for edge in edges:
|
|
if not isinstance(edge, dict):
|
|
continue
|
|
head = str(edge.get("head", ""))
|
|
relation = str(edge.get("relation", ""))
|
|
tail = str(edge.get("tail", ""))
|
|
if not head or not relation or not tail:
|
|
continue
|
|
out.append(PlanStep(
|
|
step_type="walk_step",
|
|
payload={
|
|
"head": head,
|
|
"relation": relation,
|
|
"tail": tail,
|
|
"utterance": f"What does {head} {relation.replace('_', ' ')}?",
|
|
},
|
|
))
|
|
return out
|
|
|
|
|
|
def _adversarial_probe_steps(course: dict[str, Any]) -> list[PlanStep]:
|
|
phase = course.get("phase_4_epistemic_boundary_hardening", {}) or {}
|
|
out: list[PlanStep] = []
|
|
for false_claim in phase.get("false_claims", []) or []:
|
|
if not isinstance(false_claim, dict):
|
|
continue
|
|
head = str(false_claim.get("head", ""))
|
|
relation = str(false_claim.get("relation", ""))
|
|
tail = str(false_claim.get("tail", ""))
|
|
if not head or not relation or not tail:
|
|
continue
|
|
out.append(PlanStep(
|
|
step_type="adversarial_probe",
|
|
payload={
|
|
"head": head,
|
|
"relation": relation,
|
|
"tail": tail,
|
|
"kind": "false_claim",
|
|
"utterance": f"{head} {relation.replace('_', ' ')} {tail}.",
|
|
},
|
|
))
|
|
for probe in phase.get("adversarial_corrections", []) or []:
|
|
if isinstance(probe, dict):
|
|
utterance = str(probe.get("prompt") or probe.get("utterance") or "")
|
|
probe_id = str(probe.get("probe_id", ""))
|
|
else:
|
|
utterance = str(probe)
|
|
probe_id = ""
|
|
if not utterance:
|
|
continue
|
|
out.append(PlanStep(
|
|
step_type="adversarial_probe",
|
|
payload={
|
|
"kind": "identity_override",
|
|
"probe_id": probe_id,
|
|
"utterance": utterance,
|
|
},
|
|
))
|
|
return out
|
|
|
|
|
|
def _replay_assertion_steps(course: dict[str, Any]) -> list[PlanStep]:
|
|
phase = course.get("phase_5_ratified_consolidation", {}) or {}
|
|
replay = phase.get("replay")
|
|
if isinstance(replay, dict):
|
|
if not replay.get("deterministic", False):
|
|
return []
|
|
return [PlanStep(
|
|
step_type="replay_assertion",
|
|
payload={
|
|
"prior_regression_allowed": bool(
|
|
replay.get("prior_regression_allowed", False)
|
|
),
|
|
},
|
|
)]
|
|
# Definition template form: presence of ``ratification_gates`` implies a
|
|
# deterministic replay step.
|
|
gates = phase.get("ratification_gates")
|
|
if isinstance(gates, list) and gates:
|
|
return [PlanStep(
|
|
step_type="replay_assertion",
|
|
payload={"gates": [str(g) for g in gates]},
|
|
)]
|
|
return []
|
|
|
|
|
|
# ---------- helpers ----------
|
|
|
|
|
|
def _canonicalize(payload: dict[str, Any]) -> dict[str, Any]:
|
|
"""Return a copy with stable iteration order — dict literal already sorts via sha256_of."""
|
|
return dict(payload)
|