docs(accuracy): refresh governed scan and training evidence
This commit is contained in:
@@ -21,7 +21,7 @@ from datetime import datetime, timezone
|
||||
from pathlib import Path
|
||||
from typing import Any, Iterable
|
||||
|
||||
SCANNER_VERSION = "3.0.3"
|
||||
SCANNER_VERSION = "3.1.0"
|
||||
SCHEMA_VERSION = 1
|
||||
DEFAULT_ROOTS = ("models", "datasets", "data", "storage", "artifacts", "output")
|
||||
EXCLUDED_DIRS = {".git", "node_modules", ".next", "__pycache__", ".pytest_cache"}
|
||||
@@ -101,13 +101,16 @@ def discover_files(repo_root: Path, roots: Iterable[str], evidence_dir: Path) ->
|
||||
return sorted(set(files), key=lambda item: relative_path(item, repo_root))
|
||||
|
||||
|
||||
def known_unreachable_items() -> list[dict[str, Any]]:
|
||||
"""Boundaries identified by the Phase 1 inventory but not mounted locally."""
|
||||
entries = (
|
||||
("external://tower-corpora", "Tower corpora are not mounted in this project environment"),
|
||||
("external://mounted-model-volumes", "Mounted model volumes are not available from this project environment"),
|
||||
("external://production-postgis-or-api", "No production PostGIS/API endpoint is configured in the scan environment"),
|
||||
)
|
||||
def unreachable_items(entries: Iterable[tuple[str, str]]) -> list[dict[str, Any]]:
|
||||
"""Create explicit scope records without inventing environment availability.
|
||||
|
||||
Older scanner versions always emitted three hard-coded unreachable items,
|
||||
even when executed inside the production container where the corresponding
|
||||
model and training mounts were available. Callers must now declare only
|
||||
boundaries they have actually established as unavailable; requested roots
|
||||
that do not exist are added automatically by :func:`missing_root_entries`.
|
||||
"""
|
||||
|
||||
result = []
|
||||
for path, reason in entries:
|
||||
result.append(
|
||||
@@ -140,6 +143,29 @@ def known_unreachable_items() -> list[dict[str, Any]]:
|
||||
return result
|
||||
|
||||
|
||||
def parse_unreachable_scope(value: str) -> tuple[str, str]:
|
||||
path, separator, reason = value.partition("=")
|
||||
if not separator or not path.strip() or not reason.strip():
|
||||
raise argparse.ArgumentTypeError(
|
||||
"--unreachable-scope must use PATH=CONCRETE_REASON"
|
||||
)
|
||||
return path.strip(), reason.strip()
|
||||
|
||||
|
||||
def missing_root_entries(repo_root: Path, roots: Iterable[str]) -> list[tuple[str, str]]:
|
||||
entries: list[tuple[str, str]] = []
|
||||
for root in roots:
|
||||
base = (repo_root / root).resolve(strict=False)
|
||||
if not base.exists():
|
||||
entries.append(
|
||||
(
|
||||
f"root://{root}",
|
||||
f"Configured scan root is unavailable: {base}",
|
||||
)
|
||||
)
|
||||
return entries
|
||||
|
||||
|
||||
def infer_source(rel: str, payload: Any = None) -> str:
|
||||
text = rel.lower()
|
||||
if isinstance(payload, dict):
|
||||
@@ -507,6 +533,17 @@ def parse_args() -> argparse.Namespace:
|
||||
parser.add_argument("--batch-size", type=int, default=50)
|
||||
parser.add_argument("--resume", action="store_true")
|
||||
parser.add_argument("--roots", nargs="+", default=list(DEFAULT_ROOTS))
|
||||
parser.add_argument(
|
||||
"--unreachable-scope",
|
||||
action="append",
|
||||
default=[],
|
||||
type=parse_unreachable_scope,
|
||||
metavar="PATH=CONCRETE_REASON",
|
||||
help=(
|
||||
"Explicit non-filesystem or externally mounted boundary that was "
|
||||
"verified as unavailable. May be repeated."
|
||||
),
|
||||
)
|
||||
return parser.parse_args()
|
||||
|
||||
|
||||
@@ -518,16 +555,18 @@ def main() -> int:
|
||||
raise SystemExit("--batch-size must be positive")
|
||||
paths = discover_files(repo_root, args.roots, output_dir)
|
||||
inventory_entries = [{"path": relative_path(path, repo_root), "size_bytes": path.stat().st_size, "modified_ns": path.stat().st_mtime_ns} for path in paths]
|
||||
unreachable_items = known_unreachable_items()
|
||||
unavailable = unreachable_items(
|
||||
[*missing_root_entries(repo_root, args.roots), *args.unreachable_scope]
|
||||
)
|
||||
inventory = {
|
||||
"roots": list(args.roots),
|
||||
"excluded_directories": sorted(EXCLUDED_DIRS),
|
||||
"excluded_output_dir": relative_path(output_dir, repo_root),
|
||||
"items": inventory_entries,
|
||||
"unreachable_items": [{"path": item["path"], "reason": item["anomalies"][0]["message"]} for item in unreachable_items],
|
||||
"unreachable_items": [{"path": item["path"], "reason": item["anomalies"][0]["message"]} for item in unavailable],
|
||||
"accessible_item_count": len(inventory_entries),
|
||||
"item_count": len(inventory_entries) + len(unreachable_items),
|
||||
"inventory_hash": canonical_hash({"items": inventory_entries, "unreachable_items": [{"path": item["path"], "reason": item["anomalies"][0]["message"]} for item in unreachable_items]}),
|
||||
"item_count": len(inventory_entries) + len(unavailable),
|
||||
"inventory_hash": canonical_hash({"items": inventory_entries, "unreachable_items": [{"path": item["path"], "reason": item["anomalies"][0]["message"]} for item in unavailable]}),
|
||||
}
|
||||
checkpoint_path = output_dir / "scan-checkpoint.json"
|
||||
checkpoint: dict[str, Any] | None = None
|
||||
@@ -550,7 +589,7 @@ def main() -> int:
|
||||
records[rel] = make_item(path, repo_root)
|
||||
atomic_json(checkpoint_path, {"schema_version": 1, "scanner_version": SCANNER_VERSION, "started_at": started_at, "inventory": inventory, "cursor": min(offset + args.batch_size, len(paths)), "records": sorted(records.values(), key=lambda item: item["path"])})
|
||||
items = [records[relative_path(path, repo_root)] for path in paths if relative_path(path, repo_root) in records]
|
||||
items.extend(unreachable_items)
|
||||
items.extend(unavailable)
|
||||
scan_id = "p3-" + inventory["inventory_hash"][:16]
|
||||
report = report_payload(items, inventory, scan_id, started_at=started_at, completed_at=utc_now(), repo_root=repo_root)
|
||||
output_dir.mkdir(parents=True, exist_ok=True)
|
||||
|
||||
Reference in New Issue
Block a user