oh-my-opencode 5.0.0-beta.23 → 5.0.0-beta.25

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 (142) hide show
  1. package/dist/cli/index.js +141 -184
  2. package/dist/cli-node/index.js +141 -184
  3. package/dist/index.js +1508 -1567
  4. package/dist/skills/debugging/SKILL.md +0 -2
  5. package/dist/skills/debugging/references/methodology/00-setup.md +0 -12
  6. package/dist/skills/debugging/references/methodology/02-investigate.md +0 -21
  7. package/dist/skills/debugging/references/runtimes/go.md +1 -15
  8. package/dist/skills/debugging/references/runtimes/native-binary.md +0 -38
  9. package/dist/skills/debugging/references/runtimes/node.md +0 -25
  10. package/dist/skills/debugging/references/runtimes/python.md +0 -13
  11. package/dist/skills/debugging/references/runtimes/rust.md +0 -41
  12. package/dist/tools/delegate-task/types.d.ts +0 -3
  13. package/dist/tui.js +0 -25
  14. package/package.json +15 -18
  15. package/packages/lsp-core/src/index.ts +0 -1
  16. package/packages/lsp-core/src/lsp/client-wrapper.ts +5 -25
  17. package/packages/lsp-core/src/lsp/client.ts +0 -26
  18. package/packages/lsp-core/src/lsp/connection.ts +0 -16
  19. package/packages/lsp-core/src/lsp/constants.ts +0 -1
  20. package/packages/lsp-core/src/lsp/manager.ts +1 -34
  21. package/packages/lsp-core/src/lsp/server-definitions.ts +0 -29
  22. package/packages/lsp-core/src/lsp/server-installation.ts +27 -200
  23. package/packages/lsp-core/src/lsp/server-resolution.ts +5 -18
  24. package/packages/lsp-core/src/lsp/transport.ts +0 -9
  25. package/packages/lsp-core/src/lsp/types.ts +0 -8
  26. package/packages/lsp-core/src/tool-surface.test.ts +1 -13
  27. package/packages/lsp-core/src/tools/definitions.ts +0 -14
  28. package/packages/lsp-core/src/tools/index.ts +0 -1
  29. package/packages/lsp-core/src/tools/types.ts +0 -10
  30. package/packages/lsp-daemon/dist/cli.js +144 -432
  31. package/packages/lsp-daemon/dist/client.d.ts +0 -10
  32. package/packages/lsp-daemon/dist/client.js +107 -401
  33. package/packages/lsp-daemon/dist/daemon-client.d.ts +0 -1
  34. package/packages/lsp-daemon/dist/daemon-client.js +0 -3
  35. package/packages/lsp-daemon/dist/index.js +107 -395
  36. package/packages/lsp-tools-mcp/dist/cli.js +99 -384
  37. package/packages/lsp-tools-mcp/dist/lsp/manager.js +0 -53
  38. package/packages/lsp-tools-mcp/dist/mcp.js +99 -384
  39. package/packages/lsp-tools-mcp/dist/tools.js +99 -385
  40. package/packages/omo-codex/plugin/.codex-plugin/plugin.json +1 -1
  41. package/packages/omo-codex/plugin/components/bootstrap/dist/cli.js +2 -2
  42. package/packages/omo-codex/plugin/components/bootstrap/hooks/hooks.json +1 -1
  43. package/packages/omo-codex/plugin/components/bootstrap/package.json +1 -1
  44. package/packages/omo-codex/plugin/components/codegraph/dist/cli.js +35 -69
  45. package/packages/omo-codex/plugin/components/codegraph/dist/serve.js +2 -21
  46. package/packages/omo-codex/plugin/components/codegraph/package.json +1 -1
  47. package/packages/omo-codex/plugin/components/comment-checker/hooks/hooks.json +1 -1
  48. package/packages/omo-codex/plugin/components/comment-checker/package.json +1 -1
  49. package/packages/omo-codex/plugin/components/git-bash/hooks/hooks.json +2 -2
  50. package/packages/omo-codex/plugin/components/git-bash/package.json +1 -1
  51. package/packages/omo-codex/plugin/components/lazycodex-executor-verify/hooks/hooks.json +1 -1
  52. package/packages/omo-codex/plugin/components/lazycodex-executor-verify/package.json +1 -1
  53. package/packages/omo-codex/plugin/components/lsp/dist/.omo-runtime-manifest.json +3 -3
  54. package/packages/omo-codex/plugin/components/lsp/dist/cli.js +121 -404
  55. package/packages/omo-codex/plugin/components/lsp/hooks/hooks.json +2 -2
  56. package/packages/omo-codex/plugin/components/lsp/package.json +1 -1
  57. package/packages/omo-codex/plugin/components/rules/dist/cli.js +3 -3
  58. package/packages/omo-codex/plugin/components/rules/hooks/hooks.json +4 -4
  59. package/packages/omo-codex/plugin/components/rules/package.json +1 -1
  60. package/packages/omo-codex/plugin/components/rules/src/post-compact-budget.ts +3 -3
  61. package/packages/omo-codex/plugin/components/rules/test/post-compact-budget.test.ts +4 -4
  62. package/packages/omo-codex/plugin/components/teammode/hooks/hooks.json +1 -1
  63. package/packages/omo-codex/plugin/components/teammode/package.json +1 -1
  64. package/packages/omo-codex/plugin/components/telemetry/dist/cli.js +15 -30
  65. package/packages/omo-codex/plugin/components/telemetry/dist/posthog.js +15 -30
  66. package/packages/omo-codex/plugin/components/telemetry/hooks/hooks.json +1 -1
  67. package/packages/omo-codex/plugin/components/telemetry/package.json +1 -1
  68. package/packages/omo-codex/plugin/components/ultrawork/hooks/hooks.json +1 -1
  69. package/packages/omo-codex/plugin/components/ultrawork/package.json +1 -1
  70. package/packages/omo-codex/plugin/components/ulw-execute-continuation/hooks/hooks.json +2 -2
  71. package/packages/omo-codex/plugin/components/ulw-execute-continuation/package.json +1 -1
  72. package/packages/omo-codex/plugin/components/ulw-loop/hooks/hooks.json +4 -4
  73. package/packages/omo-codex/plugin/components/ulw-loop/package.json +1 -1
  74. package/packages/omo-codex/plugin/hooks/post-compact-resetting-git-bash-mcp-reminder.json +1 -1
  75. package/packages/omo-codex/plugin/hooks/post-compact-resetting-lsp-diagnostics-cache.json +1 -1
  76. package/packages/omo-codex/plugin/hooks/post-compact-resetting-project-rule-cache.json +1 -1
  77. package/packages/omo-codex/plugin/hooks/post-tool-use-checking-codegraph-init-guidance.json +1 -1
  78. package/packages/omo-codex/plugin/hooks/post-tool-use-checking-comments.json +1 -1
  79. package/packages/omo-codex/plugin/hooks/post-tool-use-checking-lsp-diagnostics.json +1 -1
  80. package/packages/omo-codex/plugin/hooks/post-tool-use-checking-thread-title-hygiene.json +1 -1
  81. package/packages/omo-codex/plugin/hooks/post-tool-use-matching-project-rules.json +1 -1
  82. package/packages/omo-codex/plugin/hooks/pre-tool-use-enforcing-unlimited-goal-budget.json +1 -1
  83. package/packages/omo-codex/plugin/hooks/pre-tool-use-guarding-ulw-loop-spawns.json +1 -1
  84. package/packages/omo-codex/plugin/hooks/pre-tool-use-recommending-git-bash-mcp.json +1 -1
  85. package/packages/omo-codex/plugin/hooks/session-start-checking-auto-update.json +1 -1
  86. package/packages/omo-codex/plugin/hooks/session-start-checking-bootstrap-provisioning.json +1 -1
  87. package/packages/omo-codex/plugin/hooks/session-start-checking-codegraph-bootstrap.json +1 -1
  88. package/packages/omo-codex/plugin/hooks/session-start-loading-project-rules.json +1 -1
  89. package/packages/omo-codex/plugin/hooks/session-start-recording-session-telemetry.json +1 -1
  90. package/packages/omo-codex/plugin/hooks/stop-checking-ulw-execute-continuation.json +1 -1
  91. package/packages/omo-codex/plugin/hooks/stop-checking-ulw-loop-resume.json +1 -1
  92. package/packages/omo-codex/plugin/hooks/subagent-stop-checking-ulw-execute-continuation.json +1 -1
  93. package/packages/omo-codex/plugin/hooks/subagent-stop-verifying-lazycodex-executor-evidence.json +1 -1
  94. package/packages/omo-codex/plugin/hooks/user-prompt-submit-checking-ultrawork-trigger.json +1 -1
  95. package/packages/omo-codex/plugin/hooks/user-prompt-submit-checking-ulw-loop-steering.json +1 -1
  96. package/packages/omo-codex/plugin/hooks/user-prompt-submit-loading-project-rules.json +1 -1
  97. package/packages/omo-codex/plugin/model-catalog.json +3 -3
  98. package/packages/omo-codex/plugin/package-lock.json +13 -13
  99. package/packages/omo-codex/plugin/package.json +1 -1
  100. package/packages/omo-codex/plugin/scripts/migrate-codex-config/catalog.mjs +3 -3
  101. package/packages/omo-codex/plugin/skills/debugging/SKILL.md +0 -2
  102. package/packages/omo-codex/plugin/skills/debugging/references/methodology/00-setup.md +0 -12
  103. package/packages/omo-codex/plugin/skills/debugging/references/methodology/02-investigate.md +0 -21
  104. package/packages/omo-codex/plugin/skills/debugging/references/runtimes/go.md +1 -15
  105. package/packages/omo-codex/plugin/skills/debugging/references/runtimes/native-binary.md +0 -38
  106. package/packages/omo-codex/plugin/skills/debugging/references/runtimes/node.md +0 -25
  107. package/packages/omo-codex/plugin/skills/debugging/references/runtimes/python.md +0 -13
  108. package/packages/omo-codex/plugin/skills/debugging/references/runtimes/rust.md +0 -41
  109. package/packages/omo-codex/plugin/test/aggregate-model-catalog.test.mjs +1 -1
  110. package/packages/omo-codex/plugin/test/auto-update.test.mjs +2 -2
  111. package/packages/omo-codex/plugin/test/migrate-codex-config.test.mjs +8 -8
  112. package/packages/omo-codex/scripts/install-config-reasoning.test.mjs +2 -2
  113. package/packages/omo-codex/scripts/install-dist/install-local.mjs +23 -38
  114. package/packages/shared-skills/skills/debugging/SKILL.md +0 -2
  115. package/packages/shared-skills/skills/debugging/references/methodology/00-setup.md +0 -12
  116. package/packages/shared-skills/skills/debugging/references/methodology/02-investigate.md +0 -21
  117. package/packages/shared-skills/skills/debugging/references/runtimes/go.md +1 -15
  118. package/packages/shared-skills/skills/debugging/references/runtimes/native-binary.md +0 -38
  119. package/packages/shared-skills/skills/debugging/references/runtimes/node.md +0 -25
  120. package/packages/shared-skills/skills/debugging/references/runtimes/python.md +0 -13
  121. package/packages/shared-skills/skills/debugging/references/runtimes/rust.md +0 -41
  122. package/dist/skills/debugging/references/scripts/dap.mjs +0 -267
  123. package/dist/skills/debugging/references/scripts/dap.test.ts +0 -86
  124. package/dist/skills/debugging/references/scripts/fixture-adapter.mjs +0 -59
  125. package/dist/skills/debugging/references/tools/dap.md +0 -103
  126. package/dist/skills/debugging/references/tools/frida.md +0 -193
  127. package/packages/lsp-core/src/lsp/format-document.test.ts +0 -143
  128. package/packages/lsp-core/src/lsp/format-document.ts +0 -90
  129. package/packages/lsp-core/src/lsp/manager-max-clients.test.ts +0 -151
  130. package/packages/lsp-core/src/lsp/server-installation.test.ts +0 -376
  131. package/packages/lsp-core/src/lsp/server-resolution-local-binary.test.ts +0 -170
  132. package/packages/lsp-core/src/tools/format.test.ts +0 -56
  133. package/packages/lsp-core/src/tools/format.ts +0 -56
  134. package/packages/omo-codex/plugin/skills/debugging/references/scripts/dap.mjs +0 -267
  135. package/packages/omo-codex/plugin/skills/debugging/references/scripts/fixture-adapter.mjs +0 -59
  136. package/packages/omo-codex/plugin/skills/debugging/references/tools/dap.md +0 -103
  137. package/packages/omo-codex/plugin/skills/debugging/references/tools/frida.md +0 -193
  138. package/packages/shared-skills/skills/debugging/references/scripts/dap.mjs +0 -267
  139. package/packages/shared-skills/skills/debugging/references/scripts/dap.test.ts +0 -86
  140. package/packages/shared-skills/skills/debugging/references/scripts/fixture-adapter.mjs +0 -59
  141. package/packages/shared-skills/skills/debugging/references/tools/dap.md +0 -103
  142. package/packages/shared-skills/skills/debugging/references/tools/frida.md +0 -193
