oh-my-codex 0.16.3 → 0.16.4
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/Cargo.lock +5 -5
- package/Cargo.toml +1 -1
- package/README.md +3 -3
- package/dist/catalog/__tests__/plugin-bundle-ssot.test.js +9 -0
- package/dist/catalog/__tests__/plugin-bundle-ssot.test.js.map +1 -1
- package/dist/cli/__tests__/cleanup.test.js +27 -0
- package/dist/cli/__tests__/cleanup.test.js.map +1 -1
- package/dist/cli/__tests__/codex-plugin-layout.test.js +7 -5
- package/dist/cli/__tests__/codex-plugin-layout.test.js.map +1 -1
- package/dist/cli/__tests__/doctor-warning-copy.test.js +101 -6
- package/dist/cli/__tests__/doctor-warning-copy.test.js.map +1 -1
- package/dist/cli/__tests__/index.test.js +131 -2
- package/dist/cli/__tests__/index.test.js.map +1 -1
- package/dist/cli/__tests__/ralph-goal-mode-contract.test.js +2 -0
- package/dist/cli/__tests__/ralph-goal-mode-contract.test.js.map +1 -1
- package/dist/cli/__tests__/ralph.test.js +47 -0
- package/dist/cli/__tests__/ralph.test.js.map +1 -1
- package/dist/cli/__tests__/setup-hooks-shared-ownership.test.js +2 -2
- package/dist/cli/__tests__/setup-hooks-shared-ownership.test.js.map +1 -1
- package/dist/cli/__tests__/setup-install-mode.test.js +272 -26
- package/dist/cli/__tests__/setup-install-mode.test.js.map +1 -1
- package/dist/cli/__tests__/setup-refresh.test.js +85 -3
- package/dist/cli/__tests__/setup-refresh.test.js.map +1 -1
- package/dist/cli/__tests__/setup-scope.test.js +1 -1
- package/dist/cli/__tests__/setup-scope.test.js.map +1 -1
- package/dist/cli/__tests__/setup-skills-overwrite.test.js +2 -1
- package/dist/cli/__tests__/setup-skills-overwrite.test.js.map +1 -1
- package/dist/cli/__tests__/team.test.js +108 -0
- package/dist/cli/__tests__/team.test.js.map +1 -1
- package/dist/cli/__tests__/ultragoal.test.js +69 -0
- package/dist/cli/__tests__/ultragoal.test.js.map +1 -1
- package/dist/cli/__tests__/uninstall.test.js +54 -8
- package/dist/cli/__tests__/uninstall.test.js.map +1 -1
- package/dist/cli/cleanup.d.ts.map +1 -1
- package/dist/cli/cleanup.js +8 -4
- package/dist/cli/cleanup.js.map +1 -1
- package/dist/cli/codex-feature-probe.d.ts +9 -0
- package/dist/cli/codex-feature-probe.d.ts.map +1 -0
- package/dist/cli/codex-feature-probe.js +28 -0
- package/dist/cli/codex-feature-probe.js.map +1 -0
- package/dist/cli/doctor.d.ts +1 -0
- package/dist/cli/doctor.d.ts.map +1 -1
- package/dist/cli/doctor.js +152 -17
- package/dist/cli/doctor.js.map +1 -1
- package/dist/cli/index.d.ts +9 -2
- package/dist/cli/index.d.ts.map +1 -1
- package/dist/cli/index.js +135 -17
- package/dist/cli/index.js.map +1 -1
- package/dist/cli/mcp-parity.js +8 -8
- package/dist/cli/mcp-parity.js.map +1 -1
- package/dist/cli/plugin-marketplace.d.ts +3 -0
- package/dist/cli/plugin-marketplace.d.ts.map +1 -1
- package/dist/cli/plugin-marketplace.js +88 -0
- package/dist/cli/plugin-marketplace.js.map +1 -1
- package/dist/cli/ralph.d.ts.map +1 -1
- package/dist/cli/ralph.js +21 -0
- package/dist/cli/ralph.js.map +1 -1
- package/dist/cli/setup-preferences.d.ts +4 -0
- package/dist/cli/setup-preferences.d.ts.map +1 -1
- package/dist/cli/setup-preferences.js +7 -0
- package/dist/cli/setup-preferences.js.map +1 -1
- package/dist/cli/setup.d.ts +5 -3
- package/dist/cli/setup.d.ts.map +1 -1
- package/dist/cli/setup.js +114 -44
- package/dist/cli/setup.js.map +1 -1
- package/dist/cli/ultragoal.d.ts +1 -1
- package/dist/cli/ultragoal.d.ts.map +1 -1
- package/dist/cli/ultragoal.js +64 -5
- package/dist/cli/ultragoal.js.map +1 -1
- package/dist/cli/uninstall.d.ts +2 -0
- package/dist/cli/uninstall.d.ts.map +1 -1
- package/dist/cli/uninstall.js +12 -3
- package/dist/cli/uninstall.js.map +1 -1
- package/dist/config/__tests__/codex-feature-flags.test.d.ts +2 -0
- package/dist/config/__tests__/codex-feature-flags.test.d.ts.map +1 -0
- package/dist/config/__tests__/codex-feature-flags.test.js +35 -0
- package/dist/config/__tests__/codex-feature-flags.test.js.map +1 -0
- package/dist/config/__tests__/codex-hooks.test.js +7 -0
- package/dist/config/__tests__/codex-hooks.test.js.map +1 -1
- package/dist/config/__tests__/generator-idempotent.test.js +70 -9
- package/dist/config/__tests__/generator-idempotent.test.js.map +1 -1
- package/dist/config/__tests__/generator-notify.test.js +116 -11
- package/dist/config/__tests__/generator-notify.test.js.map +1 -1
- package/dist/config/__tests__/wiki-config-contract.test.js +6 -3
- package/dist/config/__tests__/wiki-config-contract.test.js.map +1 -1
- package/dist/config/codex-feature-flags.d.ts +21 -0
- package/dist/config/codex-feature-flags.d.ts.map +1 -0
- package/dist/config/codex-feature-flags.js +56 -0
- package/dist/config/codex-feature-flags.js.map +1 -0
- package/dist/config/codex-hooks.d.ts +2 -0
- package/dist/config/codex-hooks.d.ts.map +1 -1
- package/dist/config/codex-hooks.js +25 -3
- package/dist/config/codex-hooks.js.map +1 -1
- package/dist/config/generator.d.ts +11 -2
- package/dist/config/generator.d.ts.map +1 -1
- package/dist/config/generator.js +221 -123
- package/dist/config/generator.js.map +1 -1
- package/dist/config/omx-first-party-mcp.d.ts +3 -1
- package/dist/config/omx-first-party-mcp.d.ts.map +1 -1
- package/dist/config/omx-first-party-mcp.js +2 -2
- package/dist/config/omx-first-party-mcp.js.map +1 -1
- package/dist/hooks/__tests__/keyword-detector.test.js +92 -2
- package/dist/hooks/__tests__/keyword-detector.test.js.map +1 -1
- package/dist/hooks/__tests__/notify-hook-non-omx-guard.test.js +125 -1
- package/dist/hooks/__tests__/notify-hook-non-omx-guard.test.js.map +1 -1
- package/dist/hooks/__tests__/skill-catalog-hygiene.test.d.ts +2 -0
- package/dist/hooks/__tests__/skill-catalog-hygiene.test.d.ts.map +1 -0
- package/dist/hooks/__tests__/skill-catalog-hygiene.test.js +84 -0
- package/dist/hooks/__tests__/skill-catalog-hygiene.test.js.map +1 -0
- package/dist/hooks/agents-overlay.js +2 -2
- package/dist/hooks/agents-overlay.js.map +1 -1
- package/dist/hooks/keyword-detector.d.ts +1 -0
- package/dist/hooks/keyword-detector.d.ts.map +1 -1
- package/dist/hooks/keyword-detector.js +7 -5
- package/dist/hooks/keyword-detector.js.map +1 -1
- package/dist/hud/__tests__/state.test.js +164 -0
- package/dist/hud/__tests__/state.test.js.map +1 -1
- package/dist/hud/state.d.ts.map +1 -1
- package/dist/hud/state.js +4 -5
- package/dist/hud/state.js.map +1 -1
- package/dist/mcp/__tests__/state-paths.test.js +61 -0
- package/dist/mcp/__tests__/state-paths.test.js.map +1 -1
- package/dist/mcp/__tests__/state-server.test.js +166 -0
- package/dist/mcp/__tests__/state-server.test.js.map +1 -1
- package/dist/mcp/state-paths.d.ts.map +1 -1
- package/dist/mcp/state-paths.js +23 -2
- package/dist/mcp/state-paths.js.map +1 -1
- package/dist/modes/__tests__/base-session-scope.test.js +22 -0
- package/dist/modes/__tests__/base-session-scope.test.js.map +1 -1
- package/dist/modes/__tests__/base-tmux-pane.test.js +57 -26
- package/dist/modes/__tests__/base-tmux-pane.test.js.map +1 -1
- package/dist/modes/base.d.ts.map +1 -1
- package/dist/modes/base.js +5 -0
- package/dist/modes/base.js.map +1 -1
- package/dist/planning/__tests__/approved-execution-lifecycle-matrix.test.d.ts +2 -0
- package/dist/planning/__tests__/approved-execution-lifecycle-matrix.test.d.ts.map +1 -0
- package/dist/planning/__tests__/approved-execution-lifecycle-matrix.test.js +316 -0
- package/dist/planning/__tests__/approved-execution-lifecycle-matrix.test.js.map +1 -0
- package/dist/planning/__tests__/approved-launch-hint-lineage-matrix.test.d.ts +2 -0
- package/dist/planning/__tests__/approved-launch-hint-lineage-matrix.test.d.ts.map +1 -0
- package/dist/planning/__tests__/approved-launch-hint-lineage-matrix.test.js +481 -0
- package/dist/planning/__tests__/approved-launch-hint-lineage-matrix.test.js.map +1 -0
- package/dist/planning/__tests__/artifacts.test.js +533 -4
- package/dist/planning/__tests__/artifacts.test.js.map +1 -1
- package/dist/planning/__tests__/context-pack-status.test.js +524 -0
- package/dist/planning/__tests__/context-pack-status.test.js.map +1 -1
- package/dist/planning/__tests__/markdown-structure.test.d.ts +2 -0
- package/dist/planning/__tests__/markdown-structure.test.d.ts.map +1 -0
- package/dist/planning/__tests__/markdown-structure.test.js +459 -0
- package/dist/planning/__tests__/markdown-structure.test.js.map +1 -0
- package/dist/planning/__tests__/ready-context-pack-role-refs.test.js +523 -1
- package/dist/planning/__tests__/ready-context-pack-role-refs.test.js.map +1 -1
- package/dist/planning/artifacts.d.ts +1 -1
- package/dist/planning/artifacts.d.ts.map +1 -1
- package/dist/planning/artifacts.js +227 -28
- package/dist/planning/artifacts.js.map +1 -1
- package/dist/planning/context-pack-status.d.ts +25 -0
- package/dist/planning/context-pack-status.d.ts.map +1 -1
- package/dist/planning/context-pack-status.js +272 -31
- package/dist/planning/context-pack-status.js.map +1 -1
- package/dist/planning/markdown-structure.d.ts +20 -0
- package/dist/planning/markdown-structure.d.ts.map +1 -0
- package/dist/planning/markdown-structure.js +137 -0
- package/dist/planning/markdown-structure.js.map +1 -0
- package/dist/ralph/__tests__/completion-audit.test.d.ts +2 -0
- package/dist/ralph/__tests__/completion-audit.test.d.ts.map +1 -0
- package/dist/ralph/__tests__/completion-audit.test.js +121 -0
- package/dist/ralph/__tests__/completion-audit.test.js.map +1 -0
- package/dist/ralph/completion-audit.d.ts +8 -0
- package/dist/ralph/completion-audit.d.ts.map +1 -0
- package/dist/ralph/completion-audit.js +99 -0
- package/dist/ralph/completion-audit.js.map +1 -0
- package/dist/scripts/__tests__/codex-native-hook.test.js +220 -13
- package/dist/scripts/__tests__/codex-native-hook.test.js.map +1 -1
- package/dist/scripts/__tests__/notify-dispatcher.test.d.ts +2 -0
- package/dist/scripts/__tests__/notify-dispatcher.test.d.ts.map +1 -0
- package/dist/scripts/__tests__/notify-dispatcher.test.js +126 -0
- package/dist/scripts/__tests__/notify-dispatcher.test.js.map +1 -0
- package/dist/scripts/codex-native-hook.d.ts.map +1 -1
- package/dist/scripts/codex-native-hook.js +133 -54
- package/dist/scripts/codex-native-hook.js.map +1 -1
- package/dist/scripts/codex-native-pre-post.d.ts.map +1 -1
- package/dist/scripts/codex-native-pre-post.js +4 -2
- package/dist/scripts/codex-native-pre-post.js.map +1 -1
- package/dist/scripts/notify-dispatcher.js +30 -1
- package/dist/scripts/notify-dispatcher.js.map +1 -1
- package/dist/scripts/notify-hook.js +3 -1
- package/dist/scripts/notify-hook.js.map +1 -1
- package/dist/state/__tests__/workflow-transition.test.js +102 -27
- package/dist/state/__tests__/workflow-transition.test.js.map +1 -1
- package/dist/state/operations.d.ts.map +1 -1
- package/dist/state/operations.js +9 -3
- package/dist/state/operations.js.map +1 -1
- package/dist/state/skill-active.d.ts +7 -0
- package/dist/state/skill-active.d.ts.map +1 -1
- package/dist/state/skill-active.js +25 -8
- package/dist/state/skill-active.js.map +1 -1
- package/dist/state/workflow-transition-reconcile.d.ts +1 -0
- package/dist/state/workflow-transition-reconcile.d.ts.map +1 -1
- package/dist/state/workflow-transition-reconcile.js +22 -15
- package/dist/state/workflow-transition-reconcile.js.map +1 -1
- package/dist/state/workflow-transition.js +3 -3
- package/dist/state/workflow-transition.js.map +1 -1
- package/dist/team/__tests__/approved-execution.test.js +39 -0
- package/dist/team/__tests__/approved-execution.test.js.map +1 -1
- package/dist/team/__tests__/runtime.test.js +5 -0
- package/dist/team/__tests__/runtime.test.js.map +1 -1
- package/dist/team/__tests__/scaling.test.js +497 -2
- package/dist/team/__tests__/scaling.test.js.map +1 -1
- package/dist/team/__tests__/state-root.test.js +1 -1
- package/dist/team/__tests__/state-root.test.js.map +1 -1
- package/dist/team/__tests__/worker-bootstrap.test.js +8 -0
- package/dist/team/__tests__/worker-bootstrap.test.js.map +1 -1
- package/dist/team/approved-execution.d.ts.map +1 -1
- package/dist/team/approved-execution.js +3 -0
- package/dist/team/approved-execution.js.map +1 -1
- package/dist/team/scaling.d.ts.map +1 -1
- package/dist/team/scaling.js +43 -0
- package/dist/team/scaling.js.map +1 -1
- package/dist/team/state-root.d.ts.map +1 -1
- package/dist/team/state-root.js +4 -0
- package/dist/team/state-root.js.map +1 -1
- package/dist/team/state.d.ts.map +1 -1
- package/dist/team/state.js +2 -6
- package/dist/team/state.js.map +1 -1
- package/dist/ultragoal/__tests__/artifacts.test.js +124 -1
- package/dist/ultragoal/__tests__/artifacts.test.js.map +1 -1
- package/dist/ultragoal/__tests__/docs-contract.test.js +21 -0
- package/dist/ultragoal/__tests__/docs-contract.test.js.map +1 -1
- package/dist/ultragoal/artifacts.d.ts +44 -2
- package/dist/ultragoal/artifacts.d.ts.map +1 -1
- package/dist/ultragoal/artifacts.js +197 -13
- package/dist/ultragoal/artifacts.js.map +1 -1
- package/dist/wiki/lifecycle.js +1 -1
- package/dist/wiki/lifecycle.js.map +1 -1
- package/package.json +1 -1
- package/plugins/oh-my-codex/.codex-plugin/plugin.json +1 -1
- package/plugins/oh-my-codex/.mcp.json +5 -5
- package/plugins/oh-my-codex/skills/analyze/SKILL.md +0 -2
- package/plugins/oh-my-codex/skills/autopilot/SKILL.md +2 -2
- package/plugins/oh-my-codex/skills/code-review/SKILL.md +1 -3
- package/plugins/oh-my-codex/skills/deep-interview/SKILL.md +5 -7
- package/plugins/oh-my-codex/skills/doctor/SKILL.md +2 -2
- package/plugins/oh-my-codex/skills/omx-setup/SKILL.md +3 -3
- package/plugins/oh-my-codex/skills/pipeline/SKILL.md +3 -3
- package/plugins/oh-my-codex/skills/plan/SKILL.md +3 -6
- package/plugins/oh-my-codex/skills/ralph/SKILL.md +9 -10
- package/plugins/oh-my-codex/skills/ultragoal/SKILL.md +36 -3
- package/plugins/oh-my-codex/skills/ultraqa/SKILL.md +21 -24
- package/plugins/oh-my-codex/skills/ultrawork/SKILL.md +8 -8
- package/plugins/oh-my-codex/skills/wiki/SKILL.md +13 -13
- package/skills/analyze/SKILL.md +0 -2
- package/skills/ask-claude/SKILL.md +5 -3
- package/skills/ask-gemini/SKILL.md +5 -3
- package/skills/autopilot/SKILL.md +2 -2
- package/skills/code-review/SKILL.md +1 -3
- package/skills/deep-interview/SKILL.md +5 -7
- package/skills/doctor/SKILL.md +2 -2
- package/skills/ecomode/SKILL.md +105 -1
- package/skills/frontend-ui-ux/SKILL.md +4 -26
- package/skills/git-master/SKILL.md +2 -4
- package/skills/omx-setup/SKILL.md +3 -3
- package/skills/pipeline/SKILL.md +3 -3
- package/skills/plan/SKILL.md +3 -6
- package/skills/ralph/SKILL.md +9 -10
- package/skills/swarm/SKILL.md +5 -3
- package/skills/tdd/SKILL.md +95 -1
- package/skills/ultragoal/SKILL.md +36 -3
- package/skills/ultraqa/SKILL.md +21 -24
- package/skills/ultrawork/SKILL.md +8 -8
- package/skills/web-clone/SKILL.md +348 -1
- package/skills/wiki/SKILL.md +13 -13
- package/src/scripts/__tests__/codex-native-hook.test.ts +231 -13
- package/src/scripts/__tests__/notify-dispatcher.test.ts +153 -0
- package/src/scripts/codex-native-hook.ts +160 -43
- package/src/scripts/codex-native-pre-post.ts +4 -1
- package/src/scripts/notify-dispatcher.ts +40 -1
- package/src/scripts/notify-hook.ts +3 -1
|
@@ -3,7 +3,7 @@ import assert from "node:assert/strict";
|
|
|
3
3
|
import { existsSync } from "node:fs";
|
|
4
4
|
import { cp, mkdir, mkdtemp, readFile, readdir, rm, writeFile, } from "node:fs/promises";
|
|
5
5
|
import { tmpdir } from "node:os";
|
|
6
|
-
import { join } from "node:path";
|
|
6
|
+
import { dirname, join } from "node:path";
|
|
7
7
|
import { parse as parseToml } from "@iarna/toml";
|
|
8
8
|
import { setup } from "../setup.js";
|
|
9
9
|
import { uninstall } from "../uninstall.js";
|
|
@@ -128,14 +128,71 @@ describe("notify setup scope", () => {
|
|
|
128
128
|
await rm(wd, { recursive: true, force: true });
|
|
129
129
|
}
|
|
130
130
|
});
|
|
131
|
+
it("does not preserve stale OMX dispatcher metadata as previous notify", async () => {
|
|
132
|
+
const wd = await mkdtemp(join(tmpdir(), "omx-stale-dispatcher-notify-"));
|
|
133
|
+
try {
|
|
134
|
+
await withIsolatedUserHome(wd, async (codexHomeDir) => {
|
|
135
|
+
await mkdir(codexHomeDir, { recursive: true });
|
|
136
|
+
const metadataPath = join(codexHomeDir, ".omx", "notify-dispatch.json");
|
|
137
|
+
const stalePkgRoot = join(wd, "old-global", "oh-my-codex");
|
|
138
|
+
const staleDispatcher = join(stalePkgRoot, "dist", "scripts", "notify-dispatcher.js");
|
|
139
|
+
await mkdir(dirname(metadataPath), { recursive: true });
|
|
140
|
+
await writeFile(join(codexHomeDir, "config.toml"), `notify = ["node", "${staleDispatcher}", "--metadata", "${metadataPath}"]\napproval_policy = "on-failure"\n`);
|
|
141
|
+
await writeFile(metadataPath, JSON.stringify({
|
|
142
|
+
managedBy: "oh-my-codex",
|
|
143
|
+
version: 1,
|
|
144
|
+
previousNotify: [
|
|
145
|
+
"node",
|
|
146
|
+
staleDispatcher,
|
|
147
|
+
"--metadata",
|
|
148
|
+
metadataPath,
|
|
149
|
+
],
|
|
150
|
+
omxNotify: [
|
|
151
|
+
"node",
|
|
152
|
+
join(stalePkgRoot, "dist", "scripts", "notify-hook.js"),
|
|
153
|
+
],
|
|
154
|
+
dispatcherNotify: ["node", staleDispatcher, "--metadata", metadataPath],
|
|
155
|
+
}));
|
|
156
|
+
await withTempCwd(wd, async () => {
|
|
157
|
+
await setup({ scope: "user" });
|
|
158
|
+
});
|
|
159
|
+
const config = await readFile(join(codexHomeDir, "config.toml"), "utf-8");
|
|
160
|
+
assert.match(config, /^notify = \["node", ".*notify-hook\.js"\]$/m);
|
|
161
|
+
assert.doesNotMatch(config, /notify-dispatcher\.js/);
|
|
162
|
+
});
|
|
163
|
+
}
|
|
164
|
+
finally {
|
|
165
|
+
await rm(wd, { recursive: true, force: true });
|
|
166
|
+
}
|
|
167
|
+
});
|
|
168
|
+
it("does not wrap stale global OMX notify hooks as user notify commands", async () => {
|
|
169
|
+
const wd = await mkdtemp(join(tmpdir(), "omx-stale-hook-notify-"));
|
|
170
|
+
try {
|
|
171
|
+
await withIsolatedUserHome(wd, async (codexHomeDir) => {
|
|
172
|
+
await mkdir(codexHomeDir, { recursive: true });
|
|
173
|
+
const staleHook = join("/opt", "homebrew", "lib", "node_modules", "oh-my-codex", "dist", "scripts", "notify-hook.js");
|
|
174
|
+
await writeFile(join(codexHomeDir, "config.toml"), `notify = ["node", "${staleHook}"]\napproval_policy = "on-failure"\n`);
|
|
175
|
+
await withTempCwd(wd, async () => {
|
|
176
|
+
await setup({ scope: "user" });
|
|
177
|
+
});
|
|
178
|
+
const config = await readFile(join(codexHomeDir, "config.toml"), "utf-8");
|
|
179
|
+
assert.match(config, /^notify = \["node", ".*notify-hook\.js"\]$/m);
|
|
180
|
+
assert.doesNotMatch(config, /notify-dispatcher\.js/);
|
|
181
|
+
assert.doesNotMatch(config, /lib\/node_modules\/oh-my-codex\/dist\/scripts\/notify-hook\.js/);
|
|
182
|
+
});
|
|
183
|
+
}
|
|
184
|
+
finally {
|
|
185
|
+
await rm(wd, { recursive: true, force: true });
|
|
186
|
+
}
|
|
187
|
+
});
|
|
131
188
|
});
|
|
132
189
|
async function assertProjectPluginModeArtifacts(wd) {
|
|
133
190
|
const hooks = await readFile(join(wd, ".codex", "hooks.json"), "utf-8");
|
|
134
191
|
assert.match(hooks, /codex-native-hook\.js/);
|
|
135
192
|
const config = await readFile(join(wd, ".codex", "config.toml"), "utf-8");
|
|
136
|
-
assert.match(config, /^
|
|
193
|
+
assert.match(config, /^hooks = true$/m);
|
|
137
194
|
assert.match(config, /^goals = true$/m);
|
|
138
|
-
assert.doesNotMatch(config, /developer_instructions|notify-hook
|
|
195
|
+
assert.doesNotMatch(config, /developer_instructions|notify-hook/g);
|
|
139
196
|
assert.equal(existsSync(join(wd, ".codex", "skills", "ask", "SKILL.md")), false);
|
|
140
197
|
assert.equal(existsSync(join(wd, ".codex", "agents", "planner.toml")), false);
|
|
141
198
|
assert.equal(existsSync(join(wd, ".codex", "prompts", "executor.md")), false);
|
|
@@ -144,6 +201,7 @@ async function assertProjectPluginModeArtifacts(wd) {
|
|
|
144
201
|
assert.deepEqual(persisted, {
|
|
145
202
|
scope: "project",
|
|
146
203
|
installMode: "plugin",
|
|
204
|
+
mcpMode: "none",
|
|
147
205
|
});
|
|
148
206
|
}
|
|
149
207
|
async function captureConsoleOutput(fn) {
|
|
@@ -208,7 +266,7 @@ describe("omx setup install mode behavior", () => {
|
|
|
208
266
|
},
|
|
209
267
|
});
|
|
210
268
|
});
|
|
211
|
-
assert.match(output, /Setup preference review: keep \(scope=user, installMode=legacy\)/);
|
|
269
|
+
assert.match(output, /Setup preference review: keep \(scope=user, installMode=legacy, mcpMode=not recorded\)/);
|
|
212
270
|
assert.match(output, /Using setup scope: user \(from \.omx\/setup-scope\.json\)/);
|
|
213
271
|
assert.match(output, /Using setup install mode: legacy \(from \.omx\/setup-scope\.json\)/);
|
|
214
272
|
});
|
|
@@ -237,7 +295,11 @@ describe("omx setup install mode behavior", () => {
|
|
|
237
295
|
},
|
|
238
296
|
});
|
|
239
297
|
const persisted = JSON.parse(await readFile(join(wd, ".omx", "setup-scope.json"), "utf-8"));
|
|
240
|
-
assert.deepEqual(persisted, {
|
|
298
|
+
assert.deepEqual(persisted, {
|
|
299
|
+
scope: "user",
|
|
300
|
+
installMode: "plugin",
|
|
301
|
+
mcpMode: "none",
|
|
302
|
+
});
|
|
241
303
|
});
|
|
242
304
|
});
|
|
243
305
|
}
|
|
@@ -260,7 +322,7 @@ describe("omx setup install mode behavior", () => {
|
|
|
260
322
|
},
|
|
261
323
|
});
|
|
262
324
|
const persisted = JSON.parse(await readFile(join(wd, ".omx", "setup-scope.json"), "utf-8"));
|
|
263
|
-
assert.deepEqual(persisted, { scope: "project" });
|
|
325
|
+
assert.deepEqual(persisted, { scope: "project", mcpMode: "none" });
|
|
264
326
|
});
|
|
265
327
|
});
|
|
266
328
|
}
|
|
@@ -289,7 +351,11 @@ describe("omx setup install mode behavior", () => {
|
|
|
289
351
|
});
|
|
290
352
|
assert.equal(reviewed, true);
|
|
291
353
|
const persisted = JSON.parse(await readFile(join(wd, ".omx", "setup-scope.json"), "utf-8"));
|
|
292
|
-
assert.deepEqual(persisted, {
|
|
354
|
+
assert.deepEqual(persisted, {
|
|
355
|
+
scope: "user",
|
|
356
|
+
installMode: "plugin",
|
|
357
|
+
mcpMode: "none",
|
|
358
|
+
});
|
|
293
359
|
});
|
|
294
360
|
});
|
|
295
361
|
}
|
|
@@ -318,7 +384,11 @@ describe("omx setup install mode behavior", () => {
|
|
|
318
384
|
});
|
|
319
385
|
assert.equal(reviewed, true);
|
|
320
386
|
const persisted = JSON.parse(await readFile(join(wd, ".omx", "setup-scope.json"), "utf-8"));
|
|
321
|
-
assert.deepEqual(persisted, {
|
|
387
|
+
assert.deepEqual(persisted, {
|
|
388
|
+
scope: "user",
|
|
389
|
+
installMode: "plugin",
|
|
390
|
+
mcpMode: "none",
|
|
391
|
+
});
|
|
322
392
|
});
|
|
323
393
|
});
|
|
324
394
|
}
|
|
@@ -345,7 +415,11 @@ describe("omx setup install mode behavior", () => {
|
|
|
345
415
|
},
|
|
346
416
|
});
|
|
347
417
|
const persisted = JSON.parse(await readFile(join(wd, ".omx", "setup-scope.json"), "utf-8"));
|
|
348
|
-
assert.deepEqual(persisted, {
|
|
418
|
+
assert.deepEqual(persisted, {
|
|
419
|
+
scope: "user",
|
|
420
|
+
installMode: "legacy",
|
|
421
|
+
mcpMode: "none",
|
|
422
|
+
});
|
|
349
423
|
});
|
|
350
424
|
});
|
|
351
425
|
}
|
|
@@ -395,7 +469,43 @@ describe("omx setup install mode behavior", () => {
|
|
|
395
469
|
});
|
|
396
470
|
});
|
|
397
471
|
const persisted = JSON.parse(await readFile(join(wd, ".omx", "setup-scope.json"), "utf-8"));
|
|
398
|
-
assert.deepEqual(persisted, {
|
|
472
|
+
assert.deepEqual(persisted, {
|
|
473
|
+
scope: "user",
|
|
474
|
+
installMode: "plugin",
|
|
475
|
+
mcpMode: "none",
|
|
476
|
+
});
|
|
477
|
+
}
|
|
478
|
+
finally {
|
|
479
|
+
await rm(wd, { recursive: true, force: true });
|
|
480
|
+
}
|
|
481
|
+
});
|
|
482
|
+
it("defaults setup to no first-party MCP blocks", async () => {
|
|
483
|
+
const wd = await mkdtemp(join(tmpdir(), "omx-setup-mcp-mode-"));
|
|
484
|
+
try {
|
|
485
|
+
await withIsolatedUserHome(wd, async (codexHomeDir) => {
|
|
486
|
+
await withTempCwd(wd, async () => {
|
|
487
|
+
await setup({ scope: "user", installMode: "legacy" });
|
|
488
|
+
});
|
|
489
|
+
const config = await readFile(join(codexHomeDir, "config.toml"), "utf-8");
|
|
490
|
+
assert.doesNotMatch(config, /^\[mcp_servers\.omx_state\]$/m);
|
|
491
|
+
});
|
|
492
|
+
}
|
|
493
|
+
finally {
|
|
494
|
+
await rm(wd, { recursive: true, force: true });
|
|
495
|
+
}
|
|
496
|
+
});
|
|
497
|
+
it("emits first-party MCP blocks when compat MCP mode is requested", async () => {
|
|
498
|
+
const wd = await mkdtemp(join(tmpdir(), "omx-setup-mcp-mode-"));
|
|
499
|
+
try {
|
|
500
|
+
await withIsolatedUserHome(wd, async (codexHomeDir) => {
|
|
501
|
+
await withTempCwd(wd, async () => {
|
|
502
|
+
await setup({ scope: "user", installMode: "legacy", mcpMode: "compat" });
|
|
503
|
+
});
|
|
504
|
+
const config = await readFile(join(codexHomeDir, "config.toml"), "utf-8");
|
|
505
|
+
assert.match(config, /^\[mcp_servers\.omx_state\]$/m);
|
|
506
|
+
const persisted = JSON.parse(await readFile(join(wd, ".omx", "setup-scope.json"), "utf-8"));
|
|
507
|
+
assert.equal(persisted.mcpMode, "compat");
|
|
508
|
+
});
|
|
399
509
|
}
|
|
400
510
|
finally {
|
|
401
511
|
await rm(wd, { recursive: true, force: true });
|
|
@@ -411,7 +521,11 @@ describe("omx setup install mode behavior", () => {
|
|
|
411
521
|
await writeFile(join(pluginDir, ".codex-plugin", "plugin.json"), JSON.stringify({ name: "oh-my-codex", version: "local" }));
|
|
412
522
|
await setup({ scope: "user" });
|
|
413
523
|
const persisted = JSON.parse(await readFile(join(wd, ".omx", "setup-scope.json"), "utf-8"));
|
|
414
|
-
assert.deepEqual(persisted, {
|
|
524
|
+
assert.deepEqual(persisted, {
|
|
525
|
+
scope: "user",
|
|
526
|
+
installMode: "plugin",
|
|
527
|
+
mcpMode: "none",
|
|
528
|
+
});
|
|
415
529
|
assert.equal(existsSync(join(codexHomeDir, "skills", "ask", "SKILL.md")), false);
|
|
416
530
|
const hooks = await readFile(join(codexHomeDir, "hooks.json"), "utf-8");
|
|
417
531
|
assert.match(hooks, /codex-native-hook\.js/);
|
|
@@ -474,7 +588,7 @@ describe("omx setup install mode behavior", () => {
|
|
|
474
588
|
});
|
|
475
589
|
assert.equal(promptCalls, 0);
|
|
476
590
|
const persisted = JSON.parse(await readFile(join(wd, ".omx", "setup-scope.json"), "utf-8"));
|
|
477
|
-
assert.deepEqual(persisted, { scope: "project" });
|
|
591
|
+
assert.deepEqual(persisted, { scope: "project", mcpMode: "none" });
|
|
478
592
|
}
|
|
479
593
|
finally {
|
|
480
594
|
await rm(wd, { recursive: true, force: true });
|
|
@@ -488,11 +602,11 @@ describe("omx setup install mode behavior", () => {
|
|
|
488
602
|
await setup({ scope: "user", installMode: "plugin" });
|
|
489
603
|
await setup({ scope: "project" });
|
|
490
604
|
const persisted = JSON.parse(await readFile(join(wd, ".omx", "setup-scope.json"), "utf-8"));
|
|
491
|
-
assert.deepEqual(persisted, { scope: "project" });
|
|
605
|
+
assert.deepEqual(persisted, { scope: "project", mcpMode: "none" });
|
|
492
606
|
assert.equal(existsSync(join(wd, ".codex", "skills", "ask", "SKILL.md")), true);
|
|
493
607
|
await setup({ scope: "project" });
|
|
494
608
|
const repeatedPersisted = JSON.parse(await readFile(join(wd, ".omx", "setup-scope.json"), "utf-8"));
|
|
495
|
-
assert.deepEqual(repeatedPersisted, { scope: "project" });
|
|
609
|
+
assert.deepEqual(repeatedPersisted, { scope: "project", mcpMode: "none" });
|
|
496
610
|
assert.equal(existsSync(join(wd, ".codex", "agents", "planner.toml")), true);
|
|
497
611
|
assert.equal(existsSync(join(wd, ".codex", "prompts", "executor.md")), true);
|
|
498
612
|
});
|
|
@@ -510,7 +624,11 @@ describe("omx setup install mode behavior", () => {
|
|
|
510
624
|
await setup({ scope: "project", installMode: "plugin" });
|
|
511
625
|
await setup({ scope: "user" });
|
|
512
626
|
const persisted = JSON.parse(await readFile(join(wd, ".omx", "setup-scope.json"), "utf-8"));
|
|
513
|
-
assert.deepEqual(persisted, {
|
|
627
|
+
assert.deepEqual(persisted, {
|
|
628
|
+
scope: "user",
|
|
629
|
+
installMode: "legacy",
|
|
630
|
+
mcpMode: "none",
|
|
631
|
+
});
|
|
514
632
|
assert.equal(existsSync(join(codexHomeDir, "skills", "ask", "SKILL.md")), true);
|
|
515
633
|
assert.equal(existsSync(join(codexHomeDir, "agents", "planner.toml")), true);
|
|
516
634
|
assert.equal(existsSync(join(codexHomeDir, "prompts", "executor.md")), true);
|
|
@@ -549,7 +667,11 @@ describe("omx setup install mode behavior", () => {
|
|
|
549
667
|
assert.equal(parsed.marketplaces?.other?.source, "/tmp/other");
|
|
550
668
|
assert.equal((config.match(/^\[marketplaces\.oh-my-codex-local\]$/gm) ?? [])
|
|
551
669
|
.length, 1);
|
|
552
|
-
assert.match(
|
|
670
|
+
assert.equal((config.match(/^\[plugins\."oh-my-codex@oh-my-codex-local"\]$/gm) ?? [])
|
|
671
|
+
.length, 1);
|
|
672
|
+
assert.equal(parsed.plugins?.["oh-my-codex@oh-my-codex-local"]?.enabled, true);
|
|
673
|
+
assert.match(config, /^hooks = true$/m);
|
|
674
|
+
assert.doesNotMatch(config, /^codex_hooks = true$/m);
|
|
553
675
|
assert.doesNotMatch(config, /\[mcp_servers\./);
|
|
554
676
|
assert.equal(existsSync(join(codexHomeDir, "skills", "ask", "SKILL.md")), false);
|
|
555
677
|
assert.equal(existsSync(join(codexHomeDir, "agents", "planner.toml")), false);
|
|
@@ -561,6 +683,67 @@ describe("omx setup install mode behavior", () => {
|
|
|
561
683
|
await rm(wd, { recursive: true, force: true });
|
|
562
684
|
}
|
|
563
685
|
});
|
|
686
|
+
it("enables the local Codex plugin while preserving plugin subtable policy", async () => {
|
|
687
|
+
const wd = await mkdtemp(join(tmpdir(), "omx-setup-install-mode-"));
|
|
688
|
+
try {
|
|
689
|
+
await withIsolatedUserHome(wd, async (codexHomeDir) => {
|
|
690
|
+
await withTempCwd(wd, async () => {
|
|
691
|
+
const configPath = join(codexHomeDir, "config.toml");
|
|
692
|
+
await writeFile(configPath, [
|
|
693
|
+
"[plugins.\"oh-my-codex@oh-my-codex-local\"]",
|
|
694
|
+
"enabled = false",
|
|
695
|
+
"",
|
|
696
|
+
"[plugins.\"oh-my-codex@oh-my-codex-local\".mcp_servers.omx_state]",
|
|
697
|
+
"enabled = false",
|
|
698
|
+
"",
|
|
699
|
+
].join("\n"));
|
|
700
|
+
await setup({ scope: "user", installMode: "plugin", force: true });
|
|
701
|
+
await setup({ scope: "user", installMode: "plugin", force: true });
|
|
702
|
+
const config = await readFile(configPath, "utf-8");
|
|
703
|
+
const parsed = parseToml(config);
|
|
704
|
+
assert.equal((config.match(/^\[plugins\."oh-my-codex@oh-my-codex-local"\]$/gm) ?? [])
|
|
705
|
+
.length, 1);
|
|
706
|
+
assert.equal(parsed.plugins?.["oh-my-codex@oh-my-codex-local"]?.enabled, true);
|
|
707
|
+
assert.equal(parsed.plugins?.["oh-my-codex@oh-my-codex-local"]?.mcp_servers
|
|
708
|
+
?.omx_state?.enabled, false);
|
|
709
|
+
});
|
|
710
|
+
});
|
|
711
|
+
}
|
|
712
|
+
finally {
|
|
713
|
+
await rm(wd, { recursive: true, force: true });
|
|
714
|
+
}
|
|
715
|
+
});
|
|
716
|
+
it("enables plugin MCP subtables only when compat MCP mode is requested", async () => {
|
|
717
|
+
const wd = await mkdtemp(join(tmpdir(), "omx-setup-install-mode-"));
|
|
718
|
+
try {
|
|
719
|
+
await withIsolatedUserHome(wd, async (codexHomeDir) => {
|
|
720
|
+
await withTempCwd(wd, async () => {
|
|
721
|
+
const configPath = join(codexHomeDir, "config.toml");
|
|
722
|
+
await setup({
|
|
723
|
+
scope: "user",
|
|
724
|
+
installMode: "plugin",
|
|
725
|
+
mcpMode: "compat",
|
|
726
|
+
force: true,
|
|
727
|
+
});
|
|
728
|
+
let parsed = parseToml(await readFile(configPath, "utf-8"));
|
|
729
|
+
assert.equal(parsed.plugins?.["oh-my-codex@oh-my-codex-local"]?.mcp_servers
|
|
730
|
+
?.omx_state?.enabled, true);
|
|
731
|
+
await setup({
|
|
732
|
+
scope: "user",
|
|
733
|
+
installMode: "plugin",
|
|
734
|
+
mcpMode: "none",
|
|
735
|
+
force: true,
|
|
736
|
+
});
|
|
737
|
+
parsed = parseToml(await readFile(configPath, "utf-8"));
|
|
738
|
+
assert.equal(parsed.plugins?.["oh-my-codex@oh-my-codex-local"]?.mcp_servers
|
|
739
|
+
?.omx_state?.enabled, false);
|
|
740
|
+
});
|
|
741
|
+
});
|
|
742
|
+
}
|
|
743
|
+
finally {
|
|
744
|
+
await rm(wd, { recursive: true, force: true });
|
|
745
|
+
}
|
|
746
|
+
});
|
|
564
747
|
it("reports plugin marketplace registration during dry-run without mutating config", async () => {
|
|
565
748
|
const wd = await mkdtemp(join(tmpdir(), "omx-setup-install-mode-"));
|
|
566
749
|
try {
|
|
@@ -593,13 +776,13 @@ describe("omx setup install mode behavior", () => {
|
|
|
593
776
|
const parsed = parseToml(config);
|
|
594
777
|
const managedHookStateKeys = Object.keys(parsed.hooks?.state ?? {}).filter((key) => key.includes(`${codexHomeDir}/hooks.json:`));
|
|
595
778
|
assert.equal(managedHookStateKeys.length, 7);
|
|
596
|
-
assert.match(config, /^
|
|
597
|
-
assert.doesNotMatch(config, /^
|
|
779
|
+
assert.match(config, /^hooks = true$/m);
|
|
780
|
+
assert.doesNotMatch(config, /^codex_hooks = true$/m);
|
|
598
781
|
assert.match(config, /^goals = true$/m);
|
|
599
782
|
assert.match(config, /^\[hooks\.state\.".*hooks\.json:pre_tool_use:0:0"\]$/m);
|
|
600
783
|
assert.equal((config.match(/^\[hooks\.state\.".*hooks\.json:pre_tool_use:0:0"\]$/gm) ?? []).length, 1);
|
|
601
784
|
assert.match(config, /^trusted_hash = "sha256:[a-f0-9]{64}"$/m);
|
|
602
|
-
assert.doesNotMatch(config, /developer_instructions|notify-hook
|
|
785
|
+
assert.doesNotMatch(config, /developer_instructions|notify-hook/g);
|
|
603
786
|
assert.equal(existsSync(join(codexHomeDir, "skills", "ask", "SKILL.md")), false);
|
|
604
787
|
assert.equal(existsSync(join(codexHomeDir, "agents", "planner.toml")), false);
|
|
605
788
|
assert.equal(existsSync(join(codexHomeDir, "prompts", "executor.md")), false);
|
|
@@ -634,8 +817,10 @@ describe("omx setup install mode behavior", () => {
|
|
|
634
817
|
assert.match(config, /Setup-owned prompt files and native-agent TOML defaults are intentionally omitted unless explicitly installed/);
|
|
635
818
|
assert.doesNotMatch(config, /Native subagents live in \.codex\/agents/);
|
|
636
819
|
assert.doesNotMatch(config, /Treat installed prompts as narrower execution surfaces/);
|
|
637
|
-
assert.match(config, /^
|
|
638
|
-
assert.doesNotMatch(config, /notify-hook
|
|
820
|
+
assert.match(config, /^hooks = true$/m);
|
|
821
|
+
assert.doesNotMatch(config, /notify-hook/);
|
|
822
|
+
assert.doesNotMatch(config, /^\s*\[mcp_servers[.\]]/m);
|
|
823
|
+
assert.match(config, /mcp_servers\.omx_state]\nenabled = false/);
|
|
639
824
|
const agentsMd = await readFile(join(codexHomeDir, "AGENTS.md"), "utf-8");
|
|
640
825
|
assert.match(agentsMd, /oh-my-codex - Intelligent Multi-Agent Orchestration/);
|
|
641
826
|
assert.match(agentsMd, /<!-- omx:generated:agents-md -->/);
|
|
@@ -695,7 +880,7 @@ describe("omx setup install mode behavior", () => {
|
|
|
695
880
|
});
|
|
696
881
|
const config = await readFile(configPath, "utf-8");
|
|
697
882
|
assert.match(config, /^developer_instructions = "custom"$/m);
|
|
698
|
-
assert.match(config, /^
|
|
883
|
+
assert.match(config, /^hooks = true$/m);
|
|
699
884
|
assert.equal((config.match(/^developer_instructions\s*=/gm) ?? []).length, 1);
|
|
700
885
|
});
|
|
701
886
|
});
|
|
@@ -721,7 +906,7 @@ describe("omx setup install mode behavior", () => {
|
|
|
721
906
|
assert.match(config, /You have oh-my-codex installed/);
|
|
722
907
|
assert.doesNotMatch(config, /^developer_instructions = "custom"$/m);
|
|
723
908
|
assert.equal((config.match(/^developer_instructions\s*=/gm) ?? []).length, 1);
|
|
724
|
-
assert.match(config, /^
|
|
909
|
+
assert.match(config, /^hooks = true$/m);
|
|
725
910
|
assert.match(config, /^\[hooks\.state\.".*hooks\.json:pre_tool_use:0:0"\]$/m);
|
|
726
911
|
});
|
|
727
912
|
});
|
|
@@ -730,6 +915,27 @@ describe("omx setup install mode behavior", () => {
|
|
|
730
915
|
await rm(wd, { recursive: true, force: true });
|
|
731
916
|
}
|
|
732
917
|
});
|
|
918
|
+
it("uses legacy codex_hooks only when the installed Codex reports that hook feature", async () => {
|
|
919
|
+
const wd = await mkdtemp(join(tmpdir(), "omx-setup-install-mode-"));
|
|
920
|
+
try {
|
|
921
|
+
await withIsolatedUserHome(wd, async (codexHomeDir) => {
|
|
922
|
+
await withTempCwd(wd, async () => {
|
|
923
|
+
await setup({
|
|
924
|
+
scope: "user",
|
|
925
|
+
installMode: "plugin",
|
|
926
|
+
codexFeaturesProbe: () => "codex_hooks experimental true\n",
|
|
927
|
+
codexVersionProbe: () => "codex-cli 0.129.0",
|
|
928
|
+
});
|
|
929
|
+
const config = await readFile(join(codexHomeDir, "config.toml"), "utf-8");
|
|
930
|
+
assert.match(config, /^codex_hooks = true$/m);
|
|
931
|
+
assert.doesNotMatch(config, /^hooks = true$/m);
|
|
932
|
+
});
|
|
933
|
+
});
|
|
934
|
+
}
|
|
935
|
+
finally {
|
|
936
|
+
await rm(wd, { recursive: true, force: true });
|
|
937
|
+
}
|
|
938
|
+
});
|
|
733
939
|
it("preserves existing user hooks while installing plugin-mode native hooks", async () => {
|
|
734
940
|
const wd = await mkdtemp(join(tmpdir(), "omx-setup-install-mode-"));
|
|
735
941
|
try {
|
|
@@ -743,7 +949,7 @@ describe("omx setup install mode behavior", () => {
|
|
|
743
949
|
assert.match(hooks, /"UserPromptSubmit"/);
|
|
744
950
|
assert.match(hooks, /codex-native-hook\.js/);
|
|
745
951
|
const config = await readFile(join(codexHomeDir, "config.toml"), "utf-8");
|
|
746
|
-
assert.match(config, /^
|
|
952
|
+
assert.match(config, /^hooks = true$/m);
|
|
747
953
|
});
|
|
748
954
|
});
|
|
749
955
|
}
|
|
@@ -760,6 +966,7 @@ describe("omx setup install mode behavior", () => {
|
|
|
760
966
|
assert.deepEqual(persisted, {
|
|
761
967
|
scope: "project",
|
|
762
968
|
installMode: "plugin",
|
|
969
|
+
mcpMode: "none",
|
|
763
970
|
});
|
|
764
971
|
await setup({ scope: "project" });
|
|
765
972
|
assert.equal(existsSync(join(wd, ".codex", "skills", "ask", "SKILL.md")), false);
|
|
@@ -781,7 +988,7 @@ describe("omx setup install mode behavior", () => {
|
|
|
781
988
|
await writeFile(join(wd, ".omx", "setup-scope.json"), JSON.stringify({ scope: "project", installMode: "plugin" }));
|
|
782
989
|
await setup({ scope: "project", installMode: "legacy" });
|
|
783
990
|
const persisted = JSON.parse(await readFile(join(wd, ".omx", "setup-scope.json"), "utf-8"));
|
|
784
|
-
assert.deepEqual(persisted, { scope: "project" });
|
|
991
|
+
assert.deepEqual(persisted, { scope: "project", mcpMode: "none" });
|
|
785
992
|
assert.equal(existsSync(join(wd, ".codex", "skills", "ask", "SKILL.md")), true);
|
|
786
993
|
assert.equal(existsSync(join(wd, ".codex", "agents", "planner.toml")), true);
|
|
787
994
|
assert.equal(existsSync(join(wd, ".codex", "prompts", "executor.md")), true);
|
|
@@ -803,6 +1010,7 @@ describe("omx setup install mode behavior", () => {
|
|
|
803
1010
|
assert.deepEqual(persisted, {
|
|
804
1011
|
scope: "user",
|
|
805
1012
|
installMode: "legacy",
|
|
1013
|
+
mcpMode: "none",
|
|
806
1014
|
});
|
|
807
1015
|
assert.equal(existsSync(join(codexHomeDir, "skills", "ask", "SKILL.md")), true);
|
|
808
1016
|
assert.equal(existsSync(join(codexHomeDir, "agents", "planner.toml")), true);
|
|
@@ -814,6 +1022,44 @@ describe("omx setup install mode behavior", () => {
|
|
|
814
1022
|
await rm(wd, { recursive: true, force: true });
|
|
815
1023
|
}
|
|
816
1024
|
});
|
|
1025
|
+
it("dedupes plugin-mode hook trust state when switching user setup back to legacy", async () => {
|
|
1026
|
+
const wd = await mkdtemp(join(tmpdir(), "omx-setup-install-mode-"));
|
|
1027
|
+
try {
|
|
1028
|
+
await withIsolatedUserHome(wd, async (codexHomeDir) => {
|
|
1029
|
+
await withTempCwd(wd, async () => {
|
|
1030
|
+
const configPath = join(codexHomeDir, "config.toml");
|
|
1031
|
+
await setup({ scope: "user", installMode: "plugin", force: true });
|
|
1032
|
+
const pluginConfig = await readFile(configPath, "utf-8");
|
|
1033
|
+
const staleUnfencedPluginConfig = pluginConfig
|
|
1034
|
+
.split(/\r?\n/)
|
|
1035
|
+
.filter((line) => line.trim() !== "# OMX-owned Codex hook trust state" &&
|
|
1036
|
+
line.trim() !==
|
|
1037
|
+
"# Trusts only setup-managed codex-native-hook.js wrappers." &&
|
|
1038
|
+
line.trim() !== "# End OMX-owned Codex hook trust state")
|
|
1039
|
+
.join("\n");
|
|
1040
|
+
await writeFile(configPath, staleUnfencedPluginConfig);
|
|
1041
|
+
assert.doesNotThrow(() => parseToml(staleUnfencedPluginConfig));
|
|
1042
|
+
await setup({ scope: "user", installMode: "legacy", force: true });
|
|
1043
|
+
const legacyConfig = await readFile(configPath, "utf-8");
|
|
1044
|
+
assert.doesNotThrow(() => parseToml(legacyConfig));
|
|
1045
|
+
assert.equal(legacyConfig
|
|
1046
|
+
.split(/\r?\n/)
|
|
1047
|
+
.filter((line) => line.trim() ===
|
|
1048
|
+
`[hooks.state."${join(codexHomeDir, "hooks.json")}:post_compact:0:0"]`).length, 1, "legacy setup should replace stale plugin-mode hook trust state instead of duplicating it");
|
|
1049
|
+
assert.match(legacyConfig, /# OMX-owned Codex hook trust state[\s\S]*# End OMX-owned Codex hook trust state/);
|
|
1050
|
+
const persisted = JSON.parse(await readFile(join(wd, ".omx", "setup-scope.json"), "utf-8"));
|
|
1051
|
+
assert.deepEqual(persisted, {
|
|
1052
|
+
scope: "user",
|
|
1053
|
+
installMode: "legacy",
|
|
1054
|
+
mcpMode: "none",
|
|
1055
|
+
});
|
|
1056
|
+
});
|
|
1057
|
+
});
|
|
1058
|
+
}
|
|
1059
|
+
finally {
|
|
1060
|
+
await rm(wd, { recursive: true, force: true });
|
|
1061
|
+
}
|
|
1062
|
+
});
|
|
817
1063
|
it("installs project-scoped native hooks when plugin mode is explicitly requested", async () => {
|
|
818
1064
|
const wd = await mkdtemp(join(tmpdir(), "omx-setup-install-mode-"));
|
|
819
1065
|
try {
|
|
@@ -902,7 +1148,7 @@ describe("omx setup install mode behavior", () => {
|
|
|
902
1148
|
const hooks = await readFile(hooksPath, "utf-8");
|
|
903
1149
|
assert.match(hooks, /codex-native-hook\.js/);
|
|
904
1150
|
const config = await readFile(configPath, "utf-8");
|
|
905
|
-
assert.match(config, /^
|
|
1151
|
+
assert.match(config, /^hooks = true$/m);
|
|
906
1152
|
assert.doesNotMatch(config, /^\s*(?:notify|developer_instructions)\s*=|^\s*\[mcp_servers[.\]]/m);
|
|
907
1153
|
});
|
|
908
1154
|
});
|