diff --git a/cookbook/copilot-sdk/dotnet/ralph-loop.md b/cookbook/copilot-sdk/dotnet/ralph-loop.md index eccd2c29..8ff85246 100644 --- a/cookbook/copilot-sdk/dotnet/ralph-loop.md +++ b/cookbook/copilot-sdk/dotnet/ralph-loop.md @@ -39,7 +39,7 @@ A [Ralph loop](https://ghuntley.com/ralph/) is an autonomous development workflo ## Simple Version -The minimal Ralph loop — the SDK equivalent of `while :; do cat PROMPT.md | claude ; done`: +The minimal Ralph loop — the SDK equivalent of `while :; do cat PROMPT.md | copilot ; done`: ```csharp using GitHub.Copilot.SDK; @@ -205,9 +205,9 @@ creating ad-hoc copies. 4. When tests pass, update IMPLEMENTATION_PLAN.md, then `git add -A` then `git commit` with a descriptive message. -99999. When authoring documentation, capture the why. -999999. Implement completely. No placeholders or stubs. -9999999. Keep IMPLEMENTATION_PLAN.md current — future iterations depend on it. +5. When authoring documentation, capture the why. +6. Implement completely. No placeholders or stubs. +7. Keep IMPLEMENTATION_PLAN.md current — future iterations depend on it. ``` ### Example `AGENTS.md` @@ -241,12 +241,14 @@ dotnet build ## When to Use a Ralph Loop **Good for:** + - Implementing features from specs with test-driven validation - Large refactors broken into many small tasks - Unattended, long-running development with clear requirements - Any work where backpressure (tests/builds) can verify correctness **Not good for:** + - Tasks requiring human judgment mid-loop - One-shot operations that don't benefit from iteration - Vague requirements without testable acceptance criteria diff --git a/cookbook/copilot-sdk/go/ralph-loop.md b/cookbook/copilot-sdk/go/ralph-loop.md index 4d3bf373..626ed5ea 100644 --- a/cookbook/copilot-sdk/go/ralph-loop.md +++ b/cookbook/copilot-sdk/go/ralph-loop.md @@ -39,7 +39,7 @@ A [Ralph loop](https://ghuntley.com/ralph/) is an autonomous development workflo ## Simple Version -The minimal Ralph loop — the SDK equivalent of `while :; do cat PROMPT.md | claude ; done`: +The minimal Ralph loop — the SDK equivalent of `while :; do cat PROMPT.md | copilot ; done`: ```go package main @@ -241,9 +241,9 @@ creating ad-hoc copies. 4. When tests pass, update IMPLEMENTATION_PLAN.md, then `git add -A` then `git commit` with a descriptive message. -99999. When authoring documentation, capture the why. -999999. Implement completely. No placeholders or stubs. -9999999. Keep IMPLEMENTATION_PLAN.md current — future iterations depend on it. +5. When authoring documentation, capture the why. +6. Implement completely. No placeholders or stubs. +7. Keep IMPLEMENTATION_PLAN.md current — future iterations depend on it. ``` ### Example `AGENTS.md` @@ -277,12 +277,14 @@ go build ./... ## When to Use a Ralph Loop **Good for:** + - Implementing features from specs with test-driven validation - Large refactors broken into many small tasks - Unattended, long-running development with clear requirements - Any work where backpressure (tests/builds) can verify correctness **Not good for:** + - Tasks requiring human judgment mid-loop - One-shot operations that don't benefit from iteration - Vague requirements without testable acceptance criteria diff --git a/cookbook/copilot-sdk/nodejs/ralph-loop.md b/cookbook/copilot-sdk/nodejs/ralph-loop.md index 1abb692c..87c5225f 100644 --- a/cookbook/copilot-sdk/nodejs/ralph-loop.md +++ b/cookbook/copilot-sdk/nodejs/ralph-loop.md @@ -39,35 +39,35 @@ A [Ralph loop](https://ghuntley.com/ralph/) is an autonomous development workflo ## Simple Version -The minimal Ralph loop — the SDK equivalent of `while :; do cat PROMPT.md | claude ; done`: +The minimal Ralph loop — the SDK equivalent of `while :; do cat PROMPT.md | copilot ; done`: ```typescript import { readFile } from "fs/promises"; import { CopilotClient } from "@github/copilot-sdk"; async function ralphLoop(promptFile: string, maxIterations: number = 50) { - const client = new CopilotClient(); - await client.start(); + const client = new CopilotClient(); + await client.start(); - try { - const prompt = await readFile(promptFile, "utf-8"); + try { + const prompt = await readFile(promptFile, "utf-8"); - for (let i = 1; i <= maxIterations; i++) { - console.log(`\n=== Iteration ${i}/${maxIterations} ===`); + for (let i = 1; i <= maxIterations; i++) { + console.log(`\n=== Iteration ${i}/${maxIterations} ===`); - // Fresh session each iteration — context isolation is the point - const session = await client.createSession({ model: "gpt-5.1-codex-mini" }); - try { - await session.sendAndWait({ prompt }, 600_000); - } finally { - await session.destroy(); - } + // Fresh session each iteration — context isolation is the point + const session = await client.createSession({ model: "gpt-5.1-codex-mini" }); + try { + await session.sendAndWait({ prompt }, 600_000); + } finally { + await session.destroy(); + } - console.log(`Iteration ${i} complete.`); - } - } finally { - await client.stop(); + console.log(`Iteration ${i} complete.`); } + } finally { + await client.stop(); + } } // Usage: point at your PROMPT.md @@ -87,50 +87,50 @@ import { CopilotClient } from "@github/copilot-sdk"; type Mode = "plan" | "build"; async function ralphLoop(mode: Mode, maxIterations: number = 50) { - const promptFile = mode === "plan" ? "PROMPT_plan.md" : "PROMPT_build.md"; - const client = new CopilotClient(); - await client.start(); + const promptFile = mode === "plan" ? "PROMPT_plan.md" : "PROMPT_build.md"; + const client = new CopilotClient(); + await client.start(); - console.log(`Mode: ${mode} | Prompt: ${promptFile}`); + console.log(`Mode: ${mode} | Prompt: ${promptFile}`); - try { - const prompt = await readFile(promptFile, "utf-8"); + try { + const prompt = await readFile(promptFile, "utf-8"); - for (let i = 1; i <= maxIterations; i++) { - console.log(`\n=== Iteration ${i}/${maxIterations} ===`); + for (let i = 1; i <= maxIterations; i++) { + console.log(`\n=== Iteration ${i}/${maxIterations} ===`); - const session = await client.createSession({ - model: "gpt-5.1-codex-mini", - // Pin the agent to the project directory - workingDirectory: process.cwd(), - // Auto-approve tool calls for unattended operation - onPermissionRequest: async () => ({ allow: true }), - }); + const session = await client.createSession({ + model: "gpt-5.1-codex-mini", + // Pin the agent to the project directory + workingDirectory: process.cwd(), + // Auto-approve tool calls for unattended operation + onPermissionRequest: async () => ({ allow: true }), + }); - // Log tool usage for visibility - session.on((event) => { - if (event.type === "tool.execution_start") { - console.log(` ⚙ ${event.data.toolName}`); - } - }); - - try { - await session.sendAndWait({ prompt }, 600_000); - } finally { - await session.destroy(); - } - - console.log(`Iteration ${i} complete.`); + // Log tool usage for visibility + session.on((event) => { + if (event.type === "tool.execution_start") { + console.log(` ⚙ ${event.data.toolName}`); } - } finally { - await client.stop(); + }); + + try { + await session.sendAndWait({ prompt }, 600_000); + } finally { + await session.destroy(); + } + + console.log(`Iteration ${i} complete.`); } + } finally { + await client.stop(); + } } // Parse CLI args: npx tsx ralph-loop.ts [plan] [max_iterations] const args = process.argv.slice(2); const mode: Mode = args.includes("plan") ? "plan" : "build"; -const maxArg = args.find(a => /^\d+$/.test(a)); +const maxArg = args.find((a) => /^\d+$/.test(a)); const maxIterations = maxArg ? parseInt(maxArg) : 50; ralphLoop(mode, maxIterations); @@ -182,9 +182,9 @@ creating ad-hoc copies. 4. When tests pass, update IMPLEMENTATION_PLAN.md, then `git add -A` then `git commit` with a descriptive message. -99999. When authoring documentation, capture the why. -999999. Implement completely. No placeholders or stubs. -9999999. Keep IMPLEMENTATION_PLAN.md current — future iterations depend on it. +5. When authoring documentation, capture the why. +6. Implement completely. No placeholders or stubs. +7. Keep IMPLEMENTATION_PLAN.md current — future iterations depend on it. ``` ### Example `AGENTS.md` @@ -219,12 +219,14 @@ npm run build ## When to Use a Ralph Loop **Good for:** + - Implementing features from specs with test-driven validation - Large refactors broken into many small tasks - Unattended, long-running development with clear requirements - Any work where backpressure (tests/builds) can verify correctness **Not good for:** + - Tasks requiring human judgment mid-loop - One-shot operations that don't benefit from iteration - Vague requirements without testable acceptance criteria diff --git a/cookbook/copilot-sdk/nodejs/recipe/package-lock.json b/cookbook/copilot-sdk/nodejs/recipe/package-lock.json new file mode 100644 index 00000000..47e85e5a --- /dev/null +++ b/cookbook/copilot-sdk/nodejs/recipe/package-lock.json @@ -0,0 +1,629 @@ +{ + "name": "copilot-sdk-cookbook-recipes", + "version": "1.0.0", + "lockfileVersion": 3, + "requires": true, + "packages": { + "": { + "name": "copilot-sdk-cookbook-recipes", + "version": "1.0.0", + "dependencies": { + "@github/copilot-sdk": "*" + }, + "devDependencies": { + "@types/node": "^22.19.7", + "tsx": "^4.19.2", + "typescript": "^5.7.2" + } + }, + "../..": { + "name": "@github/copilot-sdk", + "version": "0.1.8", + "license": "MIT", + "dependencies": { + "@github/copilot": "^0.0.388-1", + "vscode-jsonrpc": "^8.2.1", + "zod": "^4.3.5" + }, + "devDependencies": { + "@types/node": "^22.19.6", + "@typescript-eslint/eslint-plugin": "^8.0.0", + "@typescript-eslint/parser": "^8.0.0", + "esbuild": "^0.27.0", + "eslint": "^9.0.0", + "glob": "^11.0.0", + "json-schema": "^0.4.0", + "json-schema-to-typescript": "^15.0.4", + "prettier": "^3.4.0", + "quicktype-core": "^23.2.6", + "rimraf": "^6.1.2", + "semver": "^7.7.3", + "tsx": "^4.20.6", + "typescript": "^5.0.0", + "vitest": "^4.0.16" + }, + "engines": { + "node": ">=18.0.0" + } + }, + "../../..": {}, + "../../src": {}, + "node_modules/@esbuild/aix-ppc64": { + "version": "0.27.2", + "resolved": "https://registry.npmjs.org/@esbuild/aix-ppc64/-/aix-ppc64-0.27.2.tgz", + "integrity": "sha512-GZMB+a0mOMZs4MpDbj8RJp4cw+w1WV5NYD6xzgvzUJ5Ek2jerwfO2eADyI6ExDSUED+1X8aMbegahsJi+8mgpw==", + "cpu": [ + "ppc64" + ], + "dev": true, + "license": "MIT", + "optional": true, + "os": [ + "aix" + ], + "engines": { + "node": ">=18" + } + }, + "node_modules/@esbuild/android-arm": { + "version": "0.27.2", + "resolved": "https://registry.npmjs.org/@esbuild/android-arm/-/android-arm-0.27.2.tgz", + "integrity": "sha512-DVNI8jlPa7Ujbr1yjU2PfUSRtAUZPG9I1RwW4F4xFB1Imiu2on0ADiI/c3td+KmDtVKNbi+nffGDQMfcIMkwIA==", + "cpu": [ + "arm" + ], + "dev": true, + "license": "MIT", + "optional": true, + "os": [ + "android" + ], + "engines": { + "node": ">=18" + } + }, + "node_modules/@esbuild/android-arm64": { + "version": "0.27.2", + "resolved": "https://registry.npmjs.org/@esbuild/android-arm64/-/android-arm64-0.27.2.tgz", + "integrity": "sha512-pvz8ZZ7ot/RBphf8fv60ljmaoydPU12VuXHImtAs0XhLLw+EXBi2BLe3OYSBslR4rryHvweW5gmkKFwTiFy6KA==", + "cpu": [ + "arm64" + ], + "dev": true, + "license": "MIT", + "optional": true, + "os": [ + "android" + ], + "engines": { + "node": ">=18" + } + }, + "node_modules/@esbuild/android-x64": { + "version": "0.27.2", + "resolved": "https://registry.npmjs.org/@esbuild/android-x64/-/android-x64-0.27.2.tgz", + "integrity": "sha512-z8Ank4Byh4TJJOh4wpz8g2vDy75zFL0TlZlkUkEwYXuPSgX8yzep596n6mT7905kA9uHZsf/o2OJZubl2l3M7A==", + "cpu": [ + "x64" + ], + "dev": true, + "license": "MIT", + "optional": true, + "os": [ + "android" + ], + "engines": { + "node": ">=18" + } + }, + "node_modules/@esbuild/darwin-arm64": { + "version": "0.27.2", + "resolved": "https://registry.npmjs.org/@esbuild/darwin-arm64/-/darwin-arm64-0.27.2.tgz", + "integrity": "sha512-davCD2Zc80nzDVRwXTcQP/28fiJbcOwvdolL0sOiOsbwBa72kegmVU0Wrh1MYrbuCL98Omp5dVhQFWRKR2ZAlg==", + "cpu": [ + "arm64" + ], + "dev": true, + "license": "MIT", + "optional": true, + "os": [ + "darwin" + ], + "engines": { + "node": ">=18" + } + }, + "node_modules/@esbuild/darwin-x64": { + "version": "0.27.2", + "resolved": "https://registry.npmjs.org/@esbuild/darwin-x64/-/darwin-x64-0.27.2.tgz", + "integrity": "sha512-ZxtijOmlQCBWGwbVmwOF/UCzuGIbUkqB1faQRf5akQmxRJ1ujusWsb3CVfk/9iZKr2L5SMU5wPBi1UWbvL+VQA==", + "cpu": [ + "x64" + ], + "dev": true, + "license": "MIT", + "optional": true, + "os": [ + "darwin" + ], + "engines": { + "node": ">=18" + } + }, + "node_modules/@esbuild/freebsd-arm64": { + "version": "0.27.2", + "resolved": "https://registry.npmjs.org/@esbuild/freebsd-arm64/-/freebsd-arm64-0.27.2.tgz", + "integrity": "sha512-lS/9CN+rgqQ9czogxlMcBMGd+l8Q3Nj1MFQwBZJyoEKI50XGxwuzznYdwcav6lpOGv5BqaZXqvBSiB/kJ5op+g==", + "cpu": [ + "arm64" + ], + "dev": true, + "license": "MIT", + "optional": true, + "os": [ + "freebsd" + ], + "engines": { + "node": ">=18" + } + }, + "node_modules/@esbuild/freebsd-x64": { + "version": "0.27.2", + "resolved": "https://registry.npmjs.org/@esbuild/freebsd-x64/-/freebsd-x64-0.27.2.tgz", + "integrity": "sha512-tAfqtNYb4YgPnJlEFu4c212HYjQWSO/w/h/lQaBK7RbwGIkBOuNKQI9tqWzx7Wtp7bTPaGC6MJvWI608P3wXYA==", + "cpu": [ + "x64" + ], + "dev": true, + "license": "MIT", + "optional": true, + "os": [ + "freebsd" + ], + "engines": { + "node": ">=18" + } + }, + "node_modules/@esbuild/linux-arm": { + "version": "0.27.2", + "resolved": "https://registry.npmjs.org/@esbuild/linux-arm/-/linux-arm-0.27.2.tgz", + "integrity": "sha512-vWfq4GaIMP9AIe4yj1ZUW18RDhx6EPQKjwe7n8BbIecFtCQG4CfHGaHuh7fdfq+y3LIA2vGS/o9ZBGVxIDi9hw==", + "cpu": [ + "arm" + ], + "dev": true, + "license": "MIT", + "optional": true, + "os": [ + "linux" + ], + "engines": { + "node": ">=18" + } + }, + "node_modules/@esbuild/linux-arm64": { + "version": "0.27.2", + "resolved": "https://registry.npmjs.org/@esbuild/linux-arm64/-/linux-arm64-0.27.2.tgz", + "integrity": "sha512-hYxN8pr66NsCCiRFkHUAsxylNOcAQaxSSkHMMjcpx0si13t1LHFphxJZUiGwojB1a/Hd5OiPIqDdXONia6bhTw==", + "cpu": [ + "arm64" + ], + "dev": true, + "license": "MIT", + "optional": true, + "os": [ + "linux" + ], + "engines": { + "node": ">=18" + } + }, + "node_modules/@esbuild/linux-ia32": { + "version": "0.27.2", + "resolved": "https://registry.npmjs.org/@esbuild/linux-ia32/-/linux-ia32-0.27.2.tgz", + "integrity": "sha512-MJt5BRRSScPDwG2hLelYhAAKh9imjHK5+NE/tvnRLbIqUWa+0E9N4WNMjmp/kXXPHZGqPLxggwVhz7QP8CTR8w==", + "cpu": [ + "ia32" + ], + "dev": true, + "license": "MIT", + "optional": true, + "os": [ + "linux" + ], + "engines": { + "node": ">=18" + } + }, + "node_modules/@esbuild/linux-loong64": { + "version": "0.27.2", + "resolved": "https://registry.npmjs.org/@esbuild/linux-loong64/-/linux-loong64-0.27.2.tgz", + "integrity": "sha512-lugyF1atnAT463aO6KPshVCJK5NgRnU4yb3FUumyVz+cGvZbontBgzeGFO1nF+dPueHD367a2ZXe1NtUkAjOtg==", + "cpu": [ + "loong64" + ], + "dev": true, + "license": "MIT", + "optional": true, + "os": [ + "linux" + ], + "engines": { + "node": ">=18" + } + }, + "node_modules/@esbuild/linux-mips64el": { + "version": "0.27.2", + "resolved": "https://registry.npmjs.org/@esbuild/linux-mips64el/-/linux-mips64el-0.27.2.tgz", + "integrity": "sha512-nlP2I6ArEBewvJ2gjrrkESEZkB5mIoaTswuqNFRv/WYd+ATtUpe9Y09RnJvgvdag7he0OWgEZWhviS1OTOKixw==", + "cpu": [ + "mips64el" + ], + "dev": true, + "license": "MIT", + "optional": true, + "os": [ + "linux" + ], + "engines": { + "node": ">=18" + } + }, + "node_modules/@esbuild/linux-ppc64": { + "version": "0.27.2", + "resolved": "https://registry.npmjs.org/@esbuild/linux-ppc64/-/linux-ppc64-0.27.2.tgz", + "integrity": "sha512-C92gnpey7tUQONqg1n6dKVbx3vphKtTHJaNG2Ok9lGwbZil6DrfyecMsp9CrmXGQJmZ7iiVXvvZH6Ml5hL6XdQ==", + "cpu": [ + "ppc64" + ], + "dev": true, + "license": "MIT", + "optional": true, + "os": [ + "linux" + ], + "engines": { + "node": ">=18" + } + }, + "node_modules/@esbuild/linux-riscv64": { + "version": "0.27.2", + "resolved": "https://registry.npmjs.org/@esbuild/linux-riscv64/-/linux-riscv64-0.27.2.tgz", + "integrity": "sha512-B5BOmojNtUyN8AXlK0QJyvjEZkWwy/FKvakkTDCziX95AowLZKR6aCDhG7LeF7uMCXEJqwa8Bejz5LTPYm8AvA==", + "cpu": [ + "riscv64" + ], + "dev": true, + "license": "MIT", + "optional": true, + "os": [ + "linux" + ], + "engines": { + "node": ">=18" + } + }, + "node_modules/@esbuild/linux-s390x": { + "version": "0.27.2", + "resolved": "https://registry.npmjs.org/@esbuild/linux-s390x/-/linux-s390x-0.27.2.tgz", + "integrity": "sha512-p4bm9+wsPwup5Z8f4EpfN63qNagQ47Ua2znaqGH6bqLlmJ4bx97Y9JdqxgGZ6Y8xVTixUnEkoKSHcpRlDnNr5w==", + "cpu": [ + "s390x" + ], + "dev": true, + "license": "MIT", + "optional": true, + "os": [ + "linux" + ], + "engines": { + "node": ">=18" + } + }, + "node_modules/@esbuild/linux-x64": { + "version": "0.27.2", + "resolved": "https://registry.npmjs.org/@esbuild/linux-x64/-/linux-x64-0.27.2.tgz", + "integrity": "sha512-uwp2Tip5aPmH+NRUwTcfLb+W32WXjpFejTIOWZFw/v7/KnpCDKG66u4DLcurQpiYTiYwQ9B7KOeMJvLCu/OvbA==", + "cpu": [ + "x64" + ], + "dev": true, + "license": "MIT", + "optional": true, + "os": [ + "linux" + ], + "engines": { + "node": ">=18" + } + }, + "node_modules/@esbuild/netbsd-arm64": { + "version": "0.27.2", + "resolved": "https://registry.npmjs.org/@esbuild/netbsd-arm64/-/netbsd-arm64-0.27.2.tgz", + "integrity": "sha512-Kj6DiBlwXrPsCRDeRvGAUb/LNrBASrfqAIok+xB0LxK8CHqxZ037viF13ugfsIpePH93mX7xfJp97cyDuTZ3cw==", + "cpu": [ + "arm64" + ], + "dev": true, + "license": "MIT", + "optional": true, + "os": [ + "netbsd" + ], + "engines": { + "node": ">=18" + } + }, + "node_modules/@esbuild/netbsd-x64": { + "version": "0.27.2", + "resolved": "https://registry.npmjs.org/@esbuild/netbsd-x64/-/netbsd-x64-0.27.2.tgz", + "integrity": "sha512-HwGDZ0VLVBY3Y+Nw0JexZy9o/nUAWq9MlV7cahpaXKW6TOzfVno3y3/M8Ga8u8Yr7GldLOov27xiCnqRZf0tCA==", + "cpu": [ + "x64" + ], + "dev": true, + "license": "MIT", + "optional": true, + "os": [ + "netbsd" + ], + "engines": { + "node": ">=18" + } + }, + "node_modules/@esbuild/openbsd-arm64": { + "version": "0.27.2", + "resolved": "https://registry.npmjs.org/@esbuild/openbsd-arm64/-/openbsd-arm64-0.27.2.tgz", + "integrity": "sha512-DNIHH2BPQ5551A7oSHD0CKbwIA/Ox7+78/AWkbS5QoRzaqlev2uFayfSxq68EkonB+IKjiuxBFoV8ESJy8bOHA==", + "cpu": [ + "arm64" + ], + "dev": true, + "license": "MIT", + "optional": true, + "os": [ + "openbsd" + ], + "engines": { + "node": ">=18" + } + }, + "node_modules/@esbuild/openbsd-x64": { + "version": "0.27.2", + "resolved": "https://registry.npmjs.org/@esbuild/openbsd-x64/-/openbsd-x64-0.27.2.tgz", + "integrity": "sha512-/it7w9Nb7+0KFIzjalNJVR5bOzA9Vay+yIPLVHfIQYG/j+j9VTH84aNB8ExGKPU4AzfaEvN9/V4HV+F+vo8OEg==", + "cpu": [ + "x64" + ], + "dev": true, + "license": "MIT", + "optional": true, + "os": [ + "openbsd" + ], + "engines": { + "node": ">=18" + } + }, + "node_modules/@esbuild/openharmony-arm64": { + "version": "0.27.2", + "resolved": "https://registry.npmjs.org/@esbuild/openharmony-arm64/-/openharmony-arm64-0.27.2.tgz", + "integrity": "sha512-LRBbCmiU51IXfeXk59csuX/aSaToeG7w48nMwA6049Y4J4+VbWALAuXcs+qcD04rHDuSCSRKdmY63sruDS5qag==", + "cpu": [ + "arm64" + ], + "dev": true, + "license": "MIT", + "optional": true, + "os": [ + "openharmony" + ], + "engines": { + "node": ">=18" + } + }, + "node_modules/@esbuild/sunos-x64": { + "version": "0.27.2", + "resolved": "https://registry.npmjs.org/@esbuild/sunos-x64/-/sunos-x64-0.27.2.tgz", + "integrity": "sha512-kMtx1yqJHTmqaqHPAzKCAkDaKsffmXkPHThSfRwZGyuqyIeBvf08KSsYXl+abf5HDAPMJIPnbBfXvP2ZC2TfHg==", + "cpu": [ + "x64" + ], + "dev": true, + "license": "MIT", + "optional": true, + "os": [ + "sunos" + ], + "engines": { + "node": ">=18" + } + }, + "node_modules/@esbuild/win32-arm64": { + "version": "0.27.2", + "resolved": "https://registry.npmjs.org/@esbuild/win32-arm64/-/win32-arm64-0.27.2.tgz", + "integrity": "sha512-Yaf78O/B3Kkh+nKABUF++bvJv5Ijoy9AN1ww904rOXZFLWVc5OLOfL56W+C8F9xn5JQZa3UX6m+IktJnIb1Jjg==", + "cpu": [ + "arm64" + ], + "dev": true, + "license": "MIT", + "optional": true, + "os": [ + "win32" + ], + "engines": { + "node": ">=18" + } + }, + "node_modules/@esbuild/win32-ia32": { + "version": "0.27.2", + "resolved": "https://registry.npmjs.org/@esbuild/win32-ia32/-/win32-ia32-0.27.2.tgz", + "integrity": "sha512-Iuws0kxo4yusk7sw70Xa2E2imZU5HoixzxfGCdxwBdhiDgt9vX9VUCBhqcwY7/uh//78A1hMkkROMJq9l27oLQ==", + "cpu": [ + "ia32" + ], + "dev": true, + "license": "MIT", + "optional": true, + "os": [ + "win32" + ], + "engines": { + "node": ">=18" + } + }, + "node_modules/@esbuild/win32-x64": { + "version": "0.27.2", + "resolved": "https://registry.npmjs.org/@esbuild/win32-x64/-/win32-x64-0.27.2.tgz", + "integrity": "sha512-sRdU18mcKf7F+YgheI/zGf5alZatMUTKj/jNS6l744f9u3WFu4v7twcUI9vu4mknF4Y9aDlblIie0IM+5xxaqQ==", + "cpu": [ + "x64" + ], + "dev": true, + "license": "MIT", + "optional": true, + "os": [ + "win32" + ], + "engines": { + "node": ">=18" + } + }, + "node_modules/@github/copilot-sdk": { + "resolved": "../../src", + "link": true + }, + "node_modules/@types/node": { + "version": "22.19.7", + "resolved": "https://registry.npmjs.org/@types/node/-/node-22.19.7.tgz", + "integrity": "sha512-MciR4AKGHWl7xwxkBa6xUGxQJ4VBOmPTF7sL+iGzuahOFaO0jHCsuEfS80pan1ef4gWId1oWOweIhrDEYLuaOw==", + "dev": true, + "license": "MIT", + "dependencies": { + "undici-types": "~6.21.0" + } + }, + "node_modules/esbuild": { + "version": "0.27.2", + "resolved": "https://registry.npmjs.org/esbuild/-/esbuild-0.27.2.tgz", + "integrity": "sha512-HyNQImnsOC7X9PMNaCIeAm4ISCQXs5a5YasTXVliKv4uuBo1dKrG0A+uQS8M5eXjVMnLg3WgXaKvprHlFJQffw==", + "dev": true, + "hasInstallScript": true, + "license": "MIT", + "bin": { + "esbuild": "bin/esbuild" + }, + "engines": { + "node": ">=18" + }, + "optionalDependencies": { + "@esbuild/aix-ppc64": "0.27.2", + "@esbuild/android-arm": "0.27.2", + "@esbuild/android-arm64": "0.27.2", + "@esbuild/android-x64": "0.27.2", + "@esbuild/darwin-arm64": "0.27.2", + "@esbuild/darwin-x64": "0.27.2", + "@esbuild/freebsd-arm64": "0.27.2", + "@esbuild/freebsd-x64": "0.27.2", + "@esbuild/linux-arm": "0.27.2", + "@esbuild/linux-arm64": "0.27.2", + "@esbuild/linux-ia32": "0.27.2", + "@esbuild/linux-loong64": "0.27.2", + "@esbuild/linux-mips64el": "0.27.2", + "@esbuild/linux-ppc64": "0.27.2", + "@esbuild/linux-riscv64": "0.27.2", + "@esbuild/linux-s390x": "0.27.2", + "@esbuild/linux-x64": "0.27.2", + "@esbuild/netbsd-arm64": "0.27.2", + "@esbuild/netbsd-x64": "0.27.2", + "@esbuild/openbsd-arm64": "0.27.2", + "@esbuild/openbsd-x64": "0.27.2", + "@esbuild/openharmony-arm64": "0.27.2", + "@esbuild/sunos-x64": "0.27.2", + "@esbuild/win32-arm64": "0.27.2", + "@esbuild/win32-ia32": "0.27.2", + "@esbuild/win32-x64": "0.27.2" + } + }, + "node_modules/fsevents": { + "version": "2.3.3", + "resolved": "https://registry.npmjs.org/fsevents/-/fsevents-2.3.3.tgz", + "integrity": "sha512-5xoDfX+fL7faATnagmWPpbFtwh/R77WmMMqqHGS65C3vvB0YHrgF+B1YmZ3441tMj5n63k0212XNoJwzlhffQw==", + "dev": true, + "hasInstallScript": true, + "license": "MIT", + "optional": true, + "os": [ + "darwin" + ], + "engines": { + "node": "^8.16.0 || ^10.6.0 || >=11.0.0" + } + }, + "node_modules/get-tsconfig": { + "version": "4.13.0", + "resolved": "https://registry.npmjs.org/get-tsconfig/-/get-tsconfig-4.13.0.tgz", + "integrity": "sha512-1VKTZJCwBrvbd+Wn3AOgQP/2Av+TfTCOlE4AcRJE72W1ksZXbAx8PPBR9RzgTeSPzlPMHrbANMH3LbltH73wxQ==", + "dev": true, + "license": "MIT", + "dependencies": { + "resolve-pkg-maps": "^1.0.0" + }, + "funding": { + "url": "https://github.com/privatenumber/get-tsconfig?sponsor=1" + } + }, + "node_modules/resolve-pkg-maps": { + "version": "1.0.0", + "resolved": "https://registry.npmjs.org/resolve-pkg-maps/-/resolve-pkg-maps-1.0.0.tgz", + "integrity": "sha512-seS2Tj26TBVOC2NIc2rOe2y2ZO7efxITtLZcGSOnHHNOQ7CkiUBfw0Iw2ck6xkIhPwLhKNLS8BO+hEpngQlqzw==", + "dev": true, + "license": "MIT", + "funding": { + "url": "https://github.com/privatenumber/resolve-pkg-maps?sponsor=1" + } + }, + "node_modules/tsx": { + "version": "4.21.0", + "resolved": "https://registry.npmjs.org/tsx/-/tsx-4.21.0.tgz", + "integrity": "sha512-5C1sg4USs1lfG0GFb2RLXsdpXqBSEhAaA/0kPL01wxzpMqLILNxIxIOKiILz+cdg/pLnOUxFYOR5yhHU666wbw==", + "dev": true, + "license": "MIT", + "dependencies": { + "esbuild": "~0.27.0", + "get-tsconfig": "^4.7.5" + }, + "bin": { + "tsx": "dist/cli.mjs" + }, + "engines": { + "node": ">=18.0.0" + }, + "optionalDependencies": { + "fsevents": "~2.3.3" + } + }, + "node_modules/typescript": { + "version": "5.9.3", + "resolved": "https://registry.npmjs.org/typescript/-/typescript-5.9.3.tgz", + "integrity": "sha512-jl1vZzPDinLr9eUt3J/t7V6FgNEw9QjvBPdysz9KfQDD41fQrC2Y4vKQdiaUpFT4bXlb1RHhLpp8wtm6M5TgSw==", + "dev": true, + "license": "Apache-2.0", + "bin": { + "tsc": "bin/tsc", + "tsserver": "bin/tsserver" + }, + "engines": { + "node": ">=14.17" + } + }, + "node_modules/undici-types": { + "version": "6.21.0", + "resolved": "https://registry.npmjs.org/undici-types/-/undici-types-6.21.0.tgz", + "integrity": "sha512-iwDZqg0QAGrg9Rav5H4n0M64c3mkR59cJ6wQp+7C4nI0gsmExaedaYLNO44eT4AtBBwjbTiGPMlt2Md0T9H9JQ==", + "dev": true, + "license": "MIT" + } + } +} diff --git a/cookbook/copilot-sdk/python/ralph-loop.md b/cookbook/copilot-sdk/python/ralph-loop.md index 82bfc7f5..b0d1c4b6 100644 --- a/cookbook/copilot-sdk/python/ralph-loop.md +++ b/cookbook/copilot-sdk/python/ralph-loop.md @@ -43,7 +43,7 @@ A [Ralph loop](https://ghuntley.com/ralph/) is an autonomous development workflo ## Simple Version -The minimal Ralph loop — the SDK equivalent of `while :; do cat PROMPT.md | claude ; done`: +The minimal Ralph loop — the SDK equivalent of `while :; do cat PROMPT.md | copilot ; done`: ```python import asyncio @@ -117,14 +117,17 @@ async def ralph_loop(mode: str = "build", max_iterations: int = 50): # Pin the agent to the project directory working_directory=str(Path.cwd()), # Auto-approve tool calls for unattended operation - on_permission_request=lambda _req, _ctx: {"kind": "approved", "rules": []}, + on_permission_request=lambda _req, _ctx: { + "kind": "approved", "rules": [] + }, )) # Log tool usage for visibility - session.on(lambda event: - print(f" ⚙ {event.data.tool_name}") - if event.type.value == "tool.execution_start" else None - ) + def log_tool_event(event): + if event.type.value == "tool.execution_start": + print(f" ⚙ {event.data.tool_name}") + + session.on(log_tool_event) try: await session.send_and_wait( @@ -193,9 +196,9 @@ creating ad-hoc copies. 4. When tests pass, update IMPLEMENTATION_PLAN.md, then `git add -A` then `git commit` with a descriptive message. -99999. When authoring documentation, capture the why. -999999. Implement completely. No placeholders or stubs. -9999999. Keep IMPLEMENTATION_PLAN.md current — future iterations depend on it. +5. When authoring documentation, capture the why. +6. Implement completely. No placeholders or stubs. +7. Keep IMPLEMENTATION_PLAN.md current — future iterations depend on it. ``` ### Example `AGENTS.md` @@ -230,12 +233,14 @@ python -m pytest ## When to Use a Ralph Loop **Good for:** + - Implementing features from specs with test-driven validation - Large refactors broken into many small tasks - Unattended, long-running development with clear requirements - Any work where backpressure (tests/builds) can verify correctness **Not good for:** + - Tasks requiring human judgment mid-loop - One-shot operations that don't benefit from iteration - Vague requirements without testable acceptance criteria