Skip to content

[rig-tasks] Add 10 rig samples — 2026-07-29 - #272

Merged
pelikhan merged 1 commit into
mainfrom
rig-tasks/2026-07-29-db22196570b6c7ca
Jul 29, 2026
Merged

[rig-tasks] Add 10 rig samples — 2026-07-29#272
pelikhan merged 1 commit into
mainfrom
rig-tasks/2026-07-29-db22196570b6c7ca

Conversation

@github-actions

Copy link
Copy Markdown
Contributor

Summary

Added 10 new rig sample files to skills/rig/samples/.

# File Description Typecheck
1 300-server-uptime-log-parser.md Parse systemd/syslog lines for service lifecycle events pass
2 301-css-variable-extractor.md Extract CSS custom properties and detect unused vars pass
3 302-openapi-route-coverage.md Cross-reference OpenAPI spec routes vs router handlers pass
4 303-import-style-checker.md Classify JS files as ESM/CJS/mixed/unknown pass
5 304-git-tag-semver-validator.md Validate git tags against semver format pass
6 305-shell-script-safety-analyzer.md Check .sh files for set -e/set -u/pipefail safety flags pass
7 306-git-diff-stats-summarizer.md Summarize git diff --numstat with file change classification pass
8 307-dotenv-template-generator.md Scan source for process.env refs and generate .env.template pass
9 308-ts-class-hierarchy-extractor.md Build class inheritance graph from TypeScript files pass
10 309-git-bisect-helper.md Binary-search recent commits to identify a regression pass

Typecheck failures

None — all 10 programs passed typecheck on first attempt.

Tasks run

  • (reused) Server uptime log parser — p.bash journalctl, defineTool parseUptimeEvent, steering+repair
  • (reused) CSS variable extractor — p.bash find/grep, defineTool parseCssVar, s.record output
  • (reused) OpenAPI route coverage — p.readOptional + p.bash, defineTool extractRoutes
  • (reused) Import style checker — p.bash, defineTool classifyStyle with as const, s.enum
  • (reused) Git tag semver validator — p.bash git tag, defineTool parseSemver, s.optional parsed object
  • (reused) Shell script safety analyzer — async defineTool with node:fs/promises readFile, s.record
  • (new) Git diff stats summarizer — p.bash git diff --numstat, defineTool classifyDiffEntry, repair
  • (new) Dotenv template generator — p.readOptional + p.glob + async defineTool + p.write
  • (new) TS class hierarchy extractor — async defineTool extractClassInfo, steering, s.record of classes
  • (new) Git bisect helper — defineTool selectMidpoint, steering + maxTurns:8, s.enum confidence

Generated by Daily Rig Task Generator · sonnet46 98.1 AIC · ⌖ 9.42 AIC · ⊞ 6.8K ·

Co-authored-by: Copilot <223556219+Copilot@users.noreply.github.com>
@pelikhan
pelikhan marked this pull request as ready for review July 29, 2026 08:23
@pelikhan
pelikhan merged commit 3054b3b into main Jul 29, 2026
2 checks passed
@github-actions

github-actions Bot commented Jul 29, 2026

Copy link
Copy Markdown
Contributor Author

🧠 Matt Pocock Skills Reviewer has completed the skills-based review. ✅

@github-actions github-actions Bot left a comment

Copy link
Copy Markdown
Contributor Author

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Skills-Based Review 🧠

Applied /codebase-design and /grill-with-docs — requesting changes on three correctness issues and one API-pattern ambiguity.

📋 Key Themes & Highlights

Issues Found

  • Logic bug (309): selectMidpoint declares currentBad/currentGood parameters but ignores them — the binary search never actually narrows. Readers copying this pattern will get a tool that always bisects the full list.
  • Wrong default case (306): classifyDiffEntry returns "renamed" when additions and deletions are both 0. That is an unchanged file in numstat, not a rename.
  • Shadowed import (308): lambda parameter s shadows the s schema builder from "rig" — confusing in teaching material.
  • Pattern ambiguity (307): p.write in instructions and templateGenerated: s.boolean / templatePath: s.path in output try to do the same thing two ways simultaneously. Pick one idiom.

Positive Highlights

  • ✅ All 10 samples pass typecheck on first attempt — strong signal of well-structured generation.
  • ✅ Good variety of real-world use cases covering async tools, s.record, s.optional, p.readOptional, p.glob, and p.write.
  • ✅ Consistent use of steering() and repair() addons where appropriate.
  • ✅ Progressive complexity from simple regex tools (300–303) to async node:fs tools (305, 307, 308).

🧠 Reviewed using Matt Pocock's skills by Matt Pocock Skills Reviewer · sonnet46 51.3 AIC · ⌖ 6.52 AIC · ⊞ 6.3K
Comment /matt to run again

