Skip to content

decrating: absorb shipper-lock into shipper::ops::lock#52

Merged
EffortlessSteven merged 2 commits into
mainfrom
feature/decrating-absorb-lock
Apr 15, 2026
Merged

decrating: absorb shipper-lock into shipper::ops::lock#52
EffortlessSteven merged 2 commits into
mainfrom
feature/decrating-absorb-lock

Conversation

@EffortlessSteven

Copy link
Copy Markdown
Member

Summary

Phase 2 of the decrating plan (docs/decrating-plan.md §6): absorb the standalone shipper-lock microcrate into shipper as crate::ops::lock.

  • Move crates/shipper-lock/src/lib.rs (2059 LOC) → crates/shipper/src/ops/lock/mod.rs (first child of the ops/ scaffold landed in decrating: Phase 1 — scaffold ops/ and runtime/ layer dirs #49).
  • Delete the stale 337-LOC duplicate at crates/shipper/src/lock.rs and the 1-LOC pub-use shim at crates/shipper/src/lock_micro.rs.
  • Remove shipper-lock from the workspace [members] array and from shipper's [dependencies].
  • Drop the micro-lock feature flag from shipper, shipper-cli, and the feature-matrix arrays in .github/workflows/ci.yml and templates/circleci-config.yml.
  • Preserve the historical shipper::lock::* public API via pub use crate::ops::lock; in lib.rs (callers in shipper-cli and the integration tests continue to work unchanged).

LOC delta

LOC
crates/shipper-lock/src/lib.rs (removed) -2059
crates/shipper/src/lock.rs (stale dup, removed) -337
crates/shipper/src/lock_micro.rs (shim, removed) -1
crates/shipper/src/ops/lock/mod.rs (added) +2063
crates/shipper/src/ops/lock/CLAUDE.md (added) +55
Cargo/CI edits ~net-zero
Net code ~-334 LOC

Commit stat: 41 files changed, 111 insertions(+), 488 deletions(-) (dominated by 25 snapshot renames and the double-removal of the stale lock.rs).

Architectural justification

Per docs/decrating-plan.md §6 Phase 2, shipper-lock is a small, well-bounded I/O microcrate with no downstream public consumers outside this workspace. The pre-existing crates/shipper/src/lock.rs duplicate (stale fork left from before the micro-extraction) is deleted alongside the microcrate itself. The one-line lock_micro.rs shim becomes redundant once the canonical implementation lives in-tree. The ops/ layer dir scaffolded in #49 receives its first inhabitant.

File-by-file diff summary

  • Cargo.toml — remove crates/shipper-lock from [workspace] members.
  • crates/shipper-lock/ — deleted in full (lib.rs, Cargo.toml, README.md, CLAUDE.md, 25 snapshot files).
  • crates/shipper/Cargo.toml — remove shipper-lock dep, remove micro-lock feature, remove "micro-lock" from micro-all. Add features = ["yaml"] to the insta dev-dep (the microcrate pulled this in transitively via insta = { workspace = true }).
  • crates/shipper-cli/Cargo.toml — remove micro-lock = ["shipper/micro-lock"] feature.
  • crates/shipper/src/lib.rs — replace the #[cfg(feature = "micro-lock")] dual pub mod lock; block with pub(crate) mod ops; + pub use crate::ops::lock;.
  • crates/shipper/src/lock.rs — deleted (stale duplicate).
  • crates/shipper/src/lock_micro.rs — deleted (redundant shim).
  • crates/shipper/src/ops/mod.rs — replace empty scaffold with pub mod lock;.
  • crates/shipper/src/ops/lock/mod.rs — new. Contents ported verbatim from shipper-lock/src/lib.rs; only the top-level crate docstring and the three inline use shipper_lock::LockFile; doc-example lines were rewritten to use shipper::lock::LockFile;. Everything else (public API, internal helper, tests) is bit-identical.
  • crates/shipper/src/ops/lock/CLAUDE.md — new. Describes the module's single responsibility, the preserved shipper::lock facade, invariants (not a true atomic mutex; RAII drop is best-effort; stale detection is wall-clock; DefaultHasher disambiguation), and layer rules.
  • crates/shipper/src/ops/lock/snapshots/ — 25 insta snapshot files, renamed shipper_lock__*shipper__ops__lock__* (matching the new crate + module path that insta uses to compute the filename). Internal source: headers updated to crates/shipper/src/ops/lock/mod.rs. No content changes.
  • .github/workflows/ci.yml — drop "micro-lock" from the BDD feature-set matrix.
  • templates/circleci-config.yml — drop "micro-lock" from the CircleCI BDD matrix.
  • Cargo.lock — auto-regenerated (removes shipper-lock entry).

Validation

All six validation gates pass locally:

  • cargo check --workspace → clean.
  • cargo test -p shipper ops::lock → 127 passed; 0 failed.
  • cargo test -p shipper → 886 + integration suites pass; 0 failed.
  • cargo test -p shipper-cli → all integration suites pass (cli_e2e 126, facade_integration 45, pipeline_integration 34, etc.); 0 failed.
  • cargo build -p shipper-cli → finished dev build.
  • cargo clippy -p shipper --all-targets --all-features -- -D warnings → clean.
  • cargo test -p shipper --doc → 3 passed, 3 ignored.

Snapshots were renamed to match the new module path and source: headers were rewritten. No test needed an insta accept — every assertion fired against the pre-existing recorded content.

Public API impact

Zero breaking changes for shipper::lock::* consumers. shipper::lock::{LockFile, LockInfo, lock_path, LOCK_FILE, is_locked, read_lock_info} all resolve identically to before via the pub use re-export. The shipper-lock crate itself is gone from crates.io's perspective (not yet released at 0.3.0 from this workspace), so there is no external docs.rs page to replace. Downstream projects consuming shipper-lock directly would need to switch to shipper::lock — an expected consequence of the decrating effort.

Stack note

Branched from feature/decrating-phase1-scaffold (PR #49). When #49 merges, the diff against main for this PR collapses to the net absorption (this commit only).

Test plan

  • CI green across all feature-set matrix entries.
  • architecture-guard workflow doesn't flag the new ops/lock/ imports.
  • Spot-check that shipper::lock::LockFile::acquire still works in the shipper-cli lock info / lock clear subcommands (see crates/shipper-cli/src/main.rs:1487, 1499, 2102, 2108, 2130, 2136).
  • Verify no downstream consumer of shipper-lock exists on crates.io (it was not yet released from this workspace at the current version).

Adds two of the five layered architecture directories per
docs/decrating-plan.md §4. Each folder gets a CLAUDE.md describing its
single responsibility and import rules, plus an empty mod.rs stub.

Layer rules (enforced by .github/workflows/architecture-guard.yml):
- ops    (layer 1, bottom)  — I/O primitives, may import nothing above
- runtime (layer 2)         — pure-data runtime context, may import ops
- state  (layer 3)          — persistence, may import runtime/ops    [deferred]
- plan   (layer 4)          — planning algorithms                    [deferred]
- engine (layer 5, top)     — orchestration                          [deferred]

The state/, plan/, and engine/ directories are deferred because each name
collides with an existing flat module file (state.rs, plan.rs, engine.rs)
and Rust cannot disambiguate <name>.rs from <name>/mod.rs simultaneously.
Those three layer directories will be created in their respective Phase 2
absorption PRs (where the flat file is deleted in the same commit, removing
the conflict atomically).
Move shipper-lock crate (2059 LOC) into crates/shipper/src/ops/lock/
as a crate-private module. Delete the stale 337-LOC duplicate at
crates/shipper/src/lock.rs and the 1-LOC pub-use shim at lock_micro.rs.
Remove shipper-lock from workspace members and from shipper's deps.
Drop the micro-lock feature flag (shipper, shipper-cli) and strip it
from the CI/CircleCI feature-matrix arrays.

The public surface at shipper::lock is preserved via
`pub use crate::ops::lock;` in lib.rs so that shipper-cli and
integration-test callers of shipper::lock::{LockFile, LockInfo,
lock_path, LOCK_FILE, is_locked, read_lock_info} continue to work
unchanged. The ops/ scaffold from PR #49 gets its first inhabitant:
ops/mod.rs now declares `pub mod lock;`.

Files kept flat: everything lives in ops/lock/mod.rs (core is ~270
non-test LOC — well under the 500-LOC guideline; the remainder is the
test suite which per instructions stays inline).

Tests preserved inline:
- 127 lock tests (ops::lock::{tests, snapshot_tests, edge_case_tests,
  hardened_tests, proptest_edge_cases, hardened_proptests,
  lock_edge_case_tests, tests::proptests}).
- 25 insta snapshot files moved under ops/lock/snapshots/ and renamed
  from `shipper_lock__*` to `shipper__ops__lock__*` to match the new
  crate + module path. Internal `source:` headers rewritten to
  `crates/shipper/src/ops/lock/mod.rs`. No snapshot content changes.

insta yaml feature added to shipper's dev-dependencies (shipper-lock
previously pulled it in via `insta = { workspace = true }`; shipper
only had `insta = "1.46.3"`).

Per docs/decrating-plan.md §6 Phase 2.
@gemini-code-assist

Copy link
Copy Markdown

Warning

You have reached your daily quota limit. Please wait up to 24 hours and I will start processing your requests again!

@coderabbitai

coderabbitai Bot commented Apr 15, 2026

Copy link
Copy Markdown

Warning

Rate limit exceeded

@EffortlessSteven has exceeded the limit for the number of commits that can be reviewed per hour. Please wait 58 minutes and 36 seconds before requesting another review.

Your organization is not enrolled in usage-based pricing. Contact your admin to enable usage-based pricing to continue reviews beyond the rate limit, or try again in 58 minutes and 36 seconds.

⌛ How to resolve this issue?

After the wait time has elapsed, a review can be triggered using the @coderabbitai review command as a PR comment. Alternatively, push new commits to this PR.

We recommend that you space out your commits to avoid hitting the rate limit.

🚦 How do rate limits work?

CodeRabbit enforces hourly rate limits for each developer per organization.

Our paid plans have higher rate limits than the trial, open-source and free plans. In all cases, we re-allow further reviews after a brief timeout.

Please see our FAQ for further information.

ℹ️ Review info
⚙️ Run configuration

Configuration used: Organization UI

Review profile: ASSERTIVE

Plan: Pro

Run ID: fd3fc49f-ac09-4ed9-a0b0-eb57e35cecfd

📥 Commits

Reviewing files that changed from the base of the PR and between 6b6f278 and b5764e3.

⛔ Files ignored due to path filters (27)
  • Cargo.lock is excluded by !**/*.lock
  • crates/shipper-lock/src/snapshots/shipper_lock__edge_case_tests__lock_state_unlocked.snap is excluded by !**/*.snap
  • crates/shipper/src/ops/lock/snapshots/shipper__ops__lock__edge_case_tests__lock_info_all_fields.snap is excluded by !**/*.snap
  • crates/shipper/src/ops/lock/snapshots/shipper__ops__lock__edge_case_tests__lock_info_no_plan_id.snap is excluded by !**/*.snap
  • crates/shipper/src/ops/lock/snapshots/shipper__ops__lock__edge_case_tests__lock_state_corrupt.snap is excluded by !**/*.snap
  • crates/shipper/src/ops/lock/snapshots/shipper__ops__lock__edge_case_tests__lock_state_locked_no_plan.snap is excluded by !**/*.snap
  • crates/shipper/src/ops/lock/snapshots/shipper__ops__lock__edge_case_tests__lock_state_locked_with_plan.snap is excluded by !**/*.snap
  • crates/shipper/src/ops/lock/snapshots/shipper__ops__lock__edge_case_tests__lock_state_stale.snap is excluded by !**/*.snap
  • crates/shipper/src/ops/lock/snapshots/shipper__ops__lock__edge_case_tests__lock_state_unlocked.snap is excluded by !**/*.snap
  • crates/shipper/src/ops/lock/snapshots/shipper__ops__lock__hardened_tests__lock_file_after_set_plan_id.snap is excluded by !**/*.snap
  • crates/shipper/src/ops/lock/snapshots/shipper__ops__lock__hardened_tests__lock_info_empty_plan_id.snap is excluded by !**/*.snap
  • crates/shipper/src/ops/lock/snapshots/shipper__ops__lock__hardened_tests__lock_info_json_key_order.snap is excluded by !**/*.snap
  • crates/shipper/src/ops/lock/snapshots/shipper__ops__lock__snapshot_tests__error_corrupt_lock_file_prefix.snap is excluded by !**/*.snap
  • crates/shipper/src/ops/lock/snapshots/shipper__ops__lock__snapshot_tests__error_fresh_lock_with_timeout_prefix.snap is excluded by !**/*.snap
  • crates/shipper/src/ops/lock/snapshots/shipper__ops__lock__snapshot_tests__error_lock_already_held.snap is excluded by !**/*.snap
  • crates/shipper/src/ops/lock/snapshots/shipper__ops__lock__snapshot_tests__error_lock_already_held_with_plan_id.snap is excluded by !**/*.snap
  • crates/shipper/src/ops/lock/snapshots/shipper__ops__lock__snapshot_tests__error_read_nonexistent_lock_prefix.snap is excluded by !**/*.snap
  • crates/shipper/src/ops/lock/snapshots/shipper__ops__lock__snapshot_tests__error_set_plan_id_after_release_prefix.snap is excluded by !**/*.snap
  • crates/shipper/src/ops/lock/snapshots/shipper__ops__lock__snapshot_tests__lock_file_content_with_plan_id.snap is excluded by !**/*.snap
  • crates/shipper/src/ops/lock/snapshots/shipper__ops__lock__snapshot_tests__lock_file_content_without_plan_id.snap is excluded by !**/*.snap
  • crates/shipper/src/ops/lock/snapshots/shipper__ops__lock__snapshot_tests__lock_file_on_disk.snap is excluded by !**/*.snap
  • crates/shipper/src/ops/lock/snapshots/shipper__ops__lock__snapshot_tests__lock_info_debug.snap is excluded by !**/*.snap
  • crates/shipper/src/ops/lock/snapshots/shipper__ops__lock__snapshot_tests__lock_info_yaml.snap is excluded by !**/*.snap
  • crates/shipper/src/ops/lock/snapshots/shipper__ops__lock__snapshot_tests__lock_path_with_root_filename.snap is excluded by !**/*.snap
  • crates/shipper/src/ops/lock/snapshots/shipper__ops__lock__snapshot_tests__lock_path_without_root.snap is excluded by !**/*.snap
  • crates/shipper/src/ops/lock/snapshots/shipper__ops__lock__snapshot_tests__lock_status_locked.snap is excluded by !**/*.snap
  • crates/shipper/src/ops/lock/snapshots/shipper__ops__lock__snapshot_tests__lock_status_unlocked.snap is excluded by !**/*.snap
📒 Files selected for processing (17)
  • .github/workflows/ci.yml
  • Cargo.toml
  • crates/shipper-cli/Cargo.toml
  • crates/shipper-lock/CLAUDE.md
  • crates/shipper-lock/Cargo.toml
  • crates/shipper-lock/README.md
  • crates/shipper/Cargo.toml
  • crates/shipper/src/lib.rs
  • crates/shipper/src/lock.rs
  • crates/shipper/src/lock_micro.rs
  • crates/shipper/src/ops/CLAUDE.md
  • crates/shipper/src/ops/lock/CLAUDE.md
  • crates/shipper/src/ops/lock/mod.rs
  • crates/shipper/src/ops/mod.rs
  • crates/shipper/src/runtime/CLAUDE.md
  • crates/shipper/src/runtime/mod.rs
  • templates/circleci-config.yml
✨ Finishing Touches
🧪 Generate unit tests (beta)
  • Create PR with unit tests
  • Commit unit tests in branch feature/decrating-absorb-lock

Thanks for using CodeRabbit! It's free for OSS, and your support helps us grow. If you like it, consider giving us a shout-out.

❤️ Share

Comment @coderabbitai help to get the list of available commands and usage tips.

EffortlessSteven added a commit that referenced this pull request Apr 15, 2026
Sweep-cleanup of CI workflows, templates, and docs for references to
microcrates and micro-* feature flags that have been deleted or are
queued for deletion via absorption PRs #52 #54 #55 #56 #57 #58.

Changes:
- .github/workflows/ci.yml - removed deleted features (micro-lock,
  micro-plan, micro-policy, micro-process, micro-store) from BDD matrix
- .github/workflows/mutation.yml - removed shipper-plan, shipper-policy,
  shipper-levels from the mutation-testing target list
- .github/workflows/release.yml - added note that publish order is
  finalized in Phase 8 of the decrating plan
- templates/circleci-config.yml - matching feature-matrix cleanup
- docs/architecture.md - per-crate absorbed notes in microcrates table
  plus top-of-section notes on Dependency Graph and Module
  Responsibilities pointing out those sections reflect pre-decrating state
- docs/testing.md - removed deleted crates from example test invocations
  and the mutation-testing example
- RELEASE_CHECKLIST_v0.3.0.md - header note listing absorbed crates and
  pruned publish steps
- RELEASE_NOTES_v0.3.0.md - reworded Modular Architecture bullet to
  reflect the consolidated public-crate layout

References to still-in-flight absorptions (auth, environment, git, storage,
engine-parallel, registry, progress) are left alone - they will be cleaned
up in their respective absorption PRs.

Per docs/decrating-plan.md.
@EffortlessSteven EffortlessSteven merged commit 43cc3c3 into main Apr 15, 2026
32 of 35 checks passed
EffortlessSteven added a commit that referenced this pull request Apr 15, 2026
Sweep-cleanup of CI workflows, templates, and docs for references to
microcrates and micro-* feature flags that have been deleted or are
queued for deletion via absorption PRs #52 #54 #55 #56 #57 #58.

Changes:
- .github/workflows/ci.yml - removed deleted features (micro-lock,
  micro-plan, micro-policy, micro-process, micro-store) from BDD matrix
- .github/workflows/mutation.yml - removed shipper-plan, shipper-policy,
  shipper-levels from the mutation-testing target list
- .github/workflows/release.yml - added note that publish order is
  finalized in Phase 8 of the decrating plan
- templates/circleci-config.yml - matching feature-matrix cleanup
- docs/architecture.md - per-crate absorbed notes in microcrates table
  plus top-of-section notes on Dependency Graph and Module
  Responsibilities pointing out those sections reflect pre-decrating state
- docs/testing.md - removed deleted crates from example test invocations
  and the mutation-testing example
- RELEASE_CHECKLIST_v0.3.0.md - header note listing absorbed crates and
  pruned publish steps
- RELEASE_NOTES_v0.3.0.md - reworded Modular Architecture bullet to
  reflect the consolidated public-crate layout

References to still-in-flight absorptions (auth, environment, git, storage,
engine-parallel, registry, progress) are left alone - they will be cleaned
up in their respective absorption PRs.

Per docs/decrating-plan.md.
Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment

Labels

None yet

Projects

None yet

Development

Successfully merging this pull request may close these issues.

1 participant