Task — engineering-spec@1

"Skill playbooks bundle — Anthropic-Agent-Skills SKILL.md files teaching hosts how to chain plugin tools correctly"

draftTASK-PLUGIN-004
module plugin · class product · priority p0 · created 2026-05-19 · shipped null
depends on TASK-PLUGIN-002, TASK-SKILL-111 · blocks TASK-PLUGIN-007

§1 — Description (BCP-14 normative)

The PLUGIN module MUST ship 12 skill playbooks at modules/plugin/skills/<name>/SKILL.md following the Anthropic Agent Skills spec. Each playbook is a markdown file with YAML frontmatter teaching hosts WHEN and HOW to chain the MCP tools exposed in TASK-PLUGIN-002. Playbooks do NOT add new MCP tools — they are documentation that the host's skill router uses to inject just-in-time discipline into the model's prompt.

  1. MUST ship exactly 12 playbooks in v1 per DEC-2430 + DEC-2435, grouped by use-case:
  1. MUST conform to SKILL_BUNDLE_RUBRIC SKB-020..023 per DEC-2432 + TASK-SKILL-111/113:
  1. MUST carry acceptance/TRIGGER_TESTS.md per DEC-2433 + TASK-SKILL-112 with at least:
  1. MUST reference only tools registered in TASK-PLUGIN-002 — validator test test_playbooks_reference_valid_tools.py checks every tool name mentioned in the playbook body against the 8-tool registry.
  1. MUST explain in body sections: WHEN to use the playbook (one paragraph), WHICH tools it chains (bulleted), WHAT scopes are required (list), WHAT side effects occur (list), and a worked example (code block showing 2-4 sample tool calls).
  1. MUST declare the playbook frontmatter shape per Anthropic Agent Skills spec: ``yaml --- name: <skill-id> # kebab-case, matches folder name description: > One paragraph (60-480 chars) describing what this skill is for AND 4 quoted trigger examples e.g. "use this when the user asks 'run a workflow', 'execute a CUO chain', 'kick off the architect-new-system workflow', or 'start a persona workflow'" license: Apache-2.0 --- ``
  1. MUST pass TASK-SKILL-114 baseline check — once SKILL.md hits v1.0 maturity, an acceptance/BASELINE.md MUST be created freezing the trigger-test pass rate so regressions are detectable.
  1. MUST be host-portable per DEC-2434 — same SKILL.md works in Claude Code, Cowork, Codex CLI without modification. Cursor doesn't render Skills (its MCP integration surfaces tools only); the Cursor adapter (TASK-PLUGIN-007) omits skills/.
  1. MUST be subject to lazy-load discipline — host routers load only the SKILL.md description, not the body, at fingerprinting time. Body content is fetched only when the skill is triggered. Authors MUST treat the description as the load-bearing copy.
  1. MUST NOT add new playbooks in v1.x.y without a successor task (task-PLUGIN-004a, etc.) per DEC-2435.
  1. MUST NOT rename a playbook within v1.x.y — rename = breaking change requiring major bump (mirrors TASK-PLUGIN-003 clause 11).
  1. MUST NOT declare destructive operations in a playbook body without flagging in the description's trigger examples — users routed to the playbook MUST see the side effects upfront.

§2 — Why this design

Why playbooks AND commands AND tools (clauses 1+)? Three layers of host-facing surface:

Without playbooks, the host model sees tool names + brief descriptions but has no discipline to follow. Playbooks add the "use this tool ONLY when X" prose that prevents misuse.

Why exactly 12 playbooks (DEC-2430)? Same logic as TASK-PLUGIN-003 — small, learnable, well-considered. 12 covers the major use-cases with room to teach edge-cases (memory-write-discipline, audit-emission-discipline). More playbooks dilute the router's discrimination.

Why conform to SKB-020..023 (DEC-2432)? Plugin playbooks SHIP THROUGH the same Anthropic Agent Skills surface as everything else in modules/skill/. The SKB rubric is how all skills get discovered correctly. Playbooks must clear the same bar.

Why TRIGGER_TESTS (DEC-2433)? TASK-SKILL-112 introduced TRIGGER_TESTS.md as the way to measure routing accuracy. Without it, a description that triggers spuriously (false positive) or fails to trigger (false negative) goes unnoticed. With TRIGGER_TESTS, CI catches the regression.

Why reference only registered tools (clause 4)? Hallucinated tool names in playbook bodies waste the model's call attempts and produce confusing error envelopes. Validator test catches the divergence at PR time.

Why required body sections (clause 5)? Same lazy-load discipline as TASK-PLUGIN-003 commands — the body teaches the model when triggered. Without explicit "scopes required" and "side effects" sections, the model uses the playbook without knowing the consequences.

Why mandatory BASELINE.md at v1.0 (clause 7)? TASK-SKILL-114 establishes this as the regression-prevention mechanism. Playbook descriptions drift as authors tune triggers; without a baseline pass-rate snapshot, the team can't tell if a tweak improved routing or broke it.

