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,669 @@
1
+ // `foo asp <command>`: the packet-contract dispatch body — validate, reconcile
2
+ // (including --source github:), verify, status, index, init, event, task, and
3
+ // verdict — plus the per-packet compiled-module loading it prefers in
4
+ // transition. cli.ts parses the domain/command tokens and delegates here.
5
+ import { existsSync, readFileSync, writeFileSync } from "node:fs";
6
+ import path from "node:path";
7
+ import { pathToFileURL } from "node:url";
8
+ import { parse as parseYaml } from "../vendorYaml.js";
9
+ import { derivePacketStatus, renderAspStatus } from "../packetStatus.js";
10
+ import { costHeadline } from "./loop.js";
11
+ import { runAspIndex } from "../packetIndex.js";
12
+ import { serveIndex, DEFAULT_SERVE_PORT } from "../packetIndexServe.js";
13
+ import { isPacketValidationError, validatePacket as validatePacketGeneric } from "../packetValidation.js";
14
+ import { lintAnchors, migrateSpecText } from "../specSections.js";
15
+ import { parseReconcileArgs, reconcilePacket as reconcilePacketGeneric } from "../packetReconcile.js";
16
+ import { verifyPacket, renderVerifyReport, VERIFY_EVENT_TYPE } from "../packetVerify.js";
17
+ import { appendEvent, initPacket, updateTask } from "../packetWrite.js";
18
+ import { isTerminal, recordVerdict, VERDICT_STATES } from "../packetLifecycle.js";
19
+ import { glyphsEnabled } from "../statusGlyphs.js";
20
+ import { loadLoopContracts } from "../loopContracts.js";
21
+ import { estimateLoopBudget, handshakeFloorUsd, hasExternalSources, loadPricing } from "../loopBudget.js";
22
+ import { appendIntegrationRecord, approvalStates, githubSelectionReport, githubSourceId, parseGithubSource, sourceKey, } from "../sourceIngress.js";
23
+ import { reconcilePrProof, recordGithubConflicts, renderGithubReceipt, } from "../githubReconcile.js";
24
+ import { classifyThrown, markFailure, UsageError } from "../errorTaxonomy.js";
25
+ import { failThrown, failWith, flagValue, hasFlag, resolvePacketDir } from "./shared.js";
26
+ import { surplusArgs } from "../cliArgs.js";
27
+ import { readJson } from "../jsonFile.js";
28
+ import { ASP_USAGE_LINES } from "../commandUsage.js";
29
+ export function aspUsage() {
30
+ return [
31
+ "foo asp — the packet contract: scaffold it, check it, and record what happened.",
32
+ "",
33
+ ...ASP_USAGE_LINES,
34
+ "",
35
+ "The local event log appends through `foo asp event` without rewriting prior lines.",
36
+ "It is not an independently append-only or tamper-proof guarantee; the command refuses unknown input rather than guess.",
37
+ "",
38
+ ].join("\n");
39
+ }
40
+ // The flags `foo asp event` actually has. Anything else in its argv is surplus.
41
+ const EVENT_VALUE_FLAGS = ["--subject", "--data", "--summary"];
42
+ async function loadPacketCommand(root, packetArg, command) {
43
+ const modulePath = path.join(root, "dist", packetArg, `${command}.js`);
44
+ if (!existsSync(modulePath))
45
+ return null;
46
+ return import(pathToFileURL(modulePath).href);
47
+ }
48
+ function readPacketSpecId(packetDir) {
49
+ try {
50
+ const m = readFileSync(path.join(packetDir, "tasks.yaml"), "utf8").match(/^spec_id:\s*(\S+)\s*$/m);
51
+ if (m)
52
+ return m[1];
53
+ }
54
+ catch {
55
+ // fall through to a slug-derived guess
56
+ }
57
+ return path.basename(packetDir).replace(/-/g, "_");
58
+ }
59
+ // Read the packet's done_when criteria (with any check predicates) from tasks.yaml
60
+ // (github-integration-v0 T-006). The agreed criteria are the verdict's left side;
61
+ // GitHub evidence is the right side.
62
+ function readDoneWhenCriteria(packetDir) {
63
+ try {
64
+ const doc = parseYaml(readFileSync(path.join(packetDir, "tasks.yaml"), "utf8"));
65
+ const out = [];
66
+ for (const task of doc.tasks ?? []) {
67
+ for (const c of task.done_when ?? []) {
68
+ if (c.id)
69
+ out.push({ id: c.id, text: c.text, check: c.check });
70
+ }
71
+ }
72
+ return out;
73
+ }
74
+ catch {
75
+ return [];
76
+ }
77
+ }
78
+ // foo asp reconcile <packet> --source github:<url> (github-integration-v0 T-002):
79
+ // admit a per-PR/per-repo GitHub selection through the substrate gate and report
80
+ // its identity, approval, and packet-linkage. No new command (rides reconcile);
81
+ // the done_when verdict is T-003. The standalone CLI has no live MCP, so evidence
82
+ // arrives via --source-fixture (errors-as-DX hands off when it is missing).
83
+ function runGithubSourceReconcile(root, packetDir, args) {
84
+ const json = args.includes("--json");
85
+ const source = flagValue(args, "--source") ?? "";
86
+ if (!source.startsWith("github:")) {
87
+ return { code: 1, out: `--source '${source}' is not supported on asp reconcile; V0 admits only github:<pr-or-repo-url>\n` };
88
+ }
89
+ let selection;
90
+ try {
91
+ selection = parseGithubSource(source);
92
+ }
93
+ catch (error) {
94
+ return { code: 1, out: `${error instanceof Error ? error.message : String(error)}\n` };
95
+ }
96
+ const id = githubSourceId(selection);
97
+ const rel = path.relative(root, packetDir) || packetDir;
98
+ const resume = `foo asp reconcile ${rel} --source ${source} --source-fixture <file.json>`;
99
+ const approvalState = approvalStates(packetDir).get(sourceKey(id))?.state ?? "excluded";
100
+ if (approvalState !== "approved") {
101
+ // Approval is blocking for use; never auto-approve (Contracts approval-state).
102
+ return {
103
+ code: 1,
104
+ out: `GitHub source ${selection.connection_id} (${selection.external_id}) is ${approvalState} for this packet — connection is not approval.\n` +
105
+ `Approve it, then re-run:\n` +
106
+ ` foo source approve ${rel} --provider github --connection ${selection.connection_id} --external-id ${selection.external_id} --scope ${selection.external_id} --by <you>\n` +
107
+ ` ${resume}\n`,
108
+ };
109
+ }
110
+ const fixturePath = flagValue(args, "--source-fixture");
111
+ if (!fixturePath) {
112
+ return { code: 1, out: `no GitHub evidence for ${selection.url}. The CLI has no live GitHub MCP — supply it with --source-fixture <file.json>, then re-run:\n ${resume}\n` };
113
+ }
114
+ let fixture;
115
+ try {
116
+ fixture = readJson(path.resolve(root, fixturePath));
117
+ }
118
+ catch {
119
+ return { code: 1, out: `--source-fixture is not readable JSON: ${fixturePath}\n` };
120
+ }
121
+ const at = new Date().toISOString();
122
+ const specId = readPacketSpecId(packetDir);
123
+ // Per-PR selection -> the full done_when verdict + dual-reader receipt (T-006).
124
+ if (selection.unit === "pr") {
125
+ // One shared engine for both reconcile entry points (reconcile-anywhere-v0
126
+ // T-001 / D-001): asp reconcile delegates the verdict + receipt here.
127
+ const { result, receipt } = reconcilePrProof({
128
+ packet: path.basename(packetDir),
129
+ sourceId: id,
130
+ fixture,
131
+ specId,
132
+ criteria: readDoneWhenCriteria(packetDir),
133
+ observedAt: at,
134
+ });
135
+ recordGithubConflicts(packetDir, id, result, at);
136
+ // Local-only, gitignored persistence; foo posts nothing to GitHub (R-007/R-008).
137
+ appendIntegrationRecord(packetDir, { kind: "github_receipt", ...receipt });
138
+ if (json)
139
+ return { code: 0, out: `${JSON.stringify(receipt, null, 2)}\n` };
140
+ return { code: 0, out: `${renderGithubReceipt(receipt)}\nReceipt is local-only — paste the block above into the PR yourself; foo posts nothing.\n` };
141
+ }
142
+ // Per-repo selection -> the packet-linkage selection report (T-002); run per-PR for a verdict.
143
+ const report = githubSelectionReport({ packet: path.basename(packetDir), selection, approvalState, specId, fixture });
144
+ if (json)
145
+ return { code: 0, out: `${JSON.stringify(report, null, 2)}\n` };
146
+ const linkedList = report.linked.length ? ` — ${report.linked.map((l) => l.external_id).join(", ")}` : "";
147
+ const out = [
148
+ `GitHub source reconcile · ${report.packet}`,
149
+ ` selection: ${selection.unit} ${selection.connection_id} (${selection.external_id}) — approved`,
150
+ ` packet-linked PRs: ${report.linked.length}${linkedList}`,
151
+ ...(report.unlinked_excluded ? [` excluded (not packet-linked): ${report.unlinked_excluded}`] : []),
152
+ ` ${report.note}`,
153
+ "",
154
+ ].join("\n");
155
+ return { code: 0, out };
156
+ }
157
+ // Proofs-complete nudge (packet-lifecycle-truth-v0 R-003): when reconcile runs
158
+ // on a packet whose derived truth is done but whose header is still non-terminal,
159
+ // print the done-verdict suggestion. A printed signal on stderr, never an
160
+ // automatic restamp (signals-over-gates-v0) — and never on stdout, where it
161
+ // would corrupt the JSON report a pipe is parsing.
162
+ function suggestDoneVerdict(root, packetDir) {
163
+ try {
164
+ const status = derivePacketStatus(packetDir);
165
+ if (status.lifecycle_effective !== "done" || isTerminal(status.lifecycle_stored))
166
+ return;
167
+ const rel = path.relative(root, packetDir).split(path.sep).join("/");
168
+ process.stderr.write(`[signal] ${rel} is proofs-complete but lifecycle reads '${status.lifecycle_stored ?? "unset"}' — ` +
169
+ `record the completion: foo asp verdict ${rel} done --reason "<why it is done>" (a suggestion, never automatic)\n`);
170
+ }
171
+ catch {
172
+ // Advisory only — a failed derivation must never break reconcile itself.
173
+ }
174
+ }
175
+ export async function runAspCommand(root, command, packetArg, args, domainArgs) {
176
+ // Answer --help before anything else runs (alpha_tester_fixes_v0 R-001).
177
+ //
178
+ // asp used to take "whatever the first token is" as the subcommand and, inside
179
+ // `event`, as the event type — before any flag was parsed. So `foo asp --help`
180
+ // died with "packet-dir missing", and `foo asp event <packet> --help` appended
181
+ // a literal {"type":"--help"} to the local event log. The `self` domain got
182
+ // this branch (cli.ts); asp never did. Nothing may be written on the way to
183
+ // working out what was asked.
184
+ if (command === "help" || hasFlag(domainArgs, "--help") || hasFlag(domainArgs, "-h")) {
185
+ process.stdout.write(aspUsage());
186
+ return 0;
187
+ }
188
+ // Cross-packet index (packet_index_v0): takes no packet-dir argument.
189
+ if (command === "index") {
190
+ try {
191
+ const indexArgs = domainArgs.slice(1);
192
+ // Live mode: serve the index over localhost, re-rendered per request, with
193
+ // reload-on-change. Long-running until ctrl-c (bin/foo sets exitCode, never
194
+ // process.exit, so the listening server keeps the process alive).
195
+ if (indexArgs.includes("--serve")) {
196
+ const portIdx = indexArgs.indexOf("--port");
197
+ const portRaw = portIdx !== -1 ? indexArgs[portIdx + 1] : undefined;
198
+ const port = portRaw && /^\d+$/.test(portRaw) ? Number(portRaw) : DEFAULT_SERVE_PORT;
199
+ const server = serveIndex(root, { port });
200
+ await new Promise((resolve, reject) => {
201
+ server.once("error", reject);
202
+ server.once("listening", () => {
203
+ process.stdout.write(`foo live spec dashboard\n root: ${root}\n url: http://localhost:${port}/\n reloads on spec-state change · ctrl-c to stop\n`);
204
+ });
205
+ server.once("close", () => resolve());
206
+ });
207
+ return 0;
208
+ }
209
+ const htmlIdx = indexArgs.indexOf("--html");
210
+ const html = htmlIdx !== -1;
211
+ const maybePath = html ? indexArgs[htmlIdx + 1] : undefined;
212
+ const htmlPath = maybePath && !maybePath.startsWith("--") ? maybePath : undefined;
213
+ // Drift glyphs on the text index ride the same human-only gate as status
214
+ // (statusGlyphs R-008): interactive TTY only, never --json or a pipe.
215
+ const glyphs = glyphsEnabled({ isTTY: Boolean(process.stdout.isTTY), env: process.env, args: indexArgs });
216
+ process.stdout.write(runAspIndex(root, { json: indexArgs.includes("--json"), html, htmlPath, glyphs }));
217
+ return 0;
218
+ }
219
+ catch (error) {
220
+ // A throw here is a real defect, not a typo — classify it so it pages and so the
221
+ // message + stack reach the local log instead of vanishing into a bare exit 1.
222
+ markFailure(classifyThrown(error));
223
+ process.stderr.write(`${error instanceof Error ? error.message : String(error)}\n`);
224
+ return 1;
225
+ }
226
+ }
227
+ // Scaffold (asp-cli-lifecycle-v0 T-003): the packet dir does not exist yet, so
228
+ // this runs before packet resolution.
229
+ if (command === "init") {
230
+ try {
231
+ if (!packetArg)
232
+ return failWith("packet name missing");
233
+ const result = initPacket({ root: root, name: packetArg });
234
+ const rel = path.relative(root, result.packetDir).split(path.sep).join("/");
235
+ process.stdout.write(`scaffolded ${rel} (spec_id ${result.specId})\n` +
236
+ `Next: foo asp validate ${rel}\n`);
237
+ return 0;
238
+ }
239
+ catch (error) {
240
+ return failThrown(error);
241
+ }
242
+ }
243
+ const packet = (() => {
244
+ try {
245
+ return resolvePacketDir(root, packetArg);
246
+ }
247
+ catch (error) {
248
+ return null;
249
+ }
250
+ })();
251
+ // Two different failures wear the same shape here. No arg is a typo (`foo asp status`
252
+ // — two of the four errors on the owner's dashboard were exactly this). A named packet
253
+ // that does not exist is a real not-found. Only the second is a fact about the repo.
254
+ if (!packet) {
255
+ return packetArg
256
+ ? failWith(`packet directory not found: ${packetArg}`, { errorClass: "not_found", errorCode: "E_PACKET_NOT_FOUND" })
257
+ : failWith("packet-dir missing", { errorCode: "E_PACKET_DIR_MISSING" });
258
+ }
259
+ // Local event-log write (T-004): foo asp event <packet> <type> [flags].
260
+ if (command === "event") {
261
+ try {
262
+ const [type, ...eventArgs] = args;
263
+ if (!type)
264
+ return failWith("event type missing");
265
+ // A flag is not an event type. Without this, `--anything` became the type
266
+ // and went straight into the ledger (alpha_tester_fixes_v0 R-001).
267
+ if (type.startsWith("-")) {
268
+ return failWith(`event type missing — \`${type}\` is a flag, not an event type.\n` +
269
+ `Nothing was written. Try: foo asp event ${packetArg ?? "<packet-dir>"} <type> --summary "<text>"`);
270
+ }
271
+ // Refuse what we did not read. `foo asp event <packet> <type> <summary>`
272
+ // used to drop the bare summary on the floor and commit `data: {}`. For an
273
+ // local event log, refusing loudly is the only safe default — a wrong
274
+ // entry cannot be removed, so productfoo never guesses at one.
275
+ const surplus = surplusArgs(eventArgs, { value: EVENT_VALUE_FLAGS });
276
+ if (surplus.length > 0) {
277
+ const first = surplus[0];
278
+ const problem = first.startsWith("-")
279
+ ? `unknown flag: ${first}`
280
+ : `unexpected argument: ${first} — did you mean --summary "${first}"?`;
281
+ return failWith(`${problem}\nNothing was written. The local event log is not rewritten, so productfoo refuses rather than guess.`);
282
+ }
283
+ const subject = flagValue(eventArgs, "--subject");
284
+ const dataRaw = flagValue(eventArgs, "--data");
285
+ const summary = flagValue(eventArgs, "--summary");
286
+ let data = {};
287
+ if (dataRaw) {
288
+ // Malformed --data is the caller's typo, not productfoo's bug: convert the raw
289
+ // SyntaxError to a UsageError so it exits as a usage error and files no
290
+ // Bug Capsule (#778).
291
+ let parsedData;
292
+ try {
293
+ parsedData = JSON.parse(dataRaw);
294
+ }
295
+ catch (error) {
296
+ throw new UsageError(`--data is not valid JSON: ${error instanceof Error ? error.message : String(error)}`, "E_BAD_FLAG");
297
+ }
298
+ if (!parsedData || typeof parsedData !== "object" || Array.isArray(parsedData)) {
299
+ return failWith("--data must be a JSON object");
300
+ }
301
+ data = parsedData;
302
+ }
303
+ if (summary && !("summary" in data))
304
+ data.summary = summary;
305
+ const event = appendEvent({ packetDir: packet.packetDir, type, subject, data });
306
+ process.stdout.write(`${JSON.stringify(event, null, 2)}\n`);
307
+ return 0;
308
+ }
309
+ catch (error) {
310
+ return failThrown(error);
311
+ }
312
+ }
313
+ // Lifecycle verdict (packet-lifecycle-v0): foo asp verdict <packet> <state> --reason <text>.
314
+ // parked/killed retire the packet; done completes it (packet-lifecycle-truth-v0
315
+ // R-003); active reopens it. The reason is mandatory — the whole point is that
316
+ // every terminal transition gets a recorded rationale, not silence.
317
+ if (command === "verdict") {
318
+ try {
319
+ const [state, ...verdictArgs] = args;
320
+ if (!state)
321
+ return failWith(`verdict state missing (expected ${VERDICT_STATES.join(" | ")})`);
322
+ if (!VERDICT_STATES.includes(state)) {
323
+ return failWith(`invalid verdict state: ${state} (expected ${VERDICT_STATES.join(" | ")})`);
324
+ }
325
+ const reason = flagValue(verdictArgs, "--reason");
326
+ if (!reason)
327
+ return failWith("--reason is required: record why, not just that");
328
+ // A done verdict must be backed by the derived truth (R-003): every task
329
+ // done and every done_when check proven. A human can still overrule the
330
+ // derivation with --force — the event trail then records that they did.
331
+ if (state === "done" && !hasFlag(verdictArgs, "--force")) {
332
+ const status = derivePacketStatus(packet.packetDir);
333
+ if (status.lifecycle_effective !== "done") {
334
+ const open = status.tasks.total - status.tasks.done - status.tasks.dropped;
335
+ return failWith(`refusing 'done': packet is not effectively done — ${open} task(s) still open and ` +
336
+ `${status.proof.checks_done} of ${status.proof.checks_total} done_when checks are done (a done verdict needs every check done with a proof). ` +
337
+ `Finish and prove the work, or overrule the derivation with --force.`);
338
+ }
339
+ }
340
+ const result = recordVerdict({ packetDir: packet.packetDir, state: state, reason });
341
+ const rel = path.relative(root, packet.packetDir).split(path.sep).join("/");
342
+ process.stdout.write(`${rel}: lifecycle ${result.from ?? "(unset)"} -> ${result.to} (event ${result.event.id})\n` +
343
+ `Next: foo asp status ${rel}\n`);
344
+ return 0;
345
+ }
346
+ catch (error) {
347
+ return failThrown(error);
348
+ }
349
+ }
350
+ // Task status write (T-004): foo asp task <packet> <id> --status <s> [flags].
351
+ if (command === "task") {
352
+ try {
353
+ const [taskId, ...taskArgs] = args;
354
+ if (!taskId)
355
+ return failWith("task id missing");
356
+ const status = flagValue(taskArgs, "--status");
357
+ if (!status)
358
+ return failWith("--status is required");
359
+ const needsRaw = flagValue(taskArgs, "--needs");
360
+ const result = updateTask({
361
+ packetDir: packet.packetDir,
362
+ taskId,
363
+ status,
364
+ proof: flagValue(taskArgs, "--proof"),
365
+ summary: flagValue(taskArgs, "--summary"),
366
+ reason: flagValue(taskArgs, "--reason"),
367
+ needs: needsRaw ? needsRaw.split(",").map((s) => s.trim()).filter(Boolean) : undefined,
368
+ });
369
+ const rel = path.relative(root, packet.packetDir).split(path.sep).join("/");
370
+ process.stdout.write(`${taskId}: ${result.from} -> ${result.to} (event ${result.event.id})\n` +
371
+ `Next: foo asp status ${rel}\n`);
372
+ return 0;
373
+ }
374
+ catch (error) {
375
+ return failThrown(error);
376
+ }
377
+ }
378
+ // Derived status (R-019): generic over any packet, computed from tasks.yaml —
379
+ // not a per-packet module like validate/reconcile. Exits non-zero only on a
380
+ // packet error (parse/missing file), never on incomplete work.
381
+ if (command === "status") {
382
+ try {
383
+ // --html writes the self-contained single-packet progress card (the visual
384
+ // sibling of asp index --html). Like index, the only write is the artifact.
385
+ const htmlIdx = args.indexOf("--html");
386
+ if (htmlIdx !== -1) {
387
+ const maybePath = args[htmlIdx + 1];
388
+ const explicit = maybePath && !maybePath.startsWith("--") ? maybePath : undefined;
389
+ const outPath = path.resolve(root, explicit ?? `${path.basename(packet.packetDir)}-progress.html`);
390
+ writeFileSync(outPath, renderAspStatus(packet.packetDir, { html: true }));
391
+ process.stdout.write(`wrote progress card to ${outPath}\n`);
392
+ return 0;
393
+ }
394
+ // The rich card is the default in an interactive terminal; pipes, --json,
395
+ // and --plain keep the stable text view so scripts and tests never parse
396
+ // ANSI. --rich forces the layout for capture (without color unless a TTY).
397
+ const json = args.includes("--json");
398
+ const isTty = Boolean(process.stdout.isTTY);
399
+ const rich = !json && (args.includes("--rich") || (isTty && !args.includes("--plain")));
400
+ const color = rich && isTty && !process.env.NO_COLOR && process.env.TERM !== "dumb";
401
+ // Bars/truncation are visual-only and unhelpful (noisy) off a terminal, so
402
+ // they ride the real-TTY signal, not the --rich force used for capture.
403
+ const bars = rich && isTty;
404
+ // Status glyphs (foo-status-glyphs-v0) ride a human-only gate (R-008): off
405
+ // for --json, NO_COLOR, and piped/non-TTY. They decorate the text view
406
+ // (--plain / --deep); the rich card carries its own.
407
+ const glyphs = !json && glyphsEnabled({ isTTY: Boolean(process.stdout.isTTY), env: process.env, args });
408
+ process.stdout.write(renderAspStatus(packet.packetDir, { json, deep: args.includes("--deep"), rich, color, bars, glyphs }));
409
+ // Cost of what is LEFT, at the moment you choose the next task (spec-budget-v0
410
+ // R-010). A packet that is 80% done does not still cost its full build price,
411
+ // so this scales by the open task share rather than reprinting the packet
412
+ // total. Human surfaces only: the --json and --html contracts are untouched.
413
+ // Structural, never egresses, and silently absent when it cannot be honest.
414
+ if (!json) {
415
+ const cost = await costHeadline(root, packet.packetDir, { remainingOnly: true });
416
+ if (cost)
417
+ process.stdout.write(`\n Cost: ${cost}\n`);
418
+ }
419
+ return 0;
420
+ }
421
+ catch (error) {
422
+ // A throw here is a real defect, not a typo — classify it so it pages and so the
423
+ // message + stack reach the local log instead of vanishing into a bare exit 1.
424
+ markFailure(classifyThrown(error));
425
+ process.stderr.write(`${error instanceof Error ? error.message : String(error)}\n`);
426
+ return 1;
427
+ }
428
+ }
429
+ // Intent verification (intent-verification-verdict-v0): the third packet read
430
+ // leg — did we ship what we intended, with proof? Advisory by default (a
431
+ // signal, not a boundary): it surfaces the verdict and exits 0. --strict
432
+ // escalates only `drift` (a false "done") to a nonzero exit, never merely
433
+ // unproven or unfinished work. --record appends the portable verdict event so
434
+ // the proof travels in the ledger any runtime reads.
435
+ if (command === "verify") {
436
+ try {
437
+ const json = args.includes("--json");
438
+ const report = verifyPacket({ packetDir: packet.packetDir, root: root });
439
+ if (args.includes("--record")) {
440
+ appendEvent({
441
+ packetDir: packet.packetDir,
442
+ type: VERIFY_EVENT_TYPE,
443
+ data: {
444
+ verdict: report.verdict,
445
+ summary: report.summary,
446
+ tasks: report.tasks,
447
+ checks: report.checks,
448
+ requirements: report.requirements,
449
+ findings: report.findings.length,
450
+ },
451
+ });
452
+ }
453
+ if (json) {
454
+ process.stdout.write(`${JSON.stringify(report, null, 2)}\n`);
455
+ }
456
+ else {
457
+ const glyphs = glyphsEnabled({ isTTY: Boolean(process.stdout.isTTY), env: process.env, args });
458
+ process.stdout.write(renderVerifyReport(report, glyphs));
459
+ process.stdout.write(report.verdict === "drift"
460
+ ? "\n[boundary-adjacent] drift is a false completion claim — run with --strict to make it block.\n"
461
+ : "\n[signal] advisory only — asp verify surfaces the verdict, it does not block.\n");
462
+ }
463
+ return hasFlag(args, "--strict") && report.verdict === "drift" ? 1 : 0;
464
+ }
465
+ catch (error) {
466
+ // A throw here is a real defect, not a typo — classify it so it pages and so the
467
+ // message + stack reach the local log instead of vanishing into a bare exit 1.
468
+ markFailure(classifyThrown(error));
469
+ process.stderr.write(`${error instanceof Error ? error.message : String(error)}\n`);
470
+ return 1;
471
+ }
472
+ }
473
+ // packet-grammar-v1 R-006: mint missing IDs in place, prove it, refuse
474
+ // anything that is not pure insertion. Existing IDs and prose are
475
+ // untouchable (R-003) — the migrator only ever ADDS a token to a line.
476
+ if (command === "migrate") {
477
+ const dryRun = hasFlag(args, "--dry-run");
478
+ const wantJson = hasFlag(args, "--json");
479
+ const specPath = path.join(packet.packetDir, "spec.md");
480
+ if (!existsSync(specPath))
481
+ return failWith(`spec.md missing in ${packet.packetDir}`);
482
+ const original = readFileSync(specPath, "utf8");
483
+ const result = migrateSpecText(original);
484
+ const label2 = path.basename(packet.packetDir);
485
+ if (!result.proofOk) {
486
+ // Defensive: a migrator that cannot strip its own insertions back to the
487
+ // original must not write (R-006 contract — exit 2, no files touched).
488
+ process.stderr.write(`foo asp migrate — REFUSED: insertion proof failed for ${label2}; no files written.\n`);
489
+ return 2;
490
+ }
491
+ if (!dryRun && result.insertions.length > 0)
492
+ writeFileSync(specPath, result.text);
493
+ if (wantJson) {
494
+ process.stdout.write(`${JSON.stringify({
495
+ schema_version: "0.1",
496
+ packet: label2,
497
+ written: !dryRun && result.insertions.length > 0,
498
+ proof: "insertion-only",
499
+ insertions: result.insertions.map((i) => ({ line: i.line, id: i.id })),
500
+ }, null, 2)}\n`);
501
+ return 0;
502
+ }
503
+ if (result.insertions.length === 0) {
504
+ process.stdout.write(`${label2} — every anchor already has an ID; nothing to insert.\n`);
505
+ return 0;
506
+ }
507
+ const verb = dryRun ? "would insert" : "inserted";
508
+ process.stdout.write(`${label2} — ${verb} ${result.insertions.length} ID(s), prose untouched (proof: insertion-only):\n`);
509
+ for (const i of result.insertions)
510
+ process.stdout.write(` spec.md:${i.line} ${i.id}\n`);
511
+ if (!dryRun)
512
+ process.stdout.write(`Next: foo asp validate ${packet.packetArg}\n`);
513
+ return 0;
514
+ }
515
+ if (command !== "validate" && command !== "reconcile") {
516
+ return failWith(`unknown command: ${command}`);
517
+ }
518
+ // A compiled per-packet module is preferred during transition, but no longer
519
+ // required: when a packet ships no validate/reconcile module, both commands
520
+ // fall back to the shared engines (asp-cli-lifecycle-v0 T-002), so any packet
521
+ // dir — including a freshly scaffolded one — validates and reconciles.
522
+ const module = await loadPacketCommand(root, packet.packetArg, command);
523
+ const context = { root: root, packetDir: packet.packetDir, packetArg: packet.packetArg };
524
+ const label = path.basename(packet.packetDir);
525
+ // asp validate is advisory by default (sog_v0 T-004 / R1): it surfaces findings
526
+ // and exits 0. --strict escalates to a nonzero exit only on a boundary-class
527
+ // violation (B2 spec identity); structural findings stay signals even then.
528
+ if (command === "validate") {
529
+ const strict = hasFlag(args, "--strict");
530
+ const wantJson = hasFlag(args, "--json");
531
+ // --fix applies the migrator before validating (R-006): complaining about
532
+ // a missing ID when one command inserts it is friction with no safety.
533
+ if (hasFlag(args, "--fix")) {
534
+ const specPath = path.join(packet.packetDir, "spec.md");
535
+ if (existsSync(specPath)) {
536
+ const fixed = migrateSpecText(readFileSync(specPath, "utf8"));
537
+ if (fixed.proofOk && fixed.insertions.length > 0) {
538
+ writeFileSync(specPath, fixed.text);
539
+ if (!wantJson) {
540
+ process.stdout.write(`--fix: inserted ${fixed.insertions.length} ID(s) via foo asp migrate.\n`);
541
+ }
542
+ }
543
+ }
544
+ }
545
+ try {
546
+ const message = module?.validatePacket
547
+ ? await module.validatePacket(context)
548
+ : validatePacketGeneric({ packetDir: packet.packetDir, label, requireSpecSections: true });
549
+ // Grammar lint (packet-grammar-v1 R-004): advisory findings with stable
550
+ // codes, never touching the exit code — blocking is the commit gate's
551
+ // call (R-005), and only for the malformed/duplicate subset.
552
+ const grammar = lintAnchors(readFileSync(path.join(packet.packetDir, "spec.md"), "utf8")).map((f) => ({ ...f, file: "spec.md" }));
553
+ const decisions = derivePacketStatus(packet.packetDir).decision_findings.map((f) => ({ ...f, file: "spec.md" }));
554
+ const findings = [...grammar, ...decisions];
555
+ if (wantJson) {
556
+ process.stdout.write(`${JSON.stringify({ schema_version: "0.1", packet: label, ok: true, findings }, null, 2)}\n`);
557
+ return 0;
558
+ }
559
+ process.stdout.write(`${message}\n`);
560
+ for (const f of findings) {
561
+ process.stdout.write(`[signal] ${f.code} ${f.file}:${f.line} — ${f.detail}\n`);
562
+ }
563
+ // B4 at authoring time. `asp validate` is the reflex an agent runs right after
564
+ // editing a packet (AGENTS.md), and it used to say a plain "ok" for a packet
565
+ // carrying an unbudgeted, spending loop — it never looked at loops.yaml at all.
566
+ // So the one moment someone is actually holding the loop contract was the one
567
+ // moment nothing mentioned the budget. Surfaced here as a SIGNAL (foo blocks in
568
+ // `self check`/CI, per signals-over-gates); the point is to tell the author now,
569
+ // not to ambush them in CI.
570
+ const loopSignal = loopBudgetSignal(root, packet.packetDir);
571
+ if (loopSignal)
572
+ process.stdout.write(`\n${loopSignal}\n`);
573
+ return 0;
574
+ }
575
+ catch (error) {
576
+ const message = error instanceof Error ? error.message : String(error);
577
+ if (!isPacketValidationError(error))
578
+ markFailure(classifyThrown(error));
579
+ // B2 spec identity is the only boundary asp validate surfaces; every other
580
+ // structural failure is an advisory signal that never blocks.
581
+ const isBoundary = /spec_id must match/.test(message);
582
+ if (wantJson) {
583
+ process.stdout.write(`${JSON.stringify({ schema_version: "0.1", packet: label, ok: false, error: message, findings: [] }, null, 2)}\n`);
584
+ return strict && isBoundary ? 1 : 0;
585
+ }
586
+ process.stdout.write(`${message}\n`);
587
+ process.stdout.write(isBoundary
588
+ ? "\n[boundary] B2 spec identity — run with --strict to make this block.\n"
589
+ : "\n[signal] advisory only — asp validate never blocks on structural findings.\n");
590
+ return strict && isBoundary ? 1 : 0;
591
+ }
592
+ }
593
+ try {
594
+ // GitHub source reconcile (github-integration-v0 T-002): `asp reconcile
595
+ // --source github:<url>` admits a PR/repo selection rather than diffing files.
596
+ if (flagValue(args, "--source")) {
597
+ const result = runGithubSourceReconcile(root, packet.packetDir, args);
598
+ process.stdout.write(result.out);
599
+ if (result.code === 0)
600
+ suggestDoneVerdict(root, packet.packetDir);
601
+ return result.code;
602
+ }
603
+ if (module?.reconcilePacket) {
604
+ const report = await module.reconcilePacket({ ...context, args });
605
+ process.stdout.write(`${JSON.stringify(report, null, 2)}\n`);
606
+ suggestDoneVerdict(root, packet.packetDir);
607
+ return 0;
608
+ }
609
+ const report = reconcilePacketGeneric({
610
+ ...parseReconcileArgs(args),
611
+ packetDir: packet.packetDir,
612
+ root: root,
613
+ });
614
+ process.stdout.write(`${JSON.stringify(report, null, 2)}\n`);
615
+ suggestDoneVerdict(root, packet.packetDir);
616
+ return 0;
617
+ }
618
+ catch (error) {
619
+ // Mark it, like every other catch in this file does. This one did not, so a real crash
620
+ // here reached the top with no class, no code and — worst — no STACK: it fingerprinted
621
+ // as the stackless E_UNKNOWN sentinel and fused with every other unmarked nonzero exit
622
+ // in foo. The bug's own trace was discarded at the only place that still had it.
623
+ markFailure(classifyThrown(error));
624
+ process.stderr.write(`${error instanceof Error ? error.message : String(error)}\n`);
625
+ return 1;
626
+ }
627
+ }
628
+ // B4 authoring-time signal (see the call site in `asp validate`). Read-only and
629
+ // status-aware, mirroring `self check`: a draft contract cannot spend, so it is a
630
+ // nudge; an ARMED one that has not been budgeted is called out as the boundary
631
+ // violation it is. Returns null when there is nothing to say.
632
+ export function loopBudgetSignal(root, packetDir) {
633
+ if (!existsSync(path.join(packetDir, "loops.yaml")))
634
+ return null;
635
+ let loops;
636
+ try {
637
+ loops = loadLoopContracts(packetDir).loops;
638
+ }
639
+ catch (error) {
640
+ return `[signal] loops.yaml does not parse as a loop contract (${error instanceof Error ? error.message : String(error)}) — foo self check will block on this (B4).`;
641
+ }
642
+ const pricing = loadPricing(root);
643
+ const floor = handshakeFloorUsd();
644
+ const packetRel = path.relative(root, packetDir).split(path.sep).join("/") || packetDir;
645
+ const lines = [];
646
+ for (const loop of loops) {
647
+ if (loop.budget?.agreed)
648
+ continue;
649
+ const estimate = estimateLoopBudget({ packetDir, sources: loop.observe.sources, pricing, unit: "usd", budget: loop.budget });
650
+ const unmeasurable = hasExternalSources(estimate.measured);
651
+ // A loop that can prove it is cheap auto-approves on `loop check` — nothing to say.
652
+ if (estimate.priced && !unmeasurable && estimate.usd.expected < floor)
653
+ continue;
654
+ const armed = loop.status === "ready" || loop.status === "active";
655
+ // Never quote a dollar figure we cannot stand behind.
656
+ const cost = unmeasurable
657
+ ? "its cost is unknown (it reads sources productfoo cannot size)"
658
+ : !estimate.priced
659
+ ? "its cost could not be priced"
660
+ : `it prices at $${estimate.usd.expected.toFixed(2)} expected, at or above the $${floor.toFixed(2)} floor`;
661
+ const fix = unmeasurable
662
+ ? `foo loop estimate ${packetRel} --agree --limit <usd> (you set the cap; productfoo will not invent one)`
663
+ : `foo loop estimate ${packetRel} --agree`;
664
+ lines.push(armed
665
+ ? `[boundary] B4 — loop ${loop.id} is ${loop.status} (armed) with no agreed budget, and ${cost}. foo self check and CI will block this.\n Authorise it: ${fix}`
666
+ : `[signal] loop ${loop.id} (${loop.status}) has no agreed budget, and ${cost}.\n Budget it before arming it: ${fix}`);
667
+ }
668
+ return lines.length > 0 ? lines.join("\n") : null;
669
+ }