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,423 @@
1
+ // ideate-cost-v1 (R-002, T-003) — the diversity meter, computed.
2
+ //
3
+ // The v0 run had the orchestrator read 70 markdown ideas and hand-cluster them;
4
+ // the recorded `near_dupes_merged: 38` was a number a human eyeballed while
5
+ // reading, and every downstream consumer treated it as measured. That is worse
6
+ // than no number. So ideator/panelist output becomes a validated object, and
7
+ // merging becomes deterministic code over those objects: same ideas in, same
8
+ // meter out, reproducible by anyone holding the record.
9
+ //
10
+ // RISK-002: `mechanism` is free text that survives the schema so nuance is not
11
+ // flattened — it is read by humans and NEVER enters the clustering feature set.
12
+ // One idea, as an ideator or panelist returns it.
13
+ import { parse as parseYaml } from "../vendorYaml.js";
14
+ // Which clusterer produced a meter. Stamped into the record next to the meter
15
+ // so a reader can tell a number computed by today's code from one computed by
16
+ // an older, weaker one — and so the provenance gate can say "recompute this"
17
+ // instead of "your arithmetic is wrong" when the algorithm moves under a record.
18
+ //
19
+ // v1 was set-Jaccard over unweighted tokens at 0.5. Bump this whenever a change
20
+ // would move the meter on the same pool.
21
+ //
22
+ // v3 (#693): v2 clustered on claim + assumption + relied-on facts, which reads
23
+ // TOPIC diversity — one move repeated across twenty spend categories scored as
24
+ // twenty clusters, because each category's rare nouns drove the vectors apart
25
+ // while the shared move lived in fields the clusterer never saw. v3 adds the
26
+ // frames-v1 `reasoning` field to the feature set: the reasoning carries the
27
+ // move (the failure ingredients enumerated, the source domain named), so two
28
+ // ideas making the same move now share the vocabulary that actually matters.
29
+ // On pre-frames-v1 pools reasoning is empty and v3 computes exactly what v2
30
+ // computed, so old measured records still reproduce.
31
+ export const CLUSTERER_ID = "idf-cosine-v3-moves";
32
+ // Two ideas are the same idea when their weighted feature vectors point this
33
+ // close to the same direction. Held here so the number is auditable rather than
34
+ // implicit, and calibrated against a real pool rather than picked by taste — see
35
+ // the note on `similarity` below for the measurement.
36
+ export const NEAR_DUPE_THRESHOLD = 0.25;
37
+ // A floor under every token's IDF weight. Pure IDF has a degenerate case that
38
+ // matters here: when EVERY idea in the pool rests on the same fact, that fact
39
+ // appears in every document, so IDF calls it uninformative and starves the very
40
+ // signal that makes the pool homogeneous — a pool that is 100% one move would
41
+ // read as maximally diverse, which is the #613 failure wearing a new hat. The
42
+ // floor keeps universally-shared content contributing. Measured across both
43
+ // cases: 0.4 is the smallest floor that collapses a fully convergent pool to one
44
+ // cluster while leaving unrelated ideas apart and holding precision at 0.98 on
45
+ // the real 47-idea pool.
46
+ const IDF_FLOOR = 0.4;
47
+ // How much harder a shared empirical dependency counts than a shared ordinary
48
+ // word. Two ideators who independently leaned on the same observed fact are
49
+ // usually making the same move; two who both said "harness" are not.
50
+ const RELIED_WEIGHT = 3;
51
+ // v3: how much a shared reasoning token counts. The reasoning field carries the
52
+ // move itself, so it sits between ordinary prose (1) and a shared empirical
53
+ // dependency (3): strong evidence of the same move, weaker than the same fact.
54
+ const REASONING_WEIGHT = 2;
55
+ const STOPWORDS = new Set([
56
+ "a", "an", "and", "are", "as", "at", "be", "but", "by", "can", "for", "from", "has", "have", "in", "into",
57
+ "is", "it", "its", "not", "of", "on", "or", "so", "that", "the", "their", "then", "there", "they", "this",
58
+ "to", "was", "we", "were", "when", "which", "will", "with", "you", "your",
59
+ ]);
60
+ // Light suffix folding so "pin"/"pinning", "invoke"/"invocation" and
61
+ // "dependency"/"dependencies" are one feature. Deliberately crude: a real
62
+ // stemmer is a dependency, and the failure mode we care about (the same
63
+ // mechanism described in two vocabularies) is mostly carried by rare nouns that
64
+ // survive this untouched.
65
+ const SUFFIXES = ["ing", "edly", "ed", "es", "s", "ly", "ment", "tion", "ance", "ence"];
66
+ function stem(word) {
67
+ for (const suffix of SUFFIXES) {
68
+ if (word.length - suffix.length >= 4 && word.endsWith(suffix))
69
+ return word.slice(0, -suffix.length);
70
+ }
71
+ return word;
72
+ }
73
+ function tokens(text) {
74
+ return text
75
+ .toLowerCase()
76
+ .split(/[^a-z0-9]+/)
77
+ .filter((t) => t.length > 2 && !STOPWORDS.has(t))
78
+ .map(stem);
79
+ }
80
+ // The clustering feature set: what the idea says (claim), what it rests on
81
+ // (assumption), and which empirical claims it relies on — the last weighted
82
+ // `RELIED_WEIGHT` times heavier and, unlike v1, sharing one namespace with the
83
+ // prose. v1 namespaced relied-on tokens as `relied:<t>`, which meant the fact
84
+ // "interactive is Boolean(process.stdout.isTTY)" in one idea's `claims_relied_on`
85
+ // could never match the same fact stated in another idea's `claim`. That is
86
+ // precisely the match we need, so the namespace is gone; IDF now does the job
87
+ // namespacing was there for, by starving common words of weight.
88
+ //
89
+ // `mechanism`, `frame`, and `lens` remain deliberately absent: mechanism is the
90
+ // nuance we promised not to cluster on (RISK-002), and frame/lens are the cell
91
+ // the idea came from, so including them would make independence look like
92
+ // similarity. `reasoning` (v3) is the exception that proves the rule: it holds
93
+ // the MOVE, not the nuance, and the move is exactly what the meter must read.
94
+ export function featureSet(idea) {
95
+ const feats = new Map();
96
+ const add = (t, weight) => feats.set(t, (feats.get(t) ?? 0) + weight);
97
+ for (const t of tokens(idea.claim))
98
+ add(t, 1);
99
+ for (const t of tokens(idea.assumption))
100
+ add(t, 1);
101
+ // v3 (#693): the reasoning content joins the feature set — it is where the
102
+ // move lives. The frames-v1 shape LABELS ("guarantee-failure:", "bedrock:")
103
+ // are stripped first: every idea in the same frame carries the same labels,
104
+ // so leaving them in would make sharing a frame look like sharing a move.
105
+ for (const t of tokens((idea.reasoning ?? "").replace(/\b[a-z][a-z0-9-]*:/gi, " ")))
106
+ add(t, REASONING_WEIGHT);
107
+ for (const claim of idea.claims_relied_on)
108
+ for (const t of tokens(claim))
109
+ add(t, RELIED_WEIGHT);
110
+ return feats;
111
+ }
112
+ // Inverse document frequency across the pool being measured. This is what makes
113
+ // the meter read ideas rather than wordcounts: in a pool about productfoo's CLI, every
114
+ // idea says "foo" and "command", so those carry almost no weight, while
115
+ // "isTTY" or "invocation" — said by only the ideators who found the same
116
+ // mechanism — carry a lot.
117
+ //
118
+ // Note the consequence, which is a property of the measure and not a bug: IDF is
119
+ // computed over the pool, so similarity is a fact about ideas *in this pool*,
120
+ // not an absolute. Adding ideas can move existing pair scores. The meter is a
121
+ // statement about a pool, and it is recomputed whole, so this stays coherent —
122
+ // but it is why a meter must be recomputed rather than incrementally patched.
123
+ function inverseDocumentFrequency(pool) {
124
+ const documentCount = new Map();
125
+ for (const feats of pool) {
126
+ for (const t of feats.keys())
127
+ documentCount.set(t, (documentCount.get(t) ?? 0) + 1);
128
+ }
129
+ const idf = new Map();
130
+ for (const [t, df] of documentCount)
131
+ idf.set(t, Math.log((pool.length + 1) / (df + 0.5)) + IDF_FLOOR);
132
+ return idf;
133
+ }
134
+ function cosine(a, b, idf) {
135
+ let dot = 0;
136
+ let normA = 0;
137
+ let normB = 0;
138
+ for (const [t, weight] of a) {
139
+ const w = weight * (idf.get(t) ?? 0);
140
+ normA += w * w;
141
+ const other = b.get(t);
142
+ if (other !== undefined)
143
+ dot += w * other * (idf.get(t) ?? 0);
144
+ }
145
+ for (const [t, weight] of b) {
146
+ const w = weight * (idf.get(t) ?? 0);
147
+ normB += w * w;
148
+ }
149
+ if (normA === 0 || normB === 0)
150
+ return 0;
151
+ return dot / (Math.sqrt(normA) * Math.sqrt(normB));
152
+ }
153
+ // Similarity of two ideas *within a pool*. The pool argument is required because
154
+ // the weighting is IDF — see above. `similarityIn` is the honest signature;
155
+ // `similarity` keeps the old two-argument shape for callers measuring a single
156
+ // pair, by treating the pair as its own pool.
157
+ //
158
+ // Calibration (2026-07-24, the 47-idea pool from the run that filed #613, whose
159
+ // four convergent clusters were identified by reading all 47): v1's Jaccard-at-
160
+ // 0.5 merged 0 of 78 same-idea pairs — and the same-pair and different-pair
161
+ // score distributions overlapped under that feature set, so *no* threshold could
162
+ // have separated them. This measure does: at 0.25 it recovers the clusters with
163
+ // precision 0.98 and recall 0.77, and it reads a fully convergent pool as one
164
+ // cluster rather than as maximum diversity.
165
+ export function similarityIn(a, b, pool) {
166
+ const feats = pool.map(featureSet);
167
+ return cosine(featureSet(a), featureSet(b), inverseDocumentFrequency(feats));
168
+ }
169
+ export function similarity(a, b) {
170
+ return similarityIn(a, b, [a, b]);
171
+ }
172
+ // Average-linkage agglomerative clustering: repeatedly merge the two closest
173
+ // clusters, where distance between clusters is the mean similarity across all
174
+ // their member pairs, until nothing is closer than NEAR_DUPE_THRESHOLD.
175
+ //
176
+ // v1 used single linkage, on the reasoning that near-dupe is transitive. Under a
177
+ // measure sensitive enough to actually find near-dupes, it isn't: single linkage
178
+ // chains, so one lucky link between two genuinely different ideas fuses their
179
+ // whole clusters. Measured on the #613 pool, single linkage at this threshold
180
+ // collapsed 47 ideas into 15 clusters and fused two distinct attractors into one
181
+ // blob of 14 (precision 0.40). Average linkage on the same pool and threshold
182
+ // gives 23 clusters at precision 0.98, and degrades gracefully as the threshold
183
+ // moves rather than falling off a cliff.
184
+ //
185
+ // That asymmetry is deliberate: over-merging invents convergence that is not
186
+ // there, which is the failure this meter exists to prevent. When the clusterer
187
+ // is unsure, it should leave two ideas apart and let a reader find the overlap.
188
+ //
189
+ // The result does not depend on the order the ideators happened to report in — a
190
+ // meter that moves when you shuffle the input is not a measurement — so ties are
191
+ // broken on idea id, not on position.
192
+ export function computeDiversity(ideas, exhausted = false) {
193
+ // Feature vectors and the pool's IDF are computed once, not per pair: the
194
+ // comparison is O(n²) and rebuilding the weighting inside it would be O(n³).
195
+ const feats = ideas.map(featureSet);
196
+ const idf = inverseDocumentFrequency(feats);
197
+ const n = ideas.length;
198
+ const pair = Array.from({ length: n }, () => new Array(n).fill(0));
199
+ for (let i = 0; i < n; i += 1) {
200
+ for (let j = i + 1; j < n; j += 1) {
201
+ pair[i][j] = pair[j][i] = cosine(feats[i], feats[j], idf);
202
+ }
203
+ }
204
+ // Clusters as index lists, in first-appearance order. `members` is kept sorted
205
+ // by original index so cluster contents render in pool order.
206
+ let groups = ideas.map((_, i) => [i]);
207
+ const meanSimilarity = (a, b) => {
208
+ let total = 0;
209
+ for (const i of a)
210
+ for (const j of b)
211
+ total += pair[i][j];
212
+ return total / (a.length * b.length);
213
+ };
214
+ for (;;) {
215
+ let best = -1;
216
+ let bestX = -1;
217
+ let bestY = -1;
218
+ for (let x = 0; x < groups.length; x += 1) {
219
+ for (let y = x + 1; y < groups.length; y += 1) {
220
+ const value = meanSimilarity(groups[x], groups[y]);
221
+ if (value < NEAR_DUPE_THRESHOLD)
222
+ continue;
223
+ // Strictly-greater keeps the first pair on a tie, and because groups are
224
+ // held in first-appearance order that first pair is a function of the
225
+ // ideas, not of the order they arrived in.
226
+ if (value > best) {
227
+ best = value;
228
+ bestX = x;
229
+ bestY = y;
230
+ }
231
+ }
232
+ }
233
+ if (bestX === -1)
234
+ break;
235
+ const merged = [...groups[bestX], ...groups[bestY]].sort((a, b) => a - b);
236
+ groups = groups.filter((_, i) => i !== bestX && i !== bestY);
237
+ groups.push(merged);
238
+ groups.sort((a, b) => a[0] - b[0]);
239
+ }
240
+ const clusters = groups.map((group) => group.map((i) => ideas[i].id));
241
+ return {
242
+ raw: ideas.length,
243
+ distinct_clusters: clusters.length,
244
+ // The whole definition, stated once: a merge is an idea that did not earn
245
+ // its own cluster. Nothing here is a judgment call.
246
+ near_dupes_merged: ideas.length - clusters.length,
247
+ exhausted,
248
+ clusters,
249
+ };
250
+ }
251
+ // --- Record I/O ---------------------------------------------------------------
252
+ // The structured pool lives in the record inside a fenced block so the record
253
+ // stays one human-readable file and still carries its own show-your-work.
254
+ export const IDEAS_FENCE_OPEN = "```json ideas";
255
+ const IDEAS_BLOCK = /```json ideas\s*\n([\s\S]*?)```/;
256
+ const REQUIRED_TEXT = ["id", "claim", "frame", "lens", "mechanism", "assumption", "novelty"];
257
+ // Validation is presence-and-shape only. It refuses prose where an object
258
+ // belongs; it does not grade the idea — that is what the panel is for.
259
+ export function parseIdeaObjects(recordText) {
260
+ const block = recordText.match(IDEAS_BLOCK);
261
+ if (!block)
262
+ return { ideas: [], errors: [], present: false };
263
+ let parsed;
264
+ try {
265
+ parsed = JSON.parse(block[1].trim() || "[]");
266
+ }
267
+ catch (err) {
268
+ return { ideas: [], errors: [`ideas block is not valid JSON: ${err.message}`], present: true };
269
+ }
270
+ if (!Array.isArray(parsed))
271
+ return { ideas: [], errors: ["ideas block must be a JSON array"], present: true };
272
+ const errors = [];
273
+ const ideas = [];
274
+ const seen = new Set();
275
+ parsed.forEach((entry, i) => {
276
+ const at = `idea[${i}]`;
277
+ if (typeof entry !== "object" || entry === null || Array.isArray(entry)) {
278
+ errors.push(`${at}: not an object`);
279
+ return;
280
+ }
281
+ const obj = entry;
282
+ const missing = REQUIRED_TEXT.filter((f) => typeof obj[f] !== "string" || obj[f].trim() === "");
283
+ if (missing.length)
284
+ errors.push(`${at}: missing or empty ${missing.join(", ")}`);
285
+ const relied = obj.claims_relied_on;
286
+ if (!Array.isArray(relied) || relied.some((c) => typeof c !== "string")) {
287
+ errors.push(`${at}: claims_relied_on must be an array of strings (use [] when the idea rests on none)`);
288
+ return;
289
+ }
290
+ if (missing.length)
291
+ return;
292
+ const id = String(obj.id);
293
+ if (seen.has(id))
294
+ errors.push(`${at}: duplicate id ${id}`);
295
+ seen.add(id);
296
+ ideas.push({
297
+ id,
298
+ claim: String(obj.claim),
299
+ frame: String(obj.frame),
300
+ lens: String(obj.lens),
301
+ // Lenient on purpose: pre-frames-v1 records have no reasoning field, and
302
+ // the provenance gate must keep reproducing their meters. Presence is
303
+ // enforced by the frame-reasoning gate, only on frames-v1 records.
304
+ reasoning: typeof obj.reasoning === "string" ? obj.reasoning : "",
305
+ mechanism: String(obj.mechanism),
306
+ assumption: String(obj.assumption),
307
+ novelty: String(obj.novelty),
308
+ claims_relied_on: relied,
309
+ });
310
+ });
311
+ return { ideas, errors, present: true };
312
+ }
313
+ export const DIVERSITY_METER_LINE = /^diversity:\s*\{\s*raw:\s*(\d+),\s*distinct_clusters:\s*(\d+),\s*near_dupes_merged:\s*(\d+),\s*exhausted:\s*(true|false)\s*\}/m;
314
+ export function readDeclaredMeter(recordText) {
315
+ const m = recordText.match(DIVERSITY_METER_LINE);
316
+ if (!m)
317
+ return null;
318
+ return {
319
+ raw: Number(m[1]),
320
+ distinct_clusters: Number(m[2]),
321
+ near_dupes_merged: Number(m[3]),
322
+ exhausted: m[4] === "true",
323
+ };
324
+ }
325
+ // Absent reads as `estimated`: an older record never claimed to have computed
326
+ // anything, and the gate's job is to refuse a FALSE `measured`, not to
327
+ // retroactively fail records that were honest about being eyeballed.
328
+ export function readDiversityMethod(recordText) {
329
+ const m = recordText.match(/^diversity_method:\s*(\S+)/m);
330
+ if (!m)
331
+ return { value: "estimated", declared: false };
332
+ const value = m[1].trim();
333
+ if (value !== "measured" && value !== "estimated")
334
+ return null;
335
+ return { value, declared: true };
336
+ }
337
+ // Which clusterer computed the meter in this record, if it said. Absent means
338
+ // "older than the stamp" — which, for a `measured` record, is the same practical
339
+ // state as stale: the number was computed, but not by this code.
340
+ export function readClustererId(recordText) {
341
+ const m = recordText.match(/^diversity_clusterer:\s*(\S+)/m);
342
+ return m ? m[1].trim() : null;
343
+ }
344
+ export function clustererLine() {
345
+ return `diversity_clusterer: ${CLUSTERER_ID}`;
346
+ }
347
+ export function meterLine(meter) {
348
+ return `diversity: { raw: ${meter.raw}, distinct_clusters: ${meter.distinct_clusters}, near_dupes_merged: ${meter.near_dupes_merged}, exhausted: ${meter.exhausted} }`;
349
+ }
350
+ // --- frames-v1: executable frames (#697) --------------------------------------
351
+ // The contract version a record was scaffolded under. Gates that this version
352
+ // introduces (frame-reasoning, stress evidence, novelty anchor, cheapest test)
353
+ // apply only to records that carry the line — a record honest about being older
354
+ // is never retroactively failed.
355
+ export const IDEATE_CONTRACT_VERSION = "frames-v1";
356
+ export function ideateFrontmatter(record) {
357
+ const frontmatter = record.match(/^---\r?\n([\s\S]*?)\r?\n---(?:\r?\n|$)/)?.[1];
358
+ if (frontmatter === undefined)
359
+ return {};
360
+ try {
361
+ const value = parseYaml(frontmatter);
362
+ return value && typeof value === "object" && !Array.isArray(value) ? value : null;
363
+ }
364
+ catch {
365
+ return null;
366
+ }
367
+ }
368
+ export function ideateContractVersion(record) {
369
+ const value = ideateFrontmatter(record);
370
+ if (value === null)
371
+ return "invalid";
372
+ if (!Object.hasOwn(value, "ideate_contract"))
373
+ return null;
374
+ return typeof value.ideate_contract === "string" ? value.ideate_contract : "invalid";
375
+ }
376
+ export function hasExecutableFramesContract(recordText) {
377
+ const version = ideateContractVersion(recordText);
378
+ return version === IDEATE_CONTRACT_VERSION || version === "decisions-v2";
379
+ }
380
+ // The checkable SHAPE of each frame's move. Shape, never quality: an inversion
381
+ // that cannot show the failure it negated did not run inversion, whatever its
382
+ // label says — but how good the negation is stays with blind judging.
383
+ const FRAME_SHAPES = {
384
+ analogy: {
385
+ tags: [/source-domain:/i, /mechanism-stolen:/i],
386
+ hint: "reasoning must contain `source-domain:` and `mechanism-stolen:`",
387
+ },
388
+ inversion: {
389
+ tags: [/guarantee-failure:/i, /negated:/i],
390
+ hint: "reasoning must contain `guarantee-failure: <ingredient>; <ingredient>` then `negated:`",
391
+ },
392
+ "how-might-we": {
393
+ tags: [/tension:/i, /answer:/i],
394
+ hint: "reasoning must contain `tension:` and `answer:`",
395
+ },
396
+ "first-principles": {
397
+ tags: [/bedrock:/i, /discarded-assumption:/i],
398
+ hint: "reasoning must contain `bedrock:` and `discarded-assumption:`",
399
+ },
400
+ "second-order": {
401
+ tags: [/then-1:/i, /then-2:/i],
402
+ hint: "reasoning must contain `then-1:` and `then-2:`",
403
+ },
404
+ };
405
+ // Free-text frames (panel lenses, build-on, custom) still owe a shown move,
406
+ // just not a tagged one.
407
+ const MIN_FREE_REASONING = 20;
408
+ export function frameReasoningOffenders(ideas) {
409
+ const offenders = [];
410
+ for (const idea of ideas) {
411
+ const shape = FRAME_SHAPES[idea.frame.trim().toLowerCase()];
412
+ const reasoning = (idea.reasoning ?? "").trim();
413
+ if (shape) {
414
+ const missing = shape.tags.filter((t) => !t.test(reasoning));
415
+ if (missing.length)
416
+ offenders.push(`${idea.id} (${idea.frame}): ${shape.hint}`);
417
+ }
418
+ else if (reasoning.length < MIN_FREE_REASONING) {
419
+ offenders.push(`${idea.id} (${idea.frame}): reasoning must state the move (free text, not empty)`);
420
+ }
421
+ }
422
+ return offenders;
423
+ }
@@ -0,0 +1,7 @@
1
+ import type { Cell, Depth, FamilyDefinition, GateResult, RenderContext, Tier } from "./types.js";
2
+ export declare function slugify(text: string): string;
3
+ export declare function buildCells(family: FamilyDefinition, tier: Tier): Cell[];
4
+ export declare function renderContext(family: FamilyDefinition, target: string, depth: Depth, at: string, root: string): RenderContext;
5
+ export declare function scaffoldRecord(ctx: RenderContext): string;
6
+ export declare function renderContract(ctx: RenderContext): string;
7
+ export declare function checkRecord(family: FamilyDefinition, recordText: string): GateResult;