patchwork-os 0.2.0-beta.9.canary.93 → 1.1.0-beta.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 (739) hide show
  1. package/README.bridge.md +15 -16
  2. package/README.md +46 -458
  3. package/dist/activationMetrics.js +2 -3
  4. package/dist/activationMetrics.js.map +1 -1
  5. package/dist/activityLog.d.ts +1 -0
  6. package/dist/activityLog.js +8 -3
  7. package/dist/activityLog.js.map +1 -1
  8. package/dist/adapters/gemini.js +2 -2
  9. package/dist/adapters/gemini.js.map +1 -1
  10. package/dist/adapters/grok.js +6 -1
  11. package/dist/adapters/grok.js.map +1 -1
  12. package/dist/adapters/openai.js +4 -0
  13. package/dist/adapters/openai.js.map +1 -1
  14. package/dist/approvalHttp.d.ts +9 -0
  15. package/dist/approvalHttp.js +210 -171
  16. package/dist/approvalHttp.js.map +1 -1
  17. package/dist/approvalKpi.d.ts +102 -0
  18. package/dist/approvalKpi.js +282 -0
  19. package/dist/approvalKpi.js.map +1 -0
  20. package/dist/approvalQueue.d.ts +1 -1
  21. package/dist/approvalQueue.js.map +1 -1
  22. package/dist/automation.d.ts +45 -4
  23. package/dist/automation.js +123 -15
  24. package/dist/automation.js.map +1 -1
  25. package/dist/bridge.d.ts +10 -0
  26. package/dist/bridge.js +225 -46
  27. package/dist/bridge.js.map +1 -1
  28. package/dist/bridgeLockDiscovery.d.ts +16 -1
  29. package/dist/bridgeLockDiscovery.js +38 -4
  30. package/dist/bridgeLockDiscovery.js.map +1 -1
  31. package/dist/bridgeToolsRules.js +3 -18
  32. package/dist/bridgeToolsRules.js.map +1 -1
  33. package/dist/claudeAuthHttp.d.ts +25 -0
  34. package/dist/claudeAuthHttp.js +219 -0
  35. package/dist/claudeAuthHttp.js.map +1 -0
  36. package/dist/claudeDriver.js +4 -1
  37. package/dist/claudeDriver.js.map +1 -1
  38. package/dist/claudeOrchestrator.d.ts +15 -0
  39. package/dist/claudeOrchestrator.js +44 -0
  40. package/dist/claudeOrchestrator.js.map +1 -1
  41. package/dist/commands/connect.d.ts +47 -0
  42. package/dist/commands/connect.js +419 -0
  43. package/dist/commands/connect.js.map +1 -0
  44. package/dist/commands/install.js +3 -10
  45. package/dist/commands/install.js.map +1 -1
  46. package/dist/commands/launchd.d.ts +7 -0
  47. package/dist/commands/launchd.js +20 -2
  48. package/dist/commands/launchd.js.map +1 -1
  49. package/dist/commands/patchworkInit.d.ts +7 -0
  50. package/dist/commands/patchworkInit.js +26 -0
  51. package/dist/commands/patchworkInit.js.map +1 -1
  52. package/dist/commands/recipe.d.ts +59 -4
  53. package/dist/commands/recipe.js +206 -5
  54. package/dist/commands/recipe.js.map +1 -1
  55. package/dist/commands/recipeInstall.d.ts +9 -0
  56. package/dist/commands/recipeInstall.js +56 -3
  57. package/dist/commands/recipeInstall.js.map +1 -1
  58. package/dist/commands/task.d.ts +25 -0
  59. package/dist/commands/task.js +61 -41
  60. package/dist/commands/task.js.map +1 -1
  61. package/dist/commands/tokenEfficiency.d.ts +4 -0
  62. package/dist/commands/tokenEfficiency.js +23 -26
  63. package/dist/commands/tokenEfficiency.js.map +1 -1
  64. package/dist/commands/tracesExport.d.ts +15 -1
  65. package/dist/commands/tracesExport.js +39 -5
  66. package/dist/commands/tracesExport.js.map +1 -1
  67. package/dist/config.js +16 -0
  68. package/dist/config.js.map +1 -1
  69. package/dist/connectorRoutes.js +613 -62
  70. package/dist/connectorRoutes.js.map +1 -1
  71. package/dist/connectors/asana.js +9 -3
  72. package/dist/connectors/asana.js.map +1 -1
  73. package/dist/connectors/baseConnector.d.ts +16 -0
  74. package/dist/connectors/baseConnector.js +2 -0
  75. package/dist/connectors/baseConnector.js.map +1 -1
  76. package/dist/connectors/caldiy.js +34 -0
  77. package/dist/connectors/caldiy.js.map +1 -1
  78. package/dist/connectors/confluence.js +9 -2
  79. package/dist/connectors/confluence.js.map +1 -1
  80. package/dist/connectors/connectorActivity.d.ts +24 -0
  81. package/dist/connectors/connectorActivity.js +32 -0
  82. package/dist/connectors/connectorActivity.js.map +1 -0
  83. package/dist/connectors/connectorRedirectUri.js +22 -2
  84. package/dist/connectors/connectorRedirectUri.js.map +1 -1
  85. package/dist/connectors/connectorRegistry.d.ts +0 -3
  86. package/dist/connectors/connectorRegistry.js +8 -8
  87. package/dist/connectors/connectorRegistry.js.map +1 -1
  88. package/dist/connectors/datadog.js +8 -1
  89. package/dist/connectors/datadog.js.map +1 -1
  90. package/dist/connectors/discord.js +4 -3
  91. package/dist/connectors/discord.js.map +1 -1
  92. package/dist/connectors/elasticsearch.js +22 -0
  93. package/dist/connectors/elasticsearch.js.map +1 -1
  94. package/dist/connectors/github.d.ts +38 -0
  95. package/dist/connectors/github.js +91 -5
  96. package/dist/connectors/github.js.map +1 -1
  97. package/dist/connectors/gitlab.js +19 -16
  98. package/dist/connectors/gitlab.js.map +1 -1
  99. package/dist/connectors/gmail.d.ts +5 -0
  100. package/dist/connectors/gmail.js +53 -11
  101. package/dist/connectors/gmail.js.map +1 -1
  102. package/dist/connectors/googleCalendar.js +5 -4
  103. package/dist/connectors/googleCalendar.js.map +1 -1
  104. package/dist/connectors/googleDocs.js +7 -6
  105. package/dist/connectors/googleDocs.js.map +1 -1
  106. package/dist/connectors/googleDrive.js +15 -8
  107. package/dist/connectors/googleDrive.js.map +1 -1
  108. package/dist/connectors/grafana.js +39 -3
  109. package/dist/connectors/grafana.js.map +1 -1
  110. package/dist/connectors/jira.d.ts +1 -1
  111. package/dist/connectors/jira.js +19 -4
  112. package/dist/connectors/jira.js.map +1 -1
  113. package/dist/connectors/linear.js +2 -2
  114. package/dist/connectors/linear.js.map +1 -1
  115. package/dist/connectors/mcpClient.d.ts +29 -1
  116. package/dist/connectors/mcpClient.js +114 -44
  117. package/dist/connectors/mcpClient.js.map +1 -1
  118. package/dist/connectors/mcpOAuth.d.ts +1 -0
  119. package/dist/connectors/mcpOAuth.js +49 -4
  120. package/dist/connectors/mcpOAuth.js.map +1 -1
  121. package/dist/connectors/monday.js +5 -4
  122. package/dist/connectors/monday.js.map +1 -1
  123. package/dist/connectors/mongodb.js +32 -5
  124. package/dist/connectors/mongodb.js.map +1 -1
  125. package/dist/connectors/notion.d.ts +1 -1
  126. package/dist/connectors/notion.js +22 -6
  127. package/dist/connectors/notion.js.map +1 -1
  128. package/dist/connectors/oauthError.d.ts +17 -0
  129. package/dist/connectors/oauthError.js +50 -0
  130. package/dist/connectors/oauthError.js.map +1 -0
  131. package/dist/connectors/postgres.d.ts +7 -0
  132. package/dist/connectors/postgres.js +32 -2
  133. package/dist/connectors/postgres.js.map +1 -1
  134. package/dist/connectors/posthog.js +26 -0
  135. package/dist/connectors/posthog.js.map +1 -1
  136. package/dist/connectors/redis.d.ts +1 -0
  137. package/dist/connectors/redis.js +47 -20
  138. package/dist/connectors/redis.js.map +1 -1
  139. package/dist/connectors/salesforce.js +66 -5
  140. package/dist/connectors/salesforce.js.map +1 -1
  141. package/dist/connectors/sentry.js +2 -2
  142. package/dist/connectors/sentry.js.map +1 -1
  143. package/dist/connectors/slack.js +37 -14
  144. package/dist/connectors/slack.js.map +1 -1
  145. package/dist/connectors/snowflake.js +24 -0
  146. package/dist/connectors/snowflake.js.map +1 -1
  147. package/dist/connectors/stripe.js +9 -2
  148. package/dist/connectors/stripe.js.map +1 -1
  149. package/dist/connectors/supabase.js +34 -0
  150. package/dist/connectors/supabase.js.map +1 -1
  151. package/dist/connectors/tokenStorage.d.ts +20 -0
  152. package/dist/connectors/tokenStorage.js +196 -64
  153. package/dist/connectors/tokenStorage.js.map +1 -1
  154. package/dist/connectors/woocommerce.js +34 -0
  155. package/dist/connectors/woocommerce.js.map +1 -1
  156. package/dist/copilot/parseIntent.d.ts +58 -0
  157. package/dist/copilot/parseIntent.js +149 -0
  158. package/dist/copilot/parseIntent.js.map +1 -0
  159. package/dist/decisionReplay.d.ts +8 -6
  160. package/dist/decisionReplay.js +35 -11
  161. package/dist/decisionReplay.js.map +1 -1
  162. package/dist/decisionTraceLog.d.ts +9 -0
  163. package/dist/decisionTraceLog.js +6 -0
  164. package/dist/decisionTraceLog.js.map +1 -1
  165. package/dist/drivers/claude/api.js +49 -7
  166. package/dist/drivers/claude/api.js.map +1 -1
  167. package/dist/drivers/claude/envSanitizer.d.ts +9 -1
  168. package/dist/drivers/claude/envSanitizer.js +41 -3
  169. package/dist/drivers/claude/envSanitizer.js.map +1 -1
  170. package/dist/drivers/claude/streamParser.d.ts +13 -0
  171. package/dist/drivers/claude/streamParser.js.map +1 -1
  172. package/dist/drivers/claude/subprocess.js +131 -16
  173. package/dist/drivers/claude/subprocess.js.map +1 -1
  174. package/dist/drivers/claude/subprocessSettings.d.ts +1 -1
  175. package/dist/drivers/claude/subprocessSettings.js +18 -4
  176. package/dist/drivers/claude/subprocessSettings.js.map +1 -1
  177. package/dist/drivers/gemini/index.d.ts +13 -0
  178. package/dist/drivers/gemini/index.js +211 -67
  179. package/dist/drivers/gemini/index.js.map +1 -1
  180. package/dist/drivers/local/index.d.ts +2 -17
  181. package/dist/drivers/local/index.js +5 -92
  182. package/dist/drivers/local/index.js.map +1 -1
  183. package/dist/drivers/openai/index.js +69 -9
  184. package/dist/drivers/openai/index.js.map +1 -1
  185. package/dist/drivers/outputCap.d.ts +27 -0
  186. package/dist/drivers/outputCap.js +50 -0
  187. package/dist/drivers/outputCap.js.map +1 -0
  188. package/dist/embeddings/cosine.d.ts +23 -0
  189. package/dist/embeddings/cosine.js +59 -0
  190. package/dist/embeddings/cosine.js.map +1 -0
  191. package/dist/embeddings/index.d.ts +19 -0
  192. package/dist/embeddings/index.js +35 -0
  193. package/dist/embeddings/index.js.map +1 -0
  194. package/dist/embeddings/localEmbeddings.d.ts +29 -0
  195. package/dist/embeddings/localEmbeddings.js +103 -0
  196. package/dist/embeddings/localEmbeddings.js.map +1 -0
  197. package/dist/embeddings/localEndpoints.d.ts +24 -0
  198. package/dist/embeddings/localEndpoints.js +37 -0
  199. package/dist/embeddings/localEndpoints.js.map +1 -0
  200. package/dist/embeddings/types.d.ts +32 -0
  201. package/dist/embeddings/types.js +12 -0
  202. package/dist/embeddings/types.js.map +1 -0
  203. package/dist/featureFlags.d.ts +18 -0
  204. package/dist/featureFlags.js +32 -0
  205. package/dist/featureFlags.js.map +1 -1
  206. package/dist/fp/automationInterpreter.js +118 -39
  207. package/dist/fp/automationInterpreter.js.map +1 -1
  208. package/dist/fp/automationProgram.d.ts +10 -0
  209. package/dist/fp/automationProgram.js.map +1 -1
  210. package/dist/fp/automationState.d.ts +6 -0
  211. package/dist/fp/automationState.js +38 -0
  212. package/dist/fp/automationState.js.map +1 -1
  213. package/dist/fp/commandDescription.d.ts +6 -0
  214. package/dist/fp/commandDescription.js +18 -5
  215. package/dist/fp/commandDescription.js.map +1 -1
  216. package/dist/fp/interpreterContext.d.ts +16 -5
  217. package/dist/fp/interpreterContext.js +59 -3
  218. package/dist/fp/interpreterContext.js.map +1 -1
  219. package/dist/fp/policyParser.js +18 -8
  220. package/dist/fp/policyParser.js.map +1 -1
  221. package/dist/haltPushDispatch.d.ts +4 -0
  222. package/dist/haltPushDispatch.js +7 -22
  223. package/dist/haltPushDispatch.js.map +1 -1
  224. package/dist/inboxRoutes.js +2 -2
  225. package/dist/inboxRoutes.js.map +1 -1
  226. package/dist/index.js +672 -135
  227. package/dist/index.js.map +1 -1
  228. package/dist/installGuard.js +6 -0
  229. package/dist/installGuard.js.map +1 -1
  230. package/dist/localEndpointGuard.d.ts +25 -0
  231. package/dist/localEndpointGuard.js +101 -0
  232. package/dist/localEndpointGuard.js.map +1 -0
  233. package/dist/mcpRoutes.js +1 -1
  234. package/dist/mcpRoutes.js.map +1 -1
  235. package/dist/oauth.d.ts +13 -0
  236. package/dist/oauth.js +53 -9
  237. package/dist/oauth.js.map +1 -1
  238. package/dist/orchestrator/childBridgeClient.d.ts +7 -0
  239. package/dist/orchestrator/childBridgeClient.js +42 -1
  240. package/dist/orchestrator/childBridgeClient.js.map +1 -1
  241. package/dist/orchestrator/orchestratorBridge.d.ts +33 -0
  242. package/dist/orchestrator/orchestratorBridge.js +75 -9
  243. package/dist/orchestrator/orchestratorBridge.js.map +1 -1
  244. package/dist/patchworkConfig.d.ts +4 -0
  245. package/dist/patchworkConfig.js +33 -4
  246. package/dist/patchworkConfig.js.map +1 -1
  247. package/dist/probe.js +39 -5
  248. package/dist/probe.js.map +1 -1
  249. package/dist/recipeOrchestration.d.ts +59 -0
  250. package/dist/recipeOrchestration.js +314 -60
  251. package/dist/recipeOrchestration.js.map +1 -1
  252. package/dist/recipeRoutes.d.ts +93 -0
  253. package/dist/recipeRoutes.js +664 -27
  254. package/dist/recipeRoutes.js.map +1 -1
  255. package/dist/recipes/RecipeOrchestrator.d.ts +14 -0
  256. package/dist/recipes/RecipeOrchestrator.js +42 -2
  257. package/dist/recipes/RecipeOrchestrator.js.map +1 -1
  258. package/dist/recipes/agentExecutor.d.ts +51 -2
  259. package/dist/recipes/agentExecutor.js +86 -13
  260. package/dist/recipes/agentExecutor.js.map +1 -1
  261. package/dist/recipes/chainedRunner.d.ts +111 -3
  262. package/dist/recipes/chainedRunner.js +440 -45
  263. package/dist/recipes/chainedRunner.js.map +1 -1
  264. package/dist/recipes/compiler.js +42 -29
  265. package/dist/recipes/compiler.js.map +1 -1
  266. package/dist/recipes/connectorPreflight.js +31 -0
  267. package/dist/recipes/connectorPreflight.js.map +1 -1
  268. package/dist/recipes/dependencyGraph.d.ts +16 -0
  269. package/dist/recipes/dependencyGraph.js +37 -2
  270. package/dist/recipes/dependencyGraph.js.map +1 -1
  271. package/dist/recipes/eventTriggerPrograms.d.ts +36 -0
  272. package/dist/recipes/eventTriggerPrograms.js +158 -0
  273. package/dist/recipes/eventTriggerPrograms.js.map +1 -0
  274. package/dist/recipes/githubInstallSource.d.ts +9 -2
  275. package/dist/recipes/githubInstallSource.js +36 -6
  276. package/dist/recipes/githubInstallSource.js.map +1 -1
  277. package/dist/recipes/haltCategory.d.ts +10 -0
  278. package/dist/recipes/haltCategory.js +11 -1
  279. package/dist/recipes/haltCategory.js.map +1 -1
  280. package/dist/recipes/idempotencyKey.d.ts +30 -3
  281. package/dist/recipes/idempotencyKey.js +89 -5
  282. package/dist/recipes/idempotencyKey.js.map +1 -1
  283. package/dist/recipes/installer.js +12 -35
  284. package/dist/recipes/installer.js.map +1 -1
  285. package/dist/recipes/judgeVerdict.d.ts +11 -1
  286. package/dist/recipes/judgeVerdict.js +47 -7
  287. package/dist/recipes/judgeVerdict.js.map +1 -1
  288. package/dist/recipes/names.d.ts +5 -0
  289. package/dist/recipes/names.js +10 -5
  290. package/dist/recipes/names.js.map +1 -1
  291. package/dist/recipes/parser.js +74 -10
  292. package/dist/recipes/parser.js.map +1 -1
  293. package/dist/recipes/pricing/costRouter.d.ts +43 -0
  294. package/dist/recipes/pricing/costRouter.js +44 -0
  295. package/dist/recipes/pricing/costRouter.js.map +1 -0
  296. package/dist/recipes/pricing/priceTable.d.ts +76 -0
  297. package/dist/recipes/pricing/priceTable.js +144 -0
  298. package/dist/recipes/pricing/priceTable.js.map +1 -0
  299. package/dist/recipes/replayRun.js +5 -2
  300. package/dist/recipes/replayRun.js.map +1 -1
  301. package/dist/recipes/resolveRecipePath.js +15 -1
  302. package/dist/recipes/resolveRecipePath.js.map +1 -1
  303. package/dist/recipes/runBudget.d.ts +93 -32
  304. package/dist/recipes/runBudget.js +213 -49
  305. package/dist/recipes/runBudget.js.map +1 -1
  306. package/dist/recipes/runRegistry.d.ts +32 -0
  307. package/dist/recipes/runRegistry.js +54 -0
  308. package/dist/recipes/runRegistry.js.map +1 -0
  309. package/dist/recipes/scheduler.js +6 -2
  310. package/dist/recipes/scheduler.js.map +1 -1
  311. package/dist/recipes/schema.d.ts +59 -6
  312. package/dist/recipes/schemaGenerator.d.ts +9 -0
  313. package/dist/recipes/schemaGenerator.js +446 -77
  314. package/dist/recipes/schemaGenerator.js.map +1 -1
  315. package/dist/recipes/simulation/aggregateRunRisk.d.ts +46 -0
  316. package/dist/recipes/simulation/aggregateRunRisk.js +120 -0
  317. package/dist/recipes/simulation/aggregateRunRisk.js.map +1 -0
  318. package/dist/recipes/simulation/costProjector.d.ts +32 -0
  319. package/dist/recipes/simulation/costProjector.js +194 -0
  320. package/dist/recipes/simulation/costProjector.js.map +1 -0
  321. package/dist/recipes/simulation/sideEffects.d.ts +32 -0
  322. package/dist/recipes/simulation/sideEffects.js +62 -0
  323. package/dist/recipes/simulation/sideEffects.js.map +1 -0
  324. package/dist/recipes/simulation/simulate.d.ts +36 -0
  325. package/dist/recipes/simulation/simulate.js +264 -0
  326. package/dist/recipes/simulation/simulate.js.map +1 -0
  327. package/dist/recipes/simulation/simulateMockedRun.d.ts +52 -0
  328. package/dist/recipes/simulation/simulateMockedRun.js +84 -0
  329. package/dist/recipes/simulation/simulateMockedRun.js.map +1 -0
  330. package/dist/recipes/simulation/synthesizeMockedOutputs.d.ts +31 -0
  331. package/dist/recipes/simulation/synthesizeMockedOutputs.js +50 -0
  332. package/dist/recipes/simulation/synthesizeMockedOutputs.js.map +1 -0
  333. package/dist/recipes/simulation/types.d.ts +198 -0
  334. package/dist/recipes/simulation/types.js +30 -0
  335. package/dist/recipes/simulation/types.js.map +1 -0
  336. package/dist/recipes/stepObservation.d.ts +12 -0
  337. package/dist/recipes/stepObservation.js +21 -1
  338. package/dist/recipes/stepObservation.js.map +1 -1
  339. package/dist/recipes/toolRegistry.js +61 -24
  340. package/dist/recipes/toolRegistry.js.map +1 -1
  341. package/dist/recipes/tools/airtable.d.ts +15 -0
  342. package/dist/recipes/tools/airtable.js +240 -0
  343. package/dist/recipes/tools/airtable.js.map +1 -0
  344. package/dist/recipes/tools/caldiy.d.ts +13 -0
  345. package/dist/recipes/tools/caldiy.js +215 -0
  346. package/dist/recipes/tools/caldiy.js.map +1 -0
  347. package/dist/recipes/tools/circleci.d.ts +10 -0
  348. package/dist/recipes/tools/circleci.js +204 -0
  349. package/dist/recipes/tools/circleci.js.map +1 -0
  350. package/dist/recipes/tools/cloudflare.d.ts +13 -0
  351. package/dist/recipes/tools/cloudflare.js +211 -0
  352. package/dist/recipes/tools/cloudflare.js.map +1 -0
  353. package/dist/recipes/tools/confluence.js +11 -10
  354. package/dist/recipes/tools/confluence.js.map +1 -1
  355. package/dist/recipes/tools/datadog.js +13 -12
  356. package/dist/recipes/tools/datadog.js.map +1 -1
  357. package/dist/recipes/tools/docs.d.ts +18 -0
  358. package/dist/recipes/tools/docs.js +95 -0
  359. package/dist/recipes/tools/docs.js.map +1 -0
  360. package/dist/recipes/tools/elasticsearch.d.ts +11 -0
  361. package/dist/recipes/tools/elasticsearch.js +157 -0
  362. package/dist/recipes/tools/elasticsearch.js.map +1 -0
  363. package/dist/recipes/tools/fanOut.js +4 -4
  364. package/dist/recipes/tools/fanOut.js.map +1 -1
  365. package/dist/recipes/tools/figma.d.ts +12 -0
  366. package/dist/recipes/tools/figma.js +195 -0
  367. package/dist/recipes/tools/figma.js.map +1 -0
  368. package/dist/recipes/tools/file.js +43 -22
  369. package/dist/recipes/tools/file.js.map +1 -1
  370. package/dist/recipes/tools/github.js +162 -5
  371. package/dist/recipes/tools/github.js.map +1 -1
  372. package/dist/recipes/tools/gmail.js +45 -33
  373. package/dist/recipes/tools/gmail.js.map +1 -1
  374. package/dist/recipes/tools/grafana.d.ts +11 -0
  375. package/dist/recipes/tools/grafana.js +216 -0
  376. package/dist/recipes/tools/grafana.js.map +1 -0
  377. package/dist/recipes/tools/http.d.ts +1 -1
  378. package/dist/recipes/tools/http.js +10 -28
  379. package/dist/recipes/tools/http.js.map +1 -1
  380. package/dist/recipes/tools/hubspot.js +13 -12
  381. package/dist/recipes/tools/hubspot.js.map +1 -1
  382. package/dist/recipes/tools/index.d.ts +28 -0
  383. package/dist/recipes/tools/index.js +28 -0
  384. package/dist/recipes/tools/index.js.map +1 -1
  385. package/dist/recipes/tools/intercom.js +11 -10
  386. package/dist/recipes/tools/intercom.js.map +1 -1
  387. package/dist/recipes/tools/jira.js +13 -0
  388. package/dist/recipes/tools/jira.js.map +1 -1
  389. package/dist/recipes/tools/meetingNotes.js +2 -2
  390. package/dist/recipes/tools/monday.d.ts +22 -0
  391. package/dist/recipes/tools/monday.js +242 -0
  392. package/dist/recipes/tools/monday.js.map +1 -0
  393. package/dist/recipes/tools/mongodb.d.ts +19 -0
  394. package/dist/recipes/tools/mongodb.js +194 -0
  395. package/dist/recipes/tools/mongodb.js.map +1 -0
  396. package/dist/recipes/tools/notion.js +11 -10
  397. package/dist/recipes/tools/notion.js.map +1 -1
  398. package/dist/recipes/tools/obsidian.d.ts +15 -0
  399. package/dist/recipes/tools/obsidian.js +173 -0
  400. package/dist/recipes/tools/obsidian.js.map +1 -0
  401. package/dist/recipes/tools/outcomes.d.ts +15 -0
  402. package/dist/recipes/tools/outcomes.js +111 -0
  403. package/dist/recipes/tools/outcomes.js.map +1 -0
  404. package/dist/recipes/tools/paystack.d.ts +11 -0
  405. package/dist/recipes/tools/paystack.js +212 -0
  406. package/dist/recipes/tools/paystack.js.map +1 -0
  407. package/dist/recipes/tools/pipedrive.d.ts +16 -0
  408. package/dist/recipes/tools/pipedrive.js +234 -0
  409. package/dist/recipes/tools/pipedrive.js.map +1 -0
  410. package/dist/recipes/tools/postgres.d.ts +15 -0
  411. package/dist/recipes/tools/postgres.js +186 -0
  412. package/dist/recipes/tools/postgres.js.map +1 -0
  413. package/dist/recipes/tools/posthog.d.ts +16 -0
  414. package/dist/recipes/tools/posthog.js +219 -0
  415. package/dist/recipes/tools/posthog.js.map +1 -0
  416. package/dist/recipes/tools/redis.d.ts +9 -0
  417. package/dist/recipes/tools/redis.js +141 -0
  418. package/dist/recipes/tools/redis.js.map +1 -0
  419. package/dist/recipes/tools/resend.d.ts +8 -0
  420. package/dist/recipes/tools/resend.js +153 -0
  421. package/dist/recipes/tools/resend.js.map +1 -0
  422. package/dist/recipes/tools/salesforce.d.ts +16 -0
  423. package/dist/recipes/tools/salesforce.js +184 -0
  424. package/dist/recipes/tools/salesforce.js.map +1 -0
  425. package/dist/recipes/tools/sendgrid.d.ts +9 -0
  426. package/dist/recipes/tools/sendgrid.js +175 -0
  427. package/dist/recipes/tools/sendgrid.js.map +1 -0
  428. package/dist/recipes/tools/shopify.d.ts +16 -0
  429. package/dist/recipes/tools/shopify.js +266 -0
  430. package/dist/recipes/tools/shopify.js.map +1 -0
  431. package/dist/recipes/tools/snowflake.d.ts +16 -0
  432. package/dist/recipes/tools/snowflake.js +173 -0
  433. package/dist/recipes/tools/snowflake.js.map +1 -0
  434. package/dist/recipes/tools/stripe.js +13 -12
  435. package/dist/recipes/tools/stripe.js.map +1 -1
  436. package/dist/recipes/tools/supabase.d.ts +9 -0
  437. package/dist/recipes/tools/supabase.js +133 -0
  438. package/dist/recipes/tools/supabase.js.map +1 -0
  439. package/dist/recipes/tools/todoist.d.ts +15 -0
  440. package/dist/recipes/tools/todoist.js +228 -0
  441. package/dist/recipes/tools/todoist.js.map +1 -0
  442. package/dist/recipes/tools/twilio.d.ts +11 -0
  443. package/dist/recipes/tools/twilio.js +180 -0
  444. package/dist/recipes/tools/twilio.js.map +1 -0
  445. package/dist/recipes/tools/vercel.d.ts +9 -0
  446. package/dist/recipes/tools/vercel.js +146 -0
  447. package/dist/recipes/tools/vercel.js.map +1 -0
  448. package/dist/recipes/tools/webflow.d.ts +11 -0
  449. package/dist/recipes/tools/webflow.js +244 -0
  450. package/dist/recipes/tools/webflow.js.map +1 -0
  451. package/dist/recipes/tools/woocommerce.d.ts +18 -0
  452. package/dist/recipes/tools/woocommerce.js +260 -0
  453. package/dist/recipes/tools/woocommerce.js.map +1 -0
  454. package/dist/recipes/tools/wrapConnectorExecute.d.ts +25 -0
  455. package/dist/recipes/tools/wrapConnectorExecute.js +37 -0
  456. package/dist/recipes/tools/wrapConnectorExecute.js.map +1 -0
  457. package/dist/recipes/tools/zendesk.js +11 -10
  458. package/dist/recipes/tools/zendesk.js.map +1 -1
  459. package/dist/recipes/triggerVars.d.ts +15 -0
  460. package/dist/recipes/triggerVars.js +57 -0
  461. package/dist/recipes/triggerVars.js.map +1 -0
  462. package/dist/recipes/validation.d.ts +1 -1
  463. package/dist/recipes/validation.js +536 -12
  464. package/dist/recipes/validation.js.map +1 -1
  465. package/dist/recipes/yamlPositions.d.ts +1 -1
  466. package/dist/recipes/yamlPositions.js +7 -2
  467. package/dist/recipes/yamlPositions.js.map +1 -1
  468. package/dist/recipes/yamlRunner.d.ts +216 -4
  469. package/dist/recipes/yamlRunner.js +1030 -96
  470. package/dist/recipes/yamlRunner.js.map +1 -1
  471. package/dist/recipesHttp.d.ts +5 -0
  472. package/dist/recipesHttp.js +68 -6
  473. package/dist/recipesHttp.js.map +1 -1
  474. package/dist/resources.js +14 -1
  475. package/dist/resources.js.map +1 -1
  476. package/dist/riskSignals.d.ts +42 -0
  477. package/dist/riskSignals.js +197 -0
  478. package/dist/riskSignals.js.map +1 -0
  479. package/dist/riskTier.d.ts +9 -0
  480. package/dist/riskTier.js +48 -0
  481. package/dist/riskTier.js.map +1 -1
  482. package/dist/runLog.d.ts +53 -0
  483. package/dist/runLog.js +75 -16
  484. package/dist/runLog.js.map +1 -1
  485. package/dist/schemas/recipe.v1.json +360 -16
  486. package/dist/server.d.ts +60 -0
  487. package/dist/server.js +192 -31
  488. package/dist/server.js.map +1 -1
  489. package/dist/sessionCheckpoint.js +4 -1
  490. package/dist/sessionCheckpoint.js.map +1 -1
  491. package/dist/sessionDetail.d.ts +43 -0
  492. package/dist/sessionDetail.js +59 -0
  493. package/dist/sessionDetail.js.map +1 -0
  494. package/dist/settingsEnv.d.ts +47 -0
  495. package/dist/settingsEnv.js +88 -0
  496. package/dist/settingsEnv.js.map +1 -0
  497. package/dist/streamableHttp.js +44 -10
  498. package/dist/streamableHttp.js.map +1 -1
  499. package/dist/ta/backtest/abnday.d.ts +53 -0
  500. package/dist/ta/backtest/abnday.js +123 -0
  501. package/dist/ta/backtest/abnday.js.map +1 -0
  502. package/dist/ta/backtest/directional.d.ts +48 -0
  503. package/dist/ta/backtest/directional.js +103 -0
  504. package/dist/ta/backtest/directional.js.map +1 -0
  505. package/dist/ta/backtest/fundx.d.ts +67 -0
  506. package/dist/ta/backtest/fundx.js +264 -0
  507. package/dist/ta/backtest/fundx.js.map +1 -0
  508. package/dist/ta/backtest/fvg.d.ts +62 -0
  509. package/dist/ta/backtest/fvg.js +236 -0
  510. package/dist/ta/backtest/fvg.js.map +1 -0
  511. package/dist/ta/backtest/ichimoku.d.ts +41 -0
  512. package/dist/ta/backtest/ichimoku.js +146 -0
  513. package/dist/ta/backtest/ichimoku.js.map +1 -0
  514. package/dist/ta/backtest/ingest.d.ts +20 -0
  515. package/dist/ta/backtest/ingest.js +104 -0
  516. package/dist/ta/backtest/ingest.js.map +1 -0
  517. package/dist/ta/backtest/msb.d.ts +49 -0
  518. package/dist/ta/backtest/msb.js +162 -0
  519. package/dist/ta/backtest/msb.js.map +1 -0
  520. package/dist/ta/backtest/scoring.d.ts +33 -0
  521. package/dist/ta/backtest/scoring.js +82 -0
  522. package/dist/ta/backtest/scoring.js.map +1 -0
  523. package/dist/ta/backtest/summary.d.ts +20 -0
  524. package/dist/ta/backtest/summary.js +42 -0
  525. package/dist/ta/backtest/summary.js.map +1 -0
  526. package/dist/ta/backtest/tsmom.d.ts +72 -0
  527. package/dist/ta/backtest/tsmom.js +202 -0
  528. package/dist/ta/backtest/tsmom.js.map +1 -0
  529. package/dist/ta/backtest/volsq.d.ts +34 -0
  530. package/dist/ta/backtest/volsq.js +154 -0
  531. package/dist/ta/backtest/volsq.js.map +1 -0
  532. package/dist/ta/backtest/walkForward.d.ts +45 -0
  533. package/dist/ta/backtest/walkForward.js +136 -0
  534. package/dist/ta/backtest/walkForward.js.map +1 -0
  535. package/dist/ta/cycles.d.ts +15 -0
  536. package/dist/ta/cycles.js +31 -0
  537. package/dist/ta/cycles.js.map +1 -0
  538. package/dist/ta/desk/accrualEmitter.d.ts +59 -0
  539. package/dist/ta/desk/accrualEmitter.js +136 -0
  540. package/dist/ta/desk/accrualEmitter.js.map +1 -0
  541. package/dist/ta/desk/cellBacktest.d.ts +179 -0
  542. package/dist/ta/desk/cellBacktest.js +514 -0
  543. package/dist/ta/desk/cellBacktest.js.map +1 -0
  544. package/dist/ta/desk/cells/wpMaRejection.d.ts +49 -0
  545. package/dist/ta/desk/cells/wpMaRejection.js +141 -0
  546. package/dist/ta/desk/cells/wpMaRejection.js.map +1 -0
  547. package/dist/ta/desk/cells/wpVolumeClimax.d.ts +57 -0
  548. package/dist/ta/desk/cells/wpVolumeClimax.js +193 -0
  549. package/dist/ta/desk/cells/wpVolumeClimax.js.map +1 -0
  550. package/dist/ta/desk/collectors.d.ts +18 -0
  551. package/dist/ta/desk/collectors.js +450 -0
  552. package/dist/ta/desk/collectors.js.map +1 -0
  553. package/dist/ta/desk/contract.d.ts +51 -0
  554. package/dist/ta/desk/contract.js +261 -0
  555. package/dist/ta/desk/contract.js.map +1 -0
  556. package/dist/ta/desk/deskLedger.d.ts +36 -0
  557. package/dist/ta/desk/deskLedger.js +239 -0
  558. package/dist/ta/desk/deskLedger.js.map +1 -0
  559. package/dist/ta/desk/liqTape.d.ts +37 -0
  560. package/dist/ta/desk/liqTape.js +99 -0
  561. package/dist/ta/desk/liqTape.js.map +1 -0
  562. package/dist/ta/desk/post.d.ts +20 -0
  563. package/dist/ta/desk/post.js +65 -0
  564. package/dist/ta/desk/post.js.map +1 -0
  565. package/dist/ta/desk/render.d.ts +25 -0
  566. package/dist/ta/desk/render.js +398 -0
  567. package/dist/ta/desk/render.js.map +1 -0
  568. package/dist/ta/desk/surfaces.d.ts +216 -0
  569. package/dist/ta/desk/surfaces.js +472 -0
  570. package/dist/ta/desk/surfaces.js.map +1 -0
  571. package/dist/ta/desk/types.d.ts +174 -0
  572. package/dist/ta/desk/types.js +104 -0
  573. package/dist/ta/desk/types.js.map +1 -0
  574. package/dist/ta/index.d.ts +23 -0
  575. package/dist/ta/index.js +54 -0
  576. package/dist/ta/index.js.map +1 -0
  577. package/dist/ta/ledger.d.ts +44 -0
  578. package/dist/ta/ledger.js +95 -0
  579. package/dist/ta/ledger.js.map +1 -0
  580. package/dist/ta/levels.d.ts +21 -0
  581. package/dist/ta/levels.js +41 -0
  582. package/dist/ta/levels.js.map +1 -0
  583. package/dist/ta/swings.d.ts +30 -0
  584. package/dist/ta/swings.js +83 -0
  585. package/dist/ta/swings.js.map +1 -0
  586. package/dist/ta/types.d.ts +81 -0
  587. package/dist/ta/types.js +20 -0
  588. package/dist/ta/types.js.map +1 -0
  589. package/dist/telemetry.js +20 -9
  590. package/dist/telemetry.js.map +1 -1
  591. package/dist/tokenUsageTracker.d.ts +2 -1
  592. package/dist/tokenUsageTracker.js +38 -20
  593. package/dist/tokenUsageTracker.js.map +1 -1
  594. package/dist/tools/contextBundle.js +13 -9
  595. package/dist/tools/contextBundle.js.map +1 -1
  596. package/dist/tools/ctxGetTaskContext.js +8 -3
  597. package/dist/tools/ctxGetTaskContext.js.map +1 -1
  598. package/dist/tools/ctxQueryTraces.d.ts +18 -1
  599. package/dist/tools/ctxQueryTraces.js +176 -27
  600. package/dist/tools/ctxQueryTraces.js.map +1 -1
  601. package/dist/tools/enrichCommit.js +5 -2
  602. package/dist/tools/enrichCommit.js.map +1 -1
  603. package/dist/tools/getDependencyTree.js +2 -2
  604. package/dist/tools/getDependencyTree.js.map +1 -1
  605. package/dist/tools/getDiagnostics.js +3 -0
  606. package/dist/tools/getDiagnostics.js.map +1 -1
  607. package/dist/tools/getDocumentSymbols.js +5 -1
  608. package/dist/tools/getDocumentSymbols.js.map +1 -1
  609. package/dist/tools/getGitHotspots.js +12 -1
  610. package/dist/tools/getGitHotspots.js.map +1 -1
  611. package/dist/tools/getGitLog.js +5 -2
  612. package/dist/tools/getGitLog.js.map +1 -1
  613. package/dist/tools/getGitStatus.js +6 -1
  614. package/dist/tools/getGitStatus.js.map +1 -1
  615. package/dist/tools/getProjectContext.js +3 -1
  616. package/dist/tools/getProjectContext.js.map +1 -1
  617. package/dist/tools/getToolCapabilities.js +39 -4
  618. package/dist/tools/getToolCapabilities.js.map +1 -1
  619. package/dist/tools/gitWrite.js +12 -3
  620. package/dist/tools/gitWrite.js.map +1 -1
  621. package/dist/tools/github/composite.d.ts +1 -1
  622. package/dist/tools/github/composite.js +7 -7
  623. package/dist/tools/github/composite.js.map +1 -1
  624. package/dist/tools/github/pr.d.ts +6 -6
  625. package/dist/tools/github/pr.js +18 -11
  626. package/dist/tools/github/pr.js.map +1 -1
  627. package/dist/tools/httpClient.js +55 -3
  628. package/dist/tools/httpClient.js.map +1 -1
  629. package/dist/tools/index.d.ts +2 -1
  630. package/dist/tools/index.js +19 -12
  631. package/dist/tools/index.js.map +1 -1
  632. package/dist/tools/lsp.d.ts +6 -0
  633. package/dist/tools/lsp.js +81 -12
  634. package/dist/tools/lsp.js.map +1 -1
  635. package/dist/tools/previewEdit.js +16 -1
  636. package/dist/tools/previewEdit.js.map +1 -1
  637. package/dist/tools/resumeClaudeTask.js +17 -0
  638. package/dist/tools/resumeClaudeTask.js.map +1 -1
  639. package/dist/tools/searchAndReplace.js +9 -5
  640. package/dist/tools/searchAndReplace.js.map +1 -1
  641. package/dist/tools/searchTools.d.ts +26 -0
  642. package/dist/tools/searchTools.js +42 -2
  643. package/dist/tools/searchTools.js.map +1 -1
  644. package/dist/tools/terminal.js +23 -51
  645. package/dist/tools/terminal.js.map +1 -1
  646. package/dist/tools/transaction.d.ts +9 -1
  647. package/dist/tools/transaction.js +59 -4
  648. package/dist/tools/transaction.js.map +1 -1
  649. package/dist/tools/utils.d.ts +16 -0
  650. package/dist/tools/utils.js +77 -7
  651. package/dist/tools/utils.js.map +1 -1
  652. package/dist/transport.d.ts +31 -0
  653. package/dist/transport.js +117 -14
  654. package/dist/transport.js.map +1 -1
  655. package/dist/wireHaltPushDispatch.js +12 -0
  656. package/dist/wireHaltPushDispatch.js.map +1 -1
  657. package/dist/workerGateDecisionLog.d.ts +141 -0
  658. package/dist/workerGateDecisionLog.js +361 -0
  659. package/dist/workerGateDecisionLog.js.map +1 -0
  660. package/dist/workers/actionClass.d.ts +38 -0
  661. package/dist/workers/actionClass.js +155 -0
  662. package/dist/workers/actionClass.js.map +1 -0
  663. package/dist/workers/backtest.d.ts +68 -0
  664. package/dist/workers/backtest.js +113 -0
  665. package/dist/workers/backtest.js.map +1 -0
  666. package/dist/workers/contextRisk.d.ts +35 -0
  667. package/dist/workers/contextRisk.js +20 -0
  668. package/dist/workers/contextRisk.js.map +1 -0
  669. package/dist/workers/contextRiskScorer.d.ts +48 -0
  670. package/dist/workers/contextRiskScorer.js +94 -0
  671. package/dist/workers/contextRiskScorer.js.map +1 -0
  672. package/dist/workers/graduation.d.ts +61 -0
  673. package/dist/workers/graduation.js +112 -0
  674. package/dist/workers/graduation.js.map +1 -0
  675. package/dist/workers/outcomeStore.d.ts +98 -0
  676. package/dist/workers/outcomeStore.js +146 -0
  677. package/dist/workers/outcomeStore.js.map +1 -0
  678. package/dist/workers/outcomesCli.d.ts +34 -0
  679. package/dist/workers/outcomesCli.js +91 -0
  680. package/dist/workers/outcomesCli.js.map +1 -0
  681. package/dist/workers/runWorkerShadow.d.ts +90 -0
  682. package/dist/workers/runWorkerShadow.js +323 -0
  683. package/dist/workers/runWorkerShadow.js.map +1 -0
  684. package/dist/workers/shadowGate.d.ts +30 -0
  685. package/dist/workers/shadowGate.js +58 -0
  686. package/dist/workers/shadowGate.js.map +1 -0
  687. package/dist/workers/shadowObserver.d.ts +165 -0
  688. package/dist/workers/shadowObserver.js +203 -0
  689. package/dist/workers/shadowObserver.js.map +1 -0
  690. package/dist/workers/shadowReport.d.ts +16 -0
  691. package/dist/workers/shadowReport.js +61 -0
  692. package/dist/workers/shadowReport.js.map +1 -0
  693. package/dist/workers/shadowRun.d.ts +38 -0
  694. package/dist/workers/shadowRun.js +44 -0
  695. package/dist/workers/shadowRun.js.map +1 -0
  696. package/dist/workers/trustLevel.d.ts +82 -0
  697. package/dist/workers/trustLevel.js +100 -0
  698. package/dist/workers/trustLevel.js.map +1 -0
  699. package/dist/workers/worker.d.ts +49 -0
  700. package/dist/workers/worker.js +88 -0
  701. package/dist/workers/worker.js.map +1 -0
  702. package/dist/workers/workerGate.d.ts +101 -0
  703. package/dist/workers/workerGate.js +210 -0
  704. package/dist/workers/workerGate.js.map +1 -0
  705. package/dist/workers/workerLevelStore.d.ts +33 -0
  706. package/dist/workers/workerLevelStore.js +87 -0
  707. package/dist/workers/workerLevelStore.js.map +1 -0
  708. package/dist/workers/workerLoader.d.ts +7 -0
  709. package/dist/workers/workerLoader.js +31 -0
  710. package/dist/workers/workerLoader.js.map +1 -0
  711. package/dist/writeFileAtomic.js +40 -13
  712. package/dist/writeFileAtomic.js.map +1 -1
  713. package/package.json +14 -6
  714. package/scripts/mcp-stdio-shim.cjs +247 -87
  715. package/templates/CLAUDE.bridge.md +1 -1
  716. package/templates/recipes/dependency-bump.yaml +33 -0
  717. package/templates/recipes/incident-to-pr.yaml +187 -0
  718. package/templates/recipes/outcome-ingester.yaml +53 -0
  719. package/templates/recipes/release-notes.yaml +30 -0
  720. package/templates/recipes/triage-failing-tests-autofile.yaml +152 -0
  721. package/templates/recipes/triage-failing-tests.yaml +38 -0
  722. package/templates/workers/dependency-upkeep.worker.yaml +26 -0
  723. package/templates/workers/release-notes.worker.yaml +17 -0
  724. package/templates/workers/test-guardian.worker.yaml +24 -0
  725. package/deploy/README.md +0 -172
  726. package/deploy/bootstrap-new-vps.sh +0 -364
  727. package/deploy/bootstrap-vps.sh +0 -192
  728. package/deploy/claude-ide-bridge.service.template +0 -67
  729. package/deploy/claude-ide-bridge@.service +0 -31
  730. package/deploy/deploy-dashboard.sh +0 -198
  731. package/deploy/deploy-landing.sh +0 -136
  732. package/deploy/ecosystem.config.js.example +0 -36
  733. package/deploy/install-vps-service.sh +0 -240
  734. package/deploy/macos/README.md +0 -153
  735. package/deploy/macos/com.patchwork.bridge.plist.template +0 -54
  736. package/deploy/macos/com.patchwork.tunnel.plist.template +0 -76
  737. package/deploy/macos/install-mac-bridge.sh +0 -244
  738. package/deploy/macos/uninstall-mac-bridge.sh +0 -22
  739. package/deploy/nginx-claude-bridge.conf.template +0 -129
