kushi-agents 5.0.2 → 5.0.4

This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
Files changed (62) hide show
  1. package/README.md +35 -0
  2. package/bin/cli.mjs +103 -0
  3. package/package.json +6 -2
  4. package/plugin/agents/kushi.agent.md +3 -1
  5. package/plugin/instructions/skill-authoring.instructions.md +147 -0
  6. package/plugin/instructions/skill-evals.instructions.md +130 -0
  7. package/plugin/skills/aggregate-project/evals/evals.json +33 -0
  8. package/plugin/skills/apply-ado-update/evals/evals.json +33 -0
  9. package/plugin/skills/ask-project/SKILL.md +10 -0
  10. package/plugin/skills/ask-project/evals/evals.json +34 -0
  11. package/plugin/skills/bootstrap-project/evals/evals.json +34 -0
  12. package/plugin/skills/build-state/evals/evals.json +31 -0
  13. package/plugin/skills/consolidate-evidence/evals/evals.json +33 -0
  14. package/plugin/skills/dashboard/evals/evals.json +33 -0
  15. package/plugin/skills/emit-vertex/evals/evals.json +33 -0
  16. package/plugin/skills/eval/SKILL.md +90 -0
  17. package/plugin/skills/eval/evals.schema.json +73 -0
  18. package/plugin/skills/eval/run-evals.ps1 +372 -0
  19. package/plugin/skills/fde-intake/evals/evals.json +33 -0
  20. package/plugin/skills/fde-report/evals/evals.json +33 -0
  21. package/plugin/skills/fde-triage/evals/evals.json +33 -0
  22. package/plugin/skills/intro/SKILL.md +160 -451
  23. package/plugin/skills/intro/evals/evals.json +33 -0
  24. package/plugin/skills/intro/references/walkthrough.md +310 -0
  25. package/plugin/skills/link-entities/evals/evals.json +31 -0
  26. package/plugin/skills/project-status/SKILL.md +10 -1
  27. package/plugin/skills/project-status/evals/evals.json +33 -0
  28. package/plugin/skills/propose-ado-update/evals/evals.json +33 -0
  29. package/plugin/skills/pull-ado/evals/evals.json +35 -0
  30. package/plugin/skills/pull-crm/evals/evals.json +35 -0
  31. package/plugin/skills/pull-email/evals/evals.json +35 -0
  32. package/plugin/skills/pull-loop/evals/evals.json +35 -0
  33. package/plugin/skills/pull-meetings/evals/evals.json +35 -0
  34. package/plugin/skills/pull-misc/evals/evals.json +35 -0
  35. package/plugin/skills/pull-onenote/evals/evals.json +35 -0
  36. package/plugin/skills/pull-sharepoint/evals/evals.json +35 -0
  37. package/plugin/skills/pull-teams/evals/evals.json +35 -0
  38. package/plugin/skills/refresh-project/evals/evals.json +31 -0
  39. package/plugin/skills/self-check/SKILL.md +2 -0
  40. package/plugin/skills/self-check/evals/evals.json +28 -0
  41. package/plugin/skills/self-check/run.ps1 +144 -0
  42. package/plugin/skills/setup/SKILL.md +10 -0
  43. package/plugin/skills/setup/evals/evals.json +33 -0
  44. package/plugin/skills/skill-checker/SKILL.md +136 -0
  45. package/plugin/skills/skill-checker/check-skill.ps1 +416 -0
  46. package/plugin/skills/skill-checker/evals/evals.json +41 -0
  47. package/plugin/skills/skill-creator/SKILL.md +134 -0
  48. package/plugin/skills/skill-creator/evals/evals.json +40 -0
  49. package/plugin/skills/skill-creator/generate-eval-review.ps1 +101 -0
  50. package/plugin/skills/skill-creator/optimize-description.ps1 +87 -0
  51. package/plugin/skills/skill-creator/scaffold.ps1 +180 -0
  52. package/plugin/skills/skill-creator/templates/evals-starter.template.json +27 -0
  53. package/plugin/skills/skill-creator/templates/gotchas-stub.template.md +9 -0
  54. package/plugin/skills/skill-creator/templates/skill-skeleton.template.md +28 -0
  55. package/plugin/skills/tour/evals/evals.json +33 -0
  56. package/plugin/skills/vertex-link/SKILL.md +10 -0
  57. package/plugin/skills/vertex-link/evals/evals.json +33 -0
  58. package/src/eval-aggregator.mjs +209 -0
  59. package/src/eval-aggregator.test.mjs +64 -0
  60. package/src/eval-runner.test.mjs +69 -0
  61. package/src/skill-checker.test.mjs +118 -0
  62. package/src/skill-creator.test.mjs +92 -0
