✨ feat(skills): add public Herdr fleet workflow#32
Conversation
|
|
Warning Review limit reached
Next review available in: 26 minutes Enable usage-based reviews in Billing to review now. Otherwise, wait until the next included review is available. How can I continue?After more reviews become available, a review can be triggered using the To avoid repeated limits, reduce automatic review volume by pausing incremental auto-reviews earlier, using label-based review opt-in, excluding WIP or generated PR titles, or requesting reviews manually when the PR is ready. If your team needs uninterrupted high-volume reviews, an organization admin can enable usage-based reviews. How do review limits work?CodeRabbit enforces per-developer PR review limits for each organization. Most developers receive the normal plan review availability. For paid Pro and Pro+ PR reviews, CodeRabbit uses adaptive limits for sustained high-volume activity. When a developer's recent PR review activity reaches the 95th percentile or higher among CodeRabbit users, additional reviews become available more gradually as earlier reviews age out of the rolling window. Please refer docs for additional details. Review details⚙️ Run configurationConfiguration used: Path: .coderabbit.yaml Review profile: CHILL Plan: Pro Run ID: 📒 Files selected for processing (5)
WalkthroughAdds the ChangesHerdr fleet workflow
Estimated code review effort: 4 (Complex) | ~60 minutes Sequence Diagram(s)sequenceDiagram
participant Principal
participant ControlPane
participant HerdrCLI
participant WorkerPanes
participant Watcher
participant EventConsumer
Principal->>ControlPane: confirm roster and launch policy
ControlPane->>HerdrCLI: inspect and reconcile scoped panes
HerdrCLI-->>ControlPane: return pane inventory
ControlPane->>WorkerPanes: launch agents and dispatch assignments
ControlPane->>Watcher: start project-scoped monitoring
Watcher->>HerdrCLI: poll scoped pane state
HerdrCLI-->>Watcher: return pane output and statuses
Watcher-->>EventConsumer: append scoped NDJSON events
EventConsumer-->>ControlPane: deliver events after cursor validation
ControlPane-->>Principal: report milestones and decisions
Possibly related PRs
🚥 Pre-merge checks | ✅ 4 | ❌ 1❌ Failed checks (1 warning)
✅ Passed checks (4 passed)
✨ Finishing Touches🧪 Generate unit tests (beta)
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. Comment |
Review, PR #32 (public
|
Specialized Agent Skill reviewThe general PR review passed, but the dedicated skill-quality review found release-blocking gaps in the public orchestration contract. Required fixes:
Public-safety checks, links, role boundaries, catalog registration, and package discovery are otherwise sound. VERDICT: NEEDS_WORK
|
|
Addressed every required and minor specialized-skill review item at |
Fix re-review, PR #32 (public
|
There was a problem hiding this comment.
Actionable comments posted: 13
🤖 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 `@CHANGELOG.md`:
- Around line 13-15: Revert all additions to CHANGELOG.md, including the entries
for the Herdr fleet workflow, plugin packaging/question TUI, shared
documentation workflows, and the other referenced changes; do not commit or
modify this personal port-history file, and retain the history in the PR
description instead.
In `@skills/herdr-fleet/launch-fleet.md`:
- Around line 25-27: Update the REPO_ROOT initialization in the launch workflow
to fail immediately when git rev-parse --show-toplevel cannot identify a Git
repository; remove the pwd fallback while preserving the existing project and
BASE_KEY derivation for valid repositories.
- Around line 42-61: Update the collision-resolution flow around KEY_COLLISION
and PROJECT_KEY to re-run the ownership predicate against the resolved
PROJECT_KEY after adding a suffix. Continue extending or regenerating the
repository-derived suffix until the resulting fleet label prefix is unique, and
fail safely if uniqueness cannot be established before constructing
CONTROL_LABEL.
- Around line 8-16: Update the pre-mutation validation around the herdr pane
query to parse its current metadata and fail closed unless the reported
workspace_id and tab_id match HERDR_WORKSPACE_ID and HERDR_TAB_ID. Keep the
existing non-empty ID checks, and perform this validation before any rename,
close, split, or launch operations.
- Around line 150-159: Update the watcher startup block to include PROJECT_KEY
in MONITOR_DIR so each project fleet has isolated logs and PID state. Before
launching watch-fleet.mjs, acquire or validate a per-fleet lock/PID and reuse
the existing watcher when it is still running; only start and record a new
watcher when no valid instance exists, preserving exactly one persistent watcher
per fleet.
In `@skills/herdr-fleet/protocols.md`:
- Line 23: Update the “Conflicting verdicts” rule to use the canonical
NEEDS_WORK verdict consistently, replacing NEEDS_CHANGES unless the producer and
consumer contract explicitly defines and supports both values.
- Around line 3-5: Define a concrete persistent NDJSON consumption loop in the
protocol using the recorded watcher PID and output paths: read incrementally
from a saved byte cursor, buffer and parse only complete newline-delimited
events, persist the cursor after successful processing, and resume from it after
restart to prevent replay or loss. Detect watcher exit and stop or report
appropriately, while retaining the existing three-field scope validation before
consuming events.
In `@skills/herdr-fleet/scripts/watch-fleet.mjs`:
- Around line 48-53: Update runHerdr to impose a timeout on spawnSync calls and
terminate children that exceed it. Handle the timeout result as a failed Herdr
invocation while preserving existing stderr, spawn-error, and exit-status
reporting so watcher recovery can proceed.
- Around line 140-165: Update the compaction state handled by the watcher’s
context-threshold logic around state.compactionRequested and runHerdr to track
request age or attempts instead of permanently suppressing retries after a
successful dispatch. When usage remains at or above the compaction threshold
without dropping below the rearm threshold, retry compaction as appropriate or
emit pane_monitor_blocked after the defined limit, while preserving the existing
blocked-dialog behavior and successful rearm handling.
- Around line 92-102: Update the watch-fleet startup validation to verify that
the supplied workspaceId and tabId belong to the same active fleet scope, not
merely that they are nonempty. During a bounded startup grace period, require
scoped pane discovery to return at least one pane; otherwise emit the existing
fatal invalid-scope failure and exit rather than continuing to monitor zero
panes.
- Around line 25-35: Update parseContext to scan visible text lines from the
bottom and parse only complete current-context footer formats, rather than
matching the first percentage via the prioritized patterns array. Ensure
worker/task-output percentages are ignored and preserve both usedPercent and
untilAutoCompactPercent extraction from the footer. Add a mixed-content
self-test covering misleading earlier percentages and the real footer.
- Around line 39-42: Update option() to reject missing values and values that
are flags, returning the fallback instead of consuming the next option; ensure
the project key is non-flag and present. At the interval handling near the
polling setup, validate the parsed interval as finite and strictly positive
before using it, preserving safe fallback behavior for invalid values.
In `@skills/herdr-fleet/SKILL.md`:
- Around line 2-3: Rewrite the frontmatter description for the herdr-fleet skill
to begin with an explicit usage condition, such as “Use when you need to…”.
Preserve the listed launch, pane-management, rebuild, and queue-control
capabilities while making clear when this skill should be selected.
🪄 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: Path: .coderabbit.yaml
Review profile: CHILL
Plan: Pro
Run ID: 4bc86869-9d1d-465f-a68f-147c501a9d32
📒 Files selected for processing (6)
CHANGELOG.mddocs/catalog.mdskills/herdr-fleet/SKILL.mdskills/herdr-fleet/launch-fleet.mdskills/herdr-fleet/protocols.mdskills/herdr-fleet/scripts/watch-fleet.mjs
Specialized Agent Skill re-reviewSeven prior findings are closed. One reproducible fleet-key collision remains.
Required fix:
VERDICT: NEEDS_WORK
|
# Conflicts: # package.json # scripts/validate-package-contents.mjs
|
@coderabbitai review Fresh exact-head verdict requested for |
|
✅ Action performedReview finished.
|
|
✅ Action performedFull review finished. Your plan includes PR reviews subject to rate limits. More reviews will be available in 56 minutes. |
There was a problem hiding this comment.
Actionable comments posted: 5
🧹 Nitpick comments (1)
skills/herdr-fleet/scripts/consume-events.mjs (1)
58-70: 🚀 Performance & Scalability | 🔵 Trivial | ⚡ Quick winPrevent redundant file reads while waiting for new events.
When there are no new events, the polling loop repeatedly calls
nextEvent, which processes the event file every 500ms. This causes unnecessary CPU and I/O load during idle periods.Track the file size and cursor to only invoke the parser when a change occurs.
⚡ Proposed fix to optimize polling
async function readNext(eventsPath, cursorPath, pidPath, expectedSessionId, waitMs) { const deadline = Date.now() + waitMs; + let lastSize = -1; + let lastCursor = -1; while (Date.now() < deadline) { const cursor = cursorAt(cursorPath); if (existsSync(eventsPath)) { - const result = nextEvent(eventsPath, cursor, expectedSessionId); - if (result) return result; + const size = statSync(eventsPath).size; + if (size !== lastSize || cursor !== lastCursor) { + lastSize = size; + lastCursor = cursor; + const result = nextEvent(eventsPath, cursor, expectedSessionId); + if (result) return result; + } } if (!watcherRunning(pidPath)) throw new Error("watcher exited before the next complete event"); await new Promise((resolve) => setTimeout(resolve, 500));🤖 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/herdr-fleet/scripts/consume-events.mjs` around lines 58 - 70, Update readNext to track the event file’s last observed size and cursor, and call nextEvent only when either value changes; preserve the existing watcher-exit error, polling interval, deadline, and returned event behavior.
🤖 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 `@scripts/validate-package-contents.mjs`:
- Around line 75-80: Update the link validation flow around targetPath and
existsSync to check whether the resolved target is included in the packed
artifact rather than only whether it exists in the checkout. Reuse the script’s
existing tarball or package-content representation, and add the link to
brokenLinks when the target is absent from that packed-content set while
preserving anchor handling.
In `@skills/herdr-fleet/launch-fleet.md`:
- Around line 88-94: Update roster validation to reject any worker label equal
to the reserved control-pane label, including after rendering it as
${PROJECT_KEY}-control-pane. Validate rendered worker labels against
CONTROL_LABEL before generating the confirmation preview, while preserving the
existing unique non-empty label checks.
- Around line 153-168: After the report-metadata call, read the pane metadata
back and compare every required ownership field against the intended values,
including the conditional fleet_assignment and credential-free fleet_command.
Mark the pane non-reusable and require intake on the next rebuild if any field
is missing, truncated, normalized, or otherwise mismatched; only claim reusable
ownership proof when all values match exactly.
In `@skills/herdr-fleet/README.md`:
- Around line 23-31: Update the routed model entries in the README command table
to replace the private codenames “GPT-5.6 Sol,” “Grok 4.5,” and “GPT-5.6 Terra”
with standard documented model names or generic role placeholders, while
preserving each command’s existing routing and effort values.
In `@skills/herdr-fleet/scripts/consume-events.mjs`:
- Around line 21-31: Update
skills/herdr-fleet/scripts/consume-events.mjs#L21-L31 in nextEvent to replace
the full-file read with openSync, fstatSync, and readSync, reading only bytes
from cursor through the current file end while preserving truncation, newline,
parsing, and session checks. Update
skills/herdr-fleet/scripts/consume-events.mjs#L51-L52 in acknowledge to use
openSync and readSync for exactly the single boundary byte at nextCursor - 1.
Add fstatSync, openSync, and readSync to the node:fs imports.
---
Nitpick comments:
In `@skills/herdr-fleet/scripts/consume-events.mjs`:
- Around line 58-70: Update readNext to track the event file’s last observed
size and cursor, and call nextEvent only when either value changes; preserve the
existing watcher-exit error, polling interval, deadline, and returned event
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: Path: .coderabbit.yaml
Review profile: CHILL
Plan: Pro
Run ID: 2e3855f6-9647-422d-b7b7-ecfc08d480b8
📒 Files selected for processing (12)
docs/catalog.mdpackage.jsonscripts/validate-package-contents.mjsskills/herdr-fleet/README.mdskills/herdr-fleet/SKILL.mdskills/herdr-fleet/fixtures/project-key-collision.jsonskills/herdr-fleet/launch-fleet.mdskills/herdr-fleet/protocols.mdskills/herdr-fleet/scripts/consume-events.mjsskills/herdr-fleet/scripts/fleet-labels.mjsskills/herdr-fleet/scripts/resolve-project-key.mjsskills/herdr-fleet/scripts/watch-fleet.mjs
🚧 Files skipped from review as they are similar to previous changes (3)
- docs/catalog.md
- skills/herdr-fleet/scripts/watch-fleet.mjs
- skills/herdr-fleet/protocols.md
Final specialized Agent Skill reviewThe direct roster and Claudex requirements are satisfied, but five operational guarantees still need correction:
Minor: use third-person trigger wording and add the skill to VERDICT: NEEDS_WORK
|
Final review, PR #32 (public
|
Final specialist/general fixes — exact head
|
|
✅ Action performedFull review finished. Your plan includes PR reviews subject to rate limits. More reviews will be available in 5 minutes. |
Release review, PR #32 (public
|
Release-gate specialized Agent Skill reviewThe general reviewer passed this head, but two subtle safety guarantees remain incomplete:
Required fixes:
VERDICT: NEEDS_WORK
|
Release-gate fixes — exact head
|
|
Tip For best results, initiate chat on the files or code changes. 🧩 Analysis chain🏁 Script executed: #!/bin/bash
set -euo pipefail
expected_head="781878553ff4d889071bab3fc106164f84d7af44"
echo '== PR metadata =='
gh pr view 32 --repo AojdevStudio/agentic-utilities \
--json number,url,state,isDraft,headRefOid,baseRefName,mergeable,mergeStateStatus,statusCheckRollup \
--jq '{number,url,state,isDraft,headRefOid,baseRefName,mergeable,mergeStateStatus,statusChecks:[.statusCheckRollup[] | {name,conclusion,status}]}'
echo '== exact head checkout =='
git rev-parse HEAD
git cat-file -t "$expected_head"
git merge-base --is-ancestor "$expected_head" HEAD && echo "requested_head_is_ancestor_of_checkout=true" || true
test "$(git rev-parse HEAD)" = "$expected_head" && echo "checkout_matches_requested_head=true" || echo "checkout_matches_requested_head=false"
echo '== contribution files =='
base="$(git merge-base HEAD origin/main)"
printf 'merge_base=%s\n' "$base"
git diff --name-status "$base...HEAD"
echo '== relevant file maps =='
for f in \
skills/herdr-fleet/scripts/consume-events.mjs \
skills/herdr-fleet/scripts/review-thread-gate.mjs \
skills/herdr-fleet/scripts/watch-fleet.mjs \
skills/herdr-fleet/SKILL.md \
skills/herdr-fleet/protocols.md \
package.json \
scripts/validate-package-contents.mjs
do
if test -f "$f"; then
echo "--- $f"
ast-grep outline "$f" --items all --view expanded || true
fi
done
echo '== static references: event identity, locking, review gate, and test wiring =='
rg -n -C 4 \
-e 'instance-token|instanceToken|start\.lock|acknowledge|--ack|pending' \
-e 'review-thread|thread.*gate|pagination|unresolved|outdated|expected-head|head.*drift' \
-e 'test:herdr-fleet|consume-events.*self-test|review.*test' \
package.json .github skills scripts \
-g '!**/node_modules/**' || true
echo '== PR review threads (GraphQL pagination) =='
owner="AojdevStudio"
repo="agentic-utilities"
cursor=null
page=0
while :; do
result="$(gh api graphql \
-F owner="$owner" -F name="$repo" -F number=32 -F cursor="$cursor" \
-f query='
query($owner: String!, $name: String!, $number: Int!, $cursor: String) {
repository(owner: $owner, name: $name) {
pullRequest(number: $number) {
reviewThreads(first: 100, after: $cursor) {
nodes { id isResolved isOutdated path line comments(first: 1) { nodes { url body author { login } } } }
pageInfo { hasNextPage endCursor }
}
}
}
}' )"
echo "$result" | jq -c '.data.repository.pullRequest.reviewThreads.nodes[]'
has_next="$(echo "$result" | jq -r '.data.repository.pullRequest.reviewThreads.pageInfo.hasNextPage')"
cursor="$(echo "$result" | jq -r '.data.repository.pullRequest.reviewThreads.pageInfo.endCursor')"
page=$((page + 1))
test "$has_next" = true || break
done
printf 'review_thread_pages=%s\n' "$page"Length of output: 117926 🏁 Script executed: #!/bin/bash
set -euo pipefail
echo '== consume-events implementation and self-test =='
sed -n '1,380p' skills/herdr-fleet/scripts/consume-events.mjs
echo '== review-thread gate implementation and tests =='
sed -n '1,220p' skills/herdr-fleet/scripts/review-thread-gate.mjs
sed -n '1,180p' skills/herdr-fleet/scripts/review-thread-gate.test.mjs
echo '== skill frontmatter and merge/readiness protocol =='
sed -n '1,90p' skills/herdr-fleet/SKILL.md
sed -n '52,100p' skills/herdr-fleet/protocols.md
echo '== package validation and packed-link helper/test =='
sed -n '1,180p' scripts/validate-package-contents.mjs
sed -n '1,240p' scripts/lib/package-links.mjs
sed -n '1,200p' scripts/lib/package-links.test.mjs
echo '== CI/check wiring =='
sed -n '1,130p' package.json
sed -n '1,220p' .github/workflows/ci.yml
echo '== Markdown links in new skill content =='
rg -n '\[[^]]+\]\([^)]+\)' skills/herdr-fleet skills/README.md docs/catalog.md
echo '== shell command-construction and review-gate call sites =='
rg -n -C 5 \
-e 'review-thread-gate\.mjs|authorized-merge|MERGE_READY|CURRENT_HEAD_SHA' \
-e 'consume-events\.mjs|WATCHER_COMMAND_SUFFIX|start\.lock' \
skills/herdr-fleet
echo '== changed-file whitespace/error markers =='
git diff --check 232fd85a91f78b4d878b2965677af8d642fd28fc...HEADLength of output: 60035
General review — PASS
Specialized Agent Skill review — PASSBoth release-audit blockers are closed:
Additional verification:
VERDICT: MERGE_READY @ No blocking findings identified in either the general or specialized review. |
Exact-head release verdict, PR #32 (public
|
One-line release fix — exact head
|
There was a problem hiding this comment.
Actionable comments posted: 4
Caution
Some comments are outside the diff and can’t be posted inline due to platform limitations.
⚠️ Outside diff range comments (1)
skills/herdr-fleet/launch-fleet.md (1)
163-163: 🎯 Functional Correctness | 🟠 Major | ⚡ Quick winMandate the review-thread gate for authorized merges.
The PR objective identifies that the authorized merge path lacks a fresh, paginated review-thread evidence check immediately before readiness and merge. While
scripts/review-thread-gate.mjshas been introduced to securely verify this, theauthorized-mergepolicy definition here doesn't instruct the agent to run it.Explicitly require a clear check from
scripts/review-thread-gate.mjs(zero blocking threads/exit code 0) as a prerequisite for merging.💡 Proposed fix
-| `authorized-merge` | Merge only on explicitly allowed base branches, with the explicitly selected strategy, after a fresh verdict and green required checks. | +| `authorized-merge` | Merge only on explicitly allowed base branches, with the explicitly selected strategy, after a fresh verdict, green required checks, and a clear `bun <skill-directory>/scripts/review-thread-gate.mjs` check. |🤖 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/herdr-fleet/launch-fleet.md` at line 163, Update the authorized-merge policy definition to require running scripts/review-thread-gate.mjs immediately before readiness and merge, and permit merging only when it reports zero blocking review threads with exit code 0. Preserve the existing branch, strategy, fresh-verdict, and required-check requirements.
🧹 Nitpick comments (2)
skills/herdr-fleet/scripts/consume-events.mjs (2)
33-44: 📐 Maintainability & Code Quality | 🔵 Trivial | 💤 Low valueBounded reads correctly fix the prior O(N²) full-file-read issue.
readFromCursor+nextEventnow read only a bounded window from the persisted cursor, addressing the previously flagged quadratic memory/I/O growth.Minor nit:
65_536is duplicated as the defaultmaxBytesparameter (line 33) and the max-line-size comparison (line 58). Consider extracting a sharedconst MAX_LINE_BYTES = 65_536to keep the two in sync if this bound ever changes.Also applies to: 54-67
🤖 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/herdr-fleet/scripts/consume-events.mjs` around lines 33 - 44, Extract the duplicated 65_536 limit into a shared MAX_LINE_BYTES constant, then reuse it as the default maxBytes value in readFromCursor and in the max-line-size comparison within nextEvent. Keep the existing bounded-read and oversized-line behavior unchanged.
175-290: 📐 Maintainability & Code Quality | 🔵 Trivial | ⚡ Quick winSelf-test coverage: add regression cases once the above two fixes land.
The self-test thoroughly covers session/generation/pending-boundary mismatches and lock/release ordering, but doesn't cover (a) same-token/different-PID replacement-watcher reuse, or (b) acking a blank-line placeholder. Once the identity-binding and blank-line-ack fixes above are made, add regression tests for both so they don't regress silently.
🤖 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/herdr-fleet/scripts/consume-events.mjs` around lines 175 - 290, Extend selfTest() with regression cases for same-token replacement across different PIDs, asserting watcherIdentityMatches rejects the replacement, and for acknowledging a blank-line placeholder, asserting acknowledge handles it according to the corrected blank-line behavior. Keep the existing mismatch and lock-order tests unchanged, and update the reported check count to include the new assertions.
🤖 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 @.github/workflows/ci.yml:
- Around line 28-33: Update the CI workflow steps around the package
installation and validation commands to use npm ci, npm run check, and the
existing package dry-run validation command instead of Bun equivalents. Remove
the Bun setup step if it is no longer needed, and preserve the required CI
ordering.
In `@scripts/lib/package-links.mjs`:
- Around line 22-24: Update the link-target extraction in the matchAll loop to
trim surrounding whitespace and isolate the URL before protocol validation and
packedPathSet lookup. Ensure optional Markdown title attributes are excluded,
while preserving the existing skip behavior for absolute URLs and local-path
checking.
In `@skills/herdr-fleet/scripts/consume-events.mjs`:
- Around line 109-138: Update the pending-result validation in acknowledgeLocked
to reject only when nextEvent returns no result, not when its event is
undefined. Preserve the nextCursor equality check so valid blank-line skip
placeholders can advance cursorPath while mismatched or absent results remain
rejected.
- Around line 95-107: Update startLockManager.release() to make lock-file
cleanup race-safe: handle ENOENT or other release-time read failures so
exceptions from the acknowledge/acknowledgeLocked finally path are never masked.
Preserve the existing ownership check and only unlink the file when it still
contains the current process ID.
---
Outside diff comments:
In `@skills/herdr-fleet/launch-fleet.md`:
- Line 163: Update the authorized-merge policy definition to require running
scripts/review-thread-gate.mjs immediately before readiness and merge, and
permit merging only when it reports zero blocking review threads with exit code
0. Preserve the existing branch, strategy, fresh-verdict, and required-check
requirements.
---
Nitpick comments:
In `@skills/herdr-fleet/scripts/consume-events.mjs`:
- Around line 33-44: Extract the duplicated 65_536 limit into a shared
MAX_LINE_BYTES constant, then reuse it as the default maxBytes value in
readFromCursor and in the max-line-size comparison within nextEvent. Keep the
existing bounded-read and oversized-line behavior unchanged.
- Around line 175-290: Extend selfTest() with regression cases for same-token
replacement across different PIDs, asserting watcherIdentityMatches rejects the
replacement, and for acknowledging a blank-line placeholder, asserting
acknowledge handles it according to the corrected blank-line behavior. Keep the
existing mismatch and lock-order tests unchanged, and update the reported check
count to include the new assertions.
🪄 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: Path: .coderabbit.yaml
Review profile: CHILL
Plan: Pro
Run ID: 490df645-4a54-410a-8d09-b2136c27a697
📒 Files selected for processing (19)
.github/workflows/ci.ymlpackage.jsonscripts/lib/package-links.mjsscripts/lib/package-links.test.mjsscripts/validate-package-contents.mjsskills/README.mdskills/herdr-fleet/SKILL.mdskills/herdr-fleet/fixtures/compaction-failures.jsonskills/herdr-fleet/fixtures/fleet-state-race.jsonskills/herdr-fleet/fixtures/review-thread-pages.jsonskills/herdr-fleet/fixtures/watcher-identity.jsonskills/herdr-fleet/launch-fleet.mdskills/herdr-fleet/protocols.mdskills/herdr-fleet/scripts/consume-events.mjsskills/herdr-fleet/scripts/fleet-state.mjsskills/herdr-fleet/scripts/fleet-state.test.mjsskills/herdr-fleet/scripts/review-thread-gate.mjsskills/herdr-fleet/scripts/review-thread-gate.test.mjsskills/herdr-fleet/scripts/watch-fleet.mjs
🚧 Files skipped from review as they are similar to previous changes (4)
- scripts/validate-package-contents.mjs
- skills/herdr-fleet/SKILL.md
- skills/herdr-fleet/scripts/watch-fleet.mjs
- skills/herdr-fleet/protocols.md
|
Tip For best results, initiate chat on the files or code changes. 🧩 Analysis chain🏁 Script executed: #!/bin/bash
set -euo pipefail
repo="AojdevStudio/agentic-utilities"
pr="32"
expected_head="78b09ec7d3f4507ccdb6cf44645c61f93e07e8fe"
prior_head="781878553ff4d889071bab3fc106164f84d7af44"
echo "== exact checkout and commit ancestry =="
printf 'checkout='
git rev-parse HEAD
printf 'expected_commit_type='
git cat-file -t "$expected_head"
printf 'expected_parent='
git rev-parse "${expected_head}^"
if test "$(git rev-parse HEAD)" = "$expected_head"; then
echo "checkout_matches_expected=true"
else
echo "checkout_matches_expected=false"
fi
if git merge-base --is-ancestor "$prior_head" "$expected_head"; then
echo "prior_release_head_is_ancestor=true"
else
echo "prior_release_head_is_ancestor=false"
fi
echo "== exact delta =="
git diff --check "${expected_head}^...${expected_head}"
git diff --name-status "${expected_head}^...${expected_head}"
git diff --unified=20 "${expected_head}^...${expected_head}" -- skills/herdr-fleet/SKILL.md
echo "== current skill frontmatter and nearby contract =="
sed -n '1,55p' skills/herdr-fleet/SKILL.md
echo "== PR metadata and checks =="
gh pr view "$pr" --repo "$repo" \
--json headRefOid,state,isDraft,mergeable,mergeStateStatus,statusCheckRollup \
--jq '{headRefOid,state,isDraft,mergeable,mergeStateStatus,statusChecks:[.statusCheckRollup[] | {name,status,conclusion,isRequired}]}'
echo "== review thread state with pagination =="
owner="${repo%%/*}"
name="${repo#*/}"
cursor=null
pages=0
total=0
unresolved_current=0
while :; do
result="$(gh api graphql \
-F owner="$owner" -F name="$name" -F number="$pr" -F cursor="$cursor" \
-f query='
query($owner: String!, $name: String!, $number: Int!, $cursor: String) {
repository(owner: $owner, name: $name) {
pullRequest(number: $number) {
reviewThreads(first: 100, after: $cursor) {
nodes {
id
isResolved
isOutdated
path
line
comments(first: 1) { nodes { url } }
}
pageInfo { hasNextPage endCursor }
}
}
}
}')"
echo "$result" | jq -c '
.data.repository.pullRequest.reviewThreads.nodes[]
| select((.isResolved | not) and (.isOutdated | not))
| {id,path,line,url:(.comments.nodes[0].url // null)}'
page_total="$(echo "$result" | jq '.data.repository.pullRequest.reviewThreads.nodes | length')"
page_open="$(echo "$result" | jq '[.data.repository.pullRequest.reviewThreads.nodes[] | select((.isResolved | not) and (.isOutdated | not))] | length')"
total=$((total + page_total))
unresolved_current=$((unresolved_current + page_open))
pages=$((pages + 1))
has_next="$(echo "$result" | jq -r '.data.repository.pullRequest.reviewThreads.pageInfo.hasNextPage')"
cursor="$(echo "$result" | jq -r '.data.repository.pullRequest.reviewThreads.pageInfo.endCursor')"
test "$has_next" = true || break
done
printf 'review_thread_pages=%s total=%s unresolved_non_outdated=%s\n' "$pages" "$total" "$unresolved_current"Length of output: 14012 🏁 Script executed: #!/bin/bash
set -euo pipefail
repo="AojdevStudio/agentic-utilities"
owner="${repo%%/*}"
name="${repo#*/}"
pr="32"
echo "== unresolved, current review-thread discussions =="
gh api graphql \
-F owner="$owner" -F name="$name" -F number="$pr" \
-f query='
query($owner: String!, $name: String!, $number: Int!) {
repository(owner: $owner, name: $name) {
pullRequest(number: $number) {
reviewThreads(first: 100) {
nodes {
id
path
line
isResolved
isOutdated
comments(first: 100) {
nodes {
author { login }
createdAt
url
body
}
}
}
}
}
}
}' \
--jq '
.data.repository.pullRequest.reviewThreads.nodes[]
| select((.isResolved | not) and (.isOutdated | not))
| {id,path,line,comments:[.comments.nodes[] | {author:.author.login,createdAt,url,body}]}'
echo "== affected source context =="
for spec in \
".github/workflows/ci.yml:1:80" \
"scripts/lib/package-links.mjs:1:100" \
"skills/herdr-fleet/scripts/consume-events.mjs:75:175"
do
file="${spec%%:*}"
rest="${spec#*:}"
start="${rest%%:*}"
end="${rest##*:}"
echo "--- $file (Lines $start-$end)"
sed -n "${start},${end}p" "$file" | nl -ba -v "$start"
done
echo "== relevant call sites and test coverage =="
rg -n -C 4 \
-e 'package-links\.test|test:herdr-fleet|review-thread-gate\.test|consume-events.*self-test' \
-e 'findBrokenPackedLinks\s*\(|readTarget\s*:|watcherRunning\s*\(|acknowledge\s*\(' \
package.json .github scripts skills \
-g '!**/node_modules/**'Length of output: 12453 🏁 Script executed: #!/bin/bash
set -euo pipefail
echo "== package link helper and tests =="
cat -n scripts/lib/package-links.mjs | sed -n '1,140p'
cat -n scripts/lib/package-links.test.mjs | sed -n '1,180p'
echo "== event consumer implementation =="
cat -n skills/herdr-fleet/scripts/consume-events.mjs | sed -n '1,260p'
echo "== event consumer self-test assertions =="
rg -n -C 6 \
-e 'self-test|blank|nextEvent\(|acknowledge\(|startLockManager|ack does not match|release\(' \
skills/herdr-fleet/scripts/consume-events.mjs
echo "== event-consumption protocol and CLI call contract =="
rg -n -C 5 \
-e 'consume-events|--next|--ack|blank|NDJSON|cursor|acknowledg' \
skills/herdr-fleet/protocols.md skills/herdr-fleet/launch-fleet.md skills/herdr-fleet/SKILL.md
echo "== CI workflow and Bun package scripts =="
cat -n .github/workflows/ci.yml | sed -n '1,100p'
cat -n package.json | sed -n '1,150p'Length of output: 34901
General review — NEEDS_WORKThe requested one-line change is correct:
However, live GitHub review-thread pagination found 4 unresolved, non-outdated threads. One is not actionable: the request to revert the intentional Bun migration back to npm conflicts with the repository’s current Bun CI and package-script contract. The other three are valid:
Specialized Agent Skill review — NEEDS_WORKThe new third-person skill trigger is correct, and the earlier session/generation binding and review-thread gate remain present. But the blank-line acknowledgment defect prevents reliable forward progress of the fleet event loop, which is a release-critical operational guarantee. VERDICT: NEEDS_WORK @ The scope is narrow: fix the blank-line acknowledgment path, make lock cleanup non-masking, normalize Markdown link destinations, add regressions, reply to and resolve the three valid threads, then request a new SHA-pinned review. |
Fresh exact-head verdicts —
|
One-line delta check, PR #32 (public
|
Final CodeRabbit fixes — exact head
|
|
Tip For best results, initiate chat on the files or code changes. 🧩 Analysis chain🏁 Script executed: #!/bin/bash
set -euo pipefail
repo="AojdevStudio/agentic-utilities"
pr="32"
expected_head="cce85d41be2b396754bece05d4c5925ec189570e"
prior_head="78b09ec7d3f4507ccdb6cf44645c61f93e07e8fe"
echo "== Exact head and ancestry =="
printf 'checkout='; git rev-parse HEAD
printf 'expected_type='; git cat-file -t "$expected_head"
test "$(git rev-parse HEAD)" = "$expected_head" && echo "checkout_matches_expected=true" || echo "checkout_matches_expected=false"
git merge-base --is-ancestor "$prior_head" "$expected_head" && echo "prior_head_is_ancestor=true" || echo "prior_head_is_ancestor=false"
printf 'parent='; git rev-parse "${expected_head}^"
echo "== Exact commit delta =="
git diff --check "${expected_head}^...${expected_head}"
git diff --name-status "${expected_head}^...${expected_head}"
git diff --unified=40 "${expected_head}^...${expected_head}" -- \
skills/herdr-fleet/scripts/consume-events.mjs \
scripts/lib/package-links.mjs \
scripts/lib/package-links.test.mjs
echo "== Relevant structure =="
ast-grep outline skills/herdr-fleet/scripts/consume-events.mjs --items all --view expanded
ast-grep outline scripts/lib/package-links.mjs --items all --view expanded
ast-grep outline scripts/lib/package-links.test.mjs --items all --view expanded
echo "== Focused implementation and regression contexts =="
rg -n -C 12 \
-e 'function nextEvent|function acknowledge|function acknowledgeLocked|startLockManager|function release|blank|ENOENT|self-test' \
skills/herdr-fleet/scripts/consume-events.mjs
rg -n -C 12 \
-e 'findBrokenPackedLinks|trim\(|title|external|missing|test\(' \
scripts/lib/package-links.mjs scripts/lib/package-links.test.mjs
rg -n -C 4 \
-e 'test:herdr-fleet|package-links\.test|consume-events.*self-test|bun run check' \
package.json .github/workflows/ci.yml
echo "== PR metadata and checks =="
gh pr view "$pr" --repo "$repo" \
--json headRefOid,state,isDraft,mergeable,mergeStateStatus,statusCheckRollup \
--jq '{headRefOid,state,isDraft,mergeable,mergeStateStatus,statusChecks:[.statusCheckRollup[] | {name,status,conclusion,isRequired}]}'
echo "== Current unresolved non-outdated review threads, paginated =="
owner="${repo%%/*}"
name="${repo#*/}"
cursor=null
pages=0
total=0
open=0
while :; do
result="$(gh api graphql \
-F owner="$owner" -F name="$name" -F number="$pr" -F cursor="$cursor" \
-f query='
query($owner: String!, $name: String!, $number: Int!, $cursor: String) {
repository(owner: $owner, name: $name) {
pullRequest(number: $number) {
reviewThreads(first: 100, after: $cursor) {
nodes {
id isResolved isOutdated path line
comments(first: 1) { nodes { url } }
}
pageInfo { hasNextPage endCursor }
}
}
}
}')"
echo "$result" | jq -c '
.data.repository.pullRequest.reviewThreads.nodes[]
| select((.isResolved | not) and (.isOutdated | not))
| {id,path,line,url:(.comments.nodes[0].url // null)}'
page_total="$(echo "$result" | jq '.data.repository.pullRequest.reviewThreads.nodes | length')"
page_open="$(echo "$result" | jq '[.data.repository.pullRequest.reviewThreads.nodes[] | select((.isResolved | not) and (.isOutdated | not))] | length')"
total=$((total + page_total))
open=$((open + page_open))
pages=$((pages + 1))
has_next="$(echo "$result" | jq -r '.data.repository.pullRequest.reviewThreads.pageInfo.hasNextPage')"
cursor="$(echo "$result" | jq -r '.data.repository.pullRequest.reviewThreads.pageInfo.endCursor')"
test "$has_next" = true || break
done
printf 'review_thread_pages=%s total=%s unresolved_non_outdated=%s\n' "$pages" "$total" "$open"Length of output: 36539
General review — PASS
Specialized Agent Skill review — PASSThe event consumer’s forward-progress guarantee is restored: blank lines can no longer wedge the acknowledgment cursor. The watcher identity and generation checks, shared replacement-lock behavior, and review-thread readiness gate remain intact from the prior reviewed head. The npm-related CI finding is correctly treated as not applicable: the workflow’s Bun commands match this repository’s established Bun-only package and CI contract. VERDICT: MERGE_READY @ No blocking findings identified. |
Final exact-head evidence —
|
|
Tip For best results, initiate chat on the files or code changes. 🧩 Analysis chain🏁 Script executed: #!/bin/bash
set -euo pipefail
repo="AojdevStudio/agentic-utilities"
pr="32"
expected_head="c520924a2df0c6c1f48748e776eec690b2f2d8c5"
prior_head="cce85d41be2b396754bece05d4c5925ec189570e"
echo "== Exact head and ancestry =="
printf 'checkout='; git rev-parse HEAD
printf 'expected_type='; git cat-file -t "$expected_head"
test "$(git rev-parse HEAD)" = "$expected_head" && echo "checkout_matches_expected=true" || echo "checkout_matches_expected=false"
git merge-base --is-ancestor "$prior_head" "$expected_head" && echo "prior_head_is_ancestor=true" || echo "prior_head_is_ancestor=false"
printf 'parent='; git rev-parse "${expected_head}^"
echo "== Exact commit delta =="
git diff --check "${expected_head}^...${expected_head}"
git diff --name-status "${expected_head}^...${expected_head}"
git diff --unified=40 "${expected_head}^...${expected_head}" -- \
skills/herdr-fleet/scripts/consume-events.mjs \
skills/herdr-fleet/protocols.md \
scripts/lib/package-links.mjs \
scripts/lib/package-links.test.mjs \
package.json
echo "== Relevant outlines =="
for f in \
skills/herdr-fleet/scripts/consume-events.mjs \
scripts/lib/package-links.mjs \
scripts/lib/package-links.test.mjs \
skills/herdr-fleet/scripts/review-thread-gate.mjs
do
test -f "$f" && { echo "--- $f"; ast-grep outline "$f" --items all --view expanded; }
done
echo "== Focused source and protocol contexts =="
rg -n -C 12 \
-e 'function nextEvent|function acknowledge|function acknowledgeLocked|startLockManager|function release|status: .skip.|blank|ENOENT|self-test' \
skills/herdr-fleet/scripts/consume-events.mjs
rg -n -C 8 \
-e 'consume-events|--next|--ack|status.*skip|blank|cursor|acknowledg' \
skills/herdr-fleet/protocols.md skills/herdr-fleet/launch-fleet.md skills/herdr-fleet/SKILL.md
rg -n -C 8 \
-e 'findBrokenPackedLinks|trim\(|title|external|missing|test\(' \
scripts/lib/package-links.mjs scripts/lib/package-links.test.mjs
rg -n -C 4 \
-e 'test:herdr-fleet|package-links\.test|consume-events.*self-test|review-thread-gate\.test' \
package.json .github/workflows/ci.yml
echo "== PR metadata and checks =="
gh pr view "$pr" --repo "$repo" \
--json headRefOid,state,isDraft,mergeable,mergeStateStatus,statusCheckRollup \
--jq '{headRefOid,state,isDraft,mergeable,mergeStateStatus,statusChecks:[.statusCheckRollup[] | {name,status,conclusion,isRequired}]}'
echo "== Current unresolved, non-outdated review threads (paginated) =="
owner="${repo%%/*}"
name="${repo#*/}"
cursor=null
pages=0
total=0
open=0
while :; do
result="$(gh api graphql \
-F owner="$owner" -F name="$name" -F number="$pr" -F cursor="$cursor" \
-f query='
query($owner: String!, $name: String!, $number: Int!, $cursor: String) {
repository(owner: $owner, name: $name) {
pullRequest(number: $number) {
reviewThreads(first: 100, after: $cursor) {
nodes {
id isResolved isOutdated path line
comments(first: 1) { nodes { url } }
}
pageInfo { hasNextPage endCursor }
}
}
}
}')"
echo "$result" | jq -c '
.data.repository.pullRequest.reviewThreads.nodes[]
| select((.isResolved | not) and (.isOutdated | not))
| {id,path,line,url:(.comments.nodes[0].url // null)}'
page_total="$(echo "$result" | jq '.data.repository.pullRequest.reviewThreads.nodes | length')"
page_open="$(echo "$result" | jq '[.data.repository.pullRequest.reviewThreads.nodes[] | select((.isResolved | not) and (.isOutdated | not))] | length')"
total=$((total + page_total))
open=$((open + page_open))
pages=$((pages + 1))
has_next="$(echo "$result" | jq -r '.data.repository.pullRequest.reviewThreads.pageInfo.hasNextPage')"
cursor="$(echo "$result" | jq -r '.data.repository.pullRequest.reviewThreads.pageInfo.endCursor')"
test "$has_next" = true || break
done
printf 'review_thread_pages=%s total=%s unresolved_non_outdated=%s\n' "$pages" "$total" "$open"Length of output: 48546
General review — PASS
Specialized Agent Skill review — PASSThe consumer’s blank-record behavior is now explicit, serializable, and safely acknowledged without attempting event handling. Session/generation-bound acknowledgments, watcher identity validation under the shared start lock, and the exact-head paginated review-thread readiness gate remain intact. VERDICT: MERGE_READY @ No blocking findings identified. |
Fresh exact-head verdicts —
|
Final CodeRabbit delta review, PR #32 (public
|
Summary
herdr-fleetAgent Skill with cold-start and live-loop protocolsLinked issues
No issue required: direct control-pane assignment; no Pi-lane issue is available.
Security
secret-scanand GitGuardian checks pass at the current headVerification
bun run checkbun run pack:drygit archivesimulation:bun install --no-save --ignore-scripts,bun run check,bun run pack:drypi -e . --offline --list-modelsMain sync
origin/mainat232fd85package.jsonand package-content validation changes semanticallyReview status
781878553ff4d889071bab3fc106164f84d7af44MERGE_READYat781878553ff4d889071bab3fc106164f84d7af44MERGE_READYat781878553ff4d889071bab3fc106164f84d7af44Summary by CodeRabbit