Skip to content

fix: recover native first-fsync lock crashes before TTL expiry - #105

Merged
unbraind merged 16 commits into
mainfrom
fix/crash-restart-recovery
Oct 23, 2026
Merged

unbraind merged 16 commits into
mainfrom
fix/crash-restart-recovery

Conversation

@unbraind

@unbraind unbraind commented Oct 21, 2026 •

Copy link
Copy Markdown
Owner

Native update/comment killed at the first lock fsync preserves acknowledged data but previously restarted with lock-conflict exit 4. This change admits recovery of a fresh empty publication gate while holding its permanent kernel lease and verifying that the original process is dead on the same Linux host/namespace. Gate identity and emptiness checks remain mandatory; live, unknown, occupied and replacement gates retain their refusal behavior. The durable recovery-intent receipt precedes lock removal. Item/history serialization is unchanged.

This branch includes the PR 104 crash-harness stack and retains the original requirement to merge after PR 104. The corpus measures real SIGKILL injection at observed task-local rename/fsync entries, compares complete reference item/history bytes and raw restart receipts, and retains minimal synthetic reproductions. Each runtime uses its own exact restart reference; the shared cross-runtime acknowledgement projection is update id/status or comment id/comments.

Current main 300eaa9a9d06f0e2cfc6afcfa8b66492a960a77b is merged. Conflict resolution retains both crash/benchmark recipes and ignore rules, the main non-git process helper, and the stricter 50-writer workload of three comments per writer. The expected marker helper covers all 150 unique comments; the test also verifies every marker exactly once and the complete 151-record history chain. The documented helper keeps the existing 100-line Clippy function limit intact. A stale harness comment now describes fixed reference invocations after main introduced shared native journal recovery.

Behavioral controls at the integrated source:

  • Revert only early confirmed-dead-owner gate admission in mutation::acquire_lock_attempt, rebuild, and run node --test --test-name-pattern="retained (update|comment)" scripts/crash-harness.test.mts: two failures, both restart exit 4. Restore/rebuild: both pass.
  • Restore only the old one-marker-per-writer behavior in expected_markers, leaving the three-comment workload intact: the concurrency regression compiles and fails with exit 101, actual 150 markers versus expected 50. Restore the full marker set: the Rust acceptance command passes.
  • Original JSON receipts and fixtures remain unchanged. All 78 pre-merge branch history streams and all 80 main streams remain exact byte prefixes; no existing history was repaired or rewritten.

Pinned-PM linked acceptance passes all three commands (44 cases, zero failures or skips on Linux):

Command Passed
node --test scripts/crash-harness.test.mts 22
env CARGO_BUILD_JOBS=2 PM_RUST_REQUIRE_PUBLISHED_CLI=1 cargo +1.90.0 test --locked --test concurrency_contract --test parity_1021_contract 2 + 14
env CARGO_BUILD_JOBS=2 cargo +1.90.0 test --locked --lib gate 6

Strict erasable TypeScript, ESLint, Rust formatting, all-target/all-feature Clippy, private rustdoc, changelog regeneration/check inside the merge, and isolated required check-only tracker health pass. Existing tracker policy disables runtime result persistence; append-only item comments retain the linked receipts and negative controls.

Full CI evidence: run 40018857828 passed all nine jobs for c03cd0dce87e99e4f5c2c952b4311b8908742451. All three unchanged just release-check aggregates passed. Ordinary/instrumented Rust counts are Linux 601/601, macOS 589/589 and Windows 583/583, with zero failures or ignored tests. Lines, functions, regions and branches are exactly 100 percent on every platform at unchanged scope and thresholds. The Linux crash harness passes 22/22 with zero skips; macOS passes 13 with nine declared Linux-only skips, and Windows passes 12 with ten declared platform skips. TypeScript checking, ESLint, private rustdoc, Clippy, audit, changelog and required check-only tracker health pass. All three separate Rust and latency jobs pass, and CodeQL succeeds. Full release evidence comes from CI; no incomplete local cold build is counted as a full gate.

Retained historical evidence and boundaries:

Process-kill evidence does not establish power-loss durability, unmeasured syscall coverage, cross-runtime journal recovery, or a TypeScript coverage percentage. The existing comment lock-diagnostic mismatch and older tracker chain advisories remain separately tracked; check-only health does not certify those older history chains.

GraphQL reports zero review threads. CodeRabbit skipped automatic review and provided no review body or outside-diff findings; unavailable or skipped reviewers are missing review evidence. No thread replies/resolutions, PR merge, release, dependency-pin change or threshold reduction was performed.

