refactor(cli): decompose cli into dedicated modules
This commit is contained in:
parent
c32b0db6a9
commit
7f177bbb17
13 changed files with 3057 additions and 1901 deletions
2010
core/cli.py
2010
core/cli.py
File diff suppressed because it is too large
Load diff
379
core/cli_capability.py
Normal file
379
core/cli_capability.py
Normal file
|
|
@ -0,0 +1,379 @@
|
||||||
|
"""Extracted commands."""
|
||||||
|
from __future__ import annotations
|
||||||
|
import argparse
|
||||||
|
import json
|
||||||
|
from pathlib import Path
|
||||||
|
|
||||||
|
|
||||||
|
def cmd_capability_chains(args: argparse.Namespace) -> int:
|
||||||
|
from core.capability import chain_report
|
||||||
|
|
||||||
|
report = chain_report()
|
||||||
|
print(json.dumps(report, indent=2, sort_keys=True) if args.json else report)
|
||||||
|
return 0
|
||||||
|
|
||||||
|
|
||||||
|
def cmd_capability_flags(args: argparse.Namespace) -> int:
|
||||||
|
from core.capability import flag_report
|
||||||
|
|
||||||
|
report = flag_report()
|
||||||
|
print(json.dumps(report, indent=2, sort_keys=True) if args.json else report)
|
||||||
|
return 0
|
||||||
|
|
||||||
|
|
||||||
|
def cmd_capability_ledger(args: argparse.Namespace) -> int:
|
||||||
|
from core.capability import ledger_report
|
||||||
|
|
||||||
|
report = ledger_report()
|
||||||
|
print(json.dumps(report, indent=2, sort_keys=True) if args.json else report)
|
||||||
|
return 0
|
||||||
|
|
||||||
|
|
||||||
|
def cmd_capability_artifact(args: argparse.Namespace) -> int:
|
||||||
|
from core.capability import CapabilityArtifactQuery, artifact_report
|
||||||
|
|
||||||
|
report = artifact_report(
|
||||||
|
CapabilityArtifactQuery(lane=args.lane, split=args.split, version=args.version)
|
||||||
|
)
|
||||||
|
print(json.dumps(report, indent=2, sort_keys=True) if args.json else report)
|
||||||
|
return 0
|
||||||
|
|
||||||
|
|
||||||
|
def cmd_capability_domain_contract(args: argparse.Namespace) -> int:
|
||||||
|
"""ADR-0093 domain-contract dry-run validator.
|
||||||
|
|
||||||
|
Default behavior runs the nine ADR-0091 predicates plus eval-lane
|
||||||
|
artifact resolution and exits non-zero on any predicate failure.
|
||||||
|
The legacy structural-only output remains available via
|
||||||
|
``--structural-only`` for callers that depend on the prior shape.
|
||||||
|
"""
|
||||||
|
from language_packs.domain_contract import validate_domain_contract_pack
|
||||||
|
|
||||||
|
if getattr(args, "structural_only", False):
|
||||||
|
report = validate_domain_contract_pack(args.pack_id).as_dict()
|
||||||
|
print(json.dumps(report, indent=2, sort_keys=True) if args.json else report)
|
||||||
|
return 0 if report["valid"] else 1
|
||||||
|
|
||||||
|
from core.capability.domain_contract_predicates import evaluate_domain_contract
|
||||||
|
|
||||||
|
predicate_report = evaluate_domain_contract(args.pack_id).as_dict()
|
||||||
|
print(
|
||||||
|
json.dumps(predicate_report, indent=2, sort_keys=True)
|
||||||
|
if args.json
|
||||||
|
else predicate_report
|
||||||
|
)
|
||||||
|
return 0 if predicate_report["all_passed"] else 1
|
||||||
|
|
||||||
|
|
||||||
|
def cmd_capability_evidence_plan(args: argparse.Namespace) -> int:
|
||||||
|
from core.capability import evidence_plan_report
|
||||||
|
|
||||||
|
report = evidence_plan_report()
|
||||||
|
print(json.dumps(report, indent=2, sort_keys=True) if args.json else report)
|
||||||
|
return 0
|
||||||
|
|
||||||
|
|
||||||
|
def cmd_capability_perturbation(args: argparse.Namespace) -> int:
|
||||||
|
"""ADR-0114a Obligation #5 — reasoning-isolation perturbation suite for B3.
|
||||||
|
|
||||||
|
Generates and scores invariance-preserving and invariance-breaking
|
||||||
|
perturbations over B3 (bounded grammar) expected-correct cases.
|
||||||
|
Writes the report to ``evals/obligation_5_perturbation/<lane_id>.json``.
|
||||||
|
Exit 0 iff both preserving_rate == 1.0 AND breaking_rate == 1.0.
|
||||||
|
"""
|
||||||
|
from pathlib import Path as _Path
|
||||||
|
from core.capability.perturbation_b3 import (
|
||||||
|
validate_perturbation_suite,
|
||||||
|
emit_perturbation_report,
|
||||||
|
)
|
||||||
|
|
||||||
|
lane_id = args.lane_id
|
||||||
|
report = validate_perturbation_suite(lane_id=lane_id)
|
||||||
|
|
||||||
|
out_dir = _Path(__file__).resolve().parent.parent / "evals" / "obligation_5_perturbation"
|
||||||
|
out_dir.mkdir(parents=True, exist_ok=True)
|
||||||
|
out_path = out_dir / f"{lane_id}.json"
|
||||||
|
emit_perturbation_report(report, out_path)
|
||||||
|
|
||||||
|
if args.json:
|
||||||
|
print(json.dumps(report.as_dict(), indent=2, sort_keys=True))
|
||||||
|
else:
|
||||||
|
print(f"lane_id: {report.lane_id}")
|
||||||
|
print(f"cases_total: {report.cases_total}")
|
||||||
|
print(f"cases_expected_correct: {report.cases_expected_correct}")
|
||||||
|
print(
|
||||||
|
f"preserving: {report.preserving_correct}/{report.preserving_attempted} "
|
||||||
|
f"= {report.preserving_rate:.4f}"
|
||||||
|
)
|
||||||
|
print(
|
||||||
|
f"breaking: {report.breaking_correct}/{report.breaking_attempted} "
|
||||||
|
f"= {report.breaking_rate:.4f}"
|
||||||
|
)
|
||||||
|
print(f"obligation_5_passed: {report.obligation_5_passed}")
|
||||||
|
print(f"report_digest: {report.report_digest}")
|
||||||
|
print(f"artifact: {out_path}")
|
||||||
|
if not report.obligation_5_passed:
|
||||||
|
print(f"refusal_reason: {report.refusal_reason}")
|
||||||
|
return 0 if report.obligation_5_passed else 1
|
||||||
|
|
||||||
|
|
||||||
|
def cmd_capability_math_expert_gate(args: argparse.Namespace) -> int:
|
||||||
|
"""ADR-0131.4 — evaluate the composite math-expert promotion gate
|
||||||
|
(Benchmark 1 + 2 + 3, ADR-0131's revision of ADR-0120's single-lane
|
||||||
|
coverage check). Emits ``expert_claims_math_v1.json`` to ``--out``
|
||||||
|
(default: ``evals/math_expert_claims/v1/expert_claims_math_v1.json``).
|
||||||
|
Exit 0 iff every benchmark passes."""
|
||||||
|
from core.capability.composite_math_gate import (
|
||||||
|
emit_expert_claims_artifact,
|
||||||
|
evaluate_composite_math_gate,
|
||||||
|
)
|
||||||
|
|
||||||
|
verdict = evaluate_composite_math_gate()
|
||||||
|
out_path = Path(args.out) if args.out else (
|
||||||
|
Path(__file__).resolve().parent.parent
|
||||||
|
/ "evals" / "math_expert_claims" / "v1" / "expert_claims_math_v1.json"
|
||||||
|
)
|
||||||
|
out_path.parent.mkdir(parents=True, exist_ok=True)
|
||||||
|
emit_expert_claims_artifact(verdict, out_path)
|
||||||
|
|
||||||
|
if args.json:
|
||||||
|
print(json.dumps(verdict.as_dict(), indent=2, sort_keys=True))
|
||||||
|
else:
|
||||||
|
print(f"composite_gate_passed: {verdict.composite_gate_passed}")
|
||||||
|
print(f"claim_digest: {verdict.claim_digest}")
|
||||||
|
print(f"artifact: {out_path}")
|
||||||
|
for b in verdict.benchmarks:
|
||||||
|
print(
|
||||||
|
f" {b.benchmark_id:>20} passed={b.passed} "
|
||||||
|
f"correct={b.correct}/{b.cases_total} wrong={b.wrong} "
|
||||||
|
f"rate={b.correct_rate:.4f}"
|
||||||
|
)
|
||||||
|
hd = verdict.honest_disclosure
|
||||||
|
print(
|
||||||
|
f"GSM8K honest disclosure: admission={hd.get('admitted_solved', 0)}/"
|
||||||
|
f"{hd.get('cases_total', 0)}, wrong={hd.get('admitted_wrong', 0)}, "
|
||||||
|
f"substrate={hd.get('substrate', '?')}"
|
||||||
|
)
|
||||||
|
if not verdict.composite_gate_passed:
|
||||||
|
print(f"refusal_reason: {verdict.refusal_reason}")
|
||||||
|
return 0 if verdict.composite_gate_passed else 1
|
||||||
|
|
||||||
|
|
||||||
|
def cmd_capability_pack_provenance(args: argparse.Namespace) -> int:
|
||||||
|
"""ADR-0114a Obligation #10 — external audit that every solver
|
||||||
|
step's ``pack_lemma_id`` resolves to a real entry in the domain's
|
||||||
|
operator pack lexicon. Defaults to B3 (bounded grammar) under
|
||||||
|
``en_arithmetic_v1``. Emits report to ``--out`` (default:
|
||||||
|
``evals/obligation_10_pack_provenance/<lane_id>.json``).
|
||||||
|
Exit 0 iff obligation passes."""
|
||||||
|
from core.capability.pack_provenance import (
|
||||||
|
emit_provenance_report,
|
||||||
|
validate_lane,
|
||||||
|
)
|
||||||
|
|
||||||
|
report = validate_lane()
|
||||||
|
out_path = Path(args.out) if args.out else (
|
||||||
|
Path(__file__).resolve().parent.parent
|
||||||
|
/ "evals" / "obligation_10_pack_provenance"
|
||||||
|
/ f"{report.lane_id}.json"
|
||||||
|
)
|
||||||
|
out_path.parent.mkdir(parents=True, exist_ok=True)
|
||||||
|
emit_provenance_report(report, out_path)
|
||||||
|
|
||||||
|
if args.json:
|
||||||
|
print(json.dumps(report.as_dict(), indent=2, sort_keys=True))
|
||||||
|
else:
|
||||||
|
print(f"lane: {report.lane_id}")
|
||||||
|
print(f"pack_id: {report.pack_id}")
|
||||||
|
print(f"cases_total: {report.cases_total}")
|
||||||
|
print(f"cases_validated: {report.cases_validated}")
|
||||||
|
print(f"cases_skipped_unsolved: {report.cases_skipped_unsolved}")
|
||||||
|
print(f"cases_violated: {report.cases_violated}")
|
||||||
|
print(f"obligation_10_passed: {report.obligation_10_passed}")
|
||||||
|
print("distinct_lemma_ids_observed:")
|
||||||
|
for lid in report.distinct_lemma_ids_observed:
|
||||||
|
print(f" - {lid}")
|
||||||
|
print(f"artifact: {out_path}")
|
||||||
|
if report.refusal_reason:
|
||||||
|
print(f"refusal_reason: {report.refusal_reason}")
|
||||||
|
return 0 if report.obligation_10_passed else 1
|
||||||
|
|
||||||
|
|
||||||
|
def cmd_capability_adversarial(args: argparse.Namespace) -> int:
|
||||||
|
"""ADR-0114a Obligation #8 — adversarial generation auditor. Runs
|
||||||
|
a committed adversarial case set through the candidate-graph
|
||||||
|
pipeline; gate is ``wrong == 0`` across all families AND
|
||||||
|
``cases_total >= 30`` AND ``families_total >= 8``. Default cases
|
||||||
|
set ``evals/obligation_8_adversarial/v1/cases.jsonl``; writes
|
||||||
|
report to ``--out`` (default
|
||||||
|
``evals/obligation_8_adversarial/<lane_id>.json``). Exit 0 iff
|
||||||
|
obligation passes."""
|
||||||
|
from core.capability.adversarial import (
|
||||||
|
emit_adversarial_report,
|
||||||
|
evaluate_adversarial,
|
||||||
|
)
|
||||||
|
|
||||||
|
report = evaluate_adversarial()
|
||||||
|
out_path = Path(args.out) if args.out else (
|
||||||
|
Path(__file__).resolve().parent.parent
|
||||||
|
/ "evals" / "obligation_8_adversarial"
|
||||||
|
/ f"{report.lane_id}.json"
|
||||||
|
)
|
||||||
|
out_path.parent.mkdir(parents=True, exist_ok=True)
|
||||||
|
emit_adversarial_report(report, out_path)
|
||||||
|
|
||||||
|
if args.json:
|
||||||
|
print(json.dumps(report.as_dict(), indent=2, sort_keys=True))
|
||||||
|
else:
|
||||||
|
print(f"lane: {report.lane_id}")
|
||||||
|
print(f"cases_total: {report.cases_total} (min {report.cases_total >= 30 and 'OK' or 'FAIL'})")
|
||||||
|
print(f"families_total: {report.families_total} ({'OK' if report.families_total >= 8 else 'FAIL'})")
|
||||||
|
print(f"cases_refused: {report.cases_refused}")
|
||||||
|
print(f"cases_solved: {report.cases_solved}")
|
||||||
|
print(f"cases_wrong: {report.cases_wrong} (gate: must be 0)")
|
||||||
|
print(f"obligation_8_passed: {report.obligation_8_passed}")
|
||||||
|
print()
|
||||||
|
print(f" {'family':<22} {'total':<7} {'refused':<8} {'solved':<8} {'wrong'}")
|
||||||
|
for f in report.families:
|
||||||
|
print(f" {f.family:<22} {f.cases_total:<7} {f.cases_refused:<8} {f.cases_solved:<8} {f.cases_wrong}")
|
||||||
|
print(f"\nartifact: {out_path}")
|
||||||
|
if report.refusal_reason:
|
||||||
|
print(f"refusal_reason: {report.refusal_reason}")
|
||||||
|
return 0 if report.obligation_8_passed else 1
|
||||||
|
|
||||||
|
|
||||||
|
def cmd_capability_depth_curve(args: argparse.Namespace) -> int:
|
||||||
|
"""ADR-0114a Obligation #6 — compositional-depth curve. Re-runs the
|
||||||
|
lane's expected-correct cases, buckets by ``len(trace.steps)``,
|
||||||
|
asserts ``accuracy(N) >= accuracy(depth_1) * (1 - eps)^(N-1)`` for
|
||||||
|
eps = 0.05. Defaults to B3 (bounded grammar). Emits report to
|
||||||
|
``--out`` (default ``evals/obligation_6_depth_curve/<lane_id>.json``).
|
||||||
|
Exit 0 iff the assertion holds."""
|
||||||
|
from core.capability.depth_curve import (
|
||||||
|
emit_depth_curve_report,
|
||||||
|
evaluate_depth_curve,
|
||||||
|
)
|
||||||
|
|
||||||
|
report = evaluate_depth_curve()
|
||||||
|
out_path = Path(args.out) if args.out else (
|
||||||
|
Path(__file__).resolve().parent.parent
|
||||||
|
/ "evals" / "obligation_6_depth_curve"
|
||||||
|
/ f"{report.lane_id}.json"
|
||||||
|
)
|
||||||
|
out_path.parent.mkdir(parents=True, exist_ok=True)
|
||||||
|
emit_depth_curve_report(report, out_path)
|
||||||
|
|
||||||
|
if args.json:
|
||||||
|
print(json.dumps(report.as_dict(), indent=2, sort_keys=True))
|
||||||
|
else:
|
||||||
|
print(f"lane: {report.lane_id}")
|
||||||
|
print(f"cases_total: {report.cases_total}")
|
||||||
|
print(f"cases_solved: {report.cases_solved}")
|
||||||
|
print(f"epsilon: {report.epsilon}")
|
||||||
|
print(f"mechanism_wired: {report.obligation_6_mechanism_wired}")
|
||||||
|
print(f"assertion_holds: {report.obligation_6_assertion_holds}")
|
||||||
|
print(f"coverage_sufficient: {report.coverage_sufficient}")
|
||||||
|
print(f"populated_buckets: {list(report.populated_buckets)}")
|
||||||
|
print()
|
||||||
|
print(f" {'bucket':<12} {'total':<7} {'correct':<8} {'accuracy':<10} {'bound':<10} {'satisfied'}")
|
||||||
|
for b in report.buckets:
|
||||||
|
bound = f"{b.bound_required:.4f}" if b.bound_required is not None else "(anchor)"
|
||||||
|
print(f" {b.bucket:<12} {b.cases_total:<7} {b.cases_correct:<8} {b.accuracy:<10.4f} {bound:<10} {b.bound_satisfied}")
|
||||||
|
print(f"\nartifact: {out_path}")
|
||||||
|
if report.refusal_reason:
|
||||||
|
print(f"refusal_reason: {report.refusal_reason}")
|
||||||
|
return 0 if report.obligation_6_assertion_holds else 1
|
||||||
|
|
||||||
|
|
||||||
|
def cmd_capability_ood_ratio(args: argparse.Namespace) -> int:
|
||||||
|
"""ADR-0114a Obligation #2 — OOD surface variation ratio auditor.
|
||||||
|
|
||||||
|
Reads the B3 public ``report.json`` and the OOD lane ``report.json``,
|
||||||
|
computes ``ood_ratio = ood_accuracy / public_accuracy``, and exits 0
|
||||||
|
iff ratio >= 0.95 AND ood wrong == 0. Writes report to ``--out``
|
||||||
|
(default: ``evals/obligation_2_ood_ratio/<lane_id>.json``)."""
|
||||||
|
from core.capability.ood_ratio import (
|
||||||
|
emit_ood_ratio_report,
|
||||||
|
evaluate_ood_ratio,
|
||||||
|
)
|
||||||
|
from evals.obligation_2_ood_ratio.v1.runner import build_report, load_cases, write_report as write_ood_report
|
||||||
|
|
||||||
|
_repo_root = Path(__file__).resolve().parent.parent
|
||||||
|
|
||||||
|
# Regenerate OOD report so auditor always reads fresh results.
|
||||||
|
ood_report_path = _repo_root / "evals" / "obligation_2_ood_ratio" / "v1" / "report.json"
|
||||||
|
ood_cases = load_cases()
|
||||||
|
ood_runner_report = build_report(ood_cases)
|
||||||
|
write_ood_report(ood_runner_report, ood_report_path)
|
||||||
|
|
||||||
|
report = evaluate_ood_ratio()
|
||||||
|
out_path = Path(args.out) if args.out else (
|
||||||
|
_repo_root
|
||||||
|
/ "evals" / "obligation_2_ood_ratio"
|
||||||
|
/ f"{report.lane_id}.json"
|
||||||
|
)
|
||||||
|
out_path.parent.mkdir(parents=True, exist_ok=True)
|
||||||
|
emit_ood_ratio_report(report, out_path)
|
||||||
|
|
||||||
|
if args.json:
|
||||||
|
print(json.dumps(report.as_dict(), indent=2, sort_keys=True))
|
||||||
|
else:
|
||||||
|
print(f"lane: {report.lane_id}")
|
||||||
|
print(f"public_accuracy: {report.public_accuracy:.4f} ({report.public_cases_correct}/{report.public_cases_total})")
|
||||||
|
print(f"ood_accuracy: {report.ood_accuracy:.4f} ({report.ood_cases_correct}/{report.ood_cases_total})")
|
||||||
|
print(f"ood_ratio: {report.ood_ratio:.4f}")
|
||||||
|
print(f"obligation_2_ratio_satisfied:{report.obligation_2_ratio_satisfied}")
|
||||||
|
print(f"obligation_2_wrong_zero: {report.obligation_2_wrong_zero}")
|
||||||
|
print(f"obligation_2_passed: {report.obligation_2_passed}")
|
||||||
|
print(f"artifact: {out_path}")
|
||||||
|
if report.refusal_reason:
|
||||||
|
print(f"refusal_reason: {report.refusal_reason}")
|
||||||
|
return 0 if report.obligation_2_passed else 1
|
||||||
|
|
||||||
|
|
||||||
|
def cmd_capability_math_expert_promote(args: argparse.Namespace) -> int:
|
||||||
|
"""ADR-0120 math-expert promotion composer. Collects all 10 ADR-0114a
|
||||||
|
obligation verdicts + the ADR-0131.4 composite math gate verdict +
|
||||||
|
the reviewer-signed claim entry from ``docs/reviewers.yaml``;
|
||||||
|
emits a deterministic ``expert_claims_math_v1_signed.json``
|
||||||
|
artifact. Exit 0 iff ``promote_admitted == True``.
|
||||||
|
"""
|
||||||
|
from core.capability.expert_promotion_math import (
|
||||||
|
emit_promotion_artifact,
|
||||||
|
evaluate_math_expert_promotion,
|
||||||
|
)
|
||||||
|
|
||||||
|
verdict = evaluate_math_expert_promotion()
|
||||||
|
out_path = Path(args.out) if args.out else (
|
||||||
|
Path(__file__).resolve().parent.parent
|
||||||
|
/ "evals" / "math_expert_claims" / "v1" / "expert_claims_math_v1_signed.json"
|
||||||
|
)
|
||||||
|
out_path.parent.mkdir(parents=True, exist_ok=True)
|
||||||
|
emit_promotion_artifact(verdict, out_path)
|
||||||
|
|
||||||
|
if args.json:
|
||||||
|
print(json.dumps(verdict.as_dict(), indent=2, sort_keys=True))
|
||||||
|
else:
|
||||||
|
print(f"domain: {verdict.domain}")
|
||||||
|
print()
|
||||||
|
print(f" {'id':<4} {'passed':<7} title")
|
||||||
|
for o in verdict.obligations:
|
||||||
|
print(f" {o.obligation_id:<4} {str(o.passed):<7} {o.title}")
|
||||||
|
if not o.passed:
|
||||||
|
print(f" refusal: {o.refusal_reason}")
|
||||||
|
print()
|
||||||
|
print(f"composite_gate_passed: {verdict.composite_gate_passed}")
|
||||||
|
print(f"all_obligations_passed: {verdict.all_obligations_passed}")
|
||||||
|
print(f"technical_pass: {verdict.technical_pass}")
|
||||||
|
print(f"claim_digest: {verdict.claim_digest}")
|
||||||
|
print(f"reviewer_signature_present: {verdict.reviewer_signature is not None}")
|
||||||
|
print(f"reviewer_signature_matches: {verdict.reviewer_signature_matches}")
|
||||||
|
print(f"promote_admitted: {verdict.promote_admitted}")
|
||||||
|
print(f"artifact: {out_path}")
|
||||||
|
if verdict.refusal_reason:
|
||||||
|
print()
|
||||||
|
print("refusal_reason:")
|
||||||
|
print(f" {verdict.refusal_reason}")
|
||||||
|
return 0 if verdict.promote_admitted else 1
|
||||||
|
|
||||||
|
|
||||||
73
core/cli_doctor.py
Normal file
73
core/cli_doctor.py
Normal file
|
|
@ -0,0 +1,73 @@
|
||||||
|
"""Doctor/package-health CLI command handler."""
|
||||||
|
|
||||||
|
from __future__ import annotations
|
||||||
|
|
||||||
|
import argparse
|
||||||
|
from pathlib import Path
|
||||||
|
|
||||||
|
from core import cli_rust
|
||||||
|
|
||||||
|
|
||||||
|
DEFAULT_REPO_ROOT = Path(__file__).resolve().parent.parent
|
||||||
|
|
||||||
|
IMPORT_CHECKS: tuple[tuple[str, str], ...] = (
|
||||||
|
("algebra", "algebra"),
|
||||||
|
("alignment", "alignment.graph"),
|
||||||
|
("benchmarks", "benchmarks.run_benchmarks"),
|
||||||
|
("calibration", "calibration"),
|
||||||
|
("chat", "chat.runtime"),
|
||||||
|
("core_ingest", "core_ingest"),
|
||||||
|
("demos", "demos.claude_tool_authority"),
|
||||||
|
("engine_state", "engine_state"),
|
||||||
|
("evals", "evals.framework"),
|
||||||
|
("language_packs", "language_packs"),
|
||||||
|
("morphology", "morphology.registry"),
|
||||||
|
("packs", "packs.safety.loader"),
|
||||||
|
("scripts", "scripts.run_pulse"),
|
||||||
|
("sensorium", "sensorium.protocol"),
|
||||||
|
("teaching", "teaching"),
|
||||||
|
("workbench", "workbench"),
|
||||||
|
)
|
||||||
|
|
||||||
|
|
||||||
|
def cmd_doctor(args: argparse.Namespace, *, repo_root: Path = DEFAULT_REPO_ROOT) -> int:
|
||||||
|
"""Inspect import/package health for the CLI runtime path."""
|
||||||
|
ok = True
|
||||||
|
print(f"repo_root: {repo_root}")
|
||||||
|
for label, module_name in IMPORT_CHECKS:
|
||||||
|
try:
|
||||||
|
__import__(module_name)
|
||||||
|
except Exception as exc:
|
||||||
|
ok = False
|
||||||
|
print(f"FAIL {label:<14} {module_name}: {exc.__class__.__name__}: {exc}")
|
||||||
|
else:
|
||||||
|
print(f"OK {label:<14} {module_name}")
|
||||||
|
|
||||||
|
rust_importable, rust_detail = cli_rust.probe_core_rs()
|
||||||
|
print(
|
||||||
|
"INFO native core_rs "
|
||||||
|
f"{'importable' if rust_importable else 'not importable'}: {rust_detail}"
|
||||||
|
)
|
||||||
|
print("INFO native policy optional; run `core doctor --rust --require-rust` to gate it")
|
||||||
|
|
||||||
|
if args.packs:
|
||||||
|
try:
|
||||||
|
from language_packs import list_packs
|
||||||
|
|
||||||
|
packs = list_packs()
|
||||||
|
except Exception as exc:
|
||||||
|
ok = False
|
||||||
|
print(f"FAIL packs language_packs.list_packs: {exc.__class__.__name__}: {exc}")
|
||||||
|
else:
|
||||||
|
print("packs:")
|
||||||
|
if packs:
|
||||||
|
for pack_id in packs:
|
||||||
|
print(f" {pack_id}")
|
||||||
|
else:
|
||||||
|
print(" none found")
|
||||||
|
|
||||||
|
if args.rust:
|
||||||
|
rust_active = cli_rust.print_rust_status(repo_root=repo_root)
|
||||||
|
if args.require_rust and not rust_active:
|
||||||
|
ok = False
|
||||||
|
return 0 if ok else 1
|
||||||
258
core/cli_eval.py
Normal file
258
core/cli_eval.py
Normal file
|
|
@ -0,0 +1,258 @@
|
||||||
|
"""Extracted commands."""
|
||||||
|
from __future__ import annotations
|
||||||
|
import argparse
|
||||||
|
import json
|
||||||
|
import sys
|
||||||
|
from pathlib import Path
|
||||||
|
|
||||||
|
from core.cli import _validate_output_path, _DEFAULT_AUDIT_PATH
|
||||||
|
from core.cli import _die, _REPO_ROOT
|
||||||
|
|
||||||
|
def cmd_eval(args: argparse.Namespace) -> int:
|
||||||
|
"""Run an eval lane by name, or list available lanes."""
|
||||||
|
if getattr(args, "lane", None) == "sensorium":
|
||||||
|
return cmd_eval_sensorium(args)
|
||||||
|
if getattr(args, "lane", None) == "environment-falsification":
|
||||||
|
return cmd_eval_environment_falsification(args)
|
||||||
|
if getattr(args, "lane", None) == "math-contemplation":
|
||||||
|
return cmd_eval_math_contemplation(args)
|
||||||
|
|
||||||
|
from evals._parallel import normalize_workers
|
||||||
|
from evals.framework import (
|
||||||
|
discover_lanes,
|
||||||
|
get_lane,
|
||||||
|
load_cases,
|
||||||
|
run_lane,
|
||||||
|
write_result,
|
||||||
|
)
|
||||||
|
|
||||||
|
if args.list_lanes:
|
||||||
|
lanes = discover_lanes()
|
||||||
|
if not lanes:
|
||||||
|
print("no eval lanes found")
|
||||||
|
for lane in lanes:
|
||||||
|
versions = ", ".join(lane.versions) if lane.versions else "none"
|
||||||
|
print(f" {lane.name:20s} versions: {versions}")
|
||||||
|
return 0
|
||||||
|
|
||||||
|
lane_name = args.lane
|
||||||
|
if not lane_name:
|
||||||
|
_die("eval requires a lane name. Use `core eval --list` to see available lanes.")
|
||||||
|
|
||||||
|
try:
|
||||||
|
lane = get_lane(lane_name)
|
||||||
|
except FileNotFoundError as exc:
|
||||||
|
_die(str(exc))
|
||||||
|
|
||||||
|
version = args.version or (lane.versions[0] if lane.versions else "v1")
|
||||||
|
split = args.split
|
||||||
|
|
||||||
|
if not args.json and lane_name == "cognition":
|
||||||
|
if split == "dev":
|
||||||
|
cases_path = lane.dev_cases_path()
|
||||||
|
elif split == "public":
|
||||||
|
cases_path = lane.public_cases_path(version)
|
||||||
|
else:
|
||||||
|
cases_path = lane.holdout_cases_path(version)
|
||||||
|
cases = load_cases(cases_path)
|
||||||
|
effective_workers = normalize_workers(
|
||||||
|
args.workers if args.workers is not None else 4,
|
||||||
|
len(cases),
|
||||||
|
)
|
||||||
|
print(f"workers : {effective_workers}")
|
||||||
|
|
||||||
|
try:
|
||||||
|
result = run_lane(
|
||||||
|
lane,
|
||||||
|
version=version,
|
||||||
|
split=split,
|
||||||
|
workers=args.workers,
|
||||||
|
)
|
||||||
|
except FileNotFoundError as exc:
|
||||||
|
_die(str(exc))
|
||||||
|
|
||||||
|
if args.json:
|
||||||
|
print(json.dumps(result.as_dict(), ensure_ascii=False, indent=2, sort_keys=True))
|
||||||
|
else:
|
||||||
|
print(f"lane : {result.lane}")
|
||||||
|
print(f"version : {result.version}")
|
||||||
|
print(f"split : {result.split}")
|
||||||
|
print(f"cases : {result.metrics.get('total', 0)}")
|
||||||
|
for key, value in result.metrics.items():
|
||||||
|
if key == "total":
|
||||||
|
continue
|
||||||
|
if isinstance(value, float):
|
||||||
|
print(f"{key:15s}: {value:.1%}")
|
||||||
|
else:
|
||||||
|
print(f"{key:15s}: {value}")
|
||||||
|
if lane_name == "cognition":
|
||||||
|
# The cognition lane case_details carry `intent_correct` and
|
||||||
|
# `versor_closure` booleans; other lanes do not, so the
|
||||||
|
# cognition-specific failure printer is gated on lane identity to
|
||||||
|
# avoid spurious "failures" output for lanes that pass cleanly.
|
||||||
|
failures = [
|
||||||
|
c for c in result.case_details
|
||||||
|
if not c.get("intent_correct") or not c.get("versor_closure")
|
||||||
|
]
|
||||||
|
if failures:
|
||||||
|
print(f"\nfailures ({len(failures)}):")
|
||||||
|
for c in failures:
|
||||||
|
issues = []
|
||||||
|
if not c.get("intent_correct"):
|
||||||
|
issues.append("intent")
|
||||||
|
if not c.get("versor_closure"):
|
||||||
|
vc = c.get("versor_condition", 0)
|
||||||
|
issues.append(f"versor={vc:.2e}")
|
||||||
|
cid = c.get("case_id") or c.get("id") or "<unknown>"
|
||||||
|
print(f" {cid}: {', '.join(issues)}")
|
||||||
|
|
||||||
|
if args.save:
|
||||||
|
result_path = write_result(lane, result)
|
||||||
|
print(f"\nresult written: {result_path}", file=sys.stderr)
|
||||||
|
|
||||||
|
if args.report:
|
||||||
|
report_path = Path(args.report)
|
||||||
|
report_path.parent.mkdir(parents=True, exist_ok=True)
|
||||||
|
report_path.write_text(
|
||||||
|
json.dumps(result.as_dict(), ensure_ascii=False, indent=2, sort_keys=True)
|
||||||
|
)
|
||||||
|
print(f"\nreport written: {report_path}", file=sys.stderr)
|
||||||
|
|
||||||
|
return 0
|
||||||
|
|
||||||
|
|
||||||
|
def cmd_eval_sensorium(args: argparse.Namespace) -> int:
|
||||||
|
"""Run deterministic sensorium modality evidence reports."""
|
||||||
|
from evals.sensorium import build_sensorium_report
|
||||||
|
|
||||||
|
modality = getattr(args, "modality", "vision") or "vision"
|
||||||
|
try:
|
||||||
|
report = build_sensorium_report(modality)
|
||||||
|
except ValueError as exc:
|
||||||
|
_die(str(exc), code=2)
|
||||||
|
|
||||||
|
if getattr(args, "json", False):
|
||||||
|
print(json.dumps(report, ensure_ascii=False, indent=2, sort_keys=True))
|
||||||
|
else:
|
||||||
|
print(f"lane : {report['lane']}")
|
||||||
|
print(f"modality : {report['modality']}")
|
||||||
|
print(f"pack_id : {report['pack_id']}")
|
||||||
|
print(f"gate_engaged : {report['gate_engaged']}")
|
||||||
|
print(f"gate_closed : {report['gate_closed']}")
|
||||||
|
print(f"cases : {report['total']}")
|
||||||
|
print(f"passed : {report['passed']}")
|
||||||
|
print(f"failed : {report['failed']}")
|
||||||
|
|
||||||
|
if getattr(args, "report", None):
|
||||||
|
report_path = Path(args.report)
|
||||||
|
report_path.parent.mkdir(parents=True, exist_ok=True)
|
||||||
|
report_path.write_text(
|
||||||
|
json.dumps(report, ensure_ascii=False, indent=2, sort_keys=True)
|
||||||
|
)
|
||||||
|
print(f"\nreport written: {report_path}", file=sys.stderr)
|
||||||
|
|
||||||
|
return 0 if report["failed"] == 0 and report["gate_closed"] else 1
|
||||||
|
|
||||||
|
|
||||||
|
def cmd_eval_environment_falsification(args: argparse.Namespace) -> int:
|
||||||
|
"""Run deterministic environmental falsification replay reports."""
|
||||||
|
from evals.environment_falsification import build_environment_falsification_report
|
||||||
|
|
||||||
|
report = build_environment_falsification_report()
|
||||||
|
|
||||||
|
if getattr(args, "json", False):
|
||||||
|
print(json.dumps(report, ensure_ascii=False, indent=2, sort_keys=True))
|
||||||
|
else:
|
||||||
|
print(f"lane : {report['lane']}")
|
||||||
|
print(f"version : {report['version']}")
|
||||||
|
print(f"cases : {report['total']}")
|
||||||
|
print(f"passed : {report['passed']}")
|
||||||
|
print(f"failed : {report['failed']}")
|
||||||
|
print(f"report_sha256 : {report['report_sha256']}")
|
||||||
|
|
||||||
|
if getattr(args, "report", None):
|
||||||
|
report_path = Path(args.report)
|
||||||
|
report_path.parent.mkdir(parents=True, exist_ok=True)
|
||||||
|
report_path.write_text(
|
||||||
|
json.dumps(report, ensure_ascii=False, indent=2, sort_keys=True)
|
||||||
|
)
|
||||||
|
print(f"\nreport written: {report_path}", file=sys.stderr)
|
||||||
|
|
||||||
|
return 0 if report["failed"] == 0 and report["expected_report_hash_ok"] else 1
|
||||||
|
|
||||||
|
|
||||||
|
def cmd_eval_math_contemplation(args: argparse.Namespace) -> int:
|
||||||
|
"""ADR-0172 W3 — decompose an audit brief into refusal-shape proposals.
|
||||||
|
|
||||||
|
Reads ``--audit`` (default: ``evals/gsm8k_math/train_sample/v1/audit_brief_11.json``),
|
||||||
|
runs :func:`teaching.math_contemplation.decompose_audit`, and writes one
|
||||||
|
``canonical_bytes()`` JSON line per proposal to ``--output``
|
||||||
|
(default: ``teaching/math_proposals/proposals.jsonl``).
|
||||||
|
|
||||||
|
Idempotency: re-running on the same audit overwrites byte-identical bytes.
|
||||||
|
Output is sorted by ``proposal_id`` (matches the decomposer sort contract).
|
||||||
|
|
||||||
|
Exit codes:
|
||||||
|
0 success
|
||||||
|
1 audit file not found
|
||||||
|
2 parse error or path-traversal rejection
|
||||||
|
|
||||||
|
Forbidden by design: no proposal is auto-applied, no file outside
|
||||||
|
``teaching/math_proposals/`` is written, the audit file is not mutated.
|
||||||
|
"""
|
||||||
|
from teaching.math_contemplation import decompose_audit
|
||||||
|
from teaching.math_contemplation_proposal import to_jsonl_record
|
||||||
|
|
||||||
|
audit_raw = getattr(args, "audit", None)
|
||||||
|
output_raw = getattr(args, "output", None)
|
||||||
|
|
||||||
|
audit_path = Path(audit_raw) if audit_raw else _DEFAULT_AUDIT_PATH
|
||||||
|
if not audit_path.is_absolute():
|
||||||
|
audit_path = (_REPO_ROOT / audit_path).resolve()
|
||||||
|
|
||||||
|
if not audit_path.exists():
|
||||||
|
_die(f"audit file not found: {audit_path}", code=1)
|
||||||
|
|
||||||
|
output_path = _validate_output_path(output_raw)
|
||||||
|
|
||||||
|
try:
|
||||||
|
proposals = decompose_audit(audit_path)
|
||||||
|
except json.JSONDecodeError as exc:
|
||||||
|
_die(f"parse error in audit file {audit_path}: {exc}", code=2)
|
||||||
|
|
||||||
|
output_path.parent.mkdir(parents=True, exist_ok=True)
|
||||||
|
|
||||||
|
# Self-contained JSONL (ADR-0172 tightening follow-up #1): each line
|
||||||
|
# carries proposal_id, full evidence_pointers, and full
|
||||||
|
# reasoning_trace.steps so consumers can load without re-running the
|
||||||
|
# decomposer.
|
||||||
|
lines: list[bytes] = []
|
||||||
|
for proposal in proposals:
|
||||||
|
record = to_jsonl_record(proposal)
|
||||||
|
encoded = json.dumps(
|
||||||
|
record,
|
||||||
|
ensure_ascii=False,
|
||||||
|
sort_keys=True,
|
||||||
|
separators=(",", ":"),
|
||||||
|
).encode("utf-8")
|
||||||
|
lines.append(encoded + b"\n")
|
||||||
|
output_path.write_bytes(b"".join(lines))
|
||||||
|
|
||||||
|
if not getattr(args, "json", False):
|
||||||
|
print(f"proposals : {len(proposals)}")
|
||||||
|
print(f"output : {output_path}")
|
||||||
|
else:
|
||||||
|
print(
|
||||||
|
json.dumps(
|
||||||
|
{
|
||||||
|
"proposals": len(proposals),
|
||||||
|
"output": str(output_path),
|
||||||
|
},
|
||||||
|
ensure_ascii=False,
|
||||||
|
sort_keys=True,
|
||||||
|
)
|
||||||
|
)
|
||||||
|
|
||||||
|
return 0
|
||||||
|
|
||||||
|
|
||||||
227
core/cli_ingest.py
Normal file
227
core/cli_ingest.py
Normal file
|
|
@ -0,0 +1,227 @@
|
||||||
|
"""Operator-facing CLI for the durable ``core_ingest`` boundary."""
|
||||||
|
from __future__ import annotations
|
||||||
|
|
||||||
|
import argparse
|
||||||
|
import hashlib
|
||||||
|
import json
|
||||||
|
import sys
|
||||||
|
from pathlib import Path
|
||||||
|
from typing import Any
|
||||||
|
|
||||||
|
from core_ingest import IngestPipeline, IngestPipelineConfig, SegmentManifold
|
||||||
|
from core_ingest.types import LearningArtifact, SourceSpan, ValidationReport
|
||||||
|
|
||||||
|
|
||||||
|
_MODALITY_HINTS = ("prose", "scripture", "code", "math")
|
||||||
|
_DEFAULT_MAX_BYTES = 1_048_576
|
||||||
|
_TRUST_BOUNDARY = (
|
||||||
|
"read_only_durable_core_ingest_compile_no_gate_import_no_vault_or_pack_mutation"
|
||||||
|
)
|
||||||
|
|
||||||
|
|
||||||
|
def _source_from_args(args: argparse.Namespace) -> tuple[bytes, dict[str, Any]]:
|
||||||
|
if args.text is not None:
|
||||||
|
source = args.text.encode("utf-8")
|
||||||
|
return source, {
|
||||||
|
"kind": "text",
|
||||||
|
"bytes": len(source),
|
||||||
|
"sha256": hashlib.sha256(source).hexdigest(),
|
||||||
|
}
|
||||||
|
|
||||||
|
path = Path(args.file).expanduser()
|
||||||
|
try:
|
||||||
|
resolved = path.resolve(strict=True)
|
||||||
|
except FileNotFoundError as exc:
|
||||||
|
raise ValueError(f"source file does not exist: {path}") from exc
|
||||||
|
|
||||||
|
if not resolved.is_file():
|
||||||
|
raise ValueError(f"source path is not a regular file: {resolved}")
|
||||||
|
|
||||||
|
size = resolved.stat().st_size
|
||||||
|
if size > args.max_bytes:
|
||||||
|
raise ValueError(
|
||||||
|
f"source file is {size} bytes, above --max-bytes {args.max_bytes}"
|
||||||
|
)
|
||||||
|
|
||||||
|
source = resolved.read_bytes()
|
||||||
|
return source, {
|
||||||
|
"kind": "file",
|
||||||
|
"path": str(resolved),
|
||||||
|
"bytes": len(source),
|
||||||
|
"sha256": hashlib.sha256(source).hexdigest(),
|
||||||
|
}
|
||||||
|
|
||||||
|
|
||||||
|
def _span_payload(span: SourceSpan) -> dict[str, Any]:
|
||||||
|
return {
|
||||||
|
"byte_start": span.byte_start,
|
||||||
|
"byte_end": span.byte_end,
|
||||||
|
"source_sha256": span.source_sha256,
|
||||||
|
"page": span.page,
|
||||||
|
"region": span.region,
|
||||||
|
}
|
||||||
|
|
||||||
|
|
||||||
|
def _report_payload(
|
||||||
|
*,
|
||||||
|
source_info: dict[str, Any],
|
||||||
|
modality_hint: str,
|
||||||
|
report: ValidationReport,
|
||||||
|
artifacts: list[LearningArtifact],
|
||||||
|
manifold: SegmentManifold,
|
||||||
|
register_all: bool,
|
||||||
|
) -> dict[str, Any]:
|
||||||
|
return {
|
||||||
|
"command": "ingest compile",
|
||||||
|
"path": "durable",
|
||||||
|
"boundary_owner": "core_ingest",
|
||||||
|
"runtime_gate": "ingest/gate.py is not imported or called",
|
||||||
|
"trust_boundary": _TRUST_BOUNDARY,
|
||||||
|
"mutates": False,
|
||||||
|
"modality_hint": modality_hint,
|
||||||
|
"source": source_info,
|
||||||
|
"summary": {
|
||||||
|
"results": len(report.results),
|
||||||
|
"accepted": len(report.accepted_ids),
|
||||||
|
"rejected": len(report.rejected_ids),
|
||||||
|
"review_required": len(report.review_ids),
|
||||||
|
"acceptance_rate": report.acceptance_rate,
|
||||||
|
"manifold_keys": len(manifold),
|
||||||
|
"register_all": register_all,
|
||||||
|
},
|
||||||
|
"results": [
|
||||||
|
{
|
||||||
|
"pressure_id": result.pressure_id,
|
||||||
|
"semantic_key": result.semantic_key,
|
||||||
|
"disposition": result.disposition.value,
|
||||||
|
"gate_failed": result.gate_failed,
|
||||||
|
"failure_reason": result.failure_reason,
|
||||||
|
"warnings": list(result.warnings),
|
||||||
|
}
|
||||||
|
for result in report.results
|
||||||
|
],
|
||||||
|
"artifacts": [
|
||||||
|
{
|
||||||
|
"pressure_id": artifact.packet.pressure_id,
|
||||||
|
"semantic_key": artifact.packet.semantic_key,
|
||||||
|
"kind": artifact.packet.kind,
|
||||||
|
"modality": artifact.packet.modality.value,
|
||||||
|
"review_level": artifact.packet.review_level.value,
|
||||||
|
"instrument_id": artifact.packet.frontend.instrument_id,
|
||||||
|
"lemma": artifact.packet.lemma,
|
||||||
|
"spans": [_span_payload(span) for span in artifact.packet.provenance],
|
||||||
|
}
|
||||||
|
for artifact in artifacts
|
||||||
|
],
|
||||||
|
}
|
||||||
|
|
||||||
|
|
||||||
|
def _print_text(payload: dict[str, Any]) -> None:
|
||||||
|
summary = payload["summary"]
|
||||||
|
source = payload["source"]
|
||||||
|
source_label = (
|
||||||
|
source["path"] if source["kind"] == "file" else f"inline:{source['sha256'][:12]}"
|
||||||
|
)
|
||||||
|
print("core_ingest durable compile")
|
||||||
|
print(f"source : {source_label}")
|
||||||
|
print(f"source_bytes : {source['bytes']}")
|
||||||
|
print(f"modality_hint : {payload['modality_hint']}")
|
||||||
|
print(f"trust_boundary : {payload['trust_boundary']}")
|
||||||
|
print(f"runtime_gate : {payload['runtime_gate']}")
|
||||||
|
print(f"mutates : {payload['mutates']}")
|
||||||
|
print(f"results : {summary['results']}")
|
||||||
|
print(f"accepted : {summary['accepted']}")
|
||||||
|
print(f"rejected : {summary['rejected']}")
|
||||||
|
print(f"review_required: {summary['review_required']}")
|
||||||
|
print(f"acceptance_rate: {summary['acceptance_rate']:.3f}")
|
||||||
|
for result in payload["results"][:10]:
|
||||||
|
reason = f" {result['failure_reason']}" if result["failure_reason"] else ""
|
||||||
|
print(
|
||||||
|
f" {result['disposition']:<20} "
|
||||||
|
f"{result['pressure_id'][:12]} semantic={result['semantic_key'][:12]}"
|
||||||
|
f"{reason}"
|
||||||
|
)
|
||||||
|
if len(payload["results"]) > 10:
|
||||||
|
print(f" ... {len(payload['results']) - 10} more result(s)")
|
||||||
|
|
||||||
|
|
||||||
|
def cmd_ingest_compile(args: argparse.Namespace) -> int:
|
||||||
|
"""Run the durable core_ingest pipeline and print a validation report."""
|
||||||
|
try:
|
||||||
|
source, source_info = _source_from_args(args)
|
||||||
|
if not source:
|
||||||
|
raise ValueError("ingest source is empty")
|
||||||
|
manifold = SegmentManifold()
|
||||||
|
pipeline = IngestPipeline(
|
||||||
|
manifold=manifold,
|
||||||
|
config=IngestPipelineConfig(register_all=args.register_all),
|
||||||
|
)
|
||||||
|
report, artifacts = pipeline.run(source, modality_hint=args.modality)
|
||||||
|
except ValueError as exc:
|
||||||
|
print(f"error: {exc}", file=sys.stderr)
|
||||||
|
return 2
|
||||||
|
|
||||||
|
payload = _report_payload(
|
||||||
|
source_info=source_info,
|
||||||
|
modality_hint=args.modality,
|
||||||
|
report=report,
|
||||||
|
artifacts=artifacts,
|
||||||
|
manifold=manifold,
|
||||||
|
register_all=args.register_all,
|
||||||
|
)
|
||||||
|
if args.json:
|
||||||
|
print(json.dumps(payload, ensure_ascii=False, indent=2, sort_keys=True))
|
||||||
|
else:
|
||||||
|
_print_text(payload)
|
||||||
|
return 0
|
||||||
|
|
||||||
|
|
||||||
|
def register(subparsers: argparse._SubParsersAction) -> None:
|
||||||
|
"""Attach the ``core ingest`` subcommand tree to a top-level parser."""
|
||||||
|
ingest = subparsers.add_parser(
|
||||||
|
"ingest",
|
||||||
|
help="inspect durable input-to-pressure compilation",
|
||||||
|
description=(
|
||||||
|
"Run the durable core_ingest compiler. This is read-only: it does "
|
||||||
|
"not import ingest/gate.py, write vault memory, mutate packs, or "
|
||||||
|
"ratify learning."
|
||||||
|
),
|
||||||
|
)
|
||||||
|
sub = ingest.add_subparsers(
|
||||||
|
dest="ingest_command", metavar="ingest-command", required=True,
|
||||||
|
)
|
||||||
|
|
||||||
|
compile_cmd = sub.add_parser(
|
||||||
|
"compile",
|
||||||
|
help="compile source bytes into validated candidate pressure",
|
||||||
|
description=(
|
||||||
|
"Compile source bytes through StructuralSegmenter -> "
|
||||||
|
"IngestCompiler -> SegmentManifold and emit a validation report."
|
||||||
|
),
|
||||||
|
)
|
||||||
|
source = compile_cmd.add_mutually_exclusive_group(required=True)
|
||||||
|
source.add_argument("--text", help="inline UTF-8 source text to compile")
|
||||||
|
source.add_argument(
|
||||||
|
"--file",
|
||||||
|
type=Path,
|
||||||
|
help="regular local file to read as source bytes",
|
||||||
|
)
|
||||||
|
compile_cmd.add_argument(
|
||||||
|
"--modality",
|
||||||
|
choices=_MODALITY_HINTS,
|
||||||
|
default="prose",
|
||||||
|
help="structural modality hint (default: prose)",
|
||||||
|
)
|
||||||
|
compile_cmd.add_argument(
|
||||||
|
"--max-bytes",
|
||||||
|
type=int,
|
||||||
|
default=_DEFAULT_MAX_BYTES,
|
||||||
|
help=f"maximum file size accepted by --file (default: {_DEFAULT_MAX_BYTES})",
|
||||||
|
)
|
||||||
|
compile_cmd.add_argument(
|
||||||
|
"--register-all",
|
||||||
|
action="store_true",
|
||||||
|
help="index rejected packets in the reconstruction manifold report",
|
||||||
|
)
|
||||||
|
compile_cmd.add_argument("--json", action="store_true", help="emit JSON")
|
||||||
|
compile_cmd.set_defaults(func=cmd_ingest_compile)
|
||||||
75
core/cli_pack.py
Normal file
75
core/cli_pack.py
Normal file
|
|
@ -0,0 +1,75 @@
|
||||||
|
"""Extracted commands."""
|
||||||
|
from __future__ import annotations
|
||||||
|
import argparse
|
||||||
|
import json
|
||||||
|
import sys
|
||||||
|
|
||||||
|
from core.cli_teaching import _safe_pack_id
|
||||||
|
from core.cli import _die, _REPO_ROOT, _run
|
||||||
|
|
||||||
|
def cmd_pack_list(args: argparse.Namespace) -> int:
|
||||||
|
"""List compiled language packs."""
|
||||||
|
from language_packs import list_packs
|
||||||
|
|
||||||
|
packs = list_packs()
|
||||||
|
if not packs:
|
||||||
|
print("no compiled packs found")
|
||||||
|
return 0
|
||||||
|
for pack_id in packs:
|
||||||
|
print(pack_id)
|
||||||
|
return 0
|
||||||
|
|
||||||
|
|
||||||
|
def cmd_pack_verify(args: argparse.Namespace) -> int:
|
||||||
|
"""Verify one language pack checksum."""
|
||||||
|
return _run(sys.executable, "-m", "language_packs", "verify", args.pack_id)
|
||||||
|
|
||||||
|
|
||||||
|
def cmd_pack_validate(args: argparse.Namespace) -> int:
|
||||||
|
"""Run executable source-pack validation gates."""
|
||||||
|
pack_id = _safe_pack_id(args.pack_id)
|
||||||
|
pack_dir = _REPO_ROOT / "packs" / pack_id
|
||||||
|
validator_path = pack_dir / "validators.py"
|
||||||
|
|
||||||
|
if not validator_path.exists():
|
||||||
|
_die(f"source-pack validator not found: {validator_path}", code=1)
|
||||||
|
|
||||||
|
if getattr(args, "dry_run", False):
|
||||||
|
if args.json:
|
||||||
|
print(json.dumps({
|
||||||
|
"pack_id": pack_id,
|
||||||
|
"validator_path": str(validator_path),
|
||||||
|
"would_execute": False,
|
||||||
|
"exists": True,
|
||||||
|
}, ensure_ascii=False, indent=2, sort_keys=True))
|
||||||
|
else:
|
||||||
|
print(f"dry-run: pack_id={pack_id}")
|
||||||
|
print(f"validator: {validator_path}")
|
||||||
|
print("status: validator exists, would not execute")
|
||||||
|
return 0
|
||||||
|
|
||||||
|
if not getattr(args, "allow_arbitrary_code", False):
|
||||||
|
_die(
|
||||||
|
"dynamic validator execution requires --allow-arbitrary-code",
|
||||||
|
code=2,
|
||||||
|
)
|
||||||
|
|
||||||
|
import importlib.util
|
||||||
|
|
||||||
|
spec = importlib.util.spec_from_file_location(f"{pack_id}_validators", validator_path)
|
||||||
|
if spec is None or spec.loader is None:
|
||||||
|
_die(f"cannot load source-pack validator: {validator_path}", code=1)
|
||||||
|
module = importlib.util.module_from_spec(spec)
|
||||||
|
spec.loader.exec_module(module)
|
||||||
|
report = module.validate_pack()
|
||||||
|
if args.json:
|
||||||
|
print(json.dumps(report, ensure_ascii=False, indent=2, sort_keys=True))
|
||||||
|
else:
|
||||||
|
print(f"pack_id: {report['pack_id']}")
|
||||||
|
print(f"active : {report['active']}")
|
||||||
|
for name, result in report["gates"].items():
|
||||||
|
status = "PASS" if result["passed"] else "FAIL"
|
||||||
|
print(f"{status} {name:<12} {result['reason']}")
|
||||||
|
return 0 if report["active"] else 1
|
||||||
|
|
||||||
|
|
||||||
144
core/cli_rust.py
Normal file
144
core/cli_rust.py
Normal file
|
|
@ -0,0 +1,144 @@
|
||||||
|
"""Rust backend CLI command handlers.
|
||||||
|
|
||||||
|
The top-level CLI owns argparse construction and subprocess policy. This module
|
||||||
|
owns the Rust/native-substrate command behavior so ``core/cli.py`` does not keep
|
||||||
|
absorbing every command family.
|
||||||
|
"""
|
||||||
|
|
||||||
|
from __future__ import annotations
|
||||||
|
|
||||||
|
import argparse
|
||||||
|
import os
|
||||||
|
import shutil
|
||||||
|
import subprocess
|
||||||
|
import sys
|
||||||
|
from pathlib import Path
|
||||||
|
from typing import NoReturn, Protocol
|
||||||
|
|
||||||
|
|
||||||
|
DEFAULT_REPO_ROOT = Path(__file__).resolve().parent.parent
|
||||||
|
CORE_RS_DIR = DEFAULT_REPO_ROOT / "core-rs"
|
||||||
|
CORE_RS_MANIFEST = CORE_RS_DIR / "Cargo.toml"
|
||||||
|
|
||||||
|
|
||||||
|
class CommandRunner(Protocol):
|
||||||
|
def __call__(
|
||||||
|
self,
|
||||||
|
*args: str,
|
||||||
|
check: bool = False,
|
||||||
|
cwd: Path | None = None,
|
||||||
|
env: dict[str, str] | None = None,
|
||||||
|
) -> int: ...
|
||||||
|
|
||||||
|
|
||||||
|
class DieHandler(Protocol):
|
||||||
|
def __call__(self, message: str, *, code: int = 2) -> NoReturn: ...
|
||||||
|
|
||||||
|
|
||||||
|
def rust_paths(repo_root: Path = DEFAULT_REPO_ROOT) -> tuple[Path, Path]:
|
||||||
|
core_rs_dir = repo_root / "core-rs"
|
||||||
|
return core_rs_dir, core_rs_dir / "Cargo.toml"
|
||||||
|
|
||||||
|
|
||||||
|
def run_command(
|
||||||
|
*args: str,
|
||||||
|
check: bool = False,
|
||||||
|
cwd: Path | None = None,
|
||||||
|
env: dict[str, str] | None = None,
|
||||||
|
) -> int:
|
||||||
|
completed = subprocess.run(args, check=check, text=True, cwd=cwd, env=env)
|
||||||
|
return int(completed.returncode)
|
||||||
|
|
||||||
|
|
||||||
|
def die(message: str, *, code: int = 2) -> NoReturn:
|
||||||
|
print(f"error: {message}", file=sys.stderr)
|
||||||
|
raise SystemExit(code)
|
||||||
|
|
||||||
|
|
||||||
|
def rust_build_env() -> dict[str, str]:
|
||||||
|
"""Return the environment used for PyO3-backed Rust build/test commands."""
|
||||||
|
env = os.environ.copy()
|
||||||
|
# PyO3 0.21 supports Python through 3.12. Fresh uv environments may be
|
||||||
|
# 3.13+, so use PyO3's documented forward-compatibility escape hatch unless
|
||||||
|
# the operator has provided a more specific PYO3_* policy.
|
||||||
|
env.setdefault("PYO3_USE_ABI3_FORWARD_COMPATIBILITY", "1")
|
||||||
|
return env
|
||||||
|
|
||||||
|
|
||||||
|
def probe_core_rs() -> tuple[bool, str]:
|
||||||
|
try:
|
||||||
|
import core_rs
|
||||||
|
except Exception as exc:
|
||||||
|
return False, f"{exc.__class__.__name__}: {exc}"
|
||||||
|
return True, str(getattr(core_rs, "__file__", "<built-in>"))
|
||||||
|
|
||||||
|
|
||||||
|
def print_rust_status(*, repo_root: Path = DEFAULT_REPO_ROOT) -> bool:
|
||||||
|
from algebra.backend import using_rust
|
||||||
|
|
||||||
|
core_rs_dir, core_rs_manifest = rust_paths(repo_root)
|
||||||
|
active = using_rust()
|
||||||
|
importable, import_detail = probe_core_rs()
|
||||||
|
print(f"core_rs crate : {core_rs_dir}")
|
||||||
|
print(f"cargo manifest: {core_rs_manifest}")
|
||||||
|
print(f"CORE_BACKEND : {os.environ.get('CORE_BACKEND', '') or '(default python)'}")
|
||||||
|
print(f"core_rs import: {'ok' if importable else 'missing'}")
|
||||||
|
print(f"core_rs detail: {import_detail}")
|
||||||
|
print(f"rust backend : {'active' if active else 'inactive'}")
|
||||||
|
if not active:
|
||||||
|
print("activation : run `core rust build`")
|
||||||
|
return active
|
||||||
|
|
||||||
|
|
||||||
|
def cmd_rust_status(
|
||||||
|
args: argparse.Namespace,
|
||||||
|
*,
|
||||||
|
repo_root: Path = DEFAULT_REPO_ROOT,
|
||||||
|
) -> int:
|
||||||
|
"""Print Rust backend activation status."""
|
||||||
|
return 0 if print_rust_status(repo_root=repo_root) or not args.require_active else 1
|
||||||
|
|
||||||
|
|
||||||
|
def cmd_rust_build(
|
||||||
|
args: argparse.Namespace,
|
||||||
|
*,
|
||||||
|
repo_root: Path = DEFAULT_REPO_ROOT,
|
||||||
|
run: CommandRunner = run_command,
|
||||||
|
fail: DieHandler = die,
|
||||||
|
python_executable: str = sys.executable,
|
||||||
|
) -> int:
|
||||||
|
"""Build/install core_rs into the active Python environment."""
|
||||||
|
_, core_rs_manifest = rust_paths(repo_root)
|
||||||
|
if not core_rs_manifest.exists():
|
||||||
|
fail(f"core-rs manifest not found: {core_rs_manifest}", code=1)
|
||||||
|
if shutil.which("uv") is not None:
|
||||||
|
rc = run("uv", "pip", "install", "maturin")
|
||||||
|
if rc != 0:
|
||||||
|
return rc
|
||||||
|
cmd = [
|
||||||
|
python_executable,
|
||||||
|
"-m",
|
||||||
|
"maturin",
|
||||||
|
"develop",
|
||||||
|
"--release",
|
||||||
|
"--manifest-path",
|
||||||
|
str(core_rs_manifest),
|
||||||
|
]
|
||||||
|
if args.skip_auditwheel:
|
||||||
|
cmd.append("--skip-auditwheel")
|
||||||
|
return run(*cmd, env=rust_build_env())
|
||||||
|
|
||||||
|
|
||||||
|
def cmd_rust_test(
|
||||||
|
args: argparse.Namespace,
|
||||||
|
*,
|
||||||
|
repo_root: Path = DEFAULT_REPO_ROOT,
|
||||||
|
run: CommandRunner = run_command,
|
||||||
|
fail: DieHandler = die,
|
||||||
|
) -> int:
|
||||||
|
"""Run Rust crate tests."""
|
||||||
|
del args
|
||||||
|
core_rs_dir, _ = rust_paths(repo_root)
|
||||||
|
if shutil.which("cargo") is None:
|
||||||
|
fail("cargo not found. Install a Rust toolchain first.", code=1)
|
||||||
|
return run("cargo", "test", "--release", cwd=core_rs_dir, env=rust_build_env())
|
||||||
1283
core/cli_teaching.py
Normal file
1283
core/cli_teaching.py
Normal file
File diff suppressed because it is too large
Load diff
278
core/cli_test.py
Normal file
278
core/cli_test.py
Normal file
|
|
@ -0,0 +1,278 @@
|
||||||
|
"""Curated pytest and ruff CLI command handlers."""
|
||||||
|
|
||||||
|
from __future__ import annotations
|
||||||
|
|
||||||
|
import argparse
|
||||||
|
import subprocess
|
||||||
|
import sys
|
||||||
|
from collections.abc import Sequence
|
||||||
|
from pathlib import Path
|
||||||
|
from typing import Protocol
|
||||||
|
|
||||||
|
|
||||||
|
TEST_SUITES: dict[str, tuple[str, ...]] = {
|
||||||
|
"fast": (
|
||||||
|
"tests/test_cli_test_suites.py",
|
||||||
|
"tests/test_runtime_config.py",
|
||||||
|
"tests/test_core_semantic_seed_pack.py",
|
||||||
|
"tests/test_intent_proposition_graph.py",
|
||||||
|
"tests/test_articulation_realizer_v2.py",
|
||||||
|
"tests/test_reviewed_teaching_loop.py",
|
||||||
|
"tests/test_cognitive_eval_harness.py",
|
||||||
|
),
|
||||||
|
"smoke": (
|
||||||
|
"tests/test_chat_runtime.py",
|
||||||
|
"tests/test_achat.py",
|
||||||
|
"tests/test_runtime_config.py",
|
||||||
|
"tests/test_cognitive_turn_pipeline.py",
|
||||||
|
"tests/test_architectural_invariants.py",
|
||||||
|
# ADR-0043 — identity falsifiability: ratified identity packs must
|
||||||
|
# produce distinct, directionally-correct articulations, with a
|
||||||
|
# pack-invariant grounding/refusal floor and zero fabrication. Lives
|
||||||
|
# only under ``full`` historically, so a divergence regression cleared
|
||||||
|
# the PR gate and surfaced only post-merge. Promoted into smoke so
|
||||||
|
# the falsifiability claim blocks-on-regression rather than
|
||||||
|
# detect-after-merge.
|
||||||
|
"tests/test_pack_measurements_phase2.py",
|
||||||
|
),
|
||||||
|
"runtime": (
|
||||||
|
"tests/test_chat_runtime.py",
|
||||||
|
"tests/test_achat.py",
|
||||||
|
"tests/test_runtime_config.py",
|
||||||
|
"tests/test_session_coherence.py",
|
||||||
|
),
|
||||||
|
"cognition": (
|
||||||
|
"tests/test_intent_proposition_graph.py",
|
||||||
|
"tests/test_cognitive_turn_pipeline.py",
|
||||||
|
"tests/test_articulation_realizer_v2.py",
|
||||||
|
"tests/test_semantic_realizer_integration.py",
|
||||||
|
"tests/test_cognitive_eval_harness.py",
|
||||||
|
"tests/test_deterministic_hash.py",
|
||||||
|
"tests/test_morphology_irregular.py",
|
||||||
|
"tests/test_realizer_quantifier_agreement.py",
|
||||||
|
"tests/test_benchmarks_profiler.py",
|
||||||
|
"tests/test_compose_relations.py",
|
||||||
|
"tests/test_replay_vs_llm_benchmark.py",
|
||||||
|
),
|
||||||
|
"teaching": (
|
||||||
|
"tests/test_reviewed_teaching_loop.py",
|
||||||
|
"tests/test_pipeline_teaching_integration.py",
|
||||||
|
"tests/test_epistemic_invariants.py",
|
||||||
|
"tests/test_adr_0172_w2_decomposer.py",
|
||||||
|
"tests/test_adr_0172_w5_inference_proposal.py",
|
||||||
|
"tests/test_math_frame_ratification.py",
|
||||||
|
"tests/test_math_composition_ratification.py",
|
||||||
|
"tests/test_teaching_coverage_cli.py",
|
||||||
|
),
|
||||||
|
"packs": (
|
||||||
|
"tests/test_core_semantic_seed_pack.py",
|
||||||
|
"tests/test_adr_0127_pack_ratification.py",
|
||||||
|
"tests/test_frame_registry_load.py",
|
||||||
|
"tests/test_composition_registry_load.py",
|
||||||
|
"tests/test_composition_consult_in_injector.py",
|
||||||
|
"tests/test_consumption_case_0050_hazard_pin.py",
|
||||||
|
"tests/test_consumption_empty_registry_no_op.py",
|
||||||
|
"tests/test_consumption_partition.py",
|
||||||
|
"tests/test_matcher_extension_currency_per_unit.py",
|
||||||
|
"tests/test_matcher_extension_case_0050_hazard_pin.py",
|
||||||
|
"tests/test_matcher_extension_end_to_end_admission.py",
|
||||||
|
"tests/test_me2_cross_sentence_subject.py",
|
||||||
|
"tests/test_me2_case_0019_admits.py",
|
||||||
|
"tests/test_me3_additive_composition.py",
|
||||||
|
"tests/test_me4_subtractive_composition.py",
|
||||||
|
"tests/test_me5_all_categories_integration.py",
|
||||||
|
"tests/test_rat1_end_to_end_admission.py",
|
||||||
|
"tests/test_wave_a_multiplicative_aggregation_injector.py",
|
||||||
|
),
|
||||||
|
"algebra": (
|
||||||
|
"tests/test_versor_closure.py",
|
||||||
|
"tests/test_holonomy.py",
|
||||||
|
"tests/test_holonomy_resonance.py",
|
||||||
|
"tests/test_energy.py",
|
||||||
|
"tests/test_motor.py",
|
||||||
|
"tests/test_null_cone.py",
|
||||||
|
"tests/test_vault_recall.py",
|
||||||
|
"tests/test_vault_recall_vectorised.py",
|
||||||
|
"tests/test_vault_recall_rust_parity.py",
|
||||||
|
"tests/test_cga_inner_rust_parity.py",
|
||||||
|
"tests/test_geometric_product_rust_parity.py",
|
||||||
|
"tests/test_versor_condition_rust_parity.py",
|
||||||
|
"tests/test_versor_apply_rust_parity.py",
|
||||||
|
),
|
||||||
|
"sensorium": (
|
||||||
|
"tests/test_sensorium_compiler_delta.py",
|
||||||
|
"tests/test_audio_compiler.py",
|
||||||
|
"tests/test_audio_crdt_merge.py",
|
||||||
|
"tests/test_audio_eval_gates.py",
|
||||||
|
"tests/test_audio_pack_manifest.py",
|
||||||
|
"tests/test_audio_sensorium_mount.py",
|
||||||
|
"tests/test_vision_compiler.py",
|
||||||
|
"tests/test_event_vision_compiler.py",
|
||||||
|
"tests/test_vision_crdt_merge.py",
|
||||||
|
"tests/test_vision_eval_gates.py",
|
||||||
|
"tests/test_vision_sensorium_mount.py",
|
||||||
|
"tests/test_sensorimotor_contract.py",
|
||||||
|
"tests/test_sensorimotor_pack_manifest.py",
|
||||||
|
"tests/test_observation_frame_contract.py",
|
||||||
|
"tests/test_observation_frame_harness.py",
|
||||||
|
"tests/test_environment_falsification.py",
|
||||||
|
"tests/test_environment_falsification_eval_cli.py",
|
||||||
|
"tests/test_witness_log_importer.py",
|
||||||
|
"tests/test_tabletop_lab_protocol.py",
|
||||||
|
"tests/test_sensorium_eval_cli.py",
|
||||||
|
"tests/test_efferent_gate.py",
|
||||||
|
),
|
||||||
|
"pulse": (
|
||||||
|
"tests/test_pulse_integration.py",
|
||||||
|
"tests/test_graph_diffusion.py",
|
||||||
|
),
|
||||||
|
"formation": (
|
||||||
|
"tests/formation",
|
||||||
|
),
|
||||||
|
"proof": (
|
||||||
|
"tests/test_proof_properties.py",
|
||||||
|
),
|
||||||
|
# ADR-0024 chain suites (Phases 2-6). Each phase has its own contract
|
||||||
|
# tests so reviewers can run them independently; ``adr-0024`` runs the full
|
||||||
|
# chain end-to-end.
|
||||||
|
"refusal": (
|
||||||
|
"tests/test_refusal_contract.py",
|
||||||
|
),
|
||||||
|
"margin": (
|
||||||
|
"tests/test_margin_admissibility.py",
|
||||||
|
),
|
||||||
|
"rotor": (
|
||||||
|
"tests/test_rotor_admissibility.py",
|
||||||
|
),
|
||||||
|
"inner-loop": (
|
||||||
|
"tests/test_inner_loop_admissibility.py",
|
||||||
|
"tests/test_inner_loop_phase2.py",
|
||||||
|
"tests/test_inner_loop_phase3.py",
|
||||||
|
"tests/test_inner_loop_phase4.py",
|
||||||
|
),
|
||||||
|
"phase5": (
|
||||||
|
"tests/test_phase5_corpus.py",
|
||||||
|
),
|
||||||
|
"phase6": (
|
||||||
|
"tests/test_phase6_demo.py",
|
||||||
|
),
|
||||||
|
"adr-0024": (
|
||||||
|
"tests/test_refusal_contract.py",
|
||||||
|
"tests/test_margin_admissibility.py",
|
||||||
|
"tests/test_rotor_admissibility.py",
|
||||||
|
"tests/test_inner_loop_admissibility.py",
|
||||||
|
"tests/test_inner_loop_phase2.py",
|
||||||
|
"tests/test_inner_loop_phase3.py",
|
||||||
|
"tests/test_inner_loop_phase4.py",
|
||||||
|
"tests/test_phase5_corpus.py",
|
||||||
|
"tests/test_phase6_demo.py",
|
||||||
|
),
|
||||||
|
# ADR-0126 P6 — measurement harness for the GSM8K candidate-graph parser
|
||||||
|
# exit criterion. ``wrong == 0`` is a hard gate (Obligation #4: refuse
|
||||||
|
# rather than confabulate).
|
||||||
|
"math": (
|
||||||
|
"tests/test_adr_0126_train_sample_runner.py",
|
||||||
|
),
|
||||||
|
"deductive": (
|
||||||
|
"tests/test_deductive_logic_entail.py",
|
||||||
|
),
|
||||||
|
"full": ("tests/",),
|
||||||
|
}
|
||||||
|
|
||||||
|
|
||||||
|
class CommandRunner(Protocol):
|
||||||
|
def __call__(
|
||||||
|
self,
|
||||||
|
*args: str,
|
||||||
|
check: bool = False,
|
||||||
|
cwd: Path | None = None,
|
||||||
|
env: dict[str, str] | None = None,
|
||||||
|
) -> int: ...
|
||||||
|
|
||||||
|
|
||||||
|
def run_command(
|
||||||
|
*args: str,
|
||||||
|
check: bool = False,
|
||||||
|
cwd: Path | None = None,
|
||||||
|
env: dict[str, str] | None = None,
|
||||||
|
) -> int:
|
||||||
|
completed = subprocess.run(args, check=check, text=True, cwd=cwd, env=env)
|
||||||
|
return int(completed.returncode)
|
||||||
|
|
||||||
|
|
||||||
|
def pytest_args_for_suite(suite: str, extra_args: Sequence[str]) -> list[str]:
|
||||||
|
paths = TEST_SUITES[suite]
|
||||||
|
forwarded = list(extra_args)
|
||||||
|
if forwarded and forwarded[0] == "--":
|
||||||
|
forwarded = forwarded[1:]
|
||||||
|
return [*paths, *forwarded]
|
||||||
|
|
||||||
|
|
||||||
|
def xdist_available() -> bool:
|
||||||
|
"""Return True iff ``pytest-xdist`` is importable."""
|
||||||
|
try:
|
||||||
|
import xdist # noqa: F401
|
||||||
|
except ImportError:
|
||||||
|
return False
|
||||||
|
return True
|
||||||
|
|
||||||
|
|
||||||
|
def maybe_inject_xdist(forwarded: list[str], suite: str | None) -> list[str]:
|
||||||
|
"""Inject ``-n auto`` for suites large enough to benefit from parallelism."""
|
||||||
|
if not xdist_available():
|
||||||
|
return forwarded
|
||||||
|
# Honour explicit operator override.
|
||||||
|
if any(a.startswith("-n") or a == "--dist" for a in forwarded):
|
||||||
|
return forwarded
|
||||||
|
if suite == "full":
|
||||||
|
return ["-n", "auto", *forwarded]
|
||||||
|
return forwarded
|
||||||
|
|
||||||
|
|
||||||
|
def cmd_test(
|
||||||
|
args: argparse.Namespace,
|
||||||
|
*,
|
||||||
|
run: CommandRunner = run_command,
|
||||||
|
python_executable: str = sys.executable,
|
||||||
|
) -> int:
|
||||||
|
"""Run pytest through curated suite aliases or direct passthrough args."""
|
||||||
|
default_args = ["-q", "--tb=short"]
|
||||||
|
if args.list_suites:
|
||||||
|
for name in sorted(TEST_SUITES):
|
||||||
|
print(name)
|
||||||
|
return 0
|
||||||
|
if args.suite:
|
||||||
|
forwarded = pytest_args_for_suite(args.suite, args.args or default_args)
|
||||||
|
else:
|
||||||
|
forwarded = list(args.args or default_args)
|
||||||
|
if forwarded and forwarded[0] == "--":
|
||||||
|
forwarded = forwarded[1:]
|
||||||
|
forwarded = maybe_inject_xdist(forwarded, args.suite)
|
||||||
|
return run(python_executable, "-m", "pytest", *forwarded)
|
||||||
|
|
||||||
|
|
||||||
|
def cmd_check(
|
||||||
|
args: argparse.Namespace,
|
||||||
|
*,
|
||||||
|
run: CommandRunner = run_command,
|
||||||
|
python_executable: str = sys.executable,
|
||||||
|
) -> int:
|
||||||
|
"""Run ruff over selected project paths."""
|
||||||
|
targets = args.paths or [
|
||||||
|
"algebra",
|
||||||
|
"alignment",
|
||||||
|
"chat",
|
||||||
|
"core",
|
||||||
|
"field",
|
||||||
|
"generate",
|
||||||
|
"ingest",
|
||||||
|
"language_packs",
|
||||||
|
"morphology",
|
||||||
|
"persona",
|
||||||
|
"sensorium",
|
||||||
|
"session",
|
||||||
|
"vault",
|
||||||
|
"vocab",
|
||||||
|
"tests",
|
||||||
|
]
|
||||||
|
return run(python_executable, "-m", "ruff", "check", *targets)
|
||||||
|
|
@ -45,6 +45,8 @@ def test_rust_status_reports_backend_state(capsys: pytest.CaptureFixture[str]) -
|
||||||
out = capsys.readouterr().out
|
out = capsys.readouterr().out
|
||||||
assert "core_rs crate" in out
|
assert "core_rs crate" in out
|
||||||
assert "cargo manifest" in out
|
assert "cargo manifest" in out
|
||||||
|
assert "core_rs import" in out
|
||||||
|
assert "CORE_BACKEND" in out
|
||||||
assert "rust backend" in out
|
assert "rust backend" in out
|
||||||
|
|
||||||
|
|
||||||
|
|
@ -67,13 +69,20 @@ def test_doctor_imports_runtime_support_modules(capsys: pytest.CaptureFixture[st
|
||||||
assert main(["doctor"]) == 0
|
assert main(["doctor"]) == 0
|
||||||
out = capsys.readouterr().out
|
out = capsys.readouterr().out
|
||||||
assert "OK alignment" in out
|
assert "OK alignment" in out
|
||||||
|
assert "OK core_ingest" in out
|
||||||
|
assert "OK engine_state" in out
|
||||||
|
assert "OK packs" in out
|
||||||
|
assert "OK teaching" in out
|
||||||
assert "OK morphology" in out
|
assert "OK morphology" in out
|
||||||
assert "OK sensorium" in out
|
assert "OK sensorium" in out
|
||||||
|
assert "INFO native core_rs" in out
|
||||||
|
assert "INFO native policy" in out
|
||||||
|
|
||||||
|
|
||||||
def test_doctor_rust_reports_backend_state(capsys: pytest.CaptureFixture[str]) -> None:
|
def test_doctor_rust_reports_backend_state(capsys: pytest.CaptureFixture[str]) -> None:
|
||||||
assert main(["doctor", "--rust"]) == 0
|
assert main(["doctor", "--rust"]) == 0
|
||||||
out = capsys.readouterr().out
|
out = capsys.readouterr().out
|
||||||
|
assert "core_rs import" in out
|
||||||
assert "rust backend" in out
|
assert "rust backend" in out
|
||||||
|
|
||||||
|
|
||||||
|
|
|
||||||
104
tests/test_cli_ingest.py
Normal file
104
tests/test_cli_ingest.py
Normal file
|
|
@ -0,0 +1,104 @@
|
||||||
|
from __future__ import annotations
|
||||||
|
|
||||||
|
import builtins
|
||||||
|
import hashlib
|
||||||
|
import json
|
||||||
|
from pathlib import Path
|
||||||
|
|
||||||
|
import pytest
|
||||||
|
|
||||||
|
from core.cli import build_parser, main
|
||||||
|
|
||||||
|
|
||||||
|
def test_ingest_help_names_durable_read_only_boundary(
|
||||||
|
capsys: pytest.CaptureFixture[str],
|
||||||
|
) -> None:
|
||||||
|
with pytest.raises(SystemExit) as excinfo:
|
||||||
|
build_parser().parse_args(["ingest", "-h"])
|
||||||
|
|
||||||
|
assert excinfo.value.code == 0
|
||||||
|
out = capsys.readouterr().out
|
||||||
|
assert "durable core_ingest compiler" in out
|
||||||
|
assert "read-only" in out
|
||||||
|
assert "ingest/gate.py" in out
|
||||||
|
|
||||||
|
|
||||||
|
def test_ingest_compile_text_json_reports_durable_boundary(
|
||||||
|
capsys: pytest.CaptureFixture[str],
|
||||||
|
) -> None:
|
||||||
|
text = "The logos is the foundation.\n\nThe field remains coherent."
|
||||||
|
|
||||||
|
rc = main(["ingest", "compile", "--text", text, "--json"])
|
||||||
|
|
||||||
|
assert rc == 0
|
||||||
|
payload = json.loads(capsys.readouterr().out)
|
||||||
|
assert payload["command"] == "ingest compile"
|
||||||
|
assert payload["path"] == "durable"
|
||||||
|
assert payload["boundary_owner"] == "core_ingest"
|
||||||
|
assert payload["runtime_gate"] == "ingest/gate.py is not imported or called"
|
||||||
|
assert payload["mutates"] is False
|
||||||
|
assert payload["source"]["kind"] == "text"
|
||||||
|
assert payload["source"]["sha256"] == hashlib.sha256(text.encode()).hexdigest()
|
||||||
|
assert payload["summary"]["accepted"] == len(payload["artifacts"])
|
||||||
|
assert payload["summary"]["accepted"] >= 1
|
||||||
|
|
||||||
|
|
||||||
|
def test_ingest_compile_file_json_reports_regular_file(
|
||||||
|
tmp_path: Path,
|
||||||
|
capsys: pytest.CaptureFixture[str],
|
||||||
|
) -> None:
|
||||||
|
source = tmp_path / "source.md"
|
||||||
|
source.write_text("First paragraph.\n\nSecond paragraph.", encoding="utf-8")
|
||||||
|
|
||||||
|
rc = main(["ingest", "compile", "--file", str(source), "--json"])
|
||||||
|
|
||||||
|
assert rc == 0
|
||||||
|
payload = json.loads(capsys.readouterr().out)
|
||||||
|
assert payload["source"]["kind"] == "file"
|
||||||
|
assert payload["source"]["path"] == str(source.resolve())
|
||||||
|
assert payload["summary"]["results"] >= 1
|
||||||
|
|
||||||
|
|
||||||
|
def test_ingest_compile_file_rejects_directory(
|
||||||
|
tmp_path: Path,
|
||||||
|
capsys: pytest.CaptureFixture[str],
|
||||||
|
) -> None:
|
||||||
|
rc = main(["ingest", "compile", "--file", str(tmp_path)])
|
||||||
|
|
||||||
|
assert rc == 2
|
||||||
|
captured = capsys.readouterr()
|
||||||
|
assert "regular file" in captured.err
|
||||||
|
|
||||||
|
|
||||||
|
def test_ingest_compile_file_respects_size_limit(
|
||||||
|
tmp_path: Path,
|
||||||
|
capsys: pytest.CaptureFixture[str],
|
||||||
|
) -> None:
|
||||||
|
source = tmp_path / "source.md"
|
||||||
|
source.write_text("too large for this test", encoding="utf-8")
|
||||||
|
|
||||||
|
rc = main(["ingest", "compile", "--file", str(source), "--max-bytes", "4"])
|
||||||
|
|
||||||
|
assert rc == 2
|
||||||
|
captured = capsys.readouterr()
|
||||||
|
assert "above --max-bytes 4" in captured.err
|
||||||
|
|
||||||
|
|
||||||
|
def test_ingest_compile_does_not_import_runtime_gate(
|
||||||
|
monkeypatch: pytest.MonkeyPatch,
|
||||||
|
capsys: pytest.CaptureFixture[str],
|
||||||
|
) -> None:
|
||||||
|
real_import = builtins.__import__
|
||||||
|
|
||||||
|
def guarded_import(name, globals=None, locals=None, fromlist=(), level=0):
|
||||||
|
if name == "ingest.gate" or (name == "ingest" and "gate" in fromlist):
|
||||||
|
raise AssertionError("durable core_ingest CLI imported runtime gate")
|
||||||
|
return real_import(name, globals, locals, fromlist, level)
|
||||||
|
|
||||||
|
monkeypatch.setattr(builtins, "__import__", guarded_import)
|
||||||
|
|
||||||
|
rc = main(["ingest", "compile", "--text", "Boundary check.", "--json"])
|
||||||
|
|
||||||
|
assert rc == 0
|
||||||
|
payload = json.loads(capsys.readouterr().out)
|
||||||
|
assert payload["runtime_gate"] == "ingest/gate.py is not imported or called"
|
||||||
|
|
@ -2,11 +2,36 @@
|
||||||
|
|
||||||
from __future__ import annotations
|
from __future__ import annotations
|
||||||
|
|
||||||
|
import tomllib
|
||||||
|
from pathlib import Path
|
||||||
|
|
||||||
import pytest
|
import pytest
|
||||||
|
|
||||||
|
from core import cli_rust
|
||||||
from core import cli
|
from core import cli
|
||||||
|
|
||||||
|
|
||||||
|
def test_pyproject_installs_core_console_script_under_uv() -> None:
|
||||||
|
pyproject = Path(__file__).resolve().parents[1] / "pyproject.toml"
|
||||||
|
data = tomllib.loads(pyproject.read_text(encoding="utf-8"))
|
||||||
|
|
||||||
|
assert data["project"]["scripts"]["core"] == "core.cli:main"
|
||||||
|
assert data["tool"]["uv"]["package"] is True
|
||||||
|
package_includes = data["tool"]["setuptools"]["packages"]["find"]["include"]
|
||||||
|
expected_runtime_packages = {
|
||||||
|
"benchmarks*",
|
||||||
|
"calibration*",
|
||||||
|
"core_ingest*",
|
||||||
|
"demos*",
|
||||||
|
"engine_state*",
|
||||||
|
"evals*",
|
||||||
|
"packs*",
|
||||||
|
"scripts*",
|
||||||
|
"teaching*",
|
||||||
|
}
|
||||||
|
assert expected_runtime_packages.issubset(package_includes)
|
||||||
|
|
||||||
|
|
||||||
def test_core_test_lists_curated_suites(capsys) -> None:
|
def test_core_test_lists_curated_suites(capsys) -> None:
|
||||||
rc = cli.main(["test", "--list-suites"])
|
rc = cli.main(["test", "--list-suites"])
|
||||||
|
|
||||||
|
|
@ -129,6 +154,35 @@ def test_core_test_passthrough_still_accepts_arbitrary_pytest_args(monkeypatch)
|
||||||
)
|
)
|
||||||
|
|
||||||
|
|
||||||
|
def test_core_rust_test_sets_pyo3_forward_compat(monkeypatch) -> None:
|
||||||
|
calls: list[tuple[tuple[str, ...], object, dict[str, str] | None]] = []
|
||||||
|
|
||||||
|
def fake_which(name: str) -> str | None:
|
||||||
|
return "/usr/bin/cargo" if name == "cargo" else None
|
||||||
|
|
||||||
|
def fake_run(
|
||||||
|
*args: str,
|
||||||
|
check: bool = False,
|
||||||
|
cwd=None,
|
||||||
|
env: dict[str, str] | None = None,
|
||||||
|
) -> int:
|
||||||
|
calls.append((args, cwd, env))
|
||||||
|
return 0
|
||||||
|
|
||||||
|
monkeypatch.setattr(cli_rust.shutil, "which", fake_which)
|
||||||
|
monkeypatch.setattr(cli, "_run", fake_run)
|
||||||
|
|
||||||
|
rc = cli.main(["rust", "test"])
|
||||||
|
|
||||||
|
assert rc == 0
|
||||||
|
assert len(calls) == 1
|
||||||
|
args, cwd, env = calls[0]
|
||||||
|
assert args == ("cargo", "test", "--release")
|
||||||
|
assert cwd == cli_rust.CORE_RS_DIR
|
||||||
|
assert env is not None
|
||||||
|
assert env["PYO3_USE_ABI3_FORWARD_COMPATIBILITY"] == "1"
|
||||||
|
|
||||||
|
|
||||||
def test_non_test_commands_still_reject_unknown_args() -> None:
|
def test_non_test_commands_still_reject_unknown_args() -> None:
|
||||||
with pytest.raises(SystemExit):
|
with pytest.raises(SystemExit):
|
||||||
cli.main(["pack", "list", "-q"])
|
cli.main(["pack", "list", "-q"])
|
||||||
|
|
|
||||||
64
tests/test_repository_hygiene.py
Normal file
64
tests/test_repository_hygiene.py
Normal file
|
|
@ -0,0 +1,64 @@
|
||||||
|
from __future__ import annotations
|
||||||
|
|
||||||
|
import re
|
||||||
|
from pathlib import Path
|
||||||
|
|
||||||
|
import conftest
|
||||||
|
|
||||||
|
|
||||||
|
ROOT = Path(__file__).resolve().parents[1]
|
||||||
|
|
||||||
|
|
||||||
|
def test_top_level_contemplation_is_artifact_namespace_only() -> None:
|
||||||
|
artifact_root = ROOT / "contemplation"
|
||||||
|
code_root = ROOT / "core" / "contemplation"
|
||||||
|
|
||||||
|
assert (artifact_root / "README.md").is_file()
|
||||||
|
assert (artifact_root / "runs").is_dir()
|
||||||
|
assert not (artifact_root / "__init__.py").exists()
|
||||||
|
assert not list(artifact_root.rglob("*.py"))
|
||||||
|
assert (code_root / "__init__.py").is_file()
|
||||||
|
|
||||||
|
|
||||||
|
def test_quarantine_doc_matches_registry_count() -> None:
|
||||||
|
doc = (ROOT / "docs" / "test-debt-quarantine.md").read_text(encoding="utf-8")
|
||||||
|
match = re.search(r"^Current quarantined tests: (\d+)\.$", doc, re.MULTILINE)
|
||||||
|
|
||||||
|
assert match is not None
|
||||||
|
assert int(match.group(1)) == len(conftest.QUARANTINE)
|
||||||
|
|
||||||
|
|
||||||
|
def test_provider_files_delegate_to_agents() -> None:
|
||||||
|
for name in ("CLAUDE.md", "GEMINI.md"):
|
||||||
|
text = (ROOT / name).read_text(encoding="utf-8")
|
||||||
|
|
||||||
|
assert len(text.encode("utf-8")) <= 600
|
||||||
|
assert "`AGENTS.md` is the canonical governance file" in text
|
||||||
|
assert "Do not place architecture, invariants, memory rules" in text
|
||||||
|
|
||||||
|
|
||||||
|
def test_notes_are_non_executable_artifacts() -> None:
|
||||||
|
notes_root = ROOT / "notes"
|
||||||
|
|
||||||
|
assert (notes_root / "README.md").is_file()
|
||||||
|
assert not list(notes_root.rglob("*.py"))
|
||||||
|
|
||||||
|
|
||||||
|
def test_intentional_topology_splits_have_local_readmes() -> None:
|
||||||
|
required = (
|
||||||
|
"calibration",
|
||||||
|
"contemplation",
|
||||||
|
"core/demos",
|
||||||
|
"core_ingest",
|
||||||
|
"demos",
|
||||||
|
"ingest",
|
||||||
|
"language_packs",
|
||||||
|
"notes",
|
||||||
|
"packs",
|
||||||
|
"workbench",
|
||||||
|
"workbench-ui",
|
||||||
|
"workbench_data",
|
||||||
|
)
|
||||||
|
|
||||||
|
missing = [path for path in required if not (ROOT / path / "README.md").is_file()]
|
||||||
|
assert missing == []
|
||||||
Loading…
Reference in a new issue