oh-my-opencode 5.1.51 → 5.1.55

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 (916) hide show
  1. package/dist/agents/atlas/agent.d.ts +5 -5
  2. package/dist/agents/dynamic-agent-core-sections.d.ts +0 -1
  3. package/dist/agents/dynamic-agent-prompt-builder.d.ts +1 -1
  4. package/dist/agents/gpt-apply-patch-guard.d.ts +0 -1
  5. package/dist/agents/hephaestus/agent.d.ts +3 -7
  6. package/dist/agents/hephaestus/model-support.d.ts +6 -0
  7. package/dist/agents/metis.d.ts +0 -15
  8. package/dist/agents/native-model-prompt.d.ts +9 -0
  9. package/dist/agents/native-prompt-frame.d.ts +20 -0
  10. package/dist/agents/native-tool-snippet.d.ts +6 -0
  11. package/dist/agents/sisyphus/default.d.ts +0 -1
  12. package/dist/agents/sisyphus-agent-factory.d.ts +2 -11
  13. package/dist/agents/sisyphus-junior/agent.d.ts +2 -20
  14. package/dist/agents/sisyphus-junior/index.d.ts +1 -11
  15. package/dist/agents/sisyphus-runtime-prompt-reconciler.d.ts +6 -0
  16. package/dist/agents/types.d.ts +2 -2
  17. package/dist/cli/index.js +1174 -394
  18. package/dist/cli/service-auth/credential-lock.d.ts +11 -0
  19. package/dist/cli/service-auth/credential-owner.d.ts +10 -0
  20. package/dist/cli/service-auth/index.d.ts +3 -1
  21. package/dist/cli/service-auth/keystore.d.ts +8 -1
  22. package/dist/cli/service-auth/owned-refresh.d.ts +21 -0
  23. package/dist/cli/service-auth/protocol-v2.d.ts +27 -0
  24. package/dist/cli/service-auth/protocol.d.ts +26 -2
  25. package/dist/cli/service-auth/recovery-clock.d.ts +7 -0
  26. package/dist/cli/service-auth/refresh-attempt.d.ts +34 -0
  27. package/dist/cli/service-auth/session.d.ts +9 -2
  28. package/dist/cli-node/index.js +1174 -394
  29. package/dist/config/schema/agent-overrides.d.ts +64 -0
  30. package/dist/config/schema/categories.d.ts +8 -0
  31. package/dist/config/schema/oh-my-opencode-config.d.ts +64 -0
  32. package/dist/hooks/native-edition-nudge/hook.d.ts +3 -4
  33. package/dist/index.js +15625 -8841
  34. package/dist/oh-my-opencode.schema.json +112 -0
  35. package/dist/plugin/session-tool-permissions.d.ts +10 -0
  36. package/dist/plugin/system-transform.d.ts +2 -1
  37. package/dist/plugin/tool-definition.d.ts +1 -0
  38. package/dist/shared/bun-ffi-shim.d.ts +29 -0
  39. package/dist/shared/json-file-cache-store.d.ts +11 -0
  40. package/dist/skills/browser/runtime/omowright/index.js +24 -33
  41. package/dist/skills/browser/runtime/omowright/manifest.json +3 -3
  42. package/dist/skills/frontend/ATTRIBUTION.md +104 -1
  43. package/dist/skills/frontend/SKILL.md +7 -3
  44. package/dist/skills/frontend/references/design/design-system-architecture.md +3 -3
  45. package/dist/skills/frontend/references/perfection/craft-floor.md +59 -0
  46. package/dist/skills/frontend/references/perfection/detect.md +52 -0
  47. package/dist/skills/frontend/scripts/detect/cli.ts +70 -0
  48. package/dist/skills/frontend/scripts/detect/config.test.ts +26 -0
  49. package/dist/skills/frontend/scripts/detect/config.ts +53 -0
  50. package/dist/skills/frontend/scripts/detect/core/characters.ts +2 -0
  51. package/dist/skills/frontend/scripts/detect/core/color.test.ts +29 -0
  52. package/dist/skills/frontend/scripts/detect/core/color.ts +150 -0
  53. package/dist/skills/frontend/scripts/detect/core/page.ts +84 -0
  54. package/dist/skills/frontend/scripts/detect/core/shadow.ts +40 -0
  55. package/dist/skills/frontend/scripts/detect/core/source.ts +33 -0
  56. package/dist/skills/frontend/scripts/detect/detect.ts +77 -0
  57. package/dist/skills/frontend/scripts/detect/index.ts +23 -0
  58. package/dist/skills/frontend/scripts/detect/lint.test.ts +27 -0
  59. package/dist/skills/frontend/scripts/detect/lint.ts +98 -0
  60. package/dist/skills/frontend/scripts/detect/render/probe-placement.test.ts +19 -0
  61. package/dist/skills/frontend/scripts/detect/render/probe-placement.ts +50 -0
  62. package/dist/skills/frontend/scripts/detect/render/renderer.ts +37 -0
  63. package/dist/skills/frontend/scripts/detect/render/webview.ts +71 -0
  64. package/dist/skills/frontend/scripts/detect/report.ts +29 -0
  65. package/dist/skills/frontend/scripts/detect/rule.ts +42 -0
  66. package/dist/skills/frontend/scripts/detect/rules/color/ai-color-palette.test.ts +74 -0
  67. package/dist/skills/frontend/scripts/detect/rules/color/ai-color-palette.ts +83 -0
  68. package/dist/skills/frontend/scripts/detect/rules/color/cream-palette.test.ts +24 -0
  69. package/dist/skills/frontend/scripts/detect/rules/color/cream-palette.ts +35 -0
  70. package/dist/skills/frontend/scripts/detect/rules/color/dark-glow.test.ts +47 -0
  71. package/dist/skills/frontend/scripts/detect/rules/color/dark-glow.ts +44 -0
  72. package/dist/skills/frontend/scripts/detect/rules/color/design-system-color.test.ts +26 -0
  73. package/dist/skills/frontend/scripts/detect/rules/color/design-system-color.ts +35 -0
  74. package/dist/skills/frontend/scripts/detect/rules/color/gradient-text.test.ts +24 -0
  75. package/dist/skills/frontend/scripts/detect/rules/color/gradient-text.ts +59 -0
  76. package/dist/skills/frontend/scripts/detect/rules/color/gray-on-color.test.ts +39 -0
  77. package/dist/skills/frontend/scripts/detect/rules/color/gray-on-color.ts +38 -0
  78. package/dist/skills/frontend/scripts/detect/rules/color/index.ts +15 -0
  79. package/dist/skills/frontend/scripts/detect/rules/color/low-contrast.test.ts +209 -0
  80. package/dist/skills/frontend/scripts/detect/rules/color/low-contrast.ts +57 -0
  81. package/dist/skills/frontend/scripts/detect/rules/color/placeholder-contrast.test.ts +62 -0
  82. package/dist/skills/frontend/scripts/detect/rules/color/radial-halo.test.ts +40 -0
  83. package/dist/skills/frontend/scripts/detect/rules/color/radial-halo.ts +31 -0
  84. package/dist/skills/frontend/scripts/detect/rules/color/radial-spotlight-glow.test.ts +27 -0
  85. package/dist/skills/frontend/scripts/detect/rules/color/radial-spotlight-glow.ts +33 -0
  86. package/dist/skills/frontend/scripts/detect/rules/color/support/animation-opacity.ts +78 -0
  87. package/dist/skills/frontend/scripts/detect/rules/color/support/color-path.ts +15 -0
  88. package/dist/skills/frontend/scripts/detect/rules/color/support/contrast-pairs.ts +54 -0
  89. package/dist/skills/frontend/scripts/detect/rules/color/support/contrast-role.ts +76 -0
  90. package/dist/skills/frontend/scripts/detect/rules/color/support/glow-forms.ts +56 -0
  91. package/dist/skills/frontend/scripts/detect/rules/color/support/gradient-samples.ts +134 -0
  92. package/dist/skills/frontend/scripts/detect/rules/color/support/gradients.ts +91 -0
  93. package/dist/skills/frontend/scripts/detect/rules/color/support/mockup-roots.ts +63 -0
  94. package/dist/skills/frontend/scripts/detect/rules/color/support/page-ignore.ts +7 -0
  95. package/dist/skills/frontend/scripts/detect/rules/color/support/painted-text.ts +141 -0
  96. package/dist/skills/frontend/scripts/detect/rules/color/support/palette-roles.ts +58 -0
  97. package/dist/skills/frontend/scripts/detect/rules/color/support/placeholder-contrast.ts +25 -0
  98. package/dist/skills/frontend/scripts/detect/rules/color/support/stock-accent.ts +31 -0
  99. package/dist/skills/frontend/scripts/detect/rules/color/support/text-colors.ts +80 -0
  100. package/dist/skills/frontend/scripts/detect/rules/copy/aphoristic-cadence.test.ts +18 -0
  101. package/dist/skills/frontend/scripts/detect/rules/copy/aphoristic-cadence.ts +20 -0
  102. package/dist/skills/frontend/scripts/detect/rules/copy/broken-image.test.ts +25 -0
  103. package/dist/skills/frontend/scripts/detect/rules/copy/broken-image.ts +17 -0
  104. package/dist/skills/frontend/scripts/detect/rules/copy/em-dash-overuse.test.ts +39 -0
  105. package/dist/skills/frontend/scripts/detect/rules/copy/em-dash-overuse.ts +46 -0
  106. package/dist/skills/frontend/scripts/detect/rules/copy/index.ts +15 -0
  107. package/dist/skills/frontend/scripts/detect/rules/copy/marketing-buzzword.test.ts +18 -0
  108. package/dist/skills/frontend/scripts/detect/rules/copy/marketing-buzzword.ts +33 -0
  109. package/dist/skills/frontend/scripts/detect/rules/copy/numbered-section-labels.test.ts +58 -0
  110. package/dist/skills/frontend/scripts/detect/rules/copy/numbered-section-labels.ts +34 -0
  111. package/dist/skills/frontend/scripts/detect/rules/copy/repeated-container-text.test.ts +43 -0
  112. package/dist/skills/frontend/scripts/detect/rules/copy/repeated-container-text.ts +56 -0
  113. package/dist/skills/frontend/scripts/detect/rules/copy/script-error.test.ts +48 -0
  114. package/dist/skills/frontend/scripts/detect/rules/copy/script-error.ts +38 -0
  115. package/dist/skills/frontend/scripts/detect/rules/copy/skipped-heading.test.ts +49 -0
  116. package/dist/skills/frontend/scripts/detect/rules/copy/skipped-heading.ts +81 -0
  117. package/dist/skills/frontend/scripts/detect/rules/copy/support/numbered-label.ts +94 -0
  118. package/dist/skills/frontend/scripts/detect/rules/copy/support/page-text.ts +37 -0
  119. package/dist/skills/frontend/scripts/detect/rules/copy/theater-slop-phrase.test.ts +17 -0
  120. package/dist/skills/frontend/scripts/detect/rules/copy/theater-slop-phrase.ts +21 -0
  121. package/dist/skills/frontend/scripts/detect/rules/decoration/blinking-cursor.test.ts +43 -0
  122. package/dist/skills/frontend/scripts/detect/rules/decoration/blinking-cursor.ts +48 -0
  123. package/dist/skills/frontend/scripts/detect/rules/decoration/border-accent-on-rounded.test.ts +33 -0
  124. package/dist/skills/frontend/scripts/detect/rules/decoration/border-accent-on-rounded.ts +14 -0
  125. package/dist/skills/frontend/scripts/detect/rules/decoration/bounce-easing.test.ts +72 -0
  126. package/dist/skills/frontend/scripts/detect/rules/decoration/bounce-easing.ts +83 -0
  127. package/dist/skills/frontend/scripts/detect/rules/decoration/buried-raster.test.ts +95 -0
  128. package/dist/skills/frontend/scripts/detect/rules/decoration/buried-raster.ts +72 -0
  129. package/dist/skills/frontend/scripts/detect/rules/decoration/codex-grid-background.test.ts +28 -0
  130. package/dist/skills/frontend/scripts/detect/rules/decoration/codex-grid-background.ts +34 -0
  131. package/dist/skills/frontend/scripts/detect/rules/decoration/design-system-radius.test.ts +37 -0
  132. package/dist/skills/frontend/scripts/detect/rules/decoration/design-system-radius.ts +31 -0
  133. package/dist/skills/frontend/scripts/detect/rules/decoration/gpt-thin-border-wide-shadow.test.ts +59 -0
  134. package/dist/skills/frontend/scripts/detect/rules/decoration/gpt-thin-border-wide-shadow.ts +66 -0
  135. package/dist/skills/frontend/scripts/detect/rules/decoration/hard-offset-shadow.test.ts +45 -0
  136. package/dist/skills/frontend/scripts/detect/rules/decoration/hard-offset-shadow.ts +31 -0
  137. package/dist/skills/frontend/scripts/detect/rules/decoration/hero-eyebrow-chip.test.ts +76 -0
  138. package/dist/skills/frontend/scripts/detect/rules/decoration/hero-eyebrow-chip.ts +19 -0
  139. package/dist/skills/frontend/scripts/detect/rules/decoration/icon-tile-stack.test.ts +67 -0
  140. package/dist/skills/frontend/scripts/detect/rules/decoration/icon-tile-stack.ts +92 -0
  141. package/dist/skills/frontend/scripts/detect/rules/decoration/index.ts +38 -0
  142. package/dist/skills/frontend/scripts/detect/rules/decoration/kicker-above-heading.test.ts +126 -0
  143. package/dist/skills/frontend/scripts/detect/rules/decoration/kicker-above-heading.ts +69 -0
  144. package/dist/skills/frontend/scripts/detect/rules/decoration/marquee.test.ts +63 -0
  145. package/dist/skills/frontend/scripts/detect/rules/decoration/marquee.ts +51 -0
  146. package/dist/skills/frontend/scripts/detect/rules/decoration/organic-clip-path.test.ts +67 -0
  147. package/dist/skills/frontend/scripts/detect/rules/decoration/organic-clip-path.ts +41 -0
  148. package/dist/skills/frontend/scripts/detect/rules/decoration/pulsing-dot.test.ts +58 -0
  149. package/dist/skills/frontend/scripts/detect/rules/decoration/pulsing-dot.ts +72 -0
  150. package/dist/skills/frontend/scripts/detect/rules/decoration/repeating-stripes-gradient.test.ts +26 -0
  151. package/dist/skills/frontend/scripts/detect/rules/decoration/repeating-stripes-gradient.ts +25 -0
  152. package/dist/skills/frontend/scripts/detect/rules/decoration/shape-assembled-illustration.test.ts +59 -0
  153. package/dist/skills/frontend/scripts/detect/rules/decoration/shape-assembled-illustration.ts +58 -0
  154. package/dist/skills/frontend/scripts/detect/rules/decoration/side-tab.test.ts +91 -0
  155. package/dist/skills/frontend/scripts/detect/rules/decoration/side-tab.ts +17 -0
  156. package/dist/skills/frontend/scripts/detect/rules/decoration/support/appearance.ts +110 -0
  157. package/dist/skills/frontend/scripts/detect/rules/decoration/support/assert-cases.ts +25 -0
  158. package/dist/skills/frontend/scripts/detect/rules/decoration/support/borders.ts +150 -0
  159. package/dist/skills/frontend/scripts/detect/rules/decoration/support/clip-geometry.ts +151 -0
  160. package/dist/skills/frontend/scripts/detect/rules/decoration/support/css-candidates.ts +66 -0
  161. package/dist/skills/frontend/scripts/detect/rules/decoration/support/curve-samples.ts +55 -0
  162. package/dist/skills/frontend/scripts/detect/rules/decoration/support/gradient-pattern.ts +40 -0
  163. package/dist/skills/frontend/scripts/detect/rules/decoration/support/keyframes.ts +134 -0
  164. package/dist/skills/frontend/scripts/detect/rules/decoration/support/labels.ts +85 -0
  165. package/dist/skills/frontend/scripts/detect/rules/decoration/support/raster-state.ts +51 -0
  166. package/dist/skills/frontend/scripts/detect/rules/index.ts +16 -0
  167. package/dist/skills/frontend/scripts/detect/rules/layout/body-text-viewport-edge.test.ts +64 -0
  168. package/dist/skills/frontend/scripts/detect/rules/layout/body-text-viewport-edge.ts +62 -0
  169. package/dist/skills/frontend/scripts/detect/rules/layout/clipped-overflow-container.test.ts +40 -0
  170. package/dist/skills/frontend/scripts/detect/rules/layout/clipped-overflow-container.ts +15 -0
  171. package/dist/skills/frontend/scripts/detect/rules/layout/content-hidden-at-rest.test.ts +62 -0
  172. package/dist/skills/frontend/scripts/detect/rules/layout/content-hidden-at-rest.ts +63 -0
  173. package/dist/skills/frontend/scripts/detect/rules/layout/cramped-padding.test.ts +61 -0
  174. package/dist/skills/frontend/scripts/detect/rules/layout/cramped-padding.ts +97 -0
  175. package/dist/skills/frontend/scripts/detect/rules/layout/edge-flush-cards.test.ts +43 -0
  176. package/dist/skills/frontend/scripts/detect/rules/layout/edge-flush-cards.ts +47 -0
  177. package/dist/skills/frontend/scripts/detect/rules/layout/first-viewport-column-overflow.test.ts +28 -0
  178. package/dist/skills/frontend/scripts/detect/rules/layout/first-viewport-column-overflow.ts +43 -0
  179. package/dist/skills/frontend/scripts/detect/rules/layout/heading-rhythm.test.ts +67 -0
  180. package/dist/skills/frontend/scripts/detect/rules/layout/heading-rhythm.ts +30 -0
  181. package/dist/skills/frontend/scripts/detect/rules/layout/index.ts +21 -0
  182. package/dist/skills/frontend/scripts/detect/rules/layout/monotonous-spacing.test.ts +19 -0
  183. package/dist/skills/frontend/scripts/detect/rules/layout/monotonous-spacing.ts +32 -0
  184. package/dist/skills/frontend/scripts/detect/rules/layout/nested-cards.test.ts +60 -0
  185. package/dist/skills/frontend/scripts/detect/rules/layout/nested-cards.ts +38 -0
  186. package/dist/skills/frontend/scripts/detect/rules/layout/straggler.test.ts +33 -0
  187. package/dist/skills/frontend/scripts/detect/rules/layout/straggler.ts +28 -0
  188. package/dist/skills/frontend/scripts/detect/rules/layout/support/cards.ts +114 -0
  189. package/dist/skills/frontend/scripts/detect/rules/layout/support/clipping.ts +71 -0
  190. package/dist/skills/frontend/scripts/detect/rules/layout/support/declared-mockups.ts +46 -0
  191. package/dist/skills/frontend/scripts/detect/rules/layout/support/geometry.ts +73 -0
  192. package/dist/skills/frontend/scripts/detect/rules/layout/support/hidden-interface.ts +35 -0
  193. package/dist/skills/frontend/scripts/detect/rules/layout/support/layout-cases.ts +23 -0
  194. package/dist/skills/frontend/scripts/detect/rules/layout/support/line-breaks.ts +32 -0
  195. package/dist/skills/frontend/scripts/detect/rules/layout/support/motion.ts +77 -0
  196. package/dist/skills/frontend/scripts/detect/rules/layout/support/padding.ts +93 -0
  197. package/dist/skills/frontend/scripts/detect/rules/layout/support/rhythm.ts +161 -0
  198. package/dist/skills/frontend/scripts/detect/rules/layout/text-occlusion.test.ts +37 -0
  199. package/dist/skills/frontend/scripts/detect/rules/layout/text-occlusion.ts +84 -0
  200. package/dist/skills/frontend/scripts/detect/rules/layout/text-overflow.test.ts +83 -0
  201. package/dist/skills/frontend/scripts/detect/rules/layout/text-overflow.ts +72 -0
  202. package/dist/skills/frontend/scripts/detect/rules/layout/unbalanced-heading.test.ts +22 -0
  203. package/dist/skills/frontend/scripts/detect/rules/layout/unbalanced-heading.ts +22 -0
  204. package/dist/skills/frontend/scripts/detect/rules/layout/viewport-reflow.test.ts +34 -0
  205. package/dist/skills/frontend/scripts/detect/rules/layout/viewport-reflow.ts +33 -0
  206. package/dist/skills/frontend/scripts/detect/rules/source/ai-color-palette.test.ts +13 -0
  207. package/dist/skills/frontend/scripts/detect/rules/source/ai-color-palette.ts +11 -0
  208. package/dist/skills/frontend/scripts/detect/rules/source/aphoristic-cadence.test.ts +12 -0
  209. package/dist/skills/frontend/scripts/detect/rules/source/aphoristic-cadence.ts +14 -0
  210. package/dist/skills/frontend/scripts/detect/rules/source/border-accent-on-rounded.test.ts +14 -0
  211. package/dist/skills/frontend/scripts/detect/rules/source/border-accent-on-rounded.ts +20 -0
  212. package/dist/skills/frontend/scripts/detect/rules/source/bounce-easing.test.ts +19 -0
  213. package/dist/skills/frontend/scripts/detect/rules/source/bounce-easing.ts +21 -0
  214. package/dist/skills/frontend/scripts/detect/rules/source/broken-image.test.ts +27 -0
  215. package/dist/skills/frontend/scripts/detect/rules/source/broken-image.ts +16 -0
  216. package/dist/skills/frontend/scripts/detect/rules/source/codex-grid-background.test.ts +11 -0
  217. package/dist/skills/frontend/scripts/detect/rules/source/codex-grid-background.ts +18 -0
  218. package/dist/skills/frontend/scripts/detect/rules/source/dark-glow.test.ts +15 -0
  219. package/dist/skills/frontend/scripts/detect/rules/source/dark-glow.ts +21 -0
  220. package/dist/skills/frontend/scripts/detect/rules/source/em-dash-overuse.test.ts +13 -0
  221. package/dist/skills/frontend/scripts/detect/rules/source/em-dash-overuse.ts +15 -0
  222. package/dist/skills/frontend/scripts/detect/rules/source/gradient-text.test.ts +12 -0
  223. package/dist/skills/frontend/scripts/detect/rules/source/gradient-text.ts +11 -0
  224. package/dist/skills/frontend/scripts/detect/rules/source/gray-on-color.test.ts +20 -0
  225. package/dist/skills/frontend/scripts/detect/rules/source/gray-on-color.ts +13 -0
  226. package/dist/skills/frontend/scripts/detect/rules/source/index.ts +19 -0
  227. package/dist/skills/frontend/scripts/detect/rules/source/marketing-buzzword.test.ts +12 -0
  228. package/dist/skills/frontend/scripts/detect/rules/source/marketing-buzzword.ts +17 -0
  229. package/dist/skills/frontend/scripts/detect/rules/source/marquee.test.ts +12 -0
  230. package/dist/skills/frontend/scripts/detect/rules/source/marquee.ts +12 -0
  231. package/dist/skills/frontend/scripts/detect/rules/source/monotonous-spacing.test.ts +13 -0
  232. package/dist/skills/frontend/scripts/detect/rules/source/monotonous-spacing.ts +22 -0
  233. package/dist/skills/frontend/scripts/detect/rules/source/overused-font.test.ts +21 -0
  234. package/dist/skills/frontend/scripts/detect/rules/source/overused-font.ts +16 -0
  235. package/dist/skills/frontend/scripts/detect/rules/source/radial-halo.test.ts +16 -0
  236. package/dist/skills/frontend/scripts/detect/rules/source/radial-halo.ts +14 -0
  237. package/dist/skills/frontend/scripts/detect/rules/source/side-tab.test.ts +29 -0
  238. package/dist/skills/frontend/scripts/detect/rules/source/side-tab.ts +58 -0
  239. package/dist/skills/frontend/scripts/detect/rules/source/support/accent-scans.ts +78 -0
  240. package/dist/skills/frontend/scripts/detect/rules/source/support/check-source.ts +6 -0
  241. package/dist/skills/frontend/scripts/detect/rules/source/support/corners.ts +105 -0
  242. package/dist/skills/frontend/scripts/detect/rules/source/support/css-effects.ts +81 -0
  243. package/dist/skills/frontend/scripts/detect/rules/source/support/css-scopes.ts +131 -0
  244. package/dist/skills/frontend/scripts/detect/rules/source/support/image-tags.ts +113 -0
  245. package/dist/skills/frontend/scripts/detect/rules/source/support/js-punctuation.ts +34 -0
  246. package/dist/skills/frontend/scripts/detect/rules/source/support/markup-scope.ts +44 -0
  247. package/dist/skills/frontend/scripts/detect/rules/source/support/source-color.ts +42 -0
  248. package/dist/skills/frontend/scripts/detect/rules/source/support/source-shadow.ts +15 -0
  249. package/dist/skills/frontend/scripts/detect/rules/source/support/source-text.ts +110 -0
  250. package/dist/skills/frontend/scripts/detect/rules/typography/all-caps-body.test.ts +24 -0
  251. package/dist/skills/frontend/scripts/detect/rules/typography/all-caps-body.ts +15 -0
  252. package/dist/skills/frontend/scripts/detect/rules/typography/design-system-font-size.test.ts +21 -0
  253. package/dist/skills/frontend/scripts/detect/rules/typography/design-system-font-size.ts +23 -0
  254. package/dist/skills/frontend/scripts/detect/rules/typography/design-system-font.test.ts +22 -0
  255. package/dist/skills/frontend/scripts/detect/rules/typography/design-system-font.ts +24 -0
  256. package/dist/skills/frontend/scripts/detect/rules/typography/extreme-negative-tracking.test.ts +23 -0
  257. package/dist/skills/frontend/scripts/detect/rules/typography/extreme-negative-tracking.ts +18 -0
  258. package/dist/skills/frontend/scripts/detect/rules/typography/flat-type-hierarchy.test.ts +33 -0
  259. package/dist/skills/frontend/scripts/detect/rules/typography/flat-type-hierarchy.ts +26 -0
  260. package/dist/skills/frontend/scripts/detect/rules/typography/index.ts +21 -0
  261. package/dist/skills/frontend/scripts/detect/rules/typography/italic-serif-display.test.ts +24 -0
  262. package/dist/skills/frontend/scripts/detect/rules/typography/italic-serif-display.ts +24 -0
  263. package/dist/skills/frontend/scripts/detect/rules/typography/justified-text.test.ts +31 -0
  264. package/dist/skills/frontend/scripts/detect/rules/typography/justified-text.ts +32 -0
  265. package/dist/skills/frontend/scripts/detect/rules/typography/line-length.test.ts +43 -0
  266. package/dist/skills/frontend/scripts/detect/rules/typography/line-length.ts +28 -0
  267. package/dist/skills/frontend/scripts/detect/rules/typography/oversized-h1.test.ts +26 -0
  268. package/dist/skills/frontend/scripts/detect/rules/typography/oversized-h1.ts +20 -0
  269. package/dist/skills/frontend/scripts/detect/rules/typography/overused-font.test.ts +35 -0
  270. package/dist/skills/frontend/scripts/detect/rules/typography/overused-font.ts +45 -0
  271. package/dist/skills/frontend/scripts/detect/rules/typography/support/drawn-enlargement.ts +48 -0
  272. package/dist/skills/frontend/scripts/detect/rules/typography/support/fading-text.ts +48 -0
  273. package/dist/skills/frontend/scripts/detect/rules/typography/support/flex-runs.ts +16 -0
  274. package/dist/skills/frontend/scripts/detect/rules/typography/support/font-family.ts +28 -0
  275. package/dist/skills/frontend/scripts/detect/rules/typography/support/painted-text.test.ts +63 -0
  276. package/dist/skills/frontend/scripts/detect/rules/typography/support/painted-text.ts +81 -0
  277. package/dist/skills/frontend/scripts/detect/rules/typography/support/svg-size.ts +57 -0
  278. package/dist/skills/frontend/scripts/detect/rules/typography/support/text-context.ts +112 -0
  279. package/dist/skills/frontend/scripts/detect/rules/typography/support/text-lines.ts +43 -0
  280. package/dist/skills/frontend/scripts/detect/rules/typography/support/type-hierarchy.ts +48 -0
  281. package/dist/skills/frontend/scripts/detect/rules/typography/tight-leading.test.ts +54 -0
  282. package/dist/skills/frontend/scripts/detect/rules/typography/tight-leading.ts +47 -0
  283. package/dist/skills/frontend/scripts/detect/rules/typography/tiny-text.test.ts +60 -0
  284. package/dist/skills/frontend/scripts/detect/rules/typography/tiny-text.ts +23 -0
  285. package/dist/skills/frontend/scripts/detect/rules/typography/undersized-ui-text.test.ts +98 -0
  286. package/dist/skills/frontend/scripts/detect/rules/typography/undersized-ui-text.ts +28 -0
  287. package/dist/skills/frontend/scripts/detect/rules/typography/wide-tracking.test.ts +26 -0
  288. package/dist/skills/frontend/scripts/detect/rules/typography/wide-tracking.ts +26 -0
  289. package/dist/skills/frontend/scripts/detect/snapshot/collect.ts +158 -0
  290. package/dist/skills/frontend/scripts/detect/snapshot/style-props.ts +25 -0
  291. package/dist/skills/frontend/scripts/detect/testing/build-snapshot.ts +78 -0
  292. package/dist/skills/frontend/scripts/detect/tsconfig.json +19 -0
  293. package/dist/skills/frontend/scripts/detect/types.ts +124 -0
  294. package/dist/skills/programming/SKILL.md +17 -74
  295. package/dist/skills/programming/references/go/README.md +1 -1
  296. package/dist/skills/programming/references/go/bootstrap.md +2 -2
  297. package/dist/skills/programming/references/python/README.md +4 -4
  298. package/dist/skills/programming/references/python/one-liners.md +5 -5
  299. package/dist/skills/programming/references/testing/README.md +82 -0
  300. package/dist/skills/programming/references/testing/junk-classes.md +56 -0
  301. package/dist/skills/programming/references/typescript/README.md +1 -2
  302. package/dist/skills/programming/scripts/go/new-project.ts +197 -0
  303. package/dist/skills/programming/scripts/python/new-project.ts +231 -0
  304. package/dist/skills/programming/scripts/python/new-script.ts +134 -0
  305. package/dist/skills/programming/scripts/rust/new-project.ts +215 -0
  306. package/dist/skills/programming/scripts/scaffolders.test.ts +96 -0
  307. package/dist/skills/programming/scripts/shared/run-tool.ts +19 -0
  308. package/dist/skills/programming/scripts/typescript/check-test-junk-rules.ts +140 -0
  309. package/dist/skills/programming/scripts/typescript/check-test-junk.test.ts +125 -0
  310. package/dist/skills/programming/scripts/typescript/check-test-junk.ts +148 -0
  311. package/dist/skills/programming/scripts/typescript/mutation-proof.test.ts +43 -0
  312. package/dist/skills/programming/scripts/typescript/mutation-proof.ts +179 -0
  313. package/dist/skills/remove-ai-slops/SKILL.md +32 -20
  314. package/dist/skills/ulw-research/scripts/source-commands.mjs +3 -1
  315. package/dist/skills/ulw-research/scripts/source-integrity.test.ts +39 -2
  316. package/dist/skills/visual-qa/SKILL.md +12 -1
  317. package/dist/tools/delegate-task/models-distribution.d.ts +1 -0
  318. package/dist/tui.js +142 -42
  319. package/package.json +22 -19
  320. package/packages/lsp-core/src/lsp/config-loader.ts +18 -2
  321. package/packages/lsp-core/src/lsp/host-js-runtime.test.ts +150 -0
  322. package/packages/lsp-core/src/lsp/host-js-runtime.ts +57 -0
  323. package/packages/lsp-core/src/lsp/server-definitions.ts +10 -0
  324. package/packages/lsp-core/src/lsp/server-resolution.ts +9 -1
  325. package/packages/lsp-core/src/lsp/typescript-server-defaults.test.ts +84 -0
  326. package/packages/lsp-daemon/dist/cli.js +81 -15
  327. package/packages/lsp-daemon/dist/client.js +74 -8
  328. package/packages/lsp-daemon/dist/index.js +76 -10
  329. package/packages/lsp-tools-mcp/dist/cli.js +74 -8
  330. package/packages/lsp-tools-mcp/dist/mcp.js +74 -8
  331. package/packages/lsp-tools-mcp/dist/tools.js +74 -8
  332. package/packages/omo-codex/plugin/.codex-plugin/plugin.json +1 -1
  333. package/packages/omo-codex/plugin/components/bootstrap/dist/cli.js +22 -4
  334. package/packages/omo-codex/plugin/components/bootstrap/hooks/hooks.json +1 -1
  335. package/packages/omo-codex/plugin/components/bootstrap/package.json +1 -1
  336. package/packages/omo-codex/plugin/components/comment-checker/hooks/hooks.json +1 -1
  337. package/packages/omo-codex/plugin/components/comment-checker/package.json +1 -1
  338. package/packages/omo-codex/plugin/components/git-bash/hooks/hooks.json +2 -2
  339. package/packages/omo-codex/plugin/components/git-bash/package.json +1 -1
  340. package/packages/omo-codex/plugin/components/lazycodex-executor-verify/hooks/hooks.json +1 -1
  341. package/packages/omo-codex/plugin/components/lazycodex-executor-verify/package.json +1 -1
  342. package/packages/omo-codex/plugin/components/lsp/dist/.omo-runtime-manifest.json +3 -3
  343. package/packages/omo-codex/plugin/components/lsp/dist/cli.js +77 -13
  344. package/packages/omo-codex/plugin/components/lsp/hooks/hooks.json +2 -2
  345. package/packages/omo-codex/plugin/components/lsp/package.json +1 -1
  346. package/packages/omo-codex/plugin/components/rules/hooks/hooks.json +4 -4
  347. package/packages/omo-codex/plugin/components/rules/package.json +1 -1
  348. package/packages/omo-codex/plugin/components/teammode/hooks/hooks.json +1 -1
  349. package/packages/omo-codex/plugin/components/teammode/package.json +1 -1
  350. package/packages/omo-codex/plugin/components/telemetry/dist/cli.js +34 -2
  351. package/packages/omo-codex/plugin/components/telemetry/dist/posthog.js +34 -2
  352. package/packages/omo-codex/plugin/components/telemetry/hooks/hooks.json +1 -1
  353. package/packages/omo-codex/plugin/components/telemetry/package.json +1 -1
  354. package/packages/omo-codex/plugin/components/telemetry/test/codex-hook.test.ts +14 -1
  355. package/packages/omo-codex/plugin/components/ultrawork/hooks/hooks.json +1 -1
  356. package/packages/omo-codex/plugin/components/ultrawork/package.json +1 -1
  357. package/packages/omo-codex/plugin/components/ulw-execute-continuation/hooks/hooks.json +1 -1
  358. package/packages/omo-codex/plugin/components/ulw-execute-continuation/package.json +1 -1
  359. package/packages/omo-codex/plugin/components/ulw-loop/hooks/hooks.json +5 -5
  360. package/packages/omo-codex/plugin/components/ulw-loop/package.json +1 -1
  361. package/packages/omo-codex/plugin/hooks/post-compact-resetting-git-bash-mcp-reminder.json +1 -1
  362. package/packages/omo-codex/plugin/hooks/post-compact-resetting-lsp-diagnostics-cache.json +1 -1
  363. package/packages/omo-codex/plugin/hooks/post-compact-resetting-project-rule-cache.json +1 -1
  364. package/packages/omo-codex/plugin/hooks/post-tool-use-checking-comments.json +1 -1
  365. package/packages/omo-codex/plugin/hooks/post-tool-use-checking-lsp-diagnostics.json +1 -1
  366. package/packages/omo-codex/plugin/hooks/post-tool-use-checking-thread-title-hygiene.json +1 -1
  367. package/packages/omo-codex/plugin/hooks/post-tool-use-matching-project-rules.json +1 -1
  368. package/packages/omo-codex/plugin/hooks/post-tool-use-recording-spawn-admission.json +1 -1
  369. package/packages/omo-codex/plugin/hooks/pre-tool-use-enforcing-unlimited-goal-budget.json +1 -1
  370. package/packages/omo-codex/plugin/hooks/pre-tool-use-guarding-ulw-loop-spawns.json +1 -1
  371. package/packages/omo-codex/plugin/hooks/pre-tool-use-recommending-git-bash-mcp.json +1 -1
  372. package/packages/omo-codex/plugin/hooks/session-start-checking-auto-update.json +1 -1
  373. package/packages/omo-codex/plugin/hooks/session-start-checking-bootstrap-provisioning.json +1 -1
  374. package/packages/omo-codex/plugin/hooks/session-start-loading-project-rules.json +1 -1
  375. package/packages/omo-codex/plugin/hooks/session-start-recording-session-telemetry.json +1 -1
  376. package/packages/omo-codex/plugin/hooks/stop-checking-ulw-execute-continuation.json +1 -1
  377. package/packages/omo-codex/plugin/hooks/stop-checking-ulw-loop-resume.json +1 -1
  378. package/packages/omo-codex/plugin/hooks/subagent-stop-verifying-lazycodex-executor-evidence.json +1 -1
  379. package/packages/omo-codex/plugin/hooks/user-prompt-submit-checking-ultrawork-trigger.json +1 -1
  380. package/packages/omo-codex/plugin/hooks/user-prompt-submit-checking-ulw-loop-steering.json +1 -1
  381. package/packages/omo-codex/plugin/hooks/user-prompt-submit-loading-project-rules.json +1 -1
  382. package/packages/omo-codex/plugin/package-lock.json +12 -12
  383. package/packages/omo-codex/plugin/package.json +1 -1
  384. package/packages/omo-codex/plugin/scripts/auto-update-plan.mjs +16 -1
  385. package/packages/omo-codex/plugin/skills/browser/runtime/omowright/index.js +24 -33
  386. package/packages/omo-codex/plugin/skills/browser/runtime/omowright/manifest.json +3 -3
  387. package/packages/omo-codex/plugin/skills/frontend/ATTRIBUTION.md +104 -1
  388. package/packages/omo-codex/plugin/skills/frontend/SKILL.md +7 -3
  389. package/packages/omo-codex/plugin/skills/frontend/references/design/design-system-architecture.md +3 -3
  390. package/packages/omo-codex/plugin/skills/frontend/references/perfection/craft-floor.md +59 -0
  391. package/packages/omo-codex/plugin/skills/frontend/references/perfection/detect.md +52 -0
  392. package/packages/omo-codex/plugin/skills/frontend/scripts/detect/cli.ts +70 -0
  393. package/packages/omo-codex/plugin/skills/frontend/scripts/detect/config.ts +53 -0
  394. package/packages/omo-codex/plugin/skills/frontend/scripts/detect/core/characters.ts +2 -0
  395. package/packages/omo-codex/plugin/skills/frontend/scripts/detect/core/color.ts +150 -0
  396. package/packages/omo-codex/plugin/skills/frontend/scripts/detect/core/page.ts +84 -0
  397. package/packages/omo-codex/plugin/skills/frontend/scripts/detect/core/shadow.ts +40 -0
  398. package/packages/omo-codex/plugin/skills/frontend/scripts/detect/core/source.ts +33 -0
  399. package/packages/omo-codex/plugin/skills/frontend/scripts/detect/detect.ts +77 -0
  400. package/packages/omo-codex/plugin/skills/frontend/scripts/detect/index.ts +23 -0
  401. package/packages/omo-codex/plugin/skills/frontend/scripts/detect/lint.ts +98 -0
  402. package/packages/omo-codex/plugin/skills/frontend/scripts/detect/render/probe-placement.ts +50 -0
  403. package/packages/omo-codex/plugin/skills/frontend/scripts/detect/render/renderer.ts +37 -0
  404. package/packages/omo-codex/plugin/skills/frontend/scripts/detect/render/webview.ts +71 -0
  405. package/packages/omo-codex/plugin/skills/frontend/scripts/detect/report.ts +29 -0
  406. package/packages/omo-codex/plugin/skills/frontend/scripts/detect/rule.ts +42 -0
  407. package/packages/omo-codex/plugin/skills/frontend/scripts/detect/rules/color/ai-color-palette.ts +83 -0
  408. package/packages/omo-codex/plugin/skills/frontend/scripts/detect/rules/color/cream-palette.ts +35 -0
  409. package/packages/omo-codex/plugin/skills/frontend/scripts/detect/rules/color/dark-glow.ts +44 -0
  410. package/packages/omo-codex/plugin/skills/frontend/scripts/detect/rules/color/design-system-color.ts +35 -0
  411. package/packages/omo-codex/plugin/skills/frontend/scripts/detect/rules/color/gradient-text.ts +59 -0
  412. package/packages/omo-codex/plugin/skills/frontend/scripts/detect/rules/color/gray-on-color.ts +38 -0
  413. package/packages/omo-codex/plugin/skills/frontend/scripts/detect/rules/color/index.ts +15 -0
  414. package/packages/omo-codex/plugin/skills/frontend/scripts/detect/rules/color/low-contrast.ts +57 -0
  415. package/packages/omo-codex/plugin/skills/frontend/scripts/detect/rules/color/radial-halo.ts +31 -0
  416. package/packages/omo-codex/plugin/skills/frontend/scripts/detect/rules/color/radial-spotlight-glow.ts +33 -0
  417. package/packages/omo-codex/plugin/skills/frontend/scripts/detect/rules/color/support/animation-opacity.ts +78 -0
  418. package/packages/omo-codex/plugin/skills/frontend/scripts/detect/rules/color/support/color-path.ts +15 -0
  419. package/packages/omo-codex/plugin/skills/frontend/scripts/detect/rules/color/support/contrast-pairs.ts +54 -0
  420. package/packages/omo-codex/plugin/skills/frontend/scripts/detect/rules/color/support/contrast-role.ts +76 -0
  421. package/packages/omo-codex/plugin/skills/frontend/scripts/detect/rules/color/support/glow-forms.ts +56 -0
  422. package/packages/omo-codex/plugin/skills/frontend/scripts/detect/rules/color/support/gradient-samples.ts +134 -0
  423. package/packages/omo-codex/plugin/skills/frontend/scripts/detect/rules/color/support/gradients.ts +91 -0
  424. package/packages/omo-codex/plugin/skills/frontend/scripts/detect/rules/color/support/mockup-roots.ts +63 -0
  425. package/packages/omo-codex/plugin/skills/frontend/scripts/detect/rules/color/support/page-ignore.ts +7 -0
  426. package/packages/omo-codex/plugin/skills/frontend/scripts/detect/rules/color/support/painted-text.ts +141 -0
  427. package/packages/omo-codex/plugin/skills/frontend/scripts/detect/rules/color/support/palette-roles.ts +58 -0
  428. package/packages/omo-codex/plugin/skills/frontend/scripts/detect/rules/color/support/placeholder-contrast.ts +25 -0
  429. package/packages/omo-codex/plugin/skills/frontend/scripts/detect/rules/color/support/stock-accent.ts +31 -0
  430. package/packages/omo-codex/plugin/skills/frontend/scripts/detect/rules/color/support/text-colors.ts +80 -0
  431. package/packages/omo-codex/plugin/skills/frontend/scripts/detect/rules/copy/aphoristic-cadence.ts +20 -0
  432. package/packages/omo-codex/plugin/skills/frontend/scripts/detect/rules/copy/broken-image.ts +17 -0
  433. package/packages/omo-codex/plugin/skills/frontend/scripts/detect/rules/copy/em-dash-overuse.ts +46 -0
  434. package/packages/omo-codex/plugin/skills/frontend/scripts/detect/rules/copy/index.ts +15 -0
  435. package/packages/omo-codex/plugin/skills/frontend/scripts/detect/rules/copy/marketing-buzzword.ts +33 -0
  436. package/packages/omo-codex/plugin/skills/frontend/scripts/detect/rules/copy/numbered-section-labels.ts +34 -0
  437. package/packages/omo-codex/plugin/skills/frontend/scripts/detect/rules/copy/repeated-container-text.ts +56 -0
  438. package/packages/omo-codex/plugin/skills/frontend/scripts/detect/rules/copy/script-error.ts +38 -0
  439. package/packages/omo-codex/plugin/skills/frontend/scripts/detect/rules/copy/skipped-heading.ts +81 -0
  440. package/packages/omo-codex/plugin/skills/frontend/scripts/detect/rules/copy/support/numbered-label.ts +94 -0
  441. package/packages/omo-codex/plugin/skills/frontend/scripts/detect/rules/copy/support/page-text.ts +37 -0
  442. package/packages/omo-codex/plugin/skills/frontend/scripts/detect/rules/copy/theater-slop-phrase.ts +21 -0
  443. package/packages/omo-codex/plugin/skills/frontend/scripts/detect/rules/decoration/blinking-cursor.ts +48 -0
  444. package/packages/omo-codex/plugin/skills/frontend/scripts/detect/rules/decoration/border-accent-on-rounded.ts +14 -0
  445. package/packages/omo-codex/plugin/skills/frontend/scripts/detect/rules/decoration/bounce-easing.ts +83 -0
  446. package/packages/omo-codex/plugin/skills/frontend/scripts/detect/rules/decoration/buried-raster.ts +72 -0
  447. package/packages/omo-codex/plugin/skills/frontend/scripts/detect/rules/decoration/codex-grid-background.ts +34 -0
  448. package/packages/omo-codex/plugin/skills/frontend/scripts/detect/rules/decoration/design-system-radius.ts +31 -0
  449. package/packages/omo-codex/plugin/skills/frontend/scripts/detect/rules/decoration/gpt-thin-border-wide-shadow.ts +66 -0
  450. package/packages/omo-codex/plugin/skills/frontend/scripts/detect/rules/decoration/hard-offset-shadow.ts +31 -0
  451. package/packages/omo-codex/plugin/skills/frontend/scripts/detect/rules/decoration/hero-eyebrow-chip.ts +19 -0
  452. package/packages/omo-codex/plugin/skills/frontend/scripts/detect/rules/decoration/icon-tile-stack.ts +92 -0
  453. package/packages/omo-codex/plugin/skills/frontend/scripts/detect/rules/decoration/index.ts +38 -0
  454. package/packages/omo-codex/plugin/skills/frontend/scripts/detect/rules/decoration/kicker-above-heading.ts +69 -0
  455. package/packages/omo-codex/plugin/skills/frontend/scripts/detect/rules/decoration/marquee.ts +51 -0
  456. package/packages/omo-codex/plugin/skills/frontend/scripts/detect/rules/decoration/organic-clip-path.ts +41 -0
  457. package/packages/omo-codex/plugin/skills/frontend/scripts/detect/rules/decoration/pulsing-dot.ts +72 -0
  458. package/packages/omo-codex/plugin/skills/frontend/scripts/detect/rules/decoration/repeating-stripes-gradient.ts +25 -0
  459. package/packages/omo-codex/plugin/skills/frontend/scripts/detect/rules/decoration/shape-assembled-illustration.ts +58 -0
  460. package/packages/omo-codex/plugin/skills/frontend/scripts/detect/rules/decoration/side-tab.ts +17 -0
  461. package/packages/omo-codex/plugin/skills/frontend/scripts/detect/rules/decoration/support/appearance.ts +110 -0
  462. package/packages/omo-codex/plugin/skills/frontend/scripts/detect/rules/decoration/support/assert-cases.ts +25 -0
  463. package/packages/omo-codex/plugin/skills/frontend/scripts/detect/rules/decoration/support/borders.ts +150 -0
  464. package/packages/omo-codex/plugin/skills/frontend/scripts/detect/rules/decoration/support/clip-geometry.ts +151 -0
  465. package/packages/omo-codex/plugin/skills/frontend/scripts/detect/rules/decoration/support/css-candidates.ts +66 -0
  466. package/packages/omo-codex/plugin/skills/frontend/scripts/detect/rules/decoration/support/curve-samples.ts +55 -0
  467. package/packages/omo-codex/plugin/skills/frontend/scripts/detect/rules/decoration/support/gradient-pattern.ts +40 -0
  468. package/packages/omo-codex/plugin/skills/frontend/scripts/detect/rules/decoration/support/keyframes.ts +134 -0
  469. package/packages/omo-codex/plugin/skills/frontend/scripts/detect/rules/decoration/support/labels.ts +85 -0
  470. package/packages/omo-codex/plugin/skills/frontend/scripts/detect/rules/decoration/support/raster-state.ts +51 -0
  471. package/packages/omo-codex/plugin/skills/frontend/scripts/detect/rules/index.ts +16 -0
  472. package/packages/omo-codex/plugin/skills/frontend/scripts/detect/rules/layout/body-text-viewport-edge.ts +62 -0
  473. package/packages/omo-codex/plugin/skills/frontend/scripts/detect/rules/layout/clipped-overflow-container.ts +15 -0
  474. package/packages/omo-codex/plugin/skills/frontend/scripts/detect/rules/layout/content-hidden-at-rest.ts +63 -0
  475. package/packages/omo-codex/plugin/skills/frontend/scripts/detect/rules/layout/cramped-padding.ts +97 -0
  476. package/packages/omo-codex/plugin/skills/frontend/scripts/detect/rules/layout/edge-flush-cards.ts +47 -0
  477. package/packages/omo-codex/plugin/skills/frontend/scripts/detect/rules/layout/first-viewport-column-overflow.ts +43 -0
  478. package/packages/omo-codex/plugin/skills/frontend/scripts/detect/rules/layout/heading-rhythm.ts +30 -0
  479. package/packages/omo-codex/plugin/skills/frontend/scripts/detect/rules/layout/index.ts +21 -0
  480. package/packages/omo-codex/plugin/skills/frontend/scripts/detect/rules/layout/monotonous-spacing.ts +32 -0
  481. package/packages/omo-codex/plugin/skills/frontend/scripts/detect/rules/layout/nested-cards.ts +38 -0
  482. package/packages/omo-codex/plugin/skills/frontend/scripts/detect/rules/layout/straggler.ts +28 -0
  483. package/packages/omo-codex/plugin/skills/frontend/scripts/detect/rules/layout/support/cards.ts +114 -0
  484. package/packages/omo-codex/plugin/skills/frontend/scripts/detect/rules/layout/support/clipping.ts +71 -0
  485. package/packages/omo-codex/plugin/skills/frontend/scripts/detect/rules/layout/support/declared-mockups.ts +46 -0
  486. package/packages/omo-codex/plugin/skills/frontend/scripts/detect/rules/layout/support/geometry.ts +73 -0
  487. package/packages/omo-codex/plugin/skills/frontend/scripts/detect/rules/layout/support/hidden-interface.ts +35 -0
  488. package/packages/omo-codex/plugin/skills/frontend/scripts/detect/rules/layout/support/layout-cases.ts +23 -0
  489. package/packages/omo-codex/plugin/skills/frontend/scripts/detect/rules/layout/support/line-breaks.ts +32 -0
  490. package/packages/omo-codex/plugin/skills/frontend/scripts/detect/rules/layout/support/motion.ts +77 -0
  491. package/packages/omo-codex/plugin/skills/frontend/scripts/detect/rules/layout/support/padding.ts +93 -0
  492. package/packages/omo-codex/plugin/skills/frontend/scripts/detect/rules/layout/support/rhythm.ts +161 -0
  493. package/packages/omo-codex/plugin/skills/frontend/scripts/detect/rules/layout/text-occlusion.ts +84 -0
  494. package/packages/omo-codex/plugin/skills/frontend/scripts/detect/rules/layout/text-overflow.ts +72 -0
  495. package/packages/omo-codex/plugin/skills/frontend/scripts/detect/rules/layout/unbalanced-heading.ts +22 -0
  496. package/packages/omo-codex/plugin/skills/frontend/scripts/detect/rules/layout/viewport-reflow.ts +33 -0
  497. package/packages/omo-codex/plugin/skills/frontend/scripts/detect/rules/source/ai-color-palette.ts +11 -0
  498. package/packages/omo-codex/plugin/skills/frontend/scripts/detect/rules/source/aphoristic-cadence.ts +14 -0
  499. package/packages/omo-codex/plugin/skills/frontend/scripts/detect/rules/source/border-accent-on-rounded.ts +20 -0
  500. package/packages/omo-codex/plugin/skills/frontend/scripts/detect/rules/source/bounce-easing.ts +21 -0
  501. package/packages/omo-codex/plugin/skills/frontend/scripts/detect/rules/source/broken-image.ts +16 -0
  502. package/packages/omo-codex/plugin/skills/frontend/scripts/detect/rules/source/codex-grid-background.ts +18 -0
  503. package/packages/omo-codex/plugin/skills/frontend/scripts/detect/rules/source/dark-glow.ts +21 -0
  504. package/packages/omo-codex/plugin/skills/frontend/scripts/detect/rules/source/em-dash-overuse.ts +15 -0
  505. package/packages/omo-codex/plugin/skills/frontend/scripts/detect/rules/source/gradient-text.ts +11 -0
  506. package/packages/omo-codex/plugin/skills/frontend/scripts/detect/rules/source/gray-on-color.ts +13 -0
  507. package/packages/omo-codex/plugin/skills/frontend/scripts/detect/rules/source/index.ts +19 -0
  508. package/packages/omo-codex/plugin/skills/frontend/scripts/detect/rules/source/marketing-buzzword.ts +17 -0
  509. package/packages/omo-codex/plugin/skills/frontend/scripts/detect/rules/source/marquee.ts +12 -0
  510. package/packages/omo-codex/plugin/skills/frontend/scripts/detect/rules/source/monotonous-spacing.ts +22 -0
  511. package/packages/omo-codex/plugin/skills/frontend/scripts/detect/rules/source/overused-font.ts +16 -0
  512. package/packages/omo-codex/plugin/skills/frontend/scripts/detect/rules/source/radial-halo.ts +14 -0
  513. package/packages/omo-codex/plugin/skills/frontend/scripts/detect/rules/source/side-tab.ts +58 -0
  514. package/packages/omo-codex/plugin/skills/frontend/scripts/detect/rules/source/support/accent-scans.ts +78 -0
  515. package/packages/omo-codex/plugin/skills/frontend/scripts/detect/rules/source/support/check-source.ts +6 -0
  516. package/packages/omo-codex/plugin/skills/frontend/scripts/detect/rules/source/support/corners.ts +105 -0
  517. package/packages/omo-codex/plugin/skills/frontend/scripts/detect/rules/source/support/css-effects.ts +81 -0
  518. package/packages/omo-codex/plugin/skills/frontend/scripts/detect/rules/source/support/css-scopes.ts +131 -0
  519. package/packages/omo-codex/plugin/skills/frontend/scripts/detect/rules/source/support/image-tags.ts +113 -0
  520. package/packages/omo-codex/plugin/skills/frontend/scripts/detect/rules/source/support/js-punctuation.ts +34 -0
  521. package/packages/omo-codex/plugin/skills/frontend/scripts/detect/rules/source/support/markup-scope.ts +44 -0
  522. package/packages/omo-codex/plugin/skills/frontend/scripts/detect/rules/source/support/source-color.ts +42 -0
  523. package/packages/omo-codex/plugin/skills/frontend/scripts/detect/rules/source/support/source-shadow.ts +15 -0
  524. package/packages/omo-codex/plugin/skills/frontend/scripts/detect/rules/source/support/source-text.ts +110 -0
  525. package/packages/omo-codex/plugin/skills/frontend/scripts/detect/rules/typography/all-caps-body.ts +15 -0
  526. package/packages/omo-codex/plugin/skills/frontend/scripts/detect/rules/typography/design-system-font-size.ts +23 -0
  527. package/packages/omo-codex/plugin/skills/frontend/scripts/detect/rules/typography/design-system-font.ts +24 -0
  528. package/packages/omo-codex/plugin/skills/frontend/scripts/detect/rules/typography/extreme-negative-tracking.ts +18 -0
  529. package/packages/omo-codex/plugin/skills/frontend/scripts/detect/rules/typography/flat-type-hierarchy.ts +26 -0
  530. package/packages/omo-codex/plugin/skills/frontend/scripts/detect/rules/typography/index.ts +21 -0
  531. package/packages/omo-codex/plugin/skills/frontend/scripts/detect/rules/typography/italic-serif-display.ts +24 -0
  532. package/packages/omo-codex/plugin/skills/frontend/scripts/detect/rules/typography/justified-text.ts +32 -0
  533. package/packages/omo-codex/plugin/skills/frontend/scripts/detect/rules/typography/line-length.ts +28 -0
  534. package/packages/omo-codex/plugin/skills/frontend/scripts/detect/rules/typography/oversized-h1.ts +20 -0
  535. package/packages/omo-codex/plugin/skills/frontend/scripts/detect/rules/typography/overused-font.ts +45 -0
  536. package/packages/omo-codex/plugin/skills/frontend/scripts/detect/rules/typography/support/drawn-enlargement.ts +48 -0
  537. package/packages/omo-codex/plugin/skills/frontend/scripts/detect/rules/typography/support/fading-text.ts +48 -0
  538. package/packages/omo-codex/plugin/skills/frontend/scripts/detect/rules/typography/support/flex-runs.ts +16 -0
  539. package/packages/omo-codex/plugin/skills/frontend/scripts/detect/rules/typography/support/font-family.ts +28 -0
  540. package/packages/omo-codex/plugin/skills/frontend/scripts/detect/rules/typography/support/painted-text.ts +81 -0
  541. package/packages/omo-codex/plugin/skills/frontend/scripts/detect/rules/typography/support/svg-size.ts +57 -0
  542. package/packages/omo-codex/plugin/skills/frontend/scripts/detect/rules/typography/support/text-context.ts +112 -0
  543. package/packages/omo-codex/plugin/skills/frontend/scripts/detect/rules/typography/support/text-lines.ts +43 -0
  544. package/packages/omo-codex/plugin/skills/frontend/scripts/detect/rules/typography/support/type-hierarchy.ts +48 -0
  545. package/packages/omo-codex/plugin/skills/frontend/scripts/detect/rules/typography/tight-leading.ts +47 -0
  546. package/packages/omo-codex/plugin/skills/frontend/scripts/detect/rules/typography/tiny-text.ts +23 -0
  547. package/packages/omo-codex/plugin/skills/frontend/scripts/detect/rules/typography/undersized-ui-text.ts +28 -0
  548. package/packages/omo-codex/plugin/skills/frontend/scripts/detect/rules/typography/wide-tracking.ts +26 -0
  549. package/packages/omo-codex/plugin/skills/frontend/scripts/detect/snapshot/collect.ts +158 -0
  550. package/packages/omo-codex/plugin/skills/frontend/scripts/detect/snapshot/style-props.ts +25 -0
  551. package/packages/omo-codex/plugin/skills/frontend/scripts/detect/testing/build-snapshot.ts +78 -0
  552. package/packages/omo-codex/plugin/skills/frontend/scripts/detect/tsconfig.json +19 -0
  553. package/packages/omo-codex/plugin/skills/frontend/scripts/detect/types.ts +124 -0
  554. package/packages/omo-codex/plugin/skills/programming/SKILL.md +17 -74
  555. package/packages/omo-codex/plugin/skills/programming/references/go/README.md +1 -1
  556. package/packages/omo-codex/plugin/skills/programming/references/go/bootstrap.md +2 -2
  557. package/packages/omo-codex/plugin/skills/programming/references/python/README.md +4 -4
  558. package/packages/omo-codex/plugin/skills/programming/references/python/one-liners.md +5 -5
  559. package/packages/omo-codex/plugin/skills/programming/references/testing/README.md +82 -0
  560. package/packages/omo-codex/plugin/skills/programming/references/testing/junk-classes.md +56 -0
  561. package/packages/omo-codex/plugin/skills/programming/references/typescript/README.md +1 -2
  562. package/packages/omo-codex/plugin/skills/programming/scripts/go/new-project.ts +197 -0
  563. package/packages/omo-codex/plugin/skills/programming/scripts/python/new-project.ts +231 -0
  564. package/packages/omo-codex/plugin/skills/programming/scripts/python/new-script.ts +134 -0
  565. package/packages/omo-codex/plugin/skills/programming/scripts/rust/new-project.ts +215 -0
  566. package/packages/omo-codex/plugin/skills/programming/scripts/shared/run-tool.ts +19 -0
  567. package/packages/omo-codex/plugin/skills/programming/scripts/typescript/check-test-junk-rules.ts +140 -0
  568. package/packages/omo-codex/plugin/skills/programming/scripts/typescript/check-test-junk.ts +148 -0
  569. package/packages/omo-codex/plugin/skills/programming/scripts/typescript/mutation-proof.ts +179 -0
  570. package/packages/omo-codex/plugin/skills/remove-ai-slops/SKILL.md +32 -20
  571. package/packages/omo-codex/plugin/skills/ulw-research/scripts/source-commands.mjs +3 -1
  572. package/packages/omo-codex/plugin/skills/visual-qa/SKILL.md +12 -1
  573. package/packages/omo-codex/plugin/test/auto-update.test.mjs +62 -0
  574. package/packages/omo-codex/plugin/test/payload-equivalence.test.mjs +12 -2
  575. package/packages/omo-codex/scripts/install-dist/install-local.mjs +79 -10
  576. package/packages/shared-skills/skills/browser/runtime/omowright/index.js +24 -33
  577. package/packages/shared-skills/skills/browser/runtime/omowright/manifest.json +3 -3
  578. package/packages/shared-skills/skills/frontend/ATTRIBUTION.md +104 -1
  579. package/packages/shared-skills/skills/frontend/SKILL.md +7 -3
  580. package/packages/shared-skills/skills/frontend/references/design/design-system-architecture.md +3 -3
  581. package/packages/shared-skills/skills/frontend/references/perfection/craft-floor.md +59 -0
  582. package/packages/shared-skills/skills/frontend/references/perfection/detect.md +52 -0
  583. package/packages/shared-skills/skills/frontend/scripts/detect/cli.ts +70 -0
  584. package/packages/shared-skills/skills/frontend/scripts/detect/config.test.ts +26 -0
  585. package/packages/shared-skills/skills/frontend/scripts/detect/config.ts +53 -0
  586. package/packages/shared-skills/skills/frontend/scripts/detect/core/characters.ts +2 -0
  587. package/packages/shared-skills/skills/frontend/scripts/detect/core/color.test.ts +29 -0
  588. package/packages/shared-skills/skills/frontend/scripts/detect/core/color.ts +150 -0
  589. package/packages/shared-skills/skills/frontend/scripts/detect/core/page.ts +84 -0
  590. package/packages/shared-skills/skills/frontend/scripts/detect/core/shadow.ts +40 -0
  591. package/packages/shared-skills/skills/frontend/scripts/detect/core/source.ts +33 -0
  592. package/packages/shared-skills/skills/frontend/scripts/detect/detect.ts +77 -0
  593. package/packages/shared-skills/skills/frontend/scripts/detect/index.ts +23 -0
  594. package/packages/shared-skills/skills/frontend/scripts/detect/lint.test.ts +27 -0
  595. package/packages/shared-skills/skills/frontend/scripts/detect/lint.ts +98 -0
  596. package/packages/shared-skills/skills/frontend/scripts/detect/render/probe-placement.test.ts +19 -0
  597. package/packages/shared-skills/skills/frontend/scripts/detect/render/probe-placement.ts +50 -0
  598. package/packages/shared-skills/skills/frontend/scripts/detect/render/renderer.ts +37 -0
  599. package/packages/shared-skills/skills/frontend/scripts/detect/render/webview.ts +71 -0
  600. package/packages/shared-skills/skills/frontend/scripts/detect/report.ts +29 -0
  601. package/packages/shared-skills/skills/frontend/scripts/detect/rule.ts +42 -0
  602. package/packages/shared-skills/skills/frontend/scripts/detect/rules/color/ai-color-palette.test.ts +74 -0
  603. package/packages/shared-skills/skills/frontend/scripts/detect/rules/color/ai-color-palette.ts +83 -0
  604. package/packages/shared-skills/skills/frontend/scripts/detect/rules/color/cream-palette.test.ts +24 -0
  605. package/packages/shared-skills/skills/frontend/scripts/detect/rules/color/cream-palette.ts +35 -0
  606. package/packages/shared-skills/skills/frontend/scripts/detect/rules/color/dark-glow.test.ts +47 -0
  607. package/packages/shared-skills/skills/frontend/scripts/detect/rules/color/dark-glow.ts +44 -0
  608. package/packages/shared-skills/skills/frontend/scripts/detect/rules/color/design-system-color.test.ts +26 -0
  609. package/packages/shared-skills/skills/frontend/scripts/detect/rules/color/design-system-color.ts +35 -0
  610. package/packages/shared-skills/skills/frontend/scripts/detect/rules/color/gradient-text.test.ts +24 -0
  611. package/packages/shared-skills/skills/frontend/scripts/detect/rules/color/gradient-text.ts +59 -0
  612. package/packages/shared-skills/skills/frontend/scripts/detect/rules/color/gray-on-color.test.ts +39 -0
  613. package/packages/shared-skills/skills/frontend/scripts/detect/rules/color/gray-on-color.ts +38 -0
  614. package/packages/shared-skills/skills/frontend/scripts/detect/rules/color/index.ts +15 -0
  615. package/packages/shared-skills/skills/frontend/scripts/detect/rules/color/low-contrast.test.ts +209 -0
  616. package/packages/shared-skills/skills/frontend/scripts/detect/rules/color/low-contrast.ts +57 -0
  617. package/packages/shared-skills/skills/frontend/scripts/detect/rules/color/placeholder-contrast.test.ts +62 -0
  618. package/packages/shared-skills/skills/frontend/scripts/detect/rules/color/radial-halo.test.ts +40 -0
  619. package/packages/shared-skills/skills/frontend/scripts/detect/rules/color/radial-halo.ts +31 -0
  620. package/packages/shared-skills/skills/frontend/scripts/detect/rules/color/radial-spotlight-glow.test.ts +27 -0
  621. package/packages/shared-skills/skills/frontend/scripts/detect/rules/color/radial-spotlight-glow.ts +33 -0
  622. package/packages/shared-skills/skills/frontend/scripts/detect/rules/color/support/animation-opacity.ts +78 -0
  623. package/packages/shared-skills/skills/frontend/scripts/detect/rules/color/support/color-path.ts +15 -0
  624. package/packages/shared-skills/skills/frontend/scripts/detect/rules/color/support/contrast-pairs.ts +54 -0
  625. package/packages/shared-skills/skills/frontend/scripts/detect/rules/color/support/contrast-role.ts +76 -0
  626. package/packages/shared-skills/skills/frontend/scripts/detect/rules/color/support/glow-forms.ts +56 -0
  627. package/packages/shared-skills/skills/frontend/scripts/detect/rules/color/support/gradient-samples.ts +134 -0
  628. package/packages/shared-skills/skills/frontend/scripts/detect/rules/color/support/gradients.ts +91 -0
  629. package/packages/shared-skills/skills/frontend/scripts/detect/rules/color/support/mockup-roots.ts +63 -0
  630. package/packages/shared-skills/skills/frontend/scripts/detect/rules/color/support/page-ignore.ts +7 -0
  631. package/packages/shared-skills/skills/frontend/scripts/detect/rules/color/support/painted-text.ts +141 -0
  632. package/packages/shared-skills/skills/frontend/scripts/detect/rules/color/support/palette-roles.ts +58 -0
  633. package/packages/shared-skills/skills/frontend/scripts/detect/rules/color/support/placeholder-contrast.ts +25 -0
  634. package/packages/shared-skills/skills/frontend/scripts/detect/rules/color/support/stock-accent.ts +31 -0
  635. package/packages/shared-skills/skills/frontend/scripts/detect/rules/color/support/text-colors.ts +80 -0
  636. package/packages/shared-skills/skills/frontend/scripts/detect/rules/copy/aphoristic-cadence.test.ts +18 -0
  637. package/packages/shared-skills/skills/frontend/scripts/detect/rules/copy/aphoristic-cadence.ts +20 -0
  638. package/packages/shared-skills/skills/frontend/scripts/detect/rules/copy/broken-image.test.ts +25 -0
  639. package/packages/shared-skills/skills/frontend/scripts/detect/rules/copy/broken-image.ts +17 -0
  640. package/packages/shared-skills/skills/frontend/scripts/detect/rules/copy/em-dash-overuse.test.ts +39 -0
  641. package/packages/shared-skills/skills/frontend/scripts/detect/rules/copy/em-dash-overuse.ts +46 -0
  642. package/packages/shared-skills/skills/frontend/scripts/detect/rules/copy/index.ts +15 -0
  643. package/packages/shared-skills/skills/frontend/scripts/detect/rules/copy/marketing-buzzword.test.ts +18 -0
  644. package/packages/shared-skills/skills/frontend/scripts/detect/rules/copy/marketing-buzzword.ts +33 -0
  645. package/packages/shared-skills/skills/frontend/scripts/detect/rules/copy/numbered-section-labels.test.ts +58 -0
  646. package/packages/shared-skills/skills/frontend/scripts/detect/rules/copy/numbered-section-labels.ts +34 -0
  647. package/packages/shared-skills/skills/frontend/scripts/detect/rules/copy/repeated-container-text.test.ts +43 -0
  648. package/packages/shared-skills/skills/frontend/scripts/detect/rules/copy/repeated-container-text.ts +56 -0
  649. package/packages/shared-skills/skills/frontend/scripts/detect/rules/copy/script-error.test.ts +48 -0
  650. package/packages/shared-skills/skills/frontend/scripts/detect/rules/copy/script-error.ts +38 -0
  651. package/packages/shared-skills/skills/frontend/scripts/detect/rules/copy/skipped-heading.test.ts +49 -0
  652. package/packages/shared-skills/skills/frontend/scripts/detect/rules/copy/skipped-heading.ts +81 -0
  653. package/packages/shared-skills/skills/frontend/scripts/detect/rules/copy/support/numbered-label.ts +94 -0
  654. package/packages/shared-skills/skills/frontend/scripts/detect/rules/copy/support/page-text.ts +37 -0
  655. package/packages/shared-skills/skills/frontend/scripts/detect/rules/copy/theater-slop-phrase.test.ts +17 -0
  656. package/packages/shared-skills/skills/frontend/scripts/detect/rules/copy/theater-slop-phrase.ts +21 -0
  657. package/packages/shared-skills/skills/frontend/scripts/detect/rules/decoration/blinking-cursor.test.ts +43 -0
  658. package/packages/shared-skills/skills/frontend/scripts/detect/rules/decoration/blinking-cursor.ts +48 -0
  659. package/packages/shared-skills/skills/frontend/scripts/detect/rules/decoration/border-accent-on-rounded.test.ts +33 -0
  660. package/packages/shared-skills/skills/frontend/scripts/detect/rules/decoration/border-accent-on-rounded.ts +14 -0
  661. package/packages/shared-skills/skills/frontend/scripts/detect/rules/decoration/bounce-easing.test.ts +72 -0
  662. package/packages/shared-skills/skills/frontend/scripts/detect/rules/decoration/bounce-easing.ts +83 -0
  663. package/packages/shared-skills/skills/frontend/scripts/detect/rules/decoration/buried-raster.test.ts +95 -0
  664. package/packages/shared-skills/skills/frontend/scripts/detect/rules/decoration/buried-raster.ts +72 -0
  665. package/packages/shared-skills/skills/frontend/scripts/detect/rules/decoration/codex-grid-background.test.ts +28 -0
  666. package/packages/shared-skills/skills/frontend/scripts/detect/rules/decoration/codex-grid-background.ts +34 -0
  667. package/packages/shared-skills/skills/frontend/scripts/detect/rules/decoration/design-system-radius.test.ts +37 -0
  668. package/packages/shared-skills/skills/frontend/scripts/detect/rules/decoration/design-system-radius.ts +31 -0
  669. package/packages/shared-skills/skills/frontend/scripts/detect/rules/decoration/gpt-thin-border-wide-shadow.test.ts +59 -0
  670. package/packages/shared-skills/skills/frontend/scripts/detect/rules/decoration/gpt-thin-border-wide-shadow.ts +66 -0
  671. package/packages/shared-skills/skills/frontend/scripts/detect/rules/decoration/hard-offset-shadow.test.ts +45 -0
  672. package/packages/shared-skills/skills/frontend/scripts/detect/rules/decoration/hard-offset-shadow.ts +31 -0
  673. package/packages/shared-skills/skills/frontend/scripts/detect/rules/decoration/hero-eyebrow-chip.test.ts +76 -0
  674. package/packages/shared-skills/skills/frontend/scripts/detect/rules/decoration/hero-eyebrow-chip.ts +19 -0
  675. package/packages/shared-skills/skills/frontend/scripts/detect/rules/decoration/icon-tile-stack.test.ts +67 -0
  676. package/packages/shared-skills/skills/frontend/scripts/detect/rules/decoration/icon-tile-stack.ts +92 -0
  677. package/packages/shared-skills/skills/frontend/scripts/detect/rules/decoration/index.ts +38 -0
  678. package/packages/shared-skills/skills/frontend/scripts/detect/rules/decoration/kicker-above-heading.test.ts +126 -0
  679. package/packages/shared-skills/skills/frontend/scripts/detect/rules/decoration/kicker-above-heading.ts +69 -0
  680. package/packages/shared-skills/skills/frontend/scripts/detect/rules/decoration/marquee.test.ts +63 -0
  681. package/packages/shared-skills/skills/frontend/scripts/detect/rules/decoration/marquee.ts +51 -0
  682. package/packages/shared-skills/skills/frontend/scripts/detect/rules/decoration/organic-clip-path.test.ts +67 -0
  683. package/packages/shared-skills/skills/frontend/scripts/detect/rules/decoration/organic-clip-path.ts +41 -0
  684. package/packages/shared-skills/skills/frontend/scripts/detect/rules/decoration/pulsing-dot.test.ts +58 -0
  685. package/packages/shared-skills/skills/frontend/scripts/detect/rules/decoration/pulsing-dot.ts +72 -0
  686. package/packages/shared-skills/skills/frontend/scripts/detect/rules/decoration/repeating-stripes-gradient.test.ts +26 -0
  687. package/packages/shared-skills/skills/frontend/scripts/detect/rules/decoration/repeating-stripes-gradient.ts +25 -0
  688. package/packages/shared-skills/skills/frontend/scripts/detect/rules/decoration/shape-assembled-illustration.test.ts +59 -0
  689. package/packages/shared-skills/skills/frontend/scripts/detect/rules/decoration/shape-assembled-illustration.ts +58 -0
  690. package/packages/shared-skills/skills/frontend/scripts/detect/rules/decoration/side-tab.test.ts +91 -0
  691. package/packages/shared-skills/skills/frontend/scripts/detect/rules/decoration/side-tab.ts +17 -0
  692. package/packages/shared-skills/skills/frontend/scripts/detect/rules/decoration/support/appearance.ts +110 -0
  693. package/packages/shared-skills/skills/frontend/scripts/detect/rules/decoration/support/assert-cases.ts +25 -0
  694. package/packages/shared-skills/skills/frontend/scripts/detect/rules/decoration/support/borders.ts +150 -0
  695. package/packages/shared-skills/skills/frontend/scripts/detect/rules/decoration/support/clip-geometry.ts +151 -0
  696. package/packages/shared-skills/skills/frontend/scripts/detect/rules/decoration/support/css-candidates.ts +66 -0
  697. package/packages/shared-skills/skills/frontend/scripts/detect/rules/decoration/support/curve-samples.ts +55 -0
  698. package/packages/shared-skills/skills/frontend/scripts/detect/rules/decoration/support/gradient-pattern.ts +40 -0
  699. package/packages/shared-skills/skills/frontend/scripts/detect/rules/decoration/support/keyframes.ts +134 -0
  700. package/packages/shared-skills/skills/frontend/scripts/detect/rules/decoration/support/labels.ts +85 -0
  701. package/packages/shared-skills/skills/frontend/scripts/detect/rules/decoration/support/raster-state.ts +51 -0
  702. package/packages/shared-skills/skills/frontend/scripts/detect/rules/index.ts +16 -0
  703. package/packages/shared-skills/skills/frontend/scripts/detect/rules/layout/body-text-viewport-edge.test.ts +64 -0
  704. package/packages/shared-skills/skills/frontend/scripts/detect/rules/layout/body-text-viewport-edge.ts +62 -0
  705. package/packages/shared-skills/skills/frontend/scripts/detect/rules/layout/clipped-overflow-container.test.ts +40 -0
  706. package/packages/shared-skills/skills/frontend/scripts/detect/rules/layout/clipped-overflow-container.ts +15 -0
  707. package/packages/shared-skills/skills/frontend/scripts/detect/rules/layout/content-hidden-at-rest.test.ts +62 -0
  708. package/packages/shared-skills/skills/frontend/scripts/detect/rules/layout/content-hidden-at-rest.ts +63 -0
  709. package/packages/shared-skills/skills/frontend/scripts/detect/rules/layout/cramped-padding.test.ts +61 -0
  710. package/packages/shared-skills/skills/frontend/scripts/detect/rules/layout/cramped-padding.ts +97 -0
  711. package/packages/shared-skills/skills/frontend/scripts/detect/rules/layout/edge-flush-cards.test.ts +43 -0
  712. package/packages/shared-skills/skills/frontend/scripts/detect/rules/layout/edge-flush-cards.ts +47 -0
  713. package/packages/shared-skills/skills/frontend/scripts/detect/rules/layout/first-viewport-column-overflow.test.ts +28 -0
  714. package/packages/shared-skills/skills/frontend/scripts/detect/rules/layout/first-viewport-column-overflow.ts +43 -0
  715. package/packages/shared-skills/skills/frontend/scripts/detect/rules/layout/heading-rhythm.test.ts +67 -0
  716. package/packages/shared-skills/skills/frontend/scripts/detect/rules/layout/heading-rhythm.ts +30 -0
  717. package/packages/shared-skills/skills/frontend/scripts/detect/rules/layout/index.ts +21 -0
  718. package/packages/shared-skills/skills/frontend/scripts/detect/rules/layout/monotonous-spacing.test.ts +19 -0
  719. package/packages/shared-skills/skills/frontend/scripts/detect/rules/layout/monotonous-spacing.ts +32 -0
  720. package/packages/shared-skills/skills/frontend/scripts/detect/rules/layout/nested-cards.test.ts +60 -0
  721. package/packages/shared-skills/skills/frontend/scripts/detect/rules/layout/nested-cards.ts +38 -0
  722. package/packages/shared-skills/skills/frontend/scripts/detect/rules/layout/straggler.test.ts +33 -0
  723. package/packages/shared-skills/skills/frontend/scripts/detect/rules/layout/straggler.ts +28 -0
  724. package/packages/shared-skills/skills/frontend/scripts/detect/rules/layout/support/cards.ts +114 -0
  725. package/packages/shared-skills/skills/frontend/scripts/detect/rules/layout/support/clipping.ts +71 -0
  726. package/packages/shared-skills/skills/frontend/scripts/detect/rules/layout/support/declared-mockups.ts +46 -0
  727. package/packages/shared-skills/skills/frontend/scripts/detect/rules/layout/support/geometry.ts +73 -0
  728. package/packages/shared-skills/skills/frontend/scripts/detect/rules/layout/support/hidden-interface.ts +35 -0
  729. package/packages/shared-skills/skills/frontend/scripts/detect/rules/layout/support/layout-cases.ts +23 -0
  730. package/packages/shared-skills/skills/frontend/scripts/detect/rules/layout/support/line-breaks.ts +32 -0
  731. package/packages/shared-skills/skills/frontend/scripts/detect/rules/layout/support/motion.ts +77 -0
  732. package/packages/shared-skills/skills/frontend/scripts/detect/rules/layout/support/padding.ts +93 -0
  733. package/packages/shared-skills/skills/frontend/scripts/detect/rules/layout/support/rhythm.ts +161 -0
  734. package/packages/shared-skills/skills/frontend/scripts/detect/rules/layout/text-occlusion.test.ts +37 -0
  735. package/packages/shared-skills/skills/frontend/scripts/detect/rules/layout/text-occlusion.ts +84 -0
  736. package/packages/shared-skills/skills/frontend/scripts/detect/rules/layout/text-overflow.test.ts +83 -0
  737. package/packages/shared-skills/skills/frontend/scripts/detect/rules/layout/text-overflow.ts +72 -0
  738. package/packages/shared-skills/skills/frontend/scripts/detect/rules/layout/unbalanced-heading.test.ts +22 -0
  739. package/packages/shared-skills/skills/frontend/scripts/detect/rules/layout/unbalanced-heading.ts +22 -0
  740. package/packages/shared-skills/skills/frontend/scripts/detect/rules/layout/viewport-reflow.test.ts +34 -0
  741. package/packages/shared-skills/skills/frontend/scripts/detect/rules/layout/viewport-reflow.ts +33 -0
  742. package/packages/shared-skills/skills/frontend/scripts/detect/rules/source/ai-color-palette.test.ts +13 -0
  743. package/packages/shared-skills/skills/frontend/scripts/detect/rules/source/ai-color-palette.ts +11 -0
  744. package/packages/shared-skills/skills/frontend/scripts/detect/rules/source/aphoristic-cadence.test.ts +12 -0
  745. package/packages/shared-skills/skills/frontend/scripts/detect/rules/source/aphoristic-cadence.ts +14 -0
  746. package/packages/shared-skills/skills/frontend/scripts/detect/rules/source/border-accent-on-rounded.test.ts +14 -0
  747. package/packages/shared-skills/skills/frontend/scripts/detect/rules/source/border-accent-on-rounded.ts +20 -0
  748. package/packages/shared-skills/skills/frontend/scripts/detect/rules/source/bounce-easing.test.ts +19 -0
  749. package/packages/shared-skills/skills/frontend/scripts/detect/rules/source/bounce-easing.ts +21 -0
  750. package/packages/shared-skills/skills/frontend/scripts/detect/rules/source/broken-image.test.ts +27 -0
  751. package/packages/shared-skills/skills/frontend/scripts/detect/rules/source/broken-image.ts +16 -0
  752. package/packages/shared-skills/skills/frontend/scripts/detect/rules/source/codex-grid-background.test.ts +11 -0
  753. package/packages/shared-skills/skills/frontend/scripts/detect/rules/source/codex-grid-background.ts +18 -0
  754. package/packages/shared-skills/skills/frontend/scripts/detect/rules/source/dark-glow.test.ts +15 -0
  755. package/packages/shared-skills/skills/frontend/scripts/detect/rules/source/dark-glow.ts +21 -0
  756. package/packages/shared-skills/skills/frontend/scripts/detect/rules/source/em-dash-overuse.test.ts +13 -0
  757. package/packages/shared-skills/skills/frontend/scripts/detect/rules/source/em-dash-overuse.ts +15 -0
  758. package/packages/shared-skills/skills/frontend/scripts/detect/rules/source/gradient-text.test.ts +12 -0
  759. package/packages/shared-skills/skills/frontend/scripts/detect/rules/source/gradient-text.ts +11 -0
  760. package/packages/shared-skills/skills/frontend/scripts/detect/rules/source/gray-on-color.test.ts +20 -0
  761. package/packages/shared-skills/skills/frontend/scripts/detect/rules/source/gray-on-color.ts +13 -0
  762. package/packages/shared-skills/skills/frontend/scripts/detect/rules/source/index.ts +19 -0
  763. package/packages/shared-skills/skills/frontend/scripts/detect/rules/source/marketing-buzzword.test.ts +12 -0
  764. package/packages/shared-skills/skills/frontend/scripts/detect/rules/source/marketing-buzzword.ts +17 -0
  765. package/packages/shared-skills/skills/frontend/scripts/detect/rules/source/marquee.test.ts +12 -0
  766. package/packages/shared-skills/skills/frontend/scripts/detect/rules/source/marquee.ts +12 -0
  767. package/packages/shared-skills/skills/frontend/scripts/detect/rules/source/monotonous-spacing.test.ts +13 -0
  768. package/packages/shared-skills/skills/frontend/scripts/detect/rules/source/monotonous-spacing.ts +22 -0
  769. package/packages/shared-skills/skills/frontend/scripts/detect/rules/source/overused-font.test.ts +21 -0
  770. package/packages/shared-skills/skills/frontend/scripts/detect/rules/source/overused-font.ts +16 -0
  771. package/packages/shared-skills/skills/frontend/scripts/detect/rules/source/radial-halo.test.ts +16 -0
  772. package/packages/shared-skills/skills/frontend/scripts/detect/rules/source/radial-halo.ts +14 -0
  773. package/packages/shared-skills/skills/frontend/scripts/detect/rules/source/side-tab.test.ts +29 -0
  774. package/packages/shared-skills/skills/frontend/scripts/detect/rules/source/side-tab.ts +58 -0
  775. package/packages/shared-skills/skills/frontend/scripts/detect/rules/source/support/accent-scans.ts +78 -0
  776. package/packages/shared-skills/skills/frontend/scripts/detect/rules/source/support/check-source.ts +6 -0
  777. package/packages/shared-skills/skills/frontend/scripts/detect/rules/source/support/corners.ts +105 -0
  778. package/packages/shared-skills/skills/frontend/scripts/detect/rules/source/support/css-effects.ts +81 -0
  779. package/packages/shared-skills/skills/frontend/scripts/detect/rules/source/support/css-scopes.ts +131 -0
  780. package/packages/shared-skills/skills/frontend/scripts/detect/rules/source/support/image-tags.ts +113 -0
  781. package/packages/shared-skills/skills/frontend/scripts/detect/rules/source/support/js-punctuation.ts +34 -0
  782. package/packages/shared-skills/skills/frontend/scripts/detect/rules/source/support/markup-scope.ts +44 -0
  783. package/packages/shared-skills/skills/frontend/scripts/detect/rules/source/support/source-color.ts +42 -0
  784. package/packages/shared-skills/skills/frontend/scripts/detect/rules/source/support/source-shadow.ts +15 -0
  785. package/packages/shared-skills/skills/frontend/scripts/detect/rules/source/support/source-text.ts +110 -0
  786. package/packages/shared-skills/skills/frontend/scripts/detect/rules/typography/all-caps-body.test.ts +24 -0
  787. package/packages/shared-skills/skills/frontend/scripts/detect/rules/typography/all-caps-body.ts +15 -0
  788. package/packages/shared-skills/skills/frontend/scripts/detect/rules/typography/design-system-font-size.test.ts +21 -0
  789. package/packages/shared-skills/skills/frontend/scripts/detect/rules/typography/design-system-font-size.ts +23 -0
  790. package/packages/shared-skills/skills/frontend/scripts/detect/rules/typography/design-system-font.test.ts +22 -0
  791. package/packages/shared-skills/skills/frontend/scripts/detect/rules/typography/design-system-font.ts +24 -0
  792. package/packages/shared-skills/skills/frontend/scripts/detect/rules/typography/extreme-negative-tracking.test.ts +23 -0
  793. package/packages/shared-skills/skills/frontend/scripts/detect/rules/typography/extreme-negative-tracking.ts +18 -0
  794. package/packages/shared-skills/skills/frontend/scripts/detect/rules/typography/flat-type-hierarchy.test.ts +33 -0
  795. package/packages/shared-skills/skills/frontend/scripts/detect/rules/typography/flat-type-hierarchy.ts +26 -0
  796. package/packages/shared-skills/skills/frontend/scripts/detect/rules/typography/index.ts +21 -0
  797. package/packages/shared-skills/skills/frontend/scripts/detect/rules/typography/italic-serif-display.test.ts +24 -0
  798. package/packages/shared-skills/skills/frontend/scripts/detect/rules/typography/italic-serif-display.ts +24 -0
  799. package/packages/shared-skills/skills/frontend/scripts/detect/rules/typography/justified-text.test.ts +31 -0
  800. package/packages/shared-skills/skills/frontend/scripts/detect/rules/typography/justified-text.ts +32 -0
  801. package/packages/shared-skills/skills/frontend/scripts/detect/rules/typography/line-length.test.ts +43 -0
  802. package/packages/shared-skills/skills/frontend/scripts/detect/rules/typography/line-length.ts +28 -0
  803. package/packages/shared-skills/skills/frontend/scripts/detect/rules/typography/oversized-h1.test.ts +26 -0
  804. package/packages/shared-skills/skills/frontend/scripts/detect/rules/typography/oversized-h1.ts +20 -0
  805. package/packages/shared-skills/skills/frontend/scripts/detect/rules/typography/overused-font.test.ts +35 -0
  806. package/packages/shared-skills/skills/frontend/scripts/detect/rules/typography/overused-font.ts +45 -0
  807. package/packages/shared-skills/skills/frontend/scripts/detect/rules/typography/support/drawn-enlargement.ts +48 -0
  808. package/packages/shared-skills/skills/frontend/scripts/detect/rules/typography/support/fading-text.ts +48 -0
  809. package/packages/shared-skills/skills/frontend/scripts/detect/rules/typography/support/flex-runs.ts +16 -0
  810. package/packages/shared-skills/skills/frontend/scripts/detect/rules/typography/support/font-family.ts +28 -0
  811. package/packages/shared-skills/skills/frontend/scripts/detect/rules/typography/support/painted-text.test.ts +63 -0
  812. package/packages/shared-skills/skills/frontend/scripts/detect/rules/typography/support/painted-text.ts +81 -0
  813. package/packages/shared-skills/skills/frontend/scripts/detect/rules/typography/support/svg-size.ts +57 -0
  814. package/packages/shared-skills/skills/frontend/scripts/detect/rules/typography/support/text-context.ts +112 -0
  815. package/packages/shared-skills/skills/frontend/scripts/detect/rules/typography/support/text-lines.ts +43 -0
  816. package/packages/shared-skills/skills/frontend/scripts/detect/rules/typography/support/type-hierarchy.ts +48 -0
  817. package/packages/shared-skills/skills/frontend/scripts/detect/rules/typography/tight-leading.test.ts +54 -0
  818. package/packages/shared-skills/skills/frontend/scripts/detect/rules/typography/tight-leading.ts +47 -0
  819. package/packages/shared-skills/skills/frontend/scripts/detect/rules/typography/tiny-text.test.ts +60 -0
  820. package/packages/shared-skills/skills/frontend/scripts/detect/rules/typography/tiny-text.ts +23 -0
  821. package/packages/shared-skills/skills/frontend/scripts/detect/rules/typography/undersized-ui-text.test.ts +98 -0
  822. package/packages/shared-skills/skills/frontend/scripts/detect/rules/typography/undersized-ui-text.ts +28 -0
  823. package/packages/shared-skills/skills/frontend/scripts/detect/rules/typography/wide-tracking.test.ts +26 -0
  824. package/packages/shared-skills/skills/frontend/scripts/detect/rules/typography/wide-tracking.ts +26 -0
  825. package/packages/shared-skills/skills/frontend/scripts/detect/snapshot/collect.ts +158 -0
  826. package/packages/shared-skills/skills/frontend/scripts/detect/snapshot/style-props.ts +25 -0
  827. package/packages/shared-skills/skills/frontend/scripts/detect/testing/build-snapshot.ts +78 -0
  828. package/packages/shared-skills/skills/frontend/scripts/detect/tsconfig.json +19 -0
  829. package/packages/shared-skills/skills/frontend/scripts/detect/types.ts +124 -0
  830. package/packages/shared-skills/skills/programming/SKILL.md +17 -74
  831. package/packages/shared-skills/skills/programming/references/go/README.md +1 -1
  832. package/packages/shared-skills/skills/programming/references/go/bootstrap.md +2 -2
  833. package/packages/shared-skills/skills/programming/references/python/README.md +4 -4
  834. package/packages/shared-skills/skills/programming/references/python/one-liners.md +5 -5
  835. package/packages/shared-skills/skills/programming/references/testing/README.md +82 -0
  836. package/packages/shared-skills/skills/programming/references/testing/junk-classes.md +56 -0
  837. package/packages/shared-skills/skills/programming/references/typescript/README.md +1 -2
  838. package/packages/shared-skills/skills/programming/scripts/go/new-project.ts +197 -0
  839. package/packages/shared-skills/skills/programming/scripts/python/new-project.ts +231 -0
  840. package/packages/shared-skills/skills/programming/scripts/python/new-script.ts +134 -0
  841. package/packages/shared-skills/skills/programming/scripts/rust/new-project.ts +215 -0
  842. package/packages/shared-skills/skills/programming/scripts/scaffolders.test.ts +96 -0
  843. package/packages/shared-skills/skills/programming/scripts/shared/run-tool.ts +19 -0
  844. package/packages/shared-skills/skills/programming/scripts/typescript/check-test-junk-rules.ts +140 -0
  845. package/packages/shared-skills/skills/programming/scripts/typescript/check-test-junk.test.ts +125 -0
  846. package/packages/shared-skills/skills/programming/scripts/typescript/check-test-junk.ts +148 -0
  847. package/packages/shared-skills/skills/programming/scripts/typescript/mutation-proof.test.ts +43 -0
  848. package/packages/shared-skills/skills/programming/scripts/typescript/mutation-proof.ts +179 -0
  849. package/packages/shared-skills/skills/remove-ai-slops/SKILL.md +32 -20
  850. package/packages/shared-skills/skills/ulw-research/scripts/source-commands.mjs +3 -1
  851. package/packages/shared-skills/skills/ulw-research/scripts/source-integrity.test.ts +39 -2
  852. package/packages/shared-skills/skills/visual-qa/SKILL.md +12 -1
  853. package/dist/agents/gpt-prompt-identity.d.ts +0 -3
  854. package/dist/agents/hephaestus/gpt-5-4.d.ts +0 -24
  855. package/dist/agents/hephaestus/gpt-5-5.d.ts +0 -2
  856. package/dist/agents/hephaestus/gpt-5-6.d.ts +0 -2
  857. package/dist/agents/kimi-tool-loop-guard.d.ts +0 -1
  858. package/dist/agents/sisyphus/claude-fable-5.d.ts +0 -19
  859. package/dist/agents/sisyphus/claude-opus-4-7.d.ts +0 -22
  860. package/dist/agents/sisyphus/claude-opus-4-8.d.ts +0 -19
  861. package/dist/agents/sisyphus/claude-opus-5.d.ts +0 -33
  862. package/dist/agents/sisyphus/gemini.d.ts +0 -20
  863. package/dist/agents/sisyphus/glm-5-2.d.ts +0 -4
  864. package/dist/agents/sisyphus/gpt-5-4.d.ts +0 -26
  865. package/dist/agents/sisyphus/gpt-5-5.d.ts +0 -6
  866. package/dist/agents/sisyphus/gpt-task-system-guide.d.ts +0 -1
  867. package/dist/agents/sisyphus/grok-4.d.ts +0 -21
  868. package/dist/agents/sisyphus/index.d.ts +0 -31
  869. package/dist/agents/sisyphus/kimi-k2-6.d.ts +0 -32
  870. package/dist/agents/sisyphus/kimi-k2-7.d.ts +0 -17
  871. package/dist/agents/sisyphus/kimi-k3-1.d.ts +0 -9
  872. package/dist/agents/sisyphus/kimi-k3.d.ts +0 -19
  873. package/dist/agents/sisyphus-dynamic-prompt-builder.d.ts +0 -2
  874. package/dist/agents/sisyphus-dynamic-prompt-execution.d.ts +0 -2
  875. package/dist/agents/sisyphus-dynamic-prompt-exploration.d.ts +0 -2
  876. package/dist/agents/sisyphus-dynamic-prompt-role.d.ts +0 -2
  877. package/dist/agents/sisyphus-dynamic-prompt-sections.d.ts +0 -18
  878. package/dist/agents/sisyphus-dynamic-prompt-style.d.ts +0 -2
  879. package/dist/agents/sisyphus-dynamic-prompt.d.ts +0 -3
  880. package/dist/agents/sisyphus-gemini-fallback-overrides.d.ts +0 -1
  881. package/dist/agents/sisyphus-junior/gemini.d.ts +0 -10
  882. package/dist/agents/sisyphus-junior/glm-5-2.d.ts +0 -1
  883. package/dist/agents/sisyphus-junior/gpt-5-4.d.ts +0 -11
  884. package/dist/agents/sisyphus-junior/gpt-5-5.d.ts +0 -5
  885. package/dist/agents/sisyphus-junior/gpt.d.ts +0 -9
  886. package/dist/agents/sisyphus-junior/kimi-k2-6.d.ts +0 -13
  887. package/dist/agents/sisyphus-junior/kimi-k2-7.d.ts +0 -11
  888. package/dist/agents/sisyphus-junior/kimi-k3-1.d.ts +0 -6
  889. package/dist/agents/sisyphus-junior/kimi-k3.d.ts +0 -12
  890. package/dist/features/claude-code-agent-loader/opencode-config-agents-reader.d.ts +0 -1
  891. package/dist/features/claude-code-command-loader/loader-cache.d.ts +0 -1
  892. package/dist/features/claude-code-command-loader/loader.d.ts +0 -1
  893. package/dist/features/opencode-skill-loader/config-source-discovery.d.ts +0 -1
  894. package/dist/features/opencode-skill-loader/merger/config-skill-entry-loader.d.ts +0 -1
  895. package/dist/features/opencode-skill-loader/opencode-config-skills-reader.d.ts +0 -1
  896. package/dist/features/team-mode/team-layout-tmux/resolve-caller-tmux-session.d.ts +0 -1
  897. package/dist/features/team-mode/team-registry/team-spec-input-normalizer.d.ts +0 -1
  898. package/dist/shared/git-worktree/collect-git-diff-stats.d.ts +0 -1
  899. package/dist/shared/git-worktree/parse-status-porcelain-line.d.ts +0 -1
  900. package/dist/shared/migration/agent-names.d.ts +0 -1
  901. package/dist/shared/migration/migrations-sidecar.d.ts +0 -1
  902. package/dist/shared/skill-path-resolver.d.ts +0 -1
  903. package/dist/shared/zip-entry-listing/powershell-zip-entry-listing.d.ts +0 -1
  904. package/dist/shared/zip-entry-listing/zipinfo-zip-entry-listing.d.ts +0 -1
  905. package/dist/skills/programming/scripts/go/new-project.py +0 -138
  906. package/dist/skills/programming/scripts/python/new-project.py +0 -172
  907. package/dist/skills/programming/scripts/python/new-script.py +0 -116
  908. package/dist/skills/programming/scripts/rust/new-project.py +0 -178
  909. package/packages/omo-codex/plugin/skills/programming/scripts/go/new-project.py +0 -138
  910. package/packages/omo-codex/plugin/skills/programming/scripts/python/new-project.py +0 -172
  911. package/packages/omo-codex/plugin/skills/programming/scripts/python/new-script.py +0 -116
  912. package/packages/omo-codex/plugin/skills/programming/scripts/rust/new-project.py +0 -178
  913. package/packages/shared-skills/skills/programming/scripts/go/new-project.py +0 -138
  914. package/packages/shared-skills/skills/programming/scripts/python/new-project.py +0 -172
  915. package/packages/shared-skills/skills/programming/scripts/python/new-script.py +0 -116
  916. package/packages/shared-skills/skills/programming/scripts/rust/new-project.py +0 -178