PM: recovery work and revert receipts, crash harness. The recovery item remains in progress with its claim released for orchestrator verification.

@sourcery-ai

sourcery-ai Bot commented Oct 21, 2026

Copy link
Copy Markdown

Sorry @unbraind, you've used your own review budget of 250,000 diff characters for the last 7 days.

You can request another review in 2 days and 5 hours by commenting @sourcery-ai review. Upgrade to get a review now.

@greptile-apps greptile-apps 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.

Your trial has ended. Reactivate Greptile to resume code reviews.

@coderabbitai

coderabbitai Bot commented Oct 21, 2026 •

Copy link
Copy Markdown

Important

  • 🔍 Trigger review

This repository does not receive automatic reviews because it has fewer than 10 stars.

⚙️ Run configuration
  • Source mode: Auto
  • Repository: Unavailable
  • Branch: Unavailable
  • File: No configuration file from this repository applied
  • Commit: Unavailable
  • Layers: Organization UI
  • Review profile: ASSERTIVE
  • Plan: Advanced
  • Run ID: bbc7e79c-9877-41c4-bc44-c12911cbb60c
  • Autofix · Keep fixing CodeRabbit findings and required CI, and resolving merge conflicts

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.

@sourcery-ai

sourcery-ai Bot commented Oct 21, 2026

Copy link
Copy Markdown

Reviewer's Guide

The PR adds narrowly scoped Linux recovery for first-fsync lock crashes, backed by an extensive isolated syscall-injection harness that compares exact durable state and restart receipts, plus CI, documentation, fixtures, and 50-writer concurrency validation.

Sequence diagram for first-fsync lock crash recovery

sequenceDiagram
    participant Mutation
    participant Lock as Lock manager
    participant Gate as Publication gate
    participant Kernel as Linux kernel lease
    participant Owner as Original process
    participant Recovery as Durable recovery

    Mutation->>Lock: acquire_lock_attempt()
    Lock->>Gate: write complete lock payload
    Lock->>Gate: fsync()
    Kernel-->>Lock: SIGKILL during first fsync
    Mutation--xOwner: process dies
    Recovery->>Kernel: hold permanent lease
    Recovery->>Owner: confirmed_dead_owner()
    Recovery->>Gate: read_lock_owner()
    alt identity matches and gate is empty
        Recovery->>Recovery: write recovery intent receipt
        Recovery->>Gate: reclaim_stale_gate()
        Recovery-->>Mutation: restart succeeds before TTL expiry
    else live, unknown, replaced, or occupied gate
        Recovery-->>Mutation: LockConflict
    end
Loading

Flow diagram for syscall-injection crash corpus validation

flowchart TD
    A[Create acknowledged synthetic seed] --> B[Run update or comment reference]
    B --> C[Observe task-local rename and fsync ordinals]
    C --> D[Inject SIGKILL at each declared boundary]
    D --> E[Restart the same operation family]
    E --> F{State and receipt match reference?}
    F -->|yes| G[Verify exact item/history bytes]
    F -->|no| H[Retain bounded synthetic failure evidence]
    G --> I{Native and published parity?}
    I -->|yes| J[Pass corpus boundary]
    I -->|no| H
Loading

File-Level Changes

Change Details Files
Permit safe pre-TTL recovery of crashes occurring during first fsync of the lock payload.
  • Under the existing kernel lease, recognize a fresh empty publication gate as reclaimable only when the original owner is identity-verified dead on the same Linux host/namespace.
  • Preserve durable recovery-intent recording before lock removal and retain refusals for live, unknown, replaced, occupied, or nonempty gates.
  • Add focused unit and parity coverage for owner identity, gate occupancy, lease contention, recovery receipts, and refusal-byte preservation.
src/mutation.rs
tests/support/mutation_unit.rs
tests/parity_1021_contract.rs
Add a syscall-injection crash-conformance harness with permanent first-fsync replays.
  • Run native and pinned published CLI implementations through isolated, no-Git workspaces while injecting SIGKILL at observed per-task rename/fsync boundaries.
  • Compare exact item/history snapshots, acknowledged projections, restart state, and runtime-specific raw receipt hashes; retain privacy-safe synthetic failure artifacts and controlled replay manifests.
  • Add typed CLI refusal handling, source immutability and symlink/path safety checks, bounded execution, deterministic clock setup, storage snapshot utilities, and harness unit/integration tests.
