feat(skills): declare which surfaces each skill ships to
CI / Check / Test (push) Failing after 1s
CI / Tag release (push) Skipped

The repo distributes three ways — the Claude Code plugin, the symlinked
library for Crush/Pi/OpenCode, and claude.ai, which has no fetch path at all —
and treated every skill as belonging to all of them. claude.ai is not a fourth
host to mirror: gitea-ci, playwright and web-shot have no shell and no cluster
there, so a flat mirror installs skills that can never fire and degrades
selection for the ones that can.

Every SKILL.md now carries `surfaces:`, defaulting to [claude-code, library];
dream, own-the-task and grill-me add `chat`, matching what is actually
installed on claude.ai today. Claude Code accepts the extra key —
`claude plugin validate` passes and the skills still load.

bin/check-surfaces validates values, not just presence, because the failure
mode here is silent: a wrong surface removes a skill from a harness rather than
erroring. install.sh links only skills whose surfaces include `library`, and a
source that declares nothing at all is treated as foreign and linked as-is —
Anthropic's official set has no reason to know this convention. doctor's
missing-link check skips non-library skills for the same reason.

Refs #29
Bump-Type: minor
This commit is contained in:
2026-08-29 10:09:52 +02:00
parent 15737321ac
commit 90a58f0b9e
49 changed files with 214 additions and 1 deletions
+6 -1
View File
@@ -99,7 +99,12 @@ tasks:
# tests/check_index_test.sh rather than living untested here. # tests/check_index_test.sh rather than living untested here.
sh '{{.TASKFILE_DIR}}/bin/check-index' '{{.TASKFILE_DIR}}' || fail=1 sh '{{.TASKFILE_DIR}}/bin/check-index' '{{.TASKFILE_DIR}}' || fail=1
# 4. Plugin manifest version must match the latest tag, or installers # 4. Every skill says which surfaces it ships to, and names only
# surfaces that exist — a wrong value silently drops a skill from a
# harness instead of erroring.
sh '{{.TASKFILE_DIR}}/bin/check-surfaces' '{{.TASKFILE_DIR}}' || fail=1
# 5. Plugin manifest version must match the latest tag, or installers
# never see the update (Claude Code gates updates on this field). # never see the update (Claude Code gates updates on this field).
if [ -f '{{.PLUGIN_MANIFEST}}' ]; then if [ -f '{{.PLUGIN_MANIFEST}}' ]; then
manifest_v=$(sed -n 's/.*"version"[[:space:]]*:[[:space:]]*"\([^"]*\)".*/\1/p' '{{.PLUGIN_MANIFEST}}' | head -1) manifest_v=$(sed -n 's/.*"version"[[:space:]]*:[[:space:]]*"\([^"]*\)".*/\1/p' '{{.PLUGIN_MANIFEST}}' | head -1)
+49
View File
@@ -0,0 +1,49 @@
#!/bin/sh
# check-surfaces — every skill declares which surfaces it ships to, and only
# names surfaces that exist.
#
# The repo distributes three ways: the Claude Code plugin, the symlinked
# library (Crush/Pi/OpenCode), and claude.ai, which has no fetch path at all.
# Treating every skill as belonging to all three installs skills that can never
# fire — gitea-ci, playwright and web-shot have no shell or cluster in a chat
# surface — and degrades selection for the ones that can (#29).
#
# Values are validated, not merely counted: a wrong surface silently removes a
# skill from a harness rather than erroring, which is the failure mode this
# whole file exists to prevent.
#
# Usage: check-surfaces [checkout-root]
set -u
ROOT=${1:-$(CDPATH= cd -- "$(dirname -- "$0")/.." && pwd)}
ALLOWED='claude-code library chat'
fail=0
for dir in "$ROOT"/skills/*/; do
[ -f "$dir/SKILL.md" ] || continue
name=$(basename "$dir")
line=$(sed -n 's/^surfaces:[[:space:]]*//p' "$dir/SKILL.md" | head -1)
if [ -z "$line" ]; then
echo "ERROR: skills/$name declares no 'surfaces:' — say where it ships (${ALLOWED% *}, ${ALLOWED##* })" >&2
fail=1
continue
fi
values=$(printf '%s' "$line" | tr -d '[]' | tr ',' ' ')
count=0
for v in $values; do
count=$((count + 1))
case " $ALLOWED " in
*" $v "*) ;;
*) echo "ERROR: skills/$name names surface '$v', which does not exist — allowed: $ALLOWED" >&2; fail=1 ;;
esac
done
[ "$count" -gt 0 ] || {
echo "ERROR: skills/$name has an empty 'surfaces:' list — a skill that ships nowhere should be deleted, not declared" >&2
fail=1
}
done
exit $fail
+7
View File
@@ -153,6 +153,13 @@ elif [ -d "$AGENTS_DIR" ]; then
for dir in "$SKILLS_DIR"/*/; do for dir in "$SKILLS_DIR"/*/; do
[ -f "$dir/SKILL.md" ] || continue [ -f "$dir/SKILL.md" ] || continue
name=$(basename "$dir") name=$(basename "$dir")
# Only skills that ship to the library belong here. A chat-only skill
# missing from a Crush directory is correct, not drift (#29).
surfaces=$(sed -n 's/^surfaces:[[:space:]]*//p' "$dir/SKILL.md" | head -1)
if [ -n "$surfaces" ] \
&& ! printf '%s' "$surfaces" | tr -d '[]' | tr ',' ' ' | grep -qw library; then
continue
fi
[ -L "$AGENTS_DIR/$name" ] \ [ -L "$AGENTS_DIR/$name" ] \
|| add FAIL missing "$name is in the checkout but has no link in $AGENTS_DIR — re-run install.sh" || add FAIL missing "$name is in the checkout but has no link in $AGENTS_DIR — re-run install.sh"
done done
+11
View File
@@ -131,6 +131,17 @@ wire_skills() {
name="$(basename "$dir")" name="$(basename "$dir")"
target="${dir%/}" target="${dir%/}"
# A skill declares its surfaces; this installer serves exactly one of
# them. A chat-only skill linked into Crush can never fire and competes
# for selection with ones that can (#29). A source with no declaration
# is foreign — Anthropic's official set has no reason to know this
# convention — so silence means "link it".
surfaces="$(sed -n 's/^surfaces:[[:space:]]*//p' "$dir/SKILL.md" | head -1)"
if [ -n "$surfaces" ] && ! printf '%s' "$surfaces" | tr -d '[]' | tr ',' ' ' | grep -qw library; then
log "skipping $name — surfaces: $surfaces does not include the library"
continue
fi
if printf '%s' "$desired" | grep -qx -- "$name"; then if printf '%s' "$desired" | grep -qx -- "$name"; then
log "COLLISION: $name is offered by $target too; keeping $AGENTS_DIR/$name -> $(readlink "$AGENTS_DIR/$name" 2>/dev/null || echo '?')" log "COLLISION: $name is offered by $target too; keeping $AGENTS_DIR/$name -> $(readlink "$AGENTS_DIR/$name" 2>/dev/null || echo '?')"
continue continue
+1
View File
@@ -1,5 +1,6 @@
--- ---
name: atdd name: atdd
surfaces: [claude-code, library]
description: Implement user stories using the ATDD workflow — Red (failing acceptance test) → Green (minimal implementation) → Refactor. One story at a time. description: Implement user stories using the ATDD workflow — Red (failing acceptance test) → Green (minimal implementation) → Refactor. One story at a time.
--- ---
+1
View File
@@ -1,5 +1,6 @@
--- ---
name: cad-babysit name: cad-babysit
surfaces: [claude-code, library]
description: Focused human-in-the-loop session working CAD's stuck queue (cad-stuck output). Read-only — diagnoses, never dispatches, arms a label, or closes an issue. Use when picking up whatever CAD has run into trouble on, with a human present. description: Focused human-in-the-loop session working CAD's stuck queue (cad-stuck output). Read-only — diagnoses, never dispatches, arms a label, or closes an issue. Use when picking up whatever CAD has run into trouble on, with a human present.
--- ---
+1
View File
@@ -1,5 +1,6 @@
--- ---
name: clean-code name: clean-code
surfaces: [claude-code, library]
description: Write code that humans can read, understand, and safely change. Apply SOLID, GRASP, and Clean Code principles during the REFACTOR phase of TDD. description: Write code that humans can read, understand, and safely change. Apply SOLID, GRASP, and Clean Code principles during the REFACTOR phase of TDD.
--- ---
+1
View File
@@ -1,5 +1,6 @@
--- ---
name: code-review name: code-review
surfaces: [claude-code, library]
description: Systematic code smell detection and Go-specific review checklist. Load before any pre-merge review. description: Systematic code smell detection and Go-specific review checklist. Load before any pre-merge review.
--- ---
+1
View File
@@ -1,5 +1,6 @@
--- ---
name: cognitive-load name: cognitive-load
surfaces: [claude-code, library]
description: Measure how much mental effort a codebase demands from developers. Use when identifying hotspots, before architectural decisions, or when code feels hard to understand. description: Measure how much mental effort a codebase demands from developers. Use when identifying hotspots, before architectural decisions, or when code feels hard to understand.
--- ---
+1
View File
@@ -1,5 +1,6 @@
--- ---
name: debug name: debug
surfaces: [claude-code, library]
description: Systematic hypothesis-first debugging. Generate 3-5 ranked hypotheses with verification steps before suggesting any fix. Use when encountering a bug, test failure, or unexpected behavior. description: Systematic hypothesis-first debugging. Generate 3-5 ranked hypotheses with verification steps before suggesting any fix. Use when encountering a bug, test failure, or unexpected behavior.
--- ---
+1
View File
@@ -1,5 +1,6 @@
--- ---
name: discovery-framing name: discovery-framing
surfaces: [claude-code, library]
description: Run the discovery / framing phase of product innovation — define and quantify a focused customer problem BEFORE any solution exists. Four movements: understand the problem space, learn about customers, identify and size problems, decide pursue/table/kill. Produces a problem brief per prioritized opportunity. Use when an idea is still vague, when someone is jumping to solutions before the problem is validated, when scoping early research, or when deciding which problems are worth pursuing. Trigger phrases include "frame the problem", "discovery", "problem statement", "is this worth building", "early research", "opportunity sizing", "we have an idea for", "how might we", "what problem are we solving". description: Run the discovery / framing phase of product innovation — define and quantify a focused customer problem BEFORE any solution exists. Four movements: understand the problem space, learn about customers, identify and size problems, decide pursue/table/kill. Produces a problem brief per prioritized opportunity. Use when an idea is still vague, when someone is jumping to solutions before the problem is validated, when scoping early research, or when deciding which problems are worth pursuing. Trigger phrases include "frame the problem", "discovery", "problem statement", "is this worth building", "early research", "opportunity sizing", "we have an idea for", "how might we", "what problem are we solving".
--- ---
+1
View File
@@ -1,5 +1,6 @@
--- ---
name: dream name: dream
surfaces: [claude-code, library, chat]
description: > description: >
Run a "dream" — a reflective memory consolidation pass over an agent's memory Run a "dream" — a reflective memory consolidation pass over an agent's memory
directory. Use this skill whenever the user says "dream", "run a dream", "consolidate directory. Use this skill whenever the user says "dream", "run a dream", "consolidate
+1
View File
@@ -1,5 +1,6 @@
--- ---
name: experiment-spec name: experiment-spec
surfaces: [claude-code, library]
description: Write a rigorous experiment spec for a research phase before any code or training runs. Use instead of feature-spec for scientific/ML research projects. Enforces falsifiable hypothesis, quantitative acceptance criteria, baseline comparison, and null-result protocol. description: Write a rigorous experiment spec for a research phase before any code or training runs. Use instead of feature-spec for scientific/ML research projects. Enforces falsifiable hypothesis, quantitative acceptance criteria, baseline comparison, and null-result protocol.
--- ---
+1
View File
@@ -1,5 +1,6 @@
--- ---
name: feature-spec name: feature-spec
surfaces: [claude-code, library]
description: Write a tight implementation-level spec for a single feature or component before coding it. Use after a project-level spec exists (see spec-driven-dev) and you need to nail down one feature inside it. description: Write a tight implementation-level spec for a single feature or component before coding it. Use after a project-level spec exists (see spec-driven-dev) and you need to nail down one feature inside it.
--- ---
+1
View File
@@ -1,5 +1,6 @@
--- ---
name: gitea-ci name: gitea-ci
surfaces: [claude-code, library]
description: End-to-end Gitea CI/CD setup with self-hosted act_runner, quality gate pipeline, shared buildctl image-build script, k3s deploy, and GitHub mirror. Covers act_runner-specific gotchas that are not documented anywhere. description: End-to-end Gitea CI/CD setup with self-hosted act_runner, quality gate pipeline, shared buildctl image-build script, k3s deploy, and GitHub mirror. Covers act_runner-specific gotchas that are not documented anywhere.
--- ---
+1
View File
@@ -1,5 +1,6 @@
--- ---
name: grill-me name: grill-me
surfaces: [claude-code, library, chat]
description: Critically interrogates plans, ideas, and proposals to make them sharper, more robust, and better grounded — with the explicit goal of producing a meaningfully better plan by the end. Use this skill whenever the user wants to stress-test a plan, prepare for hard questions, check if an idea is ready to act on, validate a hypothesis, or explicitly asks to be challenged, questioned, or grilled. Also trigger when a conversation has been exploring an idea for a while and it's time to converge — use this skill to check if the idea is actually ready. Trigger phrases include "grill me", "challenge this", "poke holes", "am I missing something", "is this ready", "stress-test this", "devil's advocate", "what am I not seeing". description: Critically interrogates plans, ideas, and proposals to make them sharper, more robust, and better grounded — with the explicit goal of producing a meaningfully better plan by the end. Use this skill whenever the user wants to stress-test a plan, prepare for hard questions, check if an idea is ready to act on, validate a hypothesis, or explicitly asks to be challenged, questioned, or grilled. Also trigger when a conversation has been exploring an idea for a while and it's time to converge — use this skill to check if the idea is actually ready. Trigger phrases include "grill me", "challenge this", "poke holes", "am I missing something", "is this ready", "stress-test this", "devil's advocate", "what am I not seeing".
--- ---
+1
View File
@@ -1,5 +1,6 @@
--- ---
name: own-the-task name: own-the-task
surfaces: [claude-code, library, chat]
description: Take ownership of a delegated task like a hired employee — interview first, write a handover brief, propose a plan, then execute. Use whenever the user says "take this off my plate", "own this", "act as my AI employee", "interview me first", "ask me questions before you start", or delegates anything open-ended where the real goal, the why, and the definition of done are not yet on the table. Trigger even when "interview" is never said — any delegation where getting the intent wrong would waste the whole effort belongs here. description: Take ownership of a delegated task like a hired employee — interview first, write a handover brief, propose a plan, then execute. Use whenever the user says "take this off my plate", "own this", "act as my AI employee", "interview me first", "ask me questions before you start", or delegates anything open-ended where the real goal, the why, and the definition of done are not yet on the table. Trigger even when "interview" is never said — any delegation where getting the intent wrong would waste the whole effort belongs here.
--- ---
+1
View File
@@ -1,5 +1,6 @@
--- ---
name: planning name: planning
surfaces: [claude-code, library]
description: Decompose work into small, verifiable, ordered tasks. Use when you have a spec or clear requirements and need to break work into implementable units. description: Decompose work into small, verifiable, ordered tasks. Use when you have a spec or clear requirements and need to break work into implementable units.
--- ---
+1
View File
@@ -1,5 +1,6 @@
--- ---
name: playwright name: playwright
surfaces: [claude-code, library]
description: Add and run Playwright E2E tests for any project with a web UI — covers setup, HTMX-specific patterns, SSE/streaming, Taskfile integration, and CI wiring. description: Add and run Playwright E2E tests for any project with a web UI — covers setup, HTMX-specific patterns, SSE/streaming, Taskfile integration, and CI wiring.
--- ---
+1
View File
@@ -1,5 +1,6 @@
--- ---
name: problem-analysis name: problem-analysis
surfaces: [claude-code, library]
description: Deeply understand a problem before coding begins. Identify the real problem, stakeholders, constraints, and success criteria. Use before starting any non-trivial feature. description: Deeply understand a problem before coding begins. Identify the real problem, stakeholders, constraints, and success criteria. Use before starting any non-trivial feature.
--- ---
+1
View File
@@ -1,5 +1,6 @@
--- ---
name: refactoring name: refactoring
surfaces: [claude-code, library]
description: Systematic refactoring methodology based on Martin Fowler's catalog. Apply during the REFACTOR phase of TDD, never while making code changes that modify behavior. description: Systematic refactoring methodology based on Martin Fowler's catalog. Apply during the REFACTOR phase of TDD, never while making code changes that modify behavior.
--- ---
@@ -1,5 +1,6 @@
--- ---
name: regulatory-risk-assessment name: regulatory-risk-assessment
surfaces: [claude-code, library]
description: Produce a structured regulatory risk assessment / risk-register entry for regulated-industry features (banking, payments, PSD2/PSR, DORA, AML). Use when filing a CAD issue that needs a Risk:LOW/MEDIUM/HIGH level, or designing features touching payments, auth, data storage, or external APIs ("what are the risks?", "compliance gate", "risk register"). description: Produce a structured regulatory risk assessment / risk-register entry for regulated-industry features (banking, payments, PSD2/PSR, DORA, AML). Use when filing a CAD issue that needs a Risk:LOW/MEDIUM/HIGH level, or designing features touching payments, auth, data storage, or external APIs ("what are the risks?", "compliance gate", "risk register").
--- ---
+1
View File
@@ -1,5 +1,6 @@
--- ---
name: secret-hygiene name: secret-hygiene
surfaces: [claude-code, library]
description: Prevent agent sessions from rendering credentials into the transcript, and recover safely when one leaks. Load BEFORE any command that touches credentials - kubectl exec/env/describe, kubectl get secret, whole-file SOPS decryption, token generation or rotation, envFrom inspection, or edits to encrypted config. Also load when a credential has already been exposed and a rotation chain is needed. Triggers - "rotate this token", "decrypt the config", "check the env var", "leaked credential", "did that print a secret", "why is this secret wrong". description: Prevent agent sessions from rendering credentials into the transcript, and recover safely when one leaks. Load BEFORE any command that touches credentials - kubectl exec/env/describe, kubectl get secret, whole-file SOPS decryption, token generation or rotation, envFrom inspection, or edits to encrypted config. Also load when a credential has already been exposed and a rotation chain is needed. Triggers - "rotate this token", "decrypt the config", "check the env var", "leaked credential", "did that print a secret", "why is this secret wrong".
--- ---
+1
View File
@@ -1,5 +1,6 @@
--- ---
name: session-retrospective name: session-retrospective
surfaces: [claude-code, library]
description: Review a completed coding session (from brain/sessions/*.jsonl) and surface non-obvious learnings worth preserving. Use after a session ends, before context is lost. description: Review a completed coding session (from brain/sessions/*.jsonl) and surface non-obvious learnings worth preserving. Use after a session ends, before context is lost.
--- ---
+1
View File
@@ -1,5 +1,6 @@
--- ---
name: solid name: solid
surfaces: [claude-code, library]
description: Apply SOLID design principles in Go. Use during architecture decisions, design reviews, and when adding new abstractions. description: Apply SOLID design principles in Go. Use during architecture decisions, design reviews, and when adding new abstractions.
--- ---
+1
View File
@@ -1,5 +1,6 @@
--- ---
name: spec-driven-dev name: spec-driven-dev
surfaces: [claude-code, library]
description: Write a structured specification before writing any code. Use when starting a new project, feature, or significant change. Adapted for a PM-first workflow where why comes before how. description: Write a structured specification before writing any code. Use when starting a new project, feature, or significant change. Adapted for a PM-first workflow where why comes before how.
--- ---
+1
View File
@@ -1,5 +1,6 @@
--- ---
name: stage-gate-review name: stage-gate-review
surfaces: [claude-code, library]
description: Run or prepare a stage-gate product governance review — the go/no-go checkpoint where a council approves an initiative to advance through fixed innovation stages (Frame → Concept → Prototype → Validate → Scale), each gate guarded by a per-discipline readiness checklist. Use when preparing a Product Council / steering-group ask, building a go/no-go checklist, designing an innovation governance process, or auditing whether an initiative is genuinely ready to advance vs faking the gate. Trigger phrases include "stage gate", "product council", "go/no-go", "advance to the next stage", "is this ready to progress", "gate review", "phase gate", "innovation governance". description: Run or prepare a stage-gate product governance review — the go/no-go checkpoint where a council approves an initiative to advance through fixed innovation stages (Frame → Concept → Prototype → Validate → Scale), each gate guarded by a per-discipline readiness checklist. Use when preparing a Product Council / steering-group ask, building a go/no-go checklist, designing an innovation governance process, or auditing whether an initiative is genuinely ready to advance vs faking the gate. Trigger phrases include "stage gate", "product council", "go/no-go", "advance to the next stage", "is this ready to progress", "gate review", "phase gate", "innovation governance".
--- ---
@@ -1,5 +1,6 @@
--- ---
name: brainstorming name: brainstorming
surfaces: [claude-code, library]
description: "You MUST use this before any creative work - creating features, building components, adding functionality, or modifying behavior. Explores user intent, requirements and design before implementation." description: "You MUST use this before any creative work - creating features, building components, adding functionality, or modifying behavior. Explores user intent, requirements and design before implementation."
--- ---
@@ -1,5 +1,6 @@
--- ---
name: dispatching-parallel-agents name: dispatching-parallel-agents
surfaces: [claude-code, library]
description: Use when facing 2+ independent tasks that can be worked on without shared state or sequential dependencies description: Use when facing 2+ independent tasks that can be worked on without shared state or sequential dependencies
--- ---
@@ -1,5 +1,6 @@
--- ---
name: executing-plans name: executing-plans
surfaces: [claude-code, library]
description: Use when you have a written implementation plan to execute in a separate session with review checkpoints description: Use when you have a written implementation plan to execute in a separate session with review checkpoints
--- ---
@@ -1,5 +1,6 @@
--- ---
name: finishing-a-development-branch name: finishing-a-development-branch
surfaces: [claude-code, library]
description: Use when implementation is complete, all tests pass, and you need to decide how to integrate the work - guides completion of development work by presenting structured options for merge, PR, or cleanup description: Use when implementation is complete, all tests pass, and you need to decide how to integrate the work - guides completion of development work by presenting structured options for merge, PR, or cleanup
--- ---
@@ -1,5 +1,6 @@
--- ---
name: receiving-code-review name: receiving-code-review
surfaces: [claude-code, library]
description: Use when receiving code review feedback, before implementing suggestions, especially if feedback seems unclear or technically questionable - requires technical rigor and verification, not performative agreement or blind implementation description: Use when receiving code review feedback, before implementing suggestions, especially if feedback seems unclear or technically questionable - requires technical rigor and verification, not performative agreement or blind implementation
--- ---
@@ -1,5 +1,6 @@
--- ---
name: requesting-code-review name: requesting-code-review
surfaces: [claude-code, library]
description: Use when completing tasks, implementing major features, or before merging to verify work meets requirements description: Use when completing tasks, implementing major features, or before merging to verify work meets requirements
--- ---
@@ -1,5 +1,6 @@
--- ---
name: subagent-driven-development name: subagent-driven-development
surfaces: [claude-code, library]
description: Use when executing implementation plans with independent tasks in the current session description: Use when executing implementation plans with independent tasks in the current session
--- ---
@@ -1,5 +1,6 @@
--- ---
name: systematic-debugging name: systematic-debugging
surfaces: [claude-code, library]
description: Use when encountering any bug, test failure, or unexpected behavior, before proposing fixes description: Use when encountering any bug, test failure, or unexpected behavior, before proposing fixes
--- ---
@@ -1,5 +1,6 @@
--- ---
name: using-git-worktrees name: using-git-worktrees
surfaces: [claude-code, library]
description: Use when starting feature work that needs isolation from current workspace or before executing implementation plans - ensures an isolated workspace exists via native tools or git worktree fallback description: Use when starting feature work that needs isolation from current workspace or before executing implementation plans - ensures an isolated workspace exists via native tools or git worktree fallback
--- ---
@@ -1,5 +1,6 @@
--- ---
name: using-superpowers name: using-superpowers
surfaces: [claude-code, library]
description: Use when starting any conversation - establishes how to find and use skills, requiring Skill tool invocation before ANY response including clarifying questions description: Use when starting any conversation - establishes how to find and use skills, requiring Skill tool invocation before ANY response including clarifying questions
--- ---
@@ -1,5 +1,6 @@
--- ---
name: verification-before-completion name: verification-before-completion
surfaces: [claude-code, library]
description: Use when about to claim work is complete, fixed, or passing, before committing or creating PRs - requires running verification commands and confirming output before making any success claims; evidence before assertions always description: Use when about to claim work is complete, fixed, or passing, before committing or creating PRs - requires running verification commands and confirming output before making any success claims; evidence before assertions always
--- ---
@@ -1,5 +1,6 @@
--- ---
name: writing-plans name: writing-plans
surfaces: [claude-code, library]
description: Use when you have a spec or requirements for a multi-step task, before touching code description: Use when you have a spec or requirements for a multi-step task, before touching code
--- ---
@@ -1,5 +1,6 @@
--- ---
name: writing-skills name: writing-skills
surfaces: [claude-code, library]
description: Use when creating new skills, editing existing skills, or verifying skills work before deployment description: Use when creating new skills, editing existing skills, or verifying skills work before deployment
--- ---
+1
View File
@@ -1,5 +1,6 @@
--- ---
name: tdd name: tdd
surfaces: [claude-code, library]
description: Write failing tests first, then minimal code to pass. Non-negotiable for all new features and bug fixes. description: Write failing tests first, then minimal code to pass. Non-negotiable for all new features and bug fixes.
--- ---
+1
View File
@@ -1,5 +1,6 @@
--- ---
name: telos-load name: telos-load
surfaces: [claude-code, library]
description: Load TELOS — the intention substrate (problems, goals, strategies, status) — into a session at start so every decision traces to a goal. Use when starting any koala session, before architectural decisions, or as the CAD pipeline entry point ("load TELOS", "what are we optimizing toward?"). description: Load TELOS — the intention substrate (problems, goals, strategies, status) — into a session at start so every decision traces to a goal. Use when starting any koala session, before architectural decisions, or as the CAD pipeline entry point ("load TELOS", "what are we optimizing toward?").
--- ---
+1
View File
@@ -1,5 +1,6 @@
--- ---
name: test-design name: test-design
surfaces: [claude-code, library]
description: Evaluate test quality using Dave Farley's 8 Properties of Good Tests. Use when reviewing or writing tests to ensure they provide genuine verification. description: Evaluate test quality using Dave Farley's 8 Properties of Good Tests. Use when reviewing or writing tests to ensure they provide genuine verification.
--- ---
+1
View File
@@ -1,5 +1,6 @@
--- ---
name: trainer name: trainer
surfaces: [claude-code, library]
description: Two-phase brain curation — scan session logs to score candidate learnings (READ), then write the ones that pass the quality gate as generalized knowledge entries (WRITE). Use periodically to keep the brain useful, not noisy. description: Two-phase brain curation — scan session logs to score candidate learnings (READ), then write the ones that pass the quality gate as generalized knowledge entries (WRITE). Use periodically to keep the brain useful, not noisy.
--- ---
+1
View File
@@ -1,5 +1,6 @@
--- ---
name: user-stories name: user-stories
surfaces: [claude-code, library]
description: Decompose problems into thin, deliverable user stories using Elephant Carpaccio and INVEST criteria. Use after problem analysis, before planning and implementation. description: Decompose problems into thin, deliverable user stories using Elephant Carpaccio and INVEST criteria. Use after problem analysis, before planning and implementation.
--- ---
+1
View File
@@ -1,5 +1,6 @@
--- ---
name: web-shot name: web-shot
surfaces: [claude-code, library]
description: Screenshot any running web UI by spawning a one-shot Playwright Job on the koala k3s cluster. Auto-detects the calling host's Tailscale name so a dev server on flamingo:8099, iguana:3000 or koala:8181 just works. Use when the user asks for a screenshot, visual verification, "what does the UI look like", or any time chromium / firefox / a browser is requested but none is installed on the host. description: Screenshot any running web UI by spawning a one-shot Playwright Job on the koala k3s cluster. Auto-detects the calling host's Tailscale name so a dev server on flamingo:8099, iguana:3000 or koala:8181 just works. Use when the user asks for a screenshot, visual verification, "what does the UI look like", or any time chromium / firefox / a browser is requested but none is installed on the host.
--- ---
+65
View File
@@ -0,0 +1,65 @@
#!/bin/sh
# Tests for bin/check-surfaces.
#
# The repo ships to three surfaces — the Claude Code plugin, the symlinked
# library (Crush/Pi/OpenCode) and claude.ai, which has no fetch path at all —
# and used to treat every skill as belonging to all of them. gitea-ci,
# playwright and web-shot cannot fire in a chat surface; a flat mirror installs
# skills that can never trigger and degrades selection for the ones that can
# (#29).
#
# The risk this gate exists for: a wrong `surfaces:` value silently removes a
# skill from a harness rather than erroring. So presence is not enough — values
# are validated against the allowed set.
set -u
ROOT=$(CDPATH= cd -- "$(dirname -- "$0")/.." && pwd)
SUT="$ROOT/bin/check-surfaces"
pass=0
fail=0
WORK=${TMPDIR:-/tmp}/check_surfaces_test.$$
if [ ! -f "$SUT" ]; then
printf 'FAIL: %s does not exist\n' "$SUT"
exit 1
fi
cleanup() { rm -rf "$WORK"; }
trap cleanup EXIT INT TERM
# fixture <name> <surfaces-line-or-empty> — a checkout holding one skill.
fixture() {
_f="$WORK/$1"
mkdir -p "$_f/skills/alpha"
if [ -n "$2" ]; then
printf -- '---\nname: alpha\n%s\ndescription: a\n---\n' "$2" > "$_f/skills/alpha/SKILL.md"
else
printf -- '---\nname: alpha\ndescription: a\n---\n' > "$_f/skills/alpha/SKILL.md"
fi
printf '%s' "$_f"
}
# expect <rc> <label> <fixture> [needle]
expect() {
_want=$1; _label=$2; _fx=$3; _needle=${4:-}
_out=$(sh "$SUT" "$_fx" 2>&1); _rc=$?
if [ "$_rc" -ne "$_want" ]; then
fail=$((fail + 1)); printf ' FAIL %s (want rc=%s got %s)\n%s\n' "$_label" "$_want" "$_rc" "$_out"; return
fi
if [ -n "$_needle" ] && ! printf '%s' "$_out" | grep -q "$_needle"; then
fail=$((fail + 1)); printf ' FAIL %s (rc ok, report never says %s)\n%s\n' "$_label" "$_needle" "$_out"; return
fi
pass=$((pass + 1)); printf ' ok %s\n' "$_label"
}
expect 0 'the default pair is accepted' "$(fixture ok 'surfaces: [claude-code, library]')"
expect 0 'all three surfaces are accepted' "$(fixture three 'surfaces: [claude-code, library, chat]')"
expect 0 'a single surface is accepted' "$(fixture one 'surfaces: [chat]')"
expect 1 'a missing surfaces field fails' "$(fixture missing '')" 'alpha'
expect 1 'an unknown surface value fails' "$(fixture bogus 'surfaces: [claude-code, desktop]')" 'desktop'
expect 1 'an empty surfaces list fails' "$(fixture empty 'surfaces: []')" 'alpha'
printf '\ncheck_surfaces: %d passed, %d failed\n' "$pass" "$fail"
[ "$fail" -eq 0 ]
+7
View File
@@ -127,6 +127,13 @@ f=$(new_fixture missing); wire_clean "$f"
rm -f "$f/home/.agents/skills/beta" rm -f "$f/home/.agents/skills/beta"
assert_fails "$f" 'beta' 'a checkout skill with no link is reported' assert_fails "$f" 'beta' 'a checkout skill with no link is reported'
# ...but only for skills that ship to the library. A chat-only skill has no
# business in a Crush directory, so its absence is correct, not drift (#29).
f=$(new_fixture chatonly); wire_clean "$f"
mkdir -p "$f/ck/skills/gamma"
printf -- '---\nname: gamma\nsurfaces: [chat]\ndescription: g\n---\n' > "$f/ck/skills/gamma/SKILL.md"
assert_clean "$f" 'a chat-only skill needs no library link'
# --- 5. stray entry (the loose secret-hygiene.md that loaded nowhere) -------- # --- 5. stray entry (the loose secret-hygiene.md that loaded nowhere) --------
f=$(new_fixture stray); wire_clean "$f" f=$(new_fixture stray); wire_clean "$f"
printf 'orphan\n' > "$f/ck/skills/loose-note.md" printf 'orphan\n' > "$f/ck/skills/loose-note.md"
+27
View File
@@ -156,5 +156,32 @@ else
no 'configured sources are recorded for doctor' "$out" no 'configured sources are recorded for doctor' "$out"
fi fi
# --- 8. surfaces: the library link set is not "every skill" -----------------
# claude.ai has no shell, no cluster and no checkout, so a chat-only skill
# linked into Crush is a skill that can never fire, competing for selection
# with ones that can (#29).
f=$(new_fixture surfaces)
mkdir -p "$f/ck/skills/chatonly"
printf -- '---\nname: chatonly\nsurfaces: [chat]\ndescription: c\n---\n' > "$f/ck/skills/chatonly/SKILL.md"
printf -- '---\nname: alpha\nsurfaces: [claude-code, library]\ndescription: a\n---\n' > "$f/ck/skills/alpha/SKILL.md"
out=$(run_install "$f")
if [ -L "$f/home/.agents/skills/alpha" ] && [ ! -e "$f/home/.agents/skills/chatonly" ]; then
ok 'a skill that does not ship to the library is not linked'
else
no 'a skill that does not ship to the library is not linked' "$out"
fi
# A foreign source has no reason to know this convention, so no declaration
# means "link it" — otherwise adding Anthropic's set would link nothing.
f=$(new_fixture foreign)
mkdir -p "$f/other/xlsx"
printf -- '---\nname: xlsx\ndescription: x\n---\n' > "$f/other/xlsx/SKILL.md"
out=$(run_install "$f" "$f/other")
if [ -L "$f/home/.agents/skills/xlsx" ]; then
ok 'a source with no surfaces convention is linked as-is'
else
no 'a source with no surfaces convention is linked as-is' "$out"
fi
printf '\ninstall: %d passed, %d failed\n' "$pass" "$fail" printf '\ninstall: %d passed, %d failed\n' "$pass" "$fail"
[ "$fail" -eq 0 ] [ "$fail" -eq 0 ]