feat(observatory): admit canonical recorded replay

This commit is contained in:
DCCONSTRUCTIONS
2026-08-30 19:21:27 +03:00
parent e6a9846167
commit 023151c186
32 changed files with 4069 additions and 342 deletions
+525
View File
@@ -15,6 +15,7 @@ from k1link.device_plugins.xgrids_k1.mqtt.capture import (
iter_capture_frames,
)
from k1link.sessions import (
LabReplayCapability,
LayoutConflictError,
SessionIntegrityError,
SessionNotFoundError,
@@ -823,6 +824,7 @@ def test_lab_instance_is_independent_and_never_deletes_source_evidence(
"method": lab_method(),
},
)
assert binding.replay_capability is None
detail = store.get_session(binding.session_id)
lab_command = store.prepare_replay(binding.session_id)
@@ -879,6 +881,421 @@ def test_lab_instance_publication_is_idempotent_but_provenance_is_immutable(
store.publish_lab_instance(**{**parameters, "config_sha256": "0" * 64})
def test_lab_replay_capability_column_migrates_existing_catalog(
tmp_path: Path,
) -> None:
repository = tmp_path / "repo"
sessions = repository / "sessions"
source = make_legacy_session(sessions, "20260716T205632Z_viewer_live")
data_dir = tmp_path / "data"
initial = SessionStore(repository, data_dir=data_dir)
initial.reconcile_archive(xgrids_k1_archive_source(sessions))
legacy = initial.publish_lab_instance(
session_id="lab-e19-pre-capability",
source_session_id=source.name,
display_name="LAB E19 · pre-capability",
lab_id="LAB E19",
result_kind="e19-legacy",
result_id="e19-legacy-result",
run_created_at_utc="2026-07-23T05:19:43.138Z",
provenance={"method": lab_method()},
)
with sqlite3.connect(initial.database_path) as connection:
connection.execute(
"ALTER TABLE observation_lab_instances DROP COLUMN replay_capability_json"
)
connection.execute(
"ALTER TABLE observation_lab_instances DROP COLUMN include_recorded_media"
)
connection.commit()
migrated = SessionStore(repository, data_dir=data_dir)
with sqlite3.connect(migrated.database_path) as connection:
columns = {
row[1]
for row in connection.execute(
"PRAGMA table_info(observation_lab_instances)"
)
}
assert "replay_capability_json" in columns
assert "include_recorded_media" in columns
assert migrated.get_lab_instance(legacy.session_id).replay_capability is None
def test_migration_types_only_the_exact_rolling_canonical_projection(
tmp_path: Path,
) -> None:
repository = tmp_path / "repo"
sessions = repository / "sessions"
source = make_legacy_session(sessions, "20260828T130511Z_viewer_live")
make_recorded_camera_source(source)
data_dir = tmp_path / "data"
initial = SessionStore(repository, data_dir=data_dir)
initial.reconcile_archive(xgrids_k1_archive_source(sessions))
with sqlite3.connect(initial.database_path) as connection:
connection.execute(
"UPDATE observation_sessions SET archive_id = ? WHERE session_id = ?",
("xgrids-k1.viewer-live.evidence", source.name),
)
connection.commit()
evidence_identity = "a" * 64
capability = LabReplayCapability(
schema_version="missioncore.observation-lab-replay-capability/v1",
kind="canonical-recorded-rerun",
viewer_profile="recorded-session",
timeline="session_time",
activation="explicit",
commands_enabled=False,
)
provenance = {
"schema_version": "missioncore.canonical-recorded-lab-projection/v1",
"evidence_identity_sha256": evidence_identity,
"result_document_sha256": "b" * 64,
"replay_capability": capability.as_dict(),
"authority": {
"commands_enabled": False,
"navigation_or_safety_accepted": False,
"actuation_accepted": False,
},
"method": {
"schema_version": "missioncore.laboratory-method/v1",
"completeness": "legacy-partial",
"execution_class": "ai-inference",
"pipeline_id": "ravnoves004tree-full-eomt-ddrnet-recorded-review/v1",
"components": [
{
"kind": "source",
"name": "sealed full-route LAB result",
"version": "missioncore.lab-v1-vegetation-shadow/v1",
"role": "immutable Session catalog projection",
"identity_sha256": evidence_identity,
}
],
},
}
parameters = {
"session_id": f"lab-v1-vegetation-shadow-{evidence_identity}",
"source_session_id": source.name,
"display_name": "RAVNOVES004TREE · полный маршрут восприятия",
"lab_id": "LAB V1",
"result_kind": "recorded-perception-qualification",
"result_id": f"lab-v1-vegetation-shadow-{evidence_identity}",
"source_result_id": "lab-v1-vegetation-shadow-" + "c" * 64,
"config_sha256": None,
"run_created_at_utc": "2026-08-29T18:05:11.329061+00:00",
"duration_seconds": 718.0,
"replay_capability": capability,
"provenance": provenance,
"include_recorded_media": False,
}
binding = initial.publish_lab_instance(**parameters)
with sqlite3.connect(initial.database_path) as connection:
connection.execute(
"UPDATE observation_sessions SET modalities_json = ?, source_count = ?, "
"total_bytes = ? WHERE session_id = ?",
('["point-cloud","trajectory","video"]', 3, 999_999_999, binding.session_id),
)
connection.execute(
"ALTER TABLE observation_lab_instances DROP COLUMN replay_capability_json"
)
connection.execute(
"ALTER TABLE observation_lab_instances DROP COLUMN include_recorded_media"
)
connection.commit()
migrated = SessionStore(repository, data_dir=data_dir)
assert migrated.get_lab_instance(binding.session_id).replay_capability == capability
migrated_detail = migrated.get_session(binding.session_id)
assert migrated_detail.summary.modalities == ("point-cloud", "trajectory")
assert migrated_detail.summary.source_count == 2
assert all(source.modality != "video" for source in migrated_detail.sources)
assert migrated.list_recent(
scope="laboratory",
include_capability_projections=False,
).items == ()
assert [
item.session_id
for item in migrated.list_recent(
scope="laboratory",
include_capability_projections=True,
).items
] == [binding.session_id]
assert migrated.publish_lab_instance(**parameters).session_id == binding.session_id
def test_migration_rejects_a_non_replayable_canonical_projection(
tmp_path: Path,
) -> None:
repository = tmp_path / "repo"
sessions = repository / "sessions"
source = make_legacy_session(sessions, "20260828T130511Z_viewer_live")
make_recorded_camera_source(source)
data_dir = tmp_path / "data"
initial = SessionStore(repository, data_dir=data_dir)
initial.reconcile_archive(xgrids_k1_archive_source(sessions))
with sqlite3.connect(initial.database_path) as connection:
connection.execute(
"UPDATE observation_sessions SET archive_id = ? WHERE session_id = ?",
("xgrids-k1.viewer-live.evidence", source.name),
)
connection.commit()
capability = LabReplayCapability(
schema_version="missioncore.observation-lab-replay-capability/v1",
kind="canonical-recorded-rerun",
viewer_profile="recorded-session",
timeline="session_time",
activation="explicit",
commands_enabled=False,
)
evidence_identity = "a" * 64
result_id = f"lab-v1-vegetation-shadow-{evidence_identity}"
initial.publish_lab_instance(
session_id=result_id,
source_session_id=source.name,
display_name="RAVNOVES004TREE · полный маршрут восприятия",
lab_id="LAB V1",
result_kind="recorded-perception-qualification",
result_id=result_id,
source_result_id="lab-v1-vegetation-shadow-" + "c" * 64,
run_created_at_utc="2026-08-29T18:05:11.329061+00:00",
duration_seconds=718.0,
include_recorded_media=False,
replay_capability=capability,
provenance={
"schema_version": "missioncore.canonical-recorded-lab-projection/v1",
"evidence_identity_sha256": evidence_identity,
"result_document_sha256": "b" * 64,
"replay_capability": capability.as_dict(),
"authority": {
"commands_enabled": False,
"navigation_or_safety_accepted": False,
"actuation_accepted": False,
},
"method": {
"schema_version": "missioncore.laboratory-method/v1",
"completeness": "legacy-partial",
"execution_class": "ai-inference",
"pipeline_id": "ravnoves004tree-full-eomt-ddrnet-recorded-review/v1",
"components": [
{
"kind": "source",
"name": "sealed full-route LAB result",
"version": "missioncore.lab-v1-vegetation-shadow/v1",
"role": "immutable Session catalog projection",
"identity_sha256": evidence_identity,
}
],
},
},
)
with sqlite3.connect(initial.database_path) as connection:
connection.execute(
"UPDATE observation_sessions SET replayable = 0, "
"primary_replay_artifact_id = NULL, timeline_origin_epoch_ns = NULL, "
"timeline_origin_monotonic_ns = NULL WHERE session_id = ?",
(result_id,),
)
connection.execute(
"ALTER TABLE observation_lab_instances DROP COLUMN replay_capability_json"
)
connection.execute(
"ALTER TABLE observation_lab_instances DROP COLUMN include_recorded_media"
)
connection.commit()
with pytest.raises(SessionIntegrityError, match="LAB"):
SessionStore(repository, data_dir=data_dir)
def test_migration_rejects_boolean_aliases_in_rolling_authority(
tmp_path: Path,
) -> None:
repository = tmp_path / "repo"
data_dir = tmp_path / "data"
store = SessionStore(repository, data_dir=data_dir)
with sqlite3.connect(store.database_path) as connection:
capability = {
"schema_version": "missioncore.observation-lab-replay-capability/v1",
"kind": "canonical-recorded-rerun",
"viewer_profile": "recorded-session",
"timeline": "session_time",
"activation": "explicit",
"commands_enabled": False,
}
evidence_identity = "a" * 64
provenance = {
"schema_version": "missioncore.canonical-recorded-lab-projection/v1",
"evidence_identity_sha256": evidence_identity,
"result_document_sha256": "b" * 64,
"replay_capability": capability,
"authority": {
"commands_enabled": 0,
"navigation_or_safety_accepted": 0,
"actuation_accepted": 0,
},
"method": {
"schema_version": "missioncore.laboratory-method/v1",
"completeness": "legacy-partial",
"execution_class": "ai-inference",
"pipeline_id": "ravnoves004tree-full-eomt-ddrnet-recorded-review/v1",
"components": [
{
"kind": "source",
"name": "sealed full-route LAB result",
"version": "missioncore.lab-v1-vegetation-shadow/v1",
"role": "immutable Session catalog projection",
"identity_sha256": evidence_identity,
}
],
},
}
result_id = f"lab-v1-vegetation-shadow-{evidence_identity}"
connection.execute("PRAGMA foreign_keys = OFF")
connection.execute(
"INSERT INTO observation_sessions "
"(session_id, plugin_id, archive_id, display_name, status, modalities_json, "
"replayable, origin, source_count, total_bytes, allowed_root, session_root, "
"created_at_utc, updated_at_utc) "
"VALUES (?, ?, ?, ?, 'ready', '[]', 0, ?, 0, 0, ?, ?, ?, ?)",
(
result_id,
"fixture.plugin",
"missioncore.lab-instances",
"invalid rolling authority",
"missioncore.lab-instance/v1",
str(repository),
str(repository),
"2026-08-30T00:00:00Z",
"2026-08-30T00:00:00Z",
),
)
connection.execute(
"INSERT INTO observation_lab_instances "
"(session_id, source_session_id, lab_id, result_kind, result_id, "
"source_result_id, config_sha256, run_created_at_utc, published_at_utc, "
"include_recorded_media, replay_capability_json, provenance_json) "
"VALUES (?, ?, 'LAB V1', 'recorded-perception-qualification', ?, ?, "
"NULL, ?, ?, NULL, NULL, ?)",
(
result_id,
"20260828T130511Z_viewer_live",
result_id,
"lab-v1-vegetation-shadow-" + "c" * 64,
"2026-08-29T18:05:11.329061+00:00",
"2026-08-30T00:00:00Z",
json.dumps(provenance, sort_keys=True),
),
)
connection.commit()
migrated = SessionStore(repository, data_dir=data_dir)
with sqlite3.connect(migrated.database_path) as connection:
row = connection.execute(
"SELECT replay_capability_json, include_recorded_media "
"FROM observation_lab_instances WHERE session_id = ?",
("lab-v1-vegetation-shadow-" + "a" * 64,),
).fetchone()
assert row == (None, None)
def test_lab_instance_persists_typed_explicit_recorded_replay_capability(
tmp_path: Path,
) -> None:
repository = tmp_path / "repo"
sessions = repository / "sessions"
source = make_legacy_session(sessions, "20260716T205632Z_viewer_live")
store = SessionStore(repository, data_dir=tmp_path / "data")
store.reconcile_archive(xgrids_k1_archive_source(sessions))
capability = LabReplayCapability(
schema_version="missioncore.observation-lab-replay-capability/v1",
kind="canonical-recorded-rerun",
viewer_profile="recorded-session",
timeline="session_time",
activation="explicit",
commands_enabled=False,
)
binding = store.publish_lab_instance(
session_id="lab-recorded-replay",
source_session_id=source.name,
display_name="LAB V1 · recorded replay",
lab_id="LAB V1",
result_kind="recorded-perception-qualification",
result_id="lab-v1-vegetation-shadow-" + "a" * 64,
source_result_id="lab-v1-vegetation-shadow-" + "b" * 64,
run_created_at_utc="2026-08-29T18:05:11.329061+00:00",
replay_capability=capability,
provenance={
"replay_capability": capability.as_dict(),
"method": lab_method(),
},
)
assert binding.replay_capability == capability
assert "replay_capability" not in binding.as_dict()
assert binding.as_dict()["provenance"]["replay_capability"] == capability.as_dict()
assert store.get_lab_instance(binding.session_id) == binding
with sqlite3.connect(store.database_path) as connection:
connection.execute(
"UPDATE observation_lab_instances SET replay_capability_json = ? "
"WHERE session_id = ?",
('{"kind":"unknown"}', binding.session_id),
)
connection.commit()
with pytest.raises(SessionIntegrityError, match="replay capability"):
store.get_lab_instance(binding.session_id)
@pytest.mark.parametrize("value", [0, 1, None, True])
def test_lab_replay_capability_rejects_non_literal_false(value: object) -> None:
with pytest.raises(ValueError, match="replay capability"):
LabReplayCapability(
schema_version="missioncore.observation-lab-replay-capability/v1",
kind="canonical-recorded-rerun",
viewer_profile="recorded-session",
timeline="session_time",
activation="explicit",
commands_enabled=value, # type: ignore[arg-type]
)
def test_lab_instance_rejects_boolean_alias_in_capability_provenance(
tmp_path: Path,
) -> None:
repository = tmp_path / "repo"
sessions = repository / "sessions"
source = make_legacy_session(sessions, "20260716T205632Z_viewer_live")
store = SessionStore(repository, data_dir=tmp_path / "data")
store.reconcile_archive(xgrids_k1_archive_source(sessions))
capability = LabReplayCapability(
schema_version="missioncore.observation-lab-replay-capability/v1",
kind="canonical-recorded-rerun",
viewer_profile="recorded-session",
timeline="session_time",
activation="explicit",
commands_enabled=False,
)
aliased = {**capability.as_dict(), "commands_enabled": 0}
with pytest.raises(ValueError, match="exactly match provenance"):
store.publish_lab_instance(
session_id="lab-recorded-replay-alias",
source_session_id=source.name,
display_name="LAB V1 · recorded replay alias",
lab_id="LAB V1",
result_kind="recorded-perception-qualification",
result_id="lab-v1-vegetation-shadow-" + "a" * 64,
run_created_at_utc="2026-08-29T18:05:11.329061+00:00",
replay_capability=capability,
provenance={
"replay_capability": aliased,
"method": lab_method(),
},
)
def test_lab_instance_rejects_publication_without_a_method_manifest(
tmp_path: Path,
) -> None:
@@ -933,6 +1350,114 @@ def test_bounded_lab_instance_excludes_unbounded_recorded_media(
assert store.prepare_replay(binding.session_id).primary_artifact.path.is_file()
def test_capability_projection_summary_is_exact_and_idempotently_repairable(
tmp_path: Path,
) -> None:
repository = tmp_path / "repo"
sessions = repository / "sessions"
source = make_legacy_session(sessions, "20260716T205632Z_viewer_live")
make_recorded_camera_source(source)
store = SessionStore(repository, data_dir=tmp_path / "data")
store.reconcile_archive(xgrids_k1_archive_source(sessions))
_source_detail, source_snapshot_sha256 = (
store.get_session_with_catalog_snapshot(source.name)
)
capability = LabReplayCapability(
schema_version="missioncore.observation-lab-replay-capability/v1",
kind="canonical-recorded-rerun",
viewer_profile="recorded-session",
timeline="session_time",
activation="explicit",
commands_enabled=False,
)
parameters = {
"session_id": "lab-recorded-bounded",
"source_session_id": source.name,
"display_name": "LAB V1 · bounded recorded review",
"lab_id": "LAB V1",
"result_kind": "recorded-perception-qualification",
"result_id": "lab-v1-vegetation-shadow-" + "1" * 64,
"source_result_id": "lab-v1-vegetation-shadow-" + "2" * 64,
"run_created_at_utc": "2026-08-29T18:05:11.329061+00:00",
"duration_seconds": 59.962,
"include_recorded_media": False,
"expected_source_catalog_sha256": source_snapshot_sha256,
"replay_capability": capability,
"provenance": {
"replay_capability": capability.as_dict(),
"method": lab_method(),
},
}
binding = store.publish_lab_instance(**parameters)
detail = store.get_session(binding.session_id)
assert detail.summary.modalities == ("point-cloud", "trajectory")
assert detail.summary.source_count == len(detail.sources) == 2
referenced_artifacts = {item.artifact_id for item in detail.sources}
assert detail.summary.total_bytes == sum(
artifact.byte_length
for artifact in detail.artifacts
if artifact.artifact_id in referenced_artifacts
)
with sqlite3.connect(store.database_path) as connection:
connection.execute(
"UPDATE observation_sessions SET modalities_json = ?, source_count = ?, "
"total_bytes = ? WHERE session_id = ?",
('["point-cloud","trajectory","video"]', 3, 999_999_999, binding.session_id),
)
connection.commit()
assert store.publish_lab_instance(**parameters) == binding
repaired = store.get_session(binding.session_id)
assert repaired.summary.modalities == ("point-cloud", "trajectory")
assert repaired.summary.source_count == 2
assert repaired.summary.total_bytes == detail.summary.total_bytes
with pytest.raises(SessionIntegrityError, match="recorded-media policy"):
store.publish_lab_instance(**{**parameters, "include_recorded_media": True})
with sqlite3.connect(store.database_path) as connection:
connection.execute(
"UPDATE observation_session_artifacts SET sha256 = ? "
"WHERE session_id = ? AND artifact_id = 'raw-transport-primary'",
("0" * 64, binding.session_id),
)
connection.commit()
with pytest.raises(SessionIntegrityError, match="source snapshot"):
store.publish_lab_instance(**parameters)
def test_lab_publication_rejects_a_source_changed_after_snapshot(
tmp_path: Path,
) -> None:
repository = tmp_path / "repo"
sessions = repository / "sessions"
source = make_legacy_session(sessions, "20260716T205632Z_viewer_live")
store = SessionStore(repository, data_dir=tmp_path / "data")
store.reconcile_archive(xgrids_k1_archive_source(sessions))
_detail, snapshot_sha256 = store.get_session_with_catalog_snapshot(source.name)
with sqlite3.connect(store.database_path) as connection:
connection.execute(
"UPDATE observation_session_artifacts SET byte_length = byte_length + 1 "
"WHERE session_id = ? AND artifact_id = 'raw-transport-primary'",
(source.name,),
)
connection.commit()
with pytest.raises(SessionIntegrityError, match="changed after admission"):
store.publish_lab_instance(
session_id="lab-source-snapshot-race",
source_session_id=source.name,
display_name="LAB E21 · source snapshot race",
lab_id="LAB E21",
result_kind="source-snapshot-race",
result_id="source-snapshot-race-result",
run_created_at_utc="2026-08-29T18:05:11.329061+00:00",
provenance={"method": lab_method()},
expected_source_catalog_sha256=snapshot_sha256,
)
assert store.get_lab_instance("lab-source-snapshot-race") is None
def test_delete_session_rejects_a_catalog_target_outside_its_allowed_root(
tmp_path: Path,
) -> None: