vela-state 0.77.0__tar.gz
This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
- vela_state-0.77.0/PKG-INFO +146 -0
- vela_state-0.77.0/README.md +114 -0
- vela_state-0.77.0/pyproject.toml +61 -0
- vela_state-0.77.0/setup.cfg +4 -0
- vela_state-0.77.0/tests/test_loader_frontiers_v2.py +96 -0
- vela_state-0.77.0/vela_loader.py +420 -0
- vela_state-0.77.0/vela_reducer.py +978 -0
- vela_state-0.77.0/vela_state.egg-info/PKG-INFO +146 -0
- vela_state-0.77.0/vela_state.egg-info/SOURCES.txt +11 -0
- vela_state-0.77.0/vela_state.egg-info/dependency_links.txt +1 -0
- vela_state-0.77.0/vela_state.egg-info/requires.txt +5 -0
- vela_state-0.77.0/vela_state.egg-info/top_level.txt +3 -0
- vela_state-0.77.0/vela_verify.py +296 -0
|
@@ -0,0 +1,146 @@
|
|
|
1
|
+
Metadata-Version: 2.4
|
|
2
|
+
Name: vela-state
|
|
3
|
+
Version: 0.77.0
|
|
4
|
+
Summary: Python loader, reducer, and verifier for Vela scientific frontier state. Cross-impl mirror of the Rust substrate.
|
|
5
|
+
Author-email: Will Blair <william.blair0708@gmail.com>
|
|
6
|
+
License: Apache-2.0 OR MIT
|
|
7
|
+
Project-URL: Homepage, https://github.com/vela-science/vela
|
|
8
|
+
Project-URL: Repository, https://github.com/vela-science/vela
|
|
9
|
+
Project-URL: Documentation, https://github.com/vela-science/vela/blob/main/docs/PROTOCOL.md
|
|
10
|
+
Project-URL: Issues, https://github.com/vela-science/vela/issues
|
|
11
|
+
Project-URL: Changelog, https://github.com/vela-science/vela/releases
|
|
12
|
+
Keywords: science,version-control,frontier,carina,vela,reproducibility,provenance,ai-attribution
|
|
13
|
+
Classifier: Development Status :: 4 - Beta
|
|
14
|
+
Classifier: Intended Audience :: Science/Research
|
|
15
|
+
Classifier: License :: OSI Approved :: Apache Software License
|
|
16
|
+
Classifier: License :: OSI Approved :: MIT License
|
|
17
|
+
Classifier: Operating System :: OS Independent
|
|
18
|
+
Classifier: Programming Language :: Python :: 3
|
|
19
|
+
Classifier: Programming Language :: Python :: 3 :: Only
|
|
20
|
+
Classifier: Programming Language :: Python :: 3.10
|
|
21
|
+
Classifier: Programming Language :: Python :: 3.11
|
|
22
|
+
Classifier: Programming Language :: Python :: 3.12
|
|
23
|
+
Classifier: Programming Language :: Python :: 3.13
|
|
24
|
+
Classifier: Topic :: Scientific/Engineering
|
|
25
|
+
Classifier: Topic :: Scientific/Engineering :: Information Analysis
|
|
26
|
+
Requires-Python: >=3.10
|
|
27
|
+
Description-Content-Type: text/markdown
|
|
28
|
+
Requires-Dist: pynacl>=1.5
|
|
29
|
+
Provides-Extra: dev
|
|
30
|
+
Requires-Dist: pytest>=7; extra == "dev"
|
|
31
|
+
Requires-Dist: ruff>=0.6; extra == "dev"
|
|
32
|
+
|
|
33
|
+
# Vela Python client
|
|
34
|
+
|
|
35
|
+
Cross-implementation reducer + loader for the Vela protocol. The
|
|
36
|
+
authoritative implementation is the Rust workspace under
|
|
37
|
+
`crates/vela-protocol/`; this Python module mirrors the kernel
|
|
38
|
+
behavior so a third-party Python tool can replay a frontier's
|
|
39
|
+
event log and load a split-repo without depending on the Rust
|
|
40
|
+
binary.
|
|
41
|
+
|
|
42
|
+
The cross-impl invariant is: given the same canonical event log
|
|
43
|
+
and the same Carina kernel digest, the Rust reducer and the
|
|
44
|
+
Python reducer produce byte-equivalent finding-state digests.
|
|
45
|
+
This is the load-bearing property that lets Vela claim "the
|
|
46
|
+
protocol is implementation-portable."
|
|
47
|
+
|
|
48
|
+
## What's here
|
|
49
|
+
|
|
50
|
+
- `vela_reducer.py`: the reducer dispatch. Accepts a canonical
|
|
51
|
+
`StateEvent` JSON dict + a Project state dict, applies the
|
|
52
|
+
reducer arm for the event's `kind`, mutates state in place.
|
|
53
|
+
Mirrors `crates/vela-protocol/src/reducer.rs::apply_event`.
|
|
54
|
+
|
|
55
|
+
- `vela_loader.py`: the split-repo loader. Reads
|
|
56
|
+
`.vela/findings/`, `.vela/events/`, `.vela/proposals/`, plus
|
|
57
|
+
`frontier.yaml`, populates `project.dependencies` from the v0.59
|
|
58
|
+
`frontiers_v2` schema, replays events through the reducer.
|
|
59
|
+
Mirrors `crates/vela-protocol/src/repo.rs::load_vela_repo`.
|
|
60
|
+
Yaml is parsed via `pyyaml` if present; otherwise a
|
|
61
|
+
hand-rolled parser narrow to the manifest's exact shape.
|
|
62
|
+
|
|
63
|
+
- `tests/test_loader_frontiers_v2.py`: integration test
|
|
64
|
+
asserting the loader produces the same dependency state +
|
|
65
|
+
finding state the Rust loader does on a real frontier
|
|
66
|
+
(`projects/early-ad-biomarker-calibration`).
|
|
67
|
+
|
|
68
|
+
## Usage
|
|
69
|
+
|
|
70
|
+
```python
|
|
71
|
+
from vela_loader import load_frontier_repo
|
|
72
|
+
|
|
73
|
+
project = load_frontier_repo("/path/to/projects/early-ad-biomarker-calibration")
|
|
74
|
+
|
|
75
|
+
# project is a dict with keys:
|
|
76
|
+
# project: { name, description, dependencies }
|
|
77
|
+
# frontier_id, findings, events, proposals
|
|
78
|
+
# review_events, confidence_updates, manifest
|
|
79
|
+
# negative_results, trajectories, artifacts, evidence_atoms
|
|
80
|
+
|
|
81
|
+
print(f"frontier: {project['project']['name']} ({project['frontier_id']})")
|
|
82
|
+
print(f"findings: {len(project['findings'])}")
|
|
83
|
+
print(f"events: {len(project['events'])}")
|
|
84
|
+
print(f"deps: {len(project['project']['dependencies'])}")
|
|
85
|
+
```
|
|
86
|
+
|
|
87
|
+
## What's NOT here (honest gaps)
|
|
88
|
+
|
|
89
|
+
The Python loader does not currently rehydrate every field the
|
|
90
|
+
Rust loader does. Specifically missing:
|
|
91
|
+
|
|
92
|
+
- `vela.lock` (lockfile parsing).
|
|
93
|
+
- `actors.json`, `peers.json` (federation surfaces).
|
|
94
|
+
- `proof-state.json`.
|
|
95
|
+
- `signatures/`, `replications/`, `datasets/`, `code-artifacts/`,
|
|
96
|
+
`predictions/`, `resolutions/`, `artifacts/`.
|
|
97
|
+
- The v0.55 trajectories+nulls materialization.
|
|
98
|
+
- The v0.56 evidence-atom locator materialization.
|
|
99
|
+
- `.vela/links/manifest.json` redistribution.
|
|
100
|
+
- `project::recompute_stats`.
|
|
101
|
+
|
|
102
|
+
These are real gaps. The cross-impl invariant currently holds at
|
|
103
|
+
the finding-state-digest level only; full Project parity is a
|
|
104
|
+
follow-on cycle. Anyone implementing a third Vela language
|
|
105
|
+
binding should target the same subset first and document their
|
|
106
|
+
gaps as honestly.
|
|
107
|
+
|
|
108
|
+
## Running the test
|
|
109
|
+
|
|
110
|
+
The test runs without pytest if needed:
|
|
111
|
+
|
|
112
|
+
```bash
|
|
113
|
+
python3 clients/python/tests/test_loader_frontiers_v2.py
|
|
114
|
+
```
|
|
115
|
+
|
|
116
|
+
Or with pytest:
|
|
117
|
+
|
|
118
|
+
```bash
|
|
119
|
+
python3 -m pytest clients/python/tests/
|
|
120
|
+
```
|
|
121
|
+
|
|
122
|
+
## Cross-impl correctness
|
|
123
|
+
|
|
124
|
+
The fixture harness is Rust-side at
|
|
125
|
+
`crates/vela-protocol/tests/cross_impl_reducer_fixtures.rs`.
|
|
126
|
+
Each fixture builder generates an event log; the test exports
|
|
127
|
+
the same logs to JSON for the Python reducer to replay; the
|
|
128
|
+
finding-state digests must match byte-for-byte. The test file's
|
|
129
|
+
`fixture_coverage_includes_every_reducer_arm` assertion
|
|
130
|
+
verifies every kind in `REDUCER_MUTATION_KINDS` has a fixture
|
|
131
|
+
builder. New kinds added to the Rust reducer must be reflected
|
|
132
|
+
in this Python module (a no-op match arm is sufficient if the
|
|
133
|
+
kind doesn't mutate finding state) and in the fixture builders.
|
|
134
|
+
|
|
135
|
+
## Doctrine
|
|
136
|
+
|
|
137
|
+
The Python loader is a mirror, not the spec. When the Rust and
|
|
138
|
+
Python reducers disagree, the Rust implementation is
|
|
139
|
+
authoritative; the Python side is the bug. The cross-impl test
|
|
140
|
+
catches the disagreement; the spec at `docs/PROTOCOL.md`
|
|
141
|
+
documents the canonical behavior.
|
|
142
|
+
|
|
143
|
+
No silent edits. No event-log mutation. No version-skew
|
|
144
|
+
silently glossed; if a new kind appears in the event log that
|
|
145
|
+
the Python dispatch doesn't know, the loader raises rather
|
|
146
|
+
than silently dropping the event.
|
|
@@ -0,0 +1,114 @@
|
|
|
1
|
+
# Vela Python client
|
|
2
|
+
|
|
3
|
+
Cross-implementation reducer + loader for the Vela protocol. The
|
|
4
|
+
authoritative implementation is the Rust workspace under
|
|
5
|
+
`crates/vela-protocol/`; this Python module mirrors the kernel
|
|
6
|
+
behavior so a third-party Python tool can replay a frontier's
|
|
7
|
+
event log and load a split-repo without depending on the Rust
|
|
8
|
+
binary.
|
|
9
|
+
|
|
10
|
+
The cross-impl invariant is: given the same canonical event log
|
|
11
|
+
and the same Carina kernel digest, the Rust reducer and the
|
|
12
|
+
Python reducer produce byte-equivalent finding-state digests.
|
|
13
|
+
This is the load-bearing property that lets Vela claim "the
|
|
14
|
+
protocol is implementation-portable."
|
|
15
|
+
|
|
16
|
+
## What's here
|
|
17
|
+
|
|
18
|
+
- `vela_reducer.py`: the reducer dispatch. Accepts a canonical
|
|
19
|
+
`StateEvent` JSON dict + a Project state dict, applies the
|
|
20
|
+
reducer arm for the event's `kind`, mutates state in place.
|
|
21
|
+
Mirrors `crates/vela-protocol/src/reducer.rs::apply_event`.
|
|
22
|
+
|
|
23
|
+
- `vela_loader.py`: the split-repo loader. Reads
|
|
24
|
+
`.vela/findings/`, `.vela/events/`, `.vela/proposals/`, plus
|
|
25
|
+
`frontier.yaml`, populates `project.dependencies` from the v0.59
|
|
26
|
+
`frontiers_v2` schema, replays events through the reducer.
|
|
27
|
+
Mirrors `crates/vela-protocol/src/repo.rs::load_vela_repo`.
|
|
28
|
+
Yaml is parsed via `pyyaml` if present; otherwise a
|
|
29
|
+
hand-rolled parser narrow to the manifest's exact shape.
|
|
30
|
+
|
|
31
|
+
- `tests/test_loader_frontiers_v2.py`: integration test
|
|
32
|
+
asserting the loader produces the same dependency state +
|
|
33
|
+
finding state the Rust loader does on a real frontier
|
|
34
|
+
(`projects/early-ad-biomarker-calibration`).
|
|
35
|
+
|
|
36
|
+
## Usage
|
|
37
|
+
|
|
38
|
+
```python
|
|
39
|
+
from vela_loader import load_frontier_repo
|
|
40
|
+
|
|
41
|
+
project = load_frontier_repo("/path/to/projects/early-ad-biomarker-calibration")
|
|
42
|
+
|
|
43
|
+
# project is a dict with keys:
|
|
44
|
+
# project: { name, description, dependencies }
|
|
45
|
+
# frontier_id, findings, events, proposals
|
|
46
|
+
# review_events, confidence_updates, manifest
|
|
47
|
+
# negative_results, trajectories, artifacts, evidence_atoms
|
|
48
|
+
|
|
49
|
+
print(f"frontier: {project['project']['name']} ({project['frontier_id']})")
|
|
50
|
+
print(f"findings: {len(project['findings'])}")
|
|
51
|
+
print(f"events: {len(project['events'])}")
|
|
52
|
+
print(f"deps: {len(project['project']['dependencies'])}")
|
|
53
|
+
```
|
|
54
|
+
|
|
55
|
+
## What's NOT here (honest gaps)
|
|
56
|
+
|
|
57
|
+
The Python loader does not currently rehydrate every field the
|
|
58
|
+
Rust loader does. Specifically missing:
|
|
59
|
+
|
|
60
|
+
- `vela.lock` (lockfile parsing).
|
|
61
|
+
- `actors.json`, `peers.json` (federation surfaces).
|
|
62
|
+
- `proof-state.json`.
|
|
63
|
+
- `signatures/`, `replications/`, `datasets/`, `code-artifacts/`,
|
|
64
|
+
`predictions/`, `resolutions/`, `artifacts/`.
|
|
65
|
+
- The v0.55 trajectories+nulls materialization.
|
|
66
|
+
- The v0.56 evidence-atom locator materialization.
|
|
67
|
+
- `.vela/links/manifest.json` redistribution.
|
|
68
|
+
- `project::recompute_stats`.
|
|
69
|
+
|
|
70
|
+
These are real gaps. The cross-impl invariant currently holds at
|
|
71
|
+
the finding-state-digest level only; full Project parity is a
|
|
72
|
+
follow-on cycle. Anyone implementing a third Vela language
|
|
73
|
+
binding should target the same subset first and document their
|
|
74
|
+
gaps as honestly.
|
|
75
|
+
|
|
76
|
+
## Running the test
|
|
77
|
+
|
|
78
|
+
The test runs without pytest if needed:
|
|
79
|
+
|
|
80
|
+
```bash
|
|
81
|
+
python3 clients/python/tests/test_loader_frontiers_v2.py
|
|
82
|
+
```
|
|
83
|
+
|
|
84
|
+
Or with pytest:
|
|
85
|
+
|
|
86
|
+
```bash
|
|
87
|
+
python3 -m pytest clients/python/tests/
|
|
88
|
+
```
|
|
89
|
+
|
|
90
|
+
## Cross-impl correctness
|
|
91
|
+
|
|
92
|
+
The fixture harness is Rust-side at
|
|
93
|
+
`crates/vela-protocol/tests/cross_impl_reducer_fixtures.rs`.
|
|
94
|
+
Each fixture builder generates an event log; the test exports
|
|
95
|
+
the same logs to JSON for the Python reducer to replay; the
|
|
96
|
+
finding-state digests must match byte-for-byte. The test file's
|
|
97
|
+
`fixture_coverage_includes_every_reducer_arm` assertion
|
|
98
|
+
verifies every kind in `REDUCER_MUTATION_KINDS` has a fixture
|
|
99
|
+
builder. New kinds added to the Rust reducer must be reflected
|
|
100
|
+
in this Python module (a no-op match arm is sufficient if the
|
|
101
|
+
kind doesn't mutate finding state) and in the fixture builders.
|
|
102
|
+
|
|
103
|
+
## Doctrine
|
|
104
|
+
|
|
105
|
+
The Python loader is a mirror, not the spec. When the Rust and
|
|
106
|
+
Python reducers disagree, the Rust implementation is
|
|
107
|
+
authoritative; the Python side is the bug. The cross-impl test
|
|
108
|
+
catches the disagreement; the spec at `docs/PROTOCOL.md`
|
|
109
|
+
documents the canonical behavior.
|
|
110
|
+
|
|
111
|
+
No silent edits. No event-log mutation. No version-skew
|
|
112
|
+
silently glossed; if a new kind appears in the event log that
|
|
113
|
+
the Python dispatch doesn't know, the loader raises rather
|
|
114
|
+
than silently dropping the event.
|
|
@@ -0,0 +1,61 @@
|
|
|
1
|
+
[build-system]
|
|
2
|
+
requires = ["setuptools>=68", "wheel"]
|
|
3
|
+
build-backend = "setuptools.build_meta"
|
|
4
|
+
|
|
5
|
+
[project]
|
|
6
|
+
name = "vela-state"
|
|
7
|
+
version = "0.77.0"
|
|
8
|
+
description = "Python loader, reducer, and verifier for Vela scientific frontier state. Cross-impl mirror of the Rust substrate."
|
|
9
|
+
readme = "README.md"
|
|
10
|
+
requires-python = ">=3.10"
|
|
11
|
+
license = { text = "Apache-2.0 OR MIT" }
|
|
12
|
+
authors = [
|
|
13
|
+
{ name = "Will Blair", email = "william.blair0708@gmail.com" }
|
|
14
|
+
]
|
|
15
|
+
keywords = [
|
|
16
|
+
"science",
|
|
17
|
+
"version-control",
|
|
18
|
+
"frontier",
|
|
19
|
+
"carina",
|
|
20
|
+
"vela",
|
|
21
|
+
"reproducibility",
|
|
22
|
+
"provenance",
|
|
23
|
+
"ai-attribution",
|
|
24
|
+
]
|
|
25
|
+
classifiers = [
|
|
26
|
+
"Development Status :: 4 - Beta",
|
|
27
|
+
"Intended Audience :: Science/Research",
|
|
28
|
+
"License :: OSI Approved :: Apache Software License",
|
|
29
|
+
"License :: OSI Approved :: MIT License",
|
|
30
|
+
"Operating System :: OS Independent",
|
|
31
|
+
"Programming Language :: Python :: 3",
|
|
32
|
+
"Programming Language :: Python :: 3 :: Only",
|
|
33
|
+
"Programming Language :: Python :: 3.10",
|
|
34
|
+
"Programming Language :: Python :: 3.11",
|
|
35
|
+
"Programming Language :: Python :: 3.12",
|
|
36
|
+
"Programming Language :: Python :: 3.13",
|
|
37
|
+
"Topic :: Scientific/Engineering",
|
|
38
|
+
"Topic :: Scientific/Engineering :: Information Analysis",
|
|
39
|
+
]
|
|
40
|
+
dependencies = [
|
|
41
|
+
"pynacl>=1.5",
|
|
42
|
+
]
|
|
43
|
+
|
|
44
|
+
[project.urls]
|
|
45
|
+
Homepage = "https://github.com/vela-science/vela"
|
|
46
|
+
Repository = "https://github.com/vela-science/vela"
|
|
47
|
+
Documentation = "https://github.com/vela-science/vela/blob/main/docs/PROTOCOL.md"
|
|
48
|
+
Issues = "https://github.com/vela-science/vela/issues"
|
|
49
|
+
Changelog = "https://github.com/vela-science/vela/releases"
|
|
50
|
+
|
|
51
|
+
[project.optional-dependencies]
|
|
52
|
+
dev = [
|
|
53
|
+
"pytest>=7",
|
|
54
|
+
"ruff>=0.6",
|
|
55
|
+
]
|
|
56
|
+
|
|
57
|
+
[tool.setuptools]
|
|
58
|
+
py-modules = ["vela_loader", "vela_reducer", "vela_verify"]
|
|
59
|
+
|
|
60
|
+
[tool.setuptools.package-data]
|
|
61
|
+
"*" = ["*.md"]
|
|
@@ -0,0 +1,96 @@
|
|
|
1
|
+
#!/usr/bin/env python3
|
|
2
|
+
# Pairs with W1.7 (v0.66): the Python loader at
|
|
3
|
+
# `clients/python/vela_loader.py` must rehydrate
|
|
4
|
+
# `manifest.dependencies.frontiers_v2` into `project.dependencies`,
|
|
5
|
+
# exactly the way `crates/vela-protocol/src/repo.rs::load_vela_repo`
|
|
6
|
+
# does on the Rust side. Without it, a Python replay of the event log
|
|
7
|
+
# cannot resolve cross-frontier link references.
|
|
8
|
+
#
|
|
9
|
+
# This test loads the early-AD biomarker calibration project, which in
|
|
10
|
+
# v0.59 declared an anti-amyloid bridge dependency
|
|
11
|
+
# (vfr_5076e7b3ff8e6b0f), and confirms the Python loader sees it. It
|
|
12
|
+
# also confirms the event log replays cleanly (the v0.65 + v0.66 review
|
|
13
|
+
# verdicts are accepted findings).
|
|
14
|
+
|
|
15
|
+
from __future__ import annotations
|
|
16
|
+
|
|
17
|
+
import os
|
|
18
|
+
import sys
|
|
19
|
+
from pathlib import Path
|
|
20
|
+
|
|
21
|
+
# Allow running both as `python3 -m pytest …` from repo root and as
|
|
22
|
+
# `python3 tests/test_loader_frontiers_v2.py` from inside the package.
|
|
23
|
+
_HERE = Path(__file__).resolve().parent
|
|
24
|
+
_PACKAGE_DIR = _HERE.parent
|
|
25
|
+
if str(_PACKAGE_DIR) not in sys.path:
|
|
26
|
+
sys.path.insert(0, str(_PACKAGE_DIR))
|
|
27
|
+
|
|
28
|
+
from vela_loader import load_frontier_repo # noqa: E402
|
|
29
|
+
|
|
30
|
+
_REPO_ROOT = _PACKAGE_DIR.parent.parent
|
|
31
|
+
_PROJECT = _REPO_ROOT / "projects" / "early-ad-biomarker-calibration"
|
|
32
|
+
|
|
33
|
+
|
|
34
|
+
def test_dependencies_rehydrated_from_yaml() -> None:
|
|
35
|
+
repo = load_frontier_repo(str(_PROJECT))
|
|
36
|
+
deps = repo["project"]["dependencies"]
|
|
37
|
+
assert isinstance(deps, list) and len(deps) >= 1, (
|
|
38
|
+
"expected at least one entry under project.dependencies, got "
|
|
39
|
+
f"{deps!r}"
|
|
40
|
+
)
|
|
41
|
+
vfr_ids = {d.get("vfr_id") for d in deps}
|
|
42
|
+
assert "vfr_5076e7b3ff8e6b0f" in vfr_ids, (
|
|
43
|
+
"anti-amyloid bridge (vfr_5076e7b3ff8e6b0f) not rehydrated from "
|
|
44
|
+
f"frontier.yaml; saw {sorted(vfr_ids)!r}"
|
|
45
|
+
)
|
|
46
|
+
|
|
47
|
+
bridge = next(d for d in deps if d.get("vfr_id") == "vfr_5076e7b3ff8e6b0f")
|
|
48
|
+
assert bridge.get("source") == "vela.hub"
|
|
49
|
+
assert bridge.get("name") == "anti-amyloid-translation"
|
|
50
|
+
assert bridge.get("locator"), "bridge dep missing locator"
|
|
51
|
+
assert bridge.get("pinned_snapshot_hash"), "bridge dep missing pinned_snapshot_hash"
|
|
52
|
+
|
|
53
|
+
|
|
54
|
+
def test_events_and_accepted_findings() -> None:
|
|
55
|
+
repo = load_frontier_repo(str(_PROJECT))
|
|
56
|
+
events = repo["events"]
|
|
57
|
+
assert isinstance(events, list) and len(events) > 0, (
|
|
58
|
+
"expected non-empty events list after split-repo load"
|
|
59
|
+
)
|
|
60
|
+
|
|
61
|
+
accepted = [
|
|
62
|
+
f
|
|
63
|
+
for f in repo["findings"]
|
|
64
|
+
if (f.get("flags") or {}).get("review_state") == "accepted"
|
|
65
|
+
]
|
|
66
|
+
assert len(accepted) >= 4, (
|
|
67
|
+
f"expected at least 4 accepted findings after replay, got "
|
|
68
|
+
f"{len(accepted)} (review_states: "
|
|
69
|
+
f"{[ (f.get('flags') or {}).get('review_state') for f in repo['findings']]})"
|
|
70
|
+
)
|
|
71
|
+
|
|
72
|
+
|
|
73
|
+
def test_frontier_id_loaded() -> None:
|
|
74
|
+
repo = load_frontier_repo(str(_PROJECT))
|
|
75
|
+
assert repo["frontier_id"] == "vfr_a22c9022674a2304"
|
|
76
|
+
|
|
77
|
+
|
|
78
|
+
if __name__ == "__main__":
|
|
79
|
+
# Lightweight runner so `python3 test_loader_frontiers_v2.py` works
|
|
80
|
+
# even if pytest is unavailable in the local env.
|
|
81
|
+
failures = 0
|
|
82
|
+
for fn in (
|
|
83
|
+
test_dependencies_rehydrated_from_yaml,
|
|
84
|
+
test_events_and_accepted_findings,
|
|
85
|
+
test_frontier_id_loaded,
|
|
86
|
+
):
|
|
87
|
+
try:
|
|
88
|
+
fn()
|
|
89
|
+
print(f"ok · {fn.__name__}")
|
|
90
|
+
except AssertionError as e:
|
|
91
|
+
failures += 1
|
|
92
|
+
print(f"FAIL · {fn.__name__}: {e}")
|
|
93
|
+
except Exception as e:
|
|
94
|
+
failures += 1
|
|
95
|
+
print(f"ERR · {fn.__name__}: {type(e).__name__}: {e}")
|
|
96
|
+
raise SystemExit(0 if failures == 0 else 1)
|