Skip to content

fix(daemon): platform-aware resource thresholds for macOS#1173

Closed
ahmedibrahim085 wants to merge 5926 commits intoruvnet:mainfrom
ahmedibrahim085:fix/platform-aware-resource-thresholds
Closed

fix(daemon): platform-aware resource thresholds for macOS#1173
ahmedibrahim085 wants to merge 5926 commits intoruvnet:mainfrom
ahmedibrahim085:fix/platform-aware-resource-thresholds

Conversation

@ahmedibrahim085
Copy link

Summary

  • Daemon workers (audit, optimize, testgaps) permanently blocked on macOS due to hardcoded resource thresholds that are incompatible with macOS system metric reporting
  • CPU threshold of 2.0 is exceeded by os.loadavg() on any multi-core Mac at idle (reports aggregate load, not per-core)
  • Memory threshold of 20% is unreachable because os.freemem() reports only truly unused RAM, not reclaimable cache (macOS typically shows 5-8% "free")
  • Compute thresholds from system capabilities: CPU cores × 3 for load, 1% free memory on Darwin (5% on Linux)
  • Thresholds remain overridable via config parameter — zero breaking change

Problem

All daemon workers with resource checks fail with:

CPU load too high: 3.80
Memory too low: 7.6% free

On a 16-core Mac at idle. Workers have 0% success rate (0 runs out of hundreds of scheduler cycles).

Root cause: os.loadavg()[0] returns aggregate load (not per-core), and os.freemem() excludes reclaimable cache on macOS. The hardcoded thresholds assume Linux-like reporting semantics.

Approach

  1. import os from 'os' — Use top-level ESM import instead of await import('os') in async method. Built-in modules don't need dynamic import, and this enables synchronous access in the constructor.

  2. getDefaultResourceThresholds() — Extract threshold computation into a pure function that:

  3. Startup logging — Log computed thresholds (values, core count, platform) at daemon start for debuggability.

Test plan

  • Verified on 16-core macOS: all 5 workers execute successfully after patch
  • daemon status shows 100% success rate for audit, optimize, testgaps (were 0% before)
  • daemon trigger --worker audit completes in <1ms
  • Config override still works (config parameter takes precedence over computed defaults)
  • Verify Linux behavior unchanged (same function, higher thresholds: cores×3 for CPU, 5% for memory)

Fixes #1077

ruvnet and others added 30 commits February 8, 2026 17:28
Automatic checkpoint created by Claude Code
- Branch: rebrand/ruvflow-umbrella
- Timestamp: 2026-02-08T17:28:41Z
- Changes: 1 file(s)

