[Artifacts] Version-aware artifact registry API
Goal
Build the programmatic interface for creating, querying, and comparing artifact versions. This is the core API that all version-aware features (reproducibility, UI, model registry) depend on.
New Functions in artifact_registry.py
create_version(parent_artifact_id, **kwargs) → artifact_id
Load parent artifact by ID
Validate parent exists and is_latest=TRUE (or allow branching from any version)
Create new artifact row:
- Same artifact_type as parent
- version_number = parent.version_number + 1
- parent_version_id = parent.id
- is_latest = TRUE
- content_hash = SHA256 of new content/metadata
Set parent.is_latest = FALSE
Auto-create artifact_link: new → parent (link_type="derives_from")
Return new artifact IDget_version_history(artifact_id) → list[dict]
Follow parent_version_id chain back to root (version_number=1)
Also follow forward to find children (WHERE parent_version_id = current)
Return all versions ordered by version_number
Each entry includes: id, version_number, version_tag, changelog, created_at, content_hash, is_latestdiff_versions(v1_id, v2_id) → dict
Load both artifacts
Compare metadata JSON (key-by-key diff)
Compare title, quality_score, entity_ids
Return structured diff: {field: {old: v1_value, new: v2_value}, ...}
Flag content_hash changes (indicates substantive content change)pin_version(artifact_id, version_tag) → None
Set version_tag on the specified artifact
Tags are human-readable labels: "v1.0", "stable", "submitted", "retracted"
Tags must be unique within a version lineageget_latest_version(artifact_id) → artifact_id
Follow lineage to find the artifact with is_latest=TRUE
Useful when a consumer has a reference to an old versionREST API Endpoints (api.py)
GET /api/artifact/{id}/versions
Returns version history for the artifact lineage containing this ID.
Response:
{"artifact_id": "...", "versions": [...], "total_versions": N}GET /api/artifact/{id}/versions/{version_number}
Returns specific version of an artifact.
Response: full artifact record for that version
GET /api/artifact/{id}/diff/{other_id}
Returns structured diff between two artifact versions.
Response:
{"v1": {...summary}, "v2": {...summary}, "changes": {...}}POST /api/artifact/{id}/tag
Body:
{"tag": "v1.0"}Sets version tag on artifact.
Acceptance Criteria
☐ create_version() creates new version row with correct lineage
☐ create_version() sets parent is_latest=FALSE
☐ create_version() auto-creates derives_from link
☐ get_version_history() returns complete ordered lineage
☐ diff_versions() returns field-level metadata diff
☐ pin_version() sets unique tag within lineage
☐ get_latest_version() resolves to current head
☐ All 4 REST endpoints implemented and return JSON
☐ Edge case: creating version of version_number=1 artifact works
☐ Edge case: diffing identical versions returns empty changes
☐ Work log updated with timestamped entry
Dependencies
- a17-18-VERS0001 (version tracking schema must exist)
Dependents
- a17-24-REPR0001 (reproducible analysis chains)
- a17-25-AVUI0001 (version browser UI)
- frg-mb-04-MREG (model registry)
- d16-20-AVER0001 (demo: versioned protein design)
Work Log
2026-04-15 — Slot 55 (Re-verification)
- Task was previously marked done but audit could not verify work on main
- Checked git log on origin/main: commits
6aca5e819 and c762f241a both present
- Verified all 4 REST endpoints operational: GET /api/artifacts/{id}/versions → 200, GET /api/artifacts/{id}/versions/{ver} → 200, GET /api/artifacts/{id}/diff/{other_id} → 200, POST /api/artifacts/{id}/tag → 200
- API status healthy: 344 analyses, 516 hypotheses, 700K+ edges
- All acceptance criteria met: create_version, get_version_history, diff_versions, pin_version, get_latest_version all implemented in artifact_registry.py; all 4 REST endpoints live on main
- Result: Done — work verified on origin/main, no additional changes needed