Why omit skills from Cursor adapter (clause 8)? Cursor's MCP integration surfaces tools to the model directly. Skills (Anthropic Agent Skills) are an Anthropic-spec concept not implemented by Cursor as of 2026. Shipping them adds bloat without benefit. The canonical skills still ship in the canonical bundle for hosts that do support.

Why lazy-load discipline (clause 9)? Anthropic Skills router loads descriptions into a fingerprint index at install; bodies are fetched on match. If author treats body as load-bearing for routing, the playbook never triggers. Description is the only path to triggering.

Why no playbook renames in v1.x.y (clause 11)? Same reason as command renames: user scripts and host caches reference by slug; renames break references silently.

Why flag destructive ops in description (clause 12)? Users routed by description never see the body before the model decides to act. If "delete some memory rows" is in the body but not the description, the model may invoke without the user's expected warning. Surfacing in description triggers gives the user a glance-able heads-up.


§3 — API contract

Playbook folder layout (per playbook)

modules/plugin/skills/<name>/
├── SKILL.md                       (frontmatter + body)
└── acceptance/
    ├── TRIGGER_TESTS.md           (4 positive + 4 negative fixtures)
    └── BASELINE.md                (frozen pass rate at v1.0 promotion — added by TASK-SKILL-114)

Sample playbook — run-cuo-workflow/SKILL.md

---
name: run-cuo-workflow
description: >
  Use this skill when the user wants to execute a CyberOS persona-aware workflow chain end-to-end.
  Triggers on user requests like "run a workflow", "execute the architect-new-system workflow",
  "kick off CUO for the CTO", or "run the ADR quick-capture flow". Routes the model to call
  cyberos.cuo.execute_workflow with the right persona+workflow slugs and surfaces task status
  back to the user as the long-running execution proceeds.
license: Apache-2.0
---

## When to use

User wants to execute a CyberOS workflow they (or you) have identified. The workflow is a multi-step
chain belonging to one of the 47 active personas. Workflows emit memory audit rows at every step.

If the user only knows the goal ("architect a new payment system") and not the workflow name,
use `route-natural-language` FIRST to translate the natural-language ask into a persona+workflow
pair, then come here.

## Tools chained

