Skip to content

[rqd] Add config option for default NIMBY lock at startup#2247

Merged
DiegoTavares merged 2 commits intoAcademySoftwareFoundation:masterfrom
officialasishkumar:fix/rqd-default-nimby-lock
Apr 7, 2026
Merged

[rqd] Add config option for default NIMBY lock at startup#2247
DiegoTavares merged 2 commits intoAcademySoftwareFoundation:masterfrom
officialasishkumar:fix/rqd-default-nimby-lock

Conversation

@officialasishkumar
Copy link
Copy Markdown
Contributor

@officialasishkumar officialasishkumar commented Apr 4, 2026

Related Issues

Fixes #2195

Summarize your change.

Adds a new machine.nimby_lock_by_default setting to Rust RQD so a workstation can report nimby_locked immediately at startup when NIMBY mode is enabled. The machine monitor now seeds its initial lock state from config, uses that state in the first startup report, and the shipped sample configs document the new option.

It also adds unit tests for config parsing and initial lock-state selection.

Validation

  • cargo test -p rqd initial_nimby_state -- --nocapture
  • cargo test -p rqd nimby_lock_by_default -- --nocapture

Summary by CodeRabbit

  • New Features

    • New config option to optionally start machines in a NIMBY-locked state (requires NIMBY mode); when enabled, hosts reserve resources at startup and remain locked until user activity is recorded.
  • Chores

    • Updated configuration templates and added tests to validate the new initial NIMBY state behavior.

@linux-foundation-easycla
Copy link
Copy Markdown

linux-foundation-easycla bot commented Apr 4, 2026

CLA Signed

The committers listed above are authorized under a signed CLA.

@coderabbitai
Copy link
Copy Markdown
Contributor

coderabbitai bot commented Apr 4, 2026

No actionable comments were generated in the recent review. 🎉

ℹ️ Recent review info
⚙️ Run configuration

Configuration used: defaults

Review profile: CHILL

Plan: Pro

Run ID: 1dcb13da-a691-4764-a30a-3e9d7bf1e3ce

📥 Commits

Reviewing files that changed from the base of the PR and between 4615e34 and d7f16f3.

📒 Files selected for processing (2)
  • rust/crates/rqd/src/system/machine.rs
  • rust/crates/rqd/src/system/nimby.rs

📝 Walkthrough

Walkthrough

Adds a machine-level config nimby_lock_by_default and threads it into rqd startup and monitoring so a host can begin in a NIMBY-locked state when nimby_mode is enabled; includes tests and a small API addition to detect recorded user activity.

Changes

Cohort / File(s) Summary
Config files
rust/config/rqd.dummy.cuebot.yaml, rust/config/rqd.local.cuebot.yaml, rust/config/rqd.yaml
Introduce machine.nimby_lock_by_default (commented in examples; documented in main config with default false). Requires machine.nimby_mode: true to be effective.
Config struct & tests
rust/crates/rqd/src/config/mod.rs
Added nimby_lock_by_default: bool to MachineConfig, defaulting to false. Added tests for default value and YAML loading.
Machine monitor logic & tests
rust/crates/rqd/src/system/machine.rs
Added initial_nimby_state() and initialize nimby_state from config; propagate nimby lock into inspect_host_state(); call lock_all_cores() at startup when locked; adjusted lock-transition behavior to require recorded activity before unlocking from default-locked state; added unit tests (nimby feature gated).
NIMBY runtime API
rust/crates/rqd/src/system/nimby.rs
Added pub fn has_activity_been_recorded(&self) -> bool to indicate whether any user interaction timestamp has been observed.

Sequence Diagram

sequenceDiagram
    participant Config as Configuration File
    participant Machine as MachineMonitor
    participant Nimby as Nimby
    participant State as LockState

    Config->>Machine: load nimby_mode & nimby_lock_by_default
    Machine->>Machine: initial_nimby_state(config)
    alt nimby_mode && nimby_lock_by_default
        Machine->>State: initialize as NimbyLocked
        Machine->>Machine: lock_all_cores()
    else
        Machine->>State: initialize as Open
    end
    Machine->>Nimby: check has_activity_been_recorded()
    alt activity recorded && idle
        Nimby-->>Machine: activity recorded
        Machine->>State: transition to Open when idle
    else
        Nimby-->>Machine: no activity recorded
        Machine->>State: remain NimbyLocked
    end
Loading

Estimated code review effort

🎯 4 (Complex) | ⏱️ ~45 minutes

Poem

