{"_id":"@crcatala/ralph-unpossible","_rev":"8-e50de41c8a7077099bc301aafdacd3fc","name":"@crcatala/ralph-unpossible","dist-tags":{"latest":"1.0.0"},"versions":{"0.1.0":{"name":"@crcatala/ralph-unpossible","version":"0.1.0","_id":"@crcatala/ralph-unpossible@0.1.0","maintainers":[{"name":"crcatala","email":"crcatala@gmail.com"}],"bin":{"ralph":"dist/cli.js"},"dist":{"shasum":"f493353d043166abf2c824e81499eb06507ca91d","tarball":"https://registry.npmjs.org/@crcatala/ralph-unpossible/-/ralph-unpossible-0.1.0.tgz","fileCount":56,"integrity":"sha512-w40h7i2eFMg43v7moNhhe3Q9Y77wFAgYGMpyk5bULmcDOH3540Udl6Ej02OevwSukMvlDTSPchKY3Drxklxb0Q==","signatures":[{"sig":"MEUCIHDGCm2WvWjiwjz4mLJIqtKeJVUbUcfIxohoKXjZhV3lAiEA8Bev6Zy7MaGRARUn1kqIw9JHaBULk3BJ6euCRtoHnH8=","keyid":"SHA256:DhQ8wR5APBvFHLF/+Tc+AYvPOdTpcIDqOhxsBHRwC7U"}],"unpackedSize":162422},"type":"module","engines":{"node":">=22"},"gitHead":"160478f6a03d198d262034722833cd455a0a79ba","scripts":{"test":"npm run build && vitest run","build":"tsc -p tsconfig.json","clean":"node -e \"require('node:fs').rmSync('dist', { recursive: true, force: true })\"","verify":"npm run build && npm test && npm run test:package","prepack":"npm run build","release":"release-it","typecheck":"tsc -p tsconfig.json --noEmit","test:watch":"vitest","release:dry":"release-it --dry-run --no-npm --no-github","release:prep":"bash scripts/prep-release.sh","test:package":"bash scripts/test-package.sh","release:first":"release-it --first-release","test:coverage":"vitest run --coverage"},"_npmUser":{"name":"crcatala","email":"crcatala@gmail.com"},"_npmVersion":"10.9.3","description":"TypeScript rewrite of the Ralph autonomous loop runner","directories":{},"_nodeVersion":"22.20.0","dependencies":{"zod":"^3.24.1","yaml":"^2.4.5","kleur":"^4.1.5","commander":"^12.1.0"},"publishConfig":{"access":"public"},"_hasShrinkwrap":false,"devDependencies":{"vitest":"^2.1.8","release-it":"^20.2.1","typescript":"^5.7.3","@types/node":"^22.10.0","@release-it/keep-a-changelog":"^7.1.0"},"_npmOperationalInternal":{"tmp":"tmp/ralph-unpossible_0.1.0_1785735375591_0.3226401816484994","host":"s3://npm-registry-packages-npm-production"}},"0.1.1":{"name":"@crcatala/ralph-unpossible","version":"0.1.1","_id":"@crcatala/ralph-unpossible@0.1.1","maintainers":[{"name":"crcatala","email":"crcatala@gmail.com"}],"bin":{"ralph":"dist/cli.js"},"dist":{"shasum":"119040de76746f2641be7974fd59ca1256a864a5","tarball":"https://registry.npmjs.org/@crcatala/ralph-unpossible/-/ralph-unpossible-0.1.1.tgz","fileCount":56,"integrity":"sha512-PBe1yCuSnCCh3svAfyxND4cydTiyd8ejgdRws51/kFH6Lw1WaIjxSBZJeTyRX1jykx+GwqyhPvR8vJd5ivtc3A==","signatures":[{"sig":"MEQCIBrnkJVAwdBVLv5RGtl5xyZrCiEv+xh/p88+AQ4wsYAbAiBZmKa/G1SNzqb5NH9XvEusBqW4y+/RcAxbC8677hB/Rg==","keyid":"SHA256:DhQ8wR5APBvFHLF/+Tc+AYvPOdTpcIDqOhxsBHRwC7U"}],"unpackedSize":161909},"type":"module","engines":{"node":">=22"},"gitHead":"8f5b0f87f9261e09268e54730f705243a57993bc","scripts":{"test":"npm run build && vitest run","build":"tsc -p tsconfig.json","clean":"node -e \"require('node:fs').rmSync('dist', { recursive: true, force: true })\"","verify":"npm run build && npm test && npm run test:package","prepack":"npm run build","release":"release-it","typecheck":"tsc -p tsconfig.json --noEmit","test:watch":"vitest","release:dry":"release-it --dry-run --no-npm --no-github","release:prep":"bash scripts/prep-release.sh","test:package":"bash scripts/test-package.sh","release:first":"release-it --first-release","test:coverage":"vitest run --coverage"},"_npmUser":{"name":"crcatala","email":"crcatala@gmail.com"},"_npmVersion":"10.9.3","description":"TypeScript rewrite of the Ralph autonomous loop runner","directories":{},"_nodeVersion":"22.20.0","dependencies":{"zod":"^3.24.1","yaml":"^2.4.5","kleur":"^4.1.5","commander":"^12.1.0"},"publishConfig":{"access":"public"},"_hasShrinkwrap":false,"devDependencies":{"vitest":"^2.1.8","release-it":"^20.2.1","typescript":"^5.7.3","@types/node":"^22.10.0","@release-it/keep-a-changelog":"^7.1.0"},"_npmOperationalInternal":{"tmp":"tmp/ralph-unpossible_0.1.1_1785769145958_0.5808281259175878","host":"s3://npm-registry-packages-npm-production"}},"0.2.0":{"name":"@crcatala/ralph-unpossible","version":"0.2.0","_id":"@crcatala/ralph-unpossible@0.2.0","maintainers":[{"name":"crcatala","email":"crcatala@gmail.com"}],"bin":{"ralph":"dist/cli.js"},"dist":{"shasum":"69bfab686cfae354811c2e588a460d993dfc3b90","tarball":"https://registry.npmjs.org/@crcatala/ralph-unpossible/-/ralph-unpossible-0.2.0.tgz","fileCount":60,"integrity":"sha512-r0KD6U1Pyw6+yu6fgaNiJY+Uxdmy/RSokUpY2Pn2MGKnnoojyS1jVpqivibS19Ds2s2PNTGGfKdmI947LR7CZw==","signatures":[{"sig":"MEYCIQD8Hxm4MtYQRNxSGCXDRJSPAy93uhQlnz8EcusN7KpqawIhAJ07iPQbQZ+vNFBhJ1d2LLRtC/HZDxtPbq5S81fufR++","keyid":"SHA256:DhQ8wR5APBvFHLF/+Tc+AYvPOdTpcIDqOhxsBHRwC7U"}],"unpackedSize":167404},"type":"module","engines":{"node":">=22"},"gitHead":"7c59faad254812413fc499b6c1ed741b78801f83","scripts":{"test":"npm run build && vitest run","build":"tsc -p tsconfig.json","clean":"node -e \"require('node:fs').rmSync('dist', { recursive: true, force: true })\"","verify":"npm run build && npm test && npm run test:package","prepack":"npm run build","release":"release-it","typecheck":"tsc -p tsconfig.json --noEmit","test:watch":"vitest","release:dry":"release-it --dry-run --no-npm --no-github","release:prep":"bash scripts/prep-release.sh","test:package":"bash scripts/test-package.sh","release:first":"release-it --first-release","test:coverage":"vitest run --coverage"},"_npmUser":{"name":"crcatala","email":"crcatala@gmail.com"},"_npmVersion":"10.9.3","description":"TypeScript rewrite of the Ralph autonomous loop runner","directories":{},"_nodeVersion":"22.20.0","dependencies":{"zod":"^3.24.1","yaml":"^2.4.5","kleur":"^4.1.5","commander":"^12.1.0"},"publishConfig":{"access":"public"},"_hasShrinkwrap":false,"devDependencies":{"vitest":"^2.1.8","release-it":"^20.2.1","typescript":"^5.7.3","@types/node":"^22.10.0","@release-it/keep-a-changelog":"^7.1.0"},"_npmOperationalInternal":{"tmp":"tmp/ralph-unpossible_0.2.0_1785778910788_0.8675393081144569","host":"s3://npm-registry-packages-npm-production"}},"0.3.0":{"name":"@crcatala/ralph-unpossible","version":"0.3.0","_id":"@crcatala/ralph-unpossible@0.3.0","maintainers":[{"name":"crcatala","email":"crcatala@gmail.com"}],"bin":{"ralph":"dist/cli.js"},"dist":{"shasum":"ee92d877c6d7ffbc9077b0330a04e7eb7a9dea8a","tarball":"https://registry.npmjs.org/@crcatala/ralph-unpossible/-/ralph-unpossible-0.3.0.tgz","fileCount":125,"integrity":"sha512-DzAVxX0Fg71Z0y4+U8OsD9dknvHzhC3t4+gYm/4d1DZb1MqQudmHDj8M+71IhelblktFb51aDlcMYKEAopv9vw==","signatures":[{"sig":"MEUCIECrmehFZUKl2I72WzkcCe+K+pm0QFg902czBZ6zmhY5AiEA4du46uXqAqVdK7SEbLpx8lFWYQh0/Ac5DVKJz1nuonA=","keyid":"SHA256:DhQ8wR5APBvFHLF/+Tc+AYvPOdTpcIDqOhxsBHRwC7U"},{"sig":"MEUCIGRelE+wkPKfBvlbEvZgQHANB9I4TZoDcK07f81JKXdwAiEAxxtP8LuLoL3EjdSAFSuRPaeEp1VVCOBy4JWT16rkn6c=","keyid":"SHA256:DhQ8wR5APBvFHLF/+Tc+AYvPOdTpcIDqOhxsBHRwC7U"}],"unpackedSize":876208},"type":"module","engines":{"node":">=22"},"gitHead":"7c7120855d85c93ef940e18e61c5c4775340f679","scripts":{"test":"npm run build && vitest run","build":"tsc -p tsconfig.json","clean":"node -e \"require('node:fs').rmSync('dist', { recursive: true, force: true })\"","verify":"npm run build && npm test && npm run test:package","prepack":"npm run build","release":"release-it","typecheck":"tsc -p tsconfig.json --noEmit","test:watch":"vitest","release:dry":"release-it --dry-run --no-npm --no-github","release:prep":"bash scripts/prep-release.sh","test:package":"bash scripts/test-package.sh","release:first":"release-it --first-release","test:coverage":"vitest run --coverage"},"_npmUser":{"name":"crcatala","email":"crcatala@gmail.com"},"_npmVersion":"10.9.8","description":"TypeScript rewrite of the Ralph autonomous loop runner","directories":{},"_nodeVersion":"22.23.2","dependencies":{"zod":"^3.24.1","yaml":"^2.4.5","kleur":"^4.1.5","commander":"^12.1.0"},"publishConfig":{"access":"public"},"_hasShrinkwrap":false,"devDependencies":{"vitest":"^2.1.8","release-it":"^20.2.1","typescript":"^5.7.3","@types/node":"^22.10.0","@release-it/keep-a-changelog":"^7.1.0"},"_npmOperationalInternal":{"tmp":"tmp/ralph-unpossible_0.3.0_1789415354584_0.6603399953654576","host":"s3://npm-registry-packages-npm-production"}},"0.4.0":{"name":"@crcatala/ralph-unpossible","version":"0.4.0","_id":"@crcatala/ralph-unpossible@0.4.0","maintainers":[{"name":"crcatala","email":"crcatala@gmail.com"}],"bin":{"ralph":"dist/cli.js"},"dist":{"shasum":"4ed931ac233fd682c901924eb9d1dc4d70d6c17d","tarball":"https://registry.npmjs.org/@crcatala/ralph-unpossible/-/ralph-unpossible-0.4.0.tgz","fileCount":126,"integrity":"sha512-CJLgq/KjRPZlaotWpcLMVXMpJZoKAnfiddvuNyzgqRz0YUyobYf9u1NgQq7G1T5f4s25F5jUlxpVNOIT+nCP1Q==","signatures":[{"sig":"MEQCIBQMxFTZqU4tIh/gjt5jFLEzxVhiVN/D1YKmNYA8w8onAiAXFuosxgnjx9/lytYEZPOBOm41GQTRpwfdJEM5u5z8zA==","keyid":"SHA256:DhQ8wR5APBvFHLF/+Tc+AYvPOdTpcIDqOhxsBHRwC7U"},{"sig":"MEQCIDwTIsIs2b54anTqGNU4lf/e7lP+MrojSC7w4b9JGNi5AiB0rbyUQSEJtf0VpbfUMIptlAjw7RretLqzFEStfQZyCg==","keyid":"SHA256:DhQ8wR5APBvFHLF/+Tc+AYvPOdTpcIDqOhxsBHRwC7U"}],"unpackedSize":888043},"type":"module","engines":{"node":">=22"},"gitHead":"37d35c31e0ea0e026b15e3a7428db57ed5788844","scripts":{"test":"npm run build && vitest run","build":"tsc -p tsconfig.json","clean":"node -e \"require('node:fs').rmSync('dist', { recursive: true, force: true })\"","verify":"npm run build && npm test && npm run test:package","prepack":"npm run build","release":"release-it","typecheck":"tsc -p tsconfig.json --noEmit","test:watch":"vitest","release:dry":"release-it --dry-run --no-npm --no-github","release:prep":"bash scripts/prep-release.sh","test:package":"bash scripts/test-package.sh","release:first":"release-it --first-release","test:coverage":"vitest run --coverage"},"_npmUser":{"name":"crcatala","email":"crcatala@gmail.com"},"_npmVersion":"10.9.8","description":"TypeScript rewrite of the Ralph autonomous loop runner","directories":{},"_nodeVersion":"22.23.2","dependencies":{"zod":"^3.24.1","yaml":"^2.4.5","kleur":"^4.1.5","commander":"^12.1.0"},"publishConfig":{"access":"public"},"_hasShrinkwrap":false,"devDependencies":{"vitest":"^2.1.8","release-it":"^20.2.1","typescript":"^5.7.3","@types/node":"^22.10.0","@release-it/keep-a-changelog":"^7.1.0"},"_npmOperationalInternal":{"tmp":"tmp/ralph-unpossible_0.4.0_1789422066525_0.2511613770704","host":"s3://npm-registry-packages-npm-production"}},"0.4.1":{"name":"@crcatala/ralph-unpossible","version":"0.4.1","_id":"@crcatala/ralph-unpossible@0.4.1","maintainers":[{"name":"crcatala","email":"crcatala@gmail.com"}],"bin":{"ralph":"dist/cli.js"},"dist":{"shasum":"531bace2b69ee9f4db97c7ffed8653fb22167491","tarball":"https://registry.npmjs.org/@crcatala/ralph-unpossible/-/ralph-unpossible-0.4.1.tgz","fileCount":128,"integrity":"sha512-TMio6oC7QIgXJ/DaRhounO4C0v3i0mt4nWBA7OJ1GnerUuLgDOVyDAKXLu49o+RoFqCZSe5klyawlBxMcwnxPw==","signatures":[{"sig":"MEUCIE54R2wi4pL40il10WpZj4st0fRQpSH+jcwLRzaDJvREAiEA3vMhPEDqgcJYtRJ3kuIBtK/WRwPu7z0F+d1zQHI//Ps=","keyid":"SHA256:DhQ8wR5APBvFHLF/+Tc+AYvPOdTpcIDqOhxsBHRwC7U"},{"sig":"MEUCIBRAvHuIu7SfasuVn5p86vdmdhcSYVh1yD3RGjT98Kp5AiEAnnb8SQESk8pCfyUZn42Dxhd+9TaP66IWWgAp4KrF78o=","keyid":"SHA256:DhQ8wR5APBvFHLF/+Tc+AYvPOdTpcIDqOhxsBHRwC7U"}],"unpackedSize":909310},"type":"module","engines":{"node":">=22"},"gitHead":"e5d5a04188efc7a4a36c90d631e5e590515a5595","scripts":{"test":"npm run build && vitest run","build":"tsc -p tsconfig.json","clean":"node -e \"require('node:fs').rmSync('dist', { recursive: true, force: true })\"","verify":"npm run build && npm test && npm run test:package","prepack":"npm run build","release":"release-it","typecheck":"tsc -p tsconfig.json --noEmit","test:watch":"vitest","release:dry":"release-it --dry-run --no-npm --no-github","release:prep":"bash scripts/prep-release.sh","test:package":"bash scripts/test-package.sh","release:first":"release-it --first-release","test:coverage":"vitest run --coverage"},"_npmUser":{"name":"crcatala","email":"crcatala@gmail.com"},"_npmVersion":"10.9.8","description":"TypeScript rewrite of the Ralph autonomous loop runner","directories":{},"_nodeVersion":"22.23.2","dependencies":{"zod":"^3.24.1","yaml":"^2.4.5","kleur":"^4.1.5","commander":"^12.1.0"},"publishConfig":{"access":"public"},"_hasShrinkwrap":false,"devDependencies":{"vitest":"^2.1.8","release-it":"^20.2.1","typescript":"^5.7.3","@types/node":"^22.10.0","@release-it/keep-a-changelog":"^7.1.0"},"_npmOperationalInternal":{"tmp":"tmp/ralph-unpossible_0.4.1_1789426146970_0.5191605170846616","host":"s3://npm-registry-packages-npm-production"}},"0.5.0":{"name":"@crcatala/ralph-unpossible","version":"0.5.0","_id":"@crcatala/ralph-unpossible@0.5.0","maintainers":[{"name":"crcatala","email":"crcatala@gmail.com"}],"bin":{"ralph":"dist/cli.js"},"dist":{"shasum":"c38287a713a5b6054dfee5438709c581fad1563f","tarball":"https://registry.npmjs.org/@crcatala/ralph-unpossible/-/ralph-unpossible-0.5.0.tgz","fileCount":134,"integrity":"sha512-XseZ6sme8yGnXnSUUuTZTvAyYc8ILwPfDVskm7WvMORDTU1k3HTNEW2hCDX34WOc8HBZV5rrVfCxYWQwTc5tUA==","signatures":[{"sig":"MEQCIAhXGDPxNpY+7YF0000oat2VUWX8oaGkTAU5+PFGdUzYAiAohM07YtB2qzWES+vC7lcpw0nx25FFVdy0uzFCvtADkg==","keyid":"SHA256:DhQ8wR5APBvFHLF/+Tc+AYvPOdTpcIDqOhxsBHRwC7U"},{"sig":"MEYCIQCeOnDyLDrIrkOK1mGKOmjAOrp1eK5FPXp9zPogkQA+6wIhALWb7QeFVYoSsTjpW07LZeA0KSyzCTPOQ067wqR+Di38","keyid":"SHA256:DhQ8wR5APBvFHLF/+Tc+AYvPOdTpcIDqOhxsBHRwC7U"}],"unpackedSize":928960},"type":"module","engines":{"node":">=22"},"gitHead":"0f23427d48c308a986720751b7a3a8fec8eff1ca","scripts":{"test":"npm run build && vitest run","build":"tsc -p tsconfig.json","clean":"node -e \"require('node:fs').rmSync('dist', { recursive: true, force: true })\"","verify":"npm run build && npm test && npm run test:package","prepack":"npm run build","release":"release-it","typecheck":"tsc -p tsconfig.json --noEmit","test:watch":"vitest","release:dry":"release-it --dry-run --no-npm --no-github","release:prep":"bash scripts/prep-release.sh","test:package":"bash scripts/test-package.sh","release:first":"release-it --first-release","test:coverage":"vitest run --coverage"},"_npmUser":{"name":"crcatala","email":"crcatala@gmail.com"},"_npmVersion":"10.9.8","description":"TypeScript rewrite of the Ralph autonomous loop runner","directories":{},"_nodeVersion":"22.23.2","dependencies":{"zod":"^3.24.1","yaml":"^2.4.5","kleur":"^4.1.5","commander":"^12.1.0"},"publishConfig":{"access":"public"},"_hasShrinkwrap":false,"devDependencies":{"vitest":"^2.1.8","release-it":"^20.2.1","typescript":"^5.7.3","@types/node":"^22.10.0","@release-it/keep-a-changelog":"^7.1.0"},"_npmOperationalInternal":{"tmp":"tmp/ralph-unpossible_0.5.0_1789435854238_0.47599864406441394","host":"s3://npm-registry-packages-npm-production"}},"1.0.0":{"_id":"@crcatala/ralph-unpossible@1.0.0","bin":{"ralph":"dist/cli.js"},"dist":{"shasum":"2ccc8bc19f5aa4560785807fd02ade865e08ea6a","tarball":"https://registry.npmjs.org/@crcatala/ralph-unpossible/-/ralph-unpossible-1.0.0.tgz","fileCount":153,"integrity":"sha512-psVASPsA39mV8CdbP+EWrbhwo5f5c5AuZyc/BIgPXj4zZFoAgEH0o4JMFiYOQHq7QAEa8xSsupiId3Rfpmr/AA==","signatures":[{"sig":"MEUCIQCvMa3AlbVu5a6wjITTUQRWoXr7PQ0Km03VKCnC+YAfjwIgObveEQM2RPV3OXmWhZtwJWbQ0/i3Ni4FoFhSkhaJBxk=","keyid":"SHA256:DhQ8wR5APBvFHLF/+Tc+AYvPOdTpcIDqOhxsBHRwC7U"},{"keyid":"SHA256:DhQ8wR5APBvFHLF/+Tc+AYvPOdTpcIDqOhxsBHRwC7U","sig":"MEUCIBcj/l0KkIdydQ7aW7Y9XIz52m8F3DhzmSPtB8UD7sLvAiEAzc11KtvUaZJvnfCgwG00/3+GvzWNaCYYhlSXwSYU/KE="}],"unpackedSize":673503},"name":"@crcatala/ralph-unpossible","type":"module","engines":{"node":">=22"},"gitHead":"65cd1321f7550947cf82ccfa21782c8dd789b608","scripts":{"test":"npm run build && vitest run","build":"npm run clean && tsc -p tsconfig.json","clean":"node -e \"require('node:fs').rmSync('dist', { recursive: true, force: true })\"","verify":"npm run build && npm test && npm run test:package","prepack":"npm run build","release":"release-it","test:unit":"vitest run test/core test/output","typecheck":"tsc -p tsconfig.json --noEmit","test:watch":"vitest","release:dry":"release-it --dry-run --no-npm --no-github","release:prep":"bash scripts/prep-release.sh","test:package":"bash scripts/test-package.sh","release:first":"release-it --first-release","test:coverage":"vitest run --coverage"},"version":"1.0.0","_npmUser":{"name":"crcatala","email":"crcatala@gmail.com"},"_npmVersion":"10.9.8","description":"TypeScript rewrite of the Ralph autonomous loop runner","directories":{},"maintainers":[{"name":"crcatala","email":"crcatala@gmail.com"}],"_nodeVersion":"22.23.2","dependencies":{"zod":"^3.24.1","yaml":"^2.4.5","kleur":"^4.1.5","commander":"^12.1.0","cli-truncate":"^6.1.1","string-width":"^8.2.2"},"publishConfig":{"access":"public"},"_hasShrinkwrap":false,"devDependencies":{"vitest":"^2.1.8","release-it":"^20.2.1","typescript":"^5.7.3","@types/node":"^22.10.0","@release-it/keep-a-changelog":"^7.1.0"},"_npmOperationalInternal":{"host":"s3://npm-registry-packages-npm-production","tmp":"tmp/ralph-unpossible_1.0.0_1789668149875_0.17694498593181351"}}},"time":{"created":"2026-08-03T05:36:15.304Z","modified":"2026-09-17T18:02:30.135Z","0.1.0":"2026-08-03T05:36:15.751Z","0.1.1":"2026-08-03T14:59:06.081Z","0.2.0":"2026-08-03T17:41:50.938Z","0.3.0":"2026-09-14T19:49:14.678Z","0.4.0":"2026-09-14T21:41:06.615Z","0.4.1":"2026-09-14T22:49:07.139Z","0.5.0":"2026-09-15T01:30:54.322Z","1.0.0":"2026-09-17T18:02:29.971Z"},"description":"TypeScript rewrite of the Ralph autonomous loop runner","maintainers":[{"name":"crcatala","email":"crcatala@gmail.com"}],"readme":"# ralph-unpossible\n\nRalph is a campaign-only, ticket-native delivery runtime. Give it an explicitly\nordered list of trusted `tk` tickets and it delivers each one as a branch, a\nrecipe run, and a pull request — starting the next ticket only after the\nprevious pull request is proven merged on the fetched base branch.\n\n**Campaigns are the only product abstraction.** Each delivery executes an\neditable project-owned recipe of agent, command, and deterministic GitHub\nsteps. Ralph's controller owns the durable shell: pinned inputs, retained\nworktrees, guarded pushes, exact PR/check identity, controller-owned ticket\nclosure, merge authority, and restart-safe recovery.\n\n- Requires Node.js 22 or newer\n- Uses [`pi`](https://pi.dev/) by default; OpenCode and custom runners are supported\n- Reads the `tk` issue tracker (`ralph new`, `ralph validate`, `ralph plan`)\n\n## Install\n\n```bash\n# Run without installing\nnpx @crcatala/ralph-unpossible --help\n\n# Or install globally\nnpm install -g @crcatala/ralph-unpossible\n```\n\nFrom source:\n\n```bash\ngit clone https://github.com/crcatala/ralph-unpossible\ncd ralph-unpossible\nnpm install\nnpm run build\nnpm link\n```\n\n## Quick start: run a campaign\n\n```bash\n# 1. Install the standard recipe and prompts into .ralph/\nralph init\n\n# 2. Scaffold and edit a campaign\nralph new my-campaign --epic ru-gmir --ticket ru-6ocr --ticket ru-xxxx\n$EDITOR .ralph/campaigns/my-campaign/campaign.yaml   # Order is the dependency model\n\n# 3. Configure the implementation model you actually use\nralph config init --project --provider <provider> --model <model> --thinking <level>\n\n# 4. Check readiness, then validate, plan, and run\nralph doctor\nralph validate my-campaign     # Network-free local check; creates no runtime state\nralph plan my-campaign         # Compile the pinned plan; may fetch the base\nralph run my-campaign          # Fetch, pin, and execute deliveries in order\n```\n\n`ralph init` never overwrites files you have edited, so it is safe to re-run.\n`ralph new` scaffolds a schema-valid version-2 campaign; its editable ticket IDs\nneed not resolve until you commit them on the base branch.\n\n## The campaign model\n\n| Concept | Meaning |\n|---|---|\n| Campaign | One ordered list of `tk` ticket deliveries (`.ralph/campaigns/<name>/campaign.yaml`) |\n| Delivery | One ticket → one branch → one recipe run → one pull request → proven merge |\n| Recipe | Project-owned YAML steps (`.ralph/recipes/*.yaml`) plus editable Markdown prompts |\n| Step | One bounded `agent`, `command`, or `github.*` operation with declared Git postconditions |\n| Durable run | `state.json` is the resume authority; `events.jsonl` is the canonical operator history |\n\nThe next ticket cannot start until Ralph proves the prior pull request merged on\nthe fetched base. Immediately before the first push and PR creation, the\ncontroller closes the delivery ticket on its branch and commits that closure, so\nticket state lands atomically with its implementation. Ralph never infers or\nreorders deliveries during execution.\n\n### Campaign manifest\n\n`.ralph/campaigns/my-campaign/campaign.yaml`:\n\n```yaml\nversion: 2\nname: my-campaign\nbase_branch: main\n\nsource:\n  type: tk\n  epic: ru-gmir          # Optional campaign context ticket\n\nrecipe: .ralph/recipes/standard-pr.yaml\n\npull_request:\n  branch_template: \"ralph/{{campaign}}/{{ticket}}\"\n  title_template: \"{{ticket}}: {{ticket_title}}\"\n  draft: false\n\ndeliveries:              # Manifest order is the dependency model\n  - ticket: ru-6ocr\n  - ticket: ru-yb6r\n```\n\n`source.type` is `tk`. The manifest, recipe, prompts, epic, and every delivery\nticket must be committed on the fetched base before a run begins. Campaign\nmanifest version 1 and runtime state version 1 are rejected with an actionable\nremedy — Ralph does not migrate them.\n\n### The standard recipe\n\n`ralph init` installs `.ralph/recipes/standard-pr.yaml` and four prompts. The\ninstalled recipe uses the same public contract that you edit:\n\n```text\nimplement (commit required)\n→ open PR\n→ review/fix (commit optional)\n→ verify (commit optional)\n→ draft PR description (commit forbidden)\n→ update PR\n→ required checks\n→ merge\n```\n\nEvery `agent` and `command` step declares its accepted Git result:\n\n```yaml\ngit_head_advance: required | optional | forbidden\ngit_worktree_state: clean\n```\n\nA `required` step must leave a new, forward-descendant HEAD; `forbidden` must\nleave HEAD unchanged. A dirty result is preserved as `attention` and never\nsilently reset.\n\n## Agent runtime configuration\n\nRuntime resolution has no implicit model: missing config files are skipped, not\ninvented. `ralph config init` writes only the provider, model, and thinking you\npass. Values resolve field-by-field in this order:\n\n1. CLI flags: `--provider`, `--model`, `--thinking`\n2. Project config: `.ralph/config.json`\n3. Global config: `$RALPH_HOME/config.json` (normally `~/.ralph/config.json`)\n\n```json\n{\n  \"version\": 1,\n  \"provider\": \"openrouter\",\n  \"model\": \"z-ai/glm-5.3-flash\",\n  \"thinking\": \"high\"\n}\n```\n\n```bash\nralph config init --project --provider <provider> --model <model> --thinking <level>\nralph config show             # Show effective values and their sources\nralph doctor                  # Validate runtime and project readiness\nralph doctor --json\n```\n\nPi requires provider, model, and thinking. Before the first delivery Ralph asks\nthe installed Pi to verify the exact model, thinking capability, and credentials\nwithout making an inference request. OpenCode requires provider and model.\nProject config version 1 and recipe version 1 remain valid.\n\n## Status, logs, and recovery\n\nDefault output is organized around campaign, ticket, and recipe step — not\ninternal controller phases.\n\n```bash\nralph status my-campaign              # Merged count, active ticket/step, PR, next action\nralph status my-campaign --format json\n\nralph logs my-campaign                # Follow the canonical event ledger (human)\nralph logs my-campaign --format jsonl # Stable JSONL for machines\nralph logs my-campaign --after <event-id> --format jsonl # Resume from a durable checkpoint\nralph logs my-campaign --verbose      # Receipt paths and controller diagnostics\n\nralph resume my-campaign              # Continue after waiting/attention/blocked\nralph abort my-campaign               # Stop without deleting preserved work\n```\n\n`--format json` emits exactly one stable object on stdout; `logs --format jsonl`\nemits one canonical event per line. Diagnostics always go to stderr. Runtime\nstate and worktrees live outside the repository under `RALPH_HOME` (default\n`~/.ralph/`).\n\nTop-level run status vocabulary is small: `waiting` (healthy external wait),\n`attention` (preserved work or judgment needed), `blocked` (a proven\nidentity/safety invariant prevents progress), `aborted`, and `completed`.\n\n## Project layout\n\n```text\n.ralph/\n  config.json                    # Optional project runtime configuration\n  campaigns/<campaign>/\n    campaign.yaml                # Ordered tk delivery manifest\n  recipes/\n    standard-pr.yaml             # Editable delivery recipe\n  prompts/\n    implement.md                 # Editable agent step prompts\n    review-fix.md\n    verify.md\n    pr-description.md\n```\n\n## Documentation\n\n- [Quick command guide](GUIDE.md)\n- [Campaign operation and configuration](docs/campaigns.md)\n- [ADR-0002: Campaign-only, ticket-native delivery recipes](docs/adr/0002-campaign-only-ticket-native-delivery-recipes.md) — accepted architecture\n- [Campaign-only overhaul implementation plan](docs/campaign-only-overhaul-plan.md)\n- [ADR-0001: Prompt-native linear campaign workflows](docs/adr/0001-prompt-native-linear-campaign-workflows.md) — superseded by ADR-0002\n- [Historical campaign architecture and trust design](docs/campaigns-design.md) — superseded\n- [Historical campaign implementation plan](docs/campaigns-implementation-guide.md) — superseded\n- [Maintainer release guide](RELEASING.md)\n\n## Development\n\n```bash\nnpm install\nnpm test\nnpm run build\nnpm run test:package\n```\n","readmeFilename":"README.md"}