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
|
||||
assert "core_rs crate" in out
|
||||
assert "cargo manifest" in out
|
||||
assert "core_rs import" in out
|
||||
assert "CORE_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
|
||||
out = capsys.readouterr().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 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:
|
||||
assert main(["doctor", "--rust"]) == 0
|
||||
out = capsys.readouterr().out
|
||||
assert "core_rs import" 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
|
||||
|
||||
import tomllib
|
||||
from pathlib import Path
|
||||
|
||||
import pytest
|
||||
|
||||
from core import cli_rust
|
||||
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:
|
||||
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:
|
||||
with pytest.raises(SystemExit):
|
||||
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