seqevi 0.3.5__tar.gz → 0.4.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.
Files changed (97) hide show
  1. {seqevi-0.3.5 → seqevi-0.4.0}/PKG-INFO +75 -62
  2. {seqevi-0.3.5 → seqevi-0.4.0}/README.md +75 -62
  3. {seqevi-0.3.5 → seqevi-0.4.0}/pyproject.toml +10 -1
  4. {seqevi-0.3.5 → seqevi-0.4.0}/src/seqevi/__init__.py +4 -1
  5. {seqevi-0.3.5 → seqevi-0.4.0}/src/seqevi/annotate.py +6 -0
  6. {seqevi-0.3.5 → seqevi-0.4.0}/src/seqevi/api.py +35 -1
  7. {seqevi-0.3.5 → seqevi-0.4.0}/src/seqevi/cli.py +49 -6
  8. {seqevi-0.3.5 → seqevi-0.4.0}/src/seqevi/distribution/oci.py +61 -4
  9. {seqevi-0.3.5 → seqevi-0.4.0}/src/seqevi/evidence.py +25 -3
  10. {seqevi-0.3.5 → seqevi-0.4.0}/src/seqevi/runner.py +30 -0
  11. {seqevi-0.3.5 → seqevi-0.4.0}/src/seqevi/service/app.py +198 -18
  12. {seqevi-0.3.5 → seqevi-0.4.0}/src/seqevi/service/config.py +48 -0
  13. {seqevi-0.3.5 → seqevi-0.4.0}/src/seqevi/service/persistence.py +55 -30
  14. seqevi-0.4.0/src/seqevi/store/artifact.py +344 -0
  15. {seqevi-0.3.5 → seqevi-0.4.0}/src/seqevi/store/client.py +429 -40
  16. {seqevi-0.3.5 → seqevi-0.4.0}/src/seqevi/store/factory.py +9 -1
  17. {seqevi-0.3.5 → seqevi-0.4.0}/src/seqevi/store/local.py +2 -0
  18. {seqevi-0.3.5 → seqevi-0.4.0}/src/seqevi/store/migration.py +304 -95
  19. seqevi-0.4.0/src/seqevi/store/migrations/versions/0005_oci_artifact_storage.py +69 -0
  20. seqevi-0.4.0/src/seqevi/store/oci.py +557 -0
  21. {seqevi-0.3.5 → seqevi-0.4.0}/src/seqevi/store/schema.py +13 -1
  22. {seqevi-0.3.5 → seqevi-0.4.0}/src/seqevi/store/transport.py +117 -0
  23. {seqevi-0.3.5 → seqevi-0.4.0}/tests/test_api.py +62 -1
  24. {seqevi-0.3.5 → seqevi-0.4.0}/tests/test_architecture_contracts.py +1 -1
  25. {seqevi-0.3.5 → seqevi-0.4.0}/tests/test_artifact_store.py +1 -0
  26. seqevi-0.4.0/tests/test_artifact_upload.py +207 -0
  27. seqevi-0.4.0/tests/test_ci_change_scope.py +76 -0
  28. {seqevi-0.3.5 → seqevi-0.4.0}/tests/test_cli.py +75 -1
  29. {seqevi-0.3.5 → seqevi-0.4.0}/tests/test_dbcan_image_assets.py +38 -8
  30. {seqevi-0.3.5 → seqevi-0.4.0}/tests/test_deployment_assets.py +6 -5
  31. {seqevi-0.3.5 → seqevi-0.4.0}/tests/test_local_store.py +1 -1
  32. {seqevi-0.3.5 → seqevi-0.4.0}/tests/test_managed_setup.py +18 -0
  33. {seqevi-0.3.5 → seqevi-0.4.0}/tests/test_oci.py +57 -0
  34. seqevi-0.4.0/tests/test_oci_arg_order.py +45 -0
  35. seqevi-0.4.0/tests/test_oci_artifact_storage_migration.py +158 -0
  36. seqevi-0.4.0/tests/test_oci_cancellation.py +424 -0
  37. seqevi-0.4.0/tests/test_oci_client.py +363 -0
  38. seqevi-0.4.0/tests/test_oci_native.py +373 -0
  39. seqevi-0.4.0/tests/test_oci_postgres.py +166 -0
  40. seqevi-0.4.0/tests/test_oci_registry.py +296 -0
  41. seqevi-0.4.0/tests/test_oci_service.py +520 -0
  42. seqevi-0.4.0/tests/test_release_contract.py +193 -0
  43. seqevi-0.4.0/tests/test_runner_output_limit.py +25 -0
  44. {seqevi-0.3.5 → seqevi-0.4.0}/tests/test_shared_store.py +390 -30
  45. seqevi-0.3.5/src/seqevi/store/artifact.py +0 -225
  46. {seqevi-0.3.5 → seqevi-0.4.0}/LICENSE +0 -0
  47. {seqevi-0.3.5 → seqevi-0.4.0}/src/seqevi/__main__.py +0 -0
  48. {seqevi-0.3.5 → seqevi-0.4.0}/src/seqevi/adapters/__init__.py +0 -0
  49. {seqevi-0.3.5 → seqevi-0.4.0}/src/seqevi/adapters/base.py +0 -0
  50. {seqevi-0.3.5 → seqevi-0.4.0}/src/seqevi/adapters/dbcan_cazyme.py +0 -0
  51. {seqevi-0.3.5 → seqevi-0.4.0}/src/seqevi/adapters/eggnog.py +0 -0
  52. {seqevi-0.3.5 → seqevi-0.4.0}/src/seqevi/adapters/interpro_pfam.py +0 -0
  53. {seqevi-0.3.5 → seqevi-0.4.0}/src/seqevi/adapters/registry.py +0 -0
  54. {seqevi-0.3.5 → seqevi-0.4.0}/src/seqevi/distribution/__init__.py +0 -0
  55. {seqevi-0.3.5 → seqevi-0.4.0}/src/seqevi/distribution/manifest.py +0 -0
  56. {seqevi-0.3.5 → seqevi-0.4.0}/src/seqevi/distribution/setup.py +0 -0
  57. {seqevi-0.3.5 → seqevi-0.4.0}/src/seqevi/errors.py +0 -0
  58. {seqevi-0.3.5 → seqevi-0.4.0}/src/seqevi/execution_profile.py +0 -0
  59. {seqevi-0.3.5 → seqevi-0.4.0}/src/seqevi/hashing.py +0 -0
  60. {seqevi-0.3.5 → seqevi-0.4.0}/src/seqevi/kits/__init__.py +0 -0
  61. {seqevi-0.3.5 → seqevi-0.4.0}/src/seqevi/kits/dbcan-cazyme.toml +0 -0
  62. {seqevi-0.3.5 → seqevi-0.4.0}/src/seqevi/progress.py +0 -0
  63. {seqevi-0.3.5 → seqevi-0.4.0}/src/seqevi/resource_lock.py +0 -0
  64. {seqevi-0.3.5 → seqevi-0.4.0}/src/seqevi/result.py +0 -0
  65. {seqevi-0.3.5 → seqevi-0.4.0}/src/seqevi/runtime_identity.py +0 -0
  66. {seqevi-0.3.5 → seqevi-0.4.0}/src/seqevi/sequence.py +0 -0
  67. {seqevi-0.3.5 → seqevi-0.4.0}/src/seqevi/service/__init__.py +0 -0
  68. {seqevi-0.3.5 → seqevi-0.4.0}/src/seqevi/store/__init__.py +0 -0
  69. {seqevi-0.3.5 → seqevi-0.4.0}/src/seqevi/store/_artifact_reader.py +0 -0
  70. {seqevi-0.3.5 → seqevi-0.4.0}/src/seqevi/store/_resolver.py +0 -0
  71. {seqevi-0.3.5 → seqevi-0.4.0}/src/seqevi/store/contract.py +0 -0
  72. {seqevi-0.3.5 → seqevi-0.4.0}/src/seqevi/store/migrations/__init__.py +0 -0
  73. {seqevi-0.3.5 → seqevi-0.4.0}/src/seqevi/store/migrations/env.py +0 -0
  74. {seqevi-0.3.5 → seqevi-0.4.0}/src/seqevi/store/migrations/versions/0001_initial_store.py +0 -0
  75. {seqevi-0.3.5 → seqevi-0.4.0}/src/seqevi/store/migrations/versions/0002_artifact_byte_size_bigint.py +0 -0
  76. {seqevi-0.3.5 → seqevi-0.4.0}/src/seqevi/store/migrations/versions/0003_evidence_claim_leases.py +0 -0
  77. {seqevi-0.3.5 → seqevi-0.4.0}/src/seqevi/store/migrations/versions/0004_claim_sessions.py +0 -0
  78. {seqevi-0.3.5 → seqevi-0.4.0}/src/seqevi/store/migrations/versions/__init__.py +0 -0
  79. {seqevi-0.3.5 → seqevi-0.4.0}/tests/__init__.py +0 -0
  80. {seqevi-0.3.5 → seqevi-0.4.0}/tests/support.py +0 -0
  81. {seqevi-0.3.5 → seqevi-0.4.0}/tests/test_acceptance_containment.py +0 -0
  82. {seqevi-0.3.5 → seqevi-0.4.0}/tests/test_acceptance_harnesses.py +0 -0
  83. {seqevi-0.3.5 → seqevi-0.4.0}/tests/test_annotate.py +0 -0
  84. {seqevi-0.3.5 → seqevi-0.4.0}/tests/test_claim_leases.py +0 -0
  85. {seqevi-0.3.5 → seqevi-0.4.0}/tests/test_dbcan_cazyme.py +0 -0
  86. {seqevi-0.3.5 → seqevi-0.4.0}/tests/test_dbcan_local_candidate_harness.py +0 -0
  87. {seqevi-0.3.5 → seqevi-0.4.0}/tests/test_eggnog.py +0 -0
  88. {seqevi-0.3.5 → seqevi-0.4.0}/tests/test_evidence.py +0 -0
  89. {seqevi-0.3.5 → seqevi-0.4.0}/tests/test_execution_profile.py +0 -0
  90. {seqevi-0.3.5 → seqevi-0.4.0}/tests/test_incremental_reuse.py +0 -0
  91. {seqevi-0.3.5 → seqevi-0.4.0}/tests/test_interpro_pfam.py +0 -0
  92. {seqevi-0.3.5 → seqevi-0.4.0}/tests/test_progress.py +0 -0
  93. {seqevi-0.3.5 → seqevi-0.4.0}/tests/test_resource_lock.py +0 -0
  94. {seqevi-0.3.5 → seqevi-0.4.0}/tests/test_result_prototype.py +0 -0
  95. {seqevi-0.3.5 → seqevi-0.4.0}/tests/test_runner.py +0 -0
  96. {seqevi-0.3.5 → seqevi-0.4.0}/tests/test_runtime_identity.py +0 -0
  97. {seqevi-0.3.5 → seqevi-0.4.0}/tests/test_sequence.py +0 -0
