oh-my-opencode 5.0.0-beta.3 → 5.0.0-beta.31
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.
- package/.agents/command/publish.md +44 -16
- package/.agents/skills/publish/SKILL.md +44 -16
- package/.agents/skills/senpi-qa/SKILL.md +80 -0
- package/.agents/skills/senpi-qa/scripts/resolve-evidence-dir.mjs +65 -0
- package/.agents/skills/senpi-qa/scripts/resolve-evidence-dir.test.mjs +171 -0
- package/.agents/skills/work-with-pr/SKILL.md +37 -23
- package/.opencode/command/publish.md +44 -16
- package/.opencode/skills/work-with-pr/SKILL.md +37 -23
- package/README.ja.md +25 -21
- package/README.ko.md +25 -21
- package/README.md +38 -23
- package/README.ru.md +24 -20
- package/README.zh-cn.md +25 -21
- package/dist/agents/atlas/agent.d.ts +0 -1
- package/dist/agents/sisyphus/grok-4.d.ts +20 -0
- package/dist/agents/sisyphus/index.d.ts +2 -0
- package/dist/agents/sisyphus-agent-config.d.ts +6 -0
- package/dist/agents/sisyphus-agent-factory.d.ts +1 -1
- package/dist/agents/sisyphus-runtime-prompt-reconciler.d.ts +15 -4
- package/dist/agents/types.d.ts +2 -2
- package/dist/cli/config-manager/parse-opencode-config-file.d.ts +2 -1
- package/dist/cli/doctor/checks/system-plugin.d.ts +4 -3
- package/dist/cli/fallback-lane-policy.d.ts +1 -0
- package/dist/cli/index.js +22601 -20302
- package/dist/cli/install-codex/install-codex-test-fixtures.d.ts +1 -1
- package/dist/cli/run/on-complete-hook.d.ts +2 -0
- package/dist/cli/runtime-commands.d.ts +1 -1
- package/dist/cli/worktree-sweep/classify.d.ts +16 -0
- package/dist/cli/worktree-sweep/format.d.ts +8 -0
- package/dist/cli/worktree-sweep/git.d.ts +19 -0
- package/dist/cli/worktree-sweep/index.d.ts +7 -0
- package/dist/cli/worktree-sweep/options.d.ts +2 -0
- package/dist/cli/worktree-sweep/parse-worktree-list.d.ts +8 -0
- package/dist/cli/worktree-sweep/sweep.d.ts +2 -0
- package/dist/cli/worktree-sweep/types.d.ts +65 -0
- package/dist/cli/worktree-sweep/worktree-sweep.d.ts +2 -0
- package/dist/cli-node/index.js +22219 -19897
- package/dist/config/schema/background-task.d.ts +1 -0
- package/dist/config/schema/commands.d.ts +1 -1
- package/dist/config/schema/hooks.d.ts +1 -1
- package/dist/config/schema/oh-my-opencode-config.d.ts +5 -1
- package/dist/config/schema/ulw-execute.d.ts +5 -0
- package/dist/config/validate.d.ts +2 -0
- package/dist/create-hooks.d.ts +3 -1
- package/dist/features/background-agent/constants.d.ts +0 -7
- package/dist/features/background-agent/manager.d.ts +2 -1
- package/dist/features/background-agent/parent-wake-dispatched-tracker.d.ts +0 -1
- package/dist/features/background-agent/subagent-spawn-limits.d.ts +8 -0
- package/dist/features/btw-side/btw-command-draft.d.ts +7 -0
- package/dist/features/btw-side/context-injector.d.ts +15 -0
- package/dist/features/btw-side/index.d.ts +8 -0
- package/dist/features/btw-side/metadata.d.ts +15 -0
- package/dist/features/btw-side/parent-context-budget.d.ts +9 -0
- package/dist/features/btw-side/server-session-registry.d.ts +8 -0
- package/dist/features/btw-side/tui-adoption-cache.d.ts +13 -0
- package/dist/features/btw-side/tui-adoption-guard.d.ts +5 -0
- package/dist/features/btw-side/tui-controller-types.d.ts +68 -0
- package/dist/features/btw-side/tui-controller.d.ts +19 -0
- package/dist/features/btw-side/tui-escape-return.d.ts +12 -0
- package/dist/features/btw-side/tui-keymap.d.ts +17 -0
- package/dist/features/btw-side/tui-parent-validator.d.ts +6 -0
- package/dist/features/btw-side/tui-picker-options.d.ts +20 -0
- package/dist/features/btw-side/tui-picker.d.ts +9 -0
- package/dist/features/btw-side/tui-prompt-queue.d.ts +8 -0
- package/dist/features/btw-side/tui-session-bridge.d.ts +11 -0
- package/dist/features/btw-side/tui-session-catalog.d.ts +35 -0
- package/dist/features/btw-side/tui-side-removal.d.ts +11 -0
- package/dist/features/btw-side/tui-side-start.d.ts +9 -0
- package/dist/features/btw-side/tui-wiring.d.ts +8 -0
- package/dist/features/builtin-commands/templates/ulw-execute.d.ts +1 -0
- package/dist/features/builtin-commands/types.d.ts +1 -1
- package/dist/features/opengateway-provider/index.d.ts +13 -0
- package/dist/features/task-toast-manager/manager.d.ts +0 -24
- package/dist/features/team-mode/tools/messaging-fallback-wake.d.ts +15 -0
- package/dist/hooks/anthropic-context-window-limit-recovery/message-storage-directory.d.ts +0 -3
- package/dist/hooks/anthropic-context-window-limit-recovery/state.d.ts +1 -0
- package/dist/hooks/anthropic-context-window-limit-recovery/storage/empty-messages.d.ts +0 -1
- package/dist/hooks/atlas/atlas-hook.d.ts +1 -0
- package/dist/hooks/atlas/atlas-lifecycle-store.d.ts +50 -0
- package/dist/hooks/atlas/event-handler.d.ts +1 -0
- package/dist/hooks/atlas/final-wave-approval-gate.test-support.d.ts +50 -0
- package/dist/hooks/atlas/system-reminder-templates.d.ts +0 -1
- package/dist/hooks/atlas/tool-execute-before.d.ts +3 -0
- package/dist/hooks/atlas/types.d.ts +1 -0
- package/dist/hooks/claude-code-hooks/session-hook-state.d.ts +1 -0
- package/dist/hooks/claude-code-hooks/stop.d.ts +2 -0
- package/dist/hooks/claude-code-hooks/todo.d.ts +0 -1
- package/dist/hooks/claude-code-hooks/transcript.d.ts +2 -0
- package/dist/hooks/fsync-skip-warning/index.d.ts +4 -0
- package/dist/hooks/hashline-edit-diff-enhancer/hook.d.ts +1 -0
- package/dist/hooks/hashline-edit-diff-enhancer/pending-captures.d.ts +13 -0
- package/dist/hooks/index.d.ts +1 -1
- package/dist/hooks/keyword-detector/hook.d.ts +7 -0
- package/dist/hooks/keyword-detector/ultrawork/source-detector.d.ts +0 -1
- package/dist/hooks/model-fallback/hook.d.ts +1 -1
- package/dist/hooks/prometheus-md-only/agent-resolution.d.ts +2 -2
- package/dist/hooks/runtime-fallback/chat-message-handler.d.ts +2 -0
- package/dist/hooks/runtime-fallback/retry-model-payload.d.ts +1 -0
- package/dist/hooks/runtime-fallback/runtime-model-settings.d.ts +6 -0
- package/dist/hooks/runtime-fallback/session-status-handler.d.ts +1 -1
- package/dist/hooks/runtime-fallback/types.d.ts +3 -1
- package/dist/hooks/sisyphus-junior-notepad/constants.d.ts +1 -1
- package/dist/hooks/todo-continuation-enforcer/types.d.ts +1 -0
- package/dist/hooks/{start-work → ulw-execute}/context-info-builder.d.ts +1 -1
- package/dist/hooks/{start-work → ulw-execute}/index.d.ts +1 -1
- package/dist/hooks/ulw-execute/ulw-execute-hook.d.ts +23 -0
- package/dist/index.js +12989 -7152
- package/dist/oh-my-opencode.schema.json +20 -2
- package/dist/plugin/chat-message/types.d.ts +3 -3
- package/dist/plugin/chat-message/ulw-execute-message.d.ts +5 -0
- package/dist/plugin/event-session-lifecycle.d.ts +1 -0
- package/dist/plugin/hooks/create-core-hooks.d.ts +2 -1
- package/dist/plugin/hooks/create-session-hooks.d.ts +2 -2
- package/dist/plugin/hooks/create-transform-hooks.d.ts +2 -0
- package/dist/plugin/messages-transform.d.ts +1 -0
- package/dist/plugin-dispose.d.ts +3 -0
- package/dist/shared/agent-tool-restrictions.d.ts +0 -1
- package/dist/shared/index.d.ts +2 -0
- package/dist/shared/legacy-plugin-warning.d.ts +2 -1
- package/dist/shared/normalize-sdk-response.d.ts +1 -0
- package/dist/shared/plugin-entry-migrator.d.ts +4 -3
- package/dist/shared/plugin-entry-shape.d.ts +6 -0
- package/dist/shared/runtime-fallback-retry-marker.d.ts +16 -0
- package/dist/shared/shell-env.d.ts +1 -1
- package/dist/skills/ast-grep/AGENTS.md +51 -0
- package/dist/skills/coding-agent-sessions/AGENTS.md +62 -0
- package/dist/skills/coding-agent-sessions/SKILL.md +3 -2
- package/dist/skills/coding-agent-sessions/references/all-platforms.md +1 -1
- package/dist/skills/coding-agent-sessions/references/senpi.md +4 -4
- package/dist/skills/coding-agent-sessions/scripts/agent_sessions/pi_family.py +1 -1
- package/dist/skills/data-scientist/SKILL.md +99 -239
- package/dist/skills/data-scientist/references/execution-surfaces.md +91 -0
- package/dist/skills/data-scientist/references/placement.md +74 -0
- package/dist/skills/data-scientist/references/polars-lane.md +95 -0
- package/dist/skills/data-scientist/references/uv-setup.md +1 -1
- package/dist/skills/data-scientist/references/visualization.md +64 -0
- package/dist/skills/data-scientist/scripts/ensure-js-deps.sh +28 -0
- package/dist/skills/data-scientist/scripts/ensure-py-deps.sh +37 -0
- package/dist/skills/debugging/SKILL.md +2 -0
- package/dist/skills/debugging/references/methodology/00-setup.md +12 -0
- package/dist/skills/debugging/references/methodology/02-investigate.md +21 -0
- package/dist/skills/debugging/references/runtimes/go.md +15 -1
- package/dist/skills/debugging/references/runtimes/native-binary.md +38 -0
- package/dist/skills/debugging/references/runtimes/node.md +25 -0
- package/dist/skills/debugging/references/runtimes/python.md +13 -0
- package/dist/skills/debugging/references/runtimes/rust.md +41 -0
- package/dist/skills/debugging/references/scripts/dap.mjs +267 -0
- package/dist/skills/debugging/references/scripts/dap.test.ts +86 -0
- package/dist/skills/debugging/references/scripts/fixture-adapter.mjs +59 -0
- package/dist/skills/debugging/references/tools/dap.md +103 -0
- package/dist/skills/debugging/references/tools/frida.md +193 -0
- package/dist/skills/frontend/SKILL.md +11 -7
- package/dist/skills/frontend/references/design/_INDEX.md +1 -0
- package/dist/skills/frontend/references/design/print-paged-media.md +76 -0
- package/dist/skills/frontend/references/design/stylegallery.md +80 -0
- package/dist/skills/frontend/references/designpowers/README.md +1 -1
- package/dist/skills/frontend/references/designpowers/lane-a-direction.md +1 -1
- package/dist/skills/frontend/references/designpowers/lane-b-execution.md +11 -11
- package/dist/skills/frontend/references/designpowers/lane-d-memory.md +3 -3
- package/dist/skills/frontend/references/designpowers/orchestration.md +1 -1
- package/dist/skills/frontend/references/designpowers/routing.md +5 -5
- package/dist/skills/review-work/SKILL.md +3 -3
- package/dist/skills/ultimate-browsing/ATTRIBUTION.md +37 -10
- package/dist/skills/ultimate-browsing/SKILL.md +2 -0
- package/dist/skills/ultimate-browsing/engine/AGENTS.md +179 -0
- package/dist/skills/ultimate-browsing/engine/templates/package.json +1 -1
- package/dist/skills/ultimate-browsing/references/chrome-stealth.md +13 -11
- package/dist/skills/{start-work → ulw-execute}/SKILL.md +9 -8
- package/dist/skills/ulw-plan/SKILL.md +6 -6
- package/dist/skills/ulw-plan/references/full-workflow.md +31 -7
- package/dist/skills/ulw-plan/references/intent-clear.md +2 -1
- package/dist/skills/ulw-plan/references/intent-unclear.md +5 -5
- package/dist/skills/ulw-research/SKILL.md +4 -2
- package/dist/skills/visual-qa/AGENTS.md +58 -0
- package/dist/skills/visual-qa/SKILL.md +3 -2
- package/dist/tools/delegate-task/builtin-categories.d.ts +1 -0
- package/dist/tools/delegate-task/builtin-category-definition.d.ts +1 -0
- package/dist/tools/delegate-task/sync-session-cleanup.d.ts +3 -0
- package/dist/tools/delegate-task/sync-session-poller.d.ts +1 -0
- package/dist/tools/delegate-task/tool-description.d.ts +3 -1
- package/dist/tools/delegate-task/types.d.ts +4 -0
- package/dist/tui.d.ts +12 -0
- package/dist/tui.js +11522 -11501
- package/package.json +42 -36
- package/packages/git-bash-mcp/dist/cli.js +6 -1
- package/packages/git-bash-mcp/package.json +1 -1
- package/packages/lsp-core/src/index.ts +1 -0
- package/packages/lsp-core/src/lsp/client-diagnostics-concurrency.integration.test.ts +44 -0
- package/packages/lsp-core/src/lsp/client-diagnostics-freshness.integration.test.ts +0 -28
- package/packages/lsp-core/src/lsp/client-wrapper-outside-cwd.test.ts +78 -0
- package/packages/lsp-core/src/lsp/client-wrapper.test.ts +163 -13
- package/packages/lsp-core/src/lsp/client-wrapper.ts +110 -23
- package/packages/lsp-core/src/lsp/client.ts +26 -0
- package/packages/lsp-core/src/lsp/connection.ts +16 -0
- package/packages/lsp-core/src/lsp/constants.ts +6 -0
- package/packages/lsp-core/src/lsp/errors.ts +15 -0
- package/packages/lsp-core/src/lsp/format-document.test.ts +143 -0
- package/packages/lsp-core/src/lsp/format-document.ts +90 -0
- package/packages/lsp-core/src/lsp/manager-lifecycle.test.ts +262 -0
- package/packages/lsp-core/src/lsp/manager-max-clients.test.ts +151 -0
- package/packages/lsp-core/src/lsp/manager.ts +138 -12
- package/packages/lsp-core/src/lsp/outside-context-workspace.ts +33 -0
- package/packages/lsp-core/src/lsp/server-definitions.ts +29 -0
- package/packages/lsp-core/src/lsp/server-installation.test.ts +376 -0
- package/packages/lsp-core/src/lsp/server-installation.ts +200 -27
- package/packages/lsp-core/src/lsp/server-resolution-local-binary.test.ts +170 -0
- package/packages/lsp-core/src/lsp/server-resolution.ts +18 -5
- package/packages/lsp-core/src/lsp/transport.ts +9 -0
- package/packages/lsp-core/src/lsp/types.ts +8 -0
- package/packages/lsp-core/src/lsp/workspace-edit-adversarial.test.ts +20 -1
- package/packages/lsp-core/src/lsp/workspace-markers.ts +18 -0
- package/packages/lsp-core/src/mcp.ts +3 -0
- package/packages/lsp-core/src/request-context.test.ts +29 -0
- package/packages/lsp-core/src/request-context.ts +1 -1
- package/packages/lsp-core/src/tool-surface.test.ts +13 -1
- package/packages/lsp-core/src/tools/definitions.ts +14 -0
- package/packages/lsp-core/src/tools/diagnostics.ts +3 -3
- package/packages/lsp-core/src/tools/format.test.ts +56 -0
- package/packages/lsp-core/src/tools/format.ts +56 -0
- package/packages/lsp-core/src/tools/index.ts +1 -0
- package/packages/lsp-core/src/tools/navigation.ts +4 -2
- package/packages/lsp-core/src/tools/rename.ts +4 -2
- package/packages/lsp-core/src/tools/symbols.ts +1 -1
- package/packages/lsp-core/src/tools/types.ts +10 -0
- package/packages/lsp-daemon/dist/cli.js +752 -307
- package/packages/lsp-daemon/dist/client.d.ts +10 -0
- package/packages/lsp-daemon/dist/client.js +712 -264
- package/packages/lsp-daemon/dist/daemon-client.d.ts +1 -0
- package/packages/lsp-daemon/dist/daemon-client.js +3 -0
- package/packages/lsp-daemon/dist/ensure-daemon.js +1 -0
- package/packages/lsp-daemon/dist/index.js +716 -273
- package/packages/lsp-daemon/dist/proxy.js +3 -0
- package/packages/lsp-daemon/dist/version-reap.js +1 -1
- package/packages/lsp-daemon/package.json +1 -1
- package/packages/lsp-tools-mcp/dist/cli.js +671 -228
- package/packages/lsp-tools-mcp/dist/lsp/manager.js +207 -103
- package/packages/lsp-tools-mcp/dist/mcp.js +673 -230
- package/packages/lsp-tools-mcp/dist/request-context.js +12 -13
- package/packages/lsp-tools-mcp/dist/tools.js +677 -238
- package/packages/omo-codex/THIRD-PARTY-NOTICES.md +4 -4
- package/packages/omo-codex/plugin/.codex-plugin/plugin.json +4 -4
- package/packages/omo-codex/plugin/AGENTS.md +47 -0
- package/packages/omo-codex/plugin/README.md +1 -1
- package/packages/omo-codex/plugin/components/bootstrap/dist/cli.js +34 -33
- package/packages/omo-codex/plugin/components/bootstrap/hooks/hooks.json +1 -1
- package/packages/omo-codex/plugin/components/bootstrap/package.json +1 -1
- package/packages/omo-codex/plugin/components/bootstrap/src/hook.ts +1 -0
- package/packages/omo-codex/plugin/components/codegraph/dist/cli.js +323 -117
- package/packages/omo-codex/plugin/components/codegraph/dist/serve.js +275 -85
- package/packages/omo-codex/plugin/components/codegraph/package.json +4 -4
- package/packages/omo-codex/plugin/components/codegraph/src/mcp-bridge.ts +1 -0
- package/packages/omo-codex/plugin/components/codegraph/src/mcp-unavailable.ts +12 -0
- package/packages/omo-codex/plugin/components/codegraph/src/session-start-hook-runtime.ts +1 -0
- package/packages/omo-codex/plugin/components/codegraph/test/serve-unavailable-idle.test.ts +47 -0
- package/packages/omo-codex/plugin/components/comment-checker/AGENTS.md +9 -0
- package/packages/omo-codex/plugin/components/comment-checker/biome.json +2 -2
- package/packages/omo-codex/plugin/components/comment-checker/dist/cli.js +2 -1
- package/packages/omo-codex/plugin/components/comment-checker/hooks/hooks.json +1 -1
- package/packages/omo-codex/plugin/components/comment-checker/package.json +5 -5
- package/packages/omo-codex/plugin/components/comment-checker/src/apply-patch.ts +2 -8
- package/packages/omo-codex/plugin/components/comment-checker/src/core.ts +1 -2
- package/packages/omo-codex/plugin/components/comment-checker/src/request-extractor.ts +1 -1
- package/packages/omo-codex/plugin/components/comment-checker/src/runner.ts +1 -0
- package/packages/omo-codex/plugin/components/git-bash/AGENTS.md +1 -1
- package/packages/omo-codex/plugin/components/git-bash/hooks/hooks.json +2 -2
- package/packages/omo-codex/plugin/components/git-bash/package.json +3 -4
- package/packages/omo-codex/plugin/components/lazycodex-executor-verify/biome.json +2 -2
- package/packages/omo-codex/plugin/components/lazycodex-executor-verify/dist/cli.js +1 -5
- package/packages/omo-codex/plugin/components/lazycodex-executor-verify/dist/codex-hook.js +1 -5
- package/packages/omo-codex/plugin/components/lazycodex-executor-verify/hooks/hooks.json +1 -1
- package/packages/omo-codex/plugin/components/lazycodex-executor-verify/package.json +5 -5
- package/packages/omo-codex/plugin/components/lazycodex-executor-verify/src/codex-hook.ts +1 -5
- package/packages/omo-codex/plugin/components/lazycodex-executor-verify/test/codex-hook.test.ts +4 -21
- package/packages/omo-codex/plugin/components/lsp/AGENTS.md +30 -15
- package/packages/omo-codex/plugin/components/lsp/biome.json +2 -2
- package/packages/omo-codex/plugin/components/lsp/dist/.omo-runtime-manifest.json +4 -4
- package/packages/omo-codex/plugin/components/lsp/dist/cli.js +702 -278
- package/packages/omo-codex/plugin/components/lsp/dist/daemon-cli-path.js +1 -1
- package/packages/omo-codex/plugin/components/lsp/hooks/hooks.json +2 -2
- package/packages/omo-codex/plugin/components/lsp/package.json +5 -5
- package/packages/omo-codex/plugin/components/lsp/src/cli.ts +1 -1
- package/packages/omo-codex/plugin/components/lsp/src/codex-hook.ts +1 -1
- package/packages/omo-codex/plugin/components/lsp/src/daemon-cli-path.ts +1 -5
- package/packages/omo-codex/plugin/components/lsp/test/codex-hook-unavailable.test.ts +6 -7
- package/packages/omo-codex/plugin/components/lsp/test/codex-hook.test.ts +1 -2
- package/packages/omo-codex/plugin/components/lsp/test/package-smoke.test.ts +11 -1
- package/packages/omo-codex/plugin/components/rules/AGENTS.md +12 -0
- package/packages/omo-codex/plugin/components/rules/biome.json +2 -2
- package/packages/omo-codex/plugin/components/rules/dist/cli.js +60 -45
- package/packages/omo-codex/plugin/components/rules/hooks/hooks.json +4 -4
- package/packages/omo-codex/plugin/components/rules/package.json +7 -7
- package/packages/omo-codex/plugin/components/rules/src/config.ts +1 -2
- package/packages/omo-codex/plugin/components/rules/src/persistent-cache.ts +1 -2
- package/packages/omo-codex/plugin/components/rules/src/post-compact-budget.ts +9 -5
- package/packages/omo-codex/plugin/components/rules/src/rules-engine-factory.ts +1 -4
- package/packages/omo-codex/plugin/components/rules/src/static-injection.ts +4 -9
- package/packages/omo-codex/plugin/components/rules/test/bundled-rules-priority.test.ts +11 -16
- package/packages/omo-codex/plugin/components/rules/test/bundled-rules.test.ts +17 -25
- package/packages/omo-codex/plugin/components/rules/test/codex-hook-post-compact-budget.test.ts +9 -7
- package/packages/omo-codex/plugin/components/rules/test/codex-hook-post-compact-context.test.ts +0 -6
- package/packages/omo-codex/plugin/components/rules/test/codex-hook-post-compact-dedup.test.ts +6 -4
- package/packages/omo-codex/plugin/components/rules/test/codex-hook-post-compact-directive.test.ts +12 -9
- package/packages/omo-codex/plugin/components/rules/test/codex-hook.test.ts +28 -37
- package/packages/omo-codex/plugin/components/rules/test/dynamic-target-fingerprints.test.ts +1 -2
- package/packages/omo-codex/plugin/components/rules/test/engine.test.ts +7 -4
- package/packages/omo-codex/plugin/components/rules/test/finder.test.ts +2 -3
- package/packages/omo-codex/plugin/components/rules/test/formatter.test.ts +39 -72
- package/packages/omo-codex/plugin/components/rules/test/hephaestus-model-variant.test.ts +1 -2
- package/packages/omo-codex/plugin/components/rules/test/hook-output.test.ts +2 -3
- package/packages/omo-codex/plugin/components/rules/test/matcher.test.ts +2 -3
- package/packages/omo-codex/plugin/components/rules/test/package-smoke.test.ts +1 -1
- package/packages/omo-codex/plugin/components/rules/test/parser.test.ts +1 -2
- package/packages/omo-codex/plugin/components/rules/test/post-compact-budget.test.ts +5 -6
- package/packages/omo-codex/plugin/components/rules/test/rules-engine-consumption.test.ts +3 -6
- package/packages/omo-codex/plugin/components/rules/test/scanner.test.ts +1 -2
- package/packages/omo-codex/plugin/components/rules/test/sources.test.ts +2 -5
- package/packages/omo-codex/plugin/components/rules/test/windows-git-bash-bundled-rule.test.ts +2 -17
- package/packages/omo-codex/plugin/components/teammode/hooks/hooks.json +1 -1
- package/packages/omo-codex/plugin/components/teammode/package.json +5 -5
- package/packages/omo-codex/plugin/components/teammode/test/thread-title-hook.test.ts +3 -9
- package/packages/omo-codex/plugin/components/telemetry/AGENTS.md +8 -0
- package/packages/omo-codex/plugin/components/telemetry/biome.json +2 -2
- package/packages/omo-codex/plugin/components/telemetry/dist/cli.js +2463 -437
- package/packages/omo-codex/plugin/components/telemetry/dist/posthog.js +2467 -441
- package/packages/omo-codex/plugin/components/telemetry/hooks/hooks.json +1 -1
- package/packages/omo-codex/plugin/components/telemetry/package.json +5 -5
- package/packages/omo-codex/plugin/components/telemetry/src/codex-hook.ts +1 -4
- package/packages/omo-codex/plugin/components/telemetry/src/posthog.ts +4 -14
- package/packages/omo-codex/plugin/components/telemetry/src/product-identity.ts +1 -1
- package/packages/omo-codex/plugin/components/telemetry/test/diagnostics.test.ts +2 -5
- package/packages/omo-codex/plugin/components/ultrawork/AGENTS.md +5 -0
- package/packages/omo-codex/plugin/components/ultrawork/biome.json +2 -2
- package/packages/omo-codex/plugin/components/ultrawork/directive.md +13 -1
- package/packages/omo-codex/plugin/components/ultrawork/hooks/hooks.json +1 -1
- package/packages/omo-codex/plugin/components/ultrawork/package.json +5 -5
- package/packages/omo-codex/plugin/components/ultrawork/skills/ultrawork/SKILL.md +13 -1
- package/packages/omo-codex/plugin/components/ultrawork/skills/ulw-plan/SKILL.md +6 -6
- package/packages/omo-codex/plugin/components/ultrawork/skills/ulw-plan/references/full-workflow.md +31 -7
- package/packages/omo-codex/plugin/components/ultrawork/skills/ulw-plan/references/intent-clear.md +2 -1
- package/packages/omo-codex/plugin/components/ultrawork/skills/ulw-plan/references/intent-unclear.md +5 -5
- package/packages/omo-codex/plugin/components/ultrawork/test/codex-hook-trigger-policy.test.ts +9 -1
- package/packages/omo-codex/plugin/components/ultrawork/test/codex-hook.test.ts +0 -136
- package/packages/omo-codex/plugin/components/ultrawork/test/skill-pointer.test.ts +0 -2
- package/packages/omo-codex/plugin/components/{start-work-continuation → ulw-execute-continuation}/AGENTS.md +5 -4
- package/packages/omo-codex/plugin/components/{start-work-continuation → ulw-execute-continuation}/NOTICE +1 -1
- package/packages/omo-codex/plugin/components/{start-work-continuation → ulw-execute-continuation}/README.md +5 -5
- package/packages/omo-codex/plugin/components/{start-work-continuation → ulw-execute-continuation}/biome.json +2 -2
- package/packages/omo-codex/plugin/components/{start-work-continuation → ulw-execute-continuation}/directive.md +6 -6
- package/packages/omo-codex/plugin/components/{start-work-continuation → ulw-execute-continuation}/dist/cli.js +12 -12
- package/packages/omo-codex/plugin/components/ulw-execute-continuation/hooks/hooks.json +28 -0
- package/packages/omo-codex/plugin/components/{start-work-continuation → ulw-execute-continuation}/package.json +12 -12
- package/packages/omo-codex/plugin/components/{start-work-continuation → ulw-execute-continuation}/src/boulder-reader.ts +1 -1
- package/packages/omo-codex/plugin/components/{start-work-continuation → ulw-execute-continuation}/src/cli.ts +1 -1
- package/packages/omo-codex/plugin/components/{start-work-continuation → ulw-execute-continuation}/src/codex-hook.ts +3 -3
- package/packages/omo-codex/plugin/components/{start-work-continuation → ulw-execute-continuation}/src/directive.ts +1 -1
- package/packages/omo-codex/plugin/components/{start-work-continuation → ulw-execute-continuation}/src/index.ts +1 -1
- package/packages/omo-codex/plugin/components/{start-work-continuation → ulw-execute-continuation}/test/boulder-reader.test.ts +3 -3
- package/packages/omo-codex/plugin/components/{start-work-continuation → ulw-execute-continuation}/test/cli.test.ts +1 -4
- package/packages/omo-codex/plugin/components/{start-work-continuation → ulw-execute-continuation}/test/codex-hook.test.ts +8 -22
- package/packages/omo-codex/plugin/components/ulw-loop/AGENTS.md +17 -0
- package/packages/omo-codex/plugin/components/ulw-loop/CHANGELOG.md +1 -1
- package/packages/omo-codex/plugin/components/ulw-loop/biome.json +2 -2
- package/packages/omo-codex/plugin/components/ulw-loop/directive.md +13 -1
- package/packages/omo-codex/plugin/components/ulw-loop/dist/checkpoint.js +2 -0
- package/packages/omo-codex/plugin/components/ulw-loop/dist/cli-commands.js +5 -1
- package/packages/omo-codex/plugin/components/ulw-loop/dist/cli-output.d.ts +2 -1
- package/packages/omo-codex/plugin/components/ulw-loop/dist/cli-output.js +11 -1
- package/packages/omo-codex/plugin/components/ulw-loop/dist/cli.js +124 -68
- package/packages/omo-codex/plugin/components/ulw-loop/dist/codex-goal-instruction.d.ts +2 -0
- package/packages/omo-codex/plugin/components/ulw-loop/dist/codex-goal-instruction.js +9 -6
- package/packages/omo-codex/plugin/components/ulw-loop/dist/codex-goal-snapshot.js +1 -1
- package/packages/omo-codex/plugin/components/ulw-loop/dist/paths.js +1 -1
- package/packages/omo-codex/plugin/components/ulw-loop/dist/quality-gate.d.ts +4 -2
- package/packages/omo-codex/plugin/components/ulw-loop/dist/quality-gate.js +7 -10
- package/packages/omo-codex/plugin/components/ulw-loop/dist/spawn-guard.js +3 -2
- package/packages/omo-codex/plugin/components/ulw-loop/dist/stop-resume-hook.js +3 -3
- package/packages/omo-codex/plugin/components/ulw-loop/dist/surface.d.ts +15 -0
- package/packages/omo-codex/plugin/components/ulw-loop/dist/surface.js +50 -0
- package/packages/omo-codex/plugin/components/ulw-loop/hooks/hooks.json +4 -4
- package/packages/omo-codex/plugin/components/ulw-loop/package.json +5 -5
- package/packages/omo-codex/plugin/components/ulw-loop/skills/ulw-loop/SKILL.md +3 -2
- package/packages/omo-codex/plugin/components/ulw-loop/skills/ulw-loop/references/define-goal.md +108 -0
- package/packages/omo-codex/plugin/components/ulw-loop/skills/ulw-loop/references/full-workflow.md +1 -0
- package/packages/omo-codex/plugin/components/ulw-loop/src/checkpoint.ts +2 -0
- package/packages/omo-codex/plugin/components/ulw-loop/src/cli-commands.ts +5 -1
- package/packages/omo-codex/plugin/components/ulw-loop/src/cli-output.ts +13 -1
- package/packages/omo-codex/plugin/components/ulw-loop/src/cli.ts +3 -5
- package/packages/omo-codex/plugin/components/ulw-loop/src/codex-goal-instruction.ts +16 -5
- package/packages/omo-codex/plugin/components/ulw-loop/src/codex-goal-snapshot.ts +3 -1
- package/packages/omo-codex/plugin/components/ulw-loop/src/codex-hook.ts +3 -1
- package/packages/omo-codex/plugin/components/ulw-loop/src/paths.ts +1 -1
- package/packages/omo-codex/plugin/components/ulw-loop/src/quality-gate.ts +11 -14
- package/packages/omo-codex/plugin/components/ulw-loop/src/spawn-guard.ts +3 -2
- package/packages/omo-codex/plugin/components/ulw-loop/src/stop-resume-hook.ts +3 -3
- package/packages/omo-codex/plugin/components/ulw-loop/src/surface.ts +73 -0
- package/packages/omo-codex/plugin/components/ulw-loop/test/checkpoint-continuation.test.ts +0 -1
- package/packages/omo-codex/plugin/components/ulw-loop/test/checkpoint-final.test.ts +44 -1
- package/packages/omo-codex/plugin/components/ulw-loop/test/cli-create-goals.test.ts +25 -0
- package/packages/omo-codex/plugin/components/ulw-loop/test/cli-entrypoint.test.ts +26 -2
- package/packages/omo-codex/plugin/components/ulw-loop/test/codex-goal-instruction.test.ts +27 -2
- package/packages/omo-codex/plugin/components/ulw-loop/test/codex-goal-snapshot.test.ts +18 -0
- package/packages/omo-codex/plugin/components/ulw-loop/test/codex-hook.test.ts +0 -3
- package/packages/omo-codex/plugin/components/ulw-loop/test/fixtures/quality-gate-builder.ts +7 -3
- package/packages/omo-codex/plugin/components/ulw-loop/test/package-smoke.test.ts +5 -37
- package/packages/omo-codex/plugin/components/ulw-loop/test/paths.test.ts +9 -0
- package/packages/omo-codex/plugin/components/ulw-loop/test/quality-gate-roles.test.ts +45 -2
- package/packages/omo-codex/plugin/components/ulw-loop/test/spawn-guard.test.ts +20 -0
- package/packages/omo-codex/plugin/components/ulw-loop/test/steering.test.ts +8 -5
- package/packages/omo-codex/plugin/components/ulw-loop/test/stop-resume-hook.test.ts +1 -1
- package/packages/omo-codex/plugin/components/ulw-loop/test/surface.test.ts +74 -0
- package/packages/omo-codex/plugin/components/ulw-loop/test/ultrawork-directive.test.ts +4 -5
- package/packages/omo-codex/plugin/components/ulw-loop/vitest.config.ts +1 -0
- package/packages/omo-codex/plugin/hooks/post-compact-resetting-git-bash-mcp-reminder.json +1 -1
- package/packages/omo-codex/plugin/hooks/post-compact-resetting-lsp-diagnostics-cache.json +1 -1
- package/packages/omo-codex/plugin/hooks/post-compact-resetting-project-rule-cache.json +1 -1
- package/packages/omo-codex/plugin/hooks/post-tool-use-checking-codegraph-init-guidance.json +1 -1
- package/packages/omo-codex/plugin/hooks/post-tool-use-checking-comments.json +1 -1
- package/packages/omo-codex/plugin/hooks/post-tool-use-checking-lsp-diagnostics.json +1 -1
- package/packages/omo-codex/plugin/hooks/post-tool-use-checking-thread-title-hygiene.json +1 -1
- package/packages/omo-codex/plugin/hooks/post-tool-use-matching-project-rules.json +1 -1
- package/packages/omo-codex/plugin/hooks/pre-tool-use-enforcing-unlimited-goal-budget.json +1 -1
- package/packages/omo-codex/plugin/hooks/pre-tool-use-guarding-ulw-loop-spawns.json +1 -1
- package/packages/omo-codex/plugin/hooks/pre-tool-use-recommending-git-bash-mcp.json +1 -1
- package/packages/omo-codex/plugin/hooks/session-start-checking-auto-update.json +1 -1
- package/packages/omo-codex/plugin/hooks/session-start-checking-bootstrap-provisioning.json +1 -1
- package/packages/omo-codex/plugin/hooks/session-start-checking-codegraph-bootstrap.json +1 -1
- package/packages/omo-codex/plugin/hooks/session-start-loading-project-rules.json +1 -1
- package/packages/omo-codex/plugin/hooks/session-start-recording-session-telemetry.json +1 -1
- package/packages/omo-codex/plugin/hooks/stop-checking-ulw-execute-continuation.json +17 -0
- package/packages/omo-codex/plugin/hooks/stop-checking-ulw-loop-resume.json +1 -1
- package/packages/omo-codex/plugin/hooks/subagent-stop-checking-ulw-execute-continuation.json +17 -0
- package/packages/omo-codex/plugin/hooks/subagent-stop-verifying-lazycodex-executor-evidence.json +1 -1
- package/packages/omo-codex/plugin/hooks/user-prompt-submit-checking-ultrawork-trigger.json +1 -1
- package/packages/omo-codex/plugin/hooks/user-prompt-submit-checking-ulw-loop-steering.json +1 -1
- package/packages/omo-codex/plugin/hooks/user-prompt-submit-loading-project-rules.json +1 -1
- package/packages/omo-codex/plugin/model-catalog.json +3 -3
- package/packages/omo-codex/plugin/package-lock.json +681 -395
- package/packages/omo-codex/plugin/package.json +2 -2
- package/packages/omo-codex/plugin/scripts/AGENTS.md +40 -0
- package/packages/omo-codex/plugin/scripts/auto-update-plan.mjs +1 -1
- package/packages/omo-codex/plugin/scripts/migrate-codex-config/catalog.mjs +3 -3
- package/packages/omo-codex/plugin/scripts/sync-skills.mjs +11 -11
- package/packages/omo-codex/plugin/shared/package.json +3 -4
- package/packages/omo-codex/plugin/skills/ast-grep/AGENTS.md +51 -0
- package/packages/omo-codex/plugin/skills/coding-agent-sessions/AGENTS.md +62 -0
- package/packages/omo-codex/plugin/skills/coding-agent-sessions/SKILL.md +3 -2
- package/packages/omo-codex/plugin/skills/coding-agent-sessions/references/all-platforms.md +1 -1
- package/packages/omo-codex/plugin/skills/coding-agent-sessions/references/senpi.md +4 -4
- package/packages/omo-codex/plugin/skills/coding-agent-sessions/scripts/agent_sessions/pi_family.py +1 -1
- package/packages/omo-codex/plugin/skills/data-scientist/SKILL.md +99 -239
- package/packages/omo-codex/plugin/skills/data-scientist/references/execution-surfaces.md +91 -0
- package/packages/omo-codex/plugin/skills/data-scientist/references/placement.md +74 -0
- package/packages/omo-codex/plugin/skills/data-scientist/references/polars-lane.md +95 -0
- package/packages/omo-codex/plugin/skills/data-scientist/references/uv-setup.md +1 -1
- package/packages/omo-codex/plugin/skills/data-scientist/references/visualization.md +64 -0
- package/packages/omo-codex/plugin/skills/data-scientist/scripts/ensure-js-deps.sh +28 -0
- package/packages/omo-codex/plugin/skills/data-scientist/scripts/ensure-py-deps.sh +37 -0
- package/packages/omo-codex/plugin/skills/debugging/SKILL.md +2 -0
- package/packages/omo-codex/plugin/skills/debugging/references/methodology/00-setup.md +12 -0
- package/packages/omo-codex/plugin/skills/debugging/references/methodology/02-investigate.md +21 -0
- package/packages/omo-codex/plugin/skills/debugging/references/runtimes/go.md +15 -1
- package/packages/omo-codex/plugin/skills/debugging/references/runtimes/native-binary.md +38 -0
- package/packages/omo-codex/plugin/skills/debugging/references/runtimes/node.md +25 -0
- package/packages/omo-codex/plugin/skills/debugging/references/runtimes/python.md +13 -0
- package/packages/omo-codex/plugin/skills/debugging/references/runtimes/rust.md +41 -0
- package/packages/omo-codex/plugin/skills/debugging/references/scripts/dap.mjs +267 -0
- package/packages/omo-codex/plugin/skills/debugging/references/scripts/fixture-adapter.mjs +59 -0
- package/packages/omo-codex/plugin/skills/debugging/references/tools/dap.md +103 -0
- package/packages/omo-codex/plugin/skills/debugging/references/tools/frida.md +193 -0
- package/packages/omo-codex/plugin/skills/frontend/SKILL.md +11 -7
- package/packages/omo-codex/plugin/skills/frontend/references/design/_INDEX.md +1 -0
- package/packages/omo-codex/plugin/skills/frontend/references/design/print-paged-media.md +76 -0
- package/packages/omo-codex/plugin/skills/frontend/references/design/stylegallery.md +80 -0
- package/packages/omo-codex/plugin/skills/frontend/references/designpowers/README.md +1 -1
- package/packages/omo-codex/plugin/skills/frontend/references/designpowers/lane-a-direction.md +1 -1
- package/packages/omo-codex/plugin/skills/frontend/references/designpowers/lane-b-execution.md +11 -11
- package/packages/omo-codex/plugin/skills/frontend/references/designpowers/lane-d-memory.md +3 -3
- package/packages/omo-codex/plugin/skills/frontend/references/designpowers/orchestration.md +1 -1
- package/packages/omo-codex/plugin/skills/frontend/references/designpowers/routing.md +5 -5
- package/packages/omo-codex/plugin/skills/review-work/SKILL.md +4 -4
- package/packages/omo-codex/plugin/skills/ultimate-browsing/ATTRIBUTION.md +37 -10
- package/packages/omo-codex/plugin/skills/ultimate-browsing/SKILL.md +2 -0
- package/packages/omo-codex/plugin/skills/ultimate-browsing/engine/AGENTS.md +179 -0
- package/packages/omo-codex/plugin/skills/ultimate-browsing/engine/templates/package.json +1 -1
- package/packages/omo-codex/plugin/skills/ultimate-browsing/references/chrome-stealth.md +13 -11
- package/packages/omo-codex/plugin/skills/ultrawork/SKILL.md +13 -1
- package/packages/omo-codex/plugin/skills/{start-work → ulw-execute}/SKILL.md +12 -11
- package/packages/omo-codex/plugin/skills/ulw-execute/agents/openai.yaml +2 -0
- package/packages/omo-codex/plugin/skills/ulw-loop/SKILL.md +3 -2
- package/packages/omo-codex/plugin/skills/ulw-loop/references/define-goal.md +108 -0
- package/packages/omo-codex/plugin/skills/ulw-loop/references/full-workflow.md +1 -0
- package/packages/omo-codex/plugin/skills/ulw-plan/SKILL.md +6 -6
- package/packages/omo-codex/plugin/skills/ulw-plan/references/full-workflow.md +31 -7
- package/packages/omo-codex/plugin/skills/ulw-plan/references/intent-clear.md +2 -1
- package/packages/omo-codex/plugin/skills/ulw-plan/references/intent-unclear.md +5 -5
- package/packages/omo-codex/plugin/skills/ulw-research/SKILL.md +4 -2
- package/packages/omo-codex/plugin/skills/visual-qa/AGENTS.md +58 -0
- package/packages/omo-codex/plugin/skills/visual-qa/SKILL.md +3 -2
- package/packages/omo-codex/plugin/test/AGENTS.md +47 -0
- package/packages/omo-codex/plugin/test/aggregate-agents.test.mjs +19 -173
- package/packages/omo-codex/plugin/test/aggregate-hooks.test.mjs +8 -28
- package/packages/omo-codex/plugin/test/aggregate-manifest.test.mjs +1 -1
- package/packages/omo-codex/plugin/test/aggregate-model-catalog.test.mjs +1 -1
- package/packages/omo-codex/plugin/test/aggregate-plugin-fixture.mjs +175 -13
- package/packages/omo-codex/plugin/test/aggregate.test.mjs +78 -2
- package/packages/omo-codex/plugin/test/auto-update-release-notes.test.mjs +19 -33
- package/packages/omo-codex/plugin/test/auto-update.test.mjs +2 -2
- package/packages/omo-codex/plugin/test/component-bin-names.test.mjs +2 -2
- package/packages/omo-codex/plugin/test/component-bundled-cli.test.mjs +1 -1
- package/packages/omo-codex/plugin/test/component-hook-contract-cases.mjs +2 -2
- package/packages/omo-codex/plugin/test/hook-status-message.test.mjs +4 -4
- package/packages/omo-codex/plugin/test/lcx-contribute-bug-fix-template.test.mjs +21 -27
- package/packages/omo-codex/plugin/test/migrate-codex-config.test.mjs +8 -8
- package/packages/omo-codex/plugin/test/scaffold-plan.test.mjs +0 -36
- package/packages/omo-codex/plugin/test/sync-skills-codex-compatibility.test.mjs +101 -0
- package/packages/omo-codex/plugin/test/sync-skills-test-support.mjs +12 -12
- package/packages/omo-codex/plugin/test/sync-skills.test.mjs +1 -119
- package/packages/omo-codex/plugin/test/teammode-archive-ambiguity.test.mjs +0 -40
- package/packages/omo-codex/plugin/test/teammode-communication.test.mjs +6 -62
- package/packages/omo-codex/plugin/test/teammode-thread-links.test.mjs +3 -36
- package/packages/omo-codex/plugin/test/teammode-transport.test.mjs +0 -44
- package/packages/omo-codex/plugin/test/teammode-worktree.test.mjs +2 -6
- package/packages/omo-codex/plugin/test/ultrawork-skill-pointer.test.mjs +0 -3
- package/packages/omo-codex/plugin/test/ulw-plan-review-state-contract.test.mjs +0 -3
- package/packages/omo-codex/scripts/AGENTS.md +36 -0
- package/packages/omo-codex/scripts/install-config-reasoning.test.mjs +2 -2
- package/packages/omo-codex/scripts/install-dist/install-local.mjs +2637 -549
- package/packages/omo-codex/scripts/install-lazycodex-version-stamp.test.mjs +7 -2
- package/packages/shared-skills/skills/ast-grep/AGENTS.md +51 -0
- package/packages/shared-skills/skills/coding-agent-sessions/AGENTS.md +62 -0
- package/packages/shared-skills/skills/coding-agent-sessions/SKILL.md +3 -2
- package/packages/shared-skills/skills/coding-agent-sessions/references/all-platforms.md +1 -1
- package/packages/shared-skills/skills/coding-agent-sessions/references/senpi.md +4 -4
- package/packages/shared-skills/skills/coding-agent-sessions/scripts/agent_sessions/pi_family.py +1 -1
- package/packages/shared-skills/skills/data-scientist/SKILL.md +99 -239
- package/packages/shared-skills/skills/data-scientist/references/execution-surfaces.md +91 -0
- package/packages/shared-skills/skills/data-scientist/references/placement.md +74 -0
- package/packages/shared-skills/skills/data-scientist/references/polars-lane.md +95 -0
- package/packages/shared-skills/skills/data-scientist/references/uv-setup.md +1 -1
- package/packages/shared-skills/skills/data-scientist/references/visualization.md +64 -0
- package/packages/shared-skills/skills/data-scientist/scripts/ensure-js-deps.sh +28 -0
- package/packages/shared-skills/skills/data-scientist/scripts/ensure-py-deps.sh +37 -0
- package/packages/shared-skills/skills/debugging/SKILL.md +2 -0
- package/packages/shared-skills/skills/debugging/references/methodology/00-setup.md +12 -0
- package/packages/shared-skills/skills/debugging/references/methodology/02-investigate.md +21 -0
- package/packages/shared-skills/skills/debugging/references/runtimes/go.md +15 -1
- package/packages/shared-skills/skills/debugging/references/runtimes/native-binary.md +38 -0
- package/packages/shared-skills/skills/debugging/references/runtimes/node.md +25 -0
- package/packages/shared-skills/skills/debugging/references/runtimes/python.md +13 -0
- package/packages/shared-skills/skills/debugging/references/runtimes/rust.md +41 -0
- package/packages/shared-skills/skills/debugging/references/scripts/dap.mjs +267 -0
- package/packages/shared-skills/skills/debugging/references/scripts/dap.test.ts +86 -0
- package/packages/shared-skills/skills/debugging/references/scripts/fixture-adapter.mjs +59 -0
- package/packages/shared-skills/skills/debugging/references/tools/dap.md +103 -0
- package/packages/shared-skills/skills/debugging/references/tools/frida.md +193 -0
- package/packages/shared-skills/skills/frontend/SKILL.md +11 -7
- package/packages/shared-skills/skills/frontend/references/design/_INDEX.md +1 -0
- package/packages/shared-skills/skills/frontend/references/design/print-paged-media.md +76 -0
- package/packages/shared-skills/skills/frontend/references/design/stylegallery.md +80 -0
- package/packages/shared-skills/skills/frontend/references/designpowers/README.md +1 -1
- package/packages/shared-skills/skills/frontend/references/designpowers/lane-a-direction.md +1 -1
- package/packages/shared-skills/skills/frontend/references/designpowers/lane-b-execution.md +11 -11
- package/packages/shared-skills/skills/frontend/references/designpowers/lane-d-memory.md +3 -3
- package/packages/shared-skills/skills/frontend/references/designpowers/orchestration.md +1 -1
- package/packages/shared-skills/skills/frontend/references/designpowers/routing.md +5 -5
- package/packages/shared-skills/skills/review-work/SKILL.md +3 -3
- package/packages/shared-skills/skills/ultimate-browsing/ATTRIBUTION.md +37 -10
- package/packages/shared-skills/skills/ultimate-browsing/SKILL.md +2 -0
- package/packages/shared-skills/skills/ultimate-browsing/engine/AGENTS.md +179 -0
- package/packages/shared-skills/skills/ultimate-browsing/engine/templates/package.json +1 -1
- package/packages/shared-skills/skills/ultimate-browsing/references/chrome-stealth.md +13 -11
- package/packages/shared-skills/skills/{start-work → ulw-execute}/SKILL.md +9 -8
- package/packages/shared-skills/skills/ulw-plan/SKILL.md +6 -6
- package/packages/shared-skills/skills/ulw-plan/references/full-workflow.md +31 -7
- package/packages/shared-skills/skills/ulw-plan/references/intent-clear.md +2 -1
- package/packages/shared-skills/skills/ulw-plan/references/intent-unclear.md +5 -5
- package/packages/shared-skills/skills/ulw-research/SKILL.md +4 -2
- package/packages/shared-skills/skills/visual-qa/AGENTS.md +58 -0
- package/packages/shared-skills/skills/visual-qa/SKILL.md +3 -2
- package/script/qa/web-terminal-visual-qa.mjs +2 -0
- package/script/qa/xterm-live-terminal.mjs +18 -2
- package/dist/config/schema/start-work.d.ts +0 -5
- package/dist/features/builtin-commands/templates/start-work.d.ts +0 -1
- package/dist/hooks/ralph-loop/completion-promise-detector-test-input.d.ts +0 -11
- package/dist/hooks/ralph-loop/loop-session-recovery.d.ts +0 -7
- package/dist/hooks/start-work/start-work-hook.d.ts +0 -23
- package/dist/plugin/chat-message/start-work-message.d.ts +0 -5
- package/dist/skills/data-scientist/references/common-scenarios.md +0 -176
- package/dist/skills/data-scientist/references/execution-templates.md +0 -197
- package/dist/skills/data-scientist/references/integration-patterns.md +0 -153
- package/dist/skills/data-scientist/references/performance-benchmarks.md +0 -37
- package/dist/tools/call-omo-agent/background-agent-executor.d.ts +0 -5
- package/dist/tools/call-omo-agent/message-storage-directory.d.ts +0 -1
- package/dist/tools/delegate-task/model-string-parser.d.ts +0 -1
- package/packages/lsp-tools-mcp/dist/lsp/cleanup-errors.d.ts +0 -1
- package/packages/lsp-tools-mcp/dist/lsp/constants.d.ts +0 -1
- package/packages/lsp-tools-mcp/dist/lsp/language-mappings.d.ts +0 -1
- package/packages/lsp-tools-mcp/dist/lsp/process-signal-cleanup.d.ts +0 -1
- package/packages/lsp-tools-mcp/dist/missing-dependency-result.d.ts +0 -1
- package/packages/omo-codex/plugin/components/start-work-continuation/hooks/hooks.json +0 -28
- package/packages/omo-codex/plugin/hooks/stop-checking-start-work-continuation.json +0 -17
- package/packages/omo-codex/plugin/hooks/subagent-stop-checking-start-work-continuation.json +0 -17
- package/packages/omo-codex/plugin/skills/data-scientist/references/common-scenarios.md +0 -176
- package/packages/omo-codex/plugin/skills/data-scientist/references/execution-templates.md +0 -197
- package/packages/omo-codex/plugin/skills/data-scientist/references/integration-patterns.md +0 -153
- package/packages/omo-codex/plugin/skills/data-scientist/references/performance-benchmarks.md +0 -37
- package/packages/omo-codex/plugin/skills/start-work/agents/openai.yaml +0 -2
- package/packages/omo-codex/plugin/test/aggregate-skills.test.mjs +0 -92
- package/packages/omo-codex/plugin/test/sync-skills-orchestration.test.mjs +0 -314
- package/packages/omo-codex/plugin/test/ulw-plan-scope-contract.test.mjs +0 -24
- package/packages/shared-skills/skills/data-scientist/references/common-scenarios.md +0 -176
- package/packages/shared-skills/skills/data-scientist/references/execution-templates.md +0 -197
- package/packages/shared-skills/skills/data-scientist/references/integration-patterns.md +0 -153
- package/packages/shared-skills/skills/data-scientist/references/performance-benchmarks.md +0 -37
- /package/dist/hooks/{start-work → ulw-execute}/context-info-formatters.d.ts +0 -0
- /package/dist/hooks/{start-work → ulw-execute}/explicit-plan-context.d.ts +0 -0
- /package/dist/hooks/{start-work → ulw-execute}/notepad-scaffold.d.ts +0 -0
- /package/dist/hooks/{start-work → ulw-execute}/parse-user-request.d.ts +0 -0
- /package/dist/hooks/{start-work → ulw-execute}/plan-discovery-context.d.ts +0 -0
- /package/dist/hooks/{start-work → ulw-execute}/plan-selection.d.ts +0 -0
- /package/dist/hooks/{start-work → ulw-execute}/session-plan-affinity.d.ts +0 -0
- /package/dist/hooks/{start-work → ulw-execute}/work-initializer.d.ts +0 -0
- /package/dist/hooks/{start-work → ulw-execute}/worktree-block.d.ts +0 -0
- /package/dist/hooks/{start-work → ulw-execute}/worktree-detector.d.ts +0 -0
- /package/packages/omo-codex/plugin/components/{start-work-continuation → ulw-execute-continuation}/.gitattributes +0 -0
- /package/packages/omo-codex/plugin/components/{start-work-continuation → ulw-execute-continuation}/CHANGELOG.md +0 -0
- /package/packages/omo-codex/plugin/components/{start-work-continuation → ulw-execute-continuation}/LICENSE +0 -0
- /package/packages/omo-codex/plugin/components/{start-work-continuation → ulw-execute-continuation}/src/plan-checklist.ts +0 -0
- /package/packages/omo-codex/plugin/components/{start-work-continuation → ulw-execute-continuation}/src/types.ts +0 -0
- /package/packages/omo-codex/plugin/components/{start-work-continuation → ulw-execute-continuation}/test/fixtures/boulder-completed.json +0 -0
- /package/packages/omo-codex/plugin/components/{start-work-continuation → ulw-execute-continuation}/test/fixtures/boulder-mixed-platforms.json +0 -0
- /package/packages/omo-codex/plugin/components/{start-work-continuation → ulw-execute-continuation}/test/fixtures/boulder-single-codex-work.json +0 -0
- /package/packages/omo-codex/plugin/components/{start-work-continuation → ulw-execute-continuation}/test/fixtures/plan-all-done.md +0 -0
- /package/packages/omo-codex/plugin/components/{start-work-continuation → ulw-execute-continuation}/test/fixtures/plan-scaffold.md +0 -0
- /package/packages/omo-codex/plugin/components/{start-work-continuation → ulw-execute-continuation}/test/fixtures/plan-with-nested-checkboxes.md +0 -0
- /package/packages/omo-codex/plugin/components/{start-work-continuation → ulw-execute-continuation}/test/fixtures/plan-with-unchecked.md +0 -0
- /package/packages/omo-codex/plugin/components/{start-work-continuation → ulw-execute-continuation}/tsconfig.build.json +0 -0
- /package/packages/omo-codex/plugin/components/{start-work-continuation → ulw-execute-continuation}/tsconfig.json +0 -0
- /package/packages/omo-codex/plugin/components/{start-work-continuation → ulw-execute-continuation}/vitest.config.ts +0 -0
|
@@ -1,5 +1,5 @@
|
|
|
1
|
-
import { existsSync, statSync } from "node:fs";
|
|
2
|
-
import { dirname, join, resolve } from "node:path";
|
|
1
|
+
import { existsSync, realpathSync, statSync } from "node:fs";
|
|
2
|
+
import { basename, dirname, join, resolve } from "node:path";
|
|
3
3
|
import {
|
|
4
4
|
canonicalizeExistingOrNearestAncestor,
|
|
5
5
|
contextCwd,
|
|
@@ -16,11 +16,12 @@ import {
|
|
|
16
16
|
LspServerLookupError,
|
|
17
17
|
} from "./errors.js";
|
|
18
18
|
import { getLspManager, type LspManager } from "./manager.js";
|
|
19
|
+
import { findWorkspaceRootOutsideContext } from "./outside-context-workspace.js";
|
|
20
|
+
import { LSP_LOCAL_INSTALL_HINTS } from "./server-definitions.js";
|
|
19
21
|
import { loadInstallDecision } from "./server-install-state.js";
|
|
20
22
|
import { findServerForExtension } from "./server-resolution.js";
|
|
21
23
|
import type { ServerLookupResult } from "./types.js";
|
|
22
|
-
|
|
23
|
-
const WORKSPACE_MARKERS = [".git", "package.json", "pyproject.toml", "Cargo.toml", "go.mod", "pom.xml", "build.gradle"];
|
|
24
|
+
import { GIT_WORKSPACE_MARKER, PROJECT_WORKSPACE_MARKERS } from "./workspace-markers.js";
|
|
24
25
|
|
|
25
26
|
export function isDirectoryPath(filePath: string): boolean {
|
|
26
27
|
try {
|
|
@@ -30,31 +31,63 @@ export function isDirectoryPath(filePath: string): boolean {
|
|
|
30
31
|
}
|
|
31
32
|
}
|
|
32
33
|
|
|
34
|
+
/**
|
|
35
|
+
* Resolves the workspace root for a file inside the request cwd.
|
|
36
|
+
*
|
|
37
|
+
* A `.git`-containing ancestor always wins over nearer package markers, so all packages of a
|
|
38
|
+
* monorepo share one workspace root (one resident client per repository instead of one per
|
|
39
|
+
* package, which multiplies language-server processes by the package count). The nearest
|
|
40
|
+
* package-marked directory is remembered while walking and used only when no `.git` ancestor
|
|
41
|
+
* exists within the request cwd.
|
|
42
|
+
*/
|
|
33
43
|
export function findWorkspaceRoot(filePath: string): string {
|
|
34
|
-
const
|
|
44
|
+
const cwd = contextCwd();
|
|
45
|
+
const abs = resolveReadablePathInsideContext(filePath);
|
|
35
46
|
let dir = abs;
|
|
36
47
|
|
|
37
48
|
if (!isDirectoryPath(dir)) {
|
|
38
49
|
dir = dirname(dir);
|
|
39
50
|
}
|
|
40
51
|
|
|
41
|
-
|
|
42
|
-
|
|
43
|
-
|
|
44
|
-
|
|
45
|
-
|
|
52
|
+
if (!isPathInside(cwd, abs)) return findWorkspaceRootOutsideContext(dir);
|
|
53
|
+
|
|
54
|
+
const fallbackRoot = nearestExistingDirectoryInsideContext(dir, cwd) ?? cwd;
|
|
55
|
+
let nearestPackageRoot: string | undefined;
|
|
56
|
+
while (isPathInside(cwd, dir)) {
|
|
57
|
+
const canonicalDir = existingDirectoryInsideContext(dir, cwd);
|
|
58
|
+
if (canonicalDir !== undefined) {
|
|
59
|
+
if (existsSync(join(dir, GIT_WORKSPACE_MARKER))) {
|
|
60
|
+
return canonicalDir;
|
|
61
|
+
}
|
|
62
|
+
if (nearestPackageRoot === undefined && hasProjectWorkspaceMarker(dir)) {
|
|
63
|
+
nearestPackageRoot = canonicalDir;
|
|
46
64
|
}
|
|
47
65
|
}
|
|
48
|
-
|
|
66
|
+
if (dir === cwd) break;
|
|
49
67
|
dir = dirname(dir);
|
|
50
68
|
}
|
|
51
69
|
|
|
52
|
-
return
|
|
70
|
+
return nearestPackageRoot ?? fallbackRoot;
|
|
53
71
|
}
|
|
54
72
|
|
|
55
|
-
|
|
73
|
+
function hasProjectWorkspaceMarker(directory: string): boolean {
|
|
74
|
+
return PROJECT_WORKSPACE_MARKERS.some((marker) => existsSync(join(directory, marker)));
|
|
75
|
+
}
|
|
76
|
+
|
|
77
|
+
export function resolveReadablePathInsideContext(filePath: string): string {
|
|
56
78
|
const cwd = contextCwd();
|
|
57
79
|
const abs = resolve(cwd, filePath);
|
|
80
|
+
if (isPathInside(cwd, abs)) return abs;
|
|
81
|
+
|
|
82
|
+
const rebased = rebaseThroughCanonicalAncestor(abs, cwd);
|
|
83
|
+
if (rebased !== undefined) return rebased;
|
|
84
|
+
|
|
85
|
+
return canonicalizeExistingOrNearestAncestor(abs);
|
|
86
|
+
}
|
|
87
|
+
|
|
88
|
+
export function resolvePathInsideContext(filePath: string): string {
|
|
89
|
+
const cwd = contextCwd();
|
|
90
|
+
const abs = resolveReadablePathInsideContext(filePath);
|
|
58
91
|
const canonical = canonicalizeExistingOrNearestAncestor(abs);
|
|
59
92
|
if (!isPathInside(cwd, canonical)) {
|
|
60
93
|
throw new LspInvalidPathError(`LSP file path must be inside request cwd: ${filePath}`);
|
|
@@ -62,6 +95,39 @@ export function resolvePathInsideContext(filePath: string): string {
|
|
|
62
95
|
return canonical;
|
|
63
96
|
}
|
|
64
97
|
|
|
98
|
+
function rebaseThroughCanonicalAncestor(path: string, cwd: string): string | undefined {
|
|
99
|
+
let current = path;
|
|
100
|
+
const suffix: string[] = [];
|
|
101
|
+
while (true) {
|
|
102
|
+
if (existsSync(current)) {
|
|
103
|
+
const canonical = realpathSync(current);
|
|
104
|
+
if (isPathInside(cwd, canonical)) return suffix.length === 0 ? canonical : join(canonical, ...suffix);
|
|
105
|
+
}
|
|
106
|
+
const parent = dirname(current);
|
|
107
|
+
if (parent === current) return undefined;
|
|
108
|
+
suffix.unshift(basename(current));
|
|
109
|
+
current = parent;
|
|
110
|
+
}
|
|
111
|
+
}
|
|
112
|
+
|
|
113
|
+
function existingDirectoryInsideContext(directory: string, cwd: string): string | undefined {
|
|
114
|
+
if (!existsSync(directory)) return undefined;
|
|
115
|
+
const canonical = realpathSync(directory);
|
|
116
|
+
if (!statSync(canonical).isDirectory()) return undefined;
|
|
117
|
+
return isPathInside(cwd, canonical) ? canonical : undefined;
|
|
118
|
+
}
|
|
119
|
+
|
|
120
|
+
function nearestExistingDirectoryInsideContext(directory: string, cwd: string): string | undefined {
|
|
121
|
+
let current = directory;
|
|
122
|
+
while (isPathInside(cwd, current)) {
|
|
123
|
+
const canonical = existingDirectoryInsideContext(current, cwd);
|
|
124
|
+
if (canonical !== undefined) return canonical;
|
|
125
|
+
if (current === cwd) return undefined;
|
|
126
|
+
current = dirname(current);
|
|
127
|
+
}
|
|
128
|
+
return undefined;
|
|
129
|
+
}
|
|
130
|
+
|
|
65
131
|
export function formatServerLookupError(result: Exclude<ServerLookupResult, { status: "found" }>): string {
|
|
66
132
|
if (result.status === "not_installed") {
|
|
67
133
|
return formatNotInstalled(result);
|
|
@@ -88,6 +154,26 @@ export function formatServerLookupError(result: Exclude<ServerLookupResult, { st
|
|
|
88
154
|
].join("\n");
|
|
89
155
|
}
|
|
90
156
|
|
|
157
|
+
/**
|
|
158
|
+
* Builds the install guidance, offering the repo-local install first.
|
|
159
|
+
*
|
|
160
|
+
* A repo-local install is resolvable without touching the global environment, so it is the
|
|
161
|
+
* recommended route whenever the server ships as a project dependency.
|
|
162
|
+
*/
|
|
163
|
+
function formatInstallOptions(serverId: string, installHint: string): string[] {
|
|
164
|
+
const localHint = LSP_LOCAL_INSTALL_HINTS[serverId];
|
|
165
|
+
if (localHint === undefined) {
|
|
166
|
+
return ["To install, run:", ` ${installHint}`];
|
|
167
|
+
}
|
|
168
|
+
return [
|
|
169
|
+
"To install in THIS repository (preferred — no global install needed):",
|
|
170
|
+
` ${localHint}`,
|
|
171
|
+
"",
|
|
172
|
+
"Or install it globally:",
|
|
173
|
+
` ${installHint}`,
|
|
174
|
+
];
|
|
175
|
+
}
|
|
176
|
+
|
|
91
177
|
function formatNotInstalled(result: Extract<ServerLookupResult, { status: "not_installed" }>): string {
|
|
92
178
|
const { server, installHint } = result;
|
|
93
179
|
const extensions = server.extensions.join(", ");
|
|
@@ -104,20 +190,20 @@ function formatNotInstalled(result: Extract<ServerLookupResult, { status: "not_i
|
|
|
104
190
|
`Command not found: ${server.command[0]}`,
|
|
105
191
|
"",
|
|
106
192
|
];
|
|
193
|
+
const installOptions = formatInstallOptions(server.id, installHint);
|
|
107
194
|
|
|
108
195
|
if (decision === "allowed") {
|
|
109
196
|
return [
|
|
110
197
|
...header,
|
|
111
198
|
"The user has pre-authorized LSP installation. Run the install command, then retry this tool:",
|
|
112
|
-
|
|
199
|
+
...installOptions.slice(1),
|
|
113
200
|
].join("\n");
|
|
114
201
|
}
|
|
115
202
|
|
|
116
203
|
if (!context.capabilities.installDecisionTool) {
|
|
117
204
|
return [
|
|
118
205
|
...header,
|
|
119
|
-
|
|
120
|
-
` ${installHint}`,
|
|
206
|
+
...installOptions,
|
|
121
207
|
"",
|
|
122
208
|
"ACTION REQUIRED — ASK THE USER whether to install this LSP server.",
|
|
123
209
|
"Install-decision recording is unavailable in this harness; proceed without LSP if the user declines.",
|
|
@@ -126,8 +212,7 @@ function formatNotInstalled(result: Extract<ServerLookupResult, { status: "not_i
|
|
|
126
212
|
|
|
127
213
|
return [
|
|
128
214
|
...header,
|
|
129
|
-
|
|
130
|
-
` ${installHint}`,
|
|
215
|
+
...installOptions,
|
|
131
216
|
"",
|
|
132
217
|
"ACTION REQUIRED — ASK THE USER whether to install this LSP server.",
|
|
133
218
|
"- If the user agrees: run the install command above, then retry this tool.",
|
|
@@ -143,7 +228,7 @@ export interface WithLspClientOptions {
|
|
|
143
228
|
manager?: LspManager;
|
|
144
229
|
}
|
|
145
230
|
|
|
146
|
-
const
|
|
231
|
+
const READ_ONLY_TOOLS = new Set([
|
|
147
232
|
"diagnostics",
|
|
148
233
|
"definition",
|
|
149
234
|
"references",
|
|
@@ -154,11 +239,13 @@ const READ_ONLY_RETRY_TOOLS = new Set([
|
|
|
154
239
|
|
|
155
240
|
export async function withLspClient<T>(
|
|
156
241
|
filePath: string,
|
|
157
|
-
fn: (client: LspClient, workspaceRoot: string) => Promise<T>,
|
|
242
|
+
fn: (client: LspClient, workspaceRoot: string, resolvedFilePath: string) => Promise<T>,
|
|
158
243
|
toolName: string,
|
|
159
244
|
options: WithLspClientOptions = {},
|
|
160
245
|
): Promise<T> {
|
|
161
|
-
const absPath =
|
|
246
|
+
const absPath = READ_ONLY_TOOLS.has(toolName)
|
|
247
|
+
? resolveReadablePathInsideContext(filePath)
|
|
248
|
+
: resolvePathInsideContext(filePath);
|
|
162
249
|
|
|
163
250
|
if (isDirectoryPath(absPath)) {
|
|
164
251
|
throw new LspInvalidPathError(
|
|
@@ -181,9 +268,9 @@ export async function withLspClient<T>(
|
|
|
181
268
|
const client = await manager.getClient(root, server, options.signal);
|
|
182
269
|
|
|
183
270
|
try {
|
|
184
|
-
return await fn(client, root);
|
|
271
|
+
return await fn(client, root, absPath);
|
|
185
272
|
} catch (err) {
|
|
186
|
-
if (allowRetry &&
|
|
273
|
+
if (allowRetry && READ_ONLY_TOOLS.has(toolName) && isLspDeadConnectionError(err)) {
|
|
187
274
|
manager.invalidateClient(root, server.id, client);
|
|
188
275
|
return acquireAndCall(false);
|
|
189
276
|
}
|
|
@@ -6,6 +6,7 @@ import type { LspClientTimeoutOptions } from "./transport.js";
|
|
|
6
6
|
import type {
|
|
7
7
|
Diagnostic,
|
|
8
8
|
DocumentSymbol,
|
|
9
|
+
FormattingOptions,
|
|
9
10
|
Location,
|
|
10
11
|
LocationLink,
|
|
11
12
|
PrepareRenameDefaultBehavior,
|
|
@@ -13,6 +14,7 @@ import type {
|
|
|
13
14
|
Range,
|
|
14
15
|
ResolvedServer,
|
|
15
16
|
SymbolInfo,
|
|
17
|
+
TextEdit,
|
|
16
18
|
WorkspaceEdit,
|
|
17
19
|
} from "./types.js";
|
|
18
20
|
import { LspRequestTimeoutError } from "./errors.js";
|
|
@@ -133,6 +135,30 @@ export class LspClient extends LspClientConnection {
|
|
|
133
135
|
}, options);
|
|
134
136
|
}
|
|
135
137
|
|
|
138
|
+
/**
|
|
139
|
+
* Requests whole-document formatting edits, returning null when the server never advertised the
|
|
140
|
+
* capability so callers can report unavailability instead of surfacing a method-not-found error.
|
|
141
|
+
*/
|
|
142
|
+
async formatDocument(
|
|
143
|
+
filePath: string,
|
|
144
|
+
options: FormattingOptions,
|
|
145
|
+
signal?: AbortSignal,
|
|
146
|
+
): Promise<TextEdit[] | null> {
|
|
147
|
+
if (!this.isDocumentFormattingSupported()) return null;
|
|
148
|
+
const absPath = this.resolveWorkspacePath(filePath);
|
|
149
|
+
await this.openFile(absPath);
|
|
150
|
+
const requestOptions = signal === undefined ? {} : { signal };
|
|
151
|
+
const edits = await this.sendRequest<TextEdit[] | null>(
|
|
152
|
+
"textDocument/formatting",
|
|
153
|
+
{
|
|
154
|
+
textDocument: { uri: pathToFileURL(absPath).href },
|
|
155
|
+
options,
|
|
156
|
+
},
|
|
157
|
+
requestOptions,
|
|
158
|
+
);
|
|
159
|
+
return edits ?? [];
|
|
160
|
+
}
|
|
161
|
+
|
|
136
162
|
async workspaceSymbols(query: string, signal?: AbortSignal): Promise<SymbolInfo[]> {
|
|
137
163
|
const options = signal === undefined ? {} : { signal };
|
|
138
164
|
return this.sendRequest<SymbolInfo[]>("workspace/symbol", { query }, options);
|
|
@@ -4,6 +4,7 @@ import { LspClientTransport } from "./transport.js";
|
|
|
4
4
|
|
|
5
5
|
interface InitializeCapabilities {
|
|
6
6
|
readonly diagnosticProvider?: unknown;
|
|
7
|
+
readonly documentFormattingProvider?: unknown;
|
|
7
8
|
}
|
|
8
9
|
|
|
9
10
|
function supportsDiagnosticPull(capabilities: InitializeCapabilities | undefined): boolean {
|
|
@@ -11,6 +12,19 @@ function supportsDiagnosticPull(capabilities: InitializeCapabilities | undefined
|
|
|
11
12
|
return Object.hasOwn(capabilities, "diagnosticProvider");
|
|
12
13
|
}
|
|
13
14
|
|
|
15
|
+
/**
|
|
16
|
+
* Reads the whole-document formatting capability the server advertised at initialize time.
|
|
17
|
+
*
|
|
18
|
+
* The provider is either a boolean or an options object, and an explicit `false` means the
|
|
19
|
+
* server refuses the request, so both shapes are checked instead of mere key presence.
|
|
20
|
+
*/
|
|
21
|
+
function supportsDocumentFormatting(capabilities: InitializeCapabilities | undefined): boolean {
|
|
22
|
+
if (capabilities === undefined) return false;
|
|
23
|
+
const provider = capabilities.documentFormattingProvider;
|
|
24
|
+
if (provider === undefined || provider === null || provider === false) return false;
|
|
25
|
+
return provider === true || typeof provider === "object";
|
|
26
|
+
}
|
|
27
|
+
|
|
14
28
|
export class LspClientConnection extends LspClientTransport {
|
|
15
29
|
async initialize(): Promise<void> {
|
|
16
30
|
const rootUri = pathToFileURL(this.root).href;
|
|
@@ -28,6 +42,7 @@ export class LspClientConnection extends LspClientTransport {
|
|
|
28
42
|
references: {},
|
|
29
43
|
documentSymbol: { hierarchicalDocumentSymbolSupport: true },
|
|
30
44
|
publishDiagnostics: {},
|
|
45
|
+
formatting: { dynamicRegistration: false },
|
|
31
46
|
rename: {
|
|
32
47
|
prepareSupport: true,
|
|
33
48
|
prepareSupportDefaultBehavior: 1,
|
|
@@ -71,6 +86,7 @@ export class LspClientConnection extends LspClientTransport {
|
|
|
71
86
|
{ timeoutMs: this.initializeTimeoutMs },
|
|
72
87
|
);
|
|
73
88
|
this.setDiagnosticPullSupported(supportsDiagnosticPull(result?.capabilities));
|
|
89
|
+
this.setDocumentFormattingSupported(supportsDocumentFormatting(result?.capabilities));
|
|
74
90
|
await this.sendNotification("initialized", {});
|
|
75
91
|
await this.sendNotification("workspace/didChangeConfiguration", {
|
|
76
92
|
settings: { json: { validate: { enable: true } } },
|
|
@@ -6,6 +6,12 @@ export const DEFAULT_MAX_DIRECTORY_FILES = 50;
|
|
|
6
6
|
export const REQUEST_TIMEOUT_MS = 15_000;
|
|
7
7
|
export const INIT_TIMEOUT_MS = 60_000;
|
|
8
8
|
export const IDLE_TIMEOUT_MS = 5 * 60_000;
|
|
9
|
+
export const MAX_RESIDENT_CLIENTS = 6;
|
|
9
10
|
export const REAPER_INTERVAL_MS = 60_000;
|
|
10
11
|
export const STOP_HARD_KILL_TIMEOUT_MS = 5_000;
|
|
11
12
|
export const STOP_SIGKILL_GRACE_MS = 1_000;
|
|
13
|
+
|
|
14
|
+
/** Max consecutive dead client generations respawned for one key before admission is blocked. */
|
|
15
|
+
export const CLIENT_RESPAWN_RETRY_LIMIT = 2;
|
|
16
|
+
/** How long a spent respawn budget blocks admission before a fresh attempt window opens. */
|
|
17
|
+
export const CLIENT_RESPAWN_COOLDOWN_MS = 60_000;
|
|
@@ -69,6 +69,21 @@ export class LspProcessSpawnError extends Error {
|
|
|
69
69
|
override readonly name = "LspProcessSpawnError";
|
|
70
70
|
}
|
|
71
71
|
|
|
72
|
+
export class LspClientRespawnBudgetExceededError extends Error {
|
|
73
|
+
override readonly name = "LspClientRespawnBudgetExceededError";
|
|
74
|
+
|
|
75
|
+
constructor(
|
|
76
|
+
readonly serverId: string,
|
|
77
|
+
readonly root: string,
|
|
78
|
+
readonly retryLimit: number,
|
|
79
|
+
) {
|
|
80
|
+
super(
|
|
81
|
+
`LSP server ${serverId} at ${root} failed to stay alive; respawn budget exhausted ` +
|
|
82
|
+
`(${retryLimit} consecutive dead generations). Retrying after the cooldown may succeed.`,
|
|
83
|
+
);
|
|
84
|
+
}
|
|
85
|
+
}
|
|
86
|
+
|
|
72
87
|
export function isLspDeadConnectionError(err: unknown): err is LspConnectionClosedError | LspProcessExitedError {
|
|
73
88
|
return err instanceof LspConnectionClosedError || err instanceof LspProcessExitedError;
|
|
74
89
|
}
|
|
@@ -0,0 +1,143 @@
|
|
|
1
|
+
import { mkdtempSync, readFileSync, rmSync, statSync, writeFileSync } from "node:fs";
|
|
2
|
+
import { tmpdir } from "node:os";
|
|
3
|
+
import { join } from "node:path";
|
|
4
|
+
|
|
5
|
+
import { afterEach, describe, expect, it } from "bun:test";
|
|
6
|
+
|
|
7
|
+
import type { LspClient } from "./client.js";
|
|
8
|
+
import { formatDocumentWithClient } from "./format-document.js";
|
|
9
|
+
import type { TextEdit } from "./types.js";
|
|
10
|
+
|
|
11
|
+
const workspaces: string[] = [];
|
|
12
|
+
|
|
13
|
+
afterEach(() => {
|
|
14
|
+
for (const workspace of workspaces.splice(0)) rmSync(workspace, { recursive: true, force: true });
|
|
15
|
+
});
|
|
16
|
+
|
|
17
|
+
function workspaceWith(fileName: string, content: string): { readonly root: string; readonly filePath: string } {
|
|
18
|
+
const root = mkdtempSync(join(tmpdir(), "lsp-format-"));
|
|
19
|
+
workspaces.push(root);
|
|
20
|
+
const filePath = join(root, fileName);
|
|
21
|
+
writeFileSync(filePath, content, "utf-8");
|
|
22
|
+
return { root, filePath };
|
|
23
|
+
}
|
|
24
|
+
|
|
25
|
+
function stubClient(edits: TextEdit[] | null): LspClient {
|
|
26
|
+
return {
|
|
27
|
+
async formatDocument() {
|
|
28
|
+
return edits;
|
|
29
|
+
},
|
|
30
|
+
async openFile() {},
|
|
31
|
+
} as Pick<LspClient, "formatDocument" | "openFile"> as LspClient;
|
|
32
|
+
}
|
|
33
|
+
|
|
34
|
+
describe("formatDocumentWithClient", () => {
|
|
35
|
+
it("#given a server returning text edits #when the document is formatted #then the file is rewritten and line deltas are reported", async () => {
|
|
36
|
+
// given
|
|
37
|
+
const { filePath } = workspaceWith("sample.ts", "const a=1\nconst b =2\nconst c=3\n");
|
|
38
|
+
const edits: TextEdit[] = [
|
|
39
|
+
{ range: { start: { line: 0, character: 0 }, end: { line: 1, character: 12 } }, newText: "const a = 1;\nconst b = 2;" },
|
|
40
|
+
];
|
|
41
|
+
|
|
42
|
+
// when
|
|
43
|
+
const result = await formatDocumentWithClient(stubClient(edits), filePath);
|
|
44
|
+
|
|
45
|
+
// then
|
|
46
|
+
expect(result.status).toBe("formatted");
|
|
47
|
+
expect(readFileSync(filePath, "utf-8")).toBe("const a = 1;\nconst b = 2;\nconst c=3\n");
|
|
48
|
+
expect(result).toMatchObject({ status: "formatted", linesAdded: 2, linesRemoved: 2 });
|
|
49
|
+
});
|
|
50
|
+
|
|
51
|
+
it("#given a server returning an edit that adds lines #when the document is formatted #then the added and removed line counts differ", async () => {
|
|
52
|
+
// given
|
|
53
|
+
const { filePath } = workspaceWith("sample.ts", "const a=1;const b=2\n");
|
|
54
|
+
const edits: TextEdit[] = [
|
|
55
|
+
{ range: { start: { line: 0, character: 0 }, end: { line: 0, character: 19 } }, newText: "const a = 1;\nconst b = 2;" },
|
|
56
|
+
];
|
|
57
|
+
|
|
58
|
+
// when
|
|
59
|
+
const result = await formatDocumentWithClient(stubClient(edits), filePath);
|
|
60
|
+
|
|
61
|
+
// then
|
|
62
|
+
expect(result).toMatchObject({ status: "formatted", linesAdded: 2, linesRemoved: 1 });
|
|
63
|
+
expect(readFileSync(filePath, "utf-8")).toBe("const a = 1;\nconst b = 2;\n");
|
|
64
|
+
});
|
|
65
|
+
|
|
66
|
+
it("#given a server that does not advertise document formatting #when the document is formatted #then the result is unavailable and the file bytes are untouched", async () => {
|
|
67
|
+
// given
|
|
68
|
+
const original = "const a=1\n";
|
|
69
|
+
const { filePath } = workspaceWith("sample.ts", original);
|
|
70
|
+
const before = statSync(filePath);
|
|
71
|
+
|
|
72
|
+
// when
|
|
73
|
+
const result = await formatDocumentWithClient(stubClient(null), filePath);
|
|
74
|
+
|
|
75
|
+
// then
|
|
76
|
+
expect(result).toEqual({ status: "unavailable", reason: "capability_not_advertised" });
|
|
77
|
+
expect(readFileSync(filePath)).toEqual(Buffer.from(original));
|
|
78
|
+
expect(statSync(filePath).mtimeMs).toBe(before.mtimeMs);
|
|
79
|
+
});
|
|
80
|
+
|
|
81
|
+
it("#given a server returning no edits #when the document is formatted #then the result is unchanged and the file bytes are untouched", async () => {
|
|
82
|
+
// given
|
|
83
|
+
const original = "const a = 1;\n";
|
|
84
|
+
const { filePath } = workspaceWith("sample.ts", original);
|
|
85
|
+
|
|
86
|
+
// when
|
|
87
|
+
const result = await formatDocumentWithClient(stubClient([]), filePath);
|
|
88
|
+
|
|
89
|
+
// then
|
|
90
|
+
expect(result).toEqual({ status: "unchanged", linesAdded: 0, linesRemoved: 0 });
|
|
91
|
+
expect(readFileSync(filePath)).toEqual(Buffer.from(original));
|
|
92
|
+
});
|
|
93
|
+
|
|
94
|
+
it("#given edits that reproduce the current bytes #when the document is formatted #then the result is unchanged", async () => {
|
|
95
|
+
// given
|
|
96
|
+
const original = "const a = 1;\n";
|
|
97
|
+
const { filePath } = workspaceWith("sample.ts", original);
|
|
98
|
+
const edits: TextEdit[] = [
|
|
99
|
+
{ range: { start: { line: 0, character: 0 }, end: { line: 0, character: 12 } }, newText: "const a = 1;" },
|
|
100
|
+
];
|
|
101
|
+
|
|
102
|
+
// when
|
|
103
|
+
const result = await formatDocumentWithClient(stubClient(edits), filePath);
|
|
104
|
+
|
|
105
|
+
// then
|
|
106
|
+
expect(result.status).toBe("unchanged");
|
|
107
|
+
expect(readFileSync(filePath, "utf-8")).toBe(original);
|
|
108
|
+
});
|
|
109
|
+
|
|
110
|
+
it("#given the file shrinks after the server computed its edits #when the edits are applied #then the stale edit is rejected instead of corrupting the file", async () => {
|
|
111
|
+
// given
|
|
112
|
+
const { filePath } = workspaceWith("sample.ts", "const a=1\nconst b=2\n");
|
|
113
|
+
const staleEdits: TextEdit[] = [
|
|
114
|
+
{ range: { start: { line: 1, character: 0 }, end: { line: 1, character: 9 } }, newText: "const b = 2;" },
|
|
115
|
+
];
|
|
116
|
+
const racingClient = {
|
|
117
|
+
async formatDocument() {
|
|
118
|
+
writeFileSync(filePath, "short\n", "utf-8");
|
|
119
|
+
return staleEdits;
|
|
120
|
+
},
|
|
121
|
+
async openFile() {},
|
|
122
|
+
} as Pick<LspClient, "formatDocument" | "openFile"> as LspClient;
|
|
123
|
+
|
|
124
|
+
// when / then
|
|
125
|
+
await expect(formatDocumentWithClient(racingClient, filePath)).rejects.toThrow(/outside line/);
|
|
126
|
+
expect(readFileSync(filePath, "utf-8")).toBe("short\n");
|
|
127
|
+
});
|
|
128
|
+
|
|
129
|
+
it("#given a formatted document #when the write completes #then no temporary file is left behind", async () => {
|
|
130
|
+
// given
|
|
131
|
+
const { root, filePath } = workspaceWith("sample.ts", "const a=1\n");
|
|
132
|
+
const edits: TextEdit[] = [
|
|
133
|
+
{ range: { start: { line: 0, character: 0 }, end: { line: 0, character: 9 } }, newText: "const a = 1;" },
|
|
134
|
+
];
|
|
135
|
+
|
|
136
|
+
// when
|
|
137
|
+
await formatDocumentWithClient(stubClient(edits), filePath);
|
|
138
|
+
|
|
139
|
+
// then
|
|
140
|
+
expect(readFileSync(filePath, "utf-8")).toBe("const a = 1;\n");
|
|
141
|
+
expect(() => statSync(join(root, "sample.ts.tmp"))).toThrow();
|
|
142
|
+
});
|
|
143
|
+
});
|
|
@@ -0,0 +1,90 @@
|
|
|
1
|
+
import { readFileSync, renameSync, unlinkSync, writeFileSync } from "node:fs";
|
|
2
|
+
|
|
3
|
+
import type { LspClient } from "./client.js";
|
|
4
|
+
import type { FormattingOptions, TextEdit } from "./types.js";
|
|
5
|
+
import { normalizeTextEdits } from "./workspace-edit-text.js";
|
|
6
|
+
|
|
7
|
+
export const DEFAULT_FORMATTING_OPTIONS: FormattingOptions = {
|
|
8
|
+
tabSize: 4,
|
|
9
|
+
insertSpaces: false,
|
|
10
|
+
trimTrailingWhitespace: true,
|
|
11
|
+
insertFinalNewline: true,
|
|
12
|
+
trimFinalNewlines: true,
|
|
13
|
+
};
|
|
14
|
+
|
|
15
|
+
export type FormatDocumentResult =
|
|
16
|
+
| { readonly status: "formatted"; readonly linesAdded: number; readonly linesRemoved: number }
|
|
17
|
+
| { readonly status: "unchanged"; readonly linesAdded: 0; readonly linesRemoved: 0 }
|
|
18
|
+
| { readonly status: "unavailable"; readonly reason: "capability_not_advertised" };
|
|
19
|
+
|
|
20
|
+
export interface FormatDocumentOptions {
|
|
21
|
+
readonly formattingOptions?: FormattingOptions;
|
|
22
|
+
readonly signal?: AbortSignal;
|
|
23
|
+
}
|
|
24
|
+
|
|
25
|
+
const UNCHANGED: FormatDocumentResult = { status: "unchanged", linesAdded: 0, linesRemoved: 0 };
|
|
26
|
+
|
|
27
|
+
/**
|
|
28
|
+
* Formats one document through the resident language server and commits the result to disk.
|
|
29
|
+
*
|
|
30
|
+
* The server is asked for whole-document edits rather than formatted text, so the edits are
|
|
31
|
+
* validated and applied with the same normalization the workspace-edit path uses. Nothing is
|
|
32
|
+
* written when the server declines the capability or when the edits reproduce the current bytes,
|
|
33
|
+
* which keeps a no-op format from touching file mtimes that downstream tooling watches.
|
|
34
|
+
*/
|
|
35
|
+
export async function formatDocumentWithClient(
|
|
36
|
+
client: LspClient,
|
|
37
|
+
filePath: string,
|
|
38
|
+
options: FormatDocumentOptions = {},
|
|
39
|
+
): Promise<FormatDocumentResult> {
|
|
40
|
+
const edits = await client.formatDocument(
|
|
41
|
+
filePath,
|
|
42
|
+
options.formattingOptions ?? DEFAULT_FORMATTING_OPTIONS,
|
|
43
|
+
options.signal,
|
|
44
|
+
);
|
|
45
|
+
if (edits === null) return { status: "unavailable", reason: "capability_not_advertised" };
|
|
46
|
+
if (edits.length === 0) return UNCHANGED;
|
|
47
|
+
|
|
48
|
+
const before = readFileSync(filePath, "utf-8");
|
|
49
|
+
const normalized = normalizeTextEdits(before, edits, 0);
|
|
50
|
+
if (normalized.text === before) return UNCHANGED;
|
|
51
|
+
|
|
52
|
+
writeAtomically(filePath, normalized.text);
|
|
53
|
+
await client.openFile(filePath);
|
|
54
|
+
|
|
55
|
+
return {
|
|
56
|
+
status: "formatted",
|
|
57
|
+
...lineDelta(normalized.edits),
|
|
58
|
+
};
|
|
59
|
+
}
|
|
60
|
+
|
|
61
|
+
/**
|
|
62
|
+
* Counts the lines each edit removes from the document and adds back in its place.
|
|
63
|
+
*
|
|
64
|
+
* Counting from the edits instead of diffing the whole file keeps the report proportional to what
|
|
65
|
+
* the server actually rewrote, so an unrelated line never shows up as churn.
|
|
66
|
+
*/
|
|
67
|
+
function lineDelta(edits: readonly TextEdit[]): { readonly linesAdded: number; readonly linesRemoved: number } {
|
|
68
|
+
let linesAdded = 0;
|
|
69
|
+
let linesRemoved = 0;
|
|
70
|
+
for (const edit of edits) {
|
|
71
|
+
linesRemoved += edit.range.end.line - edit.range.start.line + 1;
|
|
72
|
+
linesAdded += edit.newText.split("\n").length;
|
|
73
|
+
}
|
|
74
|
+
return { linesAdded, linesRemoved };
|
|
75
|
+
}
|
|
76
|
+
|
|
77
|
+
function writeAtomically(filePath: string, content: string): void {
|
|
78
|
+
const tempPath = `${filePath}.omo-format.tmp`;
|
|
79
|
+
writeFileSync(tempPath, content, "utf-8");
|
|
80
|
+
try {
|
|
81
|
+
renameSync(tempPath, filePath);
|
|
82
|
+
} catch (error) {
|
|
83
|
+
try {
|
|
84
|
+
unlinkSync(tempPath);
|
|
85
|
+
} catch {
|
|
86
|
+
// The rename failure is the actionable error; a leftover temp file must not mask it.
|
|
87
|
+
}
|
|
88
|
+
throw error;
|
|
89
|
+
}
|
|
90
|
+
}
|