plugin-scanner 2.0.0__tar.gz → 2.0.2__tar.gz
This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
- plugin_scanner-2.0.2/.github/workflows/publish-action-repo.yml +206 -0
- {plugin_scanner-2.0.0 → plugin_scanner-2.0.2}/.github/workflows/publish.yml +1 -1
- {plugin_scanner-2.0.0 → plugin_scanner-2.0.2}/PKG-INFO +85 -26
- {plugin_scanner-2.0.0 → plugin_scanner-2.0.2}/README.md +83 -24
- plugin_scanner-2.0.2/action/README.legacy.md +25 -0
- {plugin_scanner-2.0.0 → plugin_scanner-2.0.2}/action/README.md +39 -27
- {plugin_scanner-2.0.0 → plugin_scanner-2.0.2}/action/action.yml +39 -12
- plugin_scanner-2.0.2/docs/guard/architecture.md +33 -0
- plugin_scanner-2.0.2/docs/guard/get-started.md +82 -0
- plugin_scanner-2.0.2/docs/guard/harness-support.md +22 -0
- plugin_scanner-2.0.2/docs/guard/local-vs-cloud.md +22 -0
- plugin_scanner-2.0.2/docs/guard/repo-boundaries.md +21 -0
- plugin_scanner-2.0.2/docs/guard/testing-matrix.md +32 -0
- {plugin_scanner-2.0.0 → plugin_scanner-2.0.2}/pyproject.toml +12 -2
- {plugin_scanner-2.0.0 → plugin_scanner-2.0.2}/src/codex_plugin_scanner/action_runner.py +29 -18
- {plugin_scanner-2.0.0 → plugin_scanner-2.0.2}/src/codex_plugin_scanner/cli.py +29 -3
- {plugin_scanner-2.0.0 → plugin_scanner-2.0.2}/src/codex_plugin_scanner/config.py +12 -5
- plugin_scanner-2.0.2/src/codex_plugin_scanner/guard/__init__.py +5 -0
- plugin_scanner-2.0.2/src/codex_plugin_scanner/guard/adapters/__init__.py +36 -0
- plugin_scanner-2.0.2/src/codex_plugin_scanner/guard/adapters/base.py +142 -0
- plugin_scanner-2.0.2/src/codex_plugin_scanner/guard/adapters/claude_code.py +199 -0
- plugin_scanner-2.0.2/src/codex_plugin_scanner/guard/adapters/codex.py +82 -0
- plugin_scanner-2.0.2/src/codex_plugin_scanner/guard/adapters/cursor.py +94 -0
- plugin_scanner-2.0.2/src/codex_plugin_scanner/guard/adapters/gemini.py +103 -0
- plugin_scanner-2.0.2/src/codex_plugin_scanner/guard/adapters/opencode.py +78 -0
- plugin_scanner-2.0.2/src/codex_plugin_scanner/guard/cli/__init__.py +5 -0
- plugin_scanner-2.0.2/src/codex_plugin_scanner/guard/cli/commands.py +425 -0
- plugin_scanner-2.0.2/src/codex_plugin_scanner/guard/cli/product.py +189 -0
- plugin_scanner-2.0.2/src/codex_plugin_scanner/guard/cli/prompt.py +342 -0
- plugin_scanner-2.0.2/src/codex_plugin_scanner/guard/cli/render.py +503 -0
- plugin_scanner-2.0.2/src/codex_plugin_scanner/guard/config.py +76 -0
- plugin_scanner-2.0.2/src/codex_plugin_scanner/guard/consumer/__init__.py +5 -0
- plugin_scanner-2.0.2/src/codex_plugin_scanner/guard/consumer/service.py +257 -0
- plugin_scanner-2.0.2/src/codex_plugin_scanner/guard/daemon/__init__.py +5 -0
- plugin_scanner-2.0.2/src/codex_plugin_scanner/guard/daemon/server.py +67 -0
- plugin_scanner-2.0.2/src/codex_plugin_scanner/guard/models.py +121 -0
- plugin_scanner-2.0.2/src/codex_plugin_scanner/guard/policy/__init__.py +5 -0
- plugin_scanner-2.0.2/src/codex_plugin_scanner/guard/policy/engine.py +31 -0
- plugin_scanner-2.0.2/src/codex_plugin_scanner/guard/proxy/__init__.py +6 -0
- plugin_scanner-2.0.2/src/codex_plugin_scanner/guard/proxy/remote.py +50 -0
- plugin_scanner-2.0.2/src/codex_plugin_scanner/guard/proxy/stdio.py +125 -0
- plugin_scanner-2.0.2/src/codex_plugin_scanner/guard/receipts/__init__.py +5 -0
- plugin_scanner-2.0.2/src/codex_plugin_scanner/guard/receipts/manager.py +36 -0
- plugin_scanner-2.0.2/src/codex_plugin_scanner/guard/runtime/__init__.py +5 -0
- plugin_scanner-2.0.2/src/codex_plugin_scanner/guard/runtime/runner.py +84 -0
- plugin_scanner-2.0.2/src/codex_plugin_scanner/guard/schemas/__init__.py +5 -0
- plugin_scanner-2.0.2/src/codex_plugin_scanner/guard/schemas/consumer_mode.py +71 -0
- plugin_scanner-2.0.2/src/codex_plugin_scanner/guard/shims.py +95 -0
- plugin_scanner-2.0.2/src/codex_plugin_scanner/guard/store.py +420 -0
- {plugin_scanner-2.0.0 → plugin_scanner-2.0.2}/src/codex_plugin_scanner/version.py +1 -1
- {plugin_scanner-2.0.0 → plugin_scanner-2.0.2}/tests/test_action_bundle.py +70 -17
- {plugin_scanner-2.0.0 → plugin_scanner-2.0.2}/tests/test_action_runner.py +46 -1
- {plugin_scanner-2.0.0 → plugin_scanner-2.0.2}/tests/test_config.py +39 -2
- plugin_scanner-2.0.2/tests/test_guard_cli.py +1039 -0
- plugin_scanner-2.0.2/tests/test_guard_launch_env.py +78 -0
- plugin_scanner-2.0.2/tests/test_guard_product_flow.py +272 -0
- plugin_scanner-2.0.2/tests/test_guard_runtime.py +627 -0
- plugin_scanner-2.0.0/.github/workflows/publish-action-repo.yml +0 -169
- {plugin_scanner-2.0.0 → plugin_scanner-2.0.2}/.clusterfuzzlite/Dockerfile +0 -0
- {plugin_scanner-2.0.0 → plugin_scanner-2.0.2}/.clusterfuzzlite/build.sh +0 -0
- {plugin_scanner-2.0.0 → plugin_scanner-2.0.2}/.clusterfuzzlite/project.yaml +0 -0
- {plugin_scanner-2.0.0 → plugin_scanner-2.0.2}/.clusterfuzzlite/requirements-atheris.txt +0 -0
- {plugin_scanner-2.0.0 → plugin_scanner-2.0.2}/.dockerignore +0 -0
- {plugin_scanner-2.0.0 → plugin_scanner-2.0.2}/.github/CODEOWNERS +0 -0
- {plugin_scanner-2.0.0 → plugin_scanner-2.0.2}/.github/dependabot.yml +0 -0
- {plugin_scanner-2.0.0 → plugin_scanner-2.0.2}/.github/workflows/ci.yml +0 -0
- {plugin_scanner-2.0.0 → plugin_scanner-2.0.2}/.github/workflows/codeql.yml +0 -0
- {plugin_scanner-2.0.0 → plugin_scanner-2.0.2}/.github/workflows/e2e-test.yml +0 -0
- {plugin_scanner-2.0.0 → plugin_scanner-2.0.2}/.github/workflows/fuzz.yml +0 -0
- {plugin_scanner-2.0.0 → plugin_scanner-2.0.2}/.github/workflows/scorecard.yml +0 -0
- {plugin_scanner-2.0.0 → plugin_scanner-2.0.2}/.gitignore +0 -0
- {plugin_scanner-2.0.0 → plugin_scanner-2.0.2}/.pre-commit-hooks.yaml +0 -0
- {plugin_scanner-2.0.0 → plugin_scanner-2.0.2}/CONTRIBUTING.md +0 -0
- {plugin_scanner-2.0.0 → plugin_scanner-2.0.2}/Dockerfile +0 -0
- {plugin_scanner-2.0.0 → plugin_scanner-2.0.2}/LICENSE +0 -0
- {plugin_scanner-2.0.0 → plugin_scanner-2.0.2}/SECURITY.md +0 -0
- {plugin_scanner-2.0.0 → plugin_scanner-2.0.2}/action/cisco-version.txt +0 -0
- {plugin_scanner-2.0.0 → plugin_scanner-2.0.2}/action/pypi-attestations-version.txt +0 -0
- {plugin_scanner-2.0.0 → plugin_scanner-2.0.2}/action/scanner-version.txt +0 -0
- {plugin_scanner-2.0.0 → plugin_scanner-2.0.2}/docker-requirements.txt +0 -0
- {plugin_scanner-2.0.0 → plugin_scanner-2.0.2}/docs/trust/mcp-trust-draft.md +0 -0
- {plugin_scanner-2.0.0 → plugin_scanner-2.0.2}/docs/trust/plugin-trust-draft.md +0 -0
- {plugin_scanner-2.0.0 → plugin_scanner-2.0.2}/docs/trust/skill-trust-local.md +0 -0
- {plugin_scanner-2.0.0 → plugin_scanner-2.0.2}/fuzzers/manifest_fuzzer.py +0 -0
- {plugin_scanner-2.0.0 → plugin_scanner-2.0.2}/schemas/plugin-quality.v1.json +0 -0
- {plugin_scanner-2.0.0 → plugin_scanner-2.0.2}/schemas/scan-result.v1.json +0 -0
- {plugin_scanner-2.0.0 → plugin_scanner-2.0.2}/schemas/verify-result.v1.json +0 -0
- {plugin_scanner-2.0.0 → plugin_scanner-2.0.2}/src/codex_plugin_scanner/__init__.py +0 -0
- {plugin_scanner-2.0.0 → plugin_scanner-2.0.2}/src/codex_plugin_scanner/checks/__init__.py +0 -0
- {plugin_scanner-2.0.0 → plugin_scanner-2.0.2}/src/codex_plugin_scanner/checks/best_practices.py +0 -0
- {plugin_scanner-2.0.0 → plugin_scanner-2.0.2}/src/codex_plugin_scanner/checks/claude.py +0 -0
- {plugin_scanner-2.0.0 → plugin_scanner-2.0.2}/src/codex_plugin_scanner/checks/code_quality.py +0 -0
- {plugin_scanner-2.0.0 → plugin_scanner-2.0.2}/src/codex_plugin_scanner/checks/ecosystem_common.py +0 -0
- {plugin_scanner-2.0.0 → plugin_scanner-2.0.2}/src/codex_plugin_scanner/checks/gemini.py +0 -0
- {plugin_scanner-2.0.0 → plugin_scanner-2.0.2}/src/codex_plugin_scanner/checks/manifest.py +0 -0
- {plugin_scanner-2.0.0 → plugin_scanner-2.0.2}/src/codex_plugin_scanner/checks/manifest_support.py +0 -0
- {plugin_scanner-2.0.0 → plugin_scanner-2.0.2}/src/codex_plugin_scanner/checks/marketplace.py +0 -0
- {plugin_scanner-2.0.0 → plugin_scanner-2.0.2}/src/codex_plugin_scanner/checks/opencode.py +0 -0
- {plugin_scanner-2.0.0 → plugin_scanner-2.0.2}/src/codex_plugin_scanner/checks/operational_security.py +0 -0
- {plugin_scanner-2.0.0 → plugin_scanner-2.0.2}/src/codex_plugin_scanner/checks/security.py +0 -0
- {plugin_scanner-2.0.0 → plugin_scanner-2.0.2}/src/codex_plugin_scanner/checks/skill_security.py +0 -0
- {plugin_scanner-2.0.0 → plugin_scanner-2.0.2}/src/codex_plugin_scanner/ecosystems/__init__.py +0 -0
- {plugin_scanner-2.0.0 → plugin_scanner-2.0.2}/src/codex_plugin_scanner/ecosystems/base.py +0 -0
- {plugin_scanner-2.0.0 → plugin_scanner-2.0.2}/src/codex_plugin_scanner/ecosystems/claude.py +0 -0
- {plugin_scanner-2.0.0 → plugin_scanner-2.0.2}/src/codex_plugin_scanner/ecosystems/codex.py +0 -0
- {plugin_scanner-2.0.0 → plugin_scanner-2.0.2}/src/codex_plugin_scanner/ecosystems/detect.py +0 -0
- {plugin_scanner-2.0.0 → plugin_scanner-2.0.2}/src/codex_plugin_scanner/ecosystems/gemini.py +0 -0
- {plugin_scanner-2.0.0 → plugin_scanner-2.0.2}/src/codex_plugin_scanner/ecosystems/opencode.py +0 -0
- {plugin_scanner-2.0.0 → plugin_scanner-2.0.2}/src/codex_plugin_scanner/ecosystems/registry.py +0 -0
- {plugin_scanner-2.0.0 → plugin_scanner-2.0.2}/src/codex_plugin_scanner/ecosystems/types.py +0 -0
- {plugin_scanner-2.0.0 → plugin_scanner-2.0.2}/src/codex_plugin_scanner/integrations/__init__.py +0 -0
- {plugin_scanner-2.0.0 → plugin_scanner-2.0.2}/src/codex_plugin_scanner/integrations/cisco_skill_scanner.py +0 -0
- {plugin_scanner-2.0.0 → plugin_scanner-2.0.2}/src/codex_plugin_scanner/lint_fixes.py +0 -0
- {plugin_scanner-2.0.0 → plugin_scanner-2.0.2}/src/codex_plugin_scanner/marketplace_support.py +0 -0
- {plugin_scanner-2.0.0 → plugin_scanner-2.0.2}/src/codex_plugin_scanner/models.py +0 -0
- {plugin_scanner-2.0.0 → plugin_scanner-2.0.2}/src/codex_plugin_scanner/path_support.py +0 -0
- {plugin_scanner-2.0.0 → plugin_scanner-2.0.2}/src/codex_plugin_scanner/policy.py +0 -0
- {plugin_scanner-2.0.0 → plugin_scanner-2.0.2}/src/codex_plugin_scanner/quality_artifact.py +0 -0
- {plugin_scanner-2.0.0 → plugin_scanner-2.0.2}/src/codex_plugin_scanner/repo_detect.py +0 -0
- {plugin_scanner-2.0.0 → plugin_scanner-2.0.2}/src/codex_plugin_scanner/reporting.py +0 -0
- {plugin_scanner-2.0.0 → plugin_scanner-2.0.2}/src/codex_plugin_scanner/rules/__init__.py +0 -0
- {plugin_scanner-2.0.0 → plugin_scanner-2.0.2}/src/codex_plugin_scanner/rules/registry.py +0 -0
- {plugin_scanner-2.0.0 → plugin_scanner-2.0.2}/src/codex_plugin_scanner/rules/specs.py +0 -0
- {plugin_scanner-2.0.0 → plugin_scanner-2.0.2}/src/codex_plugin_scanner/scanner.py +0 -0
- {plugin_scanner-2.0.0 → plugin_scanner-2.0.2}/src/codex_plugin_scanner/submission.py +0 -0
- {plugin_scanner-2.0.0 → plugin_scanner-2.0.2}/src/codex_plugin_scanner/suppressions.py +0 -0
- {plugin_scanner-2.0.0 → plugin_scanner-2.0.2}/src/codex_plugin_scanner/trust_domain_scoring.py +0 -0
- {plugin_scanner-2.0.0 → plugin_scanner-2.0.2}/src/codex_plugin_scanner/trust_helpers.py +0 -0
- {plugin_scanner-2.0.0 → plugin_scanner-2.0.2}/src/codex_plugin_scanner/trust_mcp_scoring.py +0 -0
- {plugin_scanner-2.0.0 → plugin_scanner-2.0.2}/src/codex_plugin_scanner/trust_models.py +0 -0
- {plugin_scanner-2.0.0 → plugin_scanner-2.0.2}/src/codex_plugin_scanner/trust_plugin_scoring.py +0 -0
- {plugin_scanner-2.0.0 → plugin_scanner-2.0.2}/src/codex_plugin_scanner/trust_scoring.py +0 -0
- {plugin_scanner-2.0.0 → plugin_scanner-2.0.2}/src/codex_plugin_scanner/trust_skill_scoring.py +0 -0
- {plugin_scanner-2.0.0 → plugin_scanner-2.0.2}/src/codex_plugin_scanner/trust_specs.py +0 -0
- {plugin_scanner-2.0.0 → plugin_scanner-2.0.2}/src/codex_plugin_scanner/verification.py +0 -0
- {plugin_scanner-2.0.0 → plugin_scanner-2.0.2}/tests/__init__.py +0 -0
- {plugin_scanner-2.0.0 → plugin_scanner-2.0.2}/tests/fixtures/__init__.py +0 -0
- {plugin_scanner-2.0.0 → plugin_scanner-2.0.2}/tests/fixtures/bad-plugin/.codex-plugin/plugin.json +0 -0
- {plugin_scanner-2.0.0 → plugin_scanner-2.0.2}/tests/fixtures/bad-plugin/.mcp.json +0 -0
- {plugin_scanner-2.0.0 → plugin_scanner-2.0.2}/tests/fixtures/bad-plugin/secrets.js +0 -0
- {plugin_scanner-2.0.0 → plugin_scanner-2.0.2}/tests/fixtures/claude-plugin-good/.claude-plugin/plugin.json +0 -0
- {plugin_scanner-2.0.0 → plugin_scanner-2.0.2}/tests/fixtures/claude-plugin-good/LICENSE +0 -0
- {plugin_scanner-2.0.0 → plugin_scanner-2.0.2}/tests/fixtures/claude-plugin-good/README.md +0 -0
- {plugin_scanner-2.0.0 → plugin_scanner-2.0.2}/tests/fixtures/claude-plugin-good/SECURITY.md +0 -0
- {plugin_scanner-2.0.0 → plugin_scanner-2.0.2}/tests/fixtures/claude-plugin-good/hooks/hooks.json +0 -0
- {plugin_scanner-2.0.0 → plugin_scanner-2.0.2}/tests/fixtures/claude-plugin-good/skills/example/SKILL.md +0 -0
- {plugin_scanner-2.0.0 → plugin_scanner-2.0.2}/tests/fixtures/code-quality-bad/evil.js +0 -0
- {plugin_scanner-2.0.0 → plugin_scanner-2.0.2}/tests/fixtures/code-quality-bad/inject.js +0 -0
- {plugin_scanner-2.0.0 → plugin_scanner-2.0.2}/tests/fixtures/gemini-extension-good/GEMINI.md +0 -0
- {plugin_scanner-2.0.0 → plugin_scanner-2.0.2}/tests/fixtures/gemini-extension-good/LICENSE +0 -0
- {plugin_scanner-2.0.0 → plugin_scanner-2.0.2}/tests/fixtures/gemini-extension-good/README.md +0 -0
- {plugin_scanner-2.0.0 → plugin_scanner-2.0.2}/tests/fixtures/gemini-extension-good/SECURITY.md +0 -0
- {plugin_scanner-2.0.0 → plugin_scanner-2.0.2}/tests/fixtures/gemini-extension-good/commands/hello.toml +0 -0
- {plugin_scanner-2.0.0 → plugin_scanner-2.0.2}/tests/fixtures/gemini-extension-good/gemini-extension.json +0 -0
- {plugin_scanner-2.0.0 → plugin_scanner-2.0.2}/tests/fixtures/good-plugin/.codex-plugin/plugin.json +0 -0
- {plugin_scanner-2.0.0 → plugin_scanner-2.0.2}/tests/fixtures/good-plugin/.codexignore +0 -0
- {plugin_scanner-2.0.0 → plugin_scanner-2.0.2}/tests/fixtures/good-plugin/LICENSE +0 -0
- {plugin_scanner-2.0.0 → plugin_scanner-2.0.2}/tests/fixtures/good-plugin/README.md +0 -0
- {plugin_scanner-2.0.0 → plugin_scanner-2.0.2}/tests/fixtures/good-plugin/SECURITY.md +0 -0
- {plugin_scanner-2.0.0 → plugin_scanner-2.0.2}/tests/fixtures/good-plugin/assets/icon.svg +0 -0
- {plugin_scanner-2.0.0 → plugin_scanner-2.0.2}/tests/fixtures/good-plugin/assets/logo.svg +0 -0
- {plugin_scanner-2.0.0 → plugin_scanner-2.0.2}/tests/fixtures/good-plugin/assets/screenshot.svg +0 -0
- {plugin_scanner-2.0.0 → plugin_scanner-2.0.2}/tests/fixtures/good-plugin/skills/example/SKILL.md +0 -0
- {plugin_scanner-2.0.0 → plugin_scanner-2.0.2}/tests/fixtures/malformed-json/.codex-plugin/plugin.json +0 -0
- {plugin_scanner-2.0.0 → plugin_scanner-2.0.2}/tests/fixtures/minimal-plugin/.codex-plugin/plugin.json +0 -0
- {plugin_scanner-2.0.0 → plugin_scanner-2.0.2}/tests/fixtures/missing-fields/.codex-plugin/plugin.json +0 -0
- {plugin_scanner-2.0.0 → plugin_scanner-2.0.2}/tests/fixtures/mit-license/LICENSE +0 -0
- {plugin_scanner-2.0.0 → plugin_scanner-2.0.2}/tests/fixtures/multi-ecosystem-repo/codex-plugin/.codex-plugin/plugin.json +0 -0
- {plugin_scanner-2.0.0 → plugin_scanner-2.0.2}/tests/fixtures/multi-ecosystem-repo/codex-plugin/LICENSE +0 -0
- {plugin_scanner-2.0.0 → plugin_scanner-2.0.2}/tests/fixtures/multi-ecosystem-repo/codex-plugin/README.md +0 -0
- {plugin_scanner-2.0.0 → plugin_scanner-2.0.2}/tests/fixtures/multi-ecosystem-repo/codex-plugin/SECURITY.md +0 -0
- {plugin_scanner-2.0.0 → plugin_scanner-2.0.2}/tests/fixtures/multi-ecosystem-repo/gemini-ext/README.md +0 -0
- {plugin_scanner-2.0.0 → plugin_scanner-2.0.2}/tests/fixtures/multi-ecosystem-repo/gemini-ext/gemini-extension.json +0 -0
- {plugin_scanner-2.0.0 → plugin_scanner-2.0.2}/tests/fixtures/multi-plugin-repo/.agents/plugins/marketplace.json +0 -0
- {plugin_scanner-2.0.0 → plugin_scanner-2.0.2}/tests/fixtures/multi-plugin-repo/plugins/alpha-plugin/.codex-plugin/plugin.json +0 -0
- {plugin_scanner-2.0.0 → plugin_scanner-2.0.2}/tests/fixtures/multi-plugin-repo/plugins/alpha-plugin/.codexignore +0 -0
- {plugin_scanner-2.0.0 → plugin_scanner-2.0.2}/tests/fixtures/multi-plugin-repo/plugins/alpha-plugin/LICENSE +0 -0
- {plugin_scanner-2.0.0 → plugin_scanner-2.0.2}/tests/fixtures/multi-plugin-repo/plugins/alpha-plugin/README.md +0 -0
- {plugin_scanner-2.0.0 → plugin_scanner-2.0.2}/tests/fixtures/multi-plugin-repo/plugins/alpha-plugin/SECURITY.md +0 -0
- {plugin_scanner-2.0.0 → plugin_scanner-2.0.2}/tests/fixtures/multi-plugin-repo/plugins/alpha-plugin/skills/example/SKILL.md +0 -0
- {plugin_scanner-2.0.0 → plugin_scanner-2.0.2}/tests/fixtures/multi-plugin-repo/plugins/beta-plugin/.codex-plugin/plugin.json +0 -0
- {plugin_scanner-2.0.0 → plugin_scanner-2.0.2}/tests/fixtures/multi-plugin-repo/plugins/beta-plugin/skills/example/SKILL.md +0 -0
- {plugin_scanner-2.0.0 → plugin_scanner-2.0.2}/tests/fixtures/no-version/.codex-plugin/plugin.json +0 -0
- {plugin_scanner-2.0.0 → plugin_scanner-2.0.2}/tests/fixtures/opencode-good/.opencode/commands/hello.md +0 -0
- {plugin_scanner-2.0.0 → plugin_scanner-2.0.2}/tests/fixtures/opencode-good/.opencode/plugins/example.ts +0 -0
- {plugin_scanner-2.0.0 → plugin_scanner-2.0.2}/tests/fixtures/opencode-good/LICENSE +0 -0
- {plugin_scanner-2.0.0 → plugin_scanner-2.0.2}/tests/fixtures/opencode-good/README.md +0 -0
- {plugin_scanner-2.0.0 → plugin_scanner-2.0.2}/tests/fixtures/opencode-good/SECURITY.md +0 -0
- {plugin_scanner-2.0.0 → plugin_scanner-2.0.2}/tests/fixtures/opencode-good/opencode.jsonc +0 -0
- {plugin_scanner-2.0.0 → plugin_scanner-2.0.2}/tests/fixtures/skills-missing-dir/.codex-plugin/plugin.json +0 -0
- {plugin_scanner-2.0.0 → plugin_scanner-2.0.2}/tests/fixtures/skills-no-frontmatter/.codex-plugin/plugin.json +0 -0
- {plugin_scanner-2.0.0 → plugin_scanner-2.0.2}/tests/fixtures/skills-no-frontmatter/skills/bad-skill/SKILL.md +0 -0
- {plugin_scanner-2.0.0 → plugin_scanner-2.0.2}/tests/fixtures/with-marketplace/.codex-plugin/plugin.json +0 -0
- {plugin_scanner-2.0.0 → plugin_scanner-2.0.2}/tests/fixtures/with-marketplace/marketplace-broken.json +0 -0
- {plugin_scanner-2.0.0 → plugin_scanner-2.0.2}/tests/fixtures/with-marketplace/marketplace.json +0 -0
- {plugin_scanner-2.0.0 → plugin_scanner-2.0.2}/tests/test-trust-scoring.py +0 -0
- {plugin_scanner-2.0.0 → plugin_scanner-2.0.2}/tests/test-trust-specs.py +0 -0
- {plugin_scanner-2.0.0 → plugin_scanner-2.0.2}/tests/test_best_practices.py +0 -0
- {plugin_scanner-2.0.0 → plugin_scanner-2.0.2}/tests/test_cli.py +0 -0
- {plugin_scanner-2.0.0 → plugin_scanner-2.0.2}/tests/test_code_quality.py +0 -0
- {plugin_scanner-2.0.0 → plugin_scanner-2.0.2}/tests/test_coverage_remaining.py +0 -0
- {plugin_scanner-2.0.0 → plugin_scanner-2.0.2}/tests/test_ecosystems.py +0 -0
- {plugin_scanner-2.0.0 → plugin_scanner-2.0.2}/tests/test_edge_cases.py +0 -0
- {plugin_scanner-2.0.0 → plugin_scanner-2.0.2}/tests/test_final_coverage.py +0 -0
- {plugin_scanner-2.0.0 → plugin_scanner-2.0.2}/tests/test_integration.py +0 -0
- {plugin_scanner-2.0.0 → plugin_scanner-2.0.2}/tests/test_lint_fixes.py +0 -0
- {plugin_scanner-2.0.0 → plugin_scanner-2.0.2}/tests/test_live_cisco_smoke.py +0 -0
- {plugin_scanner-2.0.0 → plugin_scanner-2.0.2}/tests/test_manifest.py +0 -0
- {plugin_scanner-2.0.0 → plugin_scanner-2.0.2}/tests/test_marketplace.py +0 -0
- {plugin_scanner-2.0.0 → plugin_scanner-2.0.2}/tests/test_operational_security.py +0 -0
- {plugin_scanner-2.0.0 → plugin_scanner-2.0.2}/tests/test_policy.py +0 -0
- {plugin_scanner-2.0.0 → plugin_scanner-2.0.2}/tests/test_quality_artifact.py +0 -0
- {plugin_scanner-2.0.0 → plugin_scanner-2.0.2}/tests/test_rule_registry.py +0 -0
- {plugin_scanner-2.0.0 → plugin_scanner-2.0.2}/tests/test_scanner.py +0 -0
- {plugin_scanner-2.0.0 → plugin_scanner-2.0.2}/tests/test_schema_contracts.py +0 -0
- {plugin_scanner-2.0.0 → plugin_scanner-2.0.2}/tests/test_security.py +0 -0
- {plugin_scanner-2.0.0 → plugin_scanner-2.0.2}/tests/test_security_ops.py +0 -0
- {plugin_scanner-2.0.0 → plugin_scanner-2.0.2}/tests/test_skill_security.py +0 -0
- {plugin_scanner-2.0.0 → plugin_scanner-2.0.2}/tests/test_submission.py +0 -0
- {plugin_scanner-2.0.0 → plugin_scanner-2.0.2}/tests/test_trust_scoring.py +0 -0
- {plugin_scanner-2.0.0 → plugin_scanner-2.0.2}/tests/test_trust_specs.py +0 -0
- {plugin_scanner-2.0.0 → plugin_scanner-2.0.2}/tests/test_verification.py +0 -0
- {plugin_scanner-2.0.0 → plugin_scanner-2.0.2}/tests/test_versioning.py +0 -0
- {plugin_scanner-2.0.0 → plugin_scanner-2.0.2}/uv.lock +0 -0
|
@@ -0,0 +1,206 @@
|
|
|
1
|
+
name: Publish GitHub Action Repository
|
|
2
|
+
|
|
3
|
+
on:
|
|
4
|
+
workflow_dispatch:
|
|
5
|
+
push:
|
|
6
|
+
branches:
|
|
7
|
+
- main
|
|
8
|
+
|
|
9
|
+
permissions:
|
|
10
|
+
contents: read
|
|
11
|
+
|
|
12
|
+
concurrency:
|
|
13
|
+
group: ai-plugin-scanner-action-repo-${{ github.ref }}
|
|
14
|
+
cancel-in-progress: false
|
|
15
|
+
|
|
16
|
+
jobs:
|
|
17
|
+
publish-action-repo:
|
|
18
|
+
name: Sync action repo + publish release notes
|
|
19
|
+
runs-on: ubuntu-latest
|
|
20
|
+
permissions:
|
|
21
|
+
contents: read
|
|
22
|
+
env:
|
|
23
|
+
ACTION_CANONICAL_REPOSITORY: ${{ vars.ACTION_CANONICAL_REPOSITORY != '' && vars.ACTION_CANONICAL_REPOSITORY || 'hashgraph-online/ai-plugin-scanner-action' }}
|
|
24
|
+
ACTION_COMPAT_REPOSITORY: ${{ vars.ACTION_COMPAT_REPOSITORY != '' && vars.ACTION_COMPAT_REPOSITORY || 'hashgraph-online/hol-codex-plugin-scanner-action' }}
|
|
25
|
+
SOURCE_REF: ${{ github.sha }}
|
|
26
|
+
SOURCE_REPOSITORY: ${{ github.repository }}
|
|
27
|
+
SOURCE_SERVER_URL: ${{ github.server_url }}
|
|
28
|
+
steps:
|
|
29
|
+
- name: Validate publication credentials
|
|
30
|
+
env:
|
|
31
|
+
ACTION_REPO_TOKEN: ${{ secrets.ACTION_REPO_TOKEN }}
|
|
32
|
+
run: |
|
|
33
|
+
if [ -z "$ACTION_REPO_TOKEN" ]; then
|
|
34
|
+
echo "ACTION_REPO_TOKEN must be configured to publish the Marketplace action repository." >&2
|
|
35
|
+
exit 1
|
|
36
|
+
fi
|
|
37
|
+
|
|
38
|
+
- name: Checkout source repository
|
|
39
|
+
uses: actions/checkout@de0fac2e4500dabe0009e67214ff5f5447ce83dd
|
|
40
|
+
with:
|
|
41
|
+
fetch-depth: 0
|
|
42
|
+
|
|
43
|
+
- name: Compute next action release tag
|
|
44
|
+
id: version
|
|
45
|
+
env:
|
|
46
|
+
GH_TOKEN: ${{ secrets.ACTION_REPO_TOKEN }}
|
|
47
|
+
run: |
|
|
48
|
+
latest_release_tag() {
|
|
49
|
+
target_repo="$1"
|
|
50
|
+
if ! gh repo view "$target_repo" >/dev/null 2>&1; then
|
|
51
|
+
return
|
|
52
|
+
fi
|
|
53
|
+
gh release list --repo "$target_repo" --limit 1 --json tagName --jq '.[0].tagName // ""'
|
|
54
|
+
}
|
|
55
|
+
|
|
56
|
+
latest_remote_tag() {
|
|
57
|
+
target_repo="$1"
|
|
58
|
+
if ! gh repo view "$target_repo" >/dev/null 2>&1; then
|
|
59
|
+
return
|
|
60
|
+
fi
|
|
61
|
+
git ls-remote --tags --refs "https://x-access-token:${GH_TOKEN}@github.com/${target_repo}.git" "refs/tags/v*" \
|
|
62
|
+
| awk -F'/' '{print $3}' \
|
|
63
|
+
| sort -V \
|
|
64
|
+
| tail -n1
|
|
65
|
+
}
|
|
66
|
+
|
|
67
|
+
LAST_TAG=""
|
|
68
|
+
for candidate in \
|
|
69
|
+
"$(latest_release_tag "$ACTION_CANONICAL_REPOSITORY")" \
|
|
70
|
+
"$(latest_release_tag "$ACTION_COMPAT_REPOSITORY")" \
|
|
71
|
+
"$(latest_remote_tag "$ACTION_CANONICAL_REPOSITORY")" \
|
|
72
|
+
"$(latest_remote_tag "$ACTION_COMPAT_REPOSITORY")"; do
|
|
73
|
+
if [ -z "$candidate" ]; then
|
|
74
|
+
continue
|
|
75
|
+
fi
|
|
76
|
+
if [ -z "$LAST_TAG" ] || [ "$(printf '%s\n%s\n' "$LAST_TAG" "$candidate" | sort -V | tail -n1)" = "$candidate" ]; then
|
|
77
|
+
LAST_TAG="$candidate"
|
|
78
|
+
fi
|
|
79
|
+
done
|
|
80
|
+
|
|
81
|
+
if [ -z "$LAST_TAG" ]; then
|
|
82
|
+
TAG="v1.0.0"
|
|
83
|
+
else
|
|
84
|
+
IFS=. read -r MAJOR MINOR PATCH <<< "${LAST_TAG#v}"
|
|
85
|
+
if [ -z "$MAJOR" ] || [ -z "$MINOR" ] || [ -z "$PATCH" ]; then
|
|
86
|
+
echo "Unsupported release tag format: $LAST_TAG" >&2
|
|
87
|
+
exit 1
|
|
88
|
+
fi
|
|
89
|
+
TAG="v${MAJOR}.${MINOR}.$((PATCH + 1))"
|
|
90
|
+
fi
|
|
91
|
+
|
|
92
|
+
echo "tag=$TAG" >> "$GITHUB_OUTPUT"
|
|
93
|
+
|
|
94
|
+
- name: Compute scanner package version
|
|
95
|
+
id: scanner_version
|
|
96
|
+
env:
|
|
97
|
+
GITHUB_REF: ${{ github.ref }}
|
|
98
|
+
GITHUB_EVENT_NAME: ${{ github.event_name }}
|
|
99
|
+
run: |
|
|
100
|
+
BASE_VERSION=$(python3 -c "import tomllib; p=tomllib.load(open('pyproject.toml','rb')); print(p['project']['version'])")
|
|
101
|
+
VERSION="$BASE_VERSION"
|
|
102
|
+
if [[ "$GITHUB_REF" == refs/tags/v* ]]; then
|
|
103
|
+
VERSION="${GITHUB_REF#refs/tags/v}"
|
|
104
|
+
elif [[ "$GITHUB_EVENT_NAME" == "push" && "$GITHUB_REF" == "refs/heads/main" ]]; then
|
|
105
|
+
LAST_TAG=$(git tag --list 'v*' --sort=-version:refname | head -n1)
|
|
106
|
+
if [[ -n "$LAST_TAG" ]]; then
|
|
107
|
+
IFS=. read -r MAJOR MINOR PATCH <<< "${LAST_TAG#v}"
|
|
108
|
+
if [[ -z "$MAJOR" || -z "$MINOR" || -z "$PATCH" ]]; then
|
|
109
|
+
echo "Unsupported release tag format: $LAST_TAG" >&2
|
|
110
|
+
exit 1
|
|
111
|
+
fi
|
|
112
|
+
VERSION="${MAJOR}.${MINOR}.$((PATCH + 1))"
|
|
113
|
+
fi
|
|
114
|
+
fi
|
|
115
|
+
echo "version=$VERSION" >> "$GITHUB_OUTPUT"
|
|
116
|
+
|
|
117
|
+
- name: Sync canonical and compatibility action repositories
|
|
118
|
+
env:
|
|
119
|
+
ACTION_REPO_TOKEN: ${{ secrets.ACTION_REPO_TOKEN }}
|
|
120
|
+
GH_TOKEN: ${{ secrets.ACTION_REPO_TOKEN }}
|
|
121
|
+
TAG: ${{ steps.version.outputs.tag }}
|
|
122
|
+
SCANNER_VERSION: ${{ steps.scanner_version.outputs.version }}
|
|
123
|
+
run: |
|
|
124
|
+
any_repo_changed="false"
|
|
125
|
+
|
|
126
|
+
publish_action_release() {
|
|
127
|
+
target_repo="$1"
|
|
128
|
+
repo_dir="$2"
|
|
129
|
+
|
|
130
|
+
git -C "$repo_dir" tag -fa v1 -m "Update floating major tag to ${TAG}"
|
|
131
|
+
if git -C "$repo_dir" ls-remote --tags origin "refs/tags/${TAG}" | grep -q .; then
|
|
132
|
+
echo "Refusing to publish action bundle with colliding existing tag ${TAG} in ${target_repo}." >&2
|
|
133
|
+
exit 1
|
|
134
|
+
fi
|
|
135
|
+
git -C "$repo_dir" tag "${TAG}"
|
|
136
|
+
git -C "$repo_dir" push origin "refs/tags/${TAG}"
|
|
137
|
+
git -C "$repo_dir" push origin refs/tags/v1 --force
|
|
138
|
+
|
|
139
|
+
if ! gh release view "${TAG}" --repo "$target_repo" >/dev/null 2>&1; then
|
|
140
|
+
gh release create "${TAG}" \
|
|
141
|
+
--repo "$target_repo" \
|
|
142
|
+
--title "${TAG}" \
|
|
143
|
+
--generate-notes \
|
|
144
|
+
--notes "Published automatically from ${SOURCE_SERVER_URL}/${SOURCE_REPOSITORY}/tree/${SOURCE_REF}"
|
|
145
|
+
fi
|
|
146
|
+
}
|
|
147
|
+
|
|
148
|
+
sync_action_repo() {
|
|
149
|
+
target_repo="$1"
|
|
150
|
+
readme_source="$2"
|
|
151
|
+
repo_description="$3"
|
|
152
|
+
repo_dir="$GITHUB_WORKSPACE/action-repos/${target_repo##*/}"
|
|
153
|
+
repo_changed="false"
|
|
154
|
+
|
|
155
|
+
if gh repo view "$target_repo" >/dev/null 2>&1; then
|
|
156
|
+
gh repo edit "$target_repo" --description "$repo_description"
|
|
157
|
+
gh repo clone "$target_repo" "$repo_dir" -- --depth 1
|
|
158
|
+
else
|
|
159
|
+
gh repo create "$target_repo" --public --description "$repo_description" --clone
|
|
160
|
+
mv "${target_repo##*/}" "$repo_dir"
|
|
161
|
+
fi
|
|
162
|
+
|
|
163
|
+
git -C "$repo_dir" remote set-url origin "https://x-access-token:${ACTION_REPO_TOKEN}@github.com/${target_repo}.git"
|
|
164
|
+
|
|
165
|
+
cp "${GITHUB_WORKSPACE}/action/action.yml" "${repo_dir}/action.yml"
|
|
166
|
+
cp "$readme_source" "${repo_dir}/README.md"
|
|
167
|
+
printf '%s\n' "$SCANNER_VERSION" > "${repo_dir}/scanner-version.txt"
|
|
168
|
+
cp "${GITHUB_WORKSPACE}/action/cisco-version.txt" "${repo_dir}/cisco-version.txt"
|
|
169
|
+
cp "${GITHUB_WORKSPACE}/action/pypi-attestations-version.txt" "${repo_dir}/pypi-attestations-version.txt"
|
|
170
|
+
cp "${GITHUB_WORKSPACE}/LICENSE" "${repo_dir}/LICENSE"
|
|
171
|
+
cp "${GITHUB_WORKSPACE}/SECURITY.md" "${repo_dir}/SECURITY.md"
|
|
172
|
+
cp "${GITHUB_WORKSPACE}/CONTRIBUTING.md" "${repo_dir}/CONTRIBUTING.md"
|
|
173
|
+
|
|
174
|
+
if [ -n "$(git -C "$repo_dir" status --short -- action.yml README.md scanner-version.txt cisco-version.txt pypi-attestations-version.txt LICENSE SECURITY.md CONTRIBUTING.md)" ]; then
|
|
175
|
+
repo_changed="true"
|
|
176
|
+
git -C "$repo_dir" config user.name "github-actions[bot]"
|
|
177
|
+
git -C "$repo_dir" config user.email "41898282+github-actions[bot]@users.noreply.github.com"
|
|
178
|
+
git -C "$repo_dir" add action.yml README.md scanner-version.txt cisco-version.txt pypi-attestations-version.txt LICENSE SECURITY.md CONTRIBUTING.md
|
|
179
|
+
git -C "$repo_dir" commit -m "chore: publish action bundle ${TAG}"
|
|
180
|
+
git -C "$repo_dir" push origin HEAD:main
|
|
181
|
+
any_repo_changed="true"
|
|
182
|
+
fi
|
|
183
|
+
|
|
184
|
+
printf '%s\t%s\n' "$target_repo" "$repo_dir" >> "$GITHUB_WORKSPACE/action-repos/publish-targets.tsv"
|
|
185
|
+
}
|
|
186
|
+
|
|
187
|
+
mkdir -p "$GITHUB_WORKSPACE/action-repos"
|
|
188
|
+
: > "$GITHUB_WORKSPACE/action-repos/publish-targets.tsv"
|
|
189
|
+
|
|
190
|
+
sync_action_repo \
|
|
191
|
+
"$ACTION_CANONICAL_REPOSITORY" \
|
|
192
|
+
"${GITHUB_WORKSPACE}/action/README.md" \
|
|
193
|
+
"HOL AI Plugin Scanner GitHub Action"
|
|
194
|
+
|
|
195
|
+
sync_action_repo \
|
|
196
|
+
"$ACTION_COMPAT_REPOSITORY" \
|
|
197
|
+
"${GITHUB_WORKSPACE}/action/README.legacy.md" \
|
|
198
|
+
"Compatibility alias for HOL AI Plugin Scanner GitHub Action"
|
|
199
|
+
|
|
200
|
+
if [ "$any_repo_changed" != "true" ]; then
|
|
201
|
+
exit 0
|
|
202
|
+
fi
|
|
203
|
+
|
|
204
|
+
while IFS=$'\t' read -r target_repo repo_dir; do
|
|
205
|
+
publish_action_release "$target_repo" "$repo_dir"
|
|
206
|
+
done < "$GITHUB_WORKSPACE/action-repos/publish-targets.tsv"
|
|
@@ -193,7 +193,7 @@ jobs:
|
|
|
193
193
|
run: |
|
|
194
194
|
VERSION="${{ needs.build.outputs.version }}"
|
|
195
195
|
BUNDLE_ROOT="dist/github-action-bundle"
|
|
196
|
-
BUNDLE_PATH="dist/
|
|
196
|
+
BUNDLE_PATH="dist/ai-plugin-scanner-action-v${VERSION}.zip"
|
|
197
197
|
|
|
198
198
|
mkdir -p "${BUNDLE_ROOT}"
|
|
199
199
|
cp action/action.yml "${BUNDLE_ROOT}/action.yml"
|
|
@@ -1,7 +1,7 @@
|
|
|
1
1
|
Metadata-Version: 2.4
|
|
2
2
|
Name: plugin-scanner
|
|
3
|
-
Version: 2.0.
|
|
4
|
-
Summary:
|
|
3
|
+
Version: 2.0.2
|
|
4
|
+
Summary: Local Guard runtime plus security and publishability scanning for Codex, Claude, Cursor, Gemini, and OpenCode.
|
|
5
5
|
Project-URL: Homepage, https://github.com/hashgraph-online/ai-plugin-scanner
|
|
6
6
|
Project-URL: Repository, https://github.com/hashgraph-online/ai-plugin-scanner
|
|
7
7
|
Project-URL: Issues, https://github.com/hashgraph-online/ai-plugin-scanner/issues
|
|
@@ -47,10 +47,47 @@ Description-Content-Type: text/markdown
|
|
|
47
47
|
[](https://github.com/hashgraph-online/ai-plugin-scanner/stargazers)
|
|
48
48
|
[](https://github.com/astral-sh/ruff)
|
|
49
49
|
|
|
50
|
-
|  | **
|
|
50
|
+
|  | **HOL Guard for local harness protection, plus the scanner CI gate for plugin ecosystems**. Protect Codex, Claude Code, Cursor, Gemini, and OpenCode before local tools run, then lint locally, verify in CI, and ship publish-ready bundles for manifests, skills, MCP, and marketplace metadata.<br><br>Use Guard when you want a local safety loop. Use the scanner when you want publishing and CI confidence.<br><br>[PyPI Package (`plugin-scanner`)](https://pypi.org/project/plugin-scanner/)<br>[Legacy Namespace (`codex-plugin-scanner`)](https://pypi.org/project/codex-plugin-scanner/)<br>[HOL Plugin Registry](https://hol.org/registry/plugins)<br>[HOL GitHub Organization](https://github.com/hashgraph-online)<br>[Report an Issue](https://github.com/hashgraph-online/ai-plugin-scanner/issues) |
|
|
51
51
|
| :--- | :--- |
|
|
52
52
|
|
|
53
|
-
## Start In
|
|
53
|
+
## Guard Start In 60 Seconds
|
|
54
|
+
|
|
55
|
+
```bash
|
|
56
|
+
# See what Guard can protect on this machine
|
|
57
|
+
pipx run plugin-guard guard start
|
|
58
|
+
|
|
59
|
+
# Install Guard in front of Codex
|
|
60
|
+
pipx run plugin-guard guard install codex
|
|
61
|
+
|
|
62
|
+
# Review the current tool state before launch
|
|
63
|
+
pipx run plugin-guard guard run codex
|
|
64
|
+
|
|
65
|
+
# Inspect local receipts later
|
|
66
|
+
pipx run plugin-guard guard receipts
|
|
67
|
+
```
|
|
68
|
+
|
|
69
|
+
Guard is local-first:
|
|
70
|
+
|
|
71
|
+
1. detect your harnesses
|
|
72
|
+
2. install a Guard launcher
|
|
73
|
+
3. run the harness through Guard
|
|
74
|
+
4. approve or block changes
|
|
75
|
+
5. inspect receipts locally
|
|
76
|
+
6. connect sync only if you want shared history later
|
|
77
|
+
|
|
78
|
+
Guard commands that matter most:
|
|
79
|
+
|
|
80
|
+
- `plugin-scanner guard start` for the first-run path
|
|
81
|
+
- `plugin-scanner guard status` for the current protection state
|
|
82
|
+
- `plugin-scanner guard install <harness>` to create a local Guard launcher
|
|
83
|
+
- `plugin-scanner guard run <harness> --dry-run` to record the current state before launch
|
|
84
|
+
- `plugin-scanner guard run <harness>` to review and approve changed tools before launch
|
|
85
|
+
- `plugin-scanner guard diff <harness>` when Guard says something changed
|
|
86
|
+
- `plugin-scanner guard receipts` for local history
|
|
87
|
+
|
|
88
|
+
See [docs/guard/get-started.md](docs/guard/get-started.md) for the full local flow.
|
|
89
|
+
|
|
90
|
+
## Scanner Start In 30 Seconds
|
|
54
91
|
|
|
55
92
|
```bash
|
|
56
93
|
# Local preflight
|
|
@@ -60,8 +97,8 @@ pipx run plugin-scanner verify .
|
|
|
60
97
|
|
|
61
98
|
```yaml
|
|
62
99
|
# GitHub Actions PR gate
|
|
63
|
-
- name:
|
|
64
|
-
uses: hashgraph-online/
|
|
100
|
+
- name: AI plugin quality gate
|
|
101
|
+
uses: hashgraph-online/ai-plugin-scanner-action@v1
|
|
65
102
|
with:
|
|
66
103
|
plugin_dir: "."
|
|
67
104
|
fail_on_severity: high
|
|
@@ -70,7 +107,27 @@ pipx run plugin-scanner verify .
|
|
|
70
107
|
|
|
71
108
|
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.
|
|
72
109
|
|
|
73
|
-
##
|
|
110
|
+
## Two Product Modes
|
|
111
|
+
|
|
112
|
+
### HOL Guard
|
|
113
|
+
|
|
114
|
+
Use Guard when the problem is local runtime safety inside a harness:
|
|
115
|
+
|
|
116
|
+
- a new MCP server showed up in local config
|
|
117
|
+
- an existing tool changed after you trusted it
|
|
118
|
+
- you want receipts for what was approved or blocked
|
|
119
|
+
- you want to review changes before Codex, Claude Code, Cursor, Gemini, or OpenCode launches
|
|
120
|
+
|
|
121
|
+
### Scanner CI Gate
|
|
122
|
+
|
|
123
|
+
Use the scanner when the problem is authoring, CI, and publish readiness:
|
|
124
|
+
|
|
125
|
+
- lint manifests and metadata
|
|
126
|
+
- verify runtime and install surfaces
|
|
127
|
+
- block PRs with policy gates
|
|
128
|
+
- emit artifacts before submission or publishing
|
|
129
|
+
|
|
130
|
+
## Use Scanner After `$plugin-creator`
|
|
74
131
|
|
|
75
132
|
`plugin-scanner` is designed as the quality gate between plugin creation and distribution:
|
|
76
133
|
|
|
@@ -248,7 +305,7 @@ For repo-scoped marketplaces, `scan`, `lint`, `verify`, and `doctor` can target
|
|
|
248
305
|
## Config + Baseline Example
|
|
249
306
|
|
|
250
307
|
```toml
|
|
251
|
-
# .
|
|
308
|
+
# .plugin-scanner.toml
|
|
252
309
|
[scanner]
|
|
253
310
|
profile = "public-marketplace"
|
|
254
311
|
baseline_file = "baseline.txt"
|
|
@@ -338,7 +395,7 @@ jobs:
|
|
|
338
395
|
runs-on: ubuntu-latest
|
|
339
396
|
steps:
|
|
340
397
|
- uses: actions/checkout@v6
|
|
341
|
-
- uses: hashgraph-online/
|
|
398
|
+
- uses: hashgraph-online/ai-plugin-scanner-action@v1
|
|
342
399
|
with:
|
|
343
400
|
plugin_dir: "."
|
|
344
401
|
mode: scan
|
|
@@ -357,9 +414,9 @@ Local pre-commit style hook:
|
|
|
357
414
|
repos:
|
|
358
415
|
- repo: local
|
|
359
416
|
hooks:
|
|
360
|
-
- id:
|
|
361
|
-
name:
|
|
362
|
-
entry:
|
|
417
|
+
- id: plugin-scanner
|
|
418
|
+
name: Plugin Scanner
|
|
419
|
+
entry: plugin-scanner
|
|
363
420
|
language: system
|
|
364
421
|
types: [directory]
|
|
365
422
|
pass_filenames: false
|
|
@@ -386,17 +443,19 @@ The source repository can publish the GitHub Action automatically into a dedicat
|
|
|
386
443
|
Configure:
|
|
387
444
|
|
|
388
445
|
- repository secret `ACTION_REPO_TOKEN`
|
|
389
|
-
It should be a token that can create or update repositories and releases in the
|
|
390
|
-
- optional repository variable `
|
|
446
|
+
It should be a token that can create or update repositories and releases in the canonical and compatibility action repositories.
|
|
447
|
+
- optional repository variable `ACTION_CANONICAL_REPOSITORY`
|
|
448
|
+
Defaults to `hashgraph-online/ai-plugin-scanner-action`.
|
|
449
|
+
- optional repository variable `ACTION_COMPAT_REPOSITORY`
|
|
391
450
|
Defaults to `hashgraph-online/hol-codex-plugin-scanner-action`.
|
|
392
451
|
|
|
393
|
-
When
|
|
452
|
+
When changes land on `main`, [publish-action-repo.yml](./.github/workflows/publish-action-repo.yml) will:
|
|
394
453
|
|
|
395
|
-
- create the
|
|
396
|
-
- sync the root-ready `action.yml`, `README.md`, `LICENSE`, and `SECURITY.md`
|
|
454
|
+
- create the canonical Marketplace repository if it does not already exist
|
|
455
|
+
- sync the root-ready `action.yml`, repo-specific `README.md`, `LICENSE`, and `SECURITY.md` into both the canonical repo and the legacy compatibility repo
|
|
397
456
|
- push the immutable release tag such as `v2.0.0`
|
|
398
457
|
- move the floating `v1` tag
|
|
399
|
-
- create or update the corresponding release in
|
|
458
|
+
- create or update the corresponding release in each action repository
|
|
400
459
|
|
|
401
460
|
GitHub Marketplace still requires the one-time listing publication step in the dedicated action repository UI, but after that this repository can keep the action repository current automatically.
|
|
402
461
|
|
|
@@ -404,7 +463,7 @@ GitHub Marketplace still requires the one-time listing publication step in the d
|
|
|
404
463
|
|
|
405
464
|
The action can also handle submission intake. A plugin repository can wire the scanner into CI so a passing scan opens or reuses a submission issue in [awesome-codex-plugins](https://github.com/hashgraph-online/awesome-codex-plugins).
|
|
406
465
|
|
|
407
|
-
It also emits
|
|
466
|
+
It also emits automation-friendly machine outputs:
|
|
408
467
|
|
|
409
468
|
- `score`, `grade`, `grade_label`, `max_severity`, and `findings_total` as GitHub Action outputs
|
|
410
469
|
- a concise markdown summary in the job summary by default
|
|
@@ -432,7 +491,7 @@ jobs:
|
|
|
432
491
|
|
|
433
492
|
- name: Scan and submit if eligible
|
|
434
493
|
id: scan
|
|
435
|
-
uses: hashgraph-online/
|
|
494
|
+
uses: hashgraph-online/ai-plugin-scanner-action@v1
|
|
436
495
|
with:
|
|
437
496
|
plugin_dir: "."
|
|
438
497
|
min_score: 80
|
|
@@ -448,9 +507,9 @@ jobs:
|
|
|
448
507
|
|
|
449
508
|
`submission_token` is required when `submission_enabled: true`. This flow is idempotent. If the plugin repository was already submitted, the action reuses the existing open issue instead of opening duplicates by matching an exact hidden plugin URL marker in the existing issue body.
|
|
450
509
|
|
|
451
|
-
### Registry Payload For
|
|
510
|
+
### Registry Payload For Plugin Ecosystem Automation
|
|
452
511
|
|
|
453
|
-
If you want to feed the same scan into a registry, badge pipeline, or another
|
|
512
|
+
If you want to feed the same scan into a registry, badge pipeline, or another plugin ecosystem automation step, request a registry payload file directly from the action:
|
|
454
513
|
|
|
455
514
|
```yaml
|
|
456
515
|
permissions:
|
|
@@ -464,12 +523,12 @@ jobs:
|
|
|
464
523
|
|
|
465
524
|
- name: Scan plugin
|
|
466
525
|
id: scan
|
|
467
|
-
uses: hashgraph-online/
|
|
526
|
+
uses: hashgraph-online/ai-plugin-scanner-action@v1
|
|
468
527
|
with:
|
|
469
528
|
plugin_dir: "."
|
|
470
529
|
format: sarif
|
|
471
|
-
output:
|
|
472
|
-
registry_payload_output:
|
|
530
|
+
output: ai-plugin-scanner.sarif
|
|
531
|
+
registry_payload_output: ai-plugin-registry-payload.json
|
|
473
532
|
|
|
474
533
|
- name: Show trust signals
|
|
475
534
|
run: |
|
|
@@ -480,7 +539,7 @@ jobs:
|
|
|
480
539
|
- name: Upload registry payload
|
|
481
540
|
uses: actions/upload-artifact@v6
|
|
482
541
|
with:
|
|
483
|
-
name:
|
|
542
|
+
name: ai-plugin-registry-payload
|
|
484
543
|
path: ${{ steps.scan.outputs.registry_payload_path }}
|
|
485
544
|
```
|
|
486
545
|
|
|
@@ -12,10 +12,47 @@
|
|
|
12
12
|
[](https://github.com/hashgraph-online/ai-plugin-scanner/stargazers)
|
|
13
13
|
[](https://github.com/astral-sh/ruff)
|
|
14
14
|
|
|
15
|
-
|  | **
|
|
15
|
+
|  | **HOL Guard for local harness protection, plus the scanner CI gate for plugin ecosystems**. Protect Codex, Claude Code, Cursor, Gemini, and OpenCode before local tools run, then lint locally, verify in CI, and ship publish-ready bundles for manifests, skills, MCP, and marketplace metadata.<br><br>Use Guard when you want a local safety loop. Use the scanner when you want publishing and CI confidence.<br><br>[PyPI Package (`plugin-scanner`)](https://pypi.org/project/plugin-scanner/)<br>[Legacy Namespace (`codex-plugin-scanner`)](https://pypi.org/project/codex-plugin-scanner/)<br>[HOL Plugin Registry](https://hol.org/registry/plugins)<br>[HOL GitHub Organization](https://github.com/hashgraph-online)<br>[Report an Issue](https://github.com/hashgraph-online/ai-plugin-scanner/issues) |
|
|
16
16
|
| :--- | :--- |
|
|
17
17
|
|
|
18
|
-
## Start In
|
|
18
|
+
## Guard Start In 60 Seconds
|
|
19
|
+
|
|
20
|
+
```bash
|
|
21
|
+
# See what Guard can protect on this machine
|
|
22
|
+
pipx run plugin-guard guard start
|
|
23
|
+
|
|
24
|
+
# Install Guard in front of Codex
|
|
25
|
+
pipx run plugin-guard guard install codex
|
|
26
|
+
|
|
27
|
+
# Review the current tool state before launch
|
|
28
|
+
pipx run plugin-guard guard run codex
|
|
29
|
+
|
|
30
|
+
# Inspect local receipts later
|
|
31
|
+
pipx run plugin-guard guard receipts
|
|
32
|
+
```
|
|
33
|
+
|
|
34
|
+
Guard is local-first:
|
|
35
|
+
|
|
36
|
+
1. detect your harnesses
|
|
37
|
+
2. install a Guard launcher
|
|
38
|
+
3. run the harness through Guard
|
|
39
|
+
4. approve or block changes
|
|
40
|
+
5. inspect receipts locally
|
|
41
|
+
6. connect sync only if you want shared history later
|
|
42
|
+
|
|
43
|
+
Guard commands that matter most:
|
|
44
|
+
|
|
45
|
+
- `plugin-scanner guard start` for the first-run path
|
|
46
|
+
- `plugin-scanner guard status` for the current protection state
|
|
47
|
+
- `plugin-scanner guard install <harness>` to create a local Guard launcher
|
|
48
|
+
- `plugin-scanner guard run <harness> --dry-run` to record the current state before launch
|
|
49
|
+
- `plugin-scanner guard run <harness>` to review and approve changed tools before launch
|
|
50
|
+
- `plugin-scanner guard diff <harness>` when Guard says something changed
|
|
51
|
+
- `plugin-scanner guard receipts` for local history
|
|
52
|
+
|
|
53
|
+
See [docs/guard/get-started.md](docs/guard/get-started.md) for the full local flow.
|
|
54
|
+
|
|
55
|
+
## Scanner Start In 30 Seconds
|
|
19
56
|
|
|
20
57
|
```bash
|
|
21
58
|
# Local preflight
|
|
@@ -25,8 +62,8 @@ pipx run plugin-scanner verify .
|
|
|
25
62
|
|
|
26
63
|
```yaml
|
|
27
64
|
# GitHub Actions PR gate
|
|
28
|
-
- name:
|
|
29
|
-
uses: hashgraph-online/
|
|
65
|
+
- name: AI plugin quality gate
|
|
66
|
+
uses: hashgraph-online/ai-plugin-scanner-action@v1
|
|
30
67
|
with:
|
|
31
68
|
plugin_dir: "."
|
|
32
69
|
fail_on_severity: high
|
|
@@ -35,7 +72,27 @@ pipx run plugin-scanner verify .
|
|
|
35
72
|
|
|
36
73
|
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.
|
|
37
74
|
|
|
38
|
-
##
|
|
75
|
+
## Two Product Modes
|
|
76
|
+
|
|
77
|
+
### HOL Guard
|
|
78
|
+
|
|
79
|
+
Use Guard when the problem is local runtime safety inside a harness:
|
|
80
|
+
|
|
81
|
+
- a new MCP server showed up in local config
|
|
82
|
+
- an existing tool changed after you trusted it
|
|
83
|
+
- you want receipts for what was approved or blocked
|
|
84
|
+
- you want to review changes before Codex, Claude Code, Cursor, Gemini, or OpenCode launches
|
|
85
|
+
|
|
86
|
+
### Scanner CI Gate
|
|
87
|
+
|
|
88
|
+
Use the scanner when the problem is authoring, CI, and publish readiness:
|
|
89
|
+
|
|
90
|
+
- lint manifests and metadata
|
|
91
|
+
- verify runtime and install surfaces
|
|
92
|
+
- block PRs with policy gates
|
|
93
|
+
- emit artifacts before submission or publishing
|
|
94
|
+
|
|
95
|
+
## Use Scanner After `$plugin-creator`
|
|
39
96
|
|
|
40
97
|
`plugin-scanner` is designed as the quality gate between plugin creation and distribution:
|
|
41
98
|
|
|
@@ -213,7 +270,7 @@ For repo-scoped marketplaces, `scan`, `lint`, `verify`, and `doctor` can target
|
|
|
213
270
|
## Config + Baseline Example
|
|
214
271
|
|
|
215
272
|
```toml
|
|
216
|
-
# .
|
|
273
|
+
# .plugin-scanner.toml
|
|
217
274
|
[scanner]
|
|
218
275
|
profile = "public-marketplace"
|
|
219
276
|
baseline_file = "baseline.txt"
|
|
@@ -303,7 +360,7 @@ jobs:
|
|
|
303
360
|
runs-on: ubuntu-latest
|
|
304
361
|
steps:
|
|
305
362
|
- uses: actions/checkout@v6
|
|
306
|
-
- uses: hashgraph-online/
|
|
363
|
+
- uses: hashgraph-online/ai-plugin-scanner-action@v1
|
|
307
364
|
with:
|
|
308
365
|
plugin_dir: "."
|
|
309
366
|
mode: scan
|
|
@@ -322,9 +379,9 @@ Local pre-commit style hook:
|
|
|
322
379
|
repos:
|
|
323
380
|
- repo: local
|
|
324
381
|
hooks:
|
|
325
|
-
- id:
|
|
326
|
-
name:
|
|
327
|
-
entry:
|
|
382
|
+
- id: plugin-scanner
|
|
383
|
+
name: Plugin Scanner
|
|
384
|
+
entry: plugin-scanner
|
|
328
385
|
language: system
|
|
329
386
|
types: [directory]
|
|
330
387
|
pass_filenames: false
|
|
@@ -351,17 +408,19 @@ The source repository can publish the GitHub Action automatically into a dedicat
|
|
|
351
408
|
Configure:
|
|
352
409
|
|
|
353
410
|
- repository secret `ACTION_REPO_TOKEN`
|
|
354
|
-
It should be a token that can create or update repositories and releases in the
|
|
355
|
-
- optional repository variable `
|
|
411
|
+
It should be a token that can create or update repositories and releases in the canonical and compatibility action repositories.
|
|
412
|
+
- optional repository variable `ACTION_CANONICAL_REPOSITORY`
|
|
413
|
+
Defaults to `hashgraph-online/ai-plugin-scanner-action`.
|
|
414
|
+
- optional repository variable `ACTION_COMPAT_REPOSITORY`
|
|
356
415
|
Defaults to `hashgraph-online/hol-codex-plugin-scanner-action`.
|
|
357
416
|
|
|
358
|
-
When
|
|
417
|
+
When changes land on `main`, [publish-action-repo.yml](./.github/workflows/publish-action-repo.yml) will:
|
|
359
418
|
|
|
360
|
-
- create the
|
|
361
|
-
- sync the root-ready `action.yml`, `README.md`, `LICENSE`, and `SECURITY.md`
|
|
419
|
+
- create the canonical Marketplace repository if it does not already exist
|
|
420
|
+
- sync the root-ready `action.yml`, repo-specific `README.md`, `LICENSE`, and `SECURITY.md` into both the canonical repo and the legacy compatibility repo
|
|
362
421
|
- push the immutable release tag such as `v2.0.0`
|
|
363
422
|
- move the floating `v1` tag
|
|
364
|
-
- create or update the corresponding release in
|
|
423
|
+
- create or update the corresponding release in each action repository
|
|
365
424
|
|
|
366
425
|
GitHub Marketplace still requires the one-time listing publication step in the dedicated action repository UI, but after that this repository can keep the action repository current automatically.
|
|
367
426
|
|
|
@@ -369,7 +428,7 @@ GitHub Marketplace still requires the one-time listing publication step in the d
|
|
|
369
428
|
|
|
370
429
|
The action can also handle submission intake. A plugin repository can wire the scanner into CI so a passing scan opens or reuses a submission issue in [awesome-codex-plugins](https://github.com/hashgraph-online/awesome-codex-plugins).
|
|
371
430
|
|
|
372
|
-
It also emits
|
|
431
|
+
It also emits automation-friendly machine outputs:
|
|
373
432
|
|
|
374
433
|
- `score`, `grade`, `grade_label`, `max_severity`, and `findings_total` as GitHub Action outputs
|
|
375
434
|
- a concise markdown summary in the job summary by default
|
|
@@ -397,7 +456,7 @@ jobs:
|
|
|
397
456
|
|
|
398
457
|
- name: Scan and submit if eligible
|
|
399
458
|
id: scan
|
|
400
|
-
uses: hashgraph-online/
|
|
459
|
+
uses: hashgraph-online/ai-plugin-scanner-action@v1
|
|
401
460
|
with:
|
|
402
461
|
plugin_dir: "."
|
|
403
462
|
min_score: 80
|
|
@@ -413,9 +472,9 @@ jobs:
|
|
|
413
472
|
|
|
414
473
|
`submission_token` is required when `submission_enabled: true`. This flow is idempotent. If the plugin repository was already submitted, the action reuses the existing open issue instead of opening duplicates by matching an exact hidden plugin URL marker in the existing issue body.
|
|
415
474
|
|
|
416
|
-
### Registry Payload For
|
|
475
|
+
### Registry Payload For Plugin Ecosystem Automation
|
|
417
476
|
|
|
418
|
-
If you want to feed the same scan into a registry, badge pipeline, or another
|
|
477
|
+
If you want to feed the same scan into a registry, badge pipeline, or another plugin ecosystem automation step, request a registry payload file directly from the action:
|
|
419
478
|
|
|
420
479
|
```yaml
|
|
421
480
|
permissions:
|
|
@@ -429,12 +488,12 @@ jobs:
|
|
|
429
488
|
|
|
430
489
|
- name: Scan plugin
|
|
431
490
|
id: scan
|
|
432
|
-
uses: hashgraph-online/
|
|
491
|
+
uses: hashgraph-online/ai-plugin-scanner-action@v1
|
|
433
492
|
with:
|
|
434
493
|
plugin_dir: "."
|
|
435
494
|
format: sarif
|
|
436
|
-
output:
|
|
437
|
-
registry_payload_output:
|
|
495
|
+
output: ai-plugin-scanner.sarif
|
|
496
|
+
registry_payload_output: ai-plugin-registry-payload.json
|
|
438
497
|
|
|
439
498
|
- name: Show trust signals
|
|
440
499
|
run: |
|
|
@@ -445,7 +504,7 @@ jobs:
|
|
|
445
504
|
- name: Upload registry payload
|
|
446
505
|
uses: actions/upload-artifact@v6
|
|
447
506
|
with:
|
|
448
|
-
name:
|
|
507
|
+
name: ai-plugin-registry-payload
|
|
449
508
|
path: ${{ steps.scan.outputs.registry_payload_path }}
|
|
450
509
|
```
|
|
451
510
|
|
|
@@ -0,0 +1,25 @@
|
|
|
1
|
+
# HOL AI Plugin Scanner GitHub Action
|
|
2
|
+
|
|
3
|
+
[](https://github.com/hashgraph-online/hol-codex-plugin-scanner-action/releases/latest)
|
|
4
|
+
[](https://github.com/hashgraph-online/hol-codex-plugin-scanner-action)
|
|
5
|
+
[](https://github.com/hashgraph-online/ai-plugin-scanner-action)
|
|
6
|
+
[](https://github.com/hashgraph-online/ai-plugin-scanner/tree/main/action)
|
|
7
|
+
|
|
8
|
+
This repository remains supported as a compatibility alias for existing workflows that use:
|
|
9
|
+
|
|
10
|
+
```yaml
|
|
11
|
+
uses: hashgraph-online/hol-codex-plugin-scanner-action@v1
|
|
12
|
+
```
|
|
13
|
+
|
|
14
|
+
New integrations should move to the canonical action slug:
|
|
15
|
+
|
|
16
|
+
```yaml
|
|
17
|
+
uses: hashgraph-online/ai-plugin-scanner-action@v1
|
|
18
|
+
```
|
|
19
|
+
|
|
20
|
+
The action behavior, release train, and source of truth are shared with the canonical repository:
|
|
21
|
+
|
|
22
|
+
- Canonical action repo: [hashgraph-online/ai-plugin-scanner-action](https://github.com/hashgraph-online/ai-plugin-scanner-action)
|
|
23
|
+
- Source repo: [hashgraph-online/ai-plugin-scanner](https://github.com/hashgraph-online/ai-plugin-scanner)
|
|
24
|
+
|
|
25
|
+
The compatibility alias continues to receive the same reviewed root bundle, release tags, and floating `v1` major tag so existing consumers do not break during the identity migration.
|