@@ -1,6 +1,6 @@
1
1
  Metadata-Version: 2.4
2
2
  Name: seqevi
3
- Version: 0.3.5
3
+ Version: 0.4.0
4
4
  Summary: Content-addressed, reusable protein sequence annotation evidence.
5
5
  Author-Email: Fuqing Zhang <fu.qing.zhang.work@gmail.com>, FuqingZhang <103730099+FuqingZh@users.noreply.github.com>
6
6
  License-Expression: MIT
@@ -45,30 +45,53 @@ single-file DuckDB result for the current FASTA.
45
45
 
46
46
  ## Status
47
47
 
48
- The target architecture and v1.1 result contracts are approved. The SeqEvi
49
- 0.3.5 source tree uses strict protein sequence identity, the single-host
50
- SQLite/POSIX Store, the external tool runner, exact cache-miss orchestration,
51
- and atomic DuckDB result materialization.
48
+ The source tree is a SeqEvi 0.4.0 release candidate. It implements strict
49
+ protein sequence identity, local SQLite/POSIX and shared HTTP/PostgreSQL Stores
50
+ with POSIX or explicit native OCI artifact storage, exact cache-miss
51
+ orchestration, Linux external-tool containment, and immutable single-file
52
+ DuckDB results. Python 3.12 or newer is required; direct adapter execution
53
+ requires Linux. SeqEvi 0.4.0 has not been tagged or published as a Python or
54
+ GitHub release, deployed to production, or used to migrate historical bytes.
52
55
 
