Agent setup audit: instructions that were wrong or not followed

Contents
Summary
The setup before the audit
Instructions that were wrong
Instructions that were not followed
The fix
Audit steps, one by one
Canary tasks per role
Rules that generalize
Open items

Summary

The aredel repo had an AI assistant setup built from the guides in this section: a three-line AGENTS.md, six skills, and three OpenCode agents on three models. It looked complete. An audit on 2026-10-22 compared the files with what the tools actually load and found that most of it did not work as written. Part of the cause was in the guides, part in the repo not following them. This page lists both, the fix, and every audit step with its command, so the audit can be repeated on this repo or any other.

FindingCauseEffect
Default and triage model pinned to a retired idguide examples not updatedagent falls back to the session model or does not start
Builder not allowed aredel-map, which AGENTS.md says to read before any PHP editguide gating examplethe role that edits PHP cannot load the PHP rules
Reviewer denied all shell, told to review the staged diffguide gating examplereviewer cannot see the diff it judges
Five skill files with frontmatter YAML rejectsguide examplesstrict parsers drop the skill silently
Skills only in .opencode/skills/repo did not follow the newer guideno aredel skill loads in Claude Code
Builder pre-allowed npm test onlygeneric example copiedevery real check asks for approval
36 links to anchors that had movedpage split without a link checkreaders land on the top of the wrong page

The setup before the audit

Files as committed before 2026-10-22:

aredel/ ├── AGENTS.md three lines, @skill references ├── opencode.jsonc model, permissions, three inline agents ├── .opencode/skills/ │ ├── aredel-map.md │ ├── aredel-page/SKILL.md │ ├── aredel-blocks/SKILL.md │ ├── aredel-css.md hidden: opencode/autoinvoke false │ └── aredel-verify.md └── container/src/ai/.opencode/skills/ └── ai-style.md inside the docroot

The root instructions, in full:

# Project instructions - Read @aredel-map before touching container/src PHP files. - Page work: @aredel-page plus @aredel-blocks. CSS: @aredel-css by hand. - Finish with @aredel-verify, then regenerate sitemap.

What OpenCode resolved for the three roles, from opencode debug agents (step 2 below), rules after the global ones:

builder gpt-6-luna shell npm test * allow shell git status * allow shell git diff * allow skill * deny skill aredel-page allow skill aredel-blocks allow skill aredel-verify allow skill ai-style allow reviewer claude-opus-5-5 edit * deny shell * deny skill * deny skill aredel-verify allow triage muse-spark-1.3-contributor-free edit * deny shell * deny skill * deny skill aredel-map allow

Instructions that were wrong

These came from the guides. Each finding shows the exact lines before and after the fix, with the file and the commit they come from.

1. A retired model id as the daily default. Five config examples in OpenCode and one in Muse Spark 1.3 pinned opencode/muse-spark-1.3-contributor-free, while Make the agents run already called that id retired. The repo followed the examples. Fixed: the current id and its fallbacks live on one page, Free OpenCode model; other pages link there.

Before, opencode.jsonc at commit 3f4dc9e2, line 3 and lines 31–35:

