Skip to content

fix(mount): default LazyRepos to off (opt-in for huge-org workspaces)#121

Merged
khaliqgant merged 3 commits intomainfrom
codex/lazyrepos-default-off
May 9, 2026
Merged

fix(mount): default LazyRepos to off (opt-in for huge-org workspaces)#121
khaliqgant merged 3 commits intomainfrom
codex/lazyrepos-default-off

Conversation

@khaliqgant
Copy link
Copy Markdown
Member

@khaliqgant khaliqgant commented May 9, 2026

Summary

  • add --lazy-repos / RELAYFILE_LAZY_REPOS opt-in wiring for relayfile-mount polling and FUSE modes
  • keep lazy GitHub materialization plumbing intact while defaulting SyncerOptions.LazyRepos to eager behavior
  • update layout/README docs and add tests for default eager behavior plus env opt-in
  • add provider eval review via OpenRouter free model and tighten the GitHub comparison eval evidence

Tests

  • go test ./internal/mountfuse/... ./internal/mountsync/...
  • go test ./cmd/relayfile-mount
  • go test ./internal/mountfuse/... ./internal/mountsync/... ./cmd/relayfile-mount
  • npm run evals:offline (12 passed, 3 needs-human, 0 failed)
  • RELAYFILE_EVAL_OPENROUTER_MODEL=openai/gpt-oss-120b:free npm run evals:provider (15 passed, 0 needs-human, 0 failed)

@coderabbitai
Copy link
Copy Markdown

coderabbitai Bot commented May 9, 2026

Review Change Stack

Caution

Review failed

Pull request was closed or merged during review

📝 Walkthrough

Walkthrough

This PR adds lazy materialization of GitHub repositories as an optional feature controlled by the --lazy-repos CLI flag and RELAYFILE_LAZY_REPOS environment variable. The setting flows from CLI through mount initialization into syncer and FUSE layer components, with fallback support for the legacy RELAYFILE_MOUNT_LAZY_GITHUB_REPOS variable. Documentation and tests are updated accordingly.

Changes

Lazy Repository Materialization Configuration

Layer / File(s) Summary
Configuration Types
internal/mountfuse/fs.go, internal/mountsync/syncer.go, cmd/relayfile-mount/main.go
Config and mountConfig structs gain LazyRepos fields; SyncerOptions.LazyRepos becomes *bool.
Environment Variable Parsing
cmd/relayfile-mount/main.go, internal/mountsync/syncer.go
lazyReposEnv() added; NewSyncer prefers explicit option, otherwise parses RELAYFILE_LAZY_REPOS with fallback to legacy RELAYFILE_MOUNT_LAZY_GITHUB_REPOS.
CLI Flag & Configuration
cmd/relayfile-mount/main.go, cmd/relayfile-mount/main_test.go
--lazy-repos flag added with env-derived default; tests for lazyReposEnv() added.
Component Wiring
cmd/relayfile-mount/fuse_mount.go, cmd/relayfile-mount/main.go, internal/mountfuse/fs.go, internal/mountsync/syncer.go
mountConfig.lazyRepos propagated into mountfuse.Config and SyncerOptions; newFSState initializes lazy materialization cache based on cfg.LazyRepos.
Documentation & Examples
README.md, internal/mountfuse/layout.go
README example expanded to show GitHub subtree; LAYOUT.md updated to document eager-by-default syncing and opt-in lazy mode with first-access one-time latency note.
Tests & Test Isolation
internal/mountsync/syncer_test.go, internal/mountfuse/fuse_test.go, cmd/relayfile-mount/main_test.go, evals/suites/integrations/cases.md
Added/updated unit tests for env defaulting and pointer-based options; FUSE tests use new helper newLazyMountTestRoot; integration eval fixture narrowed to explicit reads and stronger checks.

Evals Runner — OpenRouter Human Review