@@ -0,0 +1,101 @@
1
+ <#
2
+ .SYNOPSIS
3
+ Renders an HTML side-by-side eval-review viewer for a skill.
4
+
5
+ .DESCRIPTION
6
+ Scans Evidence/_evals/ for the most recent per-run JSON files belonging to
7
+ -Skill, picks the two newest (or up to -MaxRuns), and renders a static HTML page
8
+ that shows per-case pass/fail + duration side-by-side. Output is gitignored.
9
+
10
+ If no eval runs are found, emits a stub page noting "no runs yet — run
11
+ `npm run eval -- <skill>` first" so the viewer command never silently fails.
12
+
13
+ .PARAMETER Skill
14
+ Skill name (matches plugin/skills/<name>/).
15
+
16
+ .PARAMETER Output
17
+ Override output path. Default: Evidence/_skill-creator/<skill>/review.html.
18
+
19
+ .PARAMETER MaxRuns
20
+ Maximum number of runs to include side-by-side (default 2).
21
+
22
+ .PARAMETER Root
23
+ Repo root (default: 3 levels above this script).
24
+ #>
25
+ [CmdletBinding()]
26
+ param(
27
+ [Parameter(Mandatory=$true)][string]$Skill,
28
+ [string]$Output,
29
+ [int]$MaxRuns = 2,
30
+ [string]$Root = (Resolve-Path (Join-Path $PSScriptRoot "..\..\..")).Path
31
+ )
32
+
33
+ $ErrorActionPreference = 'Stop'
34
+
35
+ if (-not $Output) {
36
+ $Output = Join-Path $Root "Evidence/_skill-creator/$Skill/review.html"
37
+ }
38
+ $outDir = Split-Path -Parent $Output
39
+ New-Item -ItemType Directory -Force -Path $outDir | Out-Null
40
+
41
+ $evalsDir = Join-Path $Root 'Evidence/_evals'
42
+ $runs = @()
43
+ if (Test-Path $evalsDir) {
44
+ $runs = Get-ChildItem -Path $evalsDir -Filter '*.json' -File -ErrorAction SilentlyContinue |
45
+ Sort-Object LastWriteTime -Descending |
46
+ Where-Object {
47
+ try {
48
+ $j = Get-Content -Raw $_.FullName | ConvertFrom-Json
49
+ $j.cases | Where-Object { $_.skill -eq $Skill -or $j.skill -eq $Skill }
50
+ } catch { $false }
51
+ } |
52
+ Select-Object -First $MaxRuns
53
+ }
54
+
55
+ function HtmlEncode { param([string]$s) [System.Net.WebUtility]::HtmlEncode([string]$s) }
56
+
57
+ $sb = New-Object System.Text.StringBuilder
58
+ [void]$sb.AppendLine('<!doctype html><html><head><meta charset="utf-8">')
59
+ [void]$sb.AppendLine("<title>Skill review — $(HtmlEncode $Skill)</title>")
60
+ [void]$sb.AppendLine('<style>body{font-family:system-ui,sans-serif;margin:2em;}table{border-collapse:collapse;width:100%;}th,td{border:1px solid #ccc;padding:.4em .6em;text-align:left;vertical-align:top;}.pass{background:#dfd}.fail{background:#fdd}.skip{background:#eee;color:#666}.meta{color:#666;font-size:.9em}code{background:#f4f4f4;padding:0 .2em}</style>')
61
+ [void]$sb.AppendLine('</head><body>')
62
+ [void]$sb.AppendLine("<h1>Skill review — <code>$(HtmlEncode $Skill)</code></h1>")
63
+ [void]$sb.AppendLine("<p class='meta'>Generated $(Get-Date -Format o). Source: <code>Evidence/_evals/</code> (gitignored).</p>")
64
+
65
+ if (-not $runs -or $runs.Count -eq 0) {
66
+ [void]$sb.AppendLine("<p><strong>No eval runs found for <code>$(HtmlEncode $Skill)</code>.</strong></p>")
67
+ [void]$sb.AppendLine("<p>Run <code>npm run eval -- $(HtmlEncode $Skill)</code> first, then re-render.</p>")
68
+ } else {
69
+ [void]$sb.AppendLine('<table><thead><tr><th>Case</th>')
70
+ foreach ($r in $runs) { [void]$sb.AppendLine("<th>$(HtmlEncode $r.Name)</th>") }
71
+ [void]$sb.AppendLine('</tr></thead><tbody>')
72
+
73
+ # Build a unified case-id list across runs.
74
+ $parsed = $runs | ForEach-Object { Get-Content -Raw $_.FullName | ConvertFrom-Json }
75
+ $caseIds = @()
76
+ foreach ($p in $parsed) {
77
+ foreach ($c in $p.cases) { if ($caseIds -notcontains $c.id) { $caseIds += $c.id } }
78
+ }
79
+ foreach ($cid in $caseIds) {
80
+ [void]$sb.AppendLine("<tr><td><code>$(HtmlEncode $cid)</code></td>")
81
+ for ($i = 0; $i -lt $parsed.Count; $i++) {
82
+ $hit = $parsed[$i].cases | Where-Object { $_.id -eq $cid } | Select-Object -First 1
83
+ if (-not $hit) {
84
+ [void]$sb.AppendLine("<td class='skip'>—</td>")
85
+ } else {
86
+ $cls = if ($hit.skipped) { 'skip' } elseif ($hit.pass) { 'pass' } else { 'fail' }
87
+ $label = if ($hit.skipped) { 'skip' } elseif ($hit.pass) { 'pass' } else { 'fail' }
88
+ $dur = if ($hit.duration_ms) { "$($hit.duration_ms) ms" } else { '' }
89
+ [void]$sb.AppendLine("<td class='$cls'><strong>$label</strong> <span class='meta'>$dur</span></td>")
90
+ }
91
+ }
92
+ [void]$sb.AppendLine('</tr>')
93
+ }
94
+ [void]$sb.AppendLine('</tbody></table>')
95
+ }
96
+
97
+ [void]$sb.AppendLine('</body></html>')
98
+
99
+ Set-Content -LiteralPath $Output -Value $sb.ToString() -Encoding UTF8
100
+ Write-Host "skill-creator: wrote review viewer → $Output"
101
+ exit 0
@@ -0,0 +1,87 @@
1
+ <#
2
+ .SYNOPSIS
3
+ Rewrites a kushi skill description per the agentskills.io optimization rules.
4
+
5
+ .DESCRIPTION
6
+ Applies these transforms (idempotent):
7
+ 1. Ensure the description leads with "USE WHEN " in the first 160 chars.
8
+ 2. Ensure a "DO NOT USE" clause is present.
9
+ 3. Strip marketing words: powerful, comprehensive, blazing, seamless, simple,
10
+ effortless, robust, cutting-edge, world-class.
11
+ 4. Collapse internal whitespace; trim to 1024 chars.
12
+
13
+ Prints a unified diff (current → rewritten) by default; -Quiet emits only the
14
+ rewritten string for piping into scaffold.ps1.
15
+
16
+ .PARAMETER Description
17
+ The description string to rewrite.
18
+
19
+ .PARAMETER Quiet
20
+ Suppress the diff; print only the rewritten string.
21
+ #>
22
+ [CmdletBinding()]
23
+ param(
24
+ [Parameter(Mandatory=$true)][string]$Description,
25
+ [switch]$Quiet
26
+ )
27
+
28
+ $ErrorActionPreference = 'Stop'
29
+
30
+ function Optimize-Description {
31
+ param([string]$Text)
32
+ if (-not $Text) { return '' }
33
+
34
+ $out = $Text.Trim()
35
+
36
+ # 1) Marketing-word strip.
37
+ $bad = @('powerful', 'comprehensive', 'blazing', 'seamless', 'simple',
38
+ 'effortless', 'robust', 'cutting-edge', 'world-class', 'next-generation')
39
+ foreach ($w in $bad) {
40
+ $out = [regex]::Replace($out, "\b$w\s*", '', 'IgnoreCase')
41
+ }
42
+
43
+ # 2) Collapse whitespace.
44
+ $out = [regex]::Replace($out, '\s+', ' ').Trim()
45
+
46
+ # 3) Ensure leading USE WHEN.
47
+ if ($out.Substring(0, [Math]::Min(160, $out.Length)) -notmatch '\bUSE WHEN\b') {
48
+ # If a plain "When " is present, upgrade it; else prepend a placeholder.
49
+ if ($out -match '^\s*[Ww]hen\b') {
50
+ $out = $out -replace '^\s*[Ww]hen\b', 'USE WHEN'
51
+ } else {
52
+ $out = "USE WHEN <TODO: trigger>. $out"
53
+ }
54
+ }
55
+
56
+ # 4) Ensure a DO NOT USE clause.
57
+ if ($out -notmatch '(?i)\bDO NOT USE\b') {
58
+ # Insert after the first sentence terminator if any.
59
+ if ($out -match '^(.+?\.)\s+(.+)$') {
60
+ $out = "$($Matches[1]) DO NOT USE FOR <TODO: near-miss>. $($Matches[2])"
61
+ } else {
62
+ $out = "$out DO NOT USE FOR <TODO: near-miss>."
63
+ }
64
+ }
65
+
66
+ # 5) Re-collapse whitespace after edits.
67
+ $out = [regex]::Replace($out, '\s+', ' ').Trim()
68
+
69
+ # 6) Hard cap 1024 chars.
70
+ if ($out.Length -gt 1024) { $out = $out.Substring(0, 1024) }
71
+
72
+ return $out
73
+ }
74
+
75
+ $rewritten = Optimize-Description -Text $Description
76
+
77
+ if (-not $Quiet) {
78
+ Write-Host "--- before"
79
+ Write-Host $Description
80
+ Write-Host "+++ after"
81
+ Write-Host $rewritten
82
+ Write-Host ""
83
+ }
84
+
85
+ # Always emit the rewritten string on stdout (consumed by scaffold.ps1).
86
+ [Console]::Out.Write($rewritten)
87
+ exit 0
@@ -0,0 +1,180 @@
1
+ <#
2
+ .SYNOPSIS
3
+ skill-creator scaffold — emits a conformant plugin/skills/<name>/ tree.
4
+
5
+ .DESCRIPTION
6
+ Reads templates/skill-skeleton.template.md + evals-starter.template.json + (for
7
+ pull/writer) gotchas-stub.template.md, substitutes {{NAME}}/{{DESCRIPTION}}/
8
+ {{TYPE_SECTION}}, and writes the new skill folder. Adds a `.created-by-skill-
9
+ creator` marker so D34.creator-output-conforms can enforce strict lint.
10
+
11
+ Doctrine: plugin/instructions/skill-authoring.instructions.md.
12
+
13
+ .PARAMETER Name
14
+ Skill directory + front-matter name. Kebab-case, verb-led.
15
+
16
+ .PARAMETER Type
17
+ One of: pull, writer, orchestrator, other.
18
+ pull → injects ## Gotchas section
19
+ writer → injects ## Validation loop section
20
+ orchestrator → injects ## Step checklist section
21
+ other → injects ## Steps (generic) — author must add at least one of
22
+ Gotchas / Validation loop / Step checklist before lint passes.
23
+
24
+ .PARAMETER Description
25
+ Front-matter description string. Auto-rewritten via optimize-description.ps1.
26
+
27
+ .PARAMETER Force
28
+ Overwrite an existing skill folder.
29
+
30
+ .PARAMETER DryRun
31
+ Print actions only; write nothing.
32
+
33
+ .PARAMETER Root
34
+ Repo root (default: 3 levels above this script).
35
+ #>
36
+ [CmdletBinding()]
37
+ param(
38
+ [Parameter(Mandatory=$true)][string]$Name,
39
+ [Parameter(Mandatory=$true)][ValidateSet('pull','writer','orchestrator','other')][string]$Type,
40
+ [Parameter(Mandatory=$true)][string]$Description,
41
+ [switch]$Force,
42
+ [switch]$DryRun,
43
+ [string]$Root = (Resolve-Path (Join-Path $PSScriptRoot "..\..\..")).Path
44
+ )
45
+
46
+ $ErrorActionPreference = 'Stop'
47
+
48
+ if ($Name -notmatch '^[a-z][a-z0-9]*(-[a-z0-9]+)*$') {
49
+ throw "Name '$Name' is not kebab-case. Use lowercase letters, digits, and single hyphens (e.g. 'pull-onenote')."
50
+ }
51
+
52
+ $templatesDir = Join-Path $PSScriptRoot 'templates'
53
+ $optimizer = Join-Path $PSScriptRoot 'optimize-description.ps1'
54
+ $skillDir = Join-Path $Root "plugin/skills/$Name"
55
+ $skillMd = Join-Path $skillDir 'SKILL.md'
56
+ $evalsDir = Join-Path $skillDir 'evals'
57
+ $evalsJson = Join-Path $evalsDir 'evals.json'
58
+ $marker = Join-Path $skillDir '.created-by-skill-creator'
59
+
60
+ if ((Test-Path $skillDir) -and -not $Force) {
61
+ throw "Skill folder already exists: $skillDir. Pass -Force to overwrite."
62
+ }
63
+
64
+ # 1) Optimize description (best-effort; falls back to as-is on error).
65
+ $optimized = $Description
66
+ if (Test-Path $optimizer) {
67
+ try {
68
+ $optimized = (& pwsh -NoProfile -File $optimizer -Description $Description -Quiet).Trim()
69
+ if (-not $optimized) { $optimized = $Description }
70
+ } catch {
71
+ Write-Warning "optimize-description failed: $($_.Exception.Message); using as-is."
72
+ $optimized = $Description
73
+ }
74
+ }
75
+ # Escape double quotes for safe YAML embedding.
76
+ $escaped = $optimized -replace '"', '\"'
77
+
78
+ # 2) Pick type-specific section.
79
+ function Get-TypeSection {
80
+ param([string]$Type, [string]$TemplatesDir)
81
+ switch ($Type) {
82
+ 'pull' {
83
+ $g = Join-Path $TemplatesDir 'gotchas-stub.template.md'
84
+ return (Get-Content -Raw $g)
85
+ }
86
+ 'writer' {
87
+ return @'
88
+ ## Validation loop
89
+
90
+ After writing outputs:
91
+
92
+ 1. Run self-check targeted at this skill: `pwsh plugin/skills/self-check/run.ps1 -Targeted <area>`
93
+ 2. If failures: fix and re-run the affected step (not the whole skill).
94
+ 3. Repeat until self-check exits 0.
95
+ 4. Only then update `run-log.yml` with success status.
96
+
97
+ <!-- TODO(skill-creator): replace <area> with the targeted-scope substring for this skill. -->
98
+ '@
99
+ }
100
+ 'orchestrator' {
101
+ return @'
102
+ ## Step checklist
103
+
104
+ - [ ] Step 1 — <!-- TODO(skill-creator): first concrete action -->
105
+ - [ ] Step 2 — <!-- TODO(skill-creator): second concrete action -->
106
+ - [ ] Step 3 — <!-- TODO(skill-creator): third concrete action -->
107
+ - [ ] Final — Run self-check + evals; only commit on green.
108
+ '@
109
+ }
110
+ default {
111
+ return @'
112
+ ## Steps
113
+
114
+ 1. <!-- TODO(skill-creator): first step -->
115
+ 2. <!-- TODO(skill-creator): second step -->
116
+
117
+ ## Validation loop
118
+
119
+ <!-- TODO(skill-creator): describe how to verify this skill ran correctly.
120
+ Every kushi skill SHOULD ship one of: Gotchas / Validation loop / Step checklist.
121
+ Replace this block with the right section for your skill, or keep it. -->
122
+
123
+ 1. Run `pwsh plugin/skills/self-check/run.ps1 -Targeted <area>`.
124
+ 2. Fix any findings, then re-run.
125
+ '@
126
+ }
127
+ }
128
+ }
129
+ $typeSection = Get-TypeSection -Type $Type -TemplatesDir $templatesDir
130
+
131
+ # 3) Render SKILL.md.
132
+ $skeleton = Get-Content -Raw (Join-Path $templatesDir 'skill-skeleton.template.md')
133
+ $skillContent = $skeleton `
134
+ -replace '\{\{NAME\}\}', $Name `
135
+ -replace '\{\{DESCRIPTION\}\}', $escaped `
136
+ -replace '\{\{TYPE_SECTION\}\}', [regex]::Escape($typeSection)
137
+ # Undo escape (we used [regex]::Escape to preserve $ etc — restore literal).
138
+ $skillContent = $skillContent -replace [regex]::Escape([regex]::Escape($typeSection)), $typeSection
139
+ # Simpler approach: do the replacement once with literal substitution.
140
+ $skillContent = $skeleton.Replace('{{NAME}}', $Name).Replace('{{DESCRIPTION}}', $escaped).Replace('{{TYPE_SECTION}}', $typeSection)
141
+
142
+ # 4) Render evals/evals.json.
143
+ $evalsTemplate = Get-Content -Raw (Join-Path $templatesDir 'evals-starter.template.json')
144
+ $nameSlug = ($Name -replace '[^a-z0-9-]', '-')
145
+ $evalsContent = $evalsTemplate.Replace('{{NAME}}', $Name).Replace('{{NAME_SLUG}}', $nameSlug)
146
+
147
+ # 5) Write everything (or just print under -DryRun).
148
+ $actions = @(
149
+ "mkdir $skillDir",
150
+ "mkdir $evalsDir",
151
+ "write $skillMd ($(($skillContent -split "`n").Count) lines)",
152
+ "write $evalsJson",
153
+ "write $marker"
154
+ )
155
+ Write-Host ""
156
+ Write-Host "skill-creator: scaffolding '$Name' (type=$Type) under $Root"
157
+ foreach ($a in $actions) { Write-Host " - $a" }
158
+ Write-Host ""
159
+
160
+ if ($DryRun) {
161
+ Write-Host "skill-creator: -DryRun set; no files written."
162
+ exit 0
163
+ }
164
+
165
+ if ((Test-Path $skillDir) -and $Force) {
166
+ Remove-Item -LiteralPath $skillDir -Recurse -Force
167
+ }
168
+ New-Item -ItemType Directory -Force -Path $skillDir | Out-Null
169
+ New-Item -ItemType Directory -Force -Path $evalsDir | Out-Null
170
+
171
+ Set-Content -LiteralPath $skillMd -Value $skillContent -Encoding UTF8 -NoNewline
172
+ Set-Content -LiteralPath $evalsJson -Value $evalsContent -Encoding UTF8 -NoNewline
173
+ Set-Content -LiteralPath $marker -Value "Created by skill-creator on $(Get-Date -Format o).`nDelete this file only if the skill is intentionally non-conformant.`n" -Encoding UTF8
174
+
175
+ Write-Host "skill-creator: done. Next steps:"
176
+ Write-Host " 1. grep 'TODO(skill-creator)' $skillMd — fill in placeholders"
177
+ Write-Host " 2. pwsh plugin/skills/skill-checker/check-skill.ps1 -Skill $Name"
178
+ Write-Host " 3. npm run eval -- $Name"
179
+ Write-Host ""
180
+ exit 0
@@ -0,0 +1,27 @@
1
+ {
2
+ "skill": "{{NAME}}",
3
+ "version": "0.1.0",
4
+ "description": "Starter evals for {{NAME}}. Replace cases as soon as the skill has real behavior to assert.",
5
+ "cases": [
6
+ {
7
+ "id": "{{NAME_SLUG}}-skillmd-exists",
8
+ "name": "SKILL.md exists for {{NAME}}",
9
+ "input": "verify {{NAME}} skill artifacts",
10
+ "canary": false,
11
+ "grader_type": "script",
12
+ "expected_assertions": [
13
+ { "type": "file-exists", "path": "plugin/skills/{{NAME}}/SKILL.md" }
14
+ ]
15
+ },
16
+ {
17
+ "id": "{{NAME_SLUG}}-description-optimized",
18
+ "name": "SKILL.md description leads with USE WHEN",
19
+ "input": "verify {{NAME}} description shape",
20
+ "canary": false,
21
+ "grader_type": "script",
22
+ "expected_assertions": [
23
+ { "type": "file-contains", "path": "plugin/skills/{{NAME}}/SKILL.md", "value": "USE WHEN" }
24
+ ]
25
+ }
26
+ ]
27
+ }
@@ -0,0 +1,9 @@
1
+ ## Gotchas
2
+
3
+ <!-- TODO(skill-creator): top-5 failure modes. Each bullet starts with the concrete failure, then the correction. -->
4
+
5
+ - **<failure mode 1>** → <correction>
6
+ - **<failure mode 2>** → <correction>
7
+ - **<failure mode 3>** → <correction>
8
+ - **<failure mode 4>** → <correction>
9
+ - **<failure mode 5>** → <correction>
@@ -0,0 +1,28 @@
1
+ ---
2
+ name: "{{NAME}}"
3
+ version: "0.1.0"
4
+ description: "{{DESCRIPTION}}"
5
+ ---
6
+
7
+ # Skill: {{NAME}}
8
+
9
+ <!-- TODO(skill-creator): one-paragraph purpose. What does this skill DO, and when does it trigger? -->
10
+
11
+ User triggers: <!-- TODO(skill-creator): list the literal user phrases / verbs that should route here. -->
12
+
13
+ ## USE WHEN
14
+
15
+ - <!-- TODO(skill-creator): situational trigger 1 -->
16
+ - <!-- TODO(skill-creator): situational trigger 2 -->
17
+
18
+ ## DO NOT USE FOR
19
+
20
+ - <!-- TODO(skill-creator): the most likely near-miss invocation -->
21
+
22
+ {{TYPE_SECTION}}
23
+
24
+ ## References
25
+
26
+ - `plugin/instructions/skill-authoring.instructions.md`
27
+ - `plugin/instructions/agentskills-compliance.instructions.md`
28
+ <!-- TODO(skill-creator): add doctrine + reference pack links relevant to this skill. -->
@@ -0,0 +1,33 @@
1
+ {
2
+ "skill": "tour",
3
+ "version": "1.0.0",
4
+ "description": "Auto-seeded evals for tour. Replace with real cases as the skill matures.",
5
+ "cases": [
6
+ {
7
+ "id": "tour-smoke-1",
8
+ "name": "tour produces a non-empty response",
9
+ "input": "synthetic tour probe — canary smoke",
10
+ "canary": false,
11
+ "grader_type": "script",
12
+ "expected_assertions": [
13
+ {
14
+ "type": "regex-match",
15
+ "pattern": ".+"
16
+ }
17
+ ]
18
+ },
19
+ {
20
+ "id": "tour-smoke-2",
21
+ "name": "tour echoes case id",
22
+ "input": "case-id tour-smoke-2",
23
+ "canary": false,
24
+ "grader_type": "script",
25
+ "expected_assertions": [
26
+ {
27
+ "type": "regex-match",
28
+ "pattern": "tour-smoke-2"
29
+ }
30
+ ]
31
+ }
32
+ ]
33
+ }
@@ -141,3 +141,13 @@ Write one row to `<project>/Evidence/<alias>/tracking.md` per per-source-verific
141
141
 
