feat(agent): install compact shared skill

This commit is contained in:
Matt Faltyn
2026-09-11 11:54:37 +02:00
committed by xarmian
parent 328e0a4706
commit cacf492d95
4 changed files with 80 additions and 10 deletions
+1 -1
View File
@@ -97,7 +97,7 @@ pad server info # How this client is connected to Pad
### For AI Agents
**Your agent becomes a project partner.** Install the `/pad` skill once, and your AI coding tool can read, create, and update project items through natural language.
**Your agent becomes a project partner.** Install the `/pad` skill once, and your AI coding tool can read, create, and update project items through natural language. Cursor, Codex, Windsurf, and OpenCode receive a compact dispatcher and load detailed guidance by topic with `pad agent guide`, keeping routine turns small.
```bash
pad agent install # Auto-detects your tools and installs the skill
+8 -3
View File
@@ -6,9 +6,9 @@ import (
"testing"
)
// This initially records the existing shared Cursor/Codex payload with modest
// headroom. Later prompt-reduction changes should lower this budget, not spend it.
const agentSkillPromptBudget = 40 * 1024
// The compact dispatcher should stay small enough to load eagerly. Detailed
// reference material belongs behind `pad agent guide`, not in this payload.
const agentSkillPromptBudget = 5 * 1024
func TestAgentSkillPromptBudget(t *testing.T) {
skill, err := os.ReadFile(filepath.Join("..", "..", "skills", "pad", "SKILL.md"))
@@ -27,6 +27,11 @@ func TestAgentSkillPromptBudget(t *testing.T) {
if len(payload) > agentSkillPromptBudget {
t.Fatalf("%s installed skill payload is %d bytes; budget is %d", agent, len(payload), agentSkillPromptBudget)
}
for _, required := range []string{"pad bootstrap", "issue IDs", "convention_index", "pad agent guide"} {
if !contains(string(payload), required) {
t.Errorf("%s installed skill is missing core guidance %q", agent, required)
}
}
})
}
}
+65 -3
View File
@@ -82,6 +82,68 @@ var SupportedTools = []AgentTool{
},
}
// agentsSkillBody is the eager dispatcher installed for tools that share the
// .agents skill format. The full, canonical guide stays embedded in Pad and is
// available by topic through `pad agent guide`; repeating it here would charge
// Cursor and Codex for reference material on every skill load.
const agentsSkillBody = `# Pad — Talk to Your Project
Use Pad when the user discusses project work: issues, tasks, plans, ideas,
progress, dependencies, conventions, roles, standups, or retrospectives.
## Start every invocation
Run ` + "`pad bootstrap --format json`" + ` before acting. It returns the workspace,
user, collections and schemas, always-on conventions, convention index, roles,
playbooks, dashboard, and recent activity in one call.
- If ` + "`pad`" + ` is missing, ask the user to install it or add it to PATH.
- If bootstrap fails, run ` + "`pad agent guide context-loading`" + ` and follow that
section. Never initialize authentication blindly.
- Follow every body in ` + "`conventions`" + `. Before meaningful work, inspect
` + "`convention_index`" + ` and load bodies for the matching trigger.
- If ` + "`needs_onboarding`" + ` is true, offer setup and wait for consent.
- If roles exist and none was chosen in this conversation, ask once; do not block
if the user declines.
## Act safely
- Use issue IDs such as ` + "`TASK-5`" + `, never slugs.
- Read an item before updating it. Send only changed fields and include a comment
with status changes.
- Read collection schemas instead of guessing field names or terminal statuses.
- Confirm each mutation from the returned object before saying it succeeded.
- Use active playbooks when intent or an invocation slug matches; never run draft
or deprecated playbooks unless the user explicitly asks.
- Prefer summary reads and bounded lists. Fetch full bodies only when needed.
## Common commands
` + "```bash" + `
pad project dashboard --format json
pad item show TASK-5 --format json
pad item list [collection] --format json
pad item create <collection> "Title" [flags]
pad item update TASK-5 [flags]
pad item comment TASK-5 -m "Message"
pad playbook list --format json
pad playbook show <slug> --format markdown
` + "```" + `
Use ` + "`pad <group> <command> --help`" + ` for exact flags.
## Load details only when needed
` + "```bash" + `
pad agent guide # list available topics
pad agent guide items # item commands and contracts
pad agent guide before-performing-work # convention routing
pad agent guide role-awareness # role behavior
pad agent guide multi-step-workflows # planning, ideation, retro, onboarding
pad agent guide all # explicit full reference
` + "```" + `
`
// ResolveTool finds an AgentTool by name or alias. Returns nil if not found.
func ResolveTool(nameOrAlias string) *AgentTool {
lower := strings.ToLower(nameOrAlias)
@@ -206,15 +268,15 @@ func FormatForTool(tool AgentTool, embeddedContent []byte) []byte {
return embeddedContent
case "agents":
// Codex/Cursor/Windsurf/OpenCode use name + description frontmatter
body := StripFrontmatter(embeddedContent)
// Codex/Cursor/Windsurf/OpenCode use a compact eager dispatcher.
// Detailed guidance remains available through `pad agent guide`.
fm := `---
name: pad
description: "Talk to your project. Natural-language project management — create items, check status, create plans, brainstorm ideas, and more."
---
`
return append([]byte(fm), body...)
return []byte(fm + agentsSkillBody)
case "copilot":
// GitHub Copilot uses applyTo frontmatter
+6 -3
View File
@@ -101,7 +101,7 @@ Body content here.
}
})
t.Run("agents has name+description frontmatter", func(t *testing.T) {
t.Run("agents has compact dispatcher", func(t *testing.T) {
tool := *ResolveTool("agents")
got := string(FormatForTool(tool, embedded))
if got[:4] != "---\n" {
@@ -116,8 +116,11 @@ Body content here.
if contains(got, "allowed-tools") {
t.Error("Agents format should NOT contain allowed-tools")
}
if !contains(got, "# Pad Skill") {
t.Error("Agents format should contain body")
if !contains(got, "pad agent guide") {
t.Error("Agents format should point to on-demand guidance")
}
if contains(got, "Body content here") {
t.Error("Agents format should not eagerly copy the full embedded guide")
}
})