Files
ely-eye/backend/src/ely_eye/cli.py
T
ZacharyZhang-NY 9145a23f18 Require a token for writes and quarantine what nobody vouches for
Sixteen mutating routes now refuse a caller who cannot present the token the
server started with; queries stay open, because a question is not a write. The
environment variable is ELY_EYE_AUTH_TOKEN, following the repo's env_prefix
convention — the shorter name I reached for first returned 403 where the smoke
expected 401, and the server printed the reason.

Words from a stranger are quarantined on the way in: an HTTP upload is
third_party by definition, and a sentence carrying an instruction-shaped phrase
is quarantined whoever wrote it. A quarantined atom stays findable and stays out
of the compiled context until a second, live, unquarantined source agrees with
its rarest words. Corroboration is computed at read time because it is a
property of the corpus now, not of the moment a memory was written; it is
term-level, and the docstring says so.

forget now erases the source row and the compiled contexts beside the atoms, so
a forgotten memory leaves nothing that can still speak. The semantic cache key
carries a store revision, which fixes a real staleness: a context compiled
before new evidence arrived kept its old quarantine decision forever.

bench.audit --product still pointed at evals.py, which the p1-6 split moved into
backend/src/ely_eye/proofs/. It failed fast, but the anti-self-justification
rule had quietly stopped auditing the product; it now walks the package, and a
test pins that the package exists and holds no re-roll.

Gates: pytest 306 passed; ruff clean; mypy cold cache 24 errors in 9 files, the
recorded baseline, net zero; pyright 0 errors on the 23 backend files and the 2
bench files; go build/vet/test and gofmt clean; npm run build 221.39 kB with
eslint exit 0; bench/filesize_check clean; bench.audit --product clean over 31
harness files; scripts/mcp_write_smoke.sh PASS with the gate live across two
servers and the MCP child.
2026-10-08 23:05:15 -04:00

496 lines
16 KiB
Python

