refactor(harness): route workflow persistence through repositories

This commit is contained in:
User
2026-07-16 18:01:29 +02:00
parent 259f021313
commit c1cddaa667
30 changed files with 925 additions and 348 deletions
+38 -20
View File
@@ -42,12 +42,14 @@ def require_action(cfg, action: str) -> None:
def promoted_tables_for(cfg, session_id: str | None) -> set[str] | None:
if session_id is None:
return None
linking_path = cfg.paths.sessions / session_id / "schema_linking.json"
if not linking_path.exists():
from tht.cli.session_cmd import load_snapshot_or_exit
raw = load_snapshot_or_exit(cfg, session_id).artifacts.get("schema_linking")
if raw is None:
return None
from tht.session.models import SchemaLinking
linking = SchemaLinking.model_validate(json.loads(linking_path.read_text()))
linking = SchemaLinking.model_validate(json.loads(raw))
return {
c.name for c in linking.candidates
if c.kind == "table" and c.decision == "promoted"
@@ -59,12 +61,14 @@ def promoted_tables_for(cfg, session_id: str | None) -> set[str] | None:
def promoted_columns_for(cfg, session_id: str | None) -> set[str] | None:
if session_id is None:
return None
linking_path = cfg.paths.sessions / session_id / "schema_linking.json"
if not linking_path.exists():
from tht.cli.session_cmd import load_snapshot_or_exit
raw = load_snapshot_or_exit(cfg, session_id).artifacts.get("schema_linking")
if raw is None:
return None
from tht.session.models import SchemaLinking
linking = SchemaLinking.model_validate(json.loads(linking_path.read_text()))
linking = SchemaLinking.model_validate(json.loads(raw))
return {
c.name for c in linking.candidates
if c.kind == "column" and c.decision == "promoted"
@@ -182,7 +186,7 @@ def preview_cmd(
"""Esecuzione controllata con LIMIT iniettato; aggregati mostrati per interi.
Se FILE è omesso e --session è fornito, il file viene risolto automaticamente
come <workspace>/sessions/<session>/sql_final.sql (tramite _session_sql_file).
dall'artefatto `sql_final` del repository della sessione.
"""
from tht.execute import ExecutionError
@@ -195,8 +199,7 @@ def preview_cmd(
fg=typer.colors.RED, err=True,
)
raise typer.Exit(code=1)
resolved = _session_sql_file(cfg, session)
sql = resolved.read_text()
sql = _session_sql(cfg, session)
else:
sql = _read_sql(file)
check = validate_or_exit(cfg, sql, session)
@@ -247,15 +250,32 @@ def preview_cmd(
typer.secho(f" warning: {w}", fg=typer.colors.YELLOW)
def _session_sql_file(cfg, session_id: str) -> Path:
from tht.cli.session_cmd import load_session_or_exit, session_dir
def _session_sql(cfg, session_id: str) -> str:
from tht.cli.session_cmd import load_snapshot_or_exit
load_session_or_exit(cfg, session_id)
sql_file = session_dir(cfg, session_id) / "sql_final.sql"
if not sql_file.exists():
typer.secho(f"ERRORE: {sql_file} non trovato.", fg=typer.colors.RED, err=True)
sql = load_snapshot_or_exit(cfg, session_id).artifacts.get("sql_final")
if sql is None:
typer.secho("ERRORE: sql_final.sql non trovato.", fg=typer.colors.RED, err=True)
raise typer.Exit(code=1)
return sql_file
return sql
@sql_app.command("set-final")
def set_final_cmd(
session: str = typer.Option(..., "--session"),
file: str = typer.Option(..., "--file", help="File SQL, oppure '-' per stdin."),
config: Path = CONFIG_OPT,
) -> None:
"""Persist clean final SQL through the configured session repository."""
import sys
from tht.cli.session_cmd import load_session_or_exit, session_repository
cfg = _load_config_or_exit(config)
load_session_or_exit(cfg, session)
sql = sys.stdin.read() if file == "-" else _read_sql(Path(file))
session_repository(cfg).write_artifact(session, "sql_final", sql)
typer.secho("OK: SQL finale salvato.", fg=typer.colors.GREEN)
@sql_app.command("save")
@@ -266,9 +286,8 @@ def save_cmd(
) -> None:
"""Salva una copia di sql_final.sql nel percorso indicato (su richiesta esplicita)."""
cfg = _load_config_or_exit(config)
sql_file = _session_sql_file(cfg, session)
dest.parent.mkdir(parents=True, exist_ok=True)
dest.write_text(sql_file.read_text())
dest.write_text(_session_sql(cfg, session))
typer.secho(f"OK: SQL salvato in {dest}", fg=typer.colors.GREEN)
@@ -286,8 +305,7 @@ def export_cmd(
cfg = _load_config_or_exit(config)
require_action(cfg, "export")
sql_file = _session_sql_file(cfg, session)
sql = sql_file.read_text()
sql = _session_sql(cfg, session)
validate_or_exit(cfg, sql, session)
try:
result = do_run(cfg, sql, limit=cfg.execution.max_export_rows)