Fix CLI help/runtime imports and add doctor command (#4)

* Make core CLI help robust and intuitive

* Package runtime support modules for core CLI

* Add CLI help and doctor tests

* Fix CLI trace help and pack listing

* Export language pack listing helper

* Bootstrap repo root for console runtime imports

* Align trace formatter with Proposition schema

* Cover real trace payload formatting
This commit is contained in:
Shay 2026-05-13 21:15:51 -07:00 committed by GitHub
parent 7f302760ef
commit 09c3664773
No known key found for this signature in database
GPG key ID: B5690EEEBB952194
4 changed files with 370 additions and 139 deletions

View file

@ -1,180 +1,323 @@
"""core CLI — single entry point for the versor engine.
Subcommands
-----------
core chat Start interactive chat session (delegates to python -m chat)
core test [args] Run pytest suite with sane defaults
core check Run ruff on the whole project
core trace <text> Trace one turn: show field condition, dialogue role, proposition
core oov <token> Ground a single unknown token and show the constructed versor info
core pack list List mounted language packs
core pack verify <id> Verify a language pack checksum
"""
"""Command line interface for the CORE versor engine."""
from __future__ import annotations
import argparse
import json
import subprocess
import sys
from typing import NoReturn
from collections.abc import Sequence
from pathlib import Path
from typing import Any, NoReturn
# ---------------------------------------------------------------------------
# Helpers
# ---------------------------------------------------------------------------
def _run(*args: str, check: bool = True) -> subprocess.CompletedProcess[str]:
return subprocess.run(args, check=check, text=True)
# The `core` console script may be installed through stale editable metadata while
# this repo is moving quickly. Ensure sibling top-level packages such as
# alignment/, morphology/, and sensorium/ are importable from the checked-out
# source tree before any runtime imports execute.
_REPO_ROOT = Path(__file__).resolve().parent.parent
if str(_REPO_ROOT) not in sys.path:
sys.path.insert(0, str(_REPO_ROOT))
def _die(msg: str) -> NoReturn:
print(f"error: {msg}", file=sys.stderr)
sys.exit(1)
DESCRIPTION = "CORE versor engine command suite."
EPILOG = "Examples:\n core chat\n core trace \"word beginning truth\"\n core trace --pack en_minimal_v1 --json \"word beginning truth\"\n core oov covenant\n core pack list\n core pack verify en_minimal_v1\n core test tests/test_alignment_graph.py -q"
def _usage() -> NoReturn:
print(__doc__)
sys.exit(0)
def _run(*args: str, check: bool = False) -> int:
"""Run a child command and return its exit code."""
completed = subprocess.run(args, check=check, text=True)
return int(completed.returncode)
# ---------------------------------------------------------------------------
# Subcommands
# ---------------------------------------------------------------------------
def _die(message: str, *, code: int = 2) -> NoReturn:
print(f"error: {message}", file=sys.stderr)
raise SystemExit(code)
def cmd_chat(argv: list[str]) -> None:
def _print_runtime_import_hint(exc: BaseException) -> NoReturn:
_die(
"runtime import failed. Run `core doctor` to inspect packaging. Root cause: "
f"{exc.__class__.__name__}: {exc}",
code=1,
)
def cmd_chat(args: argparse.Namespace) -> int:
"""Launch the readline REPL backed by ChatRuntime."""
_run(sys.executable, "-m", "chat", *argv, check=False)
return _run(sys.executable, "-m", "chat", *args.args)
def cmd_test(argv: list[str]) -> None:
"""Run the pytest suite. Extra args are forwarded to pytest."""
def cmd_test(args: argparse.Namespace) -> int:
"""Run pytest. Extra args are forwarded unchanged."""
default_args = ["-q", "--tb=short"]
_run(sys.executable, "-m", "pytest", *(argv or default_args), check=False)
return _run(sys.executable, "-m", "pytest", *(args.args or default_args))
def cmd_check(argv: list[str]) -> None:
"""Run ruff over the project source."""
targets = argv or [
"algebra", "ingest", "field", "vocab", "vault", "persona",
"generate", "session", "chat", "core", "language_packs", "tests",
def cmd_check(args: argparse.Namespace) -> 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",
]
_run(sys.executable, "-m", "ruff", "check", *targets, check=False)
return _run(sys.executable, "-m", "ruff", "check", *targets)
def cmd_trace(argv: list[str]) -> None:
"""Trace one chat turn and print field telemetry."""
if not argv:
_die("usage: core trace <text>")
text = " ".join(argv)
def _runtime_for_trace(pack: list[str] | None):
try:
from chat.runtime import ChatRuntime
except Exception as exc: # pragma: no cover - exercised by CLI in broken envs
_print_runtime_import_hint(exc)
pack_arg: str | tuple[str, ...]
pack_arg = tuple(pack) if pack else ("en_minimal_v1", "he_logos_micro_v1", "grc_logos_micro_v1")
try:
return ChatRuntime(pack_arg)
except Exception as exc:
_die(
"failed to initialize ChatRuntime. Check mounted language packs with "
"`core pack list` and `core pack verify <pack_id>`. Root cause: "
f"{exc.__class__.__name__}: {exc}",
code=1,
)
from chat.runtime import ChatRuntime
rt = ChatRuntime()
resp = rt.chat(text)
print(f"input : {text}")
print(f"surface : {resp.surface}")
print(f"dialogue_role : {resp.dialogue_role}")
print(f"versor_cond : {resp.versor_condition:.2e}")
p = resp.proposition
print(f"proposition : {p.surface!r}")
print(f" frame_id : {p.frame_id}")
print(f" subject : {p.subject_surface!r}")
print(f" predicate : {p.predicate_surface!r}")
if hasattr(p, "object_surface") and p.object_surface:
print(f" object : {p.object_surface!r}")
def _trace_payload(text: str, resp: Any, runtime: Any) -> dict[str, Any]:
import numpy as np
print(f" relation_norm: {float(np.linalg.norm(p.relation)):.4f}")
session = rt.session
print(f"vault_entries : {len(session.vault)}")
oov = getattr(session.vocab, "unknown_token_log", [])
if oov:
print(f"oov_grounded : {len(oov)} token(s)")
for entry in oov:
proposition = resp.proposition
payload: dict[str, Any] = {
"input": text,
"surface": resp.surface,
"dialogue_role": str(resp.dialogue_role),
"versor_condition": float(resp.versor_condition),
"proposition": {
"surface": proposition.surface,
"frame_id": proposition.frame_id,
"subject": proposition.subject,
"predicate": proposition.predicate,
"object": proposition.object_,
"relation_norm": float(np.linalg.norm(proposition.relation)),
},
"vault_entries": len(runtime.session.vault),
"oov_grounded": list(getattr(runtime.session.vocab, "unknown_token_log", [])),
}
return payload
def _print_trace(payload: dict[str, Any]) -> None:
print(f"input : {payload['input']}")
print(f"surface : {payload['surface']}")
print(f"dialogue_role : {payload['dialogue_role']}")
print(f"versor_cond : {payload['versor_condition']:.2e}")
proposition = payload["proposition"]
print(f"proposition : {proposition['surface']!r}")
print(f" frame_id : {proposition['frame_id']}")
print(f" subject : {proposition['subject']!r}")
print(f" predicate : {proposition['predicate']!r}")
if proposition.get("object"):
print(f" object : {proposition['object']!r}")
print(f" relation_norm: {proposition['relation_norm']:.4f}")
print(f"vault_entries : {payload['vault_entries']}")
oov_entries = payload["oov_grounded"]
if oov_entries:
print(f"oov_grounded : {len(oov_entries)} token(s)")
for entry in oov_entries:
print(f" {entry}")
def cmd_oov(argv: list[str]) -> None:
"""Ground a single unknown token and show the constructed versor info."""
if not argv:
_die("usage: core oov <token>")
token = argv[0]
def cmd_trace(args: argparse.Namespace) -> int:
"""Trace one chat turn and print field telemetry."""
text = " ".join(args.text).strip()
if not text:
_die("trace requires input text. Try: core trace \"word beginning truth\"")
from chat.runtime import ChatRuntime
from algebra.versor import versor_condition
rt = ChatRuntime()
vocab = rt.session.vocab
# Try known first
runtime = _runtime_for_trace(args.pack)
try:
v = vocab.get_versor(token)
print(f"{token!r} is already in the manifold")
import numpy as np
print(f" versor_cond: {versor_condition(v):.2e}")
return
except KeyError:
pass
# Ground it
from ingest.gate import inject
state = inject([token], vocab)
import numpy as np
print(f"{token!r} — grounded as transient")
print(f" versor_cond : {versor_condition(state.F):.2e}")
oov_log = getattr(vocab, "unknown_token_log", [])
if oov_log:
last = oov_log[-1]
print(f" root_used : {last.get('root_used', '?')}")
print(f" ops_applied : {last.get('operators_applied', [])}")
def cmd_pack(argv: list[str]) -> None:
"""Manage language packs."""
if not argv:
_die("usage: core pack [list | verify <pack_id>]")
sub = argv[0]
if sub == "list":
from language_packs import list_packs
packs = list_packs()
if not packs:
print("no compiled packs found")
for pid in packs:
print(pid)
elif sub == "verify":
if len(argv) < 2:
_die("usage: core pack verify <pack_id>")
pack_id = argv[1]
_run(sys.executable, "-m", "language_packs", "verify", pack_id, check=False)
response = runtime.chat(text, max_tokens=args.max_tokens)
except Exception as exc:
_die(f"trace failed: {exc.__class__.__name__}: {exc}", code=1)
payload = _trace_payload(text, response, runtime)
if args.json:
print(json.dumps(payload, ensure_ascii=False, indent=2, sort_keys=True))
else:
_die(f"unknown pack subcommand: {sub!r}")
_print_trace(payload)
return 0
# ---------------------------------------------------------------------------
# Dispatch
# ---------------------------------------------------------------------------
def cmd_oov(args: argparse.Namespace) -> int:
"""Ground a single unknown token and show constructed versor info."""
try:
from algebra.versor import versor_condition
from chat.runtime import ChatRuntime
except Exception as exc: # pragma: no cover - exercised by CLI in broken envs
_print_runtime_import_hint(exc)
_COMMANDS = {
"chat": cmd_chat,
"test": cmd_test,
"check": cmd_check,
"trace": cmd_trace,
"oov": cmd_oov,
"pack": cmd_pack,
}
runtime = ChatRuntime(tuple(args.pack) if args.pack else ("en_minimal_v1", "he_logos_micro_v1", "grc_logos_micro_v1"))
vocab = runtime.session.vocab
try:
versor = vocab.get_versor(args.token)
except KeyError:
from ingest.gate import inject
state = inject([args.token], vocab)
print(f"{args.token!r} — grounded as transient")
print(f" versor_cond : {versor_condition(state.F):.2e}")
oov_log = getattr(vocab, "unknown_token_log", [])
if oov_log:
last = oov_log[-1]
print(f" root_used : {last.get('root_used', '?')}")
print(f" ops_applied : {last.get('operators_applied', [])}")
else:
print(f"{args.token!r} is already in the manifold")
print(f" versor_cond: {versor_condition(versor):.2e}")
return 0
def main() -> None:
args = sys.argv[1:]
if not args or args[0] in {"-h", "--help"}:
_usage()
sub = args[0]
if sub not in _COMMANDS:
_die(f"unknown subcommand {sub!r}. Try: {', '.join(_COMMANDS)}")
_COMMANDS[sub](args[1:])
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_doctor(args: argparse.Namespace) -> int:
"""Inspect import/package health for the CLI runtime path."""
checks = [
("algebra", "algebra"),
("alignment", "alignment.graph"),
("chat", "chat.runtime"),
("language_packs", "language_packs"),
("morphology", "morphology.registry"),
("sensorium", "sensorium.protocol"),
]
ok = True
print(f"repo_root: {_REPO_ROOT}")
for label, module_name in 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}")
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")
return 0 if ok else 1
def build_parser() -> argparse.ArgumentParser:
parser = argparse.ArgumentParser(
prog="core",
description=DESCRIPTION,
epilog=EPILOG,
formatter_class=argparse.RawDescriptionHelpFormatter,
)
parser.add_argument("--version", action="store_true", help="print package version and exit")
subparsers = parser.add_subparsers(dest="command", metavar="command")
chat = subparsers.add_parser("chat", help="start the interactive chat REPL")
chat.add_argument("args", nargs=argparse.REMAINDER, help="arguments forwarded to python -m chat")
chat.set_defaults(func=cmd_chat)
test = subparsers.add_parser("test", help="run pytest with sane defaults")
test.add_argument("args", nargs=argparse.REMAINDER, help="arguments forwarded to pytest")
test.set_defaults(func=cmd_test)
check = subparsers.add_parser("check", help="run ruff check")
check.add_argument("paths", nargs="*", help="optional paths to check")
check.set_defaults(func=cmd_check)
trace = subparsers.add_parser(
"trace",
help="trace one chat turn with field telemetry",
description="trace one chat turn with field telemetry",
)
trace.add_argument("--pack", action="append", help="language pack to mount; repeat for multiple packs")
trace.add_argument("--max-tokens", type=int, default=32, help="maximum generated tokens; default: 32")
trace.add_argument("--json", action="store_true", help="emit machine-readable JSON")
trace.add_argument("text", nargs=argparse.REMAINDER, help="input text to trace")
trace.set_defaults(func=cmd_trace)
oov = subparsers.add_parser("oov", help="ground or inspect one token")
oov.add_argument("--pack", action="append", help="language pack to mount; repeat for multiple packs")
oov.add_argument("token", help="token to inspect or ground")
oov.set_defaults(func=cmd_oov)
pack = subparsers.add_parser("pack", help="inspect and verify language packs")
pack_sub = pack.add_subparsers(dest="pack_command", metavar="pack-command", required=True)
pack_list = pack_sub.add_parser("list", help="list compiled packs")
pack_list.set_defaults(func=cmd_pack_list)
pack_verify = pack_sub.add_parser("verify", help="verify a pack checksum")
pack_verify.add_argument("pack_id", help="pack id, e.g. en_minimal_v1")
pack_verify.set_defaults(func=cmd_pack_verify)
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.set_defaults(func=cmd_doctor)
return parser
def _print_version() -> None:
try:
from importlib.metadata import version
print(version("core-versor"))
except Exception:
print("core-versor unknown")
def main(argv: Sequence[str] | None = None) -> int:
parser = build_parser()
args = parser.parse_args(list(argv) if argv is not None else None)
if args.version:
_print_version()
return 0
func = getattr(args, "func", None)
if func is None:
parser.print_help()
return 0
return int(func(args))
if __name__ == "__main__":
main()
raise SystemExit(main())

