Plan: Agent & Skill Frontmatter Fix + End-to-End Verification
Vision
The team of AI agents that runs Lucas Draney's operations. Each agent has a defined personality, role, SOPs, and toolset. Betty Sue coordinates from the main session, spawned agents execute in isolation. Every agent is documented, every workflow is an SOP, every interaction follows convention.
Projects & Repos Touched
| Project/Repo | Platform | Role in this plan |
|---|---|---|
| claude-custom | Forgejo | Agent .md files and skill SKILL.md files live here (~/.claude/agents/, ~/.claude/skills/). This is the enforcement layer — hooks, frontmatter, settings. |
| pal-e-docs (knowledge) | Forgejo | Agent profiles, skill notes, SOPs, templates, enforcement docs — all need alignment. This is where the SOPs live (owned by AI Agency). |
Context
On 2026-02-28, we discovered that all agent files in
~/.claude/agents/ are plain markdown without YAML frontmatter. Claude Code requires YAML frontmatter (name and description at minimum) to recognize files as subagents. Without it, they're invisible — Claude Code doesn't know they exist.Similarly, all skill files in
~/.claude/skills/*/SKILL.md are missing frontmatter. They work as slash commands via backwards compatibility with the old .claude/commands/ format, but they lack configuration (tool restrictions, model selection, context forking, agent delegation).The project page (
project-ai-agency) falsely claims "Profile complete" for all agents. The previous plan (plan-2026-02-25-agent-profiles) delivered markdown content but not Claude Code-compliant configuration.Additionally, multiple pal-e-docs notes are stale: enforcement architecture references deprecated agent names, hook events reference has wrong matcher info for SubagentStart, templates don't document frontmatter, and the agent-workflow SOP uses deprecated names. Approximately 25 notes are also assigned to wrong projects — see
todo-reassign-notes-to-ai-agency for the full inventory.What's already done
- [x] Agent profile content written in pal-e-docs (agent-qa, agent-dev, agent-issue-creator, agent-betty-sue)
- [x] Agent .md files exist in ~/.claude/agents/ (qa.md, dev.md, issue-creator.md, betty-sue.md)
- [x] Skill SKILL.md files exist in ~/.claude/skills/ (plan, review-pr, implement-phase, fix-review, create-issue, ssh-client-setup)
- [x] check-agent-spawn.sh hook enforces "no plan, no agent" on Agent/Task tool (PreToolUse)
- [x] SOP: Claude Config Development is accurate — no changes needed
- [x] YAML frontmatter on agent files — PR #41 merged
- [x] YAML frontmatter on skill files — PR #41 merged
- [x] Agent ↔ skill wiring (context: fork + agent field) — PR #43 merged (convenience wiring, not enforcement)
- [x] Ownership boundary documented — project-claude-config and project-ai-agency updated with enforcement stack
- [x] SOP/template/enforcement doc alignment — Phase 4 DONE (2026-03-01)
- [x] Note project reassignment (~25 notes) —
todo-reassign-notes-to-ai-agencyDONE - [x] SubagentStart docs corrected — cannot block, can only inject context (2026-03-01). All notes updated: hook-events-reference, enforcement-architecture, agent-spawn-conventions, convention-agent-skill-mcp-wiring.
- [x] MCP-in-forked-context test gate PASSED (2026-03-01) —
/review-pr forgejo_admin/claude-custom#43invoked by user. QA agent successfully called mcp__pal-e-docs__get_note, mcp__forgejo__review_pr, and mcp__forgejo__comment_on_pr from inside forked context. MCP tools inherit correctly. - [x] Hook enforcement — PR #45 merged (2026-03-01). SubagentStart context injection + frontmatter PreToolUse hooks. All agents blocked from pal-e-docs writes. QA/Issue Creator blocked from Write/Edit/Bash. Verified live 2026-03-01.
Previous Plan
plan-2026-02-25-agent-profilesDepends On
None.
Decisions Made
| Decision | Rationale |
|---|---|
| <strong>Enforcement stack: hooks are the only hard guarantee</strong> | Agents wrap skills. Skills wrap MCP tools. But none of that is enforcement — it's organizational convenience. The only guaranteed enforcement mechanism is hooks (exit 2 blocks execution). Agent <code>disallowedTools</code> and skill <code>context: fork</code> are useful for organizing work but are not enforcement boundaries. True QA enforcement and template compliance must be done via hooks. |
| <strong>Ownership boundary: AI Agency owns SOPs, Claude Config enforces them</strong> | Claude Config is the technical enforcement layer — hooks, frontmatter, settings.json. It implements SOPs; it doesn't own them. SOPs, agent profiles, skill definitions, templates, and architecture docs are owned by AI Agency. The boundary: "what should happen" = AI Agency, "how it's technically enforced" = Claude Config. |
| betty-sue.md stays as-is (no subagent frontmatter) | Betty Sue is the main session personality injected via SessionStart hook, not a spawned subagent. Making it a subagent would conflict with the main session. |
| Use <code>disallowedTools</code> instead of <code>tools</code> for restricting agents | Per docs: when <code>tools</code> is omitted, agents inherit ALL tools including MCP. Using <code>disallowedTools</code> is cleaner — block what you don't want. The <code>tools</code> field uses internal tool names only (Read, Grep, Glob, Bash, Edit, Write) — MCP tools are NOT listed in the <code>tools</code> field. |
| Use <code>mcpServers</code> to control MCP access per-agent | Per docs: <code>mcpServers</code> field controls which MCP servers are available. Each entry is a server name referencing an already-configured server or inline definition. |
| <strong>SubagentStart CANNOT block — enforcement asymmetry (corrected 2026-03-01)</strong> | Per official Claude Code docs (re-verified 2026-03-01): "SubagentStart hooks cannot block subagent creation." Exit code 2 only shows stderr to user. SubagentStart CAN inject <code>additionalContext</code> into the subagent. This means native delegation cannot be prevented — only guided. Previous plan incorrectly assumed SubagentStart could block via exit 2. All docs corrected. |
| <strong>Layered defense for native delegation</strong> | Since SubagentStart can't block: (1) SubagentStart injects plan context via additionalContext — guidance, (2) Frontmatter PreToolUse hooks enforce tool restrictions inside agents — hard enforcement, (3) disallowedTools provides organizational belt to the frontmatter hook suspenders. This gives us hard tool enforcement even though we can't block the spawn itself. |
| <strong>Skills should use context: fork — CONFIRMED (2026-03-01)</strong> | MCP-in-forked-context test passed. <code>/review-pr</code> invoked live, QA agent successfully used mcp__pal-e-docs__get_note, mcp__forgejo__review_pr, and mcp__forgejo__comment_on_pr from inside forked context. MCP tools inherit into forked subagent context. No revert needed. |
| <strong>No agent writes to pal-e-docs — broadened 2026-03-01</strong> | Original constraint was "Dev agent can't update pal-e-docs notes." Broadened to: ALL agents are blocked from ALL pal-e-docs write operations (7 tools: create_note, update_note, delete_note, update_note_links, create_project, create_repo, update_repo). Rationale: main session owns docs, agents own repos. No exceptions. |
| <strong>disallowedTools strips tools from palette — discovered 2026-03-01</strong> | Testing revealed that <code>disallowedTools</code> removes tools from the agent's tool palette entirely — the agent cannot even attempt the call. This is stronger than frontmatter PreToolUse hooks (which intercept the call). For internal tools (Write/Edit/Bash), disallowedTools is defense layer 1. For MCP tools, frontmatter PreToolUse hooks are defense layer 1 since disallowedTools can't filter individual MCP tools. |
| This is one plan, not a parent plan | Everything here is one coherent fix: align ~/.claude/ files with Claude Code's actual feature set, and align pal-e-docs with reality. Splitting would create coordination overhead with no benefit. |
Documentation Cross-Reference (re-verified 2026-03-01)
Claims verified against official Claude Code docs:
Subagent frontmatter (source)
- Required fields:
name(lowercase, hyphens) anddescription toolsfield: Comma-separated internal tool names. Inherits ALL tools including MCP if omitted.disallowedToolsfield: Tools to deny, removed from inherited or specified list. Verified: strips tools from palette entirely — agent cannot even attempt the call.mcpServersfield: Server name referencing already-configured server OR inline definitionisolationfield: "worktree" for git worktree isolationskillsfield: Skills to preload into context. Full content injected. Subagents don't inherit skills from parent.memoryfield: user/project/local. Automatically enables Read/Write/Edit for memory management.hooksfield: PreToolUse, PostToolUse, Stop (converted to SubagentStop at runtime). Scoped to this subagent only. YAML syntax confirmed — same structure as settings.json but in YAML. Verified: PreToolUse hooks fire inside subagent context and block via exit 2.backgroundfield: Set to true to always run as background task.maxTurnsfield: Max agentic turns before subagent stops.permissionModefield: default, acceptEdits, dontAsk, bypassPermissions, or plan.- Subagents cannot spawn other subagents.
- Subagents receive only their system prompt + basic env, NOT the full Claude Code system prompt.
Frontmatter hooks syntax (confirmed 2026-03-01)
All hook events are supported in frontmatter. For subagents,
Stop hooks are automatically converted to SubagentStop. Hooks use the same configuration format as settings-based hooks but are scoped to the component's lifetime.Skill frontmatter (source)
- No required fields. Only
descriptionis recommended. context: fork: Runs in isolated subagent context. Skill content becomes the prompt. NO conversation history. Only works for skills with explicit task instructions.agent: Which subagent type when context: fork. Built-in (Explore, Plan, general-purpose) OR custom from .claude/agents/.disable-model-invocation: true: Only user can invoke.argument-hint: Hint shown during autocomplete for expected arguments.user-invocable: Set to false to hide from / menu.allowed-tools: Tools Claude can use without asking permission.
Hooks (source)
- SubagentStart: CANNOT block (exit 2 only shows stderr to user). CAN inject additionalContext. Supports matchers by agent type name. Command-only hook type.
- SubagentStop: CAN block via decision: "block" (prevents subagent from stopping). Supports matchers by agent type name. All four hook types supported.
- PreToolUse on Agent: CAN block. Enforcement point for "no plan, no agent" via manual Agent tool calls.
- Subagent frontmatter hooks: PreToolUse, PostToolUse, Stop supported. Scoped to subagent lifetime only. Hard enforcement inside agents.
Phases
Phase 1: Agent frontmatter [DONE]
Slug:
Goal: Add YAML frontmatter to all agent .md files so Claude Code recognizes them as subagents.
Owner: Agent: Dev
Issue: #40 — combined with Phase 2
PR: #41 — merged
phase-2026-02-28-1-agent-frontmatterGoal: Add YAML frontmatter to all agent .md files so Claude Code recognizes them as subagents.
Owner: Agent: Dev
Issue: #40 — combined with Phase 2
PR: #41 — merged
Phase 2: Skill frontmatter [DONE]
Slug:
Goal: Add YAML frontmatter to all skill SKILL.md files.
Owner: Agent: Dev
Issue: #40 — combined with Phase 1
PR: #41 — merged
phase-2026-02-28-2-skill-frontmatterGoal: Add YAML frontmatter to all skill SKILL.md files.
Owner: Agent: Dev
Issue: #40 — combined with Phase 1
PR: #41 — merged
Phase 3: Wire skills to agents — CONVENIENCE WIRING [DONE — FULLY VERIFIED]
Slug:
Goal: Skills that spawn work should delegate to the correct agent via context: fork.
Layer: Convenience — routes work to the right agent but does NOT enforce anything. See enforcement stack in Decisions Made.
Owner: Agent: Dev
Issue: #42 /
PR: #43 — merged. QA approved.
phase-2026-02-28-3-skill-agent-wiringGoal: Skills that spawn work should delegate to the correct agent via context: fork.
Layer: Convenience — routes work to the right agent but does NOT enforce anything. See enforcement stack in Decisions Made.
Owner: Agent: Dev
Issue: #42 /
issue-claude-custom-skill-agent-wiring (resolved)PR: #43 — merged. QA approved.
MCP-in-forked-context test: PASSED (2026-03-01). User invoked
/review-pr forgejo_admin/claude-custom#43. QA agent ran inside forked context and successfully called mcp__pal-e-docs__get_note, mcp__forgejo__review_pr, and mcp__forgejo__comment_on_pr. MCP tools inherit into forked subagent context. Phase 3 is fully complete.Phase 4: Docs, templates, and SOP alignment [DONE]
Slug:
Goal: Update ALL stale pal-e-docs notes to reflect reality. Reassign scattered notes to correct projects per ownership boundary. Purge deprecated agent names.
Owner: Main session (Betty Sue)
Completed: 2026-03-01
phase-2026-02-28-4-docs-alignmentGoal: Update ALL stale pal-e-docs notes to reflect reality. Reassign scattered notes to correct projects per ownership boundary. Purge deprecated agent names.
Owner: Main session (Betty Sue)
Completed: 2026-03-01
Deliverables:
- 25+ notes reassigned from Claude Config/pal-e-docs to AI Agency project
- "Devy"/"Mandy" purged from enforcement-architecture, agent-paradigm, agent-workflow, pr-lifecycle
template-agent— Frontmatter Fields section (12 YAML fields) + File Format section addedtemplate-skill— Frontmatter Fields table (9 fields) + Wiring Pattern section + updated SKILL.md example with frontmatterenforcement-architecture— Full rewrite: enforcement stack hierarchy, SubagentStart/SubagentStop in Pillar 1, mcpServers/disallowedTools in Pillar 4, "Two Spawn Paths" tablehook-events-reference— SubagentStart/SubagentStop rows fixed. Added detail section with matcher examples and input schema.agent-workflow— "Two Spawn Paths" section added (manual vs native delegation)agent-spawn-conventions— "Dual Enforcement" section + "Native Delegation vs Manual Spawning" comparison tableagent-dev,agent-qa,agent-issue-creator— Frontmatter Fields tables added with exact values from ~/.claude/agents/ filesconvention-agent-skill-mcp-wiring— New convention note: full wiring pattern, enforcement stack, current wiring table, dual source of truthtodo-reassign-notes-to-ai-agency— marked done
Docs correction (2026-03-01): After Phase 4 completed, we verified against official Claude Code docs that SubagentStart CANNOT block — only inject context. Four notes corrected: hook-events-reference, enforcement-architecture, agent-spawn-conventions, convention-agent-skill-mcp-wiring. "Dual Enforcement" renamed to "Enforcement Asymmetry" across all docs.
Phase 5: Hook alignment — LAYERED DEFENSE [DONE — VERIFIED]
Slug:
Goal: Add SubagentStart context injection + frontmatter PreToolUse hooks for defense-in-depth. Manual spawns are already enforced (PreToolUse on Agent tool). Native delegation needs layered defense since SubagentStart cannot block.
Layer: Mixed — SubagentStart is guidance (additionalContext), frontmatter PreToolUse is hard enforcement (exit 2 blocks tool use).
Owner: Agent: Dev
Issue: #44 /
PR: #45 — merged. QA approved (3 review rounds). Scope broadened during review: all agents blocked from all pal-e-docs writes (not just Dev from notes).
phase-2026-02-28-5-hook-alignmentGoal: Add SubagentStart context injection + frontmatter PreToolUse hooks for defense-in-depth. Manual spawns are already enforced (PreToolUse on Agent tool). Native delegation needs layered defense since SubagentStart cannot block.
Layer: Mixed — SubagentStart is guidance (additionalContext), frontmatter PreToolUse is hard enforcement (exit 2 blocks tool use).
Owner: Agent: Dev
Issue: #44 /
issue-claude-custom-phase5-layered-defense-hooks (resolved)PR: #45 — merged. QA approved (3 review rounds). Scope broadened during review: all agents blocked from all pal-e-docs writes (not just Dev from notes).
Enforcement Asymmetry (verified 2026-03-01):
| Spawn path | Can block spawn? | Can inject context? | Can enforce tool use? |
|---|---|---|---|
| Manual (Agent tool) | <strong>Yes</strong> — PreToolUse deny | Yes — via prompt | Yes — PreToolUse hooks |
| Native delegation | <strong>No</strong> — SubagentStart cannot block | Yes — additionalContext | Yes — frontmatter PreToolUse hooks |
Live test results (2026-03-01):
| Agent | Action tested | Result | Enforcement layer |
|---|---|---|---|
| QA | Write tool | <strong>BLOCKED</strong> | <code>disallowedTools</code> strips from palette — can't even attempt |
| QA | Edit tool | <strong>BLOCKED</strong> | <code>disallowedTools</code> strips from palette |
| QA | mcp__pal-e-docs__update_note | <strong>BLOCKED</strong> | Frontmatter PreToolUse hook (<code>block-docs-writes.sh</code>, exit 2) |
| Dev | mcp__pal-e-docs__create_note | <strong>BLOCKED</strong> | Frontmatter PreToolUse hook (<code>block-docs-writes.sh</code>, exit 2) |
| Dev | mcp__pal-e-docs__update_note | <strong>BLOCKED</strong> | Frontmatter PreToolUse hook (<code>block-docs-writes.sh</code>, exit 2) |
| Dev | Write tool (no issue) | <strong>BLOCKED</strong> | Settings PreToolUse hook (<code>check-issue.sh</code> — bonus layer) |
| Dev | Read tool | <strong>ALLOWED</strong> | No restriction — correct |
Key finding:
disallowedTools strips internal tools (Write/Edit/Bash) from the agent's tool palette entirely — the agent cannot even attempt the call. This is defense layer 1 for internal tools. For MCP tools, frontmatter PreToolUse hooks are defense layer 1 since disallowedTools cannot filter individual MCP tools (only mcpServers controls server-level access). The existing check-issue.sh hook provides a bonus layer for Dev's Write/Edit calls — they require an active issue even when the tool is available.Key Files
| Phase | File | Repo/Location | Change |
|---|---|---|---|
| 1 | ~/.claude/agents/{qa,dev,issue-creator}.md | claude-custom | Add YAML frontmatter |
| 2 | ~/.claude/skills/*/SKILL.md (6 files) | claude-custom | Add YAML frontmatter |
| 3 | ~/.claude/skills/{review-pr,implement-phase,fix-review,create-issue}/SKILL.md | claude-custom | Add context: fork + agent (convenience) |
| 4 | ~25 pal-e-docs notes | pal-e-docs | Reassign to AI Agency project per ownership boundary |
| 4 | enforcement-architecture, agent-paradigm, agent-workflow, pr-lifecycle | pal-e-docs | Purge deprecated agent names, add enforcement stack |
| 4 | template-agent, template-skill | pal-e-docs | Add frontmatter sections |
| 4 | enforcement-architecture, hook-events-reference | pal-e-docs | Add enforcement stack, fix SubagentStart info |
| 4 | agent-workflow, agent-spawn-conventions | pal-e-docs | Add native delegation + enforcement asymmetry |
| 4 | agent-dev, agent-qa, agent-issue-creator | pal-e-docs | Add frontmatter fields tables |
| 4 | convention-agent-skill-mcp-wiring | pal-e-docs | New convention note |
| 5 | ~/.claude/hooks/inject-subagent-context.sh | claude-custom | New — SubagentStart context injection script |
| 5 | ~/.claude/settings.json | claude-custom | Add SubagentStart hook with matchers (context injection) |
| 5 | ~/.claude/hooks/block-write-tools.sh | claude-custom | New — blocks Write/Edit/Bash (for QA + Issue Creator frontmatter hooks) |
| 5 | ~/.claude/hooks/block-docs-writes.sh | claude-custom | New — blocks ALL pal-e-docs write MCP calls (for ALL agents) |
| 5 | ~/.claude/agents/{qa,dev,issue-creator}.md | claude-custom | Add frontmatter PreToolUse hooks (hard enforcement) — both write tools + docs writes |
Verification
- [x]
claude agentslists qa, dev, issue-creator — PR #41 merged - [x] Ownership boundary documented on project-claude-config and project-ai-agency
- [x] Enforcement stack documented (hooks > agents > skills > MCP)
- [x] Skill-to-agent wiring merged — PR #43 (convenience layer)
- [x] template-agent has frontmatter section — Phase 4
- [x] template-skill has frontmatter section — Phase 4
- [x] No deprecated agent names in any pal-e-docs note — Phase 4
- [x] All operational notes assigned to AI Agency project per ownership boundary — Phase 4
- [x] hook-events-reference shows SubagentStart CANNOT block + CAN inject context — corrected 2026-03-01
- [x] enforcement-architecture includes enforcement asymmetry — corrected 2026-03-01
- [x] agent-spawn-conventions documents enforcement asymmetry — corrected 2026-03-01
- [x] MCP tools work inside forked subagent context — PASSED 2026-03-01. /review-pr invoked, QA agent used pal-e-docs + forgejo MCP successfully.
- [x]
/review-prruns inside QA agent context via context: fork — verified 2026-03-01 - [x] SubagentStart hook injects additionalContext into spawned agents — verified 2026-03-01. Both QA and Dev agents received context guidance on spawn.
- [x] QA agent cannot use Write, Edit, or Bash — verified 2026-03-01.
disallowedToolsstrips them from palette entirely. - [x] QA agent CAN use mcp__forgejo__review_pr and mcp__pal-e-docs__get_note — verified via /review-pr test 2026-03-01.
- [x] Dev agent cannot write to pal-e-docs — verified 2026-03-01.
block-docs-writes.shblocks create_note, update_note with exit 2. - [x] Dev agent launches in worktree — verified 2026-03-01 during Phase 5 implementation (agent ran in isolation: worktree).
- [x] Frontmatter PreToolUse hooks fire inside subagent context — VERIFIED 2026-03-01. QA: pal-e-docs update_note blocked. Dev: pal-e-docs create_note and update_note blocked. Hard enforcement working.
- [x] All agents blocked from ALL pal-e-docs writes (7 tools) — broadened from "Dev only" to "all agents" during QA review 2026-03-01.
Next Plan Seeds
- Agent memory: add
memory: userto agents so they build knowledge over time - Background agents: evaluate
background: truefor Dev agent during long implementations - Agent teams: evaluate Claude Code agent teams feature for multi-agent parallel work
- Plugin packaging: package agents + skills as a Claude Code plugin for portability
Related
plan-2026-02-25-agent-profiles— previous plantodo-fix-agent-skill-frontmatter— the TODO that triggered thistodo-reassign-notes-to-ai-agency— note project reassignment + deprecated name cleanup (DONE)agent-workflow— operating model SOP (updated Phase 4)agent-spawn-conventions— spawn axiom + enforcement asymmetry (corrected 2026-03-01)enforcement-architecture— four pillars + enforcement asymmetry (corrected 2026-03-01)hook-events-reference— event reference + SubagentStart cannot block (corrected 2026-03-01)convention-agent-skill-mcp-wiring— wiring convention (corrected 2026-03-01)template-agent— agent template (updated Phase 4)template-skill— skill template (updated Phase 4)project-ai-agency— project page (updated with ownership boundary)project-claude-config— project page (updated with enforcement stack)sop-claude-config-development— development SOP (accurate, no changes)- Claude Code subagent docs
- Claude Code skills docs
- Claude Code hooks docs
- Claude Code permissions docs