Layer / File(s) Summary
Eval Runner Implementation
scripts/evals/run-relayfile-evals.mjs
Add OpenRouter-based reviewWithOpenRouter() path invoked in provider mode for human-review cases; includes prompt builder, response extraction, verdict parsing, API-key handling, and timeout.
CLI Help & NPM Scripts
scripts/evals/run-relayfile-evals.mjs, package.json
CLI help updated to document --provider alias; package.json scripts add evals:provider and rewrite evals:offline to run compile-then-run flow.
Eval Fixture Adjustments
evals/suites/integrations/cases.md
Integration eval changed to explicitly read two issue JSON files and strengthened deterministic checks and call allowances.

Sequence Diagram(s)

sequenceDiagram
  participant User
  participant CLI
  participant MountMain
  participant Syncer
  participant FUSE
  participant Remote
  User->>CLI: invoke relayfile mount (--lazy-repos)
  CLI->>MountMain: parsed flag (default from env)
  MountMain->>Syncer: build SyncerOptions (LazyRepos pointer)
  MountMain->>FUSE: build mountfuse.Config (LazyRepos)
  Syncer->>Remote: sync/decide eager vs lazy (env/opts)
  FUSE->>Remote: first ls/stat triggers materialize when lazy
Loading

Estimated code review effort

🎯 3 (Moderate) | ⏱️ ~20 minutes

Possibly related PRs

Poem

🐰 I toggled lazy flags with care,
Repos wait asleep until someone dares,
First stat wakes a one-time fetch and cheer,
Eager by default, opt-in keeps them near,
Mounts hum softly and tests run clear.

🚥 Pre-merge checks | ✅ 4 | ❌ 1

❌ Failed checks (1 warning)

Check name Status Explanation Resolution
Docstring Coverage ⚠️ Warning Docstring coverage is 0.00% which is insufficient. The required threshold is 80.00%. Write docstrings for the functions missing them to satisfy the coverage threshold.
✅ Passed checks (4 passed)
Check name Status Explanation
Title check ✅ Passed The title accurately captures the main change: defaulting LazyRepos to off (eager behavior) with an opt-in mechanism for workspaces that need it.
Description check ✅ Passed The description is comprehensive and clearly relates to the changeset, detailing the opt-in wiring, default behavior changes, documentation updates, and test additions across multiple files.
Linked Issues check ✅ Passed Check skipped because no linked issues were found for this pull request.
Out of Scope Changes check ✅ Passed Check skipped because no linked issues were found for this pull request.

✏️ Tip: You can configure your own custom pre-merge checks in the settings.

✨ 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 codex/lazyrepos-default-off

Comment @coderabbitai help to get the list of available commands and usage tips.

Copy link
Copy Markdown

@coderabbitai coderabbitai Bot left a comment

Choose a reason for hiding this comment

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

Actionable comments posted: 1

Caution

Some comments are outside the diff and can’t be posted inline due to platform limitations.

⚠️ Outside diff range comments (1)
internal/mountsync/syncer.go (1)

633-645: ⚠️ Potential issue | 🟠 Major | ⚡ Quick win

NewSyncer currently overrides explicit SyncerOptions.LazyRepos with process env

This makes caller intent non-deterministic (for example, an explicit --lazy-repos=false can still end up enabled if env is set), which breaks expected flag-over-env precedence.

💡 Proposed fix
  lazyRepos := opts.LazyRepos
- if raw := strings.TrimSpace(os.Getenv("RELAYFILE_LAZY_REPOS")); raw != "" {
- 	if parsed, perr := strconv.ParseBool(raw); perr == nil {
- 		lazyRepos = parsed
- 	} else if opts.Logger != nil {
- 		opts.Logger.Printf("ignoring invalid RELAYFILE_LAZY_REPOS=%q: %v", raw, perr)
- 	}
- } else if raw := strings.TrimSpace(os.Getenv("RELAYFILE_MOUNT_LAZY_GITHUB_REPOS")); raw != "" {
- 	if parsed, perr := strconv.ParseBool(raw); perr == nil {
- 		lazyRepos = parsed
- 	} else if opts.Logger != nil {
- 		opts.Logger.Printf("ignoring invalid RELAYFILE_MOUNT_LAZY_GITHUB_REPOS=%q: %v", raw, perr)
- 	}
- }

If env fallback is still needed for non-CLI callers, resolve it at the call site once (or move to a tri-state option) so precedence is explicit.

