Skip to content
Merged
Show file tree
Hide file tree
Changes from all commits
Commits
File filter

Filter by extension

Filter by extension

Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
25 changes: 25 additions & 0 deletions skills/rig/samples/511-commit-type-enum-classifier.md
Original file line number Diff line number Diff line change
@@ -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;
```
23 changes: 23 additions & 0 deletions skills/rig/samples/512-nested-tsconfig-validator.md
Original file line number Diff line number Diff line change
@@ -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;
```
29 changes: 29 additions & 0 deletions skills/rig/samples/513-json-repair-addon-demo.md
Original file line number Diff line number Diff line change
@@ -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;
```
20 changes: 20 additions & 0 deletions skills/rig/samples/514-timeout-health-prober.md
Original file line number Diff line number Diff line change
@@ -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;
```
75 changes: 75 additions & 0 deletions skills/rig/samples/515-sequential-release-gate-workflow.md
Original file line number Diff line number Diff line change
@@ -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;
```
30 changes: 30 additions & 0 deletions skills/rig/samples/516-fanout-file-tag-aggregator.md
Original file line number Diff line number Diff line change
@@ -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;
```
39 changes: 39 additions & 0 deletions skills/rig/samples/517-custom-tool-port-scanner-stub.md
Original file line number Diff line number Diff line change
@@ -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<string, boolean> = {};
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;
```
29 changes: 29 additions & 0 deletions skills/rig/samples/518-write-sideeffect-report-generator.md
Original file line number Diff line number Diff line change
@@ -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;
```
27 changes: 27 additions & 0 deletions skills/rig/samples/519-nullable-env-config-resolver.md
Original file line number Diff line number Diff line change
@@ -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;
```
43 changes: 43 additions & 0 deletions skills/rig/samples/520-multi-stage-churn-risk-pipeline.md
Original file line number Diff line number Diff line change
@@ -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;
```
Loading