From 5951048326a7e2bfe1745e33bd82ce1648a3434b Mon Sep 17 00:00:00 2001 From: "github-actions[bot]" <41898282+github-actions[bot]@users.noreply.github.com> Date: Wed, 7 Oct 2026 14:04:05 +0000 Subject: [PATCH] =?UTF-8?q?Add=2010=20rig=20samples=20=E2=80=94=202026-10-?= =?UTF-8?q?07?= MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit Daily rig evaluation run: 10/10 generated tasks passed typecheck. All tasks were freshly generated (no cached pool existed yet); it now seeds the task pool for future reuse. Co-authored-by: Copilot <223556219+Copilot@users.noreply.github.com> --- .../511-commit-type-enum-classifier.md | 25 +++++++ .../samples/512-nested-tsconfig-validator.md | 23 ++++++ .../rig/samples/513-json-repair-addon-demo.md | 29 +++++++ .../rig/samples/514-timeout-health-prober.md | 20 +++++ .../515-sequential-release-gate-workflow.md | 75 +++++++++++++++++++ .../samples/516-fanout-file-tag-aggregator.md | 30 ++++++++ .../517-custom-tool-port-scanner-stub.md | 39 ++++++++++ .../518-write-sideeffect-report-generator.md | 29 +++++++ .../519-nullable-env-config-resolver.md | 27 +++++++ .../520-multi-stage-churn-risk-pipeline.md | 43 +++++++++++ 10 files changed, 340 insertions(+) create mode 100644 skills/rig/samples/511-commit-type-enum-classifier.md create mode 100644 skills/rig/samples/512-nested-tsconfig-validator.md create mode 100644 skills/rig/samples/513-json-repair-addon-demo.md create mode 100644 skills/rig/samples/514-timeout-health-prober.md create mode 100644 skills/rig/samples/515-sequential-release-gate-workflow.md create mode 100644 skills/rig/samples/516-fanout-file-tag-aggregator.md create mode 100644 skills/rig/samples/517-custom-tool-port-scanner-stub.md create mode 100644 skills/rig/samples/518-write-sideeffect-report-generator.md create mode 100644 skills/rig/samples/519-nullable-env-config-resolver.md create mode 100644 skills/rig/samples/520-multi-stage-churn-risk-pipeline.md diff --git a/skills/rig/samples/511-commit-type-enum-classifier.md b/skills/rig/samples/511-commit-type-enum-classifier.md new file mode 100644 index 0000000..94f2adc --- /dev/null +++ b/skills/rig/samples/511-commit-type-enum-classifier.md @@ -0,0 +1,25 @@ +# 511 - Commit Type Enum Classifier + +```rig +import { agent, p, s } from "rig"; + +// Agent role: classify recent commit messages into conventional-commit types +// and group the matching subject lines by type. +const classifyCommits = agent({ + name: "commit-type-enum-classifier", + model: "small", + instructions: p`Classify each commit subject from the log below into exactly one type: +feat, fix, docs, chore, refactor, test, or other. Use the conventional-commit +prefix if present (e.g. "feat:", "fix(scope):"); otherwise infer the best +matching type from the subject wording, defaulting to "other" when unclear. + +${p.bash("git log -20 --oneline")} + +Return a record keyed by commit type, where each value is the array of full +commit subject strings (without the hash) classified under that type. Omit +keys with no matches.`, + output: s.record(s.array(s.string)), +}); + +export default classifyCommits; +``` diff --git a/skills/rig/samples/512-nested-tsconfig-validator.md b/skills/rig/samples/512-nested-tsconfig-validator.md new file mode 100644 index 0000000..7f2fd4d --- /dev/null +++ b/skills/rig/samples/512-nested-tsconfig-validator.md @@ -0,0 +1,23 @@ +# 512 - Nested Tsconfig Validator + +```rig +import { agent, p, s } from "rig"; + +// Agent role: read tsconfig.json, validate it against a deeply nested schema, and report validation issues. +const validateTsconfig = agent({ + model: "small", + instructions: p`Inspect the project's tsconfig at ${p.read("tsconfig.json")}. +Parse it and validate it against the required nested structure: a top-level object +that may contain "compilerOptions" with optional "strict" (boolean), optional +"target" (string), and optional "paths" (a record mapping string keys to arrays +of string values). Flag any structural problems (e.g. wrong types, malformed +paths entries, missing compilerOptions) as human-readable issue strings. Set +"valid" to true only if no issues were found.`, + output: s.object({ + valid: s.boolean, + issues: s.array(s.string), + }), +}); + +export default validateTsconfig; +``` diff --git a/skills/rig/samples/513-json-repair-addon-demo.md b/skills/rig/samples/513-json-repair-addon-demo.md new file mode 100644 index 0000000..6dfc84f --- /dev/null +++ b/skills/rig/samples/513-json-repair-addon-demo.md @@ -0,0 +1,29 @@ +# 513 - Json Repair Addon Demo + +```rig +import { agent, p, s, repair } from "rig"; + +// Agent role: analyze the README text and produce a strict structured +// assessment. If the model's first response is not valid JSON matching the +// output schema, the repair() addon automatically re-prompts the model with +// the validation error and asks it to fix the output, consuming additional +// turns from maxTurns until it succeeds or the budget is exhausted. +const analyzeReadme = agent({ + model: "small", + maxTurns: 6, + instructions: p`Analyze the following text and return a strict JSON object +matching the declared schema: a one-sentence summary, a quality score from +0 to 10, and a list of relevant topic tags. + +Text: +${p.read("README.md")}`, + output: s.object({ + summary: s.string, + score: s.number, + tags: s.array(s.string), + }), + addons: [repair()], +}); + +export default analyzeReadme; +``` diff --git a/skills/rig/samples/514-timeout-health-prober.md b/skills/rig/samples/514-timeout-health-prober.md new file mode 100644 index 0000000..f99dfb8 --- /dev/null +++ b/skills/rig/samples/514-timeout-health-prober.md @@ -0,0 +1,20 @@ +# 514 - Timeout Health Prober + +```rig +import { agent, p, s, timeout } from "rig"; + +// Agent role: run a bash health-check probe and report its timing and status. +const healthProber = agent({ + model: "mini", + instructions: p`Run the health-check command ${p.bash("sleep 1 && echo ok")} and report the outcome. +If the command output contains "ok", set status to "ok". If the command did not complete or you were cut off before finishing, set status to "timeout". If any other error occurred, set status to "error". +Estimate durationMs as the elapsed time in milliseconds for the command to run.`, + output: s.object({ + status: s.enum("ok", "timeout", "error"), + durationMs: s.number, + }), + addons: timeout({ timeout: 5_000 }), +}); + +export default healthProber; +``` diff --git a/skills/rig/samples/515-sequential-release-gate-workflow.md b/skills/rig/samples/515-sequential-release-gate-workflow.md new file mode 100644 index 0000000..7b3de08 --- /dev/null +++ b/skills/rig/samples/515-sequential-release-gate-workflow.md @@ -0,0 +1,75 @@ +# 515 - Sequential Release Gate Workflow + +```rig +import { agent, p, s, workflow } from "rig"; + +// Agent role: run typecheck and report pass/fail with captured output. +const lintCheck = agent({ + name: "lintCheck", + model: "small", + instructions: p`Run ${p.bash("npm run typecheck")} and report whether it passed.`, + output: s.object({ + pass: s.boolean, + output: s.string, + }), +}); + +// Agent role: run the test suite and report pass/fail with captured output. +const testCheck = agent({ + name: "testCheck", + model: "small", + instructions: p`Run ${p.bash("npm test")} and report whether it passed.`, + output: s.object({ + pass: s.boolean, + output: s.string, + }), +}); + +// Agent role: combine lint and test results into a final release gate decision. +const releaseGate = agent({ + name: "releaseGate", + model: "small", + input: s.object({ + lintPass: s.boolean, + lintOutput: s.string, + testPass: s.boolean, + testOutput: s.string, + }), + instructions: p`Given lint pass=${p.inputField("lintPass")} with output ${p.inputField("lintOutput")}, and test pass=${p.inputField("testPass")} with output ${p.inputField("testOutput")}, decide whether the release is approved or blocked and list reasons.`, + output: s.object({ + decision: s.enum("approved", "blocked"), + reasons: s.array(s.string), + }), +}); + +// Workflow role: sequentially gate a release through lint, test, then a final decision step. +const releaseGateWorkflow = workflow({ + meta: { + name: "sequential-release-gate", + description: "Chain lint check, test check, and gate decision sequentially", + phases: ["Lint", "Test", "Gate"], + }, + body: async ({ call, phase }) => { + phase("Lint"); + const lint = await call(lintCheck, "", { label: "lint" }); + const lintPass = lint?.pass ?? false; + const lintOutput = lint?.output ?? "lint agent failed to run"; + + phase("Test"); + const test = await call(testCheck, "", { label: "test" }); + const testPass = test?.pass ?? false; + const testOutput = test?.output ?? "test agent failed to run"; + + phase("Gate"); + const gate = await call( + releaseGate, + { lintPass, lintOutput, testPass, testOutput }, + { label: "gate" }, + ); + + return { lint, test, gate }; + }, +}); + +export default releaseGateWorkflow; +``` diff --git a/skills/rig/samples/516-fanout-file-tag-aggregator.md b/skills/rig/samples/516-fanout-file-tag-aggregator.md new file mode 100644 index 0000000..9ff6263 --- /dev/null +++ b/skills/rig/samples/516-fanout-file-tag-aggregator.md @@ -0,0 +1,30 @@ +# 516 - Fanout File Tag Aggregator + +```rig +import { agent, p, s } from "rig"; + +// Agent role: read one source file and assign topical tags to it. +const tagger = agent({ + name: "tagger", + model: "small", + input: s.object({ path: s.path }), + output: s.object({ + tags: s.array(s.enum("schema", "prompt", "engine", "test", "util")), + }), + instructions: p`Read ${p.readInput("path")} and assign one or more topical tags that best describe its content.`, +}); + +// Agent role: discover TypeScript source files, delegate tagging per file to the +// tagger subagent, and aggregate results into a tag-to-file-paths map. +const tagAggregator = agent({ + name: "tagAggregator", + model: "small", + agents: { tagger }, + output: s.object({ + tagsToFiles: s.record(s.array(s.path)), + }), + instructions: p`Find source files with ${p.glob("src/**/*.ts")}. For each discovered path, call tagger with { path } to obtain its tags. Aggregate the results into a single map from each tag to the list of file paths assigned that tag, and return it as tagsToFiles.`, +}); + +export default tagAggregator; +``` diff --git a/skills/rig/samples/517-custom-tool-port-scanner-stub.md b/skills/rig/samples/517-custom-tool-port-scanner-stub.md new file mode 100644 index 0000000..61bcff0 --- /dev/null +++ b/skills/rig/samples/517-custom-tool-port-scanner-stub.md @@ -0,0 +1,39 @@ +# 517 - Custom Tool Port Scanner Stub + +```rig +import { agent, defineTool, s } from "rig"; + +// Custom tool: simulate port reachability without real network calls. +const scanPorts = defineTool("scan_ports", { + description: "Simulate reachability of ports on a host.", + parameters: s.object({ + host: s.string, + ports: s.array(s.number), + }), + handler: async ({ host: _host, ports }: { host: string; ports: number[] }) => { + const result: Record = {}; + for (const port of ports) { + result[String(port)] = port < 1024 ? false : true; + } + return result; + }, +}); + +// Agent role: scan the given host/ports with the scan_ports tool and summarize results. +const portScanner = agent({ + model: "mini", + instructions: + "Call scan_ports with the provided host and ports, then summarize which ports are open and produce a short human-readable summary.", + input: s.object({ + host: s.string, + ports: s.array(s.number), + }), + output: s.object({ + openPorts: s.array(s.number), + summary: s.string, + }), + tools: [scanPorts], +}); + +export default portScanner; +``` diff --git a/skills/rig/samples/518-write-sideeffect-report-generator.md b/skills/rig/samples/518-write-sideeffect-report-generator.md new file mode 100644 index 0000000..8411692 --- /dev/null +++ b/skills/rig/samples/518-write-sideeffect-report-generator.md @@ -0,0 +1,29 @@ +# 518 - Write Sideeffect Report Generator + +```rig +import { agent, p, s } from "rig"; + +// Agent role: inspect package.json dependencies, draft a markdown dependency +// report, persist it to disk, and return a structured summary. +const dependencyReportGenerator = agent({ + model: "mini", + instructions: p`Inspect ${p.read("package.json")}. + Count the total number of entries across "dependencies" and "devDependencies". + Draft a concise markdown dependency report listing each dependency and its + declared version, with a short section flagging any dependencies whose + version appears unusually old or loosely pinned (your best guess list). + ${p.writeOutput("reportMarkdown", "DEPENDENCY_REPORT.md")} + Return the declared output: the total dependency count, the list of + package names you flagged as possibly outdated, the markdown report + content itself, and the path the report was written to + ("DEPENDENCY_REPORT.md").`, + output: s.object({ + totalDeps: s.number, + outdatedGuess: s.array(s.string), + reportMarkdown: s.string, + reportPath: s.string, + }), +}); + +export default dependencyReportGenerator; +``` diff --git a/skills/rig/samples/519-nullable-env-config-resolver.md b/skills/rig/samples/519-nullable-env-config-resolver.md new file mode 100644 index 0000000..d430c79 --- /dev/null +++ b/skills/rig/samples/519-nullable-env-config-resolver.md @@ -0,0 +1,27 @@ +# 519 - Nullable Env Config Resolver + +```rig +import { agent, p, s } from "rig"; + +// Agent role: parse a .env-like config and classify each entry's resolution source. +const resolveEnvConfig = agent({ + model: "small", + instructions: p`Given the raw config contents below, parse each line into key=value pairs. +Ignore blank lines and lines starting with '#'. For each entry, classify source as: +"file" if the key has a non-empty value present in the file, "default" if the key is present +but has no value (empty string after '='), and "missing" if the raw content is literally "none" +(no file found) in which case return an empty array. + +Raw config contents: +${p.bash("cat .env.example 2>/dev/null || echo none")} + +Return only the declared output.`, + output: s.array(s.object({ + key: s.string, + value: s.optional(s.string), + source: s.enum("file", "default", "missing"), + })), +}); + +export default resolveEnvConfig; +``` diff --git a/skills/rig/samples/520-multi-stage-churn-risk-pipeline.md b/skills/rig/samples/520-multi-stage-churn-risk-pipeline.md new file mode 100644 index 0000000..f3d8665 --- /dev/null +++ b/skills/rig/samples/520-multi-stage-churn-risk-pipeline.md @@ -0,0 +1,43 @@ +# 520 - Multi Stage Churn Risk Pipeline + +```rig +import { agent, p, s } from "rig"; + +// Agent role: gather recent file churn from git history, compute per-file change +// counts, classify each file's risk, and return a risk-sorted report. +const churnRiskAnalyzer = agent({ + name: "churn-risk-analyzer", + model: "small", + instructions: p`You are analyzing recent repository churn to flag risky files. + +Step 1: Review the recently changed file list below, produced by +"git log --since=30.days --name-only --pretty=format:". Each non-empty line +is a file path that changed in one commit; the same path may repeat across +multiple commits. + +${p.bash("git log --since=30.days --name-only --pretty=format:")} + +Step 2: For each distinct file path, compute its churn count: the number of +times that path appears (non-empty lines) in the list above. Ignore blank +lines. + +Step 3: Classify each file's risk based on its churn count using these +thresholds: +- "low": churn is 1-2 +- "medium": churn is 3-5 +- "high": churn is 6 or more + +Return only the declared output: one entry per distinct file path with its +path, churn count, and risk classification, sorted by risk descending +(high first, then medium, then low).`, + output: s.array( + s.object({ + path: s.path, + churn: s.number, + risk: s.enum("low", "medium", "high"), + }), + ), +}); + +export default churnRiskAnalyzer; +```