🤖 Generated with [Claude Code](https://claude.com/claude-code)

Co-Authored-By: Claude Opus 4.5 <noreply@anthropic.com>
Automatic checkpoint created by Claude Code
- Branch: rebrand/ruvflow-umbrella
- Timestamp: 2026-02-08T17:28:42Z
- Changes: 1 file(s)

🤖 Generated with [Claude Code](https://claude.com/claude-code)

Co-Authored-By: Claude Opus 4.5 <noreply@anthropic.com>
Automatic checkpoint created by Claude Code
- Branch: rebrand/ruvflow-umbrella
- Timestamp: 2026-02-08T17:28:49Z
- Changes: 1 file(s)

🤖 Generated with [Claude Code](https://claude.com/claude-code)

Co-Authored-By: Claude Opus 4.5 <noreply@anthropic.com>
Automatic checkpoint created by Claude Code
- Branch: rebrand/ruvflow-umbrella
- Timestamp: 2026-02-08T17:31:20Z
- Changes: 1 file(s)

🤖 Generated with [Claude Code](https://claude.com/claude-code)

Co-Authored-By: Claude Opus 4.5 <noreply@anthropic.com>
Automatic checkpoint created by Claude Code
- Branch: rebrand/ruvflow-umbrella
- Timestamp: 2026-02-08T17:35:33Z
- Changes: 5 file(s)

🤖 Generated with [Claude Code](https://claude.com/claude-code)

Co-Authored-By: Claude Opus 4.5 <noreply@anthropic.com>
Automatic checkpoint created by Claude Code
- Branch: rebrand/ruvflow-umbrella
- Timestamp: 2026-02-08T17:52:17Z
- Changes: 1 file(s)

🤖 Generated with [Claude Code](https://claude.com/claude-code)

Co-Authored-By: Claude Opus 4.5 <noreply@anthropic.com>
Automatic checkpoint created by Claude Code
- Branch: rebrand/ruvflow-umbrella
- Timestamp: 2026-02-08T17:52:29Z
- Changes: 1 file(s)

🤖 Generated with [Claude Code](https://claude.com/claude-code)

Co-Authored-By: Claude Opus 4.5 <noreply@anthropic.com>
Automatic checkpoint created by Claude Code
- Branch: rebrand/ruvflow-umbrella
- Timestamp: 2026-02-08T17:52:38Z
- Changes: 1 file(s)

🤖 Generated with [Claude Code](https://claude.com/claude-code)

Co-Authored-By: Claude Opus 4.5 <noreply@anthropic.com>
Automatic checkpoint created by Claude Code
- Branch: rebrand/ruvflow-umbrella
- Timestamp: 2026-02-08T17:53:15Z
- Changes: 2 file(s)

🤖 Generated with [Claude Code](https://claude.com/claude-code)

Co-Authored-By: Claude Opus 4.5 <noreply@anthropic.com>
Automatic checkpoint created by Claude Code
- Branch: rebrand/ruvflow-umbrella
- Timestamp: 2026-02-08T20:39:45Z
- Changes: 1 file(s)

🤖 Generated with [Claude Code](https://claude.com/claude-code)

Co-Authored-By: Claude Opus 4.5 <noreply@anthropic.com>
Automatic checkpoint created by Claude Code
- Branch: rebrand/ruvflow-umbrella
- Timestamp: 2026-02-08T20:39:54Z
- Changes: 1 file(s)

🤖 Generated with [Claude Code](https://claude.com/claude-code)

Co-Authored-By: Claude Opus 4.5 <noreply@anthropic.com>
Automatic checkpoint created by Claude Code
- Branch: rebrand/ruvflow-umbrella
- Timestamp: 2026-02-08T20:40:34Z
- Changes: 1 file(s)

🤖 Generated with [Claude Code](https://claude.com/claude-code)

Co-Authored-By: Claude Opus 4.5 <noreply@anthropic.com>
Automatic checkpoint created by Claude Code
- Branch: rebrand/ruvflow-umbrella
- Timestamp: 2026-02-08T20:40:39Z
- Changes: 1 file(s)

🤖 Generated with [Claude Code](https://claude.com/claude-code)

Co-Authored-By: Claude Opus 4.5 <noreply@anthropic.com>
Automatic checkpoint created by Claude Code
- Branch: rebrand/ruvflow-umbrella
- Timestamp: 2026-02-08T20:41:40Z
- Changes: 1 file(s)

🤖 Generated with [Claude Code](https://claude.com/claude-code)

Co-Authored-By: Claude Opus 4.5 <noreply@anthropic.com>
Automatic checkpoint created by Claude Code
- Branch: rebrand/ruvflow-umbrella
- Timestamp: 2026-02-08T20:41:52Z
- Changes: 1 file(s)

🤖 Generated with [Claude Code](https://claude.com/claude-code)

Co-Authored-By: Claude Opus 4.5 <noreply@anthropic.com>
Automatic checkpoint created by Claude Code
- Branch: rebrand/ruvflow-umbrella
- Timestamp: 2026-02-08T20:42:38Z
- Changes: 1 file(s)

🤖 Generated with [Claude Code](https://claude.com/claude-code)

Co-Authored-By: Claude Opus 4.5 <noreply@anthropic.com>
Automatic checkpoint created by Claude Code
- Branch: rebrand/ruvflow-umbrella
- Timestamp: 2026-02-08T21:20:16Z
- Changes: 6 file(s)

🤖 Generated with [Claude Code](https://claude.com/claude-code)

Co-Authored-By: Claude Opus 4.5 <noreply@anthropic.com>
Automatic checkpoint created by Claude Code
- Branch: rebrand/ruvflow-umbrella
- Timestamp: 2026-02-08T21:20:20Z
- Changes: 1 file(s)

🤖 Generated with [Claude Code](https://claude.com/claude-code)

Co-Authored-By: Claude Opus 4.5 <noreply@anthropic.com>
Automatic checkpoint created by Claude Code
- Branch: rebrand/ruvflow-umbrella
- Timestamp: 2026-02-08T21:20:27Z
- Changes: 1 file(s)

🤖 Generated with [Claude Code](https://claude.com/claude-code)

Co-Authored-By: Claude Opus 4.5 <noreply@anthropic.com>
Automatic checkpoint created by Claude Code
- Branch: rebrand/ruvflow-umbrella
- Timestamp: 2026-02-08T21:20:35Z
- Changes: 1 file(s)

🤖 Generated with [Claude Code](https://claude.com/claude-code)

Co-Authored-By: Claude Opus 4.5 <noreply@anthropic.com>
Automatic checkpoint created by Claude Code
- Branch: rebrand/ruvflow-umbrella
- Timestamp: 2026-02-08T21:20:45Z
- Changes: 1 file(s)

🤖 Generated with [Claude Code](https://claude.com/claude-code)

Co-Authored-By: Claude Opus 4.5 <noreply@anthropic.com>
Automatic checkpoint created by Claude Code
- Branch: rebrand/ruvflow-umbrella
- Timestamp: 2026-02-08T21:20:58Z
- Changes: 1 file(s)

🤖 Generated with [Claude Code](https://claude.com/claude-code)

Co-Authored-By: Claude Opus 4.5 <noreply@anthropic.com>
Automatic checkpoint created by Claude Code
- Branch: rebrand/ruvflow-umbrella
- Timestamp: 2026-02-08T21:21:06Z
- Changes: 1 file(s)

🤖 Generated with [Claude Code](https://claude.com/claude-code)

Co-Authored-By: Claude Opus 4.5 <noreply@anthropic.com>
Automatic checkpoint created by Claude Code
- Branch: rebrand/ruvflow-umbrella
- Timestamp: 2026-02-08T21:21:10Z
- Changes: 1 file(s)

🤖 Generated with [Claude Code](https://claude.com/claude-code)

Co-Authored-By: Claude Opus 4.5 <noreply@anthropic.com>
Automatic checkpoint created by Claude Code
- Branch: rebrand/ruvflow-umbrella
- Timestamp: 2026-02-08T21:21:15Z
- Changes: 1 file(s)

🤖 Generated with [Claude Code](https://claude.com/claude-code)

Co-Authored-By: Claude Opus 4.5 <noreply@anthropic.com>
Automatic checkpoint created by Claude Code
- Branch: rebrand/ruvflow-umbrella
- Timestamp: 2026-02-08T21:21:20Z
- Changes: 1 file(s)

🤖 Generated with [Claude Code](https://claude.com/claude-code)

Co-Authored-By: Claude Opus 4.5 <noreply@anthropic.com>
Automatic checkpoint created by Claude Code
- Branch: rebrand/ruvflow-umbrella
- Timestamp: 2026-02-08T21:26:02Z
- Changes: 1 file(s)

🤖 Generated with [Claude Code](https://claude.com/claude-code)

Co-Authored-By: Claude Opus 4.5 <noreply@anthropic.com>
Automatic checkpoint created by Claude Code
- Branch: rebrand/ruvflow-umbrella
- Timestamp: 2026-02-08T21:26:33Z
- Changes: 1 file(s)

🤖 Generated with [Claude Code](https://claude.com/claude-code)

Co-Authored-By: Claude Opus 4.5 <noreply@anthropic.com>
Automatic checkpoint created by Claude Code
- Branch: rebrand/ruvflow-umbrella
- Timestamp: 2026-02-08T21:26:41Z
- Changes: 1 file(s)

🤖 Generated with [Claude Code](https://claude.com/claude-code)

Co-Authored-By: Claude Opus 4.5 <noreply@anthropic.com>
Automatic checkpoint created by Claude Code
- Branch: rebrand/ruvflow-umbrella
- Timestamp: 2026-02-08T21:27:23Z
- Changes: 1 file(s)

🤖 Generated with [Claude Code](https://claude.com/claude-code)

Co-Authored-By: Claude Opus 4.5 <noreply@anthropic.com>
ruvnet and others added 27 commits February 11, 2026 20:59
Automatic checkpoint created by Claude Code
- Branch: rebrand/ruvflow-umbrella
- Timestamp: 2026-02-11T20:59:12Z
- Changes: 1 file(s)

🤖 Generated with [Claude Code](https://claude.com/claude-code)

Co-Authored-By: Claude Opus 4.5 <noreply@anthropic.com>
Automatic checkpoint created by Claude Code
- Branch: rebrand/ruvflow-umbrella
- Timestamp: 2026-02-11T21:05:13Z
- Changes: 5 file(s)

🤖 Generated with [Claude Code](https://claude.com/claude-code)

Co-Authored-By: Claude Opus 4.5 <noreply@anthropic.com>
Automatic checkpoint created by Claude Code
- Branch: rebrand/ruvflow-umbrella
- Timestamp: 2026-02-11T22:50:34Z
- Changes: 7 file(s)

🤖 Generated with [Claude Code](https://claude.com/claude-code)

Co-Authored-By: Claude Opus 4.5 <noreply@anthropic.com>
Automatic checkpoint created by Claude Code
- Branch: rebrand/ruvflow-umbrella
- Timestamp: 2026-02-11T22:50:47Z
- Changes: 1 file(s)

🤖 Generated with [Claude Code](https://claude.com/claude-code)

Co-Authored-By: Claude Opus 4.5 <noreply@anthropic.com>
Automatic checkpoint created by Claude Code
- Branch: rebrand/ruvflow-umbrella
- Timestamp: 2026-02-11T22:50:57Z
- Changes: 1 file(s)

🤖 Generated with [Claude Code](https://claude.com/claude-code)

Co-Authored-By: Claude Opus 4.5 <noreply@anthropic.com>
Automatic checkpoint created by Claude Code
- Branch: rebrand/ruvflow-umbrella
- Timestamp: 2026-02-11T22:51:03Z
- Changes: 1 file(s)

🤖 Generated with [Claude Code](https://claude.com/claude-code)

Co-Authored-By: Claude Opus 4.5 <noreply@anthropic.com>
Automatic checkpoint created by Claude Code
- Branch: rebrand/ruvflow-umbrella
- Timestamp: 2026-02-11T22:52:01Z
- Changes: 1 file(s)

🤖 Generated with [Claude Code](https://claude.com/claude-code)

Co-Authored-By: Claude Opus 4.5 <noreply@anthropic.com>
Automatic checkpoint created by Claude Code
- Branch: rebrand/ruvflow-umbrella
- Timestamp: 2026-02-11T22:52:39Z
- Changes: 1 file(s)

🤖 Generated with [Claude Code](https://claude.com/claude-code)

Co-Authored-By: Claude Opus 4.5 <noreply@anthropic.com>
- Remove sqlite3 and bcrypt from dependency chain (closes ruvnet#1091)
  - Eliminates 10 HIGH severity vulnerabilities (tar@6.2.1 CVEs)
  - Removes 73+ packages from install footprint
  - Pin agentdb@2.0.0-alpha.3.5 in memory and umbrella packages

- Add backward compatibility for older settings.json configs
  - Default --success to true in post-edit, post-command, post-task
  - Default --file to 'unknown' in pre-edit, post-edit
  - Old hook configs no longer error with "Required option missing"

- Add Agent Teams hooks to init settings generator
  - TeammateIdle: auto-assign pending tasks to idle teammates
  - TaskCompleted: train patterns and record completion

- Rename helpers from .js to .cjs for ESM compatibility
  - Root package.json has "type": "module", .js files parse as ESM
  - .cjs extension ensures CommonJS require() works correctly

Published: @claude-flow/cli@3.1.0-alpha.34, claude-flow@3.1.0-alpha.34,
@claude-flow/memory@3.0.0-alpha.9

Co-Authored-By: claude-flow <ruv@ruv.net>
Regenerate package-lock.json and pnpm-lock.yaml to match
updated agentdb dependency. Fixes CI failures where npm ci
and pnpm --frozen-lockfile rejected the version mismatch.

Co-Authored-By: claude-flow <ruv@ruv.net>
- @claude-flow/shared: Add helmet, express, cors, ws as devDeps
  (needed for pnpm strict hoisting in CI). Remove obsolete
  @types/helmet (helmet v7+ ships own types)

- @claude-flow/integration: Fix TS2339 for agentic-flow VERSION
  export removed upstream. Use bracket notation to bypass
  compile-time check (runtime already handled gracefully)

- @claude-flow/testing: Add explicit Mock type annotations to
  vi.fn() fields to fix TS2742 portable type inference errors

All 20 V3 packages now build clean with pnpm -r build.

Co-Authored-By: claude-flow <ruv@ruv.net>
agentdb@2.0.0-alpha.3.6 includes:
- CLI Commander parsing fix (resolves "unknown command 'node'" error)
- LLM Router (FastGRNN-based intelligent model selection)
- Hyperbolic geometry (Poincare ball operations)
- Curriculum learning (hard negative mining, contrastive loss)

Published: claude-flow@3.1.0-alpha.35, @claude-flow/cli@3.1.0-alpha.35,
@claude-flow/memory@3.0.0-alpha.10

Co-Authored-By: claude-flow <ruv@ruv.net>
The command parser enforces `required: true` on option specs BEFORE
the action function runs, so defaulting values in the action was
insufficient. Changed 5 option specs from required to optional:
- pre-edit: --file (defaults to 'unknown')
- post-edit: --file (defaults to 'unknown'), --success (defaults to true)
- post-command: --success (defaults to true)
- post-task: --success (defaults to true)

This enables Claude Code hooks to call these commands without explicit
flags, matching the PostToolUse convention where success is implied.

Published as @claude-flow/cli@3.1.0-alpha.36 and claude-flow@3.1.0-alpha.36.

Co-Authored-By: claude-flow <ruv@ruv.net>
Co-Authored-By: claude-flow <ruv@ruv.net>
- Remove unpublished optional deps from gastown-bridge (gastown-formula-wasm,
  ruvector-gnn-wasm) that caused npm 11 to crash with "Invalid Version:"
- Bump agentdb 2.0.0-alpha.3.6 -> 3.7 (pins @ruvector/gnn@0.1.23 with all
  platform binaries published)
- Bump agentic-flow ^2.0.1-alpha.80 -> ^2.0.7 (pins @ruvector/tiny-dancer@0.1.17
  with linux-arm64-gnu stub published)
- Bump gastown-bridge ^0.1.2 -> ^0.1.3
- Version bump to 3.1.0-alpha.39

Published packages: gastown-bridge@0.1.3, agentdb@2.0.0-alpha.3.7,
agentic-flow@2.0.7, @ruvector/gnn platform stubs @0.1.22+0.1.23,
@ruvector/tiny-dancer-linux-arm64-gnu@0.1.16+0.1.17,
@claude-flow/cli@3.1.0-alpha.39, claude-flow@3.1.0-alpha.39

Co-Authored-By: claude-flow <ruv@ruv.net>
V3 Security, Backward Compat & Agent Teams Hooks
…e Day

- Switch download badges from ruflo to claude-flow npm package
- Add GitHub Project of the Day badge above existing badges
- Bump version to 3.1.0-alpha.40 and publish to npm

Co-Authored-By: claude-flow <ruv@ruv.net>
- Fix ruflo bin to walk node_modules tree instead of using require.resolve
  (blocked by @claude-flow/cli strict exports map)
- Use git rev-parse --show-toplevel for all hook paths in settings.json
  so hooks work from any subdirectory
- Update CLAUDE.md publishing rules to include ruflo as third package
- Bump ruflo to 3.1.0-alpha.16

Co-Authored-By: claude-flow <ruv@ruv.net>
Resolves "Invalid Version:" crash on npm 11.10.0+ caused by
@ruvector/gnn caret-range dedup triggering arborist bug with
corrupted npx cache entries. agentdb 3.7 uses exact gnn@0.1.23.

Co-Authored-By: claude-flow <ruv@ruv.net>
…uvnet#1161)

The PreToolUse:Task hook used $TOOL_INPUT_prompt which expands to the
full agent prompt (thousands of characters), overflowing the shell's
argument length limit. Switched to $TOOL_INPUT_description (the short
3-5 word field) and truncated to 200 chars.

Fixes ruvnet#1160
Co-Authored-By: claude-flow <ruv@ruv.net>
…#1163)

ruflo.js now imports CLI class directly and passes ruflo branding
(name, description) instead of re-importing cli.js with defaults.
Also fixed two hardcoded 'claude-flow' strings in index.ts help text
to use this.name for proper branding in both packages.

Fixes ruvnet#1162
Co-Authored-By: claude-flow <ruv@ruv.net>
On Windows, import() requires file:// URLs, not bare C:\ paths.
Added pathToFileURL() wrapper for all dynamic imports in ruflo.js.

Fixes ruvnet#1164
…port

The `os` module was imported dynamically via `await import('os')` inside
the async `canRunWorker()` method. Since `os` is a Node.js built-in that
is always available and never changes at runtime, this dynamic import
adds unnecessary overhead on every resource check call.

Move to a standard top-level ESM import. This also enables synchronous
access to `os` APIs (like `os.cpus()`) in non-async contexts such as
the constructor, which the next commit requires for platform-aware
threshold computation.
…tead of hardcoded values

Daemon workers (audit, optimize, testgaps) never execute on macOS because
the hardcoded resource thresholds are incompatible with how macOS reports
system metrics.

CPU: os.loadavg() returns aggregate load across all cores. A 16-core Mac
at modest utilization reports loadavg ~3-5, permanently exceeding the
hardcoded maxCpuLoad of 2.0. Workers are blocked even when the system is
effectively idle.

Memory: macOS uses available RAM as filesystem cache. os.freemem() reports
only truly unused memory (typically 5-8%), not reclaimable cache. The 20%
minFreeMemoryPercent threshold is unreachable under normal macOS operation.

Extract threshold computation into getDefaultResourceThresholds() that
scales CPU threshold by core count (cores × 3) and uses a 1% free memory
floor on Darwin. Linux gets a 5% floor since its memory reporting is more
conservative. Both remain overridable via config parameter.

Fixes ruvnet#1077
When debugging why workers are blocked, the first question is "what
thresholds is the daemon using?" Currently this requires reading the
daemon-state.json file after startup.

Add a single log line at daemon start that shows the active maxCpuLoad,
core count, minFreeMemoryPercent, and platform. This makes threshold
misconfiguration immediately visible in daemon logs without additional
tooling.
Copy link

@mixingchex mixingchex left a comment

Choose a reason for hiding this comment

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

REQUEST_CHANGES — Reviewed via hive-mind swarm analysis.

The fix correctly diagnoses the macOS issue — os.loadavg() scaling and macOS memory reporting make hardcoded thresholds permanently block all workers. The memory thresholds (1% Darwin, 5% Linux) are sound.

Required change:
The CPU multiplier cpuCount * 3 is too aggressive — on a 16-core Mac it sets maxCpuLoad = 48, effectively disabling the resource gate entirely.

System Cores Current (2.0) Proposed (x3) Recommended (x1.0)
1-core 1 2.0 3.0 2.0 (floor)
4-core 4 2.0 12.0 4.0
8-core 8 2.0 24.0 8.0
16-core 16 2.0 48.0 16.0

Recommended fix:

maxCpuLoad: Math.max(cpuCount * 1.0, 2.0),

This means "allow workers when load < 100% per core, with a minimum of 2.0 for small machines."

Everything else (static import, startup logging, config override preservation) is clean.

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: Daemon workers never execute on macOS due to unrealistic resource thresholds

3 participants