lazycodex-ai 5.1.48 → 5.1.51

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 (437) hide show
  1. package/dist/cli/index.js +1194 -752
  2. package/dist/cli/service-auth/accounts-gate.d.ts +11 -0
  3. package/dist/cli/service-auth/commands.d.ts +2 -4
  4. package/dist/cli/service-auth/index.d.ts +1 -1
  5. package/dist/cli/service-auth/keystore.d.ts +26 -2
  6. package/dist/cli/service-auth/protocol.d.ts +7 -1
  7. package/dist/cli/service-auth/session.d.ts +6 -0
  8. package/dist/cli/service-auth/signed-out-marker.d.ts +11 -0
  9. package/dist/cli-node/index.js +1194 -752
  10. package/package.json +3 -1
  11. package/packages/lsp-core/package.json +45 -0
  12. package/packages/lsp-core/src/index.ts +30 -0
  13. package/packages/lsp-core/src/lsp/bun-command-output.ts +82 -0
  14. package/packages/lsp-core/src/lsp/bun-project-checks.test.ts +170 -0
  15. package/packages/lsp-core/src/lsp/bun-project-checks.ts +223 -0
  16. package/packages/lsp-core/src/lsp/cleanup-errors.test.ts +18 -0
  17. package/packages/lsp-core/src/lsp/cleanup-errors.ts +14 -0
  18. package/packages/lsp-core/src/lsp/client-diagnostics-concurrency.integration.test.ts +52 -0
  19. package/packages/lsp-core/src/lsp/client-diagnostics-freshness.integration.test.ts +471 -0
  20. package/packages/lsp-core/src/lsp/client-diagnostics-pull-timeout.test.ts +64 -0
  21. package/packages/lsp-core/src/lsp/client-wrapper-outside-cwd.test.ts +78 -0
  22. package/packages/lsp-core/src/lsp/client-wrapper.test.ts +213 -0
  23. package/packages/lsp-core/src/lsp/client-wrapper.ts +290 -0
  24. package/packages/lsp-core/src/lsp/client.ts +398 -0
  25. package/packages/lsp-core/src/lsp/config-loader.ts +254 -0
  26. package/packages/lsp-core/src/lsp/connection.ts +95 -0
  27. package/packages/lsp-core/src/lsp/constants.ts +17 -0
  28. package/packages/lsp-core/src/lsp/controlled-clock-test-support.ts +90 -0
  29. package/packages/lsp-core/src/lsp/directory-diagnostics.test.ts +221 -0
  30. package/packages/lsp-core/src/lsp/directory-diagnostics.ts +187 -0
  31. package/packages/lsp-core/src/lsp/effective-extension.ts +10 -0
  32. package/packages/lsp-core/src/lsp/errors.ts +89 -0
  33. package/packages/lsp-core/src/lsp/fake-bun-test-support.ts +102 -0
  34. package/packages/lsp-core/src/lsp/fixtures/diagnostics-freshness-contract-probe.ts +283 -0
  35. package/packages/lsp-core/src/lsp/fixtures/disposed-stdin-epipe-probe.ts +28 -0
  36. package/packages/lsp-core/src/lsp/fixtures/workspace-edit-contract-probe.ts +196 -0
  37. package/packages/lsp-core/src/lsp/fixtures/workspace-edit-server.mjs +234 -0
  38. package/packages/lsp-core/src/lsp/format-document.test.ts +143 -0
  39. package/packages/lsp-core/src/lsp/format-document.ts +90 -0
  40. package/packages/lsp-core/src/lsp/formatters.ts +144 -0
  41. package/packages/lsp-core/src/lsp/infer-extension.ts +66 -0
  42. package/packages/lsp-core/src/lsp/json-rpc-connection-cancellation.test.ts +97 -0
  43. package/packages/lsp-core/src/lsp/json-rpc-connection.ts +369 -0
  44. package/packages/lsp-core/src/lsp/language-mappings.ts +173 -0
  45. package/packages/lsp-core/src/lsp/manager-lifecycle.test.ts +262 -0
  46. package/packages/lsp-core/src/lsp/manager-max-clients.test.ts +151 -0
  47. package/packages/lsp-core/src/lsp/manager.ts +495 -0
  48. package/packages/lsp-core/src/lsp/outside-context-workspace.ts +33 -0
  49. package/packages/lsp-core/src/lsp/process-pipe-errors.test.ts +21 -0
  50. package/packages/lsp-core/src/lsp/process-signal-cleanup.ts +21 -0
  51. package/packages/lsp-core/src/lsp/process.ts +221 -0
  52. package/packages/lsp-core/src/lsp/server-definitions.ts +205 -0
  53. package/packages/lsp-core/src/lsp/server-install-state.ts +67 -0
  54. package/packages/lsp-core/src/lsp/server-installation.test.ts +376 -0
  55. package/packages/lsp-core/src/lsp/server-installation.ts +218 -0
  56. package/packages/lsp-core/src/lsp/server-resolution-local-binary.test.ts +170 -0
  57. package/packages/lsp-core/src/lsp/server-resolution.ts +117 -0
  58. package/packages/lsp-core/src/lsp/startup-failure.ts +1 -0
  59. package/packages/lsp-core/src/lsp/timer-provider.ts +13 -0
  60. package/packages/lsp-core/src/lsp/transport-protocol.ts +52 -0
  61. package/packages/lsp-core/src/lsp/transport-request-timeout.test.ts +73 -0
  62. package/packages/lsp-core/src/lsp/transport.ts +339 -0
  63. package/packages/lsp-core/src/lsp/types.ts +134 -0
  64. package/packages/lsp-core/src/lsp/utils.test.ts +72 -0
  65. package/packages/lsp-core/src/lsp/utils.ts +40 -0
  66. package/packages/lsp-core/src/lsp/workspace-apply-edit-failure.ts +19 -0
  67. package/packages/lsp-core/src/lsp/workspace-apply-edit-lease.integration.test.ts +218 -0
  68. package/packages/lsp-core/src/lsp/workspace-apply-edit-sync.integration.test.ts +113 -0
  69. package/packages/lsp-core/src/lsp/workspace-apply-edit-test-support.ts +194 -0
  70. package/packages/lsp-core/src/lsp/workspace-apply-edit.integration.test.ts +163 -0
  71. package/packages/lsp-core/src/lsp/workspace-document-state.test.ts +150 -0
  72. package/packages/lsp-core/src/lsp/workspace-document-state.ts +392 -0
  73. package/packages/lsp-core/src/lsp/workspace-edit-adversarial.test.ts +132 -0
  74. package/packages/lsp-core/src/lsp/workspace-edit-commit.test.ts +140 -0
  75. package/packages/lsp-core/src/lsp/workspace-edit-commit.ts +220 -0
  76. package/packages/lsp-core/src/lsp/workspace-edit-contract-evidence.test.ts +56 -0
  77. package/packages/lsp-core/src/lsp/workspace-edit-contract-evidence.ts +30 -0
  78. package/packages/lsp-core/src/lsp/workspace-edit-fingerprint.ts +44 -0
  79. package/packages/lsp-core/src/lsp/workspace-edit-options.test.ts +147 -0
  80. package/packages/lsp-core/src/lsp/workspace-edit-parse-helpers.ts +59 -0
  81. package/packages/lsp-core/src/lsp/workspace-edit-parser.ts +130 -0
  82. package/packages/lsp-core/src/lsp/workspace-edit-path.ts +98 -0
  83. package/packages/lsp-core/src/lsp/workspace-edit-plan-types.ts +60 -0
  84. package/packages/lsp-core/src/lsp/workspace-edit-plan.ts +73 -0
  85. package/packages/lsp-core/src/lsp/workspace-edit-prevalidation.test.ts +174 -0
  86. package/packages/lsp-core/src/lsp/workspace-edit-resource-parser.ts +89 -0
  87. package/packages/lsp-core/src/lsp/workspace-edit-simulation.ts +183 -0
  88. package/packages/lsp-core/src/lsp/workspace-edit-snapshot.ts +53 -0
  89. package/packages/lsp-core/src/lsp/workspace-edit-text.ts +125 -0
  90. package/packages/lsp-core/src/lsp/workspace-edit-types.ts +121 -0
  91. package/packages/lsp-core/src/lsp/workspace-edit.characterization.test.ts +95 -0
  92. package/packages/lsp-core/src/lsp/workspace-edit.ts +55 -0
  93. package/packages/lsp-core/src/lsp/workspace-markers.ts +18 -0
  94. package/packages/lsp-core/src/lsp/workspace-mutation-controller.ts +182 -0
  95. package/packages/lsp-core/src/mcp-protocol-pin.test.ts +97 -0
  96. package/packages/lsp-core/src/mcp.ts +122 -0
  97. package/packages/lsp-core/src/missing-dependency-result.test.ts +135 -0
  98. package/packages/lsp-core/src/missing-dependency-result.ts +79 -0
  99. package/packages/lsp-core/src/post-edit/file-location.ts +55 -0
  100. package/packages/lsp-core/src/post-edit/index.ts +3 -0
  101. package/packages/lsp-core/src/post-edit/not-installed-guidance.ts +36 -0
  102. package/packages/lsp-core/src/post-edit/not-installed.test.ts +224 -0
  103. package/packages/lsp-core/src/post-edit/orchestration.test.ts +157 -0
  104. package/packages/lsp-core/src/post-edit/orchestration.ts +205 -0
  105. package/packages/lsp-core/src/request-context.test.ts +200 -0
  106. package/packages/lsp-core/src/request-context.ts +235 -0
  107. package/packages/lsp-core/src/tool-surface.test.ts +173 -0
  108. package/packages/lsp-core/src/tools/bun-directory-diagnostics.test.ts +113 -0
  109. package/packages/lsp-core/src/tools/bun-directory-diagnostics.ts +75 -0
  110. package/packages/lsp-core/src/tools/definitions.ts +156 -0
  111. package/packages/lsp-core/src/tools/diagnostics.ts +133 -0
  112. package/packages/lsp-core/src/tools/format.test.ts +56 -0
  113. package/packages/lsp-core/src/tools/format.ts +56 -0
  114. package/packages/lsp-core/src/tools/index.ts +11 -0
  115. package/packages/lsp-core/src/tools/install-decision.ts +39 -0
  116. package/packages/lsp-core/src/tools/navigation.ts +88 -0
  117. package/packages/lsp-core/src/tools/parameters.test.ts +51 -0
  118. package/packages/lsp-core/src/tools/parameters.ts +49 -0
  119. package/packages/lsp-core/src/tools/rename.ts +69 -0
  120. package/packages/lsp-core/src/tools/result.ts +5 -0
  121. package/packages/lsp-core/src/tools/runtime.ts +21 -0
  122. package/packages/lsp-core/src/tools/schema.ts +9 -0
  123. package/packages/lsp-core/src/tools/status.ts +28 -0
  124. package/packages/lsp-core/src/tools/symbols.ts +99 -0
  125. package/packages/lsp-core/src/tools/types.ts +116 -0
  126. package/packages/lsp-core/src/tools.ts +1 -0
  127. package/packages/omo-codex/plugin/.codex-plugin/plugin.json +1 -1
  128. package/packages/omo-codex/plugin/README.md +1 -1
  129. package/packages/omo-codex/plugin/components/bootstrap/hooks/hooks.json +1 -1
  130. package/packages/omo-codex/plugin/components/bootstrap/package.json +1 -1
  131. package/packages/omo-codex/plugin/components/comment-checker/hooks/hooks.json +1 -1
  132. package/packages/omo-codex/plugin/components/comment-checker/package.json +1 -1
  133. package/packages/omo-codex/plugin/components/git-bash/hooks/hooks.json +2 -2
  134. package/packages/omo-codex/plugin/components/git-bash/package.json +1 -1
  135. package/packages/omo-codex/plugin/components/lazycodex-executor-verify/hooks/hooks.json +1 -1
  136. package/packages/omo-codex/plugin/components/lazycodex-executor-verify/package.json +1 -1
  137. package/packages/omo-codex/plugin/components/lcx/skills/lcx-contribute-bug-fix/SKILL.md +51 -55
  138. package/packages/omo-codex/plugin/components/lcx/skills/lcx-contribute-bug-fix/agents/openai.yaml +1 -1
  139. package/packages/omo-codex/plugin/components/lcx/skills/lcx-report-bug/SKILL.md +7 -7
  140. package/packages/omo-codex/plugin/components/lcx/skills/lcx-report-bug/agents/openai.yaml +1 -1
  141. package/packages/omo-codex/plugin/components/lsp/dist/.omo-runtime-manifest.json +2 -2
  142. package/packages/omo-codex/plugin/components/lsp/hooks/hooks.json +2 -2
  143. package/packages/omo-codex/plugin/components/lsp/package.json +1 -1
  144. package/packages/omo-codex/plugin/components/rules/hooks/hooks.json +4 -4
  145. package/packages/omo-codex/plugin/components/rules/package.json +1 -1
  146. package/packages/omo-codex/plugin/components/teammode/hooks/hooks.json +1 -1
  147. package/packages/omo-codex/plugin/components/teammode/package.json +2 -2
  148. package/packages/omo-codex/plugin/components/telemetry/README.md +2 -2
  149. package/packages/omo-codex/plugin/components/telemetry/dist/cli.js +52 -15
  150. package/packages/omo-codex/plugin/components/telemetry/dist/posthog.js +52 -19
  151. package/packages/omo-codex/plugin/components/telemetry/hooks/hooks.json +1 -1
  152. package/packages/omo-codex/plugin/components/telemetry/package.json +1 -1
  153. package/packages/omo-codex/plugin/components/telemetry/src/codex-hook.ts +2 -9
  154. package/packages/omo-codex/plugin/components/telemetry/src/posthog.ts +4 -13
  155. package/packages/omo-codex/plugin/components/telemetry/src/product-identity.ts +0 -2
  156. package/packages/omo-codex/plugin/components/telemetry/test/codex-hook-diagnostics.test.ts +0 -3
  157. package/packages/omo-codex/plugin/components/telemetry/test/codex-hook.test.ts +3 -8
  158. package/packages/omo-codex/plugin/components/ultrawork/dist/cli.js +3 -0
  159. package/packages/omo-codex/plugin/components/ultrawork/hooks/hooks.json +1 -1
  160. package/packages/omo-codex/plugin/components/ultrawork/package.json +1 -1
  161. package/packages/omo-codex/plugin/components/ultrawork/src/directive-content.ts +1 -1
  162. package/packages/omo-codex/plugin/components/ulw-execute-continuation/hooks/hooks.json +1 -1
  163. package/packages/omo-codex/plugin/components/ulw-execute-continuation/package.json +1 -1
  164. package/packages/omo-codex/plugin/components/ulw-loop/directive.md +3 -0
  165. package/packages/omo-codex/plugin/components/ulw-loop/hooks/hooks.json +5 -5
  166. package/packages/omo-codex/plugin/components/ulw-loop/package.json +1 -1
  167. package/packages/omo-codex/plugin/hooks/post-compact-resetting-git-bash-mcp-reminder.json +1 -1
  168. package/packages/omo-codex/plugin/hooks/post-compact-resetting-lsp-diagnostics-cache.json +1 -1
  169. package/packages/omo-codex/plugin/hooks/post-compact-resetting-project-rule-cache.json +1 -1
  170. package/packages/omo-codex/plugin/hooks/post-tool-use-checking-comments.json +1 -1
  171. package/packages/omo-codex/plugin/hooks/post-tool-use-checking-lsp-diagnostics.json +1 -1
  172. package/packages/omo-codex/plugin/hooks/post-tool-use-checking-thread-title-hygiene.json +1 -1
  173. package/packages/omo-codex/plugin/hooks/post-tool-use-matching-project-rules.json +1 -1
  174. package/packages/omo-codex/plugin/hooks/post-tool-use-recording-spawn-admission.json +1 -1
  175. package/packages/omo-codex/plugin/hooks/pre-tool-use-enforcing-unlimited-goal-budget.json +1 -1
  176. package/packages/omo-codex/plugin/hooks/pre-tool-use-guarding-ulw-loop-spawns.json +1 -1
  177. package/packages/omo-codex/plugin/hooks/pre-tool-use-recommending-git-bash-mcp.json +1 -1
  178. package/packages/omo-codex/plugin/hooks/session-start-checking-auto-update.json +1 -1
  179. package/packages/omo-codex/plugin/hooks/session-start-checking-bootstrap-provisioning.json +1 -1
  180. package/packages/omo-codex/plugin/hooks/session-start-loading-project-rules.json +1 -1
  181. package/packages/omo-codex/plugin/hooks/session-start-recording-session-telemetry.json +1 -1
  182. package/packages/omo-codex/plugin/hooks/stop-checking-ulw-execute-continuation.json +1 -1
  183. package/packages/omo-codex/plugin/hooks/stop-checking-ulw-loop-resume.json +1 -1
  184. package/packages/omo-codex/plugin/hooks/subagent-stop-verifying-lazycodex-executor-evidence.json +1 -1
  185. package/packages/omo-codex/plugin/hooks/user-prompt-submit-checking-ultrawork-trigger.json +1 -1
  186. package/packages/omo-codex/plugin/hooks/user-prompt-submit-checking-ulw-loop-steering.json +1 -1
  187. package/packages/omo-codex/plugin/hooks/user-prompt-submit-loading-project-rules.json +1 -1
  188. package/packages/omo-codex/plugin/package-lock.json +16 -16
  189. package/packages/omo-codex/plugin/package.json +1 -1
  190. package/packages/omo-codex/plugin/shared/package.json +1 -1
  191. package/packages/omo-codex/plugin/skills/ast-grep/README.md +1 -1
  192. package/packages/omo-codex/plugin/skills/ast-grep/install.ps1 +5 -3
  193. package/packages/omo-codex/plugin/skills/ast-grep/install.sh +4 -5
  194. package/packages/omo-codex/plugin/skills/ast-grep/references/install.md +2 -2
  195. package/packages/omo-codex/plugin/skills/ast-grep/scripts/ast_grep_helper.py +13 -3
  196. package/packages/omo-codex/plugin/skills/browser/runtime/omowright/manifest.json +1 -1
  197. package/packages/omo-codex/plugin/skills/coding-agent-sessions/AGENTS.md +5 -4
  198. package/packages/omo-codex/plugin/skills/coding-agent-sessions/SKILL.md +11 -11
  199. package/packages/omo-codex/plugin/skills/coding-agent-sessions/references/all-platforms.md +2 -2
  200. package/packages/omo-codex/plugin/skills/coding-agent-sessions/references/codex.md +4 -4
  201. package/packages/omo-codex/plugin/skills/coding-agent-sessions/scripts/agent_sessions/cli.py +1 -1
  202. package/packages/omo-codex/plugin/skills/coding-agent-sessions/scripts/find-agent-sessions.py +6 -3
  203. package/packages/omo-codex/plugin/skills/frontend/ATTRIBUTION.md +1 -1
  204. package/packages/omo-codex/plugin/skills/frontend/SKILL.md +34 -12
  205. package/packages/omo-codex/plugin/skills/frontend/references/design/README.md +2 -2
  206. package/packages/omo-codex/plugin/skills/frontend/references/design/_INDEX.md +2 -1
  207. package/packages/omo-codex/plugin/skills/frontend/references/design/component-catalogs.md +14 -10
  208. package/packages/omo-codex/plugin/skills/frontend/references/design/design-system-architecture.md +19 -6
  209. package/packages/omo-codex/plugin/skills/frontend/references/design/grounding.md +29 -0
  210. package/packages/omo-codex/plugin/skills/frontend/references/ui-ux-db/scripts/design_system.py +2 -0
  211. package/packages/omo-codex/plugin/skills/frontend/references/ui-ux-db/scripts/search.py +2 -0
  212. package/packages/omo-codex/plugin/skills/lcx-contribute-bug-fix/SKILL.md +51 -55
  213. package/packages/omo-codex/plugin/skills/lcx-contribute-bug-fix/agents/openai.yaml +1 -1
  214. package/packages/omo-codex/plugin/skills/lcx-report-bug/SKILL.md +7 -7
  215. package/packages/omo-codex/plugin/skills/lcx-report-bug/agents/openai.yaml +1 -1
  216. package/packages/omo-codex/plugin/skills/ultimate-browsing/SKILL.md +5 -4
  217. package/packages/omo-codex/plugin/skills/ultimate-browsing/engine/AGENTS.md +2 -2
  218. package/packages/omo-codex/plugin/skills/ultimate-browsing/engine/__main__.py +9 -6
  219. package/packages/omo-codex/plugin/skills/ultimate-browsing/engine/summary.py +1 -1
  220. package/packages/omo-codex/plugin/skills/ultimate-browsing/references/insane-search/README.md +4 -4
  221. package/packages/omo-codex/plugin/skills/ultimate-browsing/scripts/extract_cookies.py +4 -2
  222. package/packages/omo-codex/plugin/skills/ultrawork/SKILL.md +3 -0
  223. package/packages/omo-codex/plugin/skills/ulw-research/AGENTS.md +8 -4
  224. package/packages/omo-codex/plugin/skills/ulw-research/SKILL.md +7 -316
  225. package/packages/omo-codex/plugin/skills/ulw-research/references/deliverable-phase.md +23 -21
  226. package/packages/omo-codex/plugin/skills/ulw-research/references/fact-ledger-grammar.md +7 -3
  227. package/packages/omo-codex/plugin/skills/ulw-research/references/fact-ledger.md +42 -8
  228. package/packages/omo-codex/plugin/skills/ulw-research/references/fidelity-claim-kinds.md +1 -1
  229. package/packages/omo-codex/plugin/skills/ulw-research/references/markdown-blocks.md +12 -0
  230. package/packages/omo-codex/plugin/skills/ulw-research/references/report-gates.md +12 -5
  231. package/packages/omo-codex/plugin/skills/ulw-research/references/research-collection.md +195 -0
  232. package/packages/omo-codex/plugin/skills/ulw-research/references/research-delivery.md +123 -0
  233. package/packages/omo-codex/plugin/skills/ulw-research/scripts/claim-kinds.mjs +33 -5
  234. package/packages/omo-codex/plugin/skills/ulw-research/scripts/contracts.mjs +13 -4
  235. package/packages/omo-codex/plugin/skills/ulw-research/scripts/conversion-probe.mjs +229 -0
  236. package/packages/omo-codex/plugin/skills/ulw-research/scripts/css-hiding.mjs +158 -0
  237. package/packages/omo-codex/plugin/skills/ulw-research/scripts/css-lite.mjs +4 -2
  238. package/packages/omo-codex/plugin/skills/ulw-research/scripts/entities.mjs +13 -4
  239. package/packages/omo-codex/plugin/skills/ulw-research/scripts/fact-commands-fill.mjs +11 -1
  240. package/packages/omo-codex/plugin/skills/ulw-research/scripts/fact-commands-meaning.mjs +13 -9
  241. package/packages/omo-codex/plugin/skills/ulw-research/scripts/fact-commands-polish.mjs +40 -18
  242. package/packages/omo-codex/plugin/skills/ulw-research/scripts/fact-commands-verify.mjs +25 -8
  243. package/packages/omo-codex/plugin/skills/ulw-research/scripts/fact-commands.mjs +35 -16
  244. package/packages/omo-codex/plugin/skills/ulw-research/scripts/fact-derive.mjs +7 -2
  245. package/packages/omo-codex/plugin/skills/ulw-research/scripts/fact-fill.mjs +6 -4
  246. package/packages/omo-codex/plugin/skills/ulw-research/scripts/fact-ledger-kinds.mjs +6 -7
  247. package/packages/omo-codex/plugin/skills/ulw-research/scripts/fact-locate.mjs +15 -9
  248. package/packages/omo-codex/plugin/skills/ulw-research/scripts/fidelity-claims.mjs +4 -3
  249. package/packages/omo-codex/plugin/skills/ulw-research/scripts/fidelity-csv.mjs +32 -0
  250. package/packages/omo-codex/plugin/skills/ulw-research/scripts/fidelity-lexicon.mjs +1 -1
  251. package/packages/omo-codex/plugin/skills/ulw-research/scripts/fidelity-originals.mjs +161 -0
  252. package/packages/omo-codex/plugin/skills/ulw-research/scripts/fidelity-policy.mjs +4 -4
  253. package/packages/omo-codex/plugin/skills/ulw-research/scripts/fidelity-records.mjs +81 -14
  254. package/packages/omo-codex/plugin/skills/ulw-research/scripts/fidelity-snapshot-readability.mjs +49 -0
  255. package/packages/omo-codex/plugin/skills/ulw-research/scripts/fidelity-sources.mjs +76 -0
  256. package/packages/omo-codex/plugin/skills/ulw-research/scripts/fidelity-trace.mjs +25 -11
  257. package/packages/omo-codex/plugin/skills/ulw-research/scripts/fidelity-value-unit.mjs +202 -0
  258. package/packages/omo-codex/plugin/skills/ulw-research/scripts/fidelity-values.mjs +40 -39
  259. package/packages/omo-codex/plugin/skills/ulw-research/scripts/gates-fidelity.mjs +8 -6
  260. package/packages/omo-codex/plugin/skills/ulw-research/scripts/gates-static.mjs +10 -1
  261. package/packages/omo-codex/plugin/skills/ulw-research/scripts/html-lite.mjs +6 -2
  262. package/packages/omo-codex/plugin/skills/ulw-research/scripts/html-markup.mjs +2 -2
  263. package/packages/omo-codex/plugin/skills/ulw-research/scripts/html-text-map.mjs +140 -0
  264. package/packages/omo-codex/plugin/skills/ulw-research/scripts/markdown-closers.mjs +126 -0
  265. package/packages/omo-codex/plugin/skills/ulw-research/scripts/md-lite.mjs +1 -1
  266. package/packages/omo-codex/plugin/skills/ulw-research/scripts/number-grammar.mjs +33 -0
  267. package/packages/omo-codex/plugin/skills/ulw-research/scripts/numerals.mjs +18 -7
  268. package/packages/omo-codex/plugin/skills/ulw-research/scripts/outcome-start.mjs +66 -0
  269. package/packages/omo-codex/plugin/skills/ulw-research/scripts/outcome.mjs +11 -22
  270. package/packages/omo-codex/plugin/skills/ulw-research/scripts/placeholder.mjs +18 -6
  271. package/packages/omo-codex/plugin/skills/ulw-research/scripts/polish-apply.mjs +3 -2
  272. package/packages/omo-codex/plugin/skills/ulw-research/scripts/raw-decode.mjs +110 -0
  273. package/packages/omo-codex/plugin/skills/ulw-research/scripts/raw-locator.mjs +47 -0
  274. package/packages/omo-codex/plugin/skills/ulw-research/scripts/report-tools-commands.mjs +1 -1
  275. package/packages/omo-codex/plugin/skills/ulw-research/scripts/report-tools.mjs +7 -1
  276. package/packages/omo-codex/plugin/skills/ulw-research/scripts/source-commands.mjs +79 -26
  277. package/packages/omo-codex/plugin/skills/ulw-research/scripts/source-refresh.mjs +82 -0
  278. package/packages/omo-codex/plugin/skills/ulw-research/scripts/source-snapshot.mjs +73 -69
  279. package/packages/omo-codex/plugin/skills/ulw-research/scripts/source-view.mjs +89 -0
  280. package/packages/omo-codex/plugin/skills/ulw-research/scripts/sources-citation.mjs +203 -0
  281. package/packages/omo-codex/plugin/skills/ulw-research/scripts/units.mjs +14 -3
  282. package/packages/omo-codex/plugin/test/payload-equivalence.test.mjs +6 -4
  283. package/packages/omo-codex/plugin/test/sync-skills.test.mjs +4 -3
  284. package/packages/omo-codex/scripts/install-dist/install-local.mjs +338 -237
  285. package/packages/prompts-core/prompts/ultrawork/codex.md +3 -0
  286. package/packages/shared-skills/skill-source-filter.mjs +6 -2
  287. package/packages/shared-skills/skills/ast-grep/README.md +1 -1
  288. package/packages/shared-skills/skills/ast-grep/install.ps1 +5 -3
  289. package/packages/shared-skills/skills/ast-grep/install.sh +4 -5
  290. package/packages/shared-skills/skills/ast-grep/references/install.md +2 -2
  291. package/packages/shared-skills/skills/ast-grep/scripts/ast_grep_helper.py +13 -3
  292. package/packages/shared-skills/skills/browser/runtime/omowright/manifest.json +1 -1
  293. package/packages/shared-skills/skills/coding-agent-sessions/AGENTS.md +5 -4
  294. package/packages/shared-skills/skills/coding-agent-sessions/SKILL.md +11 -11
  295. package/packages/shared-skills/skills/coding-agent-sessions/references/all-platforms.md +2 -2
  296. package/packages/shared-skills/skills/coding-agent-sessions/references/codex.md +4 -4
  297. package/packages/shared-skills/skills/coding-agent-sessions/scripts/agent_sessions/cli.py +1 -1
  298. package/packages/shared-skills/skills/coding-agent-sessions/scripts/find-agent-sessions.py +6 -3
  299. package/packages/shared-skills/skills/frontend/ATTRIBUTION.md +1 -1
  300. package/packages/shared-skills/skills/frontend/SKILL.md +34 -12
  301. package/packages/shared-skills/skills/frontend/references/design/README.md +2 -2
  302. package/packages/shared-skills/skills/frontend/references/design/_INDEX.md +2 -1
  303. package/packages/shared-skills/skills/frontend/references/design/component-catalogs.md +14 -10
  304. package/packages/shared-skills/skills/frontend/references/design/design-system-architecture.md +19 -6
  305. package/packages/shared-skills/skills/frontend/references/design/grounding.md +29 -0
  306. package/packages/shared-skills/skills/frontend/references/ui-ux-db/scripts/design_system.py +2 -0
  307. package/packages/shared-skills/skills/frontend/references/ui-ux-db/scripts/search.py +2 -0
  308. package/packages/shared-skills/skills/ultimate-browsing/SKILL.md +5 -4
  309. package/packages/shared-skills/skills/ultimate-browsing/engine/AGENTS.md +2 -2
  310. package/packages/shared-skills/skills/ultimate-browsing/engine/__main__.py +9 -6
  311. package/packages/shared-skills/skills/ultimate-browsing/engine/summary.py +1 -1
  312. package/packages/shared-skills/skills/ultimate-browsing/references/insane-search/README.md +4 -4
  313. package/packages/shared-skills/skills/ultimate-browsing/scripts/extract_cookies.py +4 -2
  314. package/packages/shared-skills/skills/ulw-research/AGENTS.md +8 -4
  315. package/packages/shared-skills/skills/ulw-research/SKILL.md +7 -316
  316. package/packages/shared-skills/skills/ulw-research/references/deliverable-phase.md +23 -21
  317. package/packages/shared-skills/skills/ulw-research/references/fact-ledger-grammar.md +7 -3
  318. package/packages/shared-skills/skills/ulw-research/references/fact-ledger.md +42 -8
  319. package/packages/shared-skills/skills/ulw-research/references/fidelity-claim-kinds.md +1 -1
  320. package/packages/shared-skills/skills/ulw-research/references/markdown-blocks.md +12 -0
  321. package/packages/shared-skills/skills/ulw-research/references/report-gates.md +12 -5
  322. package/packages/shared-skills/skills/ulw-research/references/research-collection.md +195 -0
  323. package/packages/shared-skills/skills/ulw-research/references/research-delivery.md +123 -0
  324. package/packages/shared-skills/skills/ulw-research/scripts/claim-kinds.mjs +33 -5
  325. package/packages/shared-skills/skills/ulw-research/scripts/claim-kinds.test.ts +37 -2
  326. package/packages/shared-skills/skills/ulw-research/scripts/claim-prefix.test.ts +76 -0
  327. package/packages/shared-skills/skills/ulw-research/scripts/contracts-validation.test.ts +83 -0
  328. package/packages/shared-skills/skills/ulw-research/scripts/contracts.mjs +13 -4
  329. package/packages/shared-skills/skills/ulw-research/scripts/contracts.test.ts +6 -110
  330. package/packages/shared-skills/skills/ulw-research/scripts/conversion-altered.test.ts +154 -0
  331. package/packages/shared-skills/skills/ulw-research/scripts/conversion-originals.test.ts +297 -0
  332. package/packages/shared-skills/skills/ulw-research/scripts/conversion-probe-classes.test.ts +361 -0
  333. package/packages/shared-skills/skills/ulw-research/scripts/conversion-probe.mjs +229 -0
  334. package/packages/shared-skills/skills/ulw-research/scripts/conversion-probe.test.ts +218 -0
  335. package/packages/shared-skills/skills/ulw-research/scripts/copy-returns-polish.test.ts +4 -3
  336. package/packages/shared-skills/skills/ulw-research/scripts/css-hiding.mjs +158 -0
  337. package/packages/shared-skills/skills/ulw-research/scripts/css-lite.mjs +4 -2
  338. package/packages/shared-skills/skills/ulw-research/scripts/delivery-barrier-meaning.test.ts +186 -0
  339. package/packages/shared-skills/skills/ulw-research/scripts/delivery-barrier.test.ts +40 -87
  340. package/packages/shared-skills/skills/ulw-research/scripts/entities.mjs +13 -4
  341. package/packages/shared-skills/skills/ulw-research/scripts/fact-commands-fill.mjs +11 -1
  342. package/packages/shared-skills/skills/ulw-research/scripts/fact-commands-meaning.mjs +13 -9
  343. package/packages/shared-skills/skills/ulw-research/scripts/fact-commands-polish.mjs +40 -18
  344. package/packages/shared-skills/skills/ulw-research/scripts/fact-commands-verify.mjs +25 -8
  345. package/packages/shared-skills/skills/ulw-research/scripts/fact-commands.mjs +35 -16
  346. package/packages/shared-skills/skills/ulw-research/scripts/fact-derive-2.test.ts +149 -0
  347. package/packages/shared-skills/skills/ulw-research/scripts/fact-derive.mjs +7 -2
  348. package/packages/shared-skills/skills/ulw-research/scripts/fact-derive.test.ts +7 -192
  349. package/packages/shared-skills/skills/ulw-research/scripts/fact-fill.mjs +6 -4
  350. package/packages/shared-skills/skills/ulw-research/scripts/fact-ledger-kinds.mjs +6 -7
  351. package/packages/shared-skills/skills/ulw-research/scripts/fact-ledger-kinds.test.ts +2 -1
  352. package/packages/shared-skills/skills/ulw-research/scripts/fact-ledger-legacy.test.ts +2 -1
  353. package/packages/shared-skills/skills/ulw-research/scripts/fact-locate.mjs +15 -9
  354. package/packages/shared-skills/skills/ulw-research/scripts/fact-unit-dimensions-2.test.ts +149 -0
  355. package/packages/shared-skills/skills/ulw-research/scripts/fact-unit-dimensions.test.ts +4 -168
  356. package/packages/shared-skills/skills/ulw-research/scripts/fact-unit-rules.test.ts +3 -229
  357. package/packages/shared-skills/skills/ulw-research/scripts/fidelity-claims.mjs +4 -3
  358. package/packages/shared-skills/skills/ulw-research/scripts/fidelity-csv.mjs +32 -0
  359. package/packages/shared-skills/skills/ulw-research/scripts/fidelity-lexicon.mjs +1 -1
  360. package/packages/shared-skills/skills/ulw-research/scripts/fidelity-originals.mjs +161 -0
  361. package/packages/shared-skills/skills/ulw-research/scripts/fidelity-policy.mjs +4 -4
  362. package/packages/shared-skills/skills/ulw-research/scripts/fidelity-records.mjs +81 -14
  363. package/packages/shared-skills/skills/ulw-research/scripts/fidelity-snapshot-readability.mjs +49 -0
  364. package/packages/shared-skills/skills/ulw-research/scripts/fidelity-sources.mjs +76 -0
  365. package/packages/shared-skills/skills/ulw-research/scripts/fidelity-trace.mjs +25 -11
  366. package/packages/shared-skills/skills/ulw-research/scripts/fidelity-value-unit.mjs +202 -0
  367. package/packages/shared-skills/skills/ulw-research/scripts/fidelity-values.mjs +40 -39
  368. package/packages/shared-skills/skills/ulw-research/scripts/fidelity-values.test.ts +8 -29
  369. package/packages/shared-skills/skills/ulw-research/scripts/gates-fidelity.mjs +8 -6
  370. package/packages/shared-skills/skills/ulw-research/scripts/gates-static-headings.test.ts +17 -0
  371. package/packages/shared-skills/skills/ulw-research/scripts/gates-static.mjs +10 -1
  372. package/packages/shared-skills/skills/ulw-research/scripts/html-lite.mjs +6 -2
  373. package/packages/shared-skills/skills/ulw-research/scripts/html-markup.mjs +2 -2
  374. package/packages/shared-skills/skills/ulw-research/scripts/html-text-map.mjs +140 -0
  375. package/packages/shared-skills/skills/ulw-research/scripts/html-text-map.test.ts +148 -0
  376. package/packages/shared-skills/skills/ulw-research/scripts/markdown-closers.mjs +126 -0
  377. package/packages/shared-skills/skills/ulw-research/scripts/md-lite-boundaries.test.ts +46 -0
  378. package/packages/shared-skills/skills/ulw-research/scripts/md-lite.mjs +1 -1
  379. package/packages/shared-skills/skills/ulw-research/scripts/number-grammar.mjs +33 -0
  380. package/packages/shared-skills/skills/ulw-research/scripts/number-grammar.test.ts +36 -0
  381. package/packages/shared-skills/skills/ulw-research/scripts/numerals.mjs +18 -7
  382. package/packages/shared-skills/skills/ulw-research/scripts/numerals.test.ts +3 -0
  383. package/packages/shared-skills/skills/ulw-research/scripts/outcome-start.mjs +66 -0
  384. package/packages/shared-skills/skills/ulw-research/scripts/outcome-start.test.ts +109 -0
  385. package/packages/shared-skills/skills/ulw-research/scripts/outcome.mjs +11 -22
  386. package/packages/shared-skills/skills/ulw-research/scripts/page-source-locator.test.ts +187 -0
  387. package/packages/shared-skills/skills/ulw-research/scripts/placeholder.mjs +18 -6
  388. package/packages/shared-skills/skills/ulw-research/scripts/polish-apply.mjs +3 -2
  389. package/packages/shared-skills/skills/ulw-research/scripts/polish-markup.test.ts +15 -1
  390. package/packages/shared-skills/skills/ulw-research/scripts/polish-partial.test.ts +42 -0
  391. package/packages/shared-skills/skills/ulw-research/scripts/raw-decode.mjs +110 -0
  392. package/packages/shared-skills/skills/ulw-research/scripts/raw-locator.mjs +47 -0
  393. package/packages/shared-skills/skills/ulw-research/scripts/raw-snapshot.test.ts +139 -0
  394. package/packages/shared-skills/skills/ulw-research/scripts/report-tools-2.test.ts +233 -0
  395. package/packages/shared-skills/skills/ulw-research/scripts/report-tools-3.test.ts +141 -0
  396. package/packages/shared-skills/skills/ulw-research/scripts/report-tools-4.test.ts +135 -0
  397. package/packages/shared-skills/skills/ulw-research/scripts/report-tools-5.test.ts +231 -0
  398. package/packages/shared-skills/skills/ulw-research/scripts/report-tools-commands.mjs +1 -1
  399. package/packages/shared-skills/skills/ulw-research/scripts/report-tools.mjs +7 -1
  400. package/packages/shared-skills/skills/ulw-research/scripts/report-tools.test.ts +5 -800
  401. package/packages/shared-skills/skills/ulw-research/scripts/snapshot-readability.test.ts +116 -0
  402. package/packages/shared-skills/skills/ulw-research/scripts/source-commands.mjs +79 -26
  403. package/packages/shared-skills/skills/ulw-research/scripts/source-integrity.test.ts +243 -0
  404. package/packages/shared-skills/skills/ulw-research/scripts/source-refresh.mjs +82 -0
  405. package/packages/shared-skills/skills/ulw-research/scripts/source-snapshot.mjs +73 -69
  406. package/packages/shared-skills/skills/ulw-research/scripts/source-snapshot.test.ts +7 -4
  407. package/packages/shared-skills/skills/ulw-research/scripts/source-view.mjs +89 -0
  408. package/packages/shared-skills/skills/ulw-research/scripts/sources-citation.mjs +203 -0
  409. package/packages/shared-skills/skills/ulw-research/scripts/sources-citation.test.ts +236 -0
  410. package/packages/shared-skills/skills/ulw-research/scripts/tests/contracts-support.ts +147 -0
  411. package/packages/shared-skills/skills/ulw-research/scripts/tests/delivery-barrier-session.ts +59 -0
  412. package/packages/shared-skills/skills/ulw-research/scripts/tests/derive-clock.ts +4 -0
  413. package/packages/shared-skills/skills/ulw-research/scripts/tests/fact-derive-support.ts +65 -0
  414. package/packages/shared-skills/skills/ulw-research/scripts/tests/fact-unit-dimensions-support.ts +41 -0
  415. package/packages/shared-skills/skills/ulw-research/scripts/tests/fact-unit-rules-support.ts +241 -0
  416. package/packages/shared-skills/skills/ulw-research/scripts/tests/fidelity-values-support.ts +30 -0
  417. package/packages/shared-skills/skills/ulw-research/scripts/tests/fixtures/conversion-probe.html +14 -0
  418. package/packages/shared-skills/skills/ulw-research/scripts/tests/fixtures/sources-shapes.html +20 -0
  419. package/packages/shared-skills/skills/ulw-research/scripts/tests/numeral-classes.ts +196 -0
  420. package/packages/shared-skills/skills/ulw-research/scripts/tests/report-tools-support.ts +182 -0
  421. package/packages/shared-skills/skills/ulw-research/scripts/tests/value-mode-support.ts +48 -0
  422. package/packages/shared-skills/skills/ulw-research/scripts/units.mjs +14 -3
  423. package/packages/shared-skills/skills/ulw-research/scripts/units.test.ts +10 -0
  424. package/packages/shared-skills/skills/ulw-research/scripts/value-mode-unit-classes.test.ts +255 -0
  425. package/packages/shared-skills/skills/ulw-research/scripts/value-mode-unit.test.ts +179 -0
  426. package/packages/shared-skills/skills/ulw-research/scripts/value-rules-cli.test.ts +157 -0
  427. package/packages/shared-skills/skills/ulw-research/scripts/value-rules-followups.test.ts +72 -0
  428. package/packages/shared-skills/skills/ulw-research/scripts/value-rules-priority.test.ts +80 -0
  429. package/packages/omo-codex/plugin/skills/ultimate-browsing/engine/tests/fixtures/amp_redirect_stub.html +0 -7
  430. package/packages/omo-codex/plugin/skills/ultimate-browsing/engine/tests/fixtures/search_interstitial.html +0 -19
  431. package/packages/omo-codex/plugin/skills/ultimate-browsing/engine/tests/fixtures/wayback_available.json +0 -1
  432. package/packages/omo-codex/plugin/skills/ultimate-browsing/engine/tests/fixtures/wayback_snapshot.html +0 -1128
  433. package/packages/omo-codex/plugin/skills/ultimate-browsing/engine/tests/test_fetch_chain.py +0 -77
  434. package/packages/omo-codex/plugin/skills/ultimate-browsing/engine/tests/test_playwright_stealth.py +0 -86
  435. package/packages/omo-codex/plugin/skills/ultimate-browsing/engine/tests/test_playwright_templates.py +0 -279
  436. package/packages/omo-codex/plugin/skills/ultimate-browsing/engine/tests/test_surrogate.py +0 -252
  437. package/packages/omo-codex/plugin/skills/ultimate-browsing/engine/tests/test_surrogate_validators.py +0 -78
