diff --git a/.github/workflows/validate.yml b/.github/workflows/validate.yml new file mode 100644 index 0000000..767f70a --- /dev/null +++ b/.github/workflows/validate.yml @@ -0,0 +1,32 @@ +name: Validate + +on: + pull_request: + push: + branches: [main] + +jobs: + validate: + runs-on: ubuntu-latest + steps: + - uses: actions/checkout@v4 + + - uses: actions/setup-node@v4 + with: + node-version: 24 + + - name: Install Claude Code CLI + run: npm install -g @anthropic-ai/claude-code + + - name: Validate marketplace manifest + run: claude plugin validate --strict . + + - name: Validate plugin manifests + run: | + for plugin in plugins/*/; do + echo "==> $plugin" + claude plugin validate --strict "$plugin" + done + + - name: Check formatting + run: npx --yes prettier --check "**/*.{md,json}" diff --git a/.prettierignore b/.prettierignore new file mode 100644 index 0000000..7f485fd --- /dev/null +++ b/.prettierignore @@ -0,0 +1,2 @@ +# Local, machine-specific permission state — not part of the repo. +.claude/settings.local.json diff --git a/AGENTS.md b/AGENTS.md index 2e9c6eb..9b88b38 100644 --- a/AGENTS.md +++ b/AGENTS.md @@ -23,6 +23,7 @@ Key formats and technologies: ### Repository Layout ``` +.github/workflows/validate.yml # CI: manifest validation, bash -n, prettier .claude-plugin/marketplace.json # Claude Code marketplace definition .agents/plugins/marketplace.json # Codex/agents marketplace definition plugins/ @@ -81,14 +82,23 @@ Then apply the repository conventions below to the result. ## Testing Instructions -There is no automated test suite. "Testing" here means validation plus behavioural checks: +There is no automated test suite. "Testing" here means validation plus behavioural checks. +The validation half runs in CI on every PR and every push to `main` +([.github/workflows/validate.yml](.github/workflows/validate.yml)); run it locally before +pushing: ```bash -bash -n plugins/db-editor/skills/pcm-database/scripts/open-cdb.sh # syntax-check scripts -python3 -m json.tool .json > /dev/null # validate each JSON manifest -npx prettier --check "**/*.{md,json}" # formatting +claude plugin validate --strict . # marketplace manifest +claude plugin validate --strict plugins/db-editor # plugin manifest + its skills +npx prettier --check "**/*.{md,json}" # formatting ``` +`claude plugin validate` is an offline schema check — no API key, no network. It stops at the +first manifest it finds, so `.` only ever validates the marketplace: the plugin directory needs +its own invocation. Pointing it at a skill directory fails ("No manifest found"); skills are +validated through their plugin. `--strict` turns warnings the runtime tolerates — unrecognized +fields, missing metadata — into failures, which is what you want before a manifest ships. + Behavioural checks that matter more than the above: - **Triggering** — install the plugin and confirm the skill fires on paraphrases, not just the @@ -162,9 +172,10 @@ Consequences worth remembering: - Commit and PR titles follow Conventional Commits: `feat:`, `docs:`, `fix:` — e.g. `feat: add pcm-startlist skill`. - One skill or one coherent change per PR. -- Before opening: JSON manifests parse, scripts pass `bash -n`, and the skill has been - exercised against at least a few realistic prompts. Say in the PR description what you - tested it with. +- Before opening: `claude plugin validate --strict` passes on the repo root and on each + plugin directory, scripts pass `bash -n`, and the skill has been exercised against at least + a few realistic prompts. Say in the PR description what you tested it with. CI runs the + first two for you, but not the prompts. - Branch off `main`; `main` is the release branch. ## Security and Data Handling diff --git a/plugins/db-editor/.codex-plugin/plugin.json b/plugins/db-editor/.codex-plugin/plugin.json index 928ee63..ab38550 100644 --- a/plugins/db-editor/.codex-plugin/plugin.json +++ b/plugins/db-editor/.codex-plugin/plugin.json @@ -27,11 +27,7 @@ "longDescription": "Community tooling for Pro Cycling Manager. Open and edit the game database (.cdb) — rider ratings, team rosters, contracts, races — via the pcm-mcp MCP server or a lossless CDB to SQLite conversion, and compose race startlists exported as the .xml file the game imports. Unofficial project, not affiliated with or endorsed by Cyanide Studio or Nacon.", "developerName": "PCMStack", "category": "Developer Tools", - "capabilities": [ - "Interactive", - "Read", - "Write" - ], + "capabilities": ["Interactive", "Read", "Write"], "websiteURL": "https://github.com/PCMStack/agent-skills", "defaultPrompt": [ "List my Pro Cycling Manager saves", diff --git a/plugins/db-editor/skills/pcm-database/references/database-schema.md b/plugins/db-editor/skills/pcm-database/references/database-schema.md index 6e18161..4e38d9b 100644 --- a/plugins/db-editor/skills/pcm-database/references/database-schema.md +++ b/plugins/db-editor/skills/pcm-database/references/database-schema.md @@ -104,18 +104,18 @@ what you want here, and never what you want anywhere else. The columns worth knowing, with a real career as the example: -| Column | Example | Meaning | -| -------------------------------------------- | ------------------------------ | ------------------------------------------------------------------ | -| `game_i_starting_year` | `2025` | Season the career started in. | -| `gene_i_date` | `20250108` | Current in-game date, `YYYYMMDD` — 8 January 2025. See below. | -| `fkIDstage_current` | `1110` | Stage in progress → `STA_stage`, which points at the race and date. | -| `game_sz_version` | `pcm25_shipping_01.09.02.555` | The build that last wrote the save. | -| `gene_sz_modname` / `gene_i_modid` | `Default` / `0` | Active mod; these values mean none. | -| `fkIDgamemode` | `1` | Career vs. other modes. | -| `fkIDgame_state` | `2` | Where the save sits in the game's own state machine. | -| `fkIDdivision` | `0` | Division the player's team competes in. | -| `game_i_is_over` | `0` | `0` = career still active. | -| `gene_b_multiplayer`, `gene_b_hardcoreMode` | `0`, `0` | Solo, hardcore off. | +| Column | Example | Meaning | +| ------------------------------------------- | ----------------------------- | ------------------------------------------------------------------- | +| `game_i_starting_year` | `2025` | Season the career started in. | +| `gene_i_date` | `20250108` | Current in-game date, `YYYYMMDD` — 8 January 2025. See below. | +| `fkIDstage_current` | `1110` | Stage in progress → `STA_stage`, which points at the race and date. | +| `game_sz_version` | `pcm25_shipping_01.09.02.555` | The build that last wrote the save. | +| `gene_sz_modname` / `gene_i_modid` | `Default` / `0` | Active mod; these values mean none. | +| `fkIDgamemode` | `1` | Career vs. other modes. | +| `fkIDgame_state` | `2` | Where the save sits in the game's own state machine. | +| `fkIDdivision` | `0` | Division the player's team competes in. | +| `game_i_is_over` | `0` | `0` = career still active. | +| `gene_b_multiplayer`, `gene_b_hardcoreMode` | `0`, `0` | Solo, hardcore off. | Two habits that keep this reliable: