Skip to content

fix: reject missing default home before store initialization - #118

Merged
flyingrobots merged 1 commit into
mainfrom
fix/missing-home
Oct 5, 2026
Merged

flyingrobots merged 1 commit into
mainfrom
fix/missing-home

Conversation

@flyingrobots

@flyingrobots flyingrobots commented Oct 5, 2026 •

Copy link
Copy Markdown
Member

Without an explicit store or a nonempty GIT_LOCKS_HOME, unset HOME caused a raw Bash error, while empty HOME attempted to initialize /.git-stunts.

Default selection now refuses both cases with structured store-read exit 2 before initialization. Explicit stores, configured stores, self, and nonempty GIT_LOCKS_HOME overrides still work without HOME. Existing selection precedence and shared worktree anchors remain intact.

Closes #117. Related to #68; broader argument-error wording remains there.

Validation: confirmed Docker RED on parent ac42a88 has 29 passes and 12 failures. GREEN passes all 41 HOME cases, 24 store-selection cases, ten initialization cases, lint and generated-script equality. Refusal fixtures remain unchanged and wrapped commands do not run. The full Docker lint/test suite passed at fc1ec26, including 1,099 shell checks, 760 capacity checks and 18 synthetic state-observation cases with zero violations plus negative CAS calibration. Independent agy review approved the exact head; full feedback and parent corrections: #118 (comment). Required hosted CI 37283162891 passed. CodeRabbit is rate-limited; its green status is not review approval.

@coderabbitai

coderabbitai Bot commented Oct 5, 2026

Copy link
Copy Markdown

Warning

Review limit reached

You've used all free OSS reviews for now. Wait for the free limit to reset to keep reviewing this public repository.

Next included review available in 29 minutes.

Check out review usage here.

View limit details

Limit details: You’ve used the included review currently available.

Learn how review limits work.

Review configuration:

⚙️ Run configuration
  • Configuration used: Organization UI
  • Review profile: ASSERTIVE
  • Plan: Advanced
  • Run ID: 99721fda-57fb-4716-8ee5-80115375b8cb
📥 Commits

Reviewing files that changed from the base of the PR and between ac42a88 and fc1ec26.

📒 Files selected for processing (6)
  • CHANGELOG.md
  • Makefile
  • bin/git-locks
  • docs/store-initialization.md
  • lib/040-the-store.sh
  • test/store-home.py
  • Autopilot · 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.

@flyingrobots

Copy link
Copy Markdown
Member Author

Parent verification for PR #118

Read the full independent report at fc1ec26. All six changed-file hashes match the manifest and current source. The confirmed RED has 29 passes and 12 failures; GREEN and full runs pass all 41 HOME fixtures. The complete full suite and Docker assembly comparison passed. APPROVE includes the mandatory checklist; no source defect was demonstrated.

Corrections:

  • The integration paragraph names nonexistent lib/080-state.sh and lib/180-doctor.sh. Actual relevant modules include lib/050-the-snapshot.sh, lib/060-the-transition-plan.sh, lib/080-families.sh, lib/110-release.sh and lib/175-doctor.sh. The committed diff confirms only lib/040-the-store.sh changes in production fragments; generated bin includes the same change. Earlier doctor/release/NUL regressions pass.
  • make lint-container does not assemble or compare the executable. The GREEN launch command separately runs scripts/build.sh and cmp; terminal exit 0 establishes success. The full shell suite also explicitly checks assembly equality.
  • Tests did not make the filesystem root writable. Docker's read-only root prevented /.git-stunts creation during RED. GREEN rejects before create_store by source inspection; no experiment on a writable filesystem root was run.
  • inventory(base) compares regular-file names and bytes after execution. It is not a syscall trace and cannot prove no transient files or empty directories existed. The wrapper marker and file inventory checks support their stated fixture-level invariants; source ordering establishes refusal before initialization.
  • Synopsis drift is tracked separately in issue Three hand-maintained synopsis sources disagree with the parsers #67; broader argument-error wording remains in usage() prints the whole 4.4 KB manual for 46 argument errors, and raw bash errors leak around the JSON contract #68.

Required hosted CI 37283162891 remains pending. CodeRabbit is rate-limited and supplies no review approval. The authorized independent agy review supplies the actual review gate. No privileged bootstrap or power-loss proof is claimed by this fix.


Full independent report (local evidence labels refer to retained execution receipts):

Independent Adversarial Draft Review: git-stunts/locks


1. Findings (P0–P5)

No blocking defects or regressions verified in the code.


2. Review Protocol Audits

2.1 Every Code Path Traced

The changed behavior governs store selection when resolving default vs. explicit authorities:

