#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>
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>
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>
#803 changed scripts/build-hermes-plugin.py, so the generated Hermes plugin legitimately
changed and the drift manifest's hermes line went stale — main's "Validate converted outputs"
step failed on drift alone (25/26 passed; every invariant held). Regenerated with
scripts/test-convert-outputs.sh --update on a clean checkout of main; the suite is 26/26.
Co-Authored-By: Claude Fable 5.1 <noreply@anthropic.com>
Adds the regression eval landed in #829 to the two places contributors
actually read: item 8 of the tool-integration checklist (beside #772's
install-suite item 7) and a new item 7 under "Before Submitting", the path
every agent contributor takes. Adding or editing an agent changes the
generated product and so flips the drift manifest; the text says so plainly,
frames --update as the expected next step rather than a failure, and asks
for the refreshed manifest to be committed alongside the change.
Closes with a short note on why the checks exist: people are building
remarkable things on these agents and thousands rely on them daily, so a
slip in one converter reaches all of them at once — running the suite is how
we keep that smooth for everyone downstream.
Refs #829#828#772
Co-authored-by: Claude Fable 5.1 <noreply@anthropic.com>
Adds scripts/test-convert-outputs.sh, the output half of the regression eval
(the install half landed in #828), and wires it plus the previously
un-wired test-agent-selection.sh (#779) into CI.
Why an eval at all: every converter bug so far passed lint and the existing
tests while the installed product was broken. #778 shipped a double-wrapped
description that was valid YAML, so a wrapper check passed; #817 dropped a
whole tool from --parallel and every remaining tool looked fine. Those are
invariant violations, not syntax errors.
Layer A (no history needed), for every agent x every converted tool:
round-trip parsed(generated).description == source description
strict-parse every generated frontmatter / TOML / YAML parses with a real
parser (kimi/vibe carry only an identifier: id == slug and the
prose file exists; aider/windsurf: "## Name" + description line)
count every tool emits exactly one output per roster agent
source every SOURCE frontmatter strict-parses and carries no leaked
quote — the desktop app reads sources with js-yaml (#473)
Layer B: scripts/convert-outputs.sha256, one aggregate hash per tool plus
divisions.json / tools.json / runbooks.json. A flipped line means outputs or a
contract changed; --update regenerates deliberately so review sees the blast
radius. Date-stable (no generated file embeds a date).
The expected side is derived by an INDEPENDENT strict parse of each source,
never by lib.sh's get_field: the generator uses get_field, so an expected
value derived the same way would move with a get_field bug and hide it —
which is exactly how #778 stayed invisible. That independence found two
shipping defects on the first green run:
- get_field returned only the first line of a multi-line plain scalar.
Three healthcare agents write their description as an indented
continuation; every generated output for them shipped it truncated
mid-sentence while the app showed the whole thing. get_field now folds
continuation lines the way YAML does (newline -> single space).
- get_field stripped only "field: " (one space). The same three files use
column-aligned frontmatter (name: X), so their generated names
carried leading whitespace in every tool's output. Plain-scalar padding
is now trimmed.
After both fixes get_field agrees with PyYAML on name and description for
all 273 sources. Acceptance: re-introducing #778's double-wrap, a dropped
tool, a divisions.json change, and an unquoted source each fail the eval
(the double-wrap via Layer A round-trip, not only the manifest).
Refs #778#817#473#810#826#828#779
Co-authored-by: Claude Fable 5.1 <noreply@anthropic.com>
* Reapply "test(install): add a regression suite for install.sh + CI on Linux and macOS (#772)" (#827)
This reverts commit 4bab3cf4a2.
* fix(install): refuse --path only for tools that would overwrite each other; re-land installer test suite (#772)
Re-lands the install.sh regression suite from #772 (reverted in #827) together
with the guard change that makes it pass, so CI goes green in one step.
Background. #825 made --path refuse more than one --tool, on #819's report that
several tools sharing one destination clobber each other. That was right in
spirit and over-broad in practice, and it was implemented without verifying
the premise. Measured by installing one agent with every tool into a sandbox
and comparing what landed:
<division>-<slug>.md (raw copy) claude-code, copilot
<slug>.md (converted) gemini-cli, opencode, qwen, zcode
agency-<slug>/SKILL.md antigravity, osaurus
Tools in the same group write identical filenames and silently overwrite each
other (qwen + gemini-cli lose a file while both print [OK]). Tools in different
groups coexist (claude-code + codex, claude-code + qwen). Every other tool's
output is distinct.
The guard now refuses --path only for a colliding pair, naming both tools and
the reason, and allows the rest. path_collision_group() holds the measured
table; re-measure if a converter's naming changes.
The suite's two-tool --path cases used claude-code + copilot, which collide:
the "installs exactly one agent" count of 1 was passing because copilot had
overwritten claude-code's identical file. They now use claude-code + codex and
assert that BOTH outputs survive, which a single count cannot show; a new case
asserts the colliding pair is refused. codex has no committed output, so those
cases convert (only the two raw-copiers work under --no-convert in a fresh
checkout).
Verified under bash 3.2 (the macOS CI leg): 29 passed, 0 failed, 1 xfail.
Guard spot-checked against all three measured groups plus a cross-group pair.
Suite, workflow and CONTRIBUTING note by @SergiorCode (#772). Refs #772#819#825#827.
Co-Authored-By: SergiorCode <SergiorCode@users.noreply.github.com>
Co-Authored-By: Claude Fable 5.1 <noreply@anthropic.com>
* fix(install): auto-convert never fired in a fresh checkout — README.md read as generated output
ensure_converted decided a converted tool's output was present if its
integrations/<tool>/ directory contained any file. Every one of those
directories ships a committed README.md, so in a fresh checkout the check
always found a file, skipped convert.sh, and the installer then hard-failed
"integrations/<tool> missing. Run convert.sh first." — the exact flow #426's
auto-convert was added to prevent. This affected every converted tool; it was
masked locally by generated outputs left behind in the working tree, and
surfaced only when the test suite ran in a clean checkout.
Only files other than README.md now count as generated output. Verified in a
clean worktree under bash 3.2: the suite's serial-control case (claude-code +
codex into one --path) now auto-converts codex and both outputs land;
29 passed, 0 failed, 1 xfail.
Refs #426
Co-Authored-By: Claude Fable 5.1 <noreply@anthropic.com>
---------
Co-authored-by: SergiorCode <SergiorCode@users.noreply.github.com>
Co-authored-by: Claude Fable 5.1 <noreply@anthropic.com>
Contributors keep reaching for the same fix when a description contains ": "
and breaks YAML frontmatter: double-quote the source scalar (#473 for
zk-steward, re-proposed in #548, and again in #810). #778 fixed the same
problem one layer down by having the converters emit quoted scalars. The two
compose badly: get_field returned a quoted source's quotes as content, so
yaml_quote wrapped them again and every generated file for an already-quoted
agent shipped as description: '"..."' with a literal quote leaking into the
parsed value. zk-steward and ai-data-remediation-engineer are affected on
main today.
get_field now treats one matching outer pair of double or single quotes as
delimiters: it strips them and unescapes (\" -> ", \\ -> \, '' -> '). Quoting a
source description is now safe and harmless, so #473/#548/#810's instinct and
#778's generator-side fix reconcile. Unquoted sources are unchanged.
Verified in a sandbox end-to-end (source -> convert.sh -> parsed YAML):
zk-steward and ai-data-remediation-engineer no longer leak a quote and keep
their internal apostrophes; developer-tooling-engineer (unquoted, contains
": ") is byte-identical to before; synthetic '...''...' and "...\"...\\" cases
unescape correctly. lib.sh is only ever sourced by bash (its shebang); note
`repeat()` at the top of the TUI section is a zsh reserved word, so sourcing
lib.sh from a zsh shell errors — pre-existing and unrelated.
Refs #473#548#810#778
Co-authored-by: Claude Fable 5.1 <noreply@anthropic.com>
Four install/convert bugs reported by @sunilkumarvalmiki (#817-#820), each
verified in a sandbox before and after the change.
- convert.sh --tool all --parallel silently skipped kimi: the parallel batch
listed 11 tools and the sequential batch 2, so the 14th tool ran in neither
(kimi output: 0 files vs 273 for every other tool). Add kimi to the parallel
batch — it writes to its own integrations/kimi/<slug>/ dir so it is
parallel-safe. (#817)
- The sequential batch's progress counter was hardcoded idx=8, stale from an
older batch size, printing "aider (8/14)" instead of 12/14. Derive it from
the parallel list length so it can never drift again; now prints 13/14 and
14/14. Same root cause as #817. (#818)
- --path is a documented single-destination override; with several --tool
values every tool resolved to the same directory and clobbered each other.
Refuse --path with more than one tool. Deliberately NOT restricting the path
itself: the override is the supported way to redirect installs (e.g. to a
sandbox), and validating it against an expected dir would break that. (#819)
- clean_tool_output runs rm -rf on $OUT_DIR/$1. The tool name is validated
upstream so this is not reachable today, but a plain-slug guard on $1 makes a
future direct caller unable to steer it outside $OUT_DIR via "../" or "/".
A prefix check would not do: "$OUT_DIR/../x" still starts with the prefix. (#820)
Fixes#817Fixes#818Fixes#819Fixes#820
Co-authored-by: Claude Fable 5.1 <noreply@anthropic.com>
* Add Research division with Research Synthesist agent
New division for literature review, source evaluation, and evidence
synthesis. Wired into divisions.json, convert.sh, lint-agents.sh,
install.sh, and the lint-agents CI workflow.
* chore(hermes): regenerate agent count 272 -> 273 for research division (#770)
Co-Authored-By: Claude Opus 4.8 <noreply@anthropic.com>
---------
Co-authored-by: Prashant Raj Bista <prashant.bista.18@gmail.com>
Co-authored-by: Claude Opus 4.8 <noreply@anthropic.com>
Vendor specialist for Huawei's GaussDB OLTP (enterprise relational DB) —
performance tuning, high availability, and migration. A niche enterprise/
China-market addition, distinct from the general database-optimizer.
Gate: lint 0/0, originality 4.7% (shared DB terminology with database-optimizer,
well under thresholds), 1 H1 + 5 sections + 7 code blocks. All guards green
(divisions/tools/runbooks/hermes); Hermes roster 262 -> 263.
Claude-Session: https://claude.ai/code/session_01WKnDRWM4izsB8WAXKszhsq
Co-authored-by: opswm <opswm@users.noreply.github.com>
Co-authored-by: Claude Opus 4.8 <noreply@anthropic.com>
Production RAG pipeline specialist: chunking strategy, retrieval quality,
hybrid search, re-ranking, and eval-driven iteration. Retrieval-first
debugging mindset ("the retrieval is the crime scene, I have the evals").
Chosen over the concurrent #686 (RAG Engineer) as the keeper: same concept,
but #601 is more complete (2x content, 7 code blocks) and was submitted first.
Gate: lint 0/0, originality 0.0%, 1 H1 + 9 sections + 7 code blocks, valid
division. All guards green (divisions/tools/runbooks/hermes); Hermes roster
261 -> 262.
Claude-Session: https://claude.ai/code/session_01WKnDRWM4izsB8WAXKszhsq
Co-authored-by: MaedehJJ <MaedehJJ@users.noreply.github.com>
Co-authored-by: Claude Opus 4.8 <noreply@anthropic.com>
Candidate-side resume optimization: JD-to-experience mapping, ATS keyword
alignment, role-requirement matching. Landed on a fresh branch (the original
#586 had a stale README conflict) with the roster row authored here.
Gate: lint 0/0, originality 0.0%, 1 H1 + 14 sections + 5 code blocks, valid
division. All guards green (divisions/tools/runbooks/hermes); Hermes roster
picks it up (260 -> 261).
Claude-Session: https://claude.ai/code/session_01WKnDRWM4izsB8WAXKszhsq
Co-authored-by: rshivam973 <rshivam973@users.noreply.github.com>
Co-authored-by: Claude Opus 4.8 <noreply@anthropic.com>
Consolidates five gated PRs into one merge (each edited the README roster,
so landing individually would cascade conflicts):
- Security: AI-Generated Code Security Auditor, Secrets & Credential Hygiene
Engineer (#647, #648 — @Synvoya)
- Engineering: Database Reliability, Developer Tooling, IoT Fleet Engineer
(#705 — @Hotragn)
- Specialized: Codebase Archaeologist (#681 — @Axion-Web-dev)
All six cleared the full gate: lint 0/0, originality 0.0-0.1% (no dupes vs
roster or each other), proper structure, valid divisions. Roster rows added
to the Security/Engineering/Specialized tables (every link verified). Full
guard suite green — divisions, tools, runbooks, and the Hermes plugin guard —
and the Hermes roster picks up all six (254 -> 260 agents).
Claude-Session: https://claude.ai/code/session_01WKnDRWM4izsB8WAXKszhsq
Co-authored-by: Synvoya <Synvoya@users.noreply.github.com>
Co-authored-by: Hotragn <Hotragn@users.noreply.github.com>
Co-authored-by: Axion-Web-dev <Axion-Web-dev@users.noreply.github.com>
Co-authored-by: Claude Opus 4.8 <noreply@anthropic.com>
* feat(tools): add ZCode (Z.ai GLM agent harness)
ZCode reads per-agent markdown from `.zcode/agents/{slug}.md` (project) and
`~/.config/zcode/agents/{slug}.md` (global), with `name` + `description` YAML
frontmatter and an optional `tools` list — the same plain-agent-markdown shape
as Qwen.
- tools.json: add the `zcode` entry (dual-scope, per-agent, format `zcode-md`).
- convert.sh: add `convert_zcode` (byte-identical to the qwen converter,
output to integrations/zcode/agents/) + register in the dispatch, valid_tools,
tools_to_run, and parallel_tools.
- install.sh: add `zcode` to ALL_TOOLS, `install_zcode`, `detect_zcode`, and the
resolve_dest / bin / is_detected / display / label dispatches.
Directories + file format verified against ZCode's published docs. Renderer
contract: `zcode-md` output is byte-identical to `qwen-md`, verified by
diffing `convert.sh --tool zcode` against `--tool qwen` (243/243 files match).
check-tools.sh passes (16 tools consistent across tools.json, install.sh, and
convert.sh); bash -n clean on both scripts.
Co-Authored-By: Claude Opus 4.8 <noreply@anthropic.com>
Claude-Session: https://claude.ai/code/session_01WdX6PvnCfRgYD11yVpXVor
* zcode: gitignore generated output + add integration README
Bring the ZCode integration in line with the other tools: the 243 generated
agent files (integrations/zcode/agents/*.md) are output of `convert.sh`, not
source — add a .gitignore rule so they can't be committed, and add
integrations/zcode/README.md documenting generate/install (matching the vibe
and qwen integration READMEs).
Verified: generated agents are now git-ignored, the README is tracked, and
check-tools.sh still passes at 16 tools.
Co-Authored-By: Claude Opus 4.8 <noreply@anthropic.com>
Claude-Session: https://claude.ai/code/session_01WKnDRWM4izsB8WAXKszhsq
* zcode: fix user-scope install path to ~/.zcode/agents (per ZCode docs)
The user-scope dest was ~/.config/zcode/agents/, but the official ZCode docs
state subagents are read from ~/.zcode/agents/<name>.md — so user-scope
installs landed where ZCode never looks. (detect.agentsDir and project scope
were already correct at .zcode/agents, so this was an internal inconsistency.)
Point tools.json dest.user, install_zcode's default, the header comment, and
the list display at ~/.zcode/agents; drop the stale ~/.config/zcode detection
clause; update the integration README. Keep format `zcode-md` distinct — ZCode's
native format supports color/model/permissions, so it will diverge from gemini-md
as the converter matures rather than being a permanent alias.
Verified: a default user-scope install now writes to ~/.zcode/agents/<slug>.md
(not ~/.config/zcode); check-tools.sh passes at 16 tools; install.sh syntax and
tools.json JSON both valid.
Co-Authored-By: Claude Opus 4.8 <noreply@anthropic.com>
Claude-Session: https://claude.ai/code/session_01WKnDRWM4izsB8WAXKszhsq
---------
Co-authored-by: Claude Opus 4.8 <noreply@anthropic.com>
convert.sh's OpenClaw conversion routes persona sections (Identity,
Communication, Critical Rules, Style, Learning & Memory) to SOUL.md and
everything else to AGENTS.md by matching `## ` header keywords. 15 agents
produced an empty SOUL.md because no header matched — the same class as the
#670 fix. Two distinct causes, two minimal fixes:
- 13 agents used a `##`-level persona section under a non-canonical name
("Role Definition" / "Core Expertise"). Renamed to "Identity & Role
Definition" / "Identity & Core Expertise" — header text only, zero content
change (each is a clean +1/-1 diff).
- 2 agents (french-consulting-market, salesforce-architect) had full persona
sections but at `#` (H1) with no title — the literal #670 bug. Shifted every
header one level deeper (fence-aware, so code-block content is untouched) and
added a `# <Name>` title. These now lint 0/0.
Verified: 0 "no section headers map to SOUL.md" warnings remain (was 15);
regenerated OpenClaw output confirms all 15 SOUL.md files are now populated
with the persona; AGENTS.md retains operations; no agent content changed;
guards green. Total lint warnings 87 -> 59 (remaining are advisory
"missing Core Mission/Critical Rules", intentionally not forced).
Claude-Session: https://claude.ai/code/session_01WKnDRWM4izsB8WAXKszhsq
Co-authored-by: Claude Opus 4.8 <noreply@anthropic.com>
Consolidates ten agent PRs from @Hotragn into one merge (they each edited
the README roster, so landing them individually would cascade conflicts):
- Engineering: Search Relevance, Identity & Access, Realtime Collaboration,
Desktop App, Mobile Release, Video Streaming, FinOps, WebAssembly,
API Platform
- Academic: Statistician
All ten cleared the gate: lint 0/0, originality 0.0–0.1% (no dupes vs the
roster or each other), proper structure, valid divisions. Roster rows added
to the Engineering and Academic tables; every link verified.
Claude-Session: https://claude.ai/code/session_01WKnDRWM4izsB8WAXKszhsq
Co-authored-by: Hotragn <Hotragn@users.noreply.github.com>
Co-authored-by: Claude Opus 4.8 <noreply@anthropic.com>
The five gov-tech agents (#580–#584) merged as agent-only PRs without
roster rows. Add them to the README division tables:
- Engineering: Drupal Performance, WordPress Performance, Section 508
Accessibility Specialist, USWDS Developer
- Specialized: FedRAMP & RMF Compliance Engineer
Docs only; every link verified to resolve to a committed agent file.
Claude-Session: https://claude.ai/code/session_01WKnDRWM4izsB8WAXKszhsq
Co-authored-by: Claude Opus 4.8 <noreply@anthropic.com>
Two references in README.md still pointed at the old
`~/.gemini/antigravity/skills/` path. Per the current Antigravity spec
(verified against Google's July 2026 docs), the canonical global skills
path for all three flavors — Antigravity, AGY CLI, AGY IDE (incl. 2.0) —
is `~/.gemini/config/skills/`. #667 fixed integrations/README.md; this
fixes the two that remained in the top-level README, so every path
reference in the repo now agrees with tools.json/convert.sh/install.sh.
Verified: zero `gemini/antigravity/skills` references remain repo-wide.
Claude-Session: https://claude.ai/code/session_01WKnDRWM4izsB8WAXKszhsq
Co-authored-by: Claude Opus 4.8 <noreply@anthropic.com>
Two marketing agents had malformed heading structure that broke the
OpenClaw conversion, which buckets sections by `^## `:
- ai-citation-strategist used H1 (`#`) for its section headers (Identity,
Communication, Rules, Mission, Deliverables, Workflow, Metrics,
Capabilities), so none matched `^## ` — SOUL.md came out nearly empty and
everything landed in AGENTS.md. Promote those section headers to `##`
(leaving template content inside code fences untouched) and add a proper
`# AI Citation Strategist` H1 title.
- agentic-search-optimizer was the only file in the division with no H1
title (body opened at `## Your Identity & Memory`). Add
`# Agentic Search Optimizer`.
Verified: lint-agents passes (0/0), and the regenerated OpenClaw output now
splits correctly — SOUL.md carries the persona sections (Identity,
Communication, Critical Rules) instead of an empty file.
Fixes#670
Claude-Session: https://claude.ai/code/session_01WKnDRWM4izsB8WAXKszhsq
Co-authored-by: Claude Opus 4.8 <noreply@anthropic.com>
The help text advertised `--tool <a,b>` (a comma list), but --tool took a
single value and validated it whole, so `--tool claude-code,cursor` failed
with "Unknown tool 'claude-code,cursor'". --division and --agent already
split on commas; --tool didn't (#671).
Split --tool on commas, trim each entry, and validate each against
ALL_TOOLS (mirrors --division), so a bad entry still errors clearly by
name. Single-tool use is unchanged.
Verified: --tool claude-code,cursor installs both; "claude-code, cursor"
(with spaces) works; --tool claude-code,nope errors on 'nope'; --tool
cursor still works.
Fixes#671
Claude-Session: https://claude.ai/code/session_01WKnDRWM4izsB8WAXKszhsq
Co-authored-by: Claude Opus 4.8 <noreply@anthropic.com>
install.sh hardcoded the division set in two lists (AGENT_DIRS,
ALL_DIVISIONS), and both had gone stale — missing healthcare (#655). So
`--tool claude-code`/`copilot` skipped healthcare's 2 agents,
`--division healthcare` errored "Unknown division", the interactive team
list omitted it, and the agent count was low by 2 (#668).
Derive both lists from divisions.json (the single source of truth), using
the same no-jq awk/grep/sed parse as check-divisions.sh. ALL_DIVISIONS is
now exactly the divisions.json entries; AGENT_DIRS is that set plus
strategy/ (preserving the intentional scan of its frontmatter-less docs,
which is_agent_file filters out). This is the same fix pattern as #659
(check-agent-originality.sh) and #666 (build-hermes-plugin.py): a derived
list can't drift, so check-divisions.sh needn't be extended to cover it.
Verified: ALL_DIVISIONS resolves to 17 (healthcare in, strategy out),
strategy still scanned, and `--division healthcare --dry-run` now finds
2 agents instead of "Unknown division".
Fixes#668
Claude-Session: https://claude.ai/code/session_01WKnDRWM4izsB8WAXKszhsq
Co-authored-by: Claude Opus 4.8 <noreply@anthropic.com>
install_hermes() resolved `dest` from HERMES_PLUGIN_DIR and ran `rm -rf
"$dest"`. The var name invites setting it to the plugins *parent*
(~/.hermes/plugins) rather than the full plugin path, in which case the
rm -rf wiped the entire plugins directory and every other plugin in it.
Always target the agency-agents-router subdir (append it when the resolved
path doesn't already end in it), and add a defensive guard that refuses to
remove any path whose basename isn't `agency-agents-router`. Verified: with
HERMES_PLUGIN_DIR set to the plugins parent, a sibling plugin's data now
survives the install.
Fixes#669
Claude-Session: https://claude.ai/code/session_01WKnDRWM4izsB8WAXKszhsq
Co-authored-by: Claude Opus 4.8 <noreply@anthropic.com>
Two correctness fixes to the Hermes plugin generator:
1. slug alias (#665): agency_agents_search returns results keyed by `slug`,
but load/inspect/delegate only accepted a param named `agent`, so the
natural chain search -> load(slug=...) failed with "agent not found".
Add `slug` as an optional alias across the READ/PROMPT/DELEGATE schemas
and resolve either key in the handlers (via _identifier), with a clear
"agent or slug is required" error when neither is passed. Backward
compatible; `required` relaxed to [] (task-only for delegate).
2. division drift: AGENT_DIRS was a hardcoded copy of the division list that
the bash check-divisions.sh guard can't see (it's a Python list), so it
silently dropped healthcare (#655) — the two healthcare agents were
missing from the Hermes roster. Derive the division dirs from
divisions.json instead (mirrors the #659 fix to check-agent-originality.sh),
so the roster stays in sync with the catalog by construction.
Verified on the regenerated plugin: roster is 235 agents (healthcare now
indexed); search "clinical evidence healthcare" -> inspect(slug=...) resolves
to Clinical Evidence Agent — exercising both fixes together. agent= still works.
Fixes#665
Claude-Session: https://claude.ai/code/session_01WKnDRWM4izsB8WAXKszhsq
Co-authored-by: Claude Opus 4.8 <noreply@anthropic.com>
check-agent-originality.sh hardcoded its own copy of the division list
(AGENT_DIRS) in the Python heredoc — a 5th copy that check-divisions.sh's
bash-array parser never saw, so it drifted: it was missing `gis` and
`security` and still carried the retired `strategy`. The practical effect
was that every gis/ and security/ agent — including newly added ones —
skipped the duplicate-detection scan entirely.
Read divisions.json directly instead of hardcoding, so this check can
never drift from the catalog again. Now scans all 16 divisions; verified
green in full-audit mode.
Supersedes #649/#650, which patch the hardcoded constants rather than
removing them.
Claude-Session: https://claude.ai/code/session_01WKnDRWM4izsB8WAXKszhsq
Co-authored-by: Claude Opus 4.8 <noreply@anthropic.com>
Two related drift traps, both from hand-typed numbers/lists that no guard
watches:
1. CONTRIBUTING had no "how to add a tool" checklist, and its wording
("all output is gitignored") implied gitignoring was automatic — so
tool contributors kept committing generated integrations/<tool>/ output.
2. The division set and agent/division counts were hardcoded in prose in
several places and had already gone stale (CONTRIBUTING said "16" and
omitted healthcare; EXECUTIVE-BRIEF said "9 divisions").
Changes:
- Add an "Adding a Tool Integration" checklist to CONTRIBUTING (discuss-first,
reuse an existing `format`, the ~5-file touch list incl. the required
.gitignore rule, run check-tools.sh). Harmonize the "committed build
output" policy line to point at it.
- De-hardcode the division list in CONTRIBUTING — defer to divisions.json.
- Stop scattering roster counts: strategy/EXECUTIVE-BRIEF ("9 divisions") and
check-agent-originality.sh ("184-agent library") drop the number entirely;
README keeps a showcase stat but softens "232 across 16" to "230+ across
every division" so it never becomes a lie as the roster grows.
Claude-Session: https://claude.ai/code/session_01WKnDRWM4izsB8WAXKszhsq
Co-authored-by: Claude Opus 4.8 <noreply@anthropic.com>
The app can't reliably resolve runbook rosters from display names (catalog
slugs are inconsistently division-prefixed, and names drift). This adds a
machine-readable manifest so the app reads rosters as data and maps each
slug to a catalog agent for one-click team deploy.
- strategy/runbooks.json: the 4 NEXUS scenarios (startup-mvp,
enterprise-feature, marketing-campaign, incident-response), each with
mode, duration, summary, doc, and a grouped roster. Every agents[] entry
is a verified slug = the agent .md filename stem (the corpus id), resolved
against the live roster — not a slugified display name. (Notably
"Senior Project Manager" is project-manager-senior, NOT
project-management-senior-project-manager, which naive mapping assumes.)
- scripts/check-runbooks.sh + .github/workflows/check-runbooks.yml: guard
(mirrors check-divisions.sh) failing the build if any roster slug doesn't
resolve to a real agent file, a doc path is missing, or JSON is malformed —
so renaming/removing an agent can't silently break the app's deploy.
All 64 slug references verified; guard passes and fails correctly.
Claude-Session: https://claude.ai/code/session_01WKnDRWM4izsB8WAXKszhsq
Co-authored-by: Claude Opus 4.8 <noreply@anthropic.com>
Antigravity moved its skill directories: global skills now load from
~/.gemini/config/skills/ and project skills from <project>/.agents/skills/
(the old ~/.gemini/antigravity/skills/ is stale). Confirmed against Google's
Antigravity Skills docs.
- tools.json: antigravity → skill-md format, new user+project dests, scope
user+project (keeps the `agency-` slug prefix for namespacing).
- convert.sh: emit standard Agent-Skills frontmatter only (name + description);
drop risk/source/date_added — the date stamp made output non-deterministic,
and it's the reason the app had kept Antigravity recognized-only. Now byte-
identical to the osaurus skill-md shape. Removed the now-unused
ANTIGRAVITY_DATE_ADDED constant.
- install.sh: install + detect against ~/.gemini/config/skills/.
- Docs updated.
check-tools.sh passes (tools.json / install.sh / convert.sh consistent).
Path discovery + skill-md approach by Pedro Remedios (msitarzewski/agency-agents-app#32).
Co-authored-by: Pedro Remedios <pedro.remedios@gmail.com>
Co-Authored-By: Claude Opus 4.8 (1M context) <noreply@anthropic.com>
The catalog now has a native desktop app (macOS/Linux/Windows) that
browses the whole roster and installs it into Claude Code, Cursor,
Codex, Gemini, Osaurus and more — no clone, no scripts, auto-updating.
- Add a top callout banner + a "Download app" release shield for discovery.
- Lead Quick Start with "Option 1: Install the app (Recommended)"; the
CLI paths shift down one (Claude Code → Option 2, Reference → 3,
Other Tools → 4) and stay intact for command-line users.
Co-authored-by: Claude Opus 4.8 (1M context) <noreply@anthropic.com>
Adds `installKind` to every tool entry and enforces it in check-tools.sh. It
classifies the install MECHANISM, which is true for every consumer (not app
state, unlike renderer coverage):
- per-agent : one rendered file/dir per agent (11 tools)
- roster : one combined file for all agents (aider, windsurf)
- plugin : a built artifact, NOT per-agent renderable — CLI-only everywhere
(hermes; no consumer can render it as a string)
Why: consumers currently infer "this tool is a plugin / can't be rendered" from
the format name + multi-file dest + reading the convert script. Making it
explicit is principled, not incidental. The Agency Agents app can now branch:
install natively when installKind is per-agent|roster AND it implements the
`format`; treat `plugin` kinds as recognized-but-CLI-only. Renderer coverage
stays the consumer's concern (derived from `format`); the catalog still carries
no app-release state — installKind passes the "true for every consumer" test
that `wired` failed.
check-tools.sh now requires installKind on every entry and validates the enum
(per-agent|roster|plugin). Purely additive — agency-agents scripts don't read
it, so this lands safely independent of the app, which adopts the field on its
next bundled-baseline refresh.
Co-authored-by: Claude Opus 4.8 (1M context) <noreply@anthropic.com>
convert_antigravity() stamped `date_added: '${TODAY}'` (the convert-run date), so
every regeneration produced different bytes for every antigravity skill — churning
the gitignored output and blocking byte-reproducible rendering downstream (the app
can't implement a renderer for output it can't reproduce).
Replace ${TODAY} with a fixed constant (ANTIGRAVITY_DATE_ADDED="2026-03-08",
matching the documented example in integrations/antigravity/README.md). The field
stays (it's part of the Antigravity frontmatter format); it's just stable now.
Verified: two consecutive `convert.sh --tool antigravity` runs produce a
byte-identical SKILL.md (same sha), and no convert-run date appears in output.
This unblocks the app from rendering antigravity (format `antigravity-skill` in
tools.json) once it implements that renderer.
Co-authored-by: Claude Opus 4.8 (1M context) <noreply@anthropic.com>
Mirrors check-divisions.yml. Runs scripts/check-tools.sh on every PR and on
push to main (no path filter) so any change to ALL_TOOLS in install.sh, the
converter set in convert.sh, or tools.json that breaks consistency fails the
build — same CI protection divisions.json already has.
Co-authored-by: Claude Opus 4.8 (1M context) <noreply@anthropic.com>
Mirrors the divisions.json / check-divisions.sh pattern for the supported tool
set. tools.json (repo root) is the single source of truth for all 13 tools,
consumed by the Agency Agents app and by scripts/convert.sh + scripts/install.sh.
scripts/check-tools.sh (no-jq, bash 3.2) fails the build if tools.json disagrees
with ALL_TOOLS in install.sh or the converter set in convert.sh, or if any entry
is missing id/label/kebab/format/dest.
Every tool carries its real install contract (format, dest, scope, detect,
version) — verified against actual convert.sh/install.sh behavior via a
sandboxed install pass (all dest templates resolve to the real on-disk layout).
`format` is the renderer contract: same name => byte-identical output. The five
formerly-undescribed tools get distinct names — aider-conventions, antigravity-skill
(its non-deterministic date_added means it can't share osaurus's skill-md),
kimi-agent, openclaw-workspace, windsurf-rules — none colliding with the app's
implemented renderers. Removed the `wired` field: it encoded app renderer state
(not catalog truth); consumers derive installability from `format` against their
own implemented-format set. check-tools.sh requires format+dest for every tool,
not just some. Also fixes antigravity detect (.gemini/antigravity-cli ->
.gemini/antigravity/skills, matching the actual code).
Co-authored-by: Claude Opus 4.8 (1M context) <noreply@anthropic.com>
convert.sh overwrote per-agent output in place but never removed files for
agents that were renamed or deleted, so orphans accumulated in the gitignored
integrations/<tool>/ dirs (e.g. agency-security-engineer lingered in
antigravity/ and openclaw/ long after the source agent was gone) — and install.sh
would happily copy them.
Add clean_tool_output(), called once at the top of run_conversions (the single
choke point for serial, parallel, and single-file paths): it wipes the tool's
generated output but preserves the committed README.md (the only tracked file
under integrations/<tool>/ for conversion targets).
Verified: antigravity regenerated to 232 (was 233), orphan pruned, README kept.
Co-authored-by: Claude Opus 4.8 (1M context) <noreply@anthropic.com>
resolve_dest honors OSAURUS_SKILLS_DIR but the header's Env: line omitted it.
One-line doc add for completeness. Follow-up to #603.
Co-authored-by: Claude Opus 4.8 (1M context) <noreply@anthropic.com>
Tooling: add Osaurus (Anthropic Agent-Skills SKILL.md format) as a conversion
and install target, wired into convert.sh (convert_osaurus + dispatch/valid/all/
parallel lists, --osaurus flag) and install.sh (detect/label/dest/install_osaurus
+ dispatch). Generated output lands in integrations/osaurus/agency-*/SKILL.md and
is gitignored like every other tool's output (regenerate via convert.sh osaurus).
Docs/guardrails — make the division contract discoverable, since it lived only
in scattered script comments and tripped up multiple contributors:
- CONTRIBUTING.md: complete the division list to all 16 (was missing academic/
gis/sales) and document that divisions.json is the source of truth (CI-checked
by check-divisions.sh), how to propose a new division, and that strategy/
(NEXUS playbooks) and integrations/ (generated output) are NOT divisions.
- install.sh: correct the stale "sync with convert.sh / lint-agents.sh" comment —
install.sh intentionally keeps strategy/ in AGENT_DIRS (filtered at scan time),
so it is deliberately NOT the same set as the other two.
- .gitignore: ignore integrations/osaurus/agency-*/ (the osaurus output was the
one tool whose generated files weren't excluded).
Co-authored-by: Claude Opus 4.8 (1M context) <noreply@anthropic.com>
actual_dirs() globbed the filesystem (`for d in */`), so it picked up gitignored
or otherwise untracked top-level directories — e.g. a local notes/ scratch dir —
and reported them as "division(s) not in divisions.json". That's a false
failure: CI uses a clean `actions/checkout` and never sees those dirs, so the
check passed in CI but failed locally, undermining a guard meant to be run
locally before pushing.
Use `git ls-files` to enumerate only top-level dirs that contain a tracked file,
keeping the dot-prefix and NON_DIVISION_DIRS filters. Local now matches CI.
Verified: passes at 16 divisions; an untracked dir is ignored; a tracked
unregistered division dir still fails the check.
Co-authored-by: Claude Opus 4.8 (1M context) <noreply@anthropic.com>
strategy/ holds 16 markdown files and ZERO have agent frontmatter — they're
playbooks (playbooks/phase-*.md), runbooks (runbooks/scenario-*.md), and briefs
(EXECUTIVE-BRIEF.md, QUICKSTART.md, nexus-strategy.md), not agent definitions.
There are 16 real agent divisions, 232 agents; strategy is not one of them.
#592 added `strategy` to lint-agents.sh AGENT_DIRS and the lint workflow paths
(to match divisions.json), which made CI lint those 16 frontmatter-less docs as
agents and fail every one with "missing frontmatter opening ---". So any PR
touching strategy/ broke CI. The original lint-agents.sh correctly excluded
strategy; #592 misread that deliberate exclusion as drift (same mistake as
integrations/ in #593).
Fix: remove strategy from convert.sh / lint-agents.sh AGENT_DIRS, the lint
workflow, and divisions.json; add it to NON_DIVISION_DIRS in check-divisions.sh.
divisions.json is now 16, matching the app's parse_agent count exactly.
Also add a content-derived backstop to check-divisions.sh: every division must
contain at least one .md with '---' frontmatter, or the build fails. This is
what stops a docs/playbook directory from being registered as an empty agent
division again — regardless of whether someone remembers the exclude list.
check-divisions.sh PASSES at 16; negative-tested that re-adding strategy fails
with "division 'strategy' has no agent files".
Co-authored-by: Claude Opus 4.8 (1M context) <noreply@anthropic.com>
#592 added `integrations` to AGENT_DIRS in convert.sh and lint-agents.sh and to
the lint workflow paths, to make those lists match divisions.json. That was
wrong: integrations/ is not a source-agent category — it's where convert.sh
WRITES per-tool conversions (e.g. openclaw output → integrations/openclaw/<agent>/SOUL.md).
It holds 957 conversion outputs across openclaw/opencode/qwen/antigravity, vs
248 real source agents in the 17 genuine categories.
Scanning integrations/ as source made the toolchain re-convert its own outputs:
the same agent appears under every tool (brand-guardian ×5), output slugs
collide, and convert.sh's last-writer-wins corrupts the catalog — which broke
downstream parity checks. convert.sh originally omitted integrations on purpose;
#592 misread that deliberate exclusion as drift.
Fix: drop integrations from convert.sh / lint-agents.sh AGENT_DIRS and the lint
workflow, remove it from divisions.json (it's not a division), and add it to
NON_DIVISION_DIRS in check-divisions.sh so the guard's canonical set is the real
17 source categories. The `strategy` additions from #592 were correct and stay.
check-divisions.sh now PASSES at 17 divisions consistent across divisions.json,
directories, scripts, and CI.
Note: integrations/mcp-memory holds 2 real source agents stranded in the output
tree; relocating them to a real category is left as separate follow-up.
Co-authored-by: Claude Opus 4.8 (1M context) <noreply@anthropic.com>
* Add divisions.json — presentation metadata (label, icon, color) per division
Establishes a source of truth for how each division (top-level agent directory)
is presented: a display label, a Lucide icon name, and a brand color. Lets the
Agency Agents app (and any other tooling) render divisions consistently —
including fixing "GIS" (was title-cased to "Gis") and covering `gis` +
`integrations`, which had no metadata before.
Co-Authored-By: Claude Opus 4.8 (1M context) <noreply@anthropic.com>
* Make divisions.json the source of truth + enforce in CI
divisions.json now drives the division set. Add scripts/check-divisions.sh
(CI: check-divisions.yml, runs on every PR with no path filter) which fails
if divisions.json disagrees with the directories on disk, the AGENT_DIRS
arrays in convert.sh / lint-agents.sh, or the lint-agents.yml path filters,
or if any entry lacks label/icon/color.
Fixes pre-existing drift surfaced by the new check: integrations was missing
from convert.sh and lint-agents.sh; integrations and strategy were missing
from lint-agents.sh and the lint workflow (so those agents weren't being
linted at all).
Co-Authored-By: Claude Opus 4.8 (1M context) <noreply@anthropic.com>
---------
Co-authored-by: Claude Opus 4.8 (1M context) <noreply@anthropic.com>
Replace literal passwords in two testing-agent code samples with
environment-variable reads — the secure, idiomatic pattern for each
framework rather than a placeholder string:
- testing-api-tester.md: 'secure_password' -> process.env.TEST_USER_PASSWORD
- testing-performance-benchmarker.md: 'password123' -> __ENV.TEST_USER_PASSWORD (k6)
Removes the weak-credential examples flagged in #477 and models good
secrets hygiene for anyone copying these snippets.
Closes#477
Co-authored-by: Claude Opus 4.8 (1M context) <noreply@anthropic.com>
Account for the 9 agents merged in #450-456, #568, #569:
- README: add 3 Engineering rows (Multi-Agent Systems Architect,
Drupal/WordPress Shopping Cart Engineer) + 6 Specialized rows
(CFO, ESG & Sustainability Officer, Data Privacy Officer,
Operations Manager, M&A Integration Manager, Organizational
Psychologist); bump Stats + acknowledgements 209 -> 218.
- install.sh: fix `--list` as the final argument aborting with
exit 1 under set -e (shift 2 with only one positional). Now
treats a missing/flag-like value as "all" and shifts once.
Roster drift is now zero (218 linked rows = 218 source agents);
convert/install auto-discover the new agents via AGENT_DIRS
(specialized/ + engineering/). lint: 0 errors, 218 files.
Co-authored-by: Claude Opus 4.8 (1M context) <noreply@anthropic.com>
* feat: installer v2 — selective install, interactive TUI, consolidate cluster
One coherent, dependency-free installer (bash 3.2+, zero deps) that
consolidates 7 conflicting install.sh PRs and fixes#532.
Selective install (compose freely; empty = everything):
- --division / --agent / --agents-file filter across both source tools and
the flat converted outputs via a slug-based allow-set (#157, #487)
- --list [tools|teams|agents] and --dry-run
Install mechanics:
- --link symlink vs copy (#233); --path + env-var fallbacks (#216);
auto-run convert.sh when integration files are missing (#426);
resolve_tool_path dynamic detection (#327); set -e-safe increments (#505)
Interactive wizard (pure bash):
- Tools -> Teams -> Review, arrow-key nav, space toggle, a/n all/none,
live / search, live agent counts, inline OpenCode capacity warning,
alt-screen takeover with trap-based Ctrl-C restore, non-TTY fallback
#532: installing a subset keeps you under OpenCode's ~119 scanner cap
(upstream anomalyco/opencode#27988); installer warns when exceeded; README
documents it.
New scripts/lib.sh holds shared frontmatter/slug helpers (used by
convert.sh too) + ANSI/TUI primitives.
Closes#157, #216, #233, #327, #426, #487, #505.
Co-Authored-By: kienbui1995 <kienbui1995@users.noreply.github.com>
Co-Authored-By: Shiven0504 <Shiven0504@users.noreply.github.com>
Co-Authored-By: rounakkumarsingh <rounakkumarsingh@users.noreply.github.com>
Co-Authored-By: toukanno <toukanno@users.noreply.github.com>
Co-Authored-By: ilyaivasyk <ilyaivasyk@users.noreply.github.com>
Co-Authored-By: Jason2031 <Jason2031@users.noreply.github.com>
Co-Authored-By: ShaoJiaZhen <ShaoJiaZhen@users.noreply.github.com>
Co-Authored-By: Claude Opus 4.8 (1M context) <noreply@anthropic.com>
* fix(installer): robust arrow-key reading (bash 3.2 integer timeouts + SS3)
read_key used a fractional -t 0.01 timeout, which bash 3.2 (/bin/bash on
macOS) doesn't support — so arrow-key escape bytes ([A/[B) leaked through
and were parsed as letter commands (toggling instead of moving). Rewrite
to read the sequence byte-by-byte with integer timeouts and handle both
CSI ([) and SS3 (O) cursor modes.
Co-Authored-By: Claude Opus 4.8 (1M context) <noreply@anthropic.com>
* fix(installer): clear-to-end-of-line per row so frames don't bleed
draw_frame only cleared below the frame (\033[0J), so when a new screen's
lines were shorter than the previous screen's, the old tails (tool paths,
warnings) bled through on the right. Now erase-to-eol (\033[K) on every
line before the screen-clear.
Co-Authored-By: Claude Opus 4.8 (1M context) <noreply@anthropic.com>
* feat(installer): 2-column grid for Tools/Teams on the Review screen
Replaces the wrapping space-joined 'Tools:'/'Teams:' lines with a compact
column-major 2-column grid (each item on its own line, like the selectors),
so long rosters stay readable and on-screen instead of wrapping.
Co-Authored-By: Claude Opus 4.8 (1M context) <noreply@anthropic.com>
* feat(installer): Review layout — space after Teams, warning below Install
Co-Authored-By: Claude Opus 4.8 (1M context) <noreply@anthropic.com>
* feat(installer): consistent screen layout across all 3 screens
Standard vertical rhythm everywhere: pager -> description -> content ->
selection summary -> navigation -> warnings. Splits the selector footer
into separate summary/nav/warning lines (SEL_SUMMARY_FN/SEL_NAV/
SEL_WARN_FN) and reorders the Review screen to match.
Co-Authored-By: Claude Opus 4.8 (1M context) <noreply@anthropic.com>
---------
Co-authored-by: kienbui1995 <kienbui1995@users.noreply.github.com>
Co-authored-by: Shiven0504 <Shiven0504@users.noreply.github.com>
Co-authored-by: rounakkumarsingh <rounakkumarsingh@users.noreply.github.com>
Co-authored-by: toukanno <toukanno@users.noreply.github.com>
Co-authored-by: ilyaivasyk <ilyaivasyk@users.noreply.github.com>
Co-authored-by: Jason2031 <Jason2031@users.noreply.github.com>
Co-authored-by: ShaoJiaZhen <ShaoJiaZhen@users.noreply.github.com>
Co-authored-by: Claude Opus 4.8 (1M context) <noreply@anthropic.com>
Migrates Gemini CLI to native subagents (~/.gemini/agents/) + quotes zk-steward description. Rebased from #472; e2e-verified with real gemini v0.43.0. Closes#473.
Co-Authored-By: Tomo Wang <tomo_wang@163.com>
The README Stats and acknowledgements were stale (144 / 147 agents, "12
divisions") and 19 merged agents were missing from the division tables.
- Update both count statements to 203 agents across 14 divisions
- Add 19 missing roster rows: Design (1), Engineering (4), Marketing (5),
Project Management (1), Sales (1), Specialized (7)
- De-hardcode the Gemini CLI README ("61 Agency agents" -> "all Agency
agents") so it can't go stale again
Verified: every on-disk agent is now linked in the README (0 missing).
Thanks to the contributors whose agents are now cataloged — @epowelljr,
@hedonnn, @Subhodip-Chatterjee, @Shiven0504, @DKFuH, @ahteshamsalamatansari,
@ahruslan17, @lz-googlefycy, @jmlozano1990, @kriptoburak — and everyone
building out The Agency.
Co-authored-by: Claude Opus 4.8 (1M context) <noreply@anthropic.com>
marketing/marketing-email-strategist.md (#509) landed with CRLF line
endings, which violate .gitattributes (*.md text eol=lf) and broke
./scripts/lint-agents.sh — head -1 saw "---\r" and reported a confusing
"missing frontmatter opening ---" on a file that visibly starts with ---.
- Normalize that file to LF (content-neutral; 0 non-whitespace changes).
- Add a CRLF guard to lint-agents.sh that fails fast with a clear,
actionable message instead of the misleading frontmatter error.
Thanks @hedonnn for the Email Marketing Strategist agent — great content;
just needed the line endings normalized.
Co-authored-by: Claude Opus 4.8 (1M context) <noreply@anthropic.com>
Adds scripts/check-agent-originality.sh, which flags new agents that
substantially duplicate an existing one. It compares each candidate
against the whole roster (and other files in the same change set) using
entity-neutralized 8-word shingle overlap, so a find-replace "re-skin"
that only swaps a country/platform name can't slip past review.
- CI: new "Check agent originality" step in lint-agents.yml runs it on
changed agent files; a >=40% match fails the build.
- Docs: CONTRIBUTING.md gains a self-run "before submitting" step, a
checklist item, and a "things we'll always close" bullet for re-skins.
Calibration: across the existing 184-agent library the worst same-pair
similarity is ~1.5% (median 0%), so the WARN >=20% / FAIL >=40% defaults
leave a wide margin against false positives.
Co-authored-by: Claude Opus 4.8 (1M context) <noreply@anthropic.com>
Adds finance/ to AGENT_DIRS in all 3 scripts, CI workflow trigger paths, CONTRIBUTING.md category list, and README.md division roster. Also fixes duplicate sales entry in lint-agents.sh.
Fixes 3 agents for CONTRIBUTING.md template compliance (missing sections, incorrect headers). Reverts 2 tooling PRs (#371 promptfoo, #337 Vitest) that were merged without required Discussion — Discussions created at #434 and #435.
Thanks @MeghanBao — Civil Engineer is a welcome addition to the Specialized Division. Closes#287!
(Apologies for the back and forth — we were in the middle of a big triage session.)
Thanks @vasanth15-hts — great rewrite of the Security Engineer. The adversarial thinking framework and expanded STRIDE analysis are a real improvement.
Refined from #51 by @SiamakSafari — restructured into standard template
with proper YAML frontmatter, deliverable templates, and platform-specific
citation patterns.
Co-Authored-By: SiamakSafari <SiamakSafari@users.noreply.github.com>
Co-Authored-By: Claude Opus 4.6 (1M context) <noreply@anthropic.com>
Clarify what belongs in a PR vs. a Discussion — agent files are always
welcome, but tooling/architecture/bulk changes should start as a
Discussion first. Committed build output will always be closed.
Co-Authored-By: Claude Opus 4.6 (1M context) <noreply@anthropic.com>
Running `convert.sh --tool aider` previously also wrote the Windsurf
output (and vice versa) because write_single_file_outputs dumped all
formats unconditionally. Each single-file format now only writes when
its tool is selected.
Co-Authored-By: Claude Opus 4.6 <noreply@anthropic.com>
Added to Engineering: AI Data Remediation Engineer, Data Engineer, Feishu
Integration Developer. Added to Marketing: Book Co-Author, Cross-Border
E-Commerce Specialist, Douyin Strategist, Livestream Commerce Coach, Podcast
Strategist, Private Domain Operator, Short-Video Editing Coach, Weibo
Strategist. Added to Specialized: Automation Governance Architect, Corporate
Training Designer, Government Digital Presales Consultant, Healthcare Marketing
Compliance, Recruitment Specialist, Study Abroad Advisor, Supply Chain
Strategist.
Co-Authored-By: Claude Opus 4.6 <noreply@anthropic.com>