Skip to content

docs(orchestrating-agent-relay): fleet node enrollment + availability diagnostics - #93

Merged
khaliqgant merged 4 commits into
mainfrom
docs/fleet-node-enrollment-and-availability
Aug 6, 2026
Merged

docs(orchestrating-agent-relay): fleet node enrollment + availability diagnostics#93
khaliqgant merged 4 commits into
mainfrom
docs/fleet-node-enrollment-and-availability

Conversation

@khaliqgant

@khaliqgant khaliqgant commented Aug 6, 2026

Copy link
Copy Markdown
Member

Extends orchestrating-agent-relay (2.2.0 → 2.3.0) with the two fleet-node gaps found while recovering a Mac mini fleet node after a reboot. No new skill — the existing fleet section already owned this area, and a second skill would have split discovery.

What's added

"Is the node actually available?"online is not the same as available for placement. A node can be live and never receive a spawn. Documents checking the spawn:* capability list rather than the status field, plus an end-to-end placement proof that spawns from a different machine (so it tests placement, not a local spawn), matches dispatchedNodeId, verifies the process on the target host with pgrep, and releases.

"Enrolling a new machine as a fleet node" — the two-step API flow (POST /api/v1/fleet/enrollment-tokensPOST /api/v1/fleet/register), linking cloud/dev-stack/fleet-node-bootstrap/README.md as authoritative rather than duplicating it, since that will drift. The reaper guard is called out prominently: agent-relay node up terminates every broker whose CWD is the resolved project root, and a $HOME-rooted workdir reaps every $HOME-rooted broker — relay#1328, a real incident on a shared machine. Also notes enrollment survives reboots via the com.agentrelay.fleet-node LaunchAgent, so a rebooted machine does not need re-enrolling.

Five Common Mistakes rows for CLI behaviour that isn't documented anywhere:

  • fleet nodes hides offline/non-fleet records by default — it hid 385 of 390 on a real workspace, which is why a node that exists appears missing
  • output truncates at 64KB through a pipe, breaking JSON parsing mid-object; redirect to a file first
  • node agent list/release only read the default connection.json, rejecting --state-dir and ignoring AGENT_RELAY_DATA_DIR
  • targeted fleet spawn requires RELAY_AGENT_TOKEN, and --task is mandatory — the errors surface one at a time
  • online ≠ available

Notes

🤖 Generated with Claude Code

Review in cubic

… diagnostics

Adds the two things the skill's fleet section was missing, both learned while
recovering a Mac mini fleet node after a reboot.

"Is the node actually available?" — online is not the same as available for
placement. Documents checking the spawn:* capability list rather than the
status field, the two listing traps (fleet nodes hides offline records; output
truncates at 64KB through a pipe), and an end-to-end placement proof that
spawns from a different machine and verifies the process on the target host.

"Enrolling a new machine as a fleet node" — the mint/redeem API flow
(POST /api/v1/fleet/enrollment-tokens then /api/v1/fleet/register), linking
cloud/dev-stack/fleet-node-bootstrap/README.md as authoritative rather than
duplicating it. Calls out the mandatory reaper guard: node up kills every
broker whose CWD is the resolved project root, which is relay#1328.