53
- SeqEvi 0.3.5 provides managed setup for dbCAN only. The `eggnog` and
56
+ The 0.4.0 candidate provides managed setup for dbCAN only. The `eggnog` and
54
57
  `interpro-pfam` adapters remain supported through explicit runtimes and named
55
- host profiles; managed setup for them is later feature work. The
56
- [Slice D gate record](docs/benchmarks/20260806-v1.4-dbcan-public-release-gate.md)
57
- preserves the incomplete original public-user run and its subsequent acceptance
58
- decision. In particular, a repeat pull from that run's site is a deferred
59
- transport check rather than a 0.2.0 release blocker.
60
-
61
- The `interpro-pfam` and eggNOG-mapper 2.x `eggnog` adapters are implemented with
62
- native-output validation and fixture parity coverage. The eggNOG adapter passes
63
- direct parity against eggNOG-mapper 2.1.13 and eggNOG DB 5.0.2. The InterPro
64
- adapter passes direct parity against InterProScan 5.77-108.0 with InterPro data
65
- 108.0 and Pfam 38.1. The Phase 5 shared Store service, HTTP client, streamed
66
- POSIX artifacts, and PostgreSQL persistence are implemented and covered by
67
- local/shared plus provisioned PostgreSQL integration tests. Phase 6 resource
68
- locks avoid repeated hashing of large immutable database files and provide an
69
- explicit full-content verification command. Annotation now uses atomic FASTA
70
- staging, file-backed artifacts, bounded Store batches, adapter-native Parquet
71
- artifacts, and an operational thread setting.
58
+ host profiles; managed setup for them is later feature work.
59
+
60
+ > **Known incomplete or unavailable work:** the original managed dbCAN public-
61
+ > user Slice D run remains incomplete; managed dispatch has no claim-before-OCI
62
+ > path, so D5 is unavailable; InterPro v2 target-Store refresh remains open;
63
+ > and global cache seeding is incomplete. See the
64
+ > [documentation index](docs/README.md) for the governing records. None of
65
+ > these states is represented as a pass.
66
+
67
+ The `eggnog`, `interpro-pfam`, and `dbcan-cazyme` adapters preserve their native
68
+ schemas and have accepted direct-runtime parity evidence. Shared Store,
69
+ resource-lock, batching, and result-publication details are routed from the
70
+ [current system architecture](docs/architecture/20260825-v1.0-current-system-architecture.md).
71
+
72
+ ## Release Channels
73
+
74
+ SeqEvi treats repository CI, nightly packages, version tags, GitHub Releases,
75
+ PyPI publication, and the dbCAN runtime image as distinct states:
76
+
77
+ - pull requests and ordinary pushes run CI but do not publish;
78
+ - an off-minute daily or manually dispatched nightly validates exact `main`
79
+ and retains SHA-named wheel/sdist artifacts for 14 days without publishing;
80
+ - an immutable canonical `vX.Y.Z` tag is a validation candidate only and tag
81
+ push alone never publishes;
82
+ - publishing a stable, non-prerelease GitHub Release for that exact tag starts
83
+ the separately gated PyPI Trusted Publishing path;
84
+ - PyPI publication completes only after the external project/version/files are
85
+ read back successfully; GitHub Release publication necessarily precedes that
86
+ eventual completion; and
87
+ - dbCAN OCI image publication remains an independent, manual dispatch with
88
+ exact source-revision tags and digest readback.
89
+
90
+ Untagged builds use a PEP 440 development version derived from the most recent
91
+ canonical tag, commit distance, and source revision. Installed distribution
92
+ metadata, `seqevi.__version__`, and `seqevi --version` report one identity.
93
+ There is no TestPyPI or release-candidate publishing channel in the current
94
+ contract.
72
95
 