const classes: Array<{ className: string; parent?: string; interfaces: string[]; isAbstract: boolean }> = [];
let m: RegExpExecArray | null;
while ((m = pattern.exec(content)) !== null) {
const interfaces = m[4] ? m[4].split(",").map((s: string) => s.trim()).filter(Boolean) : [];

Copy link
Copy Markdown
Contributor Author

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

[/grill-with-docs] The lambda parameter s shadows the top-level s schema builder imported from "rig". Inside this callback s refers to the string element, not the schema helper — confusing in a sample meant to teach rig patterns.

💡 Suggested rename

Rename the lambda parameter to avoid the collision:

const interfaces = m[4] ? m[4].split(",").map((iface: string) => iface.trim()).filter(Boolean) : [];

Samples are the primary teaching material for rig; any name that collides with a core import creates a false mental model for readers.

parameters: s.object({ commits: s.array(s.string), currentBad: s.string, currentGood: s.string }),
handler({ commits }) {
if (commits.length === 0) return { midpoint: null, remaining: 0 };
const mid = Math.floor(commits.length / 2);

Copy link
Copy Markdown
Contributor Author

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

[/codebase-design] selectMidpoint ignores currentBad and currentGood — both parameters are declared but never used. The tool's binary-search purpose is undermined: it always bisects the full commits array rather than the narrowed [currentGood..currentBad] slice.

💡 Suggested fix

Either remove the unused parameters from the schema, or implement the narrowing:

handler({ commits, currentBad, currentGood }) {
  const badIdx = commits.indexOf(currentBad);
  const goodIdx = commits.indexOf(currentGood);
  const slice = badIdx !== -1 && goodIdx !== -1
    ? commits.slice(Math.min(badIdx, goodIdx), Math.max(badIdx, goodIdx) + 1)
    : commits;
  const mid = Math.floor(slice.length / 2);
  return { midpoint: slice[mid] ?? null, remaining: slice.length };
},

As a sample demonstrating bisect logic, readers will copy this pattern — unused params that carry semantic meaning are a correctness trap.

templatePath: s.path,
envKeys: s.array(s.string),
undocumentedKeys: s.array(s.string),
templateGenerated: s.boolean,

Copy link
Copy Markdown
Contributor Author

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

[/grill-with-docs] The p.write call in the instructions prompt is a placeholder that tells the LLM what to write — but the output schema already declares templateGenerated: s.boolean and templatePath: s.path. The sample conflates two different approaches: p.write as a prompt intent vs. returning a path for the caller to act on. Only one pattern should be modeled.

💡 Consider

If the intent is to show p.write as a prompt intent that instructs the model to write the file, the output schema fields templateGenerated and templatePath are redundant and should be removed. If the intent is to return structured data for the caller to write the file, remove the p.write from the instructions and keep the output schema. Mixing both patterns in one sample will confuse readers about when to use each approach.

if (additions > 0 && deletions === 0) return "added" as const;
if (additions === 0 && deletions > 0) return "deleted" as const;
if (additions > 0 && deletions > 0) return "modified" as const;
return "renamed" as const;

Copy link
Copy Markdown
Contributor Author

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

[/codebase-design] classifyDiffEntry returns "renamed" as the fallback when both additions === 0 and deletions === 0 — but that is actually an unchanged file in git diff --numstat output. A renamed file in numstat typically shows as 0 0 old => new or {old => new}. The sample teaches an incorrect classification heuristic.

💡 Suggested fix
handler({ additions, deletions }) {
  if (additions > 0 && deletions === 0) return "added" as const;
  if (additions === 0 && deletions > 0) return "deleted" as const;
  if (additions > 0 && deletions > 0) return "modified" as const;
  return "unchanged" as const;  // 0/0 means no net line changes, not a rename
},

Rename detection would require inspecting the file path string (e.g. {old => new} pattern). This is worth a brief comment so readers don't copy the wrong semantic.

parameters: s.object({ content: s.string }),
handler({ content }) {
const routes: Array<{ path: string; method: string }> = [];
const pattern = /router\.(get|post|put|delete|patch)\s*\(\s*['"`]([^'"`]+)['"`]/gi;

Copy link
Copy Markdown
Contributor Author

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

[/grill-with-docs] extractRoutes only matches Express-style router.METHOD() calls and returns them directly as the tool's return value, but the instructions pass the raw grep output (not the parsed code) to the tool. The tool receives the entire concatenated grep lines as content, which includes line numbers and file prefixes (file.ts:42:router.get(...)). The regex router\. will work on this string, but the file-prefixed format isn't called out — a reader adapting this sample may get silent mismatches.

💡 Suggestion

Either document in a comment that grep -h strips the file prefix (which the bash command already uses), or adjust the regex to anchor more carefully. A small clarifying comment near the p.bash line would close the gap for readers:

// -h suppresses filename prefix so each line starts with the code directly
${p.bash("grep -rhn 'router\.' ...")}

Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment

Projects

None yet

Development

Successfully merging this pull request may close these issues.

1 participant