@@ -53,8 +53,6 @@ These are not "optional extras". They are the correct tool in their domain, and
53
53
  | **Ghidra** | Any binary without trustworthy source — third-party closed libs, malware, vendored binaries whose behavior contradicts docs, CTF, firmware. **Use Ghidra's decompiler before `strings`/`objdump` guessing. It turns machine code into readable C.** | 📖 **[references/tools/ghidra.md](references/tools/ghidra.md)** |
54
54
  | **pwndbg** | Any native binary debugging session. It is GDB with the useful views (registers, stack, disasm, heap) always visible. **If you'd reach for plain `gdb`, reach for `pwndbg` instead — it is strictly a superset.** | 📖 **[references/tools/pwndbg.md](references/tools/pwndbg.md)** |
55
55
  | **pwntools** | Any time you need a reproducible interaction with a binary or network service — crafted payloads, exploit automation, fuzz harness, CTF scripting. | 📖 **[references/tools/pwntools.md](references/tools/pwntools.md)** |
56
- | **Frida** | Any running process you must instrument live without source or symbols — hook a function and print real argument values, trace calls, stub a return. Complements Ghidra: Ghidra reads the bytes, Frida watches them execute. **If Ghidra's static decompile has hit its limit, reach for Frida.** | 📖 **[references/tools/frida.md](references/tools/frida.md)** |
57
- | **DAP client (`dap.mjs`)** | Any time you would drive a debugger through a PTY and screen-scrape its text. Debuggers already speak the machine-readable Debug Adapter Protocol (debugpy, `dlv dap`, lldb-dap, js-debug); this bundled script drives it with bounded, monitorable output. **Prefer it over scraping `gdb`/`pdb` whenever the debugger speaks DAP.** Design modeled on oh-my-pi's `debug` tool (github.com/can1357/oh-my-pi). | 📖 **[references/tools/dap.md](references/tools/dap.md)** |
58
56
 
