From e087a0dad43753a5f49903dc2cffc2adeca8bef9 Mon Sep 17 00:00:00 2001 From: Michal Urbanek Date: Thu, 11 Jun 2026 08:15:44 +0000 Subject: [PATCH 1/8] fix: make feature-data-flow frontmatter valid YAML The single-line description contained an unquoted colon, which strict Agent Skills spec parsers reject (skill would be silently skipped by other compliant clients). Convert to a block scalar like other skills. --- ai/skills/feature-data-flow/SKILL.md | 5 ++++- 1 file changed, 4 insertions(+), 1 deletion(-) diff --git a/ai/skills/feature-data-flow/SKILL.md b/ai/skills/feature-data-flow/SKILL.md index 25e64f4..93c041c 100644 --- a/ai/skills/feature-data-flow/SKILL.md +++ b/ai/skills/feature-data-flow/SKILL.md @@ -1,6 +1,9 @@ --- name: feature-data-flow -description: Build a full feature in this Flutter repository that includes backend or storage data flow: read API schema, create DTOs, map DTOs to entities, add Riverpod use cases, connect feature state, and render UI data. Use when a task goes beyond a screen and needs real data integration. +description: > + Build a full feature in this Flutter repository that includes backend or storage data flow: + read API schema, create DTOs, map DTOs to entities, add Riverpod use cases, connect feature + state, and render UI data. Use when a task goes beyond a screen and needs real data integration. allowed-tools: Bash, Read, Grep, Glob, Edit, Write model: claude-sonnet-4-6 --- From 982be3fa8d29c173ab9fd3c8a096e2a262b0b9b9 Mon Sep 17 00:00:00 2001 From: Michal Urbanek Date: Thu, 11 Jun 2026 08:22:12 +0000 Subject: [PATCH 2/8] feat: expose skills via .agents/skills cross-client convention Symlink all ai/skills/* into .agents/skills/, the interop location from the Agent Skills spec (agentskills.io) that compliant agents scan automatically. Update the skill-creation convention in AGENTS.md from four to five steps. --- .agents/skills/build-verify | 1 + .agents/skills/create-pr | 1 + .agents/skills/feature-data-flow | 1 + .agents/skills/feature-screen | 1 + .agents/skills/implement | 1 + .agents/skills/implement-tasks-sequence | 1 + .agents/skills/layout-debug | 1 + .agents/skills/lint-format | 1 + .agents/skills/pr-review | 1 + .agents/skills/prd | 1 + .agents/skills/project-setup | 1 + .agents/skills/release-builds | 1 + .agents/skills/release-prepare | 1 + .agents/skills/review-pr-comments | 1 + .agents/skills/secrets-bootstrap | 1 + .agents/skills/start-job | 1 + .agents/skills/tasks | 1 + .agents/skills/techspec | 1 + .agents/skills/upgrade | 1 + .agents/skills/widget-test | 1 + AGENTS.md | 12 +++++++++--- 21 files changed, 29 insertions(+), 3 deletions(-) create mode 120000 .agents/skills/build-verify create mode 120000 .agents/skills/create-pr create mode 120000 .agents/skills/feature-data-flow create mode 120000 .agents/skills/feature-screen create mode 120000 .agents/skills/implement create mode 120000 .agents/skills/implement-tasks-sequence create mode 120000 .agents/skills/layout-debug create mode 120000 .agents/skills/lint-format create mode 120000 .agents/skills/pr-review create mode 120000 .agents/skills/prd create mode 120000 .agents/skills/project-setup create mode 120000 .agents/skills/release-builds create mode 120000 .agents/skills/release-prepare create mode 120000 .agents/skills/review-pr-comments create mode 120000 .agents/skills/secrets-bootstrap create mode 120000 .agents/skills/start-job create mode 120000 .agents/skills/tasks create mode 120000 .agents/skills/techspec create mode 120000 .agents/skills/upgrade create mode 120000 .agents/skills/widget-test diff --git a/.agents/skills/build-verify b/.agents/skills/build-verify new file mode 120000 index 0000000..038789c --- /dev/null +++ b/.agents/skills/build-verify @@ -0,0 +1 @@ +../../ai/skills/build-verify \ No newline at end of file diff --git a/.agents/skills/create-pr b/.agents/skills/create-pr new file mode 120000 index 0000000..d71079b --- /dev/null +++ b/.agents/skills/create-pr @@ -0,0 +1 @@ +../../ai/skills/create-pr \ No newline at end of file diff --git a/.agents/skills/feature-data-flow b/.agents/skills/feature-data-flow new file mode 120000 index 0000000..3055f98 --- /dev/null +++ b/.agents/skills/feature-data-flow @@ -0,0 +1 @@ +../../ai/skills/feature-data-flow \ No newline at end of file diff --git a/.agents/skills/feature-screen b/.agents/skills/feature-screen new file mode 120000 index 0000000..3df57fb --- /dev/null +++ b/.agents/skills/feature-screen @@ -0,0 +1 @@ +../../ai/skills/feature-screen \ No newline at end of file diff --git a/.agents/skills/implement b/.agents/skills/implement new file mode 120000 index 0000000..74bd3bf --- /dev/null +++ b/.agents/skills/implement @@ -0,0 +1 @@ +../../ai/skills/implement \ No newline at end of file diff --git a/.agents/skills/implement-tasks-sequence b/.agents/skills/implement-tasks-sequence new file mode 120000 index 0000000..9b015d6 --- /dev/null +++ b/.agents/skills/implement-tasks-sequence @@ -0,0 +1 @@ +../../ai/skills/implement-tasks-sequence \ No newline at end of file diff --git a/.agents/skills/layout-debug b/.agents/skills/layout-debug new file mode 120000 index 0000000..0ff119c --- /dev/null +++ b/.agents/skills/layout-debug @@ -0,0 +1 @@ +../../ai/skills/layout-debug \ No newline at end of file diff --git a/.agents/skills/lint-format b/.agents/skills/lint-format new file mode 120000 index 0000000..edbc66f --- /dev/null +++ b/.agents/skills/lint-format @@ -0,0 +1 @@ +../../ai/skills/lint-format \ No newline at end of file diff --git a/.agents/skills/pr-review b/.agents/skills/pr-review new file mode 120000 index 0000000..dcb8e77 --- /dev/null +++ b/.agents/skills/pr-review @@ -0,0 +1 @@ +../../ai/skills/pr-review \ No newline at end of file diff --git a/.agents/skills/prd b/.agents/skills/prd new file mode 120000 index 0000000..97e3cf4 --- /dev/null +++ b/.agents/skills/prd @@ -0,0 +1 @@ +../../ai/skills/prd \ No newline at end of file diff --git a/.agents/skills/project-setup b/.agents/skills/project-setup new file mode 120000 index 0000000..73b95d9 --- /dev/null +++ b/.agents/skills/project-setup @@ -0,0 +1 @@ +../../ai/skills/project-setup \ No newline at end of file diff --git a/.agents/skills/release-builds b/.agents/skills/release-builds new file mode 120000 index 0000000..50332b4 --- /dev/null +++ b/.agents/skills/release-builds @@ -0,0 +1 @@ +../../ai/skills/release-builds \ No newline at end of file diff --git a/.agents/skills/release-prepare b/.agents/skills/release-prepare new file mode 120000 index 0000000..243af08 --- /dev/null +++ b/.agents/skills/release-prepare @@ -0,0 +1 @@ +../../ai/skills/release-prepare \ No newline at end of file diff --git a/.agents/skills/review-pr-comments b/.agents/skills/review-pr-comments new file mode 120000 index 0000000..f6b35ff --- /dev/null +++ b/.agents/skills/review-pr-comments @@ -0,0 +1 @@ +../../ai/skills/review-pr-comments \ No newline at end of file diff --git a/.agents/skills/secrets-bootstrap b/.agents/skills/secrets-bootstrap new file mode 120000 index 0000000..fff4db6 --- /dev/null +++ b/.agents/skills/secrets-bootstrap @@ -0,0 +1 @@ +../../ai/skills/secrets-bootstrap \ No newline at end of file diff --git a/.agents/skills/start-job b/.agents/skills/start-job new file mode 120000 index 0000000..d9ea860 --- /dev/null +++ b/.agents/skills/start-job @@ -0,0 +1 @@ +../../ai/skills/start-job \ No newline at end of file diff --git a/.agents/skills/tasks b/.agents/skills/tasks new file mode 120000 index 0000000..c56e514 --- /dev/null +++ b/.agents/skills/tasks @@ -0,0 +1 @@ +../../ai/skills/tasks \ No newline at end of file diff --git a/.agents/skills/techspec b/.agents/skills/techspec new file mode 120000 index 0000000..291e8e3 --- /dev/null +++ b/.agents/skills/techspec @@ -0,0 +1 @@ +../../ai/skills/techspec \ No newline at end of file diff --git a/.agents/skills/upgrade b/.agents/skills/upgrade new file mode 120000 index 0000000..4bd522a --- /dev/null +++ b/.agents/skills/upgrade @@ -0,0 +1 @@ +../../ai/skills/upgrade \ No newline at end of file diff --git a/.agents/skills/widget-test b/.agents/skills/widget-test new file mode 120000 index 0000000..efdc1d7 --- /dev/null +++ b/.agents/skills/widget-test @@ -0,0 +1 @@ +../../ai/skills/widget-test \ No newline at end of file diff --git a/AGENTS.md b/AGENTS.md index 4c582b4..1ac04dc 100644 --- a/AGENTS.md +++ b/AGENTS.md @@ -77,10 +77,14 @@ Existing skills: that point at `ai/skills//`. Each skill is also exposed as a slash command at `.claude/commands/.md`, so `/feature-screen`, `/pr-review`, `/release-prepare`, etc. work as explicit invocations. +- **Other spec-compliant agents** auto-discover skills through + `.agents/skills/` symlinks — the cross-client interop location defined + by the [Agent Skills](https://agentskills.io) format that this repo's skills + follow. ### Creating a new skill -When adding a new repeatable workflow, complete all four steps so both Codex and -Claude can use it: +When adding a new repeatable workflow, complete all five steps so Codex, Claude, +and other skills-compliant agents can use it: 1. **Author the skill.** Create `ai/skills//SKILL.md` with YAML frontmatter and the workflow body. Required fields: - `name:` matching the folder @@ -96,7 +100,9 @@ Claude can use it: 2. **Mention it for Codex.** Add the skill to the "Existing skills" list above. 3. **Expose it to Claude Code (auto-discovery).** Add a symlink: `ln -s ../../ai/skills/ .claude/skills/` -4. **Add a slash command.** Create `.claude/commands/.md` using one of the +4. **Expose it to other agents (interop).** Add a symlink: + `ln -s ../../ai/skills/ .agents/skills/` +5. **Add a slash command.** Create `.claude/commands/.md` using one of the existing commands as a template — a short frontmatter (`description`, `argument-hint`) and a one-line body that invokes the skill, followed by `$ARGUMENTS`. From 872c0e5d3756a22a4fbecb179cfc582ea8b75863 Mon Sep 17 00:00:00 2001 From: Michal Urbanek Date: Thu, 11 Jun 2026 08:23:32 +0000 Subject: [PATCH 3/8] feat: add skill validation script to the skill-creation workflow Validates ai/skills/* against the Agent Skills spec (strict YAML frontmatter, name/description constraints, body length) and the repo convention (.claude/skills + .agents/skills symlinks, slash command). Agents run python3 ai/validate_skills.py as the final step when adding or editing skills; would have caught the feature-data-flow bug. --- AGENTS.md | 8 ++- ai/validate_skills.py | 127 ++++++++++++++++++++++++++++++++++++++++++ makefile | 2 +- 3 files changed, 135 insertions(+), 2 deletions(-) create mode 100644 ai/validate_skills.py diff --git a/AGENTS.md b/AGENTS.md index 1ac04dc..9d6671e 100644 --- a/AGENTS.md +++ b/AGENTS.md @@ -83,7 +83,7 @@ Existing skills: follow. ### Creating a new skill -When adding a new repeatable workflow, complete all five steps so Codex, Claude, +When adding a new repeatable workflow, complete all six steps so Codex, Claude, and other skills-compliant agents can use it: 1. **Author the skill.** Create `ai/skills//SKILL.md` with YAML frontmatter and the workflow body. Required fields: @@ -106,3 +106,9 @@ and other skills-compliant agents can use it: existing commands as a template — a short frontmatter (`description`, `argument-hint`) and a one-line body that invokes the skill, followed by `$ARGUMENTS`. + +6. **Validate.** Run `python3 ai/validate_skills.py` and fix any reported + issues. It checks Agent Skills spec compliance (strict YAML frontmatter, + name/description rules) and that all exposure symlinks and the slash + command from steps 3-5 exist. Also run it after editing any existing + SKILL.md frontmatter. diff --git a/ai/validate_skills.py b/ai/validate_skills.py new file mode 100644 index 0000000..0148231 --- /dev/null +++ b/ai/validate_skills.py @@ -0,0 +1,127 @@ +#!/usr/bin/env python3 +"""Validate ai/skills/* against the Agent Skills spec (agentskills.io/specification) +and this repo's skill-exposure convention (see AGENTS.md "Creating a new skill"). + +Checks per skill: + - SKILL.md exists with parseable YAML frontmatter (strict — lenient parsers in + some clients mask errors that make other clients silently skip the skill) + - name: required, 1-64 chars, lowercase alphanumerics and single hyphens, + no leading/trailing hyphen, matches the directory name + - description: required, 1-1024 chars + - unknown top-level frontmatter fields (spec fields + known Claude Code + extensions are accepted; anything else is a warning) + - SKILL.md body under 500 lines (spec recommendation; warning) + - exposure symlinks and slash command exist: + .claude/skills/, .agents/skills/, .claude/commands/.md + +Exits 1 on errors, 0 if only warnings. Requires PyYAML (pip install pyyaml). +""" + +import os +import re +import sys + +REPO_ROOT = os.path.dirname(os.path.dirname(os.path.abspath(__file__))) +SKILLS_DIR = os.path.join(REPO_ROOT, "ai", "skills") + +SPEC_FIELDS = {"name", "description", "license", "compatibility", "metadata", "allowed-tools"} +CLAUDE_EXTENSIONS = {"model", "user-invocable", "disable-model-invocation"} +NAME_RE = re.compile(r"^[a-z0-9]+(-[a-z0-9]+)*$") +MAX_BODY_LINES = 500 + +try: + import yaml +except ImportError: + print("error: PyYAML is required: pip install pyyaml") + sys.exit(1) + + +def check_skill(skill_dir: str) -> tuple[list[str], list[str]]: + errors: list[str] = [] + warnings: list[str] = [] + dirname = os.path.basename(skill_dir) + skill_md = os.path.join(skill_dir, "SKILL.md") + + if not os.path.isfile(skill_md): + return [f"missing SKILL.md"], warnings + + text = open(skill_md, encoding="utf-8").read() + match = re.match(r"^---\n(.*?)\n---\n?(.*)$", text, re.S) + if not match: + return ["SKILL.md has no YAML frontmatter block"], warnings + + try: + fm = yaml.safe_load(match.group(1)) + except yaml.YAMLError as exc: + msg = str(exc).splitlines()[0] + return [f"frontmatter is not valid YAML ({msg}) — " + "quote values containing colons or use a '>' block scalar"], warnings + if not isinstance(fm, dict): + return ["frontmatter is not a YAML mapping"], warnings + + name = fm.get("name") + if not name: + errors.append("missing required field: name") + else: + if name != dirname: + errors.append(f"name '{name}' does not match directory '{dirname}'") + if not NAME_RE.fullmatch(str(name)): + errors.append(f"name '{name}' violates spec charset rules") + if len(str(name)) > 64: + errors.append("name exceeds 64 characters") + + description = fm.get("description") + if not description: + errors.append("missing required field: description") + elif len(str(description)) > 1024: + errors.append(f"description is {len(str(description))} chars (max 1024)") + + for key in fm: + if key not in SPEC_FIELDS | CLAUDE_EXTENSIONS: + warnings.append(f"unknown frontmatter field '{key}' " + "(spec suggests nesting extras under 'metadata:')") + + body_lines = match.group(2).count("\n") + 1 + if body_lines > MAX_BODY_LINES: + warnings.append(f"body is {body_lines} lines (spec recommends < {MAX_BODY_LINES}; " + "consider moving detail into references/)") + + for rel, kind in [ + (os.path.join(".claude", "skills", dirname), "Claude Code symlink"), + (os.path.join(".agents", "skills", dirname), "interop symlink"), + (os.path.join(".claude", "commands", f"{dirname}.md"), "slash command"), + ]: + path = os.path.join(REPO_ROOT, rel) + if not os.path.exists(path): + errors.append(f"missing {kind}: {rel}") + + return errors, warnings + + +def main() -> int: + if not os.path.isdir(SKILLS_DIR): + print(f"error: skills directory not found: {SKILLS_DIR}") + return 1 + + total_errors = 0 + total_warnings = 0 + for entry in sorted(os.listdir(SKILLS_DIR)): + skill_dir = os.path.join(SKILLS_DIR, entry) + if not os.path.isdir(skill_dir): + continue + errors, warnings = check_skill(skill_dir) + total_errors += len(errors) + total_warnings += len(warnings) + status = "FAIL" if errors else ("WARN" if warnings else "OK") + print(f"{status:4} {entry}") + for issue in errors: + print(f" error: {issue}") + for issue in warnings: + print(f" warning: {issue}") + + print(f"\n{total_errors} error(s), {total_warnings} warning(s)") + return 1 if total_errors else 0 + + +if __name__ == "__main__": + sys.exit(main()) diff --git a/makefile b/makefile index 89220e5..ea1f799 100644 --- a/makefile +++ b/makefile @@ -32,7 +32,7 @@ install: # Install any required packages integration_test: # Runs Patrol Integration tests @patrol test --flavor develop -test: # Runs Flutter tests +test: # Runs Flutter tests @fvm flutter test generateAndroidProductionAppBundle: # Clean everything and build Android AppBundle From 999e1b7c65ef16bbefdfade3456e38d6faaf17d3 Mon Sep 17 00:00:00 2001 From: Michal Urbanek Date: Thu, 11 Jun 2026 08:33:54 +0000 Subject: [PATCH 4/8] refactor: make .agents/skills the canonical skills location Move skill sources from ai/skills/ into .agents/skills/, the standard cross-client Agent Skills location, so compliant agents discover them natively instead of via symlinks. Retarget .claude/skills symlinks, move the validator to .agents/, and update all path references in AGENTS.md, CLAUDE.md, README, and docs. ai/ now only holds templates. --- .agents/skills/build-verify | 1 - {ai => .agents}/skills/build-verify/SKILL.md | 0 .../skills/build-verify/scripts/verify.sh | 0 .agents/skills/create-pr | 1 - {ai => .agents}/skills/create-pr/SKILL.md | 0 .agents/skills/feature-data-flow | 1 - .../skills/feature-data-flow/SKILL.md | 0 .agents/skills/feature-screen | 1 - .../skills/feature-screen/SKILL.md | 0 .agents/skills/implement | 1 - .agents/skills/implement-tasks-sequence | 1 - .../skills/implement-tasks-sequence/SKILL.md | 0 {ai => .agents}/skills/implement/SKILL.md | 4 +- .agents/skills/layout-debug | 1 - {ai => .agents}/skills/layout-debug/SKILL.md | 0 .agents/skills/lint-format | 1 - {ai => .agents}/skills/lint-format/SKILL.md | 2 +- .../skills/lint-format/scripts/lint-format.sh | 0 .agents/skills/pr-review | 1 - {ai => .agents}/skills/pr-review/SKILL.md | 0 .agents/skills/prd | 1 - {ai => .agents}/skills/prd/SKILL.md | 0 .agents/skills/project-setup | 1 - {ai => .agents}/skills/project-setup/SKILL.md | 20 ++++----- .agents/skills/release-builds | 1 - .../skills/release-builds/SKILL.md | 10 ++--- .../release-builds/scripts/archive_ios_ipa.sh | 2 +- .agents/skills/release-prepare | 1 - .../skills/release-prepare/SKILL.md | 0 .agents/skills/review-pr-comments | 1 - .../skills/review-pr-comments/SKILL.md | 0 .agents/skills/secrets-bootstrap | 1 - .../skills/secrets-bootstrap/SKILL.md | 0 .agents/skills/start-job | 1 - {ai => .agents}/skills/start-job/SKILL.md | 0 .agents/skills/tasks | 1 - {ai => .agents}/skills/tasks/SKILL.md | 0 .agents/skills/techspec | 1 - {ai => .agents}/skills/techspec/SKILL.md | 0 .agents/skills/upgrade | 1 - {ai => .agents}/skills/upgrade/SKILL.md | 0 .agents/skills/widget-test | 1 - {ai => .agents}/skills/widget-test/SKILL.md | 0 {ai => .agents}/validate_skills.py | 9 ++-- .claude/CLAUDE.md | 18 ++++---- .claude/skills/build-verify | 2 +- .claude/skills/create-pr | 2 +- .claude/skills/feature-data-flow | 2 +- .claude/skills/feature-screen | 2 +- .claude/skills/implement | 2 +- .claude/skills/implement-tasks-sequence | 2 +- .claude/skills/layout-debug | 2 +- .claude/skills/lint-format | 2 +- .claude/skills/pr-review | 2 +- .claude/skills/prd | 2 +- .claude/skills/project-setup | 2 +- .claude/skills/release-builds | 2 +- .claude/skills/release-prepare | 2 +- .claude/skills/review-pr-comments | 2 +- .claude/skills/secrets-bootstrap | 2 +- .claude/skills/start-job | 2 +- .claude/skills/tasks | 2 +- .claude/skills/techspec | 2 +- .claude/skills/upgrade | 2 +- .claude/skills/widget-test | 2 +- AGENTS.md | 42 +++++++++---------- README.md | 16 +++---- docs/PROJECT_GUIDELINES.md | 8 ++-- 68 files changed, 84 insertions(+), 107 deletions(-) delete mode 120000 .agents/skills/build-verify rename {ai => .agents}/skills/build-verify/SKILL.md (100%) rename {ai => .agents}/skills/build-verify/scripts/verify.sh (100%) delete mode 120000 .agents/skills/create-pr rename {ai => .agents}/skills/create-pr/SKILL.md (100%) delete mode 120000 .agents/skills/feature-data-flow rename {ai => .agents}/skills/feature-data-flow/SKILL.md (100%) delete mode 120000 .agents/skills/feature-screen rename {ai => .agents}/skills/feature-screen/SKILL.md (100%) delete mode 120000 .agents/skills/implement delete mode 120000 .agents/skills/implement-tasks-sequence rename {ai => .agents}/skills/implement-tasks-sequence/SKILL.md (100%) rename {ai => .agents}/skills/implement/SKILL.md (96%) delete mode 120000 .agents/skills/layout-debug rename {ai => .agents}/skills/layout-debug/SKILL.md (100%) delete mode 120000 .agents/skills/lint-format rename {ai => .agents}/skills/lint-format/SKILL.md (98%) rename {ai => .agents}/skills/lint-format/scripts/lint-format.sh (100%) delete mode 120000 .agents/skills/pr-review rename {ai => .agents}/skills/pr-review/SKILL.md (100%) delete mode 120000 .agents/skills/prd rename {ai => .agents}/skills/prd/SKILL.md (100%) delete mode 120000 .agents/skills/project-setup rename {ai => .agents}/skills/project-setup/SKILL.md (93%) delete mode 120000 .agents/skills/release-builds rename {ai => .agents}/skills/release-builds/SKILL.md (92%) rename {ai => .agents}/skills/release-builds/scripts/archive_ios_ipa.sh (94%) delete mode 120000 .agents/skills/release-prepare rename {ai => .agents}/skills/release-prepare/SKILL.md (100%) delete mode 120000 .agents/skills/review-pr-comments rename {ai => .agents}/skills/review-pr-comments/SKILL.md (100%) delete mode 120000 .agents/skills/secrets-bootstrap rename {ai => .agents}/skills/secrets-bootstrap/SKILL.md (100%) delete mode 120000 .agents/skills/start-job rename {ai => .agents}/skills/start-job/SKILL.md (100%) delete mode 120000 .agents/skills/tasks rename {ai => .agents}/skills/tasks/SKILL.md (100%) delete mode 120000 .agents/skills/techspec rename {ai => .agents}/skills/techspec/SKILL.md (100%) delete mode 120000 .agents/skills/upgrade rename {ai => .agents}/skills/upgrade/SKILL.md (100%) delete mode 120000 .agents/skills/widget-test rename {ai => .agents}/skills/widget-test/SKILL.md (100%) rename {ai => .agents}/validate_skills.py (92%) mode change 100644 => 100755 diff --git a/.agents/skills/build-verify b/.agents/skills/build-verify deleted file mode 120000 index 038789c..0000000 --- a/.agents/skills/build-verify +++ /dev/null @@ -1 +0,0 @@ -../../ai/skills/build-verify \ No newline at end of file diff --git a/ai/skills/build-verify/SKILL.md b/.agents/skills/build-verify/SKILL.md similarity index 100% rename from ai/skills/build-verify/SKILL.md rename to .agents/skills/build-verify/SKILL.md diff --git a/ai/skills/build-verify/scripts/verify.sh b/.agents/skills/build-verify/scripts/verify.sh similarity index 100% rename from ai/skills/build-verify/scripts/verify.sh rename to .agents/skills/build-verify/scripts/verify.sh diff --git a/.agents/skills/create-pr b/.agents/skills/create-pr deleted file mode 120000 index d71079b..0000000 --- a/.agents/skills/create-pr +++ /dev/null @@ -1 +0,0 @@ -../../ai/skills/create-pr \ No newline at end of file diff --git a/ai/skills/create-pr/SKILL.md b/.agents/skills/create-pr/SKILL.md similarity index 100% rename from ai/skills/create-pr/SKILL.md rename to .agents/skills/create-pr/SKILL.md diff --git a/.agents/skills/feature-data-flow b/.agents/skills/feature-data-flow deleted file mode 120000 index 3055f98..0000000 --- a/.agents/skills/feature-data-flow +++ /dev/null @@ -1 +0,0 @@ -../../ai/skills/feature-data-flow \ No newline at end of file diff --git a/ai/skills/feature-data-flow/SKILL.md b/.agents/skills/feature-data-flow/SKILL.md similarity index 100% rename from ai/skills/feature-data-flow/SKILL.md rename to .agents/skills/feature-data-flow/SKILL.md diff --git a/.agents/skills/feature-screen b/.agents/skills/feature-screen deleted file mode 120000 index 3df57fb..0000000 --- a/.agents/skills/feature-screen +++ /dev/null @@ -1 +0,0 @@ -../../ai/skills/feature-screen \ No newline at end of file diff --git a/ai/skills/feature-screen/SKILL.md b/.agents/skills/feature-screen/SKILL.md similarity index 100% rename from ai/skills/feature-screen/SKILL.md rename to .agents/skills/feature-screen/SKILL.md diff --git a/.agents/skills/implement b/.agents/skills/implement deleted file mode 120000 index 74bd3bf..0000000 --- a/.agents/skills/implement +++ /dev/null @@ -1 +0,0 @@ -../../ai/skills/implement \ No newline at end of file diff --git a/.agents/skills/implement-tasks-sequence b/.agents/skills/implement-tasks-sequence deleted file mode 120000 index 9b015d6..0000000 --- a/.agents/skills/implement-tasks-sequence +++ /dev/null @@ -1 +0,0 @@ -../../ai/skills/implement-tasks-sequence \ No newline at end of file diff --git a/ai/skills/implement-tasks-sequence/SKILL.md b/.agents/skills/implement-tasks-sequence/SKILL.md similarity index 100% rename from ai/skills/implement-tasks-sequence/SKILL.md rename to .agents/skills/implement-tasks-sequence/SKILL.md diff --git a/ai/skills/implement/SKILL.md b/.agents/skills/implement/SKILL.md similarity index 96% rename from ai/skills/implement/SKILL.md rename to .agents/skills/implement/SKILL.md index fa9e8f8..e95a3f3 100644 --- a/ai/skills/implement/SKILL.md +++ b/.agents/skills/implement/SKILL.md @@ -101,9 +101,9 @@ In standalone mode, verify before considering the task complete. Use the smallest sufficient verification: - Run `make gen` when annotations, routes, DTOs, localization, or asset inputs changed. -- Run `ai/skills/lint-format/scripts/lint-format.sh` for normal Dart/Flutter code changes. +- Run `.agents/skills/lint-format/scripts/lint-format.sh` for normal Dart/Flutter code changes. - Run `fvm flutter test` when behavior, state, use cases, widgets, or tests changed. -- Run `ai/skills/build-verify/scripts/verify.sh` for broad, cross-platform, dependency, startup, routing, generated-code, or PR-ready tasks. +- Run `.agents/skills/build-verify/scripts/verify.sh` for broad, cross-platform, dependency, startup, routing, generated-code, or PR-ready tasks. - Run `make integration_test` only when Patrol integration flows changed or the user asks for it. If any step fails, fix the underlying issue and re-run the failed verification. Do not disable checks, delete tests, add broad `// ignore:` comments, or hand-edit generated files to make verification pass. diff --git a/.agents/skills/layout-debug b/.agents/skills/layout-debug deleted file mode 120000 index 0ff119c..0000000 --- a/.agents/skills/layout-debug +++ /dev/null @@ -1 +0,0 @@ -../../ai/skills/layout-debug \ No newline at end of file diff --git a/ai/skills/layout-debug/SKILL.md b/.agents/skills/layout-debug/SKILL.md similarity index 100% rename from ai/skills/layout-debug/SKILL.md rename to .agents/skills/layout-debug/SKILL.md diff --git a/.agents/skills/lint-format b/.agents/skills/lint-format deleted file mode 120000 index edbc66f..0000000 --- a/.agents/skills/lint-format +++ /dev/null @@ -1 +0,0 @@ -../../ai/skills/lint-format \ No newline at end of file diff --git a/ai/skills/lint-format/SKILL.md b/.agents/skills/lint-format/SKILL.md similarity index 98% rename from ai/skills/lint-format/SKILL.md rename to .agents/skills/lint-format/SKILL.md index 810ee93..4d57e32 100644 --- a/ai/skills/lint-format/SKILL.md +++ b/.agents/skills/lint-format/SKILL.md @@ -24,7 +24,7 @@ Run this skill after completing Flutter/Dart code changes unless a broader verif Run the wrapper script from the repo root: ```bash -ai/skills/lint-format/scripts/lint-format.sh +.agents/skills/lint-format/scripts/lint-format.sh ``` The script auto-detects whether Flutter-relevant files changed. When relevant files changed, it formats changed Dart files and runs a project-wide analyzer pass. diff --git a/ai/skills/lint-format/scripts/lint-format.sh b/.agents/skills/lint-format/scripts/lint-format.sh similarity index 100% rename from ai/skills/lint-format/scripts/lint-format.sh rename to .agents/skills/lint-format/scripts/lint-format.sh diff --git a/.agents/skills/pr-review b/.agents/skills/pr-review deleted file mode 120000 index dcb8e77..0000000 --- a/.agents/skills/pr-review +++ /dev/null @@ -1 +0,0 @@ -../../ai/skills/pr-review \ No newline at end of file diff --git a/ai/skills/pr-review/SKILL.md b/.agents/skills/pr-review/SKILL.md similarity index 100% rename from ai/skills/pr-review/SKILL.md rename to .agents/skills/pr-review/SKILL.md diff --git a/.agents/skills/prd b/.agents/skills/prd deleted file mode 120000 index 97e3cf4..0000000 --- a/.agents/skills/prd +++ /dev/null @@ -1 +0,0 @@ -../../ai/skills/prd \ No newline at end of file diff --git a/ai/skills/prd/SKILL.md b/.agents/skills/prd/SKILL.md similarity index 100% rename from ai/skills/prd/SKILL.md rename to .agents/skills/prd/SKILL.md diff --git a/.agents/skills/project-setup b/.agents/skills/project-setup deleted file mode 120000 index 73b95d9..0000000 --- a/.agents/skills/project-setup +++ /dev/null @@ -1 +0,0 @@ -../../ai/skills/project-setup \ No newline at end of file diff --git a/ai/skills/project-setup/SKILL.md b/.agents/skills/project-setup/SKILL.md similarity index 93% rename from ai/skills/project-setup/SKILL.md rename to .agents/skills/project-setup/SKILL.md index 5074030..2aadd89 100644 --- a/ai/skills/project-setup/SKILL.md +++ b/.agents/skills/project-setup/SKILL.md @@ -54,20 +54,20 @@ Use this when setting up a new clone, preparing AI workflows, or debugging skill - Run `gh auth login --hostname github.com --git-protocol ssh --web`. - Run `gh auth status` and fix any invalid `GITHUB_TOKEN` / `GH_TOKEN` environment variables if they override the stored login. 3. Verify repo-local script permissions and syntax: - - `test -x ai/skills/build-verify/scripts/verify.sh` - - `test -x ai/skills/lint-format/scripts/lint-format.sh` - - `test -x ai/skills/release-builds/scripts/archive_ios_ipa.sh` - - `bash -n ai/skills/build-verify/scripts/verify.sh` - - `bash -n ai/skills/lint-format/scripts/lint-format.sh` - - `sh -n ai/skills/release-builds/scripts/archive_ios_ipa.sh` + - `test -x .agents/skills/build-verify/scripts/verify.sh` + - `test -x .agents/skills/lint-format/scripts/lint-format.sh` + - `test -x .agents/skills/release-builds/scripts/archive_ios_ipa.sh` + - `bash -n .agents/skills/build-verify/scripts/verify.sh` + - `bash -n .agents/skills/lint-format/scripts/lint-format.sh` + - `sh -n .agents/skills/release-builds/scripts/archive_ios_ipa.sh` 4. Verify Claude discovery wiring when Claude Code support is needed: - - every `ai/skills//SKILL.md` has a matching `.claude/skills/` symlink + - every `.agents/skills//SKILL.md` has a matching `.claude/skills/` symlink - every skill has a matching `.claude/commands/.md` - each symlink resolves to a `SKILL.md` 5. Run lightweight help checks: - - `ai/skills/build-verify/scripts/verify.sh --help` - - `ai/skills/lint-format/scripts/lint-format.sh --help` - - `ai/skills/release-builds/scripts/archive_ios_ipa.sh` should print usage and exit non-zero when no flavor is supplied. + - `.agents/skills/build-verify/scripts/verify.sh --help` + - `.agents/skills/lint-format/scripts/lint-format.sh --help` + - `.agents/skills/release-builds/scripts/archive_ios_ipa.sh` should print usage and exit non-zero when no flavor is supplied. ## Platform Cleanup Workflow Use this workflow to automate README First steps > Automated steps item 1. diff --git a/.agents/skills/release-builds b/.agents/skills/release-builds deleted file mode 120000 index 50332b4..0000000 --- a/.agents/skills/release-builds +++ /dev/null @@ -1 +0,0 @@ -../../ai/skills/release-builds \ No newline at end of file diff --git a/ai/skills/release-builds/SKILL.md b/.agents/skills/release-builds/SKILL.md similarity index 92% rename from ai/skills/release-builds/SKILL.md rename to .agents/skills/release-builds/SKILL.md index 0ab187e..df00585 100644 --- a/ai/skills/release-builds/SKILL.md +++ b/.agents/skills/release-builds/SKILL.md @@ -16,7 +16,7 @@ Use this skill only after the release PR has been merged. - `pubspec.yaml` - `makefile` - `.github/workflows/` -- `ai/skills/release-builds/scripts/archive_ios_ipa.sh` +- `.agents/skills/release-builds/scripts/archive_ios_ipa.sh` ## Goal This skill is for the post-merge release-build phase. @@ -64,13 +64,13 @@ Immediately after each IPA build, archive the IPA out of `build/ios/ipa/` and Fl Use: ```bash -ai/skills/release-builds/scripts/archive_ios_ipa.sh +.agents/skills/release-builds/scripts/archive_ios_ipa.sh ``` Examples: -- `ai/skills/release-builds/scripts/archive_ios_ipa.sh develop` -- `ai/skills/release-builds/scripts/archive_ios_ipa.sh staging` -- `ai/skills/release-builds/scripts/archive_ios_ipa.sh production` +- `.agents/skills/release-builds/scripts/archive_ios_ipa.sh develop` +- `.agents/skills/release-builds/scripts/archive_ios_ipa.sh staging` +- `.agents/skills/release-builds/scripts/archive_ios_ipa.sh production` The script copies the generated IPA into: diff --git a/ai/skills/release-builds/scripts/archive_ios_ipa.sh b/.agents/skills/release-builds/scripts/archive_ios_ipa.sh similarity index 94% rename from ai/skills/release-builds/scripts/archive_ios_ipa.sh rename to .agents/skills/release-builds/scripts/archive_ios_ipa.sh index e752a23..ed023d2 100755 --- a/ai/skills/release-builds/scripts/archive_ios_ipa.sh +++ b/.agents/skills/release-builds/scripts/archive_ios_ipa.sh @@ -3,7 +3,7 @@ set -eu if [ "$#" -ne 1 ]; then - echo "Usage: ai/skills/release-builds/scripts/archive_ios_ipa.sh " >&2 + echo "Usage: .agents/skills/release-builds/scripts/archive_ios_ipa.sh " >&2 exit 1 fi diff --git a/.agents/skills/release-prepare b/.agents/skills/release-prepare deleted file mode 120000 index 243af08..0000000 --- a/.agents/skills/release-prepare +++ /dev/null @@ -1 +0,0 @@ -../../ai/skills/release-prepare \ No newline at end of file diff --git a/ai/skills/release-prepare/SKILL.md b/.agents/skills/release-prepare/SKILL.md similarity index 100% rename from ai/skills/release-prepare/SKILL.md rename to .agents/skills/release-prepare/SKILL.md diff --git a/.agents/skills/review-pr-comments b/.agents/skills/review-pr-comments deleted file mode 120000 index f6b35ff..0000000 --- a/.agents/skills/review-pr-comments +++ /dev/null @@ -1 +0,0 @@ -../../ai/skills/review-pr-comments \ No newline at end of file diff --git a/ai/skills/review-pr-comments/SKILL.md b/.agents/skills/review-pr-comments/SKILL.md similarity index 100% rename from ai/skills/review-pr-comments/SKILL.md rename to .agents/skills/review-pr-comments/SKILL.md diff --git a/.agents/skills/secrets-bootstrap b/.agents/skills/secrets-bootstrap deleted file mode 120000 index fff4db6..0000000 --- a/.agents/skills/secrets-bootstrap +++ /dev/null @@ -1 +0,0 @@ -../../ai/skills/secrets-bootstrap \ No newline at end of file diff --git a/ai/skills/secrets-bootstrap/SKILL.md b/.agents/skills/secrets-bootstrap/SKILL.md similarity index 100% rename from ai/skills/secrets-bootstrap/SKILL.md rename to .agents/skills/secrets-bootstrap/SKILL.md diff --git a/.agents/skills/start-job b/.agents/skills/start-job deleted file mode 120000 index d9ea860..0000000 --- a/.agents/skills/start-job +++ /dev/null @@ -1 +0,0 @@ -../../ai/skills/start-job \ No newline at end of file diff --git a/ai/skills/start-job/SKILL.md b/.agents/skills/start-job/SKILL.md similarity index 100% rename from ai/skills/start-job/SKILL.md rename to .agents/skills/start-job/SKILL.md diff --git a/.agents/skills/tasks b/.agents/skills/tasks deleted file mode 120000 index c56e514..0000000 --- a/.agents/skills/tasks +++ /dev/null @@ -1 +0,0 @@ -../../ai/skills/tasks \ No newline at end of file diff --git a/ai/skills/tasks/SKILL.md b/.agents/skills/tasks/SKILL.md similarity index 100% rename from ai/skills/tasks/SKILL.md rename to .agents/skills/tasks/SKILL.md diff --git a/.agents/skills/techspec b/.agents/skills/techspec deleted file mode 120000 index 291e8e3..0000000 --- a/.agents/skills/techspec +++ /dev/null @@ -1 +0,0 @@ -../../ai/skills/techspec \ No newline at end of file diff --git a/ai/skills/techspec/SKILL.md b/.agents/skills/techspec/SKILL.md similarity index 100% rename from ai/skills/techspec/SKILL.md rename to .agents/skills/techspec/SKILL.md diff --git a/.agents/skills/upgrade b/.agents/skills/upgrade deleted file mode 120000 index 4bd522a..0000000 --- a/.agents/skills/upgrade +++ /dev/null @@ -1 +0,0 @@ -../../ai/skills/upgrade \ No newline at end of file diff --git a/ai/skills/upgrade/SKILL.md b/.agents/skills/upgrade/SKILL.md similarity index 100% rename from ai/skills/upgrade/SKILL.md rename to .agents/skills/upgrade/SKILL.md diff --git a/.agents/skills/widget-test b/.agents/skills/widget-test deleted file mode 120000 index efdc1d7..0000000 --- a/.agents/skills/widget-test +++ /dev/null @@ -1 +0,0 @@ -../../ai/skills/widget-test \ No newline at end of file diff --git a/ai/skills/widget-test/SKILL.md b/.agents/skills/widget-test/SKILL.md similarity index 100% rename from ai/skills/widget-test/SKILL.md rename to .agents/skills/widget-test/SKILL.md diff --git a/ai/validate_skills.py b/.agents/validate_skills.py old mode 100644 new mode 100755 similarity index 92% rename from ai/validate_skills.py rename to .agents/validate_skills.py index 0148231..dc2e91b --- a/ai/validate_skills.py +++ b/.agents/validate_skills.py @@ -1,5 +1,5 @@ #!/usr/bin/env python3 -"""Validate ai/skills/* against the Agent Skills spec (agentskills.io/specification) +"""Validate .agents/skills/* against the Agent Skills spec (agentskills.io/specification) and this repo's skill-exposure convention (see AGENTS.md "Creating a new skill"). Checks per skill: @@ -11,8 +11,8 @@ - unknown top-level frontmatter fields (spec fields + known Claude Code extensions are accepted; anything else is a warning) - SKILL.md body under 500 lines (spec recommendation; warning) - - exposure symlinks and slash command exist: - .claude/skills/, .agents/skills/, .claude/commands/.md + - Claude Code exposure exists: + .claude/skills/ symlink and .claude/commands/.md slash command Exits 1 on errors, 0 if only warnings. Requires PyYAML (pip install pyyaml). """ @@ -22,7 +22,7 @@ import sys REPO_ROOT = os.path.dirname(os.path.dirname(os.path.abspath(__file__))) -SKILLS_DIR = os.path.join(REPO_ROOT, "ai", "skills") +SKILLS_DIR = os.path.join(REPO_ROOT, ".agents", "skills") SPEC_FIELDS = {"name", "description", "license", "compatibility", "metadata", "allowed-tools"} CLAUDE_EXTENSIONS = {"model", "user-invocable", "disable-model-invocation"} @@ -88,7 +88,6 @@ def check_skill(skill_dir: str) -> tuple[list[str], list[str]]: for rel, kind in [ (os.path.join(".claude", "skills", dirname), "Claude Code symlink"), - (os.path.join(".agents", "skills", dirname), "interop symlink"), (os.path.join(".claude", "commands", f"{dirname}.md"), "slash command"), ]: path = os.path.join(REPO_ROOT, rel) diff --git a/.claude/CLAUDE.md b/.claude/CLAUDE.md index cda855e..fced3ee 100644 --- a/.claude/CLAUDE.md +++ b/.claude/CLAUDE.md @@ -1,18 +1,20 @@ @../AGENTS.md -Project-specific reusable AI workflows live in `../ai/skills/` and are surfaced -to Claude Code two ways: +Project-specific reusable AI workflows live in `../.agents/skills/` — the +standard cross-client Agent Skills location — and are surfaced to Claude Code +two ways: - **auto-discovery**: `./skills/` is a symlink with target - `../../ai/skills/` (resolved from `.claude/skills/`, this points - at `/ai/skills/`), so Claude reads the SKILL.md frontmatter + `../../.agents/skills/` (resolved from `.claude/skills/`, this points + at `/.agents/skills/`), so Claude reads the SKILL.md frontmatter and triggers them based on context. - **slash commands**: `./commands/.md` exposes each skill as an explicit command. Current commands mirror the skills listed in `AGENTS.md`, including `/project-setup`, `/feature-screen`, `/feature-data-flow`, `/prd`, `/techspec`, `/tasks`, `/implement`, `/implement-tasks-sequence`, - `/start-job`, `/build-verify`, `/lint-format`, `/create-pr`, - `/review-pr-comments`, `/upgrade`, `/release-prepare`, `/release-builds`, - `/secrets-bootstrap`, and `/pr-review`. + `/start-job`, `/build-verify`, `/lint-format`, `/widget-test`, + `/layout-debug`, `/create-pr`, `/review-pr-comments`, `/upgrade`, + `/release-prepare`, `/release-builds`, `/secrets-bootstrap`, and + `/pr-review`. See the "Reusable Workflows" section of `AGENTS.md` for the canonical list of -skills and the four-step convention for adding a new one. +skills and the five-step convention for adding a new one. diff --git a/.claude/skills/build-verify b/.claude/skills/build-verify index 038789c..48131cb 120000 --- a/.claude/skills/build-verify +++ b/.claude/skills/build-verify @@ -1 +1 @@ -../../ai/skills/build-verify \ No newline at end of file +../../.agents/skills/build-verify \ No newline at end of file diff --git a/.claude/skills/create-pr b/.claude/skills/create-pr index d71079b..d5b42b7 120000 --- a/.claude/skills/create-pr +++ b/.claude/skills/create-pr @@ -1 +1 @@ -../../ai/skills/create-pr \ No newline at end of file +../../.agents/skills/create-pr \ No newline at end of file diff --git a/.claude/skills/feature-data-flow b/.claude/skills/feature-data-flow index 3055f98..4c99c50 120000 --- a/.claude/skills/feature-data-flow +++ b/.claude/skills/feature-data-flow @@ -1 +1 @@ -../../ai/skills/feature-data-flow \ No newline at end of file +../../.agents/skills/feature-data-flow \ No newline at end of file diff --git a/.claude/skills/feature-screen b/.claude/skills/feature-screen index 3df57fb..db3a86b 120000 --- a/.claude/skills/feature-screen +++ b/.claude/skills/feature-screen @@ -1 +1 @@ -../../ai/skills/feature-screen \ No newline at end of file +../../.agents/skills/feature-screen \ No newline at end of file diff --git a/.claude/skills/implement b/.claude/skills/implement index 74bd3bf..e429be8 120000 --- a/.claude/skills/implement +++ b/.claude/skills/implement @@ -1 +1 @@ -../../ai/skills/implement \ No newline at end of file +../../.agents/skills/implement \ No newline at end of file diff --git a/.claude/skills/implement-tasks-sequence b/.claude/skills/implement-tasks-sequence index 9b015d6..42b9e43 120000 --- a/.claude/skills/implement-tasks-sequence +++ b/.claude/skills/implement-tasks-sequence @@ -1 +1 @@ -../../ai/skills/implement-tasks-sequence \ No newline at end of file +../../.agents/skills/implement-tasks-sequence \ No newline at end of file diff --git a/.claude/skills/layout-debug b/.claude/skills/layout-debug index 0ff119c..a8cfcb4 120000 --- a/.claude/skills/layout-debug +++ b/.claude/skills/layout-debug @@ -1 +1 @@ -../../ai/skills/layout-debug \ No newline at end of file +../../.agents/skills/layout-debug \ No newline at end of file diff --git a/.claude/skills/lint-format b/.claude/skills/lint-format index edbc66f..200a69a 120000 --- a/.claude/skills/lint-format +++ b/.claude/skills/lint-format @@ -1 +1 @@ -../../ai/skills/lint-format \ No newline at end of file +../../.agents/skills/lint-format \ No newline at end of file diff --git a/.claude/skills/pr-review b/.claude/skills/pr-review index dcb8e77..321fc63 120000 --- a/.claude/skills/pr-review +++ b/.claude/skills/pr-review @@ -1 +1 @@ -../../ai/skills/pr-review \ No newline at end of file +../../.agents/skills/pr-review \ No newline at end of file diff --git a/.claude/skills/prd b/.claude/skills/prd index 97e3cf4..51caf15 120000 --- a/.claude/skills/prd +++ b/.claude/skills/prd @@ -1 +1 @@ -../../ai/skills/prd \ No newline at end of file +../../.agents/skills/prd \ No newline at end of file diff --git a/.claude/skills/project-setup b/.claude/skills/project-setup index 73b95d9..bee4ce4 120000 --- a/.claude/skills/project-setup +++ b/.claude/skills/project-setup @@ -1 +1 @@ -../../ai/skills/project-setup \ No newline at end of file +../../.agents/skills/project-setup \ No newline at end of file diff --git a/.claude/skills/release-builds b/.claude/skills/release-builds index 50332b4..124d2fe 120000 --- a/.claude/skills/release-builds +++ b/.claude/skills/release-builds @@ -1 +1 @@ -../../ai/skills/release-builds \ No newline at end of file +../../.agents/skills/release-builds \ No newline at end of file diff --git a/.claude/skills/release-prepare b/.claude/skills/release-prepare index 243af08..d410e30 120000 --- a/.claude/skills/release-prepare +++ b/.claude/skills/release-prepare @@ -1 +1 @@ -../../ai/skills/release-prepare \ No newline at end of file +../../.agents/skills/release-prepare \ No newline at end of file diff --git a/.claude/skills/review-pr-comments b/.claude/skills/review-pr-comments index f6b35ff..7681e8a 120000 --- a/.claude/skills/review-pr-comments +++ b/.claude/skills/review-pr-comments @@ -1 +1 @@ -../../ai/skills/review-pr-comments \ No newline at end of file +../../.agents/skills/review-pr-comments \ No newline at end of file diff --git a/.claude/skills/secrets-bootstrap b/.claude/skills/secrets-bootstrap index fff4db6..ac86810 120000 --- a/.claude/skills/secrets-bootstrap +++ b/.claude/skills/secrets-bootstrap @@ -1 +1 @@ -../../ai/skills/secrets-bootstrap \ No newline at end of file +../../.agents/skills/secrets-bootstrap \ No newline at end of file diff --git a/.claude/skills/start-job b/.claude/skills/start-job index d9ea860..ed1e0e3 120000 --- a/.claude/skills/start-job +++ b/.claude/skills/start-job @@ -1 +1 @@ -../../ai/skills/start-job \ No newline at end of file +../../.agents/skills/start-job \ No newline at end of file diff --git a/.claude/skills/tasks b/.claude/skills/tasks index c56e514..ec1609b 120000 --- a/.claude/skills/tasks +++ b/.claude/skills/tasks @@ -1 +1 @@ -../../ai/skills/tasks \ No newline at end of file +../../.agents/skills/tasks \ No newline at end of file diff --git a/.claude/skills/techspec b/.claude/skills/techspec index 291e8e3..8b0ad23 120000 --- a/.claude/skills/techspec +++ b/.claude/skills/techspec @@ -1 +1 @@ -../../ai/skills/techspec \ No newline at end of file +../../.agents/skills/techspec \ No newline at end of file diff --git a/.claude/skills/upgrade b/.claude/skills/upgrade index 4bd522a..a7972b2 120000 --- a/.claude/skills/upgrade +++ b/.claude/skills/upgrade @@ -1 +1 @@ -../../ai/skills/upgrade \ No newline at end of file +../../.agents/skills/upgrade \ No newline at end of file diff --git a/.claude/skills/widget-test b/.claude/skills/widget-test index efdc1d7..c6706f8 120000 --- a/.claude/skills/widget-test +++ b/.claude/skills/widget-test @@ -1 +1 @@ -../../ai/skills/widget-test \ No newline at end of file +../../.agents/skills/widget-test \ No newline at end of file diff --git a/AGENTS.md b/AGENTS.md index 9d6671e..bff4c9f 100644 --- a/AGENTS.md +++ b/AGENTS.md @@ -43,9 +43,10 @@ Use this file as the entrypoint for automated work in this repository. - If you learn a stable, repo-specific convention while working, update `docs/PROJECT_OVERVIEW.md` or `docs/PROJECT_GUIDELINES.md` instead of adding duplicate instructions elsewhere. ## Reusable Workflows -Repeatable procedures live as skills under `ai/skills//SKILL.md`. Each -skill has YAML frontmatter (`name:`, `description:`) so it can be auto-discovered -by AI tools that support skills. +Repeatable procedures live as skills under `.agents/skills//SKILL.md` — +the cross-client location defined by the [Agent Skills](https://agentskills.io) +format. Each skill has YAML frontmatter (`name:`, `description:`) so it can be +auto-discovered by AI tools that support skills. Existing skills: - `project-setup` — customize a new app from this template (identity, platforms, icons, splash, Firebase/secrets, validation) @@ -70,23 +71,21 @@ Existing skills: - `techspec` — translate a PRD into an implementation-ready Flutter tech spec at `.claude/tasks//techspec.md`, grounded in the Riverpod / Freezed / AutoRoute / Dio / Firebase stack ### How AI tools find these skills -- **Codex** reads this `AGENTS.md` and the referenced `ai/skills//SKILL.md` - files. When delegating, mention the workflow by name, e.g. *"use the - feature-data-flow workflow"*. +- **Spec-compliant agents** scan `.agents/skills/` directly — it is the + standard cross-client skills location, so no extra wiring is needed. +- **Codex** reads this `AGENTS.md` and the referenced + `.agents/skills//SKILL.md` files. When delegating, mention the workflow + by name, e.g. *"use the feature-data-flow workflow"*. - **Claude Code** auto-discovers skills through `.claude/skills/` symlinks - that point at `ai/skills//`. Each skill is also exposed as a slash + that point at `.agents/skills//`. Each skill is also exposed as a slash command at `.claude/commands/.md`, so `/feature-screen`, `/pr-review`, `/release-prepare`, etc. work as explicit invocations. -- **Other spec-compliant agents** auto-discover skills through - `.agents/skills/` symlinks — the cross-client interop location defined - by the [Agent Skills](https://agentskills.io) format that this repo's skills - follow. ### Creating a new skill -When adding a new repeatable workflow, complete all six steps so Codex, Claude, +When adding a new repeatable workflow, complete all five steps so Codex, Claude, and other skills-compliant agents can use it: -1. **Author the skill.** Create `ai/skills//SKILL.md` with YAML frontmatter - and the workflow body. Required fields: +1. **Author the skill.** Create `.agents/skills//SKILL.md` with YAML + frontmatter and the workflow body. Required fields: - `name:` matching the folder - `description:` explaining when to use the skill - `allowed-tools:` listing the tools the skill needs (for example @@ -99,16 +98,13 @@ and other skills-compliant agents can use it: `start-job` and `create-pr` 2. **Mention it for Codex.** Add the skill to the "Existing skills" list above. 3. **Expose it to Claude Code (auto-discovery).** Add a symlink: - `ln -s ../../ai/skills/ .claude/skills/` -4. **Expose it to other agents (interop).** Add a symlink: - `ln -s ../../ai/skills/ .agents/skills/` -5. **Add a slash command.** Create `.claude/commands/.md` using one of the + `ln -s ../../.agents/skills/ .claude/skills/` +4. **Add a slash command.** Create `.claude/commands/.md` using one of the existing commands as a template — a short frontmatter (`description`, `argument-hint`) and a one-line body that invokes the skill, followed by `$ARGUMENTS`. - -6. **Validate.** Run `python3 ai/validate_skills.py` and fix any reported +5. **Validate.** Run `python3 .agents/validate_skills.py` and fix any reported issues. It checks Agent Skills spec compliance (strict YAML frontmatter, - name/description rules) and that all exposure symlinks and the slash - command from steps 3-5 exist. Also run it after editing any existing - SKILL.md frontmatter. + name/description rules) and that the Claude Code symlink and slash command + from steps 3-4 exist. Also run it after editing any existing SKILL.md + frontmatter. diff --git a/README.md b/README.md index f6980f5..f936983 100644 --- a/README.md +++ b/README.md @@ -97,7 +97,7 @@ These are our four core values: ## Automated steps -The following steps can be completed or coordinated by `ai/skills/project-setup`. +The following steps can be completed or coordinated by `.agents/skills/project-setup`. 1. - [ ] Remove any unused platforms (Android, iOS, web, Windows, Linux (+snap), macOS) - Remove them from the folder structure of the template. @@ -503,7 +503,7 @@ Canonical project files: - `docs/PROJECT_GUIDELINES.md` contains implementation conventions and workflow defaults. - `.claude/CLAUDE.md` points Claude users at the shared project instructions. -Reusable workflow guides live under `ai/skills/`: +Reusable workflow guides live under `.agents/skills/`: - `project-setup` for app identity, icons, splash, platform cleanup, Firebase/secrets decisions, and initial validation. - `feature-screen` for route and UI scaffolding. - `feature-data-flow` for full backend-backed features with DTOs, entities, use cases, and state wiring. @@ -521,15 +521,15 @@ AI workflow prerequisites: - Install GitHub CLI for PR workflows (`brew install gh` on macOS) and authenticate with `gh auth login --hostname github.com --git-protocol ssh --web`. - Verify GitHub CLI with `gh auth status`. If an invalid `GITHUB_TOKEN` or `GH_TOKEN` is set in your environment, clear or replace it so the stored login can be used. - Repo-local scripts should be executable and syntax-check clean: - - `ai/skills/build-verify/scripts/verify.sh --help` - - `ai/skills/lint-format/scripts/lint-format.sh --help` - - `bash -n ai/skills/build-verify/scripts/verify.sh` - - `bash -n ai/skills/lint-format/scripts/lint-format.sh` - - `sh -n ai/skills/release-builds/scripts/archive_ios_ipa.sh` + - `.agents/skills/build-verify/scripts/verify.sh --help` + - `.agents/skills/lint-format/scripts/lint-format.sh --help` + - `bash -n .agents/skills/build-verify/scripts/verify.sh` + - `bash -n .agents/skills/lint-format/scripts/lint-format.sh` + - `sh -n .agents/skills/release-builds/scripts/archive_ios_ipa.sh` Recommended usage: - When working with an AI agent, explicitly mention the workflow you want to use, for example `Use the feature-data-flow skill`. -- Keep long-term project rules in `AGENTS.md` and the docs, and keep repeatable procedures in `ai/skills/`. +- Keep long-term project rules in `AGENTS.md` and the docs, and keep repeatable procedures in `.agents/skills/`. - Treat the repo-local workflow guides as project-specific assets that should evolve with the template. diff --git a/docs/PROJECT_GUIDELINES.md b/docs/PROJECT_GUIDELINES.md index 54d66f4..d03e0ce 100644 --- a/docs/PROJECT_GUIDELINES.md +++ b/docs/PROJECT_GUIDELINES.md @@ -111,11 +111,11 @@ Not every feature needs every file. Simple screens in the template only use `*_p - `fvm flutter test` ## AI Workflow Tooling -- Repo-local skills live under `ai/skills/` and Claude Code symlinks live under `.claude/skills/`. +- Repo-local skills live under `.agents/skills/` and Claude Code symlinks live under `.claude/skills/`. - Skill scripts should be executable and syntax-check clean before relying on them: - - `bash -n ai/skills/build-verify/scripts/verify.sh` - - `bash -n ai/skills/lint-format/scripts/lint-format.sh` - - `sh -n ai/skills/release-builds/scripts/archive_ios_ipa.sh` + - `bash -n .agents/skills/build-verify/scripts/verify.sh` + - `bash -n .agents/skills/lint-format/scripts/lint-format.sh` + - `sh -n .agents/skills/release-builds/scripts/archive_ios_ipa.sh` - PR-related skills use GitHub CLI. Install it locally and authenticate with `gh auth login`; verify with `gh auth status`. - If `gh auth status` reports an invalid `GITHUB_TOKEN` or `GH_TOKEN`, clear or replace that environment variable so the stored GitHub CLI login can be used. From 3909209695bf3b90cff57b6238a2f61205e36ef0 Mon Sep 17 00:00:00 2001 From: Michal Urbanek Date: Thu, 11 Jun 2026 08:37:20 +0000 Subject: [PATCH 5/8] refactor: move templates to .agents and remove the ai folder Move ai/templates/ to .agents/templates/ so all agent-facing material lives under .agents/. Retarget .claude/templates symlinks and update references in AGENTS.md and the prd, tasks, and techspec skills. --- .agents/skills/prd/SKILL.md | 6 +++--- .agents/skills/tasks/SKILL.md | 6 +++--- .agents/skills/techspec/SKILL.md | 2 +- {ai => .agents}/templates/prd.md | 0 {ai => .agents}/templates/task-list.md | 0 {ai => .agents}/templates/task.md | 0 {ai => .agents}/templates/techspec.md | 0 .claude/templates/prd.md | 2 +- .claude/templates/task-list.md | 2 +- .claude/templates/task.md | 2 +- .claude/templates/techspec.md | 2 +- AGENTS.md | 2 +- 12 files changed, 12 insertions(+), 12 deletions(-) rename {ai => .agents}/templates/prd.md (100%) rename {ai => .agents}/templates/task-list.md (100%) rename {ai => .agents}/templates/task.md (100%) rename {ai => .agents}/templates/techspec.md (100%) diff --git a/.agents/skills/prd/SKILL.md b/.agents/skills/prd/SKILL.md index 1d0eeef..942e3c6 100644 --- a/.agents/skills/prd/SKILL.md +++ b/.agents/skills/prd/SKILL.md @@ -21,14 +21,14 @@ You are a PRD creation specialist focused on producing clear, actionable product 4. Generate a PRD using the standardized template ## Template Reference -- Template: `ai/templates/prd.md` (also reachable as `.claude/templates/prd.md`) +- Template: `.agents/templates/prd.md` (also reachable as `.claude/templates/prd.md`) - Output: `.claude/tasks/[feature-name]/prd.md` ## Read First - `AGENTS.md` - `docs/PROJECT_OVERVIEW.md` - `docs/PROJECT_GUIDELINES.md` -- `ai/templates/prd.md` +- `.agents/templates/prd.md` - any user-provided brief, ticket, design, API notes, or KMP/source-platform reference material ## Scope Boundary @@ -73,7 +73,7 @@ Get explicit confirmation before drafting. ### Step 3: Draft the PRD (Mandatory) -Read the template at `ai/templates/prd.md` and use it to draft the PRD. +Read the template at `.agents/templates/prd.md` and use it to draft the PRD. - Focus on **WHAT** and **WHY**, not implementation details. - Keep requirements testable and unambiguous. - Reference domain entities from existing project docs, user input, or migration material where relevant. diff --git a/.agents/skills/tasks/SKILL.md b/.agents/skills/tasks/SKILL.md index 1512bcb..c40b0ee 100644 --- a/.agents/skills/tasks/SKILL.md +++ b/.agents/skills/tasks/SKILL.md @@ -41,7 +41,7 @@ Read both documents and identify: ### Step 2: Generate Task Structure -Order tasks following this Flutter-stack progression (mirrors the `ai/templates/task-list.md` +Order tasks following this Flutter-stack progression (mirrors the `.agents/templates/task-list.md` phases): 1. **Foundation (data layer)** — DTOs in `lib/common/data/dto/` (`@freezed` with @@ -67,13 +67,13 @@ Keep the total number of tasks reasonable — prefer fewer, well-scoped tasks ov ### Step 3: Create Task Summary -Use the template at `ai/templates/task-list.md` (also reachable as +Use the template at `.agents/templates/task-list.md` (also reachable as `.claude/templates/task-list.md` via symlink) to generate: `.claude/tasks/[feature-name]/tasks.md` ### Step 4: Generate Individual Task Files -Use the template at `ai/templates/task.md` (also reachable as `.claude/templates/task.md` +Use the template at `.agents/templates/task.md` (also reachable as `.claude/templates/task.md` via symlink) to create: `.claude/tasks/[feature-name]/[num]_task.md` diff --git a/.agents/skills/techspec/SKILL.md b/.agents/skills/techspec/SKILL.md index 12c92e1..b083466 100644 --- a/.agents/skills/techspec/SKILL.md +++ b/.agents/skills/techspec/SKILL.md @@ -74,7 +74,7 @@ Do not proceed until clarifications are resolved. ### Step 4: Generate Tech Spec -Read the template at `ai/templates/techspec.md` (also reachable at +Read the template at `.agents/templates/techspec.md` (also reachable at `.claude/templates/techspec.md` via symlink) and draft the spec. - Reference concrete files and modules from the codebase diff --git a/ai/templates/prd.md b/.agents/templates/prd.md similarity index 100% rename from ai/templates/prd.md rename to .agents/templates/prd.md diff --git a/ai/templates/task-list.md b/.agents/templates/task-list.md similarity index 100% rename from ai/templates/task-list.md rename to .agents/templates/task-list.md diff --git a/ai/templates/task.md b/.agents/templates/task.md similarity index 100% rename from ai/templates/task.md rename to .agents/templates/task.md diff --git a/ai/templates/techspec.md b/.agents/templates/techspec.md similarity index 100% rename from ai/templates/techspec.md rename to .agents/templates/techspec.md diff --git a/.claude/templates/prd.md b/.claude/templates/prd.md index f1808a0..db4f43f 120000 --- a/.claude/templates/prd.md +++ b/.claude/templates/prd.md @@ -1 +1 @@ -../../ai/templates/prd.md \ No newline at end of file +../../.agents/templates/prd.md \ No newline at end of file diff --git a/.claude/templates/task-list.md b/.claude/templates/task-list.md index 0333e67..39c6669 120000 --- a/.claude/templates/task-list.md +++ b/.claude/templates/task-list.md @@ -1 +1 @@ -../../ai/templates/task-list.md \ No newline at end of file +../../.agents/templates/task-list.md \ No newline at end of file diff --git a/.claude/templates/task.md b/.claude/templates/task.md index 17961ee..b724b87 120000 --- a/.claude/templates/task.md +++ b/.claude/templates/task.md @@ -1 +1 @@ -../../ai/templates/task.md \ No newline at end of file +../../.agents/templates/task.md \ No newline at end of file diff --git a/.claude/templates/techspec.md b/.claude/templates/techspec.md index 44313c5..bb0b2ee 120000 --- a/.claude/templates/techspec.md +++ b/.claude/templates/techspec.md @@ -1 +1 @@ -../../ai/templates/techspec.md \ No newline at end of file +../../.agents/templates/techspec.md \ No newline at end of file diff --git a/AGENTS.md b/AGENTS.md index bff4c9f..c8f7f2c 100644 --- a/AGENTS.md +++ b/AGENTS.md @@ -65,7 +65,7 @@ Existing skills: - `build-verify` — full build/test/analyze/format pass (codegen + analyze + test, then iOS + Android builds in parallel, then `dart format`); auto-scopes to the diff and leaves the working tree dirty for review - `start-job` — run the post-spec implementation pipeline (`tasks` → `implement-tasks-sequence` → `build-verify` → `pr-review`) - `prd` — create a Flutter feature Product Requirements Document under `.claude/tasks//prd.md` -- `tasks` — break a PRD + tech spec into discrete, dependency-ordered Flutter implementation tasks under `.claude/tasks//` using `ai/templates/task.md` and `ai/templates/task-list.md` +- `tasks` — break a PRD + tech spec into discrete, dependency-ordered Flutter implementation tasks under `.claude/tasks//` using `.agents/templates/task.md` and `.agents/templates/task-list.md` - `implement` — implement one generated Flutter task using the repo architecture and verification rules - `implement-tasks-sequence` — execute generated task files in dependency order before final verification - `techspec` — translate a PRD into an implementation-ready Flutter tech spec at `.claude/tasks//techspec.md`, grounded in the Riverpod / Freezed / AutoRoute / Dio / Firebase stack From 10e47d4ff22c55d7094cd8a898d46668af4ab8ed Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?Michal=20Urb=C3=A1nek?= Date: Thu, 11 Jun 2026 10:45:49 +0200 Subject: [PATCH 6/8] fix: make skill validator self-contained --- .agents/validate_skills.py | 53 +++++++++++++++++++++++++++++++++----- 1 file changed, 46 insertions(+), 7 deletions(-) diff --git a/.agents/validate_skills.py b/.agents/validate_skills.py index dc2e91b..dcef295 100755 --- a/.agents/validate_skills.py +++ b/.agents/validate_skills.py @@ -14,7 +14,7 @@ - Claude Code exposure exists: .claude/skills/ symlink and .claude/commands/.md slash command -Exits 1 on errors, 0 if only warnings. Requires PyYAML (pip install pyyaml). +Exits 1 on errors, 0 if only warnings. """ import os @@ -32,8 +32,49 @@ try: import yaml except ImportError: - print("error: PyYAML is required: pip install pyyaml") - sys.exit(1) + yaml = None + + +def parse_frontmatter(text: str) -> dict[str, object]: + if yaml is not None: + fm = yaml.safe_load(text) + if not isinstance(fm, dict): + raise ValueError("frontmatter is not a YAML mapping") + return fm + + data: dict[str, object] = {} + lines = text.splitlines() + index = 0 + while index < len(lines): + line = lines[index] + index += 1 + if not line.strip(): + continue + if line.startswith((" ", "\t")) or ":" not in line: + raise ValueError("frontmatter uses YAML syntax that requires PyYAML") + + key, value = line.split(":", 1) + key = key.strip() + value = value.strip() + if not key: + raise ValueError("frontmatter contains an empty key") + + if value in {">", "|"}: + block_lines: list[str] = [] + while index < len(lines) and (lines[index].startswith((" ", "\t")) or not lines[index].strip()): + block_lines.append(lines[index].strip()) + index += 1 + data[key] = "\n".join(block_lines).strip() if value == "|" else " ".join(block_lines).strip() + continue + + if value.lower() == "true": + data[key] = True + elif value.lower() == "false": + data[key] = False + else: + data[key] = value.strip("\"'") + + return data def check_skill(skill_dir: str) -> tuple[list[str], list[str]]: @@ -51,13 +92,11 @@ def check_skill(skill_dir: str) -> tuple[list[str], list[str]]: return ["SKILL.md has no YAML frontmatter block"], warnings try: - fm = yaml.safe_load(match.group(1)) - except yaml.YAMLError as exc: + fm = parse_frontmatter(match.group(1)) + except Exception as exc: msg = str(exc).splitlines()[0] return [f"frontmatter is not valid YAML ({msg}) — " "quote values containing colons or use a '>' block scalar"], warnings - if not isinstance(fm, dict): - return ["frontmatter is not a YAML mapping"], warnings name = fm.get("name") if not name: From 0c98919a25b1b8acf43ecbcd5afef451096c429c Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?Michal=20Urb=C3=A1nek?= Date: Thu, 11 Jun 2026 12:55:39 +0200 Subject: [PATCH 7/8] fix: validate skill allowed tools syntax --- .agents/skills/build-verify/SKILL.md | 2 +- .agents/skills/create-pr/SKILL.md | 2 +- .agents/skills/feature-data-flow/SKILL.md | 2 +- .agents/skills/feature-screen/SKILL.md | 2 +- .agents/skills/implement-tasks-sequence/SKILL.md | 2 +- .agents/skills/implement/SKILL.md | 2 +- .agents/skills/layout-debug/SKILL.md | 2 +- .agents/skills/lint-format/SKILL.md | 2 +- .agents/skills/pr-review/SKILL.md | 2 +- .agents/skills/prd/SKILL.md | 2 +- .agents/skills/project-setup/SKILL.md | 2 +- .agents/skills/release-builds/SKILL.md | 2 +- .agents/skills/release-prepare/SKILL.md | 2 +- .agents/skills/review-pr-comments/SKILL.md | 2 +- .agents/skills/secrets-bootstrap/SKILL.md | 2 +- .agents/skills/start-job/SKILL.md | 2 +- .agents/skills/tasks/SKILL.md | 2 +- .agents/skills/techspec/SKILL.md | 2 +- .agents/skills/upgrade/SKILL.md | 2 +- .agents/skills/widget-test/SKILL.md | 2 +- .agents/validate_skills.py | 16 ++++++++++++++++ AGENTS.md | 2 +- 22 files changed, 37 insertions(+), 21 deletions(-) diff --git a/.agents/skills/build-verify/SKILL.md b/.agents/skills/build-verify/SKILL.md index efddc6f..bde248d 100644 --- a/.agents/skills/build-verify/SKILL.md +++ b/.agents/skills/build-verify/SKILL.md @@ -7,7 +7,7 @@ description: > Used at the end of the prd → techspec → tasks → implement-tasks-sequence flow before `pr-review`, and can also be invoked manually when the user says "verify build", "run full verification", or "check everything". -allowed-tools: Bash, Read, Grep, Glob, Edit, Skill +allowed-tools: Bash Read Grep Glob Edit Skill model: claude-sonnet-4-6 --- diff --git a/.agents/skills/create-pr/SKILL.md b/.agents/skills/create-pr/SKILL.md index 88c0619..4464a21 100644 --- a/.agents/skills/create-pr/SKILL.md +++ b/.agents/skills/create-pr/SKILL.md @@ -6,7 +6,7 @@ description: > approved, pushes, and opens or updates the PR. Supports stacked PRs by asking for the base branch when detection is ambiguous. Use when the user says "create PR", "open PR", "push PR", or wants to submit their work for review. -allowed-tools: Bash, Read, Write, Grep, Glob, Skill, Agent +allowed-tools: Bash Read Write Grep Glob Skill Agent user-invocable: true model: claude-sonnet-4-6 --- diff --git a/.agents/skills/feature-data-flow/SKILL.md b/.agents/skills/feature-data-flow/SKILL.md index 93c041c..f87b133 100644 --- a/.agents/skills/feature-data-flow/SKILL.md +++ b/.agents/skills/feature-data-flow/SKILL.md @@ -4,7 +4,7 @@ description: > Build a full feature in this Flutter repository that includes backend or storage data flow: read API schema, create DTOs, map DTOs to entities, add Riverpod use cases, connect feature state, and render UI data. Use when a task goes beyond a screen and needs real data integration. -allowed-tools: Bash, Read, Grep, Glob, Edit, Write +allowed-tools: Bash Read Grep Glob Edit Write model: claude-sonnet-4-6 --- diff --git a/.agents/skills/feature-screen/SKILL.md b/.agents/skills/feature-screen/SKILL.md index ddb47a3..1432e69 100644 --- a/.agents/skills/feature-screen/SKILL.md +++ b/.agents/skills/feature-screen/SKILL.md @@ -1,7 +1,7 @@ --- name: feature-screen description: Create a new Flutter screen in this repository using the existing feature structure, AutoRoute setup, Riverpod state pattern, and code generation workflow. Use when adding a new page, route, stateful screen, or feature folder in this template. -allowed-tools: Bash, Read, Grep, Glob, Edit, Write +allowed-tools: Bash Read Grep Glob Edit Write model: claude-sonnet-4-6 --- diff --git a/.agents/skills/implement-tasks-sequence/SKILL.md b/.agents/skills/implement-tasks-sequence/SKILL.md index c1670ab..228991a 100644 --- a/.agents/skills/implement-tasks-sequence/SKILL.md +++ b/.agents/skills/implement-tasks-sequence/SKILL.md @@ -7,7 +7,7 @@ description: > which runs `build-verify` and `pr-review uncommitted` afterwards). Use when the user says "implement all tasks", "run the task sequence", "implement the feature", or wants to execute multiple tasks from a task list end-to-end. -allowed-tools: Bash, Read, Grep, Glob, Edit, Write, Agent +allowed-tools: Bash Read Grep Glob Edit Write Agent model: claude-sonnet-4-6 --- diff --git a/.agents/skills/implement/SKILL.md b/.agents/skills/implement/SKILL.md index e95a3f3..0a917fe 100644 --- a/.agents/skills/implement/SKILL.md +++ b/.agents/skills/implement/SKILL.md @@ -8,7 +8,7 @@ description: > start-job/build-verify. Use when the user says "implement task X", "work on task X", or wants to execute a specific task from the task list. -allowed-tools: Bash, Read, Grep, Glob, Edit, Write, Agent +allowed-tools: Bash Read Grep Glob Edit Write Agent model: claude-sonnet-4-6 --- diff --git a/.agents/skills/layout-debug/SKILL.md b/.agents/skills/layout-debug/SKILL.md index 3c11578..4eed4d2 100644 --- a/.agents/skills/layout-debug/SKILL.md +++ b/.agents/skills/layout-debug/SKILL.md @@ -6,7 +6,7 @@ description: > theme, localization, and shared widget patterns. Use when UI overflows, text clips, widgets disappear, layouts fail on mobile/tablet/desktop, or a feature needs responsive behavior. -allowed-tools: Bash, Read, Grep, Glob, Edit, Write +allowed-tools: Bash Read Grep Glob Edit Write model: claude-sonnet-4-6 --- diff --git a/.agents/skills/lint-format/SKILL.md b/.agents/skills/lint-format/SKILL.md index 4d57e32..28b85f5 100644 --- a/.agents/skills/lint-format/SKILL.md +++ b/.agents/skills/lint-format/SKILL.md @@ -4,7 +4,7 @@ description: > Run Flutter/Dart formatting and static analysis for this repository. Use after completing Dart, Flutter, generated-source-input, or project configuration changes; when the user asks to lint, format, analyze, or check code style; or when preparing code for a pull request. -allowed-tools: Bash, Read, Grep, Glob +allowed-tools: Bash Read Grep Glob model: claude-sonnet-4-6 --- diff --git a/.agents/skills/pr-review/SKILL.md b/.agents/skills/pr-review/SKILL.md index fb0e47b..ad60a51 100644 --- a/.agents/skills/pr-review/SKILL.md +++ b/.agents/skills/pr-review/SKILL.md @@ -1,7 +1,7 @@ --- name: pr-review description: Review pull requests, branch diffs, and uncommitted changes in this Flutter repository with a bug-finding mindset. Use when asked to review changes, review a PR, audit a diff, check standards, check compliance, or look for regressions, missing tests, release risks, or architecture mismatches. -allowed-tools: Agent, Bash, Read, Grep, Glob, Edit +allowed-tools: Agent Bash Read Grep Glob Edit model: claude-sonnet-4-6 --- diff --git a/.agents/skills/prd/SKILL.md b/.agents/skills/prd/SKILL.md index 942e3c6..7ab7633 100644 --- a/.agents/skills/prd/SKILL.md +++ b/.agents/skills/prd/SKILL.md @@ -6,7 +6,7 @@ description: > `.claude/tasks//prd.md`. Use when the user says "create a PRD", "write requirements", "define the feature", "start a feature spec", or wants to specify a feature before techspec/tasks/start-job. -allowed-tools: Bash, Read, Grep, Glob, Write, Edit +allowed-tools: Bash Read Grep Glob Write Edit model: claude-opus-4-7 --- diff --git a/.agents/skills/project-setup/SKILL.md b/.agents/skills/project-setup/SKILL.md index 2aadd89..db3e34c 100644 --- a/.agents/skills/project-setup/SKILL.md +++ b/.agents/skills/project-setup/SKILL.md @@ -1,7 +1,7 @@ --- name: project-setup description: Customize a new project created from this Flutter template, including app identity, package name, platform cleanup, icons, splash screen, Firebase/secrets decisions, setup tool execution, code generation, and validation. -allowed-tools: Bash, Read, Grep, Glob, Edit, Write +allowed-tools: Bash Read Grep Glob Edit Write model: claude-sonnet-4-6 --- diff --git a/.agents/skills/release-builds/SKILL.md b/.agents/skills/release-builds/SKILL.md index df00585..8d1bf10 100644 --- a/.agents/skills/release-builds/SKILL.md +++ b/.agents/skills/release-builds/SKILL.md @@ -1,7 +1,7 @@ --- name: release-builds description: Run post-merge release build steps for this repository, including Android tag-driven releases and sequential iOS IPA generation with archival for Transporter upload and Crashlytics deobfuscation. Use after the release PR has been merged. -allowed-tools: Bash, Read, Grep, Glob +allowed-tools: Bash Read Grep Glob model: claude-sonnet-4-6 --- diff --git a/.agents/skills/release-prepare/SKILL.md b/.agents/skills/release-prepare/SKILL.md index 4e2f1be..a2b503b 100644 --- a/.agents/skills/release-prepare/SKILL.md +++ b/.agents/skills/release-prepare/SKILL.md @@ -1,7 +1,7 @@ --- name: release-prepare description: Prepare a release in this repository by bumping the app version, updating release notes, creating a release branch named release/, and preparing the PR for merge before any release builds or tags are created. -allowed-tools: Bash, Read, Grep, Glob, Edit, Write +allowed-tools: Bash Read Grep Glob Edit Write model: claude-sonnet-4-6 --- diff --git a/.agents/skills/review-pr-comments/SKILL.md b/.agents/skills/review-pr-comments/SKILL.md index 4dfca1a..548bfb3 100644 --- a/.agents/skills/review-pr-comments/SKILL.md +++ b/.agents/skills/review-pr-comments/SKILL.md @@ -8,7 +8,7 @@ description: > comments, and pushes. Use when the user asks to review PR comments, resolve PR feedback, review AI comments, review human review comments, or handle code review feedback. -allowed-tools: Agent, Bash, Read, Edit, Write, Grep, Glob +allowed-tools: Agent Bash Read Edit Write Grep Glob model: claude-sonnet-4-6 --- diff --git a/.agents/skills/secrets-bootstrap/SKILL.md b/.agents/skills/secrets-bootstrap/SKILL.md index f290768..1104782 100644 --- a/.agents/skills/secrets-bootstrap/SKILL.md +++ b/.agents/skills/secrets-bootstrap/SKILL.md @@ -1,7 +1,7 @@ --- name: secrets-bootstrap description: Safely work with encrypted secrets, environment files, and signing material in this repository. Use when a task requires loading, decrypting, validating, or explaining the repo's secrets and signing setup. -allowed-tools: Bash, Read, Grep, Glob +allowed-tools: Bash Read Grep Glob model: claude-sonnet-4-6 --- diff --git a/.agents/skills/start-job/SKILL.md b/.agents/skills/start-job/SKILL.md index 5e72133..6758451 100644 --- a/.agents/skills/start-job/SKILL.md +++ b/.agents/skills/start-job/SKILL.md @@ -5,7 +5,7 @@ description: > tasks → implement-tasks-sequence → build-verify → pr-review uncommitted. Use after a PRD and tech spec are complete. Trigger phrases: "start job", "start the job", "run the full pipeline", "do it all", "implement the feature end-to-end". -allowed-tools: Bash, Read, Grep, Glob, Edit, Write, Agent, Skill +allowed-tools: Bash Read Grep Glob Edit Write Agent Skill user-invocable: true model: claude-sonnet-4-6 --- diff --git a/.agents/skills/tasks/SKILL.md b/.agents/skills/tasks/SKILL.md index c40b0ee..95df835 100644 --- a/.agents/skills/tasks/SKILL.md +++ b/.agents/skills/tasks/SKILL.md @@ -8,7 +8,7 @@ description: > for the next step. Use when the user says "break this down into tasks", "create tasks", "task breakdown", or after the tech spec is complete and the user wants to plan implementation. -allowed-tools: Bash, Read, Grep, Glob, Write, Edit +allowed-tools: Bash Read Grep Glob Write Edit model: claude-sonnet-4-6 --- diff --git a/.agents/skills/techspec/SKILL.md b/.agents/skills/techspec/SKILL.md index b083466..85da948 100644 --- a/.agents/skills/techspec/SKILL.md +++ b/.agents/skills/techspec/SKILL.md @@ -5,7 +5,7 @@ description: > through deep project analysis and clarification. Use when the user says "create a tech spec", "write the technical design", "spec this out", or after a PRD is complete and the user wants to move to technical planning. -allowed-tools: Bash, Read, Grep, Glob, Write, Edit +allowed-tools: Bash Read Grep Glob Write Edit model: claude-opus-4-7 --- diff --git a/.agents/skills/upgrade/SKILL.md b/.agents/skills/upgrade/SKILL.md index 37318e6..ea0c7a6 100644 --- a/.agents/skills/upgrade/SKILL.md +++ b/.agents/skills/upgrade/SKILL.md @@ -1,7 +1,7 @@ --- name: upgrade description: Upgrade Flutter and package dependencies in this repository while keeping .fvmrc, pubspec.yaml, code generation, CI, and tests aligned. Use when bumping Flutter, Dart constraints, direct dependencies, or generator toolchains. -allowed-tools: Bash, Read, Grep, Glob, Edit, Write +allowed-tools: Bash Read Grep Glob Edit Write model: claude-sonnet-4-6 --- diff --git a/.agents/skills/widget-test/SKILL.md b/.agents/skills/widget-test/SKILL.md index 1568ce8..4e6014b 100644 --- a/.agents/skills/widget-test/SKILL.md +++ b/.agents/skills/widget-test/SKILL.md @@ -5,7 +5,7 @@ description: > Riverpod provider overrides, generated localization, shared theme setup, and FVM test commands. Use when a task asks for widget tests, UI regression coverage, test coverage for a screen/component, or when implementation work changes visible Flutter behavior. -allowed-tools: Bash, Read, Grep, Glob, Edit, Write +allowed-tools: Bash Read Grep Glob Edit Write model: claude-sonnet-4-6 --- diff --git a/.agents/validate_skills.py b/.agents/validate_skills.py index dcef295..0ea0271 100755 --- a/.agents/validate_skills.py +++ b/.agents/validate_skills.py @@ -8,6 +8,7 @@ - name: required, 1-64 chars, lowercase alphanumerics and single hyphens, no leading/trailing hyphen, matches the directory name - description: required, 1-1024 chars + - allowed-tools: optional, space-separated string, no comma-separated values - unknown top-level frontmatter fields (spec fields + known Claude Code extensions are accepted; anything else is a warning) - SKILL.md body under 500 lines (spec recommendation; warning) @@ -27,6 +28,7 @@ SPEC_FIELDS = {"name", "description", "license", "compatibility", "metadata", "allowed-tools"} CLAUDE_EXTENSIONS = {"model", "user-invocable", "disable-model-invocation"} NAME_RE = re.compile(r"^[a-z0-9]+(-[a-z0-9]+)*$") +TOOL_RE = re.compile(r"^[A-Za-z0-9_./:-]+(?:\([^)\s]+\))?$") MAX_BODY_LINES = 500 try: @@ -115,6 +117,20 @@ def check_skill(skill_dir: str) -> tuple[list[str], list[str]]: elif len(str(description)) > 1024: errors.append(f"description is {len(str(description))} chars (max 1024)") + allowed_tools = fm.get("allowed-tools") + if allowed_tools is not None: + if not isinstance(allowed_tools, str): + errors.append("allowed-tools must be a space-separated string") + elif "," in allowed_tools: + errors.append("allowed-tools must be space-separated; commas are not valid") + else: + tools = allowed_tools.split() + if not tools: + errors.append("allowed-tools must not be empty when provided") + for tool in tools: + if not TOOL_RE.fullmatch(tool): + errors.append(f"allowed-tools contains invalid tool token '{tool}'") + for key in fm: if key not in SPEC_FIELDS | CLAUDE_EXTENSIONS: warnings.append(f"unknown frontmatter field '{key}' " diff --git a/AGENTS.md b/AGENTS.md index c8f7f2c..cd2c4fe 100644 --- a/AGENTS.md +++ b/AGENTS.md @@ -89,7 +89,7 @@ and other skills-compliant agents can use it: - `name:` matching the folder - `description:` explaining when to use the skill - `allowed-tools:` listing the tools the skill needs (for example - `Bash, Read, Grep, Glob, Edit, Write`; add `Agent` for skills that delegate + `Bash Read Grep Glob Edit Write`; add `Agent` for skills that delegate to subagents, `Skill` for orchestrators that invoke other skills) - `model:` selecting the model — use `claude-sonnet-4-6` for most implementation, verification, and review workflows, and `claude-opus-4-7` From 7c3db6a15e0de6377603295d5928d34532d9aa07 Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?Michal=20Urb=C3=A1nek?= Date: Thu, 11 Jun 2026 13:04:03 +0200 Subject: [PATCH 8/8] fix: harden skill validator checks --- .agents/validate_skills.py | 32 ++++++++++++++++++++------------ 1 file changed, 20 insertions(+), 12 deletions(-) diff --git a/.agents/validate_skills.py b/.agents/validate_skills.py index 0ea0271..9306b12 100755 --- a/.agents/validate_skills.py +++ b/.agents/validate_skills.py @@ -13,7 +13,7 @@ extensions are accepted; anything else is a warning) - SKILL.md body under 500 lines (spec recommendation; warning) - Claude Code exposure exists: - .claude/skills/ symlink and .claude/commands/.md slash command + .claude/skills/ symlink and .claude/commands/.md slash command file Exits 1 on errors, 0 if only warnings. """ @@ -103,19 +103,23 @@ def check_skill(skill_dir: str) -> tuple[list[str], list[str]]: name = fm.get("name") if not name: errors.append("missing required field: name") + elif not isinstance(name, str): + errors.append("name must be a string") else: if name != dirname: errors.append(f"name '{name}' does not match directory '{dirname}'") - if not NAME_RE.fullmatch(str(name)): + if not NAME_RE.fullmatch(name): errors.append(f"name '{name}' violates spec charset rules") - if len(str(name)) > 64: + if len(name) > 64: errors.append("name exceeds 64 characters") description = fm.get("description") if not description: errors.append("missing required field: description") - elif len(str(description)) > 1024: - errors.append(f"description is {len(str(description))} chars (max 1024)") + elif not isinstance(description, str): + errors.append("description must be a string") + elif len(description) > 1024: + errors.append(f"description is {len(description)} chars (max 1024)") allowed_tools = fm.get("allowed-tools") if allowed_tools is not None: @@ -141,13 +145,17 @@ def check_skill(skill_dir: str) -> tuple[list[str], list[str]]: warnings.append(f"body is {body_lines} lines (spec recommends < {MAX_BODY_LINES}; " "consider moving detail into references/)") - for rel, kind in [ - (os.path.join(".claude", "skills", dirname), "Claude Code symlink"), - (os.path.join(".claude", "commands", f"{dirname}.md"), "slash command"), - ]: - path = os.path.join(REPO_ROOT, rel) - if not os.path.exists(path): - errors.append(f"missing {kind}: {rel}") + skill_link_rel = os.path.join(".claude", "skills", dirname) + skill_link_path = os.path.join(REPO_ROOT, skill_link_rel) + if not os.path.exists(skill_link_path): + errors.append(f"missing Claude Code symlink: {skill_link_rel}") + elif not os.path.islink(skill_link_path): + errors.append(f"Claude Code skill exposure must be a symlink: {skill_link_rel}") + + command_rel = os.path.join(".claude", "commands", f"{dirname}.md") + command_path = os.path.join(REPO_ROOT, command_rel) + if not os.path.isfile(command_path): + errors.append(f"missing slash command file: {command_rel}") return errors, warnings