🤖 Prompt for AI Agents
Verify each finding against current code. Fix only still-valid issues, skip the
rest with a brief reason, keep changes minimal, and validate.

In `@internal/mountsync/syncer.go` around lines 633 - 645, NewSyncer currently
lets environment variables override an explicit SyncerOptions.LazyRepos; make
precedence explicit by treating LazyRepos as an optional tri-state: change
SyncerOptions.LazyRepos to *bool and in NewSyncer only consult
RELAYFILE_LAZY_REPOS / RELAYFILE_MOUNT_LAZY_GITHUB_REPOS when opts.LazyRepos ==
nil, otherwise use the provided *opts.LazyRepos value to set local lazyRepos;
keep the same parse+log behavior (opts.Logger.Printf) for invalid env values but
do not mutate or override an explicitly set opts.LazyRepos.
🤖 Prompt for all review comments with AI agents
Verify each finding against current code. Fix only still-valid issues, skip the
rest with a brief reason, keep changes minimal, and validate.

Inline comments:
In `@internal/mountfuse/fs.go`:
- Around line 168-170: newFSState currently re-checks environment via
lazyGithubReposEnabled() and can override an explicit cfg.LazyRepos; remove the
env re-read so the resolved config is authoritative: in newFSState only check
cfg.LazyRepos (i.e., if cfg.LazyRepos { state.lazyRepos =
NewLazyMaterializeCache() }) and delete the lazyGithubReposEnabled() branch so
state.lazyRepos is set solely based on cfg.LazyRepos.

---

Outside diff comments:
In `@internal/mountsync/syncer.go`:
- Around line 633-645: NewSyncer currently lets environment variables override
an explicit SyncerOptions.LazyRepos; make precedence explicit by treating
LazyRepos as an optional tri-state: change SyncerOptions.LazyRepos to *bool and
in NewSyncer only consult RELAYFILE_LAZY_REPOS /
RELAYFILE_MOUNT_LAZY_GITHUB_REPOS when opts.LazyRepos == nil, otherwise use the
provided *opts.LazyRepos value to set local lazyRepos; keep the same parse+log
behavior (opts.Logger.Printf) for invalid env values but do not mutate or
override an explicitly set opts.LazyRepos.
🪄 Autofix (Beta)

Fix all unresolved CodeRabbit comments on this PR:

  • Push a commit to this branch (recommended)
  • Create a new PR with the fixes

ℹ️ Review info
⚙️ Run configuration

Configuration used: Organization UI

Review profile: CHILL

Plan: Pro Plus

Run ID: cce59ec5-2bd2-4540-a3cc-c03b96e489d3

📥 Commits

Reviewing files that changed from the base of the PR and between bdbcd13 and cd0811b.

📒 Files selected for processing (8)
  • README.md
  • cmd/relayfile-mount/fuse_mount.go
  • cmd/relayfile-mount/main.go
  • cmd/relayfile-mount/main_test.go
  • internal/mountfuse/fs.go
  • internal/mountfuse/layout.go
  • internal/mountsync/syncer.go
  • internal/mountsync/syncer_test.go

Comment thread internal/mountfuse/fs.go Outdated
Copy link
Copy Markdown
Contributor

@devin-ai-integration devin-ai-integration Bot left a comment

Choose a reason for hiding this comment

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

Devin Review found 2 potential issues.

View 3 additional findings in Devin Review.

Open in Devin Review