59
57
  **Failing to use these tools in their domain is a process failure, not a stylistic choice.** If the bug is in a browser and you did Phase 8 without Playwright, you are doing it wrong. If the bug is in a stripped binary and you read hex with `xxd`, you are doing it wrong. The references tell you how. Read them.
60
58
 
@@ -35,18 +35,6 @@ The shape of the answers you need (commands in the runtime reference):
35
35
  | Is there an existing failing test or known repro? | Prefer amplifying an existing repro over inventing one. |
36
36
  | Are watchers (file watchers, hot reloaders, supervisors) going to restart the process mid-session? | If yes, turn them off before attaching. Restarts drop inspector connections and invalidate breakpoints. |
37
37
 
38
- ### Output budget
39
-
40
- **Bound every inspection before you run it; unbounded output destroys the investigation's working context.**
41
- - Set a frame count, element count, or byte range for every query.
42
- - Prefer one targeted query over one broad dump: ask for the value that distinguishes hypotheses.
43
- - Page through more data only when the first bounded result says it is necessary; do not re-dump the whole object.
44
- - Treat any command whose output size you cannot predict as a command that needs a limit.
45
- - Before: GDB `bt` — After: GDB `bt 10` to inspect only the top ten frames.
46
- - Before: LLDB `memory read 0x1000` — After: `memory read 0x1000 -c 32` for a bounded byte range.
47
- - Before: LLDB `frame variable` — After: `frame variable --children-count 10 user` for one variable's children.
48
- - This is not presentation etiquette: a flooded context hides the decisive observation and can end the investigation.
49
-
50
38
  ### 4. Gate check
51
39
 
52
40
  If any answer is "I'm not sure", you are not ready for Phase 1. Investigate until certain. Guessing here cascades into false-positive hypotheses in Phase 2.
@@ -39,27 +39,6 @@ If two hypotheses have identical distinguishing evidence, they aren't actually d
39
39
 
40
40
  ## Phase 3 — Parallel Investigation
41
41
 
42
- ### State freshness invariant
43
-
44
- **A debug session's state is a snapshot with a lifetime, not a fact you can carry forward indefinitely.**
45
- - Before any action that mutates the debuggee, re-observe the session's current state.
46
- - This includes continue, step, side-effecting evaluation, setting or removing breakpoints, and termination.
47
- - Record the current thread state and stop reason; those are the concrete tells for whether the old plan still applies.
48
- - An observation from an earlier turn may already be stale when the next action is issued.
49
- - Turns can be minutes apart while the debuggee runs at full speed, so this failure mode is normal, not exceptional.
50
- - If the thread state or stop reason has moved, re-observe the new state and do not replay the old plan.
51
- - Treat every mutation as conditional on the state you just observed, not on a remembered stop.
52
-
53
- ### Failure-to-recovery taxonomy
54
-
55
- | Failure signature | Most likely cause | Next move |
56
- |---|---|---|
57
- | Adapter or debugger process failed to start | Wrong binary or missing installation | Verify the tool exists, then re-launch; do not retry blindly. |
58
- | Breakpoint accepted but never bound or verified | Source path mismatch, optimized-out code, or missing debug symbols | Check the binary was built with symbols and that the debugger-resolved path matches your file. |
59
- | Attach refused | Permissions, ptrace scope, SIP, or wrong PID | Fix the environment or target identity; a retry will not change it. |
60
- | No stop event within the expected window | Process is running, the breakpoint is unreachable, or the wait was too short | Pause and inspect threads rather than waiting longer. |
61
- | Session terminated unexpectedly | The debuggee crashed or exited | Capture the exit and crash evidence before restarting. |
62
-
63
42
  Branch depending on what's available.