@@ -0,0 +1,183 @@
1
+ import { dirname, relative, resolve } from "node:path";
2
+
3
+ import { normalizeTextEdits } from "./workspace-edit-text.js";
4
+ import type {
5
+ ParsedWorkspaceOperation,
6
+ ParseFailure,
7
+ SimulatedWorkspaceEdit,
8
+ } from "./workspace-edit-plan-types.js";
9
+ import type { PlannedWorkspaceOperation, WorkspaceSnapshotEntry } from "./workspace-edit-types.js";
10
+ import { WorkspaceEditValidationError } from "./workspace-edit-types.js";
11
+
12
+ function isSameOrDescendant(candidate: string, parent: string): boolean {
13
+ const relativePath = relative(parent, candidate);
14
+ return relativePath === "" || (!relativePath.startsWith("..") && relativePath !== "..");
15
+ }
16
+
17
+ function removeVirtualSubtree(virtual: Map<string, WorkspaceSnapshotEntry>, path: string): void {
18
+ for (const candidate of [...virtual.keys()]) {
19
+ if (isSameOrDescendant(candidate, path)) virtual.delete(candidate);
20
+ }
21
+ virtual.set(path, { kind: "missing" });
22
+ }
23
+
24
+ function moveVirtualSubtree(virtual: Map<string, WorkspaceSnapshotEntry>, oldPath: string, newPath: string): void {
25
+ const moved = [...virtual.entries()].filter(([candidate]) => isSameOrDescendant(candidate, oldPath));
26
+ removeVirtualSubtree(virtual, oldPath);
27
+ removeVirtualSubtree(virtual, newPath);
28
+ for (const [candidate, entry] of moved) {
29
+ const suffix = relative(oldPath, candidate);
30
+ virtual.set(suffix === "" ? newPath : resolve(newPath, suffix), entry);
31
+ }
32
+ }
33
+
34
+ function virtualDirectoryHasChildren(virtual: ReadonlyMap<string, WorkspaceSnapshotEntry>, path: string): boolean {
35
+ for (const [candidate, entry] of virtual) {
36
+ if (candidate !== path && entry.kind !== "missing" && isSameOrDescendant(candidate, path)) return true;
37
+ }
38
+ return false;
39
+ }
40
+
41
+ function requireVirtualParent(
42
+ virtual: ReadonlyMap<string, WorkspaceSnapshotEntry>,
43
+ path: string,
44
+ changeIndex: number,
45
+ ): void {
46
+ if (virtual.get(dirname(path))?.kind !== "directory") {
47
+ throw new WorkspaceEditValidationError(changeIndex, `parent directory does not exist for ${path}`);
48
+ }
49
+ }
50
+
51
+ export function simulateOperations(
52
+ parsed: readonly ParsedWorkspaceOperation[],
53
+ snapshots: ReadonlyMap<string, WorkspaceSnapshotEntry>,
54
+ ): SimulatedWorkspaceEdit {
55
+ const virtual = new Map(snapshots);
56
+ const planned: PlannedWorkspaceOperation[] = [];
57
+ const failures: ParseFailure[] = [];
58
+ for (const operation of parsed) {
59
+ try {
60
+ planned.push(simulateOperation(operation, virtual));
61
+ } catch (error) {
62
+ if (error instanceof WorkspaceEditValidationError) {
63
+ failures.push({ changeIndex: operation.changeIndex, message: error.detail });
64
+ continue;
65
+ }
66
+ throw error;
67
+ }
68
+ }
69
+ return { operations: planned, failures };
70
+ }
71
+
72
+ function simulateOperation(
73
+ operation: ParsedWorkspaceOperation,
74
+ virtual: Map<string, WorkspaceSnapshotEntry>,
75
+ ): PlannedWorkspaceOperation {
76
+ switch (operation.kind) {
77
+ case "text":
78
+ return simulateText(operation, virtual);
79
+ case "create":
80
+ return simulateCreate(operation, virtual);
81
+ case "rename":
82
+ return simulateRename(operation, virtual);
83
+ case "delete":
84
+ return simulateDelete(operation, virtual);
85
+ }
86
+ }
87
+
88
+ function rejectSymbolicLink(operation: Exclude<ParsedWorkspaceOperation, { readonly kind: "text" }>): void {
89
+ if (operation.followedSymbolicLink) {
90
+ throw new WorkspaceEditValidationError(operation.changeIndex, "resource operations through symbolic links are unsupported");
91
+ }
92
+ }
93
+
94
+ function simulateText(
95
+ operation: Extract<ParsedWorkspaceOperation, { readonly kind: "text" }>,
96
+ virtual: Map<string, WorkspaceSnapshotEntry>,
97
+ ): PlannedWorkspaceOperation {
98
+ const entry = virtual.get(operation.path);
99
+ if (entry?.kind !== "file") throw new WorkspaceEditValidationError(operation.changeIndex, `${operation.path} is not a file`);
100
+ const normalized = normalizeTextEdits(entry.content, operation.edits, operation.changeIndex);
101
+ virtual.set(operation.path, { kind: "file", content: normalized.text });
102
+ return {
103
+ kind: "text",
104
+ changeIndex: operation.changeIndex,
105
+ path: operation.path,
106
+ beforeText: entry.content,
107
+ afterText: normalized.text,
108
+ editCount: normalized.edits.length,
109
+ documentVersion: operation.version,
110
+ };
111
+ }
112
+
113
+ function simulateCreate(
114
+ operation: Extract<ParsedWorkspaceOperation, { readonly kind: "create" }>,
115
+ virtual: Map<string, WorkspaceSnapshotEntry>,
116
+ ): PlannedWorkspaceOperation {
117
+ rejectSymbolicLink(operation);
118
+ requireVirtualParent(virtual, operation.path, operation.changeIndex);
119
+ const target = virtual.get(operation.path) ?? { kind: "missing" };
120
+ if (target.kind !== "missing") {
121
+ if (operation.overwrite && target.kind === "file") {
122
+ virtual.set(operation.path, { kind: "file", content: "" });
123
+ return { kind: "create", changeIndex: operation.changeIndex, path: operation.path, replaced: true };
124
+ }
125
+ if (operation.ignoreIfExists) return { kind: "noop", changeIndex: operation.changeIndex };
126
+ throw new WorkspaceEditValidationError(operation.changeIndex, `create target already exists: ${operation.path}`);
127
+ }
128
+ virtual.set(operation.path, { kind: "file", content: "" });
129
+ return { kind: "create", changeIndex: operation.changeIndex, path: operation.path, replaced: false };
130
+ }
131
+
132
+ function simulateRename(
133
+ operation: Extract<ParsedWorkspaceOperation, { readonly kind: "rename" }>,
134
+ virtual: Map<string, WorkspaceSnapshotEntry>,
135
+ ): PlannedWorkspaceOperation {
136
+ rejectSymbolicLink(operation);
137
+ const source = virtual.get(operation.oldPath) ?? { kind: "missing" };
138
+ if (source.kind === "missing") {
139
+ throw new WorkspaceEditValidationError(operation.changeIndex, `rename source does not exist: ${operation.oldPath}`);
140
+ }
141
+ if (operation.oldPath === operation.newPath) return { kind: "noop", changeIndex: operation.changeIndex };
142
+ if (isSameOrDescendant(operation.newPath, operation.oldPath)) {
143
+ throw new WorkspaceEditValidationError(operation.changeIndex, "cannot rename a path into its own subtree");
144
+ }
145
+ requireVirtualParent(virtual, operation.newPath, operation.changeIndex);
146
+ const destination = virtual.get(operation.newPath) ?? { kind: "missing" };
147
+ if (destination.kind !== "missing" && !operation.overwrite) {
148
+ if (operation.ignoreIfExists) return { kind: "noop", changeIndex: operation.changeIndex };
149
+ throw new WorkspaceEditValidationError(operation.changeIndex, `rename target already exists: ${operation.newPath}`);
150
+ }
151
+ moveVirtualSubtree(virtual, operation.oldPath, operation.newPath);
152
+ return {
153
+ kind: "rename",
154
+ changeIndex: operation.changeIndex,
155
+ oldPath: operation.oldPath,
156
+ newPath: operation.newPath,
157
+ sourceKind: source.kind,
158
+ replaceDestination: destination.kind !== "missing",
159
+ };
160
+ }
161
+
162
+ function simulateDelete(
163
+ operation: Extract<ParsedWorkspaceOperation, { readonly kind: "delete" }>,
164
+ virtual: Map<string, WorkspaceSnapshotEntry>,
165
+ ): PlannedWorkspaceOperation {
166
+ rejectSymbolicLink(operation);
167
+ const target = virtual.get(operation.path) ?? { kind: "missing" };
168
+ if (target.kind === "missing") {
169
+ if (operation.ignoreIfNotExists) return { kind: "noop", changeIndex: operation.changeIndex };
170
+ throw new WorkspaceEditValidationError(operation.changeIndex, `delete target does not exist: ${operation.path}`);
171
+ }
172
+ if (target.kind === "directory" && !operation.recursive && virtualDirectoryHasChildren(virtual, operation.path)) {
173
+ throw new WorkspaceEditValidationError(operation.changeIndex, `directory is not empty: ${operation.path}`);
174
+ }
175
+ removeVirtualSubtree(virtual, operation.path);
176
+ return {
177
+ kind: "delete",
178
+ changeIndex: operation.changeIndex,
179
+ path: operation.path,
180
+ targetKind: target.kind,
181
+ recursive: operation.recursive,
182
+ };
183
+ }
@@ -0,0 +1,53 @@
1
+ import { existsSync, lstatSync, readdirSync } from "node:fs";
2
+ import { dirname, resolve } from "node:path";
3
+
4
+ import { snapshotPath } from "./workspace-edit-path.js";
5
+ import type { ParsedWorkspaceOperation } from "./workspace-edit-plan-types.js";
6
+ import type { WorkspaceSnapshotEntry } from "./workspace-edit-types.js";
7
+
8
+ class WorkspaceSnapshotBuilder {
9
+ private readonly snapshots = new Map<string, WorkspaceSnapshotEntry>();
10
+
11
+ constructor(private readonly workspaceRoot: string) {}
12
+
13
+ build(operations: readonly ParsedWorkspaceOperation[]): ReadonlyMap<string, WorkspaceSnapshotEntry> {
14
+ this.add(this.workspaceRoot, false);
15
+ for (const operation of operations) {
16
+ switch (operation.kind) {
17
+ case "rename":
18
+ this.add(operation.oldPath, true);
19
+ this.add(operation.newPath, true);
20
+ break;
21
+ case "delete":
22
+ this.add(operation.path, true);
23
+ break;
24
+ case "text":
25
+ case "create":
26
+ this.add(operation.path, false);
27
+ break;
28
+ }
29
+ }
30
+ return this.snapshots;
31
+ }
32
+
33
+ private add(path: string, includeChildren: boolean): void {
34
+ let candidate = path;
35
+ while (true) {
36
+ const existing = this.snapshots.get(candidate);
37
+ if (existing === undefined || (includeChildren && existing.kind === "directory" && existing.children === undefined)) {
38
+ this.snapshots.set(candidate, snapshotPath(candidate, includeChildren && candidate === path));
39
+ }
40
+ if (candidate === this.workspaceRoot) break;
41
+ candidate = dirname(candidate);
42
+ }
43
+ if (!includeChildren || !existsSync(path) || !lstatSync(path).isDirectory()) return;
44
+ for (const child of readdirSync(path)) this.add(resolve(path, child), true);
45
+ }
46
+ }
47
+
48
+ export function snapshotOperations(
49
+ operations: readonly ParsedWorkspaceOperation[],
50
+ workspaceRoot: string,
51
+ ): ReadonlyMap<string, WorkspaceSnapshotEntry> {
52
+ return new WorkspaceSnapshotBuilder(workspaceRoot).build(operations);
53
+ }
@@ -0,0 +1,125 @@
1
+ import type { Position, Range, TextEdit } from "./types.js";
2
+ import { type NormalizedTextEditResult, WorkspaceEditValidationError } from "./workspace-edit-types.js";
3
+
4
+ interface IndexedTextEdit {
5
+ readonly edit: TextEdit;
6
+ readonly index: number;
7
+ }
8
+
9
+ interface PositionValidationContext {
10
+ readonly lines: readonly string[];
11
+ readonly changeIndex: number;
12
+ }
13
+
14
+ function comparePosition(left: Position, right: Position): number {
15
+ return left.line === right.line ? left.character - right.character : left.line - right.line;
16
+ }
17
+
18
+ function positionsEqual(left: Position, right: Position): boolean {
19
+ return left.line === right.line && left.character === right.character;
20
+ }
21
+
22
+ function rangesEqual(left: Range, right: Range): boolean {
23
+ return positionsEqual(left.start, right.start) && positionsEqual(left.end, right.end);
24
+ }
25
+
26
+ function isEmptyRange(range: Range): boolean {
27
+ return positionsEqual(range.start, range.end);
28
+ }
29
+
30
+ function formatRange(range: Range): string {
31
+ return `${range.start.line + 1}:${range.start.character + 1}-${range.end.line + 1}:${range.end.character + 1}`;
32
+ }
33
+
34
+ function validatePosition(position: Position, label: string, context: PositionValidationContext): void {
35
+ const { lines, changeIndex } = context;
36
+ if (!Number.isInteger(position.line) || !Number.isInteger(position.character)) {
37
+ throw new WorkspaceEditValidationError(changeIndex, `${label} position must use integer line and character`);
38
+ }
39
+ if (position.line < 0 || position.character < 0) {
40
+ throw new WorkspaceEditValidationError(changeIndex, `${label} position cannot be negative`);
41
+ }
42
+ const line = lines[position.line];
43
+ if (line === undefined) {
44
+ throw new WorkspaceEditValidationError(changeIndex, `${label} line ${position.line} is outside the document`);
45
+ }
46
+ if (position.character > line.length) {
47
+ throw new WorkspaceEditValidationError(
48
+ changeIndex,
49
+ `${label} character ${position.character} is outside line ${position.line}`,
50
+ );
51
+ }
52
+ }
53
+
54
+ function validateRange(range: Range, lines: readonly string[], changeIndex: number): void {
55
+ const context: PositionValidationContext = { lines, changeIndex };
56
+ validatePosition(range.start, "start", context);
57
+ validatePosition(range.end, "end", context);
58
+ if (comparePosition(range.start, range.end) > 0) {
59
+ throw new WorkspaceEditValidationError(changeIndex, `range ${formatRange(range)} ends before it starts`);
60
+ }
61
+ }
62
+
63
+ function sortAndDeduplicate(edits: readonly TextEdit[]): readonly TextEdit[] {
64
+ const sorted = edits
65
+ .map<IndexedTextEdit>((edit, index) => ({ edit, index }))
66
+ .sort((left, right) => {
67
+ const positionOrder = comparePosition(right.edit.range.start, left.edit.range.start);
68
+ return positionOrder === 0 ? right.index - left.index : positionOrder;
69
+ });
70
+ const unique: TextEdit[] = [];
71
+ for (const entry of sorted) {
72
+ const previous = unique.at(-1);
73
+ if (
74
+ previous !== undefined &&
75
+ !isEmptyRange(entry.edit.range) &&
76
+ rangesEqual(previous.range, entry.edit.range) &&
77
+ previous.newText === entry.edit.newText
78
+ ) {
79
+ continue;
80
+ }
81
+ unique.push(entry.edit);
82
+ }
83
+ return unique;
84
+ }
85
+
86
+ function validateNoOverlap(edits: readonly TextEdit[], changeIndex: number): void {
87
+ for (let index = 0; index < edits.length - 1; index += 1) {
88
+ const later = edits[index];
89
+ const earlier = edits[index + 1];
90
+ if (later === undefined || earlier === undefined) continue;
91
+ if (comparePosition(earlier.range.end, later.range.start) > 0) {
92
+ throw new WorkspaceEditValidationError(
93
+ changeIndex,
94
+ `overlapping edits ${formatRange(earlier.range)} and ${formatRange(later.range)}`,
95
+ );
96
+ }
97
+ }
98
+ }
99
+
100
+ function applyNormalizedTextEdits(content: string, edits: readonly TextEdit[]): string {
101
+ const lines = content.split("\n");
102
+ for (const edit of edits) {
103
+ const { start, end } = edit.range;
104
+ const startLine = lines[start.line];
105
+ const endLine = lines[end.line];
106
+ if (startLine === undefined || endLine === undefined) continue;
107
+ const replacement = startLine.slice(0, start.character) + edit.newText + endLine.slice(end.character);
108
+ lines.splice(start.line, end.line - start.line + 1, ...replacement.split("\n"));
109
+ }
110
+ return lines.join("\n");
111
+ }
112
+
113
+ export function normalizeTextEdits(
114
+ content: string,
115
+ edits: readonly TextEdit[],
116
+ changeIndex: number,
117
+ ): NormalizedTextEditResult {
118
+ const lines = content.split("\n");
119
+ for (const edit of edits) {
120
+ validateRange(edit.range, lines, changeIndex);
121
+ }
122
+ const normalized = sortAndDeduplicate(edits);
123
+ validateNoOverlap(normalized, changeIndex);
124
+ return { edits: normalized, text: applyNormalizedTextEdits(content, normalized) };
125
+ }
@@ -0,0 +1,121 @@
1
+ import type { TextEdit, WorkspaceEdit } from "./types.js";
2
+
3
+ export interface ApplyResult {
4
+ readonly success: boolean;
5
+ readonly filesModified: readonly string[];
6
+ readonly totalEdits: number;
7
+ readonly errors: readonly string[];
8
+ readonly failedChange?: number;
9
+ readonly lateAbort?: boolean;
10
+ }
11
+
12
+ export interface LspRenameResult {
13
+ readonly edit: WorkspaceEdit | null;
14
+ readonly apply: ApplyResult;
15
+ }
16
+
17
+ export type WorkspaceSnapshotEntry =
18
+ | { readonly kind: "missing" }
19
+ | { readonly kind: "file"; readonly content: string }
20
+ | { readonly kind: "directory"; readonly children?: readonly string[] };
21
+
22
+ export type PlannedWorkspaceOperation =
23
+ | {
24
+ readonly kind: "text";
25
+ readonly changeIndex: number;
26
+ readonly path: string;
27
+ readonly beforeText: string;
28
+ readonly afterText: string;
29
+ readonly editCount: number;
30
+ readonly documentVersion: number | null;
31
+ }
32
+ | {
33
+ readonly kind: "create";
34
+ readonly changeIndex: number;
35
+ readonly path: string;
36
+ readonly replaced: boolean;
37
+ }
38
+ | {
39
+ readonly kind: "rename";
40
+ readonly changeIndex: number;
41
+ readonly oldPath: string;
42
+ readonly newPath: string;
43
+ readonly sourceKind: "file" | "directory";
44
+ readonly replaceDestination: boolean;
45
+ }
46
+ | {
47
+ readonly kind: "delete";
48
+ readonly changeIndex: number;
49
+ readonly path: string;
50
+ readonly targetKind: "file" | "directory";
51
+ readonly recursive: boolean;
52
+ }
53
+ | { readonly kind: "noop"; readonly changeIndex: number };
54
+
55
+ export interface WorkspaceEditPlan {
56
+ readonly workspaceRoot: string;
57
+ readonly operations: readonly PlannedWorkspaceOperation[];
58
+ readonly snapshots: ReadonlyMap<string, WorkspaceSnapshotEntry>;
59
+ readonly firstChangeByPath: ReadonlyMap<string, number>;
60
+ readonly reportedPathByCanonical: ReadonlyMap<string, string>;
61
+ readonly fingerprint: string;
62
+ }
63
+
64
+ export type WorkspaceEditPlanResult =
65
+ | { readonly success: true; readonly plan: WorkspaceEditPlan }
66
+ | { readonly success: false; readonly result: ApplyResult };
67
+
68
+ export type WorkspaceMutation =
69
+ | {
70
+ readonly kind: "text";
71
+ readonly path: string;
72
+ readonly beforeText: string;
73
+ readonly afterText: string;
74
+ }
75
+ | { readonly kind: "create"; readonly path: string; readonly replaced: boolean }
76
+ | {
77
+ readonly kind: "rename";
78
+ readonly oldPath: string;
79
+ readonly newPath: string;
80
+ readonly sourceKind: "file" | "directory";
81
+ }
82
+ | { readonly kind: "delete"; readonly path: string; readonly targetKind: "file" | "directory" };
83
+
84
+ export interface WorkspaceMutationDelta {
85
+ readonly operations: readonly WorkspaceMutation[];
86
+ readonly changedPaths: readonly string[];
87
+ }
88
+
89
+ export interface WorkspaceEditCommit {
90
+ readonly result: ApplyResult;
91
+ readonly delta: WorkspaceMutationDelta;
92
+ readonly fingerprint: string | null;
93
+ }
94
+
95
+ export interface WorkspaceEditCommitIo {
96
+ readonly writeFile: (path: string, content: string) => void;
97
+ readonly rename: (oldPath: string, newPath: string) => void;
98
+ readonly remove: (path: string, recursive: boolean) => void;
99
+ }
100
+
101
+ export interface ApplyWorkspaceEditOptions {
102
+ readonly workspaceRoot?: string;
103
+ readonly signal?: AbortSignal;
104
+ readonly io?: Partial<WorkspaceEditCommitIo>;
105
+ }
106
+
107
+ export interface NormalizedTextEditResult {
108
+ readonly edits: readonly TextEdit[];
109
+ readonly text: string;
110
+ }
111
+
112
+ export class WorkspaceEditValidationError extends Error {
113
+ override readonly name = "WorkspaceEditValidationError";
114
+
115
+ constructor(
116
+ readonly changeIndex: number,
117
+ readonly detail: string,
118
+ ) {
119
+ super(`change ${changeIndex}: ${detail}`);
120
+ }
121
+ }
@@ -0,0 +1,95 @@
1
+ import { existsSync, mkdtempSync, readFileSync, rmSync, writeFileSync } from "node:fs";
2
+ import { tmpdir } from "node:os";
3
+ import { join } from "node:path";
4
+ import { pathToFileURL } from "node:url";
5
+
6
+ import { afterEach, describe, expect, it } from "bun:test";
7
+
8
+ import { applyWorkspaceEdit } from "./workspace-edit.js";
9
+
10
+ const tempDirectories: string[] = [];
11
+
12
+ afterEach(() => {
13
+ for (const directory of tempDirectories.splice(0)) {
14
+ rmSync(directory, { recursive: true, force: true });
15
+ }
16
+ });
17
+
18
+ describe("applyWorkspaceEdit preserved behavior", () => {
19
+ it("#given a valid text edit #when applied #then the file and ApplyResult remain compatible", () => {
20
+ // given
21
+ const workspace = makeTempDirectory();
22
+ const source = join(workspace, "source.ts");
23
+ writeFileSync(source, "const before = 1;\n", "utf-8");
24
+
25
+ // when
26
+ const result = applyWorkspaceEdit(
27
+ {
28
+ changes: {
29
+ [pathToFileURL(source).href]: [
30
+ {
31
+ range: { start: { line: 0, character: 6 }, end: { line: 0, character: 12 } },
32
+ newText: "after",
33
+ },
34
+ ],
35
+ },
36
+ },
37
+ { workspaceRoot: workspace },
38
+ );
39
+
40
+ // then
41
+ expect(result).toEqual({ success: true, filesModified: [source], totalEdits: 1, errors: [] });
42
+ expect(readFileSync(source, "utf-8")).toBe("const after = 1;\n");
43
+ });
44
+
45
+ it("#given a resource rename #when applied #then content moves and the destination is reported", () => {
46
+ // given
47
+ const workspace = makeTempDirectory();
48
+ const source = join(workspace, "before.ts");
49
+ const destination = join(workspace, "after.ts");
50
+ writeFileSync(source, "export const value = 1;\n", "utf-8");
51
+
52
+ // when
53
+ const result = applyWorkspaceEdit(
54
+ {
55
+ documentChanges: [
56
+ { kind: "rename", oldUri: pathToFileURL(source).href, newUri: pathToFileURL(destination).href },
57
+ ],
58
+ },
59
+ { workspaceRoot: workspace },
60
+ );
61
+
62
+ // then
63
+ expect(result).toEqual({ success: true, filesModified: [destination], totalEdits: 0, errors: [] });
64
+ expect(existsSync(source)).toBe(false);
65
+ expect(readFileSync(destination, "utf-8")).toBe("export const value = 1;\n");
66
+ });
67
+
68
+ it("#given an empty workspace edit #when applied #then it remains a successful no-op", () => {
69
+ // given
70
+ const workspace = makeTempDirectory();
71
+
72
+ // when
73
+ const result = applyWorkspaceEdit({}, { workspaceRoot: workspace });
74
+
75
+ // then
76
+ expect(result).toEqual({ success: true, filesModified: [], totalEdits: 0, errors: [] });
77
+ });
78
+
79
+ it("#given no workspace edit #when applied #then the existing failure remains explicit", () => {
80
+ // given
81
+ const workspace = makeTempDirectory();
82
+
83
+ // when
84
+ const result = applyWorkspaceEdit(null, { workspaceRoot: workspace });
85
+
86
+ // then
87
+ expect(result).toEqual({ success: false, filesModified: [], totalEdits: 0, errors: ["No edit provided"] });
88
+ });
89
+ });
90
+
91
+ function makeTempDirectory(): string {
92
+ const directory = mkdtempSync(join(tmpdir(), "lsp-workspace-characterization-"));
93
+ tempDirectories.push(directory);
94
+ return directory;
95
+ }
@@ -0,0 +1,55 @@
1
+ import { contextCwd } from "../request-context.js";
2
+ import type { WorkspaceEdit } from "./types.js";
3
+ import { commitWorkspaceEditPlan } from "./workspace-edit-commit.js";
4
+ import { fingerprintWorkspaceEdit, planWorkspaceEdit } from "./workspace-edit-plan.js";
5
+ import type {
6
+ ApplyResult,
7
+ ApplyWorkspaceEditOptions,
8
+ WorkspaceEditCommit,
9
+ WorkspaceMutationDelta,
10
+ } from "./workspace-edit-types.js";
11
+
12
+ export type {
13
+ ApplyResult,
14
+ ApplyWorkspaceEditOptions,
15
+ LspRenameResult,
16
+ PlannedWorkspaceOperation,
17
+ WorkspaceEditCommit,
18
+ WorkspaceEditCommitIo,
19
+ WorkspaceEditPlan,
20
+ WorkspaceEditPlanResult,
21
+ WorkspaceMutation,
22
+ WorkspaceMutationDelta,
23
+ } from "./workspace-edit-types.js";
24
+ export { commitWorkspaceEditPlan } from "./workspace-edit-commit.js";
25
+ export { fingerprintWorkspaceEdit, planWorkspaceEdit } from "./workspace-edit-plan.js";
26
+
27
+ const EMPTY_DELTA: WorkspaceMutationDelta = { operations: [], changedPaths: [] };
28
+
29
+ function noEditCommit(): WorkspaceEditCommit {
30
+ return {
31
+ result: { success: false, filesModified: [], totalEdits: 0, errors: ["No edit provided"] },
32
+ delta: EMPTY_DELTA,
33
+ fingerprint: null,
34
+ };
35
+ }
36
+
37
+ export function applyWorkspaceEditDetailed(
38
+ edit: WorkspaceEdit | null,
39
+ options: ApplyWorkspaceEditOptions = {},
40
+ ): WorkspaceEditCommit {
41
+ if (!edit) return noEditCommit();
42
+ const workspaceRoot = options.workspaceRoot ?? contextCwd();
43
+ const planned = planWorkspaceEdit(edit, workspaceRoot);
44
+ if (!planned.success) return { result: planned.result, delta: EMPTY_DELTA, fingerprint: null };
45
+ return commitWorkspaceEditPlan(planned.plan, options);
46
+ }
47
+
48
+ export function applyWorkspaceEdit(edit: WorkspaceEdit | null, options: ApplyWorkspaceEditOptions = {}): ApplyResult {
49
+ return applyWorkspaceEditDetailed(edit, options).result;
50
+ }
51
+
52
+ export function workspaceEditFingerprint(edit: WorkspaceEdit, workspaceRoot: string): string | null {
53
+ const fingerprint = fingerprintWorkspaceEdit(edit, workspaceRoot);
54
+ return fingerprint.success ? fingerprint.fingerprint : null;
55
+ }
@@ -0,0 +1,18 @@
1
+ /** Repository marker: an ancestor containing this always wins over intermediate package markers. */
2
+ export const GIT_WORKSPACE_MARKER = ".git" as const;
3
+
4
+ /**
5
+ * Package/project markers. On their own they resolve to the NEAREST marked directory, but inside a
6
+ * request cwd they are only a fallback: a `.git` ancestor further up collapses nested package roots
7
+ * (one client per repository instead of one per monorepo package).
8
+ */
9
+ export const PROJECT_WORKSPACE_MARKERS = [
10
+ "package.json",
11
+ "pyproject.toml",
12
+ "Cargo.toml",
13
+ "go.mod",
14
+ "pom.xml",
15
+ "build.gradle",
16
+ ] as const;
17
+
18
+ export const WORKSPACE_MARKERS = [GIT_WORKSPACE_MARKER, ...PROJECT_WORKSPACE_MARKERS] as const;