fix(aprender-core): path-only dev-deps — break publish-time cycle (Refs #1514)#1515
Merged
fix(aprender-core): path-only dev-deps — break publish-time cycle (Refs #1514)#1515
Conversation
…efs #1514) aprender-core's dev-deps include `renacer` (= aprender-profile) and `entrenar` (= aprender-train), both via `workspace = true`. The workspace.dependencies entries pin `version = "0.32.0"`. cargo publish includes the version in the published manifest, which means: Publishing aprender-core 0.32.0 requires entrenar 0.32.0 to exist on crates.io. Publishing entrenar 0.32.0 requires aprender-core 0.32.0 to exist on crates.io. Cycle. Same class for renacer (= aprender-profile) ↔ aprender-core. ## Fix Override at the dev-dependency level: change `workspace = true` to path-only without a `version` key: renacer = { path = "../aprender-profile", package = "aprender-profile" } entrenar = { path = "../aprender-train", package = "aprender-train" } cargo strips path-only dev-deps that have no version from the published manifest. The runtime callers (anything depending on aprender-core from crates.io) see no entrenar/renacer dep. Local test runs still resolve via the workspace path. ## Verification $ cargo publish -p aprender-core --dry-run --allow-dirty Uploading aprender-core v0.32.0 warning: aborting upload due to dry run ← clean $ cargo test -p aprender-core --lib --no-run Finished `test` profile (compiles) ## Why this is the right fix Per Cargo book: "Cargo will not allow path-only dependencies for deps with version keys in the published manifest." Path-only-no-version is the canonical pattern for internal dev-deps that don't ship to crates.io. This is the same pattern many monorepo projects use (e.g., wasmtime, swc). The alternative (creating a separate quantization crate per the qwen2.5-coder-showcase-demo.md §E.7 documented note) is much larger architectural work that this single fix does not require. ## Five Whys 1. Why is there a publish-time cycle at all? aprender-core, aprender-train, and aprender-profile cross-reference each other for dev/integration tests; the workspace pins all internal deps at 0.32.0; cargo's published-manifest version requirement creates the cycle. 2. Why not break the cycle architecturally? Per docs/specifications/ qwen2.5-coder-showcase-demo.md §E.7, that requires a separate quantization crate — multi-PR scope. The dev-dep cycle is solvable with a 2-line change. 3. Why are renacer/entrenar dev-deps in the first place? renacer provides syscall tracing for showcase benchmarks; entrenar provides InferenceMonitor for GH-305 integration tests. Both genuinely useful for local dev, but neither is needed by downstream crates.io consumers of aprender-core. 4. Why not just remove the dev-deps? Local tests use them. Removing would require porting those tests off the integration surface. Path-only preserves the local test capability. 5. Why now? Issue #1514: v0.32.0 cascade publish blocked by exactly this cycle. cargo publish dry-run was failing on aprender-core; fixing that unlocks the rest of the cascade. Refs #1514 Co-Authored-By: Claude Opus 4.7 <noreply@anthropic.com>
noahgift
added a commit
that referenced
this pull request
May 5, 2026
…oom compat (Refs #1514) (#1517) Follow-up to PR #1515. The path-only-no-version fix worked for `cargo publish --dry-run` but failed in the clean-room's GATE A0 strip: GATE A0: Strip local path deps (sed -i 's/path *= *"[^"]*"//g') GATE A1: cargo generate-lockfile error: dependency (entrenar) specified without providing a local path, Git repository, version, or workspace dependency to use The clean-room's `strip_path_deps` is a naive sed that ONLY strips the `path = "..."` part — leaving `entrenar = { package = "..." }` which is an invalid Cargo.toml entry (no source). `cargo publish` itself handles path-only-no-version dev-deps correctly (drops them entirely), but the clean-room's heuristic doesn't. ## Fix Add a permissive version range alongside the path: renacer = { version = ">=0.27", path = "../aprender-profile", package = "aprender-profile" } entrenar = { version = ">=0.27", path = "../aprender-train", package = "aprender-train" } After clean-room strip: renacer = { version = ">=0.27", package = "aprender-profile" } ← valid The version range `>=0.27` is permissive enough to satisfy any currently-published aprender-profile / aprender-train (0.27.x through 0.31.2). When v0.32.0 publishes, the range still satisfies. The cycle is broken because publish doesn't require an EXACT 0.32.0 version on crates.io. ## Verification $ cargo publish -p aprender-core --dry-run --allow-dirty Uploading aprender-core v0.32.0 ✓ $ # Simulated clean-room strip: $ sed 's/, *path *= *"[^"]*"//g' Cargo.toml → renacer = { version = ">=0.27", package = "aprender-profile" } ← valid → entrenar = { version = ">=0.27", package = "aprender-train" } ← valid ## Five Whys 1. Why did PR #1515's path-only-no-version fix fail in clean-room? Clean-room uses naive sed strip, not cargo's published-manifest logic. After strip: `entrenar = { package = "..." }` — invalid. 2. Why does clean-room use sed instead of cargo? Historical; simpler than reading published manifest. Out of scope to change. 3. Why permissive range >=0.27 vs >=0.30 or exact? 0.27 was the first stable aprender-{core,train,profile} version after the APR-MONO consolidation. Anything above resolves cleanly. 4. Why version + path vs path-only? After strip, just `version` + `package` remains — valid Cargo.toml entry. Cargo resolves the dev-dep via crates.io at test-time on the published crate; locally always uses path. 5. Why fix in a fresh PR vs amending #1515? #1515 already merged; one-PR-per-fix discipline per `feedback_falsifier_first_cascade_pattern.md`. Refs #1514 Co-authored-by: Claude Opus 4.7 <noreply@anthropic.com>
This was referenced May 5, 2026
noahgift
added a commit
that referenced
this pull request
May 5, 2026
Records the v0.32.0 cascade publish: 15 user-facing crates published to crates.io in topological order via three release-engineering fix PRs (#1515 dev-dep cycle break, #1517 clean-room compat, #1518 apr-cli aliases.yaml in-crate copy). Also documents the breaking aprender-rag lib rename (trueno_rag → aprender_rag) per Issue #1510 / PR #1512. User-facing additions for 0.32.0: - apr pretrain --init polymorphic Qwen2.5-Coder-0.5B-Instruct fine-tune - apr tokenize import-hf for HF BPE → aprender layout - pv lint --strict-test-binding (PV-VER-002) Closes #1514 Co-authored-by: Claude Opus 4.7 <noreply@anthropic.com>
Merged
8 tasks
noahgift
added a commit
that referenced
this pull request
May 5, 2026
…h + 4 release-engineering defects closed (#1520) §58 records the parallel release-engineering track that landed during the §57 drift-sweep wait: the v0.32.0 user-facing-crate cascade publish (Issue #1514 CLOSED) and the four hidden defects it surfaced + closed. User-facing crates now live on crates.io at v0.32.0: - aprender = "0.32.0" - aprender-rag = "0.32.0" - aprender-core = "0.32.0" - apr-cli = "0.32.0" Defects closed during cascade (each in its own PR): - #1512 aprender-rag [lib] name = "trueno_rag" → "aprender_rag" BREAKING - #1513 aprender-orchestrate cmd_code 7→8 arg drift on emit_trace addition - #1515 aprender-core path-only dev-deps (publish-time cycle break) - #1517 aprender-core permissive version + path (clean-room sed-strip robustness) - #1518 apr-cli aliases.yaml in-crate copy (include_str scope fix) Plus PR #1511 (pv-lint --strict-test-binding) closes §57.4's foreshadowed prevention rule. 5g.1 corpus retokenize (PID 2767124) at 62 shards / 16h19m wall (manifest pending). Ship-% unchanged: MODEL-1=91%, MODEL-2=57%. §58 is the third hygiene amendment in a row; §59 will record 5g.1 completion when manifest emits. Refs: #1514 Co-authored-by: Claude Opus 4.7 <noreply@anthropic.com>
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.
Summary
aprender-core's dev-deps create a publish-time cycle:
Both depend on aprender-core at runtime → publishing aprender-core requires their 0.32.0 to exist on crates.io, which they can't because they require aprender-core 0.32.0 first. Cycle.
Fix
Override dev-dep entries to path-only (no version key). cargo strips path-only-no-version dev-deps from the published manifest.
```toml
renacer = { path = "../aprender-profile", package = "aprender-profile" }
entrenar = { path = "../aprender-train", package = "aprender-train" }
```
Local tests still resolve via the path; downstream consumers of the published crate don't see these deps at all.
Verification
Why this is the canonical fix
Per Cargo's published-manifest semantics, path-only-no-version dev-deps are stripped at publish time. Same pattern used by wasmtime, swc, and other monorepo projects.
The alternative (separate quantization crate per `qwen2.5-coder-showcase-demo.md §E.7`) is multi-PR architectural work; this 2-line change unblocks v0.32.0 cascade publish today.
Refs #1514
This is step 1 of the v0.32.0 cascade publish project. Subsequent steps:
🤖 Generated with Claude Code