142
142
  - [`emit-vertex/SKILL.md`](../emit-vertex/SKILL.md)
143
143
  - [`vertex-emit.instructions.md`](../../instructions/vertex-emit.instructions.md)
144
+
145
+
146
+ ## Validation loop
147
+
148
+ <!-- TODO(retrofit): fill in — describe how to verify this skill ran correctly. Auto-added by skill-checker --retrofit --apply per skill-authoring.instructions.md. -->
149
+
150
+ 1. Run pwsh plugin/skills/self-check/run.ps1 -Targeted <area>.
151
+ 2. Fix any findings, then re-run the affected step.
152
+ 3. Repeat until self-check exits 0.
153
+ 4. Only then update
@@ -0,0 +1,33 @@
1
+ {
2
+ "skill": "vertex-link",
3
+ "version": "1.0.0",
4
+ "description": "Auto-seeded evals for vertex-link. Replace with real cases as the skill matures.",
5
+ "cases": [
6
+ {
7
+ "id": "vertex-link-smoke-1",
8
+ "name": "vertex-link produces a non-empty response",
9
+ "input": "synthetic vertex-link probe — canary smoke",
10
+ "canary": false,
11
+ "grader_type": "script",
12
+ "expected_assertions": [
13
+ {
14
+ "type": "regex-match",
15
+ "pattern": ".+"
16
+ }
17
+ ]
18
+ },
19
+ {
20
+ "id": "vertex-link-smoke-2",
21
+ "name": "vertex-link echoes case id",
22
+ "input": "case-id vertex-link-smoke-2",
23
+ "canary": false,
24
+ "grader_type": "script",
25
+ "expected_assertions": [
26
+ {
27
+ "type": "regex-match",
28
+ "pattern": "vertex-link-smoke-2"
29
+ }
30
+ ]
31
+ }
32
+ ]
33
+ }