🐇 I’n a burrow, I write with haste,
A nimby lock to guard the place.
Start locked and snug till humans play,
Then open up when they convey.
Hooray—less prance, more render grace! 🎨✨

🚥 Pre-merge checks | ✅ 5
✅ Passed checks (5 passed)
Check name Status Explanation
Description Check ✅ Passed Check skipped - CodeRabbit’s high-level summary is enabled.
Title check ✅ Passed The title accurately describes the main change: adding a config option for default NIMBY lock at startup.
Linked Issues check ✅ Passed The PR fully implements the requirement from #2195: adds a nimby_lock_by_default config option to mark hosts as NIMBY-locked at startup without user interaction.
Out of Scope Changes check ✅ Passed All changes are directly scoped to implementing the nimby_lock_by_default feature; no unrelated modifications detected.
Docstring Coverage ✅ Passed Docstring coverage is 100.00% which is sufficient. The required threshold is 80.00%.

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

✨ Finishing Touches
🧪 Generate unit tests (beta)
  • Create PR with unit tests

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 and usage tips.

@officialasishkumar officialasishkumar marked this pull request as ready for review April 4, 2026 10:15
Copilot AI review requested due to automatic review settings April 4, 2026 10:15
Copy link
Copy Markdown
Contributor

@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

🤖 Prompt for all review comments with AI agents
Verify each finding against the current code and only fix it if needed.

Inline comments:
In `@rust/crates/rqd/src/system/machine.rs`:
- Around line 106-113: The current seeding uses nimby_state for last_lock_state
which allows a default-locked machine (nimby_lock_by_default) to be auto-opened
on inactivity; change the initialization and transition checks so that when
MachineConfig.nimby_lock_by_default is true you (1) initialize last_lock_state
explicitly to LockState::NimbyLocked instead of copying nimby_state, and (2)
update the state-machine transition that currently maps (false,
LockState::NimbyLocked) -> Open to require an explicit unlock (e.g., check
config.nimby_lock_by_default or a new explicit-unlock flag) before moving
NimbyLocked -> Open; reference symbols: initial_nimby_state, last_lock_state,
nimby_state, MachineConfig, and the transition handling that checks activity +
LockState to implement this behavior.
🪄 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: defaults

Review profile: CHILL

Plan: Pro

Run ID: 5d266d3f-b32f-48af-ae74-daa1cfe0364c

📥 Commits

Reviewing files that changed from the base of the PR and between 487a92b and 4615e34.

📒 Files selected for processing (5)
  • rust/config/rqd.dummy.cuebot.yaml
  • rust/config/rqd.local.cuebot.yaml
  • rust/config/rqd.yaml
  • rust/crates/rqd/src/config/mod.rs
  • rust/crates/rqd/src/system/machine.rs

Comment thread rust/crates/rqd/src/system/machine.rs
Copy link
Copy Markdown

Copilot AI left a comment

Choose a reason for hiding this comment

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

Pull request overview

Adds a new RQD configuration option to control the initial NIMBY lock state so hosts can report nimby_locked immediately on startup (when NIMBY mode is enabled), and updates sample configs and tests accordingly.

Changes:

  • Add machine.nimby_lock_by_default to MachineConfig (default false) and document it in shipped YAML configs.
  • Seed MachineMonitor’s initial nimby_state from config and use it in the first startup report.
  • Add unit tests for config parsing and initial lock-state selection.

Reviewed changes

Copilot reviewed 5 out of 5 changed files in this pull request and generated 2 comments.

Show a summary per file
File Description
rust/crates/rqd/src/system/machine.rs Seeds initial NIMBY state from config and uses it in the initial startup host report; adds unit tests for initial state selection.
rust/crates/rqd/src/config/mod.rs Adds nimby_lock_by_default to MachineConfig defaults and adds config load tests.
rust/config/rqd.yaml Documents the new nimby_lock_by_default option in the sample config.
rust/config/rqd.local.cuebot.yaml Adds an example commented setting for nimby_lock_by_default.
rust/config/rqd.dummy.cuebot.yaml Adds an example commented setting for nimby_lock_by_default.

💡 Add Copilot custom instructions for smarter, more guided reviews. Learn how to get started.