64
43
 
65
44
  ### Path A: Team mode ENABLED
@@ -42,24 +42,10 @@ dlv exec ./bin/myserver
42
42
  # Attach to a running process
43
43
  dlv attach $(pgrep myserver)
44
44
 
45
- # Delve's JSON-RPC API (IDE / remote attach) — default port 2345
45
+ # Headless mode (IDE / remote attach) — default port 2345
46
46
  dlv debug --headless --listen=:2345 --api-version=2 ./cmd/server
47
47
  ```
48
48
 
49
- Delve exposes two distinct machine-readable interfaces:
50
-
51
- ```bash
52
- # Debug Adapter Protocol: use this for editors and DAP-aware automation
53
- dlv dap --listen=127.0.0.1:2345
54
-
55
- # Delve's JSON-RPC API: use this for clients built directly against Delve's API
56
- dlv debug --headless --listen=127.0.0.1:2345 --api-version=2 ./cmd/server
57
- ```
58
-
59
- Pick `dlv dap` when the client speaks DAP; pick headless JSON-RPC when you need Delve's
60
- native API or an existing JSON-RPC client. Both expose structured state, unlike scraping
61
- an interactive `(dlv)` session.
62
-
63
49
  ### Building a debuggable binary
64
50
 
65
51
  The compiler inlines and optimizes aggressively in normal builds, which makes stepping confusing. For serious debugging:
@@ -107,24 +107,6 @@ print(repr(data[max(0,pos-100):pos+200]))
107
107
 
108
108
  If you must keep using `strings`, lower the threshold: `strings -n 1 -t x ./target | rg ...`. The signal-to-noise drops sharply but short content is preserved.
109
109
 
110
- ### Sanitizer build for a crashing C/C++ binary
111
-
112
- If the binary can be rebuilt from C/C++ sources, reproduce the crash with sanitizers before
113
- trying to infer the fault from stripped machine code. AddressSanitizer catches out-of-bounds
114
- accesses and use-after-free; UndefinedBehaviorSanitizer reports undefined operations.
115
-
116
- ```bash
117
- # Rebuild with source locations and runtime checks enabled
118
- CFLAGS='-g -O1 -fsanitize=address,undefined' \
119
- CXXFLAGS='-g -O1 -fsanitize=address,undefined' \
120
- make clean all
121
- ./target
122
- ```
123
-
124
- The sanitizer report identifies the invalid access and its allocation/free or undefined
125
- operation stack, often making the root cause clear before dynamic analysis. For a binary
126
- that cannot be rebuilt, continue with the native tracing and debugger workflow below.
127
-
128
110
  Write the triage summary to the journal:
129
111
 
130
112
  ```markdown
@@ -247,26 +229,6 @@ lldb ./target
247
229
  (lldb) image dump symtab ./target
248
230
  ```
249
231
 
250
- ### Data watchpoints — catch the corruption, not just the crash
251
-
252
- When a value is already wrong by the time execution reaches the crash, watch the memory
253
- address for writes and stop at the instruction that corrupts it. Use the address of the
254
- field or buffer identified from the static/dynamic hypothesis; see [tools/pwndbg.md](../tools/pwndbg.md)
255
- for the richer pwndbg watchpoint workflow rather than duplicating it here.
256
-
257
- ```text
258
- # lldb: watch writes to an address (replace with a valid expression/address)
259
- (lldb) watchpoint set expression -- <addr>
260
-
261
- # gdb: stop on writes, or on reads when a read is the first observable symptom
262
- (gdb) watch *(<type> *)<addr>
263
- (gdb) rwatch *(<type> *)<addr>
264
- ```
265
-
266
- A watchpoint is most useful after narrowing the suspect object: continue from its
267
- allocation or initialization, and inspect the backtrace and writer when it triggers.
268
- Hardware watchpoint slots are limited, so remove broad watchpoints before adding more.
269
-
270
232
  **Function interception via `DYLD_INSERT_LIBRARIES`** (macOS equivalent of `LD_PRELOAD`):
271
233
 
272
234
  ```bash
@@ -98,31 +98,6 @@ bun test --inspect-brk # debug test runner
98
98
 
99
99
  **Critical**: Bun uses WebKit Inspector Protocol, not V8. `chrome://inspect` cannot connect directly. Use `debug.bun.sh` or the (currently buggy, per Bun docs) VS Code extension.
100
100
 
101
- ### Scripted V8 inspector / CDP attach
102
-
103
- The inspector port also serves machine-readable HTTP discovery endpoints. `/json` lists
104
- inspectable targets; `/json/version` includes the WebSocket debugger URL. Connect that
105
- URL with the Chrome DevTools Protocol (CDP), rather than scraping `node inspect` text.
106
- `chrome-remote-interface` is the canonical scriptable npm client. When browser automation
107
- is already in play, use Playwright's `CDPSession` instead.
108
-
109
- ```bash
110
- curl -s http://127.0.0.1:9229/json/version
111
- ```
112
-
113
- ```js
114
- const CDP = require('chrome-remote-interface');
115
- const version = await fetch('http://127.0.0.1:9229/json/version').then(r => r.json());
116
- const client = await CDP({ target: version.webSocketDebuggerUrl });
117
- await client.Runtime.enable();
118
- await client.Debugger.pause();
119
- ```
120
-
121
- The same CDP commands can be sent through `chrome-remote-interface`; with Playwright,
122
- create a session with `await context.newCDPSession(page)` and call
123
- `await session.send('Runtime.enable')`. These V8/CDP examples do not apply to Bun's
124
- WebKit inspector protocol.
125
-
126
101
  ### Deno (native V8, Chrome DevTools / VS Code compatible)
