Some checks failed
App Prod-Parity E2E Dispatch / dispatch (push) Failing after 10s
CD Storybook UI / build (push) Failing after 3m25s
CD Storybook UI / dispatch (push) Has been skipped
CD deploy main / website-changed-files (push) Successful in 18m8s
CI Agent Skills / changed-files-check (push) Successful in 18m9s
CI Create App E2E minimal / changed-files-check (push) Successful in 24s
CI Create App / changed-files-check (push) Successful in 26s
CI Docs / changed-files-check (push) Successful in 26s
CI Emails / changed-files-check (push) Successful in 28s
CI Example App Hello World / changed-files-check (push) Successful in 23s
CI Front / changed-files-check (push) Has been skipped
CI Example App Postcard / changed-files-check (push) Successful in 27s
CI UI / changed-files-check (push) Has been skipped
CI Utils Test / changed-files-check (push) Successful in 45s
CI Twenty Apps / discover (push) Successful in 1m3s
CD deploy main / deploy-main (push) Failing after 3s
CI Agent Skills / agent-skills-validate (push) Has been skipped
CI Create App / create-app-test (lint) (push) Has been skipped
CI Emails / emails-test (push) Has been skipped
CI Front / front-task (lingui:compile) (push) Has been skipped
CI Front / front-task (lint) (push) Has been skipped
CI Example App Postcard / example-app-postcard (push) Has been skipped
CI UI / ui-task (lint) (push) Has been skipped
CI UI / ui-task (pack-size) (push) Has been skipped
CI UI / ui-task (size) (push) Has been skipped
CI UI / ui-task (test) (push) Has been skipped
CI UI / ui-task (typecheck) (push) Has been skipped
CI Utils Test / utils-test (push) Has been skipped
CI Twenty Apps / ${{ matrix.app.name }} (push) Has been skipped
CI Emails / ci-emails-status-check (push) Successful in 2s
CI Example App Hello World / ci-example-app-hello-world-status-check (push) Successful in 2s
CI Example App Postcard / ci-example-app-postcard-status-check (push) Successful in 3s
CI UI / ui-sb-test (push) Has been skipped
CI Utils Test / ci-utils-test-status-check (push) Successful in 2s
CI Twenty Apps / ci-twenty-apps-status-check (push) Successful in 2s
CI UI / ci-ui-status-check (push) Successful in 2s
CI Desktop / desktop (push) Failing after 1m8s
Push docs to Crowdin / Push documentation to Crowdin (push) Failing after 55s
Push translations to Crowdin / Extract and upload translations (push) Failing after 5s
Push website translations to Crowdin / Extract and upload website translations (push) Failing after 5s
CI Create App / create-app-test (test) (push) Has been skipped
CI Create App / create-app-test (typecheck) (push) Has been skipped
CI Docs / docs-lint (push) Has been skipped
CI Example App Hello World / example-app-hello-world (push) Has been skipped
CI Front / front-task (lingui:extract) (push) Has been skipped
CI Front / front-task (test) (push) Has been skipped
CI Front / front-task (typecheck) (push) Has been skipped
CI UI / ui-sb-build (push) Failing after 1m32s
CI Twenty Apps / ${{ matrix.app.name }} (${{ matrix.server-source }}) (push) Has been skipped
CI Agent Skills / agent-skills-publish (push) Has been skipped
CI Create App / ci-create-app-status-check (push) Successful in 2s
CI Agent Skills / agent-skills-remote-source (push) Has been skipped
CI Create App E2E minimal / create-app-e2e-minimal (push) Has been cancelled
CI E2E Main / e2e-test (push) Has been cancelled
CI Front / front-sb-build (push) Has been cancelled
CI Front / front-build (push) Has been cancelled
CI Create App E2E minimal / ci-create-app-e2e-minimal-status-check (push) Has been cancelled
CI E2E Main / ci-e2e-main-status-check (push) Has been cancelled
CI E2E Main / notify-main-ci-failure (push) Has been cancelled
CI E2E Main / qa-scout-comment (push) Has been cancelled
CI Front / front-sb-test (push) Has been cancelled
CI Front / front-sb-screenshots (push) Has been cancelled
CI Front / ci-front-status-check (push) Has been cancelled
DPA Sub-Processor Sync / sync-subprocessors (push) Failing after 3s
AI Catalog Sync / sync-catalog (push) Failing after 2s
114 lines
14 KiB
Markdown
114 lines
14 KiB
Markdown
# Twenty Codex Plugin — Best Practices Compliance Checklist
|
||
|
||
This file is the authoritative compliance matrix. Every row maps an official requirement (Codex build guide, Codex best-practices guide, or OpenAI reference implementation) to either an **automated** check (a `scripts/validate-source.js` assertion function) or a **manual** sign-off.
|
||
|
||
A release is shippable when:
|
||
|
||
1. `npx nx run twenty-agent-skills:validate` and `npx nx run twenty-agent-skills:build` exit 0 (source and distribution checks pass).
|
||
2. Every `[manual]` row has a current sign-off date.
|
||
|
||
## Sources of Truth
|
||
|
||
- **Codex Plugin Build Guide** — https://developers.openai.com/codex/plugins/build
|
||
- **Codex Best Practices** — https://developers.openai.com/codex/learn/best-practices
|
||
- **Reference Implementation** — https://github.com/openai/codex-plugin-cc
|
||
|
||
## Plugin Manifest (`.codex-plugin/plugin.json`)
|
||
|
||
| # | Requirement | Source | Check |
|
||
| --- | ----------------------------------------------------------------------- | ---------------------------- | ----------------------------------------------------------------------- |
|
||
| M1 | `name` present, kebab-case, lowercase | Build guide §Naming | [automated] `assertJsonMetadata` |
|
||
| M2 | `version` follows SemVer and matches `package.json` | Build guide §Manifest | [automated] `assertJsonMetadata` |
|
||
| M3 | `description` present and concise | Build guide §Required fields | [automated] `assertInterfaceFields` (planned) |
|
||
| M4 | `mcpServers` points at `./.mcp.json` | Build guide §MCP | [automated] `assertJsonMetadata` |
|
||
| M5 | `skills` points at `./skills/` | Build guide §Skills | [automated] `assertJsonMetadata` |
|
||
| M6 | `interface.displayName` present and non-empty | Build guide §Interface | [automated] `assertInterfaceFields` (planned) |
|
||
| M7 | `interface.shortDescription` ≤ 64 chars | Build guide §Marketplace | [automated] `assertInterfaceFields` (planned) |
|
||
| M8 | `interface.longDescription` present, multi-sentence | Build guide §Marketplace | [automated] `assertInterfaceFields` (planned) |
|
||
| M9 | `interface.category` matches marketplace enum (`Coding`) | Build guide §Marketplace | [automated] `assertInterfaceFields` (planned) |
|
||
| M10 | `interface.capabilities` non-empty subset of `Interactive,Read,Write` | Build guide §Capabilities | [automated] `assertInterfaceFields` (planned) |
|
||
| M11 | `interface.websiteURL`, `privacyPolicyURL`, `termsOfServiceURL` present | Build guide §Publisher links | [automated] `assertInterfaceFields` (planned) |
|
||
| M12 | `interface.brandColor` matches `#RRGGBB` and reflects Twenty brand | Build guide §Marketplace | [automated] `assertInterfaceFields` (planned), [manual] brand alignment |
|
||
| M13 | `interface.defaultPrompt` is a non-empty array of strings | Build guide §Defaults | [automated] `assertInterfaceFields` (planned) |
|
||
| M14 | All manifest paths start with `./` and stay within plugin root | Build guide §Paths | [automated] `assertJsonMetadata` |
|
||
|
||
## Assets (`assets/`)
|
||
|
||
| # | Requirement | Source | Check |
|
||
| --- | ------------------------------------------------------------- | ------------------------ | ---------------------------------------------------- |
|
||
| A1 | `interface.logo` exists and is PNG | Build guide §Assets | [automated] `assertAssets` (planned) |
|
||
| A2 | Logo PNG is ≥ 256×256 | Build guide §Assets | [automated] `assertAssets` (planned, PNG IHDR parse) |
|
||
| A3 | `interface.composerIcon` exists and is valid SVG or PNG | Build guide §Assets | [automated] `assertAssets` (planned) |
|
||
| A4 | `interface.screenshots` has ≥ 1 entry | Build guide §Assets | [automated] `assertAssets` (planned) |
|
||
| A5 | Every screenshot path exists and is PNG | Build guide §Assets | [automated] `assertAssets` (planned) |
|
||
| A6 | Screenshots show the plugin in action (not placeholder mocks) | Build guide §Marketplace | [manual] reviewer sign-off |
|
||
|
||
## Skills (`skills/<name>/SKILL.md`)
|
||
|
||
| # | Requirement | Source | Check |
|
||
| --- | -------------------------------------------------------------------------------------------------------------------------- | ---------------------------- | ------------------------------------------------- |
|
||
| S1 | Canonical five skills present | Internal convention | [automated] `assertSkills` |
|
||
| S2 | No legacy skill names anywhere | Internal convention | [automated] `assertNoLegacySkillReferences` |
|
||
| S3 | Each `SKILL.md` has YAML frontmatter with `name` + `description` only | Build guide §Skills | [automated] `assertSkills` |
|
||
| S4 | Frontmatter `name` matches directory | Build guide §Skills | [automated] `assertSkills` |
|
||
| S5 | Each skill has `agents/openai.yaml` with `display_name`, `short_description` (≤64), `default_prompt` (mentions `$<skill>`) | OpenAI Agent format | [automated] `assertSkills` |
|
||
| S6 | Each skill is scoped to a single job with clear boundaries | Best practices §Skill scope | [manual] cross-skill audit |
|
||
| S7 | Each skill includes a `## When to use` trigger-phrase section | Best practices §Descriptions | [automated] `assertSkillTriggerPhrases` (planned) |
|
||
| S8 | Descriptions are disjoint across skills (no routing collision) | Best practices §Descriptions | [manual] cross-skill audit |
|
||
|
||
## References (`references/`)
|
||
|
||
| # | Requirement | Source | Check |
|
||
| --- | --------------------------------------------------------------------------------------------------------------------------------------------------------------- | ------------------- | ----------------------------------------------- |
|
||
| R1 | All required reference files exist | Internal convention | [automated] `assertReferences` |
|
||
| R2 | `use-twenty-mcp` formatting contract intact across SKILL.md and result-formatting.md | Internal convention | [automated] `assertTwentyMcpFormattingContract` |
|
||
| R3 | Front component guidance correctly split across develop-app skill, layout.md, front-components.md, standalone-pages.md, app-structure.md, front-component-ui.md | Internal convention | [automated] `assertFrontComponentGuidance` |
|
||
| R4 | CLI guidance correctly split between develop-app and manage-app | Internal convention | [automated] `assertCliGuidanceSplit` |
|
||
| R5 | `concepts/how-apps-work.md` is foundational and linked from every skill | Internal convention | [automated] `assertHowAppsWork` |
|
||
|
||
## MCP (`.mcp.json` and `scripts/setup-mcp.sh`)
|
||
|
||
| # | Requirement | Source | Check |
|
||
| ---- | --------------------------------------------------------- | --------------------- | -------------------------------------- |
|
||
| MCP1 | `.mcp.json` declares only the public `twenty-docs` server | Internal convention | [automated] `assertJsonMetadata` |
|
||
| MCP2 | No workspace-specific MCP configs bundled anywhere | Internal convention | [automated] `assertNoBundledMcpConfig` |
|
||
| MCP3 | No bearer tokens or API keys anywhere in the package | Build guide §Security | [automated] `assertNoBundledMcpConfig` |
|
||
| MCP4 | No non-placeholder URLs in any file | Internal convention | [automated] `assertNoBundledMcpConfig` |
|
||
| MCP5 | `scripts/setup-mcp.sh` passes `bash -n` syntax check | Internal convention | [automated] `assertSetupHelper` |
|
||
| MCP6 | `setup-mcp.sh` correctly normalizes representative URLs | Internal convention | [automated] `assertSetupHelper` |
|
||
|
||
## Marketplace & Distribution
|
||
|
||
| # | Requirement | Source | Check |
|
||
| --- | ------------------------------------------------------------------------------------------------------------------------------------ | ------------------------- | --------------------------------------- |
|
||
| D1 | `templates/marketplace.example.json` has marketplace identity, plugin name/category, a local distribution source, and valid policies | Codex marketplace schema | [automated] `assertMarketplaceTemplate` |
|
||
| D2 | Optional repo-level `.agents/plugins/marketplace.json` points at `./packages/twenty-agent-skills/dist` | Build guide §Distribution | [automated] `assertJsonMetadata` |
|
||
| D3 | `CHANGELOG.md` updated for every version bump | Reference impl | [manual] release reviewer sign-off |
|
||
|
||
## Process
|
||
|
||
| # | Requirement | Source | Check |
|
||
| --- | --------------------------------------------------------------- | ------------------- | ------------------------------------------------------------------- |
|
||
| P1 | `validate-source.js` runs in CI on every PR touching the plugin | Reference impl | [manual] confirm `.github/workflows/ci-agent-skills.yaml` is active |
|
||
| P2 | `validate-source.js` has its own unit tests | Internal convention | [manual] confirm `scripts/__tests__/` exists and runs |
|
||
| P3 | Version bump procedure documented | Internal convention | [manual] confirm `CONTRIBUTING.md` covers it |
|
||
|
||
## Manual Sign-off Log
|
||
|
||
When a manual row above is verified, add a line here.
|
||
|
||
| Date | Row(s) | Reviewer | Notes |
|
||
| ---------- | ------ | ---------------------------- | --------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------- |
|
||
| 2026-05-28 | S6, S8 | Codex plugin compliance pass | Skill descriptions reviewed side-by-side; "When To Use" sections added to all five SKILL.md files with explicit "do not use this skill for X" boundary callouts referencing the four siblings. Routing surface is disjoint. |
|
||
| 2026-05-28 | M12 | Codex plugin compliance pass | `brandColor: #000000` matches the actual logo background in `assets/twenty-logo.svg`. |
|
||
|
||
## Deferred Items
|
||
|
||
Tracked for a follow-up PR; not blocking the current release.
|
||
|
||
| Item | Reason for deferral |
|
||
| --------------------------------------------------------- | ------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------- |
|
||
| Real marketplace screenshots (A4, A5, A6) | Requires real captures against a demo workspace. `assets/screenshots/README.md` documents what's needed; `plugin.json` `screenshots` stays `[]` until the PNGs land so `assertAssets` does not regress. |
|
||
| Splitting `standalone-pages.md` / `front-component-ui.md` | The cross-doc contracts assert dozens of exact fragments per file. The mechanical risk of fragment drift outweighs the readability gain at current size (~450 lines each). Re-evaluate when either exceeds 600 lines. |
|
||
| `hooks/hooks.json` SessionStart hook | The Codex hook schema for plugin-bundled hooks needs deeper validation; a misconfigured `SessionStart` hook would fire on every Codex session. Add only when the format is verified against a working reference implementation. |
|