oh-my-opencode 5.0.0-beta.66 → 5.0.0-beta.68
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/dist/cli/index.js +15 -15
- package/dist/cli-node/index.js +15 -15
- package/dist/index.js +14 -14
- package/package.json +14 -14
- package/packages/lsp-core/src/lsp/client-diagnostics-concurrency.integration.test.ts +9 -1
- package/packages/lsp-core/src/lsp/client-diagnostics-freshness.integration.test.ts +43 -8
- package/packages/lsp-core/src/lsp/controlled-clock-test-support.ts +29 -0
- package/packages/lsp-core/src/lsp/workspace-document-state.ts +5 -0
- package/packages/lsp-daemon/dist/cli.js +2 -0
- package/packages/lsp-daemon/dist/client.js +2 -0
- package/packages/lsp-daemon/dist/index.js +2 -0
- package/packages/lsp-tools-mcp/dist/cli.js +2 -0
- package/packages/lsp-tools-mcp/dist/lsp/manager.js +2 -0
- package/packages/lsp-tools-mcp/dist/mcp.js +2 -0
- package/packages/lsp-tools-mcp/dist/tools.js +2 -0
- package/packages/omo-codex/plugin/.codex-plugin/plugin.json +1 -1
- 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/comment-checker/hooks/hooks.json +1 -1
- package/packages/omo-codex/plugin/components/comment-checker/package.json +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 +1 -1
- 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 +1 -1
- package/packages/omo-codex/plugin/components/lsp/dist/.omo-runtime-manifest.json +3 -3
- package/packages/omo-codex/plugin/components/lsp/dist/cli.js +2 -0
- package/packages/omo-codex/plugin/components/lsp/hooks/hooks.json +2 -2
- package/packages/omo-codex/plugin/components/lsp/package.json +1 -1
- package/packages/omo-codex/plugin/components/rules/hooks/hooks.json +4 -4
- package/packages/omo-codex/plugin/components/rules/package.json +1 -1
- package/packages/omo-codex/plugin/components/teammode/hooks/hooks.json +1 -1
- package/packages/omo-codex/plugin/components/teammode/package.json +1 -1
- package/packages/omo-codex/plugin/components/telemetry/hooks/hooks.json +1 -1
- package/packages/omo-codex/plugin/components/telemetry/package.json +1 -1
- package/packages/omo-codex/plugin/components/ultrawork/hooks/hooks.json +1 -1
- package/packages/omo-codex/plugin/components/ultrawork/package.json +1 -1
- package/packages/omo-codex/plugin/components/ulw-execute-continuation/hooks/hooks.json +1 -1
- package/packages/omo-codex/plugin/components/ulw-execute-continuation/package.json +1 -1
- package/packages/omo-codex/plugin/components/ulw-loop/CHANGELOG.md +1 -0
- package/packages/omo-codex/plugin/components/ulw-loop/dist/cli.js +26 -2
- package/packages/omo-codex/plugin/components/ulw-loop/dist/ledger.js +6 -1
- package/packages/omo-codex/plugin/components/ulw-loop/dist/plan-commit.js +2 -1
- package/packages/omo-codex/plugin/components/ulw-loop/dist/plan-log.d.ts +2 -1
- package/packages/omo-codex/plugin/components/ulw-loop/dist/plan-log.js +30 -1
- package/packages/omo-codex/plugin/components/ulw-loop/hooks/hooks.json +5 -5
- package/packages/omo-codex/plugin/components/ulw-loop/package.json +1 -1
- package/packages/omo-codex/plugin/components/ulw-loop/src/ledger.ts +6 -1
- package/packages/omo-codex/plugin/components/ulw-loop/src/plan-commit.ts +9 -1
- package/packages/omo-codex/plugin/components/ulw-loop/src/plan-log.ts +30 -2
- package/packages/omo-codex/plugin/components/ulw-loop/test/plan-log-legacy-projection.test.ts +228 -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-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/post-tool-use-recording-spawn-admission.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-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 +1 -1
- package/packages/omo-codex/plugin/hooks/stop-checking-ulw-loop-resume.json +1 -1
- 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/package-lock.json +12 -12
- package/packages/omo-codex/plugin/package.json +1 -1
- package/packages/omo-codex/scripts/install-dist/install-local.mjs +2 -2
package/dist/cli/index.js
CHANGED
|
@@ -64,7 +64,7 @@ var package_default;
|
|
|
64
64
|
var init_package = __esm(() => {
|
|
65
65
|
package_default = {
|
|
66
66
|
name: "oh-my-opencode",
|
|
67
|
-
version: "5.0.0-beta.
|
|
67
|
+
version: "5.0.0-beta.68",
|
|
68
68
|
description: "The Best AI Agent Harness - Batteries-Included OpenCode Plugin with Multi-Model Orchestration, Parallel Background Agents, and Crafted LSP/AST Tools",
|
|
69
69
|
main: "./dist/index.js",
|
|
70
70
|
types: "dist/index.d.ts",
|
|
@@ -246,7 +246,7 @@ var init_package = __esm(() => {
|
|
|
246
246
|
zod: "^4.4.3"
|
|
247
247
|
},
|
|
248
248
|
devDependencies: {
|
|
249
|
-
"@code-yeongyu/senpi": "2026.9.16-
|
|
249
|
+
"@code-yeongyu/senpi": "2026.9.16-3",
|
|
250
250
|
"@oh-my-opencode/agents-md-core": "workspace:*",
|
|
251
251
|
"@oh-my-opencode/ast-grep-mcp": "workspace:*",
|
|
252
252
|
"@oh-my-opencode/boulder-state": "workspace:*",
|
|
@@ -285,18 +285,18 @@ var init_package = __esm(() => {
|
|
|
285
285
|
typescript: "^7.0.2"
|
|
286
286
|
},
|
|
287
287
|
optionalDependencies: {
|
|
288
|
-
"oh-my-opencode-darwin-arm64": "5.0.0-beta.
|
|
289
|
-
"oh-my-opencode-darwin-x64": "5.0.0-beta.
|
|
290
|
-
"oh-my-opencode-darwin-x64-baseline": "5.0.0-beta.
|
|
291
|
-
"oh-my-opencode-linux-arm64": "5.0.0-beta.
|
|
292
|
-
"oh-my-opencode-linux-arm64-musl": "5.0.0-beta.
|
|
293
|
-
"oh-my-opencode-linux-x64": "5.0.0-beta.
|
|
294
|
-
"oh-my-opencode-linux-x64-baseline": "5.0.0-beta.
|
|
295
|
-
"oh-my-opencode-linux-x64-musl": "5.0.0-beta.
|
|
296
|
-
"oh-my-opencode-linux-x64-musl-baseline": "5.0.0-beta.
|
|
297
|
-
"oh-my-opencode-windows-arm64": "5.0.0-beta.
|
|
298
|
-
"oh-my-opencode-windows-x64": "5.0.0-beta.
|
|
299
|
-
"oh-my-opencode-windows-x64-baseline": "5.0.0-beta.
|
|
288
|
+
"oh-my-opencode-darwin-arm64": "5.0.0-beta.68",
|
|
289
|
+
"oh-my-opencode-darwin-x64": "5.0.0-beta.68",
|
|
290
|
+
"oh-my-opencode-darwin-x64-baseline": "5.0.0-beta.68",
|
|
291
|
+
"oh-my-opencode-linux-arm64": "5.0.0-beta.68",
|
|
292
|
+
"oh-my-opencode-linux-arm64-musl": "5.0.0-beta.68",
|
|
293
|
+
"oh-my-opencode-linux-x64": "5.0.0-beta.68",
|
|
294
|
+
"oh-my-opencode-linux-x64-baseline": "5.0.0-beta.68",
|
|
295
|
+
"oh-my-opencode-linux-x64-musl": "5.0.0-beta.68",
|
|
296
|
+
"oh-my-opencode-linux-x64-musl-baseline": "5.0.0-beta.68",
|
|
297
|
+
"oh-my-opencode-windows-arm64": "5.0.0-beta.68",
|
|
298
|
+
"oh-my-opencode-windows-x64": "5.0.0-beta.68",
|
|
299
|
+
"oh-my-opencode-windows-x64-baseline": "5.0.0-beta.68"
|
|
300
300
|
},
|
|
301
301
|
overrides: {
|
|
302
302
|
"@earendil-works/pi-agent-core": "0.84.2",
|
|
@@ -84547,7 +84547,7 @@ var package_default2;
|
|
|
84547
84547
|
var init_package2 = __esm(() => {
|
|
84548
84548
|
package_default2 = {
|
|
84549
84549
|
name: "@oh-my-opencode/omo-codex",
|
|
84550
|
-
version: "5.0.0-beta.
|
|
84550
|
+
version: "5.0.0-beta.68",
|
|
84551
84551
|
type: "module",
|
|
84552
84552
|
private: true,
|
|
84553
84553
|
description: "Codex harness adapter for oh-my-openagent. Vendored Codex plugin namespace (omo) + TypeScript installer + telemetry.",
|
package/dist/cli-node/index.js
CHANGED
|
@@ -65,7 +65,7 @@ var package_default;
|
|
|
65
65
|
var init_package = __esm(() => {
|
|
66
66
|
package_default = {
|
|
67
67
|
name: "oh-my-opencode",
|
|
68
|
-
version: "5.0.0-beta.
|
|
68
|
+
version: "5.0.0-beta.68",
|
|
69
69
|
description: "The Best AI Agent Harness - Batteries-Included OpenCode Plugin with Multi-Model Orchestration, Parallel Background Agents, and Crafted LSP/AST Tools",
|
|
70
70
|
main: "./dist/index.js",
|
|
71
71
|
types: "dist/index.d.ts",
|
|
@@ -247,7 +247,7 @@ var init_package = __esm(() => {
|
|
|
247
247
|
zod: "^4.4.3"
|
|
248
248
|
},
|
|
249
249
|
devDependencies: {
|
|
250
|
-
"@code-yeongyu/senpi": "2026.9.16-
|
|
250
|
+
"@code-yeongyu/senpi": "2026.9.16-3",
|
|
251
251
|
"@oh-my-opencode/agents-md-core": "workspace:*",
|
|
252
252
|
"@oh-my-opencode/ast-grep-mcp": "workspace:*",
|
|
253
253
|
"@oh-my-opencode/boulder-state": "workspace:*",
|
|
@@ -286,18 +286,18 @@ var init_package = __esm(() => {
|
|
|
286
286
|
typescript: "^7.0.2"
|
|
287
287
|
},
|
|
288
288
|
optionalDependencies: {
|
|
289
|
-
"oh-my-opencode-darwin-arm64": "5.0.0-beta.
|
|
290
|
-
"oh-my-opencode-darwin-x64": "5.0.0-beta.
|
|
291
|
-
"oh-my-opencode-darwin-x64-baseline": "5.0.0-beta.
|
|
292
|
-
"oh-my-opencode-linux-arm64": "5.0.0-beta.
|
|
293
|
-
"oh-my-opencode-linux-arm64-musl": "5.0.0-beta.
|
|
294
|
-
"oh-my-opencode-linux-x64": "5.0.0-beta.
|
|
295
|
-
"oh-my-opencode-linux-x64-baseline": "5.0.0-beta.
|
|
296
|
-
"oh-my-opencode-linux-x64-musl": "5.0.0-beta.
|
|
297
|
-
"oh-my-opencode-linux-x64-musl-baseline": "5.0.0-beta.
|
|
298
|
-
"oh-my-opencode-windows-arm64": "5.0.0-beta.
|
|
299
|
-
"oh-my-opencode-windows-x64": "5.0.0-beta.
|
|
300
|
-
"oh-my-opencode-windows-x64-baseline": "5.0.0-beta.
|
|
289
|
+
"oh-my-opencode-darwin-arm64": "5.0.0-beta.68",
|
|
290
|
+
"oh-my-opencode-darwin-x64": "5.0.0-beta.68",
|
|
291
|
+
"oh-my-opencode-darwin-x64-baseline": "5.0.0-beta.68",
|
|
292
|
+
"oh-my-opencode-linux-arm64": "5.0.0-beta.68",
|
|
293
|
+
"oh-my-opencode-linux-arm64-musl": "5.0.0-beta.68",
|
|
294
|
+
"oh-my-opencode-linux-x64": "5.0.0-beta.68",
|
|
295
|
+
"oh-my-opencode-linux-x64-baseline": "5.0.0-beta.68",
|
|
296
|
+
"oh-my-opencode-linux-x64-musl": "5.0.0-beta.68",
|
|
297
|
+
"oh-my-opencode-linux-x64-musl-baseline": "5.0.0-beta.68",
|
|
298
|
+
"oh-my-opencode-windows-arm64": "5.0.0-beta.68",
|
|
299
|
+
"oh-my-opencode-windows-x64": "5.0.0-beta.68",
|
|
300
|
+
"oh-my-opencode-windows-x64-baseline": "5.0.0-beta.68"
|
|
301
301
|
},
|
|
302
302
|
overrides: {
|
|
303
303
|
"@earendil-works/pi-agent-core": "0.84.2",
|
|
@@ -84626,7 +84626,7 @@ var package_default2;
|
|
|
84626
84626
|
var init_package2 = __esm(() => {
|
|
84627
84627
|
package_default2 = {
|
|
84628
84628
|
name: "@oh-my-opencode/omo-codex",
|
|
84629
|
-
version: "5.0.0-beta.
|
|
84629
|
+
version: "5.0.0-beta.68",
|
|
84630
84630
|
type: "module",
|
|
84631
84631
|
private: true,
|
|
84632
84632
|
description: "Codex harness adapter for oh-my-openagent. Vendored Codex plugin namespace (omo) + TypeScript installer + telemetry.",
|
package/dist/index.js
CHANGED
|
@@ -96515,7 +96515,7 @@ function getCachedVersion(options = {}) {
|
|
|
96515
96515
|
// package.json
|
|
96516
96516
|
var package_default = {
|
|
96517
96517
|
name: "oh-my-opencode",
|
|
96518
|
-
version: "5.0.0-beta.
|
|
96518
|
+
version: "5.0.0-beta.68",
|
|
96519
96519
|
description: "The Best AI Agent Harness - Batteries-Included OpenCode Plugin with Multi-Model Orchestration, Parallel Background Agents, and Crafted LSP/AST Tools",
|
|
96520
96520
|
main: "./dist/index.js",
|
|
96521
96521
|
types: "dist/index.d.ts",
|
|
@@ -96697,7 +96697,7 @@ var package_default = {
|
|
|
96697
96697
|
zod: "^4.4.3"
|
|
96698
96698
|
},
|
|
96699
96699
|
devDependencies: {
|
|
96700
|
-
"@code-yeongyu/senpi": "2026.9.16-
|
|
96700
|
+
"@code-yeongyu/senpi": "2026.9.16-3",
|
|
96701
96701
|
"@oh-my-opencode/agents-md-core": "workspace:*",
|
|
96702
96702
|
"@oh-my-opencode/ast-grep-mcp": "workspace:*",
|
|
96703
96703
|
"@oh-my-opencode/boulder-state": "workspace:*",
|
|
@@ -96736,18 +96736,18 @@ var package_default = {
|
|
|
96736
96736
|
typescript: "^7.0.2"
|
|
96737
96737
|
},
|
|
96738
96738
|
optionalDependencies: {
|
|
96739
|
-
"oh-my-opencode-darwin-arm64": "5.0.0-beta.
|
|
96740
|
-
"oh-my-opencode-darwin-x64": "5.0.0-beta.
|
|
96741
|
-
"oh-my-opencode-darwin-x64-baseline": "5.0.0-beta.
|
|
96742
|
-
"oh-my-opencode-linux-arm64": "5.0.0-beta.
|
|
96743
|
-
"oh-my-opencode-linux-arm64-musl": "5.0.0-beta.
|
|
96744
|
-
"oh-my-opencode-linux-x64": "5.0.0-beta.
|
|
96745
|
-
"oh-my-opencode-linux-x64-baseline": "5.0.0-beta.
|
|
96746
|
-
"oh-my-opencode-linux-x64-musl": "5.0.0-beta.
|
|
96747
|
-
"oh-my-opencode-linux-x64-musl-baseline": "5.0.0-beta.
|
|
96748
|
-
"oh-my-opencode-windows-arm64": "5.0.0-beta.
|
|
96749
|
-
"oh-my-opencode-windows-x64": "5.0.0-beta.
|
|
96750
|
-
"oh-my-opencode-windows-x64-baseline": "5.0.0-beta.
|
|
96739
|
+
"oh-my-opencode-darwin-arm64": "5.0.0-beta.68",
|
|
96740
|
+
"oh-my-opencode-darwin-x64": "5.0.0-beta.68",
|
|
96741
|
+
"oh-my-opencode-darwin-x64-baseline": "5.0.0-beta.68",
|
|
96742
|
+
"oh-my-opencode-linux-arm64": "5.0.0-beta.68",
|
|
96743
|
+
"oh-my-opencode-linux-arm64-musl": "5.0.0-beta.68",
|
|
96744
|
+
"oh-my-opencode-linux-x64": "5.0.0-beta.68",
|
|
96745
|
+
"oh-my-opencode-linux-x64-baseline": "5.0.0-beta.68",
|
|
96746
|
+
"oh-my-opencode-linux-x64-musl": "5.0.0-beta.68",
|
|
96747
|
+
"oh-my-opencode-linux-x64-musl-baseline": "5.0.0-beta.68",
|
|
96748
|
+
"oh-my-opencode-windows-arm64": "5.0.0-beta.68",
|
|
96749
|
+
"oh-my-opencode-windows-x64": "5.0.0-beta.68",
|
|
96750
|
+
"oh-my-opencode-windows-x64-baseline": "5.0.0-beta.68"
|
|
96751
96751
|
},
|
|
96752
96752
|
overrides: {
|
|
96753
96753
|
"@earendil-works/pi-agent-core": "0.84.2",
|
package/package.json
CHANGED
|
@@ -1,6 +1,6 @@
|
|
|
1
1
|
{
|
|
2
2
|
"name": "oh-my-opencode",
|
|
3
|
-
"version": "5.0.0-beta.
|
|
3
|
+
"version": "5.0.0-beta.68",
|
|
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",
|
|
@@ -182,7 +182,7 @@
|
|
|
182
182
|
"zod": "^4.4.3"
|
|
183
183
|
},
|
|
184
184
|
"devDependencies": {
|
|
185
|
-
"@code-yeongyu/senpi": "2026.9.16-
|
|
185
|
+
"@code-yeongyu/senpi": "2026.9.16-3",
|
|
186
186
|
"@oh-my-opencode/agents-md-core": "workspace:*",
|
|
187
187
|
"@oh-my-opencode/ast-grep-mcp": "workspace:*",
|
|
188
188
|
"@oh-my-opencode/boulder-state": "workspace:*",
|
|
@@ -221,18 +221,18 @@
|
|
|
221
221
|
"typescript": "^7.0.2"
|
|
222
222
|
},
|
|
223
223
|
"optionalDependencies": {
|
|
224
|
-
"oh-my-opencode-darwin-arm64": "5.0.0-beta.
|
|
225
|
-
"oh-my-opencode-darwin-x64": "5.0.0-beta.
|
|
226
|
-
"oh-my-opencode-darwin-x64-baseline": "5.0.0-beta.
|
|
227
|
-
"oh-my-opencode-linux-arm64": "5.0.0-beta.
|
|
228
|
-
"oh-my-opencode-linux-arm64-musl": "5.0.0-beta.
|
|
229
|
-
"oh-my-opencode-linux-x64": "5.0.0-beta.
|
|
230
|
-
"oh-my-opencode-linux-x64-baseline": "5.0.0-beta.
|
|
231
|
-
"oh-my-opencode-linux-x64-musl": "5.0.0-beta.
|
|
232
|
-
"oh-my-opencode-linux-x64-musl-baseline": "5.0.0-beta.
|
|
233
|
-
"oh-my-opencode-windows-arm64": "5.0.0-beta.
|
|
234
|
-
"oh-my-opencode-windows-x64": "5.0.0-beta.
|
|
235
|
-
"oh-my-opencode-windows-x64-baseline": "5.0.0-beta.
|
|
224
|
+
"oh-my-opencode-darwin-arm64": "5.0.0-beta.68",
|
|
225
|
+
"oh-my-opencode-darwin-x64": "5.0.0-beta.68",
|
|
226
|
+
"oh-my-opencode-darwin-x64-baseline": "5.0.0-beta.68",
|
|
227
|
+
"oh-my-opencode-linux-arm64": "5.0.0-beta.68",
|
|
228
|
+
"oh-my-opencode-linux-arm64-musl": "5.0.0-beta.68",
|
|
229
|
+
"oh-my-opencode-linux-x64": "5.0.0-beta.68",
|
|
230
|
+
"oh-my-opencode-linux-x64-baseline": "5.0.0-beta.68",
|
|
231
|
+
"oh-my-opencode-linux-x64-musl": "5.0.0-beta.68",
|
|
232
|
+
"oh-my-opencode-linux-x64-musl-baseline": "5.0.0-beta.68",
|
|
233
|
+
"oh-my-opencode-windows-arm64": "5.0.0-beta.68",
|
|
234
|
+
"oh-my-opencode-windows-x64": "5.0.0-beta.68",
|
|
235
|
+
"oh-my-opencode-windows-x64-baseline": "5.0.0-beta.68"
|
|
236
236
|
},
|
|
237
237
|
"overrides": {
|
|
238
238
|
"@earendil-works/pi-agent-core": "0.84.2",
|
|
@@ -1,5 +1,7 @@
|
|
|
1
1
|
import { afterEach, describe, expect, it } from "bun:test";
|
|
2
2
|
|
|
3
|
+
import { ControlledClock } from "./controlled-clock-test-support.js";
|
|
4
|
+
|
|
3
5
|
import {
|
|
4
6
|
createWorkspaceEditTestHarness,
|
|
5
7
|
diagnostic,
|
|
@@ -14,6 +16,12 @@ afterEach(async () => {
|
|
|
14
16
|
|
|
15
17
|
describe("LspClient diagnostics concurrency", () => {
|
|
16
18
|
it("#given concurrent diagnostics on a cold file and an exact didOpen publish #when pull is not advertised #then one didOpen opens the file and both requests receive the current diagnostics", async () => {
|
|
19
|
+
// The freshness window runs on a controlled clock: this case asserts that the exact-version
|
|
20
|
+
// didOpen publish satisfies BOTH requests, and the publish is what wakes them. On a real clock
|
|
21
|
+
// the 500ms window is a second, competing deadline against a real fixture server over a real
|
|
22
|
+
// pipe, so a starved Windows shard resolved the requests clean before the publish landed and
|
|
23
|
+
// the case failed with [] (#8323). Frozen, only the publish can settle it.
|
|
24
|
+
const clock = new ControlledClock();
|
|
17
25
|
const context = await harness.makeClient(
|
|
18
26
|
{
|
|
19
27
|
publishDiagnostics: [
|
|
@@ -25,7 +33,7 @@ describe("LspClient diagnostics concurrency", () => {
|
|
|
25
33
|
},
|
|
26
34
|
],
|
|
27
35
|
},
|
|
28
|
-
{ diagnosticsFreshnessTimeoutMs: 500, versionlessPublishQuiescenceMs: 5 },
|
|
36
|
+
{ diagnosticsFreshnessTimeoutMs: 500, versionlessPublishQuiescenceMs: 5, timerProvider: clock },
|
|
29
37
|
);
|
|
30
38
|
|
|
31
39
|
const [first, second] = await Promise.all([
|
|
@@ -18,6 +18,27 @@ afterEach(async () => {
|
|
|
18
18
|
await harness.cleanup();
|
|
19
19
|
});
|
|
20
20
|
|
|
21
|
+
/**
|
|
22
|
+
* Drives one `diagnostics()` call whose ONLY exit is the freshness window closing: an advertised
|
|
23
|
+
* pull that comes back "method not found" with no publish behind it.
|
|
24
|
+
*
|
|
25
|
+
* That call arms exactly two timers in order - the pull request's own timeout, then the push
|
|
26
|
+
* fallback wait - and the second can only be armed once the first was cleared by the server's
|
|
27
|
+
* reply. Waiting on the second SCHEDULE (not on a delay value, which both share) is therefore the
|
|
28
|
+
* exact signal that the fallback, and not a request timeout, is what the advance closes. On a real
|
|
29
|
+
* clock the same case resolved from whichever of the two real deadlines a starved Windows shard
|
|
30
|
+
* happened to reach first (#8323).
|
|
31
|
+
*/
|
|
32
|
+
async function resolveThroughFreshnessWindow<T>(clock: ControlledClock, start: () => Promise<T>): Promise<T> {
|
|
33
|
+
const scheduledBefore = clock.scheduledDelays.length;
|
|
34
|
+
const pending = start();
|
|
35
|
+
await clock.waitForScheduled(scheduledBefore + 2);
|
|
36
|
+
clock.advanceBy(FRESHNESS_WINDOW_MS);
|
|
37
|
+
return pending;
|
|
38
|
+
}
|
|
39
|
+
|
|
40
|
+
const FRESHNESS_WINDOW_MS = 500;
|
|
41
|
+
|
|
21
42
|
describe("LspClient diagnostics freshness", () => {
|
|
22
43
|
it("#given a versionless publish that arrives after the current change #when no newer eligible publish arrives before quiescence #then diagnostics wait for that quiescence window and return the versionless payload", async () => {
|
|
23
44
|
const clock = new ControlledClock();
|
|
@@ -159,6 +180,9 @@ describe("LspClient diagnostics freshness", () => {
|
|
|
159
180
|
});
|
|
160
181
|
|
|
161
182
|
it("#given a pull response overtaken by a later local change #when the stale full report returns first #then diagnostics restart within the same request and resolve from the current version", async () => {
|
|
183
|
+
// Both pull reports answer this request, so no freshness deadline may fire: a controlled clock
|
|
184
|
+
// removes the 800ms wall-clock race that a starved shard otherwise wins (#8323).
|
|
185
|
+
const clock = new ControlledClock();
|
|
162
186
|
const context = await harness.makeClient(
|
|
163
187
|
{
|
|
164
188
|
capabilities: { diagnosticProvider: { interFileDependencies: false, workspaceDiagnostics: false } },
|
|
@@ -172,12 +196,12 @@ describe("LspClient diagnostics freshness", () => {
|
|
|
172
196
|
},
|
|
173
197
|
],
|
|
174
198
|
},
|
|
175
|
-
{ diagnosticsFreshnessTimeoutMs: 800, versionlessPublishQuiescenceMs: 5 },
|
|
199
|
+
{ diagnosticsFreshnessTimeoutMs: 800, versionlessPublishQuiescenceMs: 5, timerProvider: clock },
|
|
176
200
|
);
|
|
177
201
|
await context.client.openFile(context.source);
|
|
178
202
|
|
|
179
203
|
const pending = context.client.diagnostics(context.source);
|
|
180
|
-
await
|
|
204
|
+
await waitForEventCountBySubscription(
|
|
181
205
|
context.events,
|
|
182
206
|
(event) => event.type === "clientRequest" && event.method === "textDocument/diagnostic",
|
|
183
207
|
1,
|
|
@@ -196,6 +220,9 @@ describe("LspClient diagnostics freshness", () => {
|
|
|
196
220
|
});
|
|
197
221
|
|
|
198
222
|
it("#given a full pull report followed by an unchanged report for the same version and resultId #when diagnostics repeat without a local change #then the cached full items are reused", async () => {
|
|
223
|
+
// Both requests are answered by the server, so a controlled clock keeps the freshness window
|
|
224
|
+
// from becoming a second deadline the shard can starve (#8323).
|
|
225
|
+
const clock = new ControlledClock();
|
|
199
226
|
const context = await harness.makeClient(
|
|
200
227
|
{
|
|
201
228
|
capabilities: { diagnosticProvider: { interFileDependencies: false, workspaceDiagnostics: false } },
|
|
@@ -208,7 +235,7 @@ describe("LspClient diagnostics freshness", () => {
|
|
|
208
235
|
},
|
|
209
236
|
],
|
|
210
237
|
},
|
|
211
|
-
{ diagnosticsFreshnessTimeoutMs: 500, versionlessPublishQuiescenceMs: 5 },
|
|
238
|
+
{ diagnosticsFreshnessTimeoutMs: 500, versionlessPublishQuiescenceMs: 5, timerProvider: clock },
|
|
212
239
|
);
|
|
213
240
|
await context.client.openFile(context.source);
|
|
214
241
|
|
|
@@ -220,6 +247,9 @@ describe("LspClient diagnostics freshness", () => {
|
|
|
220
247
|
});
|
|
221
248
|
|
|
222
249
|
it("#given a server that claims pull support but closes instead of answering #when diagnostics run #then the transport failure is not labeled clean", async () => {
|
|
250
|
+
// Deliberately left on the real clock: the client only notices the dead server when the
|
|
251
|
+
// in-flight pull request's own timeout aborts it, so a timer must actually fire here. Making
|
|
252
|
+
// the transport reject pending requests from the child's exit event is a separate change.
|
|
223
253
|
const context = await harness.makeClient(
|
|
224
254
|
{
|
|
225
255
|
capabilities: { diagnosticProvider: { interFileDependencies: false, workspaceDiagnostics: false } },
|
|
@@ -233,6 +263,9 @@ describe("LspClient diagnostics freshness", () => {
|
|
|
233
263
|
});
|
|
234
264
|
|
|
235
265
|
it("#given an advertised pull method that is explicitly unsupported and a matching push publish #when diagnostics run #then the client falls back to push diagnostics", async () => {
|
|
266
|
+
// The exact-version publish wakes the push-fallback wait, so no deadline may fire; a controlled
|
|
267
|
+
// clock keeps the 500ms window from winning that race on a starved shard (#8323).
|
|
268
|
+
const clock = new ControlledClock();
|
|
236
269
|
const context = await harness.makeClient(
|
|
237
270
|
{
|
|
238
271
|
capabilities: { diagnosticProvider: { interFileDependencies: false, workspaceDiagnostics: false } },
|
|
@@ -246,7 +279,7 @@ describe("LspClient diagnostics freshness", () => {
|
|
|
246
279
|
],
|
|
247
280
|
diagnosticResponses: [{ error: { code: -32601, message: "Method not found" } }],
|
|
248
281
|
},
|
|
249
|
-
{ diagnosticsFreshnessTimeoutMs: 500, versionlessPublishQuiescenceMs: 5 },
|
|
282
|
+
{ diagnosticsFreshnessTimeoutMs: 500, versionlessPublishQuiescenceMs: 5, timerProvider: clock },
|
|
250
283
|
);
|
|
251
284
|
|
|
252
285
|
const pending = context.client.diagnostics(context.source);
|
|
@@ -301,6 +334,7 @@ describe("LspClient diagnostics freshness", () => {
|
|
|
301
334
|
});
|
|
302
335
|
|
|
303
336
|
it("#given a pull-supported server that cached diagnostics for an older document version #when the file changes and a later pull is rejected as unsupported without any publish #then the fallback resolves empty instead of returning the stale cached diagnostics", async () => {
|
|
337
|
+
const clock = new ControlledClock();
|
|
304
338
|
const context = await harness.makeClient(
|
|
305
339
|
{
|
|
306
340
|
capabilities: { diagnosticProvider: { interFileDependencies: false, workspaceDiagnostics: false } },
|
|
@@ -309,7 +343,7 @@ describe("LspClient diagnostics freshness", () => {
|
|
|
309
343
|
{ error: { code: -32601, message: "Method not found" } },
|
|
310
344
|
],
|
|
311
345
|
},
|
|
312
|
-
{ diagnosticsFreshnessTimeoutMs: 500, versionlessPublishQuiescenceMs: 5 },
|
|
346
|
+
{ diagnosticsFreshnessTimeoutMs: 500, versionlessPublishQuiescenceMs: 5, timerProvider: clock },
|
|
313
347
|
);
|
|
314
348
|
|
|
315
349
|
const first = await context.client.diagnostics(context.source);
|
|
@@ -318,12 +352,13 @@ describe("LspClient diagnostics freshness", () => {
|
|
|
318
352
|
writeFileSync(context.source, "const changed = 1;\n");
|
|
319
353
|
await context.client.openFile(context.source);
|
|
320
354
|
|
|
321
|
-
const second = await context.client.diagnostics(context.source);
|
|
355
|
+
const second = await resolveThroughFreshnessWindow(clock, () => context.client.diagnostics(context.source));
|
|
322
356
|
expect(second.transientError).toBeUndefined();
|
|
323
357
|
expect(second.items).toEqual([]);
|
|
324
358
|
});
|
|
325
359
|
|
|
326
360
|
it("#given a pull-supported server with a current cached pull report #when a later pull is rejected as unsupported without any publish and the document is unchanged #then the fallback resolves with the current cached diagnostics", async () => {
|
|
361
|
+
const clock = new ControlledClock();
|
|
327
362
|
const context = await harness.makeClient(
|
|
328
363
|
{
|
|
329
364
|
capabilities: { diagnosticProvider: { interFileDependencies: false, workspaceDiagnostics: false } },
|
|
@@ -332,13 +367,13 @@ describe("LspClient diagnostics freshness", () => {
|
|
|
332
367
|
{ error: { code: -32601, message: "Method not found" } },
|
|
333
368
|
],
|
|
334
369
|
},
|
|
335
|
-
{ diagnosticsFreshnessTimeoutMs: 500, versionlessPublishQuiescenceMs: 5 },
|
|
370
|
+
{ diagnosticsFreshnessTimeoutMs: 500, versionlessPublishQuiescenceMs: 5, timerProvider: clock },
|
|
336
371
|
);
|
|
337
372
|
|
|
338
373
|
const first = await context.client.diagnostics(context.source);
|
|
339
374
|
expect(first.items).toEqual([diagnostic("cached-full")]);
|
|
340
375
|
|
|
341
|
-
const second = await context.client.diagnostics(context.source);
|
|
376
|
+
const second = await resolveThroughFreshnessWindow(clock, () => context.client.diagnostics(context.source));
|
|
342
377
|
expect(second.transientError).toBeUndefined();
|
|
343
378
|
expect(second.items).toEqual([diagnostic("cached-full")]);
|
|
344
379
|
});
|
|
@@ -11,6 +11,11 @@ interface TimerWaiter {
|
|
|
11
11
|
readonly resolve: () => void;
|
|
12
12
|
}
|
|
13
13
|
|
|
14
|
+
interface ScheduleWaiter {
|
|
15
|
+
readonly count: number;
|
|
16
|
+
readonly resolve: () => void;
|
|
17
|
+
}
|
|
18
|
+
|
|
14
19
|
/**
|
|
15
20
|
* Deterministic TimerProvider for tests: timers fire only through advanceBy(),
|
|
16
21
|
* and waitForTimer(delayMs) resolves once a timer with exactly that delay is
|
|
@@ -20,6 +25,7 @@ export class ControlledClock implements TimerProvider {
|
|
|
20
25
|
private readonly timers: ControlledTimer[] = [];
|
|
21
26
|
private currentTime = 0;
|
|
22
27
|
private readonly timerWaiters = new Set<TimerWaiter>();
|
|
28
|
+
private readonly scheduleWaiters = new Set<ScheduleWaiter>();
|
|
23
29
|
readonly scheduledDelays: number[] = [];
|
|
24
30
|
|
|
25
31
|
readonly now = (): number => this.currentTime;
|
|
@@ -33,6 +39,12 @@ export class ControlledClock implements TimerProvider {
|
|
|
33
39
|
waiter.resolve();
|
|
34
40
|
}
|
|
35
41
|
}
|
|
42
|
+
for (const waiter of this.scheduleWaiters) {
|
|
43
|
+
if (this.scheduledDelays.length >= waiter.count) {
|
|
44
|
+
this.scheduleWaiters.delete(waiter);
|
|
45
|
+
waiter.resolve();
|
|
46
|
+
}
|
|
47
|
+
}
|
|
36
48
|
return timer as unknown as ReturnType<typeof setTimeout>;
|
|
37
49
|
};
|
|
38
50
|
readonly clearTimeout = (handle: ReturnType<typeof setTimeout>): void => {
|
|
@@ -49,6 +61,23 @@ export class ControlledClock implements TimerProvider {
|
|
|
49
61
|
});
|
|
50
62
|
}
|
|
51
63
|
|
|
64
|
+
/**
|
|
65
|
+
* Resolves once this clock has been asked to schedule `count` timers in total.
|
|
66
|
+
*
|
|
67
|
+
* Timer DELAYS are ambiguous whenever the code under test derives several budgets from the same
|
|
68
|
+
* remaining window (an LSP request timeout and the push-fallback wait are both "whatever is left
|
|
69
|
+
* of the freshness window"). The schedule ORDER is not ambiguous: a step that only runs after an
|
|
70
|
+
* earlier request settled can only arm its timer once that request's own timer was cleared. So a
|
|
71
|
+
* test that must fire the LATER timer waits for the later schedule instead of a delay value, and
|
|
72
|
+
* never races the earlier one.
|
|
73
|
+
*/
|
|
74
|
+
waitForScheduled(count: number): Promise<void> {
|
|
75
|
+
if (this.scheduledDelays.length >= count) return Promise.resolve();
|
|
76
|
+
return new Promise((resolve) => {
|
|
77
|
+
this.scheduleWaiters.add({ count, resolve });
|
|
78
|
+
});
|
|
79
|
+
}
|
|
80
|
+
|
|
52
81
|
advanceBy(delayMs: number): void {
|
|
53
82
|
this.currentTime += delayMs;
|
|
54
83
|
for (;;) {
|
|
@@ -235,6 +235,11 @@ export class WorkspaceDocumentState {
|
|
|
235
235
|
waitForDiagnosticsActivity(snapshot: DiagnosticSnapshot, timeoutMs: number): Promise<void> {
|
|
236
236
|
const state = this.openByUri.get(normalizeDocumentUri(snapshot.uri));
|
|
237
237
|
if (!state || timeoutMs <= 0) return Promise.resolve();
|
|
238
|
+
// A publish that landed between the caller's snapshot and this registration already IS the
|
|
239
|
+
// activity being waited for, and its notifyWaiters ran before this waiter existed. Without
|
|
240
|
+
// this check that wake-up is lost and the wait can only end at the freshness deadline, which
|
|
241
|
+
// turns the deadline from a fallback into the poll interval the result depends on (#8323).
|
|
242
|
+
if (state.publishGeneration !== snapshot.publishGeneration) return Promise.resolve();
|
|
238
243
|
return new Promise((resolveActivity) => {
|
|
239
244
|
let settled = false;
|
|
240
245
|
const finish = () => {
|
|
@@ -1770,6 +1770,8 @@ class WorkspaceDocumentState {
|
|
|
1770
1770
|
const state = this.openByUri.get(normalizeDocumentUri(snapshot.uri));
|
|
1771
1771
|
if (!state || timeoutMs <= 0)
|
|
1772
1772
|
return Promise.resolve();
|
|
1773
|
+
if (state.publishGeneration !== snapshot.publishGeneration)
|
|
1774
|
+
return Promise.resolve();
|
|
1773
1775
|
return new Promise((resolveActivity) => {
|
|
1774
1776
|
let settled = false;
|
|
1775
1777
|
const finish = () => {
|
|
@@ -2428,6 +2428,8 @@ class WorkspaceDocumentState {
|
|
|
2428
2428
|
const state = this.openByUri.get(normalizeDocumentUri(snapshot.uri));
|
|
2429
2429
|
if (!state || timeoutMs <= 0)
|
|
2430
2430
|
return Promise.resolve();
|
|
2431
|
+
if (state.publishGeneration !== snapshot.publishGeneration)
|
|
2432
|
+
return Promise.resolve();
|
|
2431
2433
|
return new Promise((resolveActivity) => {
|
|
2432
2434
|
let settled = false;
|
|
2433
2435
|
const finish = () => {
|
|
@@ -1277,6 +1277,8 @@ class WorkspaceDocumentState {
|
|
|
1277
1277
|
const state = this.openByUri.get(normalizeDocumentUri(snapshot.uri));
|
|
1278
1278
|
if (!state || timeoutMs <= 0)
|
|
1279
1279
|
return Promise.resolve();
|
|
1280
|
+
if (state.publishGeneration !== snapshot.publishGeneration)
|
|
1281
|
+
return Promise.resolve();
|
|
1280
1282
|
return new Promise((resolveActivity) => {
|
|
1281
1283
|
let settled = false;
|
|
1282
1284
|
const finish = () => {
|
|
@@ -1282,6 +1282,8 @@ class WorkspaceDocumentState {
|
|
|
1282
1282
|
const state = this.openByUri.get(normalizeDocumentUri(snapshot.uri));
|
|
1283
1283
|
if (!state || timeoutMs <= 0)
|
|
1284
1284
|
return Promise.resolve();
|
|
1285
|
+
if (state.publishGeneration !== snapshot.publishGeneration)
|
|
1286
|
+
return Promise.resolve();
|
|
1285
1287
|
return new Promise((resolveActivity) => {
|
|
1286
1288
|
let settled = false;
|
|
1287
1289
|
const finish = () => {
|
|
@@ -1277,6 +1277,8 @@ class WorkspaceDocumentState {
|
|
|
1277
1277
|
const state = this.openByUri.get(normalizeDocumentUri(snapshot.uri));
|
|
1278
1278
|
if (!state || timeoutMs <= 0)
|
|
1279
1279
|
return Promise.resolve();
|
|
1280
|
+
if (state.publishGeneration !== snapshot.publishGeneration)
|
|
1281
|
+
return Promise.resolve();
|
|
1280
1282
|
return new Promise((resolveActivity) => {
|
|
1281
1283
|
let settled = false;
|
|
1282
1284
|
const finish = () => {
|
|
@@ -1771,6 +1771,8 @@ class WorkspaceDocumentState {
|
|
|
1771
1771
|
const state = this.openByUri.get(normalizeDocumentUri(snapshot.uri));
|
|
1772
1772
|
if (!state || timeoutMs <= 0)
|
|
1773
1773
|
return Promise.resolve();
|
|
1774
|
+
if (state.publishGeneration !== snapshot.publishGeneration)
|
|
1775
|
+
return Promise.resolve();
|
|
1774
1776
|
return new Promise((resolveActivity) => {
|
|
1775
1777
|
let settled = false;
|
|
1776
1778
|
const finish = () => {
|
|
@@ -1459,6 +1459,8 @@ class WorkspaceDocumentState {
|
|
|
1459
1459
|
const state = this.openByUri.get(normalizeDocumentUri(snapshot.uri));
|
|
1460
1460
|
if (!state || timeoutMs <= 0)
|
|
1461
1461
|
return Promise.resolve();
|
|
1462
|
+
if (state.publishGeneration !== snapshot.publishGeneration)
|
|
1463
|
+
return Promise.resolve();
|
|
1462
1464
|
return new Promise((resolveActivity) => {
|
|
1463
1465
|
let settled = false;
|
|
1464
1466
|
const finish = () => {
|
|
@@ -8,7 +8,7 @@
|
|
|
8
8
|
"command": "node \"${PLUGIN_ROOT}/components/bootstrap/dist/cli.js\" hook session-start",
|
|
9
9
|
"commandWindows": "powershell -NoProfile -ExecutionPolicy Bypass -File \"${PLUGIN_ROOT}\\components\\bootstrap\\scripts\\bootstrap.ps1\"",
|
|
10
10
|
"timeout": 30,
|
|
11
|
-
"statusMessage": "(OmO 5.0.0-beta.
|
|
11
|
+
"statusMessage": "(OmO 5.0.0-beta.68) Checking Bootstrap Provisioning"
|
|
12
12
|
}
|
|
13
13
|
]
|
|
14
14
|
}
|
|
@@ -1,6 +1,6 @@
|
|
|
1
1
|
{
|
|
2
2
|
"name": "@sisyphuslabs/codex-bootstrap",
|
|
3
|
-
"version": "5.0.0-beta.
|
|
3
|
+
"version": "5.0.0-beta.68",
|
|
4
4
|
"description": "Codex SessionStart bootstrap component that provisions LazyCodex runtime dependencies from a detached worker.",
|
|
5
5
|
"type": "module",
|
|
6
6
|
"private": true,
|
|
@@ -8,7 +8,7 @@
|
|
|
8
8
|
"type": "command",
|
|
9
9
|
"command": "node \"${PLUGIN_ROOT}/dist/cli.js\" hook pre-tool-use",
|
|
10
10
|
"timeout": 5,
|
|
11
|
-
"statusMessage": "(OmO 5.0.0-beta.
|
|
11
|
+
"statusMessage": "(OmO 5.0.0-beta.68) Recommending Git Bash MCP"
|
|
12
12
|
}
|
|
13
13
|
]
|
|
14
14
|
}
|
|
@@ -20,7 +20,7 @@
|
|
|
20
20
|
"type": "command",
|
|
21
21
|
"command": "node \"${PLUGIN_ROOT}/dist/cli.js\" hook post-compact",
|
|
22
22
|
"timeout": 5,
|
|
23
|
-
"statusMessage": "(OmO 5.0.0-beta.
|
|
23
|
+
"statusMessage": "(OmO 5.0.0-beta.68) Resetting Git Bash MCP Reminder"
|
|
24
24
|
}
|
|
25
25
|
]
|
|
26
26
|
}
|
|
@@ -8,7 +8,7 @@
|
|
|
8
8
|
"type": "command",
|
|
9
9
|
"command": "node \"${PLUGIN_ROOT}/components/lazycodex-executor-verify/dist/cli.js\" hook subagent-stop",
|
|
10
10
|
"timeout": 10,
|
|
11
|
-
"statusMessage": "(OmO 5.0.0-beta.
|
|
11
|
+
"statusMessage": "(OmO 5.0.0-beta.68) Verifying LazyCodex Executor Evidence"
|
|
12
12
|
}
|
|
13
13
|
]
|
|
14
14
|
}
|
|
@@ -1,6 +1,6 @@
|
|
|
1
1
|
{
|
|
2
2
|
"name": "@code-yeongyu/codex-lazycodex-executor-verify",
|
|
3
|
-
"version": "5.0.0-beta.
|
|
3
|
+
"version": "5.0.0-beta.68",
|
|
4
4
|
"description": "Codex SubagentStop evidence verifier for LazyCodex executor completions.",
|
|
5
5
|
"type": "module",
|
|
6
6
|
"packageManager": "npm@11.12.1",
|