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

Filter by extension

Filter by extension


Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
33 changes: 33 additions & 0 deletions .agents/plugins/marketplace.json
Original file line number Diff line number Diff line change
@@ -0,0 +1,33 @@
{
"name": "antonbabenko",
"interface": {
"displayName": "Agent Plugins"
},
"plugins": [
{
"name": "code-intelligence",
"source": {
"source": "local",
"path": "./plugins/code-intelligence"
},
"policy": {
"installation": "AVAILABLE",
"authentication": "ON_INSTALL"
},
"category": "Development"
},
{
"name": "terraform-skill",
"source": {
"source": "url",
"url": "git@github.com:antonbabenko/terraform-skill.git",
"ref": "v1.8.0"
},
"policy": {
"installation": "AVAILABLE",
"authentication": "ON_INSTALL"
},
"category": "Development"
}
]
}
2 changes: 1 addition & 1 deletion .claude-plugin/marketplace.json
Original file line number Diff line number Diff line change
Expand Up @@ -17,7 +17,7 @@
"repo": "antonbabenko/terraform-skill",
"ref": "v1.8.0"
},
"description": "Use when writing, reviewing, or debugging Terraform/OpenTofu modules, tests, CI, scans, or state ops \u2014 diagnoses failure mode (identity churn, secrets, blast radius, CI drift, state corruption) with version-aware guards.",
"description": "Use when writing, reviewing, or debugging Terraform/OpenTofu modules, tests, CI, scans, or state ops - diagnoses failure mode (identity churn, secrets, blast radius, CI drift, state corruption) with version-aware guards.",
"category": "development",
"keywords": [
"terraform",
Expand Down
62 changes: 48 additions & 14 deletions .github/workflows/automated-release.yml
Original file line number Diff line number Diff line change
Expand Up @@ -14,6 +14,7 @@ name: Automated Release
# For each bumped plugin the workflow:
# - bumps plugins[].version in marketplace.json
# - syncs that plugin's SKILL.md metadata.version
# - syncs that plugin's .codex-plugin/plugin.json version (if present)
# - prepends an entry to plugins/<plugin>/CHANGELOG.md
# - tags <plugin>-vX.Y.Z and creates a GitHub Release

Expand Down Expand Up @@ -156,27 +157,60 @@ jobs:
sys.exit(1)
open(skill_path, 'w').writelines(lines)

# 3. plugins/<plugin>/CHANGELOG.md entry
# 2b. Codex per-plugin manifest version (optional - only
# inline plugins that ship a .codex-plugin/plugin.json).
codex_path = os.path.join(source, '.codex-plugin', 'plugin.json')
if os.path.isfile(codex_path):
cm = json.load(open(codex_path))
cm['version'] = new
json.dump(cm, open(codex_path, 'w'), indent=2)
open(codex_path, 'a').write('\n')
print(f" synced {codex_path} -> {new}")

# 3. plugins/<plugin>/CHANGELOG.md entry.
# Markdownlint-clean and idempotent: a stable `# Changelog`
# H1 + preamble stays on top, new version sections are
# inserted below it, single blank-line separators, `*`
# bullets only. Also repairs a previously malformed file.
changelog_path = os.path.join(source, 'CHANGELOG.md')
compare = ''
if repo and last_tag:
compare = (f" "
f"([compare](https://github.com/{repo}/compare/"
compare = (f" ([compare](https://github.com/{repo}/compare/"
f"{last_tag}...{name}-v{new}))")
section = [f"## {name}-v{new} ({date.today().isoformat()}){compare}\n\n"]
lines = [
f"## {name}-v{new} "
f"({date.today().isoformat()}){compare}", ""]
if breaking:
section.append("### BREAKING CHANGES\n\n")
lines += ["### BREAKING CHANGES", ""]
if feats:
section.append("### Features\n\n")
section += [f"* {d} ({h})\n" for h, d in feats]
section.append("\n")
lines += ["### Features", ""]
lines += [f"* {d} ({h})" for h, d in feats]
lines += [""]
if fixes:
section.append("### Bug Fixes\n\n")
section += [f"* {d} ({h})\n" for h, d in fixes]
section.append("\n")
entry = "".join(section)
prev = open(changelog_path).read() if os.path.exists(changelog_path) else ""
open(changelog_path, 'w').write(entry + "\n" + prev)
lines += ["### Bug Fixes", ""]
lines += [f"* {d} ({h})" for h, d in fixes]
lines += [""]
entry = "\n".join(lines).strip()

default_header = (
"# Changelog\n\n"
f"All notable changes to the `{name}` plugin are "
"documented here. This file is managed by the per-plugin "
"release pipeline; entries are prepended on release.")
header, body = default_header, ''
if os.path.exists(changelog_path):
old = open(changelog_path).read()
cut = old.find('## ') # first version section
if old.lstrip().startswith('# ') and cut != -1:
header = old[:cut].rstrip()
body = old[cut:].strip()
elif cut != -1:
body = old[cut:].strip() # drop stray preamble
parts = [header, "", entry]
if body:
parts += ["", body]
open(changelog_path, 'w').write(
"\n".join(parts).strip() + "\n")

released.append({'name': name, 'version': new,
'tag': f'{name}-v{new}', 'notes': entry})
Expand Down
10 changes: 10 additions & 0 deletions .github/workflows/validate.yml
Original file line number Diff line number Diff line change
Expand Up @@ -196,6 +196,16 @@ jobs:
f"{name}: marketplace version {version} != "
f"SKILL.md metadata.version {skill_ver}")

# Optional Codex per-plugin manifest must stay in sync.
codex_manifest = os.path.join(
src, '.codex-plugin', 'plugin.json')
if os.path.isfile(codex_manifest):
codex_ver = json.load(open(codex_manifest)).get('version')
if codex_ver != version:
errors.append(
f"{name}: marketplace version {version} != "
f".codex-plugin/plugin.json version {codex_ver}")

elif isinstance(source, dict):
# External plugin: validate reference shape only.
n_external += 1
Expand Down
4 changes: 4 additions & 0 deletions .markdownlint.jsonc
Original file line number Diff line number Diff line change
Expand Up @@ -9,6 +9,10 @@
// "Success Criteria", ...) under different scenario parents. Allow
// duplicates when they are not siblings.
"MD024": { "siblings_only": true },
// README uses <details>/<summary> for collapsible per-host install
// blocks. Allow only those two elements; all other inline HTML stays
// flagged.
"MD033": { "allowed_elements": ["details", "summary"] },
// Table pipe spacing/alignment is cosmetic and varies across the repo's
// tables; not a useful signal (newer markdownlint only).
"MD060": false
Expand Down
10 changes: 6 additions & 4 deletions CLAUDE.md
Original file line number Diff line number Diff line change
Expand Up @@ -74,8 +74,9 @@ newer version, bump `source.ref` and the mirrored `version` in the manifest.
`description`, `version` (start at `0.1.0`), optional `category` /
`keywords`.
3. Add `plugins/<plugin>/CHANGELOG.md` (can be empty; CI prepends to it).
4. The manifest `version` must equal the SKILL.md `metadata.version`. CI
enforces this.
4. The manifest `version` must equal the SKILL.md `metadata.version`. If the
plugin ships a `.codex-plugin/plugin.json`, its `version` must match too.
CI enforces this.
5. Add `plugins/<plugin>/tests/baseline-scenarios.md` - **required**, CI
enforces it: at least one `## Scenario`, a `## Running These Tests`
protocol, and a `### Success Criteria` list. Copy the shape of
Expand Down Expand Up @@ -150,14 +151,15 @@ commits.

- bumps `plugins[].version` in `marketplace.json`,
- syncs that plugin's `SKILL.md` `metadata.version`,
- syncs that plugin's `.codex-plugin/plugin.json` `version` (if present),
- prepends an entry to `plugins/<plugin>/CHANGELOG.md`,
- tags `<plugin>-vX.Y.Z` and creates a GitHub Release.

The marketplace root `version` is the manifest schema version and is bumped
manually, not by CI.

**Never manually edit plugin version numbers** in the manifest or SKILL.md. CI
owns them. To force a release without a code change, push a scoped commit or run
**Never manually edit plugin version numbers** in the manifest, SKILL.md, or
`.codex-plugin/plugin.json`. CI owns them. To force a release without a code change, push a scoped commit or run
the workflow via `workflow_dispatch`.

> Note: inline-plugin tags are `<plugin>-vX.Y.Z` (scoped to this repo).
Expand Down
6 changes: 4 additions & 2 deletions CONTRIBUTING.md
Original file line number Diff line number Diff line change
Expand Up @@ -47,7 +47,8 @@ standards, and the per-plugin release model before contributing.
2. Add a `plugins[]` entry: `name`, `source: ./plugins/<plugin>`,
`description`, `version` (`0.1.0`), optional `category` / `keywords`.
3. `plugins/<plugin>/CHANGELOG.md` (may be empty; CI prepends to it).
4. The manifest `version` must equal the SKILL.md `metadata.version`. CI
4. The manifest `version` must equal the SKILL.md `metadata.version` (and the
`.codex-plugin/plugin.json` `version`, if the plugin ships one). CI
enforces this.
5. `plugins/<plugin>/tests/baseline-scenarios.md` is **required** and
CI-enforced (see Testing). It must contain at least one `## Scenario ...`,
Expand Down Expand Up @@ -117,7 +118,8 @@ example - copy its shape.
`validate.yml` runs on every PR touching `plugins/**` or `.claude-plugin/**`:
frontmatter, size, **inline plugin tests present** (baseline-scenarios.md with
scenarios + run protocol + success criteria), manifest validity, manifest <->
SKILL.md version sync, broken links, and markdown lint.
SKILL.md <-> `.codex-plugin/plugin.json` version sync, broken links, and
markdown lint.

Every step in **Validate Skill Files** is blocking - markdown lint included
(no `continue-on-error`). One red step fails the whole check.
Expand Down
Loading
Loading