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,99 @@
1
+ import { type BugCapsule, type DeliveryReceipt } from "./bugCapsule.js";
2
+ import { type FailureMark } from "./errorTaxonomy.js";
3
+ export declare function reportsDir(root: string): string;
4
+ export type ErrorReport = {
5
+ schema_version: "0.1";
6
+ id: string;
7
+ timestamp: string;
8
+ command: string;
9
+ version: string;
10
+ error_class: string;
11
+ error_code: string;
12
+ /**
13
+ * Stable, content-free grouping key: hash(code + normalized origin frame). It lets the
14
+ * digest collapse the same bug across testers and rank by blast radius, without the digest
15
+ * ever having to touch the (redacted) message or stack.
16
+ *
17
+ * Absent when the failure carried no stack: there is no frame to fingerprint, and a report
18
+ * with no fingerprint attaches to no bug rather than to every bug sharing its code.
19
+ */
20
+ fingerprint?: string;
21
+ /** Redacted. The whole point of the report — and the reason it needs consent to move. */
22
+ message: string;
23
+ stack?: string;
24
+ };
25
+ /**
26
+ * Write a report for a genuine failure. Callers gate on `pages(errorClass)`, so a typo or
27
+ * a gate refusal never lands here — only something actually broken does.
28
+ */
29
+ export declare function writeErrorReport(root: string, input: {
30
+ failure: FailureMark;
31
+ command: string;
32
+ version: string;
33
+ }, now?: Date): string | undefined;
34
+ export declare function pendingReports(root: string): ErrorReport[];
35
+ export type ReportInvocationMode = "interactive" | "json" | "agent" | "noninteractive";
36
+ export type ReportFinalizationDeps = {
37
+ stdin?: NodeJS.ReadStream;
38
+ stderr?: NodeJS.WriteStream;
39
+ now?: () => Date;
40
+ question?: (prompt: string) => Promise<string>;
41
+ onPrompt?: () => void;
42
+ onConsentAction?: () => void;
43
+ /** Retained for invocation compatibility; reporting never reads credentials. */
44
+ env?: NodeJS.ProcessEnv;
45
+ };
46
+ /**
47
+ * Opaque ownership token for one top-level CLI invocation. The token, rather than module
48
+ * state, keeps overlapping `main()` calls from consuming each other's capsule identity.
49
+ */
50
+ export type ReportRunContext = {
51
+ readonly _reportRunContext: "foo-report-run";
52
+ };
53
+ export declare function createReportRunContext(): ReportRunContext;
54
+ export declare function noteCapsuleFromThisRun(run: ReportRunContext, capsuleId: string): void;
55
+ /** Compatibility name: announces this invocation's local capture, without asking to send. */
56
+ export declare function askToSendReports(root: string, run: ReportRunContext, io: ReportFinalizationDeps & {
57
+ mode: ReportInvocationMode;
58
+ }): Promise<void>;
59
+ export type ReportCommandResult = {
60
+ schema_version: "0.1";
61
+ status: "ready" | "accepted" | "kept_local" | "deleted" | "empty" | "selection_required" | "refused" | "retryable";
62
+ capsule_id: string | null;
63
+ payload_digest: string | null;
64
+ destination: string | null;
65
+ payload: BugCapsule | null;
66
+ receipt: DeliveryReceipt | null;
67
+ error: null | {
68
+ code: string;
69
+ message: string;
70
+ retry_after?: string;
71
+ };
72
+ handoff: {
73
+ required: boolean;
74
+ reason: string | null;
75
+ command: string | null;
76
+ };
77
+ next_actions: string[];
78
+ /** Non-fatal problems the human must see at capture time, e.g. a field the scrubber withheld. */
79
+ warnings: string[];
80
+ };
81
+ export type ReportCommandDeps = {
82
+ stdin?: NodeJS.ReadStream;
83
+ stderr?: NodeJS.WriteStream;
84
+ now?: () => Date;
85
+ version?: string;
86
+ onPrompt?: () => void;
87
+ onConsentAction?: () => void;
88
+ question?: (prompt: string) => Promise<string>;
89
+ };
90
+ export type ReportCommandRun = {
91
+ result: ReportCommandResult;
92
+ output: string;
93
+ exitCode: 0 | 1 | 2 | 3;
94
+ status: ReportCommandResult["status"];
95
+ prompt_count: number;
96
+ consent_actions: number;
97
+ };
98
+ export declare function renderReportCommandResult(value: ReportCommandResult): string;
99
+ export declare function runReportCommand(root: string, args: string[], env?: NodeJS.ProcessEnv, deps?: ReportCommandDeps): Promise<ReportCommandRun>;
@@ -0,0 +1,443 @@
1
+ // Local diagnostic capture, review, and deletion. Reports never leave this machine.
2
+ import { existsSync, mkdirSync, readdirSync, writeFileSync } from "node:fs";
3
+ import path from "node:path";
4
+ import { captureManualCapsule, scrubDiagnostic } from "./bugCapture.js";
5
+ import { canonicalBytes, payloadDigest } from "./bugCapsule.js";
6
+ import { deleteLocalArchive, deletePending, getLocalBugRecord, getArchiveDeletionMarker, listLocalBugRecords, markPreviewed, } from "./bugReportStore.js";
7
+ import { flagValue, hasFlag, readPackageVersion } from "./commands/shared.js";
8
+ import { surplusArgs } from "./cliArgs.js";
9
+ import { errorFingerprint } from "./errorTaxonomy.js";
10
+ import { readJson } from "./jsonFile.js";
11
+ export function reportsDir(root) {
12
+ return path.join(root, ".foo", "reports");
13
+ }
14
+ /**
15
+ * Scrub a report before it touches the disk. Two passes, because they catch different things.
16
+ *
17
+ * redactEngine finds SECRETS — tokens, keys, credentials. It does not touch paths, and an
18
+ * error message is mostly paths: `EACCES: permission denied, open '/Users/taylor/work/...'`
19
+ * would retain a person's name and private directory layout in the report. That is
20
+ * not a secret by redactEngine's definition, and it is absolutely not ours to collect.
21
+ *
22
+ * So paths are anchored to placeholders first (longest prefix wins — the packet root is
23
+ * usually inside the home directory), then secrets are redacted. The result still names the
24
+ * FILE that failed, which is what makes the report debuggable; it just no longer names the
25
+ * human it belongs to.
26
+ */
27
+ function scrub(text, root) {
28
+ const result = scrubDiagnostic(text, root);
29
+ return result.state === "collected" ? result.value : "[redaction failed — content withheld]";
30
+ }
31
+ /**
32
+ * Write a report for a genuine failure. Callers gate on `pages(errorClass)`, so a typo or
33
+ * a gate refusal never lands here — only something actually broken does.
34
+ */
35
+ export function writeErrorReport(root, input, now = new Date()) {
36
+ try {
37
+ const dir = reportsDir(root);
38
+ mkdirSync(dir, { recursive: true });
39
+ const id = `err_${now.getTime().toString(36)}`;
40
+ const fingerprint = errorFingerprint(input.failure.errorCode, input.failure.stack);
41
+ const report = {
42
+ schema_version: "0.1",
43
+ id,
44
+ timestamp: now.toISOString(),
45
+ command: input.command,
46
+ version: input.version,
47
+ error_class: input.failure.errorClass,
48
+ error_code: input.failure.errorCode,
49
+ // Derived from the raw stack (a basename + function name, never a path) before it is
50
+ // scrubbed — the fingerprint carries no content, so it is safe to compute here. Omitted
51
+ // entirely when there is no stack, rather than sent as a shared no-stack constant.
52
+ ...(fingerprint ? { fingerprint } : {}),
53
+ message: scrub(input.failure.message ?? "", root),
54
+ ...(input.failure.stack ? { stack: scrub(input.failure.stack, root) } : {}),
55
+ };
56
+ const file = path.join(dir, `${id}.json`);
57
+ writeFileSync(file, `${JSON.stringify(report, null, 2)}\n`);
58
+ return file;
59
+ }
60
+ catch {
61
+ // A failure to record a failure must never become a second failure.
62
+ return undefined;
63
+ }
64
+ }
65
+ export function pendingReports(root) {
66
+ const dir = reportsDir(root);
67
+ if (!existsSync(dir))
68
+ return [];
69
+ const out = [];
70
+ for (const name of readdirSync(dir)) {
71
+ if (!name.endsWith(".json"))
72
+ continue;
73
+ try {
74
+ out.push(readJson(path.join(dir, name)));
75
+ }
76
+ catch {
77
+ // A corrupt report is not worth failing over.
78
+ }
79
+ }
80
+ return out.sort((a, b) => a.timestamp.localeCompare(b.timestamp));
81
+ }
82
+ const reportRunStates = new WeakMap();
83
+ export function createReportRunContext() {
84
+ const run = Object.freeze({ _reportRunContext: "foo-report-run" });
85
+ reportRunStates.set(run, {});
86
+ return run;
87
+ }
88
+ function reportRunState(run) {
89
+ const state = reportRunStates.get(run);
90
+ if (!state)
91
+ throw new Error("unknown report run context");
92
+ return state;
93
+ }
94
+ export function noteCapsuleFromThisRun(run, capsuleId) {
95
+ // One top-level invocation may create at most one automatic capsule. Keep the first
96
+ // identity even if a caller accidentally reports another one: falling through to a later
97
+ // pending record would make the notice describe something other than the failure
98
+ // that caused this invocation's capture.
99
+ const state = reportRunState(run);
100
+ state.capsuleId ??= capsuleId;
101
+ }
102
+ /** Compatibility name: announces this invocation's local capture, without asking to send. */
103
+ export async function askToSendReports(root, run, io) {
104
+ try {
105
+ const state = reportRunState(run);
106
+ const capsuleId = state.capsuleId;
107
+ state.capsuleId = undefined;
108
+ if (!capsuleId || getLocalBugRecord(root, capsuleId)?.state !== "pending")
109
+ return;
110
+ (io.stderr ?? process.stderr).write(`foo saved Bug Capsule ${capsuleId} locally; nothing was sent. Review it with \`foo report show ${capsuleId}\`.\n`);
111
+ }
112
+ catch {
113
+ // Reporting a failure must never become a second failure.
114
+ }
115
+ }
116
+ function commandResult(status, destination, values = {}) {
117
+ return {
118
+ schema_version: "0.1", status,
119
+ capsule_id: values.capsule_id ?? null,
120
+ payload_digest: values.payload_digest ?? null,
121
+ destination,
122
+ payload: values.payload ?? null,
123
+ receipt: values.receipt ?? null,
124
+ error: values.error ?? null,
125
+ handoff: values.handoff ?? { required: false, reason: null, command: null },
126
+ next_actions: values.next_actions ?? [],
127
+ warnings: values.warnings ?? [],
128
+ };
129
+ }
130
+ function refusal(destination, code, message, values = {}) {
131
+ return commandResult("refused", destination, { ...values, payload: null, error: { code, message } });
132
+ }
133
+ function reportExitCode(value) {
134
+ if (value.status === "selection_required")
135
+ return 2;
136
+ if (value.status === "retryable")
137
+ return 3;
138
+ if (value.status === "refused")
139
+ return 1;
140
+ return 0;
141
+ }
142
+ export function renderReportCommandResult(value) {
143
+ const warningLines = value.warnings.map((warning) => `WARNING: ${warning}`);
144
+ if (value.status === "ready" && value.payload) {
145
+ return [
146
+ `Bug Capsule ${value.capsule_id}`,
147
+ ...(value.receipt
148
+ ? ["Storage: local archive on this machine", `Historical delivery: ${value.receipt.destination} at ${value.receipt.accepted_at}. Current remote retention is unknown.`]
149
+ : ["Storage: this machine only"]),
150
+ `Payload digest: ${value.payload_digest}`,
151
+ "Scrubbing claim: secret-redacted and path-scrubbed",
152
+ ...warningLines,
153
+ "Canonical local payload:",
154
+ canonicalBytes(value.payload).toString("utf8"),
155
+ ...value.next_actions,
156
+ "",
157
+ ].join("\n");
158
+ }
159
+ if (value.status === "ready") {
160
+ return [`Bug Capsule ${value.capsule_id} saved locally.`, ...warningLines, ...value.next_actions, ""].join("\n");
161
+ }
162
+ if (value.status === "empty")
163
+ return "No Bug Capsules are waiting locally.\n";
164
+ if (value.status === "selection_required")
165
+ return `Choose one Bug Capsule:\n${value.next_actions.join("\n")}\n`;
166
+ if (value.status === "accepted")
167
+ return `Bug Capsule ${value.capsule_id} was accepted by ${value.destination}. Receipt ${value.receipt?.receipt_id}.\n`;
168
+ if (value.status === "deleted")
169
+ return [`Bug Capsule ${value.capsule_id} was deleted locally. No remote deletion was requested.`, ...warningLines, ""].join("\n");
170
+ if (value.status === "kept_local")
171
+ return `Bug Capsule ${value.capsule_id} stays on this machine.\n`;
172
+ const message = value.status === "retryable"
173
+ ? value.error?.message ?? "Local report cleanup must be retried."
174
+ : value.error?.message ?? "The report command was refused.";
175
+ return `${message}${value.next_actions.length ? `\n${value.next_actions.join("\n")}` : ""}\n`;
176
+ }
177
+ function resumeCommand(action, id, digest, json) {
178
+ return `foo report ${action} ${id} --approve ${digest}${json ? " --json" : ""}`;
179
+ }
180
+ function flagsAreExact(args, valueFlags, booleanFlags) {
181
+ const valueSet = new Set(valueFlags);
182
+ const booleanSet = new Set(booleanFlags);
183
+ const seen = new Set();
184
+ for (let index = 0; index < args.length; index += 1) {
185
+ const token = args[index];
186
+ if (valueSet.has(token)) {
187
+ if (seen.has(token))
188
+ return false;
189
+ seen.add(token);
190
+ const value = args[index + 1];
191
+ if (value === undefined || value.startsWith("--"))
192
+ return false;
193
+ index += 1;
194
+ continue;
195
+ }
196
+ if (booleanSet.has(token)) {
197
+ if (seen.has(token))
198
+ return false;
199
+ seen.add(token);
200
+ }
201
+ }
202
+ return true;
203
+ }
204
+ async function approveIdentity(action, identity, args, json, deps) {
205
+ const suppliedValue = flagValue(args, "--approve");
206
+ if (suppliedValue !== undefined)
207
+ return { approved: suppliedValue === identity.payload_digest, prompted: 0, supplied: true };
208
+ const stdin = deps.stdin ?? process.stdin;
209
+ const stderr = deps.stderr ?? process.stderr;
210
+ if (json || !stdin.isTTY || !stderr.isTTY)
211
+ return { approved: false, prompted: 0, supplied: false };
212
+ if (deps.question) {
213
+ deps.onPrompt?.();
214
+ const answer = (await deps.question(`Delete local Bug Capsule ${identity.capsule_id}? [y/N] `)).trim().toLowerCase();
215
+ return { approved: answer === "y" || answer === "yes", prompted: 1, supplied: false };
216
+ }
217
+ const readline = await import("node:readline/promises");
218
+ const rl = readline.createInterface({ input: stdin, output: stderr });
219
+ try {
220
+ deps.onPrompt?.();
221
+ const answer = (await rl.question(`Delete local Bug Capsule ${identity.capsule_id}? [y/N] `)).trim().toLowerCase();
222
+ return { approved: answer === "y" || answer === "yes", prompted: 1, supplied: false };
223
+ }
224
+ finally {
225
+ rl.close();
226
+ }
227
+ }
228
+ export async function runReportCommand(root, args, env = process.env, deps = {}) {
229
+ const json = hasFlag(args, "--json");
230
+ const destination = null;
231
+ let promptCount = 0;
232
+ let consentActions = 0;
233
+ const finish = (value) => ({
234
+ result: value,
235
+ output: json ? `${JSON.stringify(value)}\n` : renderReportCommandResult(value),
236
+ exitCode: reportExitCode(value), status: value.status,
237
+ prompt_count: promptCount, consent_actions: consentActions,
238
+ });
239
+ const sub = args[0] ?? "show";
240
+ if (!new Set(["add", "show", "send", "delete"]).has(sub)) {
241
+ return finish(refusal(destination, "E_REPORT_ARGS", "usage: foo report add|show|delete"));
242
+ }
243
+ if (sub === "send") {
244
+ return finish(refusal(destination, "E_REPORT_SEND_REMOVED", "Report sending has been removed. Reports stay on this machine; use foo report show to review them."));
245
+ }
246
+ const valueFlags = sub === "add" ? ["--expected", "--actual", "--reproduction"] : sub === "show" ? [] : ["--approve"];
247
+ if (!flagsAreExact(args.slice(1), valueFlags, ["--json"])) {
248
+ return finish(refusal(destination, "E_REPORT_ARGS", `invalid report ${sub} arguments`));
249
+ }
250
+ if (sub === "add") {
251
+ const surplus = surplusArgs(args.slice(1), { value: ["--expected", "--actual", "--reproduction"], boolean: ["--json"] });
252
+ if (surplus.length)
253
+ return finish(refusal(destination, "E_REPORT_ARGS", "invalid report add arguments"));
254
+ let expected = flagValue(args, "--expected")?.trim();
255
+ let actual = flagValue(args, "--actual")?.trim();
256
+ const reproduction = flagValue(args, "--reproduction")?.trim();
257
+ const stdin = deps.stdin ?? process.stdin;
258
+ const stderr = deps.stderr ?? process.stderr;
259
+ if ((!expected || !actual) && !json && stdin.isTTY && stderr.isTTY) {
260
+ if (deps.question) {
261
+ if (!expected) {
262
+ deps.onPrompt?.();
263
+ promptCount += 1;
264
+ expected = (await deps.question("Expected behavior: ")).trim();
265
+ }
266
+ if (!actual) {
267
+ deps.onPrompt?.();
268
+ promptCount += 1;
269
+ actual = (await deps.question("Actual behavior: ")).trim();
270
+ }
271
+ }
272
+ else {
273
+ const readline = await import("node:readline/promises");
274
+ const rl = readline.createInterface({ input: stdin, output: stderr });
275
+ try {
276
+ if (!expected) {
277
+ deps.onPrompt?.();
278
+ promptCount += 1;
279
+ expected = (await rl.question("Expected behavior: ")).trim();
280
+ }
281
+ if (!actual) {
282
+ deps.onPrompt?.();
283
+ promptCount += 1;
284
+ actual = (await rl.question("Actual behavior: ")).trim();
285
+ }
286
+ }
287
+ finally {
288
+ rl.close();
289
+ }
290
+ }
291
+ }
292
+ if (!expected || !actual) {
293
+ const command = "foo report add";
294
+ return finish(refusal(destination, "E_REPORT_INCOMPLETE", "expected and actual behavior are required", {
295
+ handoff: { required: true, reason: "missing_required_fields", command },
296
+ next_actions: ["Run `foo report add` in an interactive terminal to enter the missing fields safely."],
297
+ }));
298
+ }
299
+ try {
300
+ const saved = captureManualCapsule(root, { expected, actual, ...(reproduction ? { reproduction } : {}), command: "report add", version: deps.version ?? readPackageVersion(root) }, deps.now?.() ?? new Date());
301
+ const withheld = [
302
+ ["expected", saved.capsule.report.expected],
303
+ ["actual", saved.capsule.report.actual],
304
+ ["reproduction", saved.capsule.report.reproduction],
305
+ ].filter(([, field]) => field?.state === "withheld");
306
+ return finish(commandResult("ready", destination, {
307
+ capsule_id: saved.capsule.capsule_id, payload_digest: saved.payload_digest,
308
+ warnings: withheld.map(([name, field]) => `your ${name} text was WITHHELD from the capsule (${field.reason ?? "scrubbing_failed"}) — it contains something productfoo could not safely scrub, usually a file path. Reword the ${name} without paths and run foo report add again.`),
309
+ next_actions: [`foo report show ${saved.capsule.capsule_id}${json ? " --json" : ""}`],
310
+ }));
311
+ }
312
+ catch {
313
+ return finish(refusal(destination, "E_REPORT_CAPTURE", "Bug Capsule could not be saved locally"));
314
+ }
315
+ }
316
+ const positional = surplusArgs(args.slice(1), { value: sub === "show" ? [] : ["--approve"], boolean: ["--json"] });
317
+ if (positional.length > 1 || (sub !== "show" && positional.length !== 1)) {
318
+ return finish(refusal(destination, "E_REPORT_ARGS", `invalid report ${sub} arguments`));
319
+ }
320
+ let id = positional[0];
321
+ if (sub === "show" && !id) {
322
+ const pending = listLocalBugRecords(root).records.filter((entry) => entry.state === "pending");
323
+ if (pending.length === 0)
324
+ return finish(commandResult("empty", destination));
325
+ if (pending.length > 1)
326
+ return finish(commandResult("selection_required", destination, {
327
+ error: { code: "E_REPORT_SELECTION_REQUIRED", message: "choose one pending Bug Capsule" },
328
+ handoff: { required: true, reason: "multiple_pending", command: null },
329
+ next_actions: pending.map((entry) => `foo report show ${entry.capsule_id}${json ? " --json" : ""}`),
330
+ }));
331
+ id = pending[0].capsule_id;
332
+ }
333
+ if (sub === "delete" && id) {
334
+ let confirmation;
335
+ try {
336
+ confirmation = getArchiveDeletionMarker(root, id);
337
+ }
338
+ catch {
339
+ return finish(refusal(destination, "E_REPORT_CORRUPT", "Bug Capsule deletion confirmation is unknown or corrupt", { capsule_id: id }));
340
+ }
341
+ if (confirmation !== null) {
342
+ const digest = confirmation.payload_digest;
343
+ const approved = await approveIdentity("delete", { capsule_id: id, payload_digest: digest }, args, json, deps);
344
+ promptCount += approved.prompted;
345
+ if (!approved.approved) {
346
+ if (approved.supplied)
347
+ return finish(refusal(destination, "E_REPORT_DIGEST_MISMATCH", "approval digest does not match the reviewed payload", { capsule_id: id, payload_digest: digest }));
348
+ if (approved.prompted)
349
+ return finish(commandResult("kept_local", destination, { capsule_id: id, payload_digest: digest, next_actions: [resumeCommand("delete", id, digest, false)] }));
350
+ const command = resumeCommand("delete", id, digest, json);
351
+ return finish(refusal(destination, "E_REPORT_APPROVAL_REQUIRED", "exact payload approval is required", {
352
+ capsule_id: id, payload_digest: digest,
353
+ handoff: { required: true, reason: "approval_required", command }, next_actions: [command],
354
+ }));
355
+ }
356
+ consentActions += 1;
357
+ deps.onConsentAction?.();
358
+ try {
359
+ deleteLocalArchive(root, id, digest);
360
+ }
361
+ catch {
362
+ return finish(commandResult("retryable", destination, { capsule_id: id, payload_digest: digest, error: { code: "E_REPORT_DELETE_ARCHIVE", message: "local archive cleanup must be retried" }, next_actions: [resumeCommand("delete", id, digest, json)] }));
363
+ }
364
+ return finish(commandResult("deleted", destination, { capsule_id: id, payload_digest: digest }));
365
+ }
366
+ }
367
+ let record;
368
+ try {
369
+ record = id ? getLocalBugRecord(root, id) : null;
370
+ }
371
+ catch {
372
+ return finish(refusal(destination, "E_REPORT_CORRUPT", "Bug Capsule is unknown or corrupt", { capsule_id: id ?? null }));
373
+ }
374
+ if (!record)
375
+ return finish(refusal(destination, "E_REPORT_NOT_FOUND", "Bug Capsule was not found", { capsule_id: id ?? null }));
376
+ const digest = payloadDigest(record.capsule);
377
+ if (digest !== record.payload_digest)
378
+ return finish(refusal(destination, "E_REPORT_DIGEST_CHANGED", "Bug Capsule digest changed", { capsule_id: id, payload_digest: digest }));
379
+ if (sub === "show") {
380
+ const preview = commandResult("ready", destination, {
381
+ capsule_id: id, payload_digest: digest, payload: record.capsule,
382
+ receipt: record.receipt,
383
+ next_actions: [],
384
+ });
385
+ try {
386
+ if (json)
387
+ JSON.stringify(preview);
388
+ else
389
+ renderReportCommandResult(preview);
390
+ if (record.state === "pending")
391
+ markPreviewed(root, id, digest, "local", (deps.now?.() ?? new Date()).toISOString());
392
+ }
393
+ catch {
394
+ return finish(refusal(destination, "E_REPORT_PREVIEW_STORE", "preview snapshot could not be saved", { capsule_id: id, payload_digest: digest }));
395
+ }
396
+ return finish(preview);
397
+ }
398
+ if (hasFlag(args, "--approve") && flagValue(args, "--approve") === undefined) {
399
+ return finish(refusal(destination, "E_REPORT_ARGS", "--approve requires a payload digest", { capsule_id: id, payload_digest: digest }));
400
+ }
401
+ if (sub === "delete" && record.state === "pending" && record.preview?.payload_digest !== digest) {
402
+ const command = `foo report show ${id}${json ? " --json" : ""}`;
403
+ return finish(refusal(destination, "E_REPORT_PREVIEW_REQUIRED", "show this exact Bug Capsule before deleting", {
404
+ capsule_id: id, payload_digest: digest,
405
+ handoff: { required: true, reason: "preview_required", command }, next_actions: [command],
406
+ }));
407
+ }
408
+ const action = "delete";
409
+ const approved = await approveIdentity(action, {
410
+ capsule_id: record.capsule.capsule_id,
411
+ payload_digest: record.payload_digest,
412
+ }, args, json, deps);
413
+ promptCount += approved.prompted;
414
+ if (!approved.approved) {
415
+ if (approved.supplied)
416
+ return finish(refusal(destination, "E_REPORT_DIGEST_MISMATCH", "approval digest does not match the reviewed payload", { capsule_id: id, payload_digest: digest, receipt: record.receipt }));
417
+ if (approved.prompted)
418
+ return finish(commandResult("kept_local", destination, { capsule_id: id, payload_digest: digest, receipt: record.receipt, next_actions: [resumeCommand(action, id, digest, false)] }));
419
+ const command = resumeCommand(action, id, digest, json);
420
+ return finish(refusal(destination, "E_REPORT_APPROVAL_REQUIRED", "exact payload approval is required", {
421
+ capsule_id: id, payload_digest: digest, receipt: record.receipt,
422
+ handoff: { required: true, reason: "approval_required", command }, next_actions: [command],
423
+ }));
424
+ }
425
+ consentActions += 1;
426
+ deps.onConsentAction?.();
427
+ if (record.state === "pending") {
428
+ try {
429
+ deletePending(root, id);
430
+ return finish(commandResult("deleted", destination, { capsule_id: id, payload_digest: digest }));
431
+ }
432
+ catch {
433
+ return finish(refusal(destination, "E_REPORT_DELETE_FAILED", "pending Bug Capsule could not be deleted safely", { capsule_id: id, payload_digest: digest }));
434
+ }
435
+ }
436
+ try {
437
+ deleteLocalArchive(root, id, digest);
438
+ }
439
+ catch {
440
+ return finish(commandResult("retryable", destination, { capsule_id: id, payload_digest: digest, receipt: record.receipt, error: { code: "E_REPORT_DELETE_ARCHIVE", message: "local archive cleanup must be retried" }, next_actions: [resumeCommand("delete", id, digest, json)] }));
441
+ }
442
+ return finish(commandResult("deleted", destination, { capsule_id: id, payload_digest: digest }));
443
+ }
@@ -0,0 +1,84 @@
1
+ /** What kind of failure. Only `command_error` and `io_error` are worth paging a human for. */
2
+ export type ErrorClass = "none" | "usage_error" | "gate_block" | "not_found" | "io_error" | "command_error";
3
+ /**
4
+ * Bounded, symbolic failure codes. NEVER free text: these cross the wire under a
5
+ * metadata-only disclosure, so a code may not embed a path, an arg, or user content.
6
+ * Each maps to exactly one failure site, so a code in a digest greps straight to source.
7
+ */
8
+ export type ErrorCode = "E_COMMAND_MISSING" | "E_PACKET_DIR_MISSING" | "E_SWARM_TARGET_MISSING" | "E_IDEATE_IDEA_MISSING" | "E_SPEC_WORK_MISSING" | "E_UNKNOWN_DOMAIN" | "E_BAD_FLAG" | "E_NOT_A_RESEARCH_PAPER" | "E_PACKET_NOT_FOUND" | "E_SPEC_NOT_FOUND" | "E_SKILL_NOT_FOUND" | "E_SDR_EVENT_NOT_FOUND" | "E_GATE_B1_SECRET" | "E_GATE_B2_SPEC_ID" | "E_GATE_B4_BUDGET" | "E_GATE_B5_UNGOVERNED" | "E_GATE_B5_CLAIM_UNLABELED" | "E_GATE_BLOCKED" | "E_GATE_INTERVIEW" | "E_CONTRACT_DRIFT" | "E_SKILL_SOURCE_UNAPPROVED" | "E_IO" | "E_UNKNOWN";
9
+ /** Does a failure of this class deserve a human's attention at 3am? */
10
+ export declare function pages(errorClass: ErrorClass): boolean;
11
+ export type FailureMark = {
12
+ errorClass: ErrorClass;
13
+ errorCode: ErrorCode;
14
+ /** Rich, LOCAL-ONLY. Never sent by default (D-001) — stripped from the wire payload. */
15
+ message?: string;
16
+ stack?: string;
17
+ };
18
+ /** Give one top-level invocation its own mark across every awaited dispatch path. */
19
+ export declare function runWithFailureScope<T>(operation: () => T): T;
20
+ /** Record what kind of failure just happened. Called at the failure site. */
21
+ export declare function markFailure(mark: FailureMark): void;
22
+ /** Take the mark and clear it. Cleared on read so it can never bleed into the next run. */
23
+ export declare function consumeFailure(): FailureMark | undefined;
24
+ /** Drop any mark. Called at the start of each run so a prior command can't contaminate this one. */
25
+ export declare function resetFailure(): void;
26
+ /**
27
+ * "You invoked this wrong" — thrown rather than returned. Same meaning as failWith: a typo.
28
+ * Throw this instead of a bare Error and the failure classifies itself correctly.
29
+ */
30
+ export declare class UsageError extends Error {
31
+ readonly errorCode: ErrorCode;
32
+ constructor(message: string, errorCode?: ErrorCode);
33
+ }
34
+ /**
35
+ * A boundary refused by design — B1 safety, B2 spec identity, B4 autonomy, a default-deny
36
+ * policy. THE PRODUCT IS WORKING. It exits nonzero because it stopped you on purpose, and it
37
+ * must never, ever page anyone.
38
+ */
39
+ export declare class GateBlock extends Error {
40
+ readonly errorCode: ErrorCode;
41
+ constructor(message: string, errorCode?: ErrorCode);
42
+ }
43
+ /**
44
+ * The thing you asked for does not exist — a packet dir, a loop id, a file. Nonzero, but not
45
+ * a defect: foo worked, the target just isn't there. Classifies as `not_found`, which never
46
+ * pages. Thrown rather than returned so the caller doesn't thread a special return value out.
47
+ */
48
+ export declare class NotFoundError extends Error {
49
+ readonly errorCode: ErrorCode;
50
+ constructor(message: string, errorCode?: ErrorCode);
51
+ }
52
+ /**
53
+ * Classify a thrown error that nothing marked. An `E*` errno (ENOENT, EACCES) is the
54
+ * filesystem or network failing under us; a typo and a gate refusal are not failures at all;
55
+ * anything else is a genuine unexpected fault, and gets someone's attention.
56
+ */
57
+ export declare function classifyThrown(error: unknown): FailureMark;
58
+ /**
59
+ * A stable, privacy-safe grouping key for a failure: the bounded code plus the normalized
60
+ * origin frame. Two failures with the same code AND the same frame are the same bug — which
61
+ * is what lets the digest tell "one bug hit nine people" apart from "nine unrelated
62
+ * E_UNKNOWNs in the same command".
63
+ *
64
+ * It is a one-way hash of content-free inputs (a bounded code and a `fn (basename)` string —
65
+ * no path, no line, no argument, no message), so it is safe on the metadata-only wire.
66
+ *
67
+ * NO STACK MEANS NO FINGERPRINT. This used to hash a `<no-stack>` sentinel instead, and the
68
+ * comment defended it as degrading "deterministically ... rather than collapsing at random".
69
+ * It had it exactly backwards: hashing a constant does not spread stackless failures out, it
70
+ * funnels EVERY one of them that shares a code into a single identity. In production that
71
+ * produced `3b07a3cdfb33` = sha256("E_UNKNOWN\n<no-stack>") on eight unrelated commands at
72
+ * once — asp reconcile, self check, self gate, research gate, asp validate, research
73
+ * validate, commands validate, reconcile — which the console then drew as ONE bug, named
74
+ * after whichever row happened to sort first, with the blast radius of all eight.
75
+ *
76
+ * It also silently broke the join to error reports: a report fingerprints WITH a stack and
77
+ * these rows fingerprinted WITHOUT one, so the two could never match. 0 of 140 did. Every
78
+ * stack the console displayed came from a fallback that guessed by error code, which is how
79
+ * `foo redact` came to show a "work-item missing" crash from specCmd.js.
80
+ *
81
+ * Returning undefined is the honest answer: callers already group by command + code when
82
+ * there is no fingerprint, which keeps unrelated commands apart instead of fusing them.
83
+ */
84
+ export declare function errorFingerprint(errorCode: string, stack?: string | null): string | undefined;