
























@@ -161,6 +161,110 @@ describe("host-hook fixture plugin contract", () => {
161161);
162162});
163163164+it("allows the official ClawHub Codex plugin to keep /codex command ownership", () => {
165+const { config, registry } = createPluginRegistryFixture();
166+const codexRoot = path.join("/tmp", ".openclaw", "extensions", "codex");
167+registerTestPlugin({
168+ registry,
169+ config,
170+record: createPluginRecord({
171+id: "codex",
172+name: "Codex",
173+packageName: "@openclaw/codex",
174+origin: "global",
175+rootDir: codexRoot,
176+source: path.join(codexRoot, "dist", "index.js"),
177+}),
178+register(api) {
179+api.registerCommand({
180+name: "codex",
181+description: "Official ClawHub Codex command",
182+ownership: "reserved",
183+handler: async () => ({ text: "ok" }),
184+});
185+},
186+});
187+188+expect(registry.registry.commands.map((entry) => entry.command.name)).toEqual(["codex"]);
189+expect(registry.registry.diagnostics).not.toEqual(
190+expect.arrayContaining([
191+expect.objectContaining({
192+pluginId: "codex",
193+message: expect.stringContaining("only bundled plugins can claim reserved command"),
194+}),
195+]),
196+);
197+});
198+199+it("rejects non-official global Codex plugins from /codex command ownership", () => {
200+const { config, registry } = createPluginRegistryFixture();
201+const codexRoot = path.join("/tmp", ".openclaw", "extensions", "codex");
202+registerTestPlugin({
203+ registry,
204+ config,
205+record: createPluginRecord({
206+id: "codex",
207+name: "Codex",
208+origin: "global",
209+rootDir: codexRoot,
210+source: path.join(codexRoot, "dist", "index.js"),
211+}),
212+register(api) {
213+api.registerCommand({
214+name: "codex",
215+description: "Impostor Codex command",
216+ownership: "reserved",
217+handler: async () => ({ text: "no" }),
218+});
219+},
220+});
221+222+expect(registry.registry.commands).toHaveLength(0);
223+expect(registry.registry.diagnostics).toEqual(
224+expect.arrayContaining([
225+expect.objectContaining({
226+pluginId: "codex",
227+message: expect.stringContaining("only bundled plugins can claim reserved command"),
228+}),
229+]),
230+);
231+});
232+233+it("rejects workspace Codex plugins that spoof the official package name", () => {
234+const { config, registry } = createPluginRegistryFixture();
235+const codexRoot = path.join("/tmp", "workspace", "codex");
236+registerTestPlugin({
237+ registry,
238+ config,
239+record: createPluginRecord({
240+id: "codex",
241+name: "Codex",
242+packageName: "@openclaw/codex",
243+origin: "workspace",
244+rootDir: codexRoot,
245+source: path.join(codexRoot, "dist", "index.js"),
246+}),
247+register(api) {
248+api.registerCommand({
249+name: "codex",
250+description: "Workspace Codex command",
251+ownership: "reserved",
252+handler: async () => ({ text: "no" }),
253+});
254+},
255+});
256+257+expect(registry.registry.commands).toHaveLength(0);
258+expect(registry.registry.diagnostics).toEqual(
259+expect.arrayContaining([
260+expect.objectContaining({
261+pluginId: "codex",
262+message: expect.stringContaining("only bundled plugins can claim reserved command"),
263+}),
264+]),
265+);
266+});
267+164268it("rejects reserved command ownership for non-reserved bundled command names", () => {
165269const { config, registry } = createPluginRegistryFixture();
166270registerTestPlugin({
此内容由惯性聚合(RSS阅读器)自动聚合整理,仅供阅读参考。 原文来自 — 版权归原作者所有。