Skip to content

force-run: hand the runner the install dir as CRON_DIR - #268

Merged
thedavidmeister merged 3 commits into
mainfrom
264-force-run-cron-dir
Aug 10, 2026
Merged

thedavidmeister merged 3 commits into
mainfrom
264-force-run-cron-dir

Conversation

@thedavidmeister

@thedavidmeister thedavidmeister commented Aug 10, 2026 •

Copy link
Copy Markdown
Contributor

Closes #264.

Defect

force-run validates, canonicalizes and fast-forwards the install dir, then spawns the runner with inherited env and inherited cwd — no CRON_DIR. Both runners resolve DIR="${CRON_DIR:-$PWD}" (review-run.sh:25, campaign-run.sh:28), so the runner reads the caller's cwd as the install dir: a cwd that is some checkout of this repo silently starts a PAID run against the wrong dir, and any other cwd refuses at startup, as observed:

review-run: no review-prompt.txt in '/home/gildlab/code' — set CRON_DIR to the install dir

Fix

ForceRunPlan carries the export as typed data — env: vec![("CRON_DIR", <canonical dir>)] — applied to the child with .envs(). argv[0] stays nix, so a runner that cannot start remains the tool's own exit-2 cannot start diagnostic and never exits looking like a run that ran and failed. The previews (would run: / running:) render assignments-first with values shell-quoted only when sh needs it, making the printed line byte-for-byte the manual invocation the runner headers and README.md:3196 document, and still paste-able when the install dir carries whitespace.

