Avatar for the Jij-Inc user
Jij-Inc
ommx
BlogDocsChangelog

Performance History

Latest Results

chore(deps): Bump the dependencies group across 1 directory with 3 updates (#875) Bumps the dependencies group with 3 updates in the / directory: [rusqlite](https://github.com/rusqlite/rusqlite), [sha2](https://github.com/RustCrypto/hashes) and [tokio](https://github.com/tokio-rs/tokio). Updates `rusqlite` from 0.37.0 to 0.39.0 <details> <summary>Release notes</summary> <p><em>Sourced from <a href="https://github.com/rusqlite/rusqlite/releases">rusqlite's releases</a>.</em></p> <blockquote> <h2>0.39.0</h2> <h2>What's Changed</h2> <ul> <li>Fix constraints on VTab Aux data <a href="https://redirect.github.com/rusqlite/rusqlite/issues/1778">#1778</a>, <a href="https://redirect.github.com/rusqlite/rusqlite/issues/1771">#1771</a></li> <li>Fix docs.rs generation <a href="https://redirect.github.com/rusqlite/rusqlite/issues/1779">#1779</a></li> <li>Fix a small typo in <code>rollback_hook</code> docstring <a href="https://redirect.github.com/rusqlite/rusqlite/issues/1780">#1780</a></li> <li>Fix some warnings from Intellij <a href="https://redirect.github.com/rusqlite/rusqlite/issues/1781">#1781</a></li> <li>Minimal doc for features <a href="https://redirect.github.com/rusqlite/rusqlite/issues/1783">#1783</a></li> <li>Clear hooks only for owning connections <a href="https://redirect.github.com/rusqlite/rusqlite/issues/1785">#1785</a>, <a href="https://redirect.github.com/rusqlite/rusqlite/issues/1784">#1784</a></li> <li>Fix link to SQLite C Interface, Prepare Flags <a href="https://redirect.github.com/rusqlite/rusqlite/issues/1787">#1787</a></li> <li>Comment functions which are not usable from a loadable extension <a href="https://redirect.github.com/rusqlite/rusqlite/issues/1789">#1789</a></li> <li>Factorize code <a href="https://redirect.github.com/rusqlite/rusqlite/issues/1792">#1792</a></li> <li>Update getrandom to 0.4 <a href="https://redirect.github.com/rusqlite/rusqlite/issues/1798">#1798</a></li> <li>Update Cargo.toml <a href="https://redirect.github.com/rusqlite/rusqlite/issues/1800">#1800</a></li> <li>Fix appveyor <a href="https://redirect.github.com/rusqlite/rusqlite/issues/1807">#1807</a></li> <li>Add support to unix timestamp for chrono, jiff and time <a href="https://redirect.github.com/rusqlite/rusqlite/issues/1808">#1808</a>, <a href="https://redirect.github.com/rusqlite/rusqlite/issues/1803">#1803</a></li> <li>fix(trace): check that the sql string pointer is not NULL <a href="https://redirect.github.com/rusqlite/rusqlite/issues/1805">#1805</a></li> <li>Bump bundled SQLite version to 3.51.3 <a href="https://redirect.github.com/rusqlite/rusqlite/issues/1818">#1818</a></li> <li>Use TryFrom<!-- raw HTML omitted --> for Value <a href="https://redirect.github.com/rusqlite/rusqlite/issues/1819">#1819</a>, <a href="https://redirect.github.com/rusqlite/rusqlite/issues/1817">#1817</a></li> <li>Make possible to pass your own pointers <a href="https://redirect.github.com/rusqlite/rusqlite/issues/1626">#1626</a>, <a href="https://redirect.github.com/rusqlite/rusqlite/issues/1602">#1602</a></li> </ul> <p><strong>Full Changelog</strong>: <a href="https://github.com/rusqlite/rusqlite/compare/v0.38.0...v0.39.0">https://github.com/rusqlite/rusqlite/compare/v0.38.0...v0.39.0</a></p> <h2>0.38.0</h2> <h2>What's Changed</h2> <ul> <li>bump sqlcipher to 4.10.0 (sqlite 3.50.4) <a href="https://redirect.github.com/rusqlite/rusqlite/issues/1725">#1725</a></li> <li>Use CARGO_CFG_TARGET_FEATURE for crt-static check <a href="https://redirect.github.com/rusqlite/rusqlite/issues/1737">#1737</a></li> <li>Disable u64, usize ToSql/FromSql impl by default <a href="https://redirect.github.com/rusqlite/rusqlite/issues/1732">#1732</a>, #<a href="https://redirect.github.com/rusqlite/rusqlite/issues/1722">#1722</a> (breaking change)</li> <li>Make statement cache optional <a href="https://redirect.github.com/rusqlite/rusqlite/issues/1682">#1682</a>, <a href="https://redirect.github.com/rusqlite/rusqlite/issues/1173">#1173</a> (breaking change)</li> <li>Remove shell scripts from the published package <a href="https://redirect.github.com/rusqlite/rusqlite/issues/1744">#1744</a></li> <li>Use new interfaces with 64-bit length parameters <a href="https://redirect.github.com/rusqlite/rusqlite/issues/1749">#1749</a></li> <li>sqlite3_vtab_rhs_value <a href="https://redirect.github.com/rusqlite/rusqlite/issues/1753">#1753</a></li> <li>Handle VTab IN values <a href="https://redirect.github.com/rusqlite/rusqlite/issues/1754">#1754</a></li> <li>Give access to Connection from VTabCursor::column <a href="https://redirect.github.com/rusqlite/rusqlite/issues/1755">#1755</a></li> <li>Bump minimal SQLite version to 3.34.1 <a href="https://redirect.github.com/rusqlite/rusqlite/issues/1733">#1733</a>, <a href="https://redirect.github.com/rusqlite/rusqlite/issues/1731">#1731</a> (breaking change)</li> <li>Bump bundled SQLite version to 3.51.1 <a href="https://redirect.github.com/rusqlite/rusqlite/issues/1758">#1758</a></li> <li>Add support for transaction to the vtab module <a href="https://redirect.github.com/rusqlite/rusqlite/issues/1761">#1761</a></li> <li>Check Connection is owned when registering Closure as hook <a href="https://redirect.github.com/rusqlite/rusqlite/issues/1764">#1764</a> (breaking change)</li> <li>Turn libsqlite3-sys in a !#[no_std] crate <a href="https://redirect.github.com/rusqlite/rusqlite/issues/1767">#1767</a></li> <li>Add <code>wasm32-unknown-unknown</code> support <a href="https://redirect.github.com/rusqlite/rusqlite/issues/1769">#1769</a>, <a href="https://redirect.github.com/rusqlite/rusqlite/issues/488">#488</a>, <a href="https://redirect.github.com/rusqlite/rusqlite/issues/827">#827</a></li> <li>Remove useless Send/Sync on Module <a href="https://redirect.github.com/rusqlite/rusqlite/issues/1774">#1774</a></li> </ul> <p><strong>Full Changelog</strong>: <a href="https://github.com/rusqlite/rusqlite/compare/v0.37.0...v0.38.0">https://github.com/rusqlite/rusqlite/compare/v0.37.0...v0.38.0</a></p> </blockquote> </details> <details> <summary>Commits</summary> <ul> <li><a href="https://github.com/rusqlite/rusqlite/commit/2a1790a69107cd03dae85d501dcbdb11c5b32ef3"><code>2a1790a</code></a> Merge pull request <a href="https://redirect.github.com/rusqlite/rusqlite/issues/1820">#1820</a> from gwenn/0.39.0</li> <li><a href="https://github.com/rusqlite/rusqlite/commit/7c43afcb74fe973d22f74e9e4821a20f4fa5e94b"><code>7c43afc</code></a> Prepare next release</li> <li><a href="https://github.com/rusqlite/rusqlite/commit/487af3c2d335f6ac1409a12fd283a7b4650ed106"><code>487af3c</code></a> Merge pull request <a href="https://redirect.github.com/rusqlite/rusqlite/issues/1626">#1626</a> from gwenn/ptr</li> <li><a href="https://github.com/rusqlite/rusqlite/commit/643d581b67f91d236e63555cfd89efc8f2452a9e"><code>643d581</code></a> Warn about potential memory leak</li> <li><a href="https://github.com/rusqlite/rusqlite/commit/67f59c39f5199a7b4cfdb33bee90b8bf2ea36792"><code>67f59c3</code></a> Merge pull request <a href="https://redirect.github.com/rusqlite/rusqlite/issues/1819">#1819</a> from gwenn/utf8error</li> <li><a href="https://github.com/rusqlite/rusqlite/commit/870d5b6b3cb119b8378fc730da18fec1f69f0612"><code>870d5b6</code></a> Use TryFrom&lt;ValueRef&gt; for Value</li> <li><a href="https://github.com/rusqlite/rusqlite/commit/93085d8ac3fc5375ce17f1b01c22d229485abd51"><code>93085d8</code></a> Merge pull request <a href="https://redirect.github.com/rusqlite/rusqlite/issues/1818">#1818</a> from gwenn/3.51.3</li> <li><a href="https://github.com/rusqlite/rusqlite/commit/7bd509863f304a40ba6be1c1e3ad70a221d50490"><code>7bd5098</code></a> Bump bundled SQLite version to 3.51.3</li> <li><a href="https://github.com/rusqlite/rusqlite/commit/886832ed8416d5831158a2c6caaaf891ef8a00b4"><code>886832e</code></a> Merge pull request <a href="https://redirect.github.com/rusqlite/rusqlite/issues/1816">#1816</a> from mqudsi/undo-3.52.0</li> <li><a href="https://github.com/rusqlite/rusqlite/commit/ca911a29bb1b229cb697346cfae6351240aeb589"><code>ca911a2</code></a> Revert &quot;Bump bundled SQLite version to 3.52.0&quot;</li> <li>Additional commits viewable in <a href="https://github.com/rusqlite/rusqlite/compare/v0.37.0...v0.39.0">compare view</a></li> </ul> </details> <br /> Updates `sha2` from 0.10.9 to 0.11.0 <details> <summary>Commits</summary> <ul> <li><a href="https://github.com/RustCrypto/hashes/commit/ffe093984c004769747e998f77da8ff7c0e7a765"><code>ffe0939</code></a> Release sha2 0.11.0 (<a href="https://redirect.github.com/RustCrypto/hashes/issues/806">#806</a>)</li> <li><a href="https://github.com/RustCrypto/hashes/commit/8991b65fe400c31c4cc189510f86ae642c470cd9"><code>8991b65</code></a> Use the standard order of the <code>[package]</code> section fields (<a href="https://redirect.github.com/RustCrypto/hashes/issues/807">#807</a>)</li> <li><a href="https://github.com/RustCrypto/hashes/commit/3d2bc57db40fd6aeb25d6c6da98d67e2784c2985"><code>3d2bc57</code></a> sha2: refactor backends (<a href="https://redirect.github.com/RustCrypto/hashes/issues/802">#802</a>)</li> <li><a href="https://github.com/RustCrypto/hashes/commit/faa55fb83697c8f3113636d88070e5f5edc8c335"><code>faa55fb</code></a> sha3: bump <code>keccak</code> to v0.2 (<a href="https://redirect.github.com/RustCrypto/hashes/issues/803">#803</a>)</li> <li><a href="https://github.com/RustCrypto/hashes/commit/d3e6489e56f8486d4a93ceb7a8abf4924af1de7b"><code>d3e6489</code></a> sha3 v0.11.0-rc.9 (<a href="https://redirect.github.com/RustCrypto/hashes/issues/801">#801</a>)</li> <li><a href="https://github.com/RustCrypto/hashes/commit/bbf6f51ff97f81ab15e6e5f6cf878bfbcb1f47c8"><code>bbf6f51</code></a> sha2: tweak backend docs (<a href="https://redirect.github.com/RustCrypto/hashes/issues/800">#800</a>)</li> <li><a href="https://github.com/RustCrypto/hashes/commit/155dbbf2959dbec0ec75948a82590ddaede2d3bc"><code>155dbbf</code></a> sha3: add default value for the <code>DS</code> generic parameter on <code>TurboShake128/256</code>...</li> <li><a href="https://github.com/RustCrypto/hashes/commit/ed514f2b34526683b3b7c41670f1887982c3df64"><code>ed514f2</code></a> Use published version of <code>keccak</code> v0.2 (<a href="https://redirect.github.com/RustCrypto/hashes/issues/799">#799</a>)</li> <li><a href="https://github.com/RustCrypto/hashes/commit/702bcd83735a49c928c0fc24506924f5c0aa22af"><code>702bcd8</code></a> Migrate to closure-based <code>keccak</code> (<a href="https://redirect.github.com/RustCrypto/hashes/issues/796">#796</a>)</li> <li><a href="https://github.com/RustCrypto/hashes/commit/827c043f82d57666a0b146d156e91c39535c1305"><code>827c043</code></a> sha3 v0.11.0-rc.8 (<a href="https://redirect.github.com/RustCrypto/hashes/issues/794">#794</a>)</li> <li>Additional commits viewable in <a href="https://github.com/RustCrypto/hashes/compare/sha2-v0.10.9...sha2-v0.11.0">compare view</a></li> </ul> </details> <br /> Updates `tokio` from 1.52.1 to 1.52.3 <details> <summary>Release notes</summary> <p><em>Sourced from <a href="https://github.com/tokio-rs/tokio/releases">tokio's releases</a>.</em></p> <blockquote> <h2>Tokio v1.52.3</h2> <h1>1.52.3 (May 8th, 2026)</h1> <h3>Fixed</h3> <ul> <li>sync: fix underflow in mpsc channel <code>len()</code> (<a href="https://redirect.github.com/tokio-rs/tokio/issues/8062">#8062</a>)</li> <li>sync: notify receivers in mpsc <code>OwnedPermit::release()</code> method (<a href="https://redirect.github.com/tokio-rs/tokio/issues/8075">#8075</a>)</li> <li>sync: require that an <code>RwLock</code> has <code>max_readers != 0</code> (<a href="https://redirect.github.com/tokio-rs/tokio/issues/8076">#8076</a>)</li> <li>sync: return <code>Empty</code> from <code>try_recv()</code> when mpsc is closed with outstanding permits (<a href="https://redirect.github.com/tokio-rs/tokio/issues/8074">#8074</a>)</li> </ul> <p><a href="https://redirect.github.com/tokio-rs/tokio/issues/8062">#8062</a>: <a href="https://redirect.github.com/tokio-rs/tokio/pull/8062">tokio-rs/tokio#8062</a> <a href="https://redirect.github.com/tokio-rs/tokio/issues/8074">#8074</a>: <a href="https://redirect.github.com/tokio-rs/tokio/pull/8074">tokio-rs/tokio#8074</a> <a href="https://redirect.github.com/tokio-rs/tokio/issues/8075">#8075</a>: <a href="https://redirect.github.com/tokio-rs/tokio/pull/8075">tokio-rs/tokio#8075</a> <a href="https://redirect.github.com/tokio-rs/tokio/issues/8076">#8076</a>: <a href="https://redirect.github.com/tokio-rs/tokio/pull/8076">tokio-rs/tokio#8076</a></p> <h2>Tokio v1.52.2</h2> <h1>1.52.2 (May 4th, 2026)</h1> <p>This release reverts the LIFO slot stealing change introduced in 1.51.0 (<a href="https://redirect.github.com/tokio-rs/tokio/issues/7431">#7431</a>), due to [its performance impact]<a href="https://redirect.github.com/tokio-rs/tokio/issues/8065">#8065</a>. (<a href="https://redirect.github.com/tokio-rs/tokio/issues/8100">#8100</a>)</p> <p><a href="https://redirect.github.com/tokio-rs/tokio/issues/7431">#7431</a>: <a href="https://redirect.github.com/tokio-rs/tokio/pull/7431">tokio-rs/tokio#7431</a> <a href="https://redirect.github.com/tokio-rs/tokio/issues/8065">#8065</a>: <a href="https://redirect.github.com/tokio-rs/tokio/pull/8065">tokio-rs/tokio#8065</a> <a href="https://redirect.github.com/tokio-rs/tokio/issues/8100">#8100</a>: <a href="https://redirect.github.com/tokio-rs/tokio/pull/8100">tokio-rs/tokio#8100</a></p> </blockquote> </details> <details> <summary>Commits</summary> <ul> <li><a href="https://github.com/tokio-rs/tokio/commit/d87569164fb61145e79e7ffe0b25783569cc8f93"><code>d875691</code></a> chore: prepare Tokio v1.52.3 (<a href="https://redirect.github.com/tokio-rs/tokio/issues/8130">#8130</a>)</li> <li><a href="https://github.com/tokio-rs/tokio/commit/e1aebb031cb24bdb52289561343308f4a44a4d81"><code>e1aebb0</code></a> Merge 'tokio-1.51.3' into 'tokio-1.52.x' (<a href="https://redirect.github.com/tokio-rs/tokio/issues/8129">#8129</a>)</li> <li><a href="https://github.com/tokio-rs/tokio/commit/fd63094ee0d34b4f3f93f59507e91c65919a2d71"><code>fd63094</code></a> chore: prepare Tokio v1.51.3 (<a href="https://redirect.github.com/tokio-rs/tokio/issues/8127">#8127</a>)</li> <li><a href="https://github.com/tokio-rs/tokio/commit/8c600d0fd2cdebea4828fe9f699ced4dfd8aad3b"><code>8c600d0</code></a> Merge 'tokio-1.47.5' into 'tokio-1.51.x' (<a href="https://redirect.github.com/tokio-rs/tokio/issues/8123">#8123</a>)</li> <li><a href="https://github.com/tokio-rs/tokio/commit/11bfc1345bbd5e901187e2b3702de10b0efbffdc"><code>11bfc13</code></a> chore: prepare Tokio v1.47.5 (<a href="https://redirect.github.com/tokio-rs/tokio/issues/8122">#8122</a>)</li> <li><a href="https://github.com/tokio-rs/tokio/commit/f085b6211b8ebb6aba21f1f1f91e7b8b243aa815"><code>f085b62</code></a> sync: notify receivers in mpsc <code>OwnedPermit::release()</code> method (<a href="https://redirect.github.com/tokio-rs/tokio/issues/8075">#8075</a>)</li> <li><a href="https://github.com/tokio-rs/tokio/commit/30d25ccb8bc91ca811773ee243e71e31772275d2"><code>30d25cc</code></a> sync: require that an <code>RwLock</code> has <code>max_readers != 0</code> (<a href="https://redirect.github.com/tokio-rs/tokio/issues/8076">#8076</a>)</li> <li><a href="https://github.com/tokio-rs/tokio/commit/9fccf5339d41c1f2f863f97b9133bc8a5a10bc28"><code>9fccf53</code></a> sync: return <code>Empty</code> from <code>try_recv()</code> when mpsc is closed with outstanding p...</li> <li><a href="https://github.com/tokio-rs/tokio/commit/ebf61b45b5184018f00bc666887ebccf3d4fe51b"><code>ebf61b4</code></a> sync: fix underflow in mpsc channel <code>len()</code> (<a href="https://redirect.github.com/tokio-rs/tokio/issues/8062">#8062</a>)</li> <li><a href="https://github.com/tokio-rs/tokio/commit/4abe9d732eb01f7b092a571c3dcc4fbd266f4067"><code>4abe9d7</code></a> chore: prepare Tokio v1.52.2 (<a href="https://redirect.github.com/tokio-rs/tokio/issues/8115">#8115</a>)</li> <li>Additional commits viewable in <a href="https://github.com/tokio-rs/tokio/compare/tokio-1.52.1...tokio-1.52.3">compare view</a></li> </ul> </details> <br /> Dependabot will resolve any conflicts with this PR as long as you don't alter it yourself. You can also trigger a rebase manually by commenting `@dependabot rebase`. [//]: # (dependabot-automerge-start) [//]: # (dependabot-automerge-end) --- <details> <summary>Dependabot commands and options</summary> <br /> You can trigger Dependabot actions by commenting on this PR: - `@dependabot rebase` will rebase this PR - `@dependabot recreate` will recreate this PR, overwriting any edits that have been made to it - `@dependabot show <dependency name> ignore conditions` will show all of the ignore conditions of the specified dependency - `@dependabot ignore <dependency name> major version` will close this group update PR and stop Dependabot creating any more for the specific dependency's major version (unless you unignore this specific dependency's major version or upgrade to it yourself) - `@dependabot ignore <dependency name> minor version` will close this group update PR and stop Dependabot creating any more for the specific dependency's minor version (unless you unignore this specific dependency's minor version or upgrade to it yourself) - `@dependabot ignore <dependency name>` will close this group update PR and stop Dependabot creating any more for the specific dependency (unless you unignore this specific dependency or upgrade to it yourself) - `@dependabot unignore <dependency name>` will remove all of the ignore conditions of the specified dependency - `@dependabot unignore <dependency name> <ignore condition>` will remove the ignore condition of the specified dependency and ignore conditions </details> Signed-off-by: dependabot[bot] <support@github.com> Co-authored-by: dependabot[bot] <49699333+dependabot[bot]@users.noreply.github.com>
main
6 hours ago
v3 Step H: replace ocipkg::ImageName with ommx::artifact::ImageRef (#874) ## Summary - Introduces `ommx::artifact::ImageRef`, the OMMX-owned parsed form of an OCI image reference, and migrates every public surface (`LocalArtifact`, `LocalArtifactBuilder`, SQLite Local Registry helpers, CLI parse, PyO3 bindings, examples, dataset packaging) off `ocipkg::ImageName`. - Drops `ocipkg` from `Cargo.toml` (workspace + `rust/ommx` + `python/ommx`) and the `ocipkg::*` re-export from the top-level `ommx` crate. The `remote-artifact` feature no longer activates `ocipkg/remote`. - Rewrites the local-registry tests off `ocipkg`'s `OciDirBuilder` / `OciArtifact` to a native fixture that writes `oci-layout` + `index.json` + `blobs/sha256/...` directly, and verifies the save round-trip via the public `inspect_archive` plus a native tar walk. `ImageRef` keeps the same `host[:port]/name:reference` parsing rules and exposes `hostname()` / `port()` / `name()` / `reference()`, plus the v2-cache-compatible `as_path()` / `from_path()`. Field access (`image_name.hostname`) becomes a method call (`image_name.hostname()`). This is the final phase of ARTIFACT_V3.md §12.4 — Step H lands, and the workspace is `ocipkg`-free. ## Test plan - [x] `cargo check --workspace --all-targets` - [x] `cargo clippy --workspace --all-targets -- -D warnings` - [x] `task rust:test` — 538 unit + 9 ignored network-only + 44 doctests pass - [x] `task python:test` — full ommx + adapter suites green (excluding `ommx-jijmodeling-adapter` which is unaffected) - [x] `task python:stubgen` — auto-generated stubs unchanged after the rebuild --------- Co-authored-by: Claude Opus 4.7 (1M context) <noreply@anthropic.com>
main
6 hours ago
v3 ocipkg removal Steps D+F: native remote transport + native tar I/O (#872) ## Summary Lands Steps **D** and **F** of the §12.4 ocipkg-removal roadmap, and adopts the "archive is purely an exchange format" model from Codex's review feedback. After this PR the SDK no longer references the ocipkg `OciArchive` / `OciArchiveBuilder` / `OciDir` / `OciDirBuilder` / `OciArtifact` / `Image` / `ImageBuilder` types or the ocipkg `Remote` / `RemoteBuilder` / `auth_from_env` surface — only `ocipkg::ImageName` remains, which Step H replaces with an OMMX-owned `ImageRef`. ### Step D — native remote transport for Archive / pull paths `Artifact<OciArchive>::push` now uses the v3 `RemoteTransport` (oci-client) wrapper introduced in Step B. `pull_image` writes blobs straight into `FileBlobStore` and publishes the manifest + ref in a single SQLite transaction — no temp OCI Image Layout staging. `Artifact<OciDir>::push`, `Artifact<Remote>`, `Artifact::from_remote`, and the standalone `auth_from_env` helper are removed; dataset loaders (`miplib2017`, `qplib`), the CLI Inspect / Push paths, and `examples/pull_artifact.rs` are migrated to `pull_image` + `LocalArtifact`. CLI `Inspect <remote-ref>` keeps the manifest-only fetch via a new `fetch_remote_manifest` helper (no SQLite write). `RemoteTransport` grows `auth_for(op)`, `pull_manifest_raw`, and `pull_blob_to_vec`. The pull-blob path goes through `pull_blob_stream` so `FileBlobStore::put_bytes` is the single digest-verification point. `pull_blob_to_vec` takes the manifest- declared `expected_size` and caps `Vec::with_capacity` at it; both the registry's `Content-Length` and the accumulated chunk size are rejected if they exceed the declared size — a malicious / broken registry cannot force a runaway allocation before any digest check would catch the body. `pull_image` bails on `Conflicted` rather than returning it as `Ok(...)`: every caller (Python `Artifact.load`, CLI `ommx pull`, dataset loaders) treats a successful return as "the pulled bytes are now resident", so the silent fall-through was unsafe under tag-race / registry-mutation. ### Step F — native tar I/O + archive becomes a pure exchange format `LocalArtifact::save` is a direct `tar` crate writer producing a strict OCI Image Layout archive (`oci-layout` + `index.json` + `blobs/<algorithm>/<encoded>`). Manifest bytes are written verbatim so the archive manifest digest is byte-identical to the source SQLite digest. `tar::HeaderMode::Deterministic` keeps output reproducible. The output is opened with `OpenOptions::create_new(true)` to close the TOCTOU window between an `exists()` probe and the open. `import::archive::import_oci_archive` is a native single-pass tar reader: blobs land directly in `FileBlobStore` during the scan, `index.json` + `oci-layout` are captured for the post-pass parse, and one `publish_artifact_atomic` transaction commits the manifest + ref. Archives missing the optional `oci-layout` marker (v2-era output / older oras / crane) are accepted with a warning. **Archive load semantics shift**: v3 treats `.ommx` archives as a pure exchange format. There is no "open archive in place" path — the ocipkg-typed `Artifact<OciArchive>` and the intermediate `OmmxArchive` struct are both gone, along with `Artifact<Base: Image>` / `Artifact<OciDir>`. Workflow: - **Loading from an archive**: `Artifact.load_archive(file)` imports the archive into the user's persistent SQLite Local Registry and returns a `LocalArtifact` handle. Subsequent `Artifact.load(image_name)` calls resolve from SQLite without re-importing. - **Inspecting an archive**: CLI `ommx inspect <archive>` reads the manifest via a new native tar pre-scan (`local_registry::read_archive_manifest`) without any registry side effect. - **Pushing an archive**: CLI `ommx push <archive>` bails with a migration hint pointing at `ommx load <file>` then `ommx push <image_name>`. v3 pushes always source from the SQLite Local Registry. - **Building an archive**: `ArchiveArtifactBuilder::build()` builds into the user's persistent SQLite Local Registry **and** saves the archive file out; the temp-registry / drop-guard pattern is gone. Returns `LocalArtifact` directly. `new_archive_unnamed` is removed — v3 requires every artifact to be addressable by ref. Python's `ArtifactInner` enum collapses to a single struct backed by `LocalArtifact`. CLI `Inspect <oci-dir>` likewise reads the manifest blob directly from disk (no SQLite mutation for a read-only op). ## Test plan - [x] `task rust:test` — 522 unit + 44 doctest + 9 ignored (auth_e2e via testcontainers) - [x] `task python:test` — full Python suite + doctests + linters - [x] `cargo clippy -p ommx --all-targets --features remote-artifact,cli,built -- -D warnings` - [x] `cargo fmt --all -- --check` - [x] `cargo build -p ommx --examples --features remote-artifact,cli,built` - [ ] CI auth_e2e (`--include-ignored auth_e2e`) — anonymous push, docker-config auth, env override, env-beats-docker, load-then-push from archive, pull round-trip --------- Co-authored-by: Claude Opus 4.7 (1M context) <noreply@anthropic.com>
main
13 hours ago
Drop legacy disk OCI dir cache from v3 import / save / load paths (#871) ## Summary Implements §12.3 **Step C** from `ARTIFACT_V3.md` and lays out the remaining ocipkg-removal roadmap in §12.4. After this PR, the v3 SQLite Local Registry no longer maintains the v2-era on-disk OCI Image Layout cache — SQLite + `FileBlobStore` are the sole post-import home of every v3 artifact. ### Step C (§12.3) — drop the legacy disk OCI dir cache * `import::archive::import_oci_archive` and `import::remote::pull_image` stage into a `tempfile::TempDir` under the registry root and drop it on return. No more promotion to `registry.root().join(image_name)`. * `pull_image` short-circuits the network fetch when SQLite already resolves the image ref **and** the manifest blob is present in `FileBlobStore`. A SQLite ref with a missing blob (registry corruption, interrupted import) falls through to a fresh pull with a `tracing::warn!` rather than handing back a stale `Unchanged` that would later surface as an opaque `get_blob` failure. * New `LocalArtifact::save(output)` streams `.ommx` archives directly from SQLite via `OciArchiveBuilder::add_blob`, asserting each rehash matches the recorded manifest digest. * CLI `Push` / `Inspect` / `Save` route the `Local(name)` branch through `LocalArtifact::open`, which surfaces the `ommx artifact import` migration hint on SQLite miss. Two helpers share that hint: `bail_not_found_locally` always bails (used by `Push`); `migration_hint_if_legacy_only` returns `Ok(())` when no legacy dir exists, letting `Inspect` keep its remote fallback for genuinely-remote refs while still bailing locally for pre-v3 artifacts. * Python `ArtifactInner` collapses to `{Archive, Local}` (the v2 `OciDir` reader variant is gone). `Artifact.load_archive(dir_path)` imports the OCI Image Layout into the user's default SQLite Local Registry and returns a `Local` handle; the docstring now spells out that side effect and points users at the archive path alternative for transient reads. The file case is unchanged. `BuilderInner::Dir` renamed to `Local` (it always wrapped `LocalArtifactBuilder`). `Artifact<OciArchive>::push` is left on the legacy ocipkg path; the unification with the new transport is **Step D** in §12.4 below. ### §12.4 — ocipkg removal milestone series (D → F → H) The remaining ocipkg surface is broken into three independent PR-sized steps: * **D** — extend the Step B `oci-client` transport to `Artifact<OciArchive>::push` and replace `Artifact<Remote>::pull_to` with a native streaming pull straight to `FileBlobStore`. Drops ocipkg `Remote` / `RemoteBuilder` and `auth_from_env`. * **F** — native tar reader / writer for `.ommx` archives, dropping `OciArchive` / `OciDir` / `OciArtifact` / `Image` / `ImageBuilder`. `Artifact<Base: Image>` collapses to a single struct. * **H** — replace `ocipkg::ImageName` in public APIs with an `ommx::artifact::ImageRef` new type wrapping `oci_client::Reference`. Breaking change; must land before v3.0 stable. D and F are independent (network vs local format); H follows both. The doc calls out that D should not extend `FileBlobStore`'s write API beyond Step B's surface to avoid forcing F to redesign mid-PR. ## Pre-v3 user migration Users with only the v2 path-tree layout under `registry.root()` now hit the `ommx artifact import` migration hint instead of either an opaque "image not found" or a silent remote fetch. The existing `ommx artifact import` subcommand performs the identity-preserving migration into SQLite. ## Test plan - [x] `cargo test -p ommx --features remote-artifact,cli` — 521 unit tests + 44 doctests passing - [x] Three new Step-C invariant tests: - `import_oci_archive_does_not_leave_legacy_dir_behind` - `pull_image_short_circuits_when_ref_is_present_with_blob` - `pull_image_does_not_short_circuit_when_manifest_blob_is_missing` - [x] `cargo build --bin ommx --features remote-artifact,cli,built` - [x] `cargo fmt --check` clean; `cargo clippy` no new warnings on changed files - [x] `task python:test` (full Python suite + adapters) passing - [x] `cargo test -p ommx --features remote-artifact,built,cli --test auth_e2e` remains green (no semantic change to auth flow) - [ ] Smoke: `ommx load <archive>` → `ommx inspect <ref>` → `ommx save <ref> <out>` round-trip on a fresh tempdir registry 🤖 Generated with [Claude Code](https://claude.com/claude-code) --------- Co-authored-by: Claude Opus 4.7 (1M context) <noreply@anthropic.com>
main
1 day ago
Fix clippy warnings under --all-targets and tighten lint coverage (#870) ## Summary - Resolve all `cargo clippy --all-targets -- -D warnings` failures so the lint can be run cleanly across the lib, tests, and examples. - Extend CI and Taskfile to actually exercise `--all-targets`, so future regressions in tests/examples surface on PR checks instead of being noticed locally. ## What changed **Lint fixes** - Ran `cargo clippy --fix` to clear auto-fixable warnings — mostly `needless_borrow` / `explicit_auto_deref` in the PyO3 binding files (`python/ommx/src/*.rs`), plus a few smaller spots in `rust/ommx/`. - `rust/ommx/src/mps/convert.rs`: factored two complex return tuples into `ConvertedDecisionVariables` and `ConvertedConstraints` type aliases (`clippy::type_complexity`). - `rust/ommx/src/instance/convert.rs`: replaced four `Default::default()` + field-reassign patterns in tests with struct-literal initialization (`clippy::field_reassign_with_default`). **Lint coverage** - `.github/workflows/rust.yml`: `clippy-action` now runs with `--all-targets -- -Dwarnings` so tests and examples are linted on CI, not just lib/bin. - `rust/Taskfile.yml`: `task rust:clippy` now matches the CI invocation (`cargo clippy --all-targets -- -D warnings`), so the same check is one command away locally. ## Test plan - [ ] CI `clippy` job passes with the new `--all-targets` flag. - [ ] `task rust:clippy` runs cleanly locally. 🤖 Generated with [Claude Code](https://claude.com/claude-code) Co-authored-by: Claude Opus 4.7 (1M context) <noreply@anthropic.com>
main
1 day ago
Native LocalArtifact push via oci-client transport (#867) ## Summary - Replace the transitional `LocalArtifact` push path that materialised a legacy on-disk OCI directory before delegating to `ocipkg` with a direct SQLite + CAS → remote registry stream. - Bring in [`oci-client`](https://github.com/oras-project/rust-oci-client) (ORAS project, the actively-maintained successor to `oci-distribution`) as the OCI Distribution transport. `ocipkg` remains in place for the archive build path and the legacy import staging area, and will be revisited in Step C. - Add a new `artifact::remote_transport` module that owns a private current-thread `tokio` runtime and exposes a sync API to the rest of the SDK. Later milestones can expand the async boundary outward without rewriting callers, and ultimately surface it to Python via `pyo3-async-runtimes`. - Add a three-tier credential resolver (env override → docker config + helpers → anonymous) so an existing `docker login` / `gcloud auth configure-docker` / `aws ecr get-login-password` session is reused without copying credentials into env vars. OMMX does not own a credential store; the lookup is delegated to the [`docker_credential`](https://github.com/keirlawson/docker_credential) crate (MIT/Apache-2.0). - Route `ommx push <image>` CLI through the same `LocalArtifact::push()` path as the Python API, so a CLI user sees the same behaviour (including #606's GCAR fix) as a Python user. `ImageNameOrPath::parse` now prefers the SQLite Local Registry over the legacy disk OCI dir. - End-to-end auth coverage via `testcontainers`: 8 scenarios in `tests/auth_e2e.rs` validate every tier of the credential resolver (anonymous, docker config alone, env override, env precedence, wrong-credential rejection, partial-override bail) plus the CLI dispatch, all against real ephemeral `registry:2` containers. ## Design notes - **Manifest bytes round-trip exactly.** The SQLite-resident manifest bytes are pushed verbatim via `oci_client::Client::push_manifest_raw`, so the registry-side digest agrees byte-for-byte with the local manifest digest. The typed `OciManifest` round-trip would risk perturbing field order and optional-field rendering (`annotations: {}`, `subject`), which would change the digest. - **`oci-spec` versions coexist.** ommx (and `ocipkg`) pull `oci-spec 0.8.4`; `oci-client` brings `oci-spec 0.9.0`. The transport wrapper only converts at the boundary by stringifying `ocipkg::ImageName` and parsing into `oci_client::Reference`, so the two type universes never meet. - **Credentials.** `oci-client` only accepts pre-resolved `RegistryAuth::{Anonymous, Basic, Bearer}`, so the SDK has to materialise one of those for every push. The resolver tries `OMMX_BASIC_AUTH_*` first (explicit CI override), then `~/.docker/config.json` / `$DOCKER_CONFIG` (with credential helpers invoked transparently by `docker_credential`), then anonymous. Credential lookup is keyed on `host[:port]` (matching `docker login localhost:5000`), `DockerCredential::IdentityToken` maps to `RegistryAuth::Bearer`, and a partial env-var override (DOMAIN set but a credential variable missing) errors loudly rather than silently falling through. Helper failures are non-fatal: warn via tracing without the helper's stdout/stderr (to avoid leaking tokens from a malformed-JSON failure), then fall through. - **CLI parity.** The CLI's `ImageNameOrPath::Local` previously routed to `Artifact::from_oci_dir(get_image_dir(&name)).push()` (ocipkg). It now resolves through `LocalArtifact::try_open(name)`; if SQLite has the image, `LocalArtifact::push()` runs. The legacy disk OCI dir is kept as a fallback so pre-v3 user state remains addressable until Step C removes it. - **Auth e2e tests.** `rust/ommx/tests/auth_e2e.rs` brings up its own `registry:2` containers via `testcontainers` (anonymous + htpasswd flavours), populates the credentials the SDK is supposed to discover, and pushes a real artifact. All tests are `#[ignore = "requires docker"]` + `#[serial]`; `cargo test` skips them by default and CI runs them with `--include-ignored --test-threads=1`. An `EnvGuard` wipes every auth env var on entry/exit so failing tests can't leak state. - Removed `LocalArtifact::registry_root()` (added in #864 only to support the transitional Python push fallback that this PR deletes). ## Scope (per ARTIFACT_V3.md §12.3 Step B) - `LocalArtifact::push()` is native. Per PR #869 (Step B', merged), the SQLite Local Registry stores OCI Image Manifest with `artifactType` only, so the push path is uniform: empty config blob + each entry in `layers[]` + manifest bytes with `application/vnd.oci.image.manifest.v1+json` Content-Type. - `Artifact<OciArchive>::push` and `Artifact<OciDir>::push` stay on `ocipkg`. Migrating those is part of Step C. - `ommx push <image>` (CLI) and `Artifact.push()` (Python) both use the native path for SQLite-resident images. - `Inspect` for `ImageNameOrPath::Local` is updated to read from SQLite first (then fall back to legacy disk dir); `Save` still uses the legacy dir directly (read path, Step C scope). - Pull paths are unchanged; `local_registry::import::remote` still goes through `ocipkg` for stage 1. ## Related - Issue Jij-Inc/ommx#606 (GCAR push fails inside `ocipkg::distribution::auth::AuthChallenge::try_from` JSON parse). Expected to be addressed by switching transport away from `ocipkg`, but **not auto-closed** — needs to be verified against the reporter's Google Cloud Artifact Registry scenario before closing. The new docker-config credential path should also resolve the `gcloud auth configure-docker` flow end-to-end. ## Test plan - [x] `cargo test -p ommx --features remote-artifact` — 518 unit tests (+9 credential resolver / port-key tests), 44 integration / doctests pass. - [x] `cargo test -p ommx --features remote-artifact,built,cli --test auth_e2e -- --include-ignored --test-threads=1` — 8 e2e scenarios pass against ephemeral `registry:2` containers (anonymous + htpasswd). - [x] `cargo build --bin ommx --features remote-artifact,built,cli` — CLI binary builds clean. - [x] `task python:test` on the package — passes. - [x] `cargo clippy -p ommx --features remote-artifact,built,cli --all-targets` — no new warnings on `push.rs` / `remote_transport.rs` / `manifest.rs` / `bin/ommx.rs` / `tests/auth_e2e.rs`. - [ ] Smoke-test push to Google Cloud Artifact Registry (Jij-Inc/ommx#606 verification) before closing the issue. 🤖 Generated with [Claude Code](https://claude.com/claude-code) --------- Co-authored-by: Claude Opus 4.7 (1M context) <noreply@anthropic.com>
main
1 day ago
LocalArtifactBuilder builds OCI Image Manifest with artifactType (#869) ## Summary - Switch the SQLite Local Registry's native manifest format from the deprecated OCI Artifact Manifest (`application/vnd.oci.artifact.manifest.v1+json`, removed in OCI Image Spec v1.1) to OCI Image Manifest with the OCI 1.1 `artifactType` field plus the `application/vnd.oci.empty.v1+json` empty config descriptor, per the design unified in PR #868 (ARTIFACT_V3.md §5.5). - This is the §12.3 **Step B'** milestone that unblocks the paused native push work in draft PR #867. `distribution/distribution` v2 (`registry:2`) rejected the Artifact Manifest with `MANIFEST_INVALID`; Image Manifest with `artifactType` is what mainstream registries accept. ## Implementation notes - `LocalArtifactBuilder.stage()` now produces an `OciImageManifestBuilder` manifest and materialises the OCI empty config blob (`{}` / `sha256:44136fa3...`) as one of the staged blobs so the publish path uploads `config + layers` as a single batch. The in-builder field rename `blobs` → `layers` matches OCI Image Manifest terminology. - `LocalManifest` collapses from a 2-variant enum (`Image | Artifact`) to a `LocalManifest(Box<ImageManifest>)` newtype. `LocalManifest::parse` accepts only the Image Manifest media type and rejects the deprecated Artifact Manifest at parse time with a clear error. - `LocalRegistry::publish_artifact_manifest` now validates an `&ImageManifest`. The descriptor count check matches `manifest.layers().len() + 1` (the empty config) against the staged blob count, and the upload manifest is verified against the staged set. - `import::oci_dir` no longer carries an `OciManifestFormat` dispatch; encountering a deprecated Artifact Manifest is now a hard error rather than a sloppy fallback. - Drops `OCI_ARTIFACT_MANIFEST_MEDIA_TYPE` constant + crate-level re-export and the `ensure_ommx_artifact_manifest` validator. Adds `OCI_EMPTY_CONFIG_{MEDIA_TYPE,BYTES,DIGEST}` constants. - Tests: - `builds_native_oci_image_manifest_with_artifact_type` replaces the old Artifact Manifest builder test. - `local_registry_builds_native_image_manifest_with_artifact_type` replaces the symmetric integration test. - `rejects_import_of_deprecated_artifact_manifest_layout` asserts the import rejection path. ## Follow-up - Draft PR #867 (Step B — native SQLite → remote push via `oci-client`) can resume on top of this change. ## Test plan - [x] `cargo test -p ommx --features remote-artifact` — 508 unit tests, 44 integration / doctests pass. - [x] `cargo clippy -p ommx --features remote-artifact --lib` — no new warnings on touched files. - [x] `task python:test` on the package — 37 tests pass (Python binding unaffected because it does not dispatch on manifest format). - [ ] Step B PR #867 reopened on top of this branch and pushed to a local `registry:2` to confirm the `MANIFEST_INVALID` failure is gone. 🤖 Generated with [Claude Code](https://claude.com/claude-code) --------- Co-authored-by: Claude Opus 4.7 (1M context) <noreply@anthropic.com>
main
1 day ago
ARTIFACT_V3: unify Local Registry on OCI Image Manifest (#868) ## Summary - Drop the planned dual-format support (OCI Image Manifest + OCI Artifact Manifest coexistence) from the v3 Artifact design and commit to OCI Image Manifest with `artifactType` + empty config as the single native format. - OCI Image Spec v1.1 removed `application/vnd.oci.artifact.manifest.v1+json`; the recommended pattern is the same Image Manifest plus an `artifactType` discriminator. - `distribution/distribution` v2.x (`registry:2`) does not allow the deprecated Artifact Manifest media type in its manifest-schema allow-list and rejects pushes with `MANIFEST_INVALID`. The draft Step B PR (#867) hit this against a local test registry. - Remove §6.7 "Format convert" — the underlying format is now the same for v2 and v3 OMMX builders; there is nothing to convert. - Reorder §12.3 milestones to insert **Step B'** (refactor `LocalArtifactBuilder` to Image Manifest with `artifactType`) before **Step B** (native SQLite → remote push), and document that PR #867 is paused pending Step B' landing. ## Scope This PR is documentation-only — `ARTIFACT_V3.md` is the only file changed. The code-side cleanup (drop `LocalManifest::Artifact` variant, `OCI_ARTIFACT_MANIFEST_MEDIA_TYPE`, `ensure_ommx_artifact_manifest`, and the `LocalArtifactBuilder` Artifact Manifest generation path) is tracked in §12.2 / §12.3 Step B' as a follow-up PR. ## Test plan - [x] grep `ARTIFACT_V3.md` for `Artifact Manifest` / coexistence wording — only deliberate references remain (deprecation rationale in §5.5, removal TODO in §12, generic "Artifact manifest semantics" wording where ambiguity is unproblematic). - [x] §9.1 manifest example regenerated to show Image Manifest with `artifactType` + empty config. - [x] §12.1 (landed) annotated to explain that `LocalManifest::Artifact` and friends are dead code post this design change. - [ ] Follow-up PR will land the `LocalArtifactBuilder` refactor and remove the Artifact Manifest code paths. 🤖 Generated with [Claude Code](https://claude.com/claude-code) Co-authored-by: Claude Opus 4.7 (1M context) <noreply@anthropic.com>
main
1 day ago

Latest Branches

CodSpeed Performance Gauge
N/A
chore: refresh CodSpeed setup#858
6 days ago
2e4bf32
chore/codspeed-update
CodSpeed Performance Gauge
N/A
20 days ago
ec4ef12
claude/stoic-nobel-76577c
CodSpeed Performance Gauge
N/A
7 months ago
7abe1e8
copilot/fix-cd351290-4957-4ccd-92ca-cb64db14baf1
© 2026 CodSpeed Technology
Home Terms Privacy Docs