- `cyberos.cuo.execute_workflow` — primary call; returns task_id, status becomes "running"
- `tasks/get` — poll for status (called by host's task subsystem, not directly by you)

## Scopes required

- `cyberos:cuo:execute`
- `cyberos:memory:write` (for audit emission)

## Side effects

- Spawns one Task per invocation (long-running, 30 seconds – several minutes typical)
- Emits 1× `plugin.invoked` audit row at task start
- Emits N× `cuo.step_completed` audit rows during execution
- Emits 1× `cuo.workflow_completed` audit row at finish

## Worked example

```text
User: Run the ADR quick-capture workflow for the CTO with title "Adopt PostgreSQL 16" You: { tool: cyberos.cuo.execute_workflow,
       args: { persona: "chief-technology-officer",
               workflow: "adr-quick-capture",
               inputs: { title: "Adopt PostgreSQL 16" } } }
Host: { task_id: "t-abc123", status: "running" } [host polls via tasks/get; you tell user "started, polling..."] Host: { status: "completed", output: { adr_number: "ADR-2402", artifact_uri: "..." } } You: "ADR-2402 published: Adopt PostgreSQL 16. Took 4.2s."

### Sample `acceptance/TRIGGER_TESTS.md`

```markdown
# Trigger tests — run-cuo-workflow

## Positive (should trigger)

- "Run a CUO workflow"
- "Execute the architect-new-system workflow for the CTO"
- "Kick off ADR quick-capture for adopting PostgreSQL 16"
- "Start a persona workflow"

## Negative (should NOT trigger)

- "Find the right workflow for me" → routes to route-natural-language
- "Show me which workflows exist" → routes to workflow-inspection
- "What did the workflow do last time?" → routes to audit-trail-query
- "Cancel the running workflow" → not a separate skill; this is a tasks/cancel call from host

§4 — Acceptance criteria

  1. Exactly 12 playbook folders existls -d modules/plugin/skills/*/ | wc -l → 12.
  2. Every folder has SKILL.md and acceptance/TRIGGER_TESTS.md — test asserts presence.
  3. Every SKILL.md has frontmatter with name + description + license — test loads YAML.
  4. Every description is 60-480 chars (SKB-020) — test asserts length.
  5. Every description has ≥4 quoted trigger examples (SKB-021) — test counts quotes.
  6. No description contains XML/HTML tags (SKB-022) — regex <[a-zA-Z]+ MUST NOT match.
  7. Every description's verb stems are recognised (SKB-023) — test runs against VERB_STEMS allowlist from TASK-SKILL-115 tooling.
  8. Every TRIGGER_TESTS.md has 4+ positive + 4+ negative fixtures — test parses lists.
  9. Every tool name referenced in body matches TASK-PLUGIN-002 registry — test greps cyberos.<...> patterns and validates.
  10. Body has "When to use" section — test grep.
  11. Body has "Tools chained" section — test grep.
  12. Body has "Scopes required" section — test grep.
  13. Body has "Side effects" section — test grep.
  14. Body has "Worked example" section with a code block — test grep + code-fence check.
  15. 3 orchestration playbooks present — explicit check of folder names.
  16. 3 memory playbooks present — explicit check.
  17. 3 discovery playbooks present — explicit check.
  18. 3 governance playbooks present — explicit check.
  19. Destructive playbook (audit-trail-append) flags side effect in description — test parses description, asserts "write" or "append" phrase.
  20. Manifest skills[] array references all 12 — manifest validator check.

§5 — Verification

# modules/plugin/tests/test_playbooks_conform_to_skb.py
import re, yaml
from pathlib import Path

SKILLS = Path(__file__).parent.parent / "skills"

def test_exactly_twelve_playbooks():
    assert sum(1 for _ in SKILLS.iterdir() if _.is_dir()) == 12

def test_description_skb_020_023():
    for skill_dir in SKILLS.iterdir():
        fm = load_frontmatter(skill_dir / "SKILL.md")
        desc = fm["description"]
        assert 60 <= len(desc) <= 480, f"{skill_dir.name}: SKB-020 length"
        quote_count = desc.count('"')
        assert quote_count >= 8, f"{skill_dir.name}: SKB-021 needs ≥4 quoted examples (saw {quote_count // 2})"
        assert not re.search(r"<[a-zA-Z]+", desc), f"{skill_dir.name}: SKB-022 XML tag"
# modules/plugin/tests/test_playbooks_have_trigger_tests.py
def test_trigger_tests_present_and_balanced():
    for skill_dir in SKILLS.iterdir():
        tt = skill_dir / "acceptance" / "TRIGGER_TESTS.md"
        assert tt.exists(), f"{skill_dir.name}: missing TRIGGER_TESTS.md"
        text = tt.read_text()
        pos_section = text.split("## Positive")[1].split("## Negative")[0]
        neg_section = text.split("## Negative")[1]
        pos_count = sum(1 for line in pos_section.splitlines() if line.startswith("- "))
        neg_count = sum(1 for line in neg_section.splitlines() if line.startswith("- "))
        assert pos_count >= 4 and neg_count >= 4, \
            f"{skill_dir.name}: need ≥4 positive + ≥4 negative (got {pos_count}/{neg_count})"
# modules/plugin/tests/test_playbooks_reference_valid_tools.py
REGISTERED = {
    "cyberos.cuo.list_personas", "cyberos.cuo.list_workflows",
    "cyberos.cuo.route", "cyberos.cuo.execute_workflow",
    "cyberos.memory.read_audit", "cyberos.memory.append_audit",
    "cyberos.skill.list_catalog", "cyberos.skill.invoke_skill",
}

def test_all_referenced_tools_exist():
    pattern = re.compile(r"\bcyberos\.[a-z][a-z0-9]*\.[a-z][a-z0-9_]*\b")
    for skill_dir in SKILLS.iterdir():
        body = (skill_dir / "SKILL.md").read_text()
        for match in pattern.findall(body):
            assert match in REGISTERED, \
                f"{skill_dir.name}: tool '{match}' not in TASK-PLUGIN-002 registry"

§6 — Implementation skeleton

Each of 12 playbooks follows the pattern in §3 sample. Author writes:

Three validator tests enforce conformance.


§7 — Dependencies


§8 — Example payloads

(See §3 for full sample playbook and TRIGGER_TESTS.md.)

Manifest skills[] array entry:

{
  "id": "run-cuo-workflow",
  "path": "skills/run-cuo-workflow/SKILL.md"
}

§9 — Open questions

All resolved.


§10 — Failure modes inventory

FailureDetectionOutcomeRecovery
Description too shortSKB-020 length checktest failsAuthor expands ≥60
Description too longSKB-020 length checktest failsAuthor trims ≤480
Description missing trigger quotesSKB-021 quote counttest failsAuthor adds ≥4 quoted examples
Description has XML tagSKB-022 regextest failsAuthor rewrites without tags
Verb stems unrecognisedSKB-023 allowlisttest failsAuthor uses canonical verbs or extends VERB_STEMS via TASK-SKILL-115
Missing TRIGGER_TESTS.mdfilesystem checktest failsAuthor writes the file
TRIGGER_TESTS imbalanced (<4 pos/neg)line counttest failsAuthor adds fixtures
Tool name typo in bodyregex + registry checktest failsAuthor corrects to SEP-986 name
Body missing required sectiongrep checktest failsAuthor adds section
Playbook count != 12folder counttest failsAuthor adds/removes per task-PLUGIN-004a (additions need task)
Two playbooks with same namefilesysteminstall failsinherent
Playbook rename within v1git diffmanual reviewRevert or bump major
Worked example references missing toolregex + registrytest failsAuthor fixes
Description has unbalanced quotesYAML parse failsYAML loader raisesAuthor closes quotes
Side-effect missing from description for destructive playbookmanual reviewreviewer flagsAuthor adds phrase like "appends to memory"

§11 — Implementation notes


End of TASK-PLUGIN-004 spec.