fix: harden Task 2 schema quality boundaries
This commit is contained in:
@@ -1,6 +1,7 @@
|
||||
# ruff: noqa: BLE001
|
||||
import logging
|
||||
from collections.abc import Mapping
|
||||
from pathlib import Path
|
||||
from typing import TypedDict
|
||||
from typing import Literal, TypedDict
|
||||
|
||||
import typer
|
||||
|
||||
@@ -15,6 +16,7 @@ from tht.ports.vector import VectorWriteRecord
|
||||
from tht.vectorstore.store import SyncStats, content_hash
|
||||
|
||||
vector_app = typer.Typer(help="Indice semantico Qdrant (derivato, rigenerabile)")
|
||||
logger = logging.getLogger(__name__)
|
||||
|
||||
|
||||
def make_embedder(embeddings_cfg):
|
||||
@@ -80,10 +82,19 @@ def sync_canonical_records(collection, records, *, store, embedder):
|
||||
return stats
|
||||
|
||||
|
||||
def _print_stats(stats) -> None:
|
||||
def _print_stats(stats: SyncStats | Mapping[str, int]) -> None:
|
||||
if isinstance(stats, SyncStats):
|
||||
counts = {
|
||||
"added": stats.added,
|
||||
"updated": stats.updated,
|
||||
"deleted": stats.deleted,
|
||||
"unchanged": stats.unchanged,
|
||||
}
|
||||
else:
|
||||
counts = stats
|
||||
typer.secho(
|
||||
f"OK: {stats.added} nuovi, {stats.updated} aggiornati, "
|
||||
f"{stats.deleted} rimossi, {stats.unchanged} invariati",
|
||||
f"OK: {counts['added']} nuovi, {counts['updated']} aggiornati, "
|
||||
f"{counts['deleted']} rimossi, {counts['unchanged']} invariati",
|
||||
fg=typer.colors.GREEN,
|
||||
)
|
||||
|
||||
@@ -138,8 +149,8 @@ class IndexCounts(TypedDict):
|
||||
|
||||
|
||||
class IndexSchemaResult(TypedDict):
|
||||
status: str
|
||||
code: str
|
||||
status: Literal["succeeded", "failed"]
|
||||
code: Literal["ok"]
|
||||
counts: IndexCounts
|
||||
|
||||
|
||||
@@ -158,26 +169,31 @@ def _vector_write_or_error(cfg) -> None:
|
||||
raise _MachineVectorError("vector_write_not_allowed")
|
||||
|
||||
|
||||
def index_schema_data(config: Path) -> IndexSchemaResult:
|
||||
def index_schema_data(
|
||||
config: Path, *, suppress_legacy_warning: bool = False
|
||||
) -> IndexSchemaResult:
|
||||
"""Synchronize schema records and return a bounded machine result."""
|
||||
from tht.cli.schema_cmd import _machine_config
|
||||
from tht.cli.schema_cmd import _load_schema_config
|
||||
from tht.config import ConfigError
|
||||
from tht.mschema.models import Annotations, PhysicalSchema
|
||||
from tht.vectorstore.records import schema_records
|
||||
|
||||
try:
|
||||
cfg = _machine_config(config)
|
||||
except Exception:
|
||||
# Keep this helper free of Typer rendering while preserving a stable code.
|
||||
cfg = _load_schema_config(config, suppress_legacy_warning=suppress_legacy_warning)
|
||||
except ConfigError:
|
||||
raise _MachineVectorError("invalid_configuration") from None
|
||||
_vector_write_or_error(cfg)
|
||||
_vector_cfg_or_error(cfg)
|
||||
phys_file = physical_path(cfg)
|
||||
if not phys_file.exists():
|
||||
raise _MachineVectorError("physical_schema_missing")
|
||||
import yaml
|
||||
from pydantic import ValidationError
|
||||
|
||||
try:
|
||||
physical = PhysicalSchema.from_yaml(phys_file)
|
||||
annotations = Annotations.from_yaml(annotations_path(cfg))
|
||||
except Exception:
|
||||
except (OSError, UnicodeError, TypeError, ValueError, yaml.YAMLError, ValidationError):
|
||||
raise _MachineVectorError("schema_artifacts_invalid") from None
|
||||
records = schema_records(physical, annotations)
|
||||
from tht.adapters.factory import build_vector_store
|
||||
@@ -210,23 +226,24 @@ def index_schema_cmd(
|
||||
|
||||
if json_output:
|
||||
try:
|
||||
payload = index_schema_data(config)
|
||||
payload = index_schema_data(config, suppress_legacy_warning=True)
|
||||
except _MachineVectorError as error:
|
||||
typer.echo(json.dumps({"status": "failed", "code": error.code}, sort_keys=True, separators=(",", ":")))
|
||||
raise typer.Exit(code=1) from None
|
||||
except Exception:
|
||||
except Exception: # noqa: BLE001 - JSON CLI boundary
|
||||
typer.echo(json.dumps({"status": "failed", "code": "schema_index_failed"}, sort_keys=True, separators=(",", ":")))
|
||||
raise typer.Exit(code=1) from None
|
||||
typer.echo(json.dumps(payload, sort_keys=True, separators=(",", ":")))
|
||||
return
|
||||
try:
|
||||
payload = index_schema_data(config)
|
||||
payload = index_schema_data(config, suppress_legacy_warning=False)
|
||||
except _MachineVectorError as error:
|
||||
_render_index_schema_error(error, config)
|
||||
except Exception:
|
||||
logger.exception("Schema indexing failed")
|
||||
typer.secho("ERRORE: impossibile indicizzare lo schema.", fg=typer.colors.RED, err=True)
|
||||
raise typer.Exit(code=1) from None
|
||||
_print_stats(type("Stats", (), payload["counts"])())
|
||||
_print_stats(payload["counts"])
|
||||
|
||||
|
||||
def _render_index_schema_error(error: _MachineVectorError, config: Path) -> None:
|
||||
|
||||
Reference in New Issue
Block a user