View file

@ -6,6 +6,8 @@ linguistic manifolds: surface forms, morphology, grammar attractors,
cross-language resonances, and holonomy resonance proofs.
"""
from pathlib import Path
from .schema import (
AlignmentEdge,
GrammarAttractor,
@ -16,6 +18,23 @@ from .schema import (
MorphologyEntry,
OOVPolicy,
)
_DATA_DIR = Path(__file__).parent / "data"
def list_packs() -> list[str]:
"""Return available compiled language-pack ids."""
if not _DATA_DIR.exists():
return []
return sorted(
path.name
for path in _DATA_DIR.iterdir()
if path.is_dir()
and (path / "manifest.json").exists()
and (path / "lexicon.jsonl").exists()
)
__all__ = [
"AlignmentEdge",
"GrammarAttractor",
@ -25,6 +44,7 @@ __all__ = [
"LexicalEntry",
"MorphologyEntry",
"OOVPolicy",
"list_packs",
]

View file

@ -26,13 +26,16 @@ core = "core.cli:main"
where = ["."]
include = [
"algebra*",
"alignment*",
"chat*",
"core*",
"field*",
"generate*",
"ingest*",
"language_packs*",
"morphology*",
"persona*",
"sensorium*",
"session*",
"vault*",
"vocab*",

65
tests/test_cli.py Normal file
View file

@ -0,0 +1,65 @@
from __future__ import annotations
import pytest
from core.cli import build_parser, main
def test_top_level_help_exits_without_runtime_import(capsys: pytest.CaptureFixture[str]) -> None:
with pytest.raises(SystemExit) as excinfo:
build_parser().parse_args(["-h"])
assert excinfo.value.code == 0
out = capsys.readouterr().out
assert "CORE versor engine command suite" in out
assert "core trace" in out
def test_trace_help_exits_without_runtime_import(capsys: pytest.CaptureFixture[str]) -> None:
with pytest.raises(SystemExit) as excinfo:
build_parser().parse_args(["trace", "-h"])
assert excinfo.value.code == 0
out = capsys.readouterr().out
assert "trace one chat turn" in out
assert "--pack" in out
assert "--json" in out
def test_main_without_args_prints_help(capsys: pytest.CaptureFixture[str]) -> None:
assert main([]) == 0
out = capsys.readouterr().out
assert "CORE versor engine command suite" in out
assert "doctor" in out
def test_trace_requires_text_before_runtime_initialization(capsys: pytest.CaptureFixture[str]) -> None:
with pytest.raises(SystemExit) as excinfo:
main(["trace"])
assert excinfo.value.code == 2
err = capsys.readouterr().err
assert "trace requires input text" in err
def test_doctor_imports_runtime_support_modules(capsys: pytest.CaptureFixture[str]) -> None:
assert main(["doctor"]) == 0
out = capsys.readouterr().out
assert "OK alignment" in out
assert "OK morphology" in out
assert "OK sensorium" in out
def test_trace_formats_real_runtime_payload(capsys: pytest.CaptureFixture[str]) -> None:
assert main(["trace", "--pack", "en_minimal_v1", "word", "beginning", "truth"]) == 0
out = capsys.readouterr().out
assert "input : word beginning truth" in out
assert "proposition" in out
assert "subject" in out
assert "predicate" in out
def test_trace_json_formats_real_runtime_payload(capsys: pytest.CaptureFixture[str]) -> None:
assert main(["trace", "--pack", "en_minimal_v1", "--json", "word", "beginning", "truth"]) == 0
out = capsys.readouterr().out
assert '"input": "word beginning truth"' in out
assert '"proposition"' in out
assert '"subject"' in out
assert '"predicate"' in out