diff --git a/packages/codex-plugin/.codex-plugin/plugin.json b/packages/codex-plugin/.codex-plugin/plugin.json index a21ebe5..eae1474 100644 --- a/packages/codex-plugin/.codex-plugin/plugin.json +++ b/packages/codex-plugin/.codex-plugin/plugin.json @@ -35,7 +35,8 @@ "Read" ], "websiteURL": "https://judgmentkit.ai", - "brandColor": "#255C99", + "brandColor": "#0B0D0E", + "brandColorDark": "#F7F6F2", "defaultPrompt": [ "Make a first UI pass from this brief. Infer what you can, show the working premise and key decisions, and ask only if a missing decision would materially change the design.", "Turn this sanitized Figma or generated screen into a reviewed activity case and implementation handoff.", diff --git a/scripts/verify-codex-plugin.mjs b/scripts/verify-codex-plugin.mjs index 0909b99..1ff9791 100644 --- a/scripts/verify-codex-plugin.mjs +++ b/scripts/verify-codex-plugin.mjs @@ -18,6 +18,12 @@ export const DEFAULT_CANONICAL_SKILL_DIR = path.join( export const CODEX_PLUGIN_MCP_URL = "https://judgmentkit.ai/mcp"; export const STRICT_BASE_SEMVER_PATTERN = /^\d+\.\d+\.\d+$/; +// Approved Ink/Ivory palette in brand/slab-j/README.md. +const CANONICAL_PLUGIN_COLORS = { + brandColor: "#0B0D0E", + brandColorDark: "#F7F6F2", +}; + export const PORTABLE_SKILL_FILES = [ "SKILL.md", "references/ui-handoff-and-acceptance.md", @@ -395,6 +401,16 @@ function collectMissingWordingFailures({ skillText, uiReferenceText, deckReferen function collectManifestFailures(pluginJson) { const failures = []; + for (const [field, expected] of Object.entries(CANONICAL_PLUGIN_COLORS)) { + if (pluginJson?.interface?.[field] !== expected) { + failures.push({ + check: "canonical_brand_colors", + file: ".codex-plugin/plugin.json", + message: `Plugin manifest interface.${field} must use canonical color ${expected}.`, + }); + } + } + if (pluginJson?.name !== "judgmentkit") { failures.push({ check: "plugin_manifest", diff --git a/tests/codex-plugin.test.mjs b/tests/codex-plugin.test.mjs index d8d7378..4928250 100644 --- a/tests/codex-plugin.test.mjs +++ b/tests/codex-plugin.test.mjs @@ -69,6 +69,8 @@ async function createFixture(overrides = {}) { category: "Productivity", capabilities: ["Interactive", "Read"], websiteURL: "https://judgmentkit.ai", + brandColor: "#0B0D0E", + brandColorDark: "#F7F6F2", defaultPrompt: overrides.pluginDefaultPrompt ?? ["Make a first UI pass, show the working premise, and ask only if a missing decision would materially change the design."], @@ -190,6 +192,22 @@ for (const phrase of [ assert.ok(result.files_checked.includes("skills/judgmentkit-hosted-mcp/agents/openai.yaml")); } +for (const field of ["brandColor", "brandColorDark"]) { + for (const value of [undefined, "#255C99"]) { + const fixture = await createFixture(); + const manifestPath = path.join(fixture.sourceDir, ".codex-plugin", "plugin.json"); + const manifest = await readJson(manifestPath); + if (value === undefined) delete manifest.interface[field]; + else manifest.interface[field] = value; + await writeJson(manifestPath, manifest); + + await assertVerifyRejects( + { sourceDir: fixture.sourceDir, packageJsonPath: fixture.packageJsonPath }, + ["canonical_brand_colors"], + ); + } +} + { const fixture = await createFixture({ pluginVersion: "1.2.4" }); await assertVerifyRejects(