Commit Graph
139 Commits
Author SHA1 Message Date
Michael SitarzewskiandClaude Opus 5.5 23d0a68d7b fix(openclaw): one failed registration no longer costs the others
#915 made registration failures visible (main swallowed them with `|| true` and
reported success). But it returned at the first failure, so every agent after it
went unregistered. In real OpenClaw 2026.9.6 with one registration forced to fail,
batch 2 registered only 1 of the 2 agents that could have succeeded.

Keep registering the rest, name every failure in one message at the end, and
still exit non-zero. Verified against real OpenClaw (node:24, official npm
package): the failure case now registers both good agents and exits 1; the
normal install and the re-run are unchanged. #915's own test still passes.

Co-Authored-By: Claude Opus 5.5 (1M context) <noreply@anthropic.com>
2026-09-29 17:53:28 -05:00
Michael SitarzewskiandClaude Opus 5.5 a9feb4285f fix(install): skip a foreign destination symlink and keep going; replace our own
#916 stops cp from writing through a symlink at an agent's destination, which on
main overwrites whatever the link points at (verified: a user's file was replaced
by an agent). But it made one stray link fatal: under `set -e` the refusal aborted
the install at the first link, leaving a partial roster (57 of 279 in testing).
It also refused our own links, so re-installing without --link after a --link
install failed for every file (main fails there too, with "are the same file").

- A link into this clone ($REPO_ROOT) is ours: remove it and copy. That's the
  intended --link -> copy switch, and the clone's sources stay untouched.
- Any other link is skipped with a warning, recorded, and the install continues.
  The final summary lists what was not installed. A temp file carries the list so
  it survives the parallel installer's subshells.
- test-install.sh: #916's case now asserts skip-and-continue (sentinel intact,
  link left in place, the rest of the selection installs, summary reports it);
  new case for --link then copy (link replaced by a real file, source unchanged).
  65 passed, 0 failed.

Co-Authored-By: Claude Opus 5.5 (1M context) <noreply@anthropic.com>
2026-09-29 17:33:47 -05:00
Michael Sitarzewski 4d7acad64a Merge branch 'rudy-915' into integ/rudy-batch2 2026-09-29 14:41:13 -05:00
Michael Sitarzewski 4aaea9874e Merge branch 'rudy-913' into integ/rudy-batch2 2026-09-29 14:41:13 -05:00
Michael Sitarzewski 6c08f8db20 Merge branch 'rudy-914' into integ/rudy-batch2 2026-09-29 14:41:13 -05:00
Rudy Celekli 37678803bf fix(installer): refuse destination file symlinks when copying 2026-09-29 13:58:44 -04:00
Rudy Celekli 2ce9ca601a fix(openclaw): detect existing agents and report registration failures 2026-09-29 13:07:47 -04:00
Rudy Celekli 3acce92df2 fix(convert): refuse symlinked tool output directories 2026-09-29 12:59:47 -04:00
Rudy Celekli e4626b9040 fix(install): honor --path for Windsurf rules 2026-09-29 12:52:22 -04:00
Michael SitarzewskiandClaude Opus 5.5 d801ff90ad fix(install): never follow a symlink when replacing the Hermes plugin
`rm -rf "$dest/"` follows a symlink and empties its target. basename ignores a
trailing slash, so HERMES_PLUGIN_DIR=".../agency-agents-router/" passed every
check, and a symlinked destination (our own --link install, or a user's folder)
had its target's contents deleted. #903's ownership check didn't cover it: the
check reads through the link and the rm still follows it.

- Strip all trailing slashes from the destination before any check.
- A symlinked destination is removed with `rm -f` (the link itself), never
  `rm -rf`.
- test-install-hermes-destination.sh: two new cases (trailing slash on a
  symlink to a folder with a matching plugin.yaml; re-install over a --link
  install). Both fail before this commit and pass after.

Found by a destructive-path matrix (25 scenarios, throwaway container, fake HOME
with sentinel files): main fails 10 (deletes unrelated dirs, files and symlink
targets at the plugin path); the series without this commit fails 2 (H8/H9);
with it, 25/25.

Co-Authored-By: Claude Opus 5.5 (1M context) <noreply@anthropic.com>
2026-09-29 10:56:23 -05:00
Michael SitarzewskiandClaude Opus 5.5 d2d2101c45 chore(eval): regenerate the convert-outputs manifest for the integrated series
Co-Authored-By: Claude Opus 5.5 (1M context) <noreply@anthropic.com>
2026-09-29 10:34:01 -05:00
Michael Sitarzewski fe52dd6a2e Merge branch 'rudy-895' into integ/rudy-series
# Conflicts:
#	scripts/convert-outputs.sha256
2026-09-29 10:25:03 -05:00
Michael Sitarzewski d2089289b8 Merge branch 'rudy-906' into integ/rudy-series
# Conflicts:
#	.github/workflows/check-tools.yml
2026-09-29 10:25:02 -05:00
Michael Sitarzewski cb156e0b15 Merge branch 'rudy-902' into integ/rudy-series
# Conflicts:
#	.github/workflows/check-tools.yml
2026-09-29 10:25:02 -05:00
Michael Sitarzewski 6671f71765 Merge branch 'rudy-900' into integ/rudy-series
# Conflicts:
#	.github/workflows/check-tools.yml
2026-09-29 10:25:01 -05:00
Michael Sitarzewski 9abb989416 Merge branch 'rudy-904' into integ/rudy-series 2026-09-29 10:24:42 -05:00
Michael Sitarzewski c59cff9ce5 Merge branch 'rudy-901' into integ/rudy-series 2026-09-29 10:24:42 -05:00
Michael Sitarzewski 7a0f97ca58 Merge branch 'rudy-898' into integ/rudy-series 2026-09-29 10:24:42 -05:00
Michael Sitarzewski ea3e7e5322 Merge branch 'rudy-897' into integ/rudy-series 2026-09-29 10:24:42 -05:00
Michael Sitarzewski 731efe6c9b Merge branch 'rudy-896' into integ/rudy-series 2026-09-29 10:24:42 -05:00
Michael Sitarzewski 611d0448e7 Merge branch 'rudy-894' into integ/rudy-series 2026-09-29 10:24:42 -05:00
Michael Sitarzewski 3cc60d0e3f Merge branch 'rudy-893' into integ/rudy-series 2026-09-29 10:24:42 -05:00
Michael Sitarzewski 545b569e30 Merge branch 'rudy-892' into integ/rudy-series 2026-09-29 10:24:42 -05:00
Michael Sitarzewski 3c195668b0 Merge branch 'rudy-891' into integ/rudy-series 2026-09-29 10:24:41 -05:00
Michael Sitarzewski 747ad1576d Merge branch 'rudy-899' into integ/rudy-series 2026-09-29 10:24:41 -05:00
Michael Sitarzewski 71753b1b3f Merge branch 'rudy-903' into integ/rudy-series 2026-09-29 10:24:41 -05:00
fruitandClaude Opus 5.5 68f01534ef fix(install): Hermes plugin actually gets enabled on real Hermes configs (#881)
The Hermes installer printed "[OK] enabled plugin" and "Done!" while leaving agency-agents-router disabled or absent. On current Hermes this hit every user: the default plugins: block contains a column-0 "# ====" banner, and `hermes plugins enable/disable` writes enabled:/disabled: below it.

- Bound the enabled: sub-block at the first sibling key; sweep stale entries out of disabled: (Hermes: "an explicit disable wins"); handle inline [], [a,b], disabled: above enabled:, trailing comments, corrupted-scalar recovery; bail on shapes that can't be edited line-wise. (@guozi-lab)
- A column-0 comment no longer ends the plugins: block, and the rewrite's exit status propagates (`|| return 1`) so a bail warns instead of reporting success. (maintainer follow-up)
- check-hermes-config-rewrite.py: 16 cases, including Hermes' real shape.

Verified in real Hermes (official installer, 9a0a162) on configs Hermes wrote itself, with a live turn on local qwen3.8-27b: main -> "agency_agents_delegate does not exist"; this change -> delegated: true, real subagent, real result.

Closes #879

Co-Authored-By: Claude Opus 5.5 (1M context) <noreply@anthropic.com>
2026-09-28 07:03:44 -05:00
Rudy Celekli 9445c9cbee fix(installer): avoid SIGPIPE when checking selected agents 2026-09-28 01:19:06 -04:00
Rudy Celekli 7ed03ed5e7 fix(validation): reject unclosed agent frontmatter 2026-09-28 01:08:48 -04:00
Rudy Celekli 4e2d91d687 fix(installer): protect unrelated Hermes destinations 2026-09-28 01:05:47 -04:00
Rudy Celekli 09eba4b057 fix(convert): surface parallel failures and clean buffered logs 2026-09-28 01:00:07 -04:00
Rudy Celekli 070640f34c fix(installer): guard shared paths for detected tools 2026-09-28 00:56:56 -04:00
Rudy Celekli 25d6c10b92 fix(installer): stop after failed automatic conversion 2026-09-28 00:49:42 -04:00
Rudy Celekli fda3beeaba fix(convert): refuse duplicate agent slugs before writing 2026-09-28 00:32:16 -04:00
Rudy Celekli 8fba721291 fix(ci): reject undeployable runbook rosters 2026-09-28 00:20:02 -04:00
Rudy Celekli 435cf1d232 fix(ci): reject empty required agent metadata 2026-09-28 00:16:58 -04:00
Rudy Celekli 0249ecd37f fix(ci): select direct agent files for lint and originality 2026-09-28 00:05:15 -04:00
Rudy Celekli 2f1008453b fix(hermes): preserve continued frontmatter metadata 2026-09-27 23:54:05 -04:00
Rudy Celekli 77a898401a fix(eval): preserve manifest when output validation fails 2026-09-27 23:47:25 -04:00
Rudy Celekli 2bc53022ef fix(installer): honor --path for Aider roster 2026-09-27 23:39:04 -04:00
Rudy Celekli 3e7dda0ae7 fix(installer): honor single Copilot destination override 2026-09-27 23:32:32 -04:00
Rudy Celekli a47212e9e5 fix(convert): preserve Markdown separators in agent bodies 2026-09-27 23:24:27 -04:00
Roberto SolanoandClaude Opus 5.5 479193dcce feat(integration): add DeepSeek Harness (dsh) skills support (#846)
Adds DeepSeek Harness as an integration target: 279 agency-* SKILL.md skills installed to ${DSH_HOME:-~/.dsh}/skills (or DSH_SKILLS_DIR for project scope).

Verified in DeepSeek Harness itself (@deepseek-ai/dsh 0.1.7-rc.2, installed via the documented npx path on Ubuntu 26.04 arm64): the repo installer placed 279 skills, and dsh's own skill-filesystem parser accepted all 279 with zero warnings (a planted invalid name and a missing description were both rejected with dsh's own messages).

Co-Authored-By: Claude Opus 5.5 (1M context) <noreply@anthropic.com>
2026-09-27 18:45:36 -05:00
Michael SitarzewskiandClaude Opus 5 652277fba1 fix(install): tell aider users when their CONVENTIONS.md is our stale roster (#875)
#871 shrank the aider integration from 3.8M characters of concatenated agents
to a 97K roster index, because aider keeps a conventions file in context for a
whole session. The fix only reached new installs.

install_aider refuses to overwrite an existing CONVENTIONS.md, which is right —
it is aider's own user-authored file and the one on disk may be the reader's.
But "already exists (remove to reinstall)" says nothing about which file it is,
so anyone holding the pre-index roster re-ran the installer, read that, and
kept the broken file. The people the fix was written for were the ones it could
not reach.

Our generated file has always opened with "# The Agency — AI Agent
Conventions", so the installer can now tell its own stale copy from someone
else's conventions and say which it is. Neither branch writes anything.

Verified in a container, all three cases:
  stale Agency roster   -> names it, reports 3800039 bytes, says to delete and re-run
  user's own file       -> "leaving your file alone", file intact
  no file               -> installs, 97065 bytes

Windsurf has the same guard and the same gap; #870 already handles it there, so
this leaves that path alone rather than colliding with it.

Co-authored-by: Claude Opus 5 <noreply@anthropic.com>
2026-09-21 20:44:43 -05:00
Michael SitarzewskiandClaude Opus 5 87f8301cad chore(eval): regenerate the convert-outputs manifest for #871 and #872
Both PRs change generators, so every agent line moves: #871 rewrites the aider
CONVENTIONS.md as a roster index rather than 3.8M characters of concatenated
agents, and #872 teaches resolve_opencode_color() the `slate` and `navy` names
that were silently falling through to grey.

Neither PR carried the manifest, so main was left in drift.

Regenerated from a clean detached worktree at origin/main rather than the
managed clone: `--update` walks the working tree, and an untracked agent file
in that clone would have added a 280th line for a file no one else has.

Verified: 29 passed, 0 failed (279 roster agents x 14 tools).

Co-Authored-By: Claude Opus 5 <noreply@anthropic.com>
2026-09-20 18:39:14 -05:00
Hotragn Pettugani 1f92396556 fix(convert): two color names fall through to grey, and nothing checked (#872)
* fix(convert): two color names fall through to grey, and nothing checked

resolve_opencode_color() maps a name it does not recognise to #6B7280 and
says nothing about it. Four agents ask for a name it has never known:

  engineering/engineering-minimal-change-engineer.md   slate
  specialized/operations-manager.md                    slate
  gis/gis-technical-consultant.md                      navy
  specialized/chief-financial-officer.md               navy

All four render grey in the OpenCode integration, which reads as a
deliberate grey rather than a miss — and some agents do choose grey, so
there was nothing to notice.

`slate` and `navy` are now in the map. Values follow the CSS named color
where one exists (navy -> #000080, matching how teal already works) and
Tailwind's 500 shade otherwise (slate -> #64748B, matching gray).

Adding two names does not stop the next one, so two checks now cover it:

  - lint-agents.sh rejects a color that is neither #RRGGBB nor a name the
    converter knows, and prints the names it knows. The list is read out
    of resolve_opencode_color() rather than copied, so it cannot drift
    from the map that does the work. This runs on changed files in agent
    PRs, which is where a new color arrives.

  - test-convert-outputs.sh fails when an opencode output is #6B7280 and
    the source did not ask for grey. Grey stays a legitimate choice; the
    check is "grey only when the source said so".

CONTRIBUTING now says which color values actually work, since the template
just said `colorname or "#hexcode"`.

Verified: all 279 agents pass the new lint rule, and no opencode output
falls through to grey by accident.

* ci(lint): run the whole roster when the linter itself changes

The lint job scopes itself to the agent files a PR touched, which is right
for an agent PR and wrong for a rule change. A new rule lands without ever
having run against the other 278 agents — it either breaks a division
nobody edited or quietly does nothing, and either way CI is silent.

The colour check in the previous commit is the case in point: it changes
scripts/, so the lint workflow's path filter did not even fire, and the
rule would have merged without CI looking at a single agent.

Adds a lint-all job that runs the full-roster lint when scripts/
lint-agents.sh, convert.sh, or lib.sh is part of the diff, and says why it
is skipping when they are not. Those three paths are in the workflow's
trigger list now so the job can fire at all.
2026-09-20 18:35:13 -05:00
Hotragn Pettugani d3a3f573e3 fix(aider): CONVENTIONS.md is a roster index, not 3.8 million characters of agents (#871)
Aider loads a conventions file into context and keeps it there for the whole
session — that is what the file is for, and the docs say to load it with
--read so prompt caching can hold it. This integration concatenated every
agent body into it. At 279 agents that is 3,816,372 characters, roughly a
million tokens. No model takes that. Anyone who ran

    ./scripts/install.sh --tool aider

got a CONVENTIONS.md that either blows the context window on the first turn
or bills for a million tokens trying.

CONVENTIONS.md is now the roster index it was described as: one entry per
agent with the name, the description, the division, and the path to the
agent file. 96,823 characters, down from 3.8 million. The header explains
how to pull a single agent's full instructions into the session:

    /read-only /path/to/agency-agents/engineering/engineering-frontend-developer.md

Naming an agent in a prompt still works the way it did — the description is
what the model needed for that, and it is still there.

test-convert-outputs.sh now holds the index to being an index: it fails if
CONVENTIONS.md grows past 250,000 characters, if it does not list exactly
one path per roster agent, or if any path it prints does not resolve. The
existing round-trip check on the accumulated file still covers the names and
descriptions.
2026-09-20 18:35:10 -05:00
ad9264e309 fix(convert): track code fences when splitting OpenClaw sections, and pin it with an invariant (#855)
convert_openclaw() split on `## ` without tracking fenced code blocks, tearing six fenced examples across SOUL.md/AGENTS.md in five agents and leaving dangling fences in each. Implementation from #854 (@guozi-lab): fence helpers in lib.sh used by convert.sh and lint-agents.sh, CommonMark indent aware. Regression test from #853 (@dajiaohuang): every source fenced block must land whole in exactly one output file — verified to fail on the unfixed converter.

Reported by @AmineOzil. Closes #849. Supersedes #853 and #854.

Co-Authored-By: fruit <200041037+guozi-lab@users.noreply.github.com>
Co-Authored-By: Wu Shuwen <108231307+dajiaohuang@users.noreply.github.com>
Co-Authored-By: Claude Opus 5 <noreply@anthropic.com>
2026-09-12 11:57:20 -05:00
6d29a9b087 feat(agents): land six specialists — China Network, Platform, Focus Music, PDF Engine, ATS Validator, Universal Document Compiler (#845)
Consolidated landing of #768, #811, #808, #822, #842, #843 — agent files as submitted, README roster rows, regenerated Hermes README, manifest v2 (+6 agent lines). Verified together: lint, originality, guards, converted-frontmatter, outputs eval 26/26 (279 agents x 14 tools), installer 36/0, agent-selection, Hermes checks; PR CI green on all 7.

Closes #768. Closes #811. Closes #808. Closes #822. Closes #842. Closes #843.

Co-Authored-By: Sagarika Sultana <283121436+madebysaira@users.noreply.github.com>
Co-Authored-By: Sunil Kumar <24809771+sunilkumarvalmiki@users.noreply.github.com>
Co-Authored-By: augustoheiss <240949329+augustoheiss@users.noreply.github.com>
Co-Authored-By: Claude Fable 5.1 <noreply@anthropic.com>
2026-09-08 19:10:22 -05:00
Michael SitarzewskiandClaude Fable 5.1 449e0c71b1 test(convert): manifest v2 — one line per agent, platform-neutral hashes, advisory drift on PRs (#844)
See the PR for the why/what/proof. Contributors no longer touch scripts/convert-outputs.sha256; drift is advisory on pull requests and strict on main.

Co-Authored-By: Claude Fable 5.1 <noreply@anthropic.com>
2026-09-08 18:59:03 -05:00