73
96
  ## Why SeqEvi
74
97
 
@@ -134,8 +157,8 @@ seqevi setup dbcan-cazyme \
134
157
  `--dry-run` never mutates state. `--yes` pulls the immutable image only when
135
158
  needed, verifies the caller-owned four-file resource, creates `seqevi.lock`
136
159
  when the resource permits it, runs an ephemeral read-only smoke, and publishes
137
- the v2 profile atomically. It never downloads or copies the database. Slice C
138
- now dispatches a managed dbCAN annotation through an ephemeral Docker
160
+ the v2 profile atomically. It never downloads or copies the database. A managed
161
+ dbCAN annotation runs through an ephemeral Docker
139
162
  container with the same caller UID/GID, read-only FASTA/resource mounts and a
140
163
  local-Store `--network none` boundary:
141
164
 
@@ -147,6 +170,13 @@ seqevi annotate \
147
170
  --output results/dbcan.duckdb
148
171
  ```
149
172
 
173
+ The bundled managed kit and its selectable digest are unchanged. Separately,
174
+ an immutable SeqEvi 0.3.5 revision image was automatically published at
175
+ `ghcr.io/fuqingzh/seqevi-dbcan@sha256:1914939f1776fee3faac5241fc84f99f4534f37e20cc4d4d48eedf491c38488a`
176
+ from merged revision `f7781c4ce7d642ef46619e6f02c7be3745803ca4`. That
177
+ publication did not register a new managed kit or publish SeqEvi 0.4.0; image
178
+ publication now requires an explicit workflow dispatch.
179
+
150
180
  The dispatcher and cleanup boundary are covered by fixture tests. Real
151
181
  direct-candidate versus managed-v2 scientific equality and later-process replay
152
182
  passed the release gate. A validation harness used an immutable local image ID
@@ -240,9 +270,11 @@ seqevi resource verify \
240
270
  - Exact, immutable evidence keys.
241
271
  - Explicit `eggnog`, `interpro-pfam`, and official-runtime-validated
242
272
  `dbcan-cazyme` adapters. dbCAN direct/local/shared scientific acceptance is
243
- complete; publishing the managed runtime image remains separate work, and
244
- annotation databases remain caller supplied.
245
- - Local SQLite/POSIX Store and shared PostgreSQL/POSIX Store service.
273
+ complete. The bundled managed kit is unchanged; the separately published
274
+ immutable 0.3.5 revision image is not a new selectable kit. Annotation
275
+ databases remain caller supplied.
276
+ - Local SQLite/POSIX Store and shared PostgreSQL Store with legacy POSIX or
277
+ explicitly configured native OCI artifacts.
246
278
  - One self-describing DuckDB result per invocation; adapter-native normalized
247
279
  evidence remains Parquet inside the incremental Store.
248
280
 
@@ -252,31 +284,13 @@ schemas.
252
284
 
253
285
  ## Documentation
254
286
 
255
- Start with [the documentation index](docs/README.md).
256
-
257
- - [Architecture overview](docs/architecture/20260720-v1.0-seqevi-architecture.md)
258
- - [Sequence and evidence contract](docs/architecture/20260804-v1.1-sequence-evidence-contract.md)
259
- - [Adapter contract](docs/architecture/20260804-v1.1-adapter-contract.md)
260
- - [Result consumption contract](docs/architecture/20260804-v1.1-result-consumption-contract.md)
261
- - [Execution profile contract](docs/architecture/20260724-v1.0-execution-profile-contract.md)
262
- - [Storage and deployment architecture](docs/architecture/20260729-v1.1-storage-deployment-architecture.md)
263
- - [MVP implementation plan](docs/implementation-plan/20260720-v1.0-mvp-implementation-plan.md)
264
- - [Execution profile implementation plan](docs/implementation-plan/20260724-v1.0-execution-profile-implementation-plan.md)
265
- - [Validation strategy](docs/testing/20260720-v1.0-validation-strategy.md)
266
- - [Annotate runtime and bounded-memory plan](docs/implementation-plan/20260722-v1.0-annotate-bounded-memory-plan.md)
267
- - [Bounded-memory and operational performance](docs/benchmarks/20260722-v1.0-bounded-memory-performance.md)
268
- - [InterProScan Pfam runtime validation](docs/benchmarks/20260723-v1.0-interproscan-runtime-validation.md)
269
- - [dbCAN CAZyme adapter implementation plan](docs/implementation-plan/20260804-v1.0-dbcan-cazyme-adapter-implementation-plan.md)
270
- - [DuckDB result-consumption runtime acceptance](docs/benchmarks/20260805-v1.0-result-consumption-runtime-acceptance.md)
271
- - [dbCAN runtime image release review](docs/architecture/20260805-v1.1-dbcan-runtime-image-release-review.md)
272
-
273
- Accepted managed-boundary documents; Slice B setup and smoke plus Slice C OCI
274
- execution and real candidate acceptance are implemented, while v1 profiles
275
- remain compatible:
276
-
277
- - [Managed adapter onboarding roadmap v1.1](docs/implementation-plan/20260805-v1.1-managed-adapter-onboarding-implementation-plan.md)
278
- - [Managed-distribution architecture v1.2](docs/architecture/20260806-v1.2-managed-adapter-distribution-architecture.md)
279
- - [Execution profile v2.2 contract](docs/architecture/20260806-v2.2-execution-profile-contract.md)
287
+ Start with the [documentation index](docs/README.md), the
288
+ [current system architecture](docs/architecture/20260825-v1.0-current-system-architecture.md),
289
+ or the [first-annotation guide](docs/how-to-guides/first-annotation.md).
290
+
291
+ The index owns the current contract map, active work, incomplete evidence,
292
+ operations, and historical navigation. Superseded architecture is retained in
293
+ the [documentation archive](docs/archive/README.md), not mixed into onboarding.
280
294
 
281
295
  ## Python And Result Discovery
282
296
 
@@ -319,18 +333,17 @@ produce the new result file.
319
333
 
320
334
  ## External Tools
321
335
 
322
- Annotation runtimes and databases are supplied by the user. The current CLI has
323
- no `seqevi setup` command. SeqEvi v1 targets
336
+ Annotation runtimes and databases are normally supplied by the user. SeqEvi
337
+ targets
324
338
  [eggNOG-mapper](https://github.com/eggnogdb/eggnog-mapper) and
325
339
  [InterProScan](https://www.ebi.ac.uk/interpro/interproscan.html) with the Pfam
326
340
  application, and [dbCAN](https://github.com/bcb-unl/run_dbcan) for protein-level
327
- CAZyme annotation. A future managed path may publish a SeqEvi-maintained runtime
328
- image built from locked upstream inputs after runtime compliance review; it would
329
- not be an upstream-official image. Annotation databases remain separate and
330
- are never bundled in the wheel or runtime image. The proposed managed path
331
- uses a public, digest-pinned
332
- `ghcr.io/fuqingzh/seqevi-dbcan` runtime package; callers continue to provide the
333
- database path, and internal registry mirrors remain deployment policy.
341
+ CAZyme annotation. Managed `seqevi setup` is implemented only for dbCAN using a
342
+ public, digest-pinned `ghcr.io/fuqingzh/seqevi-dbcan` runtime image built from
343
+ locked upstream inputs. It is SeqEvi-maintained, not an upstream-official dbCAN
344
+ image. Callers still provide the database path; annotation databases are never
345
+ bundled in the wheel or runtime image, and internal registry mirrors remain
346
+ deployment policy.
334
347
 
335
348
  ## License
336
349
 
@@ -10,30 +10,53 @@ single-file DuckDB result for the current FASTA.
10
10
 
11
11
  ## Status
12
12
 
13
- The target architecture and v1.1 result contracts are approved. The SeqEvi
14
- 0.3.5 source tree uses strict protein sequence identity, the single-host
15
- SQLite/POSIX Store, the external tool runner, exact cache-miss orchestration,
16
- and atomic DuckDB result materialization.
17
-
18
- SeqEvi 0.3.5 provides managed setup for dbCAN only. The `eggnog` and
13
+ The source tree is a SeqEvi 0.4.0 release candidate. It implements strict
14
+ protein sequence identity, local SQLite/POSIX and shared HTTP/PostgreSQL Stores
15
+ with POSIX or explicit native OCI artifact storage, exact cache-miss
16
+ orchestration, Linux external-tool containment, and immutable single-file
17
+ DuckDB results. Python 3.12 or newer is required; direct adapter execution
18
+ requires Linux. SeqEvi 0.4.0 has not been tagged or published as a Python or
19
+ GitHub release, deployed to production, or used to migrate historical bytes.
20
+
21
+ The 0.4.0 candidate provides managed setup for dbCAN only. The `eggnog` and
19
22
  `interpro-pfam` adapters remain supported through explicit runtimes and named
20
- host profiles; managed setup for them is later feature work. The
21
- [Slice D gate record](docs/benchmarks/20260806-v1.4-dbcan-public-release-gate.md)
22
- preserves the incomplete original public-user run and its subsequent acceptance
23
- decision. In particular, a repeat pull from that run's site is a deferred
24
- transport check rather than a 0.2.0 release blocker.
25
-
26
- The `interpro-pfam` and eggNOG-mapper 2.x `eggnog` adapters are implemented with
27
- native-output validation and fixture parity coverage. The eggNOG adapter passes
28
- direct parity against eggNOG-mapper 2.1.13 and eggNOG DB 5.0.2. The InterPro
29
- adapter passes direct parity against InterProScan 5.77-108.0 with InterPro data
30
- 108.0 and Pfam 38.1. The Phase 5 shared Store service, HTTP client, streamed
31
- POSIX artifacts, and PostgreSQL persistence are implemented and covered by
32
- local/shared plus provisioned PostgreSQL integration tests. Phase 6 resource
33
- locks avoid repeated hashing of large immutable database files and provide an
34
- explicit full-content verification command. Annotation now uses atomic FASTA
35
- staging, file-backed artifacts, bounded Store batches, adapter-native Parquet
36
- artifacts, and an operational thread setting.
23
+ host profiles; managed setup for them is later feature work.
24
+
25
+ > **Known incomplete or unavailable work:** the original managed dbCAN public-
26
+ > user Slice D run remains incomplete; managed dispatch has no claim-before-OCI
27
+ > path, so D5 is unavailable; InterPro v2 target-Store refresh remains open;
28
+ > and global cache seeding is incomplete. See the
29
+ > [documentation index](docs/README.md) for the governing records. None of
30
+ > these states is represented as a pass.
31
+
32
+ The `eggnog`, `interpro-pfam`, and `dbcan-cazyme` adapters preserve their native
33
+ schemas and have accepted direct-runtime parity evidence. Shared Store,
34
+ resource-lock, batching, and result-publication details are routed from the
35
+ [current system architecture](docs/architecture/20260825-v1.0-current-system-architecture.md).
36
+
37
+ ## Release Channels
38
+
39
+ SeqEvi treats repository CI, nightly packages, version tags, GitHub Releases,
40
+ PyPI publication, and the dbCAN runtime image as distinct states:
41
+
42
+ - pull requests and ordinary pushes run CI but do not publish;
43
+ - an off-minute daily or manually dispatched nightly validates exact `main`
44
+ and retains SHA-named wheel/sdist artifacts for 14 days without publishing;
45
+ - an immutable canonical `vX.Y.Z` tag is a validation candidate only and tag
46
+ push alone never publishes;
47
+ - publishing a stable, non-prerelease GitHub Release for that exact tag starts
48
+ the separately gated PyPI Trusted Publishing path;
49
+ - PyPI publication completes only after the external project/version/files are
50
+ read back successfully; GitHub Release publication necessarily precedes that
51
+ eventual completion; and
52
+ - dbCAN OCI image publication remains an independent, manual dispatch with
53
+ exact source-revision tags and digest readback.
54
+
55
+ Untagged builds use a PEP 440 development version derived from the most recent
56
+ canonical tag, commit distance, and source revision. Installed distribution
57
+ metadata, `seqevi.__version__`, and `seqevi --version` report one identity.
58
+ There is no TestPyPI or release-candidate publishing channel in the current
59
+ contract.
37
60
 
38
61
  ## Why SeqEvi
39
62
 
@@ -99,8 +122,8 @@ seqevi setup dbcan-cazyme \
99
122
  `--dry-run` never mutates state. `--yes` pulls the immutable image only when
100
123
  needed, verifies the caller-owned four-file resource, creates `seqevi.lock`
101
124
  when the resource permits it, runs an ephemeral read-only smoke, and publishes
102
- the v2 profile atomically. It never downloads or copies the database. Slice C
103
- now dispatches a managed dbCAN annotation through an ephemeral Docker
125
+ the v2 profile atomically. It never downloads or copies the database. A managed
126
+ dbCAN annotation runs through an ephemeral Docker
104
127
  container with the same caller UID/GID, read-only FASTA/resource mounts and a
105
128
  local-Store `--network none` boundary:
106
129
 
@@ -112,6 +135,13 @@ seqevi annotate \
112
135
  --output results/dbcan.duckdb
113
136
  ```
