diff --git a/.agents/plugins/marketplace.json b/.agents/plugins/marketplace.json new file mode 100644 index 0000000..bdd2996 --- /dev/null +++ b/.agents/plugins/marketplace.json @@ -0,0 +1,10 @@ +{ + "name": "actdata-plugins", + "interface": { "displayName": "ACT Data Plugins" }, + "plugins": [ + { "name": "act-plugin-dev", "source": { "source": "local", "path": "./plugins/act-plugin-dev" }, "policy": { "installation": "AVAILABLE", "authentication": "ON_INSTALL" }, "category": "Development" }, + { "name": "act-platform-engineering", "source": { "source": "local", "path": "./plugins/act-platform-engineering" }, "policy": { "installation": "AVAILABLE", "authentication": "ON_INSTALL" }, "category": "Operations" }, + { "name": "act-work-tracking", "source": { "source": "local", "path": "./plugins/act-work-tracking" }, "policy": { "installation": "AVAILABLE", "authentication": "ON_INSTALL" }, "category": "Workflow" }, + { "name": "act-gitlab-ci", "source": { "source": "local", "path": "./plugins/act-gitlab-ci" }, "policy": { "installation": "AVAILABLE", "authentication": "ON_INSTALL" }, "category": "Engineering" } + ] +} diff --git a/.claude-plugin/marketplace.json b/.claude-plugin/marketplace.json index 13ec45b..cbbe5be 100644 --- a/.claude-plugin/marketplace.json +++ b/.claude-plugin/marketplace.json @@ -2,7 +2,7 @@ "$schema": "https://json.schemastore.org/claude-code-marketplace.json", "name": "actdata-plugins", "description": "ACT Data's agent plugin catalog. Installable capability for the teams building and operating ACT Data's software: plugin development, engineering standards, and delivery workflow.", - "version": "0.1.0", + "version": "0.2.0", "owner": { "name": "ACT Data", "url": "https://github.com/patterson-agents" @@ -16,7 +16,7 @@ "source": "./plugins/act-plugin-dev", "displayName": "ACT Plugin Development Toolkit", "description": "Everything needed to build a plugin for this marketplace: seven skills covering plugin structure, skills, commands, agents, hooks, MCP integration and plugin settings; three review agents (agent-creator, plugin-validator, skill-reviewer); and a guided eight-phase creation workflow that registers the finished plugin in the marketplace. Relevant to anyone authoring or reviewing a Claude Code plugin, skill, slash command, subagent, or hook, or wiring an MCP server into a plugin.", - "version": "0.1.0", + "version": "0.2.0", "author": { "name": "Daniel Bodnar" }, @@ -54,7 +54,7 @@ "source": "./plugins/act-platform-engineering", "displayName": "ACT Platform Engineering", "description": "Assessment and operations for PostgreSQL, ZFS, Linux hosts and Proxmox VE. Seven skills covering database performance, backups and replication, pool health and tuning, drive and kernel diagnostics, hypervisor and VM hygiene, observability coverage and incident response; seven role-based reasoning agents; and nine one-shot assessment commands with green/red criteria. Reads its host inventory from a site-local settings file and ships no environment identifiers. Relevant to anyone diagnosing a database or storage host, planning failover, assessing backups, or running an incident.", - "version": "0.1.0", + "version": "0.2.0", "author": { "name": "Daniel Bodnar" }, @@ -94,7 +94,7 @@ "source": "./plugins/act-work-tracking", "displayName": "ACT Work Tracking", "description": "Zoho Projects work tracking and operations reporting. Covers the task-versus-issue distinction, drafting templates for both, the REST API's quirks including the Zoho-oauthtoken header and the bugs endpoint, bulk creation from JSON with a credential-free dry run, weekly status structure, and the writing conventions that keep issues and reports actionable. Reads portal and project IDs from a site-local settings file. Relevant to anyone filing engineering work into Zoho Projects, writing a status report, or maintaining an assessment document set.", - "version": "0.1.0", + "version": "0.2.0", "author": { "name": "Daniel Bodnar" }, @@ -128,7 +128,7 @@ "source": "./plugins/act-gitlab-ci", "displayName": "ACT GitLab CI/CD", "description": "GitLab CI/CD and GitLab tooling for Claude Code. Six skills covering running Claude Code as a CI job across the Claude API, Amazon Bedrock and Vertex providers; the GitLab MCP server with its full tool catalogue and version requirements; the glab CLI; CI troubleshooting; and pipeline standards translated to GitLab and marked as derived. Ships a GitLab MCP server configuration, a pipeline security review agent, and a zero-dependency pipeline checker. Relevant to anyone writing a .gitlab-ci.yml, wiring Claude into a pipeline, connecting to GitLab over MCP, or reviewing a pipeline for credential and scan compliance.", - "version": "0.1.0", + "version": "0.2.0", "author": { "name": "Daniel Bodnar" }, diff --git a/.github/copilot-instructions.md b/.github/copilot-instructions.md new file mode 100644 index 0000000..12e6c56 --- /dev/null +++ b/.github/copilot-instructions.md @@ -0,0 +1,18 @@ +# Repository instructions + +This repository distributes ACT Data plugins for Claude Code, ChatGPT, Codex, and GitHub Copilot. +It is a catalog of agent workflows, not an application package. + +- Keep plugin names, skill directories, commands, and agents in lowercase kebab-case. +- Keep each `skills//SKILL.md` frontmatter `name` identical to its directory. +- Register every shipped plugin in `.claude-plugin/marketplace.json`, + `.agents/plugins/marketplace.json`, and `.github/plugin/marketplace.json`. +- Keep versions synchronized across all marketplace entries and the plugin's + `.claude-plugin/plugin.json`, `.codex-plugin/plugin.json`, and root `plugin.json`. +- Preserve `${CLAUDE_PLUGIN_ROOT}` only in Claude-specific components. Portable skills must resolve + bundled resources from the installed plugin or skill directory. +- Store site configuration in `.agents/.local.md`; support `.claude/.local.md` as a + legacy fallback. Never commit environment identifiers or credentials. +- Use Bun for JavaScript and TypeScript tooling. Do not add npm, Yarn, or pnpm lockfiles. +- Use `apply_patch` for edits and run `sh scripts/verify-all.sh` before considering a change done. +- Do not commit fonts, archives, Office files, PDFs, or raster images over 50 KiB. diff --git a/.github/plugin/marketplace.json b/.github/plugin/marketplace.json new file mode 100644 index 0000000..3025c75 --- /dev/null +++ b/.github/plugin/marketplace.json @@ -0,0 +1,11 @@ +{ + "name": "actdata-plugins", + "owner": { "name": "ACT Data" }, + "metadata": { "description": "ACT Data's agent plugin catalog for engineering, operations, and delivery workflows.", "version": "0.2.0" }, + "plugins": [ + { "name": "act-plugin-dev", "description": "Create and review portable agent plugins.", "version": "0.2.0", "source": "./plugins/act-plugin-dev", "category": "Development" }, + { "name": "act-platform-engineering", "description": "Assess and operate PostgreSQL, ZFS, Linux, Proxmox VE, and observability systems.", "version": "0.2.0", "source": "./plugins/act-platform-engineering", "category": "Operations" }, + { "name": "act-work-tracking", "description": "Draft Zoho Projects work and engineering status reports.", "version": "0.2.0", "source": "./plugins/act-work-tracking", "category": "Workflow" }, + { "name": "act-gitlab-ci", "description": "Build, review, and troubleshoot GitLab CI/CD integrations.", "version": "0.2.0", "source": "./plugins/act-gitlab-ci", "category": "Engineering" } + ] +} diff --git a/.gitignore b/.gitignore index 6228b4b..e62fe7b 100644 --- a/.gitignore +++ b/.gitignore @@ -158,3 +158,4 @@ pnpm-lock.yaml # in a `.local.md` the operator writes for their own site. Committing one would put the # very identifiers the plugins are designed to exclude back into the repository. .claude/*.local.md +.agents/*.local.md diff --git a/CONTRIBUTING.md b/CONTRIBUTING.md index 0c0dbe6..51476d7 100644 --- a/CONTRIBUTING.md +++ b/CONTRIBUTING.md @@ -1,7 +1,7 @@ # Contributing to actdata-plugins -`actdata-plugins` is ACT Data's Claude Code plugin marketplace: capability shipped as installable -plugins. This document is how a person or an agent proposes a change to it. +`actdata-plugins` is ACT Data's plugin marketplace for Claude Code, ChatGPT, Codex, and GitHub +Copilot. This document is how a person or an agent proposes a change to it. ## The short version @@ -24,8 +24,8 @@ checked mechanically; the rest are checked in review. | **kebab-case** | Plugin names, skill directory names, command filenames, agent filenames, issue and PR template filenames. | | **Skill name equals directory name** | A skill's directory name and its `SKILL.md` frontmatter `name:` must be the identical kebab-case string. This is the single most common defect when importing a skill written elsewhere, because Title Case names (`name: Plugin Structure`) are the norm outside this repository. The gate fails on a mismatch. | | **Plugins live at `plugins//`** | Never at the repository root, never nested deeper. `marketplace.json` declares `metadata.pluginRoot: "./plugins"`. | -| **Registration is part of shipping** | A plugin with no entry in `.claude-plugin/marketplace.json` is invisible to `claude plugin install`. Every shipped plugin needs an entry with a `relevance` block. A plugin that is still a scaffold should stay unregistered — the gate recognises TODO placeholders and reports it as a draft rather than failing. | -| **Version in two places** | `plugins//.claude-plugin/plugin.json` and the plugin's `marketplace.json` entry must carry the same version. Bump both in the same commit; the gate compares them. | +| **Registration is part of shipping** | Register shipped plugins in `.claude-plugin/marketplace.json`, `.agents/plugins/marketplace.json`, and `.github/plugin/marketplace.json`. | +| **Version everywhere** | Keep the Claude, OpenAI, and Copilot manifests and versioned catalog entries synchronized. | | **`${CLAUDE_PLUGIN_ROOT}` stays literal** | Every intra-plugin reference uses the literal token, never an absolute path a tool happened to resolve it to on someone's machine. The gate greps for expanded forms and fails on them. | | **Bun only** | `bun install`, `bun run`, `bunx`, `bun test`. `bun.lock` is the only lockfile; an `npm`, `yarn`, or `pnpm` lockfile in this repository is a bug to remove. | | **No `/tmp`** | Nothing is created or stored under `/tmp` — not scratch files, not build intermediates, not test fixtures. Scratch lives in the repository's gitignored `.tmp/`. This is a Patterson house standard enforced by a workspace hook. | @@ -57,13 +57,12 @@ registers the marketplace entry, and runs the gate: By hand, the checklist is: -1. `plugins//.claude-plugin/plugin.json` — `name` matching the directory, semver `version`, - real `description`, `license`. +1. Create the Claude, OpenAI, and Copilot manifests with matching names and semver versions. Do **not** add `"skills": ["./"]` if the plugin has a `skills/` directory; that field is the single-skill template shape and breaks auto-discovery. 2. `plugins//README.md` — model on `plugins/act-plugin-dev/README.md`. -3. An entry in `.claude-plugin/marketplace.json` with `source: "./plugins/"`, a `version` - matching `plugin.json`, and a `relevance` block. +3. Add matching entries to all three marketplace files. Keep Claude `relevance` and OpenAI policy + metadata intact. 4. A row in the catalog table in the root `README.md`. 5. `sh scripts/verify-all.sh` printing `VERIFY-ALL: PASS`. 6. `claude plugin validate .` clean. diff --git a/README.md b/README.md index 509c049..45c8d26 100644 --- a/README.md +++ b/README.md @@ -7,11 +7,11 @@ # actdata-plugins -ACT Data's institutional knowledge, encoded as installable -[agent plugins](https://code.claude.com/docs/en/plugin-marketplaces). +ACT Data's institutional knowledge, encoded as installable agent plugins for Claude Code, +ChatGPT, Codex, and GitHub Copilot. ![plugins](https://img.shields.io/badge/plugins-4-00A8E1?labelColor=003767) -![skills](https://img.shields.io/badge/skills-22-003767) +![skills](https://img.shields.io/badge/skills-50-003767) ![agents](https://img.shields.io/badge/agents-12-147EC2) ![runtime](https://img.shields.io/badge/runtime-Bun_·_no_build_step-00817D) ![gate](https://img.shields.io/badge/gate-verify--all.sh-58585B) @@ -35,16 +35,19 @@ ACT Data's institutional knowledge, encoded as installable ## What this is -A Claude Code plugin marketplace for ACT Data. It holds capability that is true across ACT's -software teams, packaged so an agent working in an ACT repository behaves the way a well-oriented -ACT colleague would. - -Right now it holds one thing: the toolkit for building the rest of it. +An agent plugin marketplace for ACT Data. It packages shared engineering and operations knowledge +for Claude Code, ChatGPT, Codex, and GitHub Copilot. ## Quick start -```sh -# inside Claude Code +> [!TIP] +> New to this repository? [`docs/onboarding.md`](docs/onboarding.md) is the day-one guide: what a +> plugin marketplace is, how to get the gate running, what to read in what order, and real first +> tasks. + +### Claude Code + +```text /plugin marketplace add patterson-agents/actdata-plugins /plugin install act-plugin-dev@actdata-plugins ``` @@ -66,6 +69,25 @@ Then: "how do I write a PreToolUse hook?" ← hook-development skill fires ``` +### ChatGPT and Codex + +The ChatGPT desktop app discovers `.agents/plugins/marketplace.json` from the repository. Restart +the app, open the Plugins Directory, choose **ACT Data Plugins**, and install a plugin. From Codex: + +```sh +codex plugin marketplace add . +codex plugin add act-plugin-dev@actdata-plugins +``` + +### GitHub Copilot + +GitHub Copilot CLI reads `.github/plugin/marketplace.json`: + +```sh +copilot plugin marketplace add . +copilot plugin install act-plugin-dev@actdata-plugins +``` + > [!WARNING] > Marketplace names occupy one **flat global namespace**. Registering a second marketplace under > the name `actdata-plugins` replaces this one rather than merging with it. @@ -74,10 +96,10 @@ Then: | Plugin | What it is | Components | |---|---|---| -| **[`act-plugin-dev`](plugins/act-plugin-dev/)**
Development | Everything needed to build a plugin for this marketplace, and the conventions that keep one from breaking at install time. A fork of Claude Code's `plugin-dev`, adapted to ACT's layout, Bun, and marketplace registration. | 7 skills · 3 agents · 1 command | -| **[`act-platform-engineering`](plugins/act-platform-engineering/)**
Operations | Assessment and operations for PostgreSQL, ZFS, Linux hosts and Proxmox VE. Diagnostic commands with green/red criteria, role-based reasoning agents, and incident practice. Reads its host inventory from a site-local settings file and ships no environment identifiers. | 7 skills · 7 agents · 9 commands | -| **[`act-work-tracking`](plugins/act-work-tracking/)**
Workflow | Zoho Projects work tracking and operations reporting: the task-versus-issue distinction, the API's quirks, bulk creation with a credential-free dry run, and the writing conventions that keep issues and reports actionable. | 2 skills · 1 agent · 3 commands | -| **[`act-gitlab-ci`](plugins/act-gitlab-ci/)**
Engineering | GitLab CI/CD and GitLab tooling: Claude Code as a CI job across three providers, the GitLab MCP server, the `glab` CLI, and pipeline standards translated to GitLab. Ships an MCP server and a zero-dependency pipeline checker. | 6 skills · 1 agent · 3 commands · 1 MCP | +| **[`act-plugin-dev`](plugins/act-plugin-dev/)**
Development | Build and review portable plugins while retaining host-specific guidance for commands, agents, hooks, and MCP. | 11 skills · 3 agents · 1 command | +| **[`act-platform-engineering`](plugins/act-platform-engineering/)**
Operations | Assessment and operations for PostgreSQL, ZFS, Linux hosts and Proxmox VE. | 23 skills · 7 agents · 9 commands | +| **[`act-work-tracking`](plugins/act-work-tracking/)**
Workflow | Zoho Projects work tracking and operations reporting. | 6 skills · 1 agent · 3 commands | +| **[`act-gitlab-ci`](plugins/act-gitlab-ci/)**
Engineering | GitLab CI/CD jobs, MCP, authentication, troubleshooting, and pipeline standards. | 10 skills · 1 agent · 3 commands · 1 MCP | ### Not yet shipped @@ -97,11 +119,14 @@ than failing the build. Once a draft has real content, registering it becomes ma ```text actdata-plugins/ -├── .claude-plugin/ -│ └── marketplace.json # the catalog agents read -- a plugin is invisible without an entry here +├── .claude-plugin/marketplace.json # Claude Code catalog +├── .agents/plugins/marketplace.json # ChatGPT and Codex catalog +├── .github/plugin/marketplace.json # GitHub Copilot catalog ├── plugins/ │ └── act-plugin-dev/ -│ ├── .claude-plugin/plugin.json +│ ├── .claude-plugin/plugin.json # Claude manifest +│ ├── .codex-plugin/plugin.json # OpenAI manifest +│ ├── plugin.json # Copilot manifest │ ├── README.md │ ├── skills// # SKILL.md · references/ · examples/ · scripts/ │ ├── agents/ @@ -111,7 +136,12 @@ actdata-plugins/ │ ├── check-no-binaries.ts # fonts / office / archive / oversized-raster validator │ ├── verify-all.sh # the gate battery -- CI and pre-commit both call this │ └── tests/run-tests.sh # TDD fixtures for the two validators -├── docs/ +├── docs/ # see docs/README.md for the index +│ ├── onboarding.md # start here on day one +│ ├── architecture.md # how the marketplace works +│ ├── verification.md # every gate check, and what nothing checks +│ ├── troubleshooting.md # symptom -> cause -> fix +│ ├── releasing.md · glossary.md │ ├── assets/ # placeholder wordmark -- see docs/assets/README.md │ └── decisions/ # ADRs ├── .github/ # issue + PR templates, ci.yml @@ -129,8 +159,8 @@ Load-bearing, not stylistic. `scripts/verify-all.sh` enforces the mechanical one | **kebab-case everywhere** | Plugin names, skill directory names, command and agent filenames. | | **Skill name equals directory name** | `skills/foo/SKILL.md` must carry `name: foo`. Title Case fails the gate. The most common defect when importing a skill from elsewhere. | | **Plugins live at `plugins//`** | `marketplace.json` declares `metadata.pluginRoot: "./plugins"`. | -| **Register, or it does not exist** | Every shipped plugin needs a `marketplace.json` entry with a `relevance` block. | -| **Version in two places** | `plugin.json` and the marketplace entry must agree. Bump both together; the gate checks it. | +| **Register, or it does not exist** | Every shipped plugin needs entries in the Claude, OpenAI, and Copilot marketplaces. | +| **Version everywhere** | All host manifests and versioned marketplace entries must agree. The gate checks them. | | **`${CLAUDE_PLUGIN_ROOT}` stays literal** | Never an absolute path a tool happened to resolve. The gate greps for expanded forms. | | **Bun only** | `bun install`, `bun run`, `bunx`, `bun test`. `bun.lock` is the only lockfile; an npm/yarn/pnpm lockfile here is a bug. | | **No `/tmp`** | Scratch goes in the repository's gitignored `.tmp/`. | @@ -206,6 +236,8 @@ files — follows `patterson-corp`, so someone moving between them finds the sam | File | Purpose | |---|---| +| [`docs/`](docs/README.md) | Full documentation: onboarding, architecture, verification, troubleshooting, releasing, glossary | +| [`docs/onboarding.md`](docs/onboarding.md) | Start here on day one: environment setup, orientation, and first tasks | | [`CONTRIBUTING.md`](CONTRIBUTING.md) | Repository conventions, the gate, and how to add a plugin | | [`CODE_OF_CONDUCT.md`](CODE_OF_CONDUCT.md) | Contributor Covenant, adapted for a B2B engineering context | | [`SECURITY.md`](SECURITY.md) | Private vulnerability reporting | @@ -213,7 +245,7 @@ files — follows `patterson-corp`, so someone moving between them finds the sam | [`.github/ISSUE_TEMPLATE/`](.github/ISSUE_TEMPLATE/) | Bug, feature, and new-plugin proposal forms | | [`.github/workflows/ci.yml`](.github/workflows/ci.yml) | Runs `scripts/verify-all.sh` on every push and pull request | | [`.githooks/pre-commit`](.githooks/pre-commit) | The fast local gate (opt in with `git config core.hooksPath .githooks`) | -| [`docs/decisions/`](docs/decisions/) | ADRs | +| [`docs/decisions/`](docs/decisions/README.md) | ADRs, with an index and the format | ## Status and open items diff --git a/docs/README.md b/docs/README.md new file mode 100644 index 0000000..72f65eb --- /dev/null +++ b/docs/README.md @@ -0,0 +1,108 @@ +
+ + + + ACT Data + + +# Documentation + +
+ +--- + +Documentation for `actdata-plugins`, ACT Data's plugin marketplace for Claude Code, ChatGPT, +Codex, and GitHub Copilot. + +## Start here + +| If you are | Read | +|---|---| +| **New to the repository** | [`onboarding.md`](onboarding.md) — environment, orientation, first tasks | +| **About to make a change** | [`../CONTRIBUTING.md`](../CONTRIBUTING.md) — the rules, stated as rules | +| **Trying to understand how it works** | [`architecture.md`](architecture.md) | +| **Stuck on an error** | [`troubleshooting.md`](troubleshooting.md) | + +## The documents + +| Document | Answers | +|---|---| +| [`onboarding.md`](onboarding.md) | How do I get set up, what do I read, and what should I work on first? | +| [`architecture.md`](architecture.md) | How does a marketplace work? What discovers what, and when? | +| [`verification.md`](verification.md) | What exactly does the gate check, and what does nothing check? | +| [`troubleshooting.md`](troubleshooting.md) | Something broke. What is it and how do I fix it? | +| [`releasing.md`](releasing.md) | How do versions work here, and what is still undecided? | +| [`glossary.md`](glossary.md) | What does this repository mean by that word? | +| [`decisions/`](decisions/) | Why is it like this, and what else was considered? | +| [`assets/`](assets/) | The brand marks, and their provenance | + +## How these fit together + +They are layered, and each avoids repeating the one below it. + +```text +onboarding.md orientation "where am I, what do I do first" + | +architecture.md explanation "how the machinery works" +verification.md reference "what is enforced, precisely" + | +CONTRIBUTING.md rules "what you must do" + | +troubleshooting.md recovery "it broke" +glossary.md vocabulary "what that word means here" +decisions/ rationale "why, and what else was considered" +``` + +`CONTRIBUTING.md` lives at the repository root rather than here because it is the file a contributor +is pointed at by convention and by GitHub's own tooling. + +## Conventions in this documentation + +**GFM alerts for emphasis, never emoji.** `> [!NOTE]`, `> [!IMPORTANT]`, `> [!WARNING]`, +`> [!CAUTION]`. Emoji are forbidden on ACT-authored surfaces; vendored upstream reference content +under `plugins/*/skills/*/references/` and `examples/` is exempt. + +**Tables where the content is a lookup**, prose where it is an argument. A bulleted list of full +sentences is prose that has been chopped up. + +**`[TBD:]` rather than a guess.** Where a source is silent, the marker records the gap so it can be +escalated to whoever owns the answer: + +```sh +grep -rn '\[TBD' docs/ plugins/ +``` + +**Claims are verified, not asserted.** Version numbers, file paths, exit codes and behaviour +described here were checked against the repository rather than recalled. Where something was not +verifiable, it says so. + +## Keeping this accurate + +Documentation decays faster than code, because the people best placed to notice are the ones least +confident about correcting it. + +If something here is wrong, stale or missing, change it in the same branch as the work that revealed +it. That is a `docs:` commit and needs no ceremony. + +> [!NOTE] +> `[TBD: no review cadence is defined for this documentation. Until one exists, the pull request that +> fixes something is the review.]` + +## Elsewhere + +Not everything is under `docs/`, and knowing where else to look saves a search: + +| Content | Location | +|---|---| +| Per-plugin documentation | `plugins//README.md` | +| Component authoring guidance | The `act-plugin-dev` skills | +| Repository overview and plugin catalog | [`../README.md`](../README.md) | +| Security policy | [`../SECURITY.md`](../SECURITY.md) | +| Code of conduct | [`../CODE_OF_CONDUCT.md`](../CODE_OF_CONDUCT.md) | +| Review ownership | [`../CODEOWNERS`](../CODEOWNERS) | +| Issue and pull request templates | [`../.github/`](../.github/) | + +> [!IMPORTANT] +> Component authoring — how to write a good skill, command, agent or hook — deliberately lives in the +> `act-plugin-dev` plugin rather than here. That content is itself a shipped product, loaded on demand +> while you work. Duplicating it into `docs/` would create two copies that disagree within a month. diff --git a/docs/architecture.md b/docs/architecture.md new file mode 100644 index 0000000..817a626 --- /dev/null +++ b/docs/architecture.md @@ -0,0 +1,357 @@ +# Architecture + +How this marketplace is put together, and why it is shaped the way it is. + +For the rules you must follow, see [`CONTRIBUTING.md`](../CONTRIBUTING.md). This document explains +the machinery those rules protect. + +## Table of contents + +- [The shape of the thing](#the-shape-of-the-thing) +- [Three catalogs, three manifests](#three-catalogs-three-manifests) +- [How components are discovered](#how-components-are-discovered) +- [Namespacing](#namespacing) +- [`${CLAUDE_PLUGIN_ROOT}`](#claude_plugin_root) +- [When things happen](#when-things-happen) +- [The config-driven pattern](#the-config-driven-pattern) +- [MCP servers inside a plugin](#mcp-servers-inside-a-plugin) +- [Dependency posture](#dependency-posture) +- [Why there is no build step](#why-there-is-no-build-step) + +--- + +## The shape of the thing + +```text +.claude-plugin/marketplace.json Claude Code catalog +.agents/plugins/marketplace.json ChatGPT and Codex catalog +.github/plugin/marketplace.json GitHub Copilot catalog + | + | one entry per installable plugin, each with a `source` path + v +plugins// + .claude-plugin/plugin.json Claude Code manifest + .codex-plugin/plugin.json OpenAI manifest + plugin.json GitHub Copilot manifest + skills//SKILL.md knowledge, loaded on demand + commands/.md user-invoked, /plugin-name:command-name + agents/.md delegated subagents + hooks/hooks.json event-driven interception + .mcp.json external tool servers + scripts/ bundled executables +``` + +Everything above is plain text. There is no compilation, bundling, or generated artefact. The three +catalogs describe the same plugin directories in each host's native schema. Reusable behavior lives +in `skills/`; Claude commands and agents remain host-specific adapters. + +### Cross-runtime invariants + +- Every shipped plugin appears in all three catalogs. +- Its directory name and all three manifest names match. +- Its version matches every manifest and every versioned catalog entry. +- OpenAI entries include installation, authentication, and category policy metadata. +- Core workflows do not require commands, agents, or hooks, because ChatGPT executes skills. + +`scripts/check-marketplace-compat.ts` enforces the mechanical parts of this contract. + +### The one asymmetry worth memorising + +A plugin's *existence on disk* and its *installability* are separate facts, and only the second one +matters to a user: + +> [!IMPORTANT] +> A plugin with no entry in `.claude-plugin/marketplace.json` cannot be installed, no matter how +> complete it is. Creating the directory and registering it are one task. + +This is gated. `scripts/verify-all.sh` step 4 fails the build on a plugin that exists on disk but is +absent from the catalog, with one deliberate exception described in +[Drafts](#drafts-the-one-permitted-gap). + +## Three catalogs, three manifests + +Each plugin ships host-specific catalog entries and host-specific per-plugin manifests. They serve +different readers and duplicate exactly one field on purpose. + +### Catalog entries (one per host) + +| | `.claude-plugin/marketplace.json` | `.agents/plugins/marketplace.json` | `.github/plugin/marketplace.json` | +|---|---|---|---| +| Host | Claude | OpenAI / Codex | GitHub Copilot | +| Answers | "What can I install, and is it relevant to me?" | Same | Same | +| Required extras | `source` (relative path), `relevance` | `source.path`, `source.source`, `policy`, `category` | `source` (relative path) | +| Version field | `version` | — (not versioned) | `version` | + +### Per-plugin manifests (one per host per plugin) + +| | `plugins//.claude-plugin/plugin.json` | `plugins//.codex-plugin/plugin.json` | `plugins//plugin.json` | +|---|---|---|---| +| Host | Claude | OpenAI / Codex | GitHub Copilot | +| Read by | The runtime, after install | Same | Same | +| Scope | One plugin | One plugin | One plugin | + +### The fields that must agree + +`version` appears in both and **must match**. The gate compares them, because a mismatch means the +advertised version is not the installed one, and that failure is silent at install time. + +`name` in `plugin.json` must equal the plugin's directory name. The gate compares those too. + +### `relevance` + +Required on every marketplace entry: + +```json +"relevance": { + "topic": "short topic phrase", + "signals": { + "filesRead": ["**/pattern-that-implies-relevance"] + } +} +``` + +This is how a plugin surfaces to someone who has not gone looking for it. The `filesRead` globs +describe the files whose presence suggests the plugin would help. `act-gitlab-ci` lists +`**/.gitlab-ci.yml`; `act-platform-engineering` lists `**/postgresql.conf` and friends. + +Write these as *evidence of the problem*, not as evidence of the plugin. A pattern matching the +plugin's own files makes it relevant only to itself. + +### Drafts: the one permitted gap + +A plugin still carrying `claude plugin init` TODO placeholders is a **draft**. It is correct for a +draft to be unregistered, because registering it would ship `TODO -- describe WHEN Claude should use +this` to users. + +The gate detects a draft by scanning the plugin's `.md` files for `TODO — `, `TODO: ` or `TODO -- `, +and reports it as a note rather than a failure. + +> [!WARNING] +> The draft exemption applies **only while the plugin is absent from the catalog**. Once an entry +> exists, `isDraft()` is never consulted and every consistency rule applies. A fully-registered +> scaffold passes the gate while shipping placeholder text to users. +> +> Note also that the draft scan reads `.md` files only. TODO markers in a `.ts` or `.json` file do +> not mark a plugin as a draft. + +## How components are discovered + +Two different mechanisms, and knowing which applies to what saves an afternoon. + +| Component | Discovered by | Failure mode when wrong | +|---|---|---| +| Skill | Directory scan of `skills/*/`, then frontmatter `name` must equal the directory name | Skill does not resolve | +| Command | YAML frontmatter in `commands/*.md` | Appears in the menu with **empty metadata** | +| Agent | YAML frontmatter in `agents/*.md` | Loads with **empty metadata** | +| Hook | Presence of `hooks/hooks.json` | Silently inert | +| MCP server | Presence of `.mcp.json` | Server absent from `/mcp` | + +### The frontmatter failure is the dangerous one + +When a command's or agent's YAML fails to parse, it does not disappear. It loads with every +frontmatter field dropped, which means: + +- the `description` is gone, so the user cannot tell what it does +- `argument-hint` is gone +- **`allowed-tools` is gone**, so the tool restriction silently does not apply + +The most common cause is an unquoted colon-space inside a plain scalar: + +```yaml +# Breaks. The ": " terminates the scalar. +description: Report coverage across the fleet: collectors, plugins, dashboards + +# Correct. +description: "Report coverage across the fleet: collectors, plugins, dashboards" +``` + +A trailing colon has the same effect: a `description:` line ending in `Examples:` is a YAML error. + +> [!CAUTION] +> `scripts/verify-all.sh` does **not** parse frontmatter, and neither does `claude plugin validate .` +> — that validates the marketplace manifest only. The check that catches this is +> `claude plugin validate plugins/`, per plugin. See [`verification.md`](verification.md). + +### The skill-name invariant + +`skills/foo-bar/SKILL.md` must contain `name: foo-bar`. Kebab-case, identical string. + +This exists because Title Case frontmatter names (`name: Plugin Structure`) are the norm outside this +repository, so any skill imported from elsewhere arrives broken. The gate reads the first 20 lines +looking for a `^name:` at column 0. + +## Namespacing + +Installed components are addressed as `:`: + +```text +/act-platform-engineering:assess-postgres a command +act-plugin-dev:skill-reviewer an agent +act-gitlab-ci:pipeline-standards a skill +``` + +Two consequences: + +**Marketplace names are one flat global namespace.** Registering a second marketplace called +`actdata-plugins` replaces this one rather than merging with it. + +**Component names only need to be unique within their plugin.** Two plugins may both ship a +`review-pipeline` command. Skills are the exception worth thinking about, because a skill competes for +attention on trigger phrases rather than on its name — two skills claiming the same user utterance +will fight regardless of namespace. + +## `${CLAUDE_PLUGIN_ROOT}` + +The literal token a plugin uses to reference its own bundled files: + +```markdown +bun "${CLAUDE_PLUGIN_ROOT}/scripts/check-pipeline.ts" .gitlab-ci.yml +``` + +It resolves at runtime to wherever the plugin was installed. Two rules: + +**Never write a resolved path.** An absolute `/home/...` or `/workspaces/...` path pointing at +`plugins/`, `skills/` or `hooks/` means a tool wrote its own machine's layout into a tracked file. +The gate greps for exactly that and fails. + +**Never use a relative path instead.** A relative path passes the gate but breaks at install time, +because commands execute from the user's working directory, not from the plugin directory. This is +the failure the gate cannot see, which makes it worth checking by eye. + +The gate carries one documented exemption: the placeholder `/home/user/.claude/plugins/my-plugin/` +appearing as the *wrong* half of a Wrong/Correct pair in `act-plugin-dev`'s teaching material. The +exemption is written as the full literal string rather than as a file allowlist, so a genuinely +leaked path landing in that same file is still caught. + +## When things happen + +Understanding the timeline explains most "why didn't my change take effect" questions. + +| Moment | What happens | +|---|---| +| **Catalog time** | `marketplace.json` is read. Only entries, `source` paths and `relevance` matter. Nothing inside a plugin is read. | +| **Install time** | The plugin directory is copied. `plugin.json` is read. Nothing executes. | +| **Session start** | Components are discovered: skills indexed by description, commands and agents by frontmatter, hooks registered, MCP servers started. | +| **Invocation** | A skill body is read when its description matches. A command runs when typed. An agent runs when delegated. A script runs when a command tells it to. | + +A change to a component does not reach an existing session. Start a fresh session, or `/reload-plugins` +where supported. + +> [!NOTE] +> Skill *descriptions* are loaded at session start; skill *bodies* are read on demand. That is why +> the description is the highest-leverage text in a skill: it is always in context, competing against +> every other skill's description, while the body costs nothing until it is needed. + +## The config-driven pattern + +The operational plugins ship **no environment identifiers**: no hostnames, addresses, database names, +portal IDs or endpoints, not even as defaults or fallbacks. + +Site-specific values live in a gitignored file the operator writes: + +```text +.agents/.local.md +``` + +`.gitignore` carries `.agents/*.local.md` so one can never be committed by accident. +`.claude/.local.md` is also supported as a legacy fallback. + +### The contract + +Every command and agent that needs a target follows the same resolution order: + +1. An explicit argument +2. The settings file +3. **Ask the user** + +Never invent, guess, or pattern-match a value. + +### Why, specifically + +A command that defaults to a plausible hostname will eventually run a diagnostic against the wrong +machine and report confident findings about it. The failure is silent and the output looks correct, +which is the worst combination available. + +A missing settings file producing a question is a good outcome, not a degraded one. + +### Implementing it + +Give the plugin a skill that owns the contract, and have the others defer to it. +`act-platform-engineering/skills/infrastructure-inventory/` is the worked example: it defines the +file location, the table schema, the resolution order and the never-invent rule, and four sibling +skills reference it by name rather than restating it. + +## MCP servers inside a plugin + +A plugin ships `.mcp.json` at its root: + +```json +{ + "mcpServers": { + "gitlab": { + "type": "http", + "url": "${GITLAB_MCP_URL}" + } + } +} +``` + +Installing the plugin registers the server. Two consequences worth weighing before shipping one: + +**Every install attempts a connection.** A plugin with an MCP server is not passive. + +**Endpoints are usually site-specific.** Hardcoding one would violate the config-driven rule, so +`act-gitlab-ci` takes its URL from an environment variable. With the variable unset the server fails +to connect, which is deliberate: it fails visibly rather than reaching somewhere unintended. + +Prefer a bundled script over an MCP server when the work is a one-shot command. A server is the right +shape when the plugin needs live, structured access to an external system across a conversation. + +## Dependency posture + +The repository's own tooling has **zero third-party dependencies**. Both validators in `scripts/` +import only `node:*` builtins. + +That is a deliberate property, not an accident of scope: + +> [!NOTE] +> A dependency-free gate runs before `bun install` and cannot itself become a supply-chain surface. +> A validator that needed packages to run could not validate a tree whose packages had not been +> vetted yet. + +New validators should hold that line. Plugin-bundled scripts should too where practical: +`act-gitlab-ci/scripts/check-pipeline.ts` is zero-dependency for the same reason, and +`act-work-tracking/scripts/zoho-create.sh` uses only `curl` and `jq`. + +Anything genuinely needed gets scored first: + +```sh +socket package shallow npm pkg:npm/@ --markdown +``` + +Flag anything under 90 and name which of the five dimensions is low. + +## Why there is no build step + +Every component is a file the runtime reads directly. Adding a build would mean the repository no +longer contains what gets installed, and the gate would be validating inputs rather than outputs. + +Two things follow: + +- **The gate can check the real artefact.** `check-size.ts` sums tracked bytes because tracked bytes + *are* the payload a clone downloads. +- **A change is testable immediately.** `claude plugin marketplace add .` against a local checkout + installs exactly what is on disk. + +`package.json` exists for scripts and a single `@types/bun` devDependency. It is not a package +anyone installs; `private: true` says so. + +## Further reading + +| Topic | Where | +|---|---| +| The rules, stated as rules | [`CONTRIBUTING.md`](../CONTRIBUTING.md) | +| The gate, check by check | [`verification.md`](verification.md) | +| Getting started | [`onboarding.md`](onboarding.md) | +| Why the big decisions were made | [`decisions/`](decisions/) | +| Authoring a specific component type | The `act-plugin-dev` skills | diff --git a/docs/decisions/0002-config-driven-plugins.md b/docs/decisions/0002-config-driven-plugins.md new file mode 100644 index 0000000..6077065 --- /dev/null +++ b/docs/decisions/0002-config-driven-plugins.md @@ -0,0 +1,91 @@ +# 2. Ship no environment identifiers; read them from a site-local settings file + +- **Status:** Accepted +- **Date:** 2026-08-14 + +## Context + +`act-platform-engineering` and `act-work-tracking` were adapted from a working skill bundle written +for one specific estate. That bundle was useful precisely because it was specific: it named the +database primary, the hypervisor nodes, the replication targets, the tracker's portal and project +IDs, and the colleagues who owned each area. + +Every one of those is an environment identifier, and they appeared in essentially every file — +including a `## Known Issues at ACT` section in all eight role agents. + +Three problems with shipping them: + +1. **They go stale silently.** A hostname in a plugin is a fact frozen at authoring time. When the + estate changes, the plugin keeps asserting the old shape confidently. +2. **They make the plugin single-tenant.** A second team, or a second environment, cannot use it. +3. **A wrong default is worse than a missing one.** A command that defaults to a plausible hostname + will eventually run a diagnostic against the wrong machine and report confident findings about it. + The output looks correct, which is the worst available failure mode. + +The third is the decisive one. The first two are inconvenience; the third produces wrong answers that +nobody questions. + +## Options considered + +| Option | Assessment | +|---|---| +| **Ship the identifiers as-is** | Defensible for an internal marketplace, and cheapest. Rejected: it makes the plugins single-tenant and leaves the wrong-default failure in place. | +| **Ship them as documented defaults, overridable** | Rejected. A default *is* the wrong-default failure. The whole risk is that a plausible value is used without anyone noticing it was assumed. | +| **Strip them, and have commands ask every time** | Rejected as the sole mechanism: correct but tedious, and tedium gets worked around by pasting values into prompts, which puts them back in an untracked, unreviewable place. | +| **Strip them; read from a gitignored site-local file; ask when it is absent** | Chosen. | + +## Decision + +The operational plugins ship **no** hostnames, addresses, database names, portal IDs, user IDs or +service endpoints. Not as defaults, not as fallbacks, not as illustrative table rows. + +Site-specific values live in `.claude/.local.md`, written by the operator. +`.gitignore` carries `.claude/*.local.md` so one cannot be committed by accident. + +> **Amendment (2026-08-16):** The portable settings path is now `.agents/.local.md`, +> supported across all three hosts (Claude, OpenAI/Codex, GitHub Copilot). The original +> `.claude/.local.md` path is retained as a legacy fallback. `.gitignore` covers +> `.agents/*.local.md` in addition to `.claude/*.local.md`. + +Every command and agent that needs a target follows one resolution order: + +1. An explicit argument +2. The settings file +3. **Ask the user** + +Never invent, guess, or pattern-match a value. + +The contract is owned by one skill per plugin — +`act-platform-engineering/skills/infrastructure-inventory/` — which defines the file location, the +table schema and the rule. Sibling skills reference it by name rather than restating it. + +## Consequences + +**An unconfigured install asks questions.** This is the intended behaviour and needs saying out loud, +because it reads as a defect: running `/act-platform-engineering:assess-postgres` with no settings +file produces a question rather than an assessment. That is the design working. + +**The plugins became reusable as a side effect.** The goal was correctness, not portability, but the +result installs cleanly into any Postgres and ZFS estate. The knowledge — thresholds, diagnostic +ordering, what a signal means — turned out to be the transferable part, and the identifiers were the +only thing tying it to one site. + +**Documentation carries the template.** Each plugin's README ships the settings-file schema, because a +config-driven plugin with no documented config is unusable. + +**Enforcement is not mechanical.** The gate cannot know which strings are environment identifiers; the +set is per-change. A targeted `git grep` is written per change instead, and this is a known gap. + +The grep used when the plugins were built, for reference: + +```sh +git grep -nEi '||||' -- plugins/ +``` + +The one intended exception is author metadata in `plugin.json`, which is authorship rather than +environment. + +**One near-miss is worth recording.** The first leak check scanned only the three plugin directories +and came back clean. Ten superseded source files were still staged under `plugins/.staging/`, +carrying the original backlog data, and were caught only by a later repository-wide check. Scope the +grep to the whole tree, not to the directories you believe you edited. diff --git a/docs/decisions/0003-three-plugin-split.md b/docs/decisions/0003-three-plugin-split.md new file mode 100644 index 0000000..8fcea49 --- /dev/null +++ b/docs/decisions/0003-three-plugin-split.md @@ -0,0 +1,86 @@ +# 3. Split the operational bundle into three plugins + +- **Status:** Accepted +- **Date:** 2026-08-14 + +## Context + +A single directory, `plugins/act-platform-engineering/`, arrived containing 33 files: eight role +agents, nine diagnostic commands, eight output templates, a 24 KB command cheatsheet, an API +reference, a backlog dump and two scripts. + +It was not a working plugin. There was no `plugin.json`, `SKILL.md` sat at the plugin root instead of +under `skills/`, and **none of the agents or commands had YAML frontmatter**, so nothing loaded at +all. It also had a `prompts/` directory, which is not a component type. + +Restructuring it was unavoidable. The question was whether the result should be one plugin or several. + +Three themes were visible in the content, and they had little to do with each other: + +- **Infrastructure diagnosis** — PostgreSQL, ZFS, disks, kernel, Proxmox, observability +- **Work tracking** — the tracker's API, task-versus-issue conventions, a bulk-creation script +- **Writing practice** — status reports, assessment-document routing, house style + +Separately, `plugins/gitlab-standards/` existed as an unregistered `claude plugin init` scaffold, +reserved for CI/CD scope, and a GitLab plugin was requested during the same work. + +## Options considered + +| Option | Assessment | +|---|---| +| **One plugin, topical skills** | Simplest to register and validate; one install gets everything. Rejected: someone who wants the tracker conventions has no interest in ZFS recordsize, and installs it anyway. Skill descriptions from unrelated domains compete for attention in every session. | +| **Two: infrastructure + everything else** | Rejected. "Everything else" is not a topic, and the writing conventions would sit under a name that does not suggest them. | +| **Three: by theme** | Chosen. | +| **Four or more, splitting infrastructure by subsystem** | Rejected. Postgres, ZFS and kernel tuning are genuinely one job on a database host — the ARC and `shared_buffers` interaction is unresolvable if the two live in different plugins. | + +The GitLab work raised a parallel question: + +| Option | Assessment | +|---|---| +| **New plugin, leave the scaffold** | Rejected: leaves a tracked, defective, unregistered scaffold next to a plugin covering the same ground. | +| **Fill the scaffold under its existing name** | Rejected: `gitlab-standards` understates the scope, which is CI jobs, an MCP server, the CLI and standards. | +| **Rename the scaffold and rewrite it** | Chosen. | + +## Decision + +Three plugins: + +| Plugin | Scope | +|---|---| +| `act-platform-engineering` | Diagnosing and operating infrastructure: Postgres, ZFS, Linux hosts, Proxmox, observability, incident response | +| `act-work-tracking` | Zoho Projects mechanics, plus reporting and writing conventions | +| `act-gitlab-ci` | GitLab CI jobs, the GitLab MCP server, `glab`, pipeline standards | + +`plugins/gitlab-standards/` was renamed to `plugins/act-gitlab-ci/` with `git mv`, and all eleven +scaffold files were deleted. + +The `act-` prefix is retained throughout: it is the marketplace's namespace convention, matching the +existing `act-plugin-dev`, not leaked environment content. + +## Consequences + +**No cross-plugin references.** The three install independently, so a handoff pointing into another +plugin would break for anyone who installed only one. Every "hand off to X" names a skill or agent +within the same plugin. + +This constrained the content layout in one visible way: the runbook and postmortem templates sit in +`act-platform-engineering`'s `incident-response` skill rather than with the other writing templates in +`act-work-tracking`, because the agent that uses them lives in the first plugin. + +**`prompts/` dissolved.** Not being a component type, its eight files moved into `references/` inside +whichever skill owns each workflow. That mapping is what made the split fall out cleanly — templates +follow their workflow, and neither plugin reaches into the other. + +**The scaffold deletion removed a dependency.** `plugins/gitlab-standards/package.json` declared +`@modelcontextprotocol/sdk`, which had never been Socket-scored, for a channel server whose only tool +returned the string `"sent"` without sending anything. Deleting the scaffold removed the only +third-party dependency in the plugin tree. + +**Nothing was kept from the scaffold.** Its `.lsp.json` pointed at a language server named +`example-language-server`; its session hook parsed stdin and discarded it; its `plugin.json` carried +`"skills": ["./"]` alongside a `skills/` directory, which breaks auto-discovery. The rename preserved +the directory's history in git, not its contents. + +**One open item was closed and one was created.** The README's recorded gap about `gitlab-standards` +is resolved. `plugins/code-review/`, `plugins/standards/` and `plugins/git-workflows/` remain empty +shells, still correctly unregistered. diff --git a/docs/decisions/0004-derived-pipeline-standards.md b/docs/decisions/0004-derived-pipeline-standards.md new file mode 100644 index 0000000..7e0b3b4 --- /dev/null +++ b/docs/decisions/0004-derived-pipeline-standards.md @@ -0,0 +1,98 @@ +# 4. Ship pipeline standards as explicitly derived, and record the platform conflict + +- **Status:** Accepted +- **Date:** 2026-08-14 + +## Context + +`act-gitlab-ci` was asked to carry ACT pipeline standards alongside its docs-sourced content. + +No ACT GitLab CI conventions exist. The repository's own `CLAUDE.md` records this as a known gap: +*"No ACT GitLab CI conventions were available to base a pipeline on."* + +What does exist is the **Patterson CI/CD Pipeline Standards**, implemented as +`patterson-engineering:cicd-pipeline-standards` in a sibling checkout. It is detailed and +well-sourced: seven required CI scans with named tools, a two-approver minimum with five required +checks, federated-credentials-only, build-once-and-promote, three permitted deployment strategies. + +It was written for Azure DevOps and GitHub. + +Translating it to GitLab surfaced a direct contradiction: + +> Its version-control clause reads: *"Use **Azure DevOps or GitHub**. Nothing else."* + +GitLab is not on the allowlist. Worse, the approved-software list that the standard depends on +excludes GitLab's built-in scanners — SAST, Dependency Scanning, Secret Detection and Container +Scanning are all unlisted, while Checkmarx, GitLeaks and Trivy are named. Under the standard's own +decision rule, an unlisted tool requires review. + +So a GitLab pipeline aiming at compliance must **disable the scanners the platform gives it for free** +and integrate three external tools instead. That is a substantial, non-obvious cost, and it is +invisible until someone compares the tool list against the platform defaults. + +## Options considered + +| Option | Assessment | +|---|---| +| **Drop the standards; ship only docs-sourced content** | Cleanest. Rejected: it was explicitly requested, and a GitLab plugin with no standards leaves the question unanswered rather than answered carefully. | +| **Translate silently and present as ACT standards** | Rejected outright. It would give derived rules the authority of policy, and a reader could not tell which clauses were reviewed and which were inferred. | +| **Translate, and mark every clause derived; record the conflict** | Chosen. | +| **Translate and resolve the conflict by adding GitLab to the allowlist** | Rejected. Not this repository's decision to make. Amending another team's standard by writing a different version of it is how two conflicting standards come to exist. | + +## Decision + +Ship `act-gitlab-ci/skills/pipeline-standards/`, translated to GitLab, with three constraints: + +**1. Provenance is stated at the top of the skill**, in a `[!CAUTION]` block, before any rule. + +**2. `_SOURCES.md` records the full lineage:** the source article and its owner, the implementing +skill, a per-clause translation table with a confidence rating, and the GitLab conflict in full. + +**3. The source's own meta-rules are carried over verbatim:** + +> Do not add requirements that are not in this file or in `references/`. If the standard does not +> cover something, say so and mark it `[TBD]`. + +> Validator scripts under `scripts/` must only enforce rules that are quoted in `references/`. A rule +> with no citation is a bug. + +Every `[TBD]` in the source stays `[TBD]`. Seven survive, including that no DAST tool is named +anywhere in the standard. + +The skill's trigger phrases are GitLab-qualified so they do not collide with the authoritative skill +in the same workspace, and it names that skill as the alternative: + +```text +For the authoritative Azure DevOps and GitHub standard, use +patterson-engineering:cicd-pipeline-standards instead. +``` + +## Consequences + +**The conflict is escalated, not resolved.** Whether ACT may use GitLab at all, and whether GitLab's +native scanners can be approved, are decisions for the standard's owner. The plugin's job is to make +the question visible to whoever hits it, with enough context to escalate. + +**Patterson lineage returns to a repository that removed it.** This repository's governance documents +were deliberately rewritten without patterson-corp references. This skill reintroduces that lineage, +confined to one directory and labelled throughout. The alternative — encoding the rules without +naming their source — would be worse, presenting derived rules as though they originated here. + +**A validator was built to the same standard as the prose.** +`act-gitlab-ci/scripts/check-pipeline.ts` enforces only rules quoted in `references/`, and each rule +in the source cites the reference documenting it. Its limitations are documented rather than hidden: +it is a regex scanner, cannot follow `include:` or `extends:`, cannot see UI-configured settings, and +cannot tell a gating scan from one with `allow_failure: true`. + +Because the standard *requires* shared templates, and the checker cannot follow them, false +"missing scan" findings are expected on a well-structured pipeline. That is stated in the skill, the +review command and the agent. + +**The test suite pins the blind spots.** `run-tests.sh` asserts the checker does **not** detect +things behind an `include:`. If that starts passing, the documented caveats have become wrong and +someone must update the prose. A limitation nobody notices being fixed is a documentation defect. + +**A clean run is never a compliance statement.** Repeated in the skill, the command, the agent and the +script's own header: + +> Treat a clean run as "nothing obvious found", not as "compliant". diff --git a/docs/decisions/README.md b/docs/decisions/README.md new file mode 100644 index 0000000..d821949 --- /dev/null +++ b/docs/decisions/README.md @@ -0,0 +1,69 @@ +# Architecture decision records + +Decisions that shaped this repository, with the reasoning that produced them and the options that +were rejected. + +An ADR is written when a choice is **hard to reverse, non-obvious, or likely to be questioned later**. +Most changes need no ADR. A change that a future reader would otherwise want to undo, without knowing +what it cost to arrive at, needs one. + +## Index + +| ADR | Decision | Status | +|---|---|---| +| [0001](0001-fork-plugin-dev.md) | Fork `plugin-dev` rather than depend on it | Accepted | +| [0002](0002-config-driven-plugins.md) | Ship no environment identifiers; read them from a site-local settings file | Accepted | +| [0003](0003-three-plugin-split.md) | Split the operational bundle into three plugins | Accepted | +| [0004](0004-derived-pipeline-standards.md) | Ship pipeline standards as explicitly derived, and record the platform conflict | Accepted | + +## Format + +Numbered sequentially, filename `NNNN-kebab-case-summary.md`, never renumbered. + +```markdown +# N. Decision, as a sentence in the imperative + +- **Status:** Proposed | Accepted | Superseded by [NNNN](NNNN-....md) +- **Date:** YYYY-MM-DD + +## Context + +What situation forced a decision. State the constraints that were real at the time, +including the ones that later turn out to have been wrong. + +## Options considered + +| Option | Assessment | +|---|---| +| **The one you rejected** | Why. Be specific and fair to it. | +| **The one you chose** | Chosen. | + +## Decision + +What was decided, stated plainly enough to act on. + +## Consequences + +What this costs, what obligation it creates, and what a future reader needs to know +before undoing it. Include the consequences you are not happy about. +``` + +## Conventions + +**Status is never edited away.** A decision that stops being true is marked superseded, with a link +forward. Deleting it removes the reasoning someone will need when they consider the same option +again. + +**Rejected options earn real assessments.** "Rejected: too slow" teaches nothing. The next person +will reconsider that option, and the record exists so they can start from where you finished. + +**Consequences include the unwelcome ones.** ADR 0001 records that forking `plugin-dev` creates a +manual re-sync obligation. ADR 0004 records that it reintroduces a lineage this repository had +deliberately removed. Those are the entries that make the record trustworthy. + +**`[TBD:]` where a source is silent.** Do not resolve a gap by inference; mark it, so it can be +escalated to whoever owns the answer. + +```sh +grep -rn '\[TBD' docs/ plugins/ +``` diff --git a/docs/glossary.md b/docs/glossary.md new file mode 100644 index 0000000..4a65f2c --- /dev/null +++ b/docs/glossary.md @@ -0,0 +1,169 @@ +# Glossary + +Terms as this repository uses them. Several are overloaded elsewhere, and the differences matter. + +--- + +### Agent + +A subagent defined at `agents/.md`, delegated to for a bounded task. Discovered by YAML +frontmatter, which must carry `name`, `description` with `` blocks, `tools` and `model`. + +The `description` is what decides when it gets used, so the examples are load-bearing rather than +illustrative. + +### Catalog + +Informal name for `.claude-plugin/marketplace.json`. See [Marketplace](#marketplace). + +### `${CLAUDE_PLUGIN_ROOT}` + +The literal token a plugin uses to reference its own bundled files. Resolves at runtime to the +install location. + +Written literally, never as a resolved path (the gate fails on those) and never replaced with a +relative path (which passes the gate and breaks at install time, since commands run from the user's +working directory). + +### Command + +A user-invoked action at `commands/.md`, addressed as `/:`. +Discovered by YAML frontmatter carrying `description`, `argument-hint` and `allowed-tools`. + +Written **for** Claude, not to the user: the body is instructions to follow, not documentation to +read. + +### Component + +Collectively: skills, commands, agents, hooks and MCP servers. The installable parts of a plugin. + +### Draft + +A plugin still carrying `claude plugin init` TODO placeholders. It is *correct* for a draft to be +unregistered, and the gate reports it as a note rather than a failure. + +The exemption applies only while it is absent from the catalog. See +[`verification.md`](verification.md#the-draft-exemption). + +### Gate + +`scripts/verify-all.sh`. The single definition of every mechanical invariant, called by CI, the +GitLab mirror and the pre-commit hook. Must print `VERIFY-ALL: PASS`. + +### Hook + +Event-driven interception, configured at `hooks/hooks.json`. Fires on events such as `PreToolUse` or +`SessionStart`. + +A hook that can block should have an off switch environment variable, and it should be documented. + +### Marketplace + +The catalog of installable plugins, `.claude-plugin/marketplace.json`. Also the repository as a +whole, in the sense "this repository is a marketplace". + +> [!IMPORTANT] +> Marketplace **names occupy one flat global namespace**. Registering a second marketplace under the +> name `actdata-plugins` replaces this one rather than merging with it. + +### MCP server + +An external tool server declared in a plugin's `.mcp.json`. Installing the plugin registers it. + +Two distinct things can share a name — GitLab, for instance, has both an HTTP server at +`/api/v4/mcp` for interactive sessions and a runner-image binary supplying tools inside CI jobs. They +are not interchangeable. + +### Plugin + +An installable unit at `plugins//`, manifested by `.claude-plugin/plugin.json` and registered +in the marketplace. + +> [!IMPORTANT] +> A plugin with no catalog entry **does not exist**, however complete it is on disk. + +### `relevance` + +A required block on every marketplace entry, describing when the plugin is worth surfacing: + +```json +"relevance": { + "topic": "short topic phrase", + "signals": { "filesRead": ["**/pattern"] } +} +``` + +Write the globs as evidence of the *problem*, not of the plugin. A pattern matching the plugin's own +files makes it relevant only to itself. + +### Progressive disclosure + +The convention that a `SKILL.md` body stays lean — roughly 1,500 to 2,000 words — with detail pushed +into `references/` and working artefacts into `examples/`. + +The body carries reasoning; references carry lookup material. It matters because skill *descriptions* +are always in context while bodies are read on demand. + +### Reference + +A file under a skill's `references/`, read on demand. Long-form detail that would bloat the skill +body. + +A reference nothing points at is dead weight; `SKILL.md` must name it. + +### Settings file + +`.agents/.local.md`, written by the operator and gitignored via `.agents/*.local.md`. +`.claude/.local.md` remains supported as a legacy fallback. + +Holds the environment identifiers plugins deliberately do not ship — hostnames, addresses, IDs. See +[ADR 0002](decisions/0002-config-driven-plugins.md). + +### Skill + +Knowledge at `skills//SKILL.md`, loaded when its description matches what the user is doing. + +> [!WARNING] +> The frontmatter `name` must be **identical** to the directory name, in kebab-case. Title Case names +> are the norm outside this repository, so imported skills usually arrive broken. The gate fails on a +> mismatch. + +### Suite + +A `run-tests.sh` anywhere in the repository. The gate discovers and runs every one; adding a suite +needs no edit to the gate. + +POSIX `sh`, self-locating, fixtures generated into `.tmp/` and never committed. + +### `[TBD:]` + +The marker for a gap that should be escalated rather than filled by inference: + +```text +[TBD: no DAST tool is named in the CI/CD Pipeline Standards] +``` + +A question for whoever owns the answer, not a defect to quietly resolve. + +```sh +grep -rn '\[TBD' plugins/ docs/ +``` + +### Tracked bytes + +The sum of on-disk sizes of files `git ls-files` reports, which is the payload a clone downloads. +Budgeted at 2 MiB. + +Deliberately not `du` block accounting, which overstates the real figure by more than a factor of two +here. + +> [!CAUTION] +> Tracked means staged or committed. Unstaged work is invisible to the validators, so `git add -A` +> before trusting a green gate. + +### `.tmp/` + +The gitignored scratch directory at the repository root. **Never** a system temp directory; a +workspace hook blocks those, matching the literal string. + +Test fixtures are generated here at run time and cleaned up with a `trap`. diff --git a/docs/onboarding.md b/docs/onboarding.md new file mode 100644 index 0000000..9c9d83f --- /dev/null +++ b/docs/onboarding.md @@ -0,0 +1,398 @@ +# Onboarding + +Your first day in `actdata-plugins`, from a fresh clone to a merged change. + +This is the orientation layer. [`CONTRIBUTING.md`](../CONTRIBUTING.md) is the rulebook and does not +repeat itself here; read this first, then that. + +## Table of contents + +- [What you are working on](#what-you-are-working-on) +- [Day one: environment](#day-one-environment) +- [Orientation: how the repository is shaped](#orientation-how-the-repository-is-shaped) +- [The gate](#the-gate) +- [Making a change](#making-a-change) +- [Learning path](#learning-path) +- [First tasks](#first-tasks) +- [Security and supply chain](#security-and-supply-chain) +- [Team, access and communication](#team-access-and-communication) +- [Keeping this guide honest](#keeping-this-guide-honest) + +--- + +## What you are working on + +`actdata-plugins` is a plugin marketplace for **Claude Code, ChatGPT, Codex, and GitHub Copilot**. It is not an application or a +service. There is no server, no build step and nothing to deploy. + +The deliverable is the three host catalogs plus the plugins under `plugins/` that they point at. +People install those plugins through Claude Code, ChatGPT/Codex, or GitHub Copilot, so **the install +experience is the product**. A plugin that is correct on disk but broken on one supported host is not +compatible with that host. + +One consequence dominates everything else: + +> [!IMPORTANT] +> A plugin that is not registered in `.claude-plugin/marketplace.json` **does not exist**. It cannot +> be installed, however finished it looks. Creating a plugin directory and registering it are one +> task, not two. + +### What a plugin is made of + +Four component types, all discovered by convention rather than declared: + +| Component | Lives at | Discovered by | +|---|---|---| +| Skill | `skills//SKILL.md` | Directory scan; frontmatter `name` must equal the directory name | +| Command | `commands/.md` | YAML frontmatter | +| Agent | `agents/.md` | YAML frontmatter | +| Hook | `hooks/hooks.json` | The file's presence | + +> [!WARNING] +> Frontmatter is not decoration. A command or agent whose YAML fails to parse still appears in the +> menu but loads with **empty metadata**, silently dropping its `allowed-tools` restriction. The +> repository gate does not catch this. See [The gate](#the-gate). + +## Day one: environment + +### Prerequisites + +| Tool | Why | Verify | +|---|---|---| +| **Bun** | The only runtime. Runs the validators and test suites. | `bun --version` | +| **git** | 2.x | `git --version` | +| **Claude Code CLI** | `claude plugin validate`, and installing what you build | `claude --version` | +| **jq** | Used by one bundled plugin script | `jq --version` | +| **trufflehog**, **trivy** | Pre-commit secret scanning. Optional; the hook skips gracefully. | `trufflehog --version` | +| **socket** | Supply-chain scoring before adding any dependency | `socket --version` | + +There is no `.mise.toml` or `.tool-versions` in this repository, so tool installation is whatever your +machine already uses. + +> [!CAUTION] +> **Bun only.** Never `npm`, `yarn` or `pnpm`. `bun.lock` is the only permitted lockfile, and any +> other lockfile appearing here is a bug to remove rather than a preference to tolerate. + +### Setup + +```sh +git clone actdata-plugins +cd actdata-plugins + +bun install # devDependencies only; nothing here needs building +git config core.hooksPath .githooks # opt into the local pre-commit gate, once per clone +``` + +### Confirm it works + +```sh +sh scripts/verify-all.sh +``` + +You want `VERIFY-ALL: PASS` on a clean checkout before you change anything. If it fails on a fresh +clone, that is a repository problem rather than a you problem, and it is worth raising immediately. + +### Install what is here, and use it + +The fastest way to understand a marketplace is to be a user of it: + +```sh +claude plugin marketplace add . +claude plugin install act-plugin-dev@actdata-plugins +``` + +Then start a fresh session and run `/help`. The commands appear namespaced as +`:`. Seeing your own change surface that way closes the loop between what +you edited and what a user gets. + +## Orientation: how the repository is shaped + +```text +.claude-plugin/marketplace.json # Claude Code catalog +.agents/plugins/marketplace.json # ChatGPT and Codex catalog +.github/plugin/marketplace.json # GitHub Copilot catalog +plugins// + .claude-plugin/plugin.json # Claude manifest + .codex-plugin/plugin.json # OpenAI manifest + plugin.json # Copilot manifest + skills//SKILL.md # frontmatter name MUST equal the directory name + agents/*.md commands/*.md hooks/hooks.json + scripts/ # bundled executables, referenced via ${CLAUDE_PLUGIN_ROOT} +scripts/verify-all.sh # the gate. One script, every mechanical invariant. +scripts/check-size.ts # node:* builtins only, run by bun +scripts/check-no-binaries.ts +docs/decisions/ # ADRs +.tmp/ # gitignored scratch. Never /tmp. A workspace hook enforces this. +``` + +### The four plugins + +| Plugin | What it is | Read it because | +|---|---|---| +| `act-plugin-dev` | The toolkit for building plugins here: 7 skills, 3 review agents, the guided creation workflow | It is both the tooling you will use and the reference implementation you will copy | +| `act-platform-engineering` | PostgreSQL, ZFS, Linux and Proxmox assessment | The largest plugin. Good example of splitting one domain across several skills. | +| `act-work-tracking` | Zoho Projects tracking and reporting conventions | Smallest complete plugin. Good first read. | +| `act-gitlab-ci` | GitLab CI, the GitLab MCP server, `glab`, pipeline standards | The only plugin shipping an MCP server and a validator with its own test suite | + +### Suggested reading order + +1. This file. +2. [`README.md`](../README.md) — what the marketplace is and the plugin catalog. +6. [`docs/decisions/`](decisions/README.md) — the ADR index. Start with + [`0001-fork-plugin-dev.md`](decisions/0001-fork-plugin-dev.md) and the reason `act-plugin-dev` is + a fork rather than a dependency. + everything: skills with references and examples, an agent, commands, a script, a test suite. +5. `plugins/act-plugin-dev/README.md` — then its skills as you need them. +6. [`docs/decisions/0001-fork-plugin-dev.md`](decisions/0001-fork-plugin-dev.md) — the one ADR, and + the reason `act-plugin-dev` is a fork rather than a dependency. + +### Two design principles worth internalising early + +**Progressive disclosure.** A `SKILL.md` body should be lean, roughly 1,500 to 2,000 words, with +detail pushed into `references/` and working artefacts into `examples/`. The body carries the +reasoning; the references carry the lookup material. + +**Config-driven, not hardcoded.** The operational plugins ship **no** environment identifiers: no +hostnames, addresses, database names or portal IDs, not even as defaults or fallbacks. Those come +from a gitignored `.claude/.local.md` the operator writes. With no settings file +present, the commands ask rather than guess. + +That constraint is deliberate. A command that defaults to a plausible-looking hostname is a command +that will eventually run a diagnostic against the wrong machine and report confident findings about +it. + +## The gate + +```sh +sh scripts/verify-all.sh +``` + +One script defines every mechanical invariant. CI (`.github/workflows/ci.yml`), the GitLab mirror +(`.gitlab-ci.yml`) and `.githooks/pre-commit` all call it. It must print `VERIFY-ALL: PASS`. + +It checks: every discovered `run-tests.sh`, skill name equals directory name, plugin manifests parse +and match their directory, marketplace registration and version consistency, no tracked binaries, the +2 MiB tracked-byte budget, and no expanded `${CLAUDE_PLUGIN_ROOT}`. + +### The trap that catches everyone once + +> [!CAUTION] +> `check-size.ts` and `check-no-binaries.ts` read **tracked** files via `git ls-files`. On unstaged +> work they measure almost nothing and pass trivially. +> +> **Run `git add -A` before treating a green gate as meaningful.** + +### What the gate does not check + +Knowing the gaps is as useful as knowing the checks: + +| Not checked | Catch it with | +|---|---| +| YAML frontmatter parses in commands and agents | `claude plugin validate plugins/` per plugin | +| Emoji | Review, and the `plugin-validator` agent. A mechanical check cannot tell an ACT-authored surface from vendored upstream content. | +| Whether a skill is any good | The `skill-reviewer` agent | +| Environment identifiers leaking into a plugin | A targeted `git grep`, written per change | + +> [!NOTE] +> `claude plugin validate .` checks the **marketplace manifest**. It does not descend into each +> plugin's commands and agents. `claude plugin validate plugins/` does, and it is the only +> thing that catches an unparseable frontmatter block. Run it per plugin when you touch one. + +## Making a change + +The full rules are in [`CONTRIBUTING.md`](../CONTRIBUTING.md). The loop: + +```sh +git switch -c feat/my-change # never work on main +# ... make the change ... +git add -A # stage BEFORE verifying; the validators read tracked files +sh scripts/verify-all.sh # must print VERIFY-ALL: PASS +claude plugin validate . +claude plugin validate plugins/ # per plugin you touched +git commit -m "feat(scope): summary" +``` + +Conventional commits, one logical change per pull request, branch from `main`. No AI attribution in +commit messages or PR bodies: no `Claude-Session:` trailers, no "Generated with" footers, no AI +co-author lines. + +### Adding a plugin + +Prefer the guided workflow. It creates the directory, writes the manifest, registers the marketplace +entry and runs the gate, which keeps a plugin from sitting half-registered: + +```text +/act-plugin-dev:create-plugin +``` + +The by-hand checklist is in [`CONTRIBUTING.md`](../CONTRIBUTING.md#adding-a-plugin). + +### When a source is silent + +Write `[TBD: what is missing]` rather than inventing an answer. A `[TBD]` is a question to escalate +to whoever owns the thing, not a defect to quietly resolve. + +```sh +grep -rn '\[TBD' plugins/ docs/ +``` + +This convention is used throughout the repository, including in this guide. + +## Learning path + +The `act-plugin-dev` plugin carries the reference material. Load a skill when you need it rather than +reading them all up front: + +| You are about to | Load | +|---|---| +| Create or restructure a plugin | `plugin-structure` | +| Write a skill | `skill-development` | +| Write a slash command | `command-development` | +| Write a subagent | `agent-development` | +| Write a hook | `hook-development` | +| Wire in an MCP server | `mcp-integration` | +| Add user-supplied configuration | `plugin-settings` | + +Three review agents are available and worth using before you open a pull request: + +- `plugin-validator` — manifest, structure, naming, registration, security +- `skill-reviewer` — description quality, progressive disclosure, writing style +- `agent-creator` — generates an agent's identifier, triggering examples and system prompt + +### Learning by reading a real diff + +`git log` is short. Reading the commit that added the three operational plugins shows a complete +worked example: manifests, marketplace registration, skills with references, agents with triggering +examples, commands with frontmatter, two test suites, and the README updates that go with them. + +## First tasks + +Real open items, roughly by increasing difficulty. Each is genuinely unfinished; none is busywork. + +### Warm-up + +**1. Fix the frontmatter parse errors in `act-plugin-dev`.** +All three agents (`agent-creator`, `plugin-validator`, `skill-reviewer`) end their `description:` +with a bare `Examples:`, which is a YAML plain-scalar error. Confirm with +`claude plugin validate plugins/act-plugin-dev`. The fix is quoting; the value is that you will +understand the failure mode described in [The gate](#the-gate) by having repaired it. + +**2. Audit `[TBD]` markers.** +Run the grep above. Each one is a real question someone needs to answer. Working out *who* owns each +answer is a fast way to learn the repository's boundaries. + +### Substantial + +**3. Close the gate's blind spot.** +Add a per-plugin `claude plugin validate plugins/` step to `scripts/verify-all.sh`. It must skip +gracefully when the CLI is absent, matching the advisory step already in `.github/workflows/ci.yml`. +This prevents recurrence of task 1 rather than fixing one instance, and it is the highest-leverage +change on this list. + +**4. Fill one of the empty shells.** +`plugins/code-review/`, `plugins/standards/` and `plugins/git-workflows/` are empty directories with +no manifest. Pick one, scope it with `/act-plugin-dev:create-plugin`, and ship it registered. + +### Deeper + +**5. Rebalance `act-platform-engineering/skills/linux-host-tuning/`.** +Its `SKILL.md` is a router with no commands in the body; everything is one file-read away in +`references/`. Compare against `proxmox-virtualization` and `observability`, which keep commands +inline. Decide whether to inline `references/disk-health.md`, and write down why. + +**6. Resolve the pipeline standards conflict.** +`act-gitlab-ci/skills/pipeline-standards/` is translated from a standard that does not permit GitLab +and whose approved-tool list excludes GitLab's built-in scanners. See +[`_SOURCES.md`](../plugins/act-gitlab-ci/skills/pipeline-standards/_SOURCES.md). This is not a coding +task; it needs a decision from whoever owns the standard. Finding out who that is, and getting an +answer, is the work. + +### Recorded gaps: do not "fix" these without asking + +- `docs/assets/` holds an **invented placeholder** wordmark. No ACT brand assets exist. +- `LicenseRef-ACT-Internal` is a provisional identifier. ACT's licensing posture is unconfirmed. +- `act-plugin-dev` is a fork, not a dependency, and does not track upstream. The divergence is + deliberate and documented. + +## Security and supply chain + +### Before adding any dependency + +```sh +socket package shallow npm pkg:npm/@ --markdown +``` + +Five scores come back on a 0-100 scale: supply chain, maintenance, quality, vulnerability, license. +**Flag anything under 90** and get explicit confirmation before installing, naming which dimension is +low. Read the `[high]`/`[middle]`/`[low]` alerts line too; it is often more actionable than the +scores. + +> [!NOTE] +> Both validators in `scripts/` import only `node:*` builtins by design. Keeping them +> dependency-free means the gate runs before `bun install` and cannot itself become a supply-chain +> surface. New validators should hold that line. + +### Guards that will stop you + +Two hooks intercept tool calls, and both fail loud rather than silently: + +| Guard | Blocks | +|---|---| +| **No `/tmp`** | Anything created or stored under a system temp directory. Use the gitignored `.tmp/`. It matches the literal string, so it will fire on a `grep` pattern containing it too. | +| **Supply-chain denylist** | Known-malicious packages and publishers in commands and manifests | + +The documented escape hatch for a demo or a genuine false positive is +`PATTERSON_ENGINEERING_HOOKS=off`. Reach for it rarely and say why. + +### Secrets + +Never commit a credential. The pre-commit hook runs trufflehog and trivy over the working tree when +they are installed, and skips with a printed notice when they are not. That skip is why the hook is +a convenience rather than the control: **you** are the control. + +Plugin scripts read credentials from environment variables and never write them anywhere. Follow that +pattern. + +## Team, access and communication + +> [!IMPORTANT] +> This section is deliberately unfilled. The team structure, communication channels and access +> procedures for this repository were not available when this guide was written, and inventing them +> would be worse than leaving them blank: a confidently wrong contact list wastes a new joiner's +> first week. +> +> If you are onboarding and can answer any of these, filling them in is a genuinely useful first +> contribution. + +- `[TBD: team structure, roles, and who owns which plugin]` +- `[TBD: communication channels, and which one is appropriate for what]` +- `[TBD: meeting cadence and which are expected of a new joiner]` +- `[TBD: mentor or buddy assignment process]` +- `[TBD: accounts and access to request on day one, and from whom]` +- `[TBD: escalation path for a blocked or ambiguous decision]` +- `[TBD: compliance or security training required before contributing]` + +What is known and does not need escalating: + +- Issue and pull request templates are in `.github/`, including a dedicated new-plugin proposal form. +- `CODEOWNERS` records review ownership. +- `SECURITY.md` documents vulnerability reporting. + +## Keeping this guide honest + +An onboarding guide decays faster than anything else in a repository, because the people best placed +to notice are the ones least confident about correcting it. + +If you are working through this and something is wrong, stale or missing, change it in the same +branch as the work that revealed it. That is a `docs:` commit and needs no ceremony. + +Two habits that keep it accurate: + +- When a `[TBD]` gets answered, replace it here rather than only in the conversation where it was + answered. +- When you hit something confusing that this guide should have warned you about, add the warning + while you still remember being confused. Nobody has that perspective for long. + +> [!NOTE] +> `[TBD: onboarding feedback mechanism and review cadence for this guide.]` Until one exists, the +> pull request that fixes something here is the feedback. diff --git a/docs/releasing.md b/docs/releasing.md new file mode 100644 index 0000000..be5fb35 --- /dev/null +++ b/docs/releasing.md @@ -0,0 +1,169 @@ +# Versioning and releasing + +How versions work here, and what is not yet decided. + +> [!NOTE] +> This repository has shipped its first feature release. Plugins and the catalog are at `0.2.0`. +> The sections below separate **what is enforced today** from **what needs deciding**, rather than +> describing a process that does not exist. + +## Table of contents + +- [Where versions live](#where-versions-live) +- [What is enforced](#what-is-enforced) +- [Choosing a version](#choosing-a-version) +- [Bumping a plugin](#bumping-a-plugin) +- [What a user actually gets](#what-a-user-actually-gets) +- [Open questions](#open-questions) + +--- + +## Where versions live + +Each plugin now has host-specific manifests and catalog entries. They describe one release and must +carry the same plugin version. + +| Version | File | Means | +|---|---|---| +| Marketplace | `.claude-plugin/marketplace.json` top level | The catalog's own version | +| Plugin manifests | `.claude-plugin/plugin.json`, `.codex-plugin/plugin.json`, and root `plugin.json` | That plugin's version | +| Catalog entries | The plugin's entries in the Claude, OpenAI, and Copilot marketplaces | The version each host advertises where supported | + +The **second and third must match**. The first is independent. + +Current state: every one of them is `0.2.0`. + +## What is enforced + +`scripts/verify-all.sh` step 4 fails the build when a plugin's `plugin.json` version disagrees with +its catalog entry: + +```text +: version 0.2.0 in plugin.json but 0.1.0 in marketplace.json +``` + +The reason is that the disagreement is otherwise silent: the catalog advertises one version and the +install delivers another, and nothing surfaces it to the user. + +Nothing else about versioning is enforced. Semver discipline, changelogs and tags are all conventions +at best — see [Open questions](#open-questions). + +## Choosing a version + +Semver, applied to what a *plugin consumer* experiences. The useful question is not "did the files +change" but "will this surprise someone who already installed it". + +| Bump | When | +|---|---| +| **Patch** `0.1.0 → 0.1.1` | A fix with no interface change. A corrected command, a clarified skill body, a typo in a reference. | +| **Minor** `0.1.0 → 0.2.0` | New capability, backward compatible. A new skill, command or agent. A new optional settings field. | +| **Major** `0.1.0 → 1.0.0` | A break. See below. | + +### What counts as a break in a plugin + +Less obvious than in a library, because the interface is partly conversational: + +- **Renaming or removing a command, agent or skill.** Anyone with it in a runbook or an alias loses it. +- **Changing a settings file's schema** so an existing one stops working. +- **Changing a command's arguments** incompatibly. +- **Adding a required settings field.** A working install starts asking questions. +- **Changing what a script does to a system**, or its exit codes. + +Deliberately *not* breaking: + +- Rewording a skill body. The knowledge changed; the interface did not. +- Adding a `references/` file. +- Broadening a skill description so it triggers more often — though narrowing one so it triggers + *less* can be, if someone depended on the old behaviour. + +### The 0.x caveat + +Everything is `0.2.0`, and under semver a `0.x` version signals that the interface is not yet stable. +That is currently accurate. It also means the major-bump rules above are theoretical until a `1.0.0` +is cut, which is one of the open questions. + +## Bumping a plugin + +```sh +# 1. All host manifests and catalogs, same commit +$EDITOR plugins//.claude-plugin/plugin.json +$EDITOR plugins//.codex-plugin/plugin.json +$EDITOR plugins//plugin.json +$EDITOR .claude-plugin/marketplace.json +$EDITOR .github/plugin/marketplace.json + +# 2. Update counts if components were added or removed +$EDITOR plugins//README.md # badges, component tables +$EDITOR README.md # catalog row, top badges + +# 3. Verify +git add -A +sh scripts/verify-all.sh +claude plugin validate . +claude plugin validate plugins/ + +# 4. Commit +git commit -m "chore(): bump to 0.2.0" +``` + +Bump both files in the **same commit**. A commit where they disagree is a commit that fails the gate, +which means a bisect lands on a broken build for reasons unrelated to what is being bisected. + +### Version the plugin, not the repository + +A change to one plugin bumps that plugin. It does not bump the others, and it does not bump the +marketplace. Plugins are installed individually and version independently. + +## What a user actually gets + +Worth understanding before designing a release process around it: + +```sh +claude plugin marketplace add patterson-agents/actdata-plugins +claude plugin install act-platform-engineering@actdata-plugins +``` + +The catalog is read from the repository. There is no registry between the two, no build artefact and +no publish step. **A merge to the default branch is the release**, for anyone who re-adds the +marketplace or installs fresh. + +Two consequences: + +- Version numbers are documentation, not distribution. They tell a reader what changed; they do not + gate what is delivered. +- Anything merged is live for the next install. There is no staging point between merge and users. + +That is why the gate runs on every push rather than at a release boundary. There is no later moment +at which to catch something. + +## Open questions + +Each is a real decision nobody has made. They are `[TBD]` rather than assumed. + +**`[TBD: whether releases are tagged, and in what format.]`** +No tags exist. If plugins version independently, per-plugin tags such as +`act-platform-engineering/v0.2.0` are one option; a repository-level tag is another and fits the +"merge is the release" model badly. + +**`[TBD: whether a changelog is kept, and at what granularity.]`** +No `CHANGELOG.md` exists at either level. Conventional commits make one generatable, which is an +argument for per-plugin changelogs generated from commit scopes. + +**`[TBD: what the marketplace's own top-level version means, and when it changes.]`** +It is `0.2.0`. Candidates: it tracks catalog structure, or it is vestigial and +should be removed. + +**`[TBD: whether a plugin may be removed from the catalog, and what a consumer sees if it is.]`** +Relevant before anything reaches `1.0.0`. + +**`[TBD: whether `main` is always installable, or whether a release branch is wanted.]`** +Today, merging makes a change live for the next install. That is fine while the audience is internal +and small; it is worth revisiting before it is not. + +## Related + +| Topic | Where | +|---|---| +| The version-consistency check | [`verification.md`](verification.md#4-marketplace-registration-and-version-consistency) | +| Commit conventions | [`CONTRIBUTING.md`](../CONTRIBUTING.md) | +| What a marketplace entry needs | [`architecture.md`](architecture.md#three-catalogs-three-manifests) | diff --git a/docs/troubleshooting.md b/docs/troubleshooting.md new file mode 100644 index 0000000..ce1893c --- /dev/null +++ b/docs/troubleshooting.md @@ -0,0 +1,396 @@ +# Troubleshooting + +Symptom, cause, fix. Every entry here is a failure that has actually occurred in this repository. + +## Table of contents + +- [The gate](#the-gate) +- [Plugins and components](#plugins-and-components) +- [Skills](#skills) +- [Commands and agents](#commands-and-agents) +- [MCP servers](#mcp-servers) +- [Hooks and guards](#hooks-and-guards) +- [Scripts and tests](#scripts-and-tests) +- [Git and tooling](#git-and-tooling) + +--- + +## The gate + +### The gate passes but I know something is wrong + +**Cause:** You did not stage. `check-size.ts` and `check-no-binaries.ts` read **tracked** files via +`git ls-files`. Untracked work is invisible to them. + +```sh +git add -A && sh scripts/verify-all.sh +``` + +This is the single most common false-green in the repository. + +### `FAIL test suites (none found -- expected at least one run-tests.sh)` + +**Cause:** The discovery `find` returned nothing. Either you are not at the repository root (unlikely +— the script resolves its own path), or the suites were removed. + +**Fix:** Confirm at least one exists: `find . -name run-tests.sh -not -path './.git/*'`. + +The zero-suite case is a deliberate failure rather than a vacuous pass, so a silently broken glob +cannot look green. + +### `FAIL skill name == directory` + +**Cause:** A `SKILL.md` frontmatter `name` does not equal its directory name. Almost always a skill +imported from elsewhere, where Title Case names are the norm. + +```yaml +# skills/plugin-structure/SKILL.md +name: Plugin Structure # wrong +name: plugin-structure # correct +``` + +**Two mechanical gotchas** if the name *looks* right: + +- The `name:` must appear in the **first 20 lines**. +- It must be at **column 0**. Indented, it is not found, and the comparison sees an empty string. + +### `FAIL marketplace registration` + +Read the printed problem line; each maps to one fix. + +| Message | Fix | +|---|---| +| `on disk but absent from marketplace.json` | Add the catalog entry, with `source`, matching `version`, and `relevance` | +| `version X in plugin.json but Y in marketplace.json` | Bump both in the same commit | +| `source "..." does not resolve` | The path is wrong or the directory moved | +| `missing required "relevance" block` | Add one; it is required on every entry | +| `registered in marketplace.json but has no plugin.json on disk` | A stale entry for a removed or renamed plugin | + +### `FAIL no expanded ${CLAUDE_PLUGIN_ROOT}` + +**Cause:** A tracked file contains an absolute `/home/...` or `/workspaces/...` path followed by +`/plugins/`, `/skills/` or `/hooks/`. Usually a tool resolved the token and wrote the result back. + +**Fix:** Replace with the literal `${CLAUDE_PLUGIN_ROOT}`. + +The printed hits include file and line. There is exactly one exemption, for a documented cautionary +placeholder in `act-plugin-dev`'s teaching material. + +### The size budget failed + +```sh +bun scripts/check-size.ts . +``` + +The `INFO` line reports total tracked bytes against the 2 MiB budget. Find the offender: + +```sh +git ls-files -z | xargs -0 du -b 2>/dev/null | sort -rn | head -20 +``` + +Usually a committed binary that `check-no-binaries.ts` should also have caught, or a large vendored +tree. + +--- + +## Plugins and components + +### My plugin does not appear in `claude plugin install` + +**Cause, in order of likelihood:** + +1. **Not registered.** No entry in `.claude-plugin/marketplace.json`. This is the answer most of the + time. A plugin that is not in the catalog does not exist. +2. The marketplace was added before your change. Re-add it: `claude plugin marketplace add .` +3. `source` does not resolve to the plugin directory. + +### My change does not take effect + +**Cause:** Components are discovered at session start. An existing session holds the old copy. + +**Fix:** Start a fresh session, or `/reload-plugins` where supported. + +### The plugin installed but nothing from it is available + +**Cause:** Discovery found no components. Check the layout — components must be at +`skills//SKILL.md`, `commands/.md`, `agents/.md`, not at the plugin root. + +A `SKILL.md` at the plugin root is the single-skill template shape. It does not combine with a +`skills/` directory. + +### `"skills": ["./"]` in `plugin.json` + +**Cause:** Copied from the single-skill template, or left behind by `claude plugin init`. + +**Fix:** Remove the field. It expects a `SKILL.md` at the plugin root and **breaks auto-discovery** +when a `skills/` directory exists. Plugins with a `skills/` directory need no `skills` field at all. + +--- + +## Skills + +### A skill never triggers + +**Cause:** The description does not contain phrasing the user actually types. Descriptions are what +skills are matched on; the body is irrelevant until after a match. + +**Fix:** Write concrete trigger phrases in the user's words, and include symbol triggers — flag +names, config keys, error strings. Those fire on pasted output, which quoted phrases never catch. + +```yaml +description: This skill should be used when the user asks to "assess Postgres", "why is the database + slow", "check replication", or mentions pg_stat_statements, replication slots, WAL shipping... +``` + +### The wrong skill triggers + +**Cause:** Two descriptions claim the same utterance. + +**Fix:** Narrow the losing one and add an explicit redirect. `gitlab-mcp-server` gave up its +connection-failure trigger to `ci-troubleshooting` and says so in its own description: + +```text +For a server that will not connect, use ci-troubleshooting instead. +``` + +This matters most when the competing skill is authoritative and yours is derived. Qualify your +triggers so the authoritative one wins. + +### A skill loads but the reference material does not + +Reference files are read on demand, not automatically. `SKILL.md` must name them, and the reader must +have a reason to open them. A `references/` file nothing points at is dead weight. + +--- + +## Commands and agents + +### A command appears but has no description, or ignores `allowed-tools` + +**Cause:** Its YAML frontmatter failed to parse. The component still loads, with **every field +dropped** — including the tool restriction. + +**Diagnose:** + +```sh +claude plugin validate plugins/ +``` + +`claude plugin validate .` will **not** catch this; it validates the marketplace manifest only. + +**The two causes:** + +```yaml +# 1. Unquoted colon-space inside a plain scalar +description: Report coverage: collectors, dashboards # breaks +description: "Report coverage: collectors, dashboards" # correct + +# 2. A trailing colon at end of line +description: ... and here are the examples. Examples: # breaks +``` + +For a multi-line description with embedded blocks, use a block scalar: + +```yaml +description: | + First line. + + + ... + +``` + +> [!NOTE] +> The validator stops at the first error. After fixing one, run it again — there may be more. + +### An agent never gets delegated to + +**Cause:** The `description` lacks concrete `` blocks, so there is nothing to match a +situation against. + +**Fix:** Three examples, each a distinct scenario, each with a `` explaining why this +agent rather than another. Generic filler examples do not help. + +### A bundled script is not found at install time + +**Cause:** A relative path. Commands execute from the user's working directory, not the plugin +directory. + +```markdown +sh scripts/thing.sh # breaks after install +"${CLAUDE_PLUGIN_ROOT}/scripts/thing.sh" # correct +``` + +The gate does **not** catch this — it only greps for *expanded* absolute paths. A relative path is +syntactically fine and silently wrong. + +--- + +## MCP servers + +### The server does not appear in `/mcp` + +1. Is `.mcp.json` at the **plugin root**, not inside `skills/` or `commands/`? +2. Does the JSON parse? +3. If the URL comes from an environment variable, is it set? + +### `${VAR}` in `.mcp.json` did not expand + +`${CLAUDE_PLUGIN_ROOT}` expands. Arbitrary environment variables may not, depending on the client +version. + +**Fix if it does not:** document the direct form instead of shipping the file. + +```sh +claude mcp add --transport http gitlab https:///api/v4/mcp +``` + +### The GitLab MCP server will not connect + +Prerequisites fail far more often than configuration does. All three must be on, and on GitLab.com +they are **per top-level group** while on Self-Managed they are instance-wide: + +1. GitLab Duo set to "Always on" or "On by default" +2. Beta and experimental features enabled +3. MCP access allowed + +Minimum GitLab 18.6 for beta. + +> [!WARNING] +> Do not retry in a loop. OAuth Dynamic Client Registration is limited to **10 registrations per hour +> per IP**. Exhausting it changes the failure into a different-looking one, and you end up debugging +> the wrong problem. + +### A GitLab MCP tool is missing + +Every tool is version-gated between 18.3 and 19.3. Several common ones arrived only in 19.3: +`list_merge_requests`, `add_branch`, `get_pipeline`, `list_pipelines`, `list_wiki_pages`. + +Check the instance version against +[`tool-catalogue.md`](../plugins/act-gitlab-ci/skills/gitlab-mcp-server/references/tool-catalogue.md). + +`semantic_code_search` additionally needs a Duo Core, Pro or Enterprise add-on. + +### A tool returns 404 for one person and works for another + +Not a bug. The server authenticates per user via OAuth and acts with **that person's** permissions. +Project access differs between people. + +--- + +## Hooks and guards + +### `BLOCKED by patterson-engineering: this command references a system temp directory` + +**Cause:** Your command contains a system temp path. Scratch belongs in the gitignored `.tmp/`. + +**The surprising case:** it matches the **literal string**, so it fires on a search pattern too: + +```sh +grep -c '/t''mp/' file.md # split the literal +grep -cE '/t[m]p/' file.md # or use a character class +``` + +Both are legitimate ways to search for the pattern without writing it. + +The documented escape hatch is `PATTERSON_ENGINEERING_HOOKS=off`, for a demo or a genuine false +positive. Reach for it rarely. + +### A hook in a plugin never fires + +1. Is it at `hooks/hooks.json`? +2. Does the JSON parse? +3. Does the command use the literal `${CLAUDE_PLUGIN_ROOT}`? +4. Is the handler executable? + +Give any blocking hook an off switch environment variable and document it. + +--- + +## Scripts and tests + +### A test suite passes locally and fails in CI + +**The usual cause:** the suite depends on something present locally and absent on the runner — +credentials, an installed binary, network access. + +**The pattern that avoids it:** make the credential-free path work with no configuration, and test +that specifically. + +`zoho-create.sh` parses `--dry-run` **before** reading any environment variable, so the dry run works +with no `ZOHO_*` set. Its suite unsets them all before running, so a developer's own environment +cannot mask a regression that would fail in CI. + +**Skip gracefully on a missing tool:** print a note and continue rather than failing. + +### A fixture trips the check it exists to test + +**Cause:** You committed it. A file proving the size check works is itself an oversized tracked file. + +**Fix:** Generate fixtures at test-run time into `.tmp/` with a cleanup trap. Never commit them. + +### `bun: command not found` in a suite + +The gate runs suites with `sh`, and they inherit the environment. Guard tool use: + +```sh +if ! command -v bun >/dev/null 2>&1; then + echo " note: bun not installed; skipping execution tests" +fi +``` + +--- + +## Git and tooling + +### `git rm` fails with "changes staged in the index" + +**Cause:** The file is staged. `git rm` refuses to discard staged content silently. + +```sh +git rm -f # after confirming you mean it +``` + +### `&&` or `||` fails in a shell command + +The environment's interactive shell is Nushell, which has neither. The `Bash` tool runs a POSIX +shell, so `&&` works there. + +If a compound command fails to parse, test which shell you are in before rewriting the command. + +| Instead of | Nushell | +|---|---| +| `a && b` | `a; b` | +| `a \|\| b` | `try { a } catch { b }` | +| `cmd &` | `job spawn { cmd }` | +| `$(cmd)` | `(cmd)` | + +### A commit was rejected by the pre-commit hook + +Read the message; it names the scanner. Both trufflehog and trivy print the command to reproduce. + +If it is a false positive, fix the pattern rather than bypassing. `git commit --no-verify` exists but +should come with an explanation. + +### Python was rejected + +Python is forbidden repository-wide: no `python`/`python3`, no `pip`, no `.py` files. Use TypeScript +under `bun`, or POSIX `sh`. + +This is why `zoho-create.sh` accepts JSON only — its CSV path used a Python converter and was removed +rather than ported. + +--- + +## Still stuck + +| Question | Where | +|---|---| +| How does any of this work? | [`architecture.md`](architecture.md) | +| What exactly does the gate check? | [`verification.md`](verification.md) | +| What are the rules? | [`CONTRIBUTING.md`](../CONTRIBUTING.md) | +| How do I write a *good* skill? | `act-plugin-dev`'s `skill-development` skill, then the `skill-reviewer` agent | +| Is my plugin correct? | The `plugin-validator` agent | + +If the answer was not here and you worked it out, add it. An entry costs three lines and saves the +next person an afternoon. diff --git a/docs/verification.md b/docs/verification.md new file mode 100644 index 0000000..80f4efb --- /dev/null +++ b/docs/verification.md @@ -0,0 +1,349 @@ +# Verification + +Every mechanical invariant in this repository, what enforces it, and what nothing enforces. + +```sh +sh scripts/verify-all.sh +``` + +One script. CI (`.github/workflows/ci.yml`), the GitLab mirror (`.gitlab-ci.yml`) and +`.githooks/pre-commit` all call it. It must print `VERIFY-ALL: PASS`. + +## Table of contents + +- [The staging trap](#the-staging-trap) +- [The seven checks](#the-seven-checks) +- [What the gate does not check](#what-the-gate-does-not-check) +- [The validators](#the-validators) +- [Writing a test suite](#writing-a-test-suite) +- [The pre-commit hook](#the-pre-commit-hook) +- [CI](#ci) +- [Known gaps in the gate itself](#known-gaps-in-the-gate-itself) + +--- + +## The staging trap + +> [!CAUTION] +> `check-size.ts` and `check-no-binaries.ts` enumerate files with `git ls-files`, which reports +> **tracked** files only. On unstaged work they measure almost nothing and pass trivially. +> +> Run `git add -A` before treating a green gate as meaningful. + +This catches everyone once. A new plugin that is entirely untracked will sail through both validators +while contributing zero bytes and zero binaries to their view of the tree. + +## The seven checks + +`verify-all.sh` resolves its own path, `cd`s to the repository root and runs these in order. Each +prints `PASS` or `FAIL`; the script exits non-zero if any failed. + +### 1. Test suites + +Discovers every `run-tests.sh` in the repository and runs each with `sh`: + +```sh +find . -path ./.git -prune -o -name node_modules -prune -o -path ./.tmp -prune \ + -o -name 'run-tests.sh' -print +``` + +`.git`, `node_modules` and `.tmp` are pruned. A vendored dependency's own harness is not this +repository's to run, and `.tmp` holds generated fixtures. + +**Adding a suite requires no edit to the gate.** Drop a `run-tests.sh` anywhere and it is picked up. + +Zero suites found is a failure, not a pass. That guards against the discovery glob silently breaking. + +Current suites: + +| Suite | Covers | +|---|---| +| `scripts/tests/run-tests.sh` | All three repository validators (`check-size.ts`, `check-no-binaries.ts`, `check-marketplace-compat.ts`) | +| `plugins/act-work-tracking/scripts/tests/run-tests.sh` | `zoho-create.sh`, 17 assertions | +| `plugins/act-gitlab-ci/scripts/tests/run-tests.sh` | `check-pipeline.ts`, 23 assertions | + +### 2. Skill name equals directory name + +Scans `plugins/*/skills/*/SKILL.md`. For each, compares the containing directory's name against the +frontmatter `name`. + +```sh +frontmatter_name=$(sed -n '1,20p' "$skill_md" | grep -m1 '^name:' | sed 's/^name:[[:space:]]*//') +``` + +Two mechanical details that matter when debugging a mismatch: + +- The `name:` must appear within the **first 20 lines**. +- It must be at **column 0**. An indented `name:` inside a nested structure is not found. + +The glob is one level deep. A skill at `plugins/x/skills/a/b/SKILL.md` is not scanned. + +### 3. Plugin manifests + +For each `plugins/*/.claude-plugin/plugin.json`: it must parse as JSON, and its `name` must equal the +plugin's directory name. + +Parsing is done by `bun -e`, so a syntax error is reported with the JSON parser's own message. + +### 4. Marketplace registration and version consistency + +The largest check. For every directory under `plugins/` that has a `plugin.json`: + +| Rule | Failure | +|---|---| +| Registered in the catalog | `: on disk but absent from marketplace.json` | +| `version` matches between the two manifests | `version X in plugin.json but Y in marketplace.json` | +| `source` resolves to a real path | `source "..." does not resolve` | +| A `relevance` block is present | `missing required "relevance" block` | + +Then the reverse direction: every catalog entry must have a `plugin.json` on disk at its `source`. + +A directory with no `plugin.json` is skipped as an empty placeholder shell rather than failing. That +is how `plugins/code-review/`, `plugins/standards/` and `plugins/git-workflows/` coexist with a green +gate. + +#### The draft exemption + +A plugin whose `.md` files contain `TODO — `, `TODO: ` or `TODO -- ` is a draft, and an unregistered +draft is reported as a note rather than failed: + +```text +note: is still a scaffold (TODO placeholders); correctly unregistered +``` + +> [!WARNING] +> The exemption applies **only while the plugin is absent from the catalog**. Once registered, +> `isDraft()` is never consulted and every rule above applies, so a fully-registered scaffold passes +> the gate while shipping placeholder text to users. +> +> The scan reads `.md` files only. TODO markers in `.ts` or `.json` do not mark a draft. + +### 5. Cross-runtime marketplace compatibility + +`scripts/check-marketplace-compat.ts` compares the Claude, OpenAI, and GitHub Copilot catalogs and +plugin manifests. It checks registration, names, versions, source paths, and required OpenAI policy +metadata. + +### 6. No binaries, and the size budget + +Both validators run against the whole repository. See [The validators](#the-validators). + +### 7. No expanded `${CLAUDE_PLUGIN_ROOT}` + +```sh +git grep -nE '(/home/|/workspaces/)[^"'"'"' ]*/(plugins|skills|hooks)/' -- . +``` + +An absolute path immediately followed by `/plugins/`, `/skills/` or `/hooks/` means a tool wrote a +resolved path back into a tracked file instead of leaving the token literal. + +One exemption, written as a full literal string: + +```text +/home/user/.claude/plugin[s]/my-plugin/ +``` + +That is the *wrong* half of a Wrong/Correct pair in `act-plugin-dev`'s command-development examples, +which teaches authors not to hardcode plugin paths. Because the exemption is the literal path rather +than a file allowlist, a genuinely leaked path landing in that same file is still caught. + +> [!NOTE] +> Both the pattern and its documentation wrap a letter in a character class (`plugin[s]`) so that +> `verify-all.sh` does not contain the literal string and therefore never flags itself. The check +> scans all tracked files, including its own source. + +## What the gate does not check + +Knowing the holes is as useful as knowing the checks. + +| Not checked | Why not | Catch it with | +|---|---|---| +| **YAML frontmatter parses** in commands and agents | The gate reads frontmatter with `sed` and `grep`, not a YAML parser | `claude plugin validate plugins/` | +| **Emoji** | A mechanical check cannot distinguish an ACT-authored surface from vendored upstream content, where check marks are semantic markers | Review, and the `plugin-validator` agent | +| **Relative paths where `${CLAUDE_PLUGIN_ROOT}` belongs** | A relative path is syntactically fine; it just breaks at install time | Reading the diff | +| **Environment identifiers leaking into a plugin** | The set of forbidden strings is per-change, not global | A targeted `git grep`, written per change | +| **Whether a skill is any good** | Not mechanical | The `skill-reviewer` agent | +| **Whether a scan in a pipeline actually gates it** | Out of scope for this repository's gate | `act-gitlab-ci`'s own checker, with its own caveats | + +### The frontmatter gap, specifically + +This is the most consequential omission, because the failure is silent and security-relevant. + +```sh +claude plugin validate . # marketplace manifest ONLY +claude plugin validate plugins/ # descends into commands and agents +``` + +The first is what `verify-all.sh` and CI run. The second is the one that catches an unparseable +`description:`. Run it per plugin you touch. + +When frontmatter fails to parse, the component still loads, with every field dropped — including +`allowed-tools`, so the tool restriction silently does not apply. + +## The validators + +All three live in `scripts/`, import only `node:*` builtins, and run under `bun`. + +### Shared contract + +| | | +|---|---| +| Usage | `bun scripts/.ts ` | +| Output | `LEVEL\|file\|line\|rule\|message` | +| Levels | `ERROR`, `WARN`, `INFO` | +| Exit 0 | Pass, no `ERROR` findings | +| Exit 1 | `ERROR` findings present | +| Exit 2 | Could not evaluate | + +`line` is always `0` for all three, since they are whole-tree checks. + +Exit 2 is distinct from exit 1 on purpose: "the tree is bad" and "I could not look at the tree" are +different outcomes, and conflating them turns a broken validator into a green build. + +### `check-size.ts` + +Sums the on-disk byte size of every file `git ls-files` reports as tracked. + +```text +BUDGET_BYTES = 2 * 1024 * 1024 # 2 MiB +``` + +It deliberately does **not** use `du` block accounting, which overstates the real figure by more than +a factor of two on this tree and would make a byte budget fire on phantom growth. Tracked bytes are +what a clone actually downloads. + +> [!NOTE] +> `[TBD: the 2 MiB budget figure is awaiting ratification; it is not specified in a Patterson +> source.]` + +### `check-no-binaries.ts` + +Flags tracked files that are fonts, office documents, PDFs, archives, or raster images over a +threshold. + +| Category | Extensions | Limit | +|---|---|---| +| Font | `.woff`, `.woff2`, `.ttf`, `.otf`, `.eot` | Any | +| Archive | `.zip` | Any | +| Document | `.pdf`, and anything starting `doc`, `xls`, `ppt` | Any | +| Raster | `.png`, `.jpg`, `.jpeg`, `.gif`, `.webp` | 50 KiB | +| **SVG** | `.svg` | **Exempt at any size** | + +SVG is exempt because it is text, and because it is the only image format this catalog ships. + +Brand fonts are licensed through Adobe Fonts and must never be committed. That is a licensing +constraint, not only a size one. + +### `check-marketplace-compat.ts` + +Verifies that every on-disk plugin is represented consistently across all three host catalogs +(Claude, OpenAI, and Copilot) and that no stale entries exist only in the OpenAI or Copilot +catalog. + +For each plugin directory that has a `.claude-plugin/plugin.json`: + +- All three per-plugin manifests (`.claude-plugin/plugin.json`, `.codex-plugin/plugin.json`, + root `plugin.json`) must exist and carry the same `version`. +- An entry must exist in all three host catalogs. +- The Claude entry's `source` must resolve to the plugin's own directory. +- The OpenAI entry's `source.path` must resolve to the plugin's directory, with `source.source` + set to `"local"`, and its `policy` must declare `AVAILABLE` / `ON_INSTALL`. +- The Copilot entry's `source` must resolve to the plugin's directory. +- No name may appear only in the OpenAI or Copilot catalog without a matching Claude entry. + +Usage requires a path argument; omitting it or passing a non-directory exits 2. + +## Writing a test suite + +The convention, established by `scripts/tests/run-tests.sh` and followed by both plugin suites: + +**POSIX `sh`, not bash.** The gate invokes suites with `sh`. + +**Self-locating.** Resolve paths from `$0` so the suite runs from anywhere: + +```sh +SUITE_DIR=$(CDPATH= cd -- "$(dirname -- "$0")" && pwd) +``` + +**Count and report.** Print one line per assertion, then a summary, and exit non-zero on any failure. + +**Generate fixtures, do not commit them.** A fixture proving the size check works would itself be an +oversized file tripping the very check it tests. Generate into the gitignored `.tmp/` with a cleanup +trap: + +```sh +mkdir -p "$ROOT/.tmp" +WORK=$(mktemp -d "$ROOT/.tmp/my-tests.XXXXXX") || exit 1 +cleanup() { rm -rf "$WORK"; } +trap cleanup EXIT +``` + +> [!CAUTION] +> Never `/tmp`. A workspace hook blocks any command referencing a system temp directory, and it +> matches the literal string — so it fires on a `grep` pattern containing it too. + +**Skip gracefully on a missing tool.** Print a note and continue rather than failing. CI runners +differ, and a suite that fails for want of `jq` teaches nobody anything. + +**Test the documented limitations too.** `act-gitlab-ci`'s suite asserts that its checker *does not* +follow `include:` directives. If that starts passing, the skill's caveats have become wrong and +someone needs to update the prose. + +### Test-first + +Write the failing fixtures before the implementation, and confirm they fail for the right reason — +missing script, not a typo in the test. All three repository validators came with their suite; new ones +should too. + +## The pre-commit hook + +Opt in once per clone: + +```sh +git config core.hooksPath .githooks +``` + +It runs the full gate, not a subset — the gate is cheap here, with no build step, so there is no +reason to run less locally than CI runs. + +It adds one thing CI cannot usefully do after the fact: a secret scan of the working tree, using +trufflehog and trivy. Both skip with a printed notice when not installed. + +> [!IMPORTANT] +> That graceful skip is why the hook is a convenience rather than a control. If neither scanner is +> installed, nothing scans. You are the control. + +Bypass deliberately with `git commit --no-verify`, and say why. + +## CI + +`.github/workflows/ci.yml` runs on every branch push and every pull request: + +- `fetch-depth: 0`, because the validators read tracked files via `git ls-files` and the suites create + throwaway git repositories +- Bun via `oven-sh/setup-bun@v2` +- `sh scripts/verify-all.sh` +- An advisory `claude plugin validate .` step, `continue-on-error: true`, which skips when the CLI is + absent from the runner + +`.gitlab-ci.yml` mirrors it. Keep the two in step: a check present in only one will be discovered by +whoever pushes to the other. + +## Known gaps in the gate itself + +Recorded rather than papered over. + +**No per-plugin `claude plugin validate`.** The highest-value addition available. It would need to +skip gracefully when the CLI is absent, matching the existing advisory step. Until it exists, the +frontmatter parse failure described above reaches `main` undetected. + +**`check-size.ts` cites a path that does not exist here.** Its budget comment refers to +`openspec/changes/add-repo-furniture/design.md` and "the OpenSpec planning root living in this +repository". There is no `openspec/` directory in `actdata-plugins`; the comment was carried over +from `patterson-corp` during the adaptation. The 2 MiB figure and the reasoning are unaffected, but +the citation is stale. + +**The emoji rule has no mechanical enforcement**, by design. See +[`CONTRIBUTING.md`](../CONTRIBUTING.md#the-emoji-exemption-stated-precisely). + +**`[TBD: no review cadence is defined for the gate itself.]`** diff --git a/package.json b/package.json index 7363a08..aa65d49 100644 --- a/package.json +++ b/package.json @@ -2,7 +2,7 @@ "name": "actdata-plugins", "private": true, "type": "module", - "description": "ACT Data's Claude Code plugin marketplace. Not a library -- see README.md.", + "description": "ACT Data's plugin marketplace for Claude Code, ChatGPT, Codex, and GitHub Copilot.", "scripts": { "verify": "sh scripts/verify-all.sh", "test": "sh scripts/tests/run-tests.sh", diff --git a/plugins/act-gitlab-ci/.claude-plugin/plugin.json b/plugins/act-gitlab-ci/.claude-plugin/plugin.json index 7085b6c..a75f73f 100644 --- a/plugins/act-gitlab-ci/.claude-plugin/plugin.json +++ b/plugins/act-gitlab-ci/.claude-plugin/plugin.json @@ -1,7 +1,7 @@ { "$schema": "https://anthropic.com/claude-code/plugin.schema.json", "name": "act-gitlab-ci", - "version": "0.1.0", + "version": "0.2.0", "description": "GitLab CI/CD and GitLab tooling for Claude Code. Covers running Claude Code as a CI job across the Claude API, Amazon Bedrock and Vertex providers, the GitLab MCP server, the glab CLI, and pipeline standards adapted for GitLab. Includes a zero-dependency pipeline validator.", "author": { "name": "Daniel Bodnar", diff --git a/plugins/act-gitlab-ci/.codex-plugin/plugin.json b/plugins/act-gitlab-ci/.codex-plugin/plugin.json new file mode 100644 index 0000000..90befb3 --- /dev/null +++ b/plugins/act-gitlab-ci/.codex-plugin/plugin.json @@ -0,0 +1,7 @@ +{ + "name": "act-gitlab-ci", "version": "0.2.0", "description": "GitLab CI/CD, MCP, authentication, troubleshooting, and pipeline review workflows for ACT Data.", + "author": { "name": "Daniel Bodnar", "email": "dbodnar@pattersonvet.com", "url": "https://github.com/patterson-agents" }, + "homepage": "https://github.com/patterson-agents/actdata-plugins", "repository": "https://github.com/patterson-agents/actdata-plugins", "license": "LicenseRef-ACT-Internal", + "keywords": ["gitlab", "gitlab-ci", "pipelines", "mcp", "oidc", "devops"], "skills": "./skills/", "mcpServers": "./.mcp.json", + "interface": { "displayName": "ACT GitLab CI/CD", "shortDescription": "Build, review, and troubleshoot GitLab pipelines", "longDescription": "Configure GitLab CI agent jobs, connect GitLab MCP, review pipeline controls, and troubleshoot authentication and execution failures.", "developerName": "ACT Data", "category": "Engineering", "capabilities": ["Read", "Write"], "websiteURL": "https://github.com/patterson-agents/actdata-plugins", "defaultPrompt": ["Review this GitLab pipeline against ACT standards.", "Help me connect the GitLab MCP server."] } +} diff --git a/plugins/act-gitlab-ci/README.md b/plugins/act-gitlab-ci/README.md index 52f7451..7ff4d35 100644 --- a/plugins/act-gitlab-ci/README.md +++ b/plugins/act-gitlab-ci/README.md @@ -9,7 +9,7 @@ GitLab CI/CD, the GitLab MCP server, the `glab` CLI, and pipeline standards. -![skills](https://img.shields.io/badge/skills-6-00A8E1?labelColor=003767) +![skills](https://img.shields.io/badge/skills-10-00A8E1?labelColor=003767) ![agents](https://img.shields.io/badge/agents-1-003767) ![commands](https://img.shields.io/badge/commands-3-147EC2) ![mcp](https://img.shields.io/badge/mcp-gitlab-00817D) @@ -51,7 +51,7 @@ Four related things: | Component | Count | What it is | |---|---|---| -| Skills | 6 | CI jobs, auth providers, MCP server, `glab`, troubleshooting, standards | +| Skills | 10 | CI jobs, auth providers, MCP server, `glab`, troubleshooting, standards, and portable command/agent adapters | | Agents | 1 | Pipeline security review | | Commands | 3 | Set up the job, review a pipeline, connect MCP | | MCP servers | 1 | GitLab, over HTTP | diff --git a/plugins/act-gitlab-ci/plugin.json b/plugins/act-gitlab-ci/plugin.json new file mode 100644 index 0000000..04da434 --- /dev/null +++ b/plugins/act-gitlab-ci/plugin.json @@ -0,0 +1,6 @@ +{ + "name": "act-gitlab-ci", "version": "0.2.0", "description": "Build, review, and troubleshoot GitLab CI/CD integrations.", + "author": { "name": "Daniel Bodnar", "email": "dbodnar@pattersonvet.com", "url": "https://github.com/patterson-agents" }, + "homepage": "https://github.com/patterson-agents/actdata-plugins", "repository": "https://github.com/patterson-agents/actdata-plugins", "license": "LicenseRef-ACT-Internal", + "keywords": ["gitlab", "gitlab-ci", "pipelines", "mcp", "oidc", "devops"], "skills": "skills/", "commands": "commands/", "mcpServers": ".mcp.json" +} diff --git a/plugins/act-gitlab-ci/skills/ci-auth-providers/SKILL.md b/plugins/act-gitlab-ci/skills/ci-auth-providers/SKILL.md index 62f596a..4a11386 100644 --- a/plugins/act-gitlab-ci/skills/ci-auth-providers/SKILL.md +++ b/plugins/act-gitlab-ci/skills/ci-auth-providers/SKILL.md @@ -1,7 +1,6 @@ --- name: ci-auth-providers description: This skill should be used when the user asks "which provider should we use for Claude in CI", "set up Bedrock for GitLab", "configure Workload Identity Federation", "how do I avoid storing an API key", or mentions AWS_ROLE_TO_ASSUME, assume-role-with-web-identity, GCP_WORKLOAD_IDENTITY_PROVIDER, CLAUDE_CODE_USE_BEDROCK, CLAUDE_CODE_USE_VERTEX, id_tokens, or GITLAB_OIDC_TOKEN. Covers the three provider options, their prerequisites and variables, and choosing between them. -version: 0.1.0 --- # CI authentication providers diff --git a/plugins/act-gitlab-ci/skills/ci-troubleshooting/SKILL.md b/plugins/act-gitlab-ci/skills/ci-troubleshooting/SKILL.md index 15bc4c0..91c8b62 100644 --- a/plugins/act-gitlab-ci/skills/ci-troubleshooting/SKILL.md +++ b/plugins/act-gitlab-ci/skills/ci-troubleshooting/SKILL.md @@ -1,7 +1,6 @@ --- name: ci-troubleshooting description: This skill should be used when a GitLab CI integration is not working -- "Claude isn't responding to @claude", "the job can't open an MR", "authentication errors in the pipeline", "the MCP server won't connect", "the job runs but nothing happens" -- or when diagnosing pipeline failures involving credentials, tokens, tool permissions or triggers. Covers the common failure modes and how to distinguish them. -version: 0.1.0 --- # CI troubleshooting diff --git a/plugins/act-gitlab-ci/skills/claude-code-ci-jobs/SKILL.md b/plugins/act-gitlab-ci/skills/claude-code-ci-jobs/SKILL.md index 1e1a4b8..782b482 100644 --- a/plugins/act-gitlab-ci/skills/claude-code-ci-jobs/SKILL.md +++ b/plugins/act-gitlab-ci/skills/claude-code-ci-jobs/SKILL.md @@ -1,7 +1,6 @@ --- name: claude-code-ci-jobs description: This skill should be used when the user asks to "run Claude in GitLab CI", "set up the Claude job", "add Claude to my pipeline", "make @claude work on merge requests", "trigger Claude from a comment", or mentions AI_FLOW_INPUT, AI_FLOW_CONTEXT, gitlab-mcp-server in a job, --permission-mode acceptEdits, --allowedTools, or the pipeline trigger API for AI jobs. Covers job definition, trigger rules, mention-driven workflows, CLI flags, cost controls and job-level limits. -version: 0.1.0 --- # Claude Code as a GitLab CI job diff --git a/plugins/act-gitlab-ci/skills/connect-gitlab-mcp/SKILL.md b/plugins/act-gitlab-ci/skills/connect-gitlab-mcp/SKILL.md new file mode 100644 index 0000000..706801b --- /dev/null +++ b/plugins/act-gitlab-ci/skills/connect-gitlab-mcp/SKILL.md @@ -0,0 +1,12 @@ +--- +name: connect-gitlab-mcp +description: "Connect an agent client to a GitLab HTTP MCP server after checking GitLab version, Duo, feature, and access prerequisites." +--- + +# Connect Gitlab Mcp + +Read and follow the canonical procedure in [../../commands/connect-gitlab-mcp.md](../../commands/connect-gitlab-mcp.md). + +Treat the user's current request as the procedure input. Ignore the source file's YAML frontmatter +and any Claude-only invocation syntax. Use equivalent tools available on the current host, preserve +all safety checks, and resolve bundled resources from this plugin rather than the user's project. diff --git a/plugins/act-gitlab-ci/skills/gitlab-mcp-server/SKILL.md b/plugins/act-gitlab-ci/skills/gitlab-mcp-server/SKILL.md index 5b14142..4bf79bf 100644 --- a/plugins/act-gitlab-ci/skills/gitlab-mcp-server/SKILL.md +++ b/plugins/act-gitlab-ci/skills/gitlab-mcp-server/SKILL.md @@ -1,7 +1,6 @@ --- name: gitlab-mcp-server description: This skill should be used when the user asks to "connect to the GitLab MCP server", "set up GitLab MCP", "which GitLab MCP tools are available", "what GitLab version do we need for MCP", or mentions /api/v4/mcp, mcp-remote, OAuth Dynamic Client Registration for GitLab, GitLab Duo settings for MCP, or specific tools like create_merge_request, get_pipeline, semantic_code_search. Covers enabling the server, connecting a client, the tool catalogue with version requirements, and the security considerations. For a server that will not connect, use ci-troubleshooting instead. -version: 0.1.0 --- # GitLab MCP server diff --git a/plugins/act-gitlab-ci/skills/glab/SKILL.md b/plugins/act-gitlab-ci/skills/glab/SKILL.md index d013ff8..e0a518f 100644 --- a/plugins/act-gitlab-ci/skills/glab/SKILL.md +++ b/plugins/act-gitlab-ci/skills/glab/SKILL.md @@ -1,7 +1,6 @@ --- name: glab description: This skill should be used before running any `glab` or GitLab API command from the shell, and when the user asks to "create a merge request", "comment on an issue", "reply in a review thread", "resolve a discussion", "check the pipeline status", "get the job log", "list my MRs", or mentions glab, `glab api`, discussion IDs, threaded replies, `--reply`, `mr note create`, or CI job traces. Covers issues, merge requests, notes and discussions, pipelines, and raw API calls, including the quoting and stdin rules that make non-interactive use safe. Prefer glab over raw API calls for command-line GitLab work. -version: 0.1.0 --- # GitLab CLI (glab) diff --git a/plugins/act-gitlab-ci/skills/pipeline-security-reviewer/SKILL.md b/plugins/act-gitlab-ci/skills/pipeline-security-reviewer/SKILL.md new file mode 100644 index 0000000..f6d4a37 --- /dev/null +++ b/plugins/act-gitlab-ci/skills/pipeline-security-reviewer/SKILL.md @@ -0,0 +1,12 @@ +--- +name: pipeline-security-reviewer +description: "Apply the ACT Data GitLab pipeline security review procedure. Use for credentials, scan coverage, permissions, and AI job controls." +--- + +# Pipeline Security Reviewer + +Read and follow the canonical procedure in [../../agents/pipeline-security-reviewer.md](../../agents/pipeline-security-reviewer.md). + +Treat the user's current request as the procedure input. Ignore the source file's YAML frontmatter +and any Claude-only invocation syntax. Use equivalent tools available on the current host, preserve +all safety checks, and resolve bundled resources from this plugin rather than the user's project. diff --git a/plugins/act-gitlab-ci/skills/pipeline-standards/SKILL.md b/plugins/act-gitlab-ci/skills/pipeline-standards/SKILL.md index 99714ea..db35bb0 100644 --- a/plugins/act-gitlab-ci/skills/pipeline-standards/SKILL.md +++ b/plugins/act-gitlab-ci/skills/pipeline-standards/SKILL.md @@ -1,7 +1,6 @@ --- name: pipeline-standards description: This skill should be used when writing or reviewing a .gitlab-ci.yml, a GitLab merge request approval rule, a GitLab CI credential configuration or a GitLab deployment job, and when asked "does this .gitlab-ci.yml meet our standards", "how many approvers do we need on a GitLab MR", "which scans are required in our GitLab pipeline", "can I use a static credential in GitLab CI", or "how do we promote a build to production in GitLab". Applies pipeline standards translated to GitLab, with every clause marked as derived rather than authoritative. For the authoritative Azure DevOps and GitHub standard, use patterson-engineering:cicd-pipeline-standards instead. -version: 0.1.0 --- # Pipeline standards (GitLab) diff --git a/plugins/act-gitlab-ci/skills/review-pipeline/SKILL.md b/plugins/act-gitlab-ci/skills/review-pipeline/SKILL.md new file mode 100644 index 0000000..edefe19 --- /dev/null +++ b/plugins/act-gitlab-ci/skills/review-pipeline/SKILL.md @@ -0,0 +1,12 @@ +--- +name: review-pipeline +description: "Review a GitLab pipeline against ACT-derived standards using the checker plus manual analysis of its blind spots." +--- + +# Review Pipeline + +Read and follow the canonical procedure in [../../commands/review-pipeline.md](../../commands/review-pipeline.md). + +Treat the user's current request as the procedure input. Ignore the source file's YAML frontmatter +and any Claude-only invocation syntax. Use equivalent tools available on the current host, preserve +all safety checks, and resolve bundled resources from this plugin rather than the user's project. diff --git a/plugins/act-gitlab-ci/skills/setup-claude-job/SKILL.md b/plugins/act-gitlab-ci/skills/setup-claude-job/SKILL.md new file mode 100644 index 0000000..0f9f27c --- /dev/null +++ b/plugins/act-gitlab-ci/skills/setup-claude-job/SKILL.md @@ -0,0 +1,12 @@ +--- +name: setup-claude-job +description: "Add or review a Claude Code job in GitLab CI with provider authentication, trigger rules, permissions, and cost bounds." +--- + +# Setup Claude Job + +Read and follow the canonical procedure in [../../commands/setup-claude-job.md](../../commands/setup-claude-job.md). + +Treat the user's current request as the procedure input. Ignore the source file's YAML frontmatter +and any Claude-only invocation syntax. Use equivalent tools available on the current host, preserve +all safety checks, and resolve bundled resources from this plugin rather than the user's project. diff --git a/plugins/act-platform-engineering/.claude-plugin/plugin.json b/plugins/act-platform-engineering/.claude-plugin/plugin.json index b590e95..1cfbb17 100644 --- a/plugins/act-platform-engineering/.claude-plugin/plugin.json +++ b/plugins/act-platform-engineering/.claude-plugin/plugin.json @@ -1,7 +1,7 @@ { "$schema": "https://anthropic.com/claude-code/plugin.schema.json", "name": "act-platform-engineering", - "version": "0.1.0", + "version": "0.2.0", "description": "Assessment and operations toolkit for PostgreSQL, ZFS, Linux hosts and Proxmox VE. Ships role-based reasoning agents, one-shot diagnostic commands with green/red criteria, and incident-response practice. Reads its host inventory from a site-local settings file, so it carries no environment identifiers of its own.", "author": { "name": "Daniel Bodnar", diff --git a/plugins/act-platform-engineering/.codex-plugin/plugin.json b/plugins/act-platform-engineering/.codex-plugin/plugin.json new file mode 100644 index 0000000..bd90f01 --- /dev/null +++ b/plugins/act-platform-engineering/.codex-plugin/plugin.json @@ -0,0 +1,7 @@ +{ + "name": "act-platform-engineering", "version": "0.2.0", "description": "Assessment and operations workflows for PostgreSQL, ZFS, Linux hosts, Proxmox VE, observability, and incidents.", + "author": { "name": "Daniel Bodnar", "email": "dbodnar@pattersonvet.com", "url": "https://github.com/patterson-agents" }, + "homepage": "https://github.com/patterson-agents/actdata-plugins", "repository": "https://github.com/patterson-agents/actdata-plugins", "license": "LicenseRef-ACT-Internal", + "keywords": ["postgresql", "zfs", "linux", "proxmox", "sre", "observability", "incident-response"], "skills": "./skills/", + "interface": { "displayName": "ACT Platform Engineering", "shortDescription": "Assess and operate ACT Data infrastructure", "longDescription": "Run evidence-backed assessments and incident workflows for PostgreSQL, ZFS, Linux, Proxmox VE, and observability systems.", "developerName": "ACT Data", "category": "Operations", "capabilities": ["Read", "Write"], "websiteURL": "https://github.com/patterson-agents/actdata-plugins", "defaultPrompt": ["Assess the health of this PostgreSQL environment.", "Check observability coverage across the fleet."] } +} diff --git a/plugins/act-platform-engineering/README.md b/plugins/act-platform-engineering/README.md index 15f131b..6bcf7d6 100644 --- a/plugins/act-platform-engineering/README.md +++ b/plugins/act-platform-engineering/README.md @@ -9,7 +9,7 @@ Assessment and operations for PostgreSQL, ZFS, Linux hosts and Proxmox VE. -![skills](https://img.shields.io/badge/skills-7-00A8E1?labelColor=003767) +![skills](https://img.shields.io/badge/skills-23-00A8E1?labelColor=003767) ![agents](https://img.shields.io/badge/agents-7-003767) ![commands](https://img.shields.io/badge/commands-9-147EC2) ![config](https://img.shields.io/badge/config-driven-00817D) @@ -49,7 +49,7 @@ it. | Component | Count | What it is | |---|---|---| -| Skills | 7 | Domain knowledge: diagnostics, thresholds, and what the output means | +| Skills | 23 | Domain knowledge plus portable command and role adapters | | Agents | 7 | Role-based reasoning for open-ended investigation | | Commands | 9 | One-shot assessments producing structured findings | | Scripts | 1 | A read-only ten-section triage pass over a database host | @@ -108,8 +108,9 @@ claude plugin install act-platform-engineering@actdata-plugins ## Configuration -Create `.claude/act-platform-engineering.local.md` in your project. It is gitignored by this -repository's `.gitignore` (`.claude/*.local.md`), and it must stay that way -- it holds exactly the +Create `.agents/act-platform-engineering.local.md` in your project. Existing Claude installations +may keep `.claude/act-platform-engineering.local.md` as a fallback. Both paths are gitignored, and +they must stay that way -- the file holds exactly the identifiers the plugin is designed not to carry. ```markdown diff --git a/plugins/act-platform-engineering/plugin.json b/plugins/act-platform-engineering/plugin.json new file mode 100644 index 0000000..5123e90 --- /dev/null +++ b/plugins/act-platform-engineering/plugin.json @@ -0,0 +1,6 @@ +{ + "name": "act-platform-engineering", "version": "0.2.0", "description": "Assess and operate PostgreSQL, ZFS, Linux, Proxmox VE, and observability systems.", + "author": { "name": "Daniel Bodnar", "email": "dbodnar@pattersonvet.com", "url": "https://github.com/patterson-agents" }, + "homepage": "https://github.com/patterson-agents/actdata-plugins", "repository": "https://github.com/patterson-agents/actdata-plugins", "license": "LicenseRef-ACT-Internal", + "keywords": ["postgresql", "zfs", "linux", "proxmox", "sre", "observability", "incident-response"], "skills": "skills/", "commands": "commands/" +} diff --git a/plugins/act-platform-engineering/skills/assess-backups/SKILL.md b/plugins/act-platform-engineering/skills/assess-backups/SKILL.md new file mode 100644 index 0000000..8d615f3 --- /dev/null +++ b/plugins/act-platform-engineering/skills/assess-backups/SKILL.md @@ -0,0 +1,14 @@ +--- +name: assess-backups +description: "Assess PostgreSQL backup and recovery readiness, including WAL archiving, base backups, destinations, retention, and restore testing." +--- + +# Assess Backups + +Read and follow the canonical procedure in [../../commands/assess-backups.md](../../commands/assess-backups.md). + +Treat the user's current request as the procedure input. Ignore the source file's YAML frontmatter +and any Claude-only invocation syntax. Use equivalent tools available on the current host, preserve +all safety checks, and resolve bundled resources from this plugin rather than the user's project. +Read site configuration from `.agents/act-platform-engineering.local.md`; fall back to the legacy +`.claude/act-platform-engineering.local.md` only when the portable file is absent. diff --git a/plugins/act-platform-engineering/skills/assess-disks/SKILL.md b/plugins/act-platform-engineering/skills/assess-disks/SKILL.md new file mode 100644 index 0000000..28b4e8f --- /dev/null +++ b/plugins/act-platform-engineering/skills/assess-disks/SKILL.md @@ -0,0 +1,14 @@ +--- +name: assess-disks +description: "Assess SMART and NVMe drive health, wear, spare capacity, temperature, media errors, and power-loss protection." +--- + +# Assess Disks + +Read and follow the canonical procedure in [../../commands/assess-disks.md](../../commands/assess-disks.md). + +Treat the user's current request as the procedure input. Ignore the source file's YAML frontmatter +and any Claude-only invocation syntax. Use equivalent tools available on the current host, preserve +all safety checks, and resolve bundled resources from this plugin rather than the user's project. +Read site configuration from `.agents/act-platform-engineering.local.md`; fall back to the legacy +`.claude/act-platform-engineering.local.md` only when the portable file is absent. diff --git a/plugins/act-platform-engineering/skills/assess-kernel/SKILL.md b/plugins/act-platform-engineering/skills/assess-kernel/SKILL.md new file mode 100644 index 0000000..d4e5b77 --- /dev/null +++ b/plugins/act-platform-engineering/skills/assess-kernel/SKILL.md @@ -0,0 +1,14 @@ +--- +name: assess-kernel +description: "Assess Linux kernel, sysctl, transparent huge pages, I/O scheduler, NUMA, and process limits on a database host." +--- + +# Assess Kernel + +Read and follow the canonical procedure in [../../commands/assess-kernel.md](../../commands/assess-kernel.md). + +Treat the user's current request as the procedure input. Ignore the source file's YAML frontmatter +and any Claude-only invocation syntax. Use equivalent tools available on the current host, preserve +all safety checks, and resolve bundled resources from this plugin rather than the user's project. +Read site configuration from `.agents/act-platform-engineering.local.md`; fall back to the legacy +`.claude/act-platform-engineering.local.md` only when the portable file is absent. diff --git a/plugins/act-platform-engineering/skills/assess-postgres/SKILL.md b/plugins/act-platform-engineering/skills/assess-postgres/SKILL.md new file mode 100644 index 0000000..8de842f --- /dev/null +++ b/plugins/act-platform-engineering/skills/assess-postgres/SKILL.md @@ -0,0 +1,14 @@ +--- +name: assess-postgres +description: "Assess PostgreSQL performance, configuration, connection health, queries, bloat, indexes, and locking." +--- + +# Assess Postgres + +Read and follow the canonical procedure in [../../commands/assess-postgres.md](../../commands/assess-postgres.md). + +Treat the user's current request as the procedure input. Ignore the source file's YAML frontmatter +and any Claude-only invocation syntax. Use equivalent tools available on the current host, preserve +all safety checks, and resolve bundled resources from this plugin rather than the user's project. +Read site configuration from `.agents/act-platform-engineering.local.md`; fall back to the legacy +`.claude/act-platform-engineering.local.md` only when the portable file is absent. diff --git a/plugins/act-platform-engineering/skills/assess-pve/SKILL.md b/plugins/act-platform-engineering/skills/assess-pve/SKILL.md new file mode 100644 index 0000000..be88aaa --- /dev/null +++ b/plugins/act-platform-engineering/skills/assess-pve/SKILL.md @@ -0,0 +1,14 @@ +--- +name: assess-pve +description: "Assess Proxmox VE quorum, nodes, storage, virtual machine inventory, backups, and high availability." +--- + +# Assess Pve + +Read and follow the canonical procedure in [../../commands/assess-pve.md](../../commands/assess-pve.md). + +Treat the user's current request as the procedure input. Ignore the source file's YAML frontmatter +and any Claude-only invocation syntax. Use equivalent tools available on the current host, preserve +all safety checks, and resolve bundled resources from this plugin rather than the user's project. +Read site configuration from `.agents/act-platform-engineering.local.md`; fall back to the legacy +`.claude/act-platform-engineering.local.md` only when the portable file is absent. diff --git a/plugins/act-platform-engineering/skills/assess-replication/SKILL.md b/plugins/act-platform-engineering/skills/assess-replication/SKILL.md new file mode 100644 index 0000000..e80c366 --- /dev/null +++ b/plugins/act-platform-engineering/skills/assess-replication/SKILL.md @@ -0,0 +1,14 @@ +--- +name: assess-replication +description: "Assess PostgreSQL streaming replication, lag, slots, replica completeness, and failover readiness." +--- + +# Assess Replication + +Read and follow the canonical procedure in [../../commands/assess-replication.md](../../commands/assess-replication.md). + +Treat the user's current request as the procedure input. Ignore the source file's YAML frontmatter +and any Claude-only invocation syntax. Use equivalent tools available on the current host, preserve +all safety checks, and resolve bundled resources from this plugin rather than the user's project. +Read site configuration from `.agents/act-platform-engineering.local.md`; fall back to the legacy +`.claude/act-platform-engineering.local.md` only when the portable file is absent. diff --git a/plugins/act-platform-engineering/skills/assess-zfs/SKILL.md b/plugins/act-platform-engineering/skills/assess-zfs/SKILL.md new file mode 100644 index 0000000..3bab21d --- /dev/null +++ b/plugins/act-platform-engineering/skills/assess-zfs/SKILL.md @@ -0,0 +1,14 @@ +--- +name: assess-zfs +description: "Assess ZFS pool health, capacity, topology, dataset tuning, ARC behavior, and snapshots." +--- + +# Assess Zfs + +Read and follow the canonical procedure in [../../commands/assess-zfs.md](../../commands/assess-zfs.md). + +Treat the user's current request as the procedure input. Ignore the source file's YAML frontmatter +and any Claude-only invocation syntax. Use equivalent tools available on the current host, preserve +all safety checks, and resolve bundled resources from this plugin rather than the user's project. +Read site configuration from `.agents/act-platform-engineering.local.md`; fall back to the legacy +`.claude/act-platform-engineering.local.md` only when the portable file is absent. diff --git a/plugins/act-platform-engineering/skills/dba/SKILL.md b/plugins/act-platform-engineering/skills/dba/SKILL.md new file mode 100644 index 0000000..0b2d8f2 --- /dev/null +++ b/plugins/act-platform-engineering/skills/dba/SKILL.md @@ -0,0 +1,14 @@ +--- +name: dba +description: "Apply the ACT Data database administrator diagnostic and production-safety procedure. Use for deep PostgreSQL operational analysis." +--- + +# Dba + +Read and follow the canonical procedure in [../../agents/dba.md](../../agents/dba.md). + +Treat the user's current request as the procedure input. Ignore the source file's YAML frontmatter +and any Claude-only invocation syntax. Use equivalent tools available on the current host, preserve +all safety checks, and resolve bundled resources from this plugin rather than the user's project. +Read site configuration from `.agents/act-platform-engineering.local.md`; fall back to the legacy +`.claude/act-platform-engineering.local.md` only when the portable file is absent. diff --git a/plugins/act-platform-engineering/skills/incident-responder/SKILL.md b/plugins/act-platform-engineering/skills/incident-responder/SKILL.md new file mode 100644 index 0000000..80e1f76 --- /dev/null +++ b/plugins/act-platform-engineering/skills/incident-responder/SKILL.md @@ -0,0 +1,14 @@ +--- +name: incident-responder +description: "Run the ACT Data incident-response procedure. Use during outages, degraded production, recovery, and post-incident follow-up." +--- + +# Incident Responder + +Read and follow the canonical procedure in [../../agents/incident-responder.md](../../agents/incident-responder.md). + +Treat the user's current request as the procedure input. Ignore the source file's YAML frontmatter +and any Claude-only invocation syntax. Use equivalent tools available on the current host, preserve +all safety checks, and resolve bundled resources from this plugin rather than the user's project. +Read site configuration from `.agents/act-platform-engineering.local.md`; fall back to the legacy +`.claude/act-platform-engineering.local.md` only when the portable file is absent. diff --git a/plugins/act-platform-engineering/skills/incident-response/SKILL.md b/plugins/act-platform-engineering/skills/incident-response/SKILL.md index 4caf652..d48ab0c 100644 --- a/plugins/act-platform-engineering/skills/incident-response/SKILL.md +++ b/plugins/act-platform-engineering/skills/incident-response/SKILL.md @@ -1,7 +1,6 @@ --- name: incident-response description: This skill should be used during or after an outage -- when the user says "the database is down", "we have an incident", "production is broken", "help me run this incident", "write a postmortem", "write a runbook", "document this procedure", or mentions blameless postmortem, incident timeline, severity, root cause, action items, or failover procedure documentation. Covers running an incident, writing the postmortem afterwards, and turning procedures into runbooks. -version: 0.1.0 --- # Incident Response diff --git a/plugins/act-platform-engineering/skills/infrastructure-inventory/SKILL.md b/plugins/act-platform-engineering/skills/infrastructure-inventory/SKILL.md index d06d00c..dce9e2f 100644 --- a/plugins/act-platform-engineering/skills/infrastructure-inventory/SKILL.md +++ b/plugins/act-platform-engineering/skills/infrastructure-inventory/SKILL.md @@ -1,7 +1,6 @@ --- name: infrastructure-inventory description: This skill should be used when any platform-engineering task needs to know which hosts, databases, or services exist -- when the user says "assess the database", "check the primary", "which hosts do we have", "run this on the replica", "what is our topology", or names a role rather than a machine. It defines where the site inventory lives, how to read it, and the rule that a hostname or address is never invented or assumed. Load it before any command that targets a host. -version: 0.1.0 --- # Infrastructure Inventory @@ -24,7 +23,8 @@ machine. ## Where the inventory lives -`.claude/act-platform-engineering.local.md`, relative to the project root. It is gitignored: the +`.agents/act-platform-engineering.local.md`, relative to the project root. For compatibility with +existing Claude installations, fall back to `.claude/act-platform-engineering.local.md`. Both are gitignored: the repository's `.gitignore` carries `.claude/*.local.md` precisely so a site inventory never lands in version control. diff --git a/plugins/act-platform-engineering/skills/linux-host-tuning/SKILL.md b/plugins/act-platform-engineering/skills/linux-host-tuning/SKILL.md index e659d5c..162a4e1 100644 --- a/plugins/act-platform-engineering/skills/linux-host-tuning/SKILL.md +++ b/plugins/act-platform-engineering/skills/linux-host-tuning/SKILL.md @@ -1,7 +1,6 @@ --- name: linux-host-tuning description: This skill should be used when the user asks to "check the disks", "check SMART", "are the drives failing", "check drive wear", "assess the kernel", "check sysctl", "is swappiness set", "check transparent huge pages", "check the I/O scheduler", "check ulimits", or mentions nvme smart-log, smartctl, percentage_used, PLP, vm.swappiness, dirty_ratio, overcommit, THP, NUMA, or file descriptor limits on a database or storage host. Covers drive health assessment and kernel and sysctl tuning. -version: 0.1.0 --- # Linux Host Tuning diff --git a/plugins/act-platform-engineering/skills/observability-engineer/SKILL.md b/plugins/act-platform-engineering/skills/observability-engineer/SKILL.md new file mode 100644 index 0000000..bd3b565 --- /dev/null +++ b/plugins/act-platform-engineering/skills/observability-engineer/SKILL.md @@ -0,0 +1,14 @@ +--- +name: observability-engineer +description: "Apply the ACT Data observability engineering procedure. Use for telemetry coverage, dashboards, alerts, and monitoring design." +--- + +# Observability Engineer + +Read and follow the canonical procedure in [../../agents/observability-engineer.md](../../agents/observability-engineer.md). + +Treat the user's current request as the procedure input. Ignore the source file's YAML frontmatter +and any Claude-only invocation syntax. Use equivalent tools available on the current host, preserve +all safety checks, and resolve bundled resources from this plugin rather than the user's project. +Read site configuration from `.agents/act-platform-engineering.local.md`; fall back to the legacy +`.claude/act-platform-engineering.local.md` only when the portable file is absent. diff --git a/plugins/act-platform-engineering/skills/observability-status/SKILL.md b/plugins/act-platform-engineering/skills/observability-status/SKILL.md new file mode 100644 index 0000000..56f21fc --- /dev/null +++ b/plugins/act-platform-engineering/skills/observability-status/SKILL.md @@ -0,0 +1,14 @@ +--- +name: observability-status +description: "Report observability coverage across collectors, dashboards, metrics, streaming, alerts, and centralized logs." +--- + +# Observability Status + +Read and follow the canonical procedure in [../../commands/observability-status.md](../../commands/observability-status.md). + +Treat the user's current request as the procedure input. Ignore the source file's YAML frontmatter +and any Claude-only invocation syntax. Use equivalent tools available on the current host, preserve +all safety checks, and resolve bundled resources from this plugin rather than the user's project. +Read site configuration from `.agents/act-platform-engineering.local.md`; fall back to the legacy +`.claude/act-platform-engineering.local.md` only when the portable file is absent. diff --git a/plugins/act-platform-engineering/skills/observability/SKILL.md b/plugins/act-platform-engineering/skills/observability/SKILL.md index 7a4d823..701b767 100644 --- a/plugins/act-platform-engineering/skills/observability/SKILL.md +++ b/plugins/act-platform-engineering/skills/observability/SKILL.md @@ -1,7 +1,6 @@ --- name: observability description: This skill should be used when the user asks "where are we on the observability rollout", "is Netdata up on all servers", "check Grafana", "observability status", "what are we not monitoring", "do we have centralized logs", "what should we alert on", or mentions Netdata, Grafana, Zabbix, Prometheus, dashboards, metric coverage, log aggregation, or monitoring blind spots. Covers assessing observability coverage across a fleet and deciding what is worth monitoring. -version: 0.1.0 --- # Observability diff --git a/plugins/act-platform-engineering/skills/platform-engineer/SKILL.md b/plugins/act-platform-engineering/skills/platform-engineer/SKILL.md new file mode 100644 index 0000000..38e97be --- /dev/null +++ b/plugins/act-platform-engineering/skills/platform-engineer/SKILL.md @@ -0,0 +1,14 @@ +--- +name: platform-engineer +description: "Apply the ACT Data platform engineering procedure. Use for platform design, automation, composition, and operational documentation." +--- + +# Platform Engineer + +Read and follow the canonical procedure in [../../agents/platform-engineer.md](../../agents/platform-engineer.md). + +Treat the user's current request as the procedure input. Ignore the source file's YAML frontmatter +and any Claude-only invocation syntax. Use equivalent tools available on the current host, preserve +all safety checks, and resolve bundled resources from this plugin rather than the user's project. +Read site configuration from `.agents/act-platform-engineering.local.md`; fall back to the legacy +`.claude/act-platform-engineering.local.md` only when the portable file is absent. diff --git a/plugins/act-platform-engineering/skills/postgres-operations/SKILL.md b/plugins/act-platform-engineering/skills/postgres-operations/SKILL.md index 5ce9c36..494e8fb 100644 --- a/plugins/act-platform-engineering/skills/postgres-operations/SKILL.md +++ b/plugins/act-platform-engineering/skills/postgres-operations/SKILL.md @@ -1,7 +1,6 @@ --- name: postgres-operations description: This skill should be used when the user asks to "assess Postgres", "check the database", "why is the database slow", "check replication", "is replication lagging", "are backups working", "check WAL archiving", "find slow queries", "is autovacuum keeping up", "check for bloat", "review Postgres configuration", or mentions pg_stat_statements, replication slots, WAL shipping, failover readiness, table bloat, or connection exhaustion. Provides diagnostic commands with green/red criteria for PostgreSQL performance, backup and recovery, and replication and high availability. -version: 0.1.0 --- # PostgreSQL Operations @@ -12,7 +11,8 @@ read-only unless explicitly marked otherwise. ## Before running anything Resolve the target host and database from the site inventory. See the `infrastructure-inventory` -skill: arguments first, then `.claude/act-platform-engineering.local.md`, then ask. **Never assume a +skill: arguments first, then `.agents/act-platform-engineering.local.md`, then the legacy +`.claude/act-platform-engineering.local.md`, then ask. **Never assume a hostname or database name.** Commands below use `$DB` for the database. Set it once from the resolved inventory value: diff --git a/plugins/act-platform-engineering/skills/proxmox-virtualization/SKILL.md b/plugins/act-platform-engineering/skills/proxmox-virtualization/SKILL.md index 16f2532..e357182 100644 --- a/plugins/act-platform-engineering/skills/proxmox-virtualization/SKILL.md +++ b/plugins/act-platform-engineering/skills/proxmox-virtualization/SKILL.md @@ -1,7 +1,6 @@ --- name: proxmox-virtualization description: This skill should be used when the user asks to "check PVE", "Proxmox health", "how are the hypervisors", "check the VM fleet", "is the cluster quorate", "check VM backups", "are there orphaned VMs", or mentions pvecm, pvesh, pvesm, vzdump, Proxmox Backup Server, ha-manager, cluster quorum, or VM sprawl. Covers Proxmox VE cluster health, node and storage checks, VM inventory hygiene, backup configuration, and high availability. -version: 0.1.0 --- # Proxmox VE diff --git a/plugins/act-platform-engineering/skills/security-engineer/SKILL.md b/plugins/act-platform-engineering/skills/security-engineer/SKILL.md new file mode 100644 index 0000000..f48d644 --- /dev/null +++ b/plugins/act-platform-engineering/skills/security-engineer/SKILL.md @@ -0,0 +1,14 @@ +--- +name: security-engineer +description: "Apply the ACT Data infrastructure security procedure. Use for trust boundaries, secrets, patching, hardening, and security review." +--- + +# Security Engineer + +Read and follow the canonical procedure in [../../agents/security-engineer.md](../../agents/security-engineer.md). + +Treat the user's current request as the procedure input. Ignore the source file's YAML frontmatter +and any Claude-only invocation syntax. Use equivalent tools available on the current host, preserve +all safety checks, and resolve bundled resources from this plugin rather than the user's project. +Read site configuration from `.agents/act-platform-engineering.local.md`; fall back to the legacy +`.claude/act-platform-engineering.local.md` only when the portable file is absent. diff --git a/plugins/act-platform-engineering/skills/sre/SKILL.md b/plugins/act-platform-engineering/skills/sre/SKILL.md new file mode 100644 index 0000000..9d63ecd --- /dev/null +++ b/plugins/act-platform-engineering/skills/sre/SKILL.md @@ -0,0 +1,14 @@ +--- +name: sre +description: "Apply the ACT Data site reliability engineering procedure. Use for reliability, failure-mode planning, observability, and operational risk." +--- + +# Sre + +Read and follow the canonical procedure in [../../agents/sre.md](../../agents/sre.md). + +Treat the user's current request as the procedure input. Ignore the source file's YAML frontmatter +and any Claude-only invocation syntax. Use equivalent tools available on the current host, preserve +all safety checks, and resolve bundled resources from this plugin rather than the user's project. +Read site configuration from `.agents/act-platform-engineering.local.md`; fall back to the legacy +`.claude/act-platform-engineering.local.md` only when the portable file is absent. diff --git a/plugins/act-platform-engineering/skills/sysadmin/SKILL.md b/plugins/act-platform-engineering/skills/sysadmin/SKILL.md new file mode 100644 index 0000000..ca98772 --- /dev/null +++ b/plugins/act-platform-engineering/skills/sysadmin/SKILL.md @@ -0,0 +1,14 @@ +--- +name: sysadmin +description: "Apply the ACT Data systems administration procedure. Use for host, filesystem, process, network, and operating-system diagnostics." +--- + +# Sysadmin + +Read and follow the canonical procedure in [../../agents/sysadmin.md](../../agents/sysadmin.md). + +Treat the user's current request as the procedure input. Ignore the source file's YAML frontmatter +and any Claude-only invocation syntax. Use equivalent tools available on the current host, preserve +all safety checks, and resolve bundled resources from this plugin rather than the user's project. +Read site configuration from `.agents/act-platform-engineering.local.md`; fall back to the legacy +`.claude/act-platform-engineering.local.md` only when the portable file is absent. diff --git a/plugins/act-platform-engineering/skills/triage-pg-host/SKILL.md b/plugins/act-platform-engineering/skills/triage-pg-host/SKILL.md new file mode 100644 index 0000000..7c167e5 --- /dev/null +++ b/plugins/act-platform-engineering/skills/triage-pg-host/SKILL.md @@ -0,0 +1,14 @@ +--- +name: triage-pg-host +description: "Run a broad read-only triage of a PostgreSQL host across system, storage, drives, database, replication, and kernel layers." +--- + +# Triage Pg Host + +Read and follow the canonical procedure in [../../commands/triage-pg-host.md](../../commands/triage-pg-host.md). + +Treat the user's current request as the procedure input. Ignore the source file's YAML frontmatter +and any Claude-only invocation syntax. Use equivalent tools available on the current host, preserve +all safety checks, and resolve bundled resources from this plugin rather than the user's project. +Read site configuration from `.agents/act-platform-engineering.local.md`; fall back to the legacy +`.claude/act-platform-engineering.local.md` only when the portable file is absent. diff --git a/plugins/act-platform-engineering/skills/zfs-storage/SKILL.md b/plugins/act-platform-engineering/skills/zfs-storage/SKILL.md index d313560..d1f0aca 100644 --- a/plugins/act-platform-engineering/skills/zfs-storage/SKILL.md +++ b/plugins/act-platform-engineering/skills/zfs-storage/SKILL.md @@ -1,7 +1,6 @@ --- name: zfs-storage description: This skill should be used when the user asks to "check ZFS", "assess the pool", "is the pool healthy", "check zpool status", "why is ZFS slow", "tune ZFS for Postgres", "check recordsize", "are we taking snapshots", "check ARC hit ratio", "the pool is filling up", or mentions zpool, zfs get, scrub, vdev, raidz, ARC, L2ARC, sanoid, zfs-auto-snapshot, or write amplification on a database host. Covers pool health and capacity, dataset tuning for PostgreSQL, and snapshot policy. -version: 0.1.0 --- # ZFS Storage diff --git a/plugins/act-plugin-dev/.claude-plugin/plugin.json b/plugins/act-plugin-dev/.claude-plugin/plugin.json index f7dcf2a..d561aca 100644 --- a/plugins/act-plugin-dev/.claude-plugin/plugin.json +++ b/plugins/act-plugin-dev/.claude-plugin/plugin.json @@ -1,7 +1,7 @@ { "$schema": "https://anthropic.com/claude-code/plugin.schema.json", "name": "act-plugin-dev", - "version": "0.1.0", + "version": "0.2.0", "description": "ACT Data's plugin development toolkit. Seven skills covering plugin structure, skills, commands, agents, hooks, MCP integration, and plugin settings, plus three review agents and a guided end-to-end creation workflow. Adapted from Claude Code's plugin-dev for the actdata-plugins marketplace: Bun, kebab-case naming, and marketplace registration built into the workflow.", "author": { "name": "Daniel Bodnar", diff --git a/plugins/act-plugin-dev/.codex-plugin/plugin.json b/plugins/act-plugin-dev/.codex-plugin/plugin.json new file mode 100644 index 0000000..6eeb0b0 --- /dev/null +++ b/plugins/act-plugin-dev/.codex-plugin/plugin.json @@ -0,0 +1,7 @@ +{ + "name": "act-plugin-dev", "version": "0.2.0", "description": "ACT Data's toolkit for creating and reviewing portable Claude, ChatGPT, Codex, and GitHub Copilot plugins.", + "author": { "name": "Daniel Bodnar", "email": "dbodnar@pattersonvet.com", "url": "https://github.com/patterson-agents" }, + "homepage": "https://github.com/patterson-agents/actdata-plugins", "repository": "https://github.com/patterson-agents/actdata-plugins", "license": "LicenseRef-ACT-Internal", + "keywords": ["plugin-development", "skills", "commands", "agents", "hooks", "mcp", "marketplace"], "skills": "./skills/", + "interface": { "displayName": "ACT Plugin Development Toolkit", "shortDescription": "Build and review portable agent plugins", "longDescription": "Create and validate ACT Data plugins for Claude Code, ChatGPT, Codex, and GitHub Copilot.", "developerName": "ACT Data", "category": "Development", "capabilities": ["Read", "Write"], "websiteURL": "https://github.com/patterson-agents/actdata-plugins", "defaultPrompt": ["Create a portable plugin for this marketplace.", "Review this plugin for compatibility."] } +} diff --git a/plugins/act-plugin-dev/README.md b/plugins/act-plugin-dev/README.md index 0eb95df..268bd73 100644 --- a/plugins/act-plugin-dev/README.md +++ b/plugins/act-plugin-dev/README.md @@ -10,7 +10,7 @@ Everything needed to build a plugin for the `actdata-plugins` marketplace, and the conventions that keep one from breaking at install time. -![skills](https://img.shields.io/badge/skills-7-00A8E1?labelColor=003767) +![skills](https://img.shields.io/badge/skills-11-00A8E1?labelColor=003767) ![agents](https://img.shields.io/badge/agents-3-003767) ![commands](https://img.shields.io/badge/commands-1-147EC2) ![size](https://img.shields.io/badge/size-535_KB-00817D) @@ -36,7 +36,8 @@ that keep one from breaking at install time. ## What this is A fork of Claude Code's `plugin-dev` toolkit, adapted for this marketplace. It carries the same -seven reference skills, the same three review agents, and the same eight-phase creation command — +seven reference skills, four portable workflow skills, the same three review agents, and the same +eight-phase creation command — with the generic advice replaced by what is actually true here: plugins live at `plugins//`, Bun is the runtime, skill names are kebab-case and must match their directory, and a plugin is not finished until it is registered in `.claude-plugin/marketplace.json`. @@ -49,7 +50,7 @@ itself. | Component | Count | What it is | |---|---|---| -| Skills | **7** | A lean `SKILL.md` with the decision rules needed immediately, plus `references/`, `examples/` and `scripts/` loaded on demand. | +| Skills | **11** | Authoring guidance plus portable creation and review workflows for supported hosts. | | Agents | **3** | `agent-creator` generates agents; `plugin-validator` audits a plugin against structure, manifest, marketplace registration, and repository conventions; `skill-reviewer` reviews a single skill. | | Command | **1** | `/act-plugin-dev:create-plugin`, an eight-phase guided workflow from concept to registered plugin. | | Utility scripts | **6** | POSIX-sh validators shipped inside the skills: `validate-agent.sh`, `validate-hook-schema.sh`, `test-hook.sh`, `hook-linter.sh`, `validate-settings.sh`, `parse-frontmatter.sh`. | @@ -67,7 +68,7 @@ runtime behaviour. | [`agent-development`](skills/agent-development/) | Subagents: system prompt design, triggering conditions, `` blocks, tool selection. | | [`hook-development`](skills/hook-development/) | All hook events, prompt-based vs command hooks, output schemas, security, portable paths. | | [`mcp-integration`](skills/mcp-integration/) | Wiring an MCP server into a plugin: stdio, SSE and HTTP server types, authentication, tool usage. | -| [`plugin-settings`](skills/plugin-settings/) | The `.claude/.local.md` pattern for user-configurable plugin state. | +| [`plugin-settings`](skills/plugin-settings/) | Portable `.agents/.local.md` settings with a legacy Claude fallback. | ## Agents diff --git a/plugins/act-plugin-dev/agents/agent-creator.md b/plugins/act-plugin-dev/agents/agent-creator.md index 3e28294..9e5a295 100644 --- a/plugins/act-plugin-dev/agents/agent-creator.md +++ b/plugins/act-plugin-dev/agents/agent-creator.md @@ -1,34 +1,34 @@ --- name: agent-creator -description: Use this agent when the user asks to "create an agent", "generate an agent", "build a new agent", "make me an agent that...", or describes agent functionality they need. Trigger when user wants to create autonomous agents for plugins. Examples: - - -Context: User wants to create a code review agent -user: "Create an agent that reviews code for quality issues" -assistant: "I'll use the agent-creator agent to generate the agent configuration." - -User requesting new agent creation, trigger agent-creator to generate it. - - - - -Context: User describes needed functionality -user: "I need an agent that generates unit tests for my code" -assistant: "I'll use the agent-creator agent to create a test generation agent." - -User describes agent need, trigger agent-creator to build it. - - - - -Context: User wants to add agent to plugin -user: "Add an agent to my plugin that validates configurations" -assistant: "I'll use the agent-creator agent to generate a configuration validator agent." - -Plugin development with agent addition, trigger agent-creator. - - - +description: | + Create Claude Code custom agents with focused triggering, tools, and system prompts. Use this agent when the user wants to build a new agent, automate a recurring task with a focused persona, or generate an agent configuration file. + + + Context: The user wants to create a code-review agent. + user: "Create an agent that reviews pull request diffs for security issues." + assistant: "I'll use the agent-creator agent to design that for you." + + The user's request maps directly to agent creation: a new agent file with a security-review persona, targeted tools, and focused triggering examples is needed. + + + + + Context: A plugin author wants to add automated documentation generation. + user: "I need an agent that writes API documentation from source comments." + assistant: "I'll use the agent-creator agent to build that documentation agent." + + Generating an agent that reads source files and produces documentation is a clear agent-creation task, so agent-creator should handle it. + + + + + Context: The user is building a plugin and wants a ready-to-use validation agent. + user: "Add a plugin-structure-checker agent to my plugin." + assistant: "I'll use the agent-creator agent to scaffold that checker agent." + + Any request to add an agent file to a plugin triggers agent-creator, which produces the frontmatter, system prompt, and example blocks the repository requires. + + model: sonnet color: magenta tools: ["Write", "Read"] diff --git a/plugins/act-plugin-dev/agents/plugin-validator.md b/plugins/act-plugin-dev/agents/plugin-validator.md index 7a226e8..1c373f7 100644 --- a/plugins/act-plugin-dev/agents/plugin-validator.md +++ b/plugins/act-plugin-dev/agents/plugin-validator.md @@ -1,36 +1,34 @@ --- name: plugin-validator -description: Use this agent when the user asks to "validate my plugin", "check plugin structure", "verify plugin is correct", "validate plugin.json", "check plugin files", or mentions plugin validation. Also trigger proactively after user creates or modifies plugin components. Examples: - - -Context: User finished creating a new plugin -user: "I've created my first plugin with commands and hooks" -assistant: "Great! Let me validate the plugin structure." - -Plugin created, proactively validate to catch issues early. - -assistant: "I'll use the plugin-validator agent to check the plugin." - - - -Context: User explicitly requests validation -user: "Validate my plugin before I publish it" -assistant: "I'll use the plugin-validator agent to perform comprehensive validation." - -Explicit validation request triggers the agent. - - - - -Context: User modified plugin.json -user: "I've updated the plugin manifest" -assistant: "Let me validate the changes." - -Manifest modified, validate to ensure correctness. - -assistant: "I'll use the plugin-validator agent to check the manifest." - - +description: | + Validate plugin structure, manifests, components, registration, and ACT repository conventions. Use this agent when the user wants to check a plugin before opening a PR, after creating or modifying plugin components, or when the repository gate fails. + + + Context: A developer just finished building a new plugin and wants to verify it before submitting. + user: "Validate the act-platform-engineering plugin." + assistant: "I'll use the plugin-validator agent to run a full validation on that plugin." + + Any explicit request to validate a plugin should route to plugin-validator, which checks manifests, naming, marketplace registration, and ACT conventions in one pass. + + + + + Context: CI has failed with a verify-all error and the author is not sure which rule fired. + user: "The gate is failing — can you check what's wrong with my plugin?" + assistant: "I'll use the plugin-validator agent to diagnose the gate failure." + + Gate failures are precisely what plugin-validator diagnoses: it runs the same checks verify-all.sh runs and reports findings with file paths and fix suggestions. + + + + + Context: The user added a new skill and wants to confirm naming and registration are correct. + user: "I added a new skill directory. Does everything look right?" + assistant: "I'll use the plugin-validator agent to check the skill name, SKILL.md frontmatter, and marketplace entry." + + Adding a skill introduces the most common failure mode (skill name does not match directory); plugin-validator checks that first among its critical findings. + + model: inherit color: yellow tools: ["Read", "Grep", "Glob", "Bash"] @@ -242,4 +240,4 @@ Location: [path] **Reporting discipline:** Report what you actually observed. If you could not read a file, say so rather than assuming it is -absent or valid. Never report `PASS` on the basis of checks you did not run. \ No newline at end of file +absent or valid. Never report `PASS` on the basis of checks you did not run. diff --git a/plugins/act-plugin-dev/agents/skill-reviewer.md b/plugins/act-plugin-dev/agents/skill-reviewer.md index d27f768..f7338fc 100644 --- a/plugins/act-plugin-dev/agents/skill-reviewer.md +++ b/plugins/act-plugin-dev/agents/skill-reviewer.md @@ -1,35 +1,34 @@ --- name: skill-reviewer -description: Use this agent when the user has created or modified a skill and needs quality review, asks to "review my skill", "check skill quality", "improve skill description", or wants to ensure skill follows best practices. Trigger proactively after skill creation. Examples: - - -Context: User just created a new skill -user: "I've created a PDF processing skill" -assistant: "Great! Let me review the skill quality." - -Skill created, proactively trigger skill-reviewer to ensure it follows best practices. - -assistant: "I'll use the skill-reviewer agent to review the skill." - - - -Context: User requests skill review -user: "Review my skill and tell me how to improve it" -assistant: "I'll use the skill-reviewer agent to analyze the skill quality." - -Explicit skill review request triggers the agent. - - - - -Context: User modified skill description -user: "I updated the skill description, does it look good?" -assistant: "I'll use the skill-reviewer agent to review the changes." - -Skill description modified, review for triggering effectiveness. - - - +description: | + Review skill triggering, structure, progressive disclosure, and instruction quality. Use this agent when the user wants feedback on a SKILL.md file, is unsure whether a skill description will trigger reliably, or wants to improve the layout of skill content. + + + Context: A plugin author just wrote a new skill and wants a quality check. + user: "Review the infrastructure-inventory skill." + assistant: "I'll use the skill-reviewer agent to evaluate its structure and triggering." + + Any request to review or evaluate a skill should route to skill-reviewer, which checks description trigger phrases, word count, progressive disclosure, and convention compliance. + + + + + Context: A skill seems not to trigger when expected and the author wants to know why. + user: "My skill never comes up in suggestions — what's wrong with the description?" + assistant: "I'll use the skill-reviewer agent to diagnose the description's trigger phrases." + + Triggering failures almost always trace to a weak description; skill-reviewer evaluates specificity, third-person phrasing, and example trigger queries. + + + + + Context: The user ported a skill from another repo and the gate fails on name mismatch. + user: "The verify-all gate fails on my skill name. Can you check it?" + assistant: "I'll use the skill-reviewer agent to compare the frontmatter name against the directory name." + + Name-vs-directory mismatch is the single most common porting defect; skill-reviewer reports it as a critical finding with the exact fix. + + model: inherit color: cyan tools: ["Read", "Grep", "Glob"] diff --git a/plugins/act-plugin-dev/plugin.json b/plugins/act-plugin-dev/plugin.json new file mode 100644 index 0000000..8c5301d --- /dev/null +++ b/plugins/act-plugin-dev/plugin.json @@ -0,0 +1,6 @@ +{ + "name": "act-plugin-dev", "version": "0.2.0", "description": "Create and review portable agent plugins.", + "author": { "name": "Daniel Bodnar", "email": "dbodnar@pattersonvet.com", "url": "https://github.com/patterson-agents" }, + "homepage": "https://github.com/patterson-agents/actdata-plugins", "repository": "https://github.com/patterson-agents/actdata-plugins", "license": "LicenseRef-ACT-Internal", + "keywords": ["plugin-development", "skills", "commands", "agents", "hooks", "mcp", "marketplace"], "skills": "skills/", "commands": "commands/" +} diff --git a/plugins/act-plugin-dev/skills/agent-creator/SKILL.md b/plugins/act-plugin-dev/skills/agent-creator/SKILL.md new file mode 100644 index 0000000..20cadd1 --- /dev/null +++ b/plugins/act-plugin-dev/skills/agent-creator/SKILL.md @@ -0,0 +1,12 @@ +--- +name: agent-creator +description: "Design a Claude Code custom agent. Use when asked to create, generate, or improve an agent or subagent definition." +--- + +# Agent Creator + +Read and follow the canonical procedure in [../../agents/agent-creator.md](../../agents/agent-creator.md). + +Treat the user's current request as the procedure input. Ignore the source file's YAML frontmatter +and any Claude-only invocation syntax. Use equivalent tools available on the current host, preserve +all safety checks, and resolve bundled resources from this plugin rather than the user's project. diff --git a/plugins/act-plugin-dev/skills/agent-development/SKILL.md b/plugins/act-plugin-dev/skills/agent-development/SKILL.md index ca0e183..79a17f1 100644 --- a/plugins/act-plugin-dev/skills/agent-development/SKILL.md +++ b/plugins/act-plugin-dev/skills/agent-development/SKILL.md @@ -1,7 +1,6 @@ --- name: agent-development description: This skill should be used when the user asks to "create an agent", "add an agent", "write a subagent", "agent frontmatter", "when to use description", "agent examples", "agent tools", "agent colors", "autonomous agent", or needs guidance on agent structure, system prompts, triggering conditions, or agent development best practices for Claude Code plugins. -version: 0.1.0 --- # Agent Development for Claude Code Plugins diff --git a/plugins/act-plugin-dev/skills/command-development/SKILL.md b/plugins/act-plugin-dev/skills/command-development/SKILL.md index 45f9eae..1e3ef15 100644 --- a/plugins/act-plugin-dev/skills/command-development/SKILL.md +++ b/plugins/act-plugin-dev/skills/command-development/SKILL.md @@ -1,7 +1,6 @@ --- name: command-development description: This skill should be used when the user asks to "create a slash command", "add a command", "write a custom command", "define command arguments", "use command frontmatter", "organize commands", "create command with file references", "interactive command", "use AskUserQuestion in command", or needs guidance on slash command structure, YAML frontmatter fields, dynamic arguments, bash execution in commands, user interaction patterns, or command development best practices for Claude Code. -version: 0.2.0 --- # Command Development for Claude Code diff --git a/plugins/act-plugin-dev/skills/create-plugin/SKILL.md b/plugins/act-plugin-dev/skills/create-plugin/SKILL.md new file mode 100644 index 0000000..95e7400 --- /dev/null +++ b/plugins/act-plugin-dev/skills/create-plugin/SKILL.md @@ -0,0 +1,17 @@ +--- +name: create-plugin +description: "Create a plugin for the actdata-plugins marketplace. Use when asked to create, scaffold, package, register, or validate a new marketplace plugin." +--- + +# Create Plugin + +Read and follow the canonical procedure in [../../commands/create-plugin.md](../../commands/create-plugin.md). + +Treat the user's current request as the procedure input. Ignore the source file's YAML frontmatter +and any Claude-only invocation syntax. Use equivalent tools available on the current host, preserve +all safety checks, and resolve bundled resources from this plugin rather than the user's project. + +For a portable plugin, create all three manifests: `.claude-plugin/plugin.json`, +`.codex-plugin/plugin.json`, and root `plugin.json`. Register it in the Claude, OpenAI, and Copilot +marketplaces. Put reusable behavior in `skills/`; treat Claude commands and agents as optional host +adapters. Keep versions identical everywhere and run the repository compatibility gate. diff --git a/plugins/act-plugin-dev/skills/hook-development/SKILL.md b/plugins/act-plugin-dev/skills/hook-development/SKILL.md index 6317441..431bd6f 100644 --- a/plugins/act-plugin-dev/skills/hook-development/SKILL.md +++ b/plugins/act-plugin-dev/skills/hook-development/SKILL.md @@ -1,7 +1,6 @@ --- name: hook-development description: This skill should be used when the user asks to "create a hook", "add a PreToolUse/PostToolUse/Stop hook", "validate tool use", "implement prompt-based hooks", "use ${CLAUDE_PLUGIN_ROOT}", "set up event-driven automation", "block dangerous commands", or mentions hook events (PreToolUse, PostToolUse, Stop, SubagentStop, SessionStart, SessionEnd, UserPromptSubmit, PreCompact, Notification). Provides comprehensive guidance for creating and implementing Claude Code plugin hooks with focus on advanced prompt-based hooks API. -version: 0.1.0 --- # Hook Development for Claude Code Plugins diff --git a/plugins/act-plugin-dev/skills/mcp-integration/SKILL.md b/plugins/act-plugin-dev/skills/mcp-integration/SKILL.md index aee6c05..5bf4069 100644 --- a/plugins/act-plugin-dev/skills/mcp-integration/SKILL.md +++ b/plugins/act-plugin-dev/skills/mcp-integration/SKILL.md @@ -1,7 +1,6 @@ --- name: mcp-integration description: This skill should be used when the user asks to "add MCP server", "integrate MCP", "configure MCP in plugin", "use .mcp.json", "set up Model Context Protocol", "connect external service", mentions "${CLAUDE_PLUGIN_ROOT} with MCP", or discusses MCP server types (SSE, stdio, HTTP, WebSocket). Provides comprehensive guidance for integrating Model Context Protocol servers into Claude Code plugins for external tool and service integration. -version: 0.1.0 --- # MCP Integration for Claude Code Plugins diff --git a/plugins/act-plugin-dev/skills/plugin-settings/SKILL.md b/plugins/act-plugin-dev/skills/plugin-settings/SKILL.md index 60ae408..3a777e3 100644 --- a/plugins/act-plugin-dev/skills/plugin-settings/SKILL.md +++ b/plugins/act-plugin-dev/skills/plugin-settings/SKILL.md @@ -1,7 +1,6 @@ --- name: plugin-settings description: This skill should be used when the user asks about "plugin settings", "store plugin configuration", "user-configurable plugin", ".local.md files", "plugin state files", "read YAML frontmatter", "per-project plugin settings", or wants to make plugin behavior configurable. Documents the .claude/plugin-name.local.md pattern for storing plugin-specific configuration with YAML frontmatter and markdown content. -version: 0.1.0 --- # Plugin Settings Pattern for Claude Code Plugins diff --git a/plugins/act-plugin-dev/skills/plugin-structure/SKILL.md b/plugins/act-plugin-dev/skills/plugin-structure/SKILL.md index 8511167..1054acd 100644 --- a/plugins/act-plugin-dev/skills/plugin-structure/SKILL.md +++ b/plugins/act-plugin-dev/skills/plugin-structure/SKILL.md @@ -1,7 +1,6 @@ --- name: plugin-structure description: This skill should be used when the user asks to "create a plugin", "scaffold a plugin", "understand plugin structure", "organize plugin components", "set up plugin.json", "use ${CLAUDE_PLUGIN_ROOT}", "add commands/agents/skills/hooks", "configure auto-discovery", or needs guidance on plugin directory layout, manifest configuration, component organization, file naming conventions, or Claude Code plugin architecture best practices. -version: 0.1.0 --- # Plugin Structure for Claude Code diff --git a/plugins/act-plugin-dev/skills/plugin-validator/SKILL.md b/plugins/act-plugin-dev/skills/plugin-validator/SKILL.md new file mode 100644 index 0000000..b2f2162 --- /dev/null +++ b/plugins/act-plugin-dev/skills/plugin-validator/SKILL.md @@ -0,0 +1,16 @@ +--- +name: plugin-validator +description: "Validate a marketplace plugin. Use when asked to check plugin structure, manifests, components, registration, or portability." +--- + +# Plugin Validator + +Read and follow the canonical procedure in [../../agents/plugin-validator.md](../../agents/plugin-validator.md). + +Treat the user's current request as the procedure input. Ignore the source file's YAML frontmatter +and any Claude-only invocation syntax. Use equivalent tools available on the current host, preserve +all safety checks, and resolve bundled resources from this plugin rather than the user's project. + +Also validate `.codex-plugin/plugin.json`, root `plugin.json`, and the `.agents/plugins` and +`.github/plugin` marketplace entries. Names, versions, and source paths must agree across all three +hosts. Core workflows must be skills so ChatGPT does not depend on commands, agents, or hooks. diff --git a/plugins/act-plugin-dev/skills/skill-development/SKILL.md b/plugins/act-plugin-dev/skills/skill-development/SKILL.md index b28fd99..2649250 100644 --- a/plugins/act-plugin-dev/skills/skill-development/SKILL.md +++ b/plugins/act-plugin-dev/skills/skill-development/SKILL.md @@ -1,7 +1,6 @@ --- name: skill-development description: This skill should be used when the user wants to "create a skill", "add a skill to plugin", "write a new skill", "improve skill description", "organize skill content", or needs guidance on skill structure, progressive disclosure, or skill development best practices for Claude Code plugins. -version: 0.1.0 --- # Skill Development for Claude Code Plugins diff --git a/plugins/act-plugin-dev/skills/skill-reviewer/SKILL.md b/plugins/act-plugin-dev/skills/skill-reviewer/SKILL.md new file mode 100644 index 0000000..91b43bc --- /dev/null +++ b/plugins/act-plugin-dev/skills/skill-reviewer/SKILL.md @@ -0,0 +1,12 @@ +--- +name: skill-reviewer +description: "Review an agent skill for structure, triggering, progressive disclosure, and instruction quality." +--- + +# Skill Reviewer + +Read and follow the canonical procedure in [../../agents/skill-reviewer.md](../../agents/skill-reviewer.md). + +Treat the user's current request as the procedure input. Ignore the source file's YAML frontmatter +and any Claude-only invocation syntax. Use equivalent tools available on the current host, preserve +all safety checks, and resolve bundled resources from this plugin rather than the user's project. diff --git a/plugins/act-work-tracking/.claude-plugin/plugin.json b/plugins/act-work-tracking/.claude-plugin/plugin.json index 27316cf..8d64e60 100644 --- a/plugins/act-work-tracking/.claude-plugin/plugin.json +++ b/plugins/act-work-tracking/.claude-plugin/plugin.json @@ -1,7 +1,7 @@ { "$schema": "https://anthropic.com/claude-code/plugin.schema.json", "name": "act-work-tracking", - "version": "0.1.0", + "version": "0.2.0", "description": "Zoho Projects work tracking and operations reporting. Covers the task-versus-issue distinction, drafting templates, the REST API's quirks, bulk creation, weekly status structure, and the writing conventions that keep issues and reports actionable. Reads portal and project IDs from a site-local settings file.", "author": { "name": "Daniel Bodnar", diff --git a/plugins/act-work-tracking/.codex-plugin/plugin.json b/plugins/act-work-tracking/.codex-plugin/plugin.json new file mode 100644 index 0000000..89a72b2 --- /dev/null +++ b/plugins/act-work-tracking/.codex-plugin/plugin.json @@ -0,0 +1,7 @@ +{ + "name": "act-work-tracking", "version": "0.2.0", "description": "Zoho Projects work tracking and operations reporting workflows for ACT Data.", + "author": { "name": "Daniel Bodnar", "email": "dbodnar@pattersonvet.com", "url": "https://github.com/patterson-agents" }, + "homepage": "https://github.com/patterson-agents/actdata-plugins", "repository": "https://github.com/patterson-agents/actdata-plugins", "license": "LicenseRef-ACT-Internal", + "keywords": ["zoho", "issue-tracking", "backlog", "status-reporting", "technical-writing"], "skills": "./skills/", + "interface": { "displayName": "ACT Work Tracking", "shortDescription": "Draft tracked work and operations reports", "longDescription": "Draft Zoho Projects tasks and issues, check for duplicates, and prepare concise engineering status reports.", "developerName": "ACT Data", "category": "Workflow", "capabilities": ["Read", "Write"], "websiteURL": "https://github.com/patterson-agents/actdata-plugins", "defaultPrompt": ["Draft a Zoho issue from this finding.", "Prepare this week's engineering status report."] } +} diff --git a/plugins/act-work-tracking/README.md b/plugins/act-work-tracking/README.md index 797f1d3..37381ee 100644 --- a/plugins/act-work-tracking/README.md +++ b/plugins/act-work-tracking/README.md @@ -9,7 +9,7 @@ Zoho Projects work tracking, and writing engineering work up so it can be acted on. -![skills](https://img.shields.io/badge/skills-2-00A8E1?labelColor=003767) +![skills](https://img.shields.io/badge/skills-6-00A8E1?labelColor=003767) ![agents](https://img.shields.io/badge/agents-1-003767) ![commands](https://img.shields.io/badge/commands-3-147EC2) ![config](https://img.shields.io/badge/config-driven-00817D) @@ -44,7 +44,7 @@ It ships **no portal IDs, project IDs or user IDs**. Those come from a settings | Component | Count | What it is | |---|---|---| -| Skills | 2 | Zoho Projects mechanics, and reporting and writing conventions | +| Skills | 6 | Zoho Projects and reporting guidance plus portable workflow adapters | | Agents | 1 | Deciding what is worth reporting and to whom | | Commands | 3 | Draft an issue, draft a task, draft the weekly status | | Scripts | 1 | Bulk creation from JSON, with a credential-free dry run | @@ -73,8 +73,8 @@ claude plugin install act-work-tracking@actdata-plugins ## Configuration -Create `.claude/act-work-tracking.local.md` in your project. It is gitignored by this repository's -`.gitignore` (`.claude/*.local.md`). +Create `.agents/act-work-tracking.local.md` in your project. Existing Claude installations may use +`.claude/act-work-tracking.local.md` as a fallback. Both paths are gitignored. ```markdown # act-work-tracking settings diff --git a/plugins/act-work-tracking/plugin.json b/plugins/act-work-tracking/plugin.json new file mode 100644 index 0000000..d7dc643 --- /dev/null +++ b/plugins/act-work-tracking/plugin.json @@ -0,0 +1,6 @@ +{ + "name": "act-work-tracking", "version": "0.2.0", "description": "Draft Zoho Projects work and engineering status reports.", + "author": { "name": "Daniel Bodnar", "email": "dbodnar@pattersonvet.com", "url": "https://github.com/patterson-agents" }, + "homepage": "https://github.com/patterson-agents/actdata-plugins", "repository": "https://github.com/patterson-agents/actdata-plugins", "license": "LicenseRef-ACT-Internal", + "keywords": ["zoho", "issue-tracking", "backlog", "status-reporting", "technical-writing"], "skills": "skills/", "commands": "commands/" +} diff --git a/plugins/act-work-tracking/skills/draft-issue/SKILL.md b/plugins/act-work-tracking/skills/draft-issue/SKILL.md new file mode 100644 index 0000000..8d064d9 --- /dev/null +++ b/plugins/act-work-tracking/skills/draft-issue/SKILL.md @@ -0,0 +1,14 @@ +--- +name: draft-issue +description: "Draft a concrete Zoho Projects issue from a finding or request and check for duplicates first." +--- + +# Draft Issue + +Read and follow the canonical procedure in [../../commands/draft-issue.md](../../commands/draft-issue.md). + +Treat the user's current request as the procedure input. Ignore the source file's YAML frontmatter +and any Claude-only invocation syntax. Use equivalent tools available on the current host, preserve +all safety checks, and resolve bundled resources from this plugin rather than the user's project. +Read site configuration from `.agents/act-work-tracking.local.md`; fall back to the legacy +`.claude/act-work-tracking.local.md` only when the portable file is absent. diff --git a/plugins/act-work-tracking/skills/draft-task/SKILL.md b/plugins/act-work-tracking/skills/draft-task/SKILL.md new file mode 100644 index 0000000..eea9ba0 --- /dev/null +++ b/plugins/act-work-tracking/skills/draft-task/SKILL.md @@ -0,0 +1,14 @@ +--- +name: draft-task +description: "Draft a Zoho Projects task that groups related issues under a durable work category." +--- + +# Draft Task + +Read and follow the canonical procedure in [../../commands/draft-task.md](../../commands/draft-task.md). + +Treat the user's current request as the procedure input. Ignore the source file's YAML frontmatter +and any Claude-only invocation syntax. Use equivalent tools available on the current host, preserve +all safety checks, and resolve bundled resources from this plugin rather than the user's project. +Read site configuration from `.agents/act-work-tracking.local.md`; fall back to the legacy +`.claude/act-work-tracking.local.md` only when the portable file is absent. diff --git a/plugins/act-work-tracking/skills/ops-reporting/SKILL.md b/plugins/act-work-tracking/skills/ops-reporting/SKILL.md index 0eb24fa..e262757 100644 --- a/plugins/act-work-tracking/skills/ops-reporting/SKILL.md +++ b/plugins/act-work-tracking/skills/ops-reporting/SKILL.md @@ -1,7 +1,6 @@ --- name: ops-reporting description: This skill should be used when the user asks to "write the weekly status", "draft a status report", "update the assessment doc", "what goes in which document", "write this up for management", or asks about tone and phrasing for issues, status reports or internal engineering documents. Covers the house writing conventions, weekly status structure, and how a multi-document assessment set divides by audience. -version: 0.1.0 --- # Operations Reporting diff --git a/plugins/act-work-tracking/skills/reporting-analyst/SKILL.md b/plugins/act-work-tracking/skills/reporting-analyst/SKILL.md new file mode 100644 index 0000000..6736236 --- /dev/null +++ b/plugins/act-work-tracking/skills/reporting-analyst/SKILL.md @@ -0,0 +1,14 @@ +--- +name: reporting-analyst +description: "Apply the ACT Data reporting analyst procedure. Use to group findings, route content by audience, and turn findings into tracked work." +--- + +# Reporting Analyst + +Read and follow the canonical procedure in [../../agents/reporting-analyst.md](../../agents/reporting-analyst.md). + +Treat the user's current request as the procedure input. Ignore the source file's YAML frontmatter +and any Claude-only invocation syntax. Use equivalent tools available on the current host, preserve +all safety checks, and resolve bundled resources from this plugin rather than the user's project. +Read site configuration from `.agents/act-work-tracking.local.md`; fall back to the legacy +`.claude/act-work-tracking.local.md` only when the portable file is absent. diff --git a/plugins/act-work-tracking/skills/weekly-status/SKILL.md b/plugins/act-work-tracking/skills/weekly-status/SKILL.md new file mode 100644 index 0000000..1a4ea1d --- /dev/null +++ b/plugins/act-work-tracking/skills/weekly-status/SKILL.md @@ -0,0 +1,14 @@ +--- +name: weekly-status +description: "Draft the weekly engineering status from completed work, tracker activity, risks, and blockers." +--- + +# Weekly Status + +Read and follow the canonical procedure in [../../commands/weekly-status.md](../../commands/weekly-status.md). + +Treat the user's current request as the procedure input. Ignore the source file's YAML frontmatter +and any Claude-only invocation syntax. Use equivalent tools available on the current host, preserve +all safety checks, and resolve bundled resources from this plugin rather than the user's project. +Read site configuration from `.agents/act-work-tracking.local.md`; fall back to the legacy +`.claude/act-work-tracking.local.md` only when the portable file is absent. diff --git a/plugins/act-work-tracking/skills/zoho-projects/SKILL.md b/plugins/act-work-tracking/skills/zoho-projects/SKILL.md index 71b78ff..ec58fa5 100644 --- a/plugins/act-work-tracking/skills/zoho-projects/SKILL.md +++ b/plugins/act-work-tracking/skills/zoho-projects/SKILL.md @@ -1,7 +1,6 @@ --- name: zoho-projects description: This skill should be used when the user asks to "create a Zoho task", "draft an issue", "add this to the backlog", "file this in Zoho", "bulk create issues", "what's the difference between a task and an issue", or mentions Zoho Projects, the bugs API, portal IDs, project IDs, Zoho-oauthtoken, or turning assessment findings into tracked work items. Covers the task-versus-issue distinction, drafting templates, the API's quirks, and bulk creation. -version: 0.1.0 --- # Zoho Projects @@ -11,6 +10,7 @@ Turning work into tracked items, and the API quirks involved in getting them the ## Configuration Portal ID, project IDs, prefixes and the default assignee come from +`.agents/act-work-tracking.local.md`, falling back to the legacy `.claude/act-work-tracking.local.md`. This plugin ships none of them. If the file is absent, ask the user to create it from the template in the plugin README. Do not diff --git a/plugins/act-work-tracking/skills/zoho-projects/references/zoho-api.md b/plugins/act-work-tracking/skills/zoho-projects/references/zoho-api.md index 6132d33..d6c0862 100644 --- a/plugins/act-work-tracking/skills/zoho-projects/references/zoho-api.md +++ b/plugins/act-work-tracking/skills/zoho-projects/references/zoho-api.md @@ -3,7 +3,8 @@ Field-tested quirks of the Zoho Projects REST API. These are the things that cost an afternoon the first time. -All portal, project and user IDs come from `.claude/act-work-tracking.local.md`. None are recorded +All portal, project and user IDs come from `.agents/act-work-tracking.local.md`, falling back to the +legacy `.claude/act-work-tracking.local.md`. None are recorded here. --- diff --git a/scripts/check-marketplace-compat.ts b/scripts/check-marketplace-compat.ts new file mode 100644 index 0000000..c544e20 --- /dev/null +++ b/scripts/check-marketplace-compat.ts @@ -0,0 +1,110 @@ +#!/usr/bin/env bun +import { existsSync, readFileSync, readdirSync, statSync } from "node:fs"; +import { join, resolve } from "node:path"; + +if (process.argv.length < 3) { + console.error("Usage: bun scripts/check-marketplace-compat.ts "); + process.exit(2); +} + +const root = resolve(process.argv[2]); + +try { + const st = statSync(root); + if (!st.isDirectory()) { + console.error(`ERROR: ${root} is not a directory`); + process.exit(2); + } +} catch { + console.error(`ERROR: ${root}: could not evaluate (path missing or unreadable)`); + process.exit(2); +} + +const problems: string[] = []; + +function json(path: string): Record { + try { + return JSON.parse(readFileSync(path, "utf8")); + } catch (error) { + problems.push(`${path}: ${error instanceof Error ? error.message : String(error)}`); + return {}; + } +} + +const claudePath = join(root, ".claude-plugin", "marketplace.json"); +const openaiPath = join(root, ".agents", "plugins", "marketplace.json"); +const copilotPath = join(root, ".github", "plugin", "marketplace.json"); +for (const path of [claudePath, openaiPath, copilotPath]) { + if (!existsSync(path)) problems.push(`${path}: required marketplace is missing`); +} + +const claude = json(claudePath); +const openai = json(openaiPath); +const copilot = json(copilotPath); +const claudeEntries = new Map((claude.plugins ?? []).map((entry: any) => [entry.name, entry])); +const openaiEntries = new Map((openai.plugins ?? []).map((entry: any) => [entry.name, entry])); +const copilotEntries = new Map((copilot.plugins ?? []).map((entry: any) => [entry.name, entry])); +for (const [host, entries] of [["OpenAI", openaiEntries], ["Copilot", copilotEntries]] as const) { + for (const name of entries.keys()) { + if (!claudeEntries.has(name)) problems.push(`${String(name)}: present only in ${host} marketplace`); + } +} + +let pluginDirs: import("node:fs").Dirent[]; +try { + pluginDirs = readdirSync(join(root, "plugins"), { withFileTypes: true }); +} catch { + console.error(`ERROR: ${root}: could not evaluate (plugins/ directory missing or unreadable)`); + process.exit(2); +} + +for (const dir of pluginDirs) { + if (!dir.isDirectory()) continue; + const pluginRoot = join(root, "plugins", dir.name); + const claudeManifestPath = join(pluginRoot, ".claude-plugin", "plugin.json"); + if (!existsSync(claudeManifestPath)) continue; + + const manifests = [ + ["Claude", claudeManifestPath], + ["OpenAI", join(pluginRoot, ".codex-plugin", "plugin.json")], + ["Copilot", join(pluginRoot, "plugin.json")], + ] as const; + const versions = new Set(); + for (const [host, path] of manifests) { + if (!existsSync(path)) { + problems.push(`${dir.name}: missing ${host} manifest ${path}`); + continue; + } + const manifest = json(path); + if (manifest.name !== dir.name) problems.push(`${path}: name must equal ${dir.name}`); + if (typeof manifest.version !== "string") problems.push(`${path}: version is required`); + else versions.add(manifest.version); + } + if (versions.size > 1) problems.push(`${dir.name}: manifest versions disagree (${[...versions].join(", ")})`); + const version = [...versions][0]; + + const ce: any = claudeEntries.get(dir.name); + const oe: any = openaiEntries.get(dir.name); + const ge: any = copilotEntries.get(dir.name); + if (!ce || !oe || !ge) { + problems.push(`${dir.name}: missing from one or more marketplaces`); + continue; + } + if (ce.version !== version || ge.version !== version) problems.push(`${dir.name}: catalog version does not match ${version}`); + if (typeof ce.source !== "string" || resolve(root, ce.source) !== pluginRoot) problems.push(`${dir.name}: Claude source must resolve to the plugin directory`); + if (oe.policy?.installation !== "AVAILABLE") problems.push(`${dir.name}: OpenAI installation policy must be AVAILABLE`); + if (oe.policy?.authentication !== "ON_INSTALL") problems.push(`${dir.name}: OpenAI authentication policy must be ON_INSTALL`); + if (typeof oe.category !== "string" || !oe.category) problems.push(`${dir.name}: OpenAI category is required`); + + const openaiSource = oe.source?.path; + if (oe.source?.source !== "local" || typeof openaiSource !== "string" || resolve(root, openaiSource) !== pluginRoot) { + problems.push(`${dir.name}: OpenAI source must resolve to the plugin directory`); + } + if (typeof ge.source !== "string" || resolve(root, ge.source) !== pluginRoot) { + problems.push(`${dir.name}: Copilot source must resolve to the plugin directory`); + } +} + +for (const problem of problems) console.log(`ERROR|marketplace|0|compat|${problem}`); +if (problems.length) process.exit(1); +console.log(`INFO|marketplace|0|compat|${claudeEntries.size} plugin(s) agree across Claude, OpenAI, and Copilot`); diff --git a/scripts/tests/run-tests.sh b/scripts/tests/run-tests.sh index 1716059..3fb0e78 100755 --- a/scripts/tests/run-tests.sh +++ b/scripts/tests/run-tests.sh @@ -1,5 +1,5 @@ #!/bin/sh -# Test harness for check-size.ts and check-no-binaries.ts. POSIX sh, no dependencies. +# Test harness for the repository validators. POSIX sh, no dependencies. # # Fixtures are generated at run time into throwaway git repositories under a scratch # directory, never committed: a real oversized tree or a real font binary living in this @@ -16,6 +16,7 @@ DIR=$(CDPATH= cd -- "$(dirname -- "$0")" && pwd) ROOT=$(CDPATH= cd -- "$DIR/../.." && pwd) SIZE_CHECK="$DIR/../check-size.ts" BIN_CHECK="$DIR/../check-no-binaries.ts" +COMPAT_CHECK="$DIR/../check-marketplace-compat.ts" fail=0 mkdir -p "$ROOT/.tmp" @@ -154,5 +155,80 @@ expect_exit 2 "$BIN_CHECK" "$WORK/does-not-exist" "missing path is 'could not ev bun "$BIN_CHECK" >/dev/null 2>&1 if [ $? -ne 2 ]; then echo "FAIL no-args: expected exit 2"; fail=1; else echo "ok no-args (exit 2)"; fi +echo "== check-marketplace-compat.ts ==" + +compat="$WORK/compat" +mkdir -p "$compat/.claude-plugin" "$compat/.agents/plugins" "$compat/.github/plugin" \ + "$compat/plugins/example/.claude-plugin" "$compat/plugins/example/.codex-plugin" +printf '%s\n' '{"plugins":[{"name":"example","version":"1.0.0","source":"./plugins/example","relevance":{}}]}' > "$compat/.claude-plugin/marketplace.json" +printf '%s\n' '{"plugins":[{"name":"example","source":{"source":"local","path":"./plugins/example"},"policy":{"installation":"AVAILABLE","authentication":"ON_INSTALL"},"category":"Test"}]}' > "$compat/.agents/plugins/marketplace.json" +printf '%s\n' '{"plugins":[{"name":"example","version":"1.0.0","source":"./plugins/example"}]}' > "$compat/.github/plugin/marketplace.json" +printf '%s\n' '{"name":"example","version":"1.0.0"}' > "$compat/plugins/example/.claude-plugin/plugin.json" +printf '%s\n' '{"name":"example","version":"1.0.0"}' > "$compat/plugins/example/.codex-plugin/plugin.json" +printf '%s\n' '{"name":"example","version":"1.0.0"}' > "$compat/plugins/example/plugin.json" +expect_exit 0 "$COMPAT_CHECK" "$compat" "matching host manifests pass" + +printf '%s\n' '{"name":"example","version":"2.0.0"}' > "$compat/plugins/example/plugin.json" +expect_exit 1 "$COMPAT_CHECK" "$compat" "cross-host version drift fails" +expect_rule "compat" "$COMPAT_CHECK" "$compat" "cross-host version drift" + +# Reset to matching versions for subsequent tests. +printf '%s\n' '{"name":"example","version":"1.0.0"}' > "$compat/plugins/example/plugin.json" + +# Negative: wrong source directory in Claude catalog. +wrong_src=$(mktemp -d "$WORK/compat-wrong-src.XXXXXX") +cp -r "$compat/." "$wrong_src/" +printf '%s\n' '{"plugins":[{"name":"example","version":"1.0.0","source":"./plugins/other","relevance":{}}]}' > "$wrong_src/.claude-plugin/marketplace.json" +expect_exit 1 "$COMPAT_CHECK" "$wrong_src" "wrong Claude source directory fails" +expect_rule "compat" "$COMPAT_CHECK" "$wrong_src" "wrong Claude source" + +# Negative: stale entry present only in Copilot catalog (not in Claude). +stale_copilot=$(mktemp -d "$WORK/compat-stale-copilot.XXXXXX") +cp -r "$compat/." "$stale_copilot/" +printf '%s\n' '{"plugins":[{"name":"example","version":"1.0.0","source":"./plugins/example"},{"name":"stale","version":"1.0.0","source":"./plugins/stale"}]}' > "$stale_copilot/.github/plugin/marketplace.json" +expect_exit 1 "$COMPAT_CHECK" "$stale_copilot" "host-only stale Copilot entry fails" +expect_rule "compat" "$COMPAT_CHECK" "$stale_copilot" "stale Copilot entry" + +# Negative: stale entry present only in OpenAI catalog. +stale_openai=$(mktemp -d "$WORK/compat-stale-openai.XXXXXX") +cp -r "$compat/." "$stale_openai/" +printf '%s\n' '{"plugins":[{"name":"example","source":{"source":"local","path":"./plugins/example"},"policy":{"installation":"AVAILABLE","authentication":"ON_INSTALL"},"category":"Test"},{"name":"stale","source":{"source":"local","path":"./plugins/stale"},"policy":{"installation":"AVAILABLE","authentication":"ON_INSTALL"},"category":"Test"}]}' > "$stale_openai/.agents/plugins/marketplace.json" +expect_exit 1 "$COMPAT_CHECK" "$stale_openai" "host-only stale OpenAI entry fails" +expect_rule "compat" "$COMPAT_CHECK" "$stale_openai" "stale OpenAI entry" + +# Negative: missing OpenAI manifest for a plugin. +no_openai_manifest=$(mktemp -d "$WORK/compat-no-openai-manifest.XXXXXX") +cp -r "$compat/." "$no_openai_manifest/" +rm "$no_openai_manifest/plugins/example/.codex-plugin/plugin.json" +expect_exit 1 "$COMPAT_CHECK" "$no_openai_manifest" "missing OpenAI manifest fails" +expect_rule "compat" "$COMPAT_CHECK" "$no_openai_manifest" "missing OpenAI manifest" + +# Negative: missing Copilot manifest for a plugin. +no_copilot_manifest=$(mktemp -d "$WORK/compat-no-copilot-manifest.XXXXXX") +cp -r "$compat/." "$no_copilot_manifest/" +rm "$no_copilot_manifest/plugins/example/plugin.json" +expect_exit 1 "$COMPAT_CHECK" "$no_copilot_manifest" "missing Copilot manifest fails" +expect_rule "compat" "$COMPAT_CHECK" "$no_copilot_manifest" "missing Copilot manifest" + +# Negative: missing OpenAI policy metadata. +no_policy=$(mktemp -d "$WORK/compat-no-policy.XXXXXX") +cp -r "$compat/." "$no_policy/" +printf '%s\n' '{"plugins":[{"name":"example","source":{"source":"local","path":"./plugins/example"},"category":"Test"}]}' > "$no_policy/.agents/plugins/marketplace.json" +expect_exit 1 "$COMPAT_CHECK" "$no_policy" "missing OpenAI policy metadata fails" +expect_rule "compat" "$COMPAT_CHECK" "$no_policy" "missing OpenAI policy" + +# Negative: malformed JSON in a host catalog. +bad_json=$(mktemp -d "$WORK/compat-bad-json.XXXXXX") +cp -r "$compat/." "$bad_json/" +printf '%s\n' '{invalid json' > "$bad_json/.agents/plugins/marketplace.json" +expect_exit 1 "$COMPAT_CHECK" "$bad_json" "malformed catalog JSON fails" + +# Negative: exit 2 for missing root path. +expect_exit 2 "$COMPAT_CHECK" "$WORK/does-not-exist" "missing path is 'could not evaluate'" + +# Negative: exit 2 when no argument is provided. +bun "$COMPAT_CHECK" >/dev/null 2>&1 +if [ $? -ne 2 ]; then echo "FAIL compat-no-args: expected exit 2"; fail=1; else echo "ok compat-no-args (exit 2)"; fi + [ "$fail" -eq 0 ] && echo "ALL TESTS PASSED" || echo "TESTS FAILED" exit "$fail" diff --git a/scripts/verify-all.sh b/scripts/verify-all.sh index 2e611b8..a37a0b7 100755 --- a/scripts/verify-all.sh +++ b/scripts/verify-all.sh @@ -199,7 +199,16 @@ else fi # --------------------------------------------------------------------------- -# 5. No tracked binaries, no size-budget overrun. The validators have their own TDD +# 5. Cross-runtime manifests and marketplaces agree. +# --------------------------------------------------------------------------- +if bun "$ROOT/scripts/check-marketplace-compat.ts" "$ROOT"; then + pass "Claude + OpenAI + Copilot marketplace compatibility" +else + fail "Claude + OpenAI + Copilot marketplace compatibility" +fi + +# --------------------------------------------------------------------------- +# 6. No tracked binaries, no size-budget overrun. The validators have their own TDD # suite (scripts/tests/run-tests.sh, already run in step 1); here they run against # the whole repository, which is their real job. # --------------------------------------------------------------------------- @@ -216,7 +225,7 @@ else fi # --------------------------------------------------------------------------- -# 6. No expanded ${CLAUDE_PLUGIN_ROOT}. An absolute filesystem path immediately followed +# 7. No expanded ${CLAUDE_PLUGIN_ROOT}. An absolute filesystem path immediately followed # by /plugins|/skills|/hooks means some tool wrote a resolved path back into a tracked # file instead of leaving the token literal. #