Comment on lines 198 to 212
/// Starts an async loop that will update the machine state every `monitor_interval_seconds`.
pub async fn start(&self, startup_flag: oneshot::Sender<()>) -> Result<()> {
let report_client = self.report_client.clone();
#[allow(unused_assignments)]
let mut nimby_locked = false;

#[cfg(feature = "nimby")]
{
nimby_locked = *self.nimby_state.read().await == LockState::NimbyLocked;
}

let host_state = {
let system_lock = self.system_manager.lock().await;
Self::inspect_host_state(&self.maching_config, &system_lock, false)?
Self::inspect_host_state(&self.maching_config, &system_lock, nimby_locked)?
};
Copy link

Copilot AI Apr 4, 2026

Choose a reason for hiding this comment

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

When nimby_lock_by_default seeds nimby_state as NimbyLocked, the startup path only reports nimby_locked but doesn’t apply the same side effects as a lock transition (locking cores / killing running frames). Because handle_nimby_state_change treats (true, NimbyLocked) as “continues locked”, those side effects will never run for a host that starts in the locked state. Consider applying the lock actions once during startup when the initial state is locked (before sending the startup report), so the daemon’s internal state (core reservations / running frames) is consistent with the reported lock state.

Copilot uses AI. Check for mistakes.
Copy link
Copy Markdown
Contributor Author

Choose a reason for hiding this comment

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

Valid concern, fixed. The startup path now explicitly calls lock_all_cores() when the initial nimby state is NimbyLocked. This ensures the daemon's internal core reservations are consistent with the reported lock state right from startup, rather than relying on a state transition that would never fire for the "continues locked" case.

Comment thread rust/crates/rqd/src/system/machine.rs Outdated
Comment on lines +201 to +207
#[allow(unused_assignments)]
let mut nimby_locked = false;

#[cfg(feature = "nimby")]
{
nimby_locked = *self.nimby_state.read().await == LockState::NimbyLocked;
}
Copy link

Copilot AI Apr 4, 2026

Choose a reason for hiding this comment

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

The #[allow(unused_assignments)] + let mut nimby_locked = false; pattern is duplicated (also appears in collect_host_report) and is only needed because the initial assignment is overwritten under the nimby feature. To avoid the lint suppression and reduce duplication, consider defining nimby_locked with #[cfg(feature = "nimby")] / #[cfg(not(feature = "nimby"))] split bindings, or extracting a small helper that returns the current nimby_locked boolean.

Suggested change
#[allow(unused_assignments)]
let mut nimby_locked = false;
#[cfg(feature = "nimby")]
{
nimby_locked = *self.nimby_state.read().await == LockState::NimbyLocked;
}
#[cfg(feature = "nimby")]
let nimby_locked = *self.nimby_state.read().await == LockState::NimbyLocked;
#[cfg(not(feature = "nimby"))]
let nimby_locked = false;

Copilot uses AI. Check for mistakes.
Copy link
Copy Markdown
Contributor Author

Choose a reason for hiding this comment

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

Good suggestion, applied exactly as proposed. Both occurrences (in start() and collect_host_report()) now use paired #[cfg(feature = "nimby")] / #[cfg(not(feature = "nimby"))] bindings, eliminating the #[allow(unused_assignments)] suppression and the mutable rebinding pattern.

The NIMBY state machine had two issues when a host started in
NimbyLocked state via the nimby_lock_by_default config option:

1. Immediate auto-unlock: is_user_active() returns false when no user
   interaction has ever been recorded (epoch=0). The state machine
   treated this the same as "user became idle", causing the
   (false, NimbyLocked) -> Open transition to fire on the very first
   monitor tick. Fix: add Nimby::has_activity_been_recorded() and use
   a match guard so the unlock transition only fires after real user
   activity has been observed and then ceased.

2. Missing startup side effects: the startup path reported
   nimby_locked=true to Cuebot but never called lock_all_cores(), so
   cores remained bookable despite the locked state. The periodic
   handle_nimby_state_change only runs side effects on the
   Open -> NimbyLocked transition, never for "continues locked". Fix:
   explicitly lock all cores during startup when nimby_locked is true.

Also cleaned up the duplicated #[allow(unused_assignments)] pattern
for the nimby_locked variable in both start() and
collect_host_report(), replacing it with paired #[cfg] / #[cfg(not)]
bindings.

Signed-off-by: Asish Kumar <officialasishkumar@gmail.com>
Copy link
Copy Markdown
Collaborator

@DiegoTavares DiegoTavares left a comment

Choose a reason for hiding this comment

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

Thanks for the contribution.

@DiegoTavares DiegoTavares merged commit a008061 into AcademySoftwareFoundation:master Apr 7, 2026
25 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.

[rust/rqd] Add config option to turn on Nimby Lock by default

3 participants