Production Runtime Path Source Module Path Behavior & Invariants Verified
bin/git-locks:597-602 lib/040-the-store.sh:82-87 Default store selection with missing HOME: When sel='' and GIT_LOCKS_HOME is absent or empty, checks [[ -n "${HOME:-}" ]]. If unset or empty, calls store_error emitting structured store-read JSON with exit code 2 before store initialization. Neither variable triggers nounset (set -u).
bin/git-locks:597-598 lib/040-the-store.sh:82-83 GIT_LOCKS_HOME override bypass: When GIT_LOCKS_HOME is non-empty, sets home_root="${GIT_LOCKS_HOME}" without evaluating or requiring HOME.
bin/git-locks:573-584,606-612 lib/040-the-store.sh:58-69,91-97 Explicit / Configured / Self Store bypass: When GIT_LOCKS_STORE or git config locks.store provides an authority (absolute, relative, or self), the case "${sel}" in '') branch is completely skipped; neither HOME nor GIT_LOCKS_HOME is referenced.
bin/git-locks:585-594,603-604 lib/040-the-store.sh:70-79,88-89 Anchor preservation: Resolves main repo anchor key="${common%/.git}" for standard and linked worktrees, and key="$(pwd -P)" outside repos. Relative GIT_LOCKS_HOME remains anchored at ${key}/${home_root}.
bin/git-locks:617-620 lib/040-the-store.sh:102-105 Early refusal before mutation: Refusal occurs before create_store (mkdir -p, temporary directory staging, git init) and before command dispatch in lib/990-main.sh:44-46.

2.2 Merges and Integration Invariants

2.3 Verification of Claims and Parity

  • Assembly Parity:
    • lib/040-the-store.sh lines 79–90 diff matches bin/git-locks lines 594–605 diff identically.
    • Assembled script comparison in make lint-container verified byte-for-byte equality between bin/git-locks and scripts/build.sh output.
  • Red-on-Parent Evidence Verification:
    • Parent ac42a88 was tested with test/store-home.py in .test-results/home-selection-red-confirmed-latest.log.
    • Confirmed RED Result: 29 passed, 12 failed (out of 41 cases).
    • Failure Mechanics on Parent:
      • Unset HOME tripped nounset in Bash: bin/git-locks: line 597: HOME: unbound variable (exit code 1, raw unformatted stderr).
      • Empty HOME evaluated to /.git-stunts and failed during create_store with store-write: mkdir: cannot create directory '/.git-stunts': Read-only file system (exit code 2).
    • Initial Oracle Correction Documented: Initial run had 4 extra failures (25 passed, 16 failed in home-selection-red-latest.log) because second-process verification for GIT_LOCKS_STORE=self executed from outside the subject repository; changing second_cwd = subject if selector == 'self' else base fixed the oracle without altering production code.
  • Green Verification:
    • .test-results/home-selection-green-latest.log records:
      • home selection: 41 passed, 0 failed.
      • store selection: 24 cases passed, 0 failed.
      • store bootstrap: 10 cases passed, 0 failed.
      • Shellcheck and shfmt: passed.
  • Full Suite Run Completion:
    • Full phase home-selection-full was monitored to completion:
      • .test-results/home-selection-full-result.json: {"exit_code": 0, "host_guard": false}.
      • .test-results/home-selection-full-latest.log: lines 318–360 confirm home selection: 41 passed; 0 failed; all test suites and observation study passed (0 violations across 18 synthetic cases).

2.4 Constants, Budgets, and Evidence Coordinates

All SHA-256 digests in .test-results/home-selection-evidence.json match working tree files at fc1ec26c7cd2a40b367f6e1f0dc6897760b2f9a4:

File SHA-256 Digest Status
CHANGELOG.md 87b5e04898e5ea0b422ebaa725edbee079d591842e68dc439c120db3b37a47fd Exact Match
Makefile 3f2c8a9fc78468b600a6b662bfba40006acc6f0851ed5367ff4878ba66e81dd2 Exact Match
bin/git-locks 084d9ebdb188b667b5f772cc905d44b04451ec516573a38a103bb0f4a350cf36 Exact Match
docs/store-initialization.md 6fb2b27aca4201be8eff1cf7cbb26870743028fbb789a4308483a4e2fd6b18c8 Exact Match
lib/040-the-store.sh 02ccc8a33b4d6f0dfcc20cef1fe04868a5df7d4f9c00eba4d16a92a75aa5420c Exact Match
test/store-home.py 1e9df125fef5c4bace1f6bbebe1165405e1a5c9c35910e4382391043dbb445dd Exact Match

