fix(cli, tests): wire core contemplation + restore INV-02 allowlist (#60)

Two follow-up fixes from end-of-session verification of recent merges:

1. core/cli.py — wire `core contemplation` subcommand
   PR #55 + #58 added the contemplation CLI at python -m core.contemplation
   but never registered it under the `core` umbrella command, so
   `core --help` didn't show it.  Adds a subparser mirroring the existing
   pattern (chat/test/check/.../doctor) that delegates to the existing
   core.contemplation.__main__:main() — no duplication of arg parsing.

   Surface preserved verbatim: reports (positional, 1+), --lane
   {frontier_compare, contradiction_detection}, --pack-id, --note,
   --report, --sink-root.

2. tests/test_architectural_invariants.py — restore INV-02 allowlist
   PR #57's evals/lab/phi_separation_probe.py imports normalize_to_versor
   for construction-time experimental rotor + embedding work, which
   triggered INV-02's AST-scan failure (the test enforces that
   normalize_to_versor is only called from a small allowed file set).

   evals/lab/ is research-only, never imported by runtime — adding the
   probe to allowed_files doesn't weaken the runtime invariant the
   test enforces.

Verification
------------
$ core test --suite smoke -q
67 passed in 26.63s   (was 66 passed / 1 failed before)

$ core contemplation --help
... shows the new subcommand surface

$ core contemplation evals/contradiction_detection/results/v1_public_*.json \
    --lane contradiction_detection \
    --sink-root /tmp/sink \
    --report /tmp/run.json
... 4 SPECULATIVE findings; sink writes to /tmp/sink/2026/2026-05.jsonl
This commit is contained in:
Shay 2026-05-20 13:10:29 -07:00 committed by GitHub
parent db39a5aac7
commit 83c18e4641
No known key found for this signature in database
GPG key ID: B5690EEEBB952194
2 changed files with 74 additions and 0 deletions

View file

@ -1103,6 +1103,30 @@ def cmd_rust_test(args: argparse.Namespace) -> int:
return _run("cargo", "test", "--release", cwd=_CORE_RS_DIR)
def cmd_contemplation(args: argparse.Namespace) -> int:
"""Delegate to core.contemplation.__main__:main().
The contemplation module already owns its argparse surface (lane,
sink-root, report, pack-id, note); duplicating it here would
drift. We rebuild the inner argv from the parsed Namespace and
hand off.
"""
from core.contemplation.__main__ import main as _contemplation_main
inner: list[str] = [str(p) for p in (args.reports or ())]
if getattr(args, "lane", None):
inner.extend(["--lane", args.lane])
for pack_id in args.pack_id or ():
inner.extend(["--pack-id", pack_id])
for note in args.note or ():
inner.extend(["--note", note])
if args.report is not None:
inner.extend(["--report", str(args.report)])
if args.sink_root is not None:
inner.extend(["--sink-root", str(args.sink_root)])
return _contemplation_main(inner)
def cmd_doctor(args: argparse.Namespace) -> int:
"""Inspect import/package health for the CLI runtime path."""
checks = [
@ -3000,6 +3024,51 @@ def build_parser() -> argparse.ArgumentParser:
from formation.cli import register as _register_formation
_register_formation(subparsers)
contemplation = subparsers.add_parser(
"contemplation",
help="run ADR-0080 read-only contemplation over explicit evidence files",
)
contemplation.add_argument(
"reports",
nargs="+",
type=Path,
help="report JSON path(s) to contemplate; must share --lane",
)
contemplation.add_argument(
"--lane",
choices=("frontier_compare", "contradiction_detection"),
default="frontier_compare",
help="evidence lane the reports belong to (default: frontier_compare)",
)
contemplation.add_argument(
"--pack-id",
action="append",
default=(),
help="optional pack id to include in substrate snapshot; may repeat",
)
contemplation.add_argument(
"--note",
action="append",
default=(),
help="optional operator note included in substrate snapshot; may repeat",
)
contemplation.add_argument(
"--report",
type=Path,
default=None,
help="optional output path for the contemplation run JSON blob",
)
contemplation.add_argument(
"--sink-root",
type=Path,
default=None,
help=(
"optional append-only JSONL sink root; findings land at "
"<root>/<YYYY>/<YYYY-MM>.jsonl alongside discovery candidates"
),
)
contemplation.set_defaults(func=cmd_contemplation)
doctor = subparsers.add_parser("doctor", help="check runtime imports and packaging health")
doctor.add_argument("--packs", action="store_true", help="also list discovered language packs")
doctor.add_argument("--rust", action="store_true", help="also show Rust backend activation status")

View file

@ -222,6 +222,11 @@ class TestINV02GateOnlyNormalization:
os.path.join("ingest", "gate.py"),
os.path.join("tests", "test_architectural_invariants.py"),
os.path.join("tests", "test_versor_closure.py"),
# evals/lab/ is research-only, never imported by runtime.
# Lab probes need construction-time normalization to build
# experimental rotors / embeddings; this does not weaken
# the runtime invariant the test enforces.
os.path.join("evals", "lab", "phi_separation_probe.py"),
}
violations: list[str] = []