feat: pristine harness JSON interfaces and require-existing semantic mode (P2)
This commit is contained in:
@@ -2,27 +2,57 @@
|
||||
|
||||
from __future__ import annotations
|
||||
|
||||
import hashlib
|
||||
import json
|
||||
import re
|
||||
import hashlib
|
||||
from pathlib import Path
|
||||
|
||||
import typer
|
||||
|
||||
from tht.cli.config_cmd import CONFIG_OPT
|
||||
from tht.config import workspace_id_from_path
|
||||
|
||||
|
||||
preprocess_app = typer.Typer(help="Materialize versioned preprocessing artifacts")
|
||||
|
||||
|
||||
def _evidence_json_context(config: Path):
|
||||
from tht.cli.schema_cmd import _load_config_or_exit
|
||||
|
||||
return _load_config_or_exit(config)
|
||||
|
||||
|
||||
def _evidence_json_payload(cfg, payload: dict, *, code: str, error: str | None = None) -> dict:
|
||||
value = {
|
||||
**payload,
|
||||
"schemaVersion": 1,
|
||||
"status": payload.get("status", "failed"),
|
||||
"code": code,
|
||||
"operation": "preprocess_evidence",
|
||||
"workspaceId": cfg._workspace_id,
|
||||
"workspaceRevision": cfg._workspace_revision,
|
||||
}
|
||||
if error is not None:
|
||||
value["error"] = error
|
||||
return value
|
||||
|
||||
|
||||
def _simple_json_payload(*, code: str, error: str) -> dict:
|
||||
return {
|
||||
"schemaVersion": 1,
|
||||
"status": "failed",
|
||||
"code": code,
|
||||
"operation": "preprocess_evidence",
|
||||
"error": error,
|
||||
}
|
||||
|
||||
|
||||
def run_dwh_from_config(
|
||||
config: Path, *, steps: tuple[str, ...], resume: str | None = None,
|
||||
):
|
||||
from tht.cli.lsh_cmd import build_lsh_artifacts
|
||||
from tht.cli.schema_cmd import _load_config_or_exit, refresh_catalog
|
||||
from tht.jobs.dwh_pipeline import (
|
||||
DwhPreprocessPipeline, config_dwh_binding,
|
||||
DwhPreprocessPipeline,
|
||||
config_dwh_binding,
|
||||
)
|
||||
|
||||
cfg = _load_config_or_exit(config)
|
||||
@@ -87,7 +117,7 @@ def run_from_config(config: Path, *, dry_run: bool = False, resume: str | None =
|
||||
return "sha256:" + hashlib.sha256(value.encode()).hexdigest()
|
||||
|
||||
return pipeline.run_as_job(
|
||||
workspace_id=workspace_id_from_path(config),
|
||||
workspace_id=cfg._workspace_id,
|
||||
workspace_root=corpus_root.parent,
|
||||
config_fingerprint=fingerprint(cfg.model_dump_json()),
|
||||
input_fingerprint=fingerprint(config.resolve().as_posix()),
|
||||
@@ -116,7 +146,7 @@ def gc_from_config(config: Path, *, dry_run: bool = False):
|
||||
pipeline_version="evidence-v1",
|
||||
retain_published_generations=cfg.vector.retain_published_generations,
|
||||
)
|
||||
pipeline.workspace_id = workspace_id_from_path(config)
|
||||
pipeline.workspace_id = cfg._workspace_id
|
||||
return pipeline.gc(workspace_root=corpus_root.parent, dry_run=dry_run)
|
||||
|
||||
|
||||
@@ -133,7 +163,7 @@ def evidence_cmd(
|
||||
if action == "gc":
|
||||
try:
|
||||
payload = gc_from_config(config, dry_run=dry_run)
|
||||
except Exception:
|
||||
except Exception: # noqa: BLE001
|
||||
payload = {"status": "failed", "error": "evidence cleanup failed"}
|
||||
if json_output:
|
||||
typer.echo(json.dumps(payload, sort_keys=True))
|
||||
@@ -145,8 +175,12 @@ def evidence_cmd(
|
||||
else:
|
||||
typer.echo(f"OK: evicted={len(payload['evicted'])} failures={len(payload['failures'])}")
|
||||
return
|
||||
cfg = _evidence_json_context(config) if json_output else None
|
||||
if resume is not None and re.fullmatch(r"[0-9a-f]{32}", resume) is None:
|
||||
payload = {"status": "failed", "error": "resume requires a preprocessing run id"}
|
||||
payload = _simple_json_payload(
|
||||
code="invalid_resume",
|
||||
error="resume requires a preprocessing run id",
|
||||
)
|
||||
if json_output:
|
||||
typer.echo(json.dumps(payload, sort_keys=True))
|
||||
else:
|
||||
@@ -154,23 +188,43 @@ def evidence_cmd(
|
||||
raise typer.Exit(code=2)
|
||||
try:
|
||||
result = run_from_config(config, dry_run=dry_run, resume=resume)
|
||||
except Exception:
|
||||
payload = {"status": "failed", "error": "preprocessing failed"}
|
||||
except Exception: # noqa: BLE001
|
||||
payload = {"status": "failed"}
|
||||
if json_output:
|
||||
typer.echo(json.dumps(payload, sort_keys=True))
|
||||
typer.echo(json.dumps(
|
||||
_evidence_json_payload(
|
||||
cfg,
|
||||
payload,
|
||||
code="preprocessing_failed",
|
||||
error="preprocessing failed",
|
||||
),
|
||||
sort_keys=True,
|
||||
))
|
||||
else:
|
||||
typer.secho("ERRORE: preprocessing failed", fg=typer.colors.RED, err=True)
|
||||
raise typer.Exit(code=1) from None
|
||||
payload = result.model_dump(mode="json")
|
||||
if payload.get("status") != "succeeded":
|
||||
payload["error"] = "preprocessing job failed"
|
||||
if json_output:
|
||||
typer.echo(json.dumps(payload, ensure_ascii=False, sort_keys=True))
|
||||
typer.echo(json.dumps(
|
||||
_evidence_json_payload(
|
||||
cfg,
|
||||
payload,
|
||||
code="preprocessing_failed",
|
||||
error="preprocessing job failed",
|
||||
),
|
||||
ensure_ascii=False,
|
||||
sort_keys=True,
|
||||
))
|
||||
else:
|
||||
typer.secho("ERRORE: preprocessing job failed", fg=typer.colors.RED, err=True)
|
||||
raise typer.Exit(code=1)
|
||||
if json_output:
|
||||
typer.echo(json.dumps(payload, ensure_ascii=False, sort_keys=True))
|
||||
typer.echo(json.dumps(
|
||||
_evidence_json_payload(cfg, payload, code="ok"),
|
||||
ensure_ascii=False,
|
||||
sort_keys=True,
|
||||
))
|
||||
else:
|
||||
counts = payload["counts"]
|
||||
typer.echo(
|
||||
@@ -205,7 +259,7 @@ def dwh_cmd(
|
||||
raise typer.Exit(code=2)
|
||||
try:
|
||||
result = run_dwh_from_config(config, steps=selected, resume=resume)
|
||||
except Exception:
|
||||
except Exception: # noqa: BLE001
|
||||
payload = {"status": "failed", "error": "DWH preprocessing failed"}
|
||||
if json_output:
|
||||
typer.echo(json.dumps(payload, sort_keys=True))
|
||||
|
||||
Reference in New Issue
Block a user