* 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.
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>
* 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>
`grep -q` exits at its first match without draining stdin, killing the
piping `echo` with SIGPIPE. Under `set -o pipefail` that 141 becomes the
pipeline's status, which is indistinguishable from "no match" — so a
section that is present gets reported missing. The race only surfaces on
bodies large enough that `echo` is still writing when `grep` bails, which
made the warning set differ between identical runs (full repo: 106/87/90
warnings across three runs; now a stable 59).
Feed both checks from a herestring so there is no writer to signal.
Co-authored-by: Jaak Vaher <jaak.vaher@cyber.ee>
Co-authored-by: Claude Opus 4.8 <noreply@anthropic.com>
Agents developed by Snark Health (github.com/snark-health).
Snark Health was founded by a practicing US physician with 25 years
of internal medicine and infectious disease experience and direct
leadership of a $2 billion risk-based Medicare bundled payment
contract with the US government, and a Kenyan engineer and operator
whose collaboration with the founding physician began in 1998 in
rural western Kenya. The frameworks in these files come from a team
that has delivered care in both US hospital systems and
resource-limited settings, managed actuarial risk under government
contract, and built health infrastructure across two continents
over 25 years.
AI Collective OS: snarkhealth.ai
Agent registry: snarkhealth.ai/registry
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>
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>
Removes strategy/ from lint-agents.sh AGENT_DIRS so the local linter no longer errors on the frontmatter-less NEXUS docs, matching the CI workflow's scope.
Thanks to @GuillaumeBld for the fix.
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.
Expands CI lint workflow to trigger on academic/ changes. Hardens lint-agents.sh with file existence checks and portable word-count handling (macOS/BSD compatibility).
Syncs agent directory lists (academic/, sales/, strategy/) across all three scripts: lint-agents.sh, convert.sh, install.sh. Refactors install.sh to use shared AGENT_DIRS constant, eliminating duplication. Closes#242.
- Add game-development to AGENT_DIRS in convert.sh, lint-agents.sh,
install.sh, and the CI workflow
- Remove maxdepth 1 from find commands so nested subdirectories
(e.g., game-development/unity/) are discovered
- Update CI git diff globs to **/*.md for recursive matching
- Remove strategy from lint AGENT_DIRS (playbooks, not agents)
Co-Authored-By: Claude Opus 4.6 <noreply@anthropic.com>
Prepares infrastructure for the upcoming Paid Media Division (PR #83).
Registers paid-media in convert.sh, lint-agents.sh, install.sh, and
the lint-agents GitHub Actions workflow.
Co-Authored-By: Claude Opus 4.6 <noreply@anthropic.com>
- Fix ((errors++)) causing early exit under set -e
- Fix command injection in workflow by using env variable
- Add strategy/ directory to lint paths and AGENT_DIRS
Adds a lint script and GitHub Actions workflow that checks agent
markdown files for required YAML frontmatter fields (name, description,
color) and recommends standard sections. Only changed files in PRs
are validated to avoid blocking on pre-existing issues.