[rig-decomposition-bench] Daily rig decomposition benchmark — 2026-10-27 — tie
I maintainer di solito rispondono entro 1 giorno
Nessuno ha ancora preso questa issue.
Valutazione
- Difficoltà
- 4/5
- Tempo stimato
- 3-5 giorni
- Idoneità per principianti
- 12/100
- Tipo di issue
- Bug
- Chiarezza
- Da chiarire
- Stato di attività
- Attiva
- Stack tecnologico
- node.js, typescript
- Ambito
- testing-qa, tooling
Direzione di ricerca
This is an auto-generated benchmark report, not a task: both attempts failed only because the rig --server subprocess could not spawn node (spawn node ENOENT), so the generated program was never typechecked or executed. Start by locating where rig's server subprocess spawns the typecheck/execute step and reproduces the environment (PATH, cwd, shell) used there. Done means that subprocess finds node and the benchmark's generated bench.ts runs to typecheck and execution, not that the tidal-buoy scores change.
Scritto dal modello di indicizzazione a partire dal testo della issue.
Descrizione
Task
Title: Reconcile a Tidal-Energy Buoy Array's Maintenance Schedule with Conflicting Sensor Logs and Vendor Contracts
Domain: Marine renewable energy operations (offshore tidal turbine buoy array maintenance planning)
Description: A small operator runs 12 tidal-energy buoys. All inputs are embedded in the prompt as inline text tables: (1) a 30-day sensor log summary per buoy (vibration RMS, bearing temperature, mooring tension, and power output, with a few deliberately corrupted or missing entries); (2) three vendor service contracts, each given as a short clause list (response-time SLAs, weather-window restrictions, per-callout fees, and penalty clauses); and (3) a 14-day marine weather forecast table giving the wave height and the safe-access flag for each day. The team must produce a single-day deliverable: a prioritized 14-day maintenance schedule. The work splits naturally across sub-agents. Agent A cleans the sensor data and flags anomalous buoys, with a stated justification for every exclusion or imputation. Agent B parses the contracts into a structured table of constraints and costs, and notes any clause conflicts. Agent C builds the schedule by assigning each flagged buoy to a vendor and a day, subject to the weather windows, SLAs, and a one-vessel-per-day limit, and minimizes total cost plus expected penalties. A reviewer agent then independently checks every assignment against the constraints and writes a one-page risk memo. The final output must be a markdown report containing the cleaned-data findings, the constraints table, the schedule table, the total cost calculation, and the memo.
Success criteria:
- The report lists exactly which buoys were flagged as anomalous and which data points were corrupted or missing, and states the handling method (excluded or imputed) for each one. The flagged set matches the answer key built into the inputs.
- The constraints table captures every vendor clause (SLA hours, weather restrictions, fees, and penalties) with no invented clauses, and explicitly identifies the one planted conflict between two clauses.
- No scheduled visit falls on an unsafe-access day, and no day has more than one vessel assigned. A reviewer pass explicitly confirms this by listing each assignment with a pass/fail result.
- The total cost in the schedule is arithmetically correct, recomputable from the stated fees and penalties, and no more than 5% above the known optimal cost for the provided inputs.
- Every high-severity buoy (those with vibration RMS or bearing temperature above the stated critical thresholds) is scheduled within the vendor's SLA window, or the memo flags it as an unavoidable breach with a reason.
- The risk memo is at most 400 words and names at least three specific residual risks tied to the data, such as forecast uncertainty on a given day or a single-vendor dependency.
Timing comparison
| Approach | Duration (ms) | Final status |
|---|---|---|
| Single call | 11709 | single solution is empty (solver returned null/empty) |
| Decomposed | 21364 | fail |
Decomposition attempts
Attempt 1 — source generation: ok · typecheck: fail · execute: skipped
Captured error
Error: spawn node ENOENT
Note: the second attempt asked the fixer to repair the program using that error; no source change was warranted by the error.
Attempt 2 — source generation: ok · typecheck: fail · execute: skipped
Captured error
Error: spawn node ENOENT
Note: no further attempts. The failure is a harness issue: the benchmark program's spawn("node", ...) could not find node from inside the rig --server subprocess. The generated source itself was never typechecked or executed, so its validity is unknown.
Grading
- Single-call score: 0
- Decomposed score: 0
- Winner: tie
- Rationale (verbatim): Neither solution produced any content. Solution A is empty and Solution B says the decomposition produced no solution. Neither meets any of the success criteria, so both score 0 and the result is a tie.
Single-call solution
Single-call solution (verbatim)
The solver returned an empty string (no content). Nothing to display.
Decomposed rig program source
import { agent, workflow, s } from "rig";
// Agent role: sensor data cleaner that flags anomalous buoys and justifies each exclusion or imputation
const cleanSensors = agent({
model: "medium",
instructions:
"You clean tidal-buoy sensor log summaries. Given the sensor tables and critical thresholds in the prompt, identify corrupted or missing data points and state for EACH one whether it was excluded or imputed, with a justification. List exactly which buoys are flagged as anomalous, and mark high-severity buoys (vibration RMS or bearing temperature above the critical thresholds). Do not invent data. Output markdown.",
output: s.string,
});
// Agent role: contract parser that builds a constraints and cost table and identifies clause conflicts
const parseContracts = agent({
model: "medium",
instructions:
"You parse vendor service contracts. Produce a markdown table covering EVERY clause (SLA hours, weather restrictions, per-callout fees, penalties) per vendor, with no invented clauses. Explicitly identify the conflict between two clauses and state a resolution assumption. Output markdown.",
output: s.string,
});
// Agent role: scheduler that assigns flagged buoys to vendors and days minimizing cost plus expected penalties
const buildSchedule = agent({
model: "large",
instructions:
"You build a 14-day maintenance schedule. Using the flagged buoys, the constraints table, and the weather forecast, assign each flagged buoy to a vendor and a day. Rules: never schedule on an unsafe-access day, at most one vessel per day, respect SLAs (high-severity buoys within SLA window), and minimize total cost plus expected penalties. Output a markdown schedule table (buoy, vendor, day, fee, penalty, reason) and a step-by-step total cost calculation that is arithmetically correct and recomputable. Prioritize by severity.",
output: s.string,
});
// Agent role: independent reviewer that verifies every assignment and writes the risk memo
const reviewSchedule = agent({
model: "large",
instructions:
"You are an independent reviewer. Check every schedule assignment against the constraints: list each assignment with PASS/FAIL for weather-safe day, one-vessel-per-day, and SLA compliance for high-severity buoys. Recompute the total cost and report any discrepancy. Then write a risk memo of at most 400 words naming at least three specific residual risks tied to the data (e.g., forecast uncertainty on a specific day, single-vendor dependency, imputed values). Flag any unavoidable SLA breach with a reason. Output markdown.",
output: s.string,
});
// Workflow role: combines the agents' outputs into the final markdown report
export default workflow({
meta: {
name: "tidal-buoy-maintenance-reconciliation",
description:
"Cleans sensor data, parses contracts, schedules maintenance, reviews it, and assembles a markdown report.",
},
body: async ({ call }) => {
const cleaned =
(await call(
cleanSensors,
"Clean the 30-day sensor log summaries for the 12 buoys embedded in the task inputs and flag anomalous buoys."
)) ?? "";
const constraints =
(await call(
parseContracts,
"Parse the three vendor contracts embedded in the task inputs into a constraints and costs table and identify the planted clause conflict."
)) ?? "";
const schedule =
(await call(
buildSchedule,
"Build the schedule.\n\n## Cleaned data findings\n" +
cleaned +
"\n\n## Constraints\n" +
constraints +
"\n\nUse the 14-day weather forecast from the task inputs for safe-access days."
)) ?? "";
const review =
(await call(
reviewSchedule,
"Review this schedule independently.\n\n## Constraints\n" +
constraints +
"\n\n## Findings\n" +
cleaned +
"\n\n## Schedule\n" +
schedule
)) ?? "";
const report =
"# Tidal Buoy Array Maintenance Report\n\n## 1. Cleaned-Data Findings\n" +
cleaned +
"\n\n## 2. Constraints Table\n" +
constraints +
"\n\n## 3. Schedule and Total Cost\n" +
schedule +
"\n\n## 4. Reviewer Verification and Risk Memo\n" +
review;
return { solution: report };
},
});
Decomposed solution:
Decomposed solution
Empty — execution never ran (typecheck subprocess failed with spawn node ENOENT on both attempts).
Benchmark program (Step 1)
bench.ts
import { agent, workflow, s, repair, configureAgent, copilotEngine } from "rig";
configureAgent(copilotEngine({ server: true }));
const DEADLINE = Date.now() + 25 * 60_000;
const remaining = () => DEADLINE - Date.now();
const SKELETON = `import { agent, workflow, s } from "rig";
// Agent role: <role>
const analyze = agent({ model: "small", instructions: "...", output: s.string });
// Workflow role: combines the agents' outputs into the final solution
export default workflow({
meta: { name: "decomposed-solution", description: "..." },
body: async ({ call }) => {
const analysis = await call(analyze, "...");
return { solution: analysis ?? "" };
},
});`;
const CONTRACT = `Write ONE self-contained TypeScript program for the "rig" library. Rules:
- Import ONLY from "rig": import { agent, workflow, s } from "rig";
- Define at least TWO agents, each preceded by a comment "// Agent role: ...". Use model "small" for simple sub-steps and "medium" or "large" for harder ones. Every agent uses output: s.string (free-form text / source), never an object wrapper for large content.
- The root must be \`export default workflow({...})\`, exported without invoking it, taking NO required input.
- A workflow() spec accepts ONLY meta ({name, description}), an optional input, and body. It has NO output or execute field. The final { solution: string } object is simply what body returns.
- body is async ({ call }) => {...}; use \`await call(agentFn, "prompt string")\` which returns string or null; coalesce null with ?? "".
- The final answer must COMBINE outputs of multiple agents (not one agent solving everything).
- Alternatively an agent() root must declare output: s.object({ solution: s.string }), but prefer the workflow.
- Output only the program source, no commentary. Markdown fences are tolerated.
Required shape (abridged to one agent; yours needs at least two):
${SKELETON}`;
// Agent role: pick a concrete benchmark task with success criteria.
const picker = agent({
name: "picker",
model: "small",
maxTurns: 2,
addons: [repair()],
instructions:
"Pick ONE concrete, complicated task a person or team might face in a single day that would naturally benefit from being split across sub-agents running different models (multi-source research and synthesis, multi-file coding with design/implementation/review, structured multi-analysis report, or multi-step data transformation). It must be self-contained (no external files or live web) and gradable. Vary the domain; choose something unusual. Return title, domain, description, and 3-6 concrete checkable success criteria.",
output: s.object({
title: s.string,
domain: s.string,
description: s.string,
criteria: s.array(s.string),
}),
});
// Agent role: solve the whole task alone in a single turn.
const solver = agent({
name: "solver",
model: "medium",
maxTurns: 1,
instructions:
"Solve the entire task yourself in one response, explicitly addressing every success criterion. No delegation, no tools. Return the complete solution.",
output: s.string,
});
// Agent role: write (or fix) a decomposed rig program.
const writer = agent({
name: "writer",
model: "medium",
maxTurns: 1,
instructions: CONTRACT,
output: s.string,
});
// Agent role: grade both solutions.
const grader = agent({
name: "grader",
model: "large",
maxTurns: 1,
instructions:
"Score each solution 0-10 on how completely and correctly it satisfies the success criteria. Judge only correctness and completeness of content — not length, and not which approach produced it. Pick winner 'single-call', 'decomposed', or 'tie' and explain.",
output: s.object({
singleScore: s.number,
decomposedScore: s.number,
winner: s.enum("single-call", "decomposed", "tie"),
rationale: s.string,
}),
});
type Attempt = {
attempt: number;
generation: string;
typecheck: string;
execute: string;
error: string;
};
function stripFences(src: string): string {
const m = src.match(/```(?:ts|typescript|rig)?\s*\n([\s\S]*?)```/);
return (m ? m[1]! : src).trim();
}
async function runRig(source: string, flag: string, limitMs: number) {
const { spawn } = await import("node:child_process");
return new Promise<{ code: number | null; stdout: string; stderr: string; timedOut: boolean }>((resolve) => {
const child = spawn("node", ["rig.ts", flag], { cwd: ".github/skills/rig" });
let stdout = "";
let stderr = "";
let timedOut = false;
const t = setTimeout(() => {
timedOut = true;
child.kill("SIGKILL");
}, Math.max(1000, limitMs));
child.stdout.on("data", (d: unknown) => { stdout += String(d); });
child.stderr.on("data", (d: unknown) => { stderr += String(d); });
child.on("error", (e: Error) => { clearTimeout(t); resolve({ code: -1, stdout, stderr: stderr + String(e), timedOut }); });
child.on("close", (code: number | null) => { clearTimeout(t); resolve({ code, stdout, stderr, timedOut }); });
child.stdin.on("error", () => {});
child.stdin.end(source);
});
}
// Workflow role: orchestrate pick, single-call, decomposed, and grading phases deterministically.
export default workflow({
meta: {
name: "decomposition-benchmark",
description: "Compare single-call vs decomposed solutions of a picked task",
phases: ["Pick", "Single", "Decompose", "Grade"],
},
body: async ({ call, phase }) => {
phase("Pick");
const task = await call(picker, "Pick the task now.");
if (!task) {
return { task: null, error: "task picker returned null", status: "fail", attempts: [] as Attempt[] };
}
const taskText = `Title: ${task.title}\nDomain: ${task.domain}\nDescription: ${task.description}\nSuccess criteria:\n${task.criteria.map((c: string, i: number) => `${i + 1}. ${c}`).join("\n")}`;
phase("Single");
const t0 = Date.now();
const single = (await call(solver, taskText)) ?? "";
const singleMs = Date.now() - t0;
phase("Decompose");
const d0 = Date.now();
const attempts: Attempt[] = [];
let source = "";
let solution = "";
let status = "fail";
let lastError = "";
for (let n = 1; n <= 2; n++) {
if (remaining() < 3 * 60_000) {
attempts.push({ attempt: n, generation: "skipped (time budget)", typecheck: "skipped", execute: "skipped", error: "" });
break;
}
let prompt: string;
if (n === 1) {
prompt = `Task:\n${taskText}\n\nWrite the decomposed rig program.`;
} else if (source.trim()) {
prompt = `Task:\n${taskText}\n\nFix this program. Fix precisely what the error names and preserve what already worked.\n\nRequired shape:\n${SKELETON}\n\nProgram:\n${source}\n\nError:\n${lastError}`;
} else {
prompt = `Task:\n${taskText}\n\nThere is no source to fix; the previous attempt produced nothing. Generate the complete program from the task and this required shape:\n${SKELETON}`;
}
const raw = await call(writer, prompt);
const cleaned = raw ? stripFences(raw) : "";
if (!cleaned.trim()) {
attempts.push({ attempt: n, generation: "empty", typecheck: "skipped", execute: "skipped", error: "writer returned null/empty" });
lastError = "";
continue;
}
source = cleaned;
const rec: Attempt = { attempt: n, generation: "ok", typecheck: "skipped", execute: "skipped", error: "" };
attempts.push(rec);
const tc = await runRig(source, "--typecheck", Math.min(2 * 60_000, remaining()));
if (tc.code !== 0) {
rec.typecheck = tc.timedOut ? "timeout" : "fail";
rec.error = (tc.stdout + tc.stderr).trim() || "typecheck failed";
lastError = rec.error;
continue;
}
rec.typecheck = "pass";
if (remaining() < 60_000) { rec.execute = "skipped (time budget)"; break; }
const ex = await runRig(source, "--server", Math.min(5 * 60_000, remaining()));
if (ex.code !== 0) {
rec.execute = ex.timedOut ? "timeout" : "fail";
rec.error = (ex.stdout + "\n" + ex.stderr).trim();
lastError = rec.error;
continue;
}
rec.execute = "pass";
try {
const parsed = JSON.parse(ex.stdout.trim());
solution = typeof parsed?.solution === "string" ? parsed.solution : JSON.stringify(parsed);
} catch {
solution = ex.stdout.trim();
}
status = solution.trim() ? "pass" : "fail";
break;
}
const decomposedMs = Date.now() - d0;
phase("Grade");
const decomposedForGrade = solution.trim() ? solution : "(Decomposition produced no solution.)";
const grade = remaining() > 0
? await call(grader, `${taskText}\n\n=== SOLUTION A (single-call) ===\n${single || "(empty)"}\n\n=== SOLUTION B (decomposed) ===\n${decomposedForGrade}`)
: null;
return { task, singleMs, decomposedMs, single, decomposedSolution: solution, attempts, status, grade, decomposedSource: source };
},
});
Verdict
Winner: tie — both scored 0/10: the single-call solver returned an empty string, and the decomposed program never executed because the benchmark's spawn("node") failed with ENOENT (a harness bug, not a rig-API error). The run was not repeated, per the one-run rule.
Generated by Daily Rig Decomposition Benchmark · copilot · auto · ~62 AIC · ⌖ ~1 AIC · ⊞ 4.1K · ◷
- expires on Nov 3, 2026, 1:12 PM UTC
- Lingua principale
- TypeScript
- Stelle
- 14
- Fork
- 0
- Merge medio
- 9h 27m
- PR unite (30g)
- 34
Preparare l'ambiente
Questo progetto non fornisce container di sviluppo, Dockerfile né guida per i contributori, quindi l'ambiente è a tuo carico: parti dal suo README e consulta la nostra guida al primo contributo per i passaggi generali.
Come iniziare
- Leggi tutta la issue e poi la guida ai contributi del progetto.
- Commenta sulla issue per dire che te ne occupi tu — evita che due persone facciano lo stesso lavoro.
- Fai un fork del repository e lavora su un branch.
- Apri una pull request che faccia riferimento al numero della issue.
Altre issue di githubnext/rig
-
agentic-workflows
Difficoltà 4/5 3-5 giorni Idoneità per principianti 12/100
githubnext/rig#738 ·
I maintainer di solito rispondono entro 1 giorno
-
ai-agent automation
Difficoltà 4/5 3-5 giorni Idoneità per principianti 42/100
githubnext/rig#737 ·
I maintainer di solito rispondono entro 1 giorno
-
agentic-workflows
Difficoltà 4/5 3-5 giorni Idoneità per principianti 22/100
githubnext/rig#736 ·
I maintainer di solito rispondono entro 1 giorno
-
ai-agent automation
Difficoltà 3/5 1-2 giorni Idoneità per principianti 18/100
githubnext/rig#735 ·
I maintainer di solito rispondono entro 1 giorno
-
[aw] Upgrade availableApertaagentic-workflows
Difficoltà 1/5 Meno di un'ora Idoneità per principianti 15/100
githubnext/rig#732 ·
I maintainer di solito rispondono entro 1 giorno
Tutte le issue di githubnext/rig
Issue simili
-
bug
Difficoltà 2/5 1-3 ore Idoneità per principianti 82/100
scaleway/ultraviolet#7089 ·
I maintainer di solito rispondono entro 2 giorni
-
Difficoltà 2/5 1-3 ore Idoneità per principianti 72/100
I maintainer di solito rispondono entro 1 giorno
-
Difficoltà 2/5 1-3 ore Idoneità per principianti 67/100
tencent-connect/dsh-qqbot#81 ·
I maintainer di solito rispondono entro 1 giorno
-
[Bug]: Pen taps on sidebar rows start a drag and lose their clickForse già presa @makhnatkin l’ha presa oggi. Aperta
Difficoltà 2/5 1-3 ore Idoneità per principianti 62/100
I maintainer di solito rispondono entro 1 giorno
-
bug
Difficoltà 2/5 1-3 ore Idoneità per principianti 66/100
clangd/vscode-clangd#1009 ·