scripts/crash-harness.mts
scripts/crash-cli.mts
scripts/crash-clock.mts
scripts/crash-process.mts
scripts/crash-storage.mts
scripts/crash-harness.test.mts
tests/fixtures/crash-restart/update.json
tests/fixtures/crash-restart/comment.json
tests/fixtures/crash-restart/fixture/.agents/pm/settings.json
tests/harness/package.json
tests/harness/package-lock.json
tests/harness/tsconfig.json
tests/harness/eslint.config.mjs
docs/CRASH_HARNESS.md
docs/CRASH_PUBLIC_COPY_2026_10_22.json
docs/CRASH_RESTART_RECOVERY_2026_10_22.json
docs/CRASH_RESTART_REVERT_PROOF_2026_10_22.json
docs/CRASH_REVERT_PROOF_2026_10_22.json
Integrate crash recovery validation and stronger concurrency coverage into project workflows.
  • Install strace on Linux CI and make crash-harness checks part of release-check.
  • Document crash corpus scope, commands, evidence, limitations, and fixture replay procedures.
  • Synchronize 50 concurrent comment writers with a barrier and verify all 150 comments/history entries survive.
  • Update ignore/task/history metadata for the crash-restart and comment lock-receipt work.
.github/workflows/ci.yml
justfile
README.md
tests/concurrency_contract.rs
.gitignore
.agents/pm/features/pm-rust-crash-harness.toon
.agents/pm/history/pm-rust-comment-lock-receipt.jsonl
.agents/pm/history/pm-rust-crash-harness.jsonl
.agents/pm/history/pm-rust-crash-lock-restart.jsonl
.agents/pm/tasks/pm-rust-comment-lock-receipt.toon
.agents/pm/tasks/pm-rust-crash-lock-restart.toon

Tips and commands

Interacting with Sourcery

  • Trigger a new review: Comment @sourcery-ai review on the pull request.
  • Continue discussions: Reply directly to Sourcery's review comments.
  • Generate a GitHub issue from a review comment: Ask Sourcery to create an
    issue from a review comment by replying to it. You can also reply to a
    review comment with @sourcery-ai issue to create an issue from it.
  • Generate a pull request title: Write @sourcery-ai anywhere in the pull
    request title to generate a title at any time. You can also comment
    @sourcery-ai title on the pull request to (re-)generate the title at any time.
  • Generate a pull request summary: Write @sourcery-ai summary anywhere in
    the pull request body to generate a PR summary at any time exactly where you
    want it. You can also comment @sourcery-ai summary on the pull request to
    (re-)generate the summary at any time.
  • Generate reviewer's guide: Comment @sourcery-ai guide on the pull
    request to (re-)generate the reviewer's guide at any time.
  • Resolve all Sourcery comments: Comment @sourcery-ai resolve on the
    pull request to resolve all Sourcery comments. Useful if you've already
    addressed all the comments and don't want to see them anymore.
  • Dismiss all Sourcery reviews: Comment @sourcery-ai dismiss on the pull
    request to dismiss all existing Sourcery reviews. Especially useful if you
    want to start fresh with a new review - don't forget to comment
    @sourcery-ai review to trigger a new review!

Customizing Your Experience

Access your dashboard to:

  • Enable or disable review features such as the Sourcery-generated pull request
    summary, the reviewer's guide, and others.
  • Change the review language.
  • Add, remove or edit custom review instructions.
  • Adjust other review settings.

Getting Help

@greptile-apps greptile-apps 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.

Your trial has ended. Reactivate Greptile to resume code reviews.

@greptile-apps greptile-apps 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.

Your trial has ended. Reactivate Greptile to resume code reviews.

@greptile-apps greptile-apps 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.

Your trial has ended. Reactivate Greptile to resume code reviews.

@greptile-apps greptile-apps 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.

Your trial has ended. Reactivate Greptile to resume code reviews.

@greptile-apps greptile-apps 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.

Your trial has ended. Reactivate Greptile to resume code reviews.

@unbraind unbraind left a comment

Copy link
Copy Markdown
Owner Author

Choose a reason for hiding this comment

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

Orchestrator review (built-in Claude review agent, verified by the orchestrator; bots are not waited for since 2026-10-22):

VERDICT: MERGE
FINDINGS:

  • none
    SUMMARY: The PR recovers fresh native lock gates before TTL expiry after confirming owner death, preserving lease, identity, emptiness and audit safeguards. Static review found meaningful crash-replay, refusal and concurrency tests with unchanged coverage gates; tests were not rerun locally.
    STOP.

@unbraind
unbraind merged commit 49b4360 into main Oct 23, 2026
17 checks passed
@unbraind
unbraind deleted the fix/crash-restart-recovery branch October 23, 2026 21:03
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