automated-qa 0.11.0

This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
Files changed (187) hide show
  1. package/LICENSE +22 -0
  2. package/NOTICE +9 -0
  3. package/README.md +100 -0
  4. package/SKILL.md +65 -0
  5. package/agent/prebuilt/darwin-universal/qa-agent +0 -0
  6. package/agent/prebuilt/linux-arm64/qa-agent +0 -0
  7. package/agent/prebuilt/linux-x64/qa-agent +0 -0
  8. package/agent/release-manifest.json +31 -0
  9. package/bin/autonomous-cache.mjs +2 -0
  10. package/bin/bench-generate.mjs +232 -0
  11. package/bin/bench-graph-query.mjs +2 -0
  12. package/bin/bench-score.mjs +10 -0
  13. package/bin/classify.mjs +15 -0
  14. package/bin/coherence-playwright.mjs +1 -0
  15. package/bin/coherence-runner.mjs +6 -0
  16. package/bin/crud-runner.mjs +12 -0
  17. package/bin/experiment-executor.mjs +10 -0
  18. package/bin/experiment-runner.mjs +3 -0
  19. package/bin/inventory.mjs +17 -0
  20. package/bin/probe.js +879 -0
  21. package/bin/qa.mjs +16 -0
  22. package/bin/rules.mjs +5 -0
  23. package/bin/run-benchmarks.mjs +2 -0
  24. package/bin/runtime-packs.mjs +3 -0
  25. package/bin/semantic-explorer.mjs +3 -0
  26. package/bin/shadow-collector.mjs +3 -0
  27. package/bin/shadow-replay.mjs +6 -0
  28. package/bin/soak-marathon.mjs +15 -0
  29. package/bin/sweep.mjs +43 -0
  30. package/bin/validate-priors.mjs +3 -0
  31. package/bin/verify-artifacts.mjs +3 -0
  32. package/bin/verify-manifest.mjs +2 -0
  33. package/install-skill.sh +45 -0
  34. package/lib/qa/agent-availability.mjs +1 -0
  35. package/lib/qa/agent-result.mjs +1 -0
  36. package/lib/qa/analysis.mjs +5 -0
  37. package/lib/qa/atlas-coverage.mjs +11 -0
  38. package/lib/qa/atlas-v1.mjs +1 -0
  39. package/lib/qa/atlas.mjs +2 -0
  40. package/lib/qa/auth/coordinator.mjs +1 -0
  41. package/lib/qa/auth/launcher.mjs +3 -0
  42. package/lib/qa/auth/lease.mjs +1 -0
  43. package/lib/qa/auth/oracle.mjs +1 -0
  44. package/lib/qa/auth/personas.mjs +3 -0
  45. package/lib/qa/autonomous-cache.mjs +3 -0
  46. package/lib/qa/block-ledger.mjs +1 -0
  47. package/lib/qa/capture-report.mjs +63 -0
  48. package/lib/qa/ci.mjs +11 -0
  49. package/lib/qa/cli.mjs +538 -0
  50. package/lib/qa/coherence/analyze.mjs +1 -0
  51. package/lib/qa/coherence/cache-key.mjs +6 -0
  52. package/lib/qa/coherence/causes.mjs +1 -0
  53. package/lib/qa/coherence/concurrency.mjs +1 -0
  54. package/lib/qa/coherence/contracts.mjs +1 -0
  55. package/lib/qa/coherence/entity-aliases.mjs +1 -0
  56. package/lib/qa/coherence/enums.mjs +1 -0
  57. package/lib/qa/coherence/family-report.mjs +1 -0
  58. package/lib/qa/coherence/flow-pool.mjs +1 -0
  59. package/lib/qa/coherence/graph.mjs +1 -0
  60. package/lib/qa/coherence/identity.mjs +1 -0
  61. package/lib/qa/coherence/ir.mjs +4 -0
  62. package/lib/qa/coherence/navigation.mjs +1 -0
  63. package/lib/qa/coherence/observe.mjs +2 -0
  64. package/lib/qa/coherence/offline.mjs +1 -0
  65. package/lib/qa/coherence/plan-join.mjs +1 -0
  66. package/lib/qa/coherence/provenance.mjs +2 -0
  67. package/lib/qa/coherence/report.mjs +1 -0
  68. package/lib/qa/coherence/representations.mjs +1 -0
  69. package/lib/qa/coherence/risk.mjs +2 -0
  70. package/lib/qa/coherence/structural-js.mjs +11 -0
  71. package/lib/qa/coherence/symbols.mjs +6 -0
  72. package/lib/qa/coherence/tanstack.mjs +4 -0
  73. package/lib/qa/coherence/views.mjs +1 -0
  74. package/lib/qa/coherence-planner.mjs +1 -0
  75. package/lib/qa/command-catalog.mjs +2 -0
  76. package/lib/qa/commands/dev.mjs +1 -0
  77. package/lib/qa/commands/fix.mjs +1 -0
  78. package/lib/qa/commands/impl/analysis.mjs +1 -0
  79. package/lib/qa/commands/impl/atlas.mjs +1 -0
  80. package/lib/qa/commands/impl/coherence.mjs +1 -0
  81. package/lib/qa/commands/impl/crud.mjs +2 -0
  82. package/lib/qa/commands/impl/doctor.mjs +1 -0
  83. package/lib/qa/commands/impl/experiments.mjs +1 -0
  84. package/lib/qa/commands/impl/fp.mjs +1 -0
  85. package/lib/qa/commands/impl/graph.mjs +1 -0
  86. package/lib/qa/commands/impl/invariants.mjs +1 -0
  87. package/lib/qa/commands/impl/lanes.mjs +7 -0
  88. package/lib/qa/commands/impl/ledger.mjs +11 -0
  89. package/lib/qa/commands/impl/loop.mjs +1 -0
  90. package/lib/qa/commands/impl/marathon.mjs +1 -0
  91. package/lib/qa/commands/impl/next.mjs +38 -0
  92. package/lib/qa/commands/impl/report.mjs +4 -0
  93. package/lib/qa/commands/impl/research.mjs +4 -0
  94. package/lib/qa/commands/impl/selftest.mjs +1 -0
  95. package/lib/qa/commands/impl/serve.mjs +1 -0
  96. package/lib/qa/commands/impl/shadow.mjs +1 -0
  97. package/lib/qa/commands/impl/stability.mjs +1 -0
  98. package/lib/qa/commands/impl/triage.mjs +1 -0
  99. package/lib/qa/commands/impl/validate.mjs +4 -0
  100. package/lib/qa/commands/impl/version.mjs +1 -0
  101. package/lib/qa/commands/impl/watch.mjs +1 -0
  102. package/lib/qa/commands/init.mjs +6 -0
  103. package/lib/qa/commands/measure.mjs +1 -0
  104. package/lib/qa/commands/run.mjs +1 -0
  105. package/lib/qa/commands/show.mjs +1 -0
  106. package/lib/qa/commands/verify.mjs +6 -0
  107. package/lib/qa/deepening.mjs +1 -0
  108. package/lib/qa/denominators.mjs +1 -0
  109. package/lib/qa/depth.mjs +4 -0
  110. package/lib/qa/doctor.mjs +2 -0
  111. package/lib/qa/experiments-default.mjs +1 -0
  112. package/lib/qa/fix-lanes.mjs +3 -0
  113. package/lib/qa/forced-states.mjs +1 -0
  114. package/lib/qa/fp.mjs +2 -0
  115. package/lib/qa/fs.mjs +6 -0
  116. package/lib/qa/graph-schema.mjs +2 -0
  117. package/lib/qa/graph.mjs +3 -0
  118. package/lib/qa/harness-plan.mjs +3 -0
  119. package/lib/qa/init.mjs +5 -0
  120. package/lib/qa/integrity.mjs +1 -0
  121. package/lib/qa/invariants.mjs +84 -0
  122. package/lib/qa/jcs.mjs +1 -0
  123. package/lib/qa/lanes.mjs +1 -0
  124. package/lib/qa/loop.mjs +7 -0
  125. package/lib/qa/marathon-coherence.mjs +1 -0
  126. package/lib/qa/marathon-phases.mjs +1 -0
  127. package/lib/qa/marathon-wait.mjs +3 -0
  128. package/lib/qa/marathon.mjs +5 -0
  129. package/lib/qa/mode-coverage.mjs +1 -0
  130. package/lib/qa/mutation-policy.mjs +1 -0
  131. package/lib/qa/pattern-ledger.mjs +3 -0
  132. package/lib/qa/pending.mjs +1 -0
  133. package/lib/qa/proc.mjs +4 -0
  134. package/lib/qa/recommend.mjs +1 -0
  135. package/lib/qa/release-manifest.mjs +1 -0
  136. package/lib/qa/report-html.mjs +178 -0
  137. package/lib/qa/reports.mjs +2 -0
  138. package/lib/qa/request-evidence.mjs +1 -0
  139. package/lib/qa/research.mjs +20 -0
  140. package/lib/qa/routing.mjs +1 -0
  141. package/lib/qa/runs.mjs +1 -0
  142. package/lib/qa/schema.mjs +1 -0
  143. package/lib/qa/serve.mjs +4 -0
  144. package/lib/qa/server.mjs +1 -0
  145. package/lib/qa/source-snapshot.mjs +3 -0
  146. package/lib/qa/stability.mjs +3 -0
  147. package/lib/qa/state-evidence.mjs +1 -0
  148. package/lib/qa/sweep-incremental.mjs +1 -0
  149. package/lib/qa/triage.mjs +2 -0
  150. package/lib/qa/verdict.mjs +1 -0
  151. package/lib/qa/watch.mjs +2 -0
  152. package/package.json +62 -0
  153. package/references/ATLAS-COVERAGE.md +231 -0
  154. package/references/atlas-v1.md +318 -0
  155. package/references/atlas.md +338 -0
  156. package/references/verify.crud.example.json +1 -0
  157. package/references/verify.impact.example.json +1 -0
  158. package/references/verify.shadow.example.json +1 -0
  159. package/schemas/agent-result.schema.json +135 -0
  160. package/schemas/analysis.schema.json +15 -0
  161. package/schemas/classify.schema.json +61 -0
  162. package/schemas/coherence-ir.schema.json +1585 -0
  163. package/schemas/coherence-observed.schema.json +1171 -0
  164. package/schemas/coherence-plan.schema.json +77 -0
  165. package/schemas/coherence-risk.schema.json +46 -0
  166. package/schemas/crud-observed.schema.json +118 -0
  167. package/schemas/experiment-execution.schema.json +82 -0
  168. package/schemas/graph-edge.schema.json +22 -0
  169. package/schemas/graph-node.schema.json +81 -0
  170. package/schemas/graph.schema.json +2493 -0
  171. package/schemas/identity-oracle.schema.json +19 -0
  172. package/schemas/inventory.schema.json +2167 -0
  173. package/schemas/lanes-plan.schema.json +52 -0
  174. package/schemas/next.schema.json +54 -0
  175. package/schemas/personas.schema.json +52 -0
  176. package/schemas/research.schema.json +192 -0
  177. package/schemas/run.schema.json +160 -0
  178. package/schemas/shadow-replay.schema.json +68 -0
  179. package/schemas/stability.schema.json +92 -0
  180. package/schemas/sweep.schema.json +239 -0
  181. package/schemas/v1/agent-result.schema.json +106 -0
  182. package/schemas/v1/run.schema.json +96 -0
  183. package/schemas/verify-crud.schema.json +37 -0
  184. package/schemas/verify-read-only.schema.json +37 -0
  185. package/templates/github-workflow.yml +80 -0
  186. package/templates/pre-commit.sample +22 -0
  187. package/verify.sh +385 -0
