oh-my-opencode 5.0.0-beta.33 → 5.0.0-beta.35
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/skills/codex-qa/scripts/lsp-e2e.sh +1 -3
- package/.agents/skills/opencode-qa/scripts/lsp-e2e.sh +1 -1
- package/.agents/skills/tech-debt-audit/SKILL.md +6 -76
- package/README.ja.md +1 -1
- package/README.ko.md +1 -1
- package/README.md +1 -1
- package/README.ru.md +1 -1
- package/README.zh-cn.md +1 -1
- package/THIRD-PARTY-NOTICES.md +27 -99
- package/dist/cli/index.js +48350 -48559
- package/dist/cli-node/index.js +48480 -48689
- package/dist/config/index.d.ts +1 -1
- package/dist/config/schema/hooks.d.ts +0 -1
- package/dist/config/schema/oh-my-opencode-config.d.ts +0 -10
- package/dist/config/schema.d.ts +0 -1
- package/dist/create-hooks.d.ts +0 -1
- package/dist/hooks/index.d.ts +0 -1
- package/dist/index.js +11675 -13742
- package/dist/mcp/index.d.ts +0 -4
- package/dist/mcp/types.d.ts +0 -1
- package/dist/oh-my-opencode.schema.json +1 -45
- package/dist/plugin/hooks/create-core-hooks.d.ts +0 -1
- package/dist/plugin/hooks/create-session-hooks.d.ts +1 -2
- package/dist/shared/omo-process-sweep.d.ts +2 -4
- package/dist/skills/init-deep/SKILL.md +13 -13
- package/dist/skills/ulw-plan/SKILL.md +0 -1
- package/dist/tui.js +44809 -44910
- package/package.json +16 -18
- package/packages/omo-codex/THIRD-PARTY-NOTICES.md +0 -17
- package/packages/omo-codex/plugin/.codex-plugin/plugin.json +1 -3
- package/packages/omo-codex/plugin/.mcp.json +0 -6
- package/packages/omo-codex/plugin/AGENTS.md +5 -5
- package/packages/omo-codex/plugin/README.md +1 -1
- package/packages/omo-codex/plugin/components/bootstrap/dist/cli.js +1 -15
- 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/lcx/skills/lcx-doctor/SKILL.md +1 -1
- package/packages/omo-codex/plugin/components/lsp/dist/.omo-runtime-manifest.json +2 -2
- 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/teammode/test/thread-title-hook.test.ts +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/dist/cli.js +2 -2
- 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/ultrawork/skills/ulw-plan/SKILL.md +0 -1
- package/packages/omo-codex/plugin/components/ultrawork/src/directive-content.ts +1 -1
- package/packages/omo-codex/plugin/components/ulw-execute-continuation/hooks/hooks.json +2 -2
- package/packages/omo-codex/plugin/components/ulw-execute-continuation/package.json +1 -1
- package/packages/omo-codex/plugin/components/ulw-loop/README.md +11 -1
- package/packages/omo-codex/plugin/components/ulw-loop/directive.md +2 -2
- package/packages/omo-codex/plugin/components/ulw-loop/dist/checkpoint-codex-validation.d.ts +12 -0
- package/packages/omo-codex/plugin/components/ulw-loop/dist/checkpoint-codex-validation.js +45 -0
- package/packages/omo-codex/plugin/components/ulw-loop/dist/checkpoint-reconciliation.d.ts +1 -0
- package/packages/omo-codex/plugin/components/ulw-loop/dist/checkpoint-reconciliation.js +5 -0
- package/packages/omo-codex/plugin/components/ulw-loop/dist/checkpoint-template.js +10 -3
- package/packages/omo-codex/plugin/components/ulw-loop/dist/checkpoint.js +35 -38
- package/packages/omo-codex/plugin/components/ulw-loop/dist/cli.js +278 -193
- package/packages/omo-codex/plugin/components/ulw-loop/dist/quality-gate-aggregate.d.ts +5 -0
- package/packages/omo-codex/plugin/components/ulw-loop/dist/quality-gate-aggregate.js +7 -51
- package/packages/omo-codex/plugin/components/ulw-loop/dist/quality-gate-artifacts.js +39 -22
- package/packages/omo-codex/plugin/components/ulw-loop/dist/quality-gate-fields.d.ts +13 -1
- package/packages/omo-codex/plugin/components/ulw-loop/dist/quality-gate-fields.js +64 -8
- package/packages/omo-codex/plugin/components/ulw-loop/dist/quality-gate-verdicts.js +5 -1
- package/packages/omo-codex/plugin/components/ulw-loop/dist/quality-gate.js +37 -18
- package/packages/omo-codex/plugin/components/ulw-loop/hooks/hooks.json +4 -4
- package/packages/omo-codex/plugin/components/ulw-loop/package.json +1 -1
- package/packages/omo-codex/plugin/components/ulw-loop/skills/ulw-loop/references/full-workflow.md +2 -1
- package/packages/omo-codex/plugin/components/ulw-loop/src/checkpoint-codex-validation.ts +81 -0
- package/packages/omo-codex/plugin/components/ulw-loop/src/checkpoint-reconciliation.ts +6 -0
- package/packages/omo-codex/plugin/components/ulw-loop/src/checkpoint-template.ts +10 -3
- package/packages/omo-codex/plugin/components/ulw-loop/src/checkpoint.ts +32 -63
- package/packages/omo-codex/plugin/components/ulw-loop/src/quality-gate-aggregate.ts +7 -53
- package/packages/omo-codex/plugin/components/ulw-loop/src/quality-gate-artifacts.ts +50 -31
- package/packages/omo-codex/plugin/components/ulw-loop/src/quality-gate-fields.ts +67 -14
- package/packages/omo-codex/plugin/components/ulw-loop/src/quality-gate-verdicts.ts +6 -1
- package/packages/omo-codex/plugin/components/ulw-loop/src/quality-gate.ts +36 -17
- package/packages/omo-codex/plugin/components/ulw-loop/test/checkpoint-final.test.ts +26 -0
- package/packages/omo-codex/plugin/components/ulw-loop/test/checkpoint-template.test.ts +47 -2
- package/packages/omo-codex/plugin/components/ulw-loop/test/quality-gate-aggregate-basics.test.ts +258 -0
- package/packages/omo-codex/plugin/components/ulw-loop/test/quality-gate-cap-and-dedupe.test.ts +22 -0
- package/packages/omo-codex/plugin/components/ulw-loop/test/quality-gate-poisoning-cascades.test.ts +97 -0
- package/packages/omo-codex/plugin/components/ulw-loop/test/quality-gate-single-report.test.ts +241 -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/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-checking-ulw-execute-continuation.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 -146
- package/packages/omo-codex/plugin/package.json +1 -2
- package/packages/omo-codex/plugin/scripts/AGENTS.md +0 -1
- package/packages/omo-codex/plugin/scripts/auto-update-plan.mjs +0 -1
- package/packages/omo-codex/plugin/scripts/auto-update.mjs +0 -9
- package/packages/omo-codex/plugin/scripts/canonical-ultrawork-directive.mjs +17 -0
- package/packages/omo-codex/plugin/scripts/hook-status-message.mjs +0 -1
- package/packages/omo-codex/plugin/scripts/sync-skills.mjs +2 -8
- package/packages/omo-codex/plugin/shared/src/config-loader.ts +2 -102
- package/packages/omo-codex/plugin/shared/src/config-migration.ts +0 -1
- package/packages/omo-codex/plugin/shared/test/config-loader.test.ts +41 -130
- package/packages/omo-codex/plugin/skills/init-deep/SKILL.md +13 -13
- package/packages/omo-codex/plugin/skills/lcx-doctor/SKILL.md +1 -1
- package/packages/omo-codex/plugin/skills/ultrawork/SKILL.md +2 -2
- package/packages/omo-codex/plugin/skills/ulw-loop/references/full-workflow.md +2 -1
- package/packages/omo-codex/plugin/skills/ulw-plan/SKILL.md +0 -1
- package/packages/omo-codex/plugin/test/AGENTS.md +2 -2
- package/packages/omo-codex/plugin/test/aggregate-hooks.test.mjs +2 -21
- package/packages/omo-codex/plugin/test/aggregate-manifest.test.mjs +1 -2
- package/packages/omo-codex/plugin/test/aggregate-mcp.test.mjs +2 -7
- package/packages/omo-codex/plugin/test/auto-update.test.mjs +0 -25
- package/packages/omo-codex/plugin/test/bootstrap-setup.test.mjs +0 -31
- package/packages/omo-codex/plugin/test/canonical-ultrawork-directive.test.mjs +53 -0
- package/packages/omo-codex/plugin/test/component-bundled-cli.test.mjs +0 -50
- package/packages/omo-codex/plugin/test/hook-status-message.test.mjs +0 -1
- package/packages/omo-codex/plugin/test/mcp-research-servers.test.mjs +1 -3
- package/packages/omo-codex/scripts/install-cache-copy.test.mjs +27 -1
- package/packages/omo-codex/scripts/install-config-git-bash.test.mjs +0 -23
- package/packages/omo-codex/scripts/install-dist/install-local.mjs +238 -431
- package/packages/omo-codex/scripts/install-git-bash-mcp-env.test.mjs +1 -25
- package/packages/omo-codex/scripts/install-mcp-runtime.test.mjs +0 -36
- package/packages/shared-skills/skills/init-deep/SKILL.md +13 -13
- package/packages/shared-skills/skills/ulw-plan/SKILL.md +0 -1
- package/dist/config/schema/codegraph.d.ts +0 -12
- package/dist/hooks/codegraph-bootstrap/command-runner.d.ts +0 -17
- package/dist/hooks/codegraph-bootstrap/hook.d.ts +0 -35
- package/dist/hooks/codegraph-bootstrap/index.d.ts +0 -1
- package/dist/hooks/codegraph-bootstrap/project-root.d.ts +0 -1
- package/dist/hooks/codegraph-bootstrap/status.d.ts +0 -11
- package/dist/mcp/codegraph.d.ts +0 -16
- package/packages/omo-codex/plugin/components/codegraph/AGENTS.md +0 -58
- package/packages/omo-codex/plugin/components/codegraph/LICENSE +0 -21
- package/packages/omo-codex/plugin/components/codegraph/NODE-RUNTIME-LICENSES.md +0 -2951
- package/packages/omo-codex/plugin/components/codegraph/NOTICE +0 -16
- package/packages/omo-codex/plugin/components/codegraph/dist/cli.js +0 -12326
- package/packages/omo-codex/plugin/components/codegraph/dist/serve.js +0 -9908
- package/packages/omo-codex/plugin/components/codegraph/package.json +0 -33
- package/packages/omo-codex/plugin/components/codegraph/src/cache-gc.ts +0 -29
- package/packages/omo-codex/plugin/components/codegraph/src/cli.ts +0 -79
- package/packages/omo-codex/plugin/components/codegraph/src/hook-input.ts +0 -33
- package/packages/omo-codex/plugin/components/codegraph/src/hook-sweep.ts +0 -25
- package/packages/omo-codex/plugin/components/codegraph/src/hook-types.ts +0 -131
- package/packages/omo-codex/plugin/components/codegraph/src/hook.ts +0 -258
- package/packages/omo-codex/plugin/components/codegraph/src/mcp-bridge.ts +0 -310
- package/packages/omo-codex/plugin/components/codegraph/src/mcp-unavailable.ts +0 -92
- package/packages/omo-codex/plugin/components/codegraph/src/post-tool-use-hook.ts +0 -34
- package/packages/omo-codex/plugin/components/codegraph/src/serve-invocation.ts +0 -29
- package/packages/omo-codex/plugin/components/codegraph/src/serve.ts +0 -263
- package/packages/omo-codex/plugin/components/codegraph/src/session-start-command.ts +0 -106
- package/packages/omo-codex/plugin/components/codegraph/src/session-start-cooldown.ts +0 -145
- package/packages/omo-codex/plugin/components/codegraph/src/session-start-hook-runtime.ts +0 -22
- package/packages/omo-codex/plugin/components/codegraph/src/session-start-lock.ts +0 -139
- package/packages/omo-codex/plugin/components/codegraph/src/session-start-outcome.ts +0 -15
- package/packages/omo-codex/plugin/components/codegraph/src/session-start-paths.ts +0 -32
- package/packages/omo-codex/plugin/components/codegraph/src/session-start-project.ts +0 -109
- package/packages/omo-codex/plugin/components/codegraph/src/session-start-worker-result.ts +0 -148
- package/packages/omo-codex/plugin/components/codegraph/src/session-start-worker.ts +0 -175
- package/packages/omo-codex/plugin/components/codegraph/src/sweep-cli.ts +0 -81
- package/packages/omo-codex/plugin/components/codegraph/test/cache-gc.test.ts +0 -34
- package/packages/omo-codex/plugin/components/codegraph/test/hook-exclusion.test.ts +0 -112
- package/packages/omo-codex/plugin/components/codegraph/test/hook-registration.test.ts +0 -26
- package/packages/omo-codex/plugin/components/codegraph/test/hook-session-start-guard.test.ts +0 -160
- package/packages/omo-codex/plugin/components/codegraph/test/hook-store-upgrade.test.ts +0 -50
- package/packages/omo-codex/plugin/components/codegraph/test/hook-sweep.test.ts +0 -29
- package/packages/omo-codex/plugin/components/codegraph/test/hook.test.ts +0 -320
- package/packages/omo-codex/plugin/components/codegraph/test/mcp-bridge-fixtures.ts +0 -172
- package/packages/omo-codex/plugin/components/codegraph/test/package-runtime.test.ts +0 -91
- package/packages/omo-codex/plugin/components/codegraph/test/provisioned-node-guard.test.ts +0 -100
- package/packages/omo-codex/plugin/components/codegraph/test/serve-built-wrapper.test.ts +0 -76
- package/packages/omo-codex/plugin/components/codegraph/test/serve-mcp-bridge-lifecycle.test.ts +0 -133
- package/packages/omo-codex/plugin/components/codegraph/test/serve-mcp-bridge.test.ts +0 -245
- package/packages/omo-codex/plugin/components/codegraph/test/serve-mcp-facade.test.ts +0 -69
- package/packages/omo-codex/plugin/components/codegraph/test/serve-node-support.test.ts +0 -43
- package/packages/omo-codex/plugin/components/codegraph/test/serve-provision.test.ts +0 -147
- package/packages/omo-codex/plugin/components/codegraph/test/serve-unavailable-idle.test.ts +0 -47
- package/packages/omo-codex/plugin/components/codegraph/test/serve-unavailable.test.ts +0 -175
- package/packages/omo-codex/plugin/components/codegraph/test/serve.test.ts +0 -385
- package/packages/omo-codex/plugin/components/codegraph/test/session-start-node-support.test.ts +0 -206
- package/packages/omo-codex/plugin/components/codegraph/test/session-start-project.test.ts +0 -58
- package/packages/omo-codex/plugin/components/codegraph/test/session-start-state.test.ts +0 -104
- package/packages/omo-codex/plugin/components/codegraph/test/session-start-trust-boundary.test.ts +0 -65
- package/packages/omo-codex/plugin/components/codegraph/test/session-start-worker-availability.test.ts +0 -106
- package/packages/omo-codex/plugin/components/codegraph/test/session-start-worker-cooldown.test.ts +0 -116
- package/packages/omo-codex/plugin/components/codegraph/test/session-start-worker-flow.test.ts +0 -258
- package/packages/omo-codex/plugin/components/codegraph/test/sweep-cli.test.ts +0 -56
- package/packages/omo-codex/plugin/components/codegraph/tsconfig.build.json +0 -13
- package/packages/omo-codex/plugin/components/codegraph/tsconfig.json +0 -25
- package/packages/omo-codex/plugin/components/ulw-loop/test/quality-gate-aggregate.test.ts +0 -101
- package/packages/omo-codex/plugin/hooks/post-tool-use-checking-codegraph-init-guidance.json +0 -18
- package/packages/omo-codex/plugin/hooks/session-start-checking-codegraph-bootstrap.json +0 -17
- package/packages/omo-codex/plugin/scripts/migrate-omo-sot/editor.mjs +0 -125
- package/packages/omo-codex/plugin/scripts/migrate-omo-sot/jsonc.mjs +0 -43
- package/packages/omo-codex/plugin/scripts/migrate-omo-sot/scaffold.mjs +0 -29
- package/packages/omo-codex/plugin/scripts/migrate-omo-sot.mjs +0 -121
- package/packages/omo-codex/plugin/test/component-codegraph-mcp-smoke.test.mjs +0 -76
- package/packages/omo-codex/plugin/test/migrate-omo-sot.test.mjs +0 -179
|
@@ -78,9 +78,9 @@ describe("getCodexOmoConfig", () => {
|
|
|
78
78
|
writeOmoConfig(
|
|
79
79
|
homeDir,
|
|
80
80
|
JSON.stringify({
|
|
81
|
-
|
|
82
|
-
"[codex]": {
|
|
83
|
-
"[opencode]": {
|
|
81
|
+
telemetry: { enabled: true },
|
|
82
|
+
"[codex]": { telemetry: { enabled: false } },
|
|
83
|
+
"[opencode]": { telemetry: { enabled: true } },
|
|
84
84
|
}),
|
|
85
85
|
)
|
|
86
86
|
|
|
@@ -88,120 +88,36 @@ describe("getCodexOmoConfig", () => {
|
|
|
88
88
|
const result = getCodexOmoConfig({ cwd, homeDir, env: {} })
|
|
89
89
|
|
|
90
90
|
// then
|
|
91
|
-
expect(result.
|
|
92
|
-
auto_provision: true,
|
|
93
|
-
daemon: true,
|
|
94
|
-
enabled: false,
|
|
95
|
-
install_dir: "/base",
|
|
96
|
-
telemetry: false,
|
|
97
|
-
})
|
|
98
|
-
expect(result.trustedCodegraphInstallDir).toBe("/base")
|
|
99
|
-
})
|
|
100
|
-
|
|
101
|
-
it("#given project SOT sets install_dir #when loading config #then only the effective value changes while trusted install root stays global", () => {
|
|
102
|
-
// given
|
|
103
|
-
const homeDir = createTemporaryDirectory("omo-codex-shared-trusted-home-")
|
|
104
|
-
const cwd = createTemporaryDirectory("omo-codex-shared-trusted-project-")
|
|
105
|
-
writeOmoConfig(homeDir, JSON.stringify({ codegraph: { enabled: true, install_dir: "/global-codegraph" } }))
|
|
106
|
-
writeOmoConfig(cwd, JSON.stringify({ codegraph: { install_dir: "/project-codegraph" } }))
|
|
107
|
-
|
|
108
|
-
// when
|
|
109
|
-
const result = getCodexOmoConfig({ cwd, homeDir, env: {} })
|
|
110
|
-
|
|
111
|
-
// then
|
|
112
|
-
expect(result.codegraph?.install_dir).toBe("/project-codegraph")
|
|
113
|
-
expect(result.trustedCodegraphInstallDir).toBe("/global-codegraph")
|
|
114
|
-
})
|
|
115
|
-
|
|
116
|
-
it("#given codex SOT sets CodeGraph excluded roots #when loading config #then roots are returned to hooks", () => {
|
|
117
|
-
// given
|
|
118
|
-
const homeDir = createTemporaryDirectory("omo-codex-shared-excluded-home-")
|
|
119
|
-
const cwd = createTemporaryDirectory("omo-codex-shared-excluded-project-")
|
|
120
|
-
writeOmoConfig(
|
|
121
|
-
homeDir,
|
|
122
|
-
JSON.stringify({
|
|
123
|
-
"[codex]": { codegraph: { excluded_roots: ["/tmp/omo-research", "/private/tmp/omo-research"] } },
|
|
124
|
-
}),
|
|
125
|
-
)
|
|
126
|
-
|
|
127
|
-
// when
|
|
128
|
-
const result = getCodexOmoConfig({ cwd, homeDir, env: {} })
|
|
129
|
-
|
|
130
|
-
// then
|
|
131
|
-
expect(result.codegraph?.excluded_roots).toEqual(["/tmp/omo-research", "/private/tmp/omo-research"])
|
|
132
|
-
})
|
|
133
|
-
|
|
134
|
-
it("#given codex SOT sets the SessionStart cooldown #when loading config #then the configured base interval is returned", () => {
|
|
135
|
-
// given
|
|
136
|
-
const homeDir = createTemporaryDirectory("omo-codex-shared-cooldown-home-")
|
|
137
|
-
const cwd = createTemporaryDirectory("omo-codex-shared-cooldown-project-")
|
|
138
|
-
writeOmoConfig(homeDir, JSON.stringify({ "[codex]": { codegraph: { session_start_cooldown_ms: 900_000 } } }))
|
|
139
|
-
|
|
140
|
-
// when
|
|
141
|
-
const result = getCodexOmoConfig({ cwd, homeDir, env: {} })
|
|
142
|
-
|
|
143
|
-
// then
|
|
144
|
-
expect(result.codegraph?.session_start_cooldown_ms).toBe(900_000)
|
|
91
|
+
expect(result.telemetry?.enabled).toBe(false)
|
|
145
92
|
expect(result.warnings).toEqual([])
|
|
146
93
|
})
|
|
147
94
|
|
|
148
|
-
it("#given
|
|
95
|
+
it("#given a project SOT layer #when loading config #then the project value overrides the user layer", () => {
|
|
149
96
|
// given
|
|
150
|
-
const homeDir = createTemporaryDirectory("omo-codex-shared-
|
|
151
|
-
const cwd = createTemporaryDirectory("omo-codex-shared-
|
|
152
|
-
writeOmoConfig(homeDir, JSON.stringify({
|
|
97
|
+
const homeDir = createTemporaryDirectory("omo-codex-shared-project-home-")
|
|
98
|
+
const cwd = createTemporaryDirectory("omo-codex-shared-project-project-")
|
|
99
|
+
writeOmoConfig(homeDir, JSON.stringify({ task: { default_concurrency: 3 } }))
|
|
100
|
+
writeOmoConfig(cwd, JSON.stringify({ task: { default_concurrency: 7 } }))
|
|
153
101
|
|
|
154
102
|
// when
|
|
155
103
|
const result = getCodexOmoConfig({ cwd, homeDir, env: {} })
|
|
156
104
|
|
|
157
105
|
// then
|
|
158
|
-
expect(result.
|
|
159
|
-
expect(result.warnings).toEqual([])
|
|
106
|
+
expect(result.task?.default_concurrency).toBe(7)
|
|
160
107
|
})
|
|
161
108
|
|
|
162
|
-
it("#given codex SOT
|
|
109
|
+
it("#given a codex SOT setting with the wrong type #when loading config #then the value is rejected with a warning", () => {
|
|
163
110
|
// given
|
|
164
|
-
const homeDir = createTemporaryDirectory("omo-codex-shared-
|
|
165
|
-
const cwd = createTemporaryDirectory("omo-codex-shared-
|
|
166
|
-
writeOmoConfig(homeDir, JSON.stringify({ "[codex]": {
|
|
111
|
+
const homeDir = createTemporaryDirectory("omo-codex-shared-invalid-home-")
|
|
112
|
+
const cwd = createTemporaryDirectory("omo-codex-shared-invalid-project-")
|
|
113
|
+
writeOmoConfig(homeDir, JSON.stringify({ telemetry: { enabled: true }, "[codex]": { telemetry: { enabled: "yes" } } }))
|
|
167
114
|
|
|
168
115
|
// when
|
|
169
116
|
const result = getCodexOmoConfig({ cwd, homeDir, env: {} })
|
|
170
117
|
|
|
171
118
|
// then
|
|
172
|
-
expect(result.
|
|
173
|
-
expect(result.warnings).
|
|
174
|
-
})
|
|
175
|
-
|
|
176
|
-
it("#given codex SOT sets codegraph.daemon to a non-boolean #when loading config #then the value is rejected with a warning", () => {
|
|
177
|
-
// given
|
|
178
|
-
const homeDir = createTemporaryDirectory("omo-codex-shared-daemon-invalid-home-")
|
|
179
|
-
const cwd = createTemporaryDirectory("omo-codex-shared-daemon-invalid-project-")
|
|
180
|
-
writeOmoConfig(homeDir, JSON.stringify({ "[codex]": { codegraph: { daemon: "yes" } } }))
|
|
181
|
-
|
|
182
|
-
// when
|
|
183
|
-
const result = getCodexOmoConfig({ cwd, homeDir, env: {} })
|
|
184
|
-
|
|
185
|
-
// then
|
|
186
|
-
expect(result.codegraph?.daemon).toBe(true)
|
|
187
|
-
expect(result.warnings).toContain(`Invalid omo config at ${join(homeDir, ".omo", "omo.jsonc")}: [codex].codegraph.daemon`)
|
|
188
|
-
})
|
|
189
|
-
|
|
190
|
-
it("#given legacy env override and SOT value #when loading config #then env wins over the SOT", () => {
|
|
191
|
-
// given
|
|
192
|
-
const homeDir = createTemporaryDirectory("omo-codex-shared-env-")
|
|
193
|
-
const cwd = createTemporaryDirectory("omo-codex-project-env-")
|
|
194
|
-
writeOmoConfig(homeDir, JSON.stringify({ codegraph: { enabled: false } }))
|
|
195
|
-
|
|
196
|
-
// when
|
|
197
|
-
const result = getCodexOmoConfig({
|
|
198
|
-
cwd,
|
|
199
|
-
homeDir,
|
|
200
|
-
env: { CODEX_CODEGRAPH_ENABLED: "1" },
|
|
201
|
-
})
|
|
202
|
-
|
|
203
|
-
// then
|
|
204
|
-
expect(result.codegraph?.enabled).toBe(true)
|
|
119
|
+
expect(result.telemetry).toBeUndefined()
|
|
120
|
+
expect(result.warnings).toContain(`Invalid omo config at ${join(homeDir, ".omo", "omo.jsonc")}: [codex].telemetry.enabled`)
|
|
205
121
|
})
|
|
206
122
|
|
|
207
123
|
it("#given no SOT files #when loading config #then returns built-in defaults and missing global source", () => {
|
|
@@ -213,12 +129,8 @@ describe("getCodexOmoConfig", () => {
|
|
|
213
129
|
const result = getCodexOmoConfig({ cwd, homeDir, env: {} })
|
|
214
130
|
|
|
215
131
|
// then
|
|
216
|
-
expect(result.
|
|
217
|
-
|
|
218
|
-
daemon: true,
|
|
219
|
-
enabled: true,
|
|
220
|
-
telemetry: false,
|
|
221
|
-
})
|
|
132
|
+
expect(result.telemetry).toBeUndefined()
|
|
133
|
+
expect(result.warnings).toEqual([])
|
|
222
134
|
expect(result.sources).toContainEqual({
|
|
223
135
|
exists: false,
|
|
224
136
|
loaded: false,
|
|
@@ -227,23 +139,10 @@ describe("getCodexOmoConfig", () => {
|
|
|
227
139
|
})
|
|
228
140
|
})
|
|
229
141
|
|
|
230
|
-
it("#given codex-unsupported codegraph setting #when loading config #then returns loader warnings", () => {
|
|
231
|
-
// given
|
|
232
|
-
const homeDir = createTemporaryDirectory("omo-codex-shared-warnings-")
|
|
233
|
-
const cwd = createTemporaryDirectory("omo-codex-project-warnings-")
|
|
234
|
-
writeOmoConfig(homeDir, JSON.stringify({ "[codex]": { codegraph: { watch_debounce_ms: 42 } } }))
|
|
235
|
-
|
|
236
|
-
// when
|
|
237
|
-
const result = getCodexOmoConfig({ cwd, homeDir, env: {} })
|
|
238
|
-
|
|
239
|
-
// then
|
|
240
|
-
expect(result.warnings).toContain("codegraph.watch_debounce_ms is not supported for harness codex")
|
|
241
|
-
})
|
|
242
|
-
|
|
243
142
|
it("#given only legacy config.jsonc #when codex starts #then migrates once with a backup before loading the unified codex view", () => {
|
|
244
143
|
// given
|
|
245
144
|
const homeDir = createTemporaryDirectory("omo-codex-legacy-upgrade-")
|
|
246
|
-
writeLegacyOmoConfig(homeDir, JSON.stringify({ "[codex]": {
|
|
145
|
+
writeLegacyOmoConfig(homeDir, JSON.stringify({ "[codex]": { telemetry: { enabled: false } } }))
|
|
247
146
|
const legacyPath = join(homeDir, ".omo", "config.jsonc")
|
|
248
147
|
|
|
249
148
|
// when
|
|
@@ -252,7 +151,7 @@ describe("getCodexOmoConfig", () => {
|
|
|
252
151
|
const second = getCodexOmoConfig({ cwd: homeDir, homeDir, env: {} })
|
|
253
152
|
|
|
254
153
|
// then
|
|
255
|
-
expect(first.
|
|
154
|
+
expect(first.telemetry?.enabled).toBe(false)
|
|
256
155
|
expect(first.warnings.some((warning) => warning.startsWith("omo-codex: migrated legacy configuration from ")
|
|
257
156
|
&& warning.endsWith("/.omo/config.jsonc"))).toBe(true)
|
|
258
157
|
expect(readOmoJson(homeDir)["_migrations"]).toEqual(["2026-07-codex-config-jsonc"])
|
|
@@ -266,8 +165,8 @@ describe("getCodexOmoConfig", () => {
|
|
|
266
165
|
it("#given a legacy migration conflict #when codex starts #then exposes the migration summary and conflict through loader warnings", () => {
|
|
267
166
|
// given
|
|
268
167
|
const homeDir = createTemporaryDirectory("omo-codex-legacy-conflict-")
|
|
269
|
-
writeOmoConfig(homeDir, JSON.stringify({
|
|
270
|
-
writeLegacyOmoConfig(homeDir, JSON.stringify({
|
|
168
|
+
writeOmoConfig(homeDir, JSON.stringify({ "[codex]": { telemetry: { enabled: true } } }))
|
|
169
|
+
writeLegacyOmoConfig(homeDir, JSON.stringify({ "[codex]": { telemetry: { enabled: false } } }))
|
|
271
170
|
|
|
272
171
|
// when
|
|
273
172
|
const result = getCodexOmoConfig({ cwd: homeDir, homeDir, env: {} })
|
|
@@ -275,7 +174,7 @@ describe("getCodexOmoConfig", () => {
|
|
|
275
174
|
// then
|
|
276
175
|
expect(result.warnings.some((warning) => warning.startsWith("omo-codex: migrated legacy configuration from ")
|
|
277
176
|
&& warning.endsWith("/.omo/config.jsonc"))).toBe(true)
|
|
278
|
-
expect(result.warnings).toContain("omo-codex: configuration migration: skipped:
|
|
177
|
+
expect(result.warnings).toContain("omo-codex: configuration migration: skipped: [codex].telemetry.enabled legacy=false kept=true")
|
|
279
178
|
})
|
|
280
179
|
|
|
281
180
|
it("#given overlapping [omo] and [senpi] blocks in legacy config #when Codex migrates #then the transform conflict is reported", () => {
|
|
@@ -310,7 +209,7 @@ describe("getCodexOmoConfig", () => {
|
|
|
310
209
|
it("#given codex starts before opencode #when both legacy source groups exist #then each distinct migration id is applied once", () => {
|
|
311
210
|
// given
|
|
312
211
|
const homeDir = createTemporaryDirectory("omo-codex-order-codex-first-")
|
|
313
|
-
writeLegacyOmoConfig(homeDir, JSON.stringify({ "[codex]": {
|
|
212
|
+
writeLegacyOmoConfig(homeDir, JSON.stringify({ "[codex]": { telemetry: { enabled: false } } }))
|
|
314
213
|
writeOpenCodeConfig(homeDir)
|
|
315
214
|
const openCodeSource = join(homeDir, ".config", "opencode", "oh-my-openagent.jsonc")
|
|
316
215
|
|
|
@@ -322,13 +221,17 @@ describe("getCodexOmoConfig", () => {
|
|
|
322
221
|
// then
|
|
323
222
|
expect(remainsAfterCodexStartup).toBe(true)
|
|
324
223
|
expect(existsSync(openCodeSource)).toBe(false)
|
|
325
|
-
expect(migrationIds(homeDir)).toEqual([
|
|
224
|
+
expect(migrationIds(homeDir)).toEqual([
|
|
225
|
+
"2026-07-codex-config-jsonc",
|
|
226
|
+
"2026-07-opencode-config-unification",
|
|
227
|
+
"2026-08-reasoning-unification",
|
|
228
|
+
])
|
|
326
229
|
})
|
|
327
230
|
|
|
328
231
|
it("#given opencode starts before codex #when both legacy source groups exist #then each distinct migration id is applied once", () => {
|
|
329
232
|
// given
|
|
330
233
|
const homeDir = createTemporaryDirectory("omo-codex-order-opencode-first-")
|
|
331
|
-
writeLegacyOmoConfig(homeDir, JSON.stringify({ "[codex]": {
|
|
234
|
+
writeLegacyOmoConfig(homeDir, JSON.stringify({ "[codex]": { telemetry: { enabled: false } } }))
|
|
332
235
|
writeOpenCodeConfig(homeDir)
|
|
333
236
|
|
|
334
237
|
// when
|
|
@@ -336,13 +239,17 @@ describe("getCodexOmoConfig", () => {
|
|
|
336
239
|
getCodexOmoConfig({ cwd: homeDir, homeDir, env: {} })
|
|
337
240
|
|
|
338
241
|
// then
|
|
339
|
-
expect(migrationIds(homeDir)).toEqual([
|
|
242
|
+
expect(migrationIds(homeDir)).toEqual([
|
|
243
|
+
"2026-07-opencode-config-unification",
|
|
244
|
+
"2026-07-codex-config-jsonc",
|
|
245
|
+
"2026-08-reasoning-unification",
|
|
246
|
+
])
|
|
340
247
|
})
|
|
341
248
|
|
|
342
249
|
it("#given concurrent codex and opencode starts #when opencode owns the shared lock #then both migration ids are applied exactly once", () => {
|
|
343
250
|
// given
|
|
344
251
|
const homeDir = createTemporaryDirectory("omo-codex-order-concurrent-")
|
|
345
|
-
writeLegacyOmoConfig(homeDir, JSON.stringify({ "[codex]": {
|
|
252
|
+
writeLegacyOmoConfig(homeDir, JSON.stringify({ "[codex]": { telemetry: { enabled: false } } }))
|
|
346
253
|
writeOpenCodeConfig(homeDir)
|
|
347
254
|
let codexResult: ReturnType<typeof runCodexStartupMigration> | undefined
|
|
348
255
|
|
|
@@ -355,6 +262,10 @@ describe("getCodexOmoConfig", () => {
|
|
|
355
262
|
// then
|
|
356
263
|
if (codexResult === undefined) throw new Error("Expected concurrent Codex migration attempt")
|
|
357
264
|
expect(codexResult.error).toBe("Configuration migration is already running")
|
|
358
|
-
expect(migrationIds(homeDir)).toEqual([
|
|
265
|
+
expect(migrationIds(homeDir)).toEqual([
|
|
266
|
+
"2026-07-opencode-config-unification",
|
|
267
|
+
"2026-07-codex-config-jsonc",
|
|
268
|
+
"2026-08-reasoning-unification",
|
|
269
|
+
])
|
|
359
270
|
})
|
|
360
271
|
})
|
|
@@ -42,7 +42,7 @@ Generate hierarchical AGENTS.md files. Root + complexity-scored subdirectories.
|
|
|
42
42
|
|
|
43
43
|
1. **Discovery + Analysis** (concurrent)
|
|
44
44
|
- Fire background explore agents immediately
|
|
45
|
-
- Main session: bash structure + LSP/
|
|
45
|
+
- Main session: bash structure + LSP/ast-grep code map + read existing AGENTS.md
|
|
46
46
|
2. **Score & Decide** - Determine AGENTS.md locations from merged findings
|
|
47
47
|
3. **Generate** - Root first, then subdirs in parallel
|
|
48
48
|
4. **Review** - Deduplicate, trim, validate
|
|
@@ -51,7 +51,7 @@ Generate hierarchical AGENTS.md files. Root + complexity-scored subdirectories.
|
|
|
51
51
|
**TodoWrite ALL phases. Mark in_progress → completed in real-time.**
|
|
52
52
|
```
|
|
53
53
|
TodoWrite([
|
|
54
|
-
{ id: "discovery", content: "Fire explore agents + LSP/
|
|
54
|
+
{ id: "discovery", content: "Fire explore agents + LSP/ast-grep map + read existing", status: "pending", priority: "high" },
|
|
55
55
|
{ id: "scoring", content: "Score directories, determine locations", status: "pending", priority: "high" },
|
|
56
56
|
{ id: "generate", content: "Generate AGENTS.md files (root + subdirs)", status: "pending", priority: "high" },
|
|
57
57
|
{ id: "review", content: "Deduplicate, validate, trim", status: "pending", priority: "medium" }
|
|
@@ -67,16 +67,16 @@ TodoWrite([
|
|
|
67
67
|
|
|
68
68
|
### Fire Background Explore Agents IMMEDIATELY
|
|
69
69
|
|
|
70
|
-
Don't wait-these run async while main session works. **
|
|
70
|
+
Don't wait-these run async while main session works. **Ground every agent in real symbol data**: any task touching structure, entry points, dependencies, or hotspots MUST query `lsp_symbols`/`lsp_find_references` and the ast-grep skill (`sg`) when present, and ground its claims in that data instead of guessing from conventions. Richer real context per agent = a more accurate project map.
|
|
71
71
|
|
|
72
72
|
```
|
|
73
73
|
// Fire all at once, collect results later
|
|
74
|
-
task(subagent_type="explore", load_skills=[], description="Explore project structure", run_in_background=true, prompt="Project structure: map real layout via
|
|
75
|
-
task(subagent_type="explore", load_skills=[], description="Find entry points", run_in_background=true, prompt="Entry points: FIND main files, trace reach via
|
|
74
|
+
task(subagent_type="explore", load_skills=[], description="Explore project structure", run_in_background=true, prompt="Project structure: map real layout via glob + lsp_symbols scope=workspace → REPORT deviations from standard patterns")
|
|
75
|
+
task(subagent_type="explore", load_skills=[], description="Find entry points", run_in_background=true, prompt="Entry points: FIND main files, trace reach via lsp_symbols + lsp_find_references → REPORT non-standard organization")
|
|
76
76
|
task(subagent_type="explore", load_skills=[], description="Find conventions", run_in_background=true, prompt="Conventions: FIND config files (.eslintrc, pyproject.toml, .editorconfig) → REPORT project-specific rules")
|
|
77
77
|
task(subagent_type="explore", load_skills=[], description="Find anti-patterns", run_in_background=true, prompt="Anti-patterns: FIND 'DO NOT', 'NEVER', 'ALWAYS', 'DEPRECATED' comments → LIST forbidden patterns")
|
|
78
78
|
task(subagent_type="explore", load_skills=[], description="Explore build/CI", run_in_background=true, prompt="Build/CI: FIND .github/workflows, Makefile → REPORT non-standard patterns")
|
|
79
|
-
task(subagent_type="explore", load_skills=[], description="Find test patterns", run_in_background=true, prompt="Test patterns: FIND test configs/structure;
|
|
79
|
+
task(subagent_type="explore", load_skills=[], description="Find test patterns", run_in_background=true, prompt="Test patterns: FIND test configs/structure; lsp_find_references on core modules to see what is covered → REPORT unique conventions")
|
|
80
80
|
```
|
|
81
81
|
|
|
82
82
|
<dynamic-agents>
|
|
@@ -138,7 +138,7 @@ For each existing file found:
|
|
|
138
138
|
|
|
139
139
|
If `--create-new`: Read all existing first (preserve context) → then delete all → regenerate.
|
|
140
140
|
|
|
141
|
-
#### 3. Code Map - drive LSP AND
|
|
141
|
+
#### 3. Code Map - drive LSP AND ast-grep (do NOT skip)
|
|
142
142
|
|
|
143
143
|
Highest-signal source for the CODE MAP and the Symbol/Export/Reference scoring rows. Complementary, not alternatives - run BOTH when present, alongside the explore agents.
|
|
144
144
|
|
|
@@ -147,10 +147,10 @@ Highest-signal source for the CODE MAP and the Symbol/Export/Reference scoring r
|
|
|
147
147
|
- `lsp_symbols` scope="workspace", query by kind (class/interface/function) -> symbol inventory.
|
|
148
148
|
- `lsp_find_references` on top exports (line/character from the symbols result) -> reference centrality.
|
|
149
149
|
|
|
150
|
-
**
|
|
151
|
-
- `
|
|
150
|
+
**ast-grep** - load the ast-grep skill; a first-class peer to LSP, NOT a last resort:
|
|
151
|
+
- `sg --pattern 'export $$$' --lang <lang>` -> export inventory; `sg --pattern 'import $$$ from "$MOD"'` -> dependency edges between modules for the scoring matrix.
|
|
152
152
|
|
|
153
|
-
Only if
|
|
153
|
+
Only if LSP is unavailable: explore agents + ast-grep alone, and mark reference centrality unmeasured in the CODE MAP.
|
|
154
154
|
|
|
155
155
|
### Collect Background Results
|
|
156
156
|
|
|
@@ -159,7 +159,7 @@ Only if NEITHER exists: explore agents + the ast-grep skill (`sg`), and mark cen
|
|
|
159
159
|
for each background task ID (`bg_...`): background_output(task_id="bg_...")
|
|
160
160
|
```
|
|
161
161
|
|
|
162
|
-
**Merge: bash + LSP/
|
|
162
|
+
**Merge: bash + LSP/ast-grep + existing + explore findings. Mark "discovery" as completed.**
|
|
163
163
|
|
|
164
164
|
---
|
|
165
165
|
|
|
@@ -235,7 +235,7 @@ NEVER use Write to overwrite an existing file. ALWAYS check existence first via
|
|
|
235
235
|
|------|----------|-------|
|
|
236
236
|
|
|
237
237
|
## CODE MAP
|
|
238
|
-
{From LSP/
|
|
238
|
+
{From LSP/ast-grep - skip only if neither exists or project <10 files}
|
|
239
239
|
|
|
240
240
|
| Symbol | Type | Location | Refs | Role |
|
|
241
241
|
|--------|------|----------|------|------|
|
|
@@ -318,7 +318,7 @@ Hierarchy:
|
|
|
318
318
|
## Anti-Patterns
|
|
319
319
|
|
|
320
320
|
- **Static agent count**: MUST vary agents based on project size/depth
|
|
321
|
-
- **Sequential execution**: MUST parallel (explore + LSP +
|
|
321
|
+
- **Sequential execution**: MUST parallel (explore + LSP + ast-grep concurrent)
|
|
322
322
|
- **Ignoring existing**: ALWAYS read existing first, even with --create-new
|
|
323
323
|
- **Over-documenting**: Not every dir needs AGENTS.md
|
|
324
324
|
- **Redundancy**: Child never repeats parent
|
|
@@ -70,7 +70,7 @@ sync_latest_source openai/codex "$LAZYCODEX_SOURCE_ROOT/openai-codex-source"
|
|
|
70
70
|
- `$CODEX_HOME/config.toml` exists and parses; LazyCodex-managed entries match what the latest installer would write.
|
|
71
71
|
- Plugin payload present and non-empty: read `.codex-plugin/plugin.json`; when that manifest declares a `hooks` array, validate every direct hook path declared by the manifest; require `hooks/hooks.json` only when the manifest declares it; do not require retired paths such as `components/workflow-selector` or `hooks/user-prompt-submit-selecting-lazycodex-workflow.json` unless the current manifest declares them.
|
|
72
72
|
- Verify the manifest-declared runtime payload, not a remembered source tree. Current payload includes `skills/`, `.mcp.json`, root CLI runtimes such as `dist/cli/index.js` and `dist/cli-node/index.js`, and every hook/MCP `components/*/dist/*.js` target referenced by installed manifests.
|
|
73
|
-
- Treat install-time materialization rewrites as expected when the rewritten target exists and is non-empty. For example, `.mcp.json` may use plugin-local or absolute installed paths for
|
|
73
|
+
- Treat install-time materialization rewrites as expected when the rewritten target exists and is non-empty. For example, `.mcp.json` may use plugin-local or absolute installed paths for MCP runtimes; that is PASS/WARN context, not payload drift. Missing or zero-byte rewritten targets are FAIL.
|
|
74
74
|
- Stale project-local leftovers the installer now removes (e.g. `.codex/hooks.json`, `.codex/skills` in the project) are flagged, not deleted.
|
|
75
75
|
4. Probe the real surface. Do not invoke `lazycodex doctor`; this skill is already running inside that doctor workflow, so calling it would recurse. Instead run non-recursive probes directly: `codex --version`, `command -v codex`, the bin-link checks above, config/plugin payload inspections, and a trivial non-interactive Codex invocation that loads the plugin. Use the configured Codex default model for the runtime probe unless the user explicitly passed a model override to the doctor surface; never force a guessed/rejected model such as `gpt-5.5-codex-mini`. Capture stderr verbatim; a clean exit with warnings is WARN, not PASS.
|
|
76
76
|
5. Compare for drift. Where installed manifest-declared bundled files differ from the same files at the installed version, or the latest source removed or renamed something the local config still references, record it with both paths. Do not report expected materialization differences, such as absolute `.mcp.json` runtime paths, as drift when their targets exist and are non-empty.
|
|
@@ -236,8 +236,8 @@ and utility functions to batch commands and reduce output. Keep direct calls
|
|
|
236
236
|
when one result chooses the next action, outputs are already small, semantic
|
|
237
237
|
judgment is required between calls, approval or side effects are involved,
|
|
238
238
|
or native artifacts / citations must be preserved.
|
|
239
|
-
- Architecture / flow / blast radius →
|
|
240
|
-
|
|
239
|
+
- Architecture / flow / blast radius → explore agents plus LSP references
|
|
240
|
+
and impact; do not guess from conventions.
|
|
241
241
|
- **SYMBOLS REQUIRE LSP** — definitions, references, rename impact,
|
|
242
242
|
workspace symbols, and diagnostics use the available `lsp_*` tools, not
|
|
243
243
|
text search. Run diagnostics after edits and treat errors as blocking.
|
|
@@ -190,6 +190,7 @@ omo-agent-toolkit ulw-loop record-evidence --goal-id <g> --criterion-id <c> --st
|
|
|
190
190
|
# Then use the harness update_goal tool with status complete.
|
|
191
191
|
omo-agent-toolkit ulw-loop checkpoint --goal-id <g> --print-template --json
|
|
192
192
|
# Fill the printed template: replace every placeholder and use real artifact paths under currentAttemptDir.
|
|
193
|
+
# codex-goal-json.goal.objective must equal the plan's codexObjective verbatim.
|
|
193
194
|
omo-agent-toolkit ulw-loop checkpoint --goal-id <g> --status complete --evidence "..." --codex-goal-json <path> --quality-gate-json <path>
|
|
194
195
|
omo-agent-toolkit ulw-loop complete-goals
|
|
195
196
|
```
|
|
@@ -214,7 +215,7 @@ omo-agent-toolkit ulw-loop checkpoint --goal-id <id> --status complete --evidenc
|
|
|
214
215
|
{
|
|
215
216
|
"codeReview":{"by":"lazycodex-code-reviewer","recommendation":"APPROVE","codeQualityStatus":"CLEAR","reportPath":"test/fixtures/artifacts/code-review.md","evidence":"Diff review passed.","blockers":[]},
|
|
216
217
|
"manualQa":{"by":"lazycodex-qa-executor","status":"passed","evidence":"CLI and data surfaces passed.","surfaceEvidence":[{"id":"surface-cli-pass","criterionRef":"C1","surface":"cli","invocation":"omo-agent-toolkit ulw-loop checkpoint --quality-gate-json sample-quality-gate.json --json","verdict":"passed","artifactRefs":["artifact-cli-pass"]},{"id":"surface-data-pass","criterionRef":"C2","surface":"data","invocation":"diff -u before-ledger.json after-ledger.json","verdict":"passed","artifactRefs":["artifact-data-diff"]}],"adversarialCases":[{"id":"adv-malformed-input","criterionRef":"C3","scenario":"malformed gate input omits manual QA evidence","expectedBehavior":"validator rejects ULW_LOOP_QUALITY_GATE_INVALID","verdict":"passed","artifactRefs":["artifact-cli-reject"]}],"artifactRefs":[{"id":"artifact-cli-pass","kind":"cli-transcript","description":"CLI pass artifact.","path":"test/fixtures/artifacts/cli-pass.txt"},{"id":"artifact-cli-reject","kind":"log","description":"Reject log artifact.","path":"test/fixtures/artifacts/rejection.txt"},{"id":"artifact-data-diff","kind":"data-diff","description":"Data diff artifact.","path":"test/fixtures/artifacts/data-diff.txt"}]},
|
|
217
|
-
"gateReview":{"by":"lazycodex-gate-reviewer","recommendation":"APPROVE","reportPath":"test/fixtures/artifacts/gate-review.md","evidence":"Gate review passed.","blockers":[]},
|
|
218
|
+
"gateReview":{"by":"lazycodex-gate-reviewer","recommendation":"APPROVE","reportPath":"test/fixtures/artifacts/gate-review.md","evidence":"Gate review passed.","blockers":[],"notes":[]},
|
|
218
219
|
"iteration":{"fullRerun":true,"status":"passed","rerunCommands":["bunx vitest run packages/omo-codex/plugin/components/ulw-loop/test/quality-gate-doc.test.ts"],"evidence":"Focused rerun passed."},
|
|
219
220
|
"criteriaCoverage":{"totalCriteria":3,"passCount":3,"originalIntent":"User wanted artifact-backed completion.","desiredOutcome":"Behavior ships with review and QA evidence.","userOutcomeReview":"Result matches brief and goals.","adversarialClassesCovered":["malformed_input","stale_state"]}
|
|
220
221
|
}
|
|
@@ -71,7 +71,6 @@ When producing the plan, encode every executable item as a column-zero Markdown
|
|
|
71
71
|
- **Decision-complete is the north star.** The executor has NO interview context - spell out exact paths, "every X in Y", and an explicit Must-NOT-Have. Leave the implementer ZERO judgment calls.
|
|
72
72
|
- **Full scope is the default.** Plan the ENTIRE request; "MVP", "v1", "phase 1", or any reduced subset is never an option you invent or ask about - it exists only if the user introduces it. Scope OUT / Must-NOT-Have entries are guardrails against unrequested additions, never reductions of the request.
|
|
73
73
|
- **Explore before asking.** Discoverable facts (repo/system/docs truth) -> research and cite, never ask. Preferences/tradeoffs -> the only things you bring to the user. When unsure which, treat it as a user-decision.
|
|
74
|
-
- **CodeGraph first when present.** Use `codegraph_explore` for repo how/where/what/flow questions before wider reads; if codegraph_* tools are absent, inactive/uninitialized, or cold-start unavailable, continue with Read/Grep/Glob/LSP and the ast-grep skill.
|
|
75
74
|
- **Two filters** on every candidate question, in order: (1) Could collected evidence answer it? -> explore instead. (2) Could the user's stated intent plus a defensible default answer it? -> adopt the default, record it, do not ask - UNLESS it is an owner-decision, which always survives as a question even when a default exists: anything irreversible / destructive / safety-critical, or a cross-cutting product choice the user lives with (public config surface, distribution / packaging, external dependency or pinned SHA, data / schema shape, real budget / paid-service spend, expected scale or capacity target, target-audience / compliance limits). Extrinsic constraints (budget, mandated stack, scale, audience) leave no repo evidence, so exploration can never surface them - sweep those axes explicitly once per plan and classify each as explored, defaulted (ledger), or asked. Default the reversible internals; surface the owner-decisions.
|
|
76
75
|
- **Explore to sufficiency, then STOP.** One research wave per open question; stop when the clearance check is answerable; never re-explore to double-check.
|
|
77
76
|
- **Parallel-dispatch** independent research in ONE turn and keep working while it runs. Subagent outputs are CLAIMS until you independently verify them.
|
|
@@ -23,10 +23,10 @@
|
|
|
23
23
|
| Aggregate wiring | `aggregate-{manifest,hooks,build,mcp,agents,model-catalog}.test.mjs` |
|
|
24
24
|
| Bootstrap | `bootstrap-{hooks,setup,binlinks,orchestration,ps-guard}.test.mjs` |
|
|
25
25
|
| Update flow | `auto-update{,-state-persistence,-restart-notice,-release-notes}.test.mjs` |
|
|
26
|
-
| Migration | `migrate-codex-config.test.mjs` (1,242 LOC — densest), `
|
|
26
|
+
| Migration | `migrate-codex-config.test.mjs` (1,242 LOC — densest), `multi-agent-v2-regression`, `subagent-limit-migration` |
|
|
27
27
|
| Skills sync | `sync-skills{,-codex-compatibility}.test.mjs`, `ulw-plan`/`ulw-research`/`ulw-loop` skill contracts |
|
|
28
28
|
| Teammode | `teammode-{transport,communication,worktree,safety,thread-links,thread-title,archive-ambiguity}.test.mjs` |
|
|
29
|
-
| Component CLIs | `component-{bundled-cli,bin-names
|
|
29
|
+
| Component CLIs | `component-{bundled-cli,bin-names}.test.mjs`, `lsp-prebuild-layouts` |
|
|
30
30
|
|
|
31
31
|
## CONVENTIONS
|
|
32
32
|
|
|
@@ -30,7 +30,6 @@ test("#given isolated components #when hooks are inspected #then commands stay i
|
|
|
30
30
|
const componentMarkers = [
|
|
31
31
|
"components/comment-checker/dist/cli.js",
|
|
32
32
|
"components/lsp/dist/cli.js",
|
|
33
|
-
"components/codegraph/dist/cli.js",
|
|
34
33
|
"components/rules/dist/cli.js",
|
|
35
34
|
"components/ulw-execute-continuation/dist/cli.js",
|
|
36
35
|
"components/telemetry/dist/cli.js",
|
|
@@ -220,34 +219,16 @@ test("#given aggregate SessionStart hooks #when inspected #then cold-start-prone
|
|
|
220
219
|
const coldStartHooks = sessionStartHooks.filter(
|
|
221
220
|
({ command }) =>
|
|
222
221
|
command.includes("components/telemetry/dist/cli.js") ||
|
|
223
|
-
command.includes("scripts/auto-update.mjs")
|
|
224
|
-
command.includes("components/codegraph/dist/cli.js"),
|
|
222
|
+
command.includes("scripts/auto-update.mjs"),
|
|
225
223
|
);
|
|
226
224
|
|
|
227
225
|
// then
|
|
228
|
-
assert.equal(coldStartHooks.length,
|
|
226
|
+
assert.equal(coldStartHooks.length, 2);
|
|
229
227
|
for (const hook of coldStartHooks) {
|
|
230
228
|
assert.equal(hook.timeout, 15, `${hook.source} must carry timeout 15 for cold-start headroom`);
|
|
231
229
|
}
|
|
232
230
|
});
|
|
233
231
|
|
|
234
|
-
test("#given aggregate PostToolUse hooks #when inspected #then CodeGraph init guidance is registered for CodeGraph tools", async () => {
|
|
235
|
-
// given
|
|
236
|
-
const commandHooks = await readAggregateCommandHooks();
|
|
237
|
-
|
|
238
|
-
// when
|
|
239
|
-
const codegraphPostToolUseHooks = commandHooks.filter(
|
|
240
|
-
(hook) =>
|
|
241
|
-
hook.eventName === "PostToolUse" &&
|
|
242
|
-
hook.handler.command === 'node "${PLUGIN_ROOT}/components/codegraph/dist/cli.js" hook post-tool-use',
|
|
243
|
-
);
|
|
244
|
-
|
|
245
|
-
// then
|
|
246
|
-
assert.equal(codegraphPostToolUseHooks.length, 1);
|
|
247
|
-
assert.equal(codegraphPostToolUseHooks[0]?.matcher, "^(codegraph[._].*|mcp__codegraph__.*)$");
|
|
248
|
-
assert.match(codegraphPostToolUseHooks[0]?.handler.statusMessage ?? "", /\S/);
|
|
249
|
-
});
|
|
250
|
-
|
|
251
232
|
test("#given aggregate PostToolUse hooks #when inspected #then thread title hygiene is registered for created Codex threads", async () => {
|
|
252
233
|
// given
|
|
253
234
|
const commandHooks = await readAggregateCommandHooks();
|
|
@@ -17,7 +17,7 @@ test("#given aggregate plugin manifest #when inspected #then it owns the omo nam
|
|
|
17
17
|
// then
|
|
18
18
|
assert.equal(manifest.name, "omo");
|
|
19
19
|
assert(Array.isArray(hookPaths));
|
|
20
|
-
assert.equal(hookPaths.length,
|
|
20
|
+
assert.equal(hookPaths.length, 21);
|
|
21
21
|
assert(hookPaths.every((hookPath) => typeof hookPath === "string" && hookPath.startsWith("./hooks/")));
|
|
22
22
|
assert(!hookPaths.includes("./hooks/hooks.json"));
|
|
23
23
|
assert(!hookPaths.includes("./hooks/user-prompt-submit-selecting-lazycodex-workflow.json"));
|
|
@@ -54,7 +54,6 @@ test("#given component directories #when scanned #then only intentional resource
|
|
|
54
54
|
// then
|
|
55
55
|
assert.deepEqual(componentNames, [
|
|
56
56
|
"bootstrap",
|
|
57
|
-
"codegraph",
|
|
58
57
|
"comment-checker",
|
|
59
58
|
"git-bash",
|
|
60
59
|
"lazycodex-executor-verify",
|
|
@@ -18,14 +18,13 @@ test("#given aggregate MCP config #when inspected #then code MCPs reference pack
|
|
|
18
18
|
// when
|
|
19
19
|
const lspServer = mcp.mcpServers.lsp;
|
|
20
20
|
const gitBashServer = mcp.mcpServers.git_bash;
|
|
21
|
-
const codegraphServer = mcp.mcpServers.codegraph;
|
|
22
21
|
const codeMcpNames = Object.keys(mcp.mcpServers)
|
|
23
|
-
.filter((name) => name === "lsp" || name === "git_bash"
|
|
22
|
+
.filter((name) => name === "lsp" || name === "git_bash")
|
|
24
23
|
.sort();
|
|
25
24
|
const componentLocalMcpSources = lspSources.filter((name) => name.startsWith("lazy-mcp") || name === "lazy-lsp-mcp.ts");
|
|
26
25
|
|
|
27
26
|
// then
|
|
28
|
-
assert.deepEqual(codeMcpNames, ["
|
|
27
|
+
assert.deepEqual(codeMcpNames, ["git_bash", "lsp"]);
|
|
29
28
|
assert.equal(packageJson.workspaces.includes("components/lsp/packages/lsp-tools-mcp"), false);
|
|
30
29
|
assert.deepEqual(packageJson.dependencies, { "@oh-my-opencode/shared-skills": "file:../../shared-skills" });
|
|
31
30
|
assert.doesNotMatch(bundledMcpBuildScript, new RegExp(["ast", "grep", "mcp"].join("-")));
|
|
@@ -38,10 +37,6 @@ test("#given aggregate MCP config #when inspected #then code MCPs reference pack
|
|
|
38
37
|
assert.equal(gitBashServer.command, "node");
|
|
39
38
|
assert.deepEqual(gitBashServer.args, ["../../git-bash-mcp/dist/cli.js", "mcp"]);
|
|
40
39
|
assert.equal(gitBashServer.cwd, ".");
|
|
41
|
-
assert.equal(codegraphServer.command, "node");
|
|
42
|
-
assert.deepEqual(codegraphServer.args, ["components/codegraph/dist/serve.js"]);
|
|
43
|
-
assert.equal(codegraphServer.cwd, ".");
|
|
44
|
-
assert.equal(codegraphServer.required, false);
|
|
45
40
|
assert.deepEqual(componentLocalMcpSources, []);
|
|
46
41
|
});
|
|
47
42
|
|
|
@@ -652,28 +652,3 @@ test("#given throttled updater and stale Codex config #when running check #then
|
|
|
652
652
|
assert.doesNotMatch(content, /gpt-5\.2/);
|
|
653
653
|
});
|
|
654
654
|
|
|
655
|
-
test("#given throttled updater and no OMO SOT #when running check #then OMO SOT seed migration still runs", async () => {
|
|
656
|
-
const root = await mkdtemp(join(tmpdir(), "lazycodex-auto-update-omo-sot-"));
|
|
657
|
-
const statePath = join(root, "state.json");
|
|
658
|
-
const home = join(root, "home");
|
|
659
|
-
await writeFile(statePath, JSON.stringify({ lastCheckedAt: 99_999 }, null, 2));
|
|
660
|
-
await mkdir(join(root, "codex-home"), { recursive: true });
|
|
661
|
-
|
|
662
|
-
const result = await runAutoUpdateCheck({
|
|
663
|
-
env: {
|
|
664
|
-
CODEX_HOME: join(root, "codex-home"),
|
|
665
|
-
HOME: home,
|
|
666
|
-
CODEX_CODEGRAPH_ENABLED: "0",
|
|
667
|
-
LAZYCODEX_MODEL_CATALOG_STATE_PATH: join(root, "model-state.json"),
|
|
668
|
-
LAZYCODEX_AUTO_UPDATE_STATE_PATH: statePath,
|
|
669
|
-
LAZYCODEX_AUTO_UPDATE_LOG_PATH: join(root, "auto-update.log"),
|
|
670
|
-
},
|
|
671
|
-
now: 100_000,
|
|
672
|
-
});
|
|
673
|
-
|
|
674
|
-
const content = await readFile(join(home, ".omo", "config.jsonc"), "utf8");
|
|
675
|
-
assert.equal(result.started, false);
|
|
676
|
-
assert.equal(result.reason, "throttled");
|
|
677
|
-
assert.match(content, /"\[codex\]"/);
|
|
678
|
-
assert.match(content, /"\[opencode\]"/);
|
|
679
|
-
});
|
|
@@ -168,37 +168,6 @@ test("#given a config.toml with no pre-existing agent entries #when the worker s
|
|
|
168
168
|
});
|
|
169
169
|
});
|
|
170
170
|
|
|
171
|
-
test("#given a package-relative CodeGraph MCP path #when worker setup runs #then the path is stamped absolute", async () => {
|
|
172
|
-
await withSetupFixture(async (fixture) => {
|
|
173
|
-
await writeFile(
|
|
174
|
-
join(fixture.pluginRoot, ".mcp.json"),
|
|
175
|
-
`${JSON.stringify(
|
|
176
|
-
{
|
|
177
|
-
mcpServers: {
|
|
178
|
-
codegraph: {
|
|
179
|
-
args: ["components/codegraph/dist/serve.js"],
|
|
180
|
-
command: "node",
|
|
181
|
-
cwd: ".",
|
|
182
|
-
required: false,
|
|
183
|
-
},
|
|
184
|
-
git_bash: { args: ["serve"], command: "node", env: {} },
|
|
185
|
-
},
|
|
186
|
-
},
|
|
187
|
-
null,
|
|
188
|
-
"\t",
|
|
189
|
-
)}\n`,
|
|
190
|
-
);
|
|
191
|
-
|
|
192
|
-
await runWorkerSetup(setupOptions(fixture));
|
|
193
|
-
|
|
194
|
-
const manifest = JSON.parse(await readFile(join(fixture.pluginRoot, ".mcp.json"), "utf8"));
|
|
195
|
-
assert.deepEqual(manifest.mcpServers.codegraph.args, [
|
|
196
|
-
join(fixture.pluginRoot, "components", "codegraph", "dist", "serve.js"),
|
|
197
|
-
]);
|
|
198
|
-
assert.equal(manifest.mcpServers.codegraph.cwd, ".");
|
|
199
|
-
});
|
|
200
|
-
});
|
|
201
|
-
|
|
202
171
|
test("#given bootstrap-managed staging #when agents are linked #then nothing is persisted under PLUGIN_ROOT", async () => {
|
|
203
172
|
await withSetupFixture(async (fixture) => {
|
|
204
173
|
await runWorkerSetup(setupOptions(fixture));
|