3`};return{diagnostics:l.[redacted](a,L).split(`
L4: `).filter(u=>u.length>0),ok:!1}}function N(t,r){let n=t.file?.fileName;return n==null?!0:n.startsWith(r)}var D=p.join(".local","tsbuildinfo");function U(t){return{allowImportingTsE...
L5: `)}function Xe(){return`${y} is up to date`}function Be(t){return[`${y} is ${t==="missing"?"missing":"out of date"} \u2014 run \`npx ripplo compile\` and commit the result`,h("setu...
93}
L94: `),$a="Failed to connect to Ripplo server";async function tn({serverUrl:e,token:t}){try{let r=await c({config:_({serverUrl:e,token:t}),document:Ca,variables:void 0});return r.curre...
L95: `);let n=r.map(i=>Xr(i));process.stdout.write(n.join(`
...
L105: `)}async function dn(e,t){let r=g(e).unwrapOr(void 0);r!=null&&await c({config:r,document:Ba,variables:{paused:t,projectId:r.projectId}}).catch(n=>{process.stderr.write(`Warning: c...
L106: `)})}import re from"fs";import ne from"path";import{input as hn,select as yn}from"@inquirer/prompts";import{graphql as wl}from"gql.tada";import{exec as Va,execFile as Ga}from"child...
L107: `)[0]??r.message:String(r);return X.warn("Install failed (%s): %s",t,n),{cmd:t,ok:!1,reason:n}}}async function tl(e){try{await D(e);return}catch(t){return`Couldn't compile initial ...
High
Command Output Exfiltration
Source combines command execution, command-output handling, and outbound requests; review data flow before blocking.
96`);import{CancellationTokenSource as Nt}from"vscode-jsonrpc/node";functionce(e){return`${e.workflowSlug}/${e.testSlug}`}functionkn(e){let{headed:n,inflight:t,jobId:r,lockfileHashValue:o,onExpire:i,runId:s,selection:a,timeoutMs:c}
2import{h as k}from"./chunk-4K4VY5OR.js";import{g as w}from"./chunk-ADSV6V6H.js";import{readFileSync as M}from"fs";import{z as F}from"zod";varO=F.object({version:F.
74`);function Jr(e){switch(e.status){case"active":return e.gitMidOperation?"\u2713 Dev session: ripplo daemon is live (hooks auto-paused while git is mid-merge/rebase/cherry-pick \u2014 they resume when the operation ends)":"\u2713 Dev session: ripplo daemon is live for this directory";case"starting":return"! Dev session: the daemon is running locally but hasn't registered with the server yet. Wait a few seconds and re-run `npx ripplo doctor`. If it persists, check the daemon output for auth or network errors.";case"missing":{let t="\u2717 Dev session: no daemon running for this directory. Start ...
4`).filter(u=>u.length>0),ok:!1}}function N(t,r){let n=t.file?.fileName;return n==null?!0:n.startsWith(r)}var D=p.join(".local","tsbuildinfo");function U(t){return{allowImportingTsExtensions:!0,allowJs:!1,esModuleInterop:!0,incremental:!0,module:l.ModuleKind.Preserve,moduleResolution:l.ModuleResolutionKind.Bundler,noEmit:!0,resolveJsonModule:!0,skipLibCheck:!0,strict:!1,target:l.ScriptTarget.ES2022,tsBuildInfoFile:p.join(t,D)}}import{createHash as q}from"crypto";import T from"fs/promises";import b from"path";import{err as c,ok as E,Result as H}from"neverthrow";var X=".ripplo/fixtures",R=10*1024 ...
5`)}functionXe(){return`${y} is up to date`}functionBe(t){return[`${y} is ${t==="missing"?"missing":"out of date"} \u2014 run \`npx ripplo compile\` and commit the result`,h("setup")].join(`
6`)}functionJe(){return`Wrote ${y}`}functionre(t){switch(t.kind){case"typecheck-failed":return["TypeScript errors in .ripplo/:",...C(t.diagnostics)].join(`
7`);case"not-ripplo":return`${t.entryPath} must default-export a Ripplo (createRipplo({ entities, singletons, workflows })). Check that the default export is the value returned by createRipplo, not a function or a re-export.`;case"invalid-lockfile":return["Lockfile failed schema validation (stale or hand-edited .ripplo/ripplo.lock?):",...C(t.issues),"Regenerate with `npx ripplo compile` \u2014 never hand-edit the lockfile."].join(`
8`);case"load-threw":return[`.ripplo/index.ts threw while loading: ${t.message}`,"Usually a bad import or a top-level throw in .ripplo/ \u2014 run `npx ripplo compile` for the stack."].join(`
9`);case"fixture-failed":returnne(t.error)}}functionC(t,r=8){return t.length<=r?t:[...t.slice(0,r),`\u2026 and ${String(t.length-r)} more`]}functionne(t){switch(t.kind){case"fixture-missing":return`Fixture "${t.name}" not found at ${t.path} \u2014 add the file under .ripplo/fixtures/ or fix the upload() name.`;case"fixture-invalid-name":return`Invalid fixture name "${t.name}" \u2014 upload() takes a bare name under .ripplo/fixtures/, no .. or absolute paths.`;case"fixture-symlink":return`Fixture "${t.name}" is a symlink \u2014 only regular files are allowed.`;case"fixture-not-file":return`Fi ...
34`);let s=awaitje({cwd:e,onReady:()=>{t("opened")},signal:n,step:o.stepIndex+1,target:i});s.kind==="done"&&s.result.kind==="handed-over"||(a.warn({kind:s.kind,runId:o.runId},"teleport could not open"),awaitt(s.kind==="unplannable"?"unplannable":"error"))}asyncfunctionno({cwd:e,devSessionId:r,runId:o,status:n}){let t=k(e).match(i=>i,()=>null);t!=null&&awaitg({config:t,document:eo,variables:{devSessionId:r,runId:o,status:n}}).catch(()=>null)}asyncfunctionto(e,r){if(r.kind==="explore"){let o=awaitio(e,r.runId);return o==null?null:{kind:"explore",repro:o}}return r.testSlug==null||r.workflow ...
78 In a git worktree? Copy the env file from the main checkout, or symlink to a shared file outside the working tree.`}functionca(e){switch(e.status){case"valid":return`\u2713 Auth: signed in as ${e.email??"unknown"}`;case"missing":return"\u2717 Auth: not signed in. Run `npx ripplo auth login`.\n (Claude Code: run it yourself in the background \u2014 the user just approves in the browser.)";case"invalid":return"\u2717 Auth: saved token rejected by the server. Run `npx ripplo auth login` to sign in again.\n (Claude Code: run it yourself in the background \u2014 the user just approves in the b ...
84`)}function ya(e){return e.installed?"\u2713 Browser: Chromium installed":"\u2717 Browser: Chromium not installed. Run `npx playwright install chromium`."}function ka(e){switch(e.status){case"enabled":return`\u2713 Adapter: enabled at ${e.url}`;case"disabled":return"\u2717 Adapter: disabled (handler returned 404). Set ENABLE_RIPPLO_TESTING=true in your app's env (e.g. apps/<app>/.env.local for Next.js) and restart the dev server.";case"bad-secret":return"\u2717 Adapter: webhook signature rejected. RIPPLO_WEBHOOK_SECRET seen by your dev server does not match the one in your env file.";case"unre ...
85
86`)}functionAe(e){return[`${p.warn("warn")} \u2014 ${b(e.length,"model coverage gap")} (not blocking):`,...e.map(t=>` ${Ra(t)}`),`Coverage gaps mean the model can't catch regressions there. Stub the missing flows. ${u("discover")}`].join(`
87`)}functionRa(e){switch(e.kind){case"entity-never-given":return`${e.entity} \u2014 declared but no implemented test seeds it, so no flow exercises this state`;case"entity-never-mutated":return`${e.entity} \u2014 seeded but never asserted created/updated/deleted, so mutations to it ship unchecked`;case"unmatchable-delete-key":return`test ${e.workflow}/${e.testSlug} asserts ${e.entity} deleted with a literal ${e.field} but no seeded ${e.entity} sets ${e.field} \u2014 the solver treats it as no-match, so counts may mispredict`}}import{graphql as xa}from"gql.tada";var Ca=xa(`
88 query DoctorAuthViewer {
89 currentUser {
90 name
91 email
92 }
93 }
94`),$a="Failed to connect to Ripplo server";asyncfunctiontn({serverUrl:e,token:t}){try{let r=awaitc({config:_({serverUrl:e,token:t}),document:Ca,variables:void0});return r.currentUser==null?{kind:"invalid"}:{email:r.currentUser.email,kind:"valid"}}catch(r){return(r instanceofError?r.message:String(r)).startsWith($a)?{kind:"unreachable"}:{kind:"invalid"}}}functionrn(e){switch(e.type){case"settings":return!e.valid;case"env-files":return e.missing.length>0;case"token":return e.status==="missing"||e.status==="invalid";case"dev-server":return!e.reachable;case"dev-session":return e.status!=="ac ...
103`);async function an(){let e=process.cwd();At(e);let t=de(e);if(je.existsSync(t)){process.stdout.write("Hooks already paused. Run `npx ripplo hooks resume` to re-enable.\n");return}je.writeFileSync(t,""),await dn(e,!0),process.stdout.write("Hooks paused. Pre-edit gates and stop enforcement are off until you run `npx ripplo hooks resume`.\n")}async function ln(){let e=process.cwd(),t=de(e);if(!je.existsSync(t)){process.stdout.write(`Hooks already active.
105`)}async function dn(e,t){let r=g(e).unwrapOr(void 0);r!=null&&await c({config:r,document:Ba,variables:{paused:t,projectId:r.projectId}}).catch(n=>{process.stderr.write(`Warning: could not push hook-pause state to the server (${n instanceof Error?n.message:String(n)}) \u2014 the dashboard may show stale hook status.
106`)})}import re from"fs";import ne from"path";import{input as hn,select as yn}from"@inquirer/prompts";import{graphql as wl}from"gql.tada";import{exec as Va,execFile as Ga}from"child_process";import{err as za,ok as cn}from"neverthrow";import w from"fs";import{createRequire as Ka}from"module";import k from"path";import{promisify as pn}from"util";var Ja=["@ripplo/testing","@ripplo/instrument"],un=".ripplo/ripplo.lock linguist-generated=true",Qa=[".ripplo/debug/",".ripplo/.local/"],Xa=pn(Va),Ya=pn(Ga);async function mn({cwd:e,onStep:t}){t("Scaffolding project files..."),dl({cwd:e}),t("Updating .git ...