@@ -2133,7 +2133,7 @@ var package_default;
2133
2133
  var init_package = __esm(() => {
2134
2134
  package_default = {
2135
2135
  name: "oh-my-opencode",
2136
- version: "5.1.51",
2136
+ version: "5.1.55",
2137
2137
  description: "The Best AI Agent Harness - Batteries-Included OpenCode Plugin with Multi-Model Orchestration, Parallel Background Agents, and Crafted LSP/AST Tools",
2138
2138
  main: "./dist/index.js",
2139
2139
  types: "dist/index.d.ts",
@@ -2157,6 +2157,7 @@ var init_package = __esm(() => {
2157
2157
  "packages/openclaw-core",
2158
2158
  "packages/boulder-state",
2159
2159
  "packages/memory-core",
2160
+ "packages/device-service-core",
2160
2161
  "packages/isolation-core",
2161
2162
  "packages/telemetry-core",
2162
2163
  "packages/claude-code-compat-core",
@@ -2275,14 +2276,15 @@ var init_package = __esm(() => {
2275
2276
  prepublishOnly: "bun run clean && bun run build:lsp-tools-mcp && bun run build:lsp-daemon && bun run build",
2276
2277
  "test:model-capabilities": "bun test --timeout 20000 packages/model-core/src/model-capability-aliases.test.ts packages/model-core/src/model-capability-guardrails.test.ts packages/model-core/src/model-capabilities.test.ts packages/omo-opencode/src/cli/doctor/checks/model-resolution.test.ts --bail",
2277
2278
  "check:copy": "bun script/check-copy.ts",
2278
- typecheck: "bun run check:copy && tsgo --noEmit && bun run typecheck:script && bun run typecheck:packages",
2279
- "typecheck:packages": "tsgo --noEmit -p packages/rules-engine/tsconfig.json && tsgo --noEmit -p packages/delegate-core/tsconfig.json && tsgo --noEmit -p packages/mcp-stdio-core/tsconfig.json && tsgo --noEmit -p packages/mcp-client-core/tsconfig.json && tsgo --noEmit -p packages/git-bash-mcp/tsconfig.json && tsgo --noEmit -p packages/ast-grep-mcp/tsconfig.json && tsgo --noEmit -p packages/lsp-core/tsconfig.json && tsgo --noEmit -p packages/utils/tsconfig.json && tsgo --noEmit -p packages/model-core/tsconfig.json && tsgo --noEmit -p packages/omo-config-core/tsconfig.json && tsgo --noEmit -p packages/prompts-core/tsconfig.json && tsgo --noEmit -p packages/comment-checker-core/tsconfig.json && tsgo --noEmit -p packages/hashline-core/tsconfig.json && tsgo --noEmit -p packages/tmux-core/tsconfig.json && tsgo --noEmit -p packages/team-core/tsconfig.json && tsgo --noEmit -p packages/openclaw-core/tsconfig.json && tsgo --noEmit -p packages/boulder-state/tsconfig.json && tsgo --noEmit -p packages/isolation-core/tsconfig.json && tsgo --noEmit -p packages/memory-core/tsconfig.json && tsgo --noEmit -p packages/telemetry-core/tsconfig.json && tsgo --noEmit -p packages/claude-code-compat-core/tsconfig.json && tsgo --noEmit -p packages/skills-loader-core/tsconfig.json && tsgo --noEmit -p packages/agents-md-core/tsconfig.json && tsgo --noEmit -p packages/omo-codex/plugin/shared/tsconfig.json && tsgo --noEmit -p packages/omo-codex/tsconfig.json && tsgo --noEmit -p packages/omo-senpi/tsconfig.json && tsgo --noEmit -p packages/senpi-task/tsconfig.json && tsgo --noEmit -p packages/omo-opencode/tsconfig.json && tsgo --noEmit -p packages/omo-native/tsconfig.json && tsgo --noEmit -p packages/senpi-desktop-protocol/tsconfig.json && tsgo --noEmit -p packages/senpi-desktop-engine/tsconfig.json && tsgo --noEmit -p packages/senpi-desktop-prelude/tsconfig.json && tsgo --noEmit -p packages/senpi-desktop-service/tsconfig.json && tsgo --noEmit -p packages/senpi-desktop-tool/tsconfig.json",
2280
- "typecheck:script": "tsgo --noEmit -p script/tsconfig.json",
2279
+ typecheck: "bun run check:copy && bun check --no-script --all -p tsconfig.json && bun run typecheck:script && bun run typecheck:packages && bun run typecheck:skill-scripts",
2280
+ "typecheck:skill-scripts": "bun check --no-script --all -p packages/shared-skills/skills/frontend/scripts/detect/tsconfig.json",
2281
+ "typecheck:packages": "bun check --no-script --all -p packages/rules-engine/tsconfig.json && bun check --no-script --all -p packages/delegate-core/tsconfig.json && bun check --no-script --all -p packages/mcp-stdio-core/tsconfig.json && bun check --no-script --all -p packages/mcp-client-core/tsconfig.json && bun check --no-script --all -p packages/git-bash-mcp/tsconfig.json && bun check --no-script --all -p packages/ast-grep-mcp/tsconfig.json && bun check --no-script --all -p packages/lsp-core/tsconfig.json && bun check --no-script --all -p packages/utils/tsconfig.json && bun check --no-script --all -p packages/device-service-core/tsconfig.json && bun check --no-script --all -p packages/model-core/tsconfig.json && bun check --no-script --all -p packages/omo-config-core/tsconfig.json && bun check --no-script --all -p packages/prompts-core/tsconfig.json && bun check --no-script --all -p packages/comment-checker-core/tsconfig.json && bun check --no-script --all -p packages/hashline-core/tsconfig.json && bun check --no-script --all -p packages/tmux-core/tsconfig.json && bun check --no-script --all -p packages/team-core/tsconfig.json && bun check --no-script --all -p packages/openclaw-core/tsconfig.json && bun check --no-script --all -p packages/boulder-state/tsconfig.json && bun check --no-script --all -p packages/isolation-core/tsconfig.json && bun check --no-script --all -p packages/memory-core/tsconfig.json && bun check --no-script --all -p packages/telemetry-core/tsconfig.json && bun check --no-script --all -p packages/claude-code-compat-core/tsconfig.json && bun check --no-script --all -p packages/skills-loader-core/tsconfig.json && bun check --no-script --all -p packages/agents-md-core/tsconfig.json && bun check --no-script --all -p packages/omo-codex/plugin/shared/tsconfig.json && bun check --no-script --all -p packages/omo-codex/tsconfig.json && bun check --no-script --all -p packages/omo-senpi/tsconfig.json && bun check --no-script --all -p packages/senpi-task/tsconfig.json && bun check --no-script --all -p packages/omo-opencode/tsconfig.json && bun check --no-script --all -p packages/omo-native/tsconfig.json && bun check --no-script --all -p packages/senpi-desktop-protocol/tsconfig.json && bun check --no-script --all -p packages/senpi-desktop-engine/tsconfig.json && bun check --no-script --all -p packages/senpi-desktop-prelude/tsconfig.json && bun check --no-script --all -p packages/senpi-desktop-service/tsconfig.json && bun check --no-script --all -p packages/senpi-desktop-tool/tsconfig.json",
2282
+ "typecheck:script": "bun check --no-script --all -p script/tsconfig.json",
2281
2283
  test: "bun test --timeout 20000",
2282
2284
  "changelog:section": "bun script/changelog-section.ts",
2283
2285
  "test:codex": "bun run build:codex-install && bun run build:git-bash-mcp && bun run build:lsp-tools-mcp && bun run build:lsp-daemon && npm --prefix packages/lsp-tools-mcp test && npm --prefix packages/omo-codex/plugin ci && npm --prefix packages/omo-codex/plugin/components/ulw-loop test && bun run --cwd packages/omo-codex/plugin build && node scripts/check-third-party-notices.mjs --ship && bun test --timeout 20000 packages/omo-opencode/src/cli/cli-installer.platform.test.ts packages/omo-codex/src/install/codex-cache.test.ts packages/omo-codex/src/install/codex-cleanup.test.ts packages/omo-codex/src/install/codex-config-agent-cleanup.test.ts packages/omo-codex/src/install/codex-config-autonomous-features.test.ts packages/omo-codex/src/install/codex-config-reasoning.test.ts packages/omo-codex/src/install/codex-config-toml.test.ts packages/omo-codex/src/install/codex-project-local-cleanup.test.ts packages/omo-codex/src/install/install-codex-project-local-cleanup.test.ts packages/omo-codex/src/install/install-codex.test.ts packages/omo-codex/src/install/install-codex-packaged.test.ts packages/omo-codex/src/install/link-cached-plugin-agents.test.ts packages/omo-codex/src/**/*.test.ts packages/utils/src/jsonc-parser.test.ts packages/utils/src/frontmatter.test.ts packages/hashline-core/src/hash-computation.test.ts packages/hashline-core/src/smoke-untested-modules.test.ts packages/rules-engine/src/index.test.ts packages/rules-engine/src/security-boundary.test.ts packages/agents-md-core/src/injector.test.ts packages/omo-codex/plugin/components/lsp/test/package-smoke.test.ts && node --test packages/omo-codex/plugin/test/*.test.mjs packages/omo-codex/scripts/install-cache-copy.test.mjs packages/omo-codex/scripts/install-cli-args.test.mjs packages/omo-codex/scripts/install-delegated-command.test.mjs packages/omo-codex/scripts/install-config-autonomous-features.test.mjs packages/omo-codex/scripts/install-config-autonomous.test.mjs packages/omo-codex/scripts/install-config-reasoning.test.mjs packages/omo-codex/scripts/install-config.test.mjs packages/omo-codex/scripts/install-hook-targets.test.mjs packages/omo-codex/scripts/install-project-local-cleanup.test.mjs packages/omo-codex/scripts/install-lazycodex-version-stamp.test.mjs packages/omo-codex/scripts/install-local-entrypoint.test.mjs packages/omo-codex/scripts/install-local-git-bash-preflight.test.mjs packages/omo-codex/scripts/install-local.test.mjs packages/omo-codex/scripts/install-marketplace-cache.test.mjs packages/omo-codex/scripts/install-mcp-context7-runtime.test.mjs packages/omo-codex/scripts/install-mcp-runtime.test.mjs packages/omo-codex/scripts/install-packaged-local.test.mjs packages/omo-codex/scripts/install-generated-bundle.test.mjs packages/omo-codex/scripts/install-agent-links.test.mjs packages/omo-codex/scripts/install-bin-links.test.mjs",
2284
2286
  "test:fast": "bun run script/test-fast.ts",
2285
- "test:senpi": "bun run build:senpi-plugin && tsgo --noEmit -p packages/omo-senpi/tsconfig.json && bun test --timeout 20000 packages/omo-senpi && bun test ./.agents/skills/senpi-qa/scripts/resolve-evidence-dir.test.mjs",
2287
+ "test:senpi": "bun run build:senpi-plugin && bun check --no-script --all -p packages/omo-senpi/tsconfig.json && bun test --timeout 20000 packages/omo-senpi && bun test ./.agents/skills/senpi-qa/scripts/resolve-evidence-dir.test.mjs",
2286
2288
  "test:windows-codex": "bun run test:codex",
2287
2289
  "build:git-bash-mcp": "bun run --cwd packages/git-bash-mcp build",
2288
2290
  "build:ast-grep-mcp": "bun run --cwd packages/ast-grep-mcp build",
@@ -2318,11 +2320,12 @@ var init_package = __esm(() => {
2318
2320
  },
2319
2321
  devDependencies: {
2320
2322
  "@clack/prompts": "^1.8.1",
2321
- "@code-yeongyu/senpi": "2026.10.27-1",
2323
+ "@code-yeongyu/senpi": "2026.10.30-1",
2322
2324
  "@modelcontextprotocol/sdk": "^1.30.0",
2323
2325
  "@oh-my-opencode/agents-md-core": "workspace:*",
2324
2326
  "@oh-my-opencode/ast-grep-mcp": "workspace:*",
2325
2327
  "@oh-my-opencode/boulder-state": "workspace:*",
2328
+ "@oh-my-opencode/device-service-core": "workspace:*",
2326
2329
  "@oh-my-opencode/claude-code-compat-core": "workspace:*",
2327
2330
  "@oh-my-opencode/comment-checker-core": "workspace:*",
2328
2331
  "@oh-my-opencode/delegate-core": "workspace:*",
@@ -2372,7 +2375,7 @@ var init_package = __esm(() => {
2372
2375
  "jsonc-parser": "^3.3.1",
2373
2376
  knip: "6.43.0",
2374
2377
  "node-pty": "^1.1.0",
2375
- omowright: "github:code-yeongyu/omowright#f87ef4d63fe7b56fe117dbab246c8ad88dd8a780",
2378
+ omowright: "github:code-yeongyu/omowright#c06d20337ad942b09dea8757a45f6c848008a68d",
2376
2379
  "oxc-parser": "0.148.0",
2377
2380
  oxlint: "1.89.0",
2378
2381
  picocolors: "^1.1.1",
@@ -2382,18 +2385,18 @@ var init_package = __esm(() => {
2382
2385
  typescript: "^7.0.2"
2383
2386
  },
2384
2387
  optionalDependencies: {
2385
- "oh-my-opencode-darwin-arm64": "5.1.51",
2386
- "oh-my-opencode-darwin-x64": "5.1.51",
2387
- "oh-my-opencode-darwin-x64-baseline": "5.1.51",
2388
- "oh-my-opencode-linux-arm64": "5.1.51",
2389
- "oh-my-opencode-linux-arm64-musl": "5.1.51",
2390
- "oh-my-opencode-linux-x64": "5.1.51",
2391
- "oh-my-opencode-linux-x64-baseline": "5.1.51",
2392
- "oh-my-opencode-linux-x64-musl": "5.1.51",
2393
- "oh-my-opencode-linux-x64-musl-baseline": "5.1.51",
2394
- "oh-my-opencode-windows-arm64": "5.1.51",
2395
- "oh-my-opencode-windows-x64": "5.1.51",
2396
- "oh-my-opencode-windows-x64-baseline": "5.1.51"
2388
+ "oh-my-opencode-darwin-arm64": "5.1.55",
2389
+ "oh-my-opencode-darwin-x64": "5.1.55",
2390
+ "oh-my-opencode-darwin-x64-baseline": "5.1.55",
2391
+ "oh-my-opencode-linux-arm64": "5.1.55",
2392
+ "oh-my-opencode-linux-arm64-musl": "5.1.55",
2393
+ "oh-my-opencode-linux-x64": "5.1.55",
2394
+ "oh-my-opencode-linux-x64-baseline": "5.1.55",
2395
+ "oh-my-opencode-linux-x64-musl": "5.1.55",
2396
+ "oh-my-opencode-linux-x64-musl-baseline": "5.1.55",
2397
+ "oh-my-opencode-windows-arm64": "5.1.55",
2398
+ "oh-my-opencode-windows-x64": "5.1.55",
2399
+ "oh-my-opencode-windows-x64-baseline": "5.1.55"
2397
2400
  },
2398
2401
  overrides: {
2399
2402
  hono: "^4.13.8",
@@ -8056,7 +8059,8 @@ var init_latest_models = __esm(() => {
8056
8059
  gptLunaFast: "gpt-6-luna-fast",
8057
8060
  glm: "glm-5.3",
8058
8061
  glmFlash: "glm-5.3-flash",
8059
- kimi: "kimi-k3",
8062
+ kimi: "kimi-k3.1-pro",
8063
+ kimiK3: "kimi-k3",
8060
8064
  geminiPro: "gemini-4-argon"
8061
8065
  };
8062
8066
  });
@@ -9379,9 +9383,13 @@ var init_agent_model_requirements = __esm(() => {
9379
9383
  variant: "max"
9380
9384
  },
9381
9385
  {
9382
- providers: ["opencode-go", "kimi-for-coding", "moonshotai", "opencode", "bailian-coding-plan", "moonshotai-cn", "firmware", "ollama-cloud", "aihubmix"],
9386
+ providers: ["opencode-go", "kimi-for-coding", "moonshotai", "moonshotai-cn"],
9383
9387
  model: LATEST_MODEL_BY_FAMILY.kimi
9384
9388
  },
9389
+ {
9390
+ providers: ["opencode", "bailian-coding-plan", "firmware", "ollama-cloud", "aihubmix"],
9391
+ model: LATEST_MODEL_BY_FAMILY.kimiK3
9392
+ },
9385
9393
  {
9386
9394
  providers: ["openai", "chatgpt-subscription", "github-copilot", "opencode"],
9387
9395
  model: "gpt-5.6-sol",
@@ -9476,10 +9484,11 @@ var init_agent_model_requirements = __esm(() => {
9476
9484
  variant: "max"
9477
9485
  },
9478
9486
  {
9479
- providers: ["opencode-go", "kimi-for-coding", "moonshotai", "opencode"],
9487
+ providers: ["opencode-go", "kimi-for-coding", "moonshotai"],
9480
9488
  model: LATEST_MODEL_BY_FAMILY.kimi,
9481
9489
  variant: "max"
9482
- }
9490
+ },
9491
+ { providers: ["opencode"], model: LATEST_MODEL_BY_FAMILY.kimiK3, variant: "max" }
9483
9492
  ])
9484
9493
  },
9485
9494
  metis: {
@@ -9500,10 +9509,11 @@ var init_agent_model_requirements = __esm(() => {
9500
9509
  variant: "max"
9501
9510
  },
9502
9511
  {
9503
- providers: ["opencode-go", "kimi-for-coding", "moonshotai", "opencode"],
9512
+ providers: ["opencode-go", "kimi-for-coding", "moonshotai"],
9504
9513
  model: LATEST_MODEL_BY_FAMILY.kimi,
9505
9514
  variant: "max"
9506
- }
9515
+ },
9516
+ { providers: ["opencode"], model: LATEST_MODEL_BY_FAMILY.kimiK3, variant: "max" }
9507
9517
  ])
9508
9518
  },
9509
9519
  momus: {
@@ -9586,10 +9596,11 @@ var init_category_model_requirements = __esm(() => {
9586
9596
  variant: "max"
9587
9597
  },
9588
9598
  {
9589
- providers: ["kimi-for-coding", "moonshotai", "opencode-go", "opencode"],
9599
+ providers: ["kimi-for-coding", "moonshotai", "opencode-go"],
9590
9600
  model: LATEST_MODEL_BY_FAMILY.kimi,
9591
9601
  variant: "max"
9592
- }
9602
+ },
9603
+ { providers: ["opencode"], model: LATEST_MODEL_BY_FAMILY.kimiK3, variant: "max" }
9593
9604
  ])
9594
9605
  },
9595
9606
  ultrabrain: {
@@ -9641,10 +9652,11 @@ var init_category_model_requirements = __esm(() => {
9641
9652
  variant: "max"
9642
9653
  },
9643
9654
  {
9644
- providers: ["kimi-for-coding", "moonshotai", "opencode-go", "opencode"],
9655
+ providers: ["kimi-for-coding", "moonshotai", "opencode-go"],
9645
9656
  model: LATEST_MODEL_BY_FAMILY.kimi,
9646
9657
  variant: "max"
9647
- }
9658
+ },
9659
+ { providers: ["opencode"], model: LATEST_MODEL_BY_FAMILY.kimiK3, variant: "max" }
9648
9660
  ])
9649
9661
  },
9650
9662
  quick: {
@@ -9707,10 +9719,11 @@ var init_category_model_requirements = __esm(() => {
9707
9719
  },
9708
9720
  { providers: ["zai-coding-plan", "opencode-go"], model: LATEST_MODEL_BY_FAMILY.glm, variant: "max" },
9709
9721
  {
9710
- providers: ["kimi-for-coding", "moonshotai", "opencode-go", "opencode"],
9722
+ providers: ["kimi-for-coding", "moonshotai", "opencode-go"],
9711
9723
  model: LATEST_MODEL_BY_FAMILY.kimi,
9712
9724
  variant: "max"
9713
- }
9725
+ },
9726
+ { providers: ["opencode"], model: LATEST_MODEL_BY_FAMILY.kimiK3, variant: "max" }
9714
9727
  ]
9715
9728
  },
9716
9729
  writing: {
@@ -10274,7 +10287,7 @@ function transformModelForProviderDisplay(provider, model) {
10274
10287
  var CLAUDE_VERSION_DOT, GEMINI_31_PRO_PREVIEW, GEMINI_3_FLASH_PREVIEW;
10275
10288
  var init_provider_model_id_transform = __esm(() => {
10276
10289
  CLAUDE_VERSION_DOT = /claude-(\w+)-(\d+)-(\d+)/g;
10277
- GEMINI_31_PRO_PREVIEW = /gemini-3\.1-pro(?!-)/g;
10290
+ GEMINI_31_PRO_PREVIEW = /(?<!antigravity-)gemini-3\.1-pro(?!-)/g;
10278
10291
  GEMINI_3_FLASH_PREVIEW = /(?<!antigravity-)gemini-3-flash(?!-)/g;
10279
10292
  });
10280
10293
 
@@ -10348,6 +10361,36 @@ var init_supplemental_entries = __esm(() => {
10348
10361
  output: 262144
10349
10362
  }
10350
10363
  },
10364
+ "kimi-k3.1-pro": {
10365
+ id: "kimi-k3.1-pro",
10366
+ family: "kimi",
10367
+ reasoning: true,
10368
+ temperature: true,
10369
+ toolCall: true,
10370
+ modalities: {
10371
+ input: ["text", "image", "video"],
10372
+ output: ["text"]
10373
+ },
10374
+ limit: {
10375
+ context: 1048576,
10376
+ output: 1048576
10377
+ }
10378
+ },
10379
+ "kimi-k3.1-pro-highspeed": {
10380
+ id: "kimi-k3.1-pro-highspeed",
10381
+ family: "kimi",
10382
+ reasoning: true,
10383
+ temperature: true,
10384
+ toolCall: true,
10385
+ modalities: {
10386
+ input: ["text", "image", "video"],
10387
+ output: ["text"]
10388
+ },
10389
+ limit: {
10390
+ context: 1048576,
10391
+ output: 1048576
10392
+ }
10393
+ },
10351
10394
  "kimi-k2.6": {
10352
10395
  id: "kimi-k2.6",
10353
10396
  family: "kimi",
@@ -12432,6 +12475,33 @@ function createJsonFileCacheStore(options) {
12432
12475
  });
12433
12476
  }
12434
12477
  }
12478
+ function writeIfChanged(value) {
12479
+ ensureCacheDir();
12480
+ const cacheFile = getCacheFilePath();
12481
+ const serialized = options.serialize?.(value) ?? JSON.stringify(value, null, 2);
12482
+ try {
12483
+ const existing = existsSync10(cacheFile) ? readFileSync3(cacheFile, "utf-8") : undefined;
12484
+ const unchanged = existing !== undefined && (existing === serialized || options.comparable !== undefined && JSON.stringify(options.comparable(JSON.parse(existing))) === JSON.stringify(options.comparable(value)));
12485
+ if (unchanged) {
12486
+ memoryValue = value;
12487
+ writtenInCurrentProcess = true;
12488
+ log2(`[${options.logPrefix}] ${options.cacheLabel} unchanged; skipped write`, options.describe(value));
12489
+ return false;
12490
+ }
12491
+ } catch {}
12492
+ try {
12493
+ writeFileSync4(cacheFile, serialized);
12494
+ memoryValue = value;
12495
+ writtenInCurrentProcess = true;
12496
+ log2(`[${options.logPrefix}] ${options.cacheLabel} written`, options.describe(value));
12497
+ return true;
12498
+ } catch (error) {
12499
+ log2(`[${options.logPrefix}] Error writing ${toLogLabel(options.cacheLabel)}`, {
12500
+ error: String(error)
12501
+ });
12502
+ return false;
12503
+ }
12504
+ }
12435
12505
  function resetMemory() {
12436
12506
  memoryValue = undefined;
12437
12507
  writtenInCurrentProcess = false;
@@ -12440,6 +12510,7 @@ function createJsonFileCacheStore(options) {
12440
12510
  read,
12441
12511
  has,
12442
12512
  write,
12513
+ writeIfChanged,
12443
12514
  resetMemory
12444
12515
  };
12445
12516
  }
@@ -67504,7 +67575,8 @@ function createModelCapabilitiesCacheStore(getCacheDir = getOmoOpenCodeCacheDir)
67504
67575
  generatedAt: snapshot.generatedAt
67505
67576
  }),
67506
67577
  serialize: (snapshot) => `${JSON.stringify(snapshot, null, 2)}
67507
- `
67578
+ `,
67579
+ comparable: ({ generatedAt: _generatedAt, ...catalog }) => catalog
67508
67580
  });
67509
67581
  function readModelCapabilitiesCache() {
67510
67582
  return snapshotCacheStore.read();
@@ -67517,7 +67589,7 @@ function createModelCapabilitiesCacheStore(getCacheDir = getOmoOpenCodeCacheDir)
67517
67589
  }
67518
67590
  async function refreshModelCapabilitiesCache(args = {}) {
67519
67591
  const snapshot = await fetchModelCapabilitiesSnapshot(args);
67520
- writeModelCapabilitiesCache(snapshot);
67592
+ snapshotCacheStore.writeIfChanged(snapshot);
67521
67593
  return snapshot;
67522
67594
  }
67523
67595
  return {
@@ -76962,6 +77034,7 @@ var init_agent = __esm(() => {
76962
77034
  prompt: string2().optional(),
76963
77035
  model: string2().optional(),
76964
77036
  models: array(OmoAgentModelEntrySchema).optional(),
77037
+ models_distribution: _enum(["sequential", "round_robin"]).optional(),
76965
77038
  reasoning: OmoReasoningSchema.optional(),
76966
77039
  variant: string2().optional(),
76967
77040
  reasoningEffort: OmoReasoningEffortSchema.optional(),
@@ -76994,6 +77067,7 @@ var init_category = __esm(() => {
76994
77067
  description: string2().optional(),
76995
77068
  model: string2().optional(),
76996
77069
  models: array(union([string2(), OmoFallbackModelObjectSchema])).optional(),
77070
+ models_distribution: _enum(["sequential", "round_robin"]).optional(),
76997
77071
  reasoning: OmoReasoningSchema.optional(),
76998
77072
  temperature: number2().min(0).max(2).optional(),
76999
77073
  top_p: number2().min(0).max(1).optional(),
@@ -77232,8 +77306,8 @@ var init_memory = __esm(() => {
77232
77306
  enabled: boolean2().optional()
77233
77307
  }).strict();
77234
77308
  OmoMemoryProjectionSchema = object({
77235
- max_entries_per_directory: number2().int().min(0).default(40),
77236
- max_bytes: number2().int().min(0).default(24576)
77309
+ max_entries_per_directory: number2().int().min(0).default(0),
77310
+ max_bytes: number2().int().min(0).default(40960)
77237
77311
  }).strict();
77238
77312
  OmoMemoryProjectionLayerSchema = object({
77239
77313
  max_entries_per_directory: number2().int().min(0).optional(),
@@ -77297,7 +77371,7 @@ var init_memory = __esm(() => {
77297
77371
  query_expansion: false
77298
77372
  }),
77299
77373
  project_scope: OmoMemoryProjectScopeSchema.default({ nudge: true, recall: true }),
77300
- projection: OmoMemoryProjectionSchema.default({ max_entries_per_directory: 40, max_bytes: 24576 }),
77374
+ projection: OmoMemoryProjectionSchema.default({ max_entries_per_directory: 0, max_bytes: 40960 }),
77301
77375
  compile_warn_tokens: number2().int().positive().default(30000),
77302
77376
  agents: record(string2(), OmoMemoryAgentOverridesSchema).default({})
77303
77377
  }).strict();
@@ -77345,6 +77419,21 @@ var init_model_catalog = __esm(() => {
77345
77419
  OmoModelCatalogLayerSchema = record(string2(), OmoModelCatalogEntryLayerSchema);
77346
77420
  });
77347
77421
 
77422
+ // packages/omo-config-core/src/schema/model-pad.ts
77423
+ var OmoModelPadLabelsSchema, OmoModelPadSchema;
77424
+ var init_model_pad = __esm(() => {
77425
+ init_zod();
77426
+ OmoModelPadLabelsSchema = object({
77427
+ daily: string2().optional(),
77428
+ geeky: string2().optional(),
77429
+ normal: string2().optional(),
77430
+ heavy: string2().optional()
77431
+ }).strict();
77432
+ OmoModelPadSchema = object({
77433
+ labels: OmoModelPadLabelsSchema.optional()
77434
+ }).strict();
77435
+ });
77436
+
77348
77437
  // packages/omo-config-core/src/schema/model-profile.ts
77349
77438
  function isRecord8(value) {
77350
77439
  return typeof value === "object" && value !== null && !Array.isArray(value);
@@ -77665,6 +77754,7 @@ var init_config = __esm(() => {
77665
77754
  init_git_master();
77666
77755
  init_memory();
77667
77756
  init_model_catalog();
77757
+ init_model_pad();
77668
77758
  init_model_profile();
77669
77759
  init_side_panel();
77670
77760
  init_task();
@@ -77686,6 +77776,7 @@ var init_config = __esm(() => {
77686
77776
  models: OmoModelCatalogLayerSchema.optional(),
77687
77777
  model_profiles: OmoModelProfilesLayerSchema.optional(),
77688
77778
  model_profile: string2().optional(),
77779
+ model_pad: OmoModelPadSchema.optional(),
77689
77780
  memory: OmoMemorySettingsLayerSchema.optional(),
77690
77781
  telemetry: OmoTelemetrySettingsLayerSchema.optional(),
77691
77782
  side_panel: OmoSidePanelSettingsLayerSchema.optional(),
@@ -77704,6 +77795,7 @@ var init_config = __esm(() => {
77704
77795
  models: OmoModelCatalogLayerSchema.optional(),
77705
77796
  model_profiles: OmoModelProfilesLayerSchema.optional(),
77706
77797
  model_profile: string2().optional(),
77798
+ model_pad: OmoModelPadSchema.optional(),
77707
77799
  memory: OmoMemorySettingsLayerSchema.optional(),
77708
77800
  telemetry: OmoTelemetrySettingsLayerSchema.optional(),
77709
77801
  side_panel: OmoSidePanelSettingsLayerSchema.optional(),
@@ -77727,6 +77819,7 @@ var init_config = __esm(() => {
77727
77819
  models: OmoModelCatalogSchema.optional(),
77728
77820
  model_profiles: OmoModelProfilesSchema.optional(),
77729
77821
  model_profile: string2().optional(),
77822
+ model_pad: OmoModelPadSchema.optional(),
77730
77823
  memory: OmoMemorySettingsSchema.optional(),
77731
77824
  telemetry: OmoTelemetrySettingsSchema.optional(),
77732
77825
  side_panel: OmoSidePanelSettingsSchema.optional(),
@@ -77753,6 +77846,7 @@ var init_config = __esm(() => {
77753
77846
  models: OmoModelCatalogLayerSchema.optional(),
77754
77847
  model_profiles: OmoModelProfilesLayerSchema.optional(),
77755
77848
  model_profile: string2().optional(),
77849
+ model_pad: OmoModelPadSchema.optional(),
77756
77850
  memory: OmoMemorySettingsLayerSchema.optional(),
77757
77851
  telemetry: OmoTelemetrySettingsLayerSchema.optional(),
77758
77852
  side_panel: OmoSidePanelSettingsLayerSchema.optional(),
@@ -77898,6 +77992,7 @@ var init_schema = __esm(() => {
77898
77992
  init_legacy_harness_names();
77899
77993
  init_memory();
77900
77994
  init_model_catalog();
77995
+ init_model_pad();
77901
77996
  init_model_profile();
77902
77997
  init_model_ref();
77903
77998
  init_provenance();
@@ -78816,9 +78911,13 @@ function resolveModelReferences(view) {
78816
78911
  }
78817
78912
  var init_model_reference_resolution = () => {};
78818
78913
 
78914
+ // packages/omo-config-core/src/models/models-distribution.ts
78915
+ var init_models_distribution = () => {};
78916
+
78819
78917
  // packages/omo-config-core/src/models/index.ts
78820
78918
  var init_models = __esm(() => {
78821
78919
  init_model_reference_resolution();
78920
+ init_models_distribution();
78822
78921
  });
78823
78922
 
78824
78923
  // packages/omo-config-core/src/writer/types.ts
@@ -82918,6 +83017,37 @@ function getDefaultTelemetryOsProvider() {
82918
83017
  }
82919
83018
  var init_machine_id = () => {};
82920
83019
 
83020
+ // packages/telemetry-core/src/terminal-program.ts
83021
+ function isKnownTerminalProgram(value) {
83022
+ return KNOWN_TERMINAL_PROGRAMS.some((known) => known === value);
83023
+ }
83024
+ function toTelemetryTerminalProgram(termProgram) {
83025
+ if (termProgram === undefined || termProgram === "")
83026
+ return;
83027
+ return isKnownTerminalProgram(termProgram) ? termProgram : "other";
83028
+ }
83029
+ var KNOWN_TERMINAL_PROGRAMS;
83030
+ var init_terminal_program = __esm(() => {
83031
+ KNOWN_TERMINAL_PROGRAMS = [
83032
+ "Apple_Terminal",
83033
+ "iTerm.app",
83034
+ "vscode",
83035
+ "cursor",
83036
+ "windsurf",
83037
+ "zed",
83038
+ "WezTerm",
83039
+ "ghostty",
83040
+ "tmux",
83041
+ "Hyper",
83042
+ "WarpTerminal",
83043
+ "kitty",
83044
+ "alacritty",
83045
+ "Tabby",
83046
+ "rio",
83047
+ "mintty"
83048
+ ];
83049
+ });
83050
+
82921
83051
  // packages/telemetry-core/src/injected-client.ts
82922
83052
  function isTelemetryClientEnabled(input) {
82923
83053
  const env = input.env ?? process.env;
@@ -83020,12 +83150,16 @@ function getSharedProperties(input) {
83020
83150
  total_memory_gb: Math.round(osProvider.totalmem() / 1024 / 1024 / 1024),
83021
83151
  locale: Intl.DateTimeFormat().resolvedOptions().locale,
83022
83152
  timezone: Intl.DateTimeFormat().resolvedOptions().timeZone,
83023
- shell: process.env.SHELL,
83153
+ shell: getShellName(process.env.SHELL),
83024
83154
  ci: Boolean(process.env.CI),
83025
- terminal: process.env.TERM_PROGRAM,
83155
+ terminal: toTelemetryTerminalProgram(process.env.TERM_PROGRAM),
83026
83156
  ...input.product.additionalProperties
83027
83157
  };
83028
83158
  }
83159
+ function getShellName(shellPath) {
83160
+ const name = shellPath?.split(/[\\/]/).pop()?.replace(/\.exe$/i, "");
83161
+ return name ? name : undefined;
83162
+ }
83029
83163
  function getSafeCpuInfo(osProvider, input) {
83030
83164
  try {
83031
83165
  const cpuInfo = osProvider.cpus();
@@ -83050,6 +83184,7 @@ var NO_OP_CLIENT;
83050
83184
  var init_injected_client = __esm(() => {
83051
83185
  init_env();
83052
83186
  init_machine_id();
83187
+ init_terminal_program();
83053
83188
  NO_OP_CLIENT = {
83054
83189
  enabled: false,
83055
83190
  trackActive: () => {
@@ -92629,7 +92764,7 @@ var package_default2;
92629
92764
  var init_package2 = __esm(() => {
92630
92765
  package_default2 = {
92631
92766
  name: "@oh-my-opencode/omo-codex",
92632
- version: "5.1.51",
92767
+ version: "5.1.55",
92633
92768
  type: "module",
92634
92769
  private: true,
92635
92770
  description: "Codex harness adapter for oh-my-openagent. Vendored Codex plugin namespace (omo) + TypeScript installer + telemetry.",
@@ -93837,11 +93972,22 @@ init_commander();
93837
93972
  // packages/omo-opencode/src/cli/install.ts
93838
93973
  init_package();
93839
93974
 
93975
+ // packages/omo-opencode/src/cli/cli-installer.ts
93976
+ import { createInterface as createInterface2 } from "node:readline/promises";
93977
+
93978
+ // packages/telemetry-core/src/install-disclosure.ts
93979
+ var TELEMETRY_PRIVACY_POLICY_URL = "https://github.com/code-yeongyu/oh-my-openagent/blob/dev/docs/legal/privacy-policy.md";
93980
+ var TELEMETRY_INSTALL_DISCLOSURE_LINES = [
93981
+ "OmO sends anonymous usage telemetry (no prompts, code, file paths, or account data) to improve the product.",
93982
+ "The data goes to PostHog in the United States.",
93983
+ "Turn it off with DO_NOT_TRACK=1 (or OMO_DISABLE_TELEMETRY=1).",
93984
+ `Details: ${TELEMETRY_PRIVACY_POLICY_URL}`
93985
+ ];
93986
+
93840
93987
  // packages/omo-opencode/src/cli/cli-installer.ts
93841
93988
  init_shared();
93842
93989
  init_config_manager();
93843
93990
  var import_picocolors3 = __toESM(require_picocolors(), 1);
93844
- import { createInterface as createInterface2 } from "node:readline/promises";
93845
93991
 
93846
93992
  // packages/omo-opencode/src/cli/install-validators.ts
93847
93993
  var import_picocolors = __toESM(require_picocolors(), 1);
@@ -100002,6 +100148,7 @@ var REQUIRED_PLUGIN_ARTIFACTS = [
100002
100148
  join66("extensions", "omo-thread-client.js"),
100003
100149
  join66("extensions", "omo-telemetry-recovery.js"),
100004
100150
  join66("extensions", "omo-feedback.js"),
100151
+ join66("extensions", "omo-desktop-toolkit.js"),
100005
100152
  join66("extensions", "omo-claim-receipt.js"),
100006
100153
  join66("extensions", "assets.generated.json"),
100007
100154
  join66("extensions", "omo-member.js"),
@@ -101280,8 +101427,8 @@ async function runCliInstaller(args, version) {
101280
101427
  }
101281
101428
  console.log();
101282
101429
  }
101283
- printInfo("Anonymous telemetry is enabled by default. Disable it with OMO_SEND_ANONYMOUS_TELEMETRY=0 or OMO_DISABLE_POSTHOG=1.");
101284
- printInfo("Docs: docs/legal/privacy-policy.md and docs/legal/terms-of-service.md");
101430
+ for (const line of TELEMETRY_INSTALL_DISCLOSURE_LINES)
101431
+ printInfo(line);
101285
101432
  console.log();
101286
101433
  printBox(`${import_picocolors3.default.bold("Pro Tip:")} Include ${import_picocolors3.default.cyan("ultrawork")} (or ${import_picocolors3.default.cyan("ulw")}) in your prompt.
101287
101434
  ` + `All features work like magic-parallel agents, background tasks,
@@ -102577,7 +102724,7 @@ async function promptInstallConfig(detected, platform, codexAutonomousOverride)
102577
102724
  message: "Do you have a Kimi For Coding subscription?",
102578
102725
  options: [
102579
102726
  { value: "no", label: "No", hint: "Will use other configured providers" },
102580
- { value: "yes", label: "Yes", hint: "Kimi K3 for Sisyphus/Prometheus fallback" }
102727
+ { value: "yes", label: "Yes", hint: "Kimi K3.1 Pro for Sisyphus/Prometheus fallback" }
102581
102728
  ],
102582
102729
  initialValue: initial.kimiForCoding
102583
102730
  });
