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,57 @@
1
+ import { type DiscoveryWrite } from "./discoveryArtifacts.js";
2
+ import { type DiscoveryEvidenceEnvelope } from "./discoveryEvidence.js";
3
+ import { type DiscoveryReceiptStatusEndpoint } from "./discoveryProcess.js";
4
+ import type { TrustStore } from "./trustEnvelope.js";
5
+ export type DiscoveryIndexEntry = {
6
+ id?: string;
7
+ path: string;
8
+ excerpt: string;
9
+ text: string;
10
+ };
11
+ export type DiscoveryIndex = {
12
+ entries: DiscoveryIndexEntry[];
13
+ };
14
+ export type ReconciliationKind = "exact" | "semantic_candidate" | "drift_candidate" | "draft_proposal";
15
+ export type ReconciliationOutcome = {
16
+ finding_id: string;
17
+ kind: ReconciliationKind;
18
+ canonical: boolean;
19
+ target_id?: string;
20
+ target_path?: string;
21
+ existing_excerpt?: string;
22
+ confidence: "low" | "medium" | "high";
23
+ dissent: string;
24
+ };
25
+ export type ReconciliationResult = {
26
+ outcomes: ReconciliationOutcome[];
27
+ };
28
+ export declare function buildDiscoveryIndex(root: string): DiscoveryIndex;
29
+ export declare function reconcileDiscoveryEvidence(root: string, envelope: DiscoveryEvidenceEnvelope): ReconciliationResult;
30
+ export declare function applyDiscoveryEvidence(root: string, studyDir: string, envelope: DiscoveryEvidenceEnvelope, now: string): {
31
+ status: "needs_review" | "clean_no_op";
32
+ writes: DiscoveryWrite[];
33
+ reconciliation: ReconciliationResult;
34
+ };
35
+ export declare function applyInboxDiscoveryEvidence(root: string, inboxDir: string, envelope: DiscoveryEvidenceEnvelope, now: string): {
36
+ status: "needs_review" | "clean_no_op";
37
+ writes: DiscoveryWrite[];
38
+ reconciliation: ReconciliationResult;
39
+ };
40
+ export type DiscoveryBundleApplyResult = {
41
+ status: "needs_review" | "clean_no_op";
42
+ writes: DiscoveryWrite[];
43
+ reconciliation: ReconciliationResult;
44
+ } | {
45
+ status: "needs_service_verification" | "invalid";
46
+ writes: [];
47
+ reason: string;
48
+ };
49
+ export declare function applyReceiptVerifiedDiscoveryBundle(input: {
50
+ root: string;
51
+ target_id: string;
52
+ studyDir: string;
53
+ bundle: unknown;
54
+ trust_store?: TrustStore<"foo">;
55
+ receipt_status?: DiscoveryReceiptStatusEndpoint;
56
+ now: string;
57
+ }): Promise<DiscoveryBundleApplyResult>;
@@ -0,0 +1,424 @@
1
+ import { appendFileSync, existsSync, readFileSync, readdirSync, writeFileSync } from "node:fs";
2
+ import path from "node:path";
3
+ import { loadDiscoveryRun, transitionDiscoveryRun } from "./discoveryArtifacts.js";
4
+ import { parseDiscoveryQualifiedRef, validateDiscoveryEvidence } from "./discoveryEvidence.js";
5
+ import { parse, stringify } from "./vendorYaml.js";
6
+ import { classifyProvider } from "./sourceIngress.js";
7
+ import { verifyDiscoveryBundleForApply } from "./discoveryProof.js";
8
+ import { createUnreachableDiscoveryReceiptStatus } from "./discoveryProcess.js";
9
+ const INDEX_DIRS = ["discovery", "research", "specs"];
10
+ const INDEX_EXTENSIONS = new Set([".md", ".yaml", ".yml", ".jsonl"]);
11
+ const ID_PATTERN = /\b([RDTFCPEH]-\d{3})\b/g;
12
+ const STOPWORDS = new Set(["about", "after", "again", "before", "being", "between", "could", "every", "should", "their", "there", "these", "those", "through", "with", "without", "would", "from", "into", "only", "that", "this", "when", "where", "which"]);
13
+ function walkFiles(dir) {
14
+ if (!existsSync(dir))
15
+ return [];
16
+ const files = [];
17
+ for (const entry of readdirSync(dir, { withFileTypes: true })) {
18
+ const full = path.join(dir, entry.name);
19
+ if (entry.isDirectory())
20
+ files.push(...walkFiles(full));
21
+ else if (entry.isFile() && INDEX_EXTENSIONS.has(path.extname(entry.name)))
22
+ files.push(full);
23
+ }
24
+ return files;
25
+ }
26
+ function excerpt(line) {
27
+ return line.trim().replace(/\s+/g, " ").slice(0, 240);
28
+ }
29
+ // YAML frontmatter is metadata wearing a document's opening lines. Indexed
30
+ // raw, its `---` delimiter became the "first content line" of every research
31
+ // paper — so review cards showed `existing_excerpt: ---` (#529).
32
+ function stripFrontmatter(text) {
33
+ if (!text.startsWith("---\n"))
34
+ return text;
35
+ const closing = text.indexOf("\n---", 4);
36
+ if (closing === -1)
37
+ return text;
38
+ const afterDelimiter = text.indexOf("\n", closing + 1);
39
+ return afterDelimiter === -1 ? "" : text.slice(afterDelimiter + 1);
40
+ }
41
+ // Paragraph-sized blocks, because the semantic score must mean CONCENTRATED
42
+ // overlap. Indexing each file as one whole-document bag of words meant the
43
+ // longest, most vocabulary-rich document cleared the overlap bar against
44
+ // nearly any paraphrase — 78 findings about unrelated industries all "matched"
45
+ // the same research paper (#529). A block that has no blank lines to split on
46
+ // (events.jsonl) falls back to per-line blocks so it can never re-become a
47
+ // whole-file bag.
48
+ function contentBlocks(text) {
49
+ const blocks = [];
50
+ for (const paragraph of stripFrontmatter(text).split(/\n{2,}/)) {
51
+ const trimmed = paragraph.trim();
52
+ if (!trimmed)
53
+ continue;
54
+ if (trimmed.length > 1500) {
55
+ for (const line of trimmed.split("\n"))
56
+ if (line.trim())
57
+ blocks.push(line.trim());
58
+ }
59
+ else {
60
+ blocks.push(trimmed);
61
+ }
62
+ }
63
+ return blocks;
64
+ }
65
+ export function buildDiscoveryIndex(root) {
66
+ const entries = [];
67
+ for (const dirName of INDEX_DIRS) {
68
+ for (const file of walkFiles(path.join(root, dirName)).sort()) {
69
+ const relative = path.relative(root, file).split(path.sep).join("/");
70
+ const text = readFileSync(file, "utf8");
71
+ for (const line of text.split("\n")) {
72
+ const ids = [...line.matchAll(ID_PATTERN)].map((match) => match[1]);
73
+ for (const id of ids)
74
+ entries.push({ id, path: relative, excerpt: excerpt(line), text: line });
75
+ }
76
+ for (const block of contentBlocks(text)) {
77
+ entries.push({ path: relative, excerpt: excerpt(block), text: block });
78
+ }
79
+ }
80
+ }
81
+ return { entries };
82
+ }
83
+ function tokens(text) {
84
+ return new Set((text.toLowerCase().match(/[a-z0-9]+/g) ?? []).filter((token) => token.length >= 4 && !STOPWORDS.has(token)));
85
+ }
86
+ function semanticScore(finding, entry) {
87
+ const left = tokens(finding);
88
+ if (left.size === 0)
89
+ return 0;
90
+ const right = tokens(entry.text);
91
+ let overlap = 0;
92
+ for (const token of left)
93
+ if (right.has(token))
94
+ overlap += 1;
95
+ if (overlap < 3)
96
+ return 0;
97
+ return overlap / left.size;
98
+ }
99
+ function exactEntry(index, refs) {
100
+ // D-011 (nango-discovery-connector-v0 T-005): only a packet-qualified
101
+ // reference can create an exact mapping, and only when it resolves to
102
+ // exactly one record inside that packet's directory. A bare `R-001`-style
103
+ // id is review-only — it falls through to semantic matching, and the
104
+ // first-match behavior this function used to have (including a bare
105
+ // substring hit on any indexed line) can never silently win for an
106
+ // ambiguous reference (V-007).
107
+ const resolved = [];
108
+ for (const ref of refs) {
109
+ const qualified = parseDiscoveryQualifiedRef(ref);
110
+ if (!qualified)
111
+ continue; // bare ids and https URLs are review-only, never exact
112
+ const packetPrefix = `specs/${qualified.packet_slug}/`;
113
+ for (const entry of index.entries) {
114
+ if (entry.id === qualified.record_id && entry.path.startsWith(packetPrefix))
115
+ resolved.push(entry);
116
+ }
117
+ }
118
+ if (resolved.length === 0)
119
+ return undefined;
120
+ // Multiple indexed mentions of the same record within one file are one
121
+ // record (definition plus body prose); mentions across files are ambiguous
122
+ // and stay review-only.
123
+ const paths = new Set(resolved.map((entry) => entry.path));
124
+ return paths.size === 1 ? resolved[0] : undefined;
125
+ }
126
+ function outcomeFor(index, finding) {
127
+ const exact = exactEntry(index, finding.explicit_refs ?? []);
128
+ if (exact) {
129
+ return {
130
+ finding_id: finding.finding_id,
131
+ kind: finding.relationship_hint === "contradicts" ? "drift_candidate" : "exact",
132
+ canonical: finding.relationship_hint !== "contradicts",
133
+ target_id: exact.id,
134
+ target_path: exact.path,
135
+ existing_excerpt: exact.excerpt,
136
+ confidence: "high",
137
+ dissent: finding.dissent,
138
+ };
139
+ }
140
+ let best;
141
+ for (const entry of index.entries) {
142
+ const score = semanticScore(finding.paraphrase, entry);
143
+ if (!best || score > best.score)
144
+ best = { entry, score };
145
+ }
146
+ if (best && best.score >= 0.35) {
147
+ return {
148
+ finding_id: finding.finding_id,
149
+ kind: finding.relationship_hint === "contradicts" ? "drift_candidate" : "semantic_candidate",
150
+ canonical: false,
151
+ target_id: best.entry.id,
152
+ target_path: best.entry.path,
153
+ existing_excerpt: best.entry.excerpt,
154
+ confidence: best.score >= 0.6 ? "high" : "medium",
155
+ dissent: finding.dissent,
156
+ };
157
+ }
158
+ return { finding_id: finding.finding_id, kind: "draft_proposal", canonical: false, confidence: "low", dissent: finding.dissent };
159
+ }
160
+ export function reconcileDiscoveryEvidence(root, envelope) {
161
+ const index = buildDiscoveryIndex(root);
162
+ return { outcomes: envelope.findings.map((finding) => outcomeFor(index, finding)) };
163
+ }
164
+ function relativeWrite(root, file) {
165
+ return { path: path.relative(root, file).split(path.sep).join("/"), action: "updated" };
166
+ }
167
+ function nextArtifactId(records, key, prefix) {
168
+ const highest = records.reduce((max, record) => {
169
+ const match = new RegExp(`^${prefix}-(\\d+)$`).exec(String(record[key] ?? ""));
170
+ return match ? Math.max(max, Number(match[1])) : max;
171
+ }, 0);
172
+ return `${prefix}-${String(highest + 1).padStart(3, "0")}`;
173
+ }
174
+ export function applyDiscoveryEvidence(root, studyDir, envelope, now) {
175
+ const run = loadDiscoveryRun(studyDir);
176
+ validateDiscoveryEvidence(envelope, { expected_study_id: run.study_id, expected_lane: "study_linked" });
177
+ const findingsPath = path.join(studyDir, "findings.yaml");
178
+ const proposalsPath = path.join(studyDir, "proposals.yaml");
179
+ const reportPath = path.join(studyDir, "report.md");
180
+ const findingsDoc = parse(readFileSync(findingsPath, "utf8"));
181
+ if (findingsDoc.findings.some((finding) => finding.source_fingerprint === envelope.source.source_fingerprint)) {
182
+ return { status: "clean_no_op", writes: [], reconciliation: { outcomes: [] } };
183
+ }
184
+ const reconciliation = reconcileDiscoveryEvidence(root, envelope);
185
+ // Every applied record carries its provider's registry classification so
186
+ // reconcile renders each source's evidence by its class (RISK-002), and —
187
+ // only when the summary is INCOMPLETE — the coverage limitation. A complete
188
+ // summary records nothing: findings never claim a raw transcript exists.
189
+ const classification = classifyProvider(envelope.source.provider);
190
+ const summaryCoverage = envelope.coverage.transcript_complete === false
191
+ ? { transcript_complete: false, caveats: [...envelope.coverage.caveats] }
192
+ : undefined;
193
+ const canonicalFindingIds = new Map();
194
+ for (const finding of envelope.findings) {
195
+ const outcome = reconciliation.outcomes.find((candidate) => candidate.finding_id === finding.finding_id);
196
+ const canonicalFindingId = nextArtifactId(findingsDoc.findings, "finding_id", "F");
197
+ canonicalFindingIds.set(finding.finding_id, canonicalFindingId);
198
+ findingsDoc.findings.push({
199
+ ...finding,
200
+ finding_id: canonicalFindingId,
201
+ source_finding_id: finding.finding_id,
202
+ lane: envelope.lane,
203
+ source_provider: envelope.source.provider,
204
+ source_category: classification.source_category,
205
+ evidence_class: classification.evidence_class,
206
+ ...(summaryCoverage ? { summary_coverage: summaryCoverage } : {}),
207
+ source_url: envelope.source.stable_url ?? null,
208
+ source_fingerprint: envelope.source.source_fingerprint,
209
+ completed_at: envelope.source.completed_at,
210
+ reconciliation: { ...outcome, finding_id: canonicalFindingId },
211
+ review_state: "needs_review",
212
+ });
213
+ }
214
+ writeFileSync(findingsPath, stringify(findingsDoc));
215
+ const proposalsDoc = parse(readFileSync(proposalsPath, "utf8"));
216
+ for (const outcome of reconciliation.outcomes.filter((candidate) => candidate.kind !== "exact")) {
217
+ const finding = envelope.findings.find((candidate) => candidate.finding_id === outcome.finding_id);
218
+ proposalsDoc.proposals.push({
219
+ proposal_id: nextArtifactId(proposalsDoc.proposals, "proposal_id", "P"),
220
+ source_finding_ids: [canonicalFindingIds.get(finding.finding_id)],
221
+ proposed_text: outcome.kind === "draft_proposal" ? finding.paraphrase : null,
222
+ rationale: outcome.kind,
223
+ existing_artifact_candidates: outcome.target_path ? [{ path: outcome.target_path, id: outcome.target_id ?? null, excerpt: outcome.existing_excerpt ?? null }] : [],
224
+ confidence: outcome.confidence,
225
+ dissent: finding.dissent,
226
+ destination: null,
227
+ state: "needs_review",
228
+ disposition: null,
229
+ });
230
+ }
231
+ writeFileSync(proposalsPath, stringify(proposalsDoc));
232
+ const findings = envelope.findings.map((finding) => `- ${canonicalFindingIds.get(finding.finding_id)}: ${finding.paraphrase} (${finding.confidence})`).join("\n");
233
+ const dissent = envelope.findings.map((finding) => `- ${canonicalFindingIds.get(finding.finding_id)}: ${finding.dissent}`).join("\n");
234
+ writeFileSync(reportPath, [
235
+ "# Discovery report",
236
+ "",
237
+ "## Current fit belief",
238
+ "",
239
+ "Needs human review; automation does not decide fit.",
240
+ "",
241
+ "## Evidence that moved the belief",
242
+ "",
243
+ findings,
244
+ "",
245
+ "## Revised belief and confidence",
246
+ "",
247
+ "Pending human review.",
248
+ "",
249
+ "## Contradictions and dissent",
250
+ "",
251
+ dissent,
252
+ "",
253
+ "## Proposals needing review",
254
+ "",
255
+ ...reconciliation.outcomes.filter((candidate) => candidate.kind !== "exact").map((candidate) => `- ${candidate.finding_id}: ${candidate.kind}`),
256
+ "",
257
+ ].join("\n"));
258
+ const writes = [relativeWrite(root, findingsPath), relativeWrite(root, proposalsPath), relativeWrite(root, reportPath)];
259
+ // A study already parked in needs_review has no needs_review -> needs_review transition
260
+ // (ALLOWED_TRANSITIONS), so re-applying a distinct-fingerprint envelope must not throw:
261
+ // record the derived artifacts and leave the state where it already is.
262
+ if (loadDiscoveryRun(studyDir).state !== "needs_review") {
263
+ writes.push(...transitionDiscoveryRun(studyDir, "needs_review", { type: "agent", id: "foo-discovery" }, now));
264
+ }
265
+ return { status: "needs_review", writes, reconciliation };
266
+ }
267
+ // A workspace whose discovery inbox has never received evidence has no
268
+ // findings/proposals files yet — nothing created them before the first apply.
269
+ // An absent file is an empty collection, not a crash.
270
+ function readInboxYamlDoc(filePath) {
271
+ if (!existsSync(filePath))
272
+ return { schema_version: "0.1", findings: [], proposals: [] };
273
+ return parse(readFileSync(filePath, "utf8"));
274
+ }
275
+ export function applyInboxDiscoveryEvidence(root, inboxDir, envelope, now) {
276
+ validateDiscoveryEvidence(envelope, { expected_study_id: envelope.study_id, expected_lane: "unassigned_call_evidence" });
277
+ const findingsPath = path.join(inboxDir, "findings.yaml");
278
+ const proposalsPath = path.join(inboxDir, "proposals.yaml");
279
+ const eventsPath = path.join(inboxDir, "events.jsonl");
280
+ const findingsDoc = readInboxYamlDoc(findingsPath);
281
+ const existingSourceRecords = findingsDoc.findings.filter((finding) => finding.source_fingerprint === envelope.source.source_fingerprint);
282
+ if (existingSourceRecords.length > 0) {
283
+ const existingIds = existingSourceRecords.map((finding) => String(finding.source_finding_id ?? "")).sort();
284
+ const replayIds = envelope.findings.map((finding) => finding.finding_id).sort();
285
+ if (existingIds.length !== replayIds.length || existingIds.some((id, index) => id !== replayIds[index])) {
286
+ throw new Error("source replay finding set does not match the existing derived evidence");
287
+ }
288
+ let repaired = false;
289
+ for (const finding of envelope.findings) {
290
+ const recordIndex = findingsDoc.findings.findIndex((candidate) => candidate.source_fingerprint === envelope.source.source_fingerprint
291
+ && candidate.source_finding_id === finding.finding_id);
292
+ const current = findingsDoc.findings[recordIndex];
293
+ let next = current;
294
+ if (typeof current.headline !== "string" || !current.headline.trim()) {
295
+ const { finding_id: findingId, ...fields } = current;
296
+ delete fields.headline;
297
+ next = { finding_id: findingId, headline: finding.headline, ...fields };
298
+ repaired = true;
299
+ }
300
+ if (envelope.source.stable_url
301
+ && (typeof next.source_url !== "string" || !next.source_url.trim())) {
302
+ next = { ...next, source_url: envelope.source.stable_url };
303
+ repaired = true;
304
+ }
305
+ findingsDoc.findings[recordIndex] = next;
306
+ }
307
+ if (!repaired)
308
+ return { status: "clean_no_op", writes: [], reconciliation: { outcomes: [] } };
309
+ writeFileSync(findingsPath, stringify(findingsDoc));
310
+ return {
311
+ status: "needs_review",
312
+ writes: [relativeWrite(root, findingsPath)],
313
+ reconciliation: { outcomes: [] },
314
+ };
315
+ }
316
+ const reconciliation = reconcileDiscoveryEvidence(root, envelope);
317
+ // Every applied record carries its provider's registry classification so
318
+ // reconcile renders each source's evidence by its class (RISK-002), and —
319
+ // only when the summary is INCOMPLETE — the coverage limitation. A complete
320
+ // summary records nothing: findings never claim a raw transcript exists.
321
+ const classification = classifyProvider(envelope.source.provider);
322
+ const summaryCoverage = envelope.coverage.transcript_complete === false
323
+ ? { transcript_complete: false, caveats: [...envelope.coverage.caveats] }
324
+ : undefined;
325
+ const canonicalFindingIds = new Map();
326
+ for (const finding of envelope.findings) {
327
+ const mapped = reconciliation.outcomes.find((candidate) => candidate.finding_id === finding.finding_id);
328
+ const canonicalFindingId = nextArtifactId(findingsDoc.findings, "finding_id", "F");
329
+ canonicalFindingIds.set(finding.finding_id, canonicalFindingId);
330
+ findingsDoc.findings.push({
331
+ ...finding,
332
+ finding_id: canonicalFindingId,
333
+ source_finding_id: finding.finding_id,
334
+ lane: "unassigned_call_evidence",
335
+ source_provider: envelope.source.provider,
336
+ source_category: classification.source_category,
337
+ evidence_class: classification.evidence_class,
338
+ ...(summaryCoverage ? { summary_coverage: summaryCoverage } : {}),
339
+ inbox_scope_id: envelope.study_id.slice("inbox:".length),
340
+ source_url: envelope.source.stable_url ?? null,
341
+ source_fingerprint: envelope.source.source_fingerprint,
342
+ completed_at: envelope.source.completed_at,
343
+ reconciliation: { ...mapped, finding_id: canonicalFindingId },
344
+ review_state: "needs_review",
345
+ attached_to: null,
346
+ });
347
+ }
348
+ writeFileSync(findingsPath, stringify(findingsDoc));
349
+ const proposalsDoc = readInboxYamlDoc(proposalsPath);
350
+ for (const mapped of reconciliation.outcomes.filter((candidate) => candidate.kind !== "exact")) {
351
+ const finding = envelope.findings.find((candidate) => candidate.finding_id === mapped.finding_id);
352
+ proposalsDoc.proposals.push({
353
+ proposal_id: nextArtifactId(proposalsDoc.proposals, "proposal_id", "P"),
354
+ source_finding_ids: [canonicalFindingIds.get(finding.finding_id)],
355
+ proposed_text: mapped.kind === "draft_proposal" ? finding.paraphrase : null,
356
+ rationale: mapped.kind,
357
+ existing_artifact_candidates: mapped.target_path ? [{ path: mapped.target_path, id: mapped.target_id ?? null, excerpt: mapped.existing_excerpt ?? null }] : [],
358
+ confidence: mapped.confidence,
359
+ dissent: finding.dissent,
360
+ destination: null,
361
+ state: "needs_review",
362
+ disposition: null,
363
+ });
364
+ }
365
+ writeFileSync(proposalsPath, stringify(proposalsDoc));
366
+ appendFileSync(eventsPath, `${JSON.stringify({
367
+ specversion: "1.0",
368
+ id: `evt_discovery_inbox_evidence_${Date.parse(now)}`,
369
+ source: "agent://foo/discovery",
370
+ type: "com.adaptivespec.discovery.inbox_evidence_applied",
371
+ subject: `scope:${envelope.study_id.slice("inbox:".length)}`,
372
+ time: now,
373
+ actor: { type: "agent", id: "foo-discovery" },
374
+ data: { finding_ids: envelope.findings.map((finding) => canonicalFindingIds.get(finding.finding_id)), review_state: "needs_review" },
375
+ })}\n`);
376
+ return {
377
+ status: "needs_review",
378
+ writes: [relativeWrite(root, findingsPath), relativeWrite(root, proposalsPath), relativeWrite(root, eventsPath)],
379
+ reconciliation,
380
+ };
381
+ }
382
+ // The hosted portable-bundle apply boundary: verify everything locally
383
+ // checkable (discoveryProof gate), then ask the service `discovery_receipt_status`
384
+ // as the LAST network boundary before any write, fail closed on unreachability,
385
+ // a non-active receipt, or any revocation-epoch movement, and only then run
386
+ // the normal discovery apply — which still re-validates and stops at
387
+ // needs_review. No outcome but the two write states touches disk (C-009).
388
+ export async function applyReceiptVerifiedDiscoveryBundle(input) {
389
+ const verified = verifyDiscoveryBundleForApply({
390
+ bundle: input.bundle,
391
+ target_id: input.target_id,
392
+ root: input.root,
393
+ study_dir: input.studyDir,
394
+ ...(input.trust_store ? { trust_store: input.trust_store } : {}),
395
+ now: input.now,
396
+ });
397
+ if (!verified.ok)
398
+ return { status: "invalid", writes: [], reason: verified.message };
399
+ try {
400
+ const status = await (input.receipt_status ?? createUnreachableDiscoveryReceiptStatus()).receiptStatus({
401
+ receipt_hash: verified.receipt_hash,
402
+ target_ref: verified.registry.target_ref,
403
+ });
404
+ if (status.receipt_status !== "active" || status.revocation_epoch !== verified.registry.revocation_epoch) {
405
+ return { status: "needs_service_verification", writes: [], reason: "the discovery service could not confirm the receipt is active at the current revocation epoch; nothing was written" };
406
+ }
407
+ }
408
+ catch {
409
+ // Bounded by design: error text can carry provider or transport content,
410
+ // so the refusal names the state, never the underlying error body.
411
+ return { status: "needs_service_verification", writes: [], reason: "the discovery service is unreachable; receipt status could not be verified and nothing was written" };
412
+ }
413
+ try {
414
+ const applied = verified.registry.lane === "inbox"
415
+ ? applyInboxDiscoveryEvidence(input.root, input.studyDir, verified.bundle.envelope, input.now)
416
+ : applyDiscoveryEvidence(input.root, input.studyDir, verified.bundle.envelope, input.now);
417
+ return { status: applied.status, writes: applied.writes, reconciliation: applied.reconciliation };
418
+ }
419
+ catch {
420
+ // Same boundary: a failed apply reports the bounded refusal, and no
421
+ // partial discovery update was accepted.
422
+ return { status: "invalid", writes: [], reason: "the verified evidence could not be applied; no partial discovery update was accepted" };
423
+ }
424
+ }
@@ -0,0 +1,12 @@
1
+ import { type DiscoveryCommandOutcome } from "./discoveryCommand.js";
2
+ import { type SynthesisTransport } from "./discoverySynthesis.js";
3
+ import { type FetchLike } from "./slackNango.js";
4
+ export type SlackDiscoveryDeps = {
5
+ fetchImpl?: FetchLike;
6
+ env?: NodeJS.ProcessEnv;
7
+ now?: () => string;
8
+ sleep?: (ms: number) => Promise<void>;
9
+ transport?: SynthesisTransport;
10
+ fetchTimeoutMs?: number;
11
+ };
12
+ export declare function runSlackDiscovery(root: string, args: string[], deps?: SlackDiscoveryDeps): Promise<DiscoveryCommandOutcome>;