oh-my-opencode 5.1.6 → 5.1.8
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 +49 -45
- package/dist/cli/run/runnable-agent-resolver.d.ts +3 -0
- package/dist/cli-node/index.js +49 -45
- package/dist/hooks/goal/validation.d.ts +1 -0
- package/dist/hooks/no-hephaestus-non-gpt/hook.d.ts +4 -0
- package/dist/index.js +108 -61
- package/dist/plugin/chat-message/loop-commands.d.ts +1 -0
- package/dist/shared/index.d.ts +0 -1
- package/dist/shared/live-server-route.d.ts +0 -2
- package/dist/shared/tmux/tmux-utils/pane-close.d.ts +0 -3
- package/dist/shared/tmux/tmux-utils/server-health.d.ts +1 -1
- package/dist/skills/browser/runtime/omowright/manifest.json +1 -1
- package/dist/skills/debugging/SKILL.md +1 -1
- package/dist/skills/debugging/references/methodology/06-fix.md +8 -0
- package/dist/tui.js +22 -42
- package/package.json +14 -14
- package/packages/lsp-core/src/post-edit/file-location.ts +7 -2
- package/packages/lsp-core/src/post-edit/not-installed.test.ts +25 -0
- package/packages/lsp-core/src/tool-surface.test.ts +11 -11
- package/packages/omo-codex/plugin/.codex-plugin/plugin.json +1 -1
- package/packages/omo-codex/plugin/components/bootstrap/dist/cli.js +13 -3
- package/packages/omo-codex/plugin/components/bootstrap/hooks/hooks.json +1 -1
- package/packages/omo-codex/plugin/components/bootstrap/package.json +1 -1
- package/packages/omo-codex/plugin/components/bootstrap/test/download.test.ts +0 -16
- package/packages/omo-codex/plugin/components/bootstrap/test/environment.test.ts +3 -0
- 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 +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/lsp/test/package-smoke.test.ts +0 -27
- package/packages/omo-codex/plugin/components/rules/README.md +0 -1
- package/packages/omo-codex/plugin/components/rules/bundled-rules/hephaestus/gpt-5.5.md +1 -1
- package/packages/omo-codex/plugin/components/rules/bundled-rules/hephaestus/gpt-5.6.md +1 -1
- package/packages/omo-codex/plugin/components/rules/bundled-rules/hephaestus/gpt-6.md +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/ultrawork/test/directive-source.test.ts +0 -6
- package/packages/omo-codex/plugin/components/ultrawork/test/package-smoke.test.ts +0 -15
- 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/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/test/spawn-role-matrix.test.ts +16 -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/plugin/skills/browser/runtime/omowright/manifest.json +1 -1
- package/packages/omo-codex/plugin/skills/debugging/SKILL.md +1 -1
- package/packages/omo-codex/plugin/skills/debugging/references/methodology/06-fix.md +8 -0
- package/packages/omo-codex/plugin/test/AGENTS.md +11 -0
- package/packages/omo-codex/plugin/test/component-bundled-cli.test.mjs +0 -50
- package/packages/omo-codex/scripts/install-config-autonomous-features.test.mjs +24 -4
- package/packages/omo-codex/scripts/install-dist/install-local.mjs +15 -5
- package/packages/shared-skills/skills/browser/runtime/omowright/manifest.json +1 -1
- package/packages/shared-skills/skills/debugging/SKILL.md +1 -1
- package/packages/shared-skills/skills/debugging/references/methodology/06-fix.md +8 -0
- package/dist/features/team-mode/team-layout-tmux/close-team-member-pane.d.ts +0 -1
- package/dist/features/team-mode/team-tasklist/claim.d.ts +0 -1
- package/dist/features/team-mode/team-tasklist/dependencies.d.ts +0 -1
- package/dist/features/team-mode/team-tasklist/get.d.ts +0 -1
- package/dist/features/team-mode/team-tasklist/store.d.ts +0 -1
- package/dist/features/team-mode/team-tasklist/update.d.ts +0 -1
- package/dist/hooks/hashline-edit-diff-enhancer/hook.d.ts +0 -29
- package/dist/hooks/hashline-edit-diff-enhancer/pending-captures.d.ts +0 -13
- package/dist/openclaw/config.d.ts +0 -1
- package/dist/openclaw/dispatcher.d.ts +0 -1
- package/dist/openclaw/gateway-url-validation.d.ts +0 -1
- package/dist/openclaw/reply-listener-injection.d.ts +0 -1
- package/dist/openclaw/reply-listener-start.d.ts +0 -1
- package/dist/openclaw/session-registry.d.ts +0 -1
- package/dist/openclaw/tmux.d.ts +0 -1
|
@@ -1,7 +1,8 @@
|
|
|
1
1
|
import { describe, expect, test } from "bun:test";
|
|
2
2
|
|
|
3
|
+
import { handleLspMcpRequest } from "./mcp.js";
|
|
3
4
|
import { createStandaloneMcpRequestContext, runWithRequestContext } from "./request-context.js";
|
|
4
|
-
import { coerceToolArguments, executeLspTool
|
|
5
|
+
import { coerceToolArguments, executeLspTool } from "./tools.js";
|
|
5
6
|
|
|
6
7
|
const expectedToolSurface = [
|
|
7
8
|
{
|
|
@@ -140,17 +141,15 @@ const expectedToolSurface = [
|
|
|
140
141
|
];
|
|
141
142
|
|
|
142
143
|
describe("LSP core tool surface", () => {
|
|
143
|
-
test("#given
|
|
144
|
-
// given
|
|
145
|
-
const
|
|
146
|
-
|
|
147
|
-
|
|
148
|
-
|
|
149
|
-
inputSchema: tool.inputSchema,
|
|
150
|
-
}));
|
|
144
|
+
test("#given a JSON-RPC tools/list request #when descriptors are returned #then the public nine-tool schemas are pinned", async () => {
|
|
145
|
+
// given
|
|
146
|
+
const request = { jsonrpc: "2.0", id: 21, method: "tools/list" };
|
|
147
|
+
|
|
148
|
+
// when
|
|
149
|
+
const response = await handleLspMcpRequest(request);
|
|
151
150
|
|
|
152
151
|
// then
|
|
153
|
-
expect(
|
|
152
|
+
expect(response?.result?.tools).toEqual(expectedToolSurface);
|
|
154
153
|
});
|
|
155
154
|
|
|
156
155
|
test("#given legacy tool aliases #when executed #then aliases are callable but not listed", async () => {
|
|
@@ -161,7 +160,8 @@ describe("LSP core tool surface", () => {
|
|
|
161
160
|
|
|
162
161
|
// then
|
|
163
162
|
expect(result.content[0]?.text).toContain("No LSP server configured for extension: .wat");
|
|
164
|
-
|
|
163
|
+
const listResponse = await handleLspMcpRequest({ jsonrpc: "2.0", id: 23, method: "tools/list" });
|
|
164
|
+
expect(listResponse?.result?.tools?.map((tool: { name: string }) => tool.name)).not.toContain("lsp_diagnostics");
|
|
165
165
|
});
|
|
166
166
|
|
|
167
167
|
test("#given non-object tool arguments #when coerced #then they produce an empty argument record", () => {
|
|
@@ -7148,7 +7148,8 @@ var OmoMemoryRecallSchema = object({
|
|
|
7148
7148
|
event_caps: OmoMemoryRecallEventCapsSchema.default({ tool_args: 400, result_head: 600, assistant: 1500, prompt: 4000 }),
|
|
7149
7149
|
sidecar_max_tokens: number2().int().positive().default(48000),
|
|
7150
7150
|
max_concurrent_wakes: number2().int().positive().default(2),
|
|
7151
|
-
tool_budget: number2().int().positive().default(8)
|
|
7151
|
+
tool_budget: number2().int().positive().default(8),
|
|
7152
|
+
query_expansion: boolean2().default(false)
|
|
7152
7153
|
}).strict();
|
|
7153
7154
|
var OmoMemoryNudgeSchema = object({
|
|
7154
7155
|
enabled: boolean2().default(true),
|
|
@@ -7209,7 +7210,8 @@ var OmoMemoryRecallLayerSchema = object({
|
|
|
7209
7210
|
event_caps: OmoMemoryRecallEventCapsLayerSchema.optional(),
|
|
7210
7211
|
sidecar_max_tokens: number2().int().positive().optional(),
|
|
7211
7212
|
max_concurrent_wakes: number2().int().positive().optional(),
|
|
7212
|
-
tool_budget: number2().int().positive().optional()
|
|
7213
|
+
tool_budget: number2().int().positive().optional(),
|
|
7214
|
+
query_expansion: boolean2().optional()
|
|
7213
7215
|
}).strict();
|
|
7214
7216
|
var OmoMemoryNudgeLayerSchema = object({
|
|
7215
7217
|
enabled: boolean2().optional(),
|
|
@@ -7286,7 +7288,8 @@ var OmoMemorySettingsSchema = object({
|
|
|
7286
7288
|
event_caps: { tool_args: 400, result_head: 600, assistant: 1500, prompt: 4000 },
|
|
7287
7289
|
sidecar_max_tokens: 48000,
|
|
7288
7290
|
max_concurrent_wakes: 2,
|
|
7289
|
-
tool_budget: 8
|
|
7291
|
+
tool_budget: 8,
|
|
7292
|
+
query_expansion: false
|
|
7290
7293
|
}),
|
|
7291
7294
|
compile_warn_tokens: number2().int().positive().default(30000),
|
|
7292
7295
|
agents: record(string2(), OmoMemoryAgentOverridesSchema).default({})
|
|
@@ -11223,6 +11226,12 @@ ${featureName} = true
|
|
|
11223
11226
|
}
|
|
11224
11227
|
return replaceOrInsertSetting(config, section, featureName, "true");
|
|
11225
11228
|
}
|
|
11229
|
+
function removeFeature(config, featureName) {
|
|
11230
|
+
const section = findTomlSection(config, "features");
|
|
11231
|
+
if (section !== null)
|
|
11232
|
+
return removeSetting(config, section, featureName);
|
|
11233
|
+
return removeRootSetting(config, `features.${featureName}`);
|
|
11234
|
+
}
|
|
11226
11235
|
|
|
11227
11236
|
// ../src/install/codex-config-marketplaces.ts
|
|
11228
11237
|
var SISYPHUS_LEGACY_MARKETPLACES = ["lazycodex", "code-yeongyu-codex-plugins"];
|
|
@@ -11815,6 +11824,7 @@ async function updateCodexConfig(input) {
|
|
|
11815
11824
|
config = ensureFeatureEnabled(config, "plugins");
|
|
11816
11825
|
config = ensureFeatureEnabled(config, "plugin_hooks");
|
|
11817
11826
|
config = ensureFeatureEnabled(config, "multi_agent");
|
|
11827
|
+
config = removeFeature(config, "child_agents_md");
|
|
11818
11828
|
config = removeUnsupportedCodexMultiAgentModeConfig(config);
|
|
11819
11829
|
config = ensureCodexReasoningConfig(config, applyReasoningOverride(await readCodexModelCatalog(input.repoRoot), input.reasoning));
|
|
11820
11830
|
config = ensureCodexMultiAgentV2Config(config, {
|
|
@@ -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.1.
|
|
11
|
+
"statusMessage": "(OmO 5.1.8) Checking Bootstrap Provisioning"
|
|
12
12
|
}
|
|
13
13
|
]
|
|
14
14
|
}
|
|
@@ -262,22 +262,6 @@ describe("downloadFromManifest", () => {
|
|
|
262
262
|
});
|
|
263
263
|
|
|
264
264
|
describe("committed manifests", () => {
|
|
265
|
-
it("#given the committed ast-grep manifest #when loaded #then every required platform pins an https URL and a sha256", async () => {
|
|
266
|
-
// given / when
|
|
267
|
-
const manifest = await loadAssetManifest("ast-grep");
|
|
268
|
-
|
|
269
|
-
// then
|
|
270
|
-
expect(manifest.name).toBe("ast-grep");
|
|
271
|
-
expect(manifest.version).toMatch(/^\d+\.\d+\.\d+$/);
|
|
272
|
-
for (const platformKey of ["darwin-arm64", "darwin-x64", "linux-x64", "win32-x64"]) {
|
|
273
|
-
const asset = manifest.platforms[platformKey];
|
|
274
|
-
if (asset === undefined) throw new Error(`missing platform ${platformKey}`);
|
|
275
|
-
expect(asset.url).toStartWith("https://");
|
|
276
|
-
expect(asset.url).toContain(manifest.version);
|
|
277
|
-
expect(asset.sha256).toMatch(/^[a-f0-9]{64}$/);
|
|
278
|
-
}
|
|
279
|
-
});
|
|
280
|
-
|
|
281
265
|
it("#given the committed node manifest #when loaded #then the win32-x64 LTS zip pins an https URL and a sha256", async () => {
|
|
282
266
|
// given / when
|
|
283
267
|
const manifest = await loadAssetManifest("node");
|
|
@@ -373,4 +373,7 @@ async function writeSyncSourceFixture(sourceRoot: string): Promise<void> {
|
|
|
373
373
|
await writeExecutableStub(join(sourceRoot, "packages", "git-bash-mcp", "dist", "cli.js"));
|
|
374
374
|
await writeExecutableStub(join(sourceRoot, "packages", "lsp-tools-mcp", "dist", "cli.js"));
|
|
375
375
|
await writeExecutableStub(join(sourceRoot, "packages", "lsp-daemon", "dist", "cli.js"));
|
|
376
|
+
// The sync bundles the root CLI and its node fallback too (script/lazycodex-runtime-dists.ts).
|
|
377
|
+
await writeExecutableStub(join(sourceRoot, "dist", "cli", "index.js"));
|
|
378
|
+
await writeExecutableStub(join(sourceRoot, "dist", "cli-node", "index.js"));
|
|
376
379
|
}
|
|
@@ -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.1.
|
|
11
|
+
"statusMessage": "(OmO 5.1.8) 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.1.
|
|
23
|
+
"statusMessage": "(OmO 5.1.8) 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.1.
|
|
11
|
+
"statusMessage": "(OmO 5.1.8) Verifying LazyCodex Executor Evidence"
|
|
12
12
|
}
|
|
13
13
|
]
|
|
14
14
|
}
|
|
@@ -1,7 +1,7 @@
|
|
|
1
1
|
{
|
|
2
2
|
"schemaVersion": 1,
|
|
3
|
-
"version": "5.1.
|
|
4
|
-
"inputDigest": "sha256:
|
|
3
|
+
"version": "5.1.8",
|
|
4
|
+
"inputDigest": "sha256:7c96b2202dae9f1403113570ac78a39817b8af2dc767c2c49ff084673798c1c0",
|
|
5
5
|
"outputs": [
|
|
6
6
|
{
|
|
7
7
|
"path": "cli.d.ts",
|
|
@@ -8,7 +8,7 @@
|
|
|
8
8
|
"type": "command",
|
|
9
9
|
"command": "node \"${PLUGIN_ROOT}/dist/cli.js\" hook post-tool-use",
|
|
10
10
|
"timeout": 60,
|
|
11
|
-
"statusMessage": "(OmO 5.1.
|
|
11
|
+
"statusMessage": "(OmO 5.1.8) Checking LSP Diagnostics"
|
|
12
12
|
}
|
|
13
13
|
]
|
|
14
14
|
}
|
|
@@ -21,7 +21,7 @@
|
|
|
21
21
|
"type": "command",
|
|
22
22
|
"command": "node \"${PLUGIN_ROOT}/dist/cli.js\" hook post-compact",
|
|
23
23
|
"timeout": 5,
|
|
24
|
-
"statusMessage": "(OmO 5.1.
|
|
24
|
+
"statusMessage": "(OmO 5.1.8) Resetting LSP Diagnostics Cache"
|
|
25
25
|
}
|
|
26
26
|
]
|
|
27
27
|
}
|
|
@@ -16,9 +16,6 @@ describe("plugin package metadata", () => {
|
|
|
16
16
|
const hooksJson = readHooksJson("hooks/hooks.json");
|
|
17
17
|
const mcpJson = readMcpJson(".mcp.json");
|
|
18
18
|
const cliSource = readTextFile("src/cli.ts");
|
|
19
|
-
const daemonCliPathSource = readTextFile("src/daemon-cli-path.ts");
|
|
20
|
-
const codexHookCliSource = readTextFile("src/codex-hook-cli.ts");
|
|
21
|
-
const codexHookSource = readTextFile("src/codex-hook.ts");
|
|
22
19
|
const sourceFiles = listDirectoryEntries("src");
|
|
23
20
|
const scripts = requireScripts(packageJson, "package.json");
|
|
24
21
|
|
|
@@ -55,30 +52,6 @@ describe("plugin package metadata", () => {
|
|
|
55
52
|
},
|
|
56
53
|
},
|
|
57
54
|
});
|
|
58
|
-
expect(cliSource).not.toContain("./lazy-lsp-mcp.js");
|
|
59
|
-
expect(cliSource).toContain("resolveLspDaemonCliPath");
|
|
60
|
-
expect(daemonCliPathSource).toContain("@code-yeongyu/lsp-daemon/cli");
|
|
61
|
-
expect(daemonCliPathSource).toContain("../../lsp-daemon/dist/cli.js");
|
|
62
|
-
expect(daemonCliPathSource).toContain("OMO_LSP_DAEMON_VERSION");
|
|
63
|
-
expect(cliSource).not.toContain("../../../../../lsp-daemon/dist/cli.js");
|
|
64
|
-
expect(codexHookSource).toContain("ensureLspDaemonCliEnv");
|
|
65
|
-
expect(codexHookCliSource).not.toContain("@code-yeongyu/lsp-daemon");
|
|
66
|
-
expect(codexHookSource).toContain("@code-yeongyu/lsp-daemon/client");
|
|
67
|
-
expect(codexHookSource).toContain("@oh-my-opencode/lsp-core/post-edit");
|
|
68
|
-
expect(codexHookSource).toContain("CODEX_HOME");
|
|
69
|
-
expect(codexHookCliSource).not.toContain("../../../../../lsp-daemon");
|
|
70
|
-
expect(codexHookSource).not.toContain("../../../../../lsp-daemon");
|
|
71
55
|
expect(sourceFiles.filter((name) => name.startsWith("lazy-mcp") || name === "lazy-lsp-mcp.ts")).toEqual([]);
|
|
72
56
|
});
|
|
73
|
-
|
|
74
|
-
it("#given built component CLI #when runtime imports are inspected #then it is self-contained except Node builtins", () => {
|
|
75
|
-
const cliSource = readTextFile("dist/cli.js");
|
|
76
|
-
const imports = [
|
|
77
|
-
...cliSource.matchAll(/\bimport\s+(?:[^'";]+?\s+from\s+)?["']([^"']+)["']/g),
|
|
78
|
-
...cliSource.matchAll(/\bimport\s*\(\s*["']([^"']+)["']\s*\)/g),
|
|
79
|
-
].flatMap((match) => (match[1] === undefined ? [] : [match[1]]));
|
|
80
|
-
expect(imports.filter((specifier) => !specifier.startsWith("node:"))).toEqual([]);
|
|
81
|
-
expect(cliSource).not.toContain("@code-yeongyu/lsp-daemon/client");
|
|
82
|
-
expect(cliSource).not.toContain("@oh-my-opencode/lsp-core");
|
|
83
|
-
});
|
|
84
57
|
});
|
|
@@ -41,7 +41,7 @@ omo-codex auto-runs LSP diagnostics after every edit and injects the result: any
|
|
|
41
41
|
|
|
42
42
|
# Subagents
|
|
43
43
|
|
|
44
|
-
Read-only Codex subagent roles live in `CODEX_HOME/agents/`. Spawn: `multi_agent_v1.spawn_agent({"message":"TASK: act as a <role>. ...","fork_context":false})`. If your tool list instead has a flat `spawn_agent` with a required `task_name` (`multi_agent_v2`): `spawn_agent({"task_name":"<lowercase_digits_underscores>","message":"TASK: act as a <role>. ...","fork_turns":"none"})` — finished agents end on their own; `wait_agent` takes only `timeout_ms`.
|
|
44
|
+
Read-only Codex subagent roles live in `CODEX_HOME/agents/`. Spawn: `multi_agent_v1.spawn_agent({"message":"TASK: act as a <role>. ...","agent_type":"<role>","fork_context":false})`. If your tool list instead has a flat `spawn_agent` with a required `task_name` (`multi_agent_v2`): `spawn_agent({"task_name":"<lowercase_digits_underscores>","message":"TASK: act as a <role>. ...","fork_turns":"none"})` — finished agents end on their own; `wait_agent` takes only `timeout_ms`.
|
|
45
45
|
|
|
46
46
|
- `explorer` - codebase search
|
|
47
47
|
- `librarian` - external docs, OSS code, API contracts
|
|
@@ -31,7 +31,7 @@ Waiting is not free: a status poll replays the whole accumulated context through
|
|
|
31
31
|
|
|
32
32
|
# Subagents
|
|
33
33
|
|
|
34
|
-
Read-only Codex subagent roles live in `CODEX_HOME/agents/`. Spawn: `multi_agent_v1.spawn_agent({"message":"TASK: act as a <role>. GOAL: ... STOP WHEN: ... EVIDENCE: ...","fork_context":false})`. If your tool list instead has a flat `spawn_agent` with a required `task_name` (`multi_agent_v2`): `spawn_agent({"task_name":"<lowercase_digits_underscores>","message":"TASK: act as a <role>. GOAL: ... STOP WHEN: ... EVIDENCE: ...","fork_turns":"none"})` - finished agents end on their own; `wait_agent` takes only `timeout_ms`.
|
|
34
|
+
Read-only Codex subagent roles live in `CODEX_HOME/agents/`. Spawn: `multi_agent_v1.spawn_agent({"message":"TASK: act as a <role>. GOAL: ... STOP WHEN: ... EVIDENCE: ...","agent_type":"<role>","fork_context":false})`. If your tool list instead has a flat `spawn_agent` with a required `task_name` (`multi_agent_v2`): `spawn_agent({"task_name":"<lowercase_digits_underscores>","message":"TASK: act as a <role>. GOAL: ... STOP WHEN: ... EVIDENCE: ...","fork_turns":"none"})` - finished agents end on their own; `wait_agent` takes only `timeout_ms`.
|
|
35
35
|
|
|
36
36
|
- `explorer` - codebase search
|
|
37
37
|
- `librarian` - external docs, OSS code, API contracts
|
|
@@ -78,7 +78,7 @@ When an approach fails, change something material - an algorithm, library, or pa
|
|
|
78
78
|
|
|
79
79
|
## Codex tool and skills notes
|
|
80
80
|
|
|
81
|
-
The actual Codex tool list and schemas determine the route. Read-only subagent roles live in `CODEX_HOME/agents/`. For `multi_agent_v1`, use `multi_agent_v1.spawn_agent({"message":"TASK: act as a <role>. GOAL: ... STOP WHEN: ... EVIDENCE: ...","fork_context":false})`. If the tool list instead exposes a flat `spawn_agent` requiring `task_name` (`multi_agent_v2`), use `spawn_agent({"task_name":"<lowercase_digits_underscores>","message":"TASK: act as a <role>. GOAL: ... STOP WHEN: ... EVIDENCE: ...","fork_turns":"none"})`. Finished agents end on their own; `wait_agent` takes only `timeout_ms`. Keep the two payloads distinct and do not send v1 fields to v2 or vice versa.
|
|
81
|
+
The actual Codex tool list and schemas determine the route. Read-only subagent roles live in `CODEX_HOME/agents/`. For `multi_agent_v1`, use `multi_agent_v1.spawn_agent({"message":"TASK: act as a <role>. GOAL: ... STOP WHEN: ... EVIDENCE: ...","agent_type":"<role>","fork_context":false})`. If the tool list instead exposes a flat `spawn_agent` requiring `task_name` (`multi_agent_v2`), use `spawn_agent({"task_name":"<lowercase_digits_underscores>","message":"TASK: act as a <role>. GOAL: ... STOP WHEN: ... EVIDENCE: ...","fork_turns":"none"})`. Finished agents end on their own; `wait_agent` takes only `timeout_ms`. Keep the two payloads distinct and do not send v1 fields to v2 or vice versa.
|
|
82
82
|
|
|
83
83
|
- `explorer`: codebase search.
|
|
84
84
|
- `librarian`: external docs, OSS code, and API contracts.
|
|
@@ -7,7 +7,7 @@
|
|
|
7
7
|
"type": "command",
|
|
8
8
|
"command": "node \"${PLUGIN_ROOT}/dist/cli.js\" hook session-start",
|
|
9
9
|
"timeout": 10,
|
|
10
|
-
"statusMessage": "(OmO 5.1.
|
|
10
|
+
"statusMessage": "(OmO 5.1.8) Loading Project Rules"
|
|
11
11
|
}
|
|
12
12
|
]
|
|
13
13
|
}
|
|
@@ -19,7 +19,7 @@
|
|
|
19
19
|
"type": "command",
|
|
20
20
|
"command": "node \"${PLUGIN_ROOT}/dist/cli.js\" hook user-prompt-submit",
|
|
21
21
|
"timeout": 10,
|
|
22
|
-
"statusMessage": "(OmO 5.1.
|
|
22
|
+
"statusMessage": "(OmO 5.1.8) Loading Project Rules"
|
|
23
23
|
}
|
|
24
24
|
]
|
|
25
25
|
}
|
|
@@ -32,7 +32,7 @@
|
|
|
32
32
|
"type": "command",
|
|
33
33
|
"command": "node \"${PLUGIN_ROOT}/dist/cli.js\" hook post-tool-use",
|
|
34
34
|
"timeout": 10,
|
|
35
|
-
"statusMessage": "(OmO 5.1.
|
|
35
|
+
"statusMessage": "(OmO 5.1.8) Matching Project Rules"
|
|
36
36
|
}
|
|
37
37
|
]
|
|
38
38
|
}
|
|
@@ -45,7 +45,7 @@
|
|
|
45
45
|
"type": "command",
|
|
46
46
|
"command": "node \"${PLUGIN_ROOT}/dist/cli.js\" hook post-compact",
|
|
47
47
|
"timeout": 10,
|
|
48
|
-
"statusMessage": "(OmO 5.1.
|
|
48
|
+
"statusMessage": "(OmO 5.1.8) Resetting Project Rule Cache"
|
|
49
49
|
}
|
|
50
50
|
]
|
|
51
51
|
}
|
|
@@ -1,6 +1,6 @@
|
|
|
1
1
|
{
|
|
2
2
|
"name": "@code-yeongyu/codex-ultrawork",
|
|
3
|
-
"version": "5.1.
|
|
3
|
+
"version": "5.1.8",
|
|
4
4
|
"description": "Codex plugin that injects the ultrawork orchestration directive and ships LazyCodex planning, review, QA, and gate agent roles.",
|
|
5
5
|
"type": "module",
|
|
6
6
|
"packageManager": "npm@11.12.1",
|
|
@@ -21,14 +21,8 @@ describe("codex ultrawork directive source", () => {
|
|
|
21
21
|
// given
|
|
22
22
|
const directiveSource = readFileSync(new URL("../src/directive.ts", import.meta.url), "utf8");
|
|
23
23
|
|
|
24
|
-
// when
|
|
25
|
-
const importsBundledConstant = directiveSource.includes(
|
|
26
|
-
'import { ULTRAWORK_DIRECTIVE_TEXT } from "./directive-content.js"',
|
|
27
|
-
);
|
|
28
|
-
|
|
29
24
|
// then
|
|
30
25
|
// prompts-core's contract: markdown is bundled at build time, never read from disk at runtime.
|
|
31
|
-
expect(importsBundledConstant).toBe(true);
|
|
32
26
|
expect(directiveSource).not.toMatch(/readFileSync|readFile\(/);
|
|
33
27
|
});
|
|
34
28
|
});
|
|
@@ -1,4 +1,3 @@
|
|
|
1
|
-
import { readFileSync } from "node:fs";
|
|
2
1
|
import { describe, expect, it } from "vitest";
|
|
3
2
|
import {
|
|
4
3
|
collectHookCommandsFromValue,
|
|
@@ -6,43 +5,29 @@ import {
|
|
|
6
5
|
readPackageJson,
|
|
7
6
|
readTextFile,
|
|
8
7
|
requireFiles,
|
|
9
|
-
requireScripts,
|
|
10
8
|
} from "../../test-support/package-smoke-fixture.js";
|
|
11
|
-
import { ULTRAWORK_DIRECTIVE } from "../src/directive.js";
|
|
12
9
|
|
|
13
10
|
describe("codex ultrawork package metadata", () => {
|
|
14
11
|
it("#given package metadata #when inspected #then hook ships as bundled CLI", () => {
|
|
15
12
|
// given
|
|
16
|
-
const canonicalDirective = readFileSync(
|
|
17
|
-
new URL(import.meta.resolve("@oh-my-opencode/prompts-core/prompts/ultrawork/codex.md")),
|
|
18
|
-
"utf8",
|
|
19
|
-
);
|
|
20
13
|
const packageJson = readPackageJson("package.json");
|
|
21
14
|
const hooksJson = readJsonFile("hooks/hooks.json");
|
|
22
15
|
const cliSource = readTextFile("src/cli.ts");
|
|
23
16
|
|
|
24
17
|
// when
|
|
25
18
|
const packageFiles = requireFiles(packageJson, "package.json");
|
|
26
|
-
const scripts = requireScripts(packageJson, "package.json");
|
|
27
19
|
const hookCommands = collectHookCommandsFromValue(hooksJson);
|
|
28
20
|
const pluginRoot = ["$", "{PLUGIN_ROOT}"].join("");
|
|
29
21
|
|
|
30
22
|
// then
|
|
31
23
|
expect(packageJson.type).toBe("module");
|
|
32
|
-
expect(packageJson.packageManager).toBe("npm@11.12.1");
|
|
33
24
|
expect(packageJson.bin["omo-ultrawork"]).toBe("./dist/cli.js");
|
|
34
|
-
expect(scripts["build"]).toBe(
|
|
35
|
-
"node scripts/sync-directive.mjs && node -e \"require('node:fs').rmSync('dist',{recursive:true,force:true})\" && bun build src/cli.ts --target node --format esm --outfile dist/cli.js",
|
|
36
|
-
);
|
|
37
|
-
expect(scripts["test"]).toBe("vitest --run");
|
|
38
25
|
expect(packageFiles).toContain("dist");
|
|
39
26
|
expect(packageFiles).toContain("skills");
|
|
40
27
|
// The directive is no longer a published file: it ships compiled into dist/cli.js via the
|
|
41
28
|
// generated src/directive-content.ts, so assert the bundled contract instead of files-list
|
|
42
29
|
// membership.
|
|
43
30
|
expect(packageFiles).not.toContain("directive.md");
|
|
44
|
-
expect(ULTRAWORK_DIRECTIVE.length).toBeGreaterThan(0);
|
|
45
|
-
expect(ULTRAWORK_DIRECTIVE).toBe(canonicalDirective);
|
|
46
31
|
expect(packageFiles).not.toContain("hooks/ultrawork-detector.py");
|
|
47
32
|
expect(cliSource.startsWith("#!/usr/bin/env node")).toBe(true);
|
|
48
33
|
expect(hookCommands).toContain(`node "${pluginRoot}/dist/cli.js" hook user-prompt-submit`);
|
|
@@ -7,7 +7,7 @@
|
|
|
7
7
|
"type": "command",
|
|
8
8
|
"command": "node \"${PLUGIN_ROOT}/components/ulw-execute-continuation/dist/cli.js\" hook stop",
|
|
9
9
|
"timeout": 10,
|
|
10
|
-
"statusMessage": "(OmO 5.1.
|
|
10
|
+
"statusMessage": "(OmO 5.1.8) Checking Ulw-Execute Continuation"
|
|
11
11
|
}
|
|
12
12
|
]
|
|
13
13
|
}
|
|
@@ -7,7 +7,7 @@
|
|
|
7
7
|
"type": "command",
|
|
8
8
|
"command": "node \"${PLUGIN_ROOT}/dist/cli.js\" hook user-prompt-submit --with-ultrawork",
|
|
9
9
|
"timeout": 10,
|
|
10
|
-
"statusMessage": "(OmO 5.1.
|
|
10
|
+
"statusMessage": "(OmO 5.1.8) Checking Ulw-Loop Steering"
|
|
11
11
|
}
|
|
12
12
|
]
|
|
13
13
|
}
|
|
@@ -20,7 +20,7 @@
|
|
|
20
20
|
"type": "command",
|
|
21
21
|
"command": "node \"${PLUGIN_ROOT}/dist/cli.js\" hook post-tool-use-spawn",
|
|
22
22
|
"timeout": 5,
|
|
23
|
-
"statusMessage": "(OmO 5.1.
|
|
23
|
+
"statusMessage": "(OmO 5.1.8) Recording Spawn Admission"
|
|
24
24
|
}
|
|
25
25
|
]
|
|
26
26
|
}
|
|
@@ -33,7 +33,7 @@
|
|
|
33
33
|
"type": "command",
|
|
34
34
|
"command": "node \"${PLUGIN_ROOT}/dist/cli.js\" hook pre-tool-use",
|
|
35
35
|
"timeout": 5,
|
|
36
|
-
"statusMessage": "(OmO 5.1.
|
|
36
|
+
"statusMessage": "(OmO 5.1.8) Enforcing Unlimited Ulw-Loop Budget"
|
|
37
37
|
}
|
|
38
38
|
]
|
|
39
39
|
},
|
|
@@ -44,7 +44,7 @@
|
|
|
44
44
|
"type": "command",
|
|
45
45
|
"command": "node \"${PLUGIN_ROOT}/dist/cli.js\" hook pre-tool-use-spawn",
|
|
46
46
|
"timeout": 5,
|
|
47
|
-
"statusMessage": "(OmO 5.1.
|
|
47
|
+
"statusMessage": "(OmO 5.1.8) Guarding Ulw-Loop Spawns"
|
|
48
48
|
}
|
|
49
49
|
]
|
|
50
50
|
}
|
|
@@ -56,7 +56,7 @@
|
|
|
56
56
|
"type": "command",
|
|
57
57
|
"command": "node \"${PLUGIN_ROOT}/dist/cli.js\" hook stop",
|
|
58
58
|
"timeout": 10,
|
|
59
|
-
"statusMessage": "(OmO 5.1.
|
|
59
|
+
"statusMessage": "(OmO 5.1.8) Checking Ulw-Loop Resume"
|
|
60
60
|
}
|
|
61
61
|
]
|
|
62
62
|
}
|
|
@@ -1,6 +1,6 @@
|
|
|
1
1
|
{
|
|
2
2
|
"name": "@code-yeongyu/codex-ulw-loop",
|
|
3
|
-
"version": "5.1.
|
|
3
|
+
"version": "5.1.8",
|
|
4
4
|
"description": "Codex plugin: durable repo-native multi-goal orchestration with embedded success criteria and observable evidence audit.",
|
|
5
5
|
"type": "module",
|
|
6
6
|
"packageManager": "npm@11.12.1",
|
|
@@ -87,6 +87,22 @@ describe("#given no active plan #when native spawns cross the role boundary", ()
|
|
|
87
87
|
);
|
|
88
88
|
expect([...LAZYCODEX_SPAWN_ROLES].sort()).toEqual(names.sort());
|
|
89
89
|
});
|
|
90
|
+
it("admits every multi_agent_v1 spawn example the bundled Hephaestus rules teach", async () => {
|
|
91
|
+
const root = new URL("../../rules/bundled-rules/hephaestus/", import.meta.url);
|
|
92
|
+
const variants = (await readdir(root)).filter((file) => file.endsWith(".md")).sort();
|
|
93
|
+
expect(variants.length, "no bundled Hephaestus variant to check").toBeGreaterThan(0);
|
|
94
|
+
for (const variant of variants) {
|
|
95
|
+
const content = await readFile(new URL(variant, root), "utf8");
|
|
96
|
+
const examples = [...content.matchAll(/multi_agent_v1[.]spawn_agent[(]([{][^)]*[}])[)]/g)].map((match) =>
|
|
97
|
+
String(match[1]).replaceAll("<role>", "explorer"),
|
|
98
|
+
);
|
|
99
|
+
expect(examples.length, `${variant} has no multi_agent_v1 spawn example`).toBeGreaterThan(0);
|
|
100
|
+
for (const example of examples) {
|
|
101
|
+
const input = JSON.parse(example) as Record<string, unknown>;
|
|
102
|
+
expect(guard("multi_agent_v1.spawn_agent", input), `${variant}: ${example}`).toBe("");
|
|
103
|
+
}
|
|
104
|
+
}
|
|
105
|
+
});
|
|
90
106
|
it("still enforces admission breakers after role validation", async () => {
|
|
91
107
|
await mkdir(join(cwd, "data", "spawn-breaker"), { recursive: true });
|
|
92
108
|
await writeFile(join(cwd, "data", "spawn-breaker", "matrix.json"), JSON.stringify({ reason: "capacity" }));
|
|
@@ -7,7 +7,7 @@
|
|
|
7
7
|
"type": "command",
|
|
8
8
|
"command": "node \"${PLUGIN_ROOT}/components/git-bash/dist/cli.js\" hook post-compact",
|
|
9
9
|
"timeout": 5,
|
|
10
|
-
"statusMessage": "(OmO 5.1.
|
|
10
|
+
"statusMessage": "(OmO 5.1.8) Resetting Git Bash MCP Reminder",
|
|
11
11
|
"commandWindows": "powershell -NoProfile -ExecutionPolicy Bypass -File \"${PLUGIN_ROOT}\\components\\bootstrap\\scripts\\node-dispatch.ps1\" \"${PLUGIN_ROOT}\\components\\git-bash\\dist\\cli.js\" hook post-compact"
|
|
12
12
|
}
|
|
13
13
|
],
|