package/lib/qa/fp.mjs ADDED
@@ -0,0 +1,2 @@
1
+ import S from"node:fs";import b from"node:os";import m from"node:path";import{createHash as F}from"node:crypto";import{spawnSync as E}from"node:child_process";import{readJson as D,writeJson as I}from"./fs.mjs";import{canonicalize as f}from"./jcs.mjs";const g=t=>F("sha256").update(t).digest("hex"),$=/^\d{4}-\d{2}-\d{2}(?:T\d{2}:\d{2}:\d{2}(?:\.\d{3})?Z)?$/;function w(){if(process.env.QA_HOME)return m.join(process.env.QA_HOME,"known-false-positives.json");const t=process.env.XDG_CONFIG_HOME||m.join(b.homedir(),".config");return m.join(t,"qa","known-false-positives.json")}function j(t=w()){const e=D(t);return Array.isArray(e?.entries)?e.entries.filter(n=>!n||!n.rule?!1:n.type!=="runtime"?!!n.anchor&&!!n.basename:/^[0-9a-f]{12}$/.test(n.fid??"")&&/^sha256:[0-9a-f]{64}$/.test(n.repoScope??"")&&/^sha256:[0-9a-f]{64}$/.test(n.evidenceScope??"")&&typeof n.note=="string"&&!!n.note&&typeof n.evidence=="string"&&!!n.evidence&&typeof n.expires=="string"&&$.test(n.expires)&&Number.isFinite(Date.parse(n.expires))):[]}function G(t,e=w()){I(e,{schema_version:1,updatedAt:new Date().toISOString(),entries:t})}function c(t,e,n){return`${t}|${e}|${n}`}function A(t){let e=null;try{const n=E("git",["-C",t,"rev-parse","--path-format=absolute","--git-common-dir"],{encoding:"utf8"});n.status===0&&n.stdout.trim()&&(e=S.realpathSync(n.stdout.trim()))}catch{}if(!e)try{e=S.realpathSync(t)}catch{e=m.resolve(t)}return"sha256:"+g(e)}function O(t,e){if(!t||t.file||t.measured!==!0||!e||e.status==="invalid"||e.integrity?.ok!==!0)return null;const n={protocol:"runtime-adjudication/v1",producer:e.measurement?.producer??{name:"sweep",atlasVersion:e.atlasVersion??1},lane:e.lane??"public-runtime",phase:t.phase,rule:t.kind,route:t.route,role:t.role??null,width:t.width??null,selector:t.at??null,ruleVersion:t.ruleVersion??e.measurement?.producer?.rulesDigest??null},r=e.measurement?.modes?.[t.phase]??e.measurement?.modes??{};return{id:"sha256:"+g(f(n)),material:n,mode:r}}function J(t){if(!t||t.status==="invalid"||t.integrity?.ok!==!0)return null;const e=t.measurement??{},n=i=>[i.role??"default",i.route??"",Number(i.width??t.width??0)],r=(t.routes??[]).filter(i=>i&&!String(i.route??"").startsWith("(")),s=r.filter(i=>!i.unmeasured&&!i.skipped&&!i.redirectedTo).map(n).sort(),o=[...t.unreached??[],...t.dynamicSkipped??[]].map(i=>[i.role??null,i.route??"",i.width??null,i.reason??null]).sort(),u=(t.routes??[]).filter(i=>String(i?.route??"").startsWith("(")).map(i=>({cell:n(i),columns:(i.columns??[]).map(a=>[a.kind??null,a.status??(a.intercepted>0?"measured":"unmeasured")]).sort(),skipped:!!i.skipped})).sort((i,a)=>f(i).localeCompare(f(a))),l={protocol:"runtime-ratchet/v1",producer:e.producer??{name:"sweep",atlasVersion:t.atlasVersion??1},lane:t.lane??"public-runtime",requested:{routes:[...new Set((e.routes??r.map(i=>i.route)).map(String))].sort(),personas:[...new Set((e.personas??t.summary?.roles??[]).map(String))].sort(),viewports:[...new Set((e.viewports??s.map(i=>i[2])).map(Number))].sort((i,a)=>i-a),modes:e.modes??{},packs:e.packs??[]},measured:{cells:s,synthetic:u},excluded:o};return{id:"sha256:"+g(f(l)),material:l}}function M(t){const e=new Map;for(const n of t)e.set(n.type==="runtime"?`runtime|${n.repoScope}|${n.evidenceScope}|${n.fid}`:c(n.rule,n.basename,n.anchor),n);return e}function N(t,e){if(!e)return null;if(!e.file){const n=t.get(`runtime|${e.repoScope}|${e.evidenceScope}|${e.fid}`)??null,r=Date.parse(n?.expires);return!n||!Number.isFinite(r)||r<Date.now()?null:n.rule===e.kind&&n.route===e.route&&n.role===(e.role??null)&&n.selector===(e.at??null)?n:null}return!e.anchor||/^L\d*\??$/.test(e.anchor)?null:t.get(c(e.kind,m.basename(e.file),e.anchor))??null}function Q(t,{rule:e,file:n,anchor:r,note:s,repo:o}){if(!e||!n||!r||/^L\d*\??$/.test(r))throw new Error("a known false positive needs a rule and a content anchor (the finding must come from a readable source line)");const u=m.basename(n),l=c(e,u,r),i=t.find(p=>c(p.rule,p.basename,p.anchor)===l);if(i)return i.note=s||i.note,i.seenIn=[...new Set([...i.seenIn??[],o].filter(Boolean))],i;const a={id:l.length>60?r+"-"+e.slice(0,12):l,rule:e,basename:u,anchor:r,note:s||"",addedAt:new Date().toISOString(),seenIn:o?[o]:[]};return t.push(a),a}function R(t,{record:e,repo:n,sweep:r,note:s,evidence:o,expires:u,now:l=new Date}){if(!e||e.file||!e.fid||!e.kind)throw new Error("a runtime false positive needs a runtime finding");if(!s)throw new Error("a runtime false positive needs a reason");if(!o)throw new Error("a runtime false positive needs an evidence reference");const i=typeof u=="string"&&/^\d{4}-\d{2}-\d{2}$/.test(u)?`${u}T23:59:59.999Z`:u;if(!$.test(i??"")||!Number.isFinite(Date.parse(i))||Date.parse(i)<=l.getTime())throw new Error("a runtime false positive needs a valid future --expires date");const a=O(e,r),p=a?.id;if(!p)throw new Error("runtime evidence was invalid or unmeasured and cannot be adjudicated");if(e.evidenceScope&&e.evidenceScope!==p)throw new Error("runtime finding evidence identity does not match its archived report");const h=e.evidenceScope??p,y=e.repoScope??A(n),k=`runtime|${y}|${h}|${e.fid}`,v=t.find(d=>d.type==="runtime"&&`runtime|${d.repoScope}|${d.evidenceScope}|${d.fid}`===k);if(v)return Object.assign(v,{note:s,evidence:o,expires:i,measurementMode:a.mode}),v;const x={type:"runtime",id:`runtime-${e.fid}-${h.slice(-8)}`,fid:e.fid,rule:e.kind,route:e.route,role:e.role??null,selector:e.at??null,repoScope:y,evidenceScope:h,note:s,evidence:o,expires:i,addedAt:l.toISOString(),measurementMode:a.mode};return t.push(x),x}function W(t,e){const n=t.findIndex(r=>r.id===e||c(r.rule,r.basename,r.anchor)===e);return n<0?null:t.splice(n,1)[0]}function Z(t,e=j()){if(!e.length)return 0;const n=M(e);let r=0;for(const s of t){const o=N(n,s);o&&(s.knownFp={id:o.id,note:o.note},o.type==="runtime"&&(s.waived=!0,s.adjudication={id:o.id,evidence:o.evidence,expires:o.expires}),r++)}return r}function z(t,e,n){try{return S.readFileSync(m.join(t,e),"utf8").split(`
2
+ `)[n-1]??null}catch{return null}}export{Q as addFp,R as addRuntimeFp,Z as annotateKnownFps,M as fpIndex,c as fpKey,w as fpStorePath,j as loadFps,N as matchFp,z as readSourceLine,W as removeFp,A as repoScope,O as runtimeEvidenceScope,J as runtimeMeasurementScope,G as saveFps};
package/lib/qa/fs.mjs ADDED
@@ -0,0 +1,6 @@
1
+ import t from"node:fs";import l from"node:path";import{InvalidError as u}from"./cli.mjs";function a(e){try{return t.accessSync(e),!0}catch{return!1}}function p(e){return t.readFileSync(e,"utf8")}function g(e,{required:r=!1,shape:i=null,what:n=null}={}){let o;try{o=t.statSync(e)}catch(s){if(s&&s.code==="ENOENT"){if(r)throw new u(`${n??"report"} missing: ${e}`);return null}throw new u(`${n??"report"} unreadable: ${e} (${s.code??s.message})`)}if(!o.isFile())throw new u(`${n??"report"} is not a file: ${e}`);let c;try{c=JSON.parse(t.readFileSync(e,"utf8"))}catch(s){throw new u(`${n??"report"} is not valid JSON: ${e} (${s.message.split(`
2
+ `)[0]})`)}if(i){const s=i(c);if(s)throw new u(`${n??"report"} has an unexpected shape: ${e} \u2014 ${s}`)}return c}function $(e,r){t.mkdirSync(l.dirname(e),{recursive:!0});const i=e+".tmp-"+process.pid+"-"+Date.now();t.writeFileSync(i,JSON.stringify(r,null,2)+`
3
+ `),t.renameSync(i,e)}function v(e){try{return JSON.parse(e)}catch{}try{return JSON.parse(d(String(e)))}catch{return null}}function d(e){let r="";const i=()=>{let n=r.length-1;for(;n>=0&&/\s/.test(r[n]);)n--;n>=0&&r[n]===","&&(r=r.slice(0,n)+r.slice(n+1))};for(let n=0;n<e.length;){const o=e[n];if(o==='"'){let c=n+1;for(;c<e.length&&e[c]!=='"';)c+=e[c]==="\\"?2:1;r+=e.slice(n,Math.min(c+1,e.length)),n=c+1}else if(o==="/"&&e[n+1]==="/")for(;n<e.length&&e[n]!==`
4
+ `;)n++;else if(o==="/"&&e[n+1]==="*"){const c=e.indexOf("*/",n+2);n=c===-1?e.length:c+2,r+=" "}else o==="}"||o==="]"?(i(),r+=o,n++):(r+=o,n++)}return r}function J(e,r){t.mkdirSync(l.dirname(e),{recursive:!0});const i=e+".tmp-"+process.pid+"-"+Date.now();t.writeFileSync(i,r),t.renameSync(i,e)}function N(e,r){t.mkdirSync(l.dirname(e),{recursive:!0}),t.appendFileSync(e,JSON.stringify(r)+`
5
+ `)}function O(e){return a(e)?p(e).split(`
6
+ `).filter(Boolean).map(r=>{try{return JSON.parse(r)}catch{return null}}).filter(Boolean):[]}function k(e,r){return a(e)?(t.mkdirSync(l.dirname(r),{recursive:!0}),t.copyFileSync(e,r),!0):!1}function y(e){if(!e||!Number.isInteger(e))return!1;try{return process.kill(e,0),!0}catch(r){return r&&r.code==="EPERM"}}function f(e){return l.join(e,".verify","qa.lock")}function m(e){const r=f(e);if(!a(r))return null;let i;try{i=JSON.parse(t.readFileSync(r,"utf8"))}catch{return{stale:!0,raw:!0}}return{...i,stale:!y(i.pid)}}function F(e,r){const i=f(e),n=m(e);if(n&&!n.stale)throw new u(`another qa run holds ${i} (pid ${n.pid}, ${n.command}, since ${n.at}); nothing else may sweep this repo while it runs`);t.mkdirSync(l.dirname(i),{recursive:!0}),t.writeFileSync(i,JSON.stringify({pid:process.pid,command:r,at:new Date().toISOString()}));let o=!1;const c=()=>{if(!o){o=!0,process.off("exit",c);try{JSON.parse(t.readFileSync(i,"utf8")).pid===process.pid&&t.unlinkSync(i)}catch{}}};return process.once("exit",c),c}function x(e){try{return t.readdirSync(e,{withFileTypes:!0}).filter(r=>r.isDirectory()).map(r=>r.name)}catch{return[]}}function E(e){t.rmSync(e,{recursive:!0,force:!0})}export{F as acquireLock,N as appendLine,k as copyIfExists,a as exists,x as listDirs,f as lockPath,v as parseJsonc,g as readJson,O as readLines,m as readLock,p as readText,E as rmrf,$ as writeJson,J as writeText};
@@ -0,0 +1,2 @@
1
+ import S from"node:fs";import{Buffer as F}from"node:buffer";const W=Object.freeze(["finding","route","component","query","mutation","entity","endpoint","role","transition","evidence"]),X=Object.freeze(["renders-through","reads","writes","writes-to","invalidates","transitions-to","owned-by","evidenced-by","observed-as"]),N=/^[0-9a-f]{64}$/,O=new Set(["inventory","classify","sweep"]),b=Object.freeze(["report","pointer","file","line"]),m=200,D=512,J=32,P=4294967295,Z=Object.freeze({finding:["severity","findingKind","status","evidenceRef"],route:["template"],component:["name"],query:["name"],mutation:["name"],entity:["name"],endpoint:["name"],role:["name"],transition:["fromRoute","toRoute"],evidence:["evidenceRef"]});function Y(e){return S.existsSync(e)?S.readFileSync(e,"utf8").split(`
2
+ `).filter(n=>n.length>0).map((n,o)=>{try{return JSON.parse(n)}catch(s){throw new Error(`${e}:${o+1}: not valid JSON (${s.message})`)}}):null}function x(e){return Z[e]??[]}function u(e,i){return Object.prototype.hasOwnProperty.call(e,i)}function h(e){return e!==null&&typeof e=="object"&&!Array.isArray(e)}function a(e){return F.byteLength(e,"utf8")}function _(e){return typeof e=="string"&&a(e)>=1&&a(e)<=m}function j(e){if(typeof e!="string"||a(e)===0||a(e)>D||!e.startsWith("/"))return!1;if(e==="/")return!0;if(e.includes("?")||e.includes("#")||e.includes("//"))return!1;const i=e.slice(1).split("/");return i.length===0||i.length>J?!1:i.every(t=>{if(t.startsWith(":")){const n=t.slice(1);return a(n)<=64&&/^[A-Za-z][A-Za-z0-9_]*$/.test(n)}return a(t)<=64&&/^[A-Za-z0-9._~-]+$/.test(t)})}function T(e){return typeof e!="string"||e!==""&&!e.startsWith("/")?!1:!/~(?![01])/u.test(e)}function z(e){return typeof e!="string"||a(e)===0||a(e)>m||/^(?:\/|\\|[A-Za-z]:)/u.test(e)?!1:!e.split(/[\\/]/u).includes("..")}function L(e){return Number.isInteger(e)&&e>=1&&e<=P}function B(e,i,t,n){if(!h(e))return n.push(`${t} must be an object`),!1;const o=new Set(i);Object.keys(e).some(s=>!o.has(s))&&n.push(`${t} contains a field outside its allowlist`);for(const s of i)u(e,s)||n.push(`${t}.${s} is required`);return!0}function l(e,i,t,n){_(e)||n.push(`${t}.${i} must be a non-empty string of at most ${m} bytes`)}function R(e,i,t,n){j(e)||n.push(`${t}.${i} is not a valid route template`)}function K(e,i,t){if(!h(e)){t.push(`${i} must be an object`);return}const n=new Set(b);Object.keys(e).some(o=>!n.has(o))&&t.push(`${i} contains a field outside its allowlist`);for(const o of["report","pointer"])u(e,o)||t.push(`${i}.${o} is required`);O.has(e.report)||t.push(`${i}.report is not a known report`),T(e.pointer)||t.push(`${i}.pointer is not a canonical RFC 6901 pointer`),u(e,"file")&&!z(e.file)&&t.push(`${i}.file is not a bounded repo-relative path`),u(e,"line")&&!L(e.line)&&t.push(`${i}.line must be an integer in the u32 source-line range`)}function C(e,i,t,n){const o=x(e);if(B(i,o,`${t}.attrs`,n))switch(e){case"finding":l(i.severity,"severity",`${t}.attrs`,n),l(i.findingKind,"findingKind",`${t}.attrs`,n),l(i.status,"status",`${t}.attrs`,n),K(i.evidenceRef,`${t}.attrs.evidenceRef`,n);break;case"route":R(i.template,"template",`${t}.attrs`,n);break;case"transition":R(i.fromRoute,"fromRoute",`${t}.attrs`,n),R(i.toRoute,"toRoute",`${t}.attrs`,n);break;case"evidence":K(i.evidenceRef,`${t}.attrs.evidenceRef`,n);break;default:l(i.name,"name",`${t}.attrs`,n);break}}function Q({nodes:e,edges:i}){const t=[],n=new Set;for(const[s,r]of e.entries()){if(r===null||typeof r!="object"||Array.isArray(r)){t.push(`node at index ${s} is not an object`);continue}const f=`node at index ${s}`;if(typeof r.recordId!="string"||!N.test(r.recordId)?t.push(`${f} has a malformed recordId`):n.has(r.recordId)?t.push(`${f} has a duplicate recordId`):n.add(r.recordId),!W.includes(r.kind)){t.push(`${f}: kind is not one of the ten allowed kinds`);continue}C(r.kind,r.attrs,f,t)}const o=new Set;for(const[s,r]of i.entries()){if(r===null||typeof r!="object"||Array.isArray(r)){t.push(`edge at index ${s} is not an object`);continue}const f=`edge at index ${s}`;typeof r.edgeId!="string"||!N.test(r.edgeId)?t.push(`${f} has a malformed edgeId`):o.has(r.edgeId)?t.push(`${f} has a duplicate edgeId`):o.add(r.edgeId),X.includes(r.relation)||t.push(`${f}: relation is not one of the nine allowed relations`),n.has(r.from)||t.push(`${f}: dangling "from" endpoint`),n.has(r.to)||t.push(`${f}: dangling "to" endpoint`)}return t.length?{ok:!1,problems:t}:{ok:!0,stats:{nodes:e.length,edges:i.length}}}function G(e){const i=x(e.kind),t={};if(h(e.attrs))for(const n of i){if(!u(e.attrs,n))continue;const o=e.attrs[n];if(n==="evidenceRef"){const s={};h(o)&&(O.has(o.report)&&(s.report=o.report),T(o.pointer)&&(s.pointer=o.pointer),u(o,"file")&&z(o.file)&&(s.file=o.file),u(o,"line")&&L(o.line)&&(s.line=o.line)),t[n]=s}else(n==="template"||n==="fromRoute"||n==="toRoute"?j(o):_(o))&&(t[n]=o)}return{recordId:e.recordId,kind:e.kind,attrs:t}}function U(e){return{edgeId:e.edgeId,from:e.from,to:e.to,relation:e.relation}}function v({nodes:e,edges:i},{kind:t=null,around:n=null,depth:o=1,limit:s=200}={}){let r;if(n){r=new Set([n]);const d=new Map(e.map(c=>[c.recordId,[]]));for(const c of i)d.get(c.from).push(c),d.get(c.to).push(c);let k=[n];for(let c=0;c<o;c++){const g=[];for(const A of k)for(const $ of d.get(A)){const y=$.from===A?$.to:$.from;r.has(y)||(r.add(y),g.push(y))}if(g.length===0)break;k=g}}else r=new Set(e.map(d=>d.recordId));let f=e.filter(d=>r.has(d.recordId)&&(!t||d.kind===t));const I=f.length,M=I>s;f=f.slice(0,s).map(G);const E=new Set(f.map(d=>d.recordId));let p=i.filter(d=>E.has(d.from)&&E.has(d.to));const w=p.length,q=w>s;return p=p.slice(0,s).map(U),{nodes:{items:f,returned:f.length,total:I,truncated:M},edges:{items:p,returned:p.length,total:w,truncated:q}}}export{Z as ATTR_ALLOWLIST,X as EDGE_RELATIONS,W as NODE_KINDS,v as neighborhood,Y as readJsonlStrict,Q as validateGraph};
@@ -0,0 +1,3 @@
1
+ import h from"node:path";import{exists as I,readLines as w}from"./fs.mjs";function p(e,a){return`${e}_${String(a??"").replace(/[^a-zA-Z0-9_]/g,"_").slice(0,160)}`}const R=e=>e?.hook?String(e.hook):`${e?.file??"?"}:${e?.line??"?"}`;function N(e){const a=new Map,l=new Set,i=[],s=(o,d,n)=>{let t=a.get(o);return t||(t={id:o,kind:d,label:n,stale:!1},a.set(o,t)),t},r=(o,d,n,t=!1)=>{const c=`${o}|${d}|${n}`;if(l.has(c)){if(t){const u=i.find(f=>f.from===o&&f.to===d&&f.relation===n);u&&(u.stale=!0)}return}l.add(c),i.push({from:o,to:d,relation:n,stale:t})},g=e?.routes??[];for(const o of g){const d=p("route",o.path);s(d,"route",o.path);for(const n of o.entities??[]){const t=p("entity",n);s(t,"entity",n),r(t,d,"read-by")}for(const n of o.mutations??[]){if(n.nonWrite||!n.writes)continue;const t=p("mutation",R(n));s(t,"mutation",n.hook?`${n.hook}()`:`${n.file}:${n.line}`);const c=p("entity",n.writes);s(c,"entity",n.writes),r(t,c,"writes")}}for(const o of e?.syncRisks??[]){if(!o.staleRoutes?.length)continue;const d=p("mutation",o.hook||String(o.mutation??"mutation"));s(d,"mutation",o.hook?`${o.hook}()`:String(o.mutation??"mutation"));for(const n of o.staleRoutes){const t=p("route",n),c=s(t,"route",n);c.stale=!0,r(d,t,"stale",!0)}}return{measured:!0,nodes:[...a.values()],edges:i}}function L(e){const a=h.join(e,".verify","autonomous"),l=h.join(a,"edges.jsonl");if(!I(l))return{measured:!1,nodes:[],edges:[]};const i=w(l),s=w(h.join(a,"nodes.jsonl")),r=new Map,g=new Map;for(const t of s){if(t?.kind!=="transition"&&t?.kind!=="transition-journey")continue;const c=t.attrs?.fromRoute??t.attrs?.from,u=t.attrs?.toRoute??t.attrs?.to;c==null||u==null||(g.set(t.recordId??t.id,{from:c,to:u}),r.set(`${c}|${u}`,{discovered:Number(t.attrs?.discovered??0),expected:Number(t.attrs?.expected??0)}))}const o=new Map,d=(t,c)=>{let u=o.get(t);return u||(u={id:t,kind:"route",label:c,stale:!1},o.set(t,u)),u},n=[];for(const t of i){if(!t||typeof t.relation!="string"||!/transition/.test(t.relation)||!t.from||!t.to)continue;const c=g.get(t.from),u=typeof t.detail=="string"?t.detail.indexOf("|"):-1,f=c?.from??(u>-1?t.detail.slice(0,u):null),$=c?.to??(u>-1?t.detail.slice(u+1):null),S=f??String(t.from).replace(/^route_?\|?/,""),j=$??String(t.to).replace(/^route_?\|?/,"");d(t.from,S);const x=d(t.to,j),k=f!=null&&$!=null?r.get(`${f}|${$}`):null,y=k?k.discovered===0:!1;y&&(x.stale=!0),n.push({from:t.from,to:t.to,relation:t.relation,stale:y})}return{measured:!0,nodes:[...o.values()],edges:n}}function m(e){return String(e??"").replace(/\\/g,"\\\\").replace(/"/g,'\\"').replace(/\r?\n/g,"\\n")}function _(e,{title:a="graph"}={}){const l=[`digraph "${m(a)}" {`," rankdir=LR;"," node [fontsize=10];"];for(const i of e.nodes){const s=[`label="${m(i.label)}"`,`shape=${i.kind==="mutation"?"box":i.kind==="entity"?"ellipse":"component"}`];i.stale&&s.push('color="red"','fontcolor="red"'),l.push(` "${m(i.id)}" [${s.join(", ")}];`)}for(const i of e.edges){const s=[`label="${m(i.relation)}"`];i.stale&&s.push('color="red"',"penwidth=2"),l.push(` "${m(i.from)}" -> "${m(i.to)}" [${s.join(", ")}];`)}return l.push("}"),l.join(`
2
+ `)}function b(e){return String(e??"").replace(/"/g,"#quot;").replace(/\r?\n/g," ")}function O(e){const a=["flowchart LR"],l=new Map;let i=0;const s=r=>(l.has(r)||l.set(r,"n"+i++),l.get(r));for(const r of e.nodes)a.push(` ${s(r.id)}["${b(r.label)}"]`),r.stale&&a.push(` class ${s(r.id)} stale;`);for(const r of e.edges)a.push(` ${s(r.from)} -->|"${b(r.relation)}"| ${s(r.to)}`);return a.push(" classDef stale stroke:#c00,stroke-width:2px,color:#c00;"),a.join(`
3
+ `)}function D(e){return JSON.stringify({measured:e.measured,nodes:e.nodes,edges:e.edges},null,2)}export{N as buildSyncGraph,L as loadTransitionGraph,p as nodeId,_ as toDot,D as toJson,O as toMermaid};
@@ -0,0 +1,3 @@
1
+ import $ from"node:fs";import k from"node:path";import{validate as C}from"./schema.mjs";import{validateMutationDeclaration as I}from"./mutation-policy.mjs";import{validatePersonas as q}from"./auth/personas.mjs";import{endpointFamily as g,entityAliasMap as N}from"./coherence/entity-aliases.mjs";const O=/^[A-Za-z][A-Za-z0-9_-]{0,63}$/,x=t=>t?.file&&Number.isInteger(t.line)?{file:t.file,line:t.line}:null,j=t=>typeof t=="string"?t.trim():"";function M(t,o,n,e,u=null){const d=k.join(t,o);if(!$.existsSync(d))return{status:"absent"};try{const i=JSON.parse($.readFileSync(d,"utf8")),p=JSON.parse($.readFileSync(k.join(e,"schemas",n),"utf8")),y=u?.(i);return C(p,i).length===0&&(!y||y.ok)?{status:"validated",value:i}:{status:"invalid"}}catch{return{status:"invalid"}}}function P(t,o){const n=M(t,"verify.crud.json","verify-crud.schema.json",o,I),e=M(t,"verify.roles.json","personas.schema.json",o,q);return{mutationValue:n.value??{},declarations:{mutationDeclaration:{status:n.status},personas:{status:e.status},identityLauncher:{status:$.existsSync(k.join(t,"verify.auth-launcher.mjs"))?"present":"absent"},coherenceDriver:{status:$.existsSync(k.join(t,"verify.coherence.mjs"))?"present":"absent"},coherenceProvenance:{status:$.existsSync(k.join(t,"verify.coherence-provenance.mjs"))?"present":"absent"}}}}function _(t,o){const n=j(o),e=Object.entries(t.matrix??{}).filter(([i])=>j(i)===n).flatMap(([,i])=>Array.isArray(i)?i:[]),u=Object.entries(t.resourceMatrix??{}).filter(([i])=>j(i)===n).flatMap(([,i])=>Array.isArray(i)?i:[]),d=(t.routes??[]).filter(i=>(i.entities??[]).some(p=>j(p)===n)).map(i=>i.path);return[...new Set([...e,...u,...d].filter(i=>typeof i=="string"))].sort()}function B(t,o){const n=t.coherence??{},e=new Set(o.map(s=>`${s.file}:${s.line}`)),u=new Set((n.mutations??[]).filter(s=>e.has(`${s.file}:${s.line}`)).map(s=>s.id)),d=new Map((n.mutations??[]).map(s=>[s.id,s.family])),i=new Set([...u].map(s=>d.get(s)).filter(Boolean)),p=new Map((n.reads??[]).map(s=>[s.id,s]));return(n.surfaces??[]).filter(s=>(s.readIds??[]).some(m=>i.has(p.get(m)?.family))).map(s=>({id:s.id,route:s.route??null,component:s.component??null,source:x(s)})).sort((s,m)=>`${s.route??""}:${s.id??""}`.localeCompare(`${m.route??""}:${m.id??""}`))}function D(t,o){const n=new Map;for(const e of t.routes??[])if(o.has(e.path))for(const u of e.derivedAssertions??[]){if(!u?.field||!u?.source)continue;const d=`${u.field}:${u.source}`;n.set(d,{field:u.field,confidence:u.confidence??"low",source:u.source})}return[...n.values()].sort((e,u)=>e.field.localeCompare(u.field)||e.source.localeCompare(u.source))}function F(t,o,n){const e=[];return t.personas.status!=="validated"&&e.push("author or repair verify.roles.json persona ownership and expected identity"),t.identityLauncher.status!=="present"&&e.push("provide verify.auth-launcher.mjs for authenticated personas; public routes need no launcher"),o||e.push("declare this entity and its endpoints in verify.crud.json with isolated fixtures and separately reserved cleanup"),o?.crosscheck||e.push("declare a schema-v2 crosscheck with authoritative readback and permitted projected-surface assertions"),n||e.push("resolve missing reader surfaces from source before claiming cross-route coverage"),t.coherenceDriver.status!=="present"&&e.push("implement verify.coherence.mjs for declared mutation, readback, and cleanup"),t.coherenceProvenance.status!=="present"&&e.push("implement verify.coherence-provenance.mjs to bind the served build to source"),e.push("verify isolated fixture ownership and cleanup capability before enabling writes; declarations are not execution"),e.push("run the harness; this plan contains no runtime proof"),e}function V({root:t,research:o,inventory:n,skillRoot:e}){const{declarations:u,mutationValue:d}=P(t,e),i=d.flows??[],p=N(d.entities??[]),y=(a,c)=>c?p.get(g(c))??a:a,s=new Map;for(const a of o.routes??[])for(const c of a.mutations??[]){const h=y(c.writes,c.endpoint),f=typeof h=="string"&&O.test(h.trim()),v=f?j(h):`unresolved:${a.path}:${c.file}:${c.line}`,w=s.get(v)??{entity:f?h.trim():null,entityStatus:f?"resolved":"unresolved",mutations:[]};w.mutations.push({route:a.path,source:x(c),hook:typeof c.hook=="string"?c.hook:null,verb:typeof c.verb=="string"?c.verb:null,endpoint:typeof c.endpoint=="string"?c.endpoint:null}),s.set(v,w)}const m=[...s.values()].map(a=>{a.mutations.sort((r,l)=>`${r.route}:${r.source?.file}:${r.source?.line}`.localeCompare(`${l.route}:${l.source?.file}:${l.source?.line}`));const c=new Map;for(const r of a.mutations){const l=JSON.stringify([r.source,r.hook,r.verb,r.endpoint,r.source?null:r.route]),S=c.get(l)??{...r,routes:[]};S.routes.includes(r.route)||S.routes.push(r.route),c.set(l,S)}const h=a.entity?_(n,a.entity):[],f=B(n,a.mutations.map(r=>({file:r.source?.file,line:r.source?.line}))),v=new Set([...h,...a.mutations.map(r=>r.route),...f.map(r=>r.route).filter(Boolean)]),w=D(o,v),b=a.mutations.map(r=>i.find(l=>a.entity!=null&&r.endpoint&&l.declared_endpoint&&y(l.crosscheck?.entity??l.name,l.declared_endpoint)===a.entity&&g(l.declared_endpoint)===g(r.endpoint))),A=b.every(Boolean)?{crosscheck:b.every(r=>!!r.crosscheck)}:null;return{entity:a.entity,entityStatus:a.entityStatus,state:"source-derived/non-executed",impact:{routes:[...v].sort(),surfaces:f,score:f.length+v.size},mutationSources:[...c.values()],assertionCandidates:w,requiredAuthoring:F(u,A,h.length>0||f.length>0)}});return m.sort((a,c)=>c.impact.score-a.impact.score||(a.entity??"").localeCompare(c.entity??"")||a.mutationSources[0].route.localeCompare(c.mutationSources[0].route)),{state:"source-derived/non-executed",declarations:u,workItems:m}}function H(t){const o=["## Harness handoff (source-derived, not executed)",""];if(!t.workItems.length)return o.concat(["No mutation source was found; no harness task was fabricated.",""]).join(`
2
+ `);o.push("One task per entity avoids repeating the same cross-route harness boilerplate. These are authoring requirements, never proof that a selector, identity, assertion, or runtime invariant exists.","");for(const n of t.workItems){o.push(`### ${n.entity??"Unresolved entity"} \u2014 impact ${n.impact.score} (${n.impact.routes.length} routes, ${n.impact.surfaces.length} surfaces)`);for(const e of n.mutationSources)o.push(`- mutation: ${e.routes.join(", ")} \xB7 ${e.source?.file??"unknown"}:${e.source?.line??"?"}${e.hook?` \xB7 ${e.hook}`:""}${e.verb?` \xB7 ${e.verb}`:""}${e.endpoint?` \xB7 ${e.endpoint}`:""}`);o.push(`- related routes: ${n.impact.routes.join(", ")||"none found in inventory/coherence"}`),n.assertionCandidates.length&&o.push(`- source-derived assertion candidates: ${n.assertionCandidates.map(e=>`${e.field} (${e.source})`).join(", ")}`);for(const e of n.requiredAuthoring)o.push(`- required: ${e}`);o.push("")}return o.join(`
3
+ `)}export{V as buildHarnessPlan,H as harnessPlanMarkdown};
@@ -0,0 +1,5 @@
1
+ import{isSafePersonaName as l,isSensitivePersonaName as u}from"./auth/personas.mjs";import{validateMutationDeclaration as p}from"./mutation-policy.mjs";const x=`{ "hooks": { "Stop": [{ "hooks": [{ "type": "command",
2
+ "command": "bash ~/.claude/skills/frontend-verify/verify.sh \\"$CLAUDE_PROJECT_DIR\\" --quiet || { echo 'BLOCKED: frontend-verify found P0/P1 findings \u2014 run it without --quiet to see them' >&2; exit 2; }" }] }] } }`,d=["_proto/","playground/","sandbox/","scratch/","design-lab/"];function b(){return["# .verifyignore \u2014 gitignore-shaped (supports * and ?). Paths listed here are","# dropped from both the inventory and the classifier.","#","# These design-lab trees are already excluded by default, with no .verifyignore","# present at all \u2014 listed here for visibility, not required:",...d.map(t=>`# ${t}`),"#","# Add your own patterns below.",""].join(`
3
+ `)}function m(t){const r=(Array.isArray(t?.principals)?t.principals:[]).map(e=>typeof e=="string"?e:e&&typeof e=="object"?e.name:null).filter(e=>typeof e=="string"&&e.trim()).map(e=>e.trim()),n=[];let s=0,i=0;for(const e of r){const c=!u(e)&&/^[A-Za-z][A-Za-z0-9]*(?:[ _-]+[A-Za-z0-9]+)+$/.test(e),a=l(e)?e:c?e.toLowerCase().replace(/[ _-]+/g,"-"):null;if(!l(a)){s++;continue}if(n.includes(a)){i++;continue}n.push(a)}return{names:n,skipped:s,deduplicated:i}}function f(t){return m(t).names}function h(t){const o=f(t);if(!o.length)return null;const r={};for(const n of o)r[n]={owns:["/"]};return r}function y(){return{default:{owns:["/"]}}}function w(t){const o=new Map;for(const r of t?.routes??[])for(const n of r.mutations??[]){if(typeof n?.writes!="string"||!n.writes.trim()||o.has(n.writes))continue;const s={name:n.writes,cleanup_required:!0,production:!1};for(const[i,e]of[["route",r.path],["declared_endpoint",n.endpoint]])typeof e=="string"&&p({flows:[{...s,[i]:e}]}).ok&&(s[i]=e);o.set(n.writes,s)}return[...o.values()].sort((r,n)=>r.name.localeCompare(n.name))}function _(t,o){const r=(o&&typeof o=="object"?Object.keys(o):f(t)).sort();return JSON.stringify({schema_version:1,personas:r.length?r:["default"],flows:w(t)},null,2)+`
4
+ `}function O(t){const o=h(t)??y();return JSON.stringify(o,null,2)+`
5
+ `}export{x as STOP_HOOK_SNIPPET,d as VERIFYIGNORE_DEFAULTS,_ as crudContent,w as crudFlows,y as defaultRoles,m as principalScaffold,f as principalsFromResearch,O as rolesContent,h as rolesFromResearch,b as verifyignoreContent};
@@ -0,0 +1 @@
1
+ import{idsOut as M}from"./reports.mjs";const p=.34,u=6;function A(s){const e=M(String(s??"").replace(/\b[A-Z]{2,}(?:-[A-Z0-9]{4,}){2,}\b/g,"<ref>"));let r=5381;for(let t=0;t<Math.min(e.length,400);t++)r=(r*33^e.charCodeAt(t))>>>0;return r.toString(36)}function y(s){return s.filter(e=>!e.redirectedTo&&!e.skipped&&e.textLen!=null)}function v(s){return(s.role??"default")+"@"+(s.width??"")}function b(s){const e=new Map;for(const t of s){const l=v(t);e.has(l)||e.set(l,{role:t.role??"default",width:t.width??null,cells:0,prints:new Map});const o=e.get(l);o.cells++,o.prints.set(t.fingerprint,(o.prints.get(t.fingerprint)??0)+1)}const r=[...e.values()].map(({role:t,width:l,cells:o,prints:n})=>({role:t,width:l,cells:o,distinct:n.size,ratio:Number((n.size/o).toFixed(2)),largestCluster:Math.max(...n.values()),collapsed:o>=u&&n.size/o<p}));return{distinctSurfaces:r.reduce((t,l)=>t+l.distinct,0),lanes:r}}function R(s){const e=new Map;for(const r of s)e.has(r.fingerprint)||e.set(r.fingerprint,new Set),e.get(r.fingerprint).add(r.route);return e.size?Math.max(...[...e.values()].map(r=>r.size)):0}function C(s,e){const r=s?.integrity,t=r?.distinctSurfaces==null,l=e.length,o=t?b(e).distinctSurfaces:r.distinctSurfaces,n=t?R(e):r.maxRoutesPerFingerprint??null,i=l?o/l:null;return{distinctSurfaces:o,cellsMeasured:l,maxRoutesPerFingerprint:n,distinctRatio:i==null?null:Number(i.toFixed(2)),sameSurface:l>=u&&i!=null&&i<p,source:t?"derived":"stored"}}function L({cells:s,unreached:e=[],isAuthRoute:r=()=>!1,textFloor:t=40,share:l=.25,aborted:o=!1}){const n=y(s),i=e.filter(a=>r(a.landedOn??"")).length,d=n.filter(a=>a.textLen<t).length,{distinctSurfaces:f,lanes:h}=b(n),F=R(n),c=n.length?f/n.length:null,m=n.length>=u&&c!=null&&c<p,g=h.reduce((a,S)=>!a||S.largestCluster>a.largestCluster?S:a,null),x=s.length>=u&&i>s.length*l,w=n.length>=u&&d>n.length*l;return{cellsPlanned:s.length,cellsMeasured:n.length,bouncedToLogin:i,cellsBelowTextFloor:d,distinctSurfaces:f,distinctRatio:c==null?null:Number(c.toFixed(2)),maxRoutesPerFingerprint:F,lanes:h,aborted:!!o,share:l,ok:!o&&n.length>0&&!x&&!w&&!m,failed:[o?"run aborted before every cell was swept":null,n.length===0?"zero cells were measured":null,x?i+" of "+s.length+" cells bounced to a login page -- this run graded the auth wall, not the app":null,w?d+" of "+n.length+" measured cells rendered under "+t+" characters of text -- the app was not up, or never rendered":null,m?n.length+" cells rendered only "+f+" distinct surfaces within their own role/width lanes -- one page measured under many names (worst: "+g.largestCluster+" routes came back as one page as "+g.role+" @"+g.width+"px)":null].filter(Boolean)}}export{p as SAME_SURFACE_RATIO,u as SAMPLE,L as gradeIntegrity,R as maxRoutesPerFingerprint,y as measuredCellsOf,A as surfaceFingerprint,b as surfaceLanes,C as surfacesOf};
@@ -0,0 +1,84 @@
1
+ import{createHash as k}from"node:crypto";import{normRoute as g,cellsOf as x}from"./reports.mjs";const S=Object.freeze(["route-reachable","no-console-errors","no-value-leaks","renders-text","endpoint-ok"]),h=Object.freeze(["route-reachable","renders-text"]),R=40,y=r=>k("sha256").update(r).digest("hex");function b(r,t,n=""){return y(`${r}|${t}|${n??""}`).slice(0,12)}function w(r,t,n){switch(r){case"route-reachable":return`route ${t} is reachable (no redirect) across measured runs`;case"no-console-errors":return`route ${t} produces no console.error or console.pageerror findings`;case"no-value-leaks":return`route ${t} produces no value.leak findings`;case"renders-text":return`route ${t} renders at least ${n} character(s) of visible text`;case"endpoint-ok":return`route ${t} request ${n} returns a non-5xx status`;default:return`route ${t} holds ${r}${n?" "+n:""}`}}function E(r,t,n){const s=r.findings??[];switch(t){case"route-reachable":return!r.redirectedTo;case"no-console-errors":return!s.some(o=>o.kind==="console.error"||o.kind==="console.pageerror");case"no-value-leaks":return!s.some(o=>o.kind==="value.leak");case"renders-text":return typeof r.textLen=="number"&&r.textLen>=n;default:return null}}function $(r){if(!r||!r.method)return null;let t=r.path;if(!t&&r.url)try{t=new URL(r.url).pathname}catch{t=r.url}return t?`${r.method} ${t}`:null}function N(r,{textFloor:t=R}={}){const n=(r??[]).filter(e=>e&&e.sweep&&Array.isArray(e.sweep.routes)),s=new Map,o=(e,a,c,d,l)=>{const i=`${e}|${a}|${c??""}`,u=s.get(i)??{kind:e,route:a,param:c??null,supportRuns:new Set,counterexampleRuns:new Set};(l?u.supportRuns:u.counterexampleRuns).add(d),s.set(i,u)};for(const e of n){const a=new Map;for(const c of x(e.sweep)){const d=g(c.route),l=a.get(d)??[];l.push(c),a.set(d,l)}for(const[c,d]of a){for(const i of["route-reachable","no-console-errors","no-value-leaks","renders-text"]){const u=i==="renders-text"?String(t):null,f=d.every(m=>E(m,i,t)===!0);o(i,c,u,e.id,f)}const l=new Map;for(const i of d)for(const u of i.requests??[]){const f=$(u);if(!f||typeof u.status!="number")continue;const m=l.get(f)??[];m.push(u),l.set(f,m)}for(const[i,u]of l){const f=u.every(m=>m.status<500);o("endpoint-ok",c,i,e.id,f)}}}return{candidates:[...s.values()].map(e=>({id:b(e.kind,e.route,e.param),kind:e.kind,route:e.route,param:e.param,statement:w(e.kind,e.route,e.param),support:e.supportRuns.size,counterexamples:e.counterexampleRuns.size,supportRuns:[...e.supportRuns].sort(),counterexampleRuns:[...e.counterexampleRuns].sort()})).sort((e,a)=>e.id.localeCompare(a.id)),runsConsidered:n.map(e=>e.id).sort()}}function v(r,t){const n=[];for(const s of r??[]){const o=(t??{})[`${s.runId}:${s.file}`];o==null?n.push({...s,now:null,reason:"archived file missing or unreadable"}):o!==s.sha256&&n.push({...s,now:o,reason:"digest mismatch -- archive changed since it was mined/approved"})}return{ok:n.length===0,mismatches:n}}function D(r,t){const n=v(r?.proofs,t);return n.ok?(r?.support??0)<2?{ok:!1,reason:"insufficient-support",mismatches:[]}:(r?.counterexamples??0)>0?{ok:!1,reason:"counterexamples-present",mismatches:[]}:{ok:!0,reason:null,mismatches:[]}:{ok:!1,reason:"tampered",mismatches:n.mismatches}}function I(){return{schemaVersion:1,enforced:[]}}function T(r,t,{by:n=null,at:s=new Date().toISOString()}={}){const o=(r?.enforced??[]).filter(e=>e.id!==t.id),p={id:t.id,kind:t.kind,route:t.route,param:t.param??null,statement:t.statement,support:t.support,counterexamples:t.counterexamples,approvedAt:s,by:n??null,proofs:t.proofs??[]};return{schemaVersion:1,enforced:[...o,p].sort((e,a)=>e.id.localeCompare(a.id))}}function A(r,t){const n=r?.enforced??[],s=n.some(o=>o.id===t);return{policy:{schemaVersion:1,enforced:n.filter(o=>o.id!==t)},present:s}}function L({candidates:r=[],policy:t=I(),packIds:n=[],currentDigests:s={}}={}){const o=new Map;for(const e of r)o.set(e.id,{...e});for(const e of t.enforced??[])o.set(e.id,{...o.get(e.id)??{},...e});const p=[...o.values()].map(e=>{const a=(t.enforced??[]).some(i=>i.id===e.id),c=n.includes(e.id),d=a?c?"enforced":"approved":"candidate",l=v(e.proofs,s);return{id:e.id,kind:e.kind,route:e.route,param:e.param??null,statement:e.statement,state:d,support:e.support??0,counterexamples:e.counterexamples??0,proofsOk:e.proofs&&e.proofs.length?l.ok:null,runtimeChecked:h.includes(e.kind)}});return p.sort((e,a)=>e.id.localeCompare(a.id)),p}function F(r,{at:t=new Date().toISOString(),skipped:n=[]}={}){return{schemaVersion:1,generatedAt:t,ids:r.map(s=>s.id),skipped:n}}function H(r){const t=r.map(o=>({id:o.id,kind:o.kind,route:o.route,param:o.param??null,statement:o.statement,proofs:(o.proofs??[]).map(p=>({runId:p.runId,file:p.file,sha256:p.sha256}))})),n=JSON.stringify(h),s=JSON.stringify(t,null,2);return`// Generated by \`qa measure invariants enforce\` -- DO NOT EDIT BY HAND.
2
+ // Independent runtime authority for the invariants approved into
3
+ // <repo>/verify.invariants.json (see lib/qa/invariants.mjs and
4
+ // lib/qa/commands/invariants.mjs in the frontend-verify skill, and
5
+ // agent/src/invariants/{model,governance}.rs for why this authority is kept
6
+ // independent of the Rust output directory).
7
+ //
8
+ // Every proof below is a sha256 digest of an archived run file under
9
+ // .verify/runs/<id>/. It is recomputed from the archive that is on disk RIGHT
10
+ // NOW, every time this module is imported (the loop just below this header).
11
+ // A tampered or regenerated archive makes that recomputation fail and this
12
+ // import throw -- the harness (bin/runtime-packs.mjs / bin/sweep.mjs) records
13
+ // that as rule-pack infrastructure, never a product finding, and the run
14
+ // exits 2.
15
+ //
16
+ // Runtime enforcement per navigated cell is limited to what a runtime(context)
17
+ // call can independently observe from a live Playwright page: the sweep's own
18
+ // collected findings and network log are not part of that context. Only
19
+ // ${n} are checked live, from the page itself.
20
+ // Other approved kinds (no-console-errors, no-value-leaks, endpoint-ok) still
21
+ // have their proofs verified above -- a tampered archive still fails the
22
+ // import -- but are not independently re-checked per cell here; see
23
+ // \`qa measure invariants status\` for the honest per-id picture.
24
+ import fs from 'node:fs';
25
+ import path from 'node:path';
26
+ import { createHash } from 'node:crypto';
27
+ import { fileURLToPath } from 'node:url';
28
+
29
+ export const id = 'invariants';
30
+ export const version = '1';
31
+ export const phase = 'runtime';
32
+
33
+ const HERE = path.dirname(fileURLToPath(import.meta.url));
34
+ const RUNS_DIR = path.resolve(HERE, '..', 'runs');
35
+ const RUNTIME_CHECKABLE = new Set(${n});
36
+ const ENFORCED = ${s};
37
+
38
+ function sha256File(p) {
39
+ return 'sha256:' + createHash('sha256').update(fs.readFileSync(p)).digest('hex');
40
+ }
41
+
42
+ for (const inv of ENFORCED) {
43
+ for (const proof of inv.proofs) {
44
+ const file = path.join(RUNS_DIR, proof.runId, proof.file);
45
+ let digest;
46
+ try { digest = sha256File(file); } catch (e) {
47
+ throw new Error('invariant ' + inv.id + ': archived proof file missing or unreadable: ' + file);
48
+ }
49
+ if (digest !== proof.sha256) {
50
+ throw new Error('invariant ' + inv.id + ': proof mismatch for ' + file + ' -- archive changed since approval (tampered or regenerated)');
51
+ }
52
+ }
53
+ }
54
+
55
+ function normRoute(route) {
56
+ if (route == null) return '(page)';
57
+ let r = String(route).split('?')[0].split('#')[0];
58
+ if (r.length > 1) r = r.replace(/\\/+$/, '');
59
+ return r || '/';
60
+ }
61
+
62
+ export async function runtime(context) {
63
+ const findings = [];
64
+ const route = normRoute(context?.route);
65
+ for (const inv of ENFORCED) {
66
+ if (inv.route !== route || !RUNTIME_CHECKABLE.has(inv.kind)) continue;
67
+ if (inv.kind === 'route-reachable') {
68
+ let landed = route;
69
+ try { landed = normRoute(new URL(context.page.url()).pathname); } catch { /* leave as route */ }
70
+ if (landed !== route) {
71
+ findings.push({ kind: 'invariant.violated', severity: 'P1', detail: inv.statement + ' (id ' + inv.id + ') -- landed on ' + landed, at: '(page)' });
72
+ }
73
+ } else if (inv.kind === 'renders-text') {
74
+ const floor = Number(inv.param) || 0;
75
+ let len = 0;
76
+ try { len = await context.page.evaluate(() => ((document.body && document.body.innerText) || '').trim().length); } catch { /* unreadable page */ }
77
+ if (len < floor) {
78
+ findings.push({ kind: 'invariant.violated', severity: 'P1', detail: inv.statement + ' (id ' + inv.id + ') -- measured ' + len + ' character(s)', at: '(page)' });
79
+ }
80
+ }
81
+ }
82
+ return findings;
83
+ }
84
+ `}export{R as DEFAULT_TEXT_FLOOR,S as KINDS,h as RUNTIME_CHECKABLE_KINDS,T as applyApprove,A as applyRevoke,b as candidateId,I as emptyPolicy,D as evaluatePolicy,H as generatePackSource,N as mineFromRuns,F as packManifestFor,v as proofsValid,w as statementFor,L as statusRows};
package/lib/qa/jcs.mjs ADDED
@@ -0,0 +1 @@
1
+ import{createHash as c}from"node:crypto";const s=(n,t)=>n<t?-1:n>t?1:0,u={'"':'\\"',"\\":"\\\\","\b":"\\b","\f":"\\f","\n":"\\n","\r":"\\r"," ":"\\t"};function f(n){let t='"';for(const o of n){const r=u[o];if(r){t+=r;continue}const i=o.codePointAt(0);t+=i<32?"\\u"+i.toString(16).padStart(4,"0"):o}return t+'"'}function a(n){if(!Number.isFinite(n))throw new TypeError(`JCS: ${n} is not a finite number`);return Object.is(n,-0)?"0":String(n)}function e(n){if(n===null)return"null";const t=typeof n;if(t==="boolean")return n?"true":"false";if(t==="number")return a(n);if(t==="string")return f(n);if(t==="undefined")throw new TypeError("JCS: undefined has no canonical form");if(t==="function"||t==="symbol"||t==="bigint")throw new TypeError(`JCS: ${t} has no canonical form`);return Array.isArray(n)?"["+n.map(e).join(",")+"]":"{"+Object.keys(n).sort(s).map(r=>f(r)+":"+e(n[r])).join(",")+"}"}function p(n){return c("sha256").update(Buffer.from(e(n),"utf8")).digest("hex")}export{e as canonicalize,p as jcsDigest};
@@ -0,0 +1 @@
1
+ import{InvalidError as r}from"./cli.mjs";const t=Object.freeze(["source","public-runtime","mock-contract","real-integration","mfa-integration"]),o=Object.freeze(["real-integration","mfa-integration"]);function c(e,{command:n}){if(e==null||e===!0||e==="")throw new r(`qa ${n} requires --lane <${t.join("|")}>`);if(!t.includes(e))throw new r(`qa ${n}: unknown lane ${JSON.stringify(e)}; expected one of ${t.join(", ")}`);return e}function s(e,n,{operation:i}){if(e!==n)throw new r(`${i} across lanes is invalid: ${e} and ${n} measure different things and cannot be compared or summed`)}function f(){return!1}function u(e){return o.includes(e)}export{t as LANES,o as REAL_LANES,s as assertSameLane,f as laneAllowsMutation,u as laneRequiresOracle,c as requireLane};
@@ -0,0 +1,7 @@
1
+ import w from"node:path";import{run as T,git as v,gitInfo as _}from"./proc.mjs";import{writeJson as $,writeText as B,readJson as C,appendLine as J}from"./fs.mjs";import{loadRun as V,runRecords as M,trajectoryPath as W}from"./runs.mjs";import{triage as U,loadRoutePriorities as X}from"./triage.mjs";import{pickNext as Y,buildBrief as Z,onlyKnownFpsLeft as ee}from"./commands/impl/next.mjs";import{BlockLedger as ne}from"./block-ledger.mjs";import{EXIT as r,InvalidError as f}from"./cli.mjs";const H=e=>w.join(e,".verify","loop.json"),u=e=>{const n=v(e,["rev-parse","HEAD"]);return n.code===0?n.stdout.trim():null},d=e=>Math.round((Date.now()-e)/1e3),te=Object.freeze([".verify",".claude",".codex"]);function N(e){try{return V(e,"latest")}catch{return null}}function oe(e){return _(e).isRepo?v(e,["status","--porcelain"]).stdout:null}function ie(e,n){return n!=null&&v(e,["status","--porcelain"]).stdout!==n}const se=e=>te.some(n=>e===n||e.startsWith(n+"/"));function re(e){return v(e,["status","--porcelain"]).stdout.split(`
2
+ `).filter(Boolean).filter(n=>!se(n.slice(3).replace(/\/$/,"")))}function I(e,n){J(W(e),{checkpoint:!0,at:new Date().toISOString(),...n})}async function ae({repo:e,skillRoot:n,verifyArgs:h,iteration:y}){if(h.includes("--no-archive"))throw new f("qa run loop: --no-archive is unsupported because the host handoff requires a fresh archived measurement");const p=process.env.QA_ALLOW_TEST_HOOKS==="1"?process.env.QA_VERIFY_CMD:null,g={QA_REPO:e,QA_ITERATION:String(y),QA_GATE_PHASE:"pre",QA_SKILL_ROOT:n};return p?T("bash",["-lc",p],{cwd:e,env:g,stdout:"capture",stderr:"capture"}):T(process.execPath,[w.join(n,"bin","qa.mjs"),"verify",e,"--ratchet",...h],{env:g,stdout:"capture",stderr:"capture"})}async function me({repo:e,skillRoot:n,verifyArgs:h=[],fixer:y=null,fixerProtocol:k=!1,commit:p=!1,fixerTimeoutMs:g=0,out:E=null}){if(y||k||p||g)throw new f("qa run loop never launches a fixer or commits source; run qa run <repo> --once and let the host agent apply .verify/next.md");if(!_(e).isRepo)throw new f(`qa run loop needs a git repository: ${e} is not one`);const D=re(e);if(D.length)throw new f(`qa run loop needs a clean git tree; dirty: ${D.slice(0,10).map(s=>s.slice(3)).join(", ")}`);const x=E?.say??(()=>{}),A=E?.warn??(()=>{}),P=new Date().toISOString(),Q=oe(n),z=C(H(e)),a=ne.from(z??{}),m=a.activeAt(1),o={startedAt:P,iterations:[],...a.toJSON(),seededBlocked:m.size},i=()=>{Object.assign(o,a.toJSON()),$(H(e),o)};i();const c=Date.now();x(""," --- host-agent handoff");const F=N(e)?.id??null;let l;try{l=await ae({repo:e,skillRoot:n,verifyArgs:h,iteration:1})}catch(s){throw o.iterations.push({i:1,runId:null,fid:null,action:"invalid",result:s.message,head:u(e),seconds:d(c)}),i(),s}if(ie(n,Q))return o.stoppedReason="skillRoot changed after gate",i(),A(` qa run loop: ${n} changed during the run -- stopping.`),r.INVALID;if(![r.OK,r.FINDINGS].includes(l.code))return o.iterations.push({i:1,runId:null,fid:null,action:"invalid",result:`gate exit ${l.code}`,head:u(e),seconds:d(c)}),i(),A(` qa run loop: gate exited ${l.code} -- INVALID; fix the QA configuration, then rerun.`),r.INVALID;if(l.code===r.OK)return o.iterations.push({i:1,runId:N(e)?.id??null,fid:null,action:"done",result:"clean within measured scope",head:u(e),seconds:d(c)}),i(),I(e,{i:1,clean:1,fixed:0,open:0,blocked:a.activeAt(1).size}),x(""," CLEAN WITHIN MEASURED SCOPE -- review unmeasured gaps before release."),r.OK;const t=N(e);if(!t||t.id===F){const s="gate exited 1 without a fresh archived run; refusing to triage stale evidence";throw o.iterations.push({i:1,runId:t?.id??null,fid:null,action:"invalid",result:s,head:u(e),seconds:d(c)}),i(),new f(`qa run loop: ${s}; refusing to triage stale evidence`)}const S=t.meta.counts?.total??null,q=M(t),b=U({records:q,inventory:t.inventory,sweep:t.sweep,classify:t.classify,prod:(t.meta.args??[]).includes("--prod"),priorities:X(e)});if(ee(b,m))return o.iterations.push({i:1,runId:t.id,fid:null,action:"known-fps-only",result:`${b.groups.filter(s=>s.allKnownFp).length} known-false-positive group(s) remain; waive in source or with qa fix fp`,head:u(e),seconds:d(c)}),i(),I(e,{i:1,clean:0,fixed:0,open:S,blocked:a.activeAt(1).size}),A(" qa run loop: every remaining finding is a known false positive; no host handoff was written."),r.FINDINGS;const L=Y(b,m);if(!L)return o.iterations.push({i:1,runId:t.id,fid:null,action:"no-fix-available",result:`${m.size} finding(s) blocked; none left to hand off`,head:u(e),seconds:d(c)}),i(),I(e,{i:1,clean:0,fixed:0,open:S,blocked:a.activeAt(1).size}),r.FINDINGS;const O=t.meta.args??[],K=O.includes("--base")?O[O.indexOf("--base")+1]:null,{json:j,md:G}=Z({repo:e,skillRoot:n,run:t,group:L,records:q,base:K,inventory:t.inventory}),R=w.join(e,".verify","next.md");return $(w.join(e,".verify","next.json"),j),B(R,`${G}
3
+
4
+ ## Host-agent next step
5
+
6
+ Read this brief, make the source change in the host worktree, run the bounded QA check, and rerun \`qa run ${e} --once\`. The CLI does not launch or commit source changes.
7
+ `),o.iterations.push({i:1,runId:t.id,fid:j.fid,action:"no-fixer",result:"brief written for the host agent",head:u(e),seconds:d(c)}),i(),I(e,{i:1,clean:0,fixed:0,open:S,blocked:a.activeAt(1).size}),x("",` host-agent handoff: ${R}`," source fixes and commits remain with the host agent"),r.FINDINGS}export{te as HARNESS_PATHS,me as runLoop};
@@ -0,0 +1 @@
1
+ import q from"node:fs";import h from"node:path";import{createHash as N}from"node:crypto";import{fileURLToPath as L}from"node:url";import{readJson as k,exists as $,writeJson as T}from"./fs.mjs";import{EXIT as I,redactArgs as F}from"./cli.mjs";import{completeAdapterInvocation as C,prepareAdapterInvocation as z}from"./reports.mjs";import{canonicalize as j,jcsDigest as w}from"./jcs.mjs";import{evaluateMutationPolicy as J}from"./mutation-policy.mjs";import{expectedSourceIdentity as M,loadServedProvenance as U}from"./coherence/provenance.mjs";const b='see references/verify.crud.example.json and README "qa measure coherence"',B=!0;function V(n){const e=n?.startedAt;return typeof e!="string"||!e?null:`marathon-${e.replace(/[^0-9]/g,"")}`}const W=h.resolve(h.dirname(L(import.meta.url)),"../.."),H=["bin/coherence-runner.mjs","lib/qa/coherence/observe.mjs","lib/qa/coherence/representations.mjs","lib/qa/coherence/provenance.mjs","lib/qa/coherence/plan-join.mjs","lib/qa/coherence-planner.mjs","lib/qa/coherence/flow-pool.mjs","lib/qa/coherence/analyze.mjs","lib/qa/coherence/contracts.mjs","lib/qa/coherence/identity.mjs","lib/qa/mutation-policy.mjs","lib/qa/jcs.mjs","lib/qa/reports.mjs","lib/qa/schema.mjs","lib/qa/marathon-coherence.mjs","schemas/coherence-observed.schema.json","schemas/coherence-plan.schema.json","schemas/verify-crud.schema.json"];function u(n){return{material:n,digest:w(n)}}function G(n){return{namespace:"marathon/measurement-configuration",version:1,measurementConfig:n.measurementConfig,autoFlags:n.autoFlags??[],prod:!!n.prod}}function E(n,e){return!n||!$(n)?{status:"absent",kind:e}:{status:"present",kind:e,document:k(n,{required:!0,what:e})}}function X(){return{namespace:"coherence/tool-build",version:1,files:Object.fromEntries(H.map(n=>[n,N("sha256").update(q.readFileSync(h.join(W,n))).digest("hex")]))}}async function K({repo:n,runId:e,base:c,lane:r,flowWorkers:t=1,planPath:s=null,evidenceIdentity:o,configurationMaterial:a,maxMutations:m=20,overrideNonLocal:v=!1}){const l=q.realpathSync(n),i=String(c??"").replace(/\/$/,""),f=k(h.join(l,"verify.crud.json"),{required:!0,what:"verify.crud.json"}),p=J({mutate:!0,base:i,lane:r,declaration:f,maxMutations:m,cleanupCapable:!0,fixtureNamespace:`coherence-${e}`,overrideNonLocal:v});if(!p.ok)throw new Error(`mutation permit could not be frozen: ${p.reason}`);const d=await U({repo:l,base:i,adapterPath:h.join(l,"verify.coherence-provenance.mjs")});if(d.status!=="measured")throw new Error(`served provenance could not be frozen: ${d.reason??d.status}`);const g=[h.join(l,"verify.roles.json"),h.join(l,".verify","roles.json")].find($)??null,S=E(s,"coherence-plan"),A={namespace:"coherence/selected-flow-declarations",version:1,schemaVersion:f.schema_version,flows:p.flows.filter(y=>y?.crosscheck)},D=g?E(g,"principal-declaration"):{status:"absent",kind:"principal-declaration"},P={namespace:"coherence/mutation-permit",version:1,allowed:!0,mutateRequested:!0,overrideNonLocalRequested:v===!0,base:i,lane:r,maxMutations:m,cleanupCapable:!0,fixtureNamespaceRule:"fixtureNamespaceFor(runId,flowName)/v1",selectedFlows:p.flows.map(y=>y.name),cleanup:p.cleanup},R={namespace:"coherence/runtime-protocol",version:1,outer:o?.toolProtocol??null};if(o?.configurationDigest!==`sha256:${w(a)}`)throw new Error("configuration material does not match outer configurationDigest");const _={runId:u(e),repoRealPath:u(l),source:u(M(l)),base:u(i),served:u(d.provenance),lane:u(r),flowWorkers:u(t),plan:u(S),flowDeclaration:u(A),principal:u(D),mutationPermit:u(P),configuration:u(a),protocol:u(R),toolBuild:u(X())},x={namespace:"coherence-evidence-envelope",version:1,outerEvidenceIdentity:u(o),coordinates:_};return{...x,digest:w(x)}}function ue(n,e){if(!e||e.namespace!=="coherence-evidence-envelope"||e.version!==1)return"namespace-or-version";const c={...e};if(delete c.digest,e.digest!==w(c))return"envelope-digest";for(const[r,t]of Object.entries(e.coordinates??{}))if(!t||t.digest!==w(t.material))return`${r}-digest`;if(e.outerEvidenceIdentity?.digest!==w(e.outerEvidenceIdentity?.material))return"outer-evidence-identity-digest";if(!n)return null;if(j(n.outerEvidenceIdentity)!==j(e.outerEvidenceIdentity))return"outer-evidence-identity";for(const r of Object.keys(n.coordinates))if(j(n.coordinates[r])!==j(e.coordinates?.[r]))return r;return n.digest===e.digest?null:"envelope-digest"}function le(n,{mutation:e}={}){const c=h.join(n,"verify.crud.json");if(!$(c))return{ok:!1,reason:`no ${c} -- write it with schema_version 3 and a flow declaring "crosscheck" (${b})`};let r;try{r=k(c)}catch{return{ok:!1,reason:`${c} is not valid JSON (${b})`}}if(r?.schema_version!==3)return{ok:!1,reason:`${c} is schema_version ${JSON.stringify(r?.schema_version??null)}, not 3 -- upgrade it and add a flow declaring "crosscheck" (${b})`};const t=Array.isArray(r.flows)?r.flows:[];if(!t.some(a=>a&&a.crosscheck))return{ok:!1,reason:`no flow in ${c} declares "crosscheck" -- add one (${b})`};const s=h.join(n,"verify.coherence.mjs");if(!$(s))return{ok:!1,reason:`no ${s} -- export createCoherenceDriver(...) (${b})`};const o=h.join(n,"verify.coherence-provenance.mjs");return $(o)?e?.ok?{ok:!0,reason:`${c} declares schema_version ${r.schema_version} with a crosscheck flow, both ${s} and ${o} exist, and writes are opted in (${e.reason})`,flows:t.filter(a=>a&&a.crosscheck)}:{ok:!1,reason:e?.reason??"mutation not opted in (see verify.crud.json)"}:{ok:!1,reason:`no ${o} -- export createCoherenceDriver(...) (${b})`}}async function de({repo:n,phaseCall:e}){const c=await e(["measure","coherence"],[n,"--json"],{stdout:"capture"});let r=null;try{r=JSON.parse(c.stdout)}catch{}const t=r?.coherence??null,s=t?.candidates??[],o=new Set(s.flatMap(m=>m.surfaceIds??[])).size,a=r?.views?.obligations?.count??0;return c.code===I.INVALID?{status:"unmeasured",reason:t?.coverage?.reason?`qa measure coherence: ${t.coverage.reason}`:`qa measure coherence --json exited ${c.code}`,counts:t?.coverage?.counts??null,candidates:s.length,affectedSurfaces:o,obligationUniverse:a,exit:c.code}:{status:t?.coverage?.status??"unmeasured",reason:null,counts:t?.coverage?.counts??null,candidates:s.length,affectedSurfaces:o,obligationUniverse:a,exit:c.code,...Q(r)}}function Q(n,{top:e=3}={}){const c={},r=n?.causes;r?.counts&&(c.causes={...r.counts,top:(r.causes??[]).filter(s=>s.label==="confirmed").slice(0,e).map(s=>({mutation:s.mutation??s.mutationId??s.rootCauseId,affectedSurfaces:(s.affectedSurfaces??[]).filter(o=>o.runtime==="disagreed").map(o=>o.route??o.surfaceId)}))});const t=n?.risk;return t&&(c.risk={status:t.status,reason:t.reason??null,windowDays:t.windowDays,top:(t.families??[]).filter(s=>s.risk!=null).slice(0,e).map(s=>({family:s.family,risk:s.risk}))}),c}async function fe({repo:n,state:e,phaseCall:c,overrideNonLocal:r,planPath:t=null,flows:s=null}){const o=(s??[]).map(a=>a?.name).filter(a=>typeof a=="string"&&a);return o.length>1?Y({repo:n,state:e,phaseCall:c,overrideNonLocal:r,planPath:t,selected:o}):O({repo:n,state:e,phaseCall:c,overrideNonLocal:r,planPath:t,flowName:o[0]??null})}async function O({repo:n,state:e,phaseCall:c,overrideNonLocal:r,planPath:t,flowName:s}){const o=[n,"--base",e.base,"--mutate"];s&&o.push("--flow",s),B&&t&&$(t)&&o.push("--plan",t);const a=V(e);a&&o.push("--runid",a);const m=e.effectiveLane??e.lane??"public-runtime",v=e.flowWorkers??1;o.push("--lane",m,"--flow-workers",String(v)),r&&o.push("--i-know-this-is-not-production");let l;try{l=z({repo:n,adapter:"coherence",evidenceIdentity:e.evidenceIdentity,command:`qa measure coherence ${F(o).join(" ")}`})}catch(d){return{ok:!1,reason:`coherence invocation could not start: ${d.message}`,invocation:null}}if(a)try{const d=await K({repo:n,runId:a,base:e.base,lane:m,flowWorkers:v,planPath:t,evidenceIdentity:e.evidenceIdentity,configurationMaterial:G(e),overrideNonLocal:r}),g=h.join(l.dir,"coherence-evidence-envelope.json");T(g,d),o.push("--evidence-envelope",g)}catch(d){const{invocation:g}=C(l,{code:I.INVALID,signal:null,timedOut:!1});return{ok:!1,reason:`coherence evidence envelope could not be prepared: ${d.message}`,invocation:g}}const i=await c(["measure","coherence"],o,{}),{invocation:f,document:p}=C(l,i);return i.code===I.INVALID?{ok:!1,reason:`qa measure coherence --mutate${s?` --flow ${s}`:""} exited ${i.code}`,invocation:f}:f.status!=="measured"?{ok:!1,reason:f.reason,invocation:f}:{ok:!0,status:p.status,counts:p.counts??null,planCoverage:p.plan?.coverage??null,invocation:f}}function me(n){const e=[],c=n?.coherence?.static;e.push(c?`coherence (static): ${c.candidates} candidate(s) over ${c.affectedSurfaces} affected surface(s), static Cartesian estimate ${c.obligationUniverse} (mutation x surface x principal x context; not the kernel obligation universe)${c.status==="unmeasured"?` (unmeasured: ${c.reason})`:""}`:"coherence (static): did not run");const r=n?.coherence?.runtime;if(r?.ok){const o=r.counts?.targets??{};if(e.push(`coherence (runtime): ${o.agreed??0} agreed / ${o.compared??0} compared / ${o.reached??0} reached / ${o.planned??0} planned`),r.planCoverage){const a=r.planCoverage;e.push(`coherence (plan): ${a.agreed??0} agreed / ${a.compared??0} compared / ${a.reached??0} reached / ${a.planned??0} planned -- the runtime sweep measured against the baseline's own coherenceObligations plan`)}}else e.push(`coherence (runtime): unmeasured -- ${r?.reason??"not run"}`);const t=n?.coherence?.causes;if(t){e.push(`coherence (causes): ${t.confirmed} confirmed / ${t.notReproduced} not reproduced / ${t.unmeasured} unmeasured of ${t.causes}`);for(const o of t.top??[])e.push(` confirmed: ${o.mutation} -- affected surfaces: ${o.affectedSurfaces.join(", ")}`)}const s=n?.coherence?.risk;return s&&e.push(s.status==="measured"?`coherence (risk): measure next ${s.top.map(o=>`${o.family} (${o.risk})`).join(", ")} over ${s.windowDays}d`:`coherence (risk): unmeasured -- ${s.reason??"not measured"}`),e}async function Y({repo:n,state:e,phaseCall:c,overrideNonLocal:r,planPath:t,selected:s}){const o={};let a="measured",m=null,v=null;for(const l of s){const i=await O({repo:n,state:e,phaseCall:c,overrideNonLocal:r,planPath:t,flowName:l});if(v=i.invocation??v,!i.ok)return{...i,invocation:v};i.status&&i.status!=="measured"&&(a=i.status),m=i.planCoverage??m;for(const[f,p]of Object.entries(i.counts??{})){o[f]??={};for(const[d,g]of Object.entries(p??{}))typeof g=="number"&&(o[f][d]=(o[f][d]??0)+g)}}return{ok:!0,status:a,counts:o,planCoverage:m,flows:s,invocation:v}}export{B as PLAN_FLAG_SUPPORTED,K as buildCoherenceEvidenceEnvelope,ue as coherenceEnvelopeMismatch,me as coherenceExitLines,V as coherenceRunId,le as coherenceRuntimeOptIn,G as evidenceConfigurationMaterial,fe as runRuntimeCoherence,de as runStaticCoherence,Q as summariseCausesAndRisk};
@@ -0,0 +1 @@
1
+ async function d({groups:a,remaining:s,coordinator:n}){for(const l of a){if(n.stopped())break;const p=l.phases??[];if(l.mode==="parallel"){const e=[];for(const t of p){if(t.budgetMs!=null&&t.budgetMs>s()){n.skip(t.name,b(t,s()));continue}e.push(t)}for(const t of e)n.start?.(t.name,t.budgetMs??null);const f=(await Promise.allSettled(e.map(t=>m(t,n)))).map((t,r)=>t.status==="fulfilled"?{name:e[r].name,...t.value}:h(e[r].name,t.reason));n.applyGroup(f)}else for(const e of p){if(n.stopped())break;if(e.budgetMs!=null&&e.budgetMs>s()){n.skip(e.name,b(e,s()));continue}n.start?.(e.name,e.budgetMs??null);let u;try{u={name:e.name,...await m(e,n)}}catch(f){u=h(e.name,f)}n.applyOne(u)}}}async function m(a,s){const n=s.heartbeatMs??5e3,l=s.heartbeat&&n>0?setInterval(()=>s.heartbeat(a.name),n):null;l?.unref();try{return await a.run()}finally{l&&clearInterval(l)}}function b(a,s){return`deadline reached: needs ~${Math.round(a.budgetMs/6e4)}m, ${Math.max(0,Math.round(s/6e4))}m left`}function h(a,s){return{name:a,result:{ok:!1,invalid:!0,message:`${a} threw: ${String(s?.message??s)}`},commands:[],decisions:[],skips:[]}}export{d as runPhaseGroups};
@@ -0,0 +1,3 @@
1
+ import E from"node:crypto";import r from"node:fs";import k from"node:path";import{InvalidError as y}from"./cli.mjs";import{watchRepo as T}from"./watch.mjs";function v({lastDurationMs:t,checkpointMs:n}){return t>0?Math.max(Math.max(1,n),Math.ceil(t*1.5+5e3)):Math.max(1,n)}function J({remainingMs:t,lastDurationMs:n,checkpointMs:o}){return t>v({lastDurationMs:n,checkpointMs:o})}function M(t){if(!Number.isInteger(t))return!1;try{return process.kill(t,0),!0}catch(n){return n?.code==="EPERM"}}function b(t){return k.join(t,".verify","marathon.lock")}function j(t){return k.join(t,".verify","marathon.lock.claims")}function I(t,{requireOwner:n=!1}={}){let o;try{o=r.lstatSync(t)}catch(e){if(e?.code==="ENOENT")return null;throw e}if(!o.isFile()||o.isSymbolicLink())throw new y(`marathon lock is not a regular file: ${t}`);let a;try{a=JSON.parse(r.readFileSync(t,"utf8"))}catch{throw new y(`marathon lock is incomplete or unreadable: ${t}; inspect it before removing it`)}if(!Number.isInteger(a?.pid)||n&&typeof a?.owner!="string")throw new y(`marathon lock is incomplete or unreadable: ${t}; inspect it before removing it`);return a}function W(t,{pid:n=process.pid,alive:o=M,now:a=()=>new Date().toISOString()}={}){const e=b(t),h=E.randomBytes(12).toString("hex"),c=j(t),d=k.join(c,`${h}.json`),u={pid:n,owner:h,at:a()};r.mkdirSync(k.dirname(e),{recursive:!0});try{const i=(()=>{try{return r.lstatSync(c)}catch(p){if(p?.code==="ENOENT")return null;throw p}})();if(i&&(!i.isDirectory()||i.isSymbolicLink()))throw new y(`marathon claim path is not a regular directory: ${c}`);i||r.mkdirSync(c),r.writeFileSync(d,JSON.stringify(u)+`
2
+ `,{flag:"wx"});const s=I(e);if(s&&o(s.pid))throw new y(`another qa run holds ${e} (pid ${s.pid}, since ${s.at??"unknown"}); use qa run ${t} --status`);for(const p of r.readdirSync(c)){const l=k.join(c,p);if(l===d)continue;const g=I(l,{requireOwner:!0});if(o(g.pid))throw new y(`another qa run holds ${e} (pid ${g.pid}, since ${g.at??"unknown"}); use qa run ${t} --status`);try{r.unlinkSync(l)}catch(N){if(N?.code!=="ENOENT")throw N}}const m=I(e);if(m&&o(m.pid))throw new y(`another qa run holds ${e} (pid ${m.pid}, since ${m.at??"unknown"}); use qa run ${t} --status`);m&&r.unlinkSync(e),r.writeFileSync(e,JSON.stringify(u)+`
3
+ `,{flag:"wx"})}catch(i){try{r.unlinkSync(d)}catch{}try{r.rmdirSync(c)}catch{}throw i}let x=!1,S=null,w=null;const f=()=>{if(!x){x=!0,process.off("exit",f),S&&process.off("SIGINT",S),w&&process.off("SIGTERM",w);try{const i=r.lstatSync(e);if(i.isFile()&&!i.isSymbolicLink()){const s=JSON.parse(r.readFileSync(e,"utf8"));s.pid===n&&s.owner===h&&r.unlinkSync(e)}}catch{}try{r.unlinkSync(d)}catch{}try{r.rmdirSync(c)}catch{}}},$=i=>{f(),setImmediate(()=>{try{process.kill(process.pid,i)}catch{process.exit(2)}})};return S=()=>$("SIGINT"),w=()=>$("SIGTERM"),process.once("exit",f),process.once("SIGINT",S),process.once("SIGTERM",w),f}function O(t,n){return T(t,{onChange:n})}function q(t,n){const o=k.join(t,".verify","lanes");r.mkdirSync(o,{recursive:!0});try{const a=r.watch(o,(e,h)=>{const c=h==null?"plan.json":String(h);(c==="plan.json"||c.startsWith("plan.json."))&&n(c)});return{stop(){try{a.close()}catch{}}}}catch{return{stop(){}}}}function A({repo:t,deadline:n,checkpointMs:o,now:a=Date.now,watchSource:e=u=>O(t,u),watchLanes:h=u=>q(t,u),setTimer:c=setTimeout,clearTimer:d=clearTimeout}){const u=n-a();if(u<=0)return Promise.resolve({kind:"deadline",path:null});const x=Math.min(u,Math.max(1,o));return new Promise((S,w)=>{let f=!1,$=null,i=null,s=null;const m=()=>{try{$?.stop()}catch{}try{i?.stop()}catch{}s!=null&&d(s)},p=(l,g=null)=>{f||(f=!0,m(),S({kind:l,path:g}))};try{$=e(l=>p("source",l)),i=h(l=>p("lanes",l)),s=c(()=>p(a()>=n?"deadline":"checkpoint"),x)}catch(l){f=!0,m(),w(l)}})}export{W as acquireMarathonLock,b as marathonLockPath,v as measurementReserveMs,J as shouldStartRemeasurement,A as waitForMarathonSignal};
@@ -0,0 +1,5 @@
1
+ import ce from"node:fs";import $ from"node:path";import{createHash as qe}from"node:crypto";import{run as Ze,git as en}from"./proc.mjs";import{readJson as W,writeJson as he,writeText as Pe,readText as ge,exists as E,appendLine as nn}from"./fs.mjs";import{EXIT as w,redactArgs as ie}from"./cli.mjs";import{BlockLedger as tn}from"./block-ledger.mjs";import{initialDepth as an,nextDepth as rn,DEPTH_LADDER as U}from"./deepening.mjs";import{listRunIds as H,loadRun as K,trajectory as sn,trajectoryPath as on,newRunId as un}from"./runs.mjs";import{loadMutationDeclaration as dn,evaluateMutationPolicy as cn}from"./mutation-policy.mjs";import{defaultQueue as ln}from"./experiments-default.mjs";import{cargoPhaseAvailability as fn,kernelPhaseAvailability as ve}from"./agent-availability.mjs";import{loadPlan as ne,currentBatch as Le}from"./commands/impl/lanes.mjs";import{boardHeaderLine as le,activeClasses as mn,allBatchesSettled as pn}from"./fix-lanes.mjs";import{coherenceRuntimeOptIn as hn,runStaticCoherence as gn,runRuntimeCoherence as vn,coherenceExitLines as bn,evidenceConfigurationMaterial as yn}from"./marathon-coherence.mjs";import{UNSUPPORTED_COVERAGE_REASONS as wn}from"./coherence/analyze.mjs";import{runPhaseGroups as xn}from"./marathon-phases.mjs";import{canonicalize as Y}from"./jcs.mjs";import{loadSourceSnapshot as Oe}from"./source-snapshot.mjs";import{assertAdapterInvocationDescriptor as Me,completeAdapterInvocation as kn,prepareAdapterInvocation as $n,validateAdapterInvocationBytes as In,validateArchivedAdapterInvocation as Ce}from"./reports.mjs";import{currentAdapterInvocations as se,verdictFor as jn}from"./verdict.mjs";import{waitForMarathonSignal as Ne,shouldStartRemeasurement as Fe}from"./marathon-wait.mjs";import{loadPersonas as Sn}from"./auth/personas.mjs";import{consumesAuthLease as An,resumeSignature as Dn}from"./auth/lease.mjs";import{createPersonaCoordinator as qn}from"./auth/coordinator.mjs";const Pn=["serve","preflight","study","baseline","deep","remediation","closing","report","done"];function R(e){const t=Pn.indexOf(e);return t===-1?0:t}function fe(e){return $.join(e,".verify","marathon.json")}function Ln(e){return W(fe(e))}function S(e,t){he(fe(e),t)}function On({hours:e,extraFlags:t,base:n,laneFlag:a=null,flowWorkers:i=1,widthsGiven:o=!1,states:d=!0,dark:s=!0,autonomous:p=!1}){const c=ie(t??[]);return{startedAt:new Date().toISOString(),deadline:Date.now()+e*36e5,pid:process.pid,depth:an({states:d,dark:s,exercise:c.includes("--exercise")}),args:c,measurementConfig:{widthsGiven:o,states:d,dark:s,extraFlags:c,autonomous:p},phase:"serve",base:n??null,prod:!1,served:null,runs:[],stability:null,ghosts:[],loopState:{iterations:[],blocked:[]},checkpoints:[],waiting:null,remeasurements:[],decisions:[],commandLog:[],deepSkips:[],deepSubphases:{},invariantsSummary:null,linkedAdapters:[],pendingLinkAdapters:[],adapterInvocations:[],pendingAdapterInvocations:[],deepEvidence:{status:"unmeasured",counts:{total:0,P0:0,P1:0,P2:0,P3:0}},rungs:[],mutation:null,lane:null,requestedLane:a,effectiveLane:null,flowWorkers:i,evidenceIdentity:null,autoFlags:[],journeys:null,closing:null,lanes:{planned:!1,batch:null}}}function Wt(e,{now:t=Date.now(),alive:n=Ee}={}){if(!e)return null;const a=Math.max(0,Math.round((e.deadline-t)/6e4)),i=e.phase!=="done"&&!!e.pid&&n(e.pid),o=e.decisions?.at(-1)??null,d=e.checkpoints?.at(-1)??null,s=e.commandLog?.at(-1)??null,p=Object.entries(e.deepSubphases??{}).find(([,g])=>g?.status==="running")??null,c=p?Math.max(0,t-Date.parse(p[1].heartbeatAt)):null;return{phase:e.phase,running:i,finished:e.phase==="done",startedAt:e.startedAt,minutesLeft:a,base:e.base??null,depth:U[e.depth??0]?.name??"baseline",runs:e.runs?.length??0,lastCommand:s?`[${s.exit}] ${s.cmd}`:null,activeCommand:e.activeCommand?{...e.activeCommand,ageMs:Math.max(0,t-Date.parse(e.activeCommand.startedAt))}:null,lastDecision:o?`${o.what} -- ${o.why}`:null,lastCheckpoint:d,mutation:e.mutation?.ok??!1,lane:e.effectiveLane??e.lane??"public-runtime",lanes:e.lanes??null,deepSubphase:p?{name:p[0],status:"running",heartbeatAgeMs:c,heartbeatStale:!Number.isFinite(c)||c>6e4}:null,kernel:e.kernel?.status??"unknown",waiting:e.waiting??null,lastRemeasurement:e.remeasurements?.at(-1)??null}}function Ht(e,t){if(!e)return` no marathon state at ${fe(t)} -- nothing has run here`;const n=[];if(n.push(` marathon ${e.finished?"finished":e.running?"running":"STOPPED (process gone, not finished -- resume with --resume)"} phase ${e.phase} ${e.minutesLeft} min left`),n.push(` base ${e.base??"none (static-only)"} lane ${e.lane} writes ${e.mutation?"on":"off"} depth ${e.depth} runs ${e.runs}`),e.activeCommand){const a=Math.round(e.activeCommand.ageMs/6e4);n.push(` running ${e.activeCommand.cmd} (${e.activeCommand.phase}, ${a} min so far)`)}if(e.lastCommand&&n.push(` last cmd ${e.lastCommand}`),e.lastDecision&&n.push(` decided ${e.lastDecision}`),e.waiting&&n.push(` waiting ${e.waiting.reason} next checkpoint ${e.waiting.nextCheckpointAt}`),e.lastRemeasurement&&n.push(` measured ${e.lastRemeasurement.status} at ${e.lastRemeasurement.finishedAt??e.lastRemeasurement.startedAt}`),e.lastCheckpoint&&n.push(` checkpoint clean ${e.lastCheckpoint.clean} \xB7 fixed ${e.lastCheckpoint.fixed} \xB7 open ${e.lastCheckpoint.open} \xB7 blocked ${e.lastCheckpoint.blocked}`),e.lanes?.planned){const a=ne(t);n.push(` lanes ${a?le(a):"planned"}`)}return n.push(` report ${$.join(t,".verify","marathon-report.md")}${e.finished?"":" (written when it finishes)"}`),n.join(`
2
+ `)}function Ee(e){if(!e||!Number.isInteger(e))return!1;try{return process.kill(e,0),!0}catch(t){return t&&t.code==="EPERM"}}function Mn(e){const t=en(e,["rev-parse","HEAD"]);return t.code===0?t.stdout.trim():null}function Cn({priorRung:e,head:t}){return e?e.head&&t&&e.head!==t?{resumeFlag:!1,resumeReason:`source changed between rungs (HEAD ${e.head.slice(0,7)} -> ${t.slice(0,7)}); a resumed sweep cannot trust cells measured against the old source`}:{resumeFlag:!0,resumeReason:"source unchanged since the previous rung"}:{resumeFlag:!1,resumeReason:"first depth escalation of this marathon: no prior rung to reuse cells from"}}function me(e){return Array.isArray(e)?e:[e]}function Nn(e,t,n,a){const i=me(n);return e?[e,...i,...a]:[$.join(t,"bin","qa.mjs"),...i,...a]}async function oe(e,t,{skillRoot:n,stdout:a="inherit",timeoutMs:i,processGroup:o=!0,termGraceMs:d,fd3:s=null}={}){const c=process.env.QA_ALLOW_TEST_HOOKS==="1"?process.env.QA_MARATHON_CMD_PREFIX:null;return Ze(process.execPath,Nn(c,n,e,t),{stdout:a,stderr:"inherit",timeoutMs:i,processGroup:o,termGraceMs:d,fd3:s})}function Re(e,t,n,a){return{phase:e,cmd:`qa ${me(t).join(" ")} ${ie(n).join(" ")}`,exit:a}}async function G(e,t,n,a,i,o,d={}){const s=me(i),p=An(s)?n._authCoordinator?.descriptor:null,c=p?[...o,"--auth-lease-fd","3"]:o;n.activeCommand={phase:a,cmd:me(i).join(" "),startedAt:new Date().toISOString()},S(e,n);let g;try{g=await oe(i,c,{skillRoot:t,...d,...p?{fd3:JSON.stringify(p)}:{}})}finally{n.activeCommand=null}return n.commandLog.push(Re(a,i,c,g.code)),S(e,n),g}function Fn(e){const t=(e?.checks??[]).find(a=>a.id==="base");if(!t)return"unknown";const n=/serverType\s+(\w+)/.exec(t.detail||"");return n?n[1]:"unknown"}function Ve(e){return(e?.checks??[]).filter(t=>t.level==="fail").map(t=>`${t.id}: ${t.detail}${t.fix?` (fix: ${t.fix})`:""}`)}function En(e,t){if(!t.length)return;const n=$.join(e,".verify","loop.json"),a=W(n)??{startedAt:new Date().toISOString(),iterations:[]},i=tn.from(a);for(const o of t)i.block(o,"ghost",0);he(n,{...a,...i.toJSON()})}function Rn(e){return(e?.meta?.findings??[]).filter(t=>t.phase!=="static"&&!t.waived&&(t.severity==="P0"||t.severity==="P1"))}function _e(e){const t=e?.meta?.exit;if(t===w.INVALID)return w.INVALID;if(e?.meta?.mode!=="runtime"&&(t===w.OK||t===w.FINDINGS))return t;const n=e?.meta?.counts??{};return(n.P0??0)+(n.P1??0)>0?w.FINDINGS:w.OK}function te(e){return!!e&&_e(e)===w.OK}function Vn(e,t=10){const n=new Set,a=[];for(const i of e){const o=i.subject??i.route;if(!(!o||n.has(o))&&(n.add(o),a.push(o),a.length>=t))break}return a}function _n({repo:e,serve:t,baseFlag:n,hours:a,stabilityRuns:i,checkpointMinutes:o,keepServing:d}){const s=[];return s.push(`repo: ${e}`),s.push(`deadline: ${a}h from start`),t?s.push("0. qa run serve <repo> --prod (serve a production build; its base becomes --base)"):n?s.push(`0. using given --base ${n}`):s.push("0. no --base given: qa run serve <repo> --prod is attempted; if the app cannot be built and served, static-only marathon (said plainly in the report)"),s.push("1. qa verify <repo> --preflight [--base <base>] (preflight; exit 2 stops everything, its fix lines are printed)"),s.push(" server type from the preflight probe decides --prod automatically on every phase below"),s.push("2. qa init <repo> --study; qa init <repo> --roles --ignore (study; scaffolds verify.roles.json from the principals found; never stops on it)"),s.push("2b. --mutate comes from a safe verify.crud.json declaration; an explicit --lane wins, otherwise the repo selects real-integration when its launcher/personas qualify; resolved draft journeys promote under the same mutation opt-in"),s.push("3. qa verify <repo> [--base <base>] [--prod] --widths 390,1440 [--states] [--dark] [--mutate] [--lane L] --ratchet (baseline; exit 2 stops)"),s.push("3b. deep measurement (once, after the baseline, before stability): qa measure crud (under the mutation opt-in above) \xB7 qa measure experiments (queue generated from the baseline's Rust route priority when none exists; needs cargo) \xB7 qa measure shadow replay (when verify.shadow-trace.json or .verify/shadow-trace.json exists) \xB7 qa measure invariants mine, qa measure invariants status (needs a runtime baseline) -- review/enforce are never run automatically; anything not enabled is a NAMED skip (reason + how to enable it) in the exit report, never silent"),s.push(`4. qa verify <repo> --base <base> --runs ${i} --routes <top P0/P1 runtime routes, max 10> (only when the baseline has runtime P0/P1; ghosts get written into .verify/loop.json's blocked list)`),s.push('5. qa fix plan <repo> --lanes N (one worktree + brief per class, disjoint batches; exit 1 "lanes ready"; the next bare qa run rebases open lanes, opens the next batch when one is settled, and re-baselines when every batch is settled)'),s.push(`6. checkpoint every ~${o}m: qa show ledger, qa show report, one line appended to .verify/trajectory.jsonl`),s.push("7. if time remains and something was fixed: qa verify again, qa show diff against the prior baseline; new findings send it back to step 4"),s.push("7b. closing verification (always, not time-boxed): qa dev validate <repo> (schema check on everything on disk; exit 2 makes the whole marathon INVALID) and qa dev atlas --strict (the skill's own detector-coverage health check; findings are reported but never change this run's PASS/FAIL verdict)"),s.push("8. exit report: .verify/marathon-report.md + qa show report HTML; the report's first word is PASS, FAIL, or INVALID"),t&&!d&&s.push("9. qa run serve <repo> --stop (stopping the server this marathon started)"),s}function Gn(e){if(!e)return{total:0,clean:0,bugFids:[],unmeasured:0};const t=e.split(`
3
+ `).filter(s=>s.startsWith("|")).map(s=>s.split("|").map(p=>p.trim())).filter(s=>s.length>=9&&s[1]!=="route"&&!/^-+$/.test(s[1]??"")),n=t.map(s=>s[s.length-2]??""),a=t.length,i=n.filter(s=>s==="clean"||s==="static-only").length,o=n.filter(s=>s.startsWith("bug:")).map(s=>s.slice(4)),d=n.filter(s=>/^(unmeasured|needs-reproduction)\b/.test(s)).length;return{total:a,clean:i,bugFids:o,unmeasured:d}}async function Ge(e,t,n){const a=await G(e,t,n,"serve",["run","serve"],[e,"--prod"]);if(a.code!==w.OK)return{ok:!1,reason:`qa run serve exited ${a.code}`};const i=W($.join(e,".verify","serve.json"));return i?.base?{ok:!0,base:i.base,pid:i.pid}:{ok:!1,reason:"qa run serve exited 0 but wrote no base to .verify/serve.json"}}async function Tn({repo:e,skillRoot:t,state:n,decide:a}){const i=[e,...n.base?["--base",n.base]:[],"--preflight","--json"],o=await G(e,t,n,"preflight","verify",i,{stdout:"capture"});let d=null;try{d=JSON.parse(o.stdout)}catch{}if(o.code===w.INVALID)return a("stop: doctor blocked",Ve(d).join("; ")||"doctor exited 2"),{ok:!1,fixLines:Ve(d)};if(n.base){const s=Fn(d);s==="prod"?n.prod=!0:s==="dev"?(n.prod=!1,a("timing findings will be P3","measuring the compiler, not the app -- serverType dev")):n.prod=!1}else n.prod=!1;return{ok:!0}}function Wn(e,t,{overrideNonLocal:n=!1,lane:a="public-runtime"}={}){const i=dn(e),o=cn({command:"marathon",mutate:!0,base:t,overrideNonLocal:n,lane:a??"public-runtime",declaration:i.declaration,declarationReason:i.reason,maxMutations:20,fixtureNamespace:`qa-marathon-${un()}`,cleanupCapable:!0});return o.ok?{ok:!0,reason:`${i.path} declares every flow production:false and ${t} is safe for declared writes`}:{ok:!1,reason:o.reason}}function Te(e){const t=$.join(e,"verify.auth-launcher.mjs");if(!E(t))return{lane:null,reason:`no ${t} -- every persona sweeps unauthenticated (public-runtime); write the launcher (README "Evidence lanes") to measure as a real principal`};const n=[$.join(e,"verify.roles.json"),$.join(e,".verify","roles.json")].find(E),a=n?W(n):null,i=a&&typeof a=="object"?Object.keys(a):[],o=i.filter(d=>!a[d]||typeof a[d]!="object"||!a[d].expect);return!i.length||o.length?{lane:null,reason:`launcher present but ${o.length?`persona(s) ${o.join(", ")} declare no "expect"`:"no persona is declared"} in ${n??"verify.roles.json"} -- a real lane cannot validate a persona that never said what it expects to see back`}:{lane:"real-integration",reason:`${t} present and every persona declares expect`}}function Hn(e){for(const t of["verify.journeys.mjs",$.join(".verify","journeys.mjs")]){const n=$.join(e,t);if(E(n)&&/\bmutates\s*:\s*true\b/.test(ge(n)))return!0}return!1}function Kn(e,t,n){const a=E($.join(e,"verify.journeys.mjs"))||E($.join(e,".verify","journeys.mjs")),i=$.join(e,".verify","journeys.draft.mjs");if(a||!E(i)){t.journeys={promoted:0,reason:a?"journeys file already present":"no draft"};return}const o=ge(i),d=(o.match(/^\s*resolved: (true|false),$/gm)??[]).length,s=(o.match(/^\s*resolved: true,$/gm)??[]).length;if(!t.mutation?.ok){t.journeys={promoted:0,total:d,reason:`${s} of ${d} draft journeys resolved from source, none promoted: a journey submits a real form, and ${t.mutation?.reason??"mutation is not opted in"}`},n("journeys not promoted",t.journeys.reason);return}if(!s){t.journeys={promoted:0,total:d,reason:`0 of ${d} draft journeys resolved every field and submit control from source; each carries a TODO naming what to find with playwright-cli`},n("journeys not promoted",t.journeys.reason);return}Pe($.join(e,".verify","journeys.mjs"),["// Promoted by qa run from journeys.draft.mjs: only the entries whose every","// field and submit control resolved from source (resolved: true). Regenerated","// on every marathon; write <repo>/verify.journeys.mjs to take over.","import draft from './journeys.draft.mjs';","export default draft.filter((j) => j.resolved === true);",""].join(`
4
+ `)),t.journeys={promoted:s,total:d,reason:`${s} of ${d} draft journeys promoted to .verify/journeys.mjs`},n("journeys promoted",t.journeys.reason)}async function zn({repo:e,skillRoot:t,state:n,overrideNonLocal:a,explicitLane:i,decide:o}){const d=await G(e,t,n,"study","init",[e,"--study"]);if(d.code===w.INVALID)return o("stop: research could not run",`qa init --study exited ${d.code}`),{ok:!1};const s=W($.join(e,".verify","research.json")),p=E($.join(e,"verify.roles.json"))||E($.join(e,".verify","roles.json")),c=s?.counts?.principals??0,g=await G(e,t,n,"study","init",[e,"--roles","--ignore"]);if(g.code===w.INVALID)return o("stop: init could not run",`qa init exited ${g.code}`),{ok:!1};c>1&&!p&&o("roles scaffolded, ownership not narrowed",`research found ${c} principals and no roles file existed; qa init wrote one role per principal, each owning "/" -- narrow owns/excludes in verify.roles.json to stop each lens re-measuring the others' trees`);const v=Te(e),b=i??n.requestedLane??Ie(n.args)??null;n.effectiveLane=n.effectiveLane??b??v.lane??"public-runtime",n.lane=n.effectiveLane==="public-runtime"&&!b?null:n.effectiveLane,o(`lane ${n.effectiveLane}`,b?`explicit --lane ${b}, persisted for every measuring phase`:v.reason),n.mutation=Wn(e,n.base,{overrideNonLocal:a,lane:n.effectiveLane}),o(n.mutation.ok?"writes enabled by declaration":"writes stay off",n.mutation.reason),Kn(e,n,o);const A=n.mutation.ok&&Hn(e);return n.mutation.ok&&!A&&o("sweep --mutate withheld","writes are authorized, but no app-owned journey declares mutates: true, so --mutate on the sweep could only invalidate the run (generic guessed replay is disabled); qa measure crud and qa measure coherence still write"),n.autoFlags=[...A?["--mutate"]:[],...n.effectiveLane!=="public-runtime"?["--lane",n.effectiveLane]:[]],{ok:!0}}function Bn({noAutonomous:e=!1,autonomous:t=null,availabilityFn:n=fn}={}){if(e)return{status:"unmeasured",reason:"--no-autonomous",enable:"drop --no-autonomous"};if(t===!0)return{status:"measured",reason:null,enable:null};const a=n();return a.status!=="measured"?{status:"unmeasured",reason:`${a.reason}, so the Rust kernel could not build`,enable:"install rustup (https://rustup.rs), then re-run \u2014 qa verify --preflight --strict now exits 2 on this"}:t===!1?{status:"unmeasured",reason:"this marathon's measurement mode was frozen without the Rust kernel when it started",enable:"start a fresh marathon (qa run <repo> --fresh) with cargo installed"}:{status:"measured",reason:null,enable:null}}function We(e){const t=[];for(let n=0;n<e.length;n++){const a=e[n];a==="--oracle-path"||a==="--launcher"?(e[n+1]!==void 0&&t.push(a,e[n+1]),n++):(a.startsWith("--oracle-path=")||a.startsWith("--launcher="))&&t.push(a)}return t}function be({prod:e,widthsGiven:t,states:n,dark:a,extraFlags:i,autonomous:o=!1}){const d=[];return e&&d.push("--prod"),o&&d.push("--autonomous"),t||d.push("--widths","390,1440"),n&&d.push("--states"),a&&d.push("--dark"),d.push(...i),d}function He(e){const t={states:e.includes("--states"),dark:e.includes("--dark"),exercise:e.includes("--exercise"),widths:null};for(let n=0;n<e.length-1;n++)(e[n]==="--widths"||e[n]==="--width")&&(t.widths=e[n+1]);return t}function Ke({current:e,remainingMs:t,widthsGiven:n,states:a,dark:i,extraFlags:o,autonomous:d=!1,prod:s=!1}){const p=be({prod:s,widthsGiven:n,states:a,dark:i,extraFlags:o,autonomous:d});let c=e;const g=[];for(;;){const v=c+1,b=rn({current:c,remainingMs:t,widthsGiven:n});if(!b)return n&&v===U.length-1&&t>=U[v].minutes*6e4&&g.push(v),{rung:null,skipped:g};const A=i?b.flags:b.flags.filter(f=>f!=="--dark"),m=He([...p,...(U[c]?.flags??[]).filter(f=>i||f!=="--dark")]),D=He([...p,...A]);if(Y(m)===Y(D)){g.push(b.index),c=b.index;continue}const I=[];for(const[f,q]of[["states","--states"],["dark","--dark"],["exercise","--exercise"]])!m[f]&&D[f]&&I.push(q);return m.widths!==D.widths&&D.widths&&I.push("--widths",D.widths),{rung:{...b,flags:I},skipped:g}}}function Jn(e,{base:t,prod:n,widthsGiven:a,states:i,dark:o,extraFlags:d,autonomous:s,resume:p,linkAdapters:c}){const g=[e];return t&&g.push("--base",t),g.push(...be({prod:n,widthsGiven:a,states:i,dark:o,extraFlags:d,autonomous:s})),p&&g.push("--resume"),c&&c.length&&g.push(`--link-adapters=${c.join(",")}`),g.push("--ratchet"),g}function Qn(e,t,n){if(!t)return"the required adapter archive was not published";try{for(const a of n)Ce(e,t,a,{publication:"pending"});return null}catch(a){return a.message}}async function ue({repo:e,skillRoot:t,state:n,phase:a,widthsGiven:i,states:o,dark:d,extraFlags:s,resume:p=!1,decide:c,timeoutMs:g=0}){const v=n.pendingLinkAdapters?.length?n.pendingLinkAdapters:null,b=v?(n.pendingAdapterInvocations??[]).filter(L=>v.includes(L.adapter)&&L.publication==="pending"):[];if(n.kernel||(n.kernel=Bn({autonomous:n.measurementConfig?.autonomous??null}),n.kernel.status!=="measured"&&c("Rust kernel unmeasured",`${n.kernel.reason} -- the graph, the coherence obligation plan, the experiment queue and triage's route priority are all unmeasured for this marathon`)),v){let L=ye(e,n);if(!L&&b.some(V=>!ae(V.evidenceIdentity,n.evidenceIdentity))&&(pe(n),L="a pending adapter descriptor does not match the current evidence identity; prior adapter evidence was superseded and must be remeasured"),L)return S(e,n),c("stop: adapter evidence identity changed",L),{ok:!1,exit:w.INVALID,message:L,resumePhase:"deep",durationMs:0,timedOut:!1}}const A=new Set(H(e)),m=Jn(e,{base:n.base,prod:n.prod,widthsGiven:i,states:o,dark:d,extraFlags:s,autonomous:n.measurementConfig.autonomous,resume:p,linkAdapters:v}),D=Date.now(),I=await G(e,t,n,a,"verify",m,{timeoutMs:g}),f=Date.now()-D;if(I.code===w.INVALID)return c("stop: baseline invalid",I.timedOut?`qa verify exceeded its ${g}ms deadline allowance`:`qa verify exited ${I.code}`),{ok:!1,exit:I.code,durationMs:f,timedOut:I.timedOut};const q=H(e).length?K(e,"latest"):null;if(v){const L=b.length!==v.length?"one or more required adapters have no pending invocation descriptor":A.has(q?.id)?"qa verify did not publish a new run for required adapter evidence":Qn(e,q,b);if(L)return c("stop: adapter publication invalid",L),{ok:!1,exit:w.INVALID,run:q,message:L,durationMs:f,timedOut:!1};const V=new Set(b.map(u=>u.invocationId??`${u.adapter}:${u.sha256}`));for(const u of n.adapterInvocations??[]){const h=u.invocationId??`${u.adapter}:${u.sha256}`;V.has(h)&&(u.publication="published",u.archiveRunId=q.id)}for(const u of Object.values(n.deepSubphases??{}))!u?.invocationId||!V.has(u.invocationId)||(u.status="published",u.publishedAt=new Date().toISOString(),u.archiveRunId=q.id);n.pendingAdapterInvocations=(n.pendingAdapterInvocations??[]).filter(u=>!V.has(u.invocationId??`${u.adapter}:${u.sha256}`)),n.pendingLinkAdapters=[...new Set(n.pendingAdapterInvocations.filter(u=>u.status==="measured").map(u=>u.adapter))],n.linkedAdapters=[...new Set([...n.linkedAdapters??[],...v])],c("adapter evidence linked",`${v.join(", ")} validated and published in archived run ${q.id}`)}return q&&n.runs.push(q.id),n.base||c("static-only marathon","no --base was given; the baseline measured static findings only"),{ok:!0,exit:I.code,run:q,durationMs:f,timedOut:!1}}function Un(e,t,n,a){e.push({name:t,reason:n,command:a??null})}const Z=e=>"sha256:"+qe("sha256").update(Y(e)).digest("hex"),Xn=new Set(["crud","experiments","coherence-runtime"]);function Yn(e,t,{at:n=new Date().toISOString()}={}){const a=Object.entries(e.deepSubphases??{}).find(([,i])=>i?.status==="invalid"&&i?.failure?.kind==="interrupted-running-subphase");if(a)return`${a[0]} remains invalid after an interrupted mutation-capable subphase; an explicit fresh marathon is required`;for(const[i,o]of Object.entries(e.deepSubphases??{}))if(!(o?.status!=="running"||!Xn.has(i)))return o.evidenceIdentityDigest!==t?`${i} lifecycle evidence identity does not match the current marathon`:(e.deepSubphases[i]={...o,status:"invalid",endedAt:n,failure:{kind:"interrupted-running-subphase"}},`${i} was interrupted while mutation-capable; it was not repeated`);return null}function Zn(e,t=null){return e?{exit:e.exit,signal:e.signal,timedOut:e.timedOut,termination:e.termination??null}:t}function ze(e,t){return{namespace:"marathon/deep-subphase-result",version:1,name:e,invocationId:t.invocationId,status:t.status,artifactDigest:t.sha256?`sha256:${t.sha256}`:null,exit:t.exit,signal:t.signal??null,timedOut:!!t.timedOut,termination:t.termination??null}}function ae(e,t){if(!e||!t)return!1;try{return Y(e)===Y(t)}catch{return!1}}function Be(e){return!e||!E(e)?null:"sha256:"+qe("sha256").update(ce.readFileSync(e)).digest("hex")}function et(e){const t=H(e).length?K(e,"latest"):null,n=t?$.join(t.dir,"agent-result.json"):null;if(!n||!E(n))return null;const a=W(n,{required:!0,what:"agent-result.json"});return Z(a.dimensions??a)}function Je(e,t,{planDigest:n=et(e)}={}){if(!t.measurementConfig)throw new Error("effective measurement configuration is missing");const a=Oe(e,{skipRules:/(^|\/)(?:\.git|\.verify|node_modules)(?:\/|$)/}),i=[$.join(e,"verify.roles.json"),$.join(e,".verify","roles.json")].find(E)??null;return{marathonRunId:`marathon-${t.startedAt.replace(/[^0-9]/g,"")}`,repoRealPath:ce.realpathSync(e),sourceDigest:`sha256:${a.identity.sourceDigest}`,base:t.base??null,lane:t.effectiveLane??t.lane??"public-runtime",flowWorkers:t.flowWorkers??1,planDigest:n,flowDeclarationDigest:Be($.join(e,"verify.crud.json")),principalDigest:Be(i),configurationDigest:Z(yn(t)),toolProtocol:"marathon-adapter/v1"}}function nt(e,t){t.evidenceIdentity=Je(e,t)}function pe(e){const t=new Set;for(const n of e.adapterInvocations??[])!n?.adapter||n.publication==="superseded"||(n.publication="superseded",t.add(n.adapter));e.pendingAdapterInvocations=[],e.pendingLinkAdapters=[],e.linkedAdapters=(e.linkedAdapters??[]).filter(n=>!t.has(n)),e.evidenceIdentity=null,e.deepEvidence={status:"invalid",counts:{total:0,P0:0,P1:0,P2:0,P3:0}},e.deepSubphases={}}function ye(e,t){if(!t.evidenceIdentity)return null;let n;try{n=Je(e,t,{planDigest:t.evidenceIdentity.planDigest})}catch(a){return pe(t),`adapter evidence identity could not be recomputed: ${a.message}`}return ae(n,t.evidenceIdentity)?null:(pe(t),"the repository evidence identity changed after adapter measurement; prior adapter evidence was superseded and must be remeasured")}function Qe(e,t){try{for(const n of se(t.adapterInvocations))if(!(!n.required||n.status!=="measured")){if(!ae(n.evidenceIdentity,t.evidenceIdentity))throw new Error(`${n.adapter} descriptor evidence identity does not match the marathon`);if(n.publication==="pending")Me(e,n.adapter,n),In(n.adapter,n,ce.readFileSync(n.rawPath));else if(n.publication==="published")Me(e,n.adapter,n,{publication:"published"}),Ce(e,K(e,n.archiveRunId),n);else throw new Error(`${n.adapter} measured descriptor has invalid publication ${JSON.stringify(n.publication)}`)}return null}catch(n){return pe(t),`required adapter evidence failed final validation: ${n.message}`}}async function we({repo:e,state:t,adapter:n,cmd:a,args:i,phaseCall:o}){let d;try{d=$n({repo:e,adapter:n,evidenceIdentity:t.evidenceIdentity,command:`qa ${a} ${ie(i).join(" ")}`})}catch(c){return{result:{code:w.INVALID,signal:null,timedOut:!1},invocation:{adapter:n,phase:n==="experiments"?"experiment":n,command:`qa ${a} ${ie(i).join(" ")}`,startedAt:new Date().toISOString(),endedAt:new Date().toISOString(),exit:w.INVALID,signal:null,timedOut:!1,status:"invalid",publication:"pending",sha256:null,bytes:0,rawPath:null,quarantinePath:null,evidenceIdentity:t.evidenceIdentity,required:!0,reason:`adapter invocation could not start: ${c.message}`,counts:{total:0,P0:0,P1:0,P2:0,P3:0}}}}const s=await o(a,i),p=kn(d,s);return{result:s,...p}}function tt({repo:e,state:t,overrideNonLocal:n=!1}){const a=[e,"--base",t.base,"--mutate","--max-mutations","20"];return t.lane&&a.push("--lane",t.lane),n&&a.push("--i-know-this-is-not-production"),a.push(...We(t.measurementConfig?.extraFlags??[])),a}async function at({repo:e,state:t,overrideNonLocal:n,phaseCall:a,skip:i,decide:o}){const d=`write ${$.join(e,"verify.crud.json")} with every flow "production": false (see references/verify.crud.example.json) and serve on loopback; qa run then runs crud on its own`;if(!t.mutation?.ok)return i("crud",t.mutation?.reason??"mutation not opted in",d),{ok:!0};const{result:s,invocation:p}=await we({repo:e,state:t,adapter:"crud",cmd:["measure","crud"],args:tt({repo:e,state:t,overrideNonLocal:n}),phaseCall:a});if(s.code===w.INVALID||p.status!=="measured"){const c=p.reason??`qa measure crud exited ${s.code}`;return o("stop: crud invalid",c),{ok:!1,message:c,invocation:p}}return{ok:!0,invocation:p}}const Ue=Object.freeze([Object.freeze({name:"latency-baseline-vs-injection",cost:2}),Object.freeze({name:"role-pair",cost:1}),Object.freeze({name:"mutation-vs-no-mutation",cost:2})]);function rt({run:e,agent:t,mutationOk:n}){const a=t?.dimensions?.routePriority;if(!a||typeof a.status!="string")return{ok:!1,reason:"the archived run carries no route-priority dimension (the Rust kernel did not run; install cargo, or pass --queue <path>)"};let i;try{i=ln({routePriority:a,families:[...Ue],inventory:e.inventory??{},metadata:{production:!n}})}catch(c){return{ok:!1,reason:`default queue: ${String(c.message??c)}`}}if(i.status!=="measured")return{ok:!1,reason:`route priority is ${i.status}: ${i.reason}`};const o=Array.isArray(e.sweep?.routes)?e.sweep.routes.reduce((c,g)=>{const v=String(g.route??"");if(!v||v.startsWith("("))return c;const b=c.get(v)??{total:0,measured:0};return b.total+=1,!g.skipped&&!g.redirectedTo&&(b.measured+=1),c.set(v,b),c},new Map):null,d=new Map,s=new Map;for(const c of i.items){const g=o?.get(c.route);if(o&&(!g||g.measured!==g.total)){s.set(c.route,{id:`route:${c.route}`,reason:`baseline did not measure every ordinary cell for this route (${g?.measured??0}/${g?.total??0})`});continue}const v=d.get(c.route);(!v||c.expectedInformation>v.expected_information)&&d.set(c.route,{id:`route:${c.route}`,expected_information:c.expectedInformation,cost:c.familyCost,mutation:c.mutation,production:c.production,explanation:`expectedInformation ${c.expectedInformation} = 1 - confidence, from the Rust route-priority dimension`})}const p=[...d.values()].sort((c,g)=>g.expected_information-c.expected_information||c.id.localeCompare(g.id));return p.length?{ok:!0,queue:{schema_version:1,source:"qa run default queue",run:e.id,accepted:p,rejected:[...s.values()].sort((c,g)=>c.id.localeCompare(g.id))}}:{ok:!1,reason:"route priority measured zero experimentally eligible routes"}}async function it({repo:e,state:t,remaining:n,phaseCall:a,skip:i,decide:o}){const d=$.join(e,".verify","autonomous","experiment-queue.json");if(!t.base)return i("experiments","no --base/--serve known -- experiments run targeted sweeps and need a live base",`qa measure experiments ${e} --base <base>`),{ok:!0};const s=H(e).length?K(e,"latest"):null,p=E(d)?W(d):null,c=p?.source==="qa run default queue"&&s&&p.run!==s.id;if(!p||c){const m=s?W($.join(s.dir,"agent-result.json")):null,D=s?rt({run:s,agent:m,mutationOk:!!t.mutation?.ok}):{ok:!1,reason:"no archived run to build a queue from"};if(!D.ok)return i("experiments",D.reason,`qa measure experiments ${e} --base <base> --queue <path>`),{ok:!0};he(d,D.queue),o(c?"stale experiment queue regenerated":"experiment queue generated",`${D.queue.accepted.length} candidate route(s) from run ${s.id}'s route priority -> ${d}`)}const g=Math.max(3e4,Math.min(30*6e4,Math.floor(n()/4))),v=[e,"--base",t.base,"--wall-ms",String(g),"--families",Ue.map(m=>m.name).join(",")];t.mutation?.ok&&v.push("--mutate"),v.push("--lane",t.effectiveLane??t.lane??"public-runtime"),v.push(...We(t.measurementConfig?.extraFlags??[]));const{result:b,invocation:A}=await we({repo:e,state:t,adapter:"experiments",cmd:["measure","experiments"],args:v,phaseCall:a});if(b.code===w.INVALID&&!b.timedOut&&!b.signal&&A.rawPath)try{const m=JSON.parse(ce.readFileSync(A.rawPath,"utf8"));if(m?.status==="unmeasured"){const D=m.reason??"experiment executor measured no eligible combination";return i("experiments",D,`qa measure experiments ${e} --base ${t.base}`),o("experiments unmeasured",D),{ok:!0,namedSkip:!0}}}catch{}if(b.code===w.INVALID||A.status!=="measured"){const m=A.reason??`qa measure experiments exited ${b.code}`;return o("stop: experiments invalid",m),{ok:!1,message:m,invocation:A}}return{ok:!0,invocation:A}}const xe=Object.freeze(["verify.shadow-trace.json",$.join(".verify","shadow-trace.json")]);async function st({repo:e,state:t,phaseCall:n,skip:a,decide:i}){const o=`collect a trace with bin/shadow-collector.mjs from real (non-production) traffic and save it as <repo>/${xe[0]}, beside a verify.shadow.json policy (references/verify.shadow.example.json)`,d=xe.map(g=>$.join(e,g)).find(E);if(!d)return a("shadow replay",`no shadow trace at ${xe.join(" or ")}`,o),{ok:!0};if(!t.base)return a("shadow replay","no --base/--serve known -- shadow replay needs an isolated base to replay against",o),{ok:!0};const s=["replay",e,"--trace",d,"--base",t.base,"--isolated"],{result:p,invocation:c}=await we({repo:e,state:t,adapter:"shadow",cmd:["measure","shadow"],args:s,phaseCall:n});if(p.code===w.INVALID||c.status!=="measured"){const g=c.reason??`qa measure shadow replay exited ${p.code}`;return i("stop: shadow replay invalid",g),{ok:!1,message:g,invocation:c}}return{ok:!0,invocation:c}}async function ot({repo:e,state:t,phaseCall:n,skip:a,decide:i}){if(!t.base)return a("invariants","static-only marathon: no runtime run with a sweep.json to mine invariants from",`qa measure invariants mine ${e} (after a runtime qa verify --base run)`),{ok:!0};const o=await n(["measure","invariants"],["mine",e]);if(o.code===w.INVALID){const b=`qa measure invariants mine exited ${o.code}`;return i("stop: invariants mine invalid",b),{ok:!1,message:b}}const s=W($.join(e,".verify","invariants","candidates.json"))?.candidates??[],p=s.length,c=s.filter(b=>b.support>=2&&b.counterexamples===0).length,g={total:p,ready:c,approveCmd:`qa measure invariants review ${e} --approve <id>`},v=await n(["measure","invariants"],["status",e]);if(v.code===w.INVALID){const b=`qa measure invariants status exited ${v.code}`;return i("stop: invariants status invalid",b),{ok:!1,message:b,invariantsSummary:g}}return{ok:!0,invariantsSummary:g}}async function ut({repo:e,skillRoot:t,phaseCall:n,skip:a}){const i=await gn({repo:e,skillRoot:t,phaseCall:n}),o=wn.find(d=>i.reason?.includes(d));return i.status==="unmeasured"&&o?(a("coherence static",`${o}: the repository data layer is outside the static coherence extractor, so this dimension remains explicitly unmeasured`,`qa measure coherence ${e} --json after adding a supported cache/data-layer adapter`),{ok:!0,namedSkip:!0,static:i}):{ok:!0,static:i}}async function dt({repo:e,state:t,overrideNonLocal:n,phaseCall:a,skip:i,decide:o}){const d=hn(e,{mutation:t.mutation});if(!d.ok)return i("coherence",d.reason,`write ${$.join(e,"verify.crud.json")} (schema_version 3, a flow declaring "crosscheck"), ${$.join(e,"verify.coherence.mjs")} and ${$.join(e,"verify.coherence-provenance.mjs")} (see references/verify.crud.example.json and README "qa measure coherence"); qa run then runs runtime coherence on its own`),{ok:!0,runtime:{ok:!1,reason:d.reason}};const s=H(e).length?K(e,"latest"):null,p=s?$.join(s.dir,"agent-result.json"):null,c=await vn({repo:e,state:t,phaseCall:a,overrideNonLocal:n,planPath:p,flows:d.flows});return c.ok?{ok:!0,runtime:c}:(o("stop: coherence runtime invalid",c.reason),{ok:!1,message:c.reason,runtime:c,invocation:c.invocation})}function Xe(e,t,n){e.commandLog.push(...n.commands);for(const o of n.decisions)e.decisions.push({at:new Date().toISOString(),what:o.what,why:o.why});for(const o of n.skips)t.push(o);const a=n.result??{},i=a.invocation??a.runtime?.invocation??null;if(i){e.adapterInvocations=e.adapterInvocations??[];for(const o of e.adapterInvocations)o.adapter===i.adapter&&o.publication==="pending"&&(o.publication="superseded");e.adapterInvocations.push(i),e.pendingAdapterInvocations=(e.pendingAdapterInvocations??[]).filter(o=>o.adapter!==i.adapter),e.pendingAdapterInvocations.push(i)}return n.name==="invariants"&&a.invariantsSummary&&(e.invariantsSummary=a.invariantsSummary),(n.name==="coherence-static"||n.name==="coherence-runtime")&&(e.coherence=e.coherence??{},n.name==="coherence-static"?(e.coherence.static=a.static??e.coherence.static??null,e.coherence.causes=a.static?.causes??e.coherence.causes??null,e.coherence.risk=a.static?.risk??e.coherence.risk??null):e.coherence.runtime=a.runtime??{ok:!1,reason:a.message??"did not run"}),a.ok===!1}function re(e,t,n,a,i){return{name:e,budgetMs:t,async run(){const o=[],d=[],s=[];let p=null;const c=async(A,m,D={})=>{const I=await oe(A,m,{skillRoot:n,...D,timeoutMs:Math.max(1,a()),processGroup:!0});return p={exit:I.code,signal:I.signal??null,timedOut:!!I.timedOut,termination:I.termination??null},o.push(Re("deep",A,m,I.code)),I},g=(A,m)=>d.push({what:A,why:m}),v=(A,m,D)=>s.push({name:A,reason:m,command:D??null});let b;try{b=await i({phaseCall:c,decide:g,skip:v})}catch(A){b={ok:!1,invalid:!0,message:`${e} threw: ${String(A?.message??A)}`}}return{result:b,commands:o,decisions:d,skips:s,processOutcome:p}}}}async function ct({repo:e,skillRoot:t,state:n,overrideNonLocal:a,remaining:i,decide:o}){const d=[],s=["crud","experiments","shadow replay","invariants","coherence"];if(i()<=0){o("deep measurement skipped","deadline reached before deep measurement could start");for(const u of s)Un(d,u,"deadline reached",null);return n.deepSkips=d,{ok:!0}}if(n.adapterInvocations=n.adapterInvocations??[],n.pendingAdapterInvocations=n.pendingAdapterInvocations??[],n.evidenceIdentity){const u=ye(e,n);if(u)o("adapter evidence identity changed",`${u}; restarting every eligible adapter under the current identity`);else{const h=Qe(e,n);h&&o("adapter evidence failed resume validation",`${h}; restarting every eligible adapter under the current identity`)}}if(!n.evidenceIdentity)try{nt(e,n)}catch(u){return{ok:!1,message:`adapter evidence identity could not be frozen: ${u.message}`}}const p=Z(n.evidenceIdentity);n.deepSubphases=n.deepSubphases??{};const c=["coherence-static","invariants","shadow","crud","experiments","coherence-runtime"];for(const u of c){const h=n.deepSubphases[u];if(h&&h.evidenceIdentityDigest!==p)return S(e,n),{ok:!1,message:`${u} lifecycle evidence identity does not match the current marathon`};if(!h){const y=new Date().toISOString();n.deepSubphases[u]={status:"planned",evidenceIdentityDigest:p,plannedAt:y,heartbeatAt:null}}}const g=Yn(n,p);if(g)return S(e,n),{ok:!1,message:g};const v=n.adapterInvocations.length>0,b=new Map(se(n.adapterInvocations).map(u=>[u.adapter,u])),A={shadow:"shadow",crud:"crud",experiments:"experiments","coherence-runtime":"coherence"};for(const[u,h]of Object.entries(n.deepSubphases)){if(!["measured","published"].includes(h.status)||!A[u])continue;const y=b.get(A[u]);if(!y||y.invocationId!==h.invocationId||`sha256:${y.sha256}`!==h.artifactDigest||h.resultDigest!==Z(ze(u,y))||!ae(y.evidenceIdentity,n.evidenceIdentity))return S(e,n),{ok:!1,message:`${u} lifecycle result digest or invocation reference is invalid`}}S(e,n);let m=null;function D(u){const h=new Date().toISOString(),y=n.deepSubphases[u.name],k=u.result??{},P=k.invocation??k.runtime?.invocation??null,r=k.namedSkip===!0&&u.skips.length>0,x=u.commands.length===0&&u.skips.length>0||r,M=u.processOutcome&&(u.processOutcome.timedOut||u.processOutcome.signal||!r&&![w.OK,w.FINDINGS].includes(u.processOutcome.exit)),z=k.ok===!1||P&&P.status!=="measured"||u.name==="coherence-static"&&k.static?.status==="unmeasured"&&!r,_=M||z?"invalid":x?"planned":"measured",O=Zn(P,u.processOutcome??null),T=_==="invalid"?{kind:O?.timedOut?"timeout":O?.signal?"signal":"subphase-invalid",reason:k.message??P?.reason??null}:null;return n.deepSubphases[u.name]={...y,status:_,endedAt:h,heartbeatAt:h,durationMs:y.startedAt?Math.max(0,Date.parse(h)-Date.parse(y.startedAt)):null,resultDigest:x?null:Z(P?ze(u.name,P):k),artifactDigest:P?.sha256?`sha256:${P.sha256}`:null,invocationId:P?.invocationId??null,processOutcome:O,failure:T,...x?{skip:u.skips[0]}:{}},_==="invalid"}const I={stopped:()=>m!==null,heartbeatMs:Number.isFinite(n.deepHeartbeatMs)?n.deepHeartbeatMs:5e3,start(u,h){const y=new Date().toISOString();n.deepSubphases[u]={...n.deepSubphases[u],status:"running",startedAt:y,heartbeatAt:y,endedAt:null,durationMs:null,estimatedBudgetMs:h,failure:null},S(e,n)},heartbeat(u){n.deepSubphases[u]?.status==="running"&&(n.deepSubphases[u].heartbeatAt=new Date().toISOString(),S(e,n))},skip(u,h){d.push({name:u,reason:h,command:null})},applyGroup(u){for(const h of u){const y=Xe(n,d,h),k=D(h);(y||k)&&!m&&(m=h.result?.message??`${h.name} exited invalid`)}S(e,n)},applyOne(u){const h=Xe(n,d,u),y=D(u);(h||y)&&!m&&(m=u.result?.message??`${u.name} exited invalid`),S(e,n)}},f=[{mode:"parallel",phases:[re("coherence-static",5e3,t,i,({phaseCall:u,skip:h})=>ut({repo:e,skillRoot:t,phaseCall:u,skip:h})),re("invariants",1e4,t,i,({phaseCall:u,skip:h,decide:y})=>ot({repo:e,state:n,phaseCall:u,skip:h,decide:y})),re("shadow",1e4,t,i,({phaseCall:u,skip:h,decide:y})=>st({repo:e,state:n,phaseCall:u,skip:h,decide:y}))]},{mode:"serial",phases:[re("crud",3e4,t,i,({phaseCall:u,skip:h,decide:y})=>at({repo:e,state:n,overrideNonLocal:a,phaseCall:u,skip:h,decide:y})),re("experiments",3e4,t,i,({phaseCall:u,skip:h,decide:y})=>it({repo:e,state:n,remaining:i,phaseCall:u,skip:h,decide:y})),re("coherence-runtime",3e4,t,i,({phaseCall:u,skip:h,decide:y})=>dt({repo:e,state:n,overrideNonLocal:a,phaseCall:u,skip:h,decide:y}))]}];if(v){const u={shadow:"shadow",crud:"crud",experiments:"experiments","coherence-runtime":"coherence"};for(const h of f)h.phases=h.phases.filter(y=>{const k=u[y.name];if(!k)return!0;const P=b.get(k);return!(P?.status==="measured"&&ae(P.evidenceIdentity,n.evidenceIdentity))})}for(const u of f)u.phases=u.phases.filter(h=>{const y=n.deepSubphases[h.name];return!A[h.name]||y?.status!=="measured"&&y?.status!=="published"});await xn({groups:f,remaining:i,coordinator:I}),n.deepSkips=v?[...n.deepSkips??[],...d]:d;const q={total:0,P0:0,P1:0,P2:0,P3:0},L=se(n.adapterInvocations),V=L.find(u=>u.required&&u.status!=="measured");!m&&V&&(m=V.reason??`${V.adapter} replacement evidence is unusable`);for(const u of L)if(u.status==="measured")for(const h of Object.keys(q))q[h]+=u.counts?.[h]??0;return n.deepEvidence={status:L.some(u=>u.required&&u.status!=="measured")?"invalid":"measured",counts:q},n.pendingLinkAdapters=[...new Set(n.pendingAdapterInvocations.filter(u=>u.status==="measured"&&ae(u.evidenceIdentity,n.evidenceIdentity)).map(u=>u.adapter))],S(e,n),m?{ok:!1,message:m}:{ok:!0}}async function lt({repo:e,skillRoot:t,state:n,decide:a}){const i=await G(e,t,n,"closing",["dev","validate"],[e]);if(i.code===w.INVALID)return a("stop: validate invalid",`qa dev validate exited ${i.code} -- an artifact violates its own schema; this run's outputs cannot be trusted`),n.closing={validateExit:i.code,atlasExit:null},{ok:!1};const o=await G(e,t,n,"closing",["dev","atlas"],["--strict"]);return o.code===w.FINDINGS&&a("atlas coverage drift",`qa dev atlas --strict exited ${o.code} -- the frontend-verify skill's own detector coverage has drifted from references/atlas.md; this is about the skill, not ${e}, and does not change this run's verdict`),n.closing={validateExit:i.code,atlasExit:o.code},{ok:!0}}async function ft({repo:e,skillRoot:t,state:n,stabilityRuns:a,widthsGiven:i,states:o,dark:d,extraFlags:s,run:p,decide:c}){const g=n.base?Rn(p):[];if(!n.base||!g.length)return c("stability skipped",n.base?"no runtime P0/P1 findings in the baseline":"no --base; static-only marathon"),{ok:!0,ghosts:[]};const v=Vn(g,10),b=[e,"--base",n.base,"--runs",String(a),"--routes",v.join(","),...be({prod:n.prod,widthsGiven:i,states:o,dark:d,extraFlags:s,autonomous:n.measurementConfig.autonomous})],A=await G(e,t,n,"remediation","verify",b);if(A.code===w.INVALID)return c("stop: stability invalid",`qa verify --runs N exited ${A.code}`),{ok:!1};const m=W($.join(e,".verify","stability.json")),D=(m?.needsReproduction??[]).map(f=>f.fid),I=typeof m?.gating=="boolean"?m.gating:A.code===w.FINDINGS;return n.stability=m?.id??null,D.length&&(En(e,D),n.ghosts=[...new Set([...n.ghosts??[],...D])],c("ghosts blocked from the loop",`${D.length} finding(s) reproduced too rarely to gate; needs manual reproduction: ${D.join(", ")}`)),{ok:!0,ghosts:D,gating:I}}async function mt({repo:e,skillRoot:t,state:n,phase:a}){await G(e,t,n,a,["show","ledger"],[e]),await G(e,t,n,a,["show","report"],[e]);const i=H(e).length?K(e,"latest"):null,o=i?.meta?.counts??{},d=(n.loopState?.iterations??[]).filter(b=>b.action==="fixed").length,s=n.loopState?.blocked?.length??0,p=te(i)?1:0,c=(o.P0??0)+(o.P1??0),g=Math.max(0,Math.round((n.deadline-Date.now())/6e4)),v={marathon:!0,phase:a,clean:p,fixed:d,open:c,blocked:s,minutesLeft:g};return nn(on(e),{at:new Date().toISOString(),...v}),n.checkpoints.push(v),S(e,n),v}async function pt(e){const{repo:t,skillRoot:n,state:a,stabilityRuns:i,checkpointMinutes:o,extraFlags:d,widthsGiven:s,states:p,dark:c,lanes:g=4,decide:v,once:b=!1,waitForSignal:A=Ne,initialMeasurementDurationMs:m=null}=e;let D=0;const I=Math.max(1,o*6e4);let f=a.remeasurements?.at(-1)?.durationMs??m;const q=()=>[...d,...a.rungs?.at(-1)?.flags??[]];async function L(u,{laneMode:h=!1}={}){let y=I;for(;;){const k=a.deadline-Date.now();if(k<=0)return{deadline:!0};a.waiting={reason:u,since:new Date().toISOString(),nextCheckpointAt:new Date(Date.now()+Math.min(k,y)).toISOString()},S(t,a);let P;try{P=await A({repo:t,deadline:a.deadline,checkpointMs:y})}catch(B){return{fatal:!0,message:`marathon wait failed: ${B?.message??B}`}}finally{a.waiting=null,S(t,a)}if(!P||P.kind==="deadline")return{deadline:!0};if(h)return{progress:!0,signal:P};if(!(P.kind==="source"||P.kind==="checkpoint"&&!!a.base))continue;const x=a.deadline-Date.now();if(!Fe({remainingMs:x,lastDurationMs:f,checkpointMs:I})){v("periodic measurement deferred",`only ${Math.max(0,Math.round(x/1e3))}s remain; the last observed duration plus safety reserve does not fit`),y=Math.max(1,x);continue}const M=new Date().toISOString(),z=a.measurementConfig?.dark!==!1,_=(U[a.depth??0]?.flags??[]).filter(B=>z||B!=="--dark"),O=await ue({repo:t,skillRoot:n,state:a,phase:"remediation",widthsGiven:s,states:p,dark:c,extraFlags:[...d,..._],resume:!1,decide:v,timeoutMs:Math.max(1,a.deadline-Date.now())});f=O.durationMs;const T={trigger:P.kind,startedAt:M,finishedAt:new Date().toISOString(),durationMs:O.durationMs,status:O.ok?"measured":"unmeasured",exit:O.exit,runId:O.run?.id??null,reason:O.timedOut?"deadline-capped verification did not complete":null};return a.remeasurements=[...a.remeasurements??[],T],S(t,a),O.ok?(v("periodic measurement complete",`${P.kind} triggered fresh qa verify (no --resume), run ${T.runId??"unknown"}, exit ${T.exit}`),{measured:!0,signal:P}):{fatal:!0,message:T.reason??"periodic qa verify exited 2; the attempted checkpoint is unmeasured"}}}async function V(){const u=()=>a.deadline-Date.now(),{rung:h,skipped:y}=Ke({current:a.depth??0,remainingMs:u(),widthsGiven:s,states:p,dark:c,extraFlags:d,autonomous:a.measurementConfig.autonomous,prod:a.prod});if(y.length&&v("redundant depth rungs skipped",y.map(_=>U[_].name).join(", ")),!h)return v("clean at current depth",a.depth?`no deeper measurement fits the remaining time (reached: ${U[a.depth].name})`:"gate clean"),{escalated:!1,stopped:!1,clean:!0};a.depth=h.index,v(`deepening to ${h.name}`,`gate clean at the previous depth with ${Math.round(u()/6e4)} minutes left`);const k=Mn(t),P=a.rungs?.at(-1)??null,{resumeFlag:r,resumeReason:x}=Cn({priorRung:P,head:k});v(r?`--resume requested for rung "${h.name}"`:`--resume not requested for rung "${h.name}"`,x);const M=await ue({repo:t,skillRoot:n,state:a,phase:"remediation",widthsGiven:s,states:p,dark:c,extraFlags:[...d,...h.flags],resume:r,decide:v});if(!M.ok)return{escalated:!1,stopped:!0,clean:!1,message:M.message,measurementInvalid:M.exit===w.INVALID,resumePhase:M.resumePhase};const z=M.run?.sweep?.resume??null;return a.rungs=[...a.rungs??[],{depth:h.index,flags:h.flags,head:k,resume:{requested:r,reused:r?z?.reused??null:null,rejected:r?z?.rejected??null:null,reason:x}}],S(t,a),{escalated:!0,stopped:!1,clean:te(M.run)}}for(;;){D++;const u=H(t).length?K(t,"latest"):null;if(!u||te(u)){if(a.deadline-Date.now()<=0){v("remediation stopped","deadline reached");break}const r=await V();if(r.stopped)return{ok:!1,message:r.message,measurementInvalid:r.measurementInvalid,resumePhase:r.resumePhase};if(!r.escalated){if(b)break;const x=await L(a.base?"clean at maximum affordable depth; waiting for the next runtime checkpoint or source change":"clean static-only result; waiting for a source change");if(x.fatal)return{ok:!1,fatal:!0,message:x.message};if(x.deadline){v("remediation stopped","deadline reached");break}continue}continue}if(a.deadline-Date.now()<=0){v("remediation stopped","deadline reached");break}let y=w.FINDINGS,k=!1;if(a.lanes?.planned){const r=ne(t);if(!r||pn(r)){if(!Fe({remainingMs:a.deadline-Date.now(),lastDurationMs:f,checkpointMs:I})){v("lanes settled; re-baseline deferred","the observed measurement duration plus safety reserve does not fit before the deadline");const M=await L("lanes settled but too little budget remains to re-baseline safely",{laneMode:!0});if(M.fatal)return{ok:!1,fatal:!0,message:M.message};if(M.deadline)break;continue}const x=await ue({repo:t,skillRoot:n,state:a,phase:"remediation",widthsGiven:s,states:p,dark:c,extraFlags:q(),decide:v,timeoutMs:Math.max(1,a.deadline-Date.now())});if(!x.ok)return{ok:!1,message:x.message,measurementInvalid:x.exit===w.INVALID,resumePhase:x.resumePhase};if(f=x.durationMs,a.lanes={planned:!1,batch:null},te(x.run))y=w.OK,k=!0;else continue}}if(!k){const r=await ft({repo:t,skillRoot:n,state:a,stabilityRuns:i,widthsGiven:s,states:p,dark:c,extraFlags:q(),run:u,decide:v});if(!r.ok)return{ok:!1};if(!r.gating&&!a.lanes?.planned)y=w.OK,v("stability cleared remediation gate","no stable or intermittent P0/P1 finding survived repetition; the original transient will not be sent to the fix loop");else{const x=ne(t),M=x?Le(x):null;if(x&&(mn(x).length>0||Object.values(x.classes).some(O=>O.status==="open"))){if((await G(t,n,a,"remediation","fix",["rebase",t])).code===w.INVALID)return{ok:!1,message:"qa fix rebase exited 2"};if(a.lanes={planned:!0,batch:M?x.batches.indexOf(M)+1:a.lanes?.batch??null},v("lanes open",`${le(ne(t))} -- fix the lanes, then run qa run ${t} again`),b)return{ok:!0,handoff:!0};if((await L("external lane workers are integrating changes",{laneMode:!0})).deadline)break;continue}const _=await G(t,n,a,"remediation","fix",["plan",t,"--lanes",String(g)]);if(_.code===w.INVALID)return{ok:!1,message:"qa fix plan exited 2"};if(_.code===w.FINDINGS){const O=ne(t);if(a.lanes={planned:!0,batch:O?O.batches.indexOf(Le(O))+1:1},v("lanes ready",`${O?le(O):"planned"} -- briefs in ${$.join(t,".verify","lanes")}/<class>/brief.md; host agent applies each lane, then run qa run ${t} again`),await mt({repo:t,skillRoot:n,state:a,phase:"remediation"}),b)return{ok:!0,handoff:!0};if((await L("external lane workers are integrating changes",{laneMode:!0})).deadline)break;continue}y=w.FINDINGS}}if(y===w.OK){const r=await V();if(r.stopped)return{ok:!1,message:r.message,measurementInvalid:r.measurementInvalid,resumePhase:r.resumePhase};if(!r.escalated){if(b)break;const x=await L(a.base?"clean at maximum affordable depth; waiting for the next runtime checkpoint or source change":"clean static-only result; waiting for a source change");if(x.fatal)return{ok:!1,fatal:!0,message:x.message};if(x.deadline)break;continue}continue}if(b)break;const P=await L(a.base?"no remediation progress; waiting for a fresh runtime checkpoint or source change":"no remediation progress; waiting for a source change");if(P.fatal)return{ok:!1,fatal:!0,message:P.message};if(P.deadline)break}return{ok:!0}}function ke(e,t){try{if(!H(e).length)return!1;const n=K(e,"latest");if((n.meta.exit??2)===w.INVALID)return!1;const a=n.meta.integrity??null;return a?a.ok!==!1:!0}catch{return!1}}async function ht({repo:e,skillRoot:t,state:n,verdictResult:a,reasons:i=[]}){const{verdict:o}=a;await oe(["show","ledger"],[e],{skillRoot:t}).catch(()=>{});const d=$.join(e,".verify","ledger.md"),s=E(d)?ge(d):"",{total:p,clean:c,bugFids:g,unmeasured:v}=Gn(s),b=(n.loopState?.iterations??[]).filter(f=>f.action==="fixed"&&f.head).map(f=>f.head),A=sn(e).filter(f=>!f.marathon),m=[];m.push(`${o}`),m.push(""),m.push(`# qa run exit report \u2014 ${e}`),m.push(""),m.push(`started ${n.startedAt}, deadline ${new Date(n.deadline).toISOString()}`),i.length&&m.push("",...i.map(f=>`- ${f}`)),m.push("","## routes","",`total ${p} \xB7 clean ${c} \xB7 fixed ${b.length} (commit${b.length===1?"":"s"}: ${b.join(", ")||"none"}) \xB7 open ${g.length} (${g.join(", ")||"none"}) \xB7 unmeasured ${v} \xB7 needs reproduction ${n.ghosts?.length??0} (${(n.ghosts??[]).join(", ")||"none"})`),v&&m.push("",`**${v} route(s) carry no verdict: the runtime evidence failed its own integrity gate, so nothing it observed is a finding about this application.**`),m.push("","## ratchet trajectory","");for(const f of A.slice(-30))m.push(`- ${f.at} total:${f.total} P0:${f.P0} P1:${f.P1} P2:${f.P2} P3:${f.P3}`);m.push("","## phases (command, exit code)","");for(const f of n.commandLog)m.push(`- [${f.exit}] ${f.cmd}`);m.push("","## deep phase cost","");const D=Object.entries(n.deepSubphases??{}).filter(([,f])=>f.startedAt);D.length||m.push("- no deep phase started");for(const[f,q]of D)m.push(`- ${f}: measured ${q.durationMs??"incomplete"}ms; admission estimate ${q.estimatedBudgetMs??"none"}ms; ${q.status}`);m.push("","## what was not measured","");const I=[];n.base||I.push("no --base was given: this marathon measured static findings only"),n.journeys&&!n.journeys.promoted&&E($.join(e,".verify","journeys.draft.mjs"))&&I.push(`journeys: ${n.journeys.reason}`),n.mutation&&!n.mutation.ok&&I.push(`writes (--mutate, crud, promoted journeys): ${n.mutation.reason}`),n.mutation&&!n.lane&&I.push(`identity: measured unauthenticated (public-runtime) -- ${Te(e).reason}`),!E($.join(e,"verify.roles.json"))&&!E($.join(e,".verify","roles.json"))&&I.push("no verify.roles.json: measured under a single default role"),n.kernel&&n.kernel.status!=="measured"&&I.push(`Rust kernel (graph, coherence obligation plan, experiment queue, triage route priority): ${n.kernel.reason}${n.kernel.enable?` -- to enable: ${n.kernel.enable}`:""}`);for(const f of n.deepSkips??[])I.push(`${f.name}: ${f.reason}${f.command?` -- to enable: ${f.command}`:""}`);for(const f of(n.remeasurements??[]).filter(q=>q.status!=="measured"))I.push(`periodic measurement started ${f.startedAt}: ${f.reason??`qa verify exited ${f.exit}`}; prior completed evidence remains available but this checkpoint is INVALID`);if(n.invariantsSummary){const{total:f,ready:q,approveCmd:L}=n.invariantsSummary;I.push(`invariants: ${f} candidate(s) mined (${q} ready for review) -- promotion is a human call: ${L}`)}for(const f of I.length?I:["(none)"])m.push(`- ${f}`);m.push("","## coherence","");for(const f of bn(n))m.push(`- ${f}`);if(m.push("","## adapter evidence linked into the archive",""),n.linkedAdapters?.length?m.push(`- --link-adapters=${n.linkedAdapters.join(",")} was passed on the next \`qa verify\` this marathon issued after deep measurement`):m.push("- none: no deep-measurement adapter (crud/shadow/experiments/coherence) produced validated evidence this marathon"),m.push("","## depth ladder",""),n.rungs?.length)for(const f of n.rungs){const q=U[f.depth]?.name??`rung ${f.depth}`,L=f.resume.requested?`resume requested (reused ${f.resume.reused??0} cell(s), rejected ${f.resume.rejected??0})`:"resume not requested";m.push(`- ${q}: ${L} -- ${f.resume.reason}`)}else m.push("- (no escalation: the gate never went clean with time left to deepen, or deepened once with resume not yet recorded)");if(m.push("","## closing verification",""),n.closing){const{validateExit:f,atlasExit:q}=n.closing;m.push(`- qa dev validate: ${f===w.OK?"OK":"INVALID"} (exit ${f}) -- schemas checked on everything this run wrote`),q==null?m.push("- qa dev atlas --strict: did not run (validate stopped the marathon first)"):m.push(`- qa dev atlas --strict: ${q===w.OK?"OK":"FINDINGS"} (exit ${q})${q===w.FINDINGS?" -- the frontend-verify skill's own detector coverage has drifted from references/atlas.md; this is about the skill, not this repo, and does not change this run's verdict":""}`)}else m.push("- did not run (the marathon stopped before the closing verification phase)");return m.push(""),{md:m.join(`
5
+ `),verdict:o}}async function $e({repo:e,skillRoot:t,state:n,gateExit:a,measured:i,reasons:o=[],keepServing:d,resumePhase:s=null}){const p=ye(e,n),c=p?null:Qe(e,n),g=p??c;g&&(a=w.INVALID,i=!1,s="deep",o=[...o,g],n.decisions.push({at:new Date().toISOString(),what:p?"stop: adapter evidence identity changed":"stop: adapter evidence validation failed",why:g}));const v=jn({measured:i,gateExit:a,remediation:n.remediation??{ran:!0,reason:"complete"},adapterInvocations:n.adapterInvocations??[]});n.terminalVerdict=v,n.phase="report",S(e,n);const{md:b,verdict:A}=await ht({repo:e,skillRoot:t,state:n,verdictResult:v,reasons:o});return Pe($.join(e,".verify","marathon-report.md"),b),await oe(["show","report"],[e],{skillRoot:t}).catch(()=>{}),n.served&&!d&&(await oe(["run","serve"],[e,"--stop"],{skillRoot:t}).catch(()=>{}),n.served=null),n.phase=s??(n.lanes?.planned?"remediation":"done"),n._authCoordinator?.release(),S(e,n),{exit:v.exit,verdict:A}}function Ie(e){const t=(e??[]).indexOf("--lane");return t===-1?null:e[t+1]??null}function gt(e){return!e||typeof e!="object"?null:[...e.args??[],...e.measurementConfig?.extraFlags??[]].some(n=>["--fixer","--fixer-protocol","--fixer-timeout","--measure-only","--commit"].includes(n))?"the saved marathon contains retired fixer or commit flags":["fixer","fixerSource","fixerProtocol","fixerTimeoutSec","commit"].some(n=>Object.hasOwn(e,n))?"the saved marathon contains retired fixer configuration":null}function vt(e,t){if(t._authCoordinator||!["real-integration","mfa-integration"].includes(t.effectiveLane)||!t.base)return;const n=Sn(e).personas,a=Oe(e,{skipRules:/(^|\/)(?:\.git|\.verify|node_modules)(?:\/|$)/}).identity.sourceDigest,i=Dn({lane:t.effectiveLane,targetIdentity:t.base,sourceIdentity:a,mode:"runtime",routes:[],widths:[],policy:Z(n.map(({name:d,expect:s})=>({name:d,expect:s})))}),o=qn({repo:e,runId:`marathon-auth-${String(t.startedAt).replace(/[^0-9]/g,"")}`,signature:i,launcherPath:$.join(e,"verify.auth-launcher.mjs"),base:t.base,personas:n});Object.defineProperty(t,"_authCoordinator",{value:o,enumerable:!1,configurable:!0})}async function Kt({repo:e,skillRoot:t,flags:n,out:a=null}){const i=a?.say??(()=>{}),o=a?.emit??(()=>{}),{serve:d=!1,baseFlag:s=null,hours:p=10,stabilityRuns:c=3,checkpointMinutes:g=45,resume:v=!1,fresh:b=!1,lanes:A=4,dryRun:m=!1,keepServing:D=!1,overrideNonLocal:I=!1,laneFlag:f=null,flowWorkers:q=1,once:L=!1,waitForSignal:V=Ne}=n;if(n.fixer||n.fixerSource||n.fixerProtocol||n.fixerTimeoutSec||n.commit)throw new InvalidError("qa run never launches a fixer or commits source; run with --once and let the host agent apply .verify/next.md");let{widthsGiven:u=!1,states:h=!0,dark:y=!0}=n,k=n.extraFlags??[];const P={widthsGiven:u,states:h,dark:y,extraFlags:ie(k)};if(m){const l=_n({repo:e,serve:d,baseFlag:s,hours:p,stabilityRuns:c,checkpointMinutes:g,keepServing:D});i("",` qa run (--dry-run) ${e}`,"");for(const j of l)i(` ${j}`);return i(""),o({ok:!0,dryRun:!0,repo:e,plan:l}),w.OK}let r;const x=E(fe(e))?Ln(e):null,M=!b&&x&&x.phase!=="done",z=!b&&x?.phase==="deep";if(M){const l=gt(x);if(l){const j=`${l}; start a fresh host-owned run with --fresh, then use --once for each bounded handoff`;return i("",` INVALID exit 2 -- ${j}`),o({ok:!1,exit:w.INVALID,verdict:"INVALID",repo:e,reason:j}),w.INVALID}}const _=f??Ie(k),O=x?.effectiveLane??x?.requestedLane??x?.lane??Ie(x?.args);if(M&&_&&O&&_!==O){const l=`resume --lane ${_} conflicts with persisted lane ${O}`;return i("",` INVALID exit 2 -- ${l}`),o({ok:!1,exit:w.INVALID,verdict:"INVALID",repo:e,reason:l}),w.INVALID}if(M){r=x,r.pid=process.pid,i("",` resuming qa run from phase "${r.phase}" (started ${r.startedAt})`);const l=r.phase==="deep"&&(se(r.adapterInvocations).some(j=>j.required&&j.status!=="measured")||!r.evidenceIdentity&&(r.adapterInvocations?.length??0)>0);(r.lanes?.planned||l)&&(r.deadline=Date.now()+p*36e5,r.decisions.push({at:new Date().toISOString(),what:l?"deadline reset on adapter resume":"deadline reset on lanes resume",why:`${l?"replacing invalid adapter evidence":"resuming into planned lanes"}; a fresh ${p}h budget replaces the original deadline`}),S(e,r))}else r=On({hours:p,extraFlags:k,base:s,laneFlag:f,flowWorkers:q,widthsGiven:u,states:h,dark:y,autonomous:ve(t).status==="measured"}),S(e,r),i("",` qa run ${e} --hours ${p}${d?" --serve":s?` --base ${s}`:" (static-only)"}`);r.flowWorkers=r.flowWorkers??q,r.requestedLane=r.requestedLane??f,r.effectiveLane==null&&R(r.phase)>R("study")&&(r.effectiveLane=r.lane??"public-runtime"),r.adapterInvocations=r.adapterInvocations??[],r.pendingAdapterInvocations=r.pendingAdapterInvocations??[];const T=r.evidenceIdentity||r.adapterInvocations.length||r.pendingAdapterInvocations.length||r.linkedAdapters?.length||r.pendingLinkAdapters?.length,B=M&&(!r.measurementConfig||typeof r.measurementConfig.autonomous!="boolean")&&T;!r.measurementConfig&&!B?r.measurementConfig={...P,extraFlags:r.args??P.extraFlags,autonomous:ve(t).status==="measured"}:typeof r.measurementConfig?.autonomous!="boolean"&&!B&&(r.measurementConfig.autonomous=ve(t).status==="measured");const C=(l,j)=>{r.decisions.push({at:new Date().toISOString(),what:l,why:j}),S(e,r),i(` decision: ${l} -- ${j}`)},X=()=>r.deadline-Date.now(),F=async(l,{resumePhase:j=null}={})=>{const N=await $e({repo:e,skillRoot:t,state:r,gateExit:w.INVALID,measured:!1,reasons:l,keepServing:D,resumePhase:j});return i("",` ${N.verdict} exit ${N.exit}`),o({ok:!1,exit:N.exit,verdict:N.verdict,repo:e}),N.exit};if(B){const l="legacy marathon state has adapter evidence but no effective measurement configuration; resume cannot safely reconstruct the measured scope";return C("stop: effective measurement configuration missing",l),F([l],{resumePhase:"deep"})}if(M){const l=[],j=r.measurementConfig,N=J=>{const Q=J.findIndex(De=>De==="--widths"||De==="--width");return Q<0?null:J[Q+1]??null};u&&N(k)!==N(j.extraFlags)&&l.push("width"),(n.statesGiven||h===!1)&&h!==j.states&&l.push("states"),(n.darkGiven||y===!1)&&y!==j.dark&&l.push("dark"),(n.baseGiven||s!==null)&&s!==r.base&&l.push("base"),(n.laneGiven||f!==null)&&f!==(r.requestedLane??r.effectiveLane)&&l.push("lane"),n.flowWorkersGiven&&q!==r.flowWorkers&&l.push("flow-workers"),k.length&&Y(k)!==Y(j.extraFlags)&&l.push("passthrough flags"),l.length&&C("resume measurement flags ignored",`${[...new Set(l)].join(", ")} conflict with the effective configuration frozen when this marathon started`)}if(r.served&&!Ee(r.served.pid))if(d||r.served.auto){const l=await Ge(e,t,r);if(!l.ok)return C("stop: re-serve failed",l.reason),F([l.reason]);r.base=l.base,r.served={pid:l.pid},S(e,r)}else{const l=`the recorded server (base ${r.base}) is no longer alive and --serve was not given, so it cannot be restarted`;return C("stop: server died",l),F([l])}if(R(r.phase)<=R("serve")){if(r.phase="serve",S(e,r),X()<=0)return C("stop: no time","deadline already passed before the first phase"),F(["deadline already passed before the first phase"]);if(!r.served)if(s)r.base=s,S(e,r);else{const l=await Ge(e,t,r);if(l.ok)r.base=l.base,r.served={pid:l.pid,auto:!d},d||C("served the app",`no --base given; built and started it at ${l.base}`),S(e,r);else{if(d)return C("stop: serve failed",l.reason),F([l.reason]);C("static-only marathon",`no --base given and the app could not be built and served (${l.reason}); pass --base URL to measure a running app`)}}}if(R(r.phase)<=R("preflight")){if(r.phase="preflight",S(e,r),X()<=0)return C("stop: no time","deadline reached before preflight"),F(["deadline reached before preflight"]);const l=await Tn({repo:e,skillRoot:t,state:r,decide:C});if(S(e,r),!l.ok)return F(l.fixLines?.length?l.fixLines:["qa verify --preflight exited 2"])}if(R(r.phase)<=R("study")){if(r.phase="study",S(e,r),X()<=0)return C("stop: no time","deadline reached before study"),F(["deadline reached before study"]);const l=k.indexOf("--lane"),j=await zn({repo:e,skillRoot:t,state:r,overrideNonLocal:I,explicitLane:l===-1?null:k[l+1],decide:C});if(S(e,r),!j.ok)return F(["qa init --study or qa init could not run"])}({widthsGiven:u,states:h,dark:y}=r.measurementConfig),k=[...r.measurementConfig.extraFlags];const je=k.indexOf("--lane");je!==-1&&r.effectiveLane&&(k[je+1]=r.effectiveLane);for(let l=0;l<(r.autoFlags??[]).length;l++){const j=r.autoFlags[l];if(j.startsWith("--")){if(k.includes(j)){j==="--lane"&&l++;continue}k=j==="--lane"?[...k,j,r.autoFlags[++l]]:[...k,j]}}try{vt(e,r)}catch(l){const j=`auth coordinator could not start: ${l?.message??l}`;return C("stop: auth coordinator invalid",j),F([j])}let de=null,Se=null;if(R(r.phase)<=R("baseline")){if(r.phase="baseline",S(e,r),X()<=0)return C("stop: no time","deadline reached before baseline"),F(["deadline reached before baseline"]);const l=await ue({repo:e,skillRoot:t,state:r,phase:"baseline",widthsGiven:u,states:h,dark:y,extraFlags:k,decide:C});if(S(e,r),!l.ok)return F(["qa verify (baseline) exited 2"]);de=l.run,Se=l.durationMs}if(R(r.phase)<=R("deep")){r.phase="deep",S(e,r);const l=await ct({repo:e,skillRoot:t,state:r,overrideNonLocal:I,remaining:X,decide:C});if(S(e,r),!l.ok){l.message&&C("stop: deep lifecycle invalid",l.message);const j=se(r.adapterInvocations).some(N=>N.required&&N.status!=="measured");return F([l.message??"a deep-measurement phase (crud, experiments, shadow replay, or invariants) exited 2"],j?{resumePhase:"deep"}:{})}if(r.pendingLinkAdapters.length&&(z||te(de))){const j=await ue({repo:e,skillRoot:t,state:r,phase:"remediation",widthsGiven:u,states:h,dark:y,extraFlags:[...k,...r.rungs?.at(-1)?.flags??[]],decide:C});if(S(e,r),!j.ok)return F([j.message??"required adapter evidence could not be validated and published"],{resumePhase:j.resumePhase??"deep"});de=j.run}}if(R(r.phase)<=R("remediation")){r.phase="remediation",S(e,r);const l=de??(H(e).length?K(e,"latest"):null),j=!!Ke({current:r.depth??0,remainingMs:X(),widthsGiven:u,states:h,dark:y,extraFlags:k,autonomous:r.measurementConfig.autonomous,prod:r.prod}).rung;if(L&&te(l)&&!j)C("remediation skipped","the baseline gate is already clean and no deeper measurement fits the remaining time");else if(X()<=0)C("remediation skipped","deadline reached before remediation could start");else{const N=await pt({repo:e,skillRoot:t,state:r,stabilityRuns:c,checkpointMinutes:g,extraFlags:k,widthsGiven:u,states:h,dark:y,lanes:A,decide:C,once:L,waitForSignal:V,initialMeasurementDurationMs:Se});if(S(e,r),N.handoff){const J=ne(e),Q=await $e({repo:e,skillRoot:t,state:r,gateExit:w.FINDINGS,measured:ke(e,r),reasons:[`${J?le(J):"lanes planned"} -- ${r.lanes.batch?`batch ${r.lanes.batch} `:""}lanes ready: briefs in .verify/lanes/<class>/brief.md (the host agent applies each change, then runs qa fix gate and qa fix close), then run qa run ${e} again`],keepServing:!0});return i("",` ${Q.verdict} exit ${Q.exit} -- lanes ready; run qa run ${e} again when the lanes are closed`),o({ok:!1,exit:Q.exit,verdict:Q.verdict,repo:e,lanes:r.lanes}),Q.exit}if(!N.ok){if(N.measurementInvalid)return F([N.message??"required adapter evidence could not be validated and published"],{resumePhase:N.resumePhase??"remediation"});if(N.fatal)return F([N.message??"periodic measurement did not complete; that checkpoint remains unmeasured"]);const J=ke(e,r);if(r.remediation={ran:!1,reason:J?"precondition":"invalid",detail:N.message??"a remediation phase (stability or loop) exited 2"},S(e,r),!J)return F([r.remediation.detail]);C("remediation did not run",`${r.remediation.detail} -- the measurement stands; only the fix loop never ran`)}}}if(r.pendingAdapterInvocations.some(l=>l.publication==="pending")){const l=[...new Set(r.pendingAdapterInvocations.map(j=>j.adapter))];return F([`required adapter evidence is still pending publication: ${l.join(", ")}`],{resumePhase:"remediation"})}if(R(r.phase)<=R("closing")){r.phase="closing",S(e,r);const l=await lt({repo:e,skillRoot:t,state:r,decide:C});if(S(e,r),!l.ok)return F(["qa dev validate exited 2 -- the run's own artifacts do not match their schema"])}const Ae=H(e).length?K(e,"latest"):null,Ye=Ae?_e(Ae):w.INVALID,ee=await $e({repo:e,skillRoot:t,state:r,gateExit:Ye,measured:ke(e,r),keepServing:D});return i("",` ${ee.verdict} exit ${ee.exit}`,` -> ${$.join(e,".verify","marathon-report.md")}`,` -> ${$.join(e,".verify","report.html")}`,""),o({ok:ee.exit===w.OK,exit:ee.exit,verdict:ee.verdict,repo:e,runs:r.runs,ghosts:r.ghosts,checkpoints:r.checkpoints}),ee.exit}export{Pn as PHASES,xe as SHADOW_TRACE_PATHS,rt as buildExperimentQueue,_n as buildPlan,Re as commandLogEntry,tt as crudPhaseArgs,Zn as deepProcessOutcome,Ve as fixLinesFromDoctor,Ht as formatStatus,On as freshState,Rn as gatingRuntimeFindings,We as identityFlags,Bn as kernelDecision,Te as laneOptIn,Ln as loadState,Wn as mutationOptIn,Ke as nextEffectiveDepth,Yn as recoverInterruptedDeepSubphases,Cn as resumeDecisionForRung,Vn as routesOf,Kt as runMarathon,Fn as serverTypeFromDoctor,fe as statePath,Wt as statusOf,Gn as summarizeLedger};
@@ -0,0 +1 @@
1
+ import p from"node:fs";import $ from"node:path";import*as f from"./atlas.mjs";import{buildCoverage as y,readProducerSources as S}from"./atlas-coverage.mjs";const b=Object.freeze(["static","runtime"]);function g(s,t){const n=s.split("+");return t==="static"?n.includes("S"):n.includes("R")}function L({skillRoot:s,mode:t}){if(!b.includes(t))throw new Error(`unknown mode ${JSON.stringify(t)}; expected one of ${b.join(", ")}`);const n=(...e)=>p.readFileSync($.join(s,...e),"utf8"),h=y({atlasMd:n("references","atlas.md"),classifySrc:n("bin","classify.mjs"),producerSources:S(s),kindAtlas:f.KIND_ATLAS_V2,alsoCovers:f.ALSO_COVERS_V2,atlasIdForFn:e=>f.atlasIdFor({...e,atlasVersion:2})}),c={};let r=0,a=0;for(const e of h.layers){const o={reachable:0,total:0};for(const u of e.rows)u.status==="implemented"&&(o.total++,g(u.det,t)&&o.reachable++);o.total>0&&(c[e.id]=o),r+=o.reachable,a+=o.total}const i=a-r,l=Object.entries(c).filter(([,e])=>e.reachable===0).map(([e])=>e),d=a>0?Math.round(r/a*100):null,m=t==="static"?`${r} of ${a} detector classes reachable in static mode (${d}%); ${i} need a running app -- pass --base URL to reach them`+(l.length?`. No static detector at all for: ${l.join(", ")}`:""):`${r} of ${a} detector classes reachable in runtime mode (${d}%); ${i} are static-only and ran in the static phase`;return{mode:t,reachable:r,unreachable:i,total:a,pct:d,byLayer:c,blindLayers:l,line:m}}export{L as modeCoverage};
@@ -0,0 +1 @@
1
+ import m from"node:fs";import h from"node:path";import{validateEntityAliases as b}from"./coherence/entity-aliases.mjs";const w=/prod|production/i,x=/^https?:\/\/(127\.0\.0\.1|\[::1\]|localhost|[\w.-]+\.localhost)(:\d+)?(\/|$|\?)/i,y=Object.freeze(["POST","PUT","PATCH","DELETE"]),A=new Set(["public-runtime","real-integration","mfa-integration"]);function f(e,r){if(typeof e!="string"||!e.startsWith("/")||e.startsWith("//")||e.includes("\\"))return`${r} must be a same-origin absolute path`;const a=e.split(/[?#]/,1)[0];for(const o of a.split("/")){let t=o;for(;;){let n;try{n=decodeURIComponent(t)}catch{return`${r} contains invalid path encoding`}if(n==="."||n==="..")return`${r} contains a forbidden dot segment`;if(/[\\/]/.test(n))return`${r} contains an encoded path separator`;if(n===t)break;t=n}}return null}function _(e,{overrideNonLocal:r=!1}={}){return e?w.test(e)?`--base "${e}" matches /prod|production/i -- refusing to mutate what looks like a production target`:x.test(e)||r?null:`--base "${e}" is not loopback (127.0.0.1 / ::1 / localhost) -- refusing to mutate a non-local target. A hostname not containing "prod" is not proof it is safe; pass --i-know-this-is-not-production to mutate a deliberate non-local target (a dev tunnel, a LAN/docker host, a deployed preview) anyway.`:"--base URL is required"}function k(e){if(!e||typeof e!="object"||Array.isArray(e))return{ok:!1,reason:"verify.crud.json is not a JSON object"};if(!Array.isArray(e.flows)||e.flows.length===0)return{ok:!1,reason:'verify.crud.json has no "flows" array, or it is empty'};const r=new Set;for(let o=0;o<e.flows.length;o++){const t=e.flows[o];if(!t||typeof t!="object"||Array.isArray(t))return{ok:!1,reason:`flows[${o}] is not an object`};if(typeof t.name!="string"||!t.name)return{ok:!1,reason:`flows[${o}] is missing a string "name"`};if(r.has(t.name))return{ok:!1,reason:`flow name "${t.name}" is declared more than once`};r.add(t.name);for(const n of["personas","denied"])if(t[n]!==void 0&&(!Array.isArray(t[n])||t[n].some(s=>typeof s!="string"||!s.trim())))return{ok:!1,reason:`flow "${t.name}" ${n} must be an array of persona names`};if(t.production!==!1)return{ok:!1,reason:`flow "${t.name}" does not declare "production": false -- refusing to mutate a flow that is not explicitly marked non-production`};for(const n of["route","declared_endpoint","cleanup_endpoint"]){if(t[n]===void 0)continue;const s=f(t[n],`flow "${t.name}" ${n}`);if(s)return{ok:!1,reason:s}}}if(e.beacon_paths!==void 0&&(!Array.isArray(e.beacon_paths)||e.beacon_paths.some(o=>typeof o!="string"||!o.trim())))return{ok:!1,reason:'"beacon_paths" must be an array of non-empty path strings'};if(e.idp_bootstrap!==void 0){if(!Array.isArray(e.idp_bootstrap))return{ok:!1,reason:'"idp_bootstrap" must be an array'};for(const o of e.idp_bootstrap){if(!o||typeof o!="object"||Array.isArray(o)||Object.keys(o).sort().join(",")!=="origin,path")return{ok:!1,reason:"each idp_bootstrap entry must contain only literal origin and path"};let t;try{t=new URL(o.origin)}catch{return{ok:!1,reason:"idp_bootstrap origin must be an absolute URL origin"}}if(t.origin!==o.origin||t.username||t.password||t.protocol!=="https:"&&!(t.protocol==="http:"&&["127.0.0.1","localhost","[::1]"].includes(t.hostname)))return{ok:!1,reason:"idp_bootstrap origin must be HTTPS (or loopback HTTP for an isolated fixture)"};if(f(o.path,"idp_bootstrap path")||/[?*#{}]/.test(o.path))return{ok:!1,reason:"idp_bootstrap path must be one literal safe path"}}}const a=b(e);return a.ok?{ok:!0,declaration:e}:a}function E(e,r){const a=e?.beacon_paths;return!Array.isArray(a)||a.length===0?!1:a.some(o=>u(o,r))}function q(e,{url:r,method:a,headers:o={}}={}){if(String(a).toUpperCase()!=="POST")return!1;let t;try{t=new URL(r)}catch{return!1}const n=new Set(["authorization","proxy-authorization","cookie","x-api-key"]);return Object.keys(o).some(s=>n.has(s.toLowerCase()))?!1:(e?.idp_bootstrap??[]).some(s=>s.origin===t.origin&&s.path===t.pathname)}function R(e){const r=h.join(h.resolve(e),"verify.crud.json");if(!m.existsSync(r))return{ok:!1,path:r,reason:`no verify.crud.json at ${r} -- see references/verify.crud.example.json for the shape`};try{const a=m.readFileSync(r),o=JSON.parse(a.toString("utf8"));return{...k(o),path:r,raw:a}}catch{return{ok:!1,path:r,reason:"verify.crud.json is not valid JSON"}}}function u(e,r,a=!1){if(typeof e!="string"||!e.trim())return!1;const o=String(e??"").split("?")[0].split("/").filter(Boolean),t=String(r??"").split("?")[0].split("/").filter(Boolean),n=s=>/^\{[^}]+\}$|^:[^/]+$|^\$[^/]+$/.test(s);return a&&t.length===o.length-1&&n(o.at(-1))?o.slice(0,-1).every((s,i)=>n(s)||s===t[i]):t.length<o.length?!1:o.every((s,i)=>n(s)||s===t[i])}function v(e,{flowName:r=null,route:a=null,endpoint:o=null,journey:t=null}={}){return!e||!Array.isArray(e.flows)?[]:e.flows.filter(n=>!(r!==null&&n.name!==r||a!==null&&n.route!==a||t!==null&&n.journey!==t||o!==null&&!u(n.declared_endpoint,o)))}function L(e){if(!(e?.mutates===!0))return{mutates:!1,flow:null};if(typeof e.flow!="string"||!e.flow.trim())throw new TypeError(`mutating journey "${e?.name??"unnamed"}" must name a declared flow`);return{mutates:!0,flow:e.flow}}function M(e={}){if(!e.mutate)return{ok:!1,reason:"refuses without --mutate: mutation requires the explicit --mutate opt-in"};const r=k(e.declaration);if(!r.ok)return{ok:!1,reason:e.declarationReason??r.reason};const a=_(e.base,{overrideNonLocal:!!e.overrideNonLocal});if(a)return{ok:!1,reason:a};const o=e.lane??"public-runtime";if(!A.has(o))return{ok:!1,reason:`lane "${o}" cannot authorize a real mutation`};if(!Number.isSafeInteger(e.maxMutations)||e.maxMutations<=0)return{ok:!1,reason:"--max-mutations must be a positive integer"};if(typeof e.fixtureNamespace!="string"||!e.fixtureNamespace.trim())return{ok:!1,reason:"--fixture-namespace must be a non-empty isolated fixture namespace"};const t=v(r.declaration,e);if(!t.length)return{ok:!1,reason:"no declared mutation flow matches this request scope"};if(t.some(s=>s.production!==!1))return{ok:!1,reason:'every selected flow must literally declare "production": false'};const n=t.some(s=>s.cleanup_required!==!1);return n&&!e.cleanupCapable?{ok:!1,reason:"selected flow requires declared cleanup capability"}:{ok:!0,reason:null,lane:o,flows:t,maxMutations:e.maxMutations,used:0,cleanup:{required:n,allowed:n&&!!e.cleanupCapable}}}function c({pathname:e,url:r,base:a}){if(r!==void 0)try{const t=new URL(a),n=new URL(r,t);if(n.origin!==t.origin)return{ok:!1,reason:"write request must stay on the declared base origin"};e=n.pathname}catch{return{ok:!1,reason:"write request URL is invalid"}}const o=f(e,"write request path");return o?{ok:!1,reason:o}:{ok:!0,pathname:e.split(/[?#]/,1)[0]}}function g(e,r){return(e.flows??[]).filter(a=>r==null||a.name===r)}function j(e,{method:r,pathname:a,url:o,base:t,flowName:n}={}){const s=String(r??"GET").toUpperCase();if(!y.includes(s))return{ok:!0};if(!e?.ok)return{ok:!1,reason:"mutation policy did not authorize this request"};if(e.used>=e.maxMutations)return{ok:!1,reason:"mutation budget exhausted"};const i=c({pathname:a,url:o,base:t});return i.ok?g(e,n).some(l=>u(l.declared_endpoint,i.pathname,s==="POST"))?(e.used++,{ok:!0}):{ok:!1,reason:"write request path is not declared for this mutation flow"}:i}function U(e,{method:r,pathname:a,url:o,base:t,flowName:n,cleanupPath:s}={}){const i=String(r??"GET").toUpperCase();if(!y.includes(i))return{ok:!0};if(!e?.ok||!e.cleanup?.allowed)return{ok:!1,reason:"mutation policy did not reserve cleanup for this journey"};if(i!=="DELETE")return{ok:!1,reason:"cleanup reservation permits only DELETE"};const l=c({pathname:a,url:o,base:t});if(!l.ok)return l;const d=c({pathname:s});return!d.ok||l.pathname!==d.pathname?{ok:!1,reason:"cleanup request does not match the exact reserved path"}:g(e,n).some(p=>u(p.declared_endpoint,l.pathname)||u(p.cleanup_endpoint,l.pathname))?{ok:!0}:{ok:!1,reason:"cleanup request path is not declared for this mutation flow"}}export{x as LOOPBACK_BASE_RE,y as MUTATING_METHODS,w as PROD_BASE_RE,U as cleanupRequestAllowed,u as endpointCovers,M as evaluateMutationPolicy,q as idpBootstrapAllowed,E as isBeaconPath,L as journeyMutationMetadata,R as loadMutationDeclaration,j as requestAllowed,v as selectMutationFlows,_ as unsafeBaseReason,k as validateMutationDeclaration};
@@ -0,0 +1,3 @@
1
+ import c from"node:path";import u from"node:os";import{readJson as p,writeJson as d}from"./fs.mjs";function a(){if(process.env.QA_HOME)return c.join(process.env.QA_HOME,"pattern-ledger.json");const e=process.env.XDG_CONFIG_HOME||c.join(u.homedir(),".config");return c.join(e,"qa","pattern-ledger.json")}function h(e=a()){const n=p(e);return Array.isArray(n?.entries)?n.entries.filter(t=>t&&t.id&&t.kind):[]}function g(e,n=a()){d(n,{schema_version:1,updatedAt:new Date().toISOString(),entries:e})}function y(){const e=Number(process.env.QA_PATTERN_GUARD_THRESHOLD);return Number.isInteger(e)&&e>0?e:3}function m(e){const n=[],t=[],r=[];for(const o of String(e??"").split(`
2
+ `))if(o.startsWith("diff --git ")){const s=/^diff --git a\/(.+) b\/(.+)$/.exec(o);s&&n.push(s[2])}else o.startsWith("+++")||o.startsWith("---")||(o.startsWith("+")?t.push(o.slice(1)):o.startsWith("-")&&r.push(o.slice(1)));return{files:n,added:t,removed:r}}const S=new Set(["if","for","while","switch","catch","function","return","typeof","new","super","constructor","else"]);function x(e){const n=new Map;for(const t of e)for(const r of t.matchAll(/([A-Za-z_$][\w$]*)\s*\(/g))S.has(r[1])||n.set(r[1],(n.get(r[1])??0)+1);return[...n.keys()].sort().slice(0,5)}function A(e){return e.replace(/`[^`]*`|"[^"]*"|'[^']*'/g,'"\u2026"').slice(0,100)}function $({calls:e,ext:n,addedCount:t,removedCount:r}){const o=r?`, ${r} removed`:"";return e.length?`Added call(s) ${e.join(", ")} (${t} line(s) added${o}) in a ${n} file.`:`Small edit (${t} line(s) added${o}) in a ${n} file; no recognizable call added.`}function w(e){const{files:n,added:t,removed:r}=m(e);if(!t.length&&!r.length)return null;const o=n.length&&c.extname(n[0])||"(no ext)",s=x(t);return{ext:o,calls:s,shapeKey:`${o}:${s.join(",")||"noop"}`,description:$({calls:s,ext:o,addedCount:t.length,removedCount:r.length}),snippet:t.slice(0,6).map(A).join(`
3
+ `)}}function O(e,{kind:n,diff:t,repo:r}){if(!n)return null;const o=w(t);if(!o)return null;const s=`${n}|${o.shapeKey}`,l=new Date().toISOString();let i=e.find(f=>f.id===s);return i||(i={id:s,kind:n,...o,count:0,repos:[],firstSeenAt:l},e.push(i)),i.count++,i.lastSeenAt=l,r&&(i.repos=[...new Set([...i.repos,c.basename(r)])]),i}function D({kind:e,diff:n,repo:t},r=a()){const o=h(r),s=O(o,{kind:e,diff:n,repo:t});return s&&g(o,r),s}function b(e,n){return e.filter(t=>t.kind===n).sort((t,r)=>r.repos.length-t.repos.length||r.count-t.count||String(r.lastSeenAt).localeCompare(String(t.lastSeenAt)))}export{x as extractCalls,y as guardThreshold,h as loadPatterns,b as matchesForKind,a as patternLedgerPath,O as recordFix,D as rememberFix,g as savePatterns,w as shapeOf};
@@ -0,0 +1 @@
1
+ import r from"node:fs";import c from"node:path";import{createHash as h}from"node:crypto";import{runsDir as a}from"./runs.mjs";const d=".pending-",l=".pid";function F(i,n){const o=c.join(a(i),n),e=c.join(a(i),d+n);r.mkdirSync(a(i),{recursive:!0}),r.rmSync(e,{recursive:!0,force:!0}),r.mkdirSync(e,{recursive:!0,mode:448}),r.chmodSync(e,448),r.writeFileSync(c.join(e,l),String(process.pid));let t=!1;return{id:n,dir:e,publish(){if(r.existsSync(o))throw new Error(`run ${n} already exists at ${o}`);return r.renameSync(e,o),t=!0,o},discard(){t||(r.rmSync(e,{recursive:!0,force:!0}),t=!0)}}}function y(i){if(!i||!Number.isInteger(i))return!1;try{return process.kill(i,0),!0}catch(n){return n&&n.code==="EPERM"}}function v(i,{maxAgeMs:n=14400*1e3,now:o=Date.now()}={}){const e=a(i);let t;try{t=r.readdirSync(e,{withFileTypes:!0})}catch{return[]}const s=[];for(const u of t){if(!u.isDirectory()||!u.name.startsWith(d))continue;const f=c.join(e,u.name);let m;try{m=r.statSync(f)}catch{continue}if(o-m.mtimeMs<n)continue;let p=null;try{p=parseInt(r.readFileSync(c.join(f,l),"utf8").trim(),10)}catch{}y(p)||(r.rmSync(f,{recursive:!0,force:!0}),s.push(u.name))}return s}function D(i,n){const o=[];for(const[e,t]of Object.entries(n))t!=null&&o.push(S(i,e,r.readFileSync(t)));return o.sort((e,t)=>e.name<t.name?-1:e.name>t.name?1:0)}function S(i,n,o){const e=Buffer.isBuffer(o)?o:Buffer.from(String(o)),t=c.join(i,n+".json"),s=t+".tmp";return r.writeFileSync(s,e,{mode:384}),r.renameSync(s,t),{name:n,sha256:h("sha256").update(e).digest("hex"),bytes:e.length,path:t}}export{d as PENDING_PREFIX,l as PID_FILE,v as collectOrphanedPending,F as openPending,S as snapshotInput,D as snapshotInputs};
@@ -0,0 +1,4 @@
1
+ import{spawn as _,spawnSync as x}from"node:child_process";const B=25;function C(r){if(process.platform==="win32"||!r)return[];const n=x("ps",["-A","-o","pid=,ppid="],{encoding:"utf8"});if(n.status!==0)return[];const i=new Map;for(const e of n.stdout.split(`
2
+ `)){const[p,f]=e.trim().split(/\s+/).map(Number);!Number.isInteger(p)||!Number.isInteger(f)||(i.has(f)||i.set(f,[]),i.get(f).push(p))}const l=[],c=e=>{for(const p of i.get(e)??[])c(p);e!==r&&l.push(e)};return c(r),l}function q(r,n,{cwd:i,env:l,replaceEnv:c=!1,timeoutMs:e=0,termGraceMs:p=1e3,processGroup:f=!0,stdout:T="inherit",stderr:y="inherit",input:v,fd3:G}={}){return new Promise(F=>{const D=[v==null?"ignore":"pipe",T==="capture"?"pipe":T,y==="capture"?"pipe":y];G!=null&&D.push("pipe");const H=c?{...l??{}}:{...process.env,...l??{}},h=f&&process.platform!=="win32",s=_(r,n,{cwd:i,env:H,stdio:D,detached:h});if(G!=null){const t=s.stdio[3];t.on("error",()=>{}),t.end(G)}let L="",A="";T==="capture"&&s.stdout.on("data",t=>{L+=t}),y==="capture"&&s.stderr.on("data",t=>{A+=t}),v!=null&&s.stdin.end(v);let I=!1,E=null,u=null,R=null,a=null,g=!1,d=null,b=!1,M=null;const N=new Set,m=t=>{if(h&&s.pid)try{for(const o of C(s.pid))N.add(o);for(const o of N)try{process.kill(o,t)}catch{}return process.kill(-s.pid,t),"group"}catch{}else if(process.platform==="win32"&&s.pid)try{return _("taskkill",["/PID",String(s.pid),"/T",...t==="SIGKILL"?["/F"]:[]],{stdio:"ignore"}).on("error",()=>{}),"tree"}catch{}try{s.kill(t)}catch{}return"child"},O=()=>{if(!h||!s.pid)return!1;try{return process.kill(-s.pid,0),!0}catch{return!1}};e>0&&(E=setTimeout(()=>{I=!0,a={kind:"term",scope:m("SIGTERM"),termAt:new Date().toISOString(),killAt:null},u=setTimeout(()=>{g||(b=!0,(O()||!d)&&(a.kind="kill",a.killAt=new Date().toISOString(),a.scope=m("SIGKILL")),d&&k(d))},p)},e));const S=t=>{M??=t,m(t),u||(u=setTimeout(()=>m("SIGKILL"),1e3),u.unref())};process.on("SIGINT",S),process.on("SIGTERM",S);const k=t=>{if(g)return;g=!0;const o=M;if(o&&m("SIGKILL"),E&&clearTimeout(E),u&&clearTimeout(u),R&&clearTimeout(R),process.off("SIGINT",S),process.off("SIGTERM",S),o){try{process.kill(process.pid,o)}catch{process.exit(2)}return}F(a?{...t,termination:a}:t)};s.on("error",t=>{k({code:2,signal:null,error:t,stdout:L,stderr:A,timedOut:I})}),s.on("close",(t,o)=>{const K={code:t??2,signal:o,stdout:L,stderr:A,timedOut:I};if(!(I&&h&&u&&!b)){k(K);return}d=K;const P=()=>{if(!(g||b)){if(O()){R=setTimeout(P,B);return}k(d)}};P()})})}function U(r,n,{cwd:i,env:l,timeoutMs:c=3e4}={}){const e=x(r,n,{cwd:i,env:{...process.env,...l??{}},encoding:"utf8",timeout:c});return{code:e.status==null?2:e.status,stdout:e.stdout??"",stderr:e.stderr??"",error:e.error??null}}function z(r){const n=x(process.platform==="win32"?"where":"which",[r],{encoding:"utf8"});return n.status===0?n.stdout.trim().split(`
3
+ `)[0]:null}function w(r,n,i={}){return U("git",["-C",r,...n],{timeoutMs:6e4,...i})}function J(r){const n=w(r,["rev-parse","--is-inside-work-tree"]);if(n.code!==0||n.stdout.trim()!=="true")return{isRepo:!1};const i=w(r,["rev-parse","HEAD"]).stdout.trim(),l=w(r,["rev-parse","--abbrev-ref","HEAD"]).stdout.trim(),e=w(r,["status","--porcelain"]).stdout.split(`
4
+ `).filter(Boolean);return{isRepo:!0,head:i,branch:l,dirty:e.length,dirtyFiles:e.slice(0,10)}}export{w as git,J as gitInfo,q as run,U as runSync,z as which};
@@ -0,0 +1 @@
1
+ const s=e=>String(e??"").toLowerCase().replace(/[-_./]/g,"").replace(/s$/,"");function f(e,l){if(e.file&&Number.isInteger(e.line))return{file:e.file,line:e.line,hook:e.hook??null,endpoint:e.endpoint??null,entity:e.at??null};const n=(l.syncRisks??[]).filter(t=>t.route===e.subject&&t.endpoint&&String(e.detail??"").includes(t.endpoint));if(n.length!==1)return null;const[i,r]=String(n[0].mutation??"").split(":"),o=Number(r);return!i||!Number.isInteger(o)?null:{file:i,line:o,hook:n[0].hook??null,endpoint:n[0].endpoint??null,entity:n[0].entity??null}}function a(e,l){return(e.routes??[]).filter(n=>(n.mutations??[]).some(i=>i.file===l.file&&i.line===l.line)).map(n=>({route:n.path,file:n.file??null})).sort((n,i)=>n.route.localeCompare(i.route))}function m(e,l){if(!l.entity)return null;const n=new Set((e.syncRisks??[]).map(o=>o.mutation)),i=`${l.file}:${l.line}`,r=new Set;for(const o of e.routes??[])for(const t of o.mutations??[]){if(!t.file||!Number.isInteger(t.line)||t.nonWrite||!t.clearsCache)continue;const u=`${t.file}:${t.line}`;if(u===i||n.has(u)||r.has(u))continue;r.add(u);const c=t.writes??t.entity;if(!(!c||s(c)!==s(l.entity)))return{hook:t.hook??null,file:t.file,line:t.line,entity:c}}return null}function p(e,l){if(!l||!e.kind?.startsWith("sync."))return{callers:[],example:null};const n=f(e,l);return n?{callers:a(l,n),example:m(l,n)}:{callers:[],example:null}}export{p as recommendFor};
@@ -0,0 +1 @@
1
+ import i from"node:fs";import c from"node:path";import{createHash as p}from"node:crypto";function f({skillRoot:n,platform:e,arch:r,manifest:t}){if(t.protocolVersion!==1)return{status:"unmeasured",reason:"incompatible-protocol"};if(t.binaries.length===0)return{status:"unmeasured",reason:"no-binary"};const o=t.binaries.find(u=>u.platform===e&&u.arch===r);if(!o)return{status:"unmeasured",reason:"unsupported-platform"};const s=c.join(n,o.path);let a;try{a=i.statSync(s)}catch{return{status:"unmeasured",reason:"no-binary"}}return a.isFile()?a.mode&18?{status:"unmeasured",reason:"no-binary"}:{status:"ok",path:s,sha256:o.sha256,protocolVersion:t.protocolVersion}:{status:"unmeasured",reason:"no-binary"}}function h(n,e){const r=p("sha256").update(i.readFileSync(n)).digest("hex");return{ok:r===e,actual:r}}export{f as selectBinary,h as verifyBinary};