Plus five Common Mistakes rows for the CLI behaviours that cost real time,
including node agent subcommands ignoring --state-dir and
AGENT_RELAY_DATA_DIR (filed separately as relay#1446).

Co-Authored-By: Claude Opus 5 <noreply@anthropic.com>
@cursor

cursor Bot commented Aug 6, 2026

Copy link
Copy Markdown

Bugbot is not enabled for your account, so this pull request was not reviewed.

Enable Bugbot in the Cursor dashboard to get automatic reviews on future PRs.

@coderabbitai

coderabbitai Bot commented Aug 6, 2026

Copy link
Copy Markdown

Review Change Stack

📝 Walkthrough

Walkthrough

The orchestrating-agent-relay skill now includes fleet-node diagnostics, enrollment procedures, broker access guidance, and troubleshooting entries. The published skill and package versions update from 2.2.0 to 2.3.0.

Changes

Fleet relay skill update

Layer / File(s) Summary
Fleet-node diagnostics and validation
skills/orchestrating-agent-relay/SKILL.md
The skill documents capability checks, complete fleet retrieval, targeted placement verification, target-host process validation, cleanup after failed dispatches, and related troubleshooting.
Fleet-node enrollment and broker access
skills/orchestrating-agent-relay/SKILL.md
The skill documents token enrollment, environment-based credentials, token persistence, reboot recovery, preflight isolation, non-default broker state directories, and guarded connection-file symlinks.
Published version metadata
README.md, prpm.json
The published skill and package versions change from 2.2.0 to 2.3.0.

Estimated code review effort: 2 (Simple) | ~10 minutes

Possibly related PRs

Poem

A rabbit checks each fleet-node light,
Mints safe tokens, keeps paths right.
Hosts report, and brokers align;
Version two-point-three now shines.

🚥 Pre-merge checks | ✅ 5
✅ Passed checks (5 passed)
Check name Status Explanation
Description check ✅ Passed The description accurately summarizes the documentation additions, version update, and absence of runtime behavior changes.
Title check ✅ Passed The title clearly identifies the main documentation changes for fleet-node enrollment and availability diagnostics.
Docstring Coverage ✅ Passed No functions found in the changed files to evaluate docstring coverage. Skipping docstring coverage check.
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.
✨ Finishing Touches
🧪 Generate unit tests (beta)
  • Create PR with unit tests
  • Commit unit tests in branch docs/fleet-node-enrollment-and-availability

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.

@chatgpt-codex-connector chatgpt-codex-connector Bot left a comment

Copy link
Copy Markdown

Choose a reason for hiding this comment

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

💡 Codex Review

Here are some automated review suggestions for this pull request.

Reviewed commit: 7fc22ed0ec

ℹ️ About Codex in GitHub

Your team has set up Codex to review pull requests in this repo. Reviews are triggered when you

  • Open a pull request for review
  • Mark a draft as ready
  • Comment "@codex review".

If Codex has suggestions, it will comment; otherwise it will react with 👍.

Codex can also answer questions or update the PR. Try commenting "@codex address that feedback".

Comment on lines +488 to +490
The node-side script and the authoritative reference is
`cloud/dev-stack/fleet-node-bootstrap/README.md` (supports Daytona, CF
Containers, the local dev-stack runner, and Mac minis). Inputs are env-only so

Copy link
Copy Markdown

Choose a reason for hiding this comment

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

P2 Badge Link to the external fleet bootstrap assets

The published orchestrating-agent-relay package ships only this SKILL.md (prpm.json's files list), while neither cloud/dev-stack/fleet-node-bootstrap/README.md nor sandbox-node-bootstrap.sh exists anywhere in this repository. Consequently, users installing the skill cannot access the claimed authoritative instructions or the script required by the enrollment command; provide a resolvable repository URL and a way to obtain the script.

Useful? React with 👍 / 👎.

Comment on lines +475 to +477
# on the target host:
pgrep -fl placement-proof # broker pty + CLI process must be present
agent-relay node agent release placement-proof

Copy link
Copy Markdown

Choose a reason for hiding this comment

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

P2 Badge Release the proof agent through its actual state directory

For the newly enrolled LaunchAgent-backed node described below, this cleanup command will not work: the new Common Mistakes row at line 536 explicitly says node agent release reads only the default connection file, while com.agentrelay.fleet-node starts with --state-dir. Thus the recommended end-to-end proof leaves placement-proof running unless the user independently discovers and applies the later symlink workaround; include that workaround here or use a fleet-side release operation.

Useful? React with 👍 / 👎.

@coderabbitai coderabbitai Bot left a comment

Copy link
Copy Markdown

Choose a reason for hiding this comment

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

Actionable comments posted: 3

🤖 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 `@skills/orchestrating-agent-relay/SKILL.md`:
- Line 477: Update the target-side release procedure around the placement-proof
command to work with fleet nodes configured via --state-dir: document a
supported control-plane release path or a safe symlink workaround that verifies
the default connection path is absent, compares its metadata with the target
broker, preserves any pre-existing file, and removes only the symlink created by
the procedure.
- Around line 473-474: Update the relay enrollment examples around the
placement-proof command and the corresponding lines near the later enrollment
example to avoid putting RELAY_AGENT_TOKEN directly in shell history or visible
process arguments. Use a silent read or protected environment-file flow to
populate RELAY_AGENT_TOKEN before invoking agent-relay, while preserving the
existing command behavior.
- Around line 463-465: Update the healthy placement target requirements to
require only the capability matching the requested agent type, rather than every
spawn:* capability. Keep release and relay:delivery-cursor-v1 as separate
lifecycle requirements, and preserve the behavior that records without any spawn
capability cannot be placed on.
🪄 Autofix

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: 01be1b30-5c6a-4f7b-96c7-cab28fb595f8

📥 Commits

Reviewing files that changed from the base of the PR and between 0f3fcf2 and 7fc22ed.

📒 Files selected for processing (3)
  • README.md
  • prpm.json
  • skills/orchestrating-agent-relay/SKILL.md

Comment thread skills/orchestrating-agent-relay/SKILL.md Outdated
Comment thread skills/orchestrating-agent-relay/SKILL.md Outdated
Comment thread skills/orchestrating-agent-relay/SKILL.md Outdated

@cubic-dev-ai cubic-dev-ai Bot left a comment

Copy link
Copy Markdown

Choose a reason for hiding this comment

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

All reported issues were addressed across 3 files

Reply with feedback, questions, or to request a fix.

Re-trigger cubic

Comment thread skills/orchestrating-agent-relay/SKILL.md Outdated
Comment thread skills/orchestrating-agent-relay/SKILL.md
Four review findings, all valid and all fixed.

Capability requirement was overstated: a node advertising only spawn:claude is
a valid target for `fleet spawn claude`. Now requires the spawn:<agent-type>
matching the request, with release and relay:delivery-cursor-v1 called out as
separate lifecycle capabilities.

Tokens no longer appear inline. Both the placement-proof and enrollment
examples now populate the token with a silent `read` plus an unset trap, so it
stays out of shell history as well as out of ps argv. The enrollment prose
claimed env-only inputs while the example contradicted it.

Release path was self-contradictory: the proof used `node agent release` on the
target host while the same document states that subcommand cannot reach a
--state-dir broker. Now uses the control-plane `agent-relay fleet release`,
which needs no local connection file.

The symlink workaround was actively unsafe. It used `ln -sf`, which destroys a
pre-existing connection.json -- and that file is a real regular file on at
least one host in this fleet. Replaced with a guarded form that refuses when
the path exists and removes only a link it created. Verified both branches:
refuses and preserves on the host with the real file, links/runs/cleans on the
host without.

Bootstrap assets are not shipped with this skill, so the bare relative path was
unresolvable for anyone installing it. Now names the AgentWorkforce/cloud repo
and states the access requirement.

Skipped: SkillSpector npx-pinning warnings (lines 54/75/85/549) are pre-existing
and outside this PR's diff.

Co-Authored-By: Claude Opus 5 <noreply@anthropic.com>
@khaliqgant

Copy link
Copy Markdown
Member Author

All four findings were valid and are fixed in c7927c6. Thanks — two of them were real defects, not just wording.

1. Capability requirement overstated (CodeRabbit, L465) — correct, I generalised from a fleet where all four nodes happen to advertise an identical set. Now requires the spawn:<agent-type> matching the request, with release / relay:delivery-cursor-v1 as separate lifecycle capabilities.

2. Tokens in shell history (CodeRabbit L474, Codex) — valid, and the doc contradicted itself: the enrollment prose said "inputs are env-only so secrets never reach ps argv" directly above an example with a literal token inline. Both examples now use a silent read plus an unset trap.

3. Release path unreachable for --state-dir nodes (CodeRabbit L477, Codex L477) — valid and self-contradictory: the proof called node agent release on the target host while a Common Mistakes row in the same document states that subcommand cannot reach a --state-dir broker. Fixed with the supported control-plane path, agent-relay fleet release <name>, which needs no local connection file. That's better than the symlink you offered as the fallback, so the proof recipe no longer needs one at all.

4. Symlink workaround was actively unsafe — this one deserves calling out, because it was worse than "document a guard". The row used ln -sf, which silently destroys a pre-existing connection.json. That is not hypothetical: one host in this fleet has a real regular file at that path from 2026-08-03, and anyone following the documented procedure there would have deleted it. Replaced with a guarded form that refuses when the path exists and removes only a link it created.

Validated both branches rather than assuming:

sf-mini   (real file present) → "pre-existing, do not clobber"; file untouched, still dated 2026-08-03
finn-mini (path absent)       → linked → `node agent list` ran → link removed → back to absent

5. Unresolvable bootstrap reference (Codex L490) — valid. The published package ships only SKILL.md, so a bare relative path was useless to anyone installing the skill. Now names the AgentWorkforce/cloud repository, the path within it, and states plainly that the assets are not shipped with the skill and require access to that repo.

Skipped: the SkillSpector npx version-pinning warnings (lines 54, 75, 85, 549). All four are pre-existing lines outside this PR's diff — my changes are confined to 450–512 and 534–538. Worth a separate PR rather than smuggling unrelated edits into a docs change.

The underlying --state-dir defect is filed as AgentWorkforce/relay#1446; when that lands, the guarded workaround should be deleted rather than left to outlive the bug.

@cubic-dev-ai cubic-dev-ai Bot left a comment

Copy link
Copy Markdown

Choose a reason for hiding this comment

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

1 issue found across 1 file (changes from recent commits).

Prompt for AI agents (unresolved issues)

Check if these issues are valid — if so, understand the root cause of each and fix them. If appropriate, use sub-agents to investigate and fix each issue separately.


<file name="skills/orchestrating-agent-relay/SKILL.md">

<violation number="1" location="skills/orchestrating-agent-relay/SKILL.md:477">
P3: The new silent `read -r -s -p` steps will block (or fail on EOF) when this SKILL.md is executed in a non-interactive / harnessed agent run, which is the primary way an orchestrator consumes this doc — while the change successfully keeps the token out of shell history, it trades that for an interactive stdin prompt. Recommend documenting that the token must be injected via environment in automated contexts (and that `read` is only for interactive/human use), e.g. use `${RELAY_AGENT_TOKEN:?set the token in your environment}` and the `read` snippet only as the interactive fallback, so the spawn/enroll flows stay runnable headlessly.</violation>
</file>

Reply with feedback, questions, or to request a fix.

Re-trigger cubic

Comment thread skills/orchestrating-agent-relay/SKILL.md Outdated

```bash
# Read the token without leaving it in shell history or `ps` argv.
read -r -s -p 'Agent token: ' RELAY_AGENT_TOKEN; printf '\n'

Copy link
Copy Markdown

Choose a reason for hiding this comment

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

P3: The new silent read -r -s -p steps will block (or fail on EOF) when this SKILL.md is executed in a non-interactive / harnessed agent run, which is the primary way an orchestrator consumes this doc — while the change successfully keeps the token out of shell history, it trades that for an interactive stdin prompt. Recommend documenting that the token must be injected via environment in automated contexts (and that read is only for interactive/human use), e.g. use ${RELAY_AGENT_TOKEN:?set the token in your environment} and the read snippet only as the interactive fallback, so the spawn/enroll flows stay runnable headlessly.

Prompt for AI agents
Check if this issue is valid — if so, understand the root cause and fix it. At skills/orchestrating-agent-relay/SKILL.md, line 477:

<comment>The new silent `read -r -s -p` steps will block (or fail on EOF) when this SKILL.md is executed in a non-interactive / harnessed agent run, which is the primary way an orchestrator consumes this doc — while the change successfully keeps the token out of shell history, it trades that for an interactive stdin prompt. Recommend documenting that the token must be injected via environment in automated contexts (and that `read` is only for interactive/human use), e.g. use `${RELAY_AGENT_TOKEN:?set the token in your environment}` and the `read` snippet only as the interactive fallback, so the spawn/enroll flows stay runnable headlessly.</comment>

<file context>
@@ -460,21 +460,34 @@ python3 -c 'import json;raw=open("/tmp/nodes.raw").read();d=json.loads(raw[raw.f
-pgrep -fl placement-proof            # broker pty + CLI process must be present
-agent-relay node agent release placement-proof
+# Read the token without leaving it in shell history or `ps` argv.
+read -r -s -p 'Agent token: ' RELAY_AGENT_TOKEN; printf '\n'
+export RELAY_AGENT_TOKEN
+trap 'unset RELAY_AGENT_TOKEN' EXIT
</file context>

Proof recipe now demonstrates the check it promised. The prose told readers to
spawn from a different machine and confirm dispatchedNodeId, then showed neither.
Now numbered STEP 0-3: an explicit different-machine instruction, a parser that
extracts dispatchedNodeId from the response (which carries a human-readable
preamble before the JSON, so it parses from the first brace), the on-host pgrep,
and the release. Adds a note that steps 1 and 2 are separate claims -- control
plane records dispatch whether or not anything ran, which is exactly how a broken
node looks healthy.

Moves the --state-dir workaround out of the table cell into its own subsection.
It had outgrown a single row, and a multi-line guarded procedure could not be
written safely inside one. The subsection leads with the control-plane path and
treats the symlink as the fallback it is. Adds mkdir -p for the parent directory,
which may not exist on a freshly provisioned node, and states explicitly why
ln -sf must never be used here.

Table row shrinks to a pointer at that subsection.

Validated, not assumed: the parser against a real response shape, and both guard
branches on real hosts -- refuses and preserves on the host with a real
connection file (untouched, still dated 2026-08-03), links/runs/cleans on the
host without one.

Co-Authored-By: Claude Opus 5 <noreply@anthropic.com>
@khaliqgant

Copy link
Copy Markdown
Member Author

Second round addressed in 3532a5e. Both cubic findings on c7927c6 were valid; one premise needs a correction.

P3, L472 — the recipe didn't demonstrate the check it promised. Correct, and a fair hit: the prose said "spawn from a different machine" and "confirm dispatchedNodeId matches", then showed neither. Now numbered STEP 0–3 — an explicit different-machine instruction, a parser that extracts dispatchedNodeId from the response, the on-host pgrep, and the release.

Note for anyone implementing this: fleet spawn has no --json flag, and its output carries a human-readable Note: preamble before the JSON, so the parser reads from the first brace. I validated it against a real response shape rather than guessing:

dispatched to: node_d4190c4c2ca5c26bf547301347af4028 | name: finn-mini | status: dispatched

I also added a line making explicit why both steps exist: the control plane records dispatch whether or not anything ran. Step 1 passing alone is precisely how a broken node looks healthy — which is the failure this whole section exists to catch.

P2, L559 — mkdir -p before the symlink. Accepted and added, but the stated premise is wrong and worth correcting for the record. The claim was that the parent is missing "precisely [on] the fleet node started with --state-dir". I checked both such nodes in this fleet:

finn-mini  exists
sf-mini    exists

~/.agentworkforce/relay/ holds fleet-enrollments.json, cloud-auth.json, bin/ and more, so it exists on any enrolled machine. It could legitimately be absent on a freshly provisioned sandbox node that keeps everything under its state dir — that's the real case, and mkdir -p is cheap insurance for it. The failure mode also wouldn't be silent; ln -s errors visibly on a missing parent.

Restructured rather than patched. The workaround had outgrown a table cell — a multi-line guarded procedure can't be written safely inside one, which is how the original ln -sf got in. It now lives in its own subsection, Reaching a --state-dir broker, leading with the control-plane path and treating the symlink as the fallback it is. The table row is a pointer.

Validated both guard branches on real hosts, verbatim from the doc:

sf-mini   (real connection file) → REFUSING; file intact, still dated 2026-08-03
finn-mini (path absent)          → mkdir -p → link → `node agent list` ran → link removed → absent

Already resolved: cubic's L477 finding on 7fc22ed — cubic marked it addressed in c7927c6 itself. It's the same defect CodeRabbit and Codex raised; fixed by switching to agent-relay fleet release, so the recipe needs no symlink at all now.

No review from cursor — Bugbot is disabled on this account, so that comment is an upsell, not feedback.

@cubic-dev-ai cubic-dev-ai Bot left a comment

Copy link
Copy Markdown

Choose a reason for hiding this comment

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

All reported issues were addressed across 1 file (changes from recent commits).

Tip: Review your code locally with the cubic CLI to iterate faster.

Re-trigger cubic

Comment thread skills/orchestrating-agent-relay/SKILL.md Outdated
Comment thread skills/orchestrating-agent-relay/SKILL.md Outdated
Comment thread skills/orchestrating-agent-relay/SKILL.md Outdated
Parsers no longer crash on unexpected output. Both the roster and STEP 1 probes
used raw.find("{"), which assumes the CLI preamble contains no brace and that the
call succeeded. Neither holds. Now they locate the first brace at start-of-line
via regex and degrade to printing the raw output.

The STEP 1 case mattered most: a traceback there exits non-zero and skips the
STEP 3 release, leaking the running agent the recipe just spawned -- a diagnostic
that leaks the thing it is diagnosing. The new form always exits 0.

Roster parser now prints node id. STEP 1 told readers to compare dispatchedNodeId
against the node's id while the roster command printed only name, so the mandated
comparison was impossible. Also states that dispatchedNodeId is an id, not a name.

Symlink guard now tests -L as well as -e. A dangling link is what an interrupted
run leaves behind, and -e is false for one, so the guard passed and ln -s then
failed with "File exists" while the subcommand silently never ran.

Validated on real hosts, Python 3.9.6 (stock macOS):
- failed-spawn response with a brace in the preamble: old parser raised
  JSONDecodeError, new one reports the failure and exits 0
- planted dangling symlink: [ -e ] false, [ -L ] true, new guard refuses
- roster parser prints id=node_d4190c4c... for finn-mini, matching the
  dispatchedNodeId observed in a real spawn

Co-Authored-By: Claude Opus 5 <noreply@anthropic.com>
@khaliqgant

Copy link
Copy Markdown
Member Author

Third round addressed in 1a0fb00. All three valid — the first one was the most serious defect in this PR so far.

P2, L490 — brittle parse. Correct, and worse than "prints a traceback". A json.loads failure exits non-zero, which skips STEP 3 and leaks the running agent the recipe just spawned. A diagnostic that leaks the thing it is diagnosing is exactly the wrong failure mode. Both parsers (roster and STEP 1) now locate the first brace at start-of-line via regex, and degrade to printing the raw output. STEP 1 always exits 0 so the release still runs.

Reproduced your exact scenario — a preamble containing a {, on a failed spawn:

old: json.decoder.JSONDecodeError: Expecting property name enclosed in double quotes
new: Spawn did not return an invocation — it likely failed. Raw output: …
     exit=0   (STEP 3 release still runs)

P3, L490 — id vs name. Valid, and it made the mandated comparison literally impossible: STEP 1 said "compare dispatchedNodeId against the node's id" while the roster parser printed only name. The roster parser now prints id, and the prose states plainly that dispatchedNodeId is an id (node_…), not a name. The loop now closes on real data — the roster prints finn-mini id=node_d4190c4c2ca5c26bf547301347af4028, which is exactly the dispatchedNodeId from an actual spawn.

P3, L569 — dangling symlink. Valid, and your reasoning is exactly right: a dangling link is precisely what an interrupted run leaves behind, since cleanup is only reached on the happy path. Took the suggested [ -e "$DEF" ] || [ -L "$DEF" ], plus a line telling the reader a dangling link from an interrupted run is safe to remove — otherwise the guard is correct but leaves them stuck.

Verified by planting one:

planted dangling link → [ -e ] false   [ -L ] true → guard REFUSES (correct)

All checks validated on a real host running stock Python 3.9.6, so the parser syntax is 3.9-compatible rather than only working on a modern local interpreter.

@coderabbitai coderabbitai Bot left a comment

Copy link
Copy Markdown

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 current code. Fix only still-valid issues, skip the
rest with a brief reason, keep changes minimal, and validate.

Inline comments:
In `@skills/orchestrating-agent-relay/SKILL.md`:
- Around line 495-497: Replace the fixed placement-proof name in the
placement-proof workflow with one generated unique identifier, and reuse that
identifier consistently for --name, pgrep checks, and fleet release across the
related examples. Prefer releasing by the returned invocation ID when supported,
while preserving the existing spawn and verification behavior.
🪄 Autofix

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: c31025e6-07a5-4f25-8459-fe9f35393b21

📥 Commits

Reviewing files that changed from the base of the PR and between 7fc22ed and 1a0fb00.

📒 Files selected for processing (1)
  • skills/orchestrating-agent-relay/SKILL.md

Comment on lines +495 to +497
agent-relay fleet spawn claude \
--name placement-proof --node <node> --channel general \
--task "Run hostname -s and reply with its output only." > /tmp/spawn.json

Copy link
Copy Markdown

Choose a reason for hiding this comment

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

🩺 Stability & Availability | 🟠 Major | ⚡ Quick win

Use a unique name for each placement proof.

The fixed name placement-proof can collide with a worker from a previous run or another operator. If spawning fails, agent-relay fleet release placement-proof can still terminate that unrelated worker. A stale process can also satisfy pgrep -fl placement-proof.

Generate one unique name and reuse it for --name, pgrep, and fleet release. Release by the returned invocation ID instead if the CLI supports it.

Proposed fix
+SPAWN_NAME="placement-proof-$(date +%s)-$$"
+
 agent-relay fleet spawn claude \
-  --name placement-proof --node <node> --channel general \
+  --name "$SPAWN_NAME" --node <node> --channel general \
   --task "Run hostname -s and reply with its output only." > /tmp/spawn.json
...
-pgrep -fl placement-proof
+pgrep -fl "$SPAWN_NAME"
...
-agent-relay fleet release placement-proof
+agent-relay fleet release "$SPAWN_NAME"

Also applies to: 524-524, 529-529, 641-641

🧰 Tools
🪛 SkillSpector (2.5.1)

[warning] 54: [RP1] null: npx commands without a version suffix (e.g. @1.0.0) create a rug-pull risk if the upstream server is compromised and publishes a malicious update.

Remediation: Pin the version: npx @scope/server@1.2.3

(MCP Rug Pull (RP1))


[warning] 75: [RP1] null: npx commands without a version suffix (e.g. @1.0.0) create a rug-pull risk if the upstream server is compromised and publishes a malicious update.

Remediation: Pin the version: npx @scope/server@1.2.3

(MCP Rug Pull (RP1))


[warning] 85: [RP1] null: npx commands without a version suffix (e.g. @1.0.0) create a rug-pull risk if the upstream server is compromised and publishes a malicious update.

Remediation: Pin the version: npx @scope/server@1.2.3

(MCP Rug Pull (RP1))


[warning] 652: [RP1] null: npx commands without a version suffix (e.g. @1.0.0) create a rug-pull risk if the upstream server is compromised and publishes a malicious update.

Remediation: Pin the version: npx @scope/server@1.2.3

(MCP Rug Pull (RP1))


[warning] 652: [RP1] null: npx commands without a version suffix (e.g. @1.0.0) create a rug-pull risk if the upstream server is compromised and publishes a malicious update.

Remediation: Pin the version: npx @scope/server@1.2.3

(MCP Rug Pull (RP1))

🤖 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 `@skills/orchestrating-agent-relay/SKILL.md` around lines 495 - 497, Replace
the fixed placement-proof name in the placement-proof workflow with one
generated unique identifier, and reuse that identifier consistently for --name,
pgrep checks, and fleet release across the related examples. Prefer releasing by
the returned invocation ID when supported, while preserving the existing spawn
and verification behavior.

@cubic-dev-ai cubic-dev-ai Bot left a comment

Copy link
Copy Markdown

Choose a reason for hiding this comment

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

1 issue found across 1 file (changes from recent commits).

Prompt for AI agents (unresolved issues)

Check if these issues are valid — if so, understand the root cause of each and fix them. If appropriate, use sub-agents to investigate and fix each issue separately.


<file name="skills/orchestrating-agent-relay/SKILL.md">

<violation number="1" location="skills/orchestrating-agent-relay/SKILL.md:465">
P3: The roster parser's `json.loads` is unguarded, unlike the STEP 1 parser in the same diff that catches `ValueError` to avoid a traceback. If the redirected `/tmp/nodes.raw` is empty or truncated (the very case the surrounding comments warn about), this snippet fails with a raw Python traceback instead of the graceful 'No JSON in output' message — a minor inconsistency with the robustness the PR otherwise added.</violation>
</file>

Tip: Review your code locally with the cubic CLI to iterate faster.

Re-trigger cubic

m = re.search(r"^\{", raw, re.M) # first brace at start of a line, not inside the preamble
if not m:
raise SystemExit("No JSON in output. Raw:\n" + raw[:500])
for n in json.loads(raw[m.start():]).get("nodes", []):

Copy link
Copy Markdown

Choose a reason for hiding this comment

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

P3: The roster parser's json.loads is unguarded, unlike the STEP 1 parser in the same diff that catches ValueError to avoid a traceback. If the redirected /tmp/nodes.raw is empty or truncated (the very case the surrounding comments warn about), this snippet fails with a raw Python traceback instead of the graceful 'No JSON in output' message — a minor inconsistency with the robustness the PR otherwise added.

Prompt for AI agents
Check if this issue is valid — if so, understand the root cause and fix it. At skills/orchestrating-agent-relay/SKILL.md, line 465:

<comment>The roster parser's `json.loads` is unguarded, unlike the STEP 1 parser in the same diff that catches `ValueError` to avoid a traceback. If the redirected `/tmp/nodes.raw` is empty or truncated (the very case the surrounding comments warn about), this snippet fails with a raw Python traceback instead of the graceful 'No JSON in output' message — a minor inconsistency with the robustness the PR otherwise added.</comment>

<file context>
@@ -456,10 +456,21 @@ still never receive a spawn. Check the capability list, not the status field:
+m = re.search(r"^\{", raw, re.M)          # first brace at start of a line, not inside the preamble
+if not m:
+    raise SystemExit("No JSON in output. Raw:\n" + raw[:500])
+for n in json.loads(raw[m.start():]).get("nodes", []):
+    caps = [c["name"] for c in n.get("capabilities", [])]
+    print(f'{n.get("name")}  id={n.get("id")}  {n.get("status")}  live={n.get("live")}  {caps}')
</file context>

@khaliqgant
khaliqgant merged commit d34729d into main Aug 6, 2026
2 checks passed
@khaliqgant
khaliqgant deleted the docs/fleet-node-enrollment-and-availability branch August 6, 2026 13:03
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