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
10 changes: 10 additions & 0 deletions README.md
Original file line number Diff line number Diff line change
Expand Up @@ -31,6 +31,8 @@ pipx run codex-plugin-scanner verify .
min_score: 80
```

If your repository uses a Codex marketplace root like `.agents/plugins/marketplace.json`, keep `plugin_dir: "."`. The scanner will discover local `./plugins/...` entries automatically, scan each local plugin manifest, and skip remote marketplace entries instead of treating the repo root as a single plugin.

## Use After `$plugin-creator`

`codex-plugin-scanner` is designed as the quality gate between plugin creation and distribution:
Expand Down Expand Up @@ -120,13 +122,17 @@ codex-plugin-scanner ./my-plugin --cisco-skill-scan on --cisco-policy strict
# Summary scan (legacy form still works)
codex-plugin-scanner scan ./my-plugin --format json --profile public-marketplace

# Scan a multi-plugin repo from the marketplace root
codex-plugin-scanner scan . --format json

# Rule-oriented lint (with optional mechanical fixes)
codex-plugin-scanner lint ./my-plugin --list-rules
codex-plugin-scanner lint ./my-plugin --explain README_MISSING
codex-plugin-scanner lint ./my-plugin --fix --profile strict-security

# Runtime readiness verification
codex-plugin-scanner verify ./my-plugin --format json
codex-plugin-scanner verify . --format json
codex-plugin-scanner verify ./my-plugin --online --format text

# Artifact-backed submission gate
Expand All @@ -148,6 +154,8 @@ The scanner follows the current Codex plugin packaging conventions more closely:

`lint --fix` preserves or adds the documented `./` prefixes instead of stripping them away.

For repo-scoped marketplaces, `scan`, `lint`, `verify`, and `doctor` can target the repository root directly. `submit` remains intentionally single-plugin so the emitted artifact points at one concrete plugin package.

## Config + Baseline Example

```toml
Expand Down Expand Up @@ -252,6 +260,8 @@ jobs:
upload_sarif: true
```

For a multi-plugin repo, the same workflow can stay pointed at `plugin_dir: "."` as long as the repository has `.agents/plugins/marketplace.json` with local `./plugins/...` entries.

Local pre-commit style hook:

```yaml
Expand Down
24 changes: 14 additions & 10 deletions action/README.md
Original file line number Diff line number Diff line change
Expand Up @@ -8,18 +8,20 @@ This README is intentionally root-ready for a dedicated GitHub Marketplace actio

```yaml
- name: Scan Codex Plugin
uses: your-org/hol-codex-plugin-scanner-action@v1
uses: hashgraph-online/hol-codex-plugin-scanner-action@v1
with:
plugin_dir: "./my-plugin"
min_score: 70
fail_on_severity: high
```

If your repository exposes multiple plugins from `.agents/plugins/marketplace.json`, keep `plugin_dir: "."`. The action will discover local `./plugins/...` entries automatically, scan each local plugin, and skip remote marketplace entries.

## Inputs

| Input | Description | Default |
|-------|-------------|---------|
| `plugin_dir` | Path to the plugin directory to scan | `.` |
| `plugin_dir` | Path to a single plugin directory or a repo marketplace root | `.` |
| `mode` | Execution mode: `scan`, `lint`, `verify`, or `submit` | `scan` |
| `format` | Output format: `text`, `json`, `markdown`, `sarif` | `text` |
| `output` | Write report to this file path | `""` |
Expand Down Expand Up @@ -78,7 +80,7 @@ Mode notes:
### Basic scan with minimum score gate

```yaml
- uses: your-org/hol-codex-plugin-scanner-action@v1
- uses: hashgraph-online/hol-codex-plugin-scanner-action@v1
with:
plugin_dir: "."
min_score: 70
Expand All @@ -96,7 +98,7 @@ jobs:
runs-on: ubuntu-latest
steps:
- uses: actions/checkout@v6
- uses: your-org/hol-codex-plugin-scanner-action@v1
- uses: hashgraph-online/hol-codex-plugin-scanner-action@v1
with:
plugin_dir: "."
mode: scan
Expand All @@ -105,10 +107,12 @@ jobs:
upload_sarif: true
```