from __future__ import annotations
from datetime import datetime
from pathlib import Path
import typer
import uvicorn
from .adapters import plan as adapter_plan
from .api import create_app
from .benchmarks import (
benchmark_prediction_report,
benchmark_registry_report,
benchmark_sample_report,
benchmark_source_report,
run_prediction_benchmark,
)
from .cartridge import CartridgeService
from .cartridge_assets import CartridgeAssetService
from .cli_common import json_dump
from .cli_maintenance import register as register_maintenance_commands
from .cli_senses import register as register_sense_commands
from .cli_senses import senses_report
from .cli_transactive import register as register_transactive_commands
from .config import get_settings
from .db import Database
from .ingestion import IngestionService
from .memory import MemoryService
from .profiles import runtime_profile_report
from .proofs import HashHopEvaluator, PRDProofSuite
from .proofs.contradictions import CORPUS_NAME, build_contradiction_scenarios, write_corpus
from .proofs.table import render_table
from .research_modules import ResearchModuleService
from .retrieval import RetrievalService
from .runtime import QwenRuntime
from .schemas import MemoryOrigin, SearchFilters, TimePrecision, TrainingAdapterKind
from .training import TrainingService
app = typer.Typer(no_args_is_help=True)
register_transactive_commands(app, lambda: get_settings())
register_sense_commands(app, lambda: get_settings())
register_maintenance_commands(app, lambda: get_settings())
@app.command()
def serve(host: str = "127.0.0.1", port: int = 8765) -> None:
settings = get_settings()
if settings.auth_token:
typer.echo(f"writes need Authorization: Bearer $ELY_EYE_AUTH_TOKEN; {len(settings.allowed_origins)} allowed origin(s)")
else:
typer.echo("writes are closed on this server: start it with ELY_EYE_AUTH_TOKEN set")
uvicorn.run(create_app(), host=host, port=port)
@app.command()
def status() -> None:
settings = get_settings()
runtime = QwenRuntime(settings).status()
db = Database(settings)
typer.echo(
json_dump(
{
"runtime": runtime.model_dump(mode="json"),
"atoms": db.atom_count(),
"token_equivalent": db.token_equivalent_sum(),
"library_token_equivalent": max(
db.token_equivalent_sum(),
db.cartridge_token_equivalent_sum(),
),
"cartridges": db.cartridge_count(),
"data_home": str(settings.home),
"senses": senses_report(settings, db),
}
)
)
@app.command()
def ingest(path: Path, cartridge_name: str | None = None) -> None:
result = IngestionService(get_settings()).ingest_path(path, cartridge_name)
typer.echo(result.model_dump_json(indent=2))
def _moment(value: str, option: str) -> datetime | None:
if not value:
return None
try:
return datetime.fromisoformat(value)
except ValueError as error:
raise ValueError(f"{option} {value!r} is not an ISO timestamp: {error}") from error
@app.command()
def search(
query: str,
top_k: int = typer.Option(0, "--top-k", help="hits to return; 0 uses the configured default"),
holder: str = typer.Option("", "--holder", help="only this holder's memories may answer"),
scenario: str = typer.Option("", "--scenario"),
source_id: str = typer.Option("", "--source-id"),
since: str = typer.Option("", "--since", help="event time at or after, ISO with offset"),
until: str = typer.Option("", "--until"),
min_trust: float = typer.Option(-1.0, "--min-trust", help="drop memories whose trust falls below this"),
cursor: str = typer.Option("", "--cursor", help="next_cursor from the previous page"),
image: str = typer.Option("", "--image", help="a picture to search with, instead of only words"),
) -> None:
"""Rank the memories that may answer, and say so when none may."""
settings = get_settings()
result = RetrievalService(settings).search(
query,
top_k or None,
filters=SearchFilters(
holder=holder or None,
scenario=scenario or None,
source_id=source_id or None,
since=_moment(since, "--since"),
until=_moment(until, "--until"),
min_trust=None if min_trust < 0 else min_trust,
),
cursor=cursor or None,
image=Path(image) if image else None,
)
typer.echo(result.model_dump_json(indent=2))
@app.command()
def remember(
text: str,
holder: str = typer.Option("", "--holder", help="who owns this memory"),
origin: MemoryOrigin = MemoryOrigin.self_,
scenario: str = "",
event_time: str = typer.Option("", "--event-time", help="when it was true, ISO with offset"),
precision: TimePrecision = TimePrecision.unknown,
retention_until: str = typer.Option("", "--retention-until"),
) -> None:
settings = get_settings()
atom = MemoryService(settings).remember(
text,
holder_id=holder or settings.default_holder,
origin=origin,
scenario=scenario,
event_time=_moment(event_time, "--event-time"),
event_time_precision=precision,
retention_until=_moment(retention_until, "--retention-until"),
)
typer.echo(atom.model_dump_json(indent=2))
@app.command()
def supersede(
atom_id: str,
text: str,
holder: str = typer.Option("", "--holder"),
scenario: str = "",
event_time: str = typer.Option("", "--event-time"),
precision: TimePrecision = TimePrecision.unknown,
) -> None:
settings = get_settings()
atom = MemoryService(settings).supersede(
atom_id,
text=text,
holder_id=holder or settings.default_holder,
scenario=scenario,
event_time=_moment(event_time, "--event-time"),
event_time_precision=precision,
)
typer.echo(atom.model_dump_json(indent=2))
@app.command()
def forget(atom_id: str = "", source_id: str = "", reason: str = "") -> None:
report = MemoryService(get_settings()).forget(
atom_id=atom_id or None,
source_id=source_id or None,
reason=reason,
)
typer.echo(report.model_dump_json(indent=2))
@app.command("list-cartridges")
def list_cartridges() -> None:
for manifest in CartridgeService(get_settings()).list_manifests():
typer.echo(manifest.model_dump_json(indent=2))
@app.command("mounts")
def mounts() -> None:
typer.echo(CartridgeService(get_settings()).mount_state().model_dump_json(indent=2))
@app.command()
def mount(cartridge_id: str) -> None:
"""Add a cartridge to the mounted set; a mounted search answers only from it."""
typer.echo(CartridgeService(get_settings()).mount(cartridge_id).model_dump_json(indent=2))
@app.command()
def switch(cartridge_id: str) -> None:
"""Mount one cartridge and nothing else."""
typer.echo(CartridgeService(get_settings()).switch(cartridge_id).model_dump_json(indent=2))
@app.command()
def unmount(cartridge_id: str) -> None:
typer.echo(CartridgeService(get_settings()).unmount(cartridge_id).model_dump_json(indent=2))
@app.command()
def append(
cartridge_id: str,
atom_id: list[str] = typer.Option(..., "--atom-id"),
) -> None:
"""Add memories to an existing cartridge; the bundle and its DNA follow."""
service = CartridgeService(get_settings())
typer.echo(service.append(cartridge_id, list(atom_id)).model_dump_json(indent=2))
@app.command("hashhop")
def hashhop(kind: str = "visual", hops: int = 2, token_equivalent: int = 262_144) -> None:
evaluator = HashHopEvaluator(get_settings())
if kind == "text":
proof = evaluator.generate_text_proof(hops, token_equivalent)
elif kind == "visual":
proof = evaluator.generate_visual_proof(hops, token_equivalent)
else:
raise typer.BadParameter("kind must be text or visual")
typer.echo(proof.model_dump_json(indent=2))
@app.command("proof-suite")
def proof_suite(cartridge_id: str | None = None) -> None:
report = PRDProofSuite(get_settings()).run(cartridge_id)
typer.echo(report.model_dump_json(indent=2))
@app.command("latest-proof-suite")
def latest_proof_suite(json_output: bool = typer.Option(False, "--json")) -> None:
"""Print what the last proof suite claimed and what it actually proved."""
report = PRDProofSuite(get_settings()).latest()
if report is None:
raise typer.BadParameter(
"no proof suite has been recorded yet; run: ely-eye proof-suite --cartridge-id <id>"
)
if json_output:
typer.echo(report.model_dump_json(indent=2))
else:
typer.echo(render_table(report))
if report.status == "failed":
raise typer.Exit(code=1)
@app.command("runtime-generation-proof")
def runtime_generation_proof() -> None:
check = PRDProofSuite(get_settings()).runtime_generation_proof()
typer.echo(check.model_dump_json(indent=2))
@app.command("visual-contradiction-proof")
def visual_contradiction_proof() -> None:
check = PRDProofSuite(get_settings()).visual_contradiction_proof()
typer.echo(check.model_dump_json(indent=2))
@app.command("contradiction-corpus")
def contradiction_corpus(data_dir: Path | None = None) -> None:
"""Write the corpus the contradiction lens is graded on, so it can be read and replaced."""
settings = get_settings()
target = write_corpus((data_dir or settings.data_dir) / CORPUS_NAME)
typer.echo(json_dump({"corpus": str(target), "scenarios": len(build_contradiction_scenarios())}))
@app.command("finalize-cartridge")
def finalize_cartridge(cartridge_id: str) -> None:
report = CartridgeAssetService(get_settings()).finalize(cartridge_id)
typer.echo(report.model_dump_json(indent=2))
@app.command("refresh-cartridge")
def refresh_cartridge(cartridge_id: str) -> None:
settings = get_settings()
db = Database(settings)
manifest = CartridgeService(settings, db).rebuild(
cartridge_id=cartridge_id,
atoms=db.list_atoms(),
sources=db.list_sources(),
)
typer.echo(manifest.model_dump_json(indent=2))
@app.command("benchmark-registry")
def benchmark_registry() -> None:
typer.echo(benchmark_registry_report().model_dump_json(indent=2))
@app.command("benchmark-sources")
def benchmark_sources() -> None:
typer.echo(benchmark_source_report().model_dump_json(indent=2))
@app.command("benchmark-samples")
def benchmark_samples() -> None:
settings = get_settings()
output_dir = settings.data_dir / "benchmark_samples"
typer.echo(benchmark_sample_report(output_dir).model_dump_json(indent=2))
@app.command("benchmark-predictions")
def benchmark_predictions() -> None:
settings = get_settings()
output_dir = settings.data_dir / "benchmark_predictions"
typer.echo(benchmark_prediction_report(settings, output_dir).model_dump_json(indent=2))
@app.command("run-benchmark")
def run_benchmark(
benchmark: str,
dataset_path: Path,
prediction_field: str = "prediction",
answer_field: str = "answer",
limit: int | None = None,
) -> None:
report = run_prediction_benchmark(
benchmark=benchmark,
dataset_path=dataset_path,
prediction_field=prediction_field,
answer_field=answer_field,
limit=limit,
)
typer.echo(report)
@app.command("runtime-profiles")
def runtime_profiles() -> None:
typer.echo(runtime_profile_report(get_settings()).model_dump_json(indent=2))
@app.command("research-modules")
def research_modules(query: str = "Ely-Eye V-NSA DVKV x-modal KV speculative prefetch evidence graph") -> None:
settings = get_settings()
db = Database(settings)
from .compiler import ContextCompiler
from .schemas import RuntimeProfile
context = ContextCompiler(settings, db).compile(query, RuntimeProfile.research_theater)
report = ResearchModuleService(settings, db).build_report(query, context.hits)
typer.echo(json_dump(report))
@app.command("validate-training-data")
def validate_training_data(path: Path) -> None:
samples = TrainingService(get_settings()).validate_dataset(path)
typer.echo({"samples": len(samples)})
@app.command("build-prd-training-data")
def build_prd_training_data(
prd_path: Path = Path("PRD.md"),
output_path: Path | None = None,
cartridge_id: str | None = None,
max_sections: int = 48,
) -> None:
path = TrainingService(get_settings()).build_prd_dataset(
prd_path=prd_path,
output_path=output_path,
cartridge_id=cartridge_id,
max_sections=max_sections,
)
samples = TrainingService(get_settings()).validate_dataset(path)
typer.echo({"dataset": str(path), "samples": len(samples)})
@app.command("build-visual-training-data")
def build_visual_training_data(
prd_path: Path = Path("PRD.md"),
output_path: Path | None = None,
cartridge_id: str | None = None,
image_path: list[Path] | None = typer.Option(None, "--image-path"),
) -> None:
path = TrainingService(get_settings()).build_visual_dataset(
prd_path=prd_path,
output_path=output_path,
image_paths=image_path,
cartridge_id=cartridge_id,
)
samples = TrainingService(get_settings()).validate_dataset(path)
typer.echo({"dataset": str(path), "samples": len(samples)})
@app.command("build-router-training-data")
def build_router_training_data(
prd_path: Path = Path("PRD.md"),
output_path: Path | None = None,
cartridge_id: str | None = None,
) -> None:
path = TrainingService(get_settings()).build_router_dataset(
prd_path=prd_path,
output_path=output_path,
cartridge_id=cartridge_id,
)
samples = TrainingService(get_settings()).validate_dataset(path)
typer.echo({"dataset": str(path), "samples": len(samples)})
@app.command("build-retrieval-training-data")
def build_retrieval_training_data(
prd_path: Path = Path("PRD.md"),
output_path: Path | None = None,
cartridge_id: str | None = None,
max_sections: int = 32,
) -> None:
path = TrainingService(get_settings()).build_retrieval_dataset(
prd_path=prd_path,
output_path=output_path,
cartridge_id=cartridge_id,
max_sections=max_sections,
)
samples = TrainingService(get_settings()).validate_dataset(path)
typer.echo({"dataset": str(path), "samples": len(samples)})
@app.command("train-lora")
def train_lora(
dataset_path: Path,
output_dir: Path,
max_steps: int = 8,
kind: TrainingAdapterKind = TrainingAdapterKind.hme_core_lora,
model_id: str | None = None,
rank: int = 16,
alpha: int = 32,
max_length: int | None = None,
gradient_accumulation_steps: int | None = None,
learning_rate: float | None = None,
cartridge_id: str | None = None,
) -> None:
manifest = TrainingService(get_settings()).train_lora(
dataset_path=dataset_path,
output_dir=output_dir,
max_steps=max_steps,
kind=kind,
model_id=model_id,
rank=rank,
alpha=alpha,
max_length=max_length,
gradient_accumulation_steps=gradient_accumulation_steps,
learning_rate=learning_rate,
cartridge_id=cartridge_id,
)
if cartridge_id:
CartridgeService(get_settings()).attach_adapter(cartridge_id, output_dir)
typer.echo(manifest.model_dump_json(indent=2))
@app.command("train-retrieval-lora")
def train_retrieval_lora(
dataset_path: Path,
output_dir: Path,
max_steps: int = 8,
rank: int = 8,
alpha: int = 16,
max_length: int | None = None,
learning_rate: float | None = None,
cartridge_id: str | None = None,
) -> None:
manifest = TrainingService(get_settings()).train_retrieval_lora(
dataset_path=dataset_path,
output_dir=output_dir,
max_steps=max_steps,
rank=rank,
alpha=alpha,
max_length=max_length,
learning_rate=learning_rate,
cartridge_id=cartridge_id,
)
if cartridge_id:
CartridgeService(get_settings()).attach_adapter(cartridge_id, output_dir)
typer.echo(manifest.model_dump_json(indent=2))
@app.command("attach-adapter")
def attach_adapter(cartridge_id: str, adapter_dir: Path) -> None:
manifest = CartridgeService(get_settings()).attach_adapter(cartridge_id, adapter_dir)
typer.echo(manifest.model_dump_json(indent=2))
@app.command("adapters")
def adapter_status() -> None:
"""Which adapter the runtime would load, and why each other kind would not."""
settings = get_settings()
report = adapter_plan(settings, Database(settings))
typer.echo(json_dump(report.model_dump(mode="json")))
if __name__ == "__main__":
app()