Skip to content

fix(env): seed machine.json so update/mem resolve the real checkout - #732

Merged
mlorentedev merged 5 commits into
mainfrom
fix/seed-machine-repo-dir
Jul 10, 2026
Merged

fix(env): seed machine.json so update/mem resolve the real checkout#732
mlorentedev merged 5 commits into
mainfrom
fix/seed-machine-repo-dir

Conversation

@mlorentedev

Copy link
Copy Markdown
Owner

Problem

On a docs-faithful fresh machine, nothing writes ~/.config/dotfiles/machine.json,
so the phantom contract default DOTFILES_REPO_DIR=$HOME/Projects/dotfiles
propagates through the ADR-025 cascade (env -> machine.json -> contract default) — and through the generated paths.sh/paths.ps1 — into every
consumer that resolves via env.ResolvePath:

  • dotf update reports not a git repo: ~/Projects/dotfiles — nothing to self-update and exits 0. Self-deploy is a silent no-op on every fresh machine.
  • dotf mem session-start probes ~/Projects/dotfiles/scripts/vault-health.sh,
    misses, and says "run dotfiles setup" though setup ran.

ResolvePath returns the default even when it does not exist, so the
repo == "" guards never fire. Meanwhile secrets/spec/doctor's drift check
use the RepoDir() git walk-up and work — two contradictory "where is the repo"
answers in one binary.

Fix

  • Root cause. New dotf env set <KEY> <VALUE> — the write-side counterpart of
    dotf env path: validates the key against the contract (a typo fails loud),
    merges into machine.json preserving every other override, writes atomically.
    setup-linux.sh / setup-windows.ps1 call it to seed DOTFILES_REPO_DIR to
    the checkout they run from, before dotf env generate (so the generated path
    file carries the real value too). One Go JSON-merge instead of hand-rolled JSON
    in two shells (ADR-020).
  • Defense in depth. repoForUpdate() and the mem resolvers prefer a
    cascade value only when it names an existing directory, else fall back to the
    RepoDir() walk-up (interactive dotf update/mem from inside a checkout).
  • Doctor health check. A new dotf doctor assertion FAILs (with an
    actionable hint) when the DOTFILES_REPO_DIR cascade resolves to a
    phantom/missing path. It deliberately mirrors what update/mem see (no
    walk-up masking), so the class is caught on any box.

Testing

  • Go unit tests: env set (merge/preserve/idempotent/unknown-key-fails),
    repoForUpdate walk-up fallback, and the doctor check (pass/missing/not-git).
  • End-to-end smoke of dotf env set in an isolated XDG_CONFIG_HOME: seed
    creates machine.json, re-set is idempotent, other keys are preserved, an
    unknown key exits non-zero.
  • Integration bats in verify-setup.bats asserts setup seeds machine.json with
    the checkout path and dotf env path DOTFILES_REPO_DIR resolves to a real dir
    (runs in the Linux container).
  • go build ./..., go vet ./..., go test ./... clean; bash -n setup-linux.sh; .ps1 change is ASCII-only.

Spec: specs/BUG-029-seed-machine-repo-dir.

Closes #696.

On a fresh machine nothing writes ~/.config/dotfiles/machine.json, so the
phantom contract default DOTFILES_REPO_DIR=$HOME/Projects/dotfiles propagates
through the ADR-025 cascade to every consumer that resolves via ResolvePath:
`dotf update` reports "not a git repo" and no-ops (exit 0), and `dotf mem`
prints "run setup" though setup ran. Consumers using the RepoDir() git walk-up
(secrets, spec) were unaffected — two contradictory answers in one binary.

- Add `dotf env set <KEY> <VALUE>`, the write-side counterpart of `env path`:
  validates the key against the contract, merges into machine.json preserving
  other overrides, writes atomically. setup-linux.sh / setup-windows.ps1 call it
  to seed DOTFILES_REPO_DIR to the checkout before `dotf env generate`.
- repoForUpdate() and the mem resolvers fall back to the RepoDir() walk-up when
  the cascade value is not an existing directory.
- Add a `dotf doctor` check that FAILs when the DOTFILES_REPO_DIR cascade
  resolves to a phantom/missing path (mirrors what update/mem see, no walk-up
  masking), plus Go unit tests and an integration bats asserting setup seeds
  machine.json.

Refs #696. Spec: specs/BUG-029-seed-machine-repo-dir.
@coderabbitai

coderabbitai Bot commented Jul 10, 2026

Copy link
Copy Markdown

Warning

Review limit reached

@mlorentedev, you've reached your PR review limit, so we couldn't start this review.

Next review available in: 58 minutes

Enable usage-based reviews in Billing to review now. Otherwise, wait until the next included review is available.
You're only billed for reviews past your plan's rate limits ($0.25/file).

How can I continue?

After more reviews become available, a review can be triggered using the @coderabbitai review command as a PR comment. Alternatively, push new commits to this PR.

To avoid repeated limits, reduce automatic review volume by pausing incremental auto-reviews earlier, using label-based review opt-in, excluding WIP or generated PR titles, or requesting reviews manually when the PR is ready. If your team needs uninterrupted high-volume reviews, an organization admin can enable usage-based reviews.

How do review limits work?

CodeRabbit enforces per-developer PR review limits for each organization. Most developers receive the normal plan review availability.

For paid Pro and Pro+ PR reviews, CodeRabbit uses adaptive limits for sustained high-volume activity. When a developer's recent PR review activity reaches the 95th percentile or higher among CodeRabbit users, additional reviews become available more gradually as earlier reviews age out of the rolling window.

Please refer docs for additional details.

Review details
⚙️ Run configuration

Configuration used: defaults

Review profile: CHILL

Plan: Pro Plus

Run ID: aa4d44cb-b176-4d62-9123-b4b6c9504eab

📥 Commits

Reviewing files that changed from the base of the PR and between 9be30c7 and c7bff39.

📒 Files selected for processing (15)
  • cli/internal/cmd/env.go
  • cli/internal/cmd/mem.go
  • cli/internal/cmd/update.go
  • cli/internal/cmd/update_test.go
  • cli/internal/doctor/checks_repodir.go
  • cli/internal/doctor/checks_repodir_test.go
  • cli/internal/doctor/doctor.go
  • cli/internal/env/machine.go
  • cli/internal/env/machine_test.go
  • setup-linux.sh
  • setup-windows.ps1
  • specs/BUG-029-seed-machine-repo-dir/proposal.md
  • specs/BUG-029-seed-machine-repo-dir/tasks.md
  • specs/BUG-029-seed-machine-repo-dir/verification.md
  • tests/verify-setup.bats
✨ Finishing Touches
🧪 Generate unit tests (beta)
  • Create PR with unit tests
  • Commit unit tests in branch fix/seed-machine-repo-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.

…v set ships

The integration container installs the released dotf (install-dotf.sh downloads
the pinned release, not a PR build) and dotf is off the bats-time PATH, so the
new env set subcommand cannot be exercised there yet. Guard the two #696 checks
to skip until an available dotf carries env set; the seed logic stays covered by
the Go unit tests + the doctor repo-dir check. Harness gap tracked in #734.
@mlorentedev
mlorentedev merged commit 374d816 into main Jul 10, 2026
13 checks passed
@mlorentedev
mlorentedev deleted the fix/seed-machine-repo-dir branch July 10, 2026 10:55
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.

BUG: no journey creates machine.json — phantom DOTFILES_REPO_DIR default breaks update/mem/doctor --fix

1 participant