Skip to content

[rig-tasks] Add 10 rig samples — 2026-07-30 - #294

Merged
pelikhan merged 1 commit into
mainfrom
rig-tasks/2026-07-30-22cc98ab33a2aa17
Jul 30, 2026
Merged

[rig-tasks] Add 10 rig samples — 2026-07-30#294
pelikhan merged 1 commit into
mainfrom
rig-tasks/2026-07-30-22cc98ab33a2aa17

Conversation

@github-actions

Copy link
Copy Markdown
Contributor

Summary

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

# File Description Typecheck
1 310-lock-file-drift-detector.md Lock file drift detector ✅ pass
2 311-git-conflict-marker-scanner.md Git conflict marker scanner ✅ pass
3 312-proto-field-extractor.md Proto file field extractor ✅ pass
4 313-git-remote-url-inspector.md Git remote URL inspector ✅ pass
5 314-ts-enum-value-extractor.md TypeScript enum value extractor ✅ pass
6 315-json-config-merger.md JSON config merger ✅ pass
7 316-markdown-toc-generator.md Markdown TOC generator (new) ✅ pass
8 317-git-author-email-domains.md Git author email domain aggregator (new) ✅ pass
9 318-ts-barrel-re-exporter.md TypeScript barrel re-exporter (new) ✅ pass
10 319-workflow-step-duration-estimator.md Workflow step duration estimator (new) ✅ pass

Typecheck failures

No failures — all 10 tasks passed typecheck. Task 1 required one fix: bracket notation (pkg["dependencies"]) instead of dot notation on Record<string, unknown> types due to noPropertyAccessFromIndexSignature.

Tasks run

  • (reused) Lock file drift detector — p.bash, defineTool with JSON.parse, repair()
  • (reused) Git conflict marker scanner — p.bash grep pipeline, steering()
  • (reused) Proto field extractor — async defineTool, node:fs/promises, s.record(s.array(...))
  • (reused) Git remote URL inspector — p.bash, sync defineTool, s.enum, repair()
  • (reused) TypeScript enum value extractor — async defineTool, regex, s.record(s.object(...))
  • (reused) JSON config merger — input schema with s.path, p.readInput, p.writeInput, repair()
  • (new) Markdown TOC generator — p.glob, async defineTool, p.write, file discovery pattern
  • (new) Git author email domain aggregator — sync defineTool, s.record(s.int), steering()
  • (new) TypeScript barrel re-exporter — caller-supplied paths, p.bash find, async tool, p.writeInput
  • (new) Workflow step duration estimator — p.glob, two tools (read + classify), s.enum in tool, steering()

Generated by Daily Rig Task Generator · sonnet46 94 AIC · ⌖ 6.62 AIC · ⊞ 6.8K ·

Co-authored-by: Copilot <223556219+Copilot@users.noreply.github.com>
@pelikhan
pelikhan marked this pull request as ready for review July 30, 2026 09:16
@pelikhan
pelikhan merged commit 5bc52e3 into main Jul 30, 2026
1 check passed
@github-actions

github-actions Bot commented Jul 30, 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 /grill-with-docs — requesting changes on correctness issues in three of the ten samples.

📋 Key Themes & Highlights

Blocking Issues

  • 310 — Drift detection logic is inverted; the handler will never report actual version mismatches, only missing packages.
  • 317git log | uniq -c output has count prefixes; passing lines verbatim to extractDomain can confuse the LLM about what constitutes the email argument.
  • 318sourceDir input is declared but ignored; p.bash always scans the whole repo.