The install dir resolves flag > INSTALL_DIR > CRON_DIR (the runners' own export is the more specific name; empty means unset at every level). An ambient CRON_DIR that disagrees with the resolved dir loses to the plan's export — never silently: note: CRON_DIR=<ambient> in the environment is overridden by CRON_DIR=<dir> for this run (review finding 7, implemented rather than refuted).

QA

  • Discriminating tests (each fails on base, verified by mutation below; all assert messages carry stdout AND stderr):
    • the_dir_in_the_flake_ref_is_canonical (extended) — the would run: line carries CRON_DIR=<canonical dir> nix run even for a ..-laden input.
    • cron_dir_is_an_install_dir_fallback_but_install_dir_wins (new) — CRON_DIR alone resolves the install dir; beside INSTALL_DIR it loses (its value is a nonexistent dir, so reading it first would exit 2, not 0).
    • an_overridden_ambient_cron_dir_is_said_out_loud (new) — disagreeing ambient CRON_DIR prints the note; the same dir spelled via .. does not.
    • a_runner_that_cannot_start_is_a_diagnostic_not_a_run_result (new) — PATH holds git alone so nix cannot resolve: exit 2 with cannot start on stderr, after the fast-forward succeeded. No run can start (the file's no-money invariant holds — nix is unreachable).
    • the_plan_pulls_the_dir_it_then_builds_the_runner_from (unit, extended) — plan env content for both roles; flake ref located by content, not index.
    • a_previewed_invocation_is_pasteable (unit, new) — unquoted README form when nothing needs quoting; CRON_DIR='/tmp/install dir' value-quoting and whole-word argv quoting when it does.
  • Mutations applied (baseline committed first; file restored and verified via git status after each):
    • plan env emptied (vec![]) → killed by the unit plan test AND the_dir_in_the_flake_ref_is_canonical (each 0 passed; 1 failed).
    • .or_else(|| env_dir("CRON_DIR")) deleted → killed by the fallback test (0 passed; 1 failed).
    • spawn-failure return 2 → return 127 → killed by the cannot-start test (0 passed; 1 failed).
    • override notice suppressed (if false && !same) → killed by the said-out-loud test (0 passed; 1 failed).
    • quoting disabled (shell_word always plain) → killed by the pasteable unit test (0 passed; 1 failed).
    • Residual untested glue: the .envs()/.args() application on Command itself — unreachable under the suite's no-run-ever-starts invariant; the plan data feeding it is what the mutants above prove covered.
  • Oracle: the runner scripts' own resolution and documented invocation (review-run.sh:25,78, campaign-run.sh:28,89, README.md:3196-3197), and POSIX sh word/assignment reading rules for the preview quoting — independent of the implementation.
  • Category check: issue asks that force-run propagate --install-dir into CRON_DIR so the runner works from any cwd, canonicalized, with the contract visible/testable in the --no-run preview; covered for both roles, plus the review's findings: spawn-failure exit split, CRON_DIR accepted as env fallback with documented precedence, quoted paste-able previews, ambient-override notice, corrected worst-case comments.

Full suite on the merged tree (origin/main = 2f11a52 merged): 1278 unit + 124 integration tests, 0 failures.

🤖 Generated with Claude Code

Both runners resolve DIR="${CRON_DIR:-$PWD}", so a child spawned without
the variable reads the caller's working directory as the install dir and
refuses at startup — force-run only worked when invoked from inside the
install dir. The plan now carries CRON_DIR in its own argv via env(1),
canonical like the flake ref beside it, so --no-run previews the exact
invocation the runners' headers document and the tests can kill any
mutant that drops it.

Closes #264

Co-Authored-By: Claude Fable 5 <noreply@anthropic.com>
@thedavidmeister thedavidmeister self-assigned this Aug 10, 2026
@coderabbitai

coderabbitai Bot commented Aug 10, 2026 •

Copy link
Copy Markdown

Review Change Stack

Walkthrough

force-run now includes the canonical install directory in CRON_DIR for runner invocations. Runner-plan documentation, command assertions, and an indirect-path behavioral test reflect the added environment arguments.

Changes

Force-run CRON_DIR propagation

Layer / File(s) Summary
Runner command environment
pr-review-report-rs/src/main.rs
Runner commands now prepend env CRON_DIR=<install_dir> before the existing Nix invocation.
Command assertions and indirect-path test
pr-review-report-rs/src/main.rs, pr-review-report-rs/tests/force_run.rs
Assertions account for the inserted arguments. The force-run test verifies the canonical install path in the previewed command.

Estimated code review effort: 2 (Simple) | ~10 minutes

Possibly related PRs

Suggested reviewers: claude

🚥 Pre-merge checks | ✅ 5
✅ Passed checks (5 passed)
Check name Status Explanation
Linked Issues check ✅ Passed The changes propagate the canonical install directory as CRON_DIR and add coverage for indirect force-run previews, satisfying issue #264.
Out of Scope Changes check ✅ Passed The changes are limited to CRON_DIR propagation, related runner-plan updates, assertions, and focused behavioral testing.
Docstring Coverage ✅ Passed No functions found in the changed files to evaluate docstring coverage. Skipping docstring coverage check.
Description Check ✅ Passed Check skipped - CodeRabbit’s high-level summary is enabled.
Title check ✅ Passed The title clearly and concisely describes the main change: passing the install directory to the runner through CRON_DIR.
✨ Finishing Touches
📝 Generate docstrings
  • Create stacked PR
  • Commit on current branch
🧪 Generate unit tests (beta)
  • Create PR with unit tests
  • Commit unit tests in branch 264-force-run-cron-dir

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.

thedavidmeister and others added 2 commits August 10, 2026 15:57
… paste-able preview

The plan carries CRON_DIR as a typed env field applied to the child, so
argv[0] is nix again and a runner that cannot start is the tool's own
exit-2 diagnostic rather than env(1)'s 127 dressed as a run result. The
previews render assignments-first with values shell-quoted only when sh
needs it, which makes the printed line the README's own documented form
and still paste-able for an install dir with whitespace. The install
dir resolves flag > INSTALL_DIR > CRON_DIR, an ambient CRON_DIR losing
to the resolved dir says so out loud, and the comments now state the
real pre-fix worst case: a silent paid run against the wrong cwd.

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

Copy link
Copy Markdown
Contributor Author

Reviewed f97898f: approve — env rides ForceRunPlan as typed data applied via .envs(), so a missing runner is the tool's own exit-2 diagnostic again (integration-proven against a nix-less PATH without starting a run); fallback chain flag > INSTALL_DIR > CRON_DIR with a precedence-discriminating test; preview renders from the same plan data the spawn uses and is byte-for-byte the README/header form when nothing needs quoting, correctly quoted when it does; ambient-CRON_DIR override is announced with canonical comparison; comments state the true pre-fix worst case; suite 1278+124/0 on the merged tree; 5 mutants killed with one declared residual (.envs() glue, untestable under the no-run invariant, its feeding data mutant-covered); CI green; 0 unresolved threads.
Rulings-conformance: checked against CLAUDE.md's invariants and the rulings for this work. (1) 'The Rust tool is the only transition function / plans are testable data' — the fix extends ForceRunPlan rather than burying env in the spawn call, and the preview and spawn read the same data so they cannot drift. (2) Issue #264 as filed: --install-dir now reaches the runner as CRON_DIR, with the env fallback the ecosystem's own variable — implemented with no adjacent scope. (3) The review work order (fix all nine, implement-or-refute the plausible override): all nine fixed, the override implemented as a said-out-loud note. (4) 'Comments describe current behavior' — the false refuses-at-startup and byte-for-byte claims are corrected, and the byte-for-byte claim is now true rather than restated. (5) 'Producer resolves conflicts by merging base in' — origin/main (2f11a52) merged in cleanly, full suite on the merge commit per the semantic-conflicts ruling. (6) The test file's no-money invariant is preserved: the one real spawn resolves no nix and cannot start a run. The artifact obeys every ruling named.

@thedavidmeister
thedavidmeister merged commit ebb1a05 into main Aug 10, 2026
21 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.

force-run does not propagate --install-dir into CRON_DIR, so the runner refuses unless invoked from inside the install dir

1 participant