From a3567056c096b53d7b3b11f779f01a3759adfccb Mon Sep 17 00:00:00 2001 From: YeonGyu-Kim Date: Wed, 27 May 2026 16:43:23 +0900 Subject: [PATCH] test(omo-codex): allow rules resource manifest The aggregate plugin test originally asserted that every component lacked .codex-plugin/plugin.json. That was correct when omo was only an aggregate Codex namespace: the root manifest owned plugin identity and components were implementation details. PLUGIN_BUNDLED changes the invariant for rules. The rules component now ships bundled-rules/hephaestus.md and uses a plugin-root marker to resolve bundled resources when it runs as a component package, while Codex still sees the aggregate omo manifest as the installable plugin. Chose Path A and touched only packages/omo-codex/plugin/test/aggregate.test.mjs. The test now allowlists the rules manifest and still asserts every other component has no plugin manifest, preventing accidental sprawl. Verified npm test from packages/omo-codex/plugin, bun run test:codex, and bun test src/cli/install-codex/. bun run test:codex exits 0 and covers the Linux, macOS, and Windows Codex adapter code paths. --- packages/omo-codex/plugin/test/aggregate.test.mjs | 9 ++++++++- 1 file changed, 8 insertions(+), 1 deletion(-) diff --git a/packages/omo-codex/plugin/test/aggregate.test.mjs b/packages/omo-codex/plugin/test/aggregate.test.mjs index 8adc56363..cf7630d52 100644 --- a/packages/omo-codex/plugin/test/aggregate.test.mjs +++ b/packages/omo-codex/plugin/test/aggregate.test.mjs @@ -83,9 +83,10 @@ test("#given aggregate plugin build script #when inspected #then telemetry sync assert.match(telemetrySyncScript, /syncTelemetryComponent/); }); -test("#given component directories #when scanned #then only root owns plugin identity", async () => { +test("#given component directories #when scanned #then only intentional resource roots declare plugin manifests", async () => { // given const components = await readdir(join(root, "components"), { withFileTypes: true }); + const expectedComponentManifests = new Map([["rules", { hooks: "./hooks/hooks.json" }]]); // when const componentNames = components.filter((entry) => entry.isDirectory()).map((entry) => entry.name).sort(); @@ -93,6 +94,12 @@ test("#given component directories #when scanned #then only root owns plugin ide // then assert.deepEqual(componentNames, ["comment-checker", "lsp", "rules", "telemetry", "ultragoal", "ultrawork"]); for (const name of componentNames) { + const expectedManifest = expectedComponentManifests.get(name); + if (expectedManifest !== undefined) { + assert.deepEqual(await readJson(join("components", name, ".codex-plugin", "plugin.json")), expectedManifest); + continue; + } + await assert.rejects( readFile(join(root, "components", name, ".codex-plugin", "plugin.json"), "utf8"), /code: 'ENOENT'|ENOENT/,