@@ -102836,8 +102983,8 @@ async function runTuiInstaller(args, version) {
102836
102983
  if (config.hasOpenCode) {
102837
102984
  log4.message(`Run ${import_picocolors4.default.cyan("opencode")} to start!`);
102838
102985
  }
102839
- log4.info("Anonymous telemetry is enabled by default. Disable it with OMO_SEND_ANONYMOUS_TELEMETRY=0 or OMO_DISABLE_POSTHOG=1.");
102840
- log4.info("Docs: docs/legal/privacy-policy.md and docs/legal/terms-of-service.md");
102986
+ log4.info(TELEMETRY_INSTALL_DISCLOSURE_LINES.join(`
102987
+ `));
102841
102988
  note(`Include ${import_picocolors4.default.cyan("ultrawork")} (or ${import_picocolors4.default.cyan("ulw")}) in your prompt.
102842
102989
  ` + `All features work like magic-parallel agents, background tasks,
102843
102990
  ` + `deep exploration, and relentless execution until completion.`, "The Magic Word");
@@ -104070,11 +104217,11 @@ function recordFields(value, fields) {
104070
104217
  }
104071
104218
  function modelInput(view) {
104072
104219
  const agents = isPlainRecord(view.agents) ? Object.fromEntries(Object.entries(view.agents).flatMap(([name, definition]) => {
104073
- const fields = recordFields(definition, ["description", "prompt", "model", "models", "variant", "reasoningEffort", "tools", "temperature", "disable"]);
104220
+ const fields = recordFields(definition, ["description", "prompt", "model", "models", "models_distribution", "variant", "reasoningEffort", "tools", "temperature", "disable"]);
104074
104221
  return fields === undefined ? [] : [[name, fields]];
104075
104222
  })) : undefined;
104076
104223
  const categories = isPlainRecord(view.categories) ? Object.fromEntries(Object.entries(view.categories).flatMap(([name, definition]) => {
104077
- const fields = recordFields(definition, ["description", "model", "fallback_models", "variant", "temperature", "top_p", "maxTokens", "thinking", "reasoningEffort", "textVerbosity", "tools", "prompt_append", "max_prompt_tokens", "is_unstable_agent", "disable"]);
104224
+ const fields = recordFields(definition, ["description", "model", "models", "models_distribution", "fallback_models", "variant", "temperature", "top_p", "maxTokens", "thinking", "reasoningEffort", "textVerbosity", "tools", "prompt_append", "max_prompt_tokens", "is_unstable_agent", "disable"]);
104078
104225
  return fields === undefined ? [] : [[name, fields]];
104079
104226
  })) : undefined;
104080
104227
  return {
@@ -104348,6 +104495,7 @@ var AgentPermissionSchema = object({
104348
104495
  var AgentOverrideConfigSchema = object({
104349
104496
  model: string2().optional(),
104350
104497
  models: array(union([string2(), FallbackModelObjectSchema])).optional(),
104498
+ models_distribution: _enum(["sequential", "round_robin"]).optional(),
104351
104499
  fallback_models: FallbackModelsSchema.optional(),
104352
104500
  reasoning: OmoReasoningSchema.optional(),
104353
104501
  variant: string2().optional(),
@@ -104448,6 +104596,7 @@ var CategoryConfigSchema = object({
104448
104596
  description: string2().optional(),
104449
104597
  model: string2().optional(),
104450
104598
  models: array(union([string2(), FallbackModelObjectSchema])).optional(),
104599
+ models_distribution: _enum(["sequential", "round_robin"]).optional(),
104451
104600
  fallback_models: FallbackModelsSchema.optional(),
104452
104601
  reasoning: OmoReasoningSchema.optional(),
104453
104602
  variant: string2().optional(),
@@ -105011,7 +105160,8 @@ function materializeAgentModelChains(config) {
105011
105160
  return [name, {
105012
105161
  ...rest,
105013
105162
  ...primarySettings,
105014
- fallback_models: fallbacks
105163
+ fallback_models: fallbacks,
105164
+ ...agent.models_distribution === "round_robin" ? { models: agent.models } : {}
105015
105165
  }];
105016
105166
  }));
105017
105167
  return changed ? { ...config, agents } : config;
@@ -109374,6 +109524,8 @@ var package_default3 = {
109374
109524
  },
109375
109525
  dependencies: {
109376
109526
  "@clack/prompts": "^1.8.1",
109527
+ "@code-yeongyu/senpi": "2026.10.30-1",
109528
+ "@earendil-works/pi-ai": "npm:@code-yeongyu/senpi-ai@2026.10.30-1",
109377
109529
  "@modelcontextprotocol/sdk": "^1.30.0",
109378
109530
  "@oh-my-opencode/agents-md-core": "workspace:*",
109379
109531
  "@oh-my-opencode/boulder-state": "workspace:*",
@@ -110682,6 +110834,8 @@ function isOAuthTokenData(value) {
110682
110834
  if (typeof value !== "object" || value === null || Array.isArray(value))
110683
110835
  return false;
110684
110836
  const record = value;
110837
+ if (record["issuer"] !== undefined && typeof record["issuer"] !== "string")
110838
+ return false;
110685
110839
  if (typeof record["accessToken"] !== "string")
110686
110840
  return false;
110687
110841
  const refreshToken = record["refreshToken"];
@@ -110696,6 +110850,8 @@ function isOAuthTokenData(value) {
110696
110850
  if (typeof clientInfo !== "object" || clientInfo === null || Array.isArray(clientInfo))
110697
110851
  return false;
110698
110852
  const clientRecord = clientInfo;
110853
+ if (clientRecord["issuer"] !== undefined && typeof clientRecord["issuer"] !== "string")
110854
+ return false;
110699
110855
  if (typeof clientRecord["clientId"] !== "string")
110700
110856
  return false;
110701
110857
  const clientSecret = clientRecord["clientSecret"];
@@ -110764,7 +110920,9 @@ function deleteToken(serverHost, resource) {
110764
110920
  return deleteLegacyToken(serverHost, resource);
110765
110921
  try {
110766
110922
  unlinkSync9(filePath);
110767
- return deleteTokenIndexEntry(getMcpOauthStorageDir(), getMcpOauthServerHash(serverHost, resource));
110923
+ const indexDeleted = deleteTokenIndexEntry(getMcpOauthStorageDir(), getMcpOauthServerHash(serverHost, resource));
110924
+ const legacyDeleted = deleteLegacyToken(serverHost, resource);
110925
+ return indexDeleted && legacyDeleted;
110768
110926
  } catch (deleteError) {
110769
110927
  if (!(deleteError instanceof Error))
110770
110928
  throw deleteError;
@@ -110874,19 +111032,26 @@ async function fetchMetadata(url) {
110874
111032
  }
110875
111033
  return { ok: true, json };
110876
111034
  }
110877
- function parseMetadataFields(json, resource) {
111035
+ function parseMetadataFields(json, resource, expectedIssuer) {
111036
+ const issuer = readStringField(json, "issuer");
111037
+ parseHttpsUrl(issuer, "issuer");
111038
+ if (issuer !== expectedIssuer) {
111039
+ throw new Error("OAuth metadata issuer mismatch");
111040
+ }
110878
111041
  const authorizationEndpoint = parseHttpsUrl(readStringField(json, "authorization_endpoint"), "authorization_endpoint").toString();
110879
111042
  const tokenEndpoint = parseHttpsUrl(readStringField(json, "token_endpoint"), "token_endpoint").toString();
110880
111043
  const registrationEndpointValue = json.registration_endpoint;
110881
111044
  const registrationEndpoint = typeof registrationEndpointValue === "string" && registrationEndpointValue.length > 0 ? parseHttpsUrl(registrationEndpointValue, "registration_endpoint").toString() : undefined;
110882
111045
  return {
111046
+ issuer,
111047
+ ...json.authorization_response_iss_parameter_supported === true ? { authorizationResponseIssParameterSupported: true } : {},
110883
111048
  authorizationEndpoint,
110884
111049
  tokenEndpoint,
110885
111050
  registrationEndpoint,
110886
111051
  resource
110887
111052
  };
110888
111053
  }
110889
- async function fetchAuthorizationServerMetadata(issuer, resource) {
111054
+ async function fetchAuthorizationServerMetadata(issuer, resource, allowOriginFallback = false) {
110890
111055
  const issuerUrl = parseHttpsUrl(issuer, "Authorization server URL");
110891
111056
  const issuerPath = issuerUrl.pathname.replace(/\/+$/, "");
110892
111057
  const metadataUrl = new URL(`/.well-known/oauth-authorization-server${issuerPath}`, issuerUrl).toString();
@@ -110896,7 +111061,7 @@ async function fetchAuthorizationServerMetadata(issuer, resource) {
110896
111061
  const rootMetadataUrl = new URL("/.well-known/oauth-authorization-server", issuerUrl).toString();
110897
111062
  const rootMetadata = await fetchMetadata(rootMetadataUrl);
110898
111063
  if (rootMetadata.ok) {
110899
- return parseMetadataFields(rootMetadata.json, resource);
111064
+ return parseMetadataFields(rootMetadata.json, resource, allowOriginFallback ? issuerUrl.origin : issuer);
110900
111065
  }
110901
111066
  }
110902
111067
  if (metadata.status === 404) {
@@ -110904,7 +111069,7 @@ async function fetchAuthorizationServerMetadata(issuer, resource) {
110904
111069
  }
110905
111070
  throw new Error(`OAuth authorization server metadata fetch failed (${metadata.status})`);
110906
111071
  }
110907
- return parseMetadataFields(metadata.json, resource);
111072
+ return parseMetadataFields(metadata.json, resource, issuer);
110908
111073
  }
110909
111074
  function parseAuthorizationServers(metadata) {
110910
111075
  const servers = metadata.authorization_servers;
@@ -110912,11 +111077,11 @@ function parseAuthorizationServers(metadata) {
110912
111077
  return [];
110913
111078
  return servers.filter((server) => typeof server === "string" && server.length > 0);
110914
111079
  }
110915
- async function discoverOAuthServerMetadata(resource) {
111080
+ async function discoverOAuthServerMetadata(resource, forceRefresh = false) {
110916
111081
  const resourceUrl = parseHttpsUrl(resource, "Resource server URL");
110917
111082
  const resourceKey = resourceUrl.toString();
110918
111083
  const cached = discoveryCache.get(resourceKey);
110919
- if (cached)
111084
+ if (cached && !forceRefresh)
110920
111085
  return cached;
110921
111086
  const pending = pendingDiscovery.get(resourceKey);
110922
111087
  if (pending)
@@ -110934,7 +111099,7 @@ async function discoverOAuthServerMetadata(resource) {
110934
111099
  if (prmResponse.status !== 404) {
110935
111100
  throw new Error(`OAuth protected resource metadata fetch failed (${prmResponse.status})`);
110936
111101
  }
110937
- return fetchAuthorizationServerMetadata(resourceKey, resource);
111102
+ return fetchAuthorizationServerMetadata(resource.replace(/\/+$/, ""), resource, true);
110938
111103
  })();
110939
111104
  pendingDiscovery.set(resourceKey, discoveryPromise);
110940
111105
  try {
@@ -110958,6 +111123,10 @@ async function getOrRegisterClient(options) {
110958
111123
  }
110959
111124
  const fetchImpl = options.fetch ?? globalThis.fetch;
110960
111125
  const request = {
111126
+ application_type: options.redirectUris.some((uri) => {
111127
+ const url = new URL(uri);
111128
+ return (url.protocol === "http:" || url.protocol === "https:") && !["127.0.0.1", "localhost", "[::1]"].includes(url.hostname);
111129
+ }) ? "web" : "native",
110961
111130
  redirect_uris: options.redirectUris,
110962
111131
  client_name: options.clientName,
110963
111132
  grant_types: ["authorization_code", "refresh_token"],
@@ -111034,12 +111203,20 @@ function buildAuthorizationUrl(authorizationEndpoint, options) {
111034
111203
  return url.toString();
111035
111204
  }
111036
111205
  var CALLBACK_TIMEOUT_MS = 5 * 60 * 1000;
111037
- function startCallbackServer(port) {
111206
+ function startCallbackServer(port, validation) {
111038
111207
  return new Promise((resolve, reject) => {
111039
111208
  let timeoutId;
111040
111209
  const server = createServer2((request, response) => {
111041
111210
  clearTimeout(timeoutId);
111042
111211
  const requestUrl = new URL(request.url ?? "/", `http://localhost:${port}`);
111212
+ const issuer = requestUrl.searchParams.get("iss");
111213
+ if (validation && (issuer !== null && issuer !== validation.issuer || issuer === null && validation.authorizationResponseIssParameterSupported)) {
111214
+ response.writeHead(400, { "content-type": "text/html" });
111215
+ response.end("<html><body><h1>Authorization failed</h1></body></html>");
111216
+ server.close();
111217
+ reject(new Error("OAuth authorization response issuer mismatch or missing issuer"));
111218
+ return;
111219
+ }
111043
111220
  const code = requestUrl.searchParams.get("code");
111044
111221
  const state = requestUrl.searchParams.get("state");
111045
111222
  const error = requestUrl.searchParams.get("error");
@@ -111109,7 +111286,7 @@ async function runAuthorizationCodeRedirect(options) {
111109
111286
  scopes: options.scopes,
111110
111287
  resource: options.resource
111111
111288
  });
111112
- const callbackPromise = startCallbackServer(options.callbackPort);
111289
+ const callbackPromise = startCallbackServer(options.callbackPort, options);
111113
111290
  openBrowser(authorizationUrl);
111114
111291
  const result = await callbackPromise;
111115
111292
  if (result.state !== state) {
@@ -111144,10 +111321,12 @@ function buildOAuthTokenData(tokenData, clientInfo, fallbackRefreshToken) {
111144
111321
  throw new Error("Token response missing access_token");
111145
111322
  }
111146
111323
  return {
111324
+ ...clientInfo.issuer ? { issuer: clientInfo.issuer } : {},
111147
111325
  accessToken,
111148
111326
  refreshToken: typeof tokenData["refresh_token"] === "string" ? tokenData["refresh_token"] : fallbackRefreshToken,
111149
111327
  expiresAt: typeof tokenData["expires_in"] === "number" ? Math.floor(Date.now() / 1000) + tokenData["expires_in"] : undefined,
111150
111328
  clientInfo: {
111329
+ ...clientInfo.issuer ? { issuer: clientInfo.issuer } : {},
111151
111330
  clientId: clientInfo.clientId,
111152
111331
  ...clientInfo.clientSecret ? { clientSecret: clientInfo.clientSecret } : {}
111153
111332
  }
@@ -111161,6 +111340,7 @@ class McpOAuthProvider {
111161
111340
  storedCodeVerifier = null;
111162
111341
  storedClientInfo = null;
111163
111342
  callbackPort = null;
111343
+ issuer;
111164
111344
  constructor(options) {
111165
111345
  this.serverUrl = options.serverUrl;
111166
111346
  this.configClientId = options.clientId;
@@ -111170,7 +111350,32 @@ class McpOAuthProvider {
111170
111350
  return loadToken(this.serverUrl, this.serverUrl);
111171
111351
  }
111172
111352
  saveTokens(tokenData) {
111173
- return saveToken(this.serverUrl, this.serverUrl, tokenData);
111353
+ const issuer = tokenData.issuer ?? this.issuer;
111354
+ return saveToken(this.serverUrl, this.serverUrl, issuer ? {
111355
+ ...tokenData,
111356
+ issuer,
111357
+ ...tokenData.clientInfo ? { clientInfo: { ...tokenData.clientInfo, issuer: tokenData.clientInfo.issuer ?? issuer } } : {}
111358
+ } : tokenData);
111359
+ }
111360
+ bindIssuer(issuer) {
111361
+ const token = this.tokens();
111362
+ const stamps = [token?.issuer, token?.clientInfo?.issuer, this.storedClientInfo?.issuer, this.issuer];
111363
+ const changed = stamps.some((stamp) => stamp !== undefined && stamp !== issuer);
111364
+ if (changed) {
111365
+ this.storedClientInfo = null;
111366
+ this.storedCodeVerifier = null;
111367
+ if (!deleteToken(this.serverUrl, this.serverUrl)) {
111368
+ throw new Error("Unable to discard credentials for the previous OAuth issuer");
111369
+ }
111370
+ }
111371
+ this.issuer = issuer;
111372
+ if (!changed && token && !this.saveTokens(token)) {
111373
+ throw new Error("Unable to stamp stored OAuth credentials with their issuer");
111374
+ }
111375
+ const clientInfo = this.clientInformation();
111376
+ if (clientInfo)
111377
+ this.storedClientInfo = { ...clientInfo, issuer };
111378
+ return changed;
111174
111379
  }
111175
111380
  clientInformation() {
111176
111381
  if (this.storedClientInfo)
@@ -111200,6 +111405,8 @@ class McpOAuthProvider {
111200
111405
  this.callbackPort = await findAvailablePort2();
111201
111406
  }
111202
111407
  const result = await runAuthorizationCodeRedirect({
111408
+ issuer: metadata.issuer,
111409
+ authorizationResponseIssParameterSupported: metadata.authorizationResponseIssParameterSupported,
111203
111410
  authorizationEndpoint: metadata.authorizationEndpoint,
111204
111411
  callbackPort: this.callbackPort,
111205
111412
  clientId: clientInfo.clientId,
@@ -111211,16 +111418,19 @@ class McpOAuthProvider {
111211
111418
  return { code: result.code };
111212
111419
  }
111213
111420
  async login() {
111214
- const metadata = await discoverOAuthServerMetadata(this.serverUrl);
111421
+ const metadata = await discoverOAuthServerMetadata(this.serverUrl, true);
111422
+ this.bindIssuer(metadata.issuer);
111423
+ if (this.callbackPort === null)
111424
+ this.callbackPort = await findAvailablePort2();
111215
111425
  const clientRegistrationStorage = {
111216
111426
  getClientRegistration: () => this.storedClientInfo,
111217
111427
  setClientRegistration: (_serverIdentifier, credentials) => {
111218
- this.storedClientInfo = credentials;
111428
+ this.storedClientInfo = { ...credentials, issuer: metadata.issuer };
111219
111429
  }
111220
111430
  };
111221
111431
  const clientInfo = await getOrRegisterClient({
111222
111432
  ...metadata.registrationEndpoint ? { registrationEndpoint: metadata.registrationEndpoint } : {},
111223
- serverIdentifier: this.serverUrl,
111433
+ serverIdentifier: metadata.issuer,
111224
111434
  clientName: PLUGIN_NAME4,
111225
111435
  redirectUris: [this.redirectUrl()],
111226
111436
  tokenEndpointAuthMethod: "none",
@@ -111230,7 +111440,7 @@ class McpOAuthProvider {
111230
111440
  if (!clientInfo) {
111231
111441
  throw new Error("Failed to obtain client credentials. Provide a clientId or ensure the server supports DCR.");
111232
111442
  }
111233
- this.storedClientInfo = clientInfo;
111443
+ this.storedClientInfo = { ...clientInfo, issuer: metadata.issuer };
111234
111444
  const { code } = await this.redirectToAuthorization(metadata);
111235
111445
  const verifier = this.codeVerifier();
111236
111446
  if (!verifier) {
@@ -111249,12 +111459,14 @@ class McpOAuthProvider {
111249
111459
  }).toString()
111250
111460
  });
111251
111461
  const tokenData = await parseTokenResponse(tokenResponse);
111252
- const oauthTokenData = buildOAuthTokenData(tokenData, clientInfo);
111462
+ const oauthTokenData = buildOAuthTokenData(tokenData, { ...clientInfo, issuer: metadata.issuer });
111253
111463
  this.saveTokens(oauthTokenData);
111254
111464
  return oauthTokenData;
111255
111465
  }
111256
111466
  async refresh(refreshToken) {
111257
- const metadata = await discoverOAuthServerMetadata(this.serverUrl);
111467
+ const metadata = await discoverOAuthServerMetadata(this.serverUrl, true);
111468
+ if (this.bindIssuer(metadata.issuer))
111469
+ return this.login();
111258
111470
  const clientInfo = this.clientInformation();
111259
111471
  const clientId = clientInfo?.clientId ?? this.configClientId;
111260
111472
  if (!clientId) {
@@ -111274,6 +111486,7 @@ class McpOAuthProvider {
111274
111486
  const tokenData = await parseTokenResponse(tokenResponse);
111275
111487
  const oauthTokenData = buildOAuthTokenData(tokenData, {
111276
111488
  clientId,
111489
+ issuer: metadata.issuer,
111277
111490
  ...clientInfo?.clientSecret ? { clientSecret: clientInfo.clientSecret } : {}
111278
111491
  }, refreshToken);
111279
111492
  this.saveTokens(oauthTokenData);
@@ -112121,6 +112334,17 @@ import { hostname } from "node:os";
112121
112334
  // packages/omo-opencode/src/cli/service-auth/protocol.ts
112122
112335
  init_zod();
112123
112336
 
112337
+ // packages/omo-opencode/src/cli/service-auth/credential-owner.ts
112338
+ init_zod();
112339
+ var identity = string2().regex(/^[A-Za-z0-9_-]{1,128}$/);
112340
+ var credentialOwnerSchema = object({
112341
+ accountId: identity,
112342
+ deviceId: identity,
112343
+ familyId: identity,
112344
+ generation: number2().int().positive().safe(),
112345
+ ownerHandle: string2().regex(/^[\x21-\x7e]{1,4096}$/)
112346
+ });
112347
+
112124
112348
  // packages/omo-opencode/src/cli/service-auth/terminal-text.ts
112125
112349
  import { stripVTControlCharacters as stripVTControlCharacters4 } from "node:util";
112126
112350
  function terminalText(value) {
@@ -112139,9 +112363,19 @@ class SignInError extends Error {
112139
112363
 
112140
112364
  class RequestFailure extends SignInError {
112141
112365
  notSent;
112142
- constructor(notSent) {
112366
+ responseStatus;
112367
+ constructor(notSent, responseStatus) {
112143
112368
  super("Unable to complete the service request. Check the connection and retry.", true);
112144
112369
  this.notSent = notSent;
112370
+ this.responseStatus = responseStatus;
112371
+ }
112372
+ }
112373
+
112374
+ class InvalidApiResponse extends SignInError {
112375
+ status;
112376
+ constructor(status) {
112377
+ super("The service returned an invalid error response.");
112378
+ this.status = status;
112145
112379
  }
112146
112380
  }
112147
112381
  var platformSchema = _enum(["macos", "linux", "windows"]);
@@ -112154,12 +112388,18 @@ var tokenSchema = object({
112154
112388
  });
112155
112389
  var grantSchema = tokenSchema.extend({
112156
112390
  device: object({ id: nonempty, name: nonempty }),
112157
- offlineGrant: nonempty.optional()
112391
+ offlineGrant: nonempty.optional(),
112392
+ owner: credentialOwnerSchema.optional(),
112393
+ writerFloor: union([literal(1), literal(2)]).optional(),
112394
+ freshAuthorizationProof: nonempty.optional()
112158
112395
  });
112159
112396
  var credentialSchema = grantSchema.extend({
112160
112397
  signingPrivateKey: nonempty,
112161
112398
  sealingPrivateKey: nonempty,
112162
- refreshState: literal("uncertain").optional()
112399
+ refreshState: literal("uncertain").optional(),
112400
+ credentialGeneration: nonempty.optional(),
112401
+ accountId: nonempty.optional(),
112402
+ refreshAttempt: unknown().optional()
112163
112403
  });
112164
112404
  var deviceCodeSchema = object({
112165
112405
  deviceCode: string2().regex(/^dc\.[A-Za-z0-9_-]{43}$/),
@@ -112187,6 +112427,9 @@ var limitSchema = object({
112187
112427
  var deviceListSchema = object({
112188
112428
  devices: array(object({ id: nonempty, name: nonempty, revokedAt: timestamp.nullable() }))
112189
112429
  });
112430
+ var currentDeviceListSchema = object({
112431
+ devices: array(object({ id: nonempty, current: boolean2(), revokedAt: timestamp.nullable() }))
112432
+ });
112190
112433
  var REFUSAL_CODES = [
112191
112434
  "unauthorized",
112192
112435
  "account_deleted",
@@ -112203,7 +112446,11 @@ var REFUSAL_CODES = [
112203
112446
  "unavailable",
112204
112447
  "forbidden",
112205
112448
  "invalid_request",
112206
- "not_found"
112449
+ "not_found",
112450
+ "client_upgrade_required",
112451
+ "writer_floor_mismatch",
112452
+ "service_upgrade_required",
112453
+ "refresh_recovery_expired"
112207
112454
  ];
112208
112455
  var isKnownRefusal = (code) => REFUSAL_CODES.includes(code);
112209
112456
  function refusalGuidance(code, status) {
@@ -112230,6 +112477,10 @@ function refusalGuidance(code, status) {
112230
112477
  case "access_denied":
112231
112478
  case "authorization_pending":
112232
112479
  return "account_refused";
112480
+ case "client_upgrade_required":
112481
+ case "writer_floor_mismatch":
112482
+ case "service_upgrade_required":
112483
+ case "refresh_recovery_expired":
112233
112484
  case "unknown":
112234
112485
  if (status === 401)
112235
112486
  return "sign_in_again";
@@ -112340,13 +112591,13 @@ async function requestApi(api, path, init, signal) {
112340
112591
  try {
112341
112592
  body = await response.json();
112342
112593
  } catch {
112343
- throw new RequestFailure(false);
112594
+ throw new RequestFailure(false, response.status);
112344
112595
  }
112345
112596
  if (response.ok)
112346
112597
  return body;
112347
112598
  const envelope = envelopeSchema.safeParse(body);
112348
112599
  if (!envelope.success)
112349
- throw new SignInError("The service returned an invalid error response.");
112600
+ throw new InvalidApiResponse(response.status);
112350
112601
  const error = envelope.data.error;
112351
112602
  const detail = limitSchema.safeParse(error.detail);
112352
112603
  throw new ApiRefusal(error.code, response.status, error.code === "entitlement_required" && detail.success ? detail.data : undefined, response.headers.get("retry-after"));
@@ -112450,7 +112701,7 @@ async function loginDevice(session, options) {
112450
112701
  }
112451
112702
 
112452
112703
  // packages/omo-opencode/src/cli/service-auth/keystore.ts
112453
- import { createHash as createHash10 } from "node:crypto";
112704
+ import { createHash as createHash12, randomUUID as randomUUID7 } from "node:crypto";
112454
112705
  import { basename as basename15 } from "node:path";
112455
112706
 
112456
112707
  // packages/omo-opencode/src/cli/service-auth/secret-service-lock.ts
@@ -112494,289 +112745,490 @@ var probeSecretServiceLock = () => new Promise((resolve) => {
112494
112745
  });
112495
112746
  });
112496
112747
 
112497
- // packages/omo-opencode/src/cli/service-auth/keystore.ts
112498
- class CredentialStoreError extends SignInError {
112499
- }
112748
+ // packages/omo-opencode/src/cli/service-auth/credential-lock.ts
112749
+ import { AsyncLocalStorage as AsyncLocalStorage3 } from "node:async_hooks";
112750
+ import { createHash as createHash11 } from "node:crypto";
112751
+ import { mkdir as mkdir11 } from "node:fs/promises";
112752
+ import { homedir as homedir31 } from "node:os";
112753
+ import { join as join106 } from "node:path";
112500
112754
 
112501
- class KeychainLockedError extends CredentialStoreError {
112755
+ // packages/team-core/src/team-state-store/lock-publish.ts
112756
+ import { access as access4, open as open3, unlink as unlink3 } from "node:fs/promises";
112757
+ import { dirname as dirname42 } from "node:path";
112758
+
112759
+ // packages/team-core/src/team-state-store/lock-record.ts
112760
+ import { randomUUID as randomUUID6 } from "node:crypto";
112761
+ import { readFile as readFile34, stat as stat9 } from "node:fs/promises";
112762
+
112763
+ // packages/memory-core/src/locks/process-identity.ts
112764
+ import { execFile as execFile7 } from "node:child_process";
112765
+
112766
+ // packages/memory-core/src/fs/resilient.ts
112767
+ import * as fsSync from "node:fs";
112768
+ import * as fsp from "node:fs/promises";
112769
+
112770
+ // packages/memory-core/src/fs/retry.ts
112771
+ var EINTR_RETRY_CAP = 128;
112772
+ function fsErrorCode(error) {
112773
+ if (!(error instanceof Error) || !("code" in error))
112774
+ return;
112775
+ return typeof error.code === "string" ? error.code : undefined;
112502
112776
  }
112503
- class InvalidCredentialState extends SignInError {
112777
+ async function retryOnEintr(operation) {
112778
+ for (let attempt = 0;; attempt += 1) {
112779
+ try {
112780
+ return await operation();
112781
+ } catch (error) {
112782
+ if (fsErrorCode(error) !== "EINTR" || attempt >= EINTR_RETRY_CAP)
112783
+ throw error;
112784
+ }
112785
+ }
112786
+ }
112787
+ function retryOnEintrSync(operation) {
112788
+ for (let attempt = 0;; attempt += 1) {
112789
+ try {
112790
+ return operation();
112791
+ } catch (error) {
112792
+ if (fsErrorCode(error) !== "EINTR" || attempt >= EINTR_RETRY_CAP)
112793
+ throw error;
112794
+ }
112795
+ }
112504
112796
  }
112505
112797
 
112506
- class KeychainApprovalPendingError extends CredentialStoreError {
112798
+ // packages/memory-core/src/fs/rename-contention.ts
112799
+ var CONTENTION_CODES = new Set(["EPERM", "EBUSY", "EACCES"]);
112800
+
112801
+ // packages/memory-core/src/fs/resilient.ts
112802
+ function isFunction2(value) {
112803
+ return typeof value === "function";
112507
112804
  }
112508
- var SESSION_READ_WAIT = { kind: "bounded", deadlineMs: 5000 };
112509
- var INTERACTIVE_READ_WAIT = {
112510
- kind: "interactive",
112511
- noticeAfterMs: 2000,
112512
- notice: (message) => process.stderr.write(`${message}
112513
- `)
112514
- };
112515
- var processReads = new WeakMap;
112516
- var LOCKED = /-25308|errSecInteractionNotAllowed|interaction is not allowed|locked collection/i;
112517
- var UNLOCKED_REUSE_MS = 30000;
112518
- var fallbackNoticed = false;
112519
- var stderrNoticeOncePerProcess = (message) => {
112520
- if (fallbackNoticed)
112805
+ function withAsyncRetry(operation) {
112806
+ return (...args) => retryOnEintr(async () => operation(...args));
112807
+ }
112808
+ function withSyncRetry(operation) {
112809
+ return (...args) => retryOnEintrSync(() => operation(...args));
112810
+ }
112811
+ function resilientNamespace(namespace, kind) {
112812
+ const wrapFunction = kind === "async" ? withAsyncRetry : withSyncRetry;
112813
+ const cache = new Map;
112814
+ return new Proxy(namespace, {
112815
+ get(target, property) {
112816
+ if (cache.has(property))
112817
+ return cache.get(property);
112818
+ const value = Reflect.get(target, property);
112819
+ if (!isFunction2(value))
112820
+ return value;
112821
+ const wrapped = wrapFunction(value);
112822
+ const native = Reflect.get(value, "native");
112823
+ if (isFunction2(native))
112824
+ Object.assign(wrapped, { native: wrapFunction(native) });
112825
+ cache.set(property, wrapped);
112826
+ return wrapped;
112827
+ }
112828
+ });
112829
+ }
112830
+ var IDEMPOTENT_HANDLE_METHODS = new Set(["stat", "sync", "datasync", "chmod", "chown", "utimes", "truncate"]);
112831
+ var promises = resilientNamespace(fsp, "async");
112832
+ var sync = resilientNamespace(fsSync, "sync");
112833
+ var {
112834
+ access: access3,
112835
+ chmod: chmod2,
112836
+ copyFile: copyFile4,
112837
+ cp: cp5,
112838
+ link,
112839
+ lstat: lstat18,
112840
+ mkdir: mkdir10,
112841
+ mkdtemp: mkdtemp2,
112842
+ readFile: readFile33,
112843
+ readdir: readdir17,
112844
+ readlink: readlink7,
112845
+ realpath: realpath2,
112846
+ rm: rm16,
112847
+ rmdir: rmdir2,
112848
+ stat: stat8,
112849
+ statfs,
112850
+ unlink: unlink2
112851
+ } = promises;
112852
+ var {
112853
+ accessSync: accessSync5,
112854
+ chmodSync: chmodSync7,
112855
+ fsyncSync: fsyncSync3,
112856
+ linkSync,
112857
+ lstatSync: lstatSync5,
112858
+ mkdirSync: mkdirSync19,
112859
+ readFileSync: readFileSync44,
112860
+ readdirSync: readdirSync14,
112861
+ realpathSync: realpathSync13,
112862
+ statSync: statSync8,
112863
+ unlinkSync: unlinkSync10,
112864
+ writeFileSync: writeFileSync17,
112865
+ writeSync
112866
+ } = sync;
112867
+
112868
+ // packages/memory-core/src/locks/process-start-time.ts
112869
+ var PROC_PIDTBSDINFO = 3;
112870
+ var PROC_BSDINFO_SIZE = 136;
112871
+ var START_TVSEC_OFFSET = 120;
112872
+ var procPidInfoLookup = null;
112873
+ async function openProcPidInfo() {
112874
+ if (process.platform !== "darwin")
112875
+ return null;
112876
+ try {
112877
+ const { dlopen, FFIType } = await import("bun:ffi");
112878
+ const library = dlopen("/usr/lib/libSystem.B.dylib", {
112879
+ proc_pidinfo: {
112880
+ args: [FFIType.i32, FFIType.i32, FFIType.u64, FFIType.ptr, FFIType.i32],
112881
+ returns: FFIType.i32
112882
+ }
112883
+ });
112884
+ return (pid, flavor, arg, buffer, size) => Number(library.symbols.proc_pidinfo(pid, flavor, arg, buffer, size));
112885
+ } catch {
112886
+ return null;
112887
+ }
112888
+ }
112889
+ function loadProcPidInfo() {
112890
+ procPidInfoLookup ??= openProcPidInfo();
112891
+ return procPidInfoLookup;
112892
+ }
112893
+ async function readDarwinProcessStartSeconds(pid) {
112894
+ if (process.platform !== "darwin")
112895
+ return null;
112896
+ if (!Number.isSafeInteger(pid) || pid <= 0)
112897
+ return null;
112898
+ const procPidInfo = await loadProcPidInfo();
112899
+ if (procPidInfo === null)
112900
+ return null;
112901
+ const buffer = new Uint8Array(PROC_BSDINFO_SIZE);
112902
+ let written = 0;
112903
+ try {
112904
+ written = procPidInfo(pid, PROC_PIDTBSDINFO, 0n, buffer, PROC_BSDINFO_SIZE);
112905
+ } catch {
112906
+ return null;
112907
+ }
112908
+ if (written !== PROC_BSDINFO_SIZE)
112909
+ return null;
112910
+ const view = new DataView(buffer.buffer, buffer.byteOffset, buffer.byteLength);
112911
+ const startSeconds = Number(view.getBigUint64(START_TVSEC_OFFSET, true));
112912
+ return startSeconds > 0 ? startSeconds : null;
112913
+ }
112914
+ var PROCESS_QUERY_LIMITED_INFORMATION = 4096;
112915
+ var kernel32Lookup = null;
112916
+ async function openKernel32() {
112917
+ if (process.platform !== "win32")
112918
+ return null;
112919
+ try {
112920
+ const { dlopen, FFIType } = await import("bun:ffi");
112921
+ const library = dlopen("kernel32.dll", {
112922
+ OpenProcess: { args: [FFIType.u32, FFIType.i32, FFIType.u32], returns: FFIType.ptr },
112923
+ GetProcessTimes: { args: [FFIType.ptr, FFIType.ptr, FFIType.ptr, FFIType.ptr, FFIType.ptr], returns: FFIType.i32 },
112924
+ CloseHandle: { args: [FFIType.ptr], returns: FFIType.i32 }
112925
+ });
112926
+ return library.symbols;
112927
+ } catch {
112928
+ return null;
112929
+ }
112930
+ }
112931
+ async function readWin32ProcessCreationFiletime(pid) {
112932
+ if (process.platform !== "win32")
112933
+ return null;
112934
+ if (!Number.isSafeInteger(pid) || pid <= 0)
112935
+ return null;
112936
+ kernel32Lookup ??= openKernel32();
112937
+ const kernel32 = await kernel32Lookup;
112938
+ if (kernel32 === null)
112939
+ return null;
112940
+ const handle = kernel32.OpenProcess(PROCESS_QUERY_LIMITED_INFORMATION, 0, pid);
112941
+ if (handle === null || handle === 0 || handle === 0n)
112942
+ return null;
112943
+ try {
112944
+ const creation = new BigUint64Array(1);
112945
+ const ok = kernel32.GetProcessTimes(handle, creation, new BigUint64Array(1), new BigUint64Array(1), new BigUint64Array(1));
112946
+ const filetime = creation[0] ?? 0n;
112947
+ return ok === 0 || filetime === 0n ? null : filetime;
112948
+ } finally {
112949
+ kernel32.CloseHandle(handle);
112950
+ }
112951
+ }
112952
+
112953
+ // packages/memory-core/src/locks/process-identity.ts
112954
+ function errorCode(error) {
112955
+ if (!(error instanceof Error) || !("code" in error))
112521
112956
  return;
112522
- fallbackNoticed = true;
112523
- process.stderr.write(`${message}
112524
- `);
112525
- };
112526
- var isLocked = (error) => error instanceof Error && (LOCKED.test(error.message) || LOCKED.test(String(error.code ?? "")));
112527
- function credentialId(api) {
112528
- return createHash10("sha256").update(serviceOrigin(api)).digest("hex");
112957
+ return typeof error.code === "string" ? error.code : undefined;
112529
112958
  }
112530
- function createCredentialStore(api, options = {}) {
112531
- return createSealedStore(api, "omo-cli", credentialSchema, options.secrets, options.platform, options.lockProbe, options.notice, options.wait);
112959
+ async function execFileText(command, args) {
112960
+ return await new Promise((resolve) => {
112961
+ execFile7(command, args, { encoding: "utf8", timeout: 2000, windowsHide: true }, (error, stdout) => {
112962
+ if (error !== null) {
112963
+ resolve(null);
112964
+ return;
112965
+ }
112966
+ const value = stdout.trim();
112967
+ resolve(value.length > 0 ? value : null);
112968
+ });
112969
+ });
112532
112970
  }
112533
- function createSealedStore(api, namespace, schema, secrets = typeof Bun === "undefined" ? null : Bun.secrets, platform = process.platform, lockProbe = probeSecretServiceLock, notice = stderrNoticeOncePerProcess, wait = SESSION_READ_WAIT) {
112534
- if (!secrets)
112535
- throw new SignInError("OmO sign-in needs Bun 1.4 or newer with OS credential storage. No file fallback is available.");
112536
- const platformName = platform === "darwin" ? "macOS Keychain" : platform === "linux" ? "Linux Secret Service (libsecret and an unlocked keyring)" : platform === "win32" ? "Windows Credential Manager" : null;
112537
- if (platformName === null)
112538
- throw new SignInError("This platform has no supported OS credential store.");
112539
- const key = { service: namespace, name: credentialId(api) };
112540
- const slot = `${key.service}
112541
- ${key.name}`;
112542
- const readsOf = (api) => {
112543
- const known = processReads.get(api);
112544
- if (known !== undefined)
112545
- return known;
112546
- const created = new Map;
112547
- processReads.set(api, created);
112548
- return created;
112549
- };
112550
- const forget = (api) => {
112551
- readsOf(api).delete(slot);
112552
- };
112553
- const sharedRead = (api) => {
112554
- const reads = readsOf(api);
112555
- const pending = reads.get(slot);
112556
- if (pending !== undefined)
112557
- return pending;
112558
- const read = Promise.resolve().then(() => api.get(key));
112559
- const done = () => {
112560
- if (reads.get(slot) === read)
112561
- reads.delete(slot);
112562
- };
112563
- read.then(done, done);
112564
- reads.set(slot, read);
112565
- return read;
112971
+ async function readLinuxStartIdentity(pid) {
112972
+ try {
112973
+ const stat = await readFile33(`/proc/${pid}/stat`, "utf8");
112974
+ const commandEnd = stat.lastIndexOf(")");
112975
+ if (commandEnd < 0)
112976
+ return null;
112977
+ const fieldsAfterCommand = stat.slice(commandEnd + 2).trim().split(/\s+/);
112978
+ const startTicks = fieldsAfterCommand[19];
112979
+ return startTicks === undefined ? null : `linux-proc-start-ticks:${startTicks}`;
112980
+ } catch {
112981
+ return null;
112982
+ }
112983
+ }
112984
+ async function readWin32StartIdentity(pid) {
112985
+ if (getPidLiveness(pid) === "dead")
112986
+ return null;
112987
+ const creationFiletime = await readWin32ProcessCreationFiletime(pid);
112988
+ if (creationFiletime !== null)
112989
+ return `win32-creation-filetime:${creationFiletime}`;
112990
+ const value = await execFileText("powershell.exe", [
112991
+ "-NoProfile",
112992
+ "-Command",
112993
+ `(Get-Process -Id ${pid} -ErrorAction SilentlyContinue).StartTime.ToUniversalTime().ToString('o')`
112994
+ ]);
112995
+ return value === null ? null : `win32-creation-date:${value}`;
112996
+ }
112997
+ function createProcessStartIdentityReader(read, ownPid) {
112998
+ let ownIdentity;
112999
+ return (pid) => {
113000
+ if (pid !== ownPid)
113001
+ return read(pid);
113002
+ ownIdentity ??= read(pid).then((identity) => {
113003
+ if (identity === null)
113004
+ ownIdentity = undefined;
113005
+ return identity;
113006
+ }, (error) => {
113007
+ ownIdentity = undefined;
113008
+ throw error;
113009
+ });
113010
+ return ownIdentity;
112566
113011
  };
112567
- const waiting = platform === "darwin" ? `macOS Keychain is waiting for your approval: answer the "${basename15(process.execPath)} wants to access key ${namespace}" dialog ("Always Allow" stops it asking again)` : `${platformName} has not answered; it may be waiting for your approval or an unlock in a system dialog`;
112568
- const answered = async (api) => {
112569
- const read = sharedRead(api);
112570
- let timer;
112571
- try {
112572
- if (wait.kind === "interactive") {
112573
- timer = setTimeout(() => wait.notice(`omo: ${waiting}.`), wait.noticeAfterMs);
112574
- return await read;
112575
- }
112576
- const expired = new Promise((_, reject) => {
112577
- timer = setTimeout(() => reject(new KeychainApprovalPendingError(`${waiting}, then try again. Credentials are never saved to a file.`)), wait.deadlineMs);
112578
- });
112579
- return await Promise.race([read, expired]);
112580
- } finally {
112581
- clearTimeout(timer);
112582
- }
113012
+ }
113013
+ var getProcessStartIdentity = createProcessStartIdentityReader(readProcessStartIdentity, process.pid);
113014
+ async function readProcessStartIdentity(pid) {
113015
+ if (process.platform === "linux")
113016
+ return await readLinuxStartIdentity(pid);
113017
+ if (process.platform === "darwin" || process.platform === "freebsd") {
113018
+ if (getPidLiveness(pid) === "dead")
113019
+ return null;
113020
+ const startSeconds = await readDarwinProcessStartSeconds(pid);
113021
+ if (startSeconds !== null)
113022
+ return `proc-start-epoch:${startSeconds}`;
113023
+ const value = await execFileText("/bin/ps", ["-o", "lstart=", "-p", String(pid)]);
113024
+ return value === null ? null : `ps-lstart:${value.replace(/\s+/g, " ")}`;
113025
+ }
113026
+ if (process.platform === "win32")
113027
+ return await readWin32StartIdentity(pid);
113028
+ return null;
113029
+ }
113030
+ function identityScheme(identity) {
113031
+ const separator = identity.indexOf(":");
113032
+ return separator <= 0 ? null : identity.slice(0, separator);
113033
+ }
113034
+ function startIdentitiesConflict(recorded, actual) {
113035
+ const recordedScheme = identityScheme(recorded);
113036
+ if (recordedScheme === null || recordedScheme !== identityScheme(actual))
113037
+ return false;
113038
+ return recorded !== actual;
113039
+ }
113040
+ function getPidLiveness(pid) {
113041
+ try {
113042
+ process.kill(pid, 0);
113043
+ return "alive";
113044
+ } catch (error) {
113045
+ const code = errorCode(error);
113046
+ if (code === "ESRCH")
113047
+ return "dead";
113048
+ if (code === "EPERM")
113049
+ return "alive";
113050
+ return "unknown";
113051
+ }
113052
+ }
113053
+
113054
+ // packages/team-core/src/team-state-store/lock-worker-lifetime.ts
113055
+ init_zod();
113056
+ import { randomUUID as randomUUID5 } from "node:crypto";
113057
+ import { BroadcastChannel, parentPort, threadId } from "node:worker_threads";
113058
+ var Registration = object({
113059
+ kind: literal("omo-team-lock-register-v1"),
113060
+ incarnation: string2(),
113061
+ challenge: string2()
113062
+ });
113063
+ var Message = discriminatedUnion("kind", [
113064
+ object({ kind: literal("query"), id: string2(), incarnation: string2(), record: string2() }),
113065
+ object({ kind: literal("answer"), id: string2(), released: boolean2() }),
113066
+ object({ kind: literal("hello"), threadId: number2() }),
113067
+ object({ kind: literal("register"), threadId: number2(), challenge: string2() })
113068
+ ]);
113069
+ function createState() {
113070
+ const channel = new BroadcastChannel(`omo-team-lock-lifetime-v1-${process.pid}`);
113071
+ channel.unref();
113072
+ const state = {
113073
+ incarnation: randomUUID5(),
113074
+ records: new Map,
113075
+ exited: new Set,
113076
+ observed: new WeakSet,
113077
+ observing: new Map,
113078
+ pending: new Map,
113079
+ channel,
113080
+ installed: false,
113081
+ registered: parentPort === null,
113082
+ registration: undefined,
113083
+ onRegistered: undefined
112583
113084
  };
112584
- const unavailable = (error) => isLocked(error) ? new KeychainLockedError(`${platformName} is locked. Unlock it, then try again. Credentials are never saved to a file.`) : new CredentialStoreError(`Cannot access ${platformName}. Unlock or enable the OS credential store and try again. Credentials are never saved to a file.`);
112585
- let unlockedUntil = 0;
112586
- let noticed = false;
112587
- const assertUsable = async () => {
112588
- if (platform !== "linux" || Date.now() < unlockedUntil)
112589
- return;
112590
- const lock = await lockProbe();
112591
- if (lock === "locked")
112592
- throw new KeychainLockedError(`${platformName} is locked. Unlock it, then try again. Credentials are never saved to a file.`);
112593
- if (lock === "unlocked") {
112594
- unlockedUntil = Date.now() + UNLOCKED_REUSE_MS;
113085
+ channel.onmessage = (event) => {
113086
+ const parsed = Message.safeParse(event.data);
113087
+ if (!parsed.success)
112595
113088
  return;
112596
- }
112597
- if (!noticed) {
112598
- noticed = true;
112599
- notice("omo: could not check whether the keyring is locked (gdbus or the Secret Service did not answer); using libsecret directly.");
112600
- }
112601
- };
112602
- return {
112603
- async read() {
112604
- await assertUsable();
112605
- let value;
112606
- try {
112607
- value = await answered(secrets);
112608
- } catch (error) {
112609
- if (error instanceof KeychainApprovalPendingError)
112610
- throw error;
112611
- throw unavailable(error);
112612
- }
112613
- if (value === null)
112614
- return null;
112615
- try {
112616
- return schema.parse(JSON.parse(value));
112617
- } catch {
112618
- throw new InvalidCredentialState(signInRoute() === "cli" ? "Stored sign-in data is invalid. Run omo logout, then omo login." : "The OmO sign-in saved on this computer can't be read, and it can't be reset from the terminal yet.");
113089
+ const message = parsed.data;
113090
+ switch (message.kind) {
113091
+ case "hello": {
113092
+ const observed = state.observing.get(message.threadId);
113093
+ if (observed !== undefined) {
113094
+ channel.postMessage({ kind: "register", threadId: message.threadId, challenge: observed.challenge });
113095
+ }
113096
+ return;
112619
113097
  }
112620
- },
112621
- async write(value) {
112622
- await assertUsable();
112623
- try {
112624
- await secrets.set({ ...key, value: JSON.stringify(schema.parse(value)) });
112625
- } catch (error) {
112626
- throw unavailable(error);
113098
+ case "register":
113099
+ if (message.threadId === threadId) {
113100
+ parentPort?.postMessage({
113101
+ kind: "omo-team-lock-register-v1",
113102
+ incarnation: state.incarnation,
113103
+ challenge: message.challenge
113104
+ });
113105
+ state.registered = true;
113106
+ state.onRegistered?.();
113107
+ }
113108
+ return;
113109
+ case "answer":
113110
+ state.pending.get(message.id)?.(message.released);
113111
+ return;
113112
+ case "query": {
113113
+ const status = message.incarnation === state.incarnation ? state.records.get(message.record) : undefined;
113114
+ if (status !== undefined || state.exited.has(message.incarnation)) {
113115
+ channel.postMessage({
113116
+ kind: "answer",
113117
+ id: message.id,
113118
+ released: status === "released" || state.exited.has(message.incarnation)
113119
+ });
113120
+ }
113121
+ return;
112627
113122
  }
112628
- forget(secrets);
112629
- },
112630
- async clear() {
112631
- await assertUsable();
112632
- try {
112633
- await secrets.delete(key);
112634
- } catch (error) {
112635
- throw unavailable(error);
113123
+ default: {
113124
+ const unexpected = message;
113125
+ throw new Error(`Unexpected lock lifetime message: ${unexpected}`);
112636
113126
  }
112637
- forget(secrets);
112638
113127
  }
112639
113128
  };
113129
+ return state;
112640
113130
  }
112641
-
112642
- // packages/omo-opencode/src/cli/service-auth/loopback.ts
112643
- import { createHash as createHash11, randomBytes as randomBytes5, timingSafeEqual } from "node:crypto";
112644
- import { createServer as createServer3 } from "node:http";
112645
- class BrowserUnavailable extends SignInError {
112646
- }
112647
- async function authorize(options) {
112648
- const verifier = randomBytes5(32).toString("base64url");
112649
- const state = randomBytes5(32).toString("base64url");
112650
- const answer = Promise.withResolvers();
112651
- const abort = () => answer.reject(new SignInError("Browser sign-in cancelled or timed out."));
112652
- let accepted = false;
112653
- let origin = "";
112654
- const server = createServer3((request, response) => {
112655
- response.setHeader("cache-control", "no-store");
112656
- response.setHeader("referrer-policy", "no-referrer");
112657
- response.setHeader("content-type", "text/plain; charset=utf-8");
112658
- const url = new URL(request.url ?? "/", origin);
112659
- if (request.method !== "GET" || request.headers.host !== new URL(origin).host || url.origin !== origin || url.pathname !== "/callback" || request.headers.forwarded || request.headers["x-forwarded-for"]) {
112660
- response.writeHead(404).end("Not found");
112661
- return;
112662
- }
112663
- const code = url.searchParams.get("code");
112664
- const suppliedState = Buffer.from(url.searchParams.get("state") ?? "");
112665
- const expectedState = Buffer.from(state);
112666
- if (accepted || url.searchParams.getAll("state").length !== 1 || suppliedState.length !== expectedState.length || !timingSafeEqual(suppliedState, expectedState) || url.searchParams.getAll("code").length !== 1 || !code) {
112667
- response.writeHead(400).end("Invalid sign-in response");
113131
+ var state2 = globalThis.__omoTeamLockLifetimeV1 ??= createState();
113132
+ var lockOwnerInstanceId = state2.incarnation;
113133
+ function attachWorker(worker) {
113134
+ if (state2.observed.has(worker))
113135
+ return;
113136
+ state2.observed.add(worker);
113137
+ const id = worker.threadId;
113138
+ const challenge = randomUUID5();
113139
+ state2.observing.set(id, { worker, challenge });
113140
+ const incarnations = new Set;
113141
+ let exited = false;
113142
+ worker.on("message", (message) => {
113143
+ const parsed = Registration.safeParse(message);
113144
+ if (!parsed.success || parsed.data.challenge !== challenge)
112668
113145
  return;
112669
- }
112670
- accepted = true;
112671
- response.writeHead(200).end("Return to the terminal to finish signing in.");
112672
- answer.resolve(code);
113146
+ incarnations.add(parsed.data.incarnation);
113147
+ if (exited)
113148
+ state2.exited.add(parsed.data.incarnation);
112673
113149
  });
112674
- try {
112675
- await new Promise((resolve, reject) => {
112676
- server.once("error", reject);
112677
- server.listen(0, "127.0.0.1", () => {
112678
- server.off("error", reject);
112679
- resolve();
112680
- });
112681
- });
112682
- const address = server.address();
112683
- if (!address || typeof address === "string")
112684
- throw new SignInError("Unable to start the sign-in callback.");
112685
- origin = `http://127.0.0.1:${address.port}`;
112686
- const url = new URL(serviceOrigin(options.accounts));
112687
- url.search = new URLSearchParams({
112688
- redirect_uri: `${origin}/callback`,
112689
- code_challenge: createHash11("sha256").update(verifier).digest("base64url"),
112690
- code_challenge_method: "S256",
112691
- state
112692
- }).toString();
112693
- const timer = setTimeout(abort, 5 * 60000);
112694
- options.signal?.addEventListener("abort", abort, { once: true });
112695
- try {
112696
- options.signal?.throwIfAborted();
112697
- const openerFailed = () => {
112698
- if (!accepted)
112699
- throw new BrowserUnavailable("No browser is available; use device sign-in.");
112700
- };
112701
- const [code] = await Promise.all([
112702
- answer.promise,
112703
- options.open(url.href).then((opened) => {
112704
- if (!opened)
112705
- openerFailed();
112706
- }, openerFailed)
112707
- ]);
112708
- return { code, codeVerifier: verifier };
112709
- } finally {
113150
+ worker.once("exit", () => {
113151
+ exited = true;
113152
+ if (state2.observing.get(id)?.worker === worker)
113153
+ state2.observing.delete(id);
113154
+ for (const incarnation of incarnations)
113155
+ state2.exited.add(incarnation);
113156
+ });
113157
+ }
113158
+ function installLockWorkerObserver() {
113159
+ if (state2.installed)
113160
+ return;
113161
+ state2.installed = true;
113162
+ process.on("worker", attachWorker);
113163
+ state2.channel.postMessage({ kind: "hello", threadId });
113164
+ }
113165
+ installLockWorkerObserver();
113166
+ async function registerLockWorker() {
113167
+ if (state2.registered)
113168
+ return;
113169
+ state2.registration ??= new Promise((resolve) => {
113170
+ const finish = () => {
112710
113171
  clearTimeout(timer);
112711
- options.signal?.removeEventListener("abort", abort);
112712
- }
112713
- } finally {
112714
- server.closeAllConnections();
112715
- await new Promise((resolve) => server.close(() => resolve()));
112716
- }
113172
+ state2.onRegistered = undefined;
113173
+ resolve();
113174
+ };
113175
+ const timer = setTimeout(finish, 250);
113176
+ state2.onRegistered = finish;
113177
+ state2.channel.postMessage({ kind: "hello", threadId });
113178
+ });
113179
+ await state2.registration;
112717
113180
  }
112718
- async function loginLoopback(session, options) {
112719
- await session.ready();
112720
- const keys = generateDeviceKeys();
112721
- for (;; ) {
112722
- const authorization = await authorize({ accounts: options.accounts, open: options.open, signal: session.signal });
112723
- try {
112724
- const grant = parseReply(grantSchema, await session.request("/v1/session/exchange", jsonRequest({
112725
- ...authorization,
112726
- kind: "cli",
112727
- deviceName: options.name,
112728
- platform: options.platform,
112729
- ...keys.public
112730
- })));
112731
- await session.save({ ...grant, ...keys.private });
112732
- return;
112733
- } catch (error) {
112734
- if (await session.removeForLimit(error, options.chooseDevice))
112735
- continue;
112736
- throw new SignInError("Sign-in cancelled. No device was removed.");
112737
- }
112738
- }
113181
+ function markLockRecordHeld(record) {
113182
+ state2.records.set(record, "held");
113183
+ }
113184
+ function markLockRecordReleased(record) {
113185
+ if (state2.records.has(record))
113186
+ state2.records.set(record, "released");
113187
+ }
113188
+ function forgetLockRecord(record) {
113189
+ state2.records.delete(record);
113190
+ }
113191
+ async function isWorkerLockReleased(incarnation, record) {
113192
+ if (state2.exited.has(incarnation))
113193
+ return true;
113194
+ if (incarnation === state2.incarnation)
113195
+ return state2.records.get(record) === "released";
113196
+ const id = randomUUID5();
113197
+ return await new Promise((resolve) => {
113198
+ const finish = (released) => {
113199
+ clearTimeout(timer);
113200
+ state2.pending.delete(id);
113201
+ resolve(released);
113202
+ };
113203
+ const timer = setTimeout(() => finish(false), 250);
113204
+ state2.pending.set(id, finish);
113205
+ state2.channel.postMessage({ kind: "query", id, incarnation, record });
113206
+ });
112739
113207
  }
112740
-
112741
- // packages/omo-opencode/src/cli/service-auth/session.ts
112742
- import { mkdir as mkdir11 } from "node:fs/promises";
112743
- import { homedir as homedir31 } from "node:os";
112744
- import { join as join107 } from "node:path";
112745
-
112746
- // packages/team-core/src/team-state-store/lock-publish.ts
112747
- import { access as access3, open as open2, unlink as unlink2 } from "node:fs/promises";
112748
- import { dirname as dirname42 } from "node:path";
112749
113208
 
112750
113209
  // packages/team-core/src/team-state-store/lock-record.ts
112751
- import { randomUUID as randomUUID5 } from "node:crypto";
112752
- import { readFile as readFile33, stat as stat8 } from "node:fs/promises";
112753
- var lockOwnerInstanceId = randomUUID5();
112754
- var heldLockRecords = new Set;
112755
- function buildLockRecord(ownerTag) {
112756
- return `${ownerTag} ${randomUUID5()}
113210
+ async function buildLockRecord(ownerTag) {
113211
+ await registerLockWorker();
113212
+ const processStart = await getProcessStartIdentity(process.pid);
113213
+ return `${ownerTag} ${randomUUID6()}
112757
113214
  ${process.pid}
112758
113215
  ${Date.now()}
112759
113216
  ${lockOwnerInstanceId}
113217
+ ${processStart ?? "unavailable"}
112760
113218
  `;
112761
113219
  }
112762
- function markLockRecordHeld(content) {
112763
- heldLockRecords.add(content);
112764
- }
112765
- function markLockRecordReleased(content) {
112766
- heldLockRecords.delete(content);
112767
- }
112768
- function errorCode(error) {
113220
+ function errorCode2(error) {
112769
113221
  if (!(error instanceof Error) || !("code" in error))
112770
113222
  return null;
112771
113223
  return typeof error.code === "string" ? error.code : null;
112772
113224
  }
112773
113225
  function isPathAbsenceError(error) {
112774
- const code = errorCode(error);
113226
+ const code = errorCode2(error);
112775
113227
  return code === "ENOENT" || code === "ENOTDIR";
112776
113228
  }
112777
113229
  function parseLockOwner(content) {
112778
113230
  const lines = content.split(/\r?\n/).filter((line) => line.length > 0);
112779
- if (lines.length !== 3 && lines.length !== 4)
113231
+ if (lines.length !== 3 && lines.length !== 4 && lines.length !== 5)
112780
113232
  return null;
112781
113233
  const ownerPid = Number.parseInt(lines[1] ?? "", 10);
112782
113234
  const acquiredAtEpochMs = Number.parseInt(lines[2] ?? "", 10);
@@ -112787,24 +113239,14 @@ function parseLockOwner(content) {
112787
113239
  return {
112788
113240
  ownerPid,
112789
113241
  acquiredAtEpochMs,
112790
- instanceId: lines.length === 4 ? lines[3] ?? null : null
113242
+ instanceId: lines[3] ?? null,
113243
+ processStart: lines[4] ?? null
112791
113244
  };
112792
113245
  }
112793
- function isPidAlive(pid) {
112794
- try {
112795
- process.kill(pid, 0);
112796
- return true;
112797
- } catch (error) {
112798
- if (!(error instanceof Error)) {
112799
- throw error;
112800
- }
112801
- return false;
112802
- }
112803
- }
112804
113246
  async function readLockRecord(lockPath) {
112805
113247
  try {
112806
- const content = await readFile33(lockPath, "utf8");
112807
- const { mtimeMs } = await stat8(lockPath);
113248
+ const content = await readFile34(lockPath, "utf8");
113249
+ const { mtimeMs } = await stat9(lockPath);
112808
113250
  return { content, modifiedAtEpochMs: mtimeMs };
112809
113251
  } catch (error) {
112810
113252
  if (!(error instanceof Error))
@@ -112812,23 +113254,30 @@ async function readLockRecord(lockPath) {
112812
113254
  return null;
112813
113255
  }
112814
113256
  }
112815
- function isLockRecordStale(record, staleAfterMs) {
113257
+ async function isLockRecordStale(record, staleAfterMs) {
112816
113258
  const owner = parseLockOwner(record.content);
112817
113259
  if (owner === null)
112818
113260
  return Date.now() - record.modifiedAtEpochMs > staleAfterMs;
112819
- if (owner.instanceId !== null && owner.ownerPid === process.pid) {
112820
- return owner.instanceId !== lockOwnerInstanceId || !heldLockRecords.has(record.content);
113261
+ const liveness = getPidLiveness(owner.ownerPid);
113262
+ if (liveness === "dead") {
113263
+ return owner.instanceId !== null || Date.now() - owner.acquiredAtEpochMs > staleAfterMs;
112821
113264
  }
112822
- if (isPidAlive(owner.ownerPid))
113265
+ if (liveness === "unknown")
112823
113266
  return false;
112824
- if (owner.instanceId !== null)
112825
- return true;
112826
- return Date.now() - owner.acquiredAtEpochMs > staleAfterMs;
113267
+ if (owner.processStart !== null) {
113268
+ const actual = await getProcessStartIdentity(owner.ownerPid);
113269
+ if (actual !== null && startIdentitiesConflict(owner.processStart, actual))
113270
+ return true;
113271
+ }
113272
+ if (owner.instanceId !== null && owner.ownerPid === process.pid) {
113273
+ return await isWorkerLockReleased(owner.instanceId, record.content);
113274
+ }
113275
+ return false;
112827
113276
  }
112828
113277
 
112829
113278
  // packages/team-core/src/team-state-store/lock-publish.ts
112830
113279
  async function pathMayExist(path, deps = {}) {
112831
- const accessPath = deps.access ?? access3;
113280
+ const accessPath = deps.access ?? access4;
112832
113281
  try {
112833
113282
  await accessPath(path);
112834
113283
  return true;
@@ -112839,7 +113288,7 @@ async function pathMayExist(path, deps = {}) {
112839
113288
  }
112840
113289
  }
112841
113290
  async function assertRetryableLockOpenError(lockPath, error, deps) {
112842
- const code = errorCode(error);
113291
+ const code = errorCode2(error);
112843
113292
  if (code === "EEXIST")
112844
113293
  return;
112845
113294
  if (code === "EPERM") {
@@ -112854,9 +113303,9 @@ async function publishLockRecord(lockPath, record) {
112854
113303
  markLockRecordHeld(record);
112855
113304
  let fileHandle;
112856
113305
  try {
112857
- fileHandle = await open2(lockPath, "wx");
113306
+ fileHandle = await open3(lockPath, "wx");
112858
113307
  } catch (error) {
112859
- markLockRecordReleased(record);
113308
+ forgetLockRecord(record);
112860
113309
  await assertRetryableLockOpenError(lockPath, error);
112861
113310
  return false;
112862
113311
  }
@@ -112865,7 +113314,7 @@ async function publishLockRecord(lockPath, record) {
112865
113314
  } catch (error) {
112866
113315
  markLockRecordReleased(record);
112867
113316
  await fileHandle.close();
112868
- await unlink2(lockPath).catch(() => {
113317
+ await unlink3(lockPath).catch(() => {
112869
113318
  return;
112870
113319
  });
112871
113320
  throw error;
@@ -112875,8 +113324,8 @@ async function publishLockRecord(lockPath, record) {
112875
113324
  }
112876
113325
 
112877
113326
  // packages/team-core/src/team-state-store/lock-reclaim.ts
112878
- import { createHash as createHash12 } from "node:crypto";
112879
- import { unlink as unlink3 } from "node:fs/promises";
113327
+ import { createHash as createHash10 } from "node:crypto";
113328
+ import { unlink as unlink4 } from "node:fs/promises";
112880
113329
  var RECLAIM_UNLINK_ATTEMPTS = 3;
112881
113330
  var RECLAIM_UNLINK_RETRY_MS = 25;
112882
113331
  function delay2(ms) {
@@ -112885,11 +113334,11 @@ function delay2(ms) {
112885
113334
  });
112886
113335
  }
112887
113336
  function reclaimGuardPath(lockPath, record) {
112888
- return `${lockPath}.reclaim-${createHash12("sha256").update(record).digest("hex").slice(0, 16)}`;
113337
+ return `${lockPath}.reclaim-${createHash10("sha256").update(record).digest("hex").slice(0, 16)}`;
112889
113338
  }
112890
113339
  async function unlinkWithRetry(path, deps) {
112891
113340
  const wait = deps.delay ?? delay2;
112892
- const unlinkFile = deps.unlink ?? unlink3;
113341
+ const unlinkFile = deps.unlink ?? unlink4;
112893
113342
  for (let attempt = 1;; attempt += 1) {
112894
113343
  try {
112895
113344
  await unlinkFile(path);
@@ -112899,7 +113348,7 @@ async function unlinkWithRetry(path, deps) {
112899
113348
  throw error;
112900
113349
  if (isPathAbsenceError(error))
112901
113350
  return "absent";
112902
- const code = errorCode(error);
113351
+ const code = errorCode2(error);
112903
113352
  if (code !== "EPERM" && code !== "EBUSY" || attempt === RECLAIM_UNLINK_ATTEMPTS)
112904
113353
  return "stuck";
112905
113354
  await wait(RECLAIM_UNLINK_RETRY_MS);
@@ -112908,10 +113357,10 @@ async function unlinkWithRetry(path, deps) {
112908
113357
  }
112909
113358
  async function removeLockRecordIfUnchanged(lockPath, expectedRecord, staleAfterMs, deps = {}) {
112910
113359
  const guardPath = reclaimGuardPath(lockPath, expectedRecord);
112911
- const guardRecord = buildLockRecord("lock-reclaim");
113360
+ const guardRecord = await buildLockRecord("lock-reclaim");
112912
113361
  if (!await publishLockRecord(guardPath, guardRecord)) {
112913
113362
  const guard = await readLockRecord(guardPath);
112914
- if (guard !== null && isLockRecordStale(guard, staleAfterMs)) {
113363
+ if (guard !== null && await isLockRecordStale(guard, staleAfterMs)) {
112915
113364
  await removeLockRecordIfUnchanged(guardPath, guard.content, staleAfterMs, deps);
112916
113365
  }
112917
113366
  return "busy";
@@ -112920,13 +113369,16 @@ async function removeLockRecordIfUnchanged(lockPath, expectedRecord, staleAfterM
112920
113369
  const current = await readLockRecord(lockPath);
112921
113370
  if (current === null)
112922
113371
  return "absent";
112923
- if (current.content !== expectedRecord || !isLockRecordStale(current, staleAfterMs))
113372
+ if (current.content !== expectedRecord || !await isLockRecordStale(current, staleAfterMs))
112924
113373
  return "changed";
112925
113374
  const unlinked = await unlinkWithRetry(lockPath, deps);
113375
+ if (unlinked !== "stuck")
113376
+ forgetLockRecord(expectedRecord);
112926
113377
  return unlinked === "absent" ? "absent" : unlinked;
112927
113378
  } finally {
112928
113379
  markLockRecordReleased(guardRecord);
112929
- await unlinkWithRetry(guardPath, deps);
113380
+ if (await unlinkWithRetry(guardPath, deps) !== "stuck")
113381
+ forgetLockRecord(guardRecord);
112930
113382
  }
112931
113383
  }
112932
113384
 
@@ -112945,7 +113397,7 @@ async function acquireLock(lockPath, ownerTag, staleAfterMs) {
112945
113397
  if (Date.now() - startedAt > LOCK_WAIT_TIMEOUT_MS) {
112946
113398
  throw new Error(`Timed out acquiring lock: ${lockPath}`);
112947
113399
  }
112948
- const record = buildLockRecord(ownerTag);
113400
+ const record = await buildLockRecord(ownerTag);
112949
113401
  if (await publishLockRecord(lockPath, record))
112950
113402
  return record;
112951
113403
  const outcome = await reapStaleLock(lockPath, staleAfterMs);
@@ -112962,26 +113414,327 @@ async function withLock(lockPath, fn, opts) {
112962
113414
  return await fn();
112963
113415
  } finally {
112964
113416
  markLockRecordReleased(record);
112965
- await removeLockRecordIfUnchanged(lockPath, record, staleAfterMs);
113417
+ const outcome = await removeLockRecordIfUnchanged(lockPath, record, staleAfterMs);
113418
+ if (outcome === "removed" || outcome === "absent" || outcome === "changed")
113419
+ forgetLockRecord(record);
112966
113420
  }
112967
113421
  }
112968
113422
  async function reapStaleLock(lockPath, staleAfterMs = DEFAULT_STALE_AFTER_MS, deps = {}) {
112969
113423
  const observed = await readLockRecord(lockPath);
112970
113424
  if (observed === null)
112971
113425
  return "absent";
112972
- if (!isLockRecordStale(observed, staleAfterMs))
113426
+ if (!await isLockRecordStale(observed, staleAfterMs))
112973
113427
  return "changed";
112974
113428
  return await removeLockRecordIfUnchanged(lockPath, observed.content, staleAfterMs, deps);
112975
113429
  }
112976
113430
 
113431
+ // packages/omo-opencode/src/cli/service-auth/credential-lock.ts
113432
+ var held = new AsyncLocalStorage3;
113433
+ function credentialLockPaths(api, home = homedir31()) {
113434
+ const id = createHash11("sha256").update(serviceOrigin(api)).digest("hex");
113435
+ const directory = join106(home, ".omo", "session-locks");
113436
+ return { directory, lock: join106(directory, `${id}.lock`), desktopRecord: join106(directory, `${id}.desktop-generation.json`) };
113437
+ }
113438
+ async function withCredentialLock(api, action, home = homedir31(), ownerTag = "cli-session") {
113439
+ const { directory, lock } = credentialLockPaths(api, home);
113440
+ const owned = held.getStore();
113441
+ if (owned?.has(lock))
113442
+ return action();
113443
+ await mkdir11(directory, { recursive: true, mode: 448 });
113444
+ return withLock(lock, () => held.run(new Set([...owned ?? [], lock]), action), {
113445
+ ownerTag,
113446
+ staleAfterMs: Number.POSITIVE_INFINITY
113447
+ });
113448
+ }
113449
+
113450
+ // packages/omo-opencode/src/cli/service-auth/keystore.ts
113451
+ class CredentialStoreError extends SignInError {
113452
+ }
113453
+
113454
+ class KeychainLockedError extends CredentialStoreError {
113455
+ }
113456
+ class InvalidCredentialState extends SignInError {
113457
+ }
113458
+
113459
+ class CredentialIdentityChanged extends Error {
113460
+ constructor() {
113461
+ super("The stored sign-in changed; the captured account is no longer current.");
113462
+ }
113463
+ }
113464
+
113465
+ class KeychainApprovalPendingError extends CredentialStoreError {
113466
+ }
113467
+ var SESSION_READ_WAIT = { kind: "bounded", deadlineMs: 5000 };
113468
+ var INTERACTIVE_READ_WAIT = {
113469
+ kind: "interactive",
113470
+ noticeAfterMs: 2000,
113471
+ notice: (message) => process.stderr.write(`${message}
113472
+ `)
113473
+ };
113474
+ var processReads = new WeakMap;
113475
+ var LOCKED = /-25308|errSecInteractionNotAllowed|interaction is not allowed|locked collection/i;
113476
+ var UNLOCKED_REUSE_MS = 30000;
113477
+ var fallbackNoticed = false;
113478
+ var stderrNoticeOncePerProcess = (message) => {
113479
+ if (fallbackNoticed)
113480
+ return;
113481
+ fallbackNoticed = true;
113482
+ process.stderr.write(`${message}
113483
+ `);
113484
+ };
113485
+ var isLocked = (error) => error instanceof Error && (LOCKED.test(error.message) || LOCKED.test(String(error.code ?? "")));
113486
+ function credentialId(api) {
113487
+ return createHash12("sha256").update(serviceOrigin(api)).digest("hex");
113488
+ }
113489
+ function createCredentialStore(api, options = {}) {
113490
+ const store = createSealedStore(api, "omo-cli", credentialSchema, options.secrets, options.platform, options.lockProbe, options.notice, options.wait, (current, value) => {
113491
+ const sameIdentity = current !== null && current.device.id === value.device.id && current.signingPrivateKey === value.signingPrivateKey && current.sealingPrivateKey === value.sealingPrivateKey && (value.accountId === undefined || current.accountId === undefined || current.accountId === value.accountId);
113492
+ const accountId = value.accountId ?? (sameIdentity ? current?.accountId : undefined);
113493
+ return {
113494
+ ...value,
113495
+ ...accountId === undefined ? {} : { accountId },
113496
+ credentialGeneration: sameIdentity ? current?.credentialGeneration ?? randomUUID7() : randomUUID7()
113497
+ };
113498
+ });
113499
+ return {
113500
+ read: store.read,
113501
+ readAuthoritative: store.readAuthoritative,
113502
+ write: (value) => withCredentialLock(api, () => store.write(value), options.home),
113503
+ clear: () => withCredentialLock(api, store.clear, options.home)
113504
+ };
113505
+ }
113506
+ function createSealedStore(api, namespace, schema, secrets = typeof Bun === "undefined" ? null : Bun.secrets, platform = process.platform, lockProbe = probeSecretServiceLock, notice = stderrNoticeOncePerProcess, wait = SESSION_READ_WAIT, amendWrite) {
113507
+ if (!secrets)
113508
+ throw new SignInError("OmO sign-in needs Bun 1.4 or newer with OS credential storage. No file fallback is available.");
113509
+ const platformName = platform === "darwin" ? "macOS Keychain" : platform === "linux" ? "Linux Secret Service (libsecret and an unlocked keyring)" : platform === "win32" ? "Windows Credential Manager" : null;
113510
+ if (platformName === null)
113511
+ throw new SignInError("This platform has no supported OS credential store.");
113512
+ const key = { service: namespace, name: credentialId(api) };
113513
+ const slot = `${key.service}
113514
+ ${key.name}`;
113515
+ const readsOf = (api) => {
113516
+ const known = processReads.get(api);
113517
+ if (known !== undefined)
113518
+ return known;
113519
+ const created = new Map;
113520
+ processReads.set(api, created);
113521
+ return created;
113522
+ };
113523
+ const forget = (api) => {
113524
+ readsOf(api).delete(slot);
113525
+ };
113526
+ const sharedRead = (api) => {
113527
+ const reads = readsOf(api);
113528
+ const pending = reads.get(slot);
113529
+ if (pending !== undefined)
113530
+ return pending;
113531
+ const read = Promise.resolve().then(() => api.get(key));
113532
+ const done = () => {
113533
+ if (reads.get(slot) === read)
113534
+ reads.delete(slot);
113535
+ };
113536
+ read.then(done, done);
113537
+ reads.set(slot, read);
113538
+ return read;
113539
+ };
113540
+ const waiting = platform === "darwin" ? `macOS Keychain is waiting for your approval: answer the "${basename15(process.execPath)} wants to access key ${namespace}" dialog ("Always Allow" stops it asking again)` : `${platformName} has not answered; it may be waiting for your approval or an unlock in a system dialog`;
113541
+ const answered = async (api, fresh = false) => {
113542
+ const read = fresh ? Promise.resolve().then(() => api.get(key)) : sharedRead(api);
113543
+ let timer;
113544
+ try {
113545
+ if (wait.kind === "interactive") {
113546
+ timer = setTimeout(() => wait.notice(`omo: ${waiting}.`), wait.noticeAfterMs);
113547
+ return await read;
113548
+ }
113549
+ const expired = new Promise((_, reject) => {
113550
+ timer = setTimeout(() => reject(new KeychainApprovalPendingError(`${waiting}, then try again. Credentials are never saved to a file.`)), wait.deadlineMs);
113551
+ });
113552
+ return await Promise.race([read, expired]);
113553
+ } finally {
113554
+ clearTimeout(timer);
113555
+ }
113556
+ };
113557
+ const unavailable = (error) => isLocked(error) ? new KeychainLockedError(`${platformName} is locked. Unlock it, then try again. Credentials are never saved to a file.`) : new CredentialStoreError(`Cannot access ${platformName}. Unlock or enable the OS credential store and try again. Credentials are never saved to a file.`);
113558
+ let unlockedUntil = 0;
113559
+ let noticed = false;
113560
+ const assertUsable = async () => {
113561
+ if (platform !== "linux" || Date.now() < unlockedUntil)
113562
+ return;
113563
+ const lock = await lockProbe();
113564
+ if (lock === "locked")
113565
+ throw new KeychainLockedError(`${platformName} is locked. Unlock it, then try again. Credentials are never saved to a file.`);
113566
+ if (lock === "unlocked") {
113567
+ unlockedUntil = Date.now() + UNLOCKED_REUSE_MS;
113568
+ return;
113569
+ }
113570
+ if (!noticed) {
113571
+ noticed = true;
113572
+ notice("omo: could not check whether the keyring is locked (gdbus or the Secret Service did not answer); using libsecret directly.");
113573
+ }
113574
+ };
113575
+ const parsedRead = async (fresh) => {
113576
+ await assertUsable();
113577
+ let value;
113578
+ try {
113579
+ value = await answered(secrets, fresh);
113580
+ } catch (error) {
113581
+ if (error instanceof KeychainApprovalPendingError)
113582
+ throw error;
113583
+ throw unavailable(error);
113584
+ }
113585
+ if (value === null)
113586
+ return null;
113587
+ try {
113588
+ return schema.parse(JSON.parse(value));
113589
+ } catch {
113590
+ throw new InvalidCredentialState(signInRoute() === "cli" ? "Stored sign-in data is invalid. Run omo account forget, then omo login." : "The OmO sign-in saved on this computer can't be read. Run omo account forget to remove it, then sign in again in the desktop app.");
113591
+ }
113592
+ };
113593
+ return {
113594
+ read: () => parsedRead(false),
113595
+ readAuthoritative: () => parsedRead(true),
113596
+ async write(value) {
113597
+ await assertUsable();
113598
+ try {
113599
+ let next = value;
113600
+ if (amendWrite !== undefined) {
113601
+ const raw = await answered(secrets, true);
113602
+ let previous = null;
113603
+ if (raw !== null) {
113604
+ try {
113605
+ previous = schema.parse(JSON.parse(raw));
113606
+ } catch {}
113607
+ }
113608
+ next = amendWrite(previous, value);
113609
+ }
113610
+ await secrets.set({ ...key, value: JSON.stringify(schema.parse(next)) });
113611
+ } catch (error) {
113612
+ throw unavailable(error);
113613
+ }
113614
+ forget(secrets);
113615
+ },
113616
+ async clear() {
113617
+ await assertUsable();
113618
+ try {
113619
+ await secrets.delete(key);
113620
+ } catch (error) {
113621
+ throw unavailable(error);
113622
+ }
113623
+ forget(secrets);
113624
+ }
113625
+ };
113626
+ }
113627
+
113628
+ // packages/omo-opencode/src/cli/service-auth/loopback.ts
113629
+ import { createHash as createHash13, randomBytes as randomBytes5, timingSafeEqual } from "node:crypto";
113630
+ import { createServer as createServer3 } from "node:http";
113631
+ class BrowserUnavailable extends SignInError {
113632
+ }
113633
+ async function authorize(options) {
113634
+ const verifier = randomBytes5(32).toString("base64url");
113635
+ const state = randomBytes5(32).toString("base64url");
113636
+ const answer = Promise.withResolvers();
113637
+ const abort = () => answer.reject(new SignInError("Browser sign-in cancelled or timed out."));
113638
+ let accepted = false;
113639
+ let origin = "";
113640
+ const server = createServer3((request, response) => {
113641
+ response.setHeader("cache-control", "no-store");
113642
+ response.setHeader("referrer-policy", "no-referrer");
113643
+ response.setHeader("content-type", "text/plain; charset=utf-8");
113644
+ const url = new URL(request.url ?? "/", origin);
113645
+ if (request.method !== "GET" || request.headers.host !== new URL(origin).host || url.origin !== origin || url.pathname !== "/callback" || request.headers.forwarded || request.headers["x-forwarded-for"]) {
113646
+ response.writeHead(404).end("Not found");
113647
+ return;
113648
+ }
113649
+ const code = url.searchParams.get("code");
113650
+ const suppliedState = Buffer.from(url.searchParams.get("state") ?? "");
113651
+ const expectedState = Buffer.from(state);
113652
+ if (accepted || url.searchParams.getAll("state").length !== 1 || suppliedState.length !== expectedState.length || !timingSafeEqual(suppliedState, expectedState) || url.searchParams.getAll("code").length !== 1 || !code) {
113653
+ response.writeHead(400).end("Invalid sign-in response");
113654
+ return;
113655
+ }
113656
+ accepted = true;
113657
+ response.writeHead(200).end("Return to the terminal to finish signing in.");
113658
+ answer.resolve(code);
113659
+ });
113660
+ try {
113661
+ await new Promise((resolve, reject) => {
113662
+ server.once("error", reject);
113663
+ server.listen(0, "127.0.0.1", () => {
113664
+ server.off("error", reject);
113665
+ resolve();
113666
+ });
113667
+ });
113668
+ const address = server.address();
113669
+ if (!address || typeof address === "string")
113670
+ throw new SignInError("Unable to start the sign-in callback.");
113671
+ origin = `http://127.0.0.1:${address.port}`;
113672
+ const url = new URL(serviceOrigin(options.accounts));
113673
+ url.search = new URLSearchParams({
113674
+ redirect_uri: `${origin}/callback`,
113675
+ code_challenge: createHash13("sha256").update(verifier).digest("base64url"),
113676
+ code_challenge_method: "S256",
113677
+ state
113678
+ }).toString();
113679
+ const timer = setTimeout(abort, 5 * 60000);
113680
+ options.signal?.addEventListener("abort", abort, { once: true });
113681
+ try {
113682
+ options.signal?.throwIfAborted();
113683
+ const openerFailed = () => {
113684
+ if (!accepted)
113685
+ throw new BrowserUnavailable("No browser is available; use device sign-in.");
113686
+ };
113687
+ const [code] = await Promise.all([
113688
+ answer.promise,
113689
+ options.open(url.href).then((opened) => {
113690
+ if (!opened)
113691
+ openerFailed();
113692
+ }, openerFailed)
113693
+ ]);
113694
+ return { code, codeVerifier: verifier };
113695
+ } finally {
113696
+ clearTimeout(timer);
113697
+ options.signal?.removeEventListener("abort", abort);
113698
+ }
113699
+ } finally {
113700
+ server.closeAllConnections();
113701
+ await new Promise((resolve) => server.close(() => resolve()));
113702
+ }
113703
+ }
113704
+ async function loginLoopback(session, options) {
113705
+ await session.ready();
113706
+ const keys = generateDeviceKeys();
113707
+ for (;; ) {
113708
+ const authorization = await authorize({ accounts: options.accounts, open: options.open, signal: session.signal });
113709
+ try {
113710
+ const grant = parseReply(grantSchema, await session.request("/v1/session/exchange", jsonRequest({
113711
+ ...authorization,
113712
+ kind: "cli",
113713
+ deviceName: options.name,
113714
+ platform: options.platform,
113715
+ ...keys.public
113716
+ })));
113717
+ await session.save({ ...grant, ...keys.private });
113718
+ return;
113719
+ } catch (error) {
113720
+ if (await session.removeForLimit(error, options.chooseDevice))
113721
+ continue;
113722
+ throw new SignInError("Sign-in cancelled. No device was removed.");
113723
+ }
113724
+ }
113725
+ }
113726
+
113727
+ // packages/omo-opencode/src/cli/service-auth/session.ts
113728
+ import { homedir as homedir32 } from "node:os";
113729
+
112977
113730
  // packages/omo-opencode/src/cli/service-auth/signed-out-marker.ts
112978
113731
  init_zod();
112979
- import { mkdir as mkdir10, readFile as readFile34, rename as rename7, rm as rm16, writeFile as writeFile16 } from "node:fs/promises";
112980
- import { dirname as dirname43, join as join106 } from "node:path";
113732
+ import { mkdir as mkdir12, readFile as readFile35, rename as rename8, rm as rm17, writeFile as writeFile17 } from "node:fs/promises";
113733
+ import { dirname as dirname43, join as join107 } from "node:path";
112981
113734
  var markerSchema = object({ device: string2().nullable(), at: string2() });
112982
- var signedOutMarkerPath = (home, credential) => join106(home, ".omo", "account-state", `${credential}.signed-out.json`);
113735
+ var signedOutMarkerPath = (home, credential) => join107(home, ".omo", "account-state", `${credential}.signed-out.json`);
112983
113736
  async function readSignedOutMarker(path) {
112984
- const text = await readFile34(path, "utf8").catch(() => null);
113737
+ const text = await readFile35(path, "utf8").catch(() => null);
112985
113738
  if (text === null)
112986
113739
  return null;
112987
113740
  let value;
@@ -112994,12 +113747,12 @@ async function readSignedOutMarker(path) {
112994
113747
  return parsed.success ? parsed.data : null;
112995
113748
  }
112996
113749
  async function writeSignedOutMarker(path, device) {
112997
- await mkdir10(dirname43(path), { recursive: true, mode: 448 });
113750
+ await mkdir12(dirname43(path), { recursive: true, mode: 448 });
112998
113751
  const staging = `${path}.${process.pid}.tmp`;
112999
- await writeFile16(staging, JSON.stringify({ device, at: new Date().toISOString() }), { mode: 384 });
113000
- await rename7(staging, path);
113752
+ await writeFile17(staging, JSON.stringify({ device, at: new Date().toISOString() }), { mode: 384 });
113753
+ await rename8(staging, path);
113001
113754
  }
113002
- var clearSignedOutMarker = (path) => rm16(path, { force: true });
113755
+ var clearSignedOutMarker = (path) => rm17(path, { force: true });
113003
113756
 
113004
113757
  // packages/omo-opencode/src/cli/service-auth/session.ts
113005
113758
  class SessionEnded extends SignInError {
@@ -113014,30 +113767,29 @@ class SessionEnded extends SignInError {
113014
113767
  var DEVICE_REVOKING_REFUSALS = new Set(["account_deleted", "reauth_required", "device_revoked"]);
113015
113768
  function createSession(options) {
113016
113769
  const api = serviceOrigin(options.api);
113770
+ const now = options.now ?? Date.now;
113017
113771
  const { store, signal } = options;
113018
- const directory = join107(options.home ?? homedir31(), ".omo", "session-locks");
113019
- const lockPath = join107(directory, `${credentialId(api)}.lock`);
113020
- const markerPath = signedOutMarkerPath(options.home ?? homedir31(), credentialId(api));
113772
+ const markerPath = signedOutMarkerPath(options.home ?? homedir32(), credentialId(api));
113021
113773
  async function locked(action) {
113022
- await mkdir11(directory, { recursive: true, mode: 448 });
113023
113774
  signal?.throwIfAborted();
113024
- return withLock(lockPath, async () => {
113775
+ return withCredentialLock(api, async () => {
113025
113776
  signal?.throwIfAborted();
113026
113777
  return action();
113027
- }, { ownerTag: "cli-session", staleAfterMs: Number.POSITIVE_INFINITY });
113778
+ }, options.home);
113028
113779
  }
113029
113780
  const request = (path, init) => requestApi(api, path, init, signal);
113030
- const uncertain = () => new SignInError(`The refresh outcome is unknown. Saved credentials and keys were retained, but this refresh token will not be sent again. ${signInHint("again")}`, true);
113031
- async function refreshedAccess(current) {
113032
- if (current.refreshState === "uncertain")
113033
- throw uncertain();
113034
- if (Date.parse(current.accessTokenExpiresAt) > Date.now() + 30000)
113035
- return current.accessToken;
113781
+ async function refreshed(current) {
113782
+ if (current.refreshState === "uncertain" || current.refreshAttempt !== undefined) {
113783
+ throw new SessionEnded(`Refresh recovery can no longer be proved safe. ${signInHint("again")}`, false, "refresh_recovery_expired");
113784
+ }
113785
+ if (Date.parse(current.accessTokenExpiresAt) > now() + 30000)
113786
+ return current;
113036
113787
  await store.write({ ...current, refreshState: "uncertain" });
113037
113788
  try {
113038
113789
  const tokens = parseReply(tokenSchema, await request("/v1/session/refresh", jsonRequest({ refreshToken: current.refreshToken })));
113039
- await store.write({ ...current, ...tokens });
113040
- return tokens.accessToken;
113790
+ const successor = { ...current, ...tokens };
113791
+ await store.write(successor);
113792
+ return successor;
113041
113793
  } catch (error) {
113042
113794
  if (error instanceof CredentialStoreError)
113043
113795
  throw error;
@@ -113049,12 +113801,19 @@ function createSession(options) {
113049
113801
  await store.write(current);
113050
113802
  throw error;
113051
113803
  }
113052
- throw uncertain();
113804
+ throw new SessionEnded(`The refresh outcome is unknown. Saved credentials and keys were retained. ${signInHint("again")}`, false, "refresh_recovery_expired");
113053
113805
  }
113054
113806
  }
113807
+ async function snapshot() {
113808
+ return locked(async () => {
113809
+ const current = await store.read();
113810
+ return current === null ? null : refreshed(current);
113811
+ });
113812
+ }
113055
113813
  return {
113056
113814
  request,
113057
113815
  signal,
113816
+ transaction: locked,
113058
113817
  async ready() {
113059
113818
  await store.read();
113060
113819
  },
@@ -113066,18 +113825,32 @@ function createSession(options) {
113066
113825
  },
113067
113826
  signedOutMarker: () => readSignedOutMarker(markerPath),
113068
113827
  clearSignedOutMarker: () => clearSignedOutMarker(markerPath),
113069
- async update(action) {
113070
- return locked(async () => action(await store.read()));
113828
+ async update(action, options = {}) {
113829
+ return locked(async () => {
113830
+ let current;
113831
+ try {
113832
+ current = await store.readAuthoritative();
113833
+ } catch (error) {
113834
+ if (!options.replaceInvalid || !(error instanceof InvalidCredentialState))
113835
+ throw error;
113836
+ current = null;
113837
+ }
113838
+ return action(current);
113839
+ });
113071
113840
  },
113841
+ async forget() {
113842
+ await locked(() => store.clear());
113843
+ },
113844
+ accessSnapshot: snapshot,
113072
113845
  async logout() {
113073
113846
  return locked(async () => {
113074
113847
  let current = null;
113075
113848
  try {
113076
- current = await store.read();
113849
+ current = await store.readAuthoritative();
113077
113850
  if (current !== null) {
113078
113851
  if (current.refreshState === "uncertain")
113079
113852
  return false;
113080
- const access = Date.parse(current.accessTokenExpiresAt) <= Date.now() ? await refreshedAccess(current) : current.accessToken;
113853
+ const access = Date.parse(current.accessTokenExpiresAt) <= now() ? (await refreshed(current)).accessToken : current.accessToken;
113081
113854
  await request(`/v1/devices/${encodeURIComponent(current.device.id)}`, {
113082
113855
  method: "DELETE",
113083
113856
  headers: { authorization: `Bearer ${access}` }
@@ -113096,12 +113869,19 @@ function createSession(options) {
113096
113869
  }
113097
113870
  });
113098
113871
  },
113099
- async accessToken() {
113872
+ async accessToken(expect) {
113873
+ signal?.throwIfAborted();
113874
+ const snapshot = await store.read();
113875
+ signal?.throwIfAborted();
113876
+ if (snapshot !== null && snapshot.refreshState !== "uncertain" && snapshot.refreshAttempt === undefined && Date.parse(snapshot.accessTokenExpiresAt) > now() + 30000 && (expect === undefined || expect(snapshot)))
113877
+ return snapshot.accessToken;
113100
113878
  return locked(async () => {
113101
- const current = await store.read();
113879
+ const current = await store.readAuthoritative();
113102
113880
  if (current === null)
113103
113881
  throw new SignInError(`Not signed in. ${signInHint("first")}`);
113104
- return refreshedAccess(current);
113882
+ if (expect !== undefined && !expect(current))
113883
+ throw new CredentialIdentityChanged;
113884
+ return (await refreshed(current)).accessToken;
113105
113885
  });
113106
113886
  },
113107
113887
  async removeForLimit(error, choose) {
@@ -113430,12 +114210,12 @@ async function boulder(options) {
113430
114210
  }
113431
114211
  // packages/omo-opencode/src/cli/codex-ulw-loop.ts
113432
114212
  import { spawn as spawn6 } from "node:child_process";
113433
- import { existsSync as existsSync67, readFileSync as readFileSync44, realpathSync as realpathSync13 } from "node:fs";
113434
- import { homedir as homedir32 } from "node:os";
114213
+ import { existsSync as existsSync67, readFileSync as readFileSync45, realpathSync as realpathSync14 } from "node:fs";
114214
+ import { homedir as homedir33 } from "node:os";
113435
114215
  var ULW_LOOP_DELEGATION_SENTINEL = "OMO_ULW_LOOP_DELEGATED";
113436
114216
  function resolveCodexUlwLoopCommand(input = {}) {
113437
114217
  const env = input.env ?? process.env;
113438
- const homeDir = input.homeDir ?? homedir32();
114218
+ const homeDir = input.homeDir ?? homedir33();
113439
114219
  const localComponentBin = resolveLocalUlwLoopBin(env, homeDir);
113440
114220
  if (localComponentBin !== null)
113441
114221
  return { executable: localComponentBin, argsPrefix: [] };
@@ -113480,7 +114260,7 @@ function resolveLegacyLocalOmoBin(env, homeDir, currentExecutablePaths) {
113480
114260
  }
113481
114261
  function isGeneratedRuntimeWrapper(candidate) {
113482
114262
  try {
113483
- return readFileSync44(candidate, "utf8").includes(RUNTIME_WRAPPER_MARKER);
114263
+ return readFileSync45(candidate, "utf8").includes(RUNTIME_WRAPPER_MARKER);
113484
114264
  } catch (error) {
113485
114265
  if (error instanceof Error)
113486
114266
  return false;
@@ -113493,7 +114273,7 @@ function isCurrentExecutable(candidate, currentExecutablePaths) {
113493
114273
  }
113494
114274
  function realpathOrSelf2(path) {
113495
114275
  try {
113496
- return realpathSync13(path);
114276
+ return realpathSync14(path);
113497
114277
  } catch (error) {
113498
114278
  if (error instanceof Error)
113499
114279
  return path;
@@ -113678,7 +114458,7 @@ function linkedWorktrees(records) {
113678
114458
  }
113679
114459
  // packages/omo-opencode/src/cli/worktree-sweep/sweep.ts
113680
114460
  import { existsSync as existsSync68 } from "node:fs";
113681
- import { stat as stat9 } from "node:fs/promises";
114461
+ import { stat as stat10 } from "node:fs/promises";
113682
114462
  import os7 from "node:os";
113683
114463
  import { normalize as normalize2 } from "node:path";
113684
114464
 
@@ -113761,7 +114541,7 @@ async function isOlderThan(worktreePath, days, now) {
113761
114541
  if (days <= 0)
113762
114542
  return false;
113763
114543
  try {
113764
- const stats = await stat9(worktreePath);
114544
+ const stats = await stat10(worktreePath);
113765
114545
  return now - stats.mtimeMs > days * DAY_MS;
113766
114546
  } catch {
113767
114547
  return false;
@@ -114008,7 +114788,7 @@ Model Providers (Priority: Native > Copilot > OpenCode Zen > Z.ai > Kimi > Baili
114008
114788
  Copilot github-copilot/ models (fallback)
114009
114789
  OpenCode Zen opencode/ models (opencode/claude-opus-5, etc.)
114010
114790
  Z.ai zai-coding-plan/glm-5.2 (visual-engineering fallback)
114011
- Kimi kimi-for-coding/kimi-k3 (Sisyphus/Prometheus fallback)
114791
+ Kimi kimi-for-coding/kimi-k3.1-pro (Sisyphus/Prometheus fallback)
114012
114792
  Bailian bailian-coding-plan/ models (Qwen, GLM, Kimi fallback)
114013
114793
  MiniMax minimax-coding-plan/MiniMax-M3 (utility fallback)
114014
114794
  MiniMax CN minimax-cn-coding-plan/MiniMax-M3 (utility fallback)