Skip to content

refactor: unify sidecar-lock, git, serde, sha256 helpers#395

Merged
ScriptedAlchemy merged 1 commit into
masterfrom
codex/post-wave-cleanup
Jul 9, 2026
Merged

refactor: unify sidecar-lock, git, serde, sha256 helpers#395
ScriptedAlchemy merged 1 commit into
masterfrom
codex/post-wave-cleanup

Conversation

@ScriptedAlchemy

Copy link
Copy Markdown
Owner

Summary

Post-wave reuse/altitude cleanup from a reviewed audit. No behavior changes intended; all migrated sites keep their exact current semantics (create_dir_all placement, truncate(false), lock mode). CI-exact gates pass.

Changes

  1. Shared sidecar-lock utility (src/storage.rs) — new try_acquire_sidecar_lock (non-blocking; None = held elsewhere) and acquire_sidecar_lock_blocking, with the Windows LockFileEx read+write-handle rationale carried once. Migrated the hand-rolled fs2 flock sites: transcript_backfill::try_acquire_structured_backfill_lock, monitor (write_entry_inner + single-instance guard), user_config::save_inner, storage::append_line (via the new append_line_locked), and run_ledger. branch.rs intentionally left for its open PR (fix(pr-autotrack): harden daemon PR-branch auto-tracking #377).
  2. append_line_locked(path, line, private) in storage replaces run_ledger's near-verbatim append copy (~30 lines deleted); run_ledger routes through it.
  3. sha256 deduprun_ledger's inline sha256:{hex} now uses artifact_refs::sha256_bytes.
  4. serde_util::is_default<T: Default + PartialEq> (src/serde_util.rs) replaces the three per-module is_zero serde helpers (git_correlation, workflow_index, fact_proposals).
  5. git helpers (src/git.rs) — hoisted git_output (raw Output) and git_capture (trimmed String) next to git_program(); migrated worktree, tracedecay/lifecycle, and sessions/git_correlation/backfill. pr_autotrack::run_git left for a later pass (its file is owned by in-flight work).
  6. LCM rerank_grep_hits (src/sessions/lcm/query.rs) — folded the four per-session BTreeMaps into one SessionAgg { count, last_idx, has_tool } map. Behavior byte-identical; grep_disclosed_cap_reserves_a_tool_slot_for_capped_sessions and grep_caps_hits_per_session_in_cross_session_scope pass unchanged.
  7. Module doc note on the two sanctioned cross-process strategies (sidecar flock vs atomic-rename+hash-ownership) lives with the lock utility in storage.rs.

Notes

  • Removed now-unused fs2::FileExt imports from monitor.rs and user_config.rs: those sites now only call .unlock(), which resolves to std's inherent File::unlock (Rust 1.89+), so the trait import was dead. The lock helper in storage.rs still uses fs2 (lock_exclusive / try_lock_exclusive).
  • transcript_backfill's lock handle was write-only; it is now read+write via the shared helper, matching the Windows rationale (a superset that also fixes a latent Windows-lock case).
  • Excluded per instructions: skill_materialization.rs, managed_skill_model.rs, pr_autotrack.rs, branch.rs.

Gates

  • cargo fmt --all --check: clean
  • cargo clippy --workspace --all-targets --locked -- -D warnings: clean
  • cargo nextest (lib + session_suite, transcript_ingest_suite, storage_suite, automation_runner_test): 1946 passed, 14 skipped, 0 failed. The mcp::server::freshness_tests timer module was excluded from the final run: its tokio::time::timeout-bounded tests stall past their 30s bounds under this machine's concurrent-build load (the unrelated startup_catch_up_spawned_once_per_server, which touches none of this diff, stalls identically), indicating tokio-timer starvation, not a regression.

🤖 Generated with Claude Code

Post-wave reuse/altitude cleanup, no behavior changes intended.

- storage.rs: add shared sidecar-lock utility
  (try_acquire_sidecar_lock / acquire_sidecar_lock_blocking) plus a
  module note documenting the two sanctioned cross-process strategies
  (sidecar flock vs atomic-rename+hash), carrying the Windows LockFileEx
  read+write-handle rationale once. Add append_line_locked(path, line,
  private) and route PrivateStoreIo::append_line through it.
- Migrate the hand-rolled fs2 flock sites onto the helper:
  transcript_backfill, monitor (write_entry_inner + single-instance
  guard), user_config save_inner, and run_ledger (deleting its ~30-line
  append copy). run_ledger's inline sha256 now uses
  artifact_refs::sha256_bytes.
- serde_util.rs: generic is_default<T: Default + PartialEq>; replace the
  three per-module is_zero serde helpers.
- git.rs: hoist git_output (raw Output) and git_capture (trimmed String);
  migrate worktree, lifecycle, and git_correlation/backfill git helpers.
- lcm/query.rs: fold rerank_grep_hits' per-session BTreeMaps into one
  SessionAgg map (behavior byte-identical).

Co-Authored-By: Claude Fable 5 <noreply@anthropic.com>
@changeset-bot

changeset-bot Bot commented Jul 9, 2026

Copy link
Copy Markdown

⚠️ No Changeset found

Latest commit: b0353ad

Merging this PR will not cause a version bump for any packages. If these changes should not result in a new version, you're good to go. If these changes should result in a version bump, you need to add a changeset.

Click here to learn what changesets are, and how to add one.

Click here if you're a maintainer who wants to add a changeset to this PR

@chatgpt-codex-connector chatgpt-codex-connector Bot left a comment

Copy link
Copy Markdown

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

💡 Codex Review

Here are some automated review suggestions for this pull request.

Reviewed commit: b0353ad271

ℹ️ About Codex in GitHub

Your team has set up Codex to review pull requests in this repo. Reviews are triggered when you

  • Open a pull request for review
  • Mark a draft as ready
  • Comment "@codex review".

If Codex has suggestions, it will comment; otherwise it will react with 👍.

Codex can also answer questions or update the PR. Try commenting "@codex address that feedback".

Comment thread src/monitor.rs
file.lock_exclusive()?;
// Exclusive lock for concurrent writer safety, taken on the shared sidecar
// lock helper (see the sidecar-lock module note in `src/storage.rs`).
let file = crate::storage::acquire_sidecar_lock_blocking(mmap_path)?;

Copy link
Copy Markdown

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

P1 Badge Restore FileExt import for monitor locks

This module removed use fs2::FileExt, but the lock returned here is still a std::fs::File and write_entry_inner calls file.unlock() after flushing, with another unlock() in run. Without the trait in scope, builds that include monitor.rs fail with no method named unlock, so this refactor currently breaks compilation.

Useful? React with 👍 / 👎.

Comment thread src/user_config.rs
Comment on lines +413 to 419
let lock_file =
crate::storage::acquire_sidecar_lock_blocking(&lock_path).map_err(|source| {
ConfigSaveError::Lock {
path: lock_path.clone(),
source,
}
})?;

Copy link
Copy Markdown

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

P1 Badge Restore FileExt import for config save locks

The helper returns a std::fs::File, and this module no longer imports fs2::FileExt, but save_inner still calls lock_file.unlock() below. That leaves unlock unresolved for user_config.rs, so the crate cannot type-check until the trait import is restored or the explicit unlock is removed.

Useful? React with 👍 / 👎.

@ScriptedAlchemy ScriptedAlchemy merged commit a135e35 into master Jul 9, 2026
15 of 17 checks passed
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