Non-blocking Issues

  • 315JSON.parse in the merge handler has no try/catch (inconsistent with 310's pattern).
  • 319readWorkflowFile tool is registered but not mentioned in instructions; LLM would need to guess it should call it.

Positive Highlights

  • ✅ Consistent use of s.record, s.enum, s.path, s.int across all samples — good schema discipline.
  • ✅ Proper node: import prefix throughout.
  • ✅ 310's try/catch pattern for JSON parsing is a good model — extend it to 315.
  • ✅ 311's toolless approach (two p.bash calls + steering()) is clean and idiomatic for simple scanners.
  • ✅ All samples typecheck cleanly.

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

const lockedEntry = lockPackages[lockKey];
const locked = lockedEntry?.version ?? "missing";
const declaredClean = (declared as string).replace(/^[\^~>=<]/, "");
if (locked !== declaredClean && locked !== "missing") continue;

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 drift detection logic is inverted — version mismatches are silently skipped, so the tool only ever reports missing packages, never actual version differences.

💡 Bug explanation

Line 48: if (locked !== declaredClean && locked !== "missing") continue;

This skips any entry where the locked version differs from the declared version and it is not "missing" — i.e., it skips every real drift case. Only the subsequent if (locked === "missing") block ever appends to drifted.

Fix the condition:

if (locked === "missing" || locked !== declaredClean) {
  drifted.push({ name, declared, locked });
}

instructions: p`You are a TypeScript barrel re-exporter.

Find TypeScript source files to barrel (excluding index files):
${p.bash("find . -name '*.ts' -not -name 'index.ts' -not -name '*.test.ts' -not -name '*.d.ts' -not -path '*/node_modules/*' | head -50")}

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] sourceDir is declared as an input field but p.bash hard-codes find . (whole repo), silently ignoring it — the agent will barrel files from everywhere, not from the supplied directory.

💡 Fix

Use p.readInput / the input value in the bash command:

${p.bash(`find ${p.readInput("sourceDir")} -name '*.ts' -not -name 'index.ts' ...`)}

or via a shell-safe reference so the runtime substitutes the actual path before execution.

Alternatively, drop sourceDir from the input schema if the intent is always to scan the whole repo.


Collect all author emails from the git log:
${p.bash("git log --format=%ae 2>/dev/null | sort | uniq -c | sort -rn || echo 'no commits'")}

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 git log pipeline uses uniq -c | sort -rn so each line fed to the model (and then to extractDomain) has the form 42 user@example.com, not a bare email — indexOf("@") will find the correct index, but email.slice(atIdx + 1) extracts example.com correctly only by coincidence. The real problem is the model is asked to call extractDomain once per unique email but receives count-prefixed lines; it may pass the whole line (including the count) as the email argument.

💡 Fix

Strip the count prefix in the bash command:

git log --format=%ae 2>/dev/null | sort | uniq -c | sort -rn | awk '{print $2}'

or have extractDomain accept the raw uniq -c line and parse both the count and the email:

handler({ line }: { line: string }) {
  const m = line.trim().match(/^(\d+)\s+(\S+)$/);
  if (!m) return { domain: "unknown", count: 0 };
  const [, count, email] = m;
  const atIdx = email.indexOf("@");
  return { domain: atIdx === -1 ? "unknown" : email.slice(atIdx + 1).toLowerCase(), count: Number(count) };
}

overrideJson: s.string,
}),
handler({ baseJson, overrideJson }) {
const base = JSON.parse(baseJson) as Record<string, unknown>;

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] JSON.parse in the handler has no error handling — a malformed config file will throw an uncaught exception and crash the tool call. Sample 310 handles this correctly with try/catch; this sample should do the same.

💡 Fix
handler({ baseJson, overrideJson }) {
  let base: Record<string, unknown>;
  let override: Record<string, unknown>;
  try { base = JSON.parse(baseJson); } catch { return { error: "Failed to parse base config" }; }
  try { override = JSON.parse(overrideJson); } catch { return { error: "Failed to parse override config" }; }
  // ... rest of merge logic
}

Discover workflow files:
${p.glob(".github/workflows/*.yml")}

Read each workflow file and use estimateStepDuration to classify each step's expected duration.

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 instructions tell the LLM to "read each workflow file" but never direct it to call readWorkflowFile — it would need to infer tool usage from context alone. Either mention the tool explicitly in the instructions, or inline the file content via p.glob + a p.read per file so the content is available without a separate tool call.

💡 Suggested instruction text
Discover workflow files:
${p.glob(".github/workflows/*.yml")}

For each file, call readWorkflowFile to get its content, then call estimateStepDuration for each step.
Return the declared output with per-workflow estimates.

Explicit tool direction reduces hallucination risk and makes the example clearer for readers.

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