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,304 @@
1
+ // bug-owner-autolog-v0: the owner-lane auto-logging engine behind `foo bug log`
2
+ // and the discovery signal bug destination (`foo discovery review <F-id>
3
+ // reassign --bug`). Dedupe-first, owner-gated, never silent.
4
+ //
5
+ // The dedupe stage is BLOCKING by construction, not by convention: the create
6
+ // path takes a `CreateVerdict` value that only `evaluateBugDedupe` returns, so
7
+ // a filing cannot be pipelined past the search the way the #521/#535 incident
8
+ // was — the search result must exist and be evaluated before create is even
9
+ // callable (R-002, D-001).
10
+ import { spawnSync } from "node:child_process";
11
+ import { createHash } from "node:crypto";
12
+ import { existsSync, mkdirSync, readFileSync, writeFileSync } from "node:fs";
13
+ import path from "node:path";
14
+ import { scrubDiagnostic } from "./bugCapture.js";
15
+ export const defaultGhExec = (args) => {
16
+ const run = spawnSync("gh", args, { encoding: "utf8", timeout: 60_000 });
17
+ if (run.error)
18
+ return { ok: false, stdout: "", stderr: String(run.error.message ?? run.error) };
19
+ return { ok: run.status === 0, stdout: run.stdout ?? "", stderr: run.stderr ?? "" };
20
+ };
21
+ // The ceiling only restrains a loop if it counts creations that already
22
+ // happened in earlier invocations — a per-process counter resets to zero every
23
+ // run, so a loop that re-invokes the verb once per issue never trips it. The
24
+ // creation log below is the cross-invocation memory; the window keeps it a
25
+ // rolling budget (a filing last week is not this loop) rather than a lifetime
26
+ // cap that would eventually brick honest owner use.
27
+ const CREATE_WINDOW_SECONDS = 3600;
28
+ function bugCreateLogPath(root) {
29
+ return path.join(root, ".foo", "bug-log-creates.json");
30
+ }
31
+ function createWindowMs(env) {
32
+ const raw = Number(env.FOO_BUG_LOG_WINDOW_SECONDS ?? CREATE_WINDOW_SECONDS);
33
+ return (Number.isFinite(raw) && raw > 0 ? raw : CREATE_WINDOW_SECONDS) * 1000;
34
+ }
35
+ function readCreateEntries(root, env, now) {
36
+ const file = bugCreateLogPath(root);
37
+ if (!existsSync(file))
38
+ return [];
39
+ try {
40
+ const raw = JSON.parse(readFileSync(file, "utf8"));
41
+ const windowMs = createWindowMs(env);
42
+ return (Array.isArray(raw.creates) ? raw.creates : [])
43
+ .map((entry) => ({ at: Number(entry?.at), repo: String(entry?.repo ?? "") }))
44
+ .filter((entry) => Number.isFinite(entry.at) && now - entry.at < windowMs);
45
+ }
46
+ catch {
47
+ return [];
48
+ }
49
+ }
50
+ /** Recent auto-creations for the configured owner repo, within the rolling window. */
51
+ export function recentBugCreateCount(root, env, now = Date.now()) {
52
+ const repo = (env.FOO_BUG_OWNER_REPO ?? "").trim();
53
+ return readCreateEntries(root, env, now).filter((entry) => !repo || entry.repo === repo).length;
54
+ }
55
+ /** Records one auto-creation so the next invocation's ceiling counts it (R-006/RISK-002). */
56
+ export function recordBugCreate(root, env, repo, now = Date.now()) {
57
+ const entries = readCreateEntries(root, env, now);
58
+ entries.push({ at: now, repo });
59
+ const file = bugCreateLogPath(root);
60
+ mkdirSync(path.dirname(file), { recursive: true });
61
+ writeFileSync(file, `${JSON.stringify({ creates: entries }, null, 2)}\n`);
62
+ }
63
+ export function newBugLogSession(env, root) {
64
+ const raw = Number(env.FOO_BUG_LOG_MAX_CREATES ?? "3");
65
+ // A malformed or non-positive ceiling disables creation rather than
66
+ // inventing an unbounded one (bug-capsule-v0 ceiling precedent).
67
+ const maxCreates = Number.isFinite(raw) && raw > 0 && Number.isInteger(raw) ? raw : 0;
68
+ // Seed from the persisted creation log so the ceiling spans invocations.
69
+ const created = root ? recentBugCreateCount(root, env) : 0;
70
+ return { created, max_creates: maxCreates, title_hashes: new Set() };
71
+ }
72
+ // --- Dedupe evaluation --------------------------------------------------------
73
+ const STOPWORDS = new Set(["about", "after", "again", "also", "because", "been", "before", "being", "between", "command", "could", "does", "every", "issue", "from", "have", "into", "just", "only", "should", "that", "then", "these", "they", "this", "those", "through", "using", "when", "where", "which", "will", "with", "without", "would"]);
74
+ // Mechanism tokens outrank symptom wording (R-002): the #521/#535 pair
75
+ // described one classifier defect in fully disjoint symptom vocabulary, but
76
+ // shared error codes, file names, and command tokens.
77
+ const MECHANISM_PATTERN = /\b(E_[A-Z][A-Z0-9_]+|[a-zA-Z][\w-]*\.(?:ts|js|mjs|py|yaml|yml|json|md)|foo\s+[a-z][a-z-]+(?:\s+[a-z][a-z-]+)?)\b/g;
78
+ function plainTokens(text) {
79
+ return new Set((text.toLowerCase().match(/[a-z0-9_]+/g) ?? []).filter((token) => token.length >= 4 && !STOPWORDS.has(token)));
80
+ }
81
+ function mechanismTokens(text) {
82
+ return new Set([...text.matchAll(MECHANISM_PATTERN)].map((match) => match[1].toLowerCase().replace(/\s+/g, " ")));
83
+ }
84
+ export function evaluateBugDedupe(intake, issues) {
85
+ const intakePlain = plainTokens(intake.search_text);
86
+ const intakeMechanism = mechanismTokens(intake.search_text);
87
+ let best = null;
88
+ for (const issue of issues) {
89
+ const issueText = `${issue.title}\n${issue.body}`;
90
+ const issuePlain = plainTokens(issueText);
91
+ const issueMechanism = mechanismTokens(issueText);
92
+ const mechanismShared = [...intakeMechanism].filter((token) => issueMechanism.has(token));
93
+ const plainShared = [...intakePlain].filter((token) => issuePlain.has(token));
94
+ const weightedOverlap = mechanismShared.length * 3 + plainShared.length;
95
+ const weightedIntake = intakeMechanism.size * 3 + intakePlain.size;
96
+ const score = weightedIntake === 0 ? 0 : weightedOverlap / weightedIntake;
97
+ // The bar: concentrated overlap with mechanism agreement, or overwhelming
98
+ // plain overlap. Tunable per the packet's open question; deterministic here.
99
+ const matched = (score >= 0.35 && mechanismShared.length >= 1) || score >= 0.6;
100
+ if (!matched)
101
+ continue;
102
+ if (!best || score > best.score) {
103
+ best = {
104
+ issue_number: issue.number,
105
+ issue_url: issue.url,
106
+ issue_title: issue.title,
107
+ issue_state: issue.state,
108
+ score: Number(score.toFixed(3)),
109
+ matched_terms: [...mechanismShared, ...plainShared.slice(0, 8)],
110
+ };
111
+ }
112
+ }
113
+ if (best)
114
+ return { decision: "comment", match: best };
115
+ return { decision: "create", evaluated_issues: issues.length, proof: "dedupe_evaluated" };
116
+ }
117
+ // --- Intake builders ----------------------------------------------------------
118
+ function scrubOrNull(text, root) {
119
+ const scrubbed = scrubDiagnostic(text, root);
120
+ return scrubbed.state === "collected" ? scrubbed.value : null;
121
+ }
122
+ function firstLine(text, max) {
123
+ const line = text.split("\n")[0].trim().replace(/\s+/g, " ");
124
+ return line.length <= max ? line : `${line.slice(0, max - 1).trimEnd()}…`;
125
+ }
126
+ export function buildBugLogIntake(fields) {
127
+ const refs = (fields.refs ?? []).filter((ref) => /^#\d+$/.test(ref));
128
+ const body = [
129
+ "## Expected",
130
+ "",
131
+ fields.expected.trim(),
132
+ "",
133
+ "## Actual",
134
+ "",
135
+ fields.actual.trim(),
136
+ ...(fields.reproduction ? ["", "## Reproduction", "", fields.reproduction.trim()] : []),
137
+ ...(fields.suggested ? ["", "## Suggested directions", "", fields.suggested.trim()] : []),
138
+ ...(refs.length ? ["", "## Companions", "", refs.map((ref) => `- ${ref}`).join("\n")] : []),
139
+ "",
140
+ "_Filed by `foo bug log` (owner lane); dedupe searched state:all before this filing._",
141
+ ].join("\n");
142
+ return {
143
+ title: firstLine(fields.actual, 90),
144
+ body,
145
+ search_text: [fields.expected, fields.actual, fields.reproduction ?? "", fields.suggested ?? ""].join("\n"),
146
+ refs,
147
+ };
148
+ }
149
+ /** Seeds the engine from a discovery inbox signal: headline → title candidate,
150
+ * paraphrase → evidence body with provenance. Signals are already sanitized
151
+ * paraphrases; provenance names the finding, call date, and attribution basis. */
152
+ export function buildSignalBugIntake(record) {
153
+ const paraphrase = String(record.paraphrase ?? "").trim();
154
+ const colon = paraphrase.indexOf(":");
155
+ const lead = colon > 0 && colon < 70 && !paraphrase.slice(0, colon).includes(".") ? paraphrase.slice(0, colon) : null;
156
+ // Seeding rule (bug-owner-autolog-v0): the purpose-built `headline` field is the
157
+ // intended title candidate. Fall back to the paraphrase kicker, then its first
158
+ // sentence, only when no headline is present (#567). Normalize the headline with
159
+ // firstLine (single line + 90-char cap) so a long/multi-line headline can't
160
+ // produce a broken title GitHub rejects — matching every other title path here.
161
+ const headline = String(record.headline ?? "").trim();
162
+ const title = headline ? firstLine(headline, 90) : (lead ?? firstLine(paraphrase, 90));
163
+ const provenance = [
164
+ `- Signal: ${String(record.finding_id ?? "unknown")} (discovery inbox)`,
165
+ `- Call date: ${String(record.completed_at ?? "unknown")}`,
166
+ `- Attribution basis: scope ${String(record.inbox_scope_id ?? "unknown")}, evidence ${String(record.evidence_type ?? "unknown")}, confidence ${String(record.confidence ?? "unknown")}`,
167
+ ...(typeof record.dissent === "string" && record.dissent ? [`- Dissent: ${record.dissent}`] : []),
168
+ ];
169
+ const body = [
170
+ "## Evidence",
171
+ "",
172
+ paraphrase,
173
+ "",
174
+ "## Provenance",
175
+ "",
176
+ ...provenance,
177
+ "",
178
+ "_Filed from a discovery signal via `foo discovery review … --bug`; dedupe searched state:all before this filing._",
179
+ ].join("\n");
180
+ return { title, body, search_text: paraphrase, refs: [] };
181
+ }
182
+ // --- The engine ---------------------------------------------------------------
183
+ function normalizedTitleHash(title) {
184
+ const normalized = title.toLowerCase().replace(/[^a-z0-9]+/g, " ").trim();
185
+ return createHash("sha256").update(normalized).digest("hex");
186
+ }
187
+ export function bugLogRefusal(code, message, nextActions, repo = null, withheld = null) {
188
+ return { schema_version: "0.1", status: "refused", repo, issue_number: null, issue_url: null, match: null, withheld, errors: [{ code, message }], next_actions: nextActions };
189
+ }
190
+ function retryable(code, message, nextActions, repo) {
191
+ return { schema_version: "0.1", status: "retryable", repo, issue_number: null, issue_url: null, match: null, withheld: null, errors: [{ code, message }], next_actions: nextActions };
192
+ }
193
+ function createOwnerIssue(gh, repo, title, body, verdict) {
194
+ // `verdict` is the dedupe proof token — reaching here without an evaluated
195
+ // search is a type error, and a malformed token fails closed at runtime.
196
+ if (verdict.proof !== "dedupe_evaluated")
197
+ return { ok: false, stdout: "", stderr: "dedupe verdict missing; refusing to create" };
198
+ return gh(["issue", "create", "--repo", repo, "--title", title, "--body", body]);
199
+ }
200
+ export function runBugLog(options) {
201
+ const { env, gh, session, intake, root } = options;
202
+ // R-005: owner-lane gating. No configured repo, no action at all.
203
+ const repo = (env.FOO_BUG_OWNER_REPO ?? "").trim();
204
+ if (!repo) {
205
+ return bugLogRefusal("E_BUG_OWNER_REPO", "The owner bug queue is not configured; nothing was searched or written.", ["Set the owner repository, then rerun: export FOO_BUG_OWNER_REPO=<owner>/<repo>"]);
206
+ }
207
+ if (!/^[\w.-]+\/[\w.-]+$/.test(repo)) {
208
+ return bugLogRefusal("E_BUG_OWNER_REPO", `FOO_BUG_OWNER_REPO must be <owner>/<repo>; got "${repo}". Nothing was searched or written.`, ["Fix the value, then rerun: export FOO_BUG_OWNER_REPO=<owner>/<repo>"]);
209
+ }
210
+ // Scrub everything before it can travel (RISK-005). A withheld scrub blocks
211
+ // the whole filing for a person rather than guessing.
212
+ const title = scrubOrNull(intake.title, root);
213
+ const body = scrubOrNull(intake.body, root);
214
+ if (title === null || body === null) {
215
+ return bugLogRefusal("E_BUG_SCRUB_WITHHELD", "Scrubbing could not prove the intake is secret- and path-free; nothing was written.", ["Rewrite the ambiguous fragment and rerun foo bug log."], repo);
216
+ }
217
+ // Cut line: never post to a public repository.
218
+ const view = gh(["repo", "view", repo, "--json", "visibility,isPrivate"]);
219
+ if (!view.ok) {
220
+ return retryable("E_BUG_GH_UNAVAILABLE", "Could not reach GitHub through gh; nothing was searched or written.", ["Check gh auth status (gh auth login) and network, then rerun the same command."], repo);
221
+ }
222
+ let isPrivate = false;
223
+ try {
224
+ isPrivate = Boolean(JSON.parse(view.stdout).isPrivate);
225
+ }
226
+ catch {
227
+ return retryable("E_BUG_GH_UNAVAILABLE", "gh returned an unreadable repository description; nothing was written.", ["Rerun the same command; if it persists, check gh --version."], repo);
228
+ }
229
+ if (!isPrivate) {
230
+ return bugLogRefusal("E_BUG_REPO_PUBLIC", `${repo} is public; the owner lane only writes to private repositories. Nothing was written.`, ["Point FOO_BUG_OWNER_REPO at the private owner tracker and rerun."], repo);
231
+ }
232
+ // R-002: the BLOCKING dedupe stage. state:all because duplicates get closed.
233
+ const listed = gh(["issue", "list", "--repo", repo, "--state", "all", "--limit", "200", "--json", "number,title,state,url,body"]);
234
+ if (!listed.ok) {
235
+ return retryable("E_BUG_SEARCH_FAILED", "The dedupe search failed, so no issue was created or commented — the search result must gate the filing.", ["Rerun the same command once gh can list issues in the owner repository."], repo);
236
+ }
237
+ let issues = [];
238
+ try {
239
+ const parsed = JSON.parse(listed.stdout);
240
+ issues = parsed.map((issue) => ({ number: Number(issue.number), title: String(issue.title ?? ""), state: String(issue.state ?? ""), url: String(issue.url ?? ""), body: String(issue.body ?? "") }));
241
+ }
242
+ catch {
243
+ return retryable("E_BUG_SEARCH_FAILED", "The dedupe search returned unreadable results, so no issue was created or commented.", ["Rerun the same command."], repo);
244
+ }
245
+ const verdict = evaluateBugDedupe({ ...intake, title, body }, issues);
246
+ if (verdict.decision === "comment") {
247
+ const match = verdict.match;
248
+ const comment = [
249
+ "Reproduced by `foo bug log` (owner lane).",
250
+ "",
251
+ body,
252
+ "",
253
+ `_Dedupe match evidence: score ${match.score}, shared terms: ${match.matched_terms.slice(0, 6).join(", ") || "none listed"}. A comment is the ceiling of automatic action — nothing was closed or edited._`,
254
+ ].join("\n");
255
+ const commented = gh(["issue", "comment", String(match.issue_number), "--repo", repo, "--body", comment]);
256
+ if (!commented.ok) {
257
+ return retryable("E_BUG_COMMENT_FAILED", `The reproduction comment on #${match.issue_number} failed; nothing else was written.`, ["Rerun the same command."], repo);
258
+ }
259
+ session.title_hashes.add(normalizedTitleHash(title));
260
+ return {
261
+ schema_version: "0.1",
262
+ status: "reproduced",
263
+ repo,
264
+ issue_number: match.issue_number,
265
+ issue_url: match.issue_url,
266
+ match,
267
+ withheld: null,
268
+ errors: [],
269
+ next_actions: [`Tell the owner: this defect reproduces existing issue ${match.issue_url} (${match.issue_state.toLowerCase()}); the reproduction context was added as a comment.`],
270
+ };
271
+ }
272
+ // R-006: title-hash duplicate guard against existing issues and this run.
273
+ const titleHash = normalizedTitleHash(title);
274
+ const existingTitleHashes = new Set(issues.map((issue) => normalizedTitleHash(issue.title)));
275
+ if (session.title_hashes.has(titleHash) || existingTitleHashes.has(titleHash)) {
276
+ return bugLogRefusal("E_BUG_DUPLICATE_TITLE", `An issue with this normalized title already exists in ${repo}; creation was withheld.`, ["Retitle the defect if it is genuinely different, or comment on the existing issue by hand."], repo, `duplicate title: ${title}`);
277
+ }
278
+ // R-006: creation ceiling. session.created is seeded from the persisted
279
+ // creation log, so this bounds a loop across invocations, not just within one
280
+ // process (RISK-002) — rerunning in a fresh invocation no longer resets it.
281
+ if (session.created >= session.max_creates) {
282
+ return bugLogRefusal("E_BUG_CREATE_CEILING", `The recent-creation ceiling (${session.max_creates}) is reached; this filing was withheld, not lost.`, [`Withheld: "${title}". File it by hand, or wait for the creation window to clear before the verb files automatically again.`], repo, `ceiling reached: ${title}`);
283
+ }
284
+ const created = createOwnerIssue(gh, repo, title, body, verdict);
285
+ if (!created.ok) {
286
+ return retryable("E_BUG_CREATE_FAILED", "Issue creation failed after dedupe cleared it; nothing was recorded.", ["Rerun the same command."], repo);
287
+ }
288
+ const url = created.stdout.trim().split("\n").pop() ?? "";
289
+ const numberMatch = /\/issues\/(\d+)\s*$/.exec(url);
290
+ session.created += 1;
291
+ session.title_hashes.add(titleHash);
292
+ recordBugCreate(root, env, repo);
293
+ return {
294
+ schema_version: "0.1",
295
+ status: "filed",
296
+ repo,
297
+ issue_number: numberMatch ? Number(numberMatch[1]) : null,
298
+ issue_url: url || null,
299
+ match: null,
300
+ withheld: null,
301
+ errors: [],
302
+ next_actions: [`Tell the owner: a new defect was filed at ${url || repo} after the dedupe search over ${verdict.evaluated_issues} issue(s) found no match.`],
303
+ };
304
+ }
@@ -0,0 +1,48 @@
1
+ import { type BugCapsule, type DeliveryReceipt } from "./bugCapsule.js";
2
+ export type LocalBugRecord = {
3
+ schema_version: "0.1";
4
+ capsule: BugCapsule;
5
+ payload_digest: string;
6
+ state: "pending" | "accepted" | "delete_retryable";
7
+ preview: null | {
8
+ payload_digest: string;
9
+ destination: string | null;
10
+ previewed_at: string;
11
+ };
12
+ receipt: DeliveryReceipt | null;
13
+ };
14
+ export type LocalBugRecordMetadata = {
15
+ capsule_id: string;
16
+ payload_digest: string;
17
+ state: LocalBugRecord["state"];
18
+ previewed_at: string | null;
19
+ receipt_id: string | null;
20
+ };
21
+ export type LocalBugRecordList = {
22
+ records: LocalBugRecordMetadata[];
23
+ corrupt: string[];
24
+ };
25
+ export type ArchiveDeletionMarker = {
26
+ schema_version: "0.1";
27
+ kind: "remote_deletion_confirmed" | "local_archive_deleted";
28
+ capsule_id: string;
29
+ payload_digest: string;
30
+ receipt_id: string;
31
+ destination: string;
32
+ };
33
+ export declare function getArchiveDeletionMarker(root: string, id: string, digest?: string): ArchiveDeletionMarker | null;
34
+ export declare function savePending(root: string, capsule: BugCapsule): LocalBugRecord;
35
+ export declare function listLocalBugRecords(root: string): LocalBugRecordList;
36
+ export declare function getLocalBugRecord(root: string, id: string): LocalBugRecord | null;
37
+ export declare function markPreviewed(root: string, id: string, digest: string, destination: string, previewedAt: string): LocalBugRecord;
38
+ export declare function archiveAccepted(root: string, id: string, receipt: DeliveryReceipt): LocalBugRecord;
39
+ export declare function deletePending(root: string, id: string): void;
40
+ /** Read historical server confirmations without creating or sending a request. */
41
+ export type RemoteDeletionConfirmation = ArchiveDeletionMarker & {
42
+ kind: "remote_deletion_confirmed";
43
+ };
44
+ export declare function getRemoteDeletionConfirmation(root: string, id: string, digest?: string): RemoteDeletionConfirmation | null;
45
+ /** Compatibility for legacy local-store consumers that already hold server confirmation. */
46
+ export declare function confirmRemoteDeletion(root: string, id: string, digest: string): void;
47
+ /** Remove an archived report locally, recording no claim about its historical destination. */
48
+ export declare function deleteLocalArchive(root: string, id: string, digest: string): void;