127
102
 
128
103
  ```bash
@@ -41,19 +41,6 @@ python -c 'import asyncio; print(asyncio.__version__)'
41
41
  | **post-mortem `pdb.pm()`** | Exception already happened, you want to inspect state | In an exception-caught REPL: `import pdb; pdb.pm()` after the exception propagates |
42
42
  | **debugpy (remote / IDE)** | IDE attach, remote host, containerized process | `python -m debugpy --listen 5678 --wait-for-client script.py` then attach from VS Code / PyCharm |
43
43
 
44
- `debugpy` is a Debug Adapter Protocol (DAP) adapter, not merely an IDE convenience.
45
- Its listener exposes a machine-readable protocol that an agent or other client can drive
46
- programmatically; it is a better boundary for automation than the human-oriented pdb REPL.
47
-
48
- ```bash
49
- # Listen on the requested interface and wait before executing the script
50
- python -m debugpy --listen <host:port> --wait-for-client <script>
51
- ```
52
-
53
- Use a DAP client to send structured requests and receive structured stopped/continued
54
- and stack/variable events. By contrast, `pdb` exposes prompt-oriented text: an agent
55
- using it must screen-scrape output and parse a human-facing REPL.
56
-
57
44
  ### Prefer `ipdb` or `pudb` over plain `pdb` when available
58
45
 
59
46
  - **ipdb** — drop-in replacement with tab completion, syntax highlighting. `pip install ipdb`, then `PYTHONBREAKPOINT=ipdb.set_trace` or use `import ipdb; ipdb.set_trace()`.
@@ -144,47 +144,6 @@ Rust symbols are mangled. Use either:
144
144
 
145
145
  ---
146
146
 
147
- ## Sanitizers — memory and race bugs
148
-
149
- Nightly Rust exposes LLVM sanitizers through `-Z sanitizer`. Use them when a crash,
150
- data race, or leak is otherwise too timing- or state-dependent to explain from a
151
- backtrace; they replace guesswork with a report at the invalid operation.
152
-
153
- ```bash
154
- # AddressSanitizer: out-of-bounds accesses and use-after-free
155
- cargo +nightly run -Z sanitizer=address
156
-
157
- # ThreadSanitizer: data races between threads
158
- cargo +nightly test -Z sanitizer=thread
159
-
160
- # LeakSanitizer: allocations that remain reachable at process exit
161
- cargo +nightly run -Z sanitizer=leak
162
- ```
163
-
164
- `address` catches invalid memory access and use-after-free, `thread` catches unsynchronized
165
- concurrent accesses, and `leak` reports memory that was allocated but not released. Run
166
- the invocation that matches the suspected class; sanitizer diagnostics are especially
167
- useful before attaching a debugger to optimized or timing-sensitive code.
168
-
169
- ---
170
-
171
- ## rr — time-travel debugging
172
-
173
- On supported Linux systems, record the failure once, then replay it deterministically and
174
- run backwards from the failure with `reverse-continue` or `reverse-step`:
175
-
176
- ```bash
177
- rr record ./target/debug/my_binary
178
- rr replay
179
- # (rr) reverse-continue
180
- # (rr) reverse-step
181
- ```
182
-
183
- `rr` is Linux/x86-64 only. It does not apply on Apple Silicon, including arm64 macOS;
184
- use `rust-lldb` or a sanitizer there instead.
185
-
186
- ---
187
-
188
147
  ## tokio-console — async task debugging
189
148
 
190
149
  For tokio-based async apps, this is essential when tasks are stuck or leaking.
@@ -1,5 +1,4 @@
1
1
  import type { BackgroundManager } from "../../features/background-agent";
2
- import type { OhMyOpenCodeConfig } from "../../config";
3
2
  import type { CategoriesConfig, GitMasterConfig, BrowserAutomationProvider, AgentOverrides, SisyphusAgentConfig } from "../../config/schema";
4
3
  import type { ModelFallbackControllerAccessor } from "../../hooks/model-fallback";
5
4
  import type { LoadedSkill } from "../../features/opencode-skill-loader/types";
@@ -120,8 +119,6 @@ export interface DelegateTaskToolOptions {
120
119
  availableCategories?: AvailableCategory[];
121
120
  availableSkills?: AvailableSkill[];
122
121
  agentOverrides?: AgentOverrides;
123
- /** Reload model-bearing config at task invocation time so edits are honored without rebuilding tools. */
124
- loadCurrentModelConfig?: () => Pick<OhMyOpenCodeConfig, "agents" | "categories">;
125
122
  sisyphusAgentConfig?: SisyphusAgentConfig;
126
123
  modelFallbackControllerAccessor?: ModelFallbackControllerAccessor;
127
124
  onSyncSessionCreated?: (event: SyncSessionCreatedEvent) => Promise<void>;
package/dist/tui.js CHANGED
@@ -17499,25 +17499,6 @@ var init_telemetry = __esm(() => {
17499
17499
  }).strict();
17500
17500
  });
17501
17501
 
17502
- // packages/omo-config-core/src/schema/format-on-mutation.ts
17503
- var mode, languages, OmoFormatOnMutationLayerSchema, OmoFormatOnMutationSchema;
17504
- var init_format_on_mutation = __esm(() => {
17505
- init_zod();
17506
- mode = _enum2(["off", "best-effort", "required"]);
17507
- languages = record(string2(), boolean2()).optional();
17508
- OmoFormatOnMutationLayerSchema = object({
17509
- mode: mode.optional(),
17510
- languages,
17511
- maxFileBytes: number2().int().positive().optional(),
17512
- timeoutMs: number2().int().positive().optional()
17513
- }).strict();
17514
- OmoFormatOnMutationSchema = OmoFormatOnMutationLayerSchema.extend({
17515
- mode: mode.default("best-effort"),
17516
- maxFileBytes: number2().int().positive().default(1048576),
17517
- timeoutMs: number2().int().positive().default(3000)
17518
- }).strict();
17519
- });
17520
-
17521
17502
  // packages/omo-config-core/src/schema/config.ts
17522
17503
  var OmoOpenCodeHarnessConfigSchema, OmoTypedHarnessConfigSchema, OmoConfigProfileSchema, OmoConfigSchema, OmoConfigLayerSchema;
17523
17504
  var init_config = __esm(() => {
@@ -17531,10 +17512,8 @@ var init_config = __esm(() => {
17531
17512
  init_task();
17532
17513
  init_team();
17533
17514
  init_telemetry();
17534
- init_format_on_mutation();
17535
17515
  OmoOpenCodeHarnessConfigSchema = record(string2(), unknown());
17536
17516
  OmoTypedHarnessConfigSchema = object({
17537
- formatOnMutation: OmoFormatOnMutationLayerSchema.optional(),
17538
17517
  categories: OmoCategoriesConfigSchema.optional(),
17539
17518
  agents: OmoAgentsConfigSchema.optional(),
17540
17519
  codegraph: OmoCodegraphSettingsLayerSchema.optional(),
@@ -17546,7 +17525,6 @@ var init_config = __esm(() => {
17546
17525
  telemetry: OmoTelemetrySettingsLayerSchema.optional()
17547
17526
  }).strict();
17548
17527
  OmoConfigProfileSchema = object({
17549
- formatOnMutation: OmoFormatOnMutationLayerSchema.optional(),
17550
17528
  categories: OmoCategoriesConfigSchema.optional(),
17551
17529
  agents: OmoAgentsConfigSchema.optional(),
17552
17530
  codegraph: OmoCodegraphSettingsLayerSchema.optional(),
@@ -17561,7 +17539,6 @@ var init_config = __esm(() => {
17561
17539
  "[codex]": OmoTypedHarnessConfigSchema.optional()
17562
17540
  }).strict();
17563
17541
  OmoConfigSchema = object({
17564
- formatOnMutation: OmoFormatOnMutationSchema.optional(),
17565
17542
  $schema: string2().optional(),
17566
17543
  categories: OmoCategoriesConfigSchema.optional(),
17567
17544
  agents: OmoAgentsConfigSchema.optional(),
@@ -17580,7 +17557,6 @@ var init_config = __esm(() => {
17580
17557
  legacy_migrations: record(string2(), unknown()).optional()
17581
17558
  }).strict();
17582
17559
  OmoConfigLayerSchema = object({
17583
- formatOnMutation: OmoFormatOnMutationLayerSchema.optional(),
17584
17560
  $schema: string2().optional(),
17585
17561
  categories: OmoCategoriesConfigSchema.optional(),
17586
17562
  agents: OmoAgentsConfigSchema.optional(),
@@ -17607,7 +17583,6 @@ var init_schema = __esm(() => {
17607
17583
  init_codegraph();
17608
17584
  init_config();
17609
17585
  init_fallback_models();
17610
- init_format_on_mutation();
17611
17586
  init_git_master();
17612
17587
  init_harness();
17613
17588
  init_memory();
package/package.json CHANGED
@@ -1,6 +1,6 @@
1
1
  {
2
2
  "name": "oh-my-opencode",
3
- "version": "5.0.0-beta.23",
3
+ "version": "5.0.0-beta.25",
4
4
  "description": "The Best AI Agent Harness - Batteries-Included OpenCode Plugin with Multi-Model Orchestration, Parallel Background Agents, and Crafted LSP/AST Tools",
5
5
  "main": "./dist/index.js",
6
6
  "types": "dist/index.d.ts",
@@ -181,7 +181,7 @@
181
181
  "zod": "^4.4.3"
182
182
  },
183
183
  "devDependencies": {
184
- "@code-yeongyu/senpi": "2026.8.27",
184
+ "@code-yeongyu/senpi": "2026.8.26-2",
185
185
  "@oh-my-opencode/agents-md-core": "workspace:*",
186
186
  "@oh-my-opencode/ast-grep-mcp": "workspace:*",
187
187
  "@oh-my-opencode/boulder-state": "workspace:*",
@@ -222,18 +222,18 @@
222
222
  "typescript": "^7.0.2"
223
223
  },
224
224
  "optionalDependencies": {
225
- "oh-my-opencode-darwin-arm64": "5.0.0-beta.23",
226
- "oh-my-opencode-darwin-x64": "5.0.0-beta.23",
227
- "oh-my-opencode-darwin-x64-baseline": "5.0.0-beta.23",
228
- "oh-my-opencode-linux-arm64": "5.0.0-beta.23",
229
- "oh-my-opencode-linux-arm64-musl": "5.0.0-beta.23",
230
- "oh-my-opencode-linux-x64": "5.0.0-beta.23",
231
- "oh-my-opencode-linux-x64-baseline": "5.0.0-beta.23",
232
- "oh-my-opencode-linux-x64-musl": "5.0.0-beta.23",
233
- "oh-my-opencode-linux-x64-musl-baseline": "5.0.0-beta.23",
234
- "oh-my-opencode-windows-arm64": "5.0.0-beta.23",
235
- "oh-my-opencode-windows-x64": "5.0.0-beta.23",
236
- "oh-my-opencode-windows-x64-baseline": "5.0.0-beta.23"
225
+ "oh-my-opencode-darwin-arm64": "5.0.0-beta.25",
226
+ "oh-my-opencode-darwin-x64": "5.0.0-beta.25",
227
+ "oh-my-opencode-darwin-x64-baseline": "5.0.0-beta.25",
228
+ "oh-my-opencode-linux-arm64": "5.0.0-beta.25",
229
+ "oh-my-opencode-linux-arm64-musl": "5.0.0-beta.25",
230
+ "oh-my-opencode-linux-x64": "5.0.0-beta.25",
231
+ "oh-my-opencode-linux-x64-baseline": "5.0.0-beta.25",
232
+ "oh-my-opencode-linux-x64-musl": "5.0.0-beta.25",
233
+ "oh-my-opencode-linux-x64-musl-baseline": "5.0.0-beta.25",
234
+ "oh-my-opencode-windows-arm64": "5.0.0-beta.25",
235
+ "oh-my-opencode-windows-x64": "5.0.0-beta.25",
236
+ "oh-my-opencode-windows-x64-baseline": "5.0.0-beta.25"
237
237
  },
238
238
  "overrides": {
239
239
  "@earendil-works/pi-agent-core": "0.84.2",
@@ -249,8 +249,5 @@
249
249
  },
250
250
  "trustedDependencies": [
251
251
  "@code-yeongyu/comment-checker"
252
- ],
253
- "patchedDependencies": {
254
- "@code-yeongyu/senpi@2026.8.27": "patches/@code-yeongyu%2Fsenpi@2026.8.27.patch"
255
- }
252
+ ]
256
253
  }
@@ -7,7 +7,6 @@ export * from "./lsp/constants.js";
7
7
  export * from "./lsp/directory-diagnostics.js";
8
8
  export * from "./lsp/effective-extension.js";
9
9
  export * from "./lsp/errors.js";
10
- export * from "./lsp/format-document.js";
11
10
  export * from "./lsp/formatters.js";
12
11
  export * from "./lsp/infer-extension.js";
13
12
  export * from "./lsp/json-rpc-connection.js";
@@ -17,7 +17,6 @@ import {
17
17
  } from "./errors.js";
18
18
  import { getLspManager, type LspManager } from "./manager.js";
19
19
  import { findWorkspaceRootOutsideContext } from "./outside-context-workspace.js";
20
- import { LSP_LOCAL_INSTALL_HINTS } from "./server-definitions.js";
21
20
  import { loadInstallDecision } from "./server-install-state.js";
22
21
  import { findServerForExtension } from "./server-resolution.js";
23
22
  import type { ServerLookupResult } from "./types.js";
@@ -139,26 +138,6 @@ export function formatServerLookupError(result: Exclude<ServerLookupResult, { st
139
138
  ].join("\n");
140
139
  }
141
140
 
142
- /**
143
- * Builds the install guidance, offering the repo-local install first.
144
- *
145
- * A repo-local install is resolvable without touching the global environment, so it is the
146
- * recommended route whenever the server ships as a project dependency.
147
- */
148
- function formatInstallOptions(serverId: string, installHint: string): string[] {
149
- const localHint = LSP_LOCAL_INSTALL_HINTS[serverId];
150
- if (localHint === undefined) {
151
- return ["To install, run:", ` ${installHint}`];
152
- }
153
- return [
154
- "To install in THIS repository (preferred — no global install needed):",
155
- ` ${localHint}`,
156
- "",
157
- "Or install it globally:",
158
- ` ${installHint}`,
159
- ];
160
- }
161
-
162
141
  function formatNotInstalled(result: Extract<ServerLookupResult, { status: "not_installed" }>): string {
163
142
  const { server, installHint } = result;
164
143
  const extensions = server.extensions.join(", ");
@@ -175,20 +154,20 @@ function formatNotInstalled(result: Extract<ServerLookupResult, { status: "not_i
175
154
  `Command not found: ${server.command[0]}`,
176
155
  "",
177
156
  ];
178
- const installOptions = formatInstallOptions(server.id, installHint);
179
157
 
180
158
  if (decision === "allowed") {
181
159
  return [
182
160
  ...header,
183
161
  "The user has pre-authorized LSP installation. Run the install command, then retry this tool:",
184
- ...installOptions.slice(1),
162
+ ` ${installHint}`,
185
163
  ].join("\n");
186
164
  }
187
165
 
188
166
  if (!context.capabilities.installDecisionTool) {
189
167
  return [
190
168
  ...header,
191
- ...installOptions,
169
+ "To install, run:",
170
+ ` ${installHint}`,
192
171
  "",
193
172
  "ACTION REQUIRED — ASK THE USER whether to install this LSP server.",
194
173
  "Install-decision recording is unavailable in this harness; proceed without LSP if the user declines.",
@@ -197,7 +176,8 @@ function formatNotInstalled(result: Extract<ServerLookupResult, { status: "not_i
197
176
 
198
177
  return [
199
178
  ...header,
200
- ...installOptions,
179
+ "To install, run:",
180
+ ` ${installHint}`,
201
181
  "",
202
182
  "ACTION REQUIRED — ASK THE USER whether to install this LSP server.",
203
183
  "- If the user agrees: run the install command above, then retry this tool.",
@@ -6,7 +6,6 @@ import type { LspClientTimeoutOptions } from "./transport.js";
6
6
  import type {
7
7
  Diagnostic,
8
8
  DocumentSymbol,
9
- FormattingOptions,
10
9
  Location,
11
10
  LocationLink,
12
11
  PrepareRenameDefaultBehavior,
@@ -14,7 +13,6 @@ import type {
14
13
  Range,
15
14
  ResolvedServer,
16
15
  SymbolInfo,
17
- TextEdit,
18
16
  WorkspaceEdit,
19
17
  } from "./types.js";
20
18
  import { LspRequestTimeoutError } from "./errors.js";
@@ -135,30 +133,6 @@ export class LspClient extends LspClientConnection {
135
133
  }, options);
136
134
  }
137
135
 
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
-
162
136
  async workspaceSymbols(query: string, signal?: AbortSignal): Promise<SymbolInfo[]> {
163
137
  const options = signal === undefined ? {} : { signal };
164
138
  return this.sendRequest<SymbolInfo[]>("workspace/symbol", { query }, options);
@@ -4,7 +4,6 @@ import { LspClientTransport } from "./transport.js";
4
4
 
5
5
  interface InitializeCapabilities {
6
6
  readonly diagnosticProvider?: unknown;
7
- readonly documentFormattingProvider?: unknown;
8
7
  }
9
8
 
10
9
  function supportsDiagnosticPull(capabilities: InitializeCapabilities | undefined): boolean {
@@ -12,19 +11,6 @@ function supportsDiagnosticPull(capabilities: InitializeCapabilities | undefined
12
11
  return Object.hasOwn(capabilities, "diagnosticProvider");
13
12
  }
14
13
 
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
-
28
14
  export class LspClientConnection extends LspClientTransport {
29
15
  async initialize(): Promise<void> {
30
16
  const rootUri = pathToFileURL(this.root).href;
@@ -42,7 +28,6 @@ export class LspClientConnection extends LspClientTransport {
42
28
  references: {},
43
29
  documentSymbol: { hierarchicalDocumentSymbolSupport: true },
44
30
  publishDiagnostics: {},
45
- formatting: { dynamicRegistration: false },
46
31
  rename: {
47
32
  prepareSupport: true,
48
33
  prepareSupportDefaultBehavior: 1,
@@ -86,7 +71,6 @@ export class LspClientConnection extends LspClientTransport {
86
71
  { timeoutMs: this.initializeTimeoutMs },
87
72
  );
88
73
  this.setDiagnosticPullSupported(supportsDiagnosticPull(result?.capabilities));
89
- this.setDocumentFormattingSupported(supportsDocumentFormatting(result?.capabilities));
90
74
  await this.sendNotification("initialized", {});
91
75
  await this.sendNotification("workspace/didChangeConfiguration", {
92
76
  settings: { json: { validate: { enable: true } } },
@@ -6,7 +6,6 @@ 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;
10
9
  export const REAPER_INTERVAL_MS = 60_000;
11
10
  export const STOP_HARD_KILL_TIMEOUT_MS = 5_000;
12
11
  export const STOP_SIGKILL_GRACE_MS = 1_000;
@@ -1,6 +1,6 @@
1
1
  import { reportBestEffortCleanupError } from "./cleanup-errors.js";
2
2
  import { LspClient } from "./client.js";
3
- import { IDLE_TIMEOUT_MS, INIT_TIMEOUT_MS, MAX_RESIDENT_CLIENTS, REAPER_INTERVAL_MS } from "./constants.js";
3
+ import { IDLE_TIMEOUT_MS, INIT_TIMEOUT_MS, REAPER_INTERVAL_MS } from "./constants.js";
4
4
  import { installProcessSignalCleanup } from "./process-signal-cleanup.js";
5
5
  import type { ResolvedServer } from "./types.js";
6
6
 
@@ -28,7 +28,6 @@ export interface ClientSnapshot {
28
28
  export interface LspManagerOptions {
29
29
  idleTimeoutMs?: number;
30
30
  initTimeoutMs?: number;
31
- maxResidentClients?: number;
32
31
  reaperIntervalMs?: number;
33
32
  clientFactory?: (root: string, server: ResolvedServer) => LspClient;
34
33
  now?: () => number;
@@ -81,7 +80,6 @@ export class LspManager {
81
80
 
82
81
  private readonly idleTimeoutMs: number;
83
82
  private readonly initTimeoutMs: number;
84
- private readonly maxResidentClients: number;
85
83
  private readonly reaperIntervalMs: number;
86
84
  private readonly clientFactory: (root: string, server: ResolvedServer) => LspClient;
87
85
  private readonly now: () => number;
@@ -89,7 +87,6 @@ export class LspManager {
89
87
  constructor(options: LspManagerOptions = {}) {
90
88
  this.idleTimeoutMs = options.idleTimeoutMs ?? IDLE_TIMEOUT_MS;
91
89
  this.initTimeoutMs = options.initTimeoutMs ?? INIT_TIMEOUT_MS;
92
- this.maxResidentClients = options.maxResidentClients ?? MAX_RESIDENT_CLIENTS;
93
90
  this.reaperIntervalMs = options.reaperIntervalMs ?? REAPER_INTERVAL_MS;
94
91
  this.clientFactory = options.clientFactory ?? ((root, server) => new LspClient(root, server));
95
92
  this.now = options.now ?? (() => Date.now());
@@ -137,32 +134,6 @@ export class LspManager {
137
134
  }
138
135
  }
139
136
 
140
- /**
141
- * Frees capacity for one new client by stopping the least recently used idle client.
142
- *
143
- * Only clients with no in-flight work are eligible, so a resident server is never torn down
144
- * underneath a live request; when every resident client is busy the cap is exceeded instead.
145
- */
146
- private evictForAdmission(): void {
147
- while (this.clients.size >= this.maxResidentClients) {
148
- const victim = this.leastRecentlyUsedIdleClient();
149
- if (!victim) return;
150
- this.clients.delete(victim.key);
151
- void stopClientBestEffort(victim.managed.client);
152
- }
153
- }
154
-
155
- private leastRecentlyUsedIdleClient(): { readonly key: string; readonly managed: ManagedClient } | null {
156
- let candidate: { readonly key: string; readonly managed: ManagedClient } | null = null;
157
- for (const [key, managed] of this.clients) {
158
- if (managed.refCount > 0 || managed.pendingWaiters > 0 || managed.isInitializing) continue;
159
- if (candidate === null || managed.lastUsedAt < candidate.managed.lastUsedAt) {
160
- candidate = { key, managed };
161
- }
162
- }
163
- return candidate;
164
- }
165
-
166
137
  private async tryDeleteIfOrphaned(key: string, managed: ManagedClient): Promise<void> {
167
138
  if (
168
139
  managed.refCount === 0 &&
@@ -226,8 +197,6 @@ export class LspManager {
226
197
  return managed.client;
227
198
  }
228
199
 
229
- this.evictForAdmission();
230
-
231
200
  const client = this.clientFactory(root, server);
232
201
  const initStartedAt = this.now();
233
202
  const initPromise = (async () => {
@@ -295,8 +264,6 @@ export class LspManager {
295
264
  const key = this.getKey(root, server.id);
296
265
  if (this.clients.has(key)) return;
297
266
 
298
- this.evictForAdmission();
299
-
300
267
  const client = this.clientFactory(root, server);
301
268
  const initStartedAt = this.now();
302
269
  const initPromise = (async () => {