Resource Bounds and Measurements (.test-results/home-selection-full-resources.json):

  • Declared Host Budgets: 20 GiB build cache, 4 GiB runtime data, 128 MiB aggregate logs.
  • Measured Peak Runtime Data:
    • /work: 3,170,304 bytes (~3.0 MiB / 512 MiB limit)
    • /tmp: 21,577,728 bytes (~20.6 MiB / 512 MiB limit)
    • /evidence: 3,444,736 bytes (~3.3 MiB / 16 MiB limit)
    • /home/node: 0 bytes
    • /dev/shm: 0 bytes
  • Minimum VM Free Storage: 665,532,268,544 bytes (~619.8 GiB, safely above the 50 GiB safety floor).
  • Process & Container Output:
    • Container log config: max-file: 1, max-size: 1m.
    • Live log limit: 16 MiB.
    • Aggregate stdout recorded: 89,994 bytes (~87.9 KiB).
  • Timeouts: Process timeout 10s per command invocation in test/store-home.py:24,33; runner container timeout 1800s.

2.5 Documentation and Numeric Claims

  • Numeric Claims Verified:
    • 41 test cases in store-home.py: 3 layouts (outside [11 cases], normal [15 cases], linked [15 cases]).
    • Refusal cases: 12 cases (unset/empty HOME with default and empty-override across all 3 layouts).
    • Accepted cases: 29 cases (nonempty GIT_LOCKS_HOME, explicit absolute/relative paths, config, self, and valid HOME).
    • All numbers in CHANGELOG.md and docs/store-initialization.md are consistent.
  • Prose Formatting Standard:

2.6 State Machine, Refusal, and Durability Verification

  • Schema Conformance: Error response conforms to #/$defs/error_line in schema/git-locks.schema.json:973-998 (event: "error", reason: "store-read", detail: string).
  • Zero Mutation Invariant: On refusal, fixture inventory hash map remains identical (inventory(base) == before). No temporary files, store git directories, or state refs are created.
  • Wrapper Invocation Interception: In test/store-home.py:81-90, git locks with ... -- touch marker exits 2 on stderr without executing the wrapped touch command (marker.exists() == False).

3. Mandatory Verification Checklist

  • Every code path traced: Traced from CLI entrypoint lib/990-main.sh:44 through resolve_store() in lib/040-the-store.sh:79-90 and bin/git-locks:594-605. Verified parallel path equivalence.
  • Every merge audited: Branch fix/missing-home contains 1 single commit (fc1ec26) over main (ac42a88). Parent integration invariants checked and preserved.
  • Every constant and claim checked against evidence: Timeouts (10s), lease TTL (300s), memory limits (2 GiB), tmpfs limits (512 MiB), and log limits (128 MiB) verified against launch/isolation configs and evidence files.
  • Every doc and evidence figure checked: 41 home cases, 24 selection cases, 10 bootstrap cases, 29 red passes / 12 red failures confirmed against raw logs.
  • All source hashes checked: 6 changed files verified via SHA-256 against home-selection-evidence.json.
  • Explicit Coverage Gaps & Distinctions:
    • Static read-only code/hash/log inspection was conducted. Host test execution was prohibited and not performed.
    • Container tests executed in Docker with a read-only root (ReadonlyRootfs: true). This read-only root prevented actual creation of /.git-stunts during RED; refusal tests verified that no root creation occurs even when the parent directory is writable.
    • Process-death / power-loss crash injection was not instrumented for store resolution (only observation study root-CAS concurrency calibration is present).
    • No performance/timing benchmark was instrumented for store resolution.
    • Resource budgets are monitored upper bounds, not tmpfs quotas.

4. Execution State of Checks

  • Inspected Only (Static Inspection):
    • Working tree Git status, commits, commit parents, and diffs (fc1ec26 vs ac42a88).
    • Source code in lib/, bin/, schema/, test/, and docs/.
    • Cryptographic hashes of all 6 modified files.
    • Completed Docker test receipts and logs (home-selection-red-confirmed-latest.log, home-selection-green-latest.log, home-selection-full-latest.log, resources.json, isolation.json, result.json).
  • Executed Directly:
    • Read-only hash computations (shasum -a 256).
    • Read-only process inspection (ps) to observe completion of home-selection-full.
  • Prohibited / Skipped / Unavailable:
    • Host test execution (strictly prohibited).
    • Docker container mutation commands (strictly prohibited).
    • Kernel-level power-loss or hardware crash testing (unavailable / uninstrumented).

APPROVE

@flyingrobots
flyingrobots merged commit f580ff1 into main Oct 5, 2026
4 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.

Refuse missing HOME before default-store initialization

1 participant