"model": "opencode/muse-spark-1.3-contributor-free", … "agents": { "triage": { "description": "Explains aredel code and routes tasks without editing", "mode": "primary", "model": "opencode/muse-spark-1.3-contributor-free",

After, opencode.jsonc line 11:

"model": "opencode/deepseek-v4.1-flash-free",

After, .opencode/agents/triage.md line 4:

model: opencode/deepseek-v4.1-flash-free

2. A free contributor tier as the default for every task. The same guide said never to send private code to it, yet the only read rules covered .env and credential files. Fixed: the free model is the default for public code, and secret files are denied to every role, as in Deny rules.

Before, opencode.jsonc at commit 3f4dc9e2, lines 20–29, the only read rules:

{ "action": "read", "resource": "*.env", "effect": "deny" }, { "action": "read", "resource": "*creds*", "effect": "deny" }

After, opencode.jsonc lines 63–77, the three read rules added; each also has an edit twin:

{ "action": "read", "resource": "*analyze_logs/site_logs/*", "effect": "deny" }, { "action": "read", "resource": "*services/user_profile/data/*", "effect": "deny" }, { "action": "read", "resource": "~/.config/aredel/*", "effect": "deny" },

3. Gating that hid the rules from the role that needs them. The role example let triage load only aredel-map and kept it from builder, the only role that edits PHP. Fixed: builder and reviewer see every aredel skill; only triage is narrowed.

Before, opencode.jsonc at commit 3f4dc9e2, lines 80–104, the builder skill rules; aredel-map is missing:

{ "action": "skill", "resource": "*", "effect": "deny" }, { "action": "skill", "resource": "aredel-page", "effect": "allow" }, { "action": "skill", "resource": "aredel-blocks", "effect": "allow" }, { "action": "skill", "resource": "aredel-verify", "effect": "allow" }, { "action": "skill", "resource": "ai-style", "effect": "allow" }

After, .opencode/agents/builder.md lines 1–5; the rules that follow are shell rules only, so no skill is denied:

--- description: Implements aredel page, CSS and tooling changes and runs the checks mode: primary model: opencode/gpt-6-luna permissions:

4. A reviewer told to read the staged diff with shell denied. Fixed: the reviewer may run git diff, git show, git log and git status, nothing else, and a /review command passes it the diff.

Before, opencode.jsonc at commit 3f4dc9e2, lines 112–133, the reviewer permissions:

"permissions": [ { "action": "edit", "resource": "*", "effect": "deny" }, { "action": "shell", "resource": "*", "effect": "deny" }, { "action": "skill", "resource": "*", "effect": "deny" }, { "action": "skill", "resource": "aredel-verify", "effect": "allow" } ]

After, .opencode/agents/reviewer.md lines 6–24:

permissions: - action: edit resource: "*" effect: deny - action: shell resource: "*" effect: deny - action: shell resource: "git diff *" effect: allow - action: shell resource: "git show *" effect: allow - action: shell resource: "git log *" effect: allow - action: shell resource: "git status *" effect: allow

After, .opencode/commands/review.md:

--- description: Review the staged diff on the reviewer agent agent: reviewer subagent: true --- Review this staged diff against the aredel skills for the touched paths. Findings in severity order with file and line, then a verdict. !`git diff --cached`

5. Frontmatter that YAML rejects. Examples wrote name: Git Release and description: Aredel: decide …. The first is not a valid Agent Skills name, the second is not valid YAML at all (step 5). Fixed in Anatomy of a good skill: name equals the kebab-case id, values with a colon are quoted.

Before, .opencode/skills/aredel-map.md at commit 3f4dc9e2, lines 1–4:

--- name: Aredel Map description: Aredel: decide page versus include before editing any PHP file ---

The parser on that frontmatter:

yaml.scanner.ScannerError: mapping values are not allowed here

After, .claude/skills/aredel-map/SKILL.md lines 1–4:

--- name: aredel-map description: "Aredel: decide page versus include before editing or creating any PHP file under container/src/" ---

6. Two different “recommended” skill locations. Where to put skills recommended .opencode/skills/; Share skills, split agents recommended .claude/skills/ for repos that also use Claude Code. Fixed: the shared location comes first.

Before, skill files at commit 3f4dc9e2:

.opencode/skills/aredel-blocks/SKILL.md .opencode/skills/aredel-blocks/references/block-classes.md .opencode/skills/aredel-css.md .opencode/skills/aredel-map.md .opencode/skills/aredel-page/SKILL.md .opencode/skills/aredel-page/references/page-checklist.md .opencode/skills/aredel-verify.md container/src/ai/.opencode/skills/ai-style.md

After, skill files in the repo:

.claude/skills/ai-style/SKILL.md .claude/skills/aredel-blocks/SKILL.md .claude/skills/aredel-blocks/references/block-classes.md .claude/skills/aredel-css/SKILL.md .claude/skills/aredel-map/SKILL.md .claude/skills/aredel-page/SKILL.md .claude/skills/aredel-page/references/page-checklist.md .claude/skills/aredel-tooling/SKILL.md .claude/skills/aredel-verify/SKILL.md

7. A skill inside the docroot. The nested ai-style override sat in container/src/ai/.opencode/, and the FTP deploy does not exclude .opencode, so a full upload published it. Fixed: all skills live at the repo root.

The deploy exclusions, container/tools/deploy/deploy-ftp.sh lines 472–477; no .opencode in the list:

BASE_EXCLUDE_DIRS = {"reports", "allure-results", "allure-results-host", "__pycache__", ".pytest_cache", ".git", # NOTE: no "venv" here on purpose — the only venv/ dirs in # src/ are article sections (dev/python/ve/venv and twins); # real virtualenvs live in ".venv", still excluded above. ".venv", "node_modules"}

After, .claude/skills/ai-style/SKILL.md lines 1–4, outside the docroot:

--- name: ai-style description: "Aredel: AI articles under container/src/ai/ only: model names and prices, free-model links, cross-links between the agent guides" ---

8. A hidden skill as good practice. aredel-css was hidden with opencode/autoinvoke: false, so no role was offered it during CSS work. Fixed: every skill is advertised.

Before, .opencode/skills/aredel-css.md at commit 3f4dc9e2, lines 1–6:

--- name: Aredel CSS description: Aredel: add a new code class in _codeblocks.css, then build metadata: opencode/autoinvoke: false ---

After, .claude/skills/aredel-css/SKILL.md lines 1–4:

--- name: aredel-css description: "Aredel: CSS changes: code-block classes in source/_codeblocks.css, site overrides, building the served sheets with build-css.sh" ---

9. Outdated skill bodies. The published aredel-css body described the manual minified-copy sync that the CSS build pipeline replaced on 2026-10-19, and AGENTS.md said to regenerate the sitemap after every task while the verify skill said only after a page is added or removed. Fixed: the bodies on Aredel project map are copied from the repo files.

Before, the body published on the skills page, container/src/ai/skills/index.php at commit 5a728aa8:

name: Aredel CSS description: Aredel: sync a new code class from to_build to ao.css and aredel.css metadata: opencode/autoinvoke: false --- ## Workflow 1. Clone the sibling block in to_build/_blockquotes.css, rename class, label, header colors, append at EOF. 2. Mirror the identical minified line into ao.css and aredel.css, keep trailing newline. 3. Verify grep -o counts match sibling classes and render one page with the class.

After, .claude/skills/aredel-css/SKILL.md lines 9–19:

## Workflow 1. New code class: clone the nearest sibling language block in `container/src/.css/source/_codeblocks.css` (`.phpcode`, `.pycode`, `.somecode`, …), rename the class, label and header colors. Keep the HTML class casing (`.incFr13`, not `.incfr13`). 2. Add the class to the table in `container/docs/articles.md` and to `CODE_CLASSES` in `container/tests/test_css_sources.py`. 3. Build from `container/`: `tools/css/build-css.sh`; gate with `tools/css/build-css.sh --check`. Never edit `.css/output/*.css`; language classes live in `source/_codeblocks.css`, which is a core input, so do not copy them into the layout partials or a site file.

Before, AGENTS.md at commit 3f4dc9e2, line 4:

- Finish with @aredel-verify, then regenerate sitemap.

After, AGENTS.md lines 30–31:

- Regenerate the sitemap (`cd container && ./tools/generate-sitemap.sh`) only after adding or removing pages.

10. 36 links to moved anchors. Eight pages linked to /ai/agents/#ex-triage and similar after the OpenCode examples moved to OpenCode agents. Fixed, and the link check in step 4 now runs on every audit.

Before, container/src/ai/opencode/index.php at commit 5a728aa8, line 356:

│ ├── <a href="/ai/agents/#ex-triage">triage.md</a>

After, the same file, line 345:

│ ├── <a href="/ai/opencode/agents/#ex-triage">triage.md</a>

Instructions that were not followed

These guides were right; the repo did not do what they say.

1. “Make every model id resolve” (OpenCode agents). The repo kept the retired id for its default model and triage; the lines are under finding 1. Fixed: the launcher checks every pinned id before OpenCode starts and falls back along this list.

After, container/tools/ai/free-models.txt lines 9–13:

deepseek-v4.1-flash-free glm-5.3-flash-free minimax-m3.1-flash-free mimo-v2.6-flash-free nemotron-3.5-lightning-free

2. “Author skills once under .claude/skills/” (Building AI agents). The repo kept them in .opencode/skills/, so Claude Code sessions in this repo had no aredel skill to load. The before and after file lists are under finding 6.

3. Agents as files in .opencode/agents/. The guide trees showed triage.md, builder.md and reviewer.md; the repo kept the agents inline in opencode.jsonc and had no Claude Code roles at all.

Before, opencode.jsonc at commit 3f4dc9e2, lines 31–36:

"agents": { "triage": { "description": "Explains aredel code and routes tasks without editing", "mode": "primary", "model": "opencode/muse-spark-1.3-contributor-free", "steps": 6,

After, role files in the repo:

.claude/agents/builder.md .claude/agents/reviewer.md .claude/agents/triage.md .opencode/agents/builder.md .opencode/agents/reviewer.md .opencode/agents/triage.md .opencode/commands/review.md

After, .opencode/agents/triage.md lines 1–5:

--- description: Explains aredel code and routes tasks without editing mode: primary model: opencode/deepseek-v4.1-flash-free steps: 6

4. “Give every role a canary task.” None was recorded, which is why a triage agent on a retired model went unnoticed. There is no file to show: nothing in the repo held a canary result. The tasks are now defined in Canary tasks per role.

5. Exact commands in skills and allowlists. The builder allowlist kept the generic npm test *; the repo has no package.json. Its real checks are php -l, run-tests-venv.sh and pre-commit run.

Before, opencode.jsonc at commit 3f4dc9e2, lines 64–79:

"permissions": [ { "action": "shell", "resource": "npm test *", "effect": "allow" }, { "action": "shell", "resource": "git status *", "effect": "allow" }, { "action": "shell", "resource": "git diff *", "effect": "allow" },

After, .opencode/agents/builder.md lines 5–26:

permissions: - action: shell resource: "git status *" effect: allow - action: shell resource: "git diff *" effect: allow - action: shell resource: "git log *" effect: allow - action: shell resource: "php -l *" effect: allow - action: shell resource: "pre-commit run *" effect: allow - action: shell resource: "container/tools/run-tests-venv.sh *" effect: allow - action: shell resource: "./tools/run-tests-venv.sh *" effect: allow

6. Working deep references. Two skills pointed at ../../skill.md, which from a skill directory resolves to a file that does not exist.

Before, .opencode/skills/aredel-page/SKILL.md at commit 3f4dc9e2, last two lines:

## Deep reference Working notes on page classes and migration: ../../skill.md sections 2 and 6.

After, .claude/skills/aredel-page/SKILL.md, last two lines:

## Deep reference Working notes on page classes and migration: skill.md at the repo root, sections 2 and 6.

7. “A procedure that outgrows the root file belongs in a skill” — and the reverse: rules every task needs stayed in skills that load on demand. Asking before a commit, bumping version headers and keeping Python on 3.12 were never in AGENTS.md.

Before, AGENTS.md at commit 3f4dc9e2, the whole file:

# Project instructions - Read @aredel-map before touching container/src PHP files. - Page work: @aredel-page plus @aredel-blocks. CSS: @aredel-css by hand. - Finish with @aredel-verify, then regenerate sitemap.

After, AGENTS.md lines 20–33:

## Always - Never commit without asking: finish verification, then ask whether to commit or hand over explicit-path `git add` / `git commit` commands. Never `git add -A`, never `--no-verify` or another hook bypass, never edit ignore files to hide untracked work (details: `aredel-verify`). - Bump the `# version X.Y.Z` header of every changed versioned file. - Python stays on 3.12; declare dependencies in `pyproject.toml` and lock with uv, never `pip install` into a uv-managed `.venv`. - Keep CRLF line endings where HEAD has them. - Regenerate the sitemap (`cd container && ./tools/generate-sitemap.sh`) only after adding or removing pages. - Articles written by an assistant credit `author: ['Arthur Isaev', '/about/arthur_isaev/']`.

The fix

Applied on 2026-10-22, except the open items:

aredel/ ├── AGENTS.md routing table plus the rules every task needs ├── opencode.jsonc free default model, global permissions ├── .claude/skills/ seven skills, read by OpenCode and Claude Code ├── .claude/agents/ triage, builder, reviewer for Claude Code ├── .opencode/agents/ triage, builder, reviewer for OpenCode ├── .opencode/commands/review.md reviewer on the staged diff └── container/tools/ai/ ├── opencode.sh checks model ids, then starts OpenCode ├── check_opencode_models.py pinned ids against the live catalog ├── free-models.txt fallback order of free ids └── audit_agent_setup.py the static checks of this page

Roles after the fix, the same names in both tools:

RoleOpenCode modelClaude Code modelSkillsMay editShell
triagefree OpenCode modelhaikuaredel-mapnonone
builderGPT 6 Lunainheritallyesasks; git status, diff, log, php -l, tests, pre-commit allowed; push denied
reviewerClaude Opus 5.5opusallnoread-only git only

AGENTS.md now routes each task to its skills and keeps the rules every task needs: ask before a commit, bump version headers, Python 3.12 with uv-declared dependencies, keep CRLF, regenerate the sitemap only after adding or removing pages, credit AI-written articles correctly. Its full text and every skill body are on Aredel project map. Nothing was added for the sake of having more agents: three roles cover three different sets of rights, and topic knowledge lives in skills any role can load.

Audit steps, one by one

Every step of the audit, with its command and what it showed. Run them from the repo root; steps 4 to 6 also work on any repo with the same layout.

Step 1 — list the instruction files. Everything an assistant reads as instructions, including copies in odd places:

find . -path ./node_modules -prune -o \( -name AGENTS.md -o -name CLAUDE.md -o -name opencode.jsonc -o -path "*/.opencode/*" -o -path "*/.claude/*" \) -type f -print

It turned up the skill inside the docroot, container/src/ai/.opencode/skills/ai-style.md. Read every file found, plus the deep references they name.

Step 2 — see what OpenCode actually loads. Configuration is cached by the background service, so reload first, then list the config sources and the resolved agents:

opencode reload

opencode debug config

opencode debug agents | jq -r '.[] | select(.id=="triage" or .id=="builder" or .id=="reviewer") | "\(.id) \(.model.id)"'

Without the reload, the second command kept showing rules from a config that was no longer on disk. The full output, with every permission rule per agent, produced the before listing on this page.

Step 3 — check every pinned model id against the live catalog. One line for the free ids, one script for every pinned id:

curl -s https://opencode.ai/inference/v1/models | grep -o '"[a-z0-9.-]*-free"' | sort

python3 container/tools/ai/check_opencode_models.py --check

The pinned free id was missing from the list. The script reads the model fields in opencode.jsonc and .opencode/agents/ and exits non-zero when an id is gone; the endpoint answers 403 to the default Python User-Agent, so the script sends its own.

Step 4 — run the static audit. One script checks frontmatter, skill names, references, links and model ids:

python3 container/tools/ai/audit_agent_setup.py

To audit the committed version instead of the working tree, export it and point the script at the copy:

mkdir -p /tmp/head-setup && git archive HEAD AGENTS.md opencode.jsonc .opencode container/src/ai skill.md skill_css.md _internal_ai_skill_for_files.md container/docs container/tools | tar -x -C /tmp/head-setup

python3 container/tools/ai/audit_agent_setup.py --root /tmp/head-setup

Output for the setup before the fix, links left out:

FAIL: frontmatter: .opencode/skills/aredel-blocks/SKILL.md:3: value contains ': '; quote it FAIL: frontmatter: .opencode/skills/aredel-page/SKILL.md:3: value contains ': '; quote it FAIL: frontmatter: .opencode/skills/aredel-css.md:3: value contains ': '; quote it FAIL: frontmatter: .opencode/skills/aredel-map.md:3: value contains ': '; quote it FAIL: frontmatter: .opencode/skills/aredel-verify.md:3: value contains ': '; quote it FAIL: skills: .opencode/skills/aredel-map.md: name 'Aredel Map' is not the id 'aredel-map' FAIL: skills: container/src/ai/.opencode/skills/ai-style.md: name 'AI Style' is not the id 'ai-style' FAIL: references: .opencode/skills/aredel-blocks/SKILL.md: ../../skill.md does not exist FAIL: references: .opencode/skills/aredel-page/SKILL.md: ../../skill.md does not exist FAIL: models: opencode/muse-spark-1.3-contributor-free is not in the live catalog (opencode.jsonc)

Four more name failures of the same kind are left out. The link check on the guide pages reported 36 failures such as /ai/opencode/: href="/ai/agents/#ex-triage" has no such anchor. After the fix:

ok: frontmatter ok: skills ok: references ok: links ok: models

Step 5 — confirm the YAML failures with a real parser. The audit script uses a narrow rule; a YAML library gives the exact error:

python3 -c "import sys, yaml; [print(f, yaml.safe_load(open(f).read().split('---')[1])) for f in sys.argv[1:]]" .claude/skills/*/SKILL.md

Before the fix it stopped at the first skill with mapping values are not allowed here.

Step 6 — compare each role with its job. Put the resolved permissions from step 2 next to the routing in AGENTS.md and ask, per role: can it load every skill its tasks need, and can it run the commands its instructions name? That is how the builder without aredel-map and the reviewer without git diff showed up. Then check that the pre-allowed commands exist in the repo:

ls package.json container/tools/run-tests-venv.sh

Step 7 — find instructions that contradict each other. Search the same topic across all instruction files and read the hits side by side:

grep -rn "sitemap" AGENTS.md .claude/skills skill.md

grep -rn "_blockquotes\|_codeblocks" .claude/skills skill.md skill_css.md

grep -n "ao.css" skill.md container/docs/src-study-map.md

These found the sitemap rule stated two ways, the CSS source file named two ways, and two different stylesheets claimed for ArticlePage. The deep references were corrected to match the code.

Step 8 — check what a free-model agent can read. List sensitive data on disk that is ignored by git but still readable, then compare it with the read rules from step 2:

git status --short --ignored | grep "^!!"

Ignored by git does not mean hidden from an agent: only the read-deny rules decide. See open items.

Step 9 — check that no assistant config ships with the site. The docroot must hold no agent directories, and the deploy exclusions show what a full upload would skip:

find container/src -name .opencode -o -name .claude

grep -n -A6 "BASE_EXCLUDE_DIRS =" container/tools/deploy/deploy-ftp.sh

Step 10 — prove skill discovery in each tool. In OpenCode, a throwaway repo with one dummy skill per location answers which locations load. Only dummy text reaches the model:

mkdir -p /tmp/octest/.opencode/skills/a /tmp/octest/.claude/skills/c && cd /tmp/octest && git init -q

printf -- "---\nname: a\ndescription: \"Skill a\"\n---\nBody a\n" > .opencode/skills/a/SKILL.md

printf -- "---\nname: c\ndescription: \"Skill c\"\n---\nBody c\n" > .claude/skills/c/SKILL.md

opencode run --standalone --model opencode/deepseek-v4.1-flash-free "Without using any tools, list the ids of every skill you have been told you can load, one per line, then stop."

Both a and c came back, together with the global skills, so OpenCode does read .claude/skills/. The server endpoint opencode api GET /api/skill returned an empty list in the same directory, so it is no proof either way. In Claude Code the seven aredel skills appeared in the running session as soon as they were in .claude/skills/ (/skills lists them); before the move the session had none.

Step 11 — test the tools. The model check and the audit script have offline tests with a fake catalog and a fake repo:

cd container && ./tools/run-tests-venv.sh -- tests/tools/test_agent_setup_tools.py -q

17 passed

Step 12 — gate the changed files. Lint, type checks, shellcheck and the version-header rule run through pre-commit:

pre-commit run --files AGENTS.md opencode.jsonc container/tools/ai/*.py container/tools/ai/opencode.sh

Step 13 — check the guide pages. Every changed page must lint and render through the CLI with exactly one content marker, a new page must land in the sitemap, and the local site must serve every changed page. Lint, from the repo root:

php -l container/src/ai/agents/audit/index.php

Render with a shim that sets DOCUMENT_ROOT (/tmp/shim.php holds one line, $_SERVER["DOCUMENT_ROOT"] = "/home/andrei/github/aredel/container/src";) and count the marker:

cd container/src && php -d auto_prepend_file=/tmp/shim.php ai/agents/audit/index.php | grep -c 'id="bottomid"'

All 14 changed pages exited 0 with one marker each. Two pages were added, so the sitemap is regenerated and counted:

cd container && ./tools/generate-sitemap.sh && grep -c "<loc>" src/sitemap.xml

4258

Up from 4256. Then the sitemap tests run against the local site, limited to the changed pages with a paths file, one URL path per line, for example /ai/agents/audit/. The host backend needs pytest on PATH, so the container venv goes first:

cd container && PATH="$PWD/.venv/bin:$PATH" tests/run_test.sh --host --test link,content,html-id,css,footer --paths-file /tmp/ai-pages.txt

link PASS 15 passed content PASS 15 passed engine PASS 15 passed css PASS 15 passed footer PASS 15 passed

The static HTML corruption guard covers every page in one run:

cd container && ./tools/run-tests-venv.sh -- tests/test_html_code_corruption.py tests/tools -q

Canary tasks per role

Static checks prove the files load; a canary proves the role works. One task per role, run in each tool, one pass-fail line each:

RoleTaskPass when
triageIs src/ao/chessboard/game.php a page or a tool?answers “tool” from aredel-map, edits nothing
triageFix the footer of src/ai/index.phproutes to builder, edits nothing
builderadd one cmd1 block to a page, then revert itloads aredel-blocks, runs php -l without asking, shows the diff
reviewerreview a staged diff with one planted bugruns git diff --cached, finds the bug with file and line, edits nothing

In OpenCode, start through container/tools/ai/opencode.sh and pick the role; in Claude Code, ask for the subagent by name. Then read the session history, not the folder: a role that never appears there did not run.

Rules that generalize

Open items

Article author: Arthur Isaev

Related articles
AI
Creating and developing agents
Agent setup audit: the aredel case
OpenCode agents: four complete examples
Claude Code subagents
Writing skills for AI assistants
Free OpenCode model
AI security: secrets and access rights

Search this site

Channel @aofeed Chat @aofeedchat

Contacts and cooperation:
I recommend our hosting beget.com
Write to info@aredel.com if you:
1. Want to write an article for our site or translate an article into your native language.
2. Want to place thematically relevant ads on the site.
3. Ads on my site pass maximum censorship. If you see an ad block unsuitable for school-age children, shocking or misleading - please contact us by e-mail
4. Found a mistake, inaccuracy, bug, etc. on the site. ... .......
5. Articles can be shared on social media by clicking a network icon: