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,61 @@
1
+ import { type ClientKind } from "../channelFreshness.js";
2
+ export declare function fetchLatestVersion(registry?: string, timeoutMs?: number): Promise<string | null>;
3
+ export type UpdateAction = "install" | "current" | "unreachable" | "repo";
4
+ export type UpdatePlan = {
5
+ action: UpdateAction;
6
+ running: string;
7
+ latest: string | null;
8
+ /** Exactly what an install would exec — argv, so a path with a space is not a bug. */
9
+ argv: string[] | null;
10
+ /** The same thing, as the line we show the user before running it. */
11
+ command: string | null;
12
+ };
13
+ export declare function installArgv(kind: ClientKind, latest: string, home?: string): string[] | null;
14
+ export declare function updatePlan(input: {
15
+ running: string;
16
+ latest: string | null;
17
+ kind: ClientKind;
18
+ home?: string;
19
+ }): UpdatePlan;
20
+ export type UpdateOutcome = {
21
+ output: string;
22
+ exitCode: number;
23
+ };
24
+ export type Installer = (argv: string[]) => {
25
+ status: number | null;
26
+ };
27
+ /**
28
+ * The offer — the LAST thing a run does, and the only place foo installs
29
+ * anything you did not ask it to install.
30
+ *
31
+ * The same two rules that shape the error-report ask, pulling the same two ways:
32
+ *
33
+ * Never interrupt the work. The question waits until the command has finished
34
+ * and printed everything it meant to print. foo learns about the new build
35
+ * mid-run (from a response to a request it was already making) and says
36
+ * nothing until the work is done.
37
+ *
38
+ * Never hang. Most productfoo runs are piped or agent-driven. A prompt with nobody
39
+ * there to answer is not a question, it is a deadlock — so productfoo asks only when
40
+ * a real human is on BOTH ends of the terminal, and otherwise prints the one
41
+ * line and gets out of the way.
42
+ *
43
+ * The answer defaults to no. Silence is not consent — least of all consent to
44
+ * write to an npm prefix. And a `no` is a real no: foo records that it spoke,
45
+ * and does not ask again about this build today.
46
+ */
47
+ export declare function offerUpdate(io?: {
48
+ stdin?: NodeJS.ReadStream;
49
+ stderr?: NodeJS.WriteStream;
50
+ args?: string[];
51
+ install?: Installer;
52
+ kind?: ClientKind;
53
+ }): Promise<void>;
54
+ export declare function updateCommand(args?: string[], deps?: {
55
+ latest?: () => Promise<string | null>;
56
+ install?: Installer;
57
+ running?: string;
58
+ kind?: ClientKind;
59
+ isTTY?: boolean;
60
+ env?: NodeJS.ProcessEnv;
61
+ }): Promise<UpdateOutcome>;
@@ -0,0 +1,244 @@
1
+ // `foo update` — take the build foo just told you about.
2
+ //
3
+ // The notice (updateNotice.ts) says a new version exists. This is the other
4
+ // half: the thing you type when it does. Without it, "0.1.19 is available" ends
5
+ // in a paste — select a long npm string out of a scrollback, trust it, run it —
6
+ // and a tester who is mid-task simply doesn't, which is how someone sits on a
7
+ // stale build for days while being told, correctly, every morning.
8
+ //
9
+ // Four rules:
10
+ // - UPDATE THE COPY THAT ACTUALLY RUNS. There can be two `foo` installs on one
11
+ // machine: the global npm one, and the channel one under ~/.foo/versions/dist
12
+ // that the PATH shim (`~/.foo/bin/foo`) execs. They are different directories,
13
+ // and `npm install -g` moves only the first. This is not hypothetical — it is
14
+ // why the owner's `foo` sat on 0.1.18 while a global install of 0.1.20
15
+ // reported success: the command updated a copy she never ran. An update
16
+ // command that installs somewhere other than where you are running from is
17
+ // worse than none, because it lies. So the install target is derived from
18
+ // where THIS process is executing, never assumed.
19
+ // - Never update a repo checkout. `npm install` over a dev build would replace
20
+ // what the developer is editing with a published copy. A repo run refuses.
21
+ // - Pin the version npm named. A bare package spec installs whatever
22
+ // is newest at that instant — the same drift the retired Git channel had
23
+ // when bare `main` floated — while `pkg@0.1.20` installs the build the
24
+ // user was actually told about.
25
+ // - Say what it will run before it runs it. This mutates an npm prefix; that
26
+ // is not something to do behind a spinner.
27
+ import { spawnSync } from "node:child_process";
28
+ import path from "node:path";
29
+ import { compareVersions, distributionPackageName, fooHome, runningClientKind } from "../channelFreshness.js";
30
+ import { CHANGELOG_URL, clientVersion, pendingUpdate, recordRelaySpoken, recordUpdateSpoken, } from "../updateNotice.js";
31
+ import { glyphsEnabled, withGlyph } from "../statusGlyphs.js";
32
+ // Public updates use npm package metadata. No productfoo account, token or hosted
33
+ // service participates; old private clients retain their existing server path.
34
+ const STABLE_VERSION = /^(0|[1-9]\d*)\.(0|[1-9]\d*)\.(0|[1-9]\d*)$/;
35
+ const DEFAULT_REGISTRY = "https://registry.npmjs.org";
36
+ // Match npm install's effective registry, including local npmrc settings.
37
+ // Config lookup is local; an absent npm executable falls back to public npm.
38
+ function npmRegistry(env, kind) {
39
+ const configured = env.npm_config_registry?.trim() || env.NPM_CONFIG_REGISTRY?.trim();
40
+ if (configured)
41
+ return configured;
42
+ const args = ["config", "get", "registry"];
43
+ if (kind === "global")
44
+ args.push("--global");
45
+ if (kind === "channel")
46
+ args.push("--prefix", path.join(fooHome(), "versions", "dist"));
47
+ const result = spawnSync("npm", args, { env, encoding: "utf8", timeout: 2_000 });
48
+ return result.status === 0 && result.stdout.trim() ? result.stdout.trim() : DEFAULT_REGISTRY;
49
+ }
50
+ export async function fetchLatestVersion(registry = npmRegistry(process.env), timeoutMs = 10_000) {
51
+ try {
52
+ const packageName = distributionPackageName().replace("/", "%2f");
53
+ const res = await fetch(`${registry.replace(/\/+$/, "")}/${packageName}/latest`, {
54
+ signal: AbortSignal.timeout(timeoutMs),
55
+ });
56
+ if (!res.ok)
57
+ return null;
58
+ const body = await res.json();
59
+ return typeof body?.version === "string" && STABLE_VERSION.test(body.version) ? body.version : null;
60
+ }
61
+ catch {
62
+ // Unknown stays unknown: an offline or malformed reply is never proof
63
+ // that the running copy is current.
64
+ return null;
65
+ }
66
+ }
67
+ // What npm installs: the published package at the version npm named,
68
+ // resolved through the ONE distribution-target contract (channelFreshness.ts)
69
+ // — the package name is never hardcoded here, so the owner's final npm
70
+ // identity (or a later successor rename) flows through unchanged.
71
+ //
72
+ // Where the foo that is RUNNING lives decides what npm has to be pointed at to
73
+ // replace it: global — the ordinary `npm install -g` copy; channel — the copy
74
+ // under ~/.foo/versions/<channel> that the PATH shim execs, where `-g` would
75
+ // install past it and change nothing the user runs.
76
+ //
77
+ // `--prefix <abs path>`, not the `~/.foo/...` string the docs print: argv is not
78
+ // a shell, and nothing expands a tilde here.
79
+ export function installArgv(kind, latest, home = fooHome()) {
80
+ const pkg = `${distributionPackageName()}@${latest}`;
81
+ if (kind === "global")
82
+ return ["npm", "install", "-g", pkg];
83
+ if (kind === "channel")
84
+ return ["npm", "install", "--prefix", path.join(home, "versions", "dist"), pkg];
85
+ return null; // repo — nothing to install over
86
+ }
87
+ // Pure decision, no network and no npm. Every branch below is a test.
88
+ export function updatePlan(input) {
89
+ const { running, latest, kind } = input;
90
+ const none = { running, latest, argv: null, command: null };
91
+ if (kind === "repo")
92
+ return { action: "repo", ...none };
93
+ if (!latest || !STABLE_VERSION.test(latest))
94
+ return { action: "unreachable", ...none, latest: null };
95
+ if (compareVersions(running, latest) >= 0)
96
+ return { action: "current", ...none };
97
+ const argv = installArgv(kind, latest, input.home ?? fooHome());
98
+ return { action: "install", running, latest, argv, command: argv ? argv.join(" ") : null };
99
+ }
100
+ const npmInstaller = ([command, ...args]) => spawnSync(command, args, { stdio: "inherit" });
101
+ /**
102
+ * The offer — the LAST thing a run does, and the only place foo installs
103
+ * anything you did not ask it to install.
104
+ *
105
+ * The same two rules that shape the error-report ask, pulling the same two ways:
106
+ *
107
+ * Never interrupt the work. The question waits until the command has finished
108
+ * and printed everything it meant to print. foo learns about the new build
109
+ * mid-run (from a response to a request it was already making) and says
110
+ * nothing until the work is done.
111
+ *
112
+ * Never hang. Most productfoo runs are piped or agent-driven. A prompt with nobody
113
+ * there to answer is not a question, it is a deadlock — so productfoo asks only when
114
+ * a real human is on BOTH ends of the terminal, and otherwise prints the one
115
+ * line and gets out of the way.
116
+ *
117
+ * The answer defaults to no. Silence is not consent — least of all consent to
118
+ * write to an npm prefix. And a `no` is a real no: foo records that it spoke,
119
+ * and does not ask again about this build today.
120
+ */
121
+ export async function offerUpdate(io = {}) {
122
+ try {
123
+ const p = pendingUpdate();
124
+ if (!p)
125
+ return;
126
+ const stdin = io.stdin ?? process.stdin;
127
+ const stderr = io.stderr ?? process.stderr;
128
+ const args = io.args ?? [];
129
+ const kind = io.kind ?? runningClientKind();
130
+ // The agent relay: a line for the coding agent that ran foo to surface to its
131
+ // human. Never under --json — it would corrupt the payload the agent is
132
+ // parsing — and when suppressed there, do NOT record, so a later non-json run
133
+ // in the same session still gets to relay (R-004).
134
+ if (p.audience === "agent") {
135
+ if (args.includes("--json"))
136
+ return;
137
+ stderr.write(`${p.line}\n`);
138
+ // Record into the agent's OWN session ration, never the human's day
139
+ // ration — otherwise a person who also runs foo by hand loses their
140
+ // interactive offer for the rest of the day (R-001 says it is unchanged).
141
+ recordRelaySpoken(p.latest);
142
+ return;
143
+ }
144
+ // Whatever happens below, this build has now been spoken about today. Record
145
+ // it FIRST: if the install throws, or the user ^C's out of the prompt, the
146
+ // one thing that must not happen is foo re-asking on their very next command.
147
+ recordUpdateSpoken(p.latest);
148
+ // Three reasons to state the fact and never ask:
149
+ // - nobody is on the other end (piped, hooked, agent-driven);
150
+ // - the run is emitting machine output, and a machine cannot answer;
151
+ // - it is a repo checkout, where there is nothing to install over anyway.
152
+ const canAsk = Boolean(stdin.isTTY) && Boolean(stderr.isTTY) && !args.includes("--json") && kind !== "repo";
153
+ if (!canAsk) {
154
+ stderr.write(`${p.line}\n`);
155
+ return;
156
+ }
157
+ const plan = updatePlan({ running: p.running, latest: p.latest, kind });
158
+ if (plan.action !== "install" || !plan.argv) {
159
+ stderr.write(`${p.line}\n`);
160
+ return;
161
+ }
162
+ const readline = await import("node:readline/promises");
163
+ const rl = readline.createInterface({ input: stdin, output: stderr });
164
+ try {
165
+ stderr.write(`\nfoo ${p.running} → ${p.latest} is available.\n`);
166
+ stderr.write(` What's new: ${CHANGELOG_URL}\n`);
167
+ // Say what the yes DOES. "Install now? [y/N]" hides the fact that a key is
168
+ // about to write to an npm prefix; someone on a locked-down machine needs
169
+ // to know which command they are authorizing BEFORE they press y.
170
+ stderr.write(` Installing runs: ${plan.command}\n`);
171
+ const answer = (await rl.question(" Install it now? [y/N] ")).trim().toLowerCase();
172
+ if (answer !== "y" && answer !== "yes") {
173
+ stderr.write(" Not installing. Run `foo update` whenever you want it.\n");
174
+ return;
175
+ }
176
+ stderr.write("\n");
177
+ const result = (io.install ?? npmInstaller)(plan.argv);
178
+ stderr.write(result.status === 0
179
+ ? `\nfoo ${p.latest} is installed — it takes effect on your next command.\n`
180
+ : `\nThe install failed, so you are still on foo ${p.running}. npm's error is above; \`foo update\` retries.\n`);
181
+ }
182
+ finally {
183
+ rl.close();
184
+ }
185
+ }
186
+ catch {
187
+ // An update offer may never change what the command was asked to do, and may
188
+ // never be the reason a run fails.
189
+ }
190
+ }
191
+ export async function updateCommand(args = [], deps = {}) {
192
+ const env = deps.env ?? process.env;
193
+ const asJson = args.includes("--json");
194
+ const checkOnly = args.includes("--check");
195
+ const glyphs = glyphsEnabled({ isTTY: deps.isTTY ?? Boolean(process.stdout.isTTY), env, args });
196
+ const running = deps.running ?? clientVersion();
197
+ const kind = deps.kind ?? runningClientKind();
198
+ const latest = await (deps.latest ?? (() => fetchLatestVersion(npmRegistry(env, kind))))();
199
+ const plan = updatePlan({ running, latest, kind });
200
+ if (asJson) {
201
+ return {
202
+ output: `${JSON.stringify({ running: plan.running, latest: plan.latest, state: plan.action, command: plan.command }, null, 2)}\n`,
203
+ exitCode: plan.action === "unreachable" ? 1 : 0,
204
+ };
205
+ }
206
+ switch (plan.action) {
207
+ case "repo":
208
+ // The owner, in the checkout. Nothing to install over, and saying "you are
209
+ // current" would be meaningless — the repo build is whatever they last
210
+ // edited. Give them the one fact they might actually want.
211
+ return {
212
+ output: `foo ${plan.running} — you're running the repo build, so there is nothing to install over it.${plan.latest ? ` The published release is ${plan.latest}.` : ""}\n`,
213
+ exitCode: 0,
214
+ };
215
+ case "unreachable":
216
+ return {
217
+ output: withGlyph("blocked", `blocked — couldn't get a valid latest version from npm, so we can't tell whether ${plan.running} is current. Your install is unchanged; retry with foo update --check.\n`, glyphs),
218
+ exitCode: 1,
219
+ };
220
+ case "current":
221
+ return { output: withGlyph("proven", `proven — foo ${plan.running} is the newest published build.\n`, glyphs), exitCode: 0 };
222
+ case "install": {
223
+ const header = `foo ${plan.running} → ${plan.latest}\nWhat's new: ${CHANGELOG_URL}\n`;
224
+ if (checkOnly) {
225
+ // --check is what a script or an agent runs: report, never mutate.
226
+ return { output: `${header}Update with: foo update\n`, exitCode: 0 };
227
+ }
228
+ process.stdout.write(`${header}Running: ${plan.command}\n\n`);
229
+ const result = (deps.install ?? npmInstaller)(plan.argv);
230
+ if (result.status !== 0) {
231
+ // npm already printed its own failure to the inherited stderr; do not
232
+ // paraphrase it. Say only what the user needs: nothing changed.
233
+ return {
234
+ output: withGlyph("blocked", `\nblocked — the install failed, so you are still on foo ${plan.running}. npm's error is above.\n`, glyphs),
235
+ exitCode: 1,
236
+ };
237
+ }
238
+ return {
239
+ output: withGlyph("proven", `\nproven — foo ${plan.latest} is installed. Check it: foo --version\n`, glyphs),
240
+ exitCode: 0,
241
+ };
242
+ }
243
+ }
244
+ }
@@ -0,0 +1,20 @@
1
+ export interface TurnClassification {
2
+ miss: boolean;
3
+ matched: string | null;
4
+ }
5
+ export declare function classifyTurn(text: string): TurnClassification;
6
+ export declare function observeTurn(root: string, turnText: string, at?: string): TurnClassification;
7
+ export interface MissRate {
8
+ turns: number;
9
+ misses: number;
10
+ rate: number | null;
11
+ }
12
+ export declare function missRate(root: string): MissRate;
13
+ export interface LintFinding {
14
+ file: string;
15
+ term: string;
16
+ line: number;
17
+ text: string;
18
+ }
19
+ export declare function lintShippedSurfaces(root: string): LintFinding[];
20
+ export declare function renderLint(findings: LintFinding[]): string;
@@ -0,0 +1,166 @@
1
+ // comprehension-loop-v0 — the comprehension scoreboard and the shipped-surface
2
+ // jargon lint. Both are SIGNALS, never gates (R-004): nothing here blocks,
3
+ // rewrites, or judges output with a model. The scoreboard records when the
4
+ // human had to ask for a translation; the lint reports foo-internal vocabulary
5
+ // on the surfaces that ship to a customer's agent context (commands/, skills/).
6
+ //
7
+ // Boundary, stated where a builder will read it (T-005): comprehension is a
8
+ // signal. Do not add a runtime gate that blocks or rewrites output based on a
9
+ // model's judgment of whether a human understood — that gates on fluency, the
10
+ // exact property that made the bad messages dangerous, and it retypes a
11
+ // surface that produced zero of the nineteen observed complaints. If you are
12
+ // tempted, read specs/comprehension-loop-v0/spec.md R-004 and D-001 first.
13
+ import { appendFileSync, existsSync, lstatSync, mkdirSync, readdirSync, readFileSync } from "node:fs";
14
+ import path from "node:path";
15
+ import { PM_SURFACE_FORBIDDEN } from "./initCommand.js";
16
+ // --- the translation-request detector (R-001) --------------------------------
17
+ // Deterministic, no model call. Each pattern names the complaint shape it
18
+ // catches; precision is measured against evals/comprehension/, never asserted.
19
+ // Token boundaries are (?<![\w-]) / (?![\w-]) — the researchGate lesson: a
20
+ // substring test is how `cite` once matched "excited".
21
+ const MISS_PATTERNS = [
22
+ { name: "in-english", re: /(?<![\w-])in (?:plain )?english(?![\w-])/i },
23
+ { name: "plain-english", re: /(?<![\w-])plain english(?![\w-])/i },
24
+ { name: "what-does-that-mean", re: /(?<![\w-])what does (?:that|this|it) mean(?![\w-])/i },
25
+ { name: "translate-that", re: /(?<![\w-])translate (?:that|this|it)(?![\w-])/i },
26
+ { name: "dont-understand", re: /(?<![\w-])(?:i )?don'?t understand what(?![\w-])/i },
27
+ ];
28
+ export function classifyTurn(text) {
29
+ for (const p of MISS_PATTERNS) {
30
+ if (p.re.test(text))
31
+ return { miss: true, matched: p.name };
32
+ }
33
+ return { miss: false, matched: null };
34
+ }
35
+ // --- the local scoreboard (D-003: this machine only, no rewrite authority) ---
36
+ const EVENTS_DIR = path.join(".foo", "comprehension");
37
+ const EVENTS_FILE = "events.jsonl";
38
+ export function observeTurn(root, turnText, at = new Date().toISOString()) {
39
+ const result = classifyTurn(turnText);
40
+ const dir = path.join(root, EVENTS_DIR);
41
+ mkdirSync(dir, { recursive: true });
42
+ const event = {
43
+ schema_version: "0.1",
44
+ type: result.miss ? "comprehension_miss" : "turn_observed",
45
+ at,
46
+ };
47
+ if (result.miss) {
48
+ event.matched = result.matched;
49
+ // Enough of the turn to audit a false positive later; local-only (.foo/ is
50
+ // gitignored) and never shipped anywhere.
51
+ event.excerpt = turnText.slice(0, 160);
52
+ }
53
+ appendFileSync(path.join(dir, EVENTS_FILE), `${JSON.stringify(event)}\n`);
54
+ return result;
55
+ }
56
+ export function missRate(root) {
57
+ const file = path.join(root, EVENTS_DIR, EVENTS_FILE);
58
+ if (!existsSync(file))
59
+ return { turns: 0, misses: 0, rate: null };
60
+ let turns = 0;
61
+ let misses = 0;
62
+ for (const line of readFileSync(file, "utf8").split("\n")) {
63
+ if (!line.trim())
64
+ continue;
65
+ try {
66
+ const event = JSON.parse(line);
67
+ if (event.type === "comprehension_miss") {
68
+ turns += 1;
69
+ misses += 1;
70
+ }
71
+ else if (event.type === "turn_observed") {
72
+ turns += 1;
73
+ }
74
+ }
75
+ catch {
76
+ // A corrupt line is a log problem, not a reason to fail the scoreboard.
77
+ }
78
+ }
79
+ return { turns, misses, rate: turns === 0 ? null : misses / turns };
80
+ }
81
+ // --- the shipped-surface jargon lint (R-002; a signal, never a block) --------
82
+ // Legitimate internal uses go here, narrowest scope that works: a relative
83
+ // path prefix plus the term it may use. Keep this list short and honest — an
84
+ // allowlist that grows faster than the fixes is the lint being ignored.
85
+ const LINT_ALLOWLIST = [];
86
+ const LINT_ROOTS = ["commands", "skills"];
87
+ function lintFile(root, rel, findings) {
88
+ const text = readFileSync(path.join(root, rel), "utf8");
89
+ const lines = text.split("\n");
90
+ for (const term of PM_SURFACE_FORBIDDEN) {
91
+ if (LINT_ALLOWLIST.some((a) => rel.startsWith(a.pathPrefix) && a.term === term))
92
+ continue;
93
+ const re = new RegExp(`(?<![\\w-])${term.replace(/[.*+?^${}()|[\]\\]/g, "\\$&")}(?![\\w-])`, "i");
94
+ for (let i = 0; i < lines.length; i += 1) {
95
+ if (re.test(lines[i])) {
96
+ findings.push({ file: rel, term, line: i + 1, text: lines[i].trim().slice(0, 120) });
97
+ break; // one finding per (file, term) keeps the signal readable
98
+ }
99
+ }
100
+ }
101
+ }
102
+ function walk(root, rel, acc) {
103
+ const full = path.join(root, rel);
104
+ if (!existsSync(full))
105
+ return;
106
+ // lstat, never stat: skills/ carries adapter symlinks (.codex/ links back
107
+ // into the repo) and following them walks a loop forever. Dot-entries are
108
+ // adapter surfaces, not canonical shipped files — skip both.
109
+ const stat = lstatSync(full);
110
+ if (stat.isSymbolicLink())
111
+ return;
112
+ if (stat.isFile()) {
113
+ if (rel.endsWith(".md"))
114
+ acc.push(rel);
115
+ return;
116
+ }
117
+ if (!stat.isDirectory())
118
+ return;
119
+ for (const entry of readdirSync(full).sort()) {
120
+ if (entry.startsWith("."))
121
+ continue;
122
+ walk(root, path.join(rel, entry), acc);
123
+ }
124
+ }
125
+ // comprehension-loop-v0 R-004 — the boundary, written where the next person to
126
+ // extend this lint will read it. Comprehension is a SIGNAL, never a gate. Do not
127
+ // give it a blocking verdict path and do not add a model-judged
128
+ // "did the human understand?" chokepoint: that gates on fluency, which is the exact
129
+ // property that made the observed bad messages dangerous. Signals over gates —
130
+ // a lint that blocks at this detector's precision is switched off within a week,
131
+ // and a signal that keeps its audience beats a gate that loses it.
132
+ export function lintShippedSurfaces(root) {
133
+ const files = [];
134
+ for (const dir of LINT_ROOTS)
135
+ walk(root, dir, files);
136
+ const findings = [];
137
+ for (const rel of files)
138
+ lintFile(root, rel, findings);
139
+ return findings;
140
+ }
141
+ const LINT_DETAIL_CAP = 20;
142
+ export function renderLint(findings) {
143
+ if (findings.length === 0)
144
+ return "shipped surfaces carry no flagged internal vocabulary\n";
145
+ // A 3,000-line dump is noise wearing a signal's clothes — summarize by file,
146
+ // show the worst offenders in detail, and NAME what was dropped (no silent
147
+ // caps): the full list stays one --json away.
148
+ const byFile = new Map();
149
+ for (const f of findings)
150
+ byFile.set(f.file, (byFile.get(f.file) ?? 0) + 1);
151
+ const worst = [...byFile.entries()].sort((a, b) => b[1] - a[1]);
152
+ const lines = [
153
+ `signal: ${findings.length} internal-vocabulary use(s) across ${byFile.size} shipped file(s) (commands/, skills/) — advisory, never a build failure.`,
154
+ `Worst files first:`,
155
+ ];
156
+ for (const [file, count] of worst.slice(0, 10))
157
+ lines.push(` ${file} — ${count} term(s)`);
158
+ lines.push(`First ${Math.min(LINT_DETAIL_CAP, findings.length)} finding(s) in detail:`);
159
+ for (const f of findings.slice(0, LINT_DETAIL_CAP))
160
+ lines.push(` ${f.file}:${f.line} says "${f.term}" — ${f.text}`);
161
+ if (findings.length > LINT_DETAIL_CAP) {
162
+ lines.push(` …and ${findings.length - LINT_DETAIL_CAP} more — run \`foo comprehension lint --json\` for the full list.`);
163
+ }
164
+ lines.push("Fix by saying it in the reader's words, or add the narrowest allowlist entry with a reason.");
165
+ return `${lines.join("\n")}\n`;
166
+ }
@@ -0,0 +1,48 @@
1
+ export interface IdeaObject {
2
+ id: string;
3
+ claim: string;
4
+ frame: string;
5
+ lens: string;
6
+ reasoning: string;
7
+ mechanism: string;
8
+ assumption: string;
9
+ novelty: string;
10
+ claims_relied_on: string[];
11
+ }
12
+ export interface DiversityMeter {
13
+ raw: number;
14
+ distinct_clusters: number;
15
+ near_dupes_merged: number;
16
+ exhausted: boolean;
17
+ }
18
+ export interface DiversityComputation extends DiversityMeter {
19
+ clusters: string[][];
20
+ }
21
+ export declare const CLUSTERER_ID = "idf-cosine-v3-moves";
22
+ export declare const NEAR_DUPE_THRESHOLD = 0.25;
23
+ export declare function featureSet(idea: IdeaObject): Map<string, number>;
24
+ export declare function similarityIn(a: IdeaObject, b: IdeaObject, pool: IdeaObject[]): number;
25
+ export declare function similarity(a: IdeaObject, b: IdeaObject): number;
26
+ export declare function computeDiversity(ideas: IdeaObject[], exhausted?: boolean): DiversityComputation;
27
+ export declare const IDEAS_FENCE_OPEN = "```json ideas";
28
+ export interface IdeaParseResult {
29
+ ideas: IdeaObject[];
30
+ errors: string[];
31
+ present: boolean;
32
+ }
33
+ export declare function parseIdeaObjects(recordText: string): IdeaParseResult;
34
+ export declare const DIVERSITY_METER_LINE: RegExp;
35
+ export declare function readDeclaredMeter(recordText: string): DiversityMeter | null;
36
+ export type DiversityMethod = "measured" | "estimated";
37
+ export declare function readDiversityMethod(recordText: string): {
38
+ value: DiversityMethod;
39
+ declared: boolean;
40
+ } | null;
41
+ export declare function readClustererId(recordText: string): string | null;
42
+ export declare function clustererLine(): string;
43
+ export declare function meterLine(meter: DiversityMeter): string;
44
+ export declare const IDEATE_CONTRACT_VERSION = "frames-v1";
45
+ export declare function ideateFrontmatter(record: string): Record<string, unknown> | null;
46
+ export declare function ideateContractVersion(record: string): string | null;
47
+ export declare function hasExecutableFramesContract(recordText: string): boolean;
48
+ export declare function frameReasoningOffenders(ideas: IdeaObject[]): string[];