Repository navigation
Release 0.9.0: CLI verification, integrity and recovery foundation - #31
Merged
Merged
Conversation
There was a problem hiding this comment.
🟡 Changes recommended
Unresolved critical and moderate findings affect CI, bootstrap integrity, resume behavior, FHIR attribution, and model preflight.
Get a fresh assessment by requesting another Copilot review.
Pull request overview
Establishes shared production verification, artifact integrity checks, and installed-wheel CLI coverage for TrialMatchAI.
Changes:
- Adds reusable CI/release verification and exact-wheel smoke tests.
- Adds SHA-256 manifests, strict bootstrap provenance, and a synthetic CLI demo.
- Updates FHIR attribution, model preflight, packaging, documentation, and tests.
Final findings:
- Critical (1 vote): Create
test-resultsbefore pytest runs. - Moderate (1 vote): Retry or remove invalid cached bootstrap archives.
- Critical (2 votes): Replace stale extraction trees on strict bootstrap resets.
- Critical (1 vote): Reject symlinked or non-regular bootstrap markers.
- Moderate (1 vote): Require both ranking and report outputs for demo resume.
- Critical (1 vote): Distinguish unresolved explicit FHIR subjects from absent subjects.
- Moderate (1 vote): Include enabled query-expansion models in preflight checks.
File summaries
| File | Description |
|---|---|
tests/test_fhir_robustness.py |
Tests FHIR subject attribution behavior. |
tests/test_deployment_readiness.py |
Tests stage-aware model preflight behavior. |
tests/test_cli_e2e.py |
Tests the installed CLI workflow and resume behavior. |
tests/test_bootstrap_data.py |
Tests bootstrap checksums and provenance. |
tests/test_artifact_integrity.py |
Tests manifest validation and status behavior. |
src/trialmatchai/utils/integrity.py |
Implements SHA-256 manifest utilities. |
src/trialmatchai/services/preflight.py |
Handles enabled-stage model access checks. |
src/trialmatchai/interop/importers/fhir.py |
Handles explicit FHIR subject resolution. |
src/trialmatchai/cli/main.py |
Registers CLI commands and version output. |
src/trialmatchai/cli/demo.py |
Implements the synthetic CPU workflow. |
src/trialmatchai/cli/bootstrap_data.py |
Provides strict archive and extraction verification. |
src/trialmatchai/cli/artifacts.py |
Provides artifact manifest commands. |
scripts/installed_smoke.py |
Exercises the installed public CLI. |
README.md |
Documents validation and demo usage. |
pytest.ini |
Registers the e2e marker. |
pyproject.toml |
Updates packaging and test configuration. |
mkdocs.yml |
Updates documentation configuration. |
MANIFEST.in |
Includes package resources and scripts. |
Makefile |
Updates verification and release targets. |
docs/release.md |
Documents release procedures. |
docs/production-validation.md |
Records production validation results. |
docs/production-roadmap.md |
Defines remaining qualification work. |
docs/codebase-review-2026-09-12.md |
Records baseline review findings. |
docs/audit_2026_09_12_validation.md |
Stores validation audit material. |
docs/audit_2026_09_12_reproduce.py |
Provides audit reproduction steps. |
docs/audit_2026_09_12_observations.json |
Stores audit observations. |
docs/audit_2026_09_12_inventory.json |
Stores audit inventory data. |
CHANGELOG.md |
Records the release-foundation changes. |
.pre-commit-config.yaml |
Adds workflow validation tooling. |
.github/workflows/verify.yml |
Defines required verification checks. |
.github/workflows/release.yml |
Verifies and publishes release artifacts. |
.github/workflows/ci.yml |
Delegates CI to reusable verification. |
.github/dependabot.yml |
Configures dependency updates. |
Review details
Suppressed comments (3)
src/trialmatchai/cli/bootstrap_data.py:171
- When a cached archive fails
_verify_sha256, it remains atchunk_path;_download_if_missingthen treats that path as valid and skips downloading it on every retry, including--force(which only re-extracts). A transient bad/truncated cache therefore permanently blocks strict bootstrap until manual deletion. Remove invalid archives and retry, or make the download path replace a failed cached file.
_verify_sha256(
chunk_path,
checksums[chunk_name],
)
src/trialmatchai/cli/demo.py:104
- The match stage's resume predicate treats any parseable
ranked_trials.jsonas complete, while this demo also requiresreport.html. If execution is interrupted or report generation fails after ranking is written,--resumeskips matching and then fails at the report check indefinitely because the report is never regenerated. Make ranking and report one completion unit, or force the match stage when either required output is incomplete.
root.mkdir(parents=True, exist_ok=True)
config = _create_workspace(root)
src/trialmatchai/services/preflight.py:131
- The narrowed model list no longer covers query expansion.
query_expansion.enabledcan loadquery_expansion.model(ormodel.base_model) even when RAG and the reranker are disabled, but this preflight then skips the Hub access check and the failure occurs only after the pipeline starts loading the model. Include the enabled query-expansion model inrequested_models.
requested_models = []
if rag_enabled:
requested_models.append(model_cfg.get("base_model"))
if reranker_enabled:
requested_models.append(model_cfg.get("reranker_model_path"))
if requested_models:
issues.extend(check_hf_access(requested_models))
- Files reviewed: 33/33 changed files
- Comments generated: 4
- Review effort level: Lite
💡 Add a code-review agent skill or configure MCP servers for context-aware, tailored reviews. Learn more in the docs.
| - run: uv lock --check | ||
| - run: uv run --frozen ruff check . | ||
| - run: uv run --frozen pre-commit run actionlint --all-files | ||
| - run: uv run --frozen pytest -v -m 'not e2e' --junitxml=test-results/unit.xml |
Comment on lines
+159
to
+160
| criteria_dir.mkdir(parents=True, exist_ok=True) | ||
| (criteria_dir / _EXTRACT_MARKER).unlink(missing_ok=True) |
Comment on lines
+299
to
+306
| marker = path / _EXTRACT_MARKER | ||
| if expected_checksums is None: | ||
| return marker.is_file() | ||
| try: | ||
| data = json.loads(marker.read_text(encoding="utf-8")) | ||
| return isinstance(data, dict) and data.get("schema") == 1 and data.get("sha256") == expected_checksums | ||
| except (OSError, ValueError): | ||
| return False |
Comment on lines
+213
to
+215
| # An explicit foreign/unresolved subject must never be attributed to the | ||
| # sole patient. Only a genuinely absent subject permits that fallback. | ||
| return None |
This file contains hidden or bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
Sign up for free
to join this conversation on GitHub.
Already have an account?
Sign in to comment
Add this suggestion to a batch that can be applied as a single commit.This suggestion is invalid because no changes were made to the code.Suggestions cannot be applied while the pull request is closed.Suggestions cannot be applied while viewing a subset of changes.Only one suggestion per line can be applied in a batch.Add this suggestion to a batch that can be applied as a single commit.Applying suggestions on deleted lines is not supported.You must change the existing code in this line in order to create a valid suggestion.Outdated suggestions cannot be applied.This suggestion has been applied or marked resolved.Suggestions cannot be applied from pending reviews.Suggestions cannot be applied on multi-line comments.Suggestions cannot be applied while the pull request is queued to merge.Suggestion cannot be applied right now. Please check back later.
Problem and behavior
This foundation release addresses reproducible patient attribution, artifact integrity, packaging, and recovery failures, and establishes a repeatable CLI/release verification path. The audit and roadmap cover the remaining ranking, clinical workflow, bounded-agent, and deployment work without claiming that those packages are complete.
Copilot review disposition
All six reproducible findings are addressed, including the three findings mentioned in the review summary. The JUnit-directory suggestion is a false positive: the locked pytest implementation creates the report parent directory, and an absent-directory probe succeeded.
Validation
Migration and remaining limits
Strict bootstrap migrates legacy markers by re-extracting. Tree replacement uses two renames and publishes stages individually: stop readers during updates. Retained backups/quarantines need disk space. Legacy untracked model roots are preserved conservatively; strict resume does not hash every extracted file.
This release qualifies the synthetic CPU software path only. Model/adapter compatibility, GPU security and actual inference, clinical semantics, evaluator corrections, complete cache identity, bounded agents, and production application deployment remain in
docs/production-roadmap.md. Ranking benchmark scores have not been rerun or claimed to improve.