114
137
 
138
+ The bundled managed kit and its selectable digest are unchanged. Separately,
139
+ an immutable SeqEvi 0.3.5 revision image was automatically published at
140
+ `ghcr.io/fuqingzh/seqevi-dbcan@sha256:1914939f1776fee3faac5241fc84f99f4534f37e20cc4d4d48eedf491c38488a`
141
+ from merged revision `f7781c4ce7d642ef46619e6f02c7be3745803ca4`. That
142
+ publication did not register a new managed kit or publish SeqEvi 0.4.0; image
143
+ publication now requires an explicit workflow dispatch.
144
+
115
145
  The dispatcher and cleanup boundary are covered by fixture tests. Real
116
146
  direct-candidate versus managed-v2 scientific equality and later-process replay
117
147
  passed the release gate. A validation harness used an immutable local image ID
@@ -205,9 +235,11 @@ seqevi resource verify \
205
235
  - Exact, immutable evidence keys.
206
236
  - Explicit `eggnog`, `interpro-pfam`, and official-runtime-validated
207
237
  `dbcan-cazyme` adapters. dbCAN direct/local/shared scientific acceptance is
208
- complete; publishing the managed runtime image remains separate work, and
209
- annotation databases remain caller supplied.
210
- - Local SQLite/POSIX Store and shared PostgreSQL/POSIX Store service.
238
+ complete. The bundled managed kit is unchanged; the separately published
239
+ immutable 0.3.5 revision image is not a new selectable kit. Annotation
240
+ databases remain caller supplied.
241
+ - Local SQLite/POSIX Store and shared PostgreSQL Store with legacy POSIX or
242
+ explicitly configured native OCI artifacts.
211
243
  - One self-describing DuckDB result per invocation; adapter-native normalized
