productfoo 0.0.0-stage → 1.0.1

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 (498) hide show
  1. package/LICENSE +201 -0
  2. package/README.md +338 -2
  3. package/bin/foo +3 -0
  4. package/bin/foo.mjs +42 -0
  5. package/commands/bug.md +31 -0
  6. package/commands/discovery.md +28 -0
  7. package/commands/ideate.md +27 -0
  8. package/commands/init.md +28 -0
  9. package/commands/pitch.md +27 -0
  10. package/commands/preview.md +25 -0
  11. package/commands/research.md +31 -0
  12. package/commands/roast.md +27 -0
  13. package/commands/spec.md +30 -0
  14. package/config/pricing.yaml +198 -0
  15. package/config/routing-policy.yaml +171 -0
  16. package/dist-public/src/activeModel.d.ts +83 -0
  17. package/dist-public/src/activeModel.js +331 -0
  18. package/dist-public/src/agentAdapters.d.ts +122 -0
  19. package/dist-public/src/agentAdapters.js +178 -0
  20. package/dist-public/src/agentState.d.ts +43 -0
  21. package/dist-public/src/agentState.js +177 -0
  22. package/dist-public/src/bugCapsule.d.ts +94 -0
  23. package/dist-public/src/bugCapsule.js +227 -0
  24. package/dist-public/src/bugCapture.d.ts +26 -0
  25. package/dist-public/src/bugCapture.js +251 -0
  26. package/dist-public/src/bugOwnerLog.d.ts +93 -0
  27. package/dist-public/src/bugOwnerLog.js +304 -0
  28. package/dist-public/src/bugReportStore.d.ts +48 -0
  29. package/dist-public/src/bugReportStore.js +860 -0
  30. package/dist-public/src/bugSpecContext.d.ts +7 -0
  31. package/dist-public/src/bugSpecContext.js +129 -0
  32. package/dist-public/src/channelFreshness.d.ts +25 -0
  33. package/dist-public/src/channelFreshness.js +194 -0
  34. package/dist-public/src/cli.d.ts +30 -0
  35. package/dist-public/src/cli.js +1667 -0
  36. package/dist-public/src/cliArgs.d.ts +7 -0
  37. package/dist-public/src/cliArgs.js +44 -0
  38. package/dist-public/src/codeCatalog.d.ts +41 -0
  39. package/dist-public/src/codeCatalog.js +197 -0
  40. package/dist-public/src/commandContract.d.ts +84 -0
  41. package/dist-public/src/commandContract.js +390 -0
  42. package/dist-public/src/commandUsage.d.ts +3 -0
  43. package/dist-public/src/commandUsage.js +30 -0
  44. package/dist-public/src/commands/agent.d.ts +60 -0
  45. package/dist-public/src/commands/agent.js +1353 -0
  46. package/dist-public/src/commands/asp.d.ts +8 -0
  47. package/dist-public/src/commands/asp.js +669 -0
  48. package/dist-public/src/commands/evalCmd.d.ts +4 -0
  49. package/dist-public/src/commands/evalCmd.js +405 -0
  50. package/dist-public/src/commands/login.d.ts +25 -0
  51. package/dist-public/src/commands/login.js +94 -0
  52. package/dist-public/src/commands/loop.d.ts +16 -0
  53. package/dist-public/src/commands/loop.js +619 -0
  54. package/dist-public/src/commands/reconcile.d.ts +41 -0
  55. package/dist-public/src/commands/reconcile.js +292 -0
  56. package/dist-public/src/commands/runtime.d.ts +1 -0
  57. package/dist-public/src/commands/runtime.js +36 -0
  58. package/dist-public/src/commands/scanRedact.d.ts +8 -0
  59. package/dist-public/src/commands/scanRedact.js +266 -0
  60. package/dist-public/src/commands/setup.d.ts +28 -0
  61. package/dist-public/src/commands/setup.js +398 -0
  62. package/dist-public/src/commands/shared.d.ts +17 -0
  63. package/dist-public/src/commands/shared.js +147 -0
  64. package/dist-public/src/commands/source.d.ts +1 -0
  65. package/dist-public/src/commands/source.js +134 -0
  66. package/dist-public/src/commands/specCmd.d.ts +24 -0
  67. package/dist-public/src/commands/specCmd.js +794 -0
  68. package/dist-public/src/commands/update.d.ts +61 -0
  69. package/dist-public/src/commands/update.js +244 -0
  70. package/dist-public/src/comprehensionSignal.d.ts +20 -0
  71. package/dist-public/src/comprehensionSignal.js +166 -0
  72. package/dist-public/src/conductor/diversity.d.ts +48 -0
  73. package/dist-public/src/conductor/diversity.js +423 -0
  74. package/dist-public/src/conductor/engine.d.ts +7 -0
  75. package/dist-public/src/conductor/engine.js +295 -0
  76. package/dist-public/src/conductor/families/ideate.d.ts +2 -0
  77. package/dist-public/src/conductor/families/ideate.js +255 -0
  78. package/dist-public/src/conductor/families/interview.d.ts +2 -0
  79. package/dist-public/src/conductor/families/interview.js +39 -0
  80. package/dist-public/src/conductor/families/specSwarm.d.ts +2 -0
  81. package/dist-public/src/conductor/families/specSwarm.js +146 -0
  82. package/dist-public/src/conductor/familyDelivery.d.ts +6 -0
  83. package/dist-public/src/conductor/familyDelivery.js +37 -0
  84. package/dist-public/src/conductor/familyPackArtifact.d.ts +4 -0
  85. package/dist-public/src/conductor/familyPackArtifact.js +260 -0
  86. package/dist-public/src/conductor/ideateDecision.d.ts +6 -0
  87. package/dist-public/src/conductor/ideateDecision.js +237 -0
  88. package/dist-public/src/conductor/pack.d.ts +26 -0
  89. package/dist-public/src/conductor/pack.js +75 -0
  90. package/dist-public/src/conductor/types.d.ts +111 -0
  91. package/dist-public/src/conductor/types.js +7 -0
  92. package/dist-public/src/configPath.d.ts +2 -0
  93. package/dist-public/src/configPath.js +7 -0
  94. package/dist-public/src/discoveryArtifacts.d.ts +54 -0
  95. package/dist-public/src/discoveryArtifacts.js +467 -0
  96. package/dist-public/src/discoveryCommand.d.ts +127 -0
  97. package/dist-public/src/discoveryCommand.js +2148 -0
  98. package/dist-public/src/discoveryConnections.d.ts +339 -0
  99. package/dist-public/src/discoveryConnections.js +613 -0
  100. package/dist-public/src/discoveryDocs.d.ts +129 -0
  101. package/dist-public/src/discoveryDocs.js +577 -0
  102. package/dist-public/src/discoveryEvidence.d.ts +59 -0
  103. package/dist-public/src/discoveryEvidence.js +198 -0
  104. package/dist-public/src/discoveryFireflies.d.ts +25 -0
  105. package/dist-public/src/discoveryFireflies.js +551 -0
  106. package/dist-public/src/discoveryGmail.d.ts +12 -0
  107. package/dist-public/src/discoveryGmail.js +466 -0
  108. package/dist-public/src/discoveryGong.d.ts +12 -0
  109. package/dist-public/src/discoveryGong.js +491 -0
  110. package/dist-public/src/discoveryLearningRouting.d.ts +90 -0
  111. package/dist-public/src/discoveryLearningRouting.js +405 -0
  112. package/dist-public/src/discoveryMatching.d.ts +26 -0
  113. package/dist-public/src/discoveryMatching.js +73 -0
  114. package/dist-public/src/discoveryOutlook.d.ts +12 -0
  115. package/dist-public/src/discoveryOutlook.js +492 -0
  116. package/dist-public/src/discoveryProcess.d.ts +221 -0
  117. package/dist-public/src/discoveryProcess.js +703 -0
  118. package/dist-public/src/discoveryProof.d.ts +143 -0
  119. package/dist-public/src/discoveryProof.js +529 -0
  120. package/dist-public/src/discoveryProviders.d.ts +152 -0
  121. package/dist-public/src/discoveryProviders.js +756 -0
  122. package/dist-public/src/discoveryReadiness.d.ts +219 -0
  123. package/dist-public/src/discoveryReadiness.js +672 -0
  124. package/dist-public/src/discoveryReconcile.d.ts +57 -0
  125. package/dist-public/src/discoveryReconcile.js +424 -0
  126. package/dist-public/src/discoverySlack.d.ts +12 -0
  127. package/dist-public/src/discoverySlack.js +452 -0
  128. package/dist-public/src/discoverySources.d.ts +56 -0
  129. package/dist-public/src/discoverySources.js +322 -0
  130. package/dist-public/src/discoverySync.d.ts +52 -0
  131. package/dist-public/src/discoverySync.js +151 -0
  132. package/dist-public/src/discoverySynthesis.d.ts +57 -0
  133. package/dist-public/src/discoverySynthesis.js +215 -0
  134. package/dist-public/src/discoveryTeams.d.ts +12 -0
  135. package/dist-public/src/discoveryTeams.js +516 -0
  136. package/dist-public/src/discoveryZoom.d.ts +12 -0
  137. package/dist-public/src/discoveryZoom.js +523 -0
  138. package/dist-public/src/elicitationSurface.d.ts +13 -0
  139. package/dist-public/src/elicitationSurface.js +77 -0
  140. package/dist-public/src/errorReport.d.ts +99 -0
  141. package/dist-public/src/errorReport.js +443 -0
  142. package/dist-public/src/errorTaxonomy.d.ts +84 -0
  143. package/dist-public/src/errorTaxonomy.js +189 -0
  144. package/dist-public/src/evalCalibration.d.ts +82 -0
  145. package/dist-public/src/evalCalibration.js +169 -0
  146. package/dist-public/src/evalChecks.d.ts +21 -0
  147. package/dist-public/src/evalChecks.js +295 -0
  148. package/dist-public/src/evalCompile.d.ts +56 -0
  149. package/dist-public/src/evalCompile.js +58 -0
  150. package/dist-public/src/evalImprove.d.ts +60 -0
  151. package/dist-public/src/evalImprove.js +175 -0
  152. package/dist-public/src/evalJudge.d.ts +47 -0
  153. package/dist-public/src/evalJudge.js +143 -0
  154. package/dist-public/src/evalLabels.d.ts +100 -0
  155. package/dist-public/src/evalLabels.js +287 -0
  156. package/dist-public/src/evalRecord.d.ts +68 -0
  157. package/dist-public/src/evalRecord.js +165 -0
  158. package/dist-public/src/evalRoast.d.ts +88 -0
  159. package/dist-public/src/evalRoast.js +249 -0
  160. package/dist-public/src/evidenceIntake.d.ts +66 -0
  161. package/dist-public/src/evidenceIntake.js +356 -0
  162. package/dist-public/src/feedback.d.ts +78 -0
  163. package/dist-public/src/feedback.js +294 -0
  164. package/dist-public/src/firefliesClient.d.ts +106 -0
  165. package/dist-public/src/firefliesClient.js +258 -0
  166. package/dist-public/src/firstMoveTensions.d.ts +10 -0
  167. package/dist-public/src/firstMoveTensions.js +93 -0
  168. package/dist-public/src/gitRun.d.ts +21 -0
  169. package/dist-public/src/gitRun.js +50 -0
  170. package/dist-public/src/githubReconcile.d.ts +94 -0
  171. package/dist-public/src/githubReconcile.js +205 -0
  172. package/dist-public/src/gmailNango.d.ts +131 -0
  173. package/dist-public/src/gmailNango.js +329 -0
  174. package/dist-public/src/gongNango.d.ts +118 -0
  175. package/dist-public/src/gongNango.js +308 -0
  176. package/dist-public/src/grammarGate.d.ts +13 -0
  177. package/dist-public/src/grammarGate.js +72 -0
  178. package/dist-public/src/harnessGates.d.ts +65 -0
  179. package/dist-public/src/harnessGates.js +168 -0
  180. package/dist-public/src/humanSurfaceEval.d.ts +19 -0
  181. package/dist-public/src/humanSurfaceEval.js +156 -0
  182. package/dist-public/src/ideate.d.ts +43 -0
  183. package/dist-public/src/ideate.js +255 -0
  184. package/dist-public/src/ideateContext.d.ts +11 -0
  185. package/dist-public/src/ideateContext.js +83 -0
  186. package/dist-public/src/index.d.ts +2 -0
  187. package/dist-public/src/index.js +4 -0
  188. package/dist-public/src/initCommand.d.ts +25 -0
  189. package/dist-public/src/initCommand.js +558 -0
  190. package/dist-public/src/interviewGate.d.ts +25 -0
  191. package/dist-public/src/interviewGate.js +126 -0
  192. package/dist-public/src/jsonFile.d.ts +2 -0
  193. package/dist-public/src/jsonFile.js +22 -0
  194. package/dist-public/src/loopBudget.d.ts +182 -0
  195. package/dist-public/src/loopBudget.js +494 -0
  196. package/dist-public/src/loopContracts.d.ts +35 -0
  197. package/dist-public/src/loopContracts.js +364 -0
  198. package/dist-public/src/machineState.d.ts +1 -0
  199. package/dist-public/src/machineState.js +9 -0
  200. package/dist-public/src/notionNango.d.ts +93 -0
  201. package/dist-public/src/notionNango.js +279 -0
  202. package/dist-public/src/orchestrationResult.d.ts +11 -0
  203. package/dist-public/src/orchestrationResult.js +73 -0
  204. package/dist-public/src/outlookNango.d.ts +124 -0
  205. package/dist-public/src/outlookNango.js +327 -0
  206. package/dist-public/src/packetCorrections.d.ts +40 -0
  207. package/dist-public/src/packetCorrections.js +172 -0
  208. package/dist-public/src/packetGlossary.d.ts +6 -0
  209. package/dist-public/src/packetGlossary.js +42 -0
  210. package/dist-public/src/packetIndex.d.ts +54 -0
  211. package/dist-public/src/packetIndex.js +744 -0
  212. package/dist-public/src/packetIndexEntry.d.ts +3 -0
  213. package/dist-public/src/packetIndexEntry.js +128 -0
  214. package/dist-public/src/packetIndexServe.d.ts +13 -0
  215. package/dist-public/src/packetIndexServe.js +113 -0
  216. package/dist-public/src/packetIndexWorker.d.ts +7 -0
  217. package/dist-public/src/packetIndexWorker.js +45 -0
  218. package/dist-public/src/packetLifecycle.d.ts +30 -0
  219. package/dist-public/src/packetLifecycle.js +127 -0
  220. package/dist-public/src/packetReconcile.d.ts +73 -0
  221. package/dist-public/src/packetReconcile.js +386 -0
  222. package/dist-public/src/packetStatus.d.ts +125 -0
  223. package/dist-public/src/packetStatus.js +770 -0
  224. package/dist-public/src/packetValidation.d.ts +17 -0
  225. package/dist-public/src/packetValidation.js +333 -0
  226. package/dist-public/src/packetVerify.d.ts +73 -0
  227. package/dist-public/src/packetVerify.js +303 -0
  228. package/dist-public/src/packetWrite.d.ts +52 -0
  229. package/dist-public/src/packetWrite.js +448 -0
  230. package/dist-public/src/pitch.d.ts +38 -0
  231. package/dist-public/src/pitch.js +154 -0
  232. package/dist-public/src/processMemo.d.ts +8 -0
  233. package/dist-public/src/processMemo.js +23 -0
  234. package/dist-public/src/productDetect.d.ts +30 -0
  235. package/dist-public/src/productDetect.js +376 -0
  236. package/dist-public/src/profile.d.ts +62 -0
  237. package/dist-public/src/profile.js +334 -0
  238. package/dist-public/src/questionModel.d.ts +46 -0
  239. package/dist-public/src/questionModel.js +74 -0
  240. package/dist-public/src/questionText.d.ts +7 -0
  241. package/dist-public/src/questionText.js +38 -0
  242. package/dist-public/src/redactConfig.d.ts +2 -0
  243. package/dist-public/src/redactConfig.js +11 -0
  244. package/dist-public/src/redactEngine.d.ts +59 -0
  245. package/dist-public/src/redactEngine.js +509 -0
  246. package/dist-public/src/redactGate.d.ts +63 -0
  247. package/dist-public/src/redactGate.js +209 -0
  248. package/dist-public/src/repoRead.d.ts +29 -0
  249. package/dist-public/src/repoRead.js +160 -0
  250. package/dist-public/src/research.d.ts +242 -0
  251. package/dist-public/src/research.js +1314 -0
  252. package/dist-public/src/researchCompletion.d.ts +34 -0
  253. package/dist-public/src/researchCompletion.js +123 -0
  254. package/dist-public/src/researchExecution.d.ts +47 -0
  255. package/dist-public/src/researchExecution.js +309 -0
  256. package/dist-public/src/researchFormat.d.ts +21 -0
  257. package/dist-public/src/researchFormat.js +77 -0
  258. package/dist-public/src/researchGate.d.ts +86 -0
  259. package/dist-public/src/researchGate.js +1036 -0
  260. package/dist-public/src/researchReceipt.d.ts +76 -0
  261. package/dist-public/src/researchReceipt.js +148 -0
  262. package/dist-public/src/researchRender.d.ts +2 -0
  263. package/dist-public/src/researchRender.js +267 -0
  264. package/dist-public/src/researchSigningKey.d.ts +19 -0
  265. package/dist-public/src/researchSigningKey.js +95 -0
  266. package/dist-public/src/riskClassify.d.ts +42 -0
  267. package/dist-public/src/riskClassify.js +149 -0
  268. package/dist-public/src/routines.d.ts +42 -0
  269. package/dist-public/src/routines.js +269 -0
  270. package/dist-public/src/routingPolicy.d.ts +172 -0
  271. package/dist-public/src/routingPolicy.js +646 -0
  272. package/dist-public/src/secretInput.d.ts +8 -0
  273. package/dist-public/src/secretInput.js +89 -0
  274. package/dist-public/src/selfCheck.d.ts +7 -0
  275. package/dist-public/src/selfCheck.js +473 -0
  276. package/dist-public/src/selfCheckCache.d.ts +29 -0
  277. package/dist-public/src/selfCheckCache.js +147 -0
  278. package/dist-public/src/severityClass.d.ts +15 -0
  279. package/dist-public/src/severityClass.js +22 -0
  280. package/dist-public/src/skillClientPolicy.d.ts +8 -0
  281. package/dist-public/src/skillClientPolicy.js +16 -0
  282. package/dist-public/src/skillLocal.d.ts +98 -0
  283. package/dist-public/src/skillLocal.js +463 -0
  284. package/dist-public/src/skillTreeDigest.d.ts +9 -0
  285. package/dist-public/src/skillTreeDigest.js +64 -0
  286. package/dist-public/src/slackNango.d.ts +62 -0
  287. package/dist-public/src/slackNango.js +208 -0
  288. package/dist-public/src/social/arxiv.d.ts +19 -0
  289. package/dist-public/src/social/arxiv.js +96 -0
  290. package/dist-public/src/social/github.d.ts +2 -0
  291. package/dist-public/src/social/github.js +78 -0
  292. package/dist-public/src/social/hackernews.d.ts +2 -0
  293. package/dist-public/src/social/hackernews.js +67 -0
  294. package/dist-public/src/social/index.d.ts +10 -0
  295. package/dist-public/src/social/index.js +79 -0
  296. package/dist-public/src/social/reddit.d.ts +2 -0
  297. package/dist-public/src/social/reddit.js +125 -0
  298. package/dist-public/src/social/types.d.ts +73 -0
  299. package/dist-public/src/social/types.js +61 -0
  300. package/dist-public/src/social/xml.d.ts +10 -0
  301. package/dist-public/src/social/xml.js +49 -0
  302. package/dist-public/src/social/youtube.d.ts +7 -0
  303. package/dist-public/src/social/youtube.js +217 -0
  304. package/dist-public/src/sourceIngress.d.ts +488 -0
  305. package/dist-public/src/sourceIngress.js +1651 -0
  306. package/dist-public/src/specAfter.d.ts +187 -0
  307. package/dist-public/src/specAfter.js +814 -0
  308. package/dist-public/src/specBudget.d.ts +124 -0
  309. package/dist-public/src/specBudget.js +424 -0
  310. package/dist-public/src/specDecisionSignals.d.ts +38 -0
  311. package/dist-public/src/specDecisionSignals.js +121 -0
  312. package/dist-public/src/specLinkedCommits.d.ts +7 -0
  313. package/dist-public/src/specLinkedCommits.js +107 -0
  314. package/dist-public/src/specSections.d.ts +105 -0
  315. package/dist-public/src/specSections.js +718 -0
  316. package/dist-public/src/statusGlyphs.d.ts +18 -0
  317. package/dist-public/src/statusGlyphs.js +75 -0
  318. package/dist-public/src/swarmCommand.d.ts +10 -0
  319. package/dist-public/src/swarmCommand.js +96 -0
  320. package/dist-public/src/teamsNango.d.ts +114 -0
  321. package/dist-public/src/teamsNango.js +301 -0
  322. package/dist-public/src/tokenStore.d.ts +10 -0
  323. package/dist-public/src/tokenStore.js +77 -0
  324. package/dist-public/src/trustEnvelope.d.ts +78 -0
  325. package/dist-public/src/trustEnvelope.js +392 -0
  326. package/dist-public/src/untrustedText.d.ts +6 -0
  327. package/dist-public/src/untrustedText.js +20 -0
  328. package/dist-public/src/updateNotice.d.ts +41 -0
  329. package/dist-public/src/updateNotice.js +290 -0
  330. package/dist-public/src/vendorYaml.d.ts +1 -0
  331. package/dist-public/src/vendorYaml.js +7374 -0
  332. package/dist-public/src/workflowRunActuals.d.ts +67 -0
  333. package/dist-public/src/workflowRunActuals.js +184 -0
  334. package/dist-public/src/zendeskDiscovery.d.ts +12 -0
  335. package/dist-public/src/zendeskDiscovery.js +513 -0
  336. package/dist-public/src/zendeskNango.d.ts +131 -0
  337. package/dist-public/src/zendeskNango.js +344 -0
  338. package/dist-public/src/zoomNango.d.ts +106 -0
  339. package/dist-public/src/zoomNango.js +351 -0
  340. package/docs/CHANGELOG.md +32 -0
  341. package/docs/THIRD_PARTY_NOTICES.md +36 -0
  342. package/package.json +71 -4
  343. package/schemas/bug-capsule-receipt.schema.json +54 -0
  344. package/schemas/bug-capsule.schema.json +189 -0
  345. package/schemas/discovery-evidence-envelope.schema.json +79 -0
  346. package/schemas/discovery-processing-receipt.schema.json +71 -0
  347. package/schemas/discovery-service-contract.schema.json +189 -0
  348. package/skills/AGENTS.md +32 -0
  349. package/skills/README.md +287 -0
  350. package/skills/bug/SKILL.md +49 -0
  351. package/skills/build-preview-spec/SKILL.md +103 -0
  352. package/skills/capture-external-artifact/SKILL.md +23 -0
  353. package/skills/capture-external-artifact/agents/openai.yaml +4 -0
  354. package/skills/capture-external-artifact/references/extractor-libraries.md +27 -0
  355. package/skills/check-spec-health/SKILL.md +45 -0
  356. package/skills/check-spec-health/agents/openai.yaml +4 -0
  357. package/skills/competitive-positioning/SKILL.md +86 -0
  358. package/skills/competitive-positioning/agents/openai.yaml +4 -0
  359. package/skills/cpo-lens/SKILL.md +398 -0
  360. package/skills/cpo-lens/agents/openai.yaml +4 -0
  361. package/skills/create-prd/SKILL.md +26 -0
  362. package/skills/create-prd/agents/openai.yaml +4 -0
  363. package/skills/customer-discovery/SKILL.md +192 -0
  364. package/skills/design-system/SKILL.md +49 -0
  365. package/skills/design-system/agents/openai.yaml +4 -0
  366. package/skills/discussion-guide/SKILL.md +75 -0
  367. package/skills/discussion-guide/agents/openai.yaml +4 -0
  368. package/skills/firecrawl-research-papers/SKILL.md +96 -0
  369. package/skills/firecrawl-research-papers/agents/openai.yaml +4 -0
  370. package/skills/foo-roast/SKILL.md +325 -0
  371. package/skills/generate-gtm-brief/SKILL.md +41 -0
  372. package/skills/generate-gtm-brief/agents/openai.yaml +4 -0
  373. package/skills/generate-gtm-brief/references/gtm-brief-template.md +56 -0
  374. package/skills/gong-quotes/SKILL.md +43 -0
  375. package/skills/gong-quotes/agents/openai.yaml +4 -0
  376. package/skills/grill-me/SKILL.md +27 -0
  377. package/skills/grill-me/agents/openai.yaml +4 -0
  378. package/skills/ideate/SKILL.md +180 -0
  379. package/skills/ideate/references/family-packs.md +5 -0
  380. package/skills/initiative-tracker/SKILL.md +23 -0
  381. package/skills/initiative-tracker/agents/openai.yaml +4 -0
  382. package/skills/interop-review/SKILL.md +25 -0
  383. package/skills/interop-review/agents/openai.yaml +4 -0
  384. package/skills/interview-me/SKILL.md +404 -0
  385. package/skills/interview-me/agents/openai.yaml +4 -0
  386. package/skills/loop-library-audit/SKILL.md +123 -0
  387. package/skills/pitch/SKILL.md +110 -0
  388. package/skills/pitch/references/opportunity-assessment.md +136 -0
  389. package/skills/pitch/references/prfaq-template.md +54 -0
  390. package/skills/pmm-release-briefing/SKILL.md +27 -0
  391. package/skills/pmm-release-briefing/agents/openai.yaml +4 -0
  392. package/skills/pmm-release-briefing/references/variant-generalized.md +16 -0
  393. package/skills/positioning-messaging/SKILL.md +70 -0
  394. package/skills/positioning-messaging/agents/openai.yaml +4 -0
  395. package/skills/positioning-messaging/references/guest-insights.md +1400 -0
  396. package/skills/preview-swarm/SKILL.md +418 -0
  397. package/skills/preview-swarm/agents/openai.yaml +4 -0
  398. package/skills/preview-swarm/references/html-effectiveness-build-previews.md +168 -0
  399. package/skills/product-copywriting/SKILL.md +127 -0
  400. package/skills/product-copywriting/agents/openai.yaml +4 -0
  401. package/skills/product-copywriting/references/foo-voice.md +26 -0
  402. package/skills/product-shape-interview/SKILL.md +219 -0
  403. package/skills/product-shape-interview/agents/openai.yaml +4 -0
  404. package/skills/ready-for-release/SKILL.md +39 -0
  405. package/skills/ready-for-release/agents/openai.yaml +4 -0
  406. package/skills/redact-transcripts/SKILL.md +23 -0
  407. package/skills/redact-transcripts/agents/openai.yaml +4 -0
  408. package/skills/research-brief/SKILL.md +48 -0
  409. package/skills/research-brief/agents/openai.yaml +4 -0
  410. package/skills/research-refresh/SKILL.md +63 -0
  411. package/skills/research-refresh/references/worked-cases.md +44 -0
  412. package/skills/review-loop/SKILL.md +200 -0
  413. package/skills/review-spec/SKILL.md +32 -0
  414. package/skills/review-spec/agents/openai.yaml +4 -0
  415. package/skills/rfc-from-research/SKILL.md +42 -0
  416. package/skills/rfc-from-research/agents/openai.yaml +4 -0
  417. package/skills/rfc-from-research/references/rfc-pattern.md +69 -0
  418. package/skills/skill-registry.yaml +810 -0
  419. package/skills/spec-cleanup/SKILL.md +103 -0
  420. package/skills/spec-cleanup/agents/openai.yaml +4 -0
  421. package/skills/spec-swarm/SKILL.md +87 -0
  422. package/skills/spec-swarm/agents/openai.yaml +4 -0
  423. package/skills/spec-swarm/template/SKILL.template.md +94 -0
  424. package/skills/spec-swarm/template/personas/accessibility-inclusion.md +40 -0
  425. package/skills/spec-swarm/template/personas/ai-technical-pm.md +69 -0
  426. package/skills/spec-swarm/template/personas/analytics-engineering.md +39 -0
  427. package/skills/spec-swarm/template/personas/applied-ai-eval.md +64 -0
  428. package/skills/spec-swarm/template/personas/business-gm-pm.md +67 -0
  429. package/skills/spec-swarm/template/personas/consumer-craft-pm.md +68 -0
  430. package/skills/spec-swarm/template/personas/content-design.md +40 -0
  431. package/skills/spec-swarm/template/personas/cpo.md +42 -0
  432. package/skills/spec-swarm/template/personas/data-science.md +42 -0
  433. package/skills/spec-swarm/template/personas/developer-experience.md +65 -0
  434. package/skills/spec-swarm/template/personas/dx-product.md +70 -0
  435. package/skills/spec-swarm/template/personas/field.md +43 -0
  436. package/skills/spec-swarm/template/personas/finance-cfo.md +40 -0
  437. package/skills/spec-swarm/template/personas/growth-pm.md +67 -0
  438. package/skills/spec-swarm/template/personas/platform-pm.md +67 -0
  439. package/skills/spec-swarm/template/personas/pmm.md +43 -0
  440. package/skills/spec-swarm/template/personas/principal-product-designer.md +42 -0
  441. package/skills/spec-swarm/template/personas/product-ops-program.md +41 -0
  442. package/skills/spec-swarm/template/personas/qa-release.md +41 -0
  443. package/skills/spec-swarm/template/personas/responsible-ai-safety.md +64 -0
  444. package/skills/spec-swarm/template/personas/security-privacy-legal.md +40 -0
  445. package/skills/spec-swarm/template/personas/strategy-competitive.md +41 -0
  446. package/skills/spec-swarm/template/personas/technical-architect.md +42 -0
  447. package/skills/spec-swarm/template/personas/technical-lead.md +43 -0
  448. package/skills/spec-swarm/template/personas/user-research.md +41 -0
  449. package/skills/spec-swarm-accessibility-inclusion/SKILL.md +95 -0
  450. package/skills/spec-swarm-accessibility-inclusion/agents/openai.yaml +4 -0
  451. package/skills/spec-swarm-ai-technical-pm/SKILL.md +124 -0
  452. package/skills/spec-swarm-analytics-engineering/SKILL.md +94 -0
  453. package/skills/spec-swarm-analytics-engineering/agents/openai.yaml +4 -0
  454. package/skills/spec-swarm-applied-ai-eval/SKILL.md +120 -0
  455. package/skills/spec-swarm-business-gm-pm/SKILL.md +122 -0
  456. package/skills/spec-swarm-consumer-craft-pm/SKILL.md +122 -0
  457. package/skills/spec-swarm-content-design/SKILL.md +95 -0
  458. package/skills/spec-swarm-content-design/agents/openai.yaml +4 -0
  459. package/skills/spec-swarm-cpo/SKILL.md +94 -0
  460. package/skills/spec-swarm-cpo/agents/openai.yaml +4 -0
  461. package/skills/spec-swarm-data-science/SKILL.md +95 -0
  462. package/skills/spec-swarm-data-science/agents/openai.yaml +4 -0
  463. package/skills/spec-swarm-developer-experience/SKILL.md +121 -0
  464. package/skills/spec-swarm-dx-product/SKILL.md +126 -0
  465. package/skills/spec-swarm-field/SKILL.md +96 -0
  466. package/skills/spec-swarm-field/agents/openai.yaml +4 -0
  467. package/skills/spec-swarm-finance-cfo/SKILL.md +95 -0
  468. package/skills/spec-swarm-finance-cfo/agents/openai.yaml +4 -0
  469. package/skills/spec-swarm-growth-pm/SKILL.md +122 -0
  470. package/skills/spec-swarm-platform-pm/SKILL.md +122 -0
  471. package/skills/spec-swarm-pmm/SKILL.md +96 -0
  472. package/skills/spec-swarm-pmm/agents/openai.yaml +4 -0
  473. package/skills/spec-swarm-principal-product-designer/SKILL.md +95 -0
  474. package/skills/spec-swarm-principal-product-designer/agents/openai.yaml +4 -0
  475. package/skills/spec-swarm-product-ops-program/SKILL.md +96 -0
  476. package/skills/spec-swarm-product-ops-program/agents/openai.yaml +4 -0
  477. package/skills/spec-swarm-qa-release/SKILL.md +96 -0
  478. package/skills/spec-swarm-qa-release/agents/openai.yaml +4 -0
  479. package/skills/spec-swarm-responsible-ai-safety/SKILL.md +120 -0
  480. package/skills/spec-swarm-security-privacy-legal/SKILL.md +95 -0
  481. package/skills/spec-swarm-security-privacy-legal/agents/openai.yaml +4 -0
  482. package/skills/spec-swarm-strategy-competitive/SKILL.md +96 -0
  483. package/skills/spec-swarm-strategy-competitive/agents/openai.yaml +4 -0
  484. package/skills/spec-swarm-technical-architect/SKILL.md +95 -0
  485. package/skills/spec-swarm-technical-architect/agents/openai.yaml +4 -0
  486. package/skills/spec-swarm-technical-lead/SKILL.md +96 -0
  487. package/skills/spec-swarm-technical-lead/agents/openai.yaml +4 -0
  488. package/skills/spec-swarm-user-research/SKILL.md +95 -0
  489. package/skills/spec-swarm-user-research/agents/openai.yaml +4 -0
  490. package/skills/strategy-check/SKILL.md +170 -0
  491. package/skills/strategy-check/agents/openai.yaml +4 -0
  492. package/skills/study-digest/SKILL.md +41 -0
  493. package/skills/synthetic-customer/SKILL.md +68 -0
  494. package/skills/update-cli-spec/SKILL.md +69 -0
  495. package/skills/update-cli-spec/agents/openai.yaml +4 -0
  496. package/skills/voc-researcher/SKILL.md +45 -0
  497. package/skills/voc-researcher/agents/openai.yaml +4 -0
  498. package/skills-lock.json +35 -0
