[rig-tasks] Add 10 rig samples — 2026-08-30 - #513
Conversation
- 491: dotenv-process-drift-detector — p.read + p.bash + defineTool + repair addon + s.record - 492: vitest-snapshot-count-workflow — workflow() + parallel Promise.all + two subagents - 493: git-stale-branch-reporter — p.bash + defineTool with s.enum return - 494: ts-abstract-class-finder — p.glob + p.bash + defineTool + s.boolean - 495: dockerfile-env-inspector — p.bash find + defineTool + s.array of s.object - 496: npm-script-prefix-analyzer — p.read + defineTool + s.record(s.object) + s.record(s.int) - 497: ts-default-param-extractor — p.glob + p.bash + defineTool + repair addon - 498: git-branch-risk-classifier — p.bash + defineTool + steering() + repair() addons - 499: test-file-coverage-pipeline — workflow() + 3-stage sequential call() pipeline - 500: json-schema-type-distribution — p.glob + p.bash + defineTool + s.record Co-authored-by: Copilot <223556219+Copilot@users.noreply.github.com>
|
🧠 Matt Pocock Skills Reviewer has completed the skills-based review. ✅ |
There was a problem hiding this comment.
Skills-Based Review 🧠
Applied /grill-with-docs and /codebase-design — commenting on correctness and naming issues across the new samples.
📋 Key Themes & Highlights
Key Themes
s.stringused wheres.enumis more accurate (491, 493, 498): Several samples define tools with typed union return values but uses.stringin the output schema. This is inconsistent —s.enumwould keep schemas honest and teach readers the right helper to reach for.- Dropped workflow output (492):
snapshotParser'sexportCountis never returned by the workflow, making the second agent's primary purpose invisible. - Contradictory grep in 497: The bash command greps for arrow functions then immediately filters them out, producing variable assignments rather than default parameters.
- Shell word-splitting in 495: Nested
$(find ...)subshell ingrepis fragile on paths with spaces —xargsis the conventional fix.
Positive Highlights
- ✅ All 10 samples pass typecheck — no regressions
- ✅ Good mix of patterns:
repair(),steering(), parallel and sequential workflows,s.record,s.enum,defineTool - ✅ Diverse real-world use cases keep the sample set interesting
- ✅ Null-coalescing with
?? 0throughout workflow bodies is consistent and safe
🧠 Reviewed using Matt Pocock's skills by Matt Pocock Skills Reviewer · sonnet46 44.6 AIC · ⌖ 4.64 AIC · ⊞ 6.3K
Comment /matt to run again
| return { | ||
| totalSnapshotFiles: scanResult?.totalFiles ?? 0, | ||
| totalLines: (scanResult?.files ?? []).reduce((sum: number, f: { lineCount: number }) => sum + f.lineCount, 0), | ||
| snapshotFiles: parseResult?.snapshotFiles ?? [], |
There was a problem hiding this comment.
[/codebase-design] exportCount from snapshotParser is silently dropped — the workflow never surfaces it in its return value, so the parser agent runs but its key metric goes unused. As a sample this is misleading: readers may conclude exportCount is an optional output rather than the parser's primary purpose.
💡 Include exportCount in the return value
return {
totalSnapshotFiles: scanResult?.totalFiles ?? 0,
totalLines: (scanResult?.files ?? []).reduce((sum: number, f: { lineCount: number }) => sum + f.lineCount, 0),
snapshotFiles: parseResult?.snapshotFiles ?? [],
exportCount: parseResult?.exportCount ?? 0, // add this
};| const tsDefaultParamExtractor = agent({ | ||
| model: "small", | ||
| instructions: p`Find TypeScript files with ${p.glob("src/**/*.ts")}. Search for function parameters with defaults using ${p.bash("grep -rn 'function\\|const.*=>' src/ 2>/dev/null | grep '=' | grep -v '=>' | head -50 || true")}. Use extractDefaultParam for each match. Return the full list of default parameters.`, | ||
| output: s.object({ |
There was a problem hiding this comment.
[/grill-with-docs] The bash grep filter is ambiguous and will produce many false positives. The pattern grep 'function\|const.*=>' | grep '=' | grep -v '=>' is contradictory — it greps for arrow functions (const.*=>) then excludes =>, meaning it only captures const x = ... declarations, not actual default parameters like fn(x = 1). The sample would return mostly variable assignments rather than function defaults.
💡 More precise grep for default parameters
grep -rn '([^)]*\w\+\s*=\s*[^=][^)]*)' src/ --include='*.ts' 2>/dev/null | head -50 || trueOr target function declarations and arrow function signatures specifically and filter for = inside parameter lists.
| const dockerfileEnvInspector = agent({ | ||
| model: "small", | ||
| instructions: p`Find Dockerfiles using ${p.bash("find . -name 'Dockerfile*' -not -path '*/node_modules/*' 2>/dev/null | head -20 || true")}. Extract ENV instructions with ${p.bash("grep -rn '^ENV ' $(find . -name 'Dockerfile*' -not -path '*/node_modules/*' 2>/dev/null | head -10 | tr '\\n' ' ') 2>/dev/null || true")}. Use parseEnvInstruction for each ENV line found. Return all env vars.`, | ||
| output: s.object({ |
There was a problem hiding this comment.
[/grill-with-docs] The nested shell substitution in the grep command — grep -rn '^ENV ' $(find ...) — is shell-injected via p.bash(). If any Dockerfile path contains spaces or special characters this will silently misbehave or error. Since p.bash() is a declarative placeholder (not in-process execution), showing fragile shell composition in a sample teaches an unsafe pattern.
💡 Safer alternative: use xargs
p.bash("find . -name 'Dockerfile*' -not -path '*/node_modules/*' 2>/dev/null | head -10 | xargs -I{} grep -n '^ENV ' {} 2>/dev/null || true")Using xargs -I{} avoids the subshell word-splitting problem.
| instructions: p`Compare declared env keys in ${p.read(".env.example")} with actual usages from ${p.bash("grep -rn 'process\\.env\\.' src/ 2>/dev/null || true")}. Use classifyEnvKey for each key found. Return the full drift report.`, | ||
| output: s.object({ | ||
| keys: s.record(s.object({ inExample: s.boolean, usedInCode: s.boolean, status: s.string })), | ||
| totalKeys: s.int, |
There was a problem hiding this comment.
[/grill-with-docs] The output schema has a status: s.string field but the classifyEnvKey tool returns a typed union ("declared_and_used" | "declared_not_used" | "used_not_declared"). Using s.string instead of s.enum([...]) loses the type constraint and misses a chance to demonstrate s.enum — a schema helper this sample is well-suited to showcase.
💡 Use s.enum to match the tool return type
keys: s.record(s.object({
inExample: s.boolean,
usedInCode: s.boolean,
status: s.enum(["declared_and_used", "declared_not_used", "used_not_declared"]),
})),| const gitBranchRiskClassifier = agent({ | ||
| model: "small", | ||
| instructions: p`List branches with ${p.bash("git branch --format='%(refname:short) %(ahead-behind:HEAD)' 2>/dev/null | head -20 || true")}. Use classifyBranchRisk for each branch with its ahead/behind numbers. Return the risk classification for every branch.`, | ||
| output: s.object({ |
There was a problem hiding this comment.
[/grill-with-docs] The output schema uses risk: s.string but classifyBranchRisk returns a typed union "safe" | "caution" | "risky" | "critical". Same pattern as 491 — s.enum would make the sample more faithful to the tool's contract and demonstrate the schema helper.
💡 Use s.enum in the branches array
branches: s.array(s.object({ name: s.string, ahead: s.int, behind: s.int, risk: s.enum(["safe", "caution", "risky", "critical"]) })),| const gitStaleBranchReporter = agent({ | ||
| model: "small", | ||
| instructions: p`Analyze git branches from ${p.bash("git branch -r --sort=-committerdate --format='%(refname:short) %(committerdate:relative)' 2>/dev/null | head -30 || true")}. Use classifyBranchAge for each branch to determine its freshness status. Return the full report.`, | ||
| output: s.object({ |
There was a problem hiding this comment.
[/grill-with-docs] Same pattern: status: s.string in the output schema but classifyBranchAge returns a typed union. And similarly for 494's branches array. Consider s.enum(["fresh", "aging", "stale", "ancient"]) to keep output schemas honest about the values they represent — this also teaches readers that s.enum is the right schema helper when a tool returns a discriminated string union.
Summary
Added 10 new rig sample files to
skills/rig/samples/.Typecheck failures
None — all 10 tasks passed typecheck.
Two issues were caught and fixed during development before writing the sample files:
workflow()meta object missing requireddescriptionfield.anyin.reduce()inside workflow body when operating oncall()results typed asT | null.Tasks run