This `plugin_dir: "."` pattern is correct for both single-plugin repositories and multi-plugin marketplace repositories. When `.agents/plugins/marketplace.json` exists, the action switches into repository mode and scans each local plugin entry declared under `./plugins/...`.

### With Cisco skill scanning

```yaml
- uses: your-org/hol-codex-plugin-scanner-action@v1
- uses: hashgraph-online/hol-codex-plugin-scanner-action@v1
with:
plugin_dir: "."
cisco_skill_scan: on
Expand All @@ -120,7 +124,7 @@ The action installs the scanner with its published `cisco` extra enabled, so the
### Export registry payload for Codex ecosystem automation

```yaml
- uses: your-org/hol-codex-plugin-scanner-action@v1
- uses: hashgraph-online/hol-codex-plugin-scanner-action@v1
id: scan
with:
plugin_dir: "."
Expand Down Expand Up @@ -153,7 +157,7 @@ jobs:

- name: Scan plugin and submit if eligible
id: scan
uses: your-org/hol-codex-plugin-scanner-action@v1
uses: hashgraph-online/hol-codex-plugin-scanner-action@v1
with:
plugin_dir: "."
min_score: 80
Expand All @@ -172,7 +176,7 @@ Use a fine-grained token with `issues:write` on `hashgraph-online/awesome-codex-
### Markdown report as PR comment

```yaml
- uses: your-org/hol-codex-plugin-scanner-action@v1
- uses: hashgraph-online/hol-codex-plugin-scanner-action@v1
id: scan
with:
plugin_dir: "."
Expand Down Expand Up @@ -214,12 +218,12 @@ The source bundle for this action lives in the main scanner repository under `ac
Set `mode` to one of `scan`, `lint`, `verify`, or `submit`.

```yaml
- uses: your-org/hol-codex-plugin-scanner-action@v1
- uses: hashgraph-online/hol-codex-plugin-scanner-action@v1
with:
mode: verify
plugin_dir: "."
```

For `submit` mode, use `registry_payload_output` to control artifact path.
For `submit` mode, point `plugin_dir` at one concrete plugin directory. Repository-mode discovery is supported for `scan`, `lint`, and `verify`, but `submit` intentionally remains single-plugin.

For `scan` mode, set `upload_sarif: true` to emit and upload SARIF automatically instead of wiring a separate upload step by hand.
2 changes: 1 addition & 1 deletion action/action.yml
Original file line number Diff line number Diff line change
Expand Up @@ -8,7 +8,7 @@ inputs:
required: false
default: "scan"
plugin_dir:
description: "Path to the plugin directory to scan (default: repository root)"
description: "Path to a single plugin directory or a repo marketplace root (default: repository root)"
required: false
default: "."
format:
Expand Down
88 changes: 78 additions & 10 deletions schemas/scan-result.v1.json
Original file line number Diff line number Diff line change
Expand Up @@ -9,6 +9,7 @@
"profile",
"policy_pass",
"verify_pass",
"scope",
"score",
"raw_score",
"effective_score",
Expand Down Expand Up @@ -37,6 +38,10 @@
"verify_pass": {
"type": "boolean"
},
"scope": {
"type": "string",
"enum": ["plugin", "repository"]
},
"score": {
"type": "integer",
"minimum": 0,
Expand Down Expand Up @@ -95,6 +100,32 @@
"pluginDir": {
"type": "string",
"minLength": 1
},
"repository": {
"type": "object",
"additionalProperties": false,
"required": ["marketplaceFile", "localPluginCount"],
"properties": {
"marketplaceFile": {
"type": ["string", "null"]
},
"localPluginCount": {
"type": "integer",
"minimum": 0
}
}
},
"plugins": {
"type": "array",
"items": {
"$ref": "#/$defs/pluginSummary"
}
},
"skippedTargets": {
"type": "array",
"items": {
"$ref": "#/$defs/skippedTarget"
}
}
},
"$defs": {
Expand Down Expand Up @@ -145,16 +176,20 @@
}
},
"finding": {
"allOf": [
{"$ref": "#/$defs/findingRef"},
{
"type": "object",
"required": ["category"],
"properties": {
"category": {"type": "string", "minLength": 1}
}
}
]
"type": "object",
"additionalProperties": false,
"required": ["ruleId", "severity", "title", "description", "source", "category"],
"properties": {
"ruleId": {"type": "string", "minLength": 1},
"severity": {"$ref": "#/$defs/severity"},
"title": {"type": "string", "minLength": 1},
"description": {"type": "string", "minLength": 1},
"remediation": {"type": ["string", "null"]},
"filePath": {"type": ["string", "null"]},
"lineNumber": {"type": ["integer", "null"], "minimum": 1},
"source": {"type": "string", "minLength": 1},
"category": {"type": "string", "minLength": 1}
}
},
"check": {
"type": "object",
Expand Down Expand Up @@ -185,6 +220,39 @@
"items": {"$ref": "#/$defs/check"}
}
}
},
"pluginSummary": {
"type": "object",
"additionalProperties": false,
"required": ["name", "pluginDir", "score", "grade", "summary"],
"properties": {
"name": {"type": "string", "minLength": 1},
"pluginDir": {"type": "string", "minLength": 1},
"score": {"type": "integer", "minimum": 0, "maximum": 100},
"grade": {"type": "string", "enum": ["A", "B", "C", "D", "F"]},
"summary": {
"type": "object",
"additionalProperties": false,
"required": ["findings", "integrations"],
"properties": {
"findings": {"$ref": "#/$defs/severityCounts"},
"integrations": {
"type": "array",
"items": {"$ref": "#/$defs/integration"}
}
}
}
}
},
"skippedTarget": {
"type": "object",
"additionalProperties": false,
"required": ["name", "reason", "sourcePath"],
"properties": {
"name": {"type": "string", "minLength": 1},
"reason": {"type": "string", "minLength": 1},
"sourcePath": {"type": ["string", "null"]}
}
}
}
}
72 changes: 61 additions & 11 deletions schemas/verify-result.v1.json
Original file line number Diff line number Diff line change
Expand Up @@ -3,7 +3,7 @@
"title": "VerifyResultV1",
"type": "object",
"additionalProperties": false,
"required": ["verify_pass", "workspace", "cases"],
"required": ["verify_pass", "workspace", "scope", "cases"],
"properties": {
"verify_pass": {
"type": "boolean"
Expand All @@ -12,19 +12,69 @@
"type": "string",
"minLength": 1
},
"scope": {
"type": "string",
"enum": ["plugin", "repository"]
},
"repository": {
"type": "object",
"additionalProperties": false,
"required": ["marketplaceFile", "localPluginCount"],
"properties": {
"marketplaceFile": {"type": ["string", "null"]},
"localPluginCount": {"type": "integer", "minimum": 0}
}
},
"plugins": {
"type": "array",
"items": {
"$ref": "#/$defs/pluginVerifySummary"
}
},
"skippedTargets": {
"type": "array",
"items": {
"$ref": "#/$defs/skippedTarget"
}
},
"cases": {
"type": "array",
"items": {
"type": "object",
"additionalProperties": false,
"required": ["component", "name", "passed", "message", "classification"],
"properties": {
"component": {"type": "string", "minLength": 1},
"name": {"type": "string", "minLength": 1},
"passed": {"type": "boolean"},
"message": {"type": "string"},
"classification": {"type": "string", "minLength": 1}
}
"$ref": "#/$defs/case"
}
}
},
"$defs": {
"case": {
"type": "object",
"additionalProperties": false,
"required": ["component", "name", "passed", "message", "classification"],
"properties": {
"component": {"type": "string", "minLength": 1},
"name": {"type": "string", "minLength": 1},
"passed": {"type": "boolean"},
"message": {"type": "string"},
"classification": {"type": "string", "minLength": 1}
}
},
"pluginVerifySummary": {
"type": "object",
"additionalProperties": false,
"required": ["name", "workspace", "verify_pass"],
"properties": {
"name": {"type": ["string", "null"]},
"workspace": {"type": "string", "minLength": 1},
"verify_pass": {"type": "boolean"}
}
},
"skippedTarget": {
"type": "object",
"additionalProperties": false,
"required": ["name", "reason", "sourcePath"],
"properties": {
"name": {"type": "string", "minLength": 1},
"reason": {"type": "string", "minLength": 1},
"sourcePath": {"type": ["string", "null"]}
}
}
}
Expand Down
Loading
Loading