-
Notifications
You must be signed in to change notification settings - Fork 0
✨ feat(skills): add public Herdr fleet workflow #32
New issue
Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.
By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.
Already on GitHub? Sign in to your account
Merged
Merged
Changes from all commits
Commits
Show all changes
13 commits
Select commit
Hold shift + click to select a range
2d34528
✨ feat(skills): add public Herdr fleet workflow
AojdevStudio 4ab08d1
Merge remote-tracking branch 'origin/main' into pi/add-herdr-fleet-skill
AojdevStudio 30bb886
🐛 fix(skills): harden Herdr fleet orchestration
AojdevStudio eb7300d
fix(herdr-fleet): harden roster orchestration
AojdevStudio f201764
Merge remote-tracking branch 'origin/main' into pi/add-herdr-fleet-skill
AojdevStudio 47fcb4f
fix(herdr-fleet): serialize watcher startup
AojdevStudio 358d74a
fix(herdr-fleet): bind watcher process ownership
AojdevStudio 5e2bd0b
ci: run verification with Bun
AojdevStudio 7415ffd
fix(herdr-fleet): close final review gaps
AojdevStudio 7818785
fix(herdr-fleet): bind release readiness state
AojdevStudio 78b09ec
fix(herdr-fleet): clarify skill trigger
AojdevStudio cce85d4
fix(herdr-fleet): close final stream edge cases
AojdevStudio c520924
fix(herdr-fleet): skip blank watcher records
AojdevStudio File filter
Filter by extension
Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
There are no files selected for viewing
This file contains hidden or bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
This file contains hidden or bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
This file contains hidden or bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
This file contains hidden or bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
This file contains hidden or bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
| Original file line number | Diff line number | Diff line change |
|---|---|---|
| @@ -0,0 +1,38 @@ | ||
| import path from "node:path"; | ||
|
|
||
| function headingAnchors(content) { | ||
| return new Set( | ||
| content | ||
| .split("\n") | ||
| .map((line) => line.match(/^#{1,6}\s+(.+)$/)?.[1]) | ||
| .filter(Boolean) | ||
| .map((heading) => | ||
| heading | ||
| .toLowerCase() | ||
| .replace(/[`*_~]/g, "") | ||
| .replace(/[^\p{L}\p{N}\s-]/gu, "") | ||
| .trim() | ||
| .replace(/\s+/g, "-"), | ||
| ), | ||
| ); | ||
| } | ||
|
|
||
| export function findBrokenPackedLinks({ sourcePath, content, packedPathSet, readTarget }) { | ||
| const broken = []; | ||
| for (const match of content.matchAll(/\[[^\]]+\]\(([^)]+)\)/g)) { | ||
| const target = match[1].trim().split(/\s+/, 1)[0]; | ||
| if (/^[a-z][a-z0-9+.-]*:/i.test(target)) continue; | ||
|
coderabbitai[bot] marked this conversation as resolved.
|
||
| const [relativeTarget, anchor] = target.split("#", 2); | ||
| const targetPath = relativeTarget | ||
| ? path.posix.normalize(path.posix.join(path.posix.dirname(sourcePath), relativeTarget)) | ||
| : sourcePath; | ||
| if (!packedPathSet.has(targetPath)) { | ||
| broken.push(`${sourcePath} -> ${target}`); | ||
| continue; | ||
| } | ||
| if (anchor && !headingAnchors(readTarget(targetPath)).has(anchor)) { | ||
| broken.push(`${sourcePath} -> #${anchor}`); | ||
| } | ||
| } | ||
| return broken; | ||
| } | ||
This file contains hidden or bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
| Original file line number | Diff line number | Diff line change |
|---|---|---|
| @@ -0,0 +1,45 @@ | ||
| import { test } from "bun:test"; | ||
| import assert from "node:assert/strict"; | ||
| import { findBrokenPackedLinks } from "./package-links.mjs"; | ||
|
|
||
| const readTarget = () => "# Included target\n"; | ||
|
|
||
| test("checkout-only targets fail packed-link validation", () => { | ||
| const broken = findBrokenPackedLinks({ | ||
| sourcePath: "skills/herdr-fleet/README.md", | ||
| content: "[private](private.md)", | ||
| packedPathSet: new Set(["skills/herdr-fleet/README.md"]), | ||
| readTarget, | ||
| }); | ||
| assert.deepEqual(broken, ["skills/herdr-fleet/README.md -> private.md"]); | ||
| }); | ||
|
|
||
| test("packed targets with valid anchors pass", () => { | ||
| const broken = findBrokenPackedLinks({ | ||
| sourcePath: "skills/herdr-fleet/README.md", | ||
| content: "[included](included.md#included-target)", | ||
| packedPathSet: new Set(["skills/herdr-fleet/README.md", "skills/herdr-fleet/included.md"]), | ||
| readTarget, | ||
| }); | ||
| assert.deepEqual(broken, []); | ||
| }); | ||
|
|
||
| test("link destinations ignore surrounding whitespace and optional titles", () => { | ||
| const broken = findBrokenPackedLinks({ | ||
| sourcePath: "skills/herdr-fleet/README.md", | ||
| content: '[included]( included.md#included-target "Title" ) [external]( https://example.com "Title" )', | ||
| packedPathSet: new Set(["skills/herdr-fleet/README.md", "skills/herdr-fleet/included.md"]), | ||
| readTarget, | ||
| }); | ||
| assert.deepEqual(broken, []); | ||
| }); | ||
|
|
||
| test("whitespace-prefixed missing targets remain broken after title removal", () => { | ||
| const broken = findBrokenPackedLinks({ | ||
| sourcePath: "skills/herdr-fleet/README.md", | ||
| content: '[missing]( missing.md "Title" )', | ||
| packedPathSet: new Set(["skills/herdr-fleet/README.md"]), | ||
| readTarget, | ||
| }); | ||
| assert.deepEqual(broken, ["skills/herdr-fleet/README.md -> missing.md"]); | ||
| }); |
This file contains hidden or bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
This file contains hidden or bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
This file contains hidden or bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
| Original file line number | Diff line number | Diff line change |
|---|---|---|
| @@ -0,0 +1,36 @@ | ||
| # Herdr Fleet | ||
|
|
||
| `herdr-fleet` helps one control pane launch or rebuild a project-scoped Herdr fleet. It asks the user for the roster, previews the pane map, reuses ownership-proven workers, and creates only confirmed missing panes. There is no default worker count or fixed worker roster. | ||
|
|
||
| See [SKILL.md](SKILL.md) for the agent contract, [launch-fleet.md](launch-fleet.md) for intake and reconciliation, and [protocols.md](protocols.md) for the live event loop. | ||
|
|
||
| ## Roster intake | ||
|
|
||
| Each worker is user-selected: | ||
|
|
||
| - label; | ||
| - launch command; | ||
| - role (`implementer`, `reviewer`, or another role); | ||
| - optional assignment or lane constraint; | ||
| - pane placement. | ||
|
|
||
| The current control pane is fixed and is not included in the worker count. Launch and rebuild require an `AskUserQuestion` roster preview and confirmation before worker-pane mutation. | ||
|
|
||
| ## Launcher menu | ||
|
|
||
| These are launcher options, not a default roster: | ||
|
|
||
| | Command | Routed model | Effort | | ||
| | --- | --- | --- | | ||
| | `claudex` | GPT-5.6 Sol | xhigh | | ||
| | `claudex --model fable` | GPT-5.6 Sol | xhigh | | ||
| | `claudex --model opus` | GPT-5.6 Sol | high | | ||
| | `claudex --model sonnet` | Grok 4.5 | high | | ||
| | `claudex --model haiku` | GPT-5.6 Terra | medium | | ||
| | `claude` | Native Claude Code | native model selection | | ||
|
|
||
|
coderabbitai[bot] marked this conversation as resolved.
|
||
| The roster can also use `pi`, `codex`, or any user-provided command. | ||
|
|
||
| Claudex keeps the Claude Code harness—its tools, permissions, skills, hooks, context management, and interface—while routing model traffic through CLIProxyAPI. Ossie's setup article, [The Fable Effect](https://aojdevstudio.me/blog/the-fable-effect/#how-i-ran-gpt-56-sol-inside-the-claude-code-harness), is the canonical setup reference. The article is currently a draft, so the URL may return 404 until publication. | ||
|
|
||
| This package intentionally does not duplicate proxy configuration, credentials, local paths, or setup secrets. | ||
Oops, something went wrong.
Oops, something went wrong.
Add this suggestion to a batch that can be applied as a single commit.
This suggestion is invalid because no changes were made to the code.
Suggestions cannot be applied while the pull request is closed.
Suggestions cannot be applied while viewing a subset of changes.
Only one suggestion per line can be applied in a batch.
Add this suggestion to a batch that can be applied as a single commit.
Applying suggestions on deleted lines is not supported.
You must change the existing code in this line in order to create a valid suggestion.
Outdated suggestions cannot be applied.
This suggestion has been applied or marked resolved.
Suggestions cannot be applied from pending reviews.
Suggestions cannot be applied on multi-line comments.
Suggestions cannot be applied while the pull request is queued to merge.
Suggestion cannot be applied right now. Please check back later.
Uh oh!
There was an error while loading. Please reload this page.