212
244
  evidence remains Parquet inside the incremental Store.
213
245
 
@@ -217,31 +249,13 @@ schemas.
217
249
 
218
250
  ## Documentation
219
251
 
220
- Start with [the documentation index](docs/README.md).
221
-
222
- - [Architecture overview](docs/architecture/20260720-v1.0-seqevi-architecture.md)
223
- - [Sequence and evidence contract](docs/architecture/20260804-v1.1-sequence-evidence-contract.md)
224
- - [Adapter contract](docs/architecture/20260804-v1.1-adapter-contract.md)
225
- - [Result consumption contract](docs/architecture/20260804-v1.1-result-consumption-contract.md)
226
- - [Execution profile contract](docs/architecture/20260724-v1.0-execution-profile-contract.md)
227
- - [Storage and deployment architecture](docs/architecture/20260729-v1.1-storage-deployment-architecture.md)
228
- - [MVP implementation plan](docs/implementation-plan/20260720-v1.0-mvp-implementation-plan.md)
229
- - [Execution profile implementation plan](docs/implementation-plan/20260724-v1.0-execution-profile-implementation-plan.md)
230
- - [Validation strategy](docs/testing/20260720-v1.0-validation-strategy.md)
231
- - [Annotate runtime and bounded-memory plan](docs/implementation-plan/20260722-v1.0-annotate-bounded-memory-plan.md)
232
- - [Bounded-memory and operational performance](docs/benchmarks/20260722-v1.0-bounded-memory-performance.md)
233
- - [InterProScan Pfam runtime validation](docs/benchmarks/20260723-v1.0-interproscan-runtime-validation.md)
234
- - [dbCAN CAZyme adapter implementation plan](docs/implementation-plan/20260804-v1.0-dbcan-cazyme-adapter-implementation-plan.md)
235
- - [DuckDB result-consumption runtime acceptance](docs/benchmarks/20260805-v1.0-result-consumption-runtime-acceptance.md)
236
- - [dbCAN runtime image release review](docs/architecture/20260805-v1.1-dbcan-runtime-image-release-review.md)
237
-
238
- Accepted managed-boundary documents; Slice B setup and smoke plus Slice C OCI
239
- execution and real candidate acceptance are implemented, while v1 profiles
240
- remain compatible:
241
-
242
- - [Managed adapter onboarding roadmap v1.1](docs/implementation-plan/20260805-v1.1-managed-adapter-onboarding-implementation-plan.md)
243
- - [Managed-distribution architecture v1.2](docs/architecture/20260806-v1.2-managed-adapter-distribution-architecture.md)
244
- - [Execution profile v2.2 contract](docs/architecture/20260806-v2.2-execution-profile-contract.md)
252
+ Start with the [documentation index](docs/README.md), the
253
+ [current system architecture](docs/architecture/20260825-v1.0-current-system-architecture.md),
254
+ or the [first-annotation guide](docs/how-to-guides/first-annotation.md).
255
+
256
+ The index owns the current contract map, active work, incomplete evidence,
257
+ operations, and historical navigation. Superseded architecture is retained in
258
+ the [documentation archive](docs/archive/README.md), not mixed into onboarding.
245
259
 