@@ -0,0 +1,216 @@
1
+ /**
2
+ * surfaces.ts — PURE fact-producing functions for each desk surface.
3
+ *
4
+ * Every function returns plain facts (numbers/labels/booleans). NEVER computes a
5
+ * probability, midpoint, composite, or target. Risk math is deterministic
6
+ * arithmetic on a user-supplied trade. Positioning data (taker-buy%, crowd%) is
7
+ * returned as RAW ARCHIVED FACT with NO directional lean (deterministic ≠
8
+ * validated). Ichimoku is computed ONLY as a no-edge LOCATION line.
9
+ *
10
+ * See /tmp/qumo-design/signals-spec.md + DESIGN.md §5/§6.
11
+ */
12
+ import type { Candle } from "../types.js";
13
+ import type { Collected, DepthBook, OptionRow, Posture, QumoTrade, SectorRow } from "./types.js";
14
+ /** Liq-distance posture bands (rendered inline, never a forward call). */
15
+ export declare const LIQ_WIDE_PCT = 8;
16
+ export declare const LIQ_CONTESTED_PCT = 2;
17
+ /** Linear-perp maintenance-margin proxy for the liq-price estimate. */
18
+ export declare const MAINTENANCE_MARGIN = 0.005;
19
+ /** Trend CONSISTENT band: |24h%| <= this → neutral. */
20
+ export declare const TREND_NEUTRAL_BAND = 1;
21
+ /** Rekt Shield outcome window (bookkeeping grade-at). */
22
+ export declare const REKT_WINDOW_DAYS = 7;
23
+ export interface TodaysReadFacts {
24
+ posture: Posture;
25
+ reason: string;
26
+ nRisk: number;
27
+ nWatch: number;
28
+ nConfirm: number;
29
+ nGreen: number | null;
30
+ nRed: number | null;
31
+ universeN: number | null;
32
+ }
33
+ /**
34
+ * Deterministic posture rule (pre-registered):
35
+ * - load-bearing feed offline WHILE an open risk tally stands → "Alarm fired"
36
+ * (cannot manage live risk blind)
37
+ * - any other load-bearing feed offline OR zero confirms → "Standing aside"
38
+ * - any risk tally → "Holding-defensive"
39
+ * - any watch tally (no risk) → "Watching X"
40
+ * - confirms present, no risk/watch, feeds healthy → "Holding"
41
+ * Engine-decided, never LLM vibe. Every one of the five ALLOWED_POSTURES is
42
+ * reachable by this rule.
43
+ */
44
+ export declare function computeTodaysRead(feeds: Collected, tri: {
45
+ nRisk: number;
46
+ nWatch: number;
47
+ nConfirm: number;
48
+ }): TodaysReadFacts;
49
+ export interface RektFacts {
50
+ idle: boolean;
51
+ /** the supplied stop price (for the structural stop-vs-band line). */
52
+ stop?: number;
53
+ liqPrice?: number;
54
+ liqDistancePct?: number;
55
+ rrRatio?: number;
56
+ riskLegPct?: number;
57
+ rewardLegPct?: number;
58
+ capitalAtRiskPct?: number;
59
+ liqPosture?: "WIDE" | "NEAR" | "CONTESTED";
60
+ gradeAt?: string;
61
+ }
62
+ /**
63
+ * Pure risk arithmetic. No prediction. liqPrice from leverage + maintenance;
64
+ * R:R from entry/stop/target legs; capital-at-risk = riskLeg/leverage proxy.
65
+ */
66
+ export declare function computeRektShield(trade: QumoTrade | null, nowMs: number): RektFacts;
67
+ export interface DnaFacts {
68
+ /** trend lean is allowed (price-only validated). */
69
+ trend: {
70
+ live: boolean;
71
+ pct: number | null;
72
+ lean: string;
73
+ };
74
+ /** funding raw (lean only if a funding claim matured — never in v1). */
75
+ funding: {
76
+ live: boolean;
77
+ pct: number | null;
78
+ };
79
+ spotConfirm: {
80
+ live: boolean;
81
+ pct: number | null;
82
+ };
83
+ leverage: {
84
+ live: boolean;
85
+ crowdPct: number | null;
86
+ oiPct: number | null;
87
+ };
88
+ liveCount: number;
89
+ }
90
+ export declare function computeBtcDna(feeds: Collected): DnaFacts;
91
+ export interface IchimokuLocation {
92
+ available: boolean;
93
+ /** "above" | "below" | "in" the cloud, location only. */
94
+ cloud?: "above" | "below" | "in";
95
+ /** bars since the last TK cross, location only. */
96
+ tkCrossBarsAgo?: number | null;
97
+ }
98
+ /**
99
+ * Compute cloud position + TK cross as a LOCATION line. NEVER a directional
100
+ * lean, NEVER graded, NEVER in numbersIndex as a tradeable claim. The render
101
+ * layer attaches the explicit no-edge label. Standard 9/26/52 Hosoda params.
102
+ */
103
+ export declare function computeIchimokuLocation(candles: Candle[] | null): IchimokuLocation;
104
+ export interface AtlasFacts {
105
+ available: boolean;
106
+ sectors: SectorRow[];
107
+ leaders: string[];
108
+ laggards: string[];
109
+ }
110
+ export declare function computeAtlas(rows: SectorRow[] | null): AtlasFacts;
111
+ export interface DepthFacts {
112
+ available: boolean;
113
+ mid?: number;
114
+ /** bid notional $ within ±1% / ±2% of mid. */
115
+ bid1Pct?: number;
116
+ bid2Pct?: number;
117
+ /** ask notional $ within ±1% / ±2% of mid. */
118
+ ask1Pct?: number;
119
+ ask2Pct?: number;
120
+ /** descriptive ratio word (NOT a forecast). */
121
+ skew?: "bid-heavy" | "ask-heavy" | "balanced";
122
+ /** single largest bid wall within ±2% (price + $ notional). */
123
+ bidWallPrice?: number;
124
+ bidWallUsd?: number;
125
+ /** single largest ask wall within ±2% (price + $ notional). */
126
+ askWallPrice?: number;
127
+ askWallUsd?: number;
128
+ /** widest adjacent-level price gap (thin zone) within ±2% [lo, hi]. */
129
+ thinLo?: number;
130
+ thinHi?: number;
131
+ /** false when the book is too dense for a meaningful vacuum (sub-tick gap). */
132
+ thinZone?: boolean;
133
+ }
134
+ /**
135
+ * Pure book-structure facts. mid = (bestBid+bestAsk)/2. Notional = price*qty
136
+ * summed within ±1%/±2% bands; largest single-level wall per side; widest
137
+ * adjacent-level gap as a "thin zone". NEVER a direction/target/signal — "skew"
138
+ * is a descriptive ratio word only.
139
+ */
140
+ export declare function depthSurface(book: DepthBook | null): DepthFacts;
141
+ export interface MaxPainFacts {
142
+ available: boolean;
143
+ /** parsed expiry token of the front (nearest) expiry (e.g. "27JUN26"). */
144
+ expiry?: string;
145
+ /**
146
+ * Front expiry as a canonical ISO date (YYYY-MM-DD). The render layer narrates
147
+ * THIS, never the raw Deribit DDMMMYY token — the DDMMMYY form embeds bare
148
+ * digits (27, 26) that would otherwise leak as un-indexed narrated numbers
149
+ * (only ISO YYYY-MM-DD dates are machine-exempt from the numbersIndex spine).
150
+ */
151
+ expiryIso?: string;
152
+ /** max-pain strike = argmin total intrinsic value (OI-weighted). */
153
+ maxPainStrike?: number;
154
+ /** put/call OI ratio for that expiry. */
155
+ putCallRatio?: number;
156
+ /** total option OI (BTC) for that expiry. */
157
+ totalOi?: number;
158
+ }
159
+ /**
160
+ * Front-expiry max-pain. Selects the NEAREST not-yet-expired expiry, then for
161
+ * each listed strike S computes pain(S) = Σ_calls OI*max(0,S-K) +
162
+ * Σ_puts OI*max(0,K-S); max-pain = argmin. Also the put/call OI ratio + total
163
+ * OI for that expiry. This is an OI SNAPSHOT — NOT a price magnet/target. The
164
+ * render layer attaches the explicit no-magnet label.
165
+ */
166
+ export declare function maxPainSurface(rows: OptionRow[] | null, nowMs: number): MaxPainFacts;
167
+ /** Standard leverage buckets the geometry is modeled at (frozen). */
168
+ export declare const LIQ_LEVERAGE_BUCKETS: readonly [10, 25, 50, 100];
169
+ /** One leverage bucket's modeled long/short liq price bands (whole dollars). */
170
+ export interface LiqBand {
171
+ n: number;
172
+ /** long-liq price ≈ mid·(1 − 1/N), rounded to whole dollars. */
173
+ longLiq: number;
174
+ /** short-liq price ≈ mid·(1 + 1/N), rounded to whole dollars. */
175
+ shortLiq: number;
176
+ }
177
+ export interface LiqGeoFacts {
178
+ available: boolean;
179
+ /** order-book mid (or fallback close) the geometry is modeled from. */
180
+ mid?: number;
181
+ /** total perp OI notional ($) — pool that COULD be exposed (not distributed). */
182
+ oiNotional?: number | null;
183
+ bands?: LiqBand[];
184
+ }
185
+ /**
186
+ * Pure leverage-bucket geometry — NO network fetch, NO forecast. For each
187
+ * standard leverage N ∈ {10,25,50,100}: long-liq ≈ mid·(1−1/N), short-liq ≈
188
+ * mid·(1+1/N), rounded to whole dollars. The total perp OI $ is reported as the
189
+ * pool that COULD be exposed, NOT distributed (we do not know per-position entry
190
+ * or leverage). This is GEOMETRY/LOCATION, exactly like order-book walls — never
191
+ * a magnet, never a forecast, never directional. The render layer attaches the
192
+ * explicit no-forecast/no-magnet label.
193
+ */
194
+ export declare function liqGeometrySurface(mid: number | null, oiNotional: number | null): LiqGeoFacts;
195
+ /**
196
+ * Structural stop-vs-band read for Rekt Shield — PURE location, NO recommendation
197
+ * and NO forecast. Given the trade's stop + side, find the modeled liq band on
198
+ * the SAME side (long trade → long-liq bands; short → short-liq) NEAREST the stop,
199
+ * and report whether the stop sits within NEAR_PCT of it or clear of it. Returns
200
+ * null when geometry is unavailable. Wording is assembled in the render layer.
201
+ */
202
+ export interface StopBandFact {
203
+ /** leverage bucket of the nearest same-side band. */
204
+ n: number;
205
+ /** the band price (whole dollars). */
206
+ bandPrice: number;
207
+ /** absolute % distance stop→band. */
208
+ pct: number;
209
+ /** within NEAR_PCT → "within", else "clear of". */
210
+ within: boolean;
211
+ side: "long" | "short";
212
+ }
213
+ /** Stop-vs-band proximity threshold (%). Pure structure, not a recommendation. */
214
+ export declare const STOP_BAND_NEAR_PCT = 5;
215
+ export declare function stopVsBand(trade: QumoTrade | null, geo: LiqGeoFacts): StopBandFact | null;
216
+ export declare function fmtSigned(n: number): string;
@@ -0,0 +1,472 @@
1
+ /**
2
+ * surfaces.ts — PURE fact-producing functions for each desk surface.
3
+ *
4
+ * Every function returns plain facts (numbers/labels/booleans). NEVER computes a
5
+ * probability, midpoint, composite, or target. Risk math is deterministic
6
+ * arithmetic on a user-supplied trade. Positioning data (taker-buy%, crowd%) is
7
+ * returned as RAW ARCHIVED FACT with NO directional lean (deterministic ≠
8
+ * validated). Ichimoku is computed ONLY as a no-edge LOCATION line.
9
+ *
10
+ * See /tmp/qumo-design/signals-spec.md + DESIGN.md §5/§6.
11
+ */
12
+ // ── Pre-registered thresholds (frozen; docs/qumo-desk-precommit.md) ──────────
13
+ /** Liq-distance posture bands (rendered inline, never a forward call). */
14
+ export const LIQ_WIDE_PCT = 8; // > 8% → WIDE
15
+ export const LIQ_CONTESTED_PCT = 2; // < 2% → CONTESTED; else NEAR
16
+ /** Linear-perp maintenance-margin proxy for the liq-price estimate. */
17
+ export const MAINTENANCE_MARGIN = 0.005;
18
+ /** Trend CONSISTENT band: |24h%| <= this → neutral. */
19
+ export const TREND_NEUTRAL_BAND = 1.0;
20
+ /** Rekt Shield outcome window (bookkeeping grade-at). */
21
+ export const REKT_WINDOW_DAYS = 7;
22
+ /**
23
+ * Deterministic posture rule (pre-registered):
24
+ * - load-bearing feed offline WHILE an open risk tally stands → "Alarm fired"
25
+ * (cannot manage live risk blind)
26
+ * - any other load-bearing feed offline OR zero confirms → "Standing aside"
27
+ * - any risk tally → "Holding-defensive"
28
+ * - any watch tally (no risk) → "Watching X"
29
+ * - confirms present, no risk/watch, feeds healthy → "Holding"
30
+ * Engine-decided, never LLM vibe. Every one of the five ALLOWED_POSTURES is
31
+ * reachable by this rule.
32
+ */
33
+ export function computeTodaysRead(feeds, tri) {
34
+ const breadth = feeds.breadth.value;
35
+ const loadBearingOffline = feeds.btc1d.state !== "live" || feeds.btc24hPct.state !== "live";
36
+ let posture;
37
+ let reason;
38
+ if (loadBearingOffline && tri.nRisk > 0) {
39
+ posture = "Alarm fired";
40
+ reason =
41
+ "load-bearing price feed offline while open risk stands — cannot manage risk blind";
42
+ }
43
+ else if (loadBearingOffline) {
44
+ posture = "Standing aside";
45
+ reason = "load-bearing price feed offline — no read";
46
+ }
47
+ else if (tri.nRisk > 0) {
48
+ posture = "Holding-defensive";
49
+ reason = "open risk tally on the live ledger";
50
+ }
51
+ else if (tri.nWatch > 0) {
52
+ posture = "Watching X";
53
+ reason = "watch tally accruing, no confirmed risk";
54
+ }
55
+ else if (tri.nConfirm === 0) {
56
+ posture = "Standing aside";
57
+ reason = "no confirmed signals and no open tallies";
58
+ }
59
+ else {
60
+ const pct = feeds.btc24hPct.value;
61
+ posture = "Holding";
62
+ reason =
63
+ pct !== null && Math.abs(pct) <= TREND_NEUTRAL_BAND
64
+ ? `trend flat (24h ${fmtSigned(pct)}%), confirms present`
65
+ : "confirms present, no open risk";
66
+ }
67
+ return {
68
+ posture,
69
+ reason,
70
+ nRisk: tri.nRisk,
71
+ nWatch: tri.nWatch,
72
+ nConfirm: tri.nConfirm,
73
+ nGreen: breadth ? breadth.green : null,
74
+ nRed: breadth ? breadth.red : null,
75
+ universeN: breadth ? breadth.universe : null,
76
+ };
77
+ }
78
+ /**
79
+ * Pure risk arithmetic. No prediction. liqPrice from leverage + maintenance;
80
+ * R:R from entry/stop/target legs; capital-at-risk = riskLeg/leverage proxy.
81
+ */
82
+ export function computeRektShield(trade, nowMs) {
83
+ if (!trade)
84
+ return { idle: true };
85
+ const { side, entry, stop, target, leverage } = trade;
86
+ if (!(entry > 0) ||
87
+ !(leverage > 0) ||
88
+ !Number.isFinite(stop) ||
89
+ !Number.isFinite(target)) {
90
+ return { idle: true };
91
+ }
92
+ const long = side === "long";
93
+ // Liquidation price for an isolated linear perp (maintenance-margin proxy).
94
+ // M27: clamp to a minimum fraction — at leverage >= 200x the naive formula
95
+ // yields a non-positive liqFrac (e.g. 250x: 1/250 - 0.005 = -0.001), which
96
+ // would place liqPrice above entry on a long trade (impossible).
97
+ const liqFrac = Math.max(1 / leverage - MAINTENANCE_MARGIN, 0.0001);
98
+ const liqPrice = long ? entry * (1 - liqFrac) : entry * (1 + liqFrac);
99
+ const liqDistancePct = Number((liqFrac * 100).toFixed(1));
100
+ const riskLeg = Math.abs(entry - stop);
101
+ const rewardLeg = Math.abs(target - entry);
102
+ const riskLegPct = Number(((riskLeg / entry) * 100).toFixed(1));
103
+ const rewardLegPct = Number(((rewardLeg / entry) * 100).toFixed(1));
104
+ const rrRatio = riskLeg > 0 ? Number((rewardLeg / riskLeg).toFixed(2)) : 0;
105
+ // Capital at risk: price-delta risk leg multiplied by leverage (H9).
106
+ // Without the leverage factor, a 1% stop at 10x reports only 1% at risk
107
+ // instead of the correct 10% of margin capital.
108
+ const capitalAtRiskPct = Number((riskLegPct * leverage).toFixed(1));
109
+ const liqPosture = liqDistancePct > LIQ_WIDE_PCT
110
+ ? "WIDE"
111
+ : liqDistancePct < LIQ_CONTESTED_PCT
112
+ ? "CONTESTED"
113
+ : "NEAR";
114
+ const gradeAt = new Date(nowMs + REKT_WINDOW_DAYS * 86_400_000).toISOString();
115
+ return {
116
+ idle: false,
117
+ stop: Number(stop.toFixed(roundDigits(stop))),
118
+ liqPrice: Number(liqPrice.toFixed(roundDigits(liqPrice))),
119
+ liqDistancePct,
120
+ rrRatio,
121
+ riskLegPct,
122
+ rewardLegPct,
123
+ capitalAtRiskPct,
124
+ liqPosture,
125
+ gradeAt,
126
+ };
127
+ }
128
+ export function computeBtcDna(feeds) {
129
+ const pct = feeds.btc24hPct.value;
130
+ const trendLive = feeds.btc24hPct.state === "live" && pct !== null;
131
+ let lean = "feed offline";
132
+ if (trendLive && pct !== null) {
133
+ lean =
134
+ Math.abs(pct) <= TREND_NEUTRAL_BAND
135
+ ? "neutral (consistent)"
136
+ : pct > 0
137
+ ? "up — consistent"
138
+ : "down — consistent";
139
+ }
140
+ const fundingLive = feeds.funding.state === "live" && feeds.funding.value !== null;
141
+ const spotLive = feeds.takerBuyPct.state === "live" && feeds.takerBuyPct.value !== null;
142
+ const levLive = feeds.crowdLongPct.state === "live" && feeds.crowdLongPct.value !== null;
143
+ // Only price-trend counts as a LIVE lean-bearing strand. Funding/positioning
144
+ // are archived/raw, not "read", per the moat — so the live-strand count is
145
+ // trend-only when present.
146
+ const liveCount = trendLive ? 1 : 0;
147
+ return {
148
+ trend: { live: trendLive, pct, lean },
149
+ funding: { live: fundingLive, pct: feeds.funding.value },
150
+ spotConfirm: { live: spotLive, pct: feeds.takerBuyPct.value },
151
+ leverage: {
152
+ live: levLive,
153
+ crowdPct: feeds.crowdLongPct.value,
154
+ oiPct: feeds.oiChangePct.value,
155
+ },
156
+ liveCount,
157
+ };
158
+ }
159
+ /**
160
+ * Compute cloud position + TK cross as a LOCATION line. NEVER a directional
161
+ * lean, NEVER graded, NEVER in numbersIndex as a tradeable claim. The render
162
+ * layer attaches the explicit no-edge label. Standard 9/26/52 Hosoda params.
163
+ */
164
+ export function computeIchimokuLocation(candles) {
165
+ if (!candles || candles.length < 53)
166
+ return { available: false };
167
+ const n = candles.length;
168
+ const last = candles[n - 1];
169
+ const periodHL = (lookback, end) => {
170
+ let hi = -Infinity;
171
+ let lo = Infinity;
172
+ for (let i = end - lookback + 1; i <= end; i++) {
173
+ if (i < 0)
174
+ continue;
175
+ hi = Math.max(hi, candles[i].high);
176
+ lo = Math.min(lo, candles[i].low);
177
+ }
178
+ return (hi + lo) / 2;
179
+ };
180
+ // Senkou A/B projected 26 forward; for "current cloud" use the spans plotted
181
+ // at the current bar (computed from 26 bars ago).
182
+ const tenkanAt = (end) => periodHL(9, end);
183
+ const kijunAt = (end) => periodHL(26, end);
184
+ const senkouAAt = (end) => (tenkanAt(end) + kijunAt(end)) / 2;
185
+ const senkouBAt = (end) => periodHL(52, end);
186
+ const spanEnd = n - 1 - 26;
187
+ if (spanEnd < 52) {
188
+ // not enough history for a plotted cloud at the current bar
189
+ return { available: false };
190
+ }
191
+ const a = senkouAAt(spanEnd);
192
+ const b = senkouBAt(spanEnd);
193
+ const cloudTop = Math.max(a, b);
194
+ const cloudBot = Math.min(a, b);
195
+ const cloud = last.close > cloudTop ? "above" : last.close < cloudBot ? "below" : "in";
196
+ // TK cross: walk back to find the most recent tenkan/kijun sign change.
197
+ let tkCrossBarsAgo = null;
198
+ let prevSign = 0;
199
+ for (let i = 26; i < n; i++) {
200
+ const t = tenkanAt(i);
201
+ const k = kijunAt(i);
202
+ const sign = Math.sign(t - k);
203
+ if (sign !== 0 && prevSign !== 0 && sign !== prevSign) {
204
+ tkCrossBarsAgo = n - 1 - i;
205
+ }
206
+ if (sign !== 0)
207
+ prevSign = sign;
208
+ }
209
+ return { available: true, cloud, tkCrossBarsAgo };
210
+ }
211
+ export function computeAtlas(rows) {
212
+ if (!rows || rows.length === 0)
213
+ return { available: false, sectors: [], leaders: [], laggards: [] };
214
+ const sorted = [...rows].sort((x, y) => y.change24hPct - x.change24hPct);
215
+ return {
216
+ available: true,
217
+ sectors: sorted,
218
+ leaders: sorted.slice(0, 1).map((s) => s.name),
219
+ laggards: sorted.slice(-1).map((s) => s.name),
220
+ };
221
+ }
222
+ /** Skew threshold — ratio outside [1/x, x] is heavy; inside is balanced. */
223
+ const DEPTH_SKEW_RATIO = 1.25;
224
+ /**
225
+ * Pure book-structure facts. mid = (bestBid+bestAsk)/2. Notional = price*qty
226
+ * summed within ±1%/±2% bands; largest single-level wall per side; widest
227
+ * adjacent-level gap as a "thin zone". NEVER a direction/target/signal — "skew"
228
+ * is a descriptive ratio word only.
229
+ */
230
+ export function depthSurface(book) {
231
+ if (!book || book.bids.length === 0 || book.asks.length === 0) {
232
+ return { available: false };
233
+ }
234
+ const bestBid = book.bids[0][0];
235
+ const bestAsk = book.asks[0][0];
236
+ if (!(bestBid > 0) || !(bestAsk > 0))
237
+ return { available: false };
238
+ const mid = (bestBid + bestAsk) / 2;
239
+ const band1 = mid * 0.01;
240
+ const band2 = mid * 0.02;
241
+ let bid1 = 0;
242
+ let bid2 = 0;
243
+ let bidWallUsd = 0;
244
+ let bidWallPrice = 0;
245
+ // Bids: prices <= mid, walk down. Within-band = mid-price <= band.
246
+ const bidLevels = [];
247
+ for (const [p, q] of book.bids) {
248
+ const dist = mid - p;
249
+ if (dist > band2)
250
+ break; // bids descend → past ±2% we can stop
251
+ if (dist < 0)
252
+ continue; // crossed level (rare); skip
253
+ const notional = p * q;
254
+ if (dist <= band1)
255
+ bid1 += notional;
256
+ bid2 += notional;
257
+ bidLevels.push([p, notional]);
258
+ if (notional > bidWallUsd) {
259
+ bidWallUsd = notional;
260
+ bidWallPrice = p;
261
+ }
262
+ }
263
+ let ask1 = 0;
264
+ let ask2 = 0;
265
+ let askWallUsd = 0;
266
+ let askWallPrice = 0;
267
+ const askLevels = [];
268
+ for (const [p, q] of book.asks) {
269
+ const dist = p - mid;
270
+ if (dist > band2)
271
+ break; // asks ascend → past ±2% stop
272
+ if (dist < 0)
273
+ continue;
274
+ const notional = p * q;
275
+ if (dist <= band1)
276
+ ask1 += notional;
277
+ ask2 += notional;
278
+ askLevels.push([p, notional]);
279
+ if (notional > askWallUsd) {
280
+ askWallUsd = notional;
281
+ askWallPrice = p;
282
+ }
283
+ }
284
+ // Descriptive skew on ±1% notional (closed vocab, not a forecast).
285
+ let skew = "balanced";
286
+ if (ask1 > 0 && bid1 > 0) {
287
+ const ratio = bid1 / ask1;
288
+ skew =
289
+ ratio >= DEPTH_SKEW_RATIO
290
+ ? "bid-heavy"
291
+ : ratio <= 1 / DEPTH_SKEW_RATIO
292
+ ? "ask-heavy"
293
+ : "balanced";
294
+ }
295
+ // Thin zone — widest adjacent-level price gap across the merged ±2% window
296
+ // (low cumulative depth between two priced levels). Location only.
297
+ const merged = [
298
+ ...bidLevels.map(([p]) => p),
299
+ ...askLevels.map(([p]) => p),
300
+ ].sort((a, b) => a - b);
301
+ let thinLo = 0;
302
+ let thinHi = 0;
303
+ let widest = 0;
304
+ for (let i = 1; i < merged.length; i++) {
305
+ const gap = merged[i] - merged[i - 1];
306
+ if (gap > widest) {
307
+ widest = gap;
308
+ thinLo = merged[i - 1];
309
+ thinHi = merged[i];
310
+ }
311
+ }
312
+ const round0 = (n) => Math.round(n);
313
+ const round1 = (n) => Number(n.toFixed(1)); // BTC-perp tick precision
314
+ const usdM = (n) => Number((n / 1_000_000).toFixed(1)); // $ millions, 1dp
315
+ // A thin zone is meaningful only when the widest gap clears multiple ticks —
316
+ // on a dense 1000-level book the gap is sub-dollar (no real vacuum). Honest:
317
+ // report the zone only when it is materially wider than the typical spacing
318
+ // (>= $5 here), else flag it as negligible so we never paint a fake vacuum.
319
+ const THIN_MIN_USD = 5;
320
+ const thinZone = widest >= THIN_MIN_USD && round1(thinLo) !== round1(thinHi);
321
+ return {
322
+ available: true,
323
+ mid: round0(mid),
324
+ bid1Pct: usdM(bid1),
325
+ bid2Pct: usdM(bid2),
326
+ ask1Pct: usdM(ask1),
327
+ ask2Pct: usdM(ask2),
328
+ skew,
329
+ bidWallPrice: round0(bidWallPrice),
330
+ bidWallUsd: usdM(bidWallUsd),
331
+ askWallPrice: round0(askWallPrice),
332
+ askWallUsd: usdM(askWallUsd),
333
+ thinLo: round1(thinLo),
334
+ thinHi: round1(thinHi),
335
+ thinZone,
336
+ };
337
+ }
338
+ /**
339
+ * Front-expiry max-pain. Selects the NEAREST not-yet-expired expiry, then for
340
+ * each listed strike S computes pain(S) = Σ_calls OI*max(0,S-K) +
341
+ * Σ_puts OI*max(0,K-S); max-pain = argmin. Also the put/call OI ratio + total
342
+ * OI for that expiry. This is an OI SNAPSHOT — NOT a price magnet/target. The
343
+ * render layer attaches the explicit no-magnet label.
344
+ */
345
+ export function maxPainSurface(rows, nowMs) {
346
+ if (!rows || rows.length === 0)
347
+ return { available: false };
348
+ // Nearest expiry strictly in the future; fall back to nearest overall if all
349
+ // listed expiries are past (stale Deribit snapshot).
350
+ let frontMs = Infinity;
351
+ for (const r of rows) {
352
+ if (r.expiryMs >= nowMs && r.expiryMs < frontMs)
353
+ frontMs = r.expiryMs;
354
+ }
355
+ if (!Number.isFinite(frontMs)) {
356
+ for (const r of rows) {
357
+ if (r.expiryMs < frontMs || frontMs === Infinity)
358
+ frontMs = r.expiryMs;
359
+ }
360
+ }
361
+ const front = rows.filter((r) => r.expiryMs === frontMs);
362
+ if (front.length === 0)
363
+ return { available: false };
364
+ const expiry = front[0].expiry;
365
+ // Canonical ISO date for the narrated prose (date-exempt class). Derived from
366
+ // the authoritative expiryMs so it never depends on parsing the DDMMMYY token.
367
+ const expiryIso = new Date(frontMs).toISOString().slice(0, 10);
368
+ const strikes = Array.from(new Set(front.map((r) => r.strike))).sort((a, b) => a - b);
369
+ if (strikes.length === 0)
370
+ return { available: false };
371
+ let callOi = 0;
372
+ let putOi = 0;
373
+ for (const r of front) {
374
+ if (r.kind === "C")
375
+ callOi += r.openInterest;
376
+ else
377
+ putOi += r.openInterest;
378
+ }
379
+ const totalOi = callOi + putOi;
380
+ let bestStrike = strikes[0];
381
+ let bestPain = Infinity;
382
+ for (const S of strikes) {
383
+ let pain = 0;
384
+ for (const r of front) {
385
+ if (r.kind === "C")
386
+ pain += r.openInterest * Math.max(0, S - r.strike);
387
+ else
388
+ pain += r.openInterest * Math.max(0, r.strike - S);
389
+ }
390
+ if (pain < bestPain) {
391
+ bestPain = pain;
392
+ bestStrike = S;
393
+ }
394
+ }
395
+ const putCallRatio = callOi > 0 ? Number((putOi / callOi).toFixed(2)) : 0;
396
+ return {
397
+ available: true,
398
+ expiry,
399
+ expiryIso,
400
+ maxPainStrike: bestStrike,
401
+ putCallRatio,
402
+ totalOi: Number(totalOi.toFixed(1)),
403
+ };
404
+ }
405
+ // ── MODELED LIQUIDATION GEOMETRY — leverage-bucket location (NOT a forecast) ──
406
+ /** Standard leverage buckets the geometry is modeled at (frozen). */
407
+ export const LIQ_LEVERAGE_BUCKETS = [10, 25, 50, 100];
408
+ /**
409
+ * Pure leverage-bucket geometry — NO network fetch, NO forecast. For each
410
+ * standard leverage N ∈ {10,25,50,100}: long-liq ≈ mid·(1−1/N), short-liq ≈
411
+ * mid·(1+1/N), rounded to whole dollars. The total perp OI $ is reported as the
412
+ * pool that COULD be exposed, NOT distributed (we do not know per-position entry
413
+ * or leverage). This is GEOMETRY/LOCATION, exactly like order-book walls — never
414
+ * a magnet, never a forecast, never directional. The render layer attaches the
415
+ * explicit no-forecast/no-magnet label.
416
+ */
417
+ export function liqGeometrySurface(mid, oiNotional) {
418
+ if (mid === null || !(mid > 0) || !Number.isFinite(mid)) {
419
+ return { available: false };
420
+ }
421
+ const bands = LIQ_LEVERAGE_BUCKETS.map((n) => ({
422
+ n,
423
+ longLiq: Math.round(mid * (1 - 1 / n)),
424
+ shortLiq: Math.round(mid * (1 + 1 / n)),
425
+ }));
426
+ return {
427
+ available: true,
428
+ mid: Math.round(mid),
429
+ oiNotional: oiNotional !== null && Number.isFinite(oiNotional) && oiNotional > 0
430
+ ? Math.round(oiNotional)
431
+ : null,
432
+ bands,
433
+ };
434
+ }
435
+ /** Stop-vs-band proximity threshold (%). Pure structure, not a recommendation. */
436
+ export const STOP_BAND_NEAR_PCT = 5;
437
+ export function stopVsBand(trade, geo) {
438
+ if (!trade || !geo.available || !geo.bands)
439
+ return null;
440
+ const { side, stop } = trade;
441
+ if (!Number.isFinite(stop) || !(stop > 0))
442
+ return null;
443
+ let best = null;
444
+ for (const b of geo.bands) {
445
+ const bandPrice = side === "long" ? b.longLiq : b.shortLiq;
446
+ if (!(bandPrice > 0))
447
+ continue;
448
+ const pct = Number(((Math.abs(stop - bandPrice) / stop) * 100).toFixed(1));
449
+ if (best === null || pct < best.pct) {
450
+ best = {
451
+ n: b.n,
452
+ bandPrice,
453
+ pct,
454
+ within: pct <= STOP_BAND_NEAR_PCT,
455
+ side,
456
+ };
457
+ }
458
+ }
459
+ return best;
460
+ }
461
+ // ── helpers ──────────────────────────────────────────────────────────────────
462
+ export function fmtSigned(n) {
463
+ return n > 0 ? `+${n}` : `${n}`;
464
+ }
465
+ function roundDigits(price) {
466
+ if (price >= 1000)
467
+ return 0;
468
+ if (price >= 1)
469
+ return 2;
470
+ return 4;
471
+ }
472
+ //# sourceMappingURL=surfaces.js.map