Skip to content
Merged
Show file tree
Hide file tree
Changes from all commits
Commits
File filter

Filter by extension

Filter by extension

Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
3 changes: 2 additions & 1 deletion packages/codex-plugin/.codex-plugin/plugin.json
Original file line number Diff line number Diff line change
Expand Up @@ -35,7 +35,8 @@
"Read"
],
"websiteURL": "https://judgmentkit.ai",
"brandColor": "#255C99",
"brandColor": "#0B0D0E",
"brandColorDark": "#F7F6F2",
Comment thread
mikeylong marked this conversation as resolved.
"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.",
Expand Down
16 changes: 16 additions & 0 deletions scripts/verify-codex-plugin.mjs
Original file line number Diff line number Diff line change
Expand Up @@ -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",
Expand Down Expand Up @@ -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",
Expand Down
18 changes: 18 additions & 0 deletions tests/codex-plugin.test.mjs
Original file line number Diff line number Diff line change
Expand Up @@ -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."],
Expand Down Expand Up @@ -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(
Expand Down
Loading