131 lines
5.3 KiB
Python
131 lines
5.3 KiB
Python
from __future__ import annotations
|
|
|
|
import json
|
|
import sys
|
|
from datetime import datetime
|
|
from pathlib import Path
|
|
|
|
import pytest
|
|
|
|
ROOT = Path(__file__).resolve().parents[2]
|
|
sys.path.insert(0, str(ROOT))
|
|
sys.path.insert(0, str(ROOT / "backend/src"))
|
|
|
|
from scripts.portfolio_gitea_snapshot import (
|
|
EXECUTABLE_LOCAL_MODEL_REPOSITORIES,
|
|
build_snapshot,
|
|
load_offline_heads,
|
|
load_repository_ids,
|
|
main,
|
|
request_digest,
|
|
)
|
|
|
|
from modelforge_api.domain.portfolio import PortfolioReconcileRequest
|
|
from modelforge_api.services.portfolio_registry import snapshot_digest
|
|
|
|
REQUEST_PATH = ROOT / "docs/product/PORTFOLIO_RECONCILE_REQUEST_2026-09-25.json"
|
|
HEADS_PATH = ROOT / "docs/product/PORTFOLIO_DEFAULT_HEADS_2026-09-25.json"
|
|
RUNTIME_STATUS_PATH = ROOT / "docs/product/PORTFOLIO_RUNTIME_STATUS_2026-09-25.json"
|
|
COMPLETE_REQUEST_PATH = ROOT / "docs/product/PORTFOLIO_RECONCILE_REQUEST_COMPLETE_2026-09-25.json"
|
|
|
|
|
|
def test_review_request_is_partial_secret_free_and_identity_stable() -> None:
|
|
request = json.loads(REQUEST_PATH.read_text(encoding="utf-8"))
|
|
manifest = json.loads(HEADS_PATH.read_text(encoding="utf-8"))
|
|
runtime_status = json.loads(RUNTIME_STATUS_PATH.read_text(encoding="utf-8"))
|
|
validated = PortfolioReconcileRequest.model_validate(request)
|
|
|
|
assert validated.complete is False
|
|
assert manifest["owner_inventory_verified"] is False
|
|
assert manifest["default_heads_stable_across_two_reads"] is True
|
|
assert len(validated.repositories) == manifest["repository_count"] == 69
|
|
assert len({row.external_repository_id for row in validated.repositories}) == 69
|
|
|
|
heads = load_offline_heads(HEADS_PATH)
|
|
for row in validated.repositories:
|
|
current = heads[row.slug.split("/", 1)[1]]
|
|
assert row.default_branch == current["default_branch"]
|
|
assert row.head_sha == current["head_sha"]
|
|
assert row.accept_head_update is False
|
|
assert row.runtime_evidence == []
|
|
assert all(not item.capabilities for item in row.code_evidence)
|
|
|
|
local_model_rows = [row for row in validated.repositories if row.classification == "local_model"]
|
|
assert {row.slug.split("/", 1)[1] for row in local_model_rows} == set(
|
|
EXECUTABLE_LOCAL_MODEL_REPOSITORIES
|
|
)
|
|
project_keys = [row.project_key for row in local_model_rows]
|
|
assert len(project_keys) == len(set(project_keys)) == 12
|
|
|
|
config_marker_rows = [
|
|
row for row in validated.repositories if row.classification == "unknown" and row.code_evidence
|
|
]
|
|
assert {row.slug.split("/", 1)[1] for row in config_marker_rows} == {
|
|
"codex-router",
|
|
"ITWorx_OpenChamber_MCP",
|
|
}
|
|
assert all(row.project_key is None for row in config_marker_rows)
|
|
|
|
assert runtime_status["source_snapshot_id"] == validated.snapshot_id
|
|
runtime_rows = runtime_status["repositories"]
|
|
assert {row["external_repository_id"] for row in runtime_rows} == {
|
|
row.external_repository_id for row in local_model_rows
|
|
}
|
|
assert all(row["runtime_status"] == "UNKNOWN" for row in runtime_rows)
|
|
assert all(row["reason"] == "no_live_request_evidence_collected" for row in runtime_rows)
|
|
|
|
observed_at = datetime.fromisoformat(request["observed_at"])
|
|
rebuilt = build_snapshot(
|
|
[row.model_dump(mode="json") for row in validated.repositories],
|
|
observed_at,
|
|
complete=False,
|
|
expected_count=manifest["repository_count"],
|
|
repository_ids=load_repository_ids(),
|
|
)
|
|
assert rebuilt == request
|
|
assert request_digest(request) == snapshot_digest(validated)
|
|
|
|
encoded = json.dumps(request, sort_keys=True)
|
|
assert "MODELFORGE_GITEA_TOKEN" not in encoded
|
|
assert "Authorization" not in encoded
|
|
assert "OLLAMA_BASE_URL" not in encoded
|
|
|
|
|
|
def test_unverified_owner_inventory_cannot_be_emitted_as_complete(tmp_path: Path) -> None:
|
|
with pytest.raises(SystemExit) as error:
|
|
main(
|
|
[
|
|
"--offline-heads",
|
|
str(HEADS_PATH),
|
|
"--checkout-root",
|
|
str(ROOT),
|
|
"--output",
|
|
str(tmp_path / "must-not-exist.json"),
|
|
]
|
|
)
|
|
|
|
assert error.value.code == 2
|
|
assert not (tmp_path / "must-not-exist.json").exists()
|
|
|
|
|
|
def test_authenticated_complete_request_has_exact_inventory_without_runtime_claims() -> None:
|
|
partial = PortfolioReconcileRequest.model_validate_json(REQUEST_PATH.read_text(encoding="utf-8"))
|
|
complete = PortfolioReconcileRequest.model_validate_json(
|
|
COMPLETE_REQUEST_PATH.read_text(encoding="utf-8")
|
|
)
|
|
|
|
assert complete.complete is True
|
|
assert complete.source_system == "gitea"
|
|
assert len(complete.repositories) == 69
|
|
assert {row.external_repository_id for row in complete.repositories} == {
|
|
row.external_repository_id for row in partial.repositories
|
|
}
|
|
assert {row.slug: row.head_sha for row in complete.repositories} == {
|
|
row.slug: row.head_sha for row in partial.repositories
|
|
}
|
|
assert sum(row.classification == "local_model" for row in complete.repositories) == 12
|
|
assert all(not row.accept_head_update for row in complete.repositories)
|
|
assert all(not row.runtime_evidence for row in complete.repositories)
|
|
assert all(not evidence.capabilities for row in complete.repositories for evidence in row.code_evidence)
|
|
assert request_digest(json.loads(COMPLETE_REQUEST_PATH.read_text(encoding="utf-8"))) == snapshot_digest(complete)
|