plugin-scanner 2.0.108__tar.gz → 2.0.109__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.108 → plugin_scanner-2.0.109}/PKG-INFO +20 -9
- {plugin_scanner-2.0.108 → plugin_scanner-2.0.109}/README.md +19 -8
- {plugin_scanner-2.0.108 → plugin_scanner-2.0.109}/docs/guard/get-started.md +24 -0
- {plugin_scanner-2.0.108 → plugin_scanner-2.0.109}/docs/guard/testing-matrix.md +10 -0
- {plugin_scanner-2.0.108 → plugin_scanner-2.0.109}/pyproject.toml +1 -1
- {plugin_scanner-2.0.108 → plugin_scanner-2.0.109}/pyproject.toml.bak +1 -1
- {plugin_scanner-2.0.108 → plugin_scanner-2.0.109}/src/codex_plugin_scanner/guard/cli/commands.py +9 -1
- {plugin_scanner-2.0.108 → plugin_scanner-2.0.109}/src/codex_plugin_scanner/guard/cli/render.py +117 -51
- {plugin_scanner-2.0.108 → plugin_scanner-2.0.109}/src/codex_plugin_scanner/version.py +1 -1
- {plugin_scanner-2.0.108 → plugin_scanner-2.0.109}/tests/test_cli.py +36 -0
- {plugin_scanner-2.0.108 → plugin_scanner-2.0.109}/tests/test_guard_cli.py +157 -0
- {plugin_scanner-2.0.108 → plugin_scanner-2.0.109}/tests/test_guard_product_flow.py +11 -0
- {plugin_scanner-2.0.108 → plugin_scanner-2.0.109}/tests/test_guard_runtime.py +40 -1
- {plugin_scanner-2.0.108 → plugin_scanner-2.0.109}/.clusterfuzzlite/Dockerfile +0 -0
- {plugin_scanner-2.0.108 → plugin_scanner-2.0.109}/.clusterfuzzlite/build.sh +0 -0
- {plugin_scanner-2.0.108 → plugin_scanner-2.0.109}/.clusterfuzzlite/project.yaml +0 -0
- {plugin_scanner-2.0.108 → plugin_scanner-2.0.109}/.clusterfuzzlite/requirements-atheris.txt +0 -0
- {plugin_scanner-2.0.108 → plugin_scanner-2.0.109}/.dockerignore +0 -0
- {plugin_scanner-2.0.108 → plugin_scanner-2.0.109}/.github/CODEOWNERS +0 -0
- {plugin_scanner-2.0.108 → plugin_scanner-2.0.109}/.github/ISSUE_TEMPLATE/bug-report.yml +0 -0
- {plugin_scanner-2.0.108 → plugin_scanner-2.0.109}/.github/ISSUE_TEMPLATE/config.yml +0 -0
- {plugin_scanner-2.0.108 → plugin_scanner-2.0.109}/.github/ISSUE_TEMPLATE/feature-request.yml +0 -0
- {plugin_scanner-2.0.108 → plugin_scanner-2.0.109}/.github/dependabot.yml +0 -0
- {plugin_scanner-2.0.108 → plugin_scanner-2.0.109}/.github/workflows/ci.yml +0 -0
- {plugin_scanner-2.0.108 → plugin_scanner-2.0.109}/.github/workflows/codeql.yml +0 -0
- {plugin_scanner-2.0.108 → plugin_scanner-2.0.109}/.github/workflows/dependabot-uv-lock.yml +0 -0
- {plugin_scanner-2.0.108 → plugin_scanner-2.0.109}/.github/workflows/fuzz.yml +0 -0
- {plugin_scanner-2.0.108 → plugin_scanner-2.0.109}/.github/workflows/harness-smoke.yml +0 -0
- {plugin_scanner-2.0.108 → plugin_scanner-2.0.109}/.github/workflows/publish.yml +0 -0
- {plugin_scanner-2.0.108 → plugin_scanner-2.0.109}/.github/workflows/scorecard.yml +0 -0
- {plugin_scanner-2.0.108 → plugin_scanner-2.0.109}/.gitignore +0 -0
- {plugin_scanner-2.0.108 → plugin_scanner-2.0.109}/.pre-commit-hooks.yaml +0 -0
- {plugin_scanner-2.0.108 → plugin_scanner-2.0.109}/CONTRIBUTING.md +0 -0
- {plugin_scanner-2.0.108 → plugin_scanner-2.0.109}/Dockerfile +0 -0
- {plugin_scanner-2.0.108 → plugin_scanner-2.0.109}/LICENSE +0 -0
- {plugin_scanner-2.0.108 → plugin_scanner-2.0.109}/SECURITY.md +0 -0
- {plugin_scanner-2.0.108 → plugin_scanner-2.0.109}/dashboard/index.html +0 -0
- {plugin_scanner-2.0.108 → plugin_scanner-2.0.109}/dashboard/package.json +0 -0
- {plugin_scanner-2.0.108 → plugin_scanner-2.0.109}/dashboard/pnpm-lock.yaml +0 -0
- {plugin_scanner-2.0.108 → plugin_scanner-2.0.109}/dashboard/public/apple-touch-icon.png +0 -0
- {plugin_scanner-2.0.108 → plugin_scanner-2.0.109}/dashboard/public/brand/Logo_Icon_Dark.png +0 -0
- {plugin_scanner-2.0.108 → plugin_scanner-2.0.109}/dashboard/public/brand/Logo_Whole.png +0 -0
- {plugin_scanner-2.0.108 → plugin_scanner-2.0.109}/dashboard/public/favicon-16x16.png +0 -0
- {plugin_scanner-2.0.108 → plugin_scanner-2.0.109}/dashboard/public/favicon-32x32.png +0 -0
- {plugin_scanner-2.0.108 → plugin_scanner-2.0.109}/dashboard/public/favicon.ico +0 -0
- {plugin_scanner-2.0.108 → plugin_scanner-2.0.109}/dashboard/src/app.tsx +0 -0
- {plugin_scanner-2.0.108 → plugin_scanner-2.0.109}/dashboard/src/approval-center-layout.tsx +0 -0
- {plugin_scanner-2.0.108 → plugin_scanner-2.0.109}/dashboard/src/approval-center-primitives.tsx +0 -0
- {plugin_scanner-2.0.108 → plugin_scanner-2.0.109}/dashboard/src/approval-center-utils.ts +0 -0
- {plugin_scanner-2.0.108 → plugin_scanner-2.0.109}/dashboard/src/fleet-workspace.tsx +0 -0
- {plugin_scanner-2.0.108 → plugin_scanner-2.0.109}/dashboard/src/guard-api.test.ts +0 -0
- {plugin_scanner-2.0.108 → plugin_scanner-2.0.109}/dashboard/src/guard-api.ts +0 -0
- {plugin_scanner-2.0.108 → plugin_scanner-2.0.109}/dashboard/src/guard-demo.ts +0 -0
- {plugin_scanner-2.0.108 → plugin_scanner-2.0.109}/dashboard/src/guard-types.ts +0 -0
- {plugin_scanner-2.0.108 → plugin_scanner-2.0.109}/dashboard/src/main.tsx +0 -0
- {plugin_scanner-2.0.108 → plugin_scanner-2.0.109}/dashboard/src/receipts-workspace.tsx +0 -0
- {plugin_scanner-2.0.108 → plugin_scanner-2.0.109}/dashboard/src/runtime-overview.tsx +0 -0
- {plugin_scanner-2.0.108 → plugin_scanner-2.0.109}/dashboard/src/settings-workspace.tsx +0 -0
- {plugin_scanner-2.0.108 → plugin_scanner-2.0.109}/dashboard/src/styles.css +0 -0
- {plugin_scanner-2.0.108 → plugin_scanner-2.0.109}/dashboard/src/vite-env.d.ts +0 -0
- {plugin_scanner-2.0.108 → plugin_scanner-2.0.109}/dashboard/tsconfig.json +0 -0
- {plugin_scanner-2.0.108 → plugin_scanner-2.0.109}/dashboard/vite.config.ts +0 -0
- {plugin_scanner-2.0.108 → plugin_scanner-2.0.109}/docker-requirements.txt +0 -0
- {plugin_scanner-2.0.108 → plugin_scanner-2.0.109}/docs/guard/approval-audit.md +0 -0
- {plugin_scanner-2.0.108 → plugin_scanner-2.0.109}/docs/guard/architecture.md +0 -0
- {plugin_scanner-2.0.108 → plugin_scanner-2.0.109}/docs/guard/harness-support.md +0 -0
- {plugin_scanner-2.0.108 → plugin_scanner-2.0.109}/docs/guard/local-vs-cloud.md +0 -0
- {plugin_scanner-2.0.108 → plugin_scanner-2.0.109}/docs/trust/mcp-trust-draft.md +0 -0
- {plugin_scanner-2.0.108 → plugin_scanner-2.0.109}/docs/trust/plugin-trust-draft.md +0 -0
- {plugin_scanner-2.0.108 → plugin_scanner-2.0.109}/docs/trust/skill-trust-local.md +0 -0
- {plugin_scanner-2.0.108 → plugin_scanner-2.0.109}/fuzzers/manifest_fuzzer.py +0 -0
- {plugin_scanner-2.0.108 → plugin_scanner-2.0.109}/requirements.txt +0 -0
- {plugin_scanner-2.0.108 → plugin_scanner-2.0.109}/schemas/plugin-quality.v1.json +0 -0
- {plugin_scanner-2.0.108 → plugin_scanner-2.0.109}/schemas/scan-result.v1.json +0 -0
- {plugin_scanner-2.0.108 → plugin_scanner-2.0.109}/schemas/verify-result.v1.json +0 -0
- {plugin_scanner-2.0.108 → plugin_scanner-2.0.109}/src/codex_plugin_scanner/__init__.py +0 -0
- {plugin_scanner-2.0.108 → plugin_scanner-2.0.109}/src/codex_plugin_scanner/action_runner.py +0 -0
- {plugin_scanner-2.0.108 → plugin_scanner-2.0.109}/src/codex_plugin_scanner/argparse_utils.py +0 -0
- {plugin_scanner-2.0.108 → plugin_scanner-2.0.109}/src/codex_plugin_scanner/checks/__init__.py +0 -0
- {plugin_scanner-2.0.108 → plugin_scanner-2.0.109}/src/codex_plugin_scanner/checks/best_practices.py +0 -0
- {plugin_scanner-2.0.108 → plugin_scanner-2.0.109}/src/codex_plugin_scanner/checks/claude.py +0 -0
- {plugin_scanner-2.0.108 → plugin_scanner-2.0.109}/src/codex_plugin_scanner/checks/code_quality.py +0 -0
- {plugin_scanner-2.0.108 → plugin_scanner-2.0.109}/src/codex_plugin_scanner/checks/ecosystem_common.py +0 -0
- {plugin_scanner-2.0.108 → plugin_scanner-2.0.109}/src/codex_plugin_scanner/checks/gemini.py +0 -0
- {plugin_scanner-2.0.108 → plugin_scanner-2.0.109}/src/codex_plugin_scanner/checks/manifest.py +0 -0
- {plugin_scanner-2.0.108 → plugin_scanner-2.0.109}/src/codex_plugin_scanner/checks/manifest_support.py +0 -0
- {plugin_scanner-2.0.108 → plugin_scanner-2.0.109}/src/codex_plugin_scanner/checks/marketplace.py +0 -0
- {plugin_scanner-2.0.108 → plugin_scanner-2.0.109}/src/codex_plugin_scanner/checks/mcp_security.py +0 -0
- {plugin_scanner-2.0.108 → plugin_scanner-2.0.109}/src/codex_plugin_scanner/checks/opencode.py +0 -0
- {plugin_scanner-2.0.108 → plugin_scanner-2.0.109}/src/codex_plugin_scanner/checks/operational_security.py +0 -0
- {plugin_scanner-2.0.108 → plugin_scanner-2.0.109}/src/codex_plugin_scanner/checks/security.py +0 -0
- {plugin_scanner-2.0.108 → plugin_scanner-2.0.109}/src/codex_plugin_scanner/checks/skill_security.py +0 -0
- {plugin_scanner-2.0.108 → plugin_scanner-2.0.109}/src/codex_plugin_scanner/cli.py +0 -0
- {plugin_scanner-2.0.108 → plugin_scanner-2.0.109}/src/codex_plugin_scanner/cli_ui.py +0 -0
- {plugin_scanner-2.0.108 → plugin_scanner-2.0.109}/src/codex_plugin_scanner/config.py +0 -0
- {plugin_scanner-2.0.108 → plugin_scanner-2.0.109}/src/codex_plugin_scanner/ecosystems/__init__.py +0 -0
- {plugin_scanner-2.0.108 → plugin_scanner-2.0.109}/src/codex_plugin_scanner/ecosystems/base.py +0 -0
- {plugin_scanner-2.0.108 → plugin_scanner-2.0.109}/src/codex_plugin_scanner/ecosystems/claude.py +0 -0
- {plugin_scanner-2.0.108 → plugin_scanner-2.0.109}/src/codex_plugin_scanner/ecosystems/codex.py +0 -0
- {plugin_scanner-2.0.108 → plugin_scanner-2.0.109}/src/codex_plugin_scanner/ecosystems/detect.py +0 -0
- {plugin_scanner-2.0.108 → plugin_scanner-2.0.109}/src/codex_plugin_scanner/ecosystems/gemini.py +0 -0
- {plugin_scanner-2.0.108 → plugin_scanner-2.0.109}/src/codex_plugin_scanner/ecosystems/opencode.py +0 -0
- {plugin_scanner-2.0.108 → plugin_scanner-2.0.109}/src/codex_plugin_scanner/ecosystems/registry.py +0 -0
- {plugin_scanner-2.0.108 → plugin_scanner-2.0.109}/src/codex_plugin_scanner/ecosystems/types.py +0 -0
- {plugin_scanner-2.0.108 → plugin_scanner-2.0.109}/src/codex_plugin_scanner/github_reporting.py +0 -0
- {plugin_scanner-2.0.108 → plugin_scanner-2.0.109}/src/codex_plugin_scanner/guard/__init__.py +0 -0
- {plugin_scanner-2.0.108 → plugin_scanner-2.0.109}/src/codex_plugin_scanner/guard/adapters/__init__.py +0 -0
- {plugin_scanner-2.0.108 → plugin_scanner-2.0.109}/src/codex_plugin_scanner/guard/adapters/antigravity.py +0 -0
- {plugin_scanner-2.0.108 → plugin_scanner-2.0.109}/src/codex_plugin_scanner/guard/adapters/base.py +0 -0
- {plugin_scanner-2.0.108 → plugin_scanner-2.0.109}/src/codex_plugin_scanner/guard/adapters/claude_code.py +0 -0
- {plugin_scanner-2.0.108 → plugin_scanner-2.0.109}/src/codex_plugin_scanner/guard/adapters/cloud_identity.py +0 -0
- {plugin_scanner-2.0.108 → plugin_scanner-2.0.109}/src/codex_plugin_scanner/guard/adapters/codex.py +0 -0
- {plugin_scanner-2.0.108 → plugin_scanner-2.0.109}/src/codex_plugin_scanner/guard/adapters/copilot.py +0 -0
- {plugin_scanner-2.0.108 → plugin_scanner-2.0.109}/src/codex_plugin_scanner/guard/adapters/cursor.py +0 -0
- {plugin_scanner-2.0.108 → plugin_scanner-2.0.109}/src/codex_plugin_scanner/guard/adapters/gemini.py +0 -0
- {plugin_scanner-2.0.108 → plugin_scanner-2.0.109}/src/codex_plugin_scanner/guard/adapters/hermes.py +0 -0
- {plugin_scanner-2.0.108 → plugin_scanner-2.0.109}/src/codex_plugin_scanner/guard/adapters/mcp_servers.py +0 -0
- {plugin_scanner-2.0.108 → plugin_scanner-2.0.109}/src/codex_plugin_scanner/guard/adapters/openclaw.py +0 -0
- {plugin_scanner-2.0.108 → plugin_scanner-2.0.109}/src/codex_plugin_scanner/guard/adapters/openclaw_config.py +0 -0
- {plugin_scanner-2.0.108 → plugin_scanner-2.0.109}/src/codex_plugin_scanner/guard/adapters/openclaw_support.py +0 -0
- {plugin_scanner-2.0.108 → plugin_scanner-2.0.109}/src/codex_plugin_scanner/guard/adapters/opencode.py +0 -0
- {plugin_scanner-2.0.108 → plugin_scanner-2.0.109}/src/codex_plugin_scanner/guard/adapters/opencode_artifacts.py +0 -0
- {plugin_scanner-2.0.108 → plugin_scanner-2.0.109}/src/codex_plugin_scanner/guard/advisory_model.py +0 -0
- {plugin_scanner-2.0.108 → plugin_scanner-2.0.109}/src/codex_plugin_scanner/guard/approvals.py +0 -0
- {plugin_scanner-2.0.108 → plugin_scanner-2.0.109}/src/codex_plugin_scanner/guard/bridge/__init__.py +0 -0
- {plugin_scanner-2.0.108 → plugin_scanner-2.0.109}/src/codex_plugin_scanner/guard/capabilities.py +0 -0
- {plugin_scanner-2.0.108 → plugin_scanner-2.0.109}/src/codex_plugin_scanner/guard/cli/__init__.py +0 -0
- {plugin_scanner-2.0.108 → plugin_scanner-2.0.109}/src/codex_plugin_scanner/guard/cli/approval_commands.py +0 -0
- {plugin_scanner-2.0.108 → plugin_scanner-2.0.109}/src/codex_plugin_scanner/guard/cli/bootstrap.py +0 -0
- {plugin_scanner-2.0.108 → plugin_scanner-2.0.109}/src/codex_plugin_scanner/guard/cli/connect_flow.py +0 -0
- {plugin_scanner-2.0.108 → plugin_scanner-2.0.109}/src/codex_plugin_scanner/guard/cli/install_commands.py +0 -0
- {plugin_scanner-2.0.108 → plugin_scanner-2.0.109}/src/codex_plugin_scanner/guard/cli/product.py +0 -0
- {plugin_scanner-2.0.108 → plugin_scanner-2.0.109}/src/codex_plugin_scanner/guard/cli/prompt.py +0 -0
- {plugin_scanner-2.0.108 → plugin_scanner-2.0.109}/src/codex_plugin_scanner/guard/cli/update_commands.py +0 -0
- {plugin_scanner-2.0.108 → plugin_scanner-2.0.109}/src/codex_plugin_scanner/guard/codex_config.py +0 -0
- {plugin_scanner-2.0.108 → plugin_scanner-2.0.109}/src/codex_plugin_scanner/guard/config.py +0 -0
- {plugin_scanner-2.0.108 → plugin_scanner-2.0.109}/src/codex_plugin_scanner/guard/consumer/__init__.py +0 -0
- {plugin_scanner-2.0.108 → plugin_scanner-2.0.109}/src/codex_plugin_scanner/guard/consumer/service.py +0 -0
- {plugin_scanner-2.0.108 → plugin_scanner-2.0.109}/src/codex_plugin_scanner/guard/daemon/__init__.py +0 -0
- {plugin_scanner-2.0.108 → plugin_scanner-2.0.109}/src/codex_plugin_scanner/guard/daemon/client.py +0 -0
- {plugin_scanner-2.0.108 → plugin_scanner-2.0.109}/src/codex_plugin_scanner/guard/daemon/manager.py +0 -0
- {plugin_scanner-2.0.108 → plugin_scanner-2.0.109}/src/codex_plugin_scanner/guard/daemon/server.py +0 -0
- {plugin_scanner-2.0.108 → plugin_scanner-2.0.109}/src/codex_plugin_scanner/guard/daemon/static/apple-touch-icon.png +0 -0
- {plugin_scanner-2.0.108 → plugin_scanner-2.0.109}/src/codex_plugin_scanner/guard/daemon/static/assets/guard-dashboard.js +0 -0
- {plugin_scanner-2.0.108 → plugin_scanner-2.0.109}/src/codex_plugin_scanner/guard/daemon/static/assets/index.css +0 -0
- {plugin_scanner-2.0.108 → plugin_scanner-2.0.109}/src/codex_plugin_scanner/guard/daemon/static/brand/Logo_Icon_Dark.png +0 -0
- {plugin_scanner-2.0.108 → plugin_scanner-2.0.109}/src/codex_plugin_scanner/guard/daemon/static/brand/Logo_Whole.png +0 -0
- {plugin_scanner-2.0.108 → plugin_scanner-2.0.109}/src/codex_plugin_scanner/guard/daemon/static/favicon-16x16.png +0 -0
- {plugin_scanner-2.0.108 → plugin_scanner-2.0.109}/src/codex_plugin_scanner/guard/daemon/static/favicon-32x32.png +0 -0
- {plugin_scanner-2.0.108 → plugin_scanner-2.0.109}/src/codex_plugin_scanner/guard/daemon/static/favicon.ico +0 -0
- {plugin_scanner-2.0.108 → plugin_scanner-2.0.109}/src/codex_plugin_scanner/guard/daemon/static/index.html +0 -0
- {plugin_scanner-2.0.108 → plugin_scanner-2.0.109}/src/codex_plugin_scanner/guard/edge_events.py +0 -0
- {plugin_scanner-2.0.108 → plugin_scanner-2.0.109}/src/codex_plugin_scanner/guard/incident.py +0 -0
- {plugin_scanner-2.0.108 → plugin_scanner-2.0.109}/src/codex_plugin_scanner/guard/launcher.py +0 -0
- {plugin_scanner-2.0.108 → plugin_scanner-2.0.109}/src/codex_plugin_scanner/guard/mcp_tool_calls.py +0 -0
- {plugin_scanner-2.0.108 → plugin_scanner-2.0.109}/src/codex_plugin_scanner/guard/models.py +0 -0
- {plugin_scanner-2.0.108 → plugin_scanner-2.0.109}/src/codex_plugin_scanner/guard/policy/__init__.py +0 -0
- {plugin_scanner-2.0.108 → plugin_scanner-2.0.109}/src/codex_plugin_scanner/guard/policy/engine.py +0 -0
- {plugin_scanner-2.0.108 → plugin_scanner-2.0.109}/src/codex_plugin_scanner/guard/protect.py +0 -0
- {plugin_scanner-2.0.108 → plugin_scanner-2.0.109}/src/codex_plugin_scanner/guard/proxy/__init__.py +0 -0
- {plugin_scanner-2.0.108 → plugin_scanner-2.0.109}/src/codex_plugin_scanner/guard/proxy/remote.py +0 -0
- {plugin_scanner-2.0.108 → plugin_scanner-2.0.109}/src/codex_plugin_scanner/guard/proxy/runtime_mcp.py +0 -0
- {plugin_scanner-2.0.108 → plugin_scanner-2.0.109}/src/codex_plugin_scanner/guard/proxy/stdio.py +0 -0
- {plugin_scanner-2.0.108 → plugin_scanner-2.0.109}/src/codex_plugin_scanner/guard/receipts/__init__.py +0 -0
- {plugin_scanner-2.0.108 → plugin_scanner-2.0.109}/src/codex_plugin_scanner/guard/receipts/manager.py +0 -0
- {plugin_scanner-2.0.108 → plugin_scanner-2.0.109}/src/codex_plugin_scanner/guard/redaction.py +0 -0
- {plugin_scanner-2.0.108 → plugin_scanner-2.0.109}/src/codex_plugin_scanner/guard/risk.py +0 -0
- {plugin_scanner-2.0.108 → plugin_scanner-2.0.109}/src/codex_plugin_scanner/guard/runtime/__init__.py +0 -0
- {plugin_scanner-2.0.108 → plugin_scanner-2.0.109}/src/codex_plugin_scanner/guard/runtime/actions.py +0 -0
- {plugin_scanner-2.0.108 → plugin_scanner-2.0.109}/src/codex_plugin_scanner/guard/runtime/decisions.py +0 -0
- {plugin_scanner-2.0.108 → plugin_scanner-2.0.109}/src/codex_plugin_scanner/guard/runtime/detectors.py +0 -0
- {plugin_scanner-2.0.108 → plugin_scanner-2.0.109}/src/codex_plugin_scanner/guard/runtime/runner.py +0 -0
- {plugin_scanner-2.0.108 → plugin_scanner-2.0.109}/src/codex_plugin_scanner/guard/runtime/secret_file_requests.py +0 -0
- {plugin_scanner-2.0.108 → plugin_scanner-2.0.109}/src/codex_plugin_scanner/guard/runtime/secret_sensitivity.py +0 -0
- {plugin_scanner-2.0.108 → plugin_scanner-2.0.109}/src/codex_plugin_scanner/guard/runtime/signals.py +0 -0
- {plugin_scanner-2.0.108 → plugin_scanner-2.0.109}/src/codex_plugin_scanner/guard/runtime/surface_server.py +0 -0
- {plugin_scanner-2.0.108 → plugin_scanner-2.0.109}/src/codex_plugin_scanner/guard/schemas/__init__.py +0 -0
- {plugin_scanner-2.0.108 → plugin_scanner-2.0.109}/src/codex_plugin_scanner/guard/schemas/consumer_mode.py +0 -0
- {plugin_scanner-2.0.108 → plugin_scanner-2.0.109}/src/codex_plugin_scanner/guard/schemas/guard_event_v1.py +0 -0
- {plugin_scanner-2.0.108 → plugin_scanner-2.0.109}/src/codex_plugin_scanner/guard/schemas/surface_server.py +0 -0
- {plugin_scanner-2.0.108 → plugin_scanner-2.0.109}/src/codex_plugin_scanner/guard/shims.py +0 -0
- {plugin_scanner-2.0.108 → plugin_scanner-2.0.109}/src/codex_plugin_scanner/guard/store.py +0 -0
- {plugin_scanner-2.0.108 → plugin_scanner-2.0.109}/src/codex_plugin_scanner/guard/store_approvals.py +0 -0
- {plugin_scanner-2.0.108 → plugin_scanner-2.0.109}/src/codex_plugin_scanner/guard/store_connect.py +0 -0
- {plugin_scanner-2.0.108 → plugin_scanner-2.0.109}/src/codex_plugin_scanner/guard/types.py +0 -0
- {plugin_scanner-2.0.108 → plugin_scanner-2.0.109}/src/codex_plugin_scanner/integrations/__init__.py +0 -0
- {plugin_scanner-2.0.108 → plugin_scanner-2.0.109}/src/codex_plugin_scanner/integrations/cisco_mcp_scanner.py +0 -0
- {plugin_scanner-2.0.108 → plugin_scanner-2.0.109}/src/codex_plugin_scanner/integrations/cisco_skill_scanner.py +0 -0
- {plugin_scanner-2.0.108 → plugin_scanner-2.0.109}/src/codex_plugin_scanner/lint_fixes.py +0 -0
- {plugin_scanner-2.0.108 → plugin_scanner-2.0.109}/src/codex_plugin_scanner/marketplace_support.py +0 -0
- {plugin_scanner-2.0.108 → plugin_scanner-2.0.109}/src/codex_plugin_scanner/models.py +0 -0
- {plugin_scanner-2.0.108 → plugin_scanner-2.0.109}/src/codex_plugin_scanner/path_support.py +0 -0
- {plugin_scanner-2.0.108 → plugin_scanner-2.0.109}/src/codex_plugin_scanner/policy.py +0 -0
- {plugin_scanner-2.0.108 → plugin_scanner-2.0.109}/src/codex_plugin_scanner/quality_artifact.py +0 -0
- {plugin_scanner-2.0.108 → plugin_scanner-2.0.109}/src/codex_plugin_scanner/repo_detect.py +0 -0
- {plugin_scanner-2.0.108 → plugin_scanner-2.0.109}/src/codex_plugin_scanner/reporting.py +0 -0
- {plugin_scanner-2.0.108 → plugin_scanner-2.0.109}/src/codex_plugin_scanner/rules/__init__.py +0 -0
- {plugin_scanner-2.0.108 → plugin_scanner-2.0.109}/src/codex_plugin_scanner/rules/registry.py +0 -0
- {plugin_scanner-2.0.108 → plugin_scanner-2.0.109}/src/codex_plugin_scanner/rules/specs.py +0 -0
- {plugin_scanner-2.0.108 → plugin_scanner-2.0.109}/src/codex_plugin_scanner/scanner.py +0 -0
- {plugin_scanner-2.0.108 → plugin_scanner-2.0.109}/src/codex_plugin_scanner/submission.py +0 -0
- {plugin_scanner-2.0.108 → plugin_scanner-2.0.109}/src/codex_plugin_scanner/suppressions.py +0 -0
- {plugin_scanner-2.0.108 → plugin_scanner-2.0.109}/src/codex_plugin_scanner/trust_domain_scoring.py +0 -0
- {plugin_scanner-2.0.108 → plugin_scanner-2.0.109}/src/codex_plugin_scanner/trust_helpers.py +0 -0
- {plugin_scanner-2.0.108 → plugin_scanner-2.0.109}/src/codex_plugin_scanner/trust_mcp_scoring.py +0 -0
- {plugin_scanner-2.0.108 → plugin_scanner-2.0.109}/src/codex_plugin_scanner/trust_models.py +0 -0
- {plugin_scanner-2.0.108 → plugin_scanner-2.0.109}/src/codex_plugin_scanner/trust_plugin_scoring.py +0 -0
- {plugin_scanner-2.0.108 → plugin_scanner-2.0.109}/src/codex_plugin_scanner/trust_scoring.py +0 -0
- {plugin_scanner-2.0.108 → plugin_scanner-2.0.109}/src/codex_plugin_scanner/trust_skill_scoring.py +0 -0
- {plugin_scanner-2.0.108 → plugin_scanner-2.0.109}/src/codex_plugin_scanner/trust_specs.py +0 -0
- {plugin_scanner-2.0.108 → plugin_scanner-2.0.109}/src/codex_plugin_scanner/verification.py +0 -0
- {plugin_scanner-2.0.108 → plugin_scanner-2.0.109}/tests/__init__.py +0 -0
- {plugin_scanner-2.0.108 → plugin_scanner-2.0.109}/tests/conftest.py +0 -0
- {plugin_scanner-2.0.108 → plugin_scanner-2.0.109}/tests/fixtures/__init__.py +0 -0
- {plugin_scanner-2.0.108 → plugin_scanner-2.0.109}/tests/fixtures/bad-plugin/.codex-plugin/plugin.json +0 -0
- {plugin_scanner-2.0.108 → plugin_scanner-2.0.109}/tests/fixtures/bad-plugin/.mcp.json +0 -0
- {plugin_scanner-2.0.108 → plugin_scanner-2.0.109}/tests/fixtures/bad-plugin/secrets.js +0 -0
- {plugin_scanner-2.0.108 → plugin_scanner-2.0.109}/tests/fixtures/claude-plugin-good/.claude-plugin/plugin.json +0 -0
- {plugin_scanner-2.0.108 → plugin_scanner-2.0.109}/tests/fixtures/claude-plugin-good/LICENSE +0 -0
- {plugin_scanner-2.0.108 → plugin_scanner-2.0.109}/tests/fixtures/claude-plugin-good/README.md +0 -0
- {plugin_scanner-2.0.108 → plugin_scanner-2.0.109}/tests/fixtures/claude-plugin-good/SECURITY.md +0 -0
- {plugin_scanner-2.0.108 → plugin_scanner-2.0.109}/tests/fixtures/claude-plugin-good/hooks/hooks.json +0 -0
- {plugin_scanner-2.0.108 → plugin_scanner-2.0.109}/tests/fixtures/claude-plugin-good/skills/example/SKILL.md +0 -0
- {plugin_scanner-2.0.108 → plugin_scanner-2.0.109}/tests/fixtures/code-quality-bad/evil.js +0 -0
- {plugin_scanner-2.0.108 → plugin_scanner-2.0.109}/tests/fixtures/code-quality-bad/inject.js +0 -0
- {plugin_scanner-2.0.108 → plugin_scanner-2.0.109}/tests/fixtures/gemini-extension-good/GEMINI.md +0 -0
- {plugin_scanner-2.0.108 → plugin_scanner-2.0.109}/tests/fixtures/gemini-extension-good/LICENSE +0 -0
- {plugin_scanner-2.0.108 → plugin_scanner-2.0.109}/tests/fixtures/gemini-extension-good/README.md +0 -0
- {plugin_scanner-2.0.108 → plugin_scanner-2.0.109}/tests/fixtures/gemini-extension-good/SECURITY.md +0 -0
- {plugin_scanner-2.0.108 → plugin_scanner-2.0.109}/tests/fixtures/gemini-extension-good/commands/hello.toml +0 -0
- {plugin_scanner-2.0.108 → plugin_scanner-2.0.109}/tests/fixtures/gemini-extension-good/gemini-extension.json +0 -0
- {plugin_scanner-2.0.108 → plugin_scanner-2.0.109}/tests/fixtures/good-plugin/.codex-plugin/plugin.json +0 -0
- {plugin_scanner-2.0.108 → plugin_scanner-2.0.109}/tests/fixtures/good-plugin/.codexignore +0 -0
- {plugin_scanner-2.0.108 → plugin_scanner-2.0.109}/tests/fixtures/good-plugin/LICENSE +0 -0
- {plugin_scanner-2.0.108 → plugin_scanner-2.0.109}/tests/fixtures/good-plugin/README.md +0 -0
- {plugin_scanner-2.0.108 → plugin_scanner-2.0.109}/tests/fixtures/good-plugin/SECURITY.md +0 -0
- {plugin_scanner-2.0.108 → plugin_scanner-2.0.109}/tests/fixtures/good-plugin/assets/icon.svg +0 -0
- {plugin_scanner-2.0.108 → plugin_scanner-2.0.109}/tests/fixtures/good-plugin/assets/logo.svg +0 -0
- {plugin_scanner-2.0.108 → plugin_scanner-2.0.109}/tests/fixtures/good-plugin/assets/screenshot.svg +0 -0
- {plugin_scanner-2.0.108 → plugin_scanner-2.0.109}/tests/fixtures/good-plugin/skills/example/SKILL.md +0 -0
- {plugin_scanner-2.0.108 → plugin_scanner-2.0.109}/tests/fixtures/guard-codex-malicious-mcp/.codex/config.toml +0 -0
- {plugin_scanner-2.0.108 → plugin_scanner-2.0.109}/tests/fixtures/hermes-plugin-evil/config.yaml +0 -0
- {plugin_scanner-2.0.108 → plugin_scanner-2.0.109}/tests/fixtures/hermes-plugin-evil/mcp_servers.json +0 -0
- {plugin_scanner-2.0.108 → plugin_scanner-2.0.109}/tests/fixtures/hermes-plugin-evil/skills/security/malicious/SKILL.md +0 -0
- {plugin_scanner-2.0.108 → plugin_scanner-2.0.109}/tests/fixtures/hermes-plugin-evil/skills/stealth/sneaky/SKILL.md +0 -0
- {plugin_scanner-2.0.108 → plugin_scanner-2.0.109}/tests/fixtures/hermes-plugin-evil/skills/stealth/sneaky/references/api-setup.md +0 -0
- {plugin_scanner-2.0.108 → plugin_scanner-2.0.109}/tests/fixtures/hermes-plugin-evil/skills/stealth/sneaky/scripts/deploy.sh +0 -0
- {plugin_scanner-2.0.108 → plugin_scanner-2.0.109}/tests/fixtures/hermes-plugin-evil/skills/utils/benign/SKILL.md +0 -0
- {plugin_scanner-2.0.108 → plugin_scanner-2.0.109}/tests/fixtures/malformed-json/.codex-plugin/plugin.json +0 -0
- {plugin_scanner-2.0.108 → plugin_scanner-2.0.109}/tests/fixtures/malicious-skill-plugin/.codex-plugin/plugin.json +0 -0
- {plugin_scanner-2.0.108 → plugin_scanner-2.0.109}/tests/fixtures/malicious-skill-plugin/.codexignore +0 -0
- {plugin_scanner-2.0.108 → plugin_scanner-2.0.109}/tests/fixtures/malicious-skill-plugin/LICENSE +0 -0
- {plugin_scanner-2.0.108 → plugin_scanner-2.0.109}/tests/fixtures/malicious-skill-plugin/README.md +0 -0
- {plugin_scanner-2.0.108 → plugin_scanner-2.0.109}/tests/fixtures/malicious-skill-plugin/SECURITY.md +0 -0
- {plugin_scanner-2.0.108 → plugin_scanner-2.0.109}/tests/fixtures/malicious-skill-plugin/skills/leaky-skill/SKILL.md +0 -0
- {plugin_scanner-2.0.108 → plugin_scanner-2.0.109}/tests/fixtures/mcp-canary-server.py +0 -0
- {plugin_scanner-2.0.108 → plugin_scanner-2.0.109}/tests/fixtures/minimal-plugin/.codex-plugin/plugin.json +0 -0
- {plugin_scanner-2.0.108 → plugin_scanner-2.0.109}/tests/fixtures/missing-fields/.codex-plugin/plugin.json +0 -0
- {plugin_scanner-2.0.108 → plugin_scanner-2.0.109}/tests/fixtures/mit-license/LICENSE +0 -0
- {plugin_scanner-2.0.108 → plugin_scanner-2.0.109}/tests/fixtures/multi-ecosystem-repo/codex-plugin/.codex-plugin/plugin.json +0 -0
- {plugin_scanner-2.0.108 → plugin_scanner-2.0.109}/tests/fixtures/multi-ecosystem-repo/codex-plugin/LICENSE +0 -0
- {plugin_scanner-2.0.108 → plugin_scanner-2.0.109}/tests/fixtures/multi-ecosystem-repo/codex-plugin/README.md +0 -0
- {plugin_scanner-2.0.108 → plugin_scanner-2.0.109}/tests/fixtures/multi-ecosystem-repo/codex-plugin/SECURITY.md +0 -0
- {plugin_scanner-2.0.108 → plugin_scanner-2.0.109}/tests/fixtures/multi-ecosystem-repo/gemini-ext/README.md +0 -0
- {plugin_scanner-2.0.108 → plugin_scanner-2.0.109}/tests/fixtures/multi-ecosystem-repo/gemini-ext/gemini-extension.json +0 -0
- {plugin_scanner-2.0.108 → plugin_scanner-2.0.109}/tests/fixtures/multi-plugin-repo/.agents/plugins/marketplace.json +0 -0
- {plugin_scanner-2.0.108 → plugin_scanner-2.0.109}/tests/fixtures/multi-plugin-repo/plugins/alpha-plugin/.codex-plugin/plugin.json +0 -0
- {plugin_scanner-2.0.108 → plugin_scanner-2.0.109}/tests/fixtures/multi-plugin-repo/plugins/alpha-plugin/.codexignore +0 -0
- {plugin_scanner-2.0.108 → plugin_scanner-2.0.109}/tests/fixtures/multi-plugin-repo/plugins/alpha-plugin/LICENSE +0 -0
- {plugin_scanner-2.0.108 → plugin_scanner-2.0.109}/tests/fixtures/multi-plugin-repo/plugins/alpha-plugin/README.md +0 -0
- {plugin_scanner-2.0.108 → plugin_scanner-2.0.109}/tests/fixtures/multi-plugin-repo/plugins/alpha-plugin/SECURITY.md +0 -0
- {plugin_scanner-2.0.108 → plugin_scanner-2.0.109}/tests/fixtures/multi-plugin-repo/plugins/alpha-plugin/skills/example/SKILL.md +0 -0
- {plugin_scanner-2.0.108 → plugin_scanner-2.0.109}/tests/fixtures/multi-plugin-repo/plugins/beta-plugin/.codex-plugin/plugin.json +0 -0
- {plugin_scanner-2.0.108 → plugin_scanner-2.0.109}/tests/fixtures/multi-plugin-repo/plugins/beta-plugin/skills/example/SKILL.md +0 -0
- {plugin_scanner-2.0.108 → plugin_scanner-2.0.109}/tests/fixtures/no-version/.codex-plugin/plugin.json +0 -0
- {plugin_scanner-2.0.108 → plugin_scanner-2.0.109}/tests/fixtures/opencode-good/.opencode/commands/hello.md +0 -0
- {plugin_scanner-2.0.108 → plugin_scanner-2.0.109}/tests/fixtures/opencode-good/.opencode/plugins/example.ts +0 -0
- {plugin_scanner-2.0.108 → plugin_scanner-2.0.109}/tests/fixtures/opencode-good/LICENSE +0 -0
- {plugin_scanner-2.0.108 → plugin_scanner-2.0.109}/tests/fixtures/opencode-good/README.md +0 -0
- {plugin_scanner-2.0.108 → plugin_scanner-2.0.109}/tests/fixtures/opencode-good/SECURITY.md +0 -0
- {plugin_scanner-2.0.108 → plugin_scanner-2.0.109}/tests/fixtures/opencode-good/opencode.jsonc +0 -0
- {plugin_scanner-2.0.108 → plugin_scanner-2.0.109}/tests/fixtures/skills-missing-dir/.codex-plugin/plugin.json +0 -0
- {plugin_scanner-2.0.108 → plugin_scanner-2.0.109}/tests/fixtures/skills-no-frontmatter/.codex-plugin/plugin.json +0 -0
- {plugin_scanner-2.0.108 → plugin_scanner-2.0.109}/tests/fixtures/skills-no-frontmatter/skills/bad-skill/SKILL.md +0 -0
- {plugin_scanner-2.0.108 → plugin_scanner-2.0.109}/tests/fixtures/with-marketplace/.codex-plugin/plugin.json +0 -0
- {plugin_scanner-2.0.108 → plugin_scanner-2.0.109}/tests/fixtures/with-marketplace/marketplace-broken.json +0 -0
- {plugin_scanner-2.0.108 → plugin_scanner-2.0.109}/tests/fixtures/with-marketplace/marketplace.json +0 -0
- {plugin_scanner-2.0.108 → plugin_scanner-2.0.109}/tests/test-trust-scoring.py +0 -0
- {plugin_scanner-2.0.108 → plugin_scanner-2.0.109}/tests/test-trust-specs.py +0 -0
- {plugin_scanner-2.0.108 → plugin_scanner-2.0.109}/tests/test_action_runner.py +0 -0
- {plugin_scanner-2.0.108 → plugin_scanner-2.0.109}/tests/test_best_practices.py +0 -0
- {plugin_scanner-2.0.108 → plugin_scanner-2.0.109}/tests/test_cisco_install_surfaces.py +0 -0
- {plugin_scanner-2.0.108 → plugin_scanner-2.0.109}/tests/test_code_quality.py +0 -0
- {plugin_scanner-2.0.108 → plugin_scanner-2.0.109}/tests/test_config.py +0 -0
- {plugin_scanner-2.0.108 → plugin_scanner-2.0.109}/tests/test_coverage_remaining.py +0 -0
- {plugin_scanner-2.0.108 → plugin_scanner-2.0.109}/tests/test_ecosystems.py +0 -0
- {plugin_scanner-2.0.108 → plugin_scanner-2.0.109}/tests/test_edge_cases.py +0 -0
- {plugin_scanner-2.0.108 → plugin_scanner-2.0.109}/tests/test_final_coverage.py +0 -0
- {plugin_scanner-2.0.108 → plugin_scanner-2.0.109}/tests/test_guard_access_graph.py +0 -0
- {plugin_scanner-2.0.108 → plugin_scanner-2.0.109}/tests/test_guard_approvals.py +0 -0
- {plugin_scanner-2.0.108 → plugin_scanner-2.0.109}/tests/test_guard_bootstrap.py +0 -0
- {plugin_scanner-2.0.108 → plugin_scanner-2.0.109}/tests/test_guard_capabilities.py +0 -0
- {plugin_scanner-2.0.108 → plugin_scanner-2.0.109}/tests/test_guard_claude_adapter.py +0 -0
- {plugin_scanner-2.0.108 → plugin_scanner-2.0.109}/tests/test_guard_codex_e2e.py +0 -0
- {plugin_scanner-2.0.108 → plugin_scanner-2.0.109}/tests/test_guard_codex_install.py +0 -0
- {plugin_scanner-2.0.108 → plugin_scanner-2.0.109}/tests/test_guard_codex_proxy.py +0 -0
- {plugin_scanner-2.0.108 → plugin_scanner-2.0.109}/tests/test_guard_config_paths.py +0 -0
- {plugin_scanner-2.0.108 → plugin_scanner-2.0.109}/tests/test_guard_connect_flow.py +0 -0
- {plugin_scanner-2.0.108 → plugin_scanner-2.0.109}/tests/test_guard_consumer_mode.py +0 -0
- {plugin_scanner-2.0.108 → plugin_scanner-2.0.109}/tests/test_guard_copilot_adapter.py +0 -0
- {plugin_scanner-2.0.108 → plugin_scanner-2.0.109}/tests/test_guard_copilot_proxy.py +0 -0
- {plugin_scanner-2.0.108 → plugin_scanner-2.0.109}/tests/test_guard_daemon_manager.py +0 -0
- {plugin_scanner-2.0.108 → plugin_scanner-2.0.109}/tests/test_guard_event_schema_v1.py +0 -0
- {plugin_scanner-2.0.108 → plugin_scanner-2.0.109}/tests/test_guard_events.py +0 -0
- {plugin_scanner-2.0.108 → plugin_scanner-2.0.109}/tests/test_guard_launch_env.py +0 -0
- {plugin_scanner-2.0.108 → plugin_scanner-2.0.109}/tests/test_guard_opencode_proxy.py +0 -0
- {plugin_scanner-2.0.108 → plugin_scanner-2.0.109}/tests/test_guard_protect.py +0 -0
- {plugin_scanner-2.0.108 → plugin_scanner-2.0.109}/tests/test_guard_render.py +0 -0
- {plugin_scanner-2.0.108 → plugin_scanner-2.0.109}/tests/test_guard_risk.py +0 -0
- {plugin_scanner-2.0.108 → plugin_scanner-2.0.109}/tests/test_guard_runtime_action_harnesses.py +0 -0
- {plugin_scanner-2.0.108 → plugin_scanner-2.0.109}/tests/test_guard_runtime_actions.py +0 -0
- {plugin_scanner-2.0.108 → plugin_scanner-2.0.109}/tests/test_guard_runtime_decisions.py +0 -0
- {plugin_scanner-2.0.108 → plugin_scanner-2.0.109}/tests/test_guard_runtime_detectors.py +0 -0
- {plugin_scanner-2.0.108 → plugin_scanner-2.0.109}/tests/test_guard_runtime_signals.py +0 -0
- {plugin_scanner-2.0.108 → plugin_scanner-2.0.109}/tests/test_guard_store_migrations.py +0 -0
- {plugin_scanner-2.0.108 → plugin_scanner-2.0.109}/tests/test_guard_surface_server.py +0 -0
- {plugin_scanner-2.0.108 → plugin_scanner-2.0.109}/tests/test_guard_verdicts.py +0 -0
- {plugin_scanner-2.0.108 → plugin_scanner-2.0.109}/tests/test_hermes_adapter.py +0 -0
- {plugin_scanner-2.0.108 → plugin_scanner-2.0.109}/tests/test_integration.py +0 -0
- {plugin_scanner-2.0.108 → plugin_scanner-2.0.109}/tests/test_lint_fixes.py +0 -0
- {plugin_scanner-2.0.108 → plugin_scanner-2.0.109}/tests/test_live_cisco_smoke.py +0 -0
- {plugin_scanner-2.0.108 → plugin_scanner-2.0.109}/tests/test_manifest.py +0 -0
- {plugin_scanner-2.0.108 → plugin_scanner-2.0.109}/tests/test_marketplace.py +0 -0
- {plugin_scanner-2.0.108 → plugin_scanner-2.0.109}/tests/test_mcp_security.py +0 -0
- {plugin_scanner-2.0.108 → plugin_scanner-2.0.109}/tests/test_openclaw_adapter.py +0 -0
- {plugin_scanner-2.0.108 → plugin_scanner-2.0.109}/tests/test_operational_security.py +0 -0
- {plugin_scanner-2.0.108 → plugin_scanner-2.0.109}/tests/test_policy.py +0 -0
- {plugin_scanner-2.0.108 → plugin_scanner-2.0.109}/tests/test_quality_artifact.py +0 -0
- {plugin_scanner-2.0.108 → plugin_scanner-2.0.109}/tests/test_rule_registry.py +0 -0
- {plugin_scanner-2.0.108 → plugin_scanner-2.0.109}/tests/test_scanner.py +0 -0
- {plugin_scanner-2.0.108 → plugin_scanner-2.0.109}/tests/test_schema_contracts.py +0 -0
- {plugin_scanner-2.0.108 → plugin_scanner-2.0.109}/tests/test_security.py +0 -0
- {plugin_scanner-2.0.108 → plugin_scanner-2.0.109}/tests/test_security_ops.py +0 -0
- {plugin_scanner-2.0.108 → plugin_scanner-2.0.109}/tests/test_skill_security.py +0 -0
- {plugin_scanner-2.0.108 → plugin_scanner-2.0.109}/tests/test_submission.py +0 -0
- {plugin_scanner-2.0.108 → plugin_scanner-2.0.109}/tests/test_trust_scoring.py +0 -0
- {plugin_scanner-2.0.108 → plugin_scanner-2.0.109}/tests/test_trust_specs.py +0 -0
- {plugin_scanner-2.0.108 → plugin_scanner-2.0.109}/tests/test_verification.py +0 -0
- {plugin_scanner-2.0.108 → plugin_scanner-2.0.109}/tests/test_versioning.py +0 -0
- {plugin_scanner-2.0.108 → plugin_scanner-2.0.109}/uv.lock +0 -0
|
@@ -1,6 +1,6 @@
|
|
|
1
1
|
Metadata-Version: 2.4
|
|
2
2
|
Name: plugin-scanner
|
|
3
|
-
Version: 2.0.
|
|
3
|
+
Version: 2.0.109
|
|
4
4
|
Summary: Lint, verify, and gate plugin ecosystems for maintainers, CI, and publish workflows.
|
|
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
|
|
@@ -302,33 +302,44 @@ The scanner evaluates only the surfaces a plugin actually exposes, then normaliz
|
|
|
302
302
|
|
|
303
303
|
```bash
|
|
304
304
|
# Scan a plugin directory
|
|
305
|
-
plugin-scanner ./my-plugin
|
|
305
|
+
plugin-scanner scan ./my-plugin
|
|
306
306
|
|
|
307
307
|
# Auto-detect all supported ecosystems inside a repo (default)
|
|
308
|
-
plugin-scanner ./plugins-repo --ecosystem auto
|
|
308
|
+
plugin-scanner scan ./plugins-repo --ecosystem auto
|
|
309
309
|
|
|
310
310
|
# Scan only Claude package surfaces
|
|
311
|
-
plugin-scanner ./plugins-repo --ecosystem claude
|
|
311
|
+
plugin-scanner scan ./plugins-repo --ecosystem claude
|
|
312
312
|
|
|
313
313
|
# List supported ecosystems
|
|
314
314
|
plugin-scanner --list-ecosystems
|
|
315
315
|
|
|
316
316
|
# Output JSON
|
|
317
|
-
plugin-scanner ./my-plugin --json
|
|
317
|
+
plugin-scanner scan ./my-plugin --format json
|
|
318
318
|
|
|
319
319
|
# Write a SARIF report for GitHub code scanning
|
|
320
|
-
plugin-scanner ./my-plugin --format sarif --output plugin-scanner.sarif
|
|
320
|
+
plugin-scanner scan ./my-plugin --format sarif --output plugin-scanner.sarif
|
|
321
321
|
|
|
322
322
|
# Fail CI on findings at or above high severity
|
|
323
|
-
plugin-scanner ./my-plugin --fail-on-severity high
|
|
323
|
+
plugin-scanner scan ./my-plugin --fail-on-severity high
|
|
324
324
|
|
|
325
325
|
# Require Cisco skill scanning with a strict policy
|
|
326
|
-
plugin-scanner ./my-plugin --cisco-skill-scan on --cisco-policy strict
|
|
326
|
+
plugin-scanner scan ./my-plugin --cisco-skill-scan on --cisco-policy strict
|
|
327
327
|
|
|
328
328
|
# Require optional Cisco MCP static analysis
|
|
329
|
-
plugin-scanner ./my-plugin --cisco-mcp-scan on
|
|
329
|
+
plugin-scanner scan ./my-plugin --cisco-mcp-scan on
|
|
330
330
|
```
|
|
331
331
|
|
|
332
|
+
Use the bare `plugin-scanner ./my-plugin` form only for compatibility with older automation. New scripts and docs should
|
|
333
|
+
prefer explicit subcommands so `scan`, `lint`, `verify`, `submit`, and `doctor` have predictable help, flags, and output.
|
|
334
|
+
|
|
335
|
+
| Need | Command | Output contract |
|
|
336
|
+
| :--- | :--- | :--- |
|
|
337
|
+
| Human release summary | `plugin-scanner scan ./my-plugin` | terminal summary first, optional JSON/Markdown/SARIF with `--format` |
|
|
338
|
+
| Rule-level authoring feedback | `plugin-scanner lint ./my-plugin` | human findings by default, JSON with `--format json` |
|
|
339
|
+
| Runtime readiness details | `plugin-scanner verify ./my-plugin` | human pass/fail by default, JSON with `--format json` |
|
|
340
|
+
| Publishable quality artifact | `plugin-scanner submit ./my-plugin --attest dist/plugin-quality.json` | writes one artifact for one plugin directory |
|
|
341
|
+
| Troubleshooting bundle | `plugin-scanner doctor ./my-plugin --component mcp --bundle dist/doctor.zip` | diagnostic JSON and bundle artifacts |
|
|
342
|
+
|
|
332
343
|
## Quality Suite Commands
|
|
333
344
|
|
|
334
345
|
```bash
|
|
@@ -262,33 +262,44 @@ The scanner evaluates only the surfaces a plugin actually exposes, then normaliz
|
|
|
262
262
|
|
|
263
263
|
```bash
|
|
264
264
|
# Scan a plugin directory
|
|
265
|
-
plugin-scanner ./my-plugin
|
|
265
|
+
plugin-scanner scan ./my-plugin
|
|
266
266
|
|
|
267
267
|
# Auto-detect all supported ecosystems inside a repo (default)
|
|
268
|
-
plugin-scanner ./plugins-repo --ecosystem auto
|
|
268
|
+
plugin-scanner scan ./plugins-repo --ecosystem auto
|
|
269
269
|
|
|
270
270
|
# Scan only Claude package surfaces
|
|
271
|
-
plugin-scanner ./plugins-repo --ecosystem claude
|
|
271
|
+
plugin-scanner scan ./plugins-repo --ecosystem claude
|
|
272
272
|
|
|
273
273
|
# List supported ecosystems
|
|
274
274
|
plugin-scanner --list-ecosystems
|
|
275
275
|
|
|
276
276
|
# Output JSON
|
|
277
|
-
plugin-scanner ./my-plugin --json
|
|
277
|
+
plugin-scanner scan ./my-plugin --format json
|
|
278
278
|
|
|
279
279
|
# Write a SARIF report for GitHub code scanning
|
|
280
|
-
plugin-scanner ./my-plugin --format sarif --output plugin-scanner.sarif
|
|
280
|
+
plugin-scanner scan ./my-plugin --format sarif --output plugin-scanner.sarif
|
|
281
281
|
|
|
282
282
|
# Fail CI on findings at or above high severity
|
|
283
|
-
plugin-scanner ./my-plugin --fail-on-severity high
|
|
283
|
+
plugin-scanner scan ./my-plugin --fail-on-severity high
|
|
284
284
|
|
|
285
285
|
# Require Cisco skill scanning with a strict policy
|
|
286
|
-
plugin-scanner ./my-plugin --cisco-skill-scan on --cisco-policy strict
|
|
286
|
+
plugin-scanner scan ./my-plugin --cisco-skill-scan on --cisco-policy strict
|
|
287
287
|
|
|
288
288
|
# Require optional Cisco MCP static analysis
|
|
289
|
-
plugin-scanner ./my-plugin --cisco-mcp-scan on
|
|
289
|
+
plugin-scanner scan ./my-plugin --cisco-mcp-scan on
|
|
290
290
|
```
|
|
291
291
|
|
|
292
|
+
Use the bare `plugin-scanner ./my-plugin` form only for compatibility with older automation. New scripts and docs should
|
|
293
|
+
prefer explicit subcommands so `scan`, `lint`, `verify`, `submit`, and `doctor` have predictable help, flags, and output.
|
|
294
|
+
|
|
295
|
+
| Need | Command | Output contract |
|
|
296
|
+
| :--- | :--- | :--- |
|
|
297
|
+
| Human release summary | `plugin-scanner scan ./my-plugin` | terminal summary first, optional JSON/Markdown/SARIF with `--format` |
|
|
298
|
+
| Rule-level authoring feedback | `plugin-scanner lint ./my-plugin` | human findings by default, JSON with `--format json` |
|
|
299
|
+
| Runtime readiness details | `plugin-scanner verify ./my-plugin` | human pass/fail by default, JSON with `--format json` |
|
|
300
|
+
| Publishable quality artifact | `plugin-scanner submit ./my-plugin --attest dist/plugin-quality.json` | writes one artifact for one plugin directory |
|
|
301
|
+
| Troubleshooting bundle | `plugin-scanner doctor ./my-plugin --component mcp --bundle dist/doctor.zip` | diagnostic JSON and bundle artifacts |
|
|
302
|
+
|
|
292
303
|
## Quality Suite Commands
|
|
293
304
|
|
|
294
305
|
```bash
|
|
@@ -76,6 +76,30 @@ Use it when you want to protect a harness before local MCP servers, skills, hook
|
|
|
76
76
|
hol-guard device rotate
|
|
77
77
|
```
|
|
78
78
|
|
|
79
|
+
## Which command should I use?
|
|
80
|
+
|
|
81
|
+
| Situation | Command | What it answers |
|
|
82
|
+
| :--- | :--- | :--- |
|
|
83
|
+
| I need the current protection posture | `hol-guard status` | What is Guard watching, is sync connected, and what is the next action? |
|
|
84
|
+
| I need setup or runtime troubleshooting | `hol-guard doctor <harness>` | Why is this harness or Guard runtime not behaving correctly? |
|
|
85
|
+
| A launch was blocked or changed | `hol-guard diff <harness>` | What changed since the last recorded snapshot? |
|
|
86
|
+
| I need to resolve a queued block | `hol-guard approvals` | Which requests are waiting, and how do I approve or deny them? |
|
|
87
|
+
| I need decision history | `hol-guard receipts` | What decisions did Guard record locally? |
|
|
88
|
+
| I need the tracked catalog | `hol-guard inventory` | Which artifacts are currently tracked and present? |
|
|
89
|
+
| I need an exportable evidence artifact | `hol-guard abom` | What local AI-BOM can I attach to an audit or handoff? |
|
|
90
|
+
| I need the chronological log | `hol-guard events` | What happened over time on this machine? |
|
|
91
|
+
|
|
92
|
+
## Troubleshooting
|
|
93
|
+
|
|
94
|
+
| Symptom | Start here | Then try |
|
|
95
|
+
| :--- | :--- | :--- |
|
|
96
|
+
| Guard did not find my harness | `hol-guard detect --json` | `hol-guard doctor <harness> --json` for adapter-specific warnings |
|
|
97
|
+
| `hol-guard run` paused a launch | `hol-guard diff <harness>` | `hol-guard approvals`, then retry `hol-guard run <harness>` |
|
|
98
|
+
| I approved a prompt and want proof | `hol-guard receipts` | `hol-guard explain <artifact-id>` for the latest receipt and diff context |
|
|
99
|
+
| I need audit or handoff evidence | `hol-guard inventory` | `hol-guard abom --format json` for machine-readable export |
|
|
100
|
+
| I need to understand recent activity | `hol-guard events` | Use `--name <event>` to filter a noisy local timeline |
|
|
101
|
+
| Cloud sync or pairing looks wrong | `hol-guard status` | `hol-guard connect` or `hol-guard sync --json` depending on the status output |
|
|
102
|
+
|
|
79
103
|
## Evidence-first decisions
|
|
80
104
|
|
|
81
105
|
Guard now scores local decisions from structured evidence, not only string heuristics. Each changed artifact carries:
|
|
@@ -10,6 +10,8 @@ Automated coverage in this phase includes:
|
|
|
10
10
|
- consumer-mode JSON contract generation against scanner fixtures
|
|
11
11
|
- local HTTP sync against a live in-process server instead of mocked transport
|
|
12
12
|
- scheduled self-hosted harness smoke through `.github/workflows/harness-smoke.yml`
|
|
13
|
+
- CLI DX contract tests for summary-first `run`, `explain`, `doctor`, `scan`, `lint`, and `verify` output
|
|
14
|
+
- scanner command consistency tests for nonexistent target handling across `scan`, `lint`, `verify`, `doctor`, and `submit`
|
|
13
15
|
|
|
14
16
|
Manual verification should include:
|
|
15
17
|
|
|
@@ -32,6 +34,14 @@ Manual verification should include:
|
|
|
32
34
|
- `hol-guard install codex`
|
|
33
35
|
- `hol-guard run codex --dry-run --default-action allow --json`
|
|
34
36
|
- `hol-guard receipts`
|
|
37
|
+
- `hol-guard explain codex:project:<artifact-name>`
|
|
38
|
+
- `hol-guard diff codex`
|
|
39
|
+
- `hol-guard events`
|
|
40
|
+
- `hol-guard abom`
|
|
41
|
+
- `plugin-scanner scan tests/fixtures/good-plugin --format json`
|
|
42
|
+
- `plugin-scanner lint tests/fixtures/good-plugin --format json`
|
|
43
|
+
- `plugin-scanner verify tests/fixtures/good-plugin --format json`
|
|
44
|
+
- `plugin-scanner doctor tests/fixtures/good-plugin --component mcp --bundle dist/doctor.zip`
|
|
35
45
|
- `codex mcp list`
|
|
36
46
|
- `cursor-agent mcp list`
|
|
37
47
|
- `antigravity --help`
|
|
@@ -4,7 +4,7 @@ build-backend = "hatchling.build"
|
|
|
4
4
|
|
|
5
5
|
[project]
|
|
6
6
|
name = "plugin-scanner"
|
|
7
|
-
version = "2.0.
|
|
7
|
+
version = "2.0.109"
|
|
8
8
|
description = "Lint, verify, and gate plugin ecosystems for maintainers, CI, and publish workflows."
|
|
9
9
|
readme = "README.md"
|
|
10
10
|
license = "Apache-2.0"
|
|
@@ -4,7 +4,7 @@ build-backend = "hatchling.build"
|
|
|
4
4
|
|
|
5
5
|
[project]
|
|
6
6
|
name = "hol-guard"
|
|
7
|
-
version = "2.0.
|
|
7
|
+
version = "2.0.109"
|
|
8
8
|
description = "Protect local AI harnesses with HOL Guard and run scanner checks for Codex, Claude, Cursor, Gemini, and OpenCode."
|
|
9
9
|
readme = "README.md"
|
|
10
10
|
license = "Apache-2.0"
|
{plugin_scanner-2.0.108 → plugin_scanner-2.0.109}/src/codex_plugin_scanner/guard/cli/commands.py
RENAMED
|
@@ -150,7 +150,15 @@ _GUARD_HELP_GROUPS = (
|
|
|
150
150
|
" bootstrap Detect, install, and launch the approval center\n"
|
|
151
151
|
" install Enable Guard management for a harness\n"
|
|
152
152
|
" uninstall Disable Guard management for a harness\n"
|
|
153
|
-
" update Update hol-guard in the current environment"
|
|
153
|
+
" update Update hol-guard in the current environment\n"
|
|
154
|
+
"\n"
|
|
155
|
+
"Command selection:\n"
|
|
156
|
+
" Use status for current posture and the next safe step\n"
|
|
157
|
+
" Use doctor for setup and runtime probes\n"
|
|
158
|
+
" Use diff for changed artifacts after a blocked launch\n"
|
|
159
|
+
" Use explain for detailed artifact evidence\n"
|
|
160
|
+
" Use approvals for queued decisions and receipts for audit history\n"
|
|
161
|
+
" Use events for the local timeline"
|
|
154
162
|
)
|
|
155
163
|
|
|
156
164
|
|
{plugin_scanner-2.0.108 → plugin_scanner-2.0.109}/src/codex_plugin_scanner/guard/cli/render.py
RENAMED
|
@@ -285,37 +285,37 @@ def _render_doctor(console: Console, payload: dict[str, object]) -> None:
|
|
|
285
285
|
)
|
|
286
286
|
adapters = _coerce_dict_list(payload.get("adapters"))
|
|
287
287
|
console.print(_build_harness_table(adapters))
|
|
288
|
-
|
|
289
|
-
|
|
290
|
-
|
|
291
|
-
|
|
292
|
-
|
|
293
|
-
|
|
294
|
-
|
|
295
|
-
|
|
296
|
-
|
|
297
|
-
|
|
298
|
-
|
|
299
|
-
|
|
300
|
-
summary.add_row("
|
|
301
|
-
|
|
302
|
-
|
|
303
|
-
|
|
304
|
-
|
|
305
|
-
|
|
306
|
-
|
|
307
|
-
|
|
308
|
-
|
|
288
|
+
else:
|
|
289
|
+
warnings = _coerce_string_list(payload.get("warnings"))
|
|
290
|
+
summary = Table.grid(padding=(0, 1))
|
|
291
|
+
summary.add_row("Harness", f"[bold]{payload.get('harness', 'unknown')}[/bold]")
|
|
292
|
+
summary.add_row("Installed", _bool_label(bool(payload.get("installed"))))
|
|
293
|
+
summary.add_row("Command", _bool_label(bool(payload.get("command_available"))))
|
|
294
|
+
summary.add_row("Artifacts", str(len(_coerce_dict_list(payload.get("artifacts")))))
|
|
295
|
+
registry = payload.get("runtime_detector_registry")
|
|
296
|
+
if isinstance(registry, dict):
|
|
297
|
+
registry_state = "enabled" if bool(registry.get("enabled")) else "disabled"
|
|
298
|
+
timeout_ms = registry.get("timeout_ms")
|
|
299
|
+
summary.add_row("Detector registry", f"{registry_state}, {timeout_ms} ms")
|
|
300
|
+
summary.add_row("Warnings", str(len(warnings)))
|
|
301
|
+
console.print(Panel(summary, title="Guard doctor", border_style="cyan"))
|
|
302
|
+
if warnings:
|
|
303
|
+
warning_text = "\n".join(
|
|
304
|
+
textwrap.fill(
|
|
305
|
+
f"• {warning}",
|
|
306
|
+
width=72,
|
|
307
|
+
subsequent_indent=" ",
|
|
308
|
+
)
|
|
309
|
+
for warning in warnings
|
|
309
310
|
)
|
|
310
|
-
|
|
311
|
-
)
|
|
312
|
-
|
|
313
|
-
|
|
314
|
-
|
|
315
|
-
|
|
316
|
-
|
|
317
|
-
|
|
318
|
-
console.print(_build_artifact_table(artifacts))
|
|
311
|
+
console.print(Panel(Text(warning_text), title="Attention", border_style="yellow"))
|
|
312
|
+
runtime_probe = payload.get("runtime_probe")
|
|
313
|
+
if isinstance(runtime_probe, dict):
|
|
314
|
+
console.print(_build_runtime_probe_panel(runtime_probe))
|
|
315
|
+
artifacts = _coerce_dict_list(payload.get("artifacts"))
|
|
316
|
+
if artifacts:
|
|
317
|
+
console.print(_build_artifact_table(artifacts))
|
|
318
|
+
console.print(_build_diagnostic_command_panel())
|
|
319
319
|
|
|
320
320
|
|
|
321
321
|
def _render_run(console: Console, payload: dict[str, object]) -> None:
|
|
@@ -481,7 +481,11 @@ def _render_advisories(console: Console, payload: dict[str, object]) -> None:
|
|
|
481
481
|
border_style="cyan",
|
|
482
482
|
)
|
|
483
483
|
)
|
|
484
|
-
|
|
484
|
+
console.print(_build_advisory_table(items))
|
|
485
|
+
|
|
486
|
+
|
|
487
|
+
def _build_advisory_table(items: list[dict[str, object]], *, title: str | None = None) -> Table:
|
|
488
|
+
table = Table(title=title, box=box.SIMPLE_HEAVY, show_header=True)
|
|
485
489
|
table.add_column("Publisher", style="bold")
|
|
486
490
|
table.add_column("Severity")
|
|
487
491
|
table.add_column("Headline")
|
|
@@ -493,7 +497,7 @@ def _render_advisories(console: Console, payload: dict[str, object]) -> None:
|
|
|
493
497
|
str(item.get("headline") or item.get("cache_key") or "advisory"),
|
|
494
498
|
str(item.get("updated_at") or "unknown"),
|
|
495
499
|
)
|
|
496
|
-
|
|
500
|
+
return table
|
|
497
501
|
|
|
498
502
|
|
|
499
503
|
def _render_events(console: Console, payload: dict[str, object]) -> None:
|
|
@@ -1077,6 +1081,40 @@ def _render_scan(console: Console, payload: dict[str, object]) -> None:
|
|
|
1077
1081
|
_render_cisco_evidence(console, payload)
|
|
1078
1082
|
|
|
1079
1083
|
|
|
1084
|
+
def _render_explain(console: Console, payload: dict[str, object]) -> None:
|
|
1085
|
+
advisories = _coerce_dict_list(payload.get("advisories"))
|
|
1086
|
+
if "artifact_snapshot" in payload:
|
|
1087
|
+
console.print(Panel(_build_consumer_summary_table(payload), title="Path evidence", border_style="cyan"))
|
|
1088
|
+
_render_consumer_evidence_panels(console, payload)
|
|
1089
|
+
_render_cisco_evidence(console, payload)
|
|
1090
|
+
if advisories:
|
|
1091
|
+
console.print(_build_advisory_table(advisories, title="Matching advisories"))
|
|
1092
|
+
return
|
|
1093
|
+
artifact = payload.get("artifact")
|
|
1094
|
+
if not isinstance(artifact, dict):
|
|
1095
|
+
_render_fallback(console, payload)
|
|
1096
|
+
return
|
|
1097
|
+
latest_receipt = payload.get("latest_receipt")
|
|
1098
|
+
latest_diff = payload.get("latest_diff")
|
|
1099
|
+
body = Table.grid(padding=(0, 1))
|
|
1100
|
+
body.add_row("Artifact", str(artifact.get("artifact_name") or artifact.get("artifact_id") or "unknown"))
|
|
1101
|
+
body.add_row("Harness", str(artifact.get("harness") or "unknown"))
|
|
1102
|
+
body.add_row("Type", str(artifact.get("artifact_type") or "artifact"))
|
|
1103
|
+
body.add_row("Scope", str(artifact.get("source_scope") or "unknown"))
|
|
1104
|
+
body.add_row("Present", _bool_label(bool(artifact.get("present"))))
|
|
1105
|
+
if isinstance(latest_receipt, dict):
|
|
1106
|
+
body.add_row("Latest decision", _action_text(str(latest_receipt.get("policy_decision") or "warn")))
|
|
1107
|
+
body.add_row("Receipt time", str(latest_receipt.get("timestamp") or "unknown"))
|
|
1108
|
+
if isinstance(latest_diff, dict):
|
|
1109
|
+
changed_fields = ", ".join(_coerce_string_list(latest_diff.get("changed_fields"))) or "no field changes"
|
|
1110
|
+
body.add_row("Latest diff", changed_fields)
|
|
1111
|
+
body.add_row("Current hash", str(latest_diff.get("current_hash") or "unknown"))
|
|
1112
|
+
body.add_row("Advisories", str(len(advisories)))
|
|
1113
|
+
console.print(Panel(body, title="Guard artifact evidence", border_style="cyan"))
|
|
1114
|
+
if advisories:
|
|
1115
|
+
console.print(_build_advisory_table(advisories, title="Matching advisories"))
|
|
1116
|
+
|
|
1117
|
+
|
|
1080
1118
|
def _render_preflight(console: Console, payload: dict[str, object]) -> None:
|
|
1081
1119
|
install_verdict = payload.get("install_verdict")
|
|
1082
1120
|
install_target = payload.get("install_target")
|
|
@@ -1209,6 +1247,21 @@ def _build_steps_panel(steps: list[dict[str, object]]) -> Panel:
|
|
|
1209
1247
|
return Panel("\n\n".join(lines), title="Next steps", border_style="green")
|
|
1210
1248
|
|
|
1211
1249
|
|
|
1250
|
+
def _build_diagnostic_command_panel() -> Panel:
|
|
1251
|
+
return Panel(
|
|
1252
|
+
"\n".join(
|
|
1253
|
+
(
|
|
1254
|
+
"Use status for current posture: hol-guard status",
|
|
1255
|
+
"Use doctor for setup and runtime probes: hol-guard doctor <harness>",
|
|
1256
|
+
"Use diff for changed artifacts: hol-guard diff <harness>",
|
|
1257
|
+
"Use events for the local timeline: hol-guard events",
|
|
1258
|
+
)
|
|
1259
|
+
),
|
|
1260
|
+
title="Which diagnostic command?",
|
|
1261
|
+
border_style="blue",
|
|
1262
|
+
)
|
|
1263
|
+
|
|
1264
|
+
|
|
1212
1265
|
def _render_harness_detail(console: Console, detection: dict[str, object]) -> None:
|
|
1213
1266
|
artifacts = _coerce_dict_list(detection.get("artifacts"))
|
|
1214
1267
|
warnings = _coerce_string_list(detection.get("warnings"))
|
|
@@ -1308,13 +1361,7 @@ def _build_run_steps(payload: dict[str, object], *, blocked: bool, dry_run: bool
|
|
|
1308
1361
|
approvals_command = payload.get("approvals_command")
|
|
1309
1362
|
if blocked and dry_run:
|
|
1310
1363
|
review_command = (
|
|
1311
|
-
str(
|
|
1312
|
-
if approval_center_url and isinstance(approvals_command, str) and approvals_command
|
|
1313
|
-
else "hol-guard approvals"
|
|
1314
|
-
if approval_center_url
|
|
1315
|
-
else str(rerun_command)
|
|
1316
|
-
if isinstance(rerun_command, str) and rerun_command
|
|
1317
|
-
else f"hol-guard run {harness}"
|
|
1364
|
+
str(rerun_command) if isinstance(rerun_command, str) and rerun_command else f"hol-guard run {harness}"
|
|
1318
1365
|
)
|
|
1319
1366
|
inspect_command = (
|
|
1320
1367
|
str(diff_command) if isinstance(diff_command, str) and diff_command else f"hol-guard diff {harness}"
|
|
@@ -1324,12 +1371,29 @@ def _build_run_steps(payload: dict[str, object], *, blocked: bool, dry_run: bool
|
|
|
1324
1371
|
if isinstance(review_hint, str) and review_hint
|
|
1325
1372
|
else "Rerun without --dry-run to review the full blocker set and continue into the harness launch."
|
|
1326
1373
|
)
|
|
1327
|
-
|
|
1374
|
+
steps = [
|
|
1328
1375
|
{
|
|
1329
1376
|
"title": "Resolve the blocked launch",
|
|
1330
1377
|
"command": review_command,
|
|
1331
1378
|
"detail": review_detail,
|
|
1332
1379
|
},
|
|
1380
|
+
]
|
|
1381
|
+
if approval_center_url:
|
|
1382
|
+
approval_command = (
|
|
1383
|
+
str(approvals_command)
|
|
1384
|
+
if isinstance(approvals_command, str) and approvals_command
|
|
1385
|
+
else "hol-guard approvals"
|
|
1386
|
+
)
|
|
1387
|
+
steps.append(
|
|
1388
|
+
{
|
|
1389
|
+
"title": "Open the approvals queue",
|
|
1390
|
+
"command": approval_command,
|
|
1391
|
+
"detail": (
|
|
1392
|
+
"Review any queued approval requests after the prompt appears, then retry the guarded command."
|
|
1393
|
+
),
|
|
1394
|
+
}
|
|
1395
|
+
)
|
|
1396
|
+
steps.append(
|
|
1333
1397
|
{
|
|
1334
1398
|
"title": "Inspect only the changed config entries (optional)",
|
|
1335
1399
|
"command": inspect_command,
|
|
@@ -1338,17 +1402,19 @@ def _build_run_steps(payload: dict[str, object], *, blocked: bool, dry_run: bool
|
|
|
1338
1402
|
"Guard still needs you to review."
|
|
1339
1403
|
),
|
|
1340
1404
|
},
|
|
1341
|
-
]
|
|
1342
|
-
if blocked and isinstance(review_hint, str) and review_hint:
|
|
1343
|
-
command = (
|
|
1344
|
-
str(approvals_command)
|
|
1345
|
-
if approval_center_url and isinstance(approvals_command, str) and approvals_command
|
|
1346
|
-
else "hol-guard approvals"
|
|
1347
|
-
if approval_center_url
|
|
1348
|
-
else str(rerun_command)
|
|
1349
|
-
if isinstance(rerun_command, str) and rerun_command
|
|
1350
|
-
else f"hol-guard run {harness}"
|
|
1351
1405
|
)
|
|
1406
|
+
return steps
|
|
1407
|
+
if blocked and isinstance(review_hint, str) and review_hint:
|
|
1408
|
+
if approval_center_url:
|
|
1409
|
+
command = (
|
|
1410
|
+
str(approvals_command)
|
|
1411
|
+
if isinstance(approvals_command, str) and approvals_command
|
|
1412
|
+
else "hol-guard approvals"
|
|
1413
|
+
)
|
|
1414
|
+
elif isinstance(rerun_command, str) and rerun_command:
|
|
1415
|
+
command = str(rerun_command)
|
|
1416
|
+
else:
|
|
1417
|
+
command = f"hol-guard run {harness}"
|
|
1352
1418
|
return [{"title": "Resolve the blocked launch", "command": command, "detail": review_hint}]
|
|
1353
1419
|
if dry_run:
|
|
1354
1420
|
launch_command = (
|
|
@@ -1749,5 +1815,5 @@ _RENDERERS: dict[str, Any] = {
|
|
|
1749
1815
|
"protect": _render_protect,
|
|
1750
1816
|
"preflight": _render_preflight,
|
|
1751
1817
|
"scan": _render_scan,
|
|
1752
|
-
"explain":
|
|
1818
|
+
"explain": _render_explain,
|
|
1753
1819
|
}
|
|
@@ -162,6 +162,42 @@ class TestMain:
|
|
|
162
162
|
rc = main(["/nonexistent/path/that/does/not/exist"])
|
|
163
163
|
assert rc == 1
|
|
164
164
|
|
|
165
|
+
def test_scan_and_lint_reject_nonexistent_directory_consistently(self, capsys):
|
|
166
|
+
scan_rc = main(["scan", str(NONEXISTENT_PLUGIN_DIR), "--format", "json"])
|
|
167
|
+
scan_captured = capsys.readouterr()
|
|
168
|
+
|
|
169
|
+
lint_rc = main(["lint", str(NONEXISTENT_PLUGIN_DIR), "--format", "json"])
|
|
170
|
+
lint_captured = capsys.readouterr()
|
|
171
|
+
|
|
172
|
+
expected = f'Error: "{NONEXISTENT_PLUGIN_DIR}" is not a directory.'
|
|
173
|
+
assert scan_rc == 1
|
|
174
|
+
assert lint_rc == 1
|
|
175
|
+
assert expected in scan_captured.err
|
|
176
|
+
assert expected in lint_captured.err
|
|
177
|
+
assert scan_captured.out == ""
|
|
178
|
+
assert lint_captured.out == ""
|
|
179
|
+
|
|
180
|
+
def test_scanner_human_outputs_stay_summary_first(self, capsys):
|
|
181
|
+
scan_rc = main(["scan", str(FIXTURES / "good-plugin")])
|
|
182
|
+
scan_output = capsys.readouterr().out
|
|
183
|
+
|
|
184
|
+
lint_rc = main(["lint", str(FIXTURES / "good-plugin")])
|
|
185
|
+
lint_output = capsys.readouterr().out
|
|
186
|
+
|
|
187
|
+
verify_rc = main(["verify", str(FIXTURES / "good-plugin")])
|
|
188
|
+
verify_output = capsys.readouterr().out
|
|
189
|
+
|
|
190
|
+
assert scan_rc == 0
|
|
191
|
+
assert lint_rc == 0
|
|
192
|
+
assert verify_rc == 0
|
|
193
|
+
assert "Plugin Scanner" in scan_output
|
|
194
|
+
assert "Final Score" in scan_output
|
|
195
|
+
assert "Lint profile" in lint_output
|
|
196
|
+
assert "Verification: PASS" in verify_output
|
|
197
|
+
assert '"schema_version"' not in scan_output
|
|
198
|
+
assert '"policy_pass"' not in lint_output
|
|
199
|
+
assert '"verify_pass"' not in verify_output
|
|
200
|
+
|
|
165
201
|
def test_invalid_top_level_command_suggests_closest_match(self, capsys):
|
|
166
202
|
with pytest.raises(SystemExit) as exc_info:
|
|
167
203
|
main(["verfy"])
|