Comment thread internal/mountfuse/fs.go Outdated
pathByInode: map[uint64]string{1: normalizeRemotePath(cfg.RemoteRoot)},
}
if lazyGithubReposEnabled() {
if cfg.LazyRepos || lazyGithubReposEnabled() {
Copy link
Copy Markdown
Contributor

Choose a reason for hiding this comment

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

🟡 FUSE path: --lazy-repos=false cannot override env var due to || with lazyGithubReposEnabled()

In newFSState, the condition cfg.LazyRepos || lazyGithubReposEnabled() at internal/mountfuse/fs.go:168 means the env var RELAYFILE_LAZY_REPOS (or RELAYFILE_MOUNT_LAZY_GITHUB_REPOS) is read twice: once by the CLI to set the flag default (cmd/relayfile-mount/main.go:70), and again directly from the environment by lazyGithubReposEnabled(). When a user sets RELAYFILE_LAZY_REPOS=true and explicitly passes --lazy-repos=false, the CLI correctly resolves cfg.LazyRepos = false, but lazyGithubReposEnabled() re-reads the env var and returns true, so the || evaluates to true and lazy repos is enabled anyway. The explicit CLI flag is silently ignored on the FUSE path.

Suggested change
if cfg.LazyRepos || lazyGithubReposEnabled() {
if cfg.LazyRepos {
Open in Devin Review

Was this helpful? React with 👍 or 👎 to provide feedback.

Comment thread internal/mountsync/syncer.go Outdated
Comment on lines 633 to 642
if raw := strings.TrimSpace(os.Getenv("RELAYFILE_LAZY_REPOS")); raw != "" {
if parsed, perr := strconv.ParseBool(raw); perr == nil {
lazyRepos = parsed
} else if opts.Logger != nil {
opts.Logger.Printf("ignoring invalid RELAYFILE_LAZY_REPOS=%q: %v", raw, perr)
}
} else if raw := strings.TrimSpace(os.Getenv("RELAYFILE_MOUNT_LAZY_GITHUB_REPOS")); raw != "" {
if parsed, perr := strconv.ParseBool(raw); perr == nil {
lazyRepos = parsed
} else if opts.Logger != nil {
Copy link
Copy Markdown
Contributor

Choose a reason for hiding this comment

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

🟡 Syncer path: env var unconditionally overrides opts.LazyRepos, defeating --lazy-repos=false CLI flag

In NewSyncer at internal/mountsync/syncer.go:633-645, the env var RELAYFILE_LAZY_REPOS is read and unconditionally overrides opts.LazyRepos. When the CLI is the caller, opts.LazyRepos has already been resolved from the same env var plus the explicit --lazy-repos flag (cmd/relayfile-mount/main.go:70,112,167). If a user has RELAYFILE_LAZY_REPOS=true and passes --lazy-repos=false, the CLI sets opts.LazyRepos = false, but the syncer re-reads the env var and overrides it back to true. This is the same double-reading issue as the FUSE path but on the poll mode side.

Scenario trace
  1. CLI: lazyReposEnv() reads RELAYFILE_LAZY_REPOS=true → default = true
  2. User passes --lazy-repos=false*lazyRepos = false
  3. cfg.lazyRepos = falseopts.LazyRepos = false
  4. Syncer: lazyRepos := opts.LazyReposfalse
  5. Syncer: os.Getenv("RELAYFILE_LAZY_REPOS")"true"lazyRepos = true ← override!

(Refers to lines 633-645)

Prompt for agents
The env var override in NewSyncer at syncer.go:633-645 unconditionally re-reads RELAYFILE_LAZY_REPOS and RELAYFILE_MOUNT_LAZY_GITHUB_REPOS, overriding the opts.LazyRepos value that the CLI has already resolved from those same env vars plus the --lazy-repos flag. This defeats the explicit CLI flag.

The challenge is that NewSyncer is also called from non-CLI code (tests, programmatic use) where opts.LazyRepos might be the zero value and the env var should serve as a fallback. A bool field has no sentinel to distinguish 'not explicitly set' from 'explicitly set to false.'

Possible approaches:
1. Remove the env var re-reading from NewSyncer entirely and rely on callers to resolve env vars (simplest, but breaks non-CLI callers that rely on the env var fallback).
2. Change SyncerOptions.LazyRepos from bool to *bool so nil means 'not set' and allows the env var fallback, while an explicit false means 'explicitly disabled.'
3. Have the CLI mark that the env var was already resolved (e.g., a separate field like LazyReposExplicit bool), so the syncer only applies the env var override when not explicitly set.
Open in Devin Review

Was this helpful? React with 👍 or 👎 to provide feedback.

@khaliqgant khaliqgant merged commit 38b511a into main May 9, 2026
6 of 7 checks passed
@khaliqgant khaliqgant deleted the codex/lazyrepos-default-off branch May 9, 2026 10:42
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