@@ -0,0 +1,295 @@
1
+ // Deterministic eval checks (foo-eval-system-v0 R-002). Every check that can
2
+ // be code is code — no judge spend where a regex suffices. Carried posture from
3
+ // the research-format gate: only unambiguous misses hard-fail ("fail");
4
+ // ambiguous findings surface as advisory ("warn") with reasons, and strict mode
5
+ // promotes them.
6
+ // A quantity the one-number rule counts: plain numbers, money, percents,
7
+ // multipliers, and unit-suffixed figures. A number inside a word (v2, utf8)
8
+ // is not a quantity.
9
+ const QUANTITY = /(?<![\w.$])\$?\d[\d,]*(?:\.\d+)?(?:\s?%|x|k|M|B|bn)?(?![\w.])/g;
10
+ // Markers that make a quantity accounted-for under the sourcing lint: a
11
+ // markdown link in the same sentence, an estimate flag, or the "our rule"
12
+ // label the seed roast introduced.
13
+ const SOURCE_MARKERS = [
14
+ /\[[^\]]+\]\([^)]+\)/, // markdown link
15
+ /(?<![\w-])(?:estimate[ds]?|est\.)(?![\w-])/i,
16
+ /(?<![\w-])our rule(?![\w-])/i,
17
+ ];
18
+ function stripInlineCode(line) {
19
+ return line.replace(/`[^`]*`/g, (span) => " ".repeat(span.length));
20
+ }
21
+ function proseLines(text) {
22
+ const output = [];
23
+ let inFence = false;
24
+ for (const [index, raw] of text.split(/\r?\n/).entries()) {
25
+ if (/^\s*(`{3,}|~{3,})/.test(raw)) {
26
+ inFence = !inFence;
27
+ continue;
28
+ }
29
+ if (inFence)
30
+ continue;
31
+ output.push({ line: index + 1, text: stripInlineCode(raw) });
32
+ }
33
+ return output;
34
+ }
35
+ function sentences(text) {
36
+ return text
37
+ .split(/(?<=[.!?])\s+/)
38
+ .map((sentence) => sentence.trim())
39
+ .filter((sentence) => sentence.length > 0);
40
+ }
41
+ function quantities(sentence) {
42
+ return [...sentence.matchAll(QUANTITY)].map((match) => match[0]);
43
+ }
44
+ function numberValue(params, key, fallback) {
45
+ const value = params[key];
46
+ return typeof value === "number" && Number.isFinite(value) ? value : fallback;
47
+ }
48
+ const oneNumberRule = (lines, params, findings) => {
49
+ const max = numberValue(params, "maxPerSentence", 2);
50
+ for (const { line, text } of lines) {
51
+ for (const sentence of sentences(text)) {
52
+ const found = quantities(sentence);
53
+ if (found.length > max) {
54
+ findings.push({
55
+ check: "one-number-rule",
56
+ line,
57
+ phrase: found.join(", "),
58
+ message: `Sentence carries ${found.length} quantities; the limit is ${max}. Split the sentence or move figures to a table.`,
59
+ severity: "fail",
60
+ });
61
+ }
62
+ }
63
+ }
64
+ };
65
+ const lengthLimit = (lines, params, findings) => {
66
+ const maxWords = numberValue(params, "maxWords", 1000);
67
+ const words = lines.reduce((count, { text }) => count + text.split(/\s+/).filter((word) => word.length > 0).length, 0);
68
+ if (words > maxWords) {
69
+ findings.push({
70
+ check: "length-limit",
71
+ line: lines.at(-1)?.line ?? 1,
72
+ phrase: `${words} words`,
73
+ message: `The artifact runs ${words} words against a limit of ${maxWords}. Cut before polishing.`,
74
+ severity: "fail",
75
+ });
76
+ }
77
+ };
78
+ const numberSourcing = (lines, _params, findings) => {
79
+ for (const { line, text } of lines) {
80
+ for (const sentence of sentences(text)) {
81
+ const found = quantities(sentence);
82
+ if (found.length === 0)
83
+ continue;
84
+ const sourced = SOURCE_MARKERS.some((marker) => marker.test(sentence));
85
+ if (!sourced) {
86
+ // Advisory, not a hard fail: a bare number can be legitimately
87
+ // self-evident (a date, a version); the reader rules, strict promotes.
88
+ findings.push({
89
+ check: "number-sourcing",
90
+ line,
91
+ phrase: found[0],
92
+ message: "A quantity with no source link, estimate flag, or “our rule” label in its sentence. Source it, flag it, or own it.",
93
+ severity: "warn",
94
+ });
95
+ }
96
+ }
97
+ }
98
+ };
99
+ const flagConservation = (lines, params, findings) => {
100
+ // Guarded substance the improve loop must not trade away (R-005): counts of
101
+ // these markers may grow, never shrink, relative to the recorded baseline.
102
+ const baselines = [
103
+ { key: "minCitations", pattern: /\[[^\]]+\]\([^)]+\)/g, label: "citations" },
104
+ { key: "minEstimateFlags", pattern: /(?<![\w-])(?:estimate[ds]?|est\.)(?![\w-])/gi, label: "estimate flags" },
105
+ { key: "minOurRuleLabels", pattern: /(?<![\w-])our rule(?![\w-])/gi, label: "“our rule” labels" },
106
+ ];
107
+ const text = lines.map(({ text: value }) => value).join("\n");
108
+ for (const { key, pattern, label } of baselines) {
109
+ const floor = numberValue(params ?? {}, key, 0);
110
+ if (floor <= 0)
111
+ continue;
112
+ const count = [...text.matchAll(pattern)].length;
113
+ if (count < floor) {
114
+ findings.push({
115
+ check: "flag-conservation",
116
+ line: 1,
117
+ phrase: `${count} ${label}`,
118
+ message: `The artifact carries ${count} ${label}; the recorded baseline is ${floor}. A higher score bought by cutting guarded substance is refused.`,
119
+ severity: "fail",
120
+ });
121
+ }
122
+ }
123
+ };
124
+ // ── Agent-relay update-notice checks (seed 2, foo-eval-system-v0) ───────────
125
+ //
126
+ // The update-notice relay (src/updateNotice.ts) addresses the coding agent
127
+ // that ran foo and rides stderr; under --json it is suppressed entirely. The
128
+ // observed failures these checks pin (agent-relay-update-notice-v0 R-004):
129
+ // the notice reaching a payload an agent parses, and a structured payload
130
+ // carrying relay addressing vocabulary. The signature markers are the
131
+ // renderer's own stable strings — the address prefix and the head — chosen
132
+ // because updateNotice never renders them inside code spans (only the
133
+ // `foo update` span is backticked, which stripInlineCode blanks).
134
+ const RELAY_SIGNATURE = [
135
+ "[foo → the human you're working for]",
136
+ "A newer productfoo is available",
137
+ ];
138
+ // Corpus capture format for two-channel runs: the packet's evals/README.md
139
+ // documents it. Checks that read a channel refuse to guess on other shapes.
140
+ const STDOUT_DELIMITER = "--- stdout ---";
141
+ const STDERR_DELIMITER = "--- stderr ---";
142
+ function channelLines(lines) {
143
+ let current = null;
144
+ const channels = { stdout: [], stderr: [] };
145
+ for (const entry of lines) {
146
+ if (entry.text.trim() === STDOUT_DELIMITER) {
147
+ current = "stdout";
148
+ continue;
149
+ }
150
+ if (entry.text.trim() === STDERR_DELIMITER) {
151
+ current = "stderr";
152
+ continue;
153
+ }
154
+ if (current === "stdout")
155
+ channels.stdout.push(entry);
156
+ else if (current === "stderr")
157
+ channels.stderr.push(entry);
158
+ }
159
+ // No delimiters seen at all: not an artifact this check can read.
160
+ return current === null ? null : channels;
161
+ }
162
+ // One finding per line even when both signature markers hit — the phrase
163
+ // carries every marker that matched.
164
+ function relaySignatureFindings(check, lines, message, findings) {
165
+ for (const { line, text } of lines) {
166
+ const hits = RELAY_SIGNATURE.filter((marker) => text.includes(marker));
167
+ if (hits.length === 0)
168
+ continue;
169
+ findings.push({ check, line, phrase: hits.join(", "), message, severity: "fail" });
170
+ }
171
+ }
172
+ function noCaptureSections(check, findings) {
173
+ findings.push({
174
+ check,
175
+ line: 1,
176
+ phrase: STDOUT_DELIMITER,
177
+ message: `The artifact carries no ${STDOUT_DELIMITER} / ${STDERR_DELIMITER} capture sections; this check reads a two-channel run capture (packet evals/README.md documents the format).`,
178
+ severity: "warn",
179
+ });
180
+ }
181
+ // Relay addressing vocabulary as JSON keys, matched on PARSED keys so token
182
+ // boundaries are exact: a value or key named "protocol" does not carry the
183
+ // key "to", and "history" does not carry "to" as a substring.
184
+ const RELAY_FORBIDDEN_KEYS = [
185
+ /^to$/i,
186
+ /^(?:relay|chat|webhook)(?:[-_](?:target|url|endpoint|channel|thread|id))?$/i,
187
+ /^spawn(?:[-_]agents?)?$/i,
188
+ ];
189
+ function forbiddenRelayKey(key) {
190
+ return RELAY_FORBIDDEN_KEYS.some((pattern) => pattern.test(key));
191
+ }
192
+ function walkRelayKeys(node, path, lines, findings) {
193
+ if (Array.isArray(node)) {
194
+ node.forEach((item, index) => walkRelayKeys(item, `${path}[${index}]`, lines, findings));
195
+ return;
196
+ }
197
+ if (node === null || typeof node !== "object")
198
+ return;
199
+ for (const [key, value] of Object.entries(node)) {
200
+ if (forbiddenRelayKey(key)) {
201
+ findings.push({
202
+ check: "relay-json-exclusion",
203
+ line: lines.find(({ text }) => text.includes(`"${key}"`))?.line ?? 1,
204
+ phrase: `"${key}"`,
205
+ message: `Structured payload carries relay addressing key "${key}"${path ? ` at ${path}` : ""}. The --json payload speaks data, never relay addressing.`,
206
+ severity: "fail",
207
+ });
208
+ }
209
+ walkRelayKeys(value, path ? `${path}.${key}` : key, lines, findings);
210
+ }
211
+ }
212
+ const relayJsonExclusion = (lines, _params, findings) => {
213
+ // 1. The relay line itself, rendered or quoted, anywhere in the payload.
214
+ relaySignatureFindings("relay-json-exclusion", lines, "The update-notice relay line reaches a payload an agent parses as data. The notice rides stderr only — never stdout, never --json.", findings);
215
+ // 2. Addressing vocabulary as JSON keys — parseable payloads only, so the
216
+ // key match is structural, not a substring guess.
217
+ let payload;
218
+ try {
219
+ payload = JSON.parse(lines.map(({ text }) => text).join("\n"));
220
+ }
221
+ catch {
222
+ payload = undefined;
223
+ }
224
+ if (payload !== undefined) {
225
+ walkRelayKeys(payload, "", lines, findings);
226
+ return;
227
+ }
228
+ // Unparseable: a corrupted payload leaves the relay-line scan above as the
229
+ // evidence; an artifact with no JSON at all is the wrong target and the
230
+ // check says so instead of reading as covered.
231
+ const hasStructure = lines.some(({ text }) => text.includes("{"));
232
+ findings.push({
233
+ check: "relay-json-exclusion",
234
+ line: 1,
235
+ phrase: hasStructure ? "unparseable JSON" : "no JSON payload",
236
+ message: hasStructure
237
+ ? "The artifact is not valid JSON, so key-level relay addressing cannot be measured. If this is a corrupted payload, the relay-line scan above carries the evidence."
238
+ : "The artifact carries no JSON payload; this check targets the --json output surface and cannot see anything here.",
239
+ severity: "warn",
240
+ });
241
+ };
242
+ const relayStdoutClean = (lines, _params, findings) => {
243
+ const channels = channelLines(lines);
244
+ if (!channels) {
245
+ noCaptureSections("relay-stdout-clean", findings);
246
+ return;
247
+ }
248
+ relaySignatureFindings("relay-stdout-clean", channels.stdout, "The update-notice relay line reached stdout — the machine-readable channel an agent parses. The relay rides stderr only.", findings);
249
+ };
250
+ const relayHeadlessSilent = (lines, _params, findings) => {
251
+ const channels = channelLines(lines);
252
+ if (!channels) {
253
+ noCaptureSections("relay-headless-silent", findings);
254
+ return;
255
+ }
256
+ const message = "A headless run carried the update-notice relay line. With no agent present, the relay has no addressee — silence is the contract.";
257
+ relaySignatureFindings("relay-headless-silent", channels.stdout, message, findings);
258
+ relaySignatureFindings("relay-headless-silent", channels.stderr, message, findings);
259
+ };
260
+ const REGISTRY = {
261
+ "one-number-rule": oneNumberRule,
262
+ "length-limit": lengthLimit,
263
+ "number-sourcing": numberSourcing,
264
+ "flag-conservation": flagConservation,
265
+ "relay-json-exclusion": relayJsonExclusion,
266
+ "relay-stdout-clean": relayStdoutClean,
267
+ "relay-headless-silent": relayHeadlessSilent,
268
+ };
269
+ export const DETERMINISTIC_CHECK_IDS = Object.freeze(Object.keys(REGISTRY));
270
+ /** Run the requested deterministic checks over an artifact's markdown. */
271
+ export function runDeterministicChecks(artifactText, checks, options = {}) {
272
+ const findings = [];
273
+ const lines = proseLines(artifactText);
274
+ for (const { id, params } of checks) {
275
+ const check = REGISTRY[id];
276
+ if (!check) {
277
+ // Refuse unknown input rather than guess — an eval that silently
278
+ // no-ops reads as "covered" when it is not.
279
+ findings.push({
280
+ check: id,
281
+ line: 1,
282
+ phrase: id,
283
+ message: `Unknown deterministic check. Known checks: ${DETERMINISTIC_CHECK_IDS.join(", ")}.`,
284
+ severity: "fail",
285
+ });
286
+ continue;
287
+ }
288
+ check(lines, params ?? {}, findings);
289
+ }
290
+ if (options.strict) {
291
+ for (const finding of findings)
292
+ finding.severity = "fail";
293
+ }
294
+ return { ok: findings.every((finding) => finding.severity !== "fail"), findings };
295
+ }
@@ -0,0 +1,56 @@
1
+ import { type CalibrationReport } from "./evalCalibration.js";
2
+ import { type EvalChecksResult } from "./evalChecks.js";
3
+ import { type JudgeTransport } from "./evalJudge.js";
4
+ import type { EvalRecord } from "./evalRecord.js";
5
+ export type CompiledJudge = {
6
+ id: string;
7
+ /** The criterion the judge scores, verbatim from the record. */
8
+ criterion: string;
9
+ /** The judge model pinned by the record — calibration is keyed to it. */
10
+ model: string;
11
+ };
12
+ export type CompiledSuite = {
13
+ /** Deterministic records, run natively. */
14
+ deterministic: EvalRecord[];
15
+ judges: EvalRecord[];
16
+ /** The judge plan: what will be asked, of which model. */
17
+ judgePlan: CompiledJudge[];
18
+ /** Approved-only is the rule (R-004); what was skipped stays visible. */
19
+ skippedUnapproved: string[];
20
+ };
21
+ export type JudgeOutcome = {
22
+ id: string;
23
+ verdict: "pass" | "fail" | "error";
24
+ /** True until the judge's calibration report exists and holds (D-007). */
25
+ advisory: boolean;
26
+ /** Why the judge is (or is not) allowed to gate. */
27
+ gating_reason: string;
28
+ /** The order-swap check disagreed with itself on this artifact. */
29
+ flipped?: boolean;
30
+ /** Verdict from the required confirmation; absent if the first call errored. */
31
+ swapped?: "pass" | "fail" | "error";
32
+ reason?: string;
33
+ };
34
+ export type SuiteRunResult = {
35
+ /** True means no gating check failed, not that any gating check passed. Read status. */
36
+ ok: boolean;
37
+ /** Coverage: zero approved checks is not_run; only uncalibrated judges is advisory_only. */
38
+ status: "passed" | "failed" | "not_run" | "advisory_only";
39
+ deterministic: EvalChecksResult;
40
+ judges: JudgeOutcome[];
41
+ skippedUnapproved: string[];
42
+ };
43
+ /** Plan an approved suite: split kinds and render each judge's ask. */
44
+ export declare function compileSuite(records: EvalRecord[]): CompiledSuite;
45
+ /**
46
+ * Run a compiled suite over an artifact. Deterministic checks gate; judge
47
+ * verdicts gate only when calibrated — uncalibrated judges are advisory-only
48
+ * and can never fail the run (R-003/D-007).
49
+ */
50
+ export declare function runSuite(compiled: CompiledSuite, artifactText: string, options?: {
51
+ strict?: boolean;
52
+ /** Resolve a judge record's calibration reference to its report. */
53
+ calibration?: (record: EvalRecord) => CalibrationReport | undefined;
54
+ /** Injected for tests; defaults to the real model call. */
55
+ transport?: JudgeTransport;
56
+ }): Promise<SuiteRunResult>;
@@ -0,0 +1,58 @@
1
+ import { judgeMayGate } from "./evalCalibration.js";
2
+ import { runDeterministicChecks } from "./evalChecks.js";
3
+ import { callJudgeWithSwap } from "./evalJudge.js";
4
+ /** Plan an approved suite: split kinds and render each judge's ask. */
5
+ export function compileSuite(records) {
6
+ const approved = records.filter((record) => record.approved);
7
+ const skippedUnapproved = records
8
+ .filter((record) => !record.approved)
9
+ .map((record) => record.id);
10
+ const deterministic = approved.filter((record) => record.kind === "deterministic");
11
+ const judges = approved.filter((record) => record.kind === "judge");
12
+ return {
13
+ deterministic,
14
+ judges,
15
+ judgePlan: judges.map((record) => ({
16
+ id: record.id,
17
+ criterion: record.judge.prompt,
18
+ model: record.judge.model,
19
+ })),
20
+ skippedUnapproved,
21
+ };
22
+ }
23
+ /**
24
+ * Run a compiled suite over an artifact. Deterministic checks gate; judge
25
+ * verdicts gate only when calibrated — uncalibrated judges are advisory-only
26
+ * and can never fail the run (R-003/D-007).
27
+ */
28
+ export async function runSuite(compiled, artifactText, options = {}) {
29
+ const deterministic = runDeterministicChecks(artifactText, compiled.deterministic.map((record) => ({
30
+ id: record.check.id,
31
+ params: record.check.params,
32
+ })), options);
33
+ const judges = [];
34
+ for (const record of compiled.judges) {
35
+ const gate = judgeMayGate(record.judge, record.judge?.calibration ? options.calibration?.(record) : undefined);
36
+ const call = await callJudgeWithSwap({ prompt: record.judge.prompt, model: record.judge.model, artifact: artifactText }, options.transport);
37
+ judges.push({
38
+ id: record.id,
39
+ verdict: call.verdict,
40
+ advisory: !gate.allowed,
41
+ gating_reason: gate.reason,
42
+ flipped: call.flipped,
43
+ swapped: call.swapped,
44
+ reason: call.error ?? call.note,
45
+ });
46
+ }
47
+ const gatingJudgeFailed = judges.some((judge) => !judge.advisory && judge.verdict !== "pass");
48
+ const ran = compiled.deterministic.length + judges.length;
49
+ const gating = compiled.deterministic.length + judges.filter(judge => !judge.advisory).length;
50
+ const ok = ran > 0 && deterministic.ok && !gatingJudgeFailed;
51
+ return {
52
+ ok,
53
+ status: ran === 0 ? "not_run" : gating === 0 ? "advisory_only" : ok ? "passed" : "failed",
54
+ deterministic,
55
+ judges,
56
+ skippedUnapproved: compiled.skippedUnapproved,
57
+ };
58
+ }
@@ -0,0 +1,60 @@
1
+ import type { SuiteRunResult } from "./evalCompile.js";
2
+ /** R-005's agreed budget. A loop without one is the B4 boundary. */
3
+ export declare const IMPROVE_MAX_ROUNDS = 3;
4
+ /**
5
+ * The substance a round may never trade for a better score. Each guard is a
6
+ * countable property of the artifact, because "did it keep the counter-case"
7
+ * has to be decidable without asking a judge — a judge is exactly the thing
8
+ * that might be gamed here.
9
+ */
10
+ export type ConservationGuard = {
11
+ id: "citations" | "estimate-flags" | "counter-case";
12
+ label: string;
13
+ /** How many instances the artifact carries. Never allowed to fall. */
14
+ count: (artifact: string) => number;
15
+ };
16
+ export declare const CONSERVATION_GUARDS: readonly ConservationGuard[];
17
+ export type ConservationBreach = {
18
+ guard: ConservationGuard["id"];
19
+ label: string;
20
+ before: number;
21
+ after: number;
22
+ };
23
+ /**
24
+ * Compare a proposed revision against the artifact it replaces. A guard breaks
25
+ * when its count falls; holding steady or rising is fine, because the loop is
26
+ * guarding against removal, not against editing.
27
+ */
28
+ export declare function conservationBreaches(before: string, after: string): ConservationBreach[];
29
+ export type ImproveStop = "all-checks-pass" | "evaluation-error" | "not-run" | "no-change" | "budget-spent" | "conservation-refused";
30
+ export type ImproveRound = {
31
+ round: number;
32
+ /** Gating failures after this round: deterministic misses plus calibrated judge fails. */
33
+ failing: string[];
34
+ /** Judge verdicts that were reported but could not gate. */
35
+ advisory: string[];
36
+ /** Present when the round's revision was refused. */
37
+ refused?: ConservationBreach[];
38
+ };
39
+ export type ImproveResult = {
40
+ rounds: ImproveRound[];
41
+ stop: ImproveStop;
42
+ /** The artifact the loop landed on — the last accepted revision. */
43
+ artifact: string;
44
+ };
45
+ /** Produce the next revision. Returns null when it has nothing further to try. */
46
+ export type ImproveReviser = (artifact: string, failing: string[], round: number) => Promise<string | null>;
47
+ /** Score an artifact. Injected so the loop is testable without a model call. */
48
+ export type ImproveScorer = (artifact: string) => Promise<SuiteRunResult>;
49
+ /**
50
+ * Run the loop.
51
+ *
52
+ * A calibrated judge that would stop the loop is asked twice: a single
53
+ * stochastic flip should not end a run, so the failure stands only if it
54
+ * repeats (R-005). Deterministic checks are never re-asked — they do not flip.
55
+ */
56
+ export declare function runImproveLoop(artifact: string, score: ImproveScorer, revise: ImproveReviser, options?: {
57
+ maxRounds?: number;
58
+ }): Promise<ImproveResult>;
59
+ /** Where it landed and why it stopped — printed every run, human surfaces only. */
60
+ export declare function renderImproveLanding(result: ImproveResult, glyphsOn: boolean): string;
@@ -0,0 +1,175 @@
1
+ // foo-eval-system-v0 T-006 (R-005): the critique-and-improve loop, budgeted.
2
+ //
3
+ // The loop is roast → apply the roast's next prompt → re-score, and its danger
4
+ // is obvious once named: a scoring loop optimises whatever it can measure, so
5
+ // the cheapest way to raise a score is to delete the substance the score does
6
+ // not look at. A round that scores better by cutting the counter-case, the
7
+ // citations, or the estimate flags has not improved the artifact; it has eaten
8
+ // it. Those cuts are refused here, by name, rather than celebrated.
9
+ //
10
+ // Everything else is budget and honesty: at most three rounds, early stop when
11
+ // nothing is failing or nothing changed, uncalibrated judges never allowed to
12
+ // stop or extend a round, and a landing report every run that says where it
13
+ // stopped and why.
14
+ import { withGlyph } from "./statusGlyphs.js";
15
+ /** R-005's agreed budget. A loop without one is the B4 boundary. */
16
+ export const IMPROVE_MAX_ROUNDS = 3;
17
+ const CITATION = /\[[^\]\n]*·[^\]\n]*\]|\[\d+\]|\(https?:\/\/[^)\s]+\)/g;
18
+ const ESTIMATE_FLAG = /(?<![\w-])(?:estimate|estimated|approx\.?|approximately|~\d|assumption|assumed)(?![\w-])/gi;
19
+ const COUNTER_CASE = /(?<![\w-])(?:however|but |counter-case|on the other hand|the case against|dissent|objection|risk[s]? (?:i|we)['’]d flag)(?![\w-])/gi;
20
+ export const CONSERVATION_GUARDS = [
21
+ { id: "citations", label: "citations", count: (text) => (text.match(CITATION) ?? []).length },
22
+ { id: "estimate-flags", label: "estimate flags", count: (text) => (text.match(ESTIMATE_FLAG) ?? []).length },
23
+ { id: "counter-case", label: "counter-case", count: (text) => (text.match(COUNTER_CASE) ?? []).length },
24
+ ];
25
+ /**
26
+ * Compare a proposed revision against the artifact it replaces. A guard breaks
27
+ * when its count falls; holding steady or rising is fine, because the loop is
28
+ * guarding against removal, not against editing.
29
+ */
30
+ export function conservationBreaches(before, after) {
31
+ const breaches = [];
32
+ for (const guard of CONSERVATION_GUARDS) {
33
+ const had = guard.count(before);
34
+ const has = guard.count(after);
35
+ if (has < had)
36
+ breaches.push({ guard: guard.id, label: guard.label, before: had, after: has });
37
+ }
38
+ return breaches;
39
+ }
40
+ function gatingFailures(result) {
41
+ const failures = [];
42
+ for (const finding of result.deterministic.findings) {
43
+ // Only unambiguous misses gate; advisory findings are reported, never fatal
44
+ // (R-002, carrying the research-format-gate posture).
45
+ if (finding.severity === "fail")
46
+ failures.push(`${finding.check}: ${finding.message}`);
47
+ }
48
+ for (const judge of result.judges) {
49
+ // An uncalibrated judge is reported and ignored. It may not stop the loop
50
+ // and it may not extend it — being wrong in either direction is expensive.
51
+ if (judge.advisory)
52
+ continue;
53
+ if (judge.verdict === "fail")
54
+ failures.push(`${judge.id}: ${judge.reason ?? "judge failed"}`);
55
+ }
56
+ return failures;
57
+ }
58
+ function advisoryNotes(result) {
59
+ return result.judges
60
+ .filter((judge) => judge.advisory && judge.verdict !== "pass")
61
+ .map((judge) => `${judge.id}: ${judge.verdict} (advisory — ${judge.gating_reason})`);
62
+ }
63
+ /** Missing checks or a failed calibrated judge cannot authorize improvement. */
64
+ function unavailableEvaluation(result) {
65
+ if (result.status === "not_run")
66
+ return { stop: "not-run", reasons: ["No approved checks ran."] };
67
+ if (result.status === "advisory_only")
68
+ return { stop: "not-run", reasons: ["No gating checks ran — judge results are advisory only."] };
69
+ const errors = result.judges.filter(judge => !judge.advisory && judge.verdict === "error");
70
+ if (errors.length)
71
+ return {
72
+ stop: "evaluation-error",
73
+ reasons: errors.map(judge => `${judge.id}: ${judge.reason ?? "judge error"}`),
74
+ };
75
+ return undefined;
76
+ }
77
+ /**
78
+ * Run the loop.
79
+ *
80
+ * A calibrated judge that would stop the loop is asked twice: a single
81
+ * stochastic flip should not end a run, so the failure stands only if it
82
+ * repeats (R-005). Deterministic checks are never re-asked — they do not flip.
83
+ */
84
+ export async function runImproveLoop(artifact, score, revise, options = {}) {
85
+ const budget = Math.max(1, Math.min(options.maxRounds ?? IMPROVE_MAX_ROUNDS, IMPROVE_MAX_ROUNDS));
86
+ const rounds = [];
87
+ let current = artifact;
88
+ for (let round = 1; round <= budget; round += 1) {
89
+ let result = await score(current);
90
+ const unavailable = unavailableEvaluation(result);
91
+ if (unavailable) {
92
+ rounds.push({ round, failing: unavailable.reasons, advisory: advisoryNotes(result) });
93
+ return { rounds, stop: unavailable.stop, artifact: current };
94
+ }
95
+ let failing = gatingFailures(result);
96
+ // Re-ask once before a judge verdict is allowed to end the run.
97
+ if (failing.length > 0 && result.judges.some((judge) => !judge.advisory && judge.verdict === "fail")) {
98
+ const second = await score(current);
99
+ const unavailable = unavailableEvaluation(second);
100
+ if (unavailable) {
101
+ rounds.push({ round, failing: unavailable.reasons, advisory: advisoryNotes(second) });
102
+ return { rounds, stop: unavailable.stop, artifact: current };
103
+ }
104
+ const stillFailing = gatingFailures(second);
105
+ if (stillFailing.length === 0) {
106
+ result = second;
107
+ failing = stillFailing;
108
+ }
109
+ }
110
+ if (failing.length === 0) {
111
+ rounds.push({ round, failing: [], advisory: advisoryNotes(result) });
112
+ return { rounds, stop: "all-checks-pass", artifact: current };
113
+ }
114
+ const proposed = await revise(current, failing, round);
115
+ if (proposed === null || proposed === current) {
116
+ rounds.push({ round, failing, advisory: advisoryNotes(result) });
117
+ return { rounds, stop: "no-change", artifact: current };
118
+ }
119
+ const breaches = conservationBreaches(current, proposed);
120
+ if (breaches.length > 0) {
121
+ // The round is refused, not scored. Accepting it and reporting the breach
122
+ // afterwards would still leave the cut substance in the landed artifact.
123
+ rounds.push({ round, failing, advisory: advisoryNotes(result), refused: breaches });
124
+ return { rounds, stop: "conservation-refused", artifact: current };
125
+ }
126
+ rounds.push({ round, failing, advisory: advisoryNotes(result) });
127
+ current = proposed;
128
+ }
129
+ return { rounds, stop: "budget-spent", artifact: current };
130
+ }
131
+ /** Where it landed and why it stopped — printed every run, human surfaces only. */
132
+ export function renderImproveLanding(result, glyphsOn) {
133
+ const lines = [];
134
+ const last = result.rounds.at(-1);
135
+ switch (result.stop) {
136
+ case "all-checks-pass":
137
+ lines.push(withGlyph("proven", `improve loop — every gating check passes after ${result.rounds.length} round(s).`, glyphsOn));
138
+ break;
139
+ case "evaluation-error":
140
+ lines.push(withGlyph("blocked", "improve loop — evaluation failed to produce a verdict; the artifact was kept.", glyphsOn));
141
+ break;
142
+ case "not-run":
143
+ lines.push(withGlyph("needs_input", "improve loop — no gating checks ran; the artifact was kept.", glyphsOn));
144
+ break;
145
+ case "no-change":
146
+ lines.push(withGlyph("claimed", `improve loop — stopped at round ${result.rounds.length}: the round changed nothing.`, glyphsOn));
147
+ break;
148
+ case "budget-spent":
149
+ lines.push(withGlyph("needs_input", `improve loop — spent its ${result.rounds.length}-round budget with checks still failing.`, glyphsOn));
150
+ break;
151
+ case "conservation-refused":
152
+ lines.push(withGlyph("blocked", `improve loop — refused round ${result.rounds.length}: it raised the score by cutting guarded substance.`, glyphsOn));
153
+ break;
154
+ }
155
+ if (last?.refused) {
156
+ lines.push("");
157
+ for (const breach of last.refused) {
158
+ lines.push(` ${breach.label}: ${breach.before} → ${breach.after} — a round may not trade this for a better score.`);
159
+ }
160
+ }
161
+ if (last && last.failing.length > 0 && result.stop !== "all-checks-pass") {
162
+ lines.push("");
163
+ lines.push("Still failing:");
164
+ for (const failure of last.failing)
165
+ lines.push(` ${failure}`);
166
+ }
167
+ const advisory = last?.advisory ?? [];
168
+ if (advisory.length > 0) {
169
+ lines.push("");
170
+ lines.push("Advisory (reported, never counted):");
171
+ for (const note of advisory)
172
+ lines.push(` ${note}`);
173
+ }
174
+ return lines.join("\n");
175
+ }