246
260
  ## Python And Result Discovery
247
261
 
@@ -284,18 +298,17 @@ produce the new result file.
284
298
 
285
299
  ## External Tools
286
300
 
287
- Annotation runtimes and databases are supplied by the user. The current CLI has
288
- no `seqevi setup` command. SeqEvi v1 targets
301
+ Annotation runtimes and databases are normally supplied by the user. SeqEvi
302
+ targets
289
303
  [eggNOG-mapper](https://github.com/eggnogdb/eggnog-mapper) and
290
304
  [InterProScan](https://www.ebi.ac.uk/interpro/interproscan.html) with the Pfam
291
305
  application, and [dbCAN](https://github.com/bcb-unl/run_dbcan) for protein-level
292
- CAZyme annotation. A future managed path may publish a SeqEvi-maintained runtime
293
- image built from locked upstream inputs after runtime compliance review; it would
294
- not be an upstream-official image. Annotation databases remain separate and
295
- are never bundled in the wheel or runtime image. The proposed managed path
296
- uses a public, digest-pinned
297
- `ghcr.io/fuqingzh/seqevi-dbcan` runtime package; callers continue to provide the
298
- database path, and internal registry mirrors remain deployment policy.
306
+ CAZyme annotation. Managed `seqevi setup` is implemented only for dbCAN using a
307
+ public, digest-pinned `ghcr.io/fuqingzh/seqevi-dbcan` runtime image built from
308
+ locked upstream inputs. It is SeqEvi-maintained, not an upstream-official dbCAN
309
+ image. Callers still provide the database path; annotation databases are never
310
+ bundled in the wheel or runtime image, and internal registry mirrors remain
311
+ deployment policy.
299
312
 
300
313
  ## License
301
314
 
@@ -1,6 +1,6 @@
1
1
  [project]
2
2
  name = "seqevi"
3
- version = "0.3.5"
3
+ dynamic = []
4
4
  description = "Content-addressed, reusable protein sequence annotation evidence."
5
5
  authors = [
6
6
  { name = "Fuqing Zhang", email = "fu.qing.zhang.work@gmail.com" },
@@ -31,6 +31,7 @@ classifiers = [
31
31
  "Topic :: Scientific/Engineering :: Bio-Informatics",
32
32
  ]
33
33
  license = "MIT"
34
+ version = "0.4.0"
34
35
 
35
36
  [project.urls]
36
37
  Homepage = "https://github.com/FuqingZh/seqevi"
@@ -64,11 +65,19 @@ dev = [
64
65
  "pytest-timeout>=2.4,<3",
65
66
  "pytest-xdist>=3.8,<4",
66
67
  "ruff>=0.15,<0.16",
68
+ "packaging<27,>=25",
69
+ "twine<7,>=6.2",
67
70
  ]
68
71
 
69
72
  [tool.pdm]
70
73
  distribution = true
71
74
 
75
+ [tool.pdm.version]
76
+ source = "scm"
77
+ tag_filter = "v[0-9]*.[0-9]*.[0-9]*"
78
+ tag_regex = "^v(?P<version>(0|[1-9][0-9]*)\\.(0|[1-9][0-9]*)\\.(0|[1-9][0-9]*))$"
79
+ version_format = "scripts.version:format_version"
80
+
72
81
  [tool.pdm.scripts]
73
82
  format = "ruff format ."
74
83
  format-check = "ruff format --check ."
@@ -1,6 +1,9 @@
1
1
  """Content-addressed protein sequence annotation evidence."""
2
2
 
3
- __version__ = "0.3.5"
3
+ from importlib.metadata import version
4
+
5
+
6
+ __version__ = version("seqevi")
4
7
 
5
8
  from .api import annotate, scan_annotations
6
9
 
@@ -123,11 +123,17 @@ class _MeasuringToolRunner(ToolRunner):
123
123
  *,
124
124
  timeout_seconds: float | None = None,
125
125
  cancellation_signal: threading.Event | None = None,
126
+ output_limit_bytes: int | None = None,
126
127
  ) -> ToolRunResult:
127
128
  result = self.delegate.run(
128
129
  command,
129
130
  timeout_seconds=timeout_seconds,
130
131
  cancellation_signal=cancellation_signal or self.cancellation_signal,
132
+ **(
133
+ {"output_limit_bytes": output_limit_bytes}
134
+ if output_limit_bytes is not None
135
+ else {}
136
+ ),
131
137
  )
132
138
  self.duration_seconds += result.duration_seconds
133
139
  return result
@@ -35,6 +35,7 @@ from .progress import (
35
35
  )
36
36
  from .result import RESULT_FORMAT_VERSION, scan_annotations as _scan_annotations
37
37
  from .store import open_evidence_store
38
+ from .store.oci import OciClientFiles
38
39
 
39
40
 
40
41
  @dataclass(frozen=True, slots=True)
@@ -78,6 +79,8 @@ def annotate(
78
79
  store: str | Path | None = None,
79
80
  threads: int | None = None,
80
81
  timeout_seconds: float | None = None,
82
+ oci_registry_config: str | Path | None = None,
83
+ oci_registry_ca_file: str | Path | None = None,
81
84
  ) -> duckdb.DuckDBPyRelation:
82
85
  """Annotate a protein FASTA and return its native DuckDB relation.
83
86
 
@@ -92,6 +95,9 @@ def annotate(
92
95
  store: Local Store path or shared Store URL.
93
96
  threads: Operational worker-thread override.
94
97
  timeout_seconds: Optional external-tool timeout.
98
+ oci_registry_config: Optional Docker/ORAS registry config file for one
99
+ OCI-backed shared Store invocation. It is never persisted in a profile.
100
+ oci_registry_ca_file: Optional PEM trust anchor for that registry.
95
101
 
96
102
  Returns:
97
103
  The `main.annotations` DuckDB relation. It keeps the read-only result
@@ -127,6 +133,8 @@ def annotate(
127
133
  store=store,
128
134
  threads=threads,
129
135
  timeout_seconds=timeout_seconds,
136
+ oci_registry_config=oci_registry_config,
137
+ oci_registry_ca_file=oci_registry_ca_file,
130
138
  )
131
139
  return invocation.relation
132
140
 
@@ -170,9 +178,15 @@ def _run_annotation_application(
170
178
  store: str | Path | None,
171
179
  threads: int | None,
172
180
  timeout_seconds: float | None,
181
+ oci_registry_config: str | Path | None = None,
182
+ oci_registry_ca_file: str | Path | None = None,
173
183
  adapter_factory: Callable[[AdapterConfiguration], AnnotationAdapter] | None = None,
174
184
  progress_sink: ProgressSink | None = None,
175
185
  ) -> AnnotationInvocation:
186
+ oci_files = _resolve_oci_client_files(
187
+ oci_registry_config=oci_registry_config,
188
+ oci_registry_ca_file=oci_registry_ca_file,
189
+ )
176
190
  emit_progress(
177
191
  progress_sink,
178
192
  ProgressEvent(
@@ -207,6 +221,7 @@ def _run_annotation_application(
207
221
  store=inputs.store,
208
222
  threads=inputs.threads,
209
223
  timeout_seconds=inputs.timeout_seconds,
224
+ oci_files=oci_files,
210
225
  )
211
226
  emit_progress(
212
227
  progress_sink,
@@ -243,7 +258,7 @@ def _run_annotation_application(
243
258
  )
244
259
  )
245
260
  metadata = _result_metadata_template(configured_adapter)
246
- with open_evidence_store(inputs.store) as evidence_store:
261
+ with open_evidence_store(inputs.store, oci_files=oci_files) as evidence_store:
247
262
  summary = run_annotation(
248
263
  fasta_path=fasta.expanduser().resolve(),
249
264
  output_dir=output.expanduser().resolve(),
@@ -290,6 +305,25 @@ def _run_annotation_application(
290
305
  return invocation
291
306
 
292
307
 
308
+ def _resolve_oci_client_files(
309
+ *,
310
+ oci_registry_config: str | Path | None,
311
+ oci_registry_ca_file: str | Path | None,
312
+ ) -> OciClientFiles | None:
313
+ """Resolve invocation-only OCI client files without reading credentials."""
314
+
315
+ if oci_registry_config is None and oci_registry_ca_file is None:
316
+ return None
317
+ return OciClientFiles(
318
+ registry_config=(
319
+ Path(oci_registry_config) if oci_registry_config is not None else None
320
+ ),
321
+ ca_file=Path(oci_registry_ca_file)
322
+ if oci_registry_ca_file is not None
323
+ else None,
324
+ ).validated()
325
+
326
+
293
327
  def resolve_annotation_inputs(
294
328
  *,
295
329
  profile: str | None,