The generic "node command not allowed" error gives no indication of why the
command was rejected, making it hard to diagnose issues (e.g. running
`nodes notify` against a Linux node that does not declare `system.notify`).
Include the rejection reason and node platform in the error message so
callers can tell whether the command is not supported by the node, not in
the platform allowlist, or the node did not advertise its capabilities.
Fixes#24616
Co-Authored-By: Claude Opus 4.6 <noreply@anthropic.com>
(cherry picked from commit e3d74619bc9d2cf6d93bc5cb19e35d318784bf6a)
* fix: reduce log noise for node disconnect/late invoke errors
- Handle both 'node not connected' and 'node disconnected' errors at info level
- Return success with late:true for unknown invoke IDs instead of error
- Add 30-second throttle to skills change listener to prevent rapid-fire probes
- Add tests for isNodeUnavailableError and late invoke handling
* fix: clean up skills refresh timer and listener on shutdown
Store the return value from registerSkillsChangeListener() and call it
on gateway shutdown. Also clear any pending refresh timer. This follows
the same pattern used for agentUnsub and heartbeatUnsub.
* refactor: simplify KISS/YAGNI - inline checks, remove unit tests for internal utilities
* fix: reduce gateway log noise (#1607) (thanks @petter-b)
* test: align agent id casing expectations (#1607)
---------
Co-authored-by: Peter Steinberger <steipete@gmail.com>