plugin-scanner 2.0.102__tar.gz → 2.0.104__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.
Files changed (349) hide show
  1. {plugin_scanner-2.0.102 → plugin_scanner-2.0.104}/PKG-INFO +1 -1
  2. {plugin_scanner-2.0.102 → plugin_scanner-2.0.104}/dashboard/src/approval-center-layout.tsx +14 -18
  3. {plugin_scanner-2.0.102 → plugin_scanner-2.0.104}/dashboard/src/approval-center-utils.ts +30 -0
  4. {plugin_scanner-2.0.102 → plugin_scanner-2.0.104}/dashboard/src/guard-api.test.ts +141 -3
  5. {plugin_scanner-2.0.102 → plugin_scanner-2.0.104}/dashboard/src/guard-api.ts +112 -4
  6. {plugin_scanner-2.0.102 → plugin_scanner-2.0.104}/dashboard/src/guard-types.ts +57 -0
  7. {plugin_scanner-2.0.102 → plugin_scanner-2.0.104}/pyproject.toml +1 -1
  8. {plugin_scanner-2.0.102 → plugin_scanner-2.0.104}/pyproject.toml.bak +1 -1
  9. {plugin_scanner-2.0.102 → plugin_scanner-2.0.104}/src/codex_plugin_scanner/guard/cli/commands.py +3 -4
  10. {plugin_scanner-2.0.102 → plugin_scanner-2.0.104}/src/codex_plugin_scanner/guard/config.py +22 -0
  11. plugin_scanner-2.0.104/src/codex_plugin_scanner/guard/daemon/static/assets/guard-dashboard.js +9 -0
  12. plugin_scanner-2.0.104/src/codex_plugin_scanner/guard/runtime/detectors.py +148 -0
  13. {plugin_scanner-2.0.102 → plugin_scanner-2.0.104}/src/codex_plugin_scanner/guard/runtime/runner.py +37 -0
  14. {plugin_scanner-2.0.102 → plugin_scanner-2.0.104}/src/codex_plugin_scanner/version.py +1 -1
  15. {plugin_scanner-2.0.102 → plugin_scanner-2.0.104}/tests/test_guard_config_paths.py +21 -0
  16. {plugin_scanner-2.0.102 → plugin_scanner-2.0.104}/tests/test_guard_runtime.py +38 -0
  17. plugin_scanner-2.0.104/tests/test_guard_runtime_detectors.py +295 -0
  18. plugin_scanner-2.0.102/src/codex_plugin_scanner/guard/daemon/static/assets/guard-dashboard.js +0 -9
  19. {plugin_scanner-2.0.102 → plugin_scanner-2.0.104}/.clusterfuzzlite/Dockerfile +0 -0
  20. {plugin_scanner-2.0.102 → plugin_scanner-2.0.104}/.clusterfuzzlite/build.sh +0 -0
  21. {plugin_scanner-2.0.102 → plugin_scanner-2.0.104}/.clusterfuzzlite/project.yaml +0 -0
  22. {plugin_scanner-2.0.102 → plugin_scanner-2.0.104}/.clusterfuzzlite/requirements-atheris.txt +0 -0
  23. {plugin_scanner-2.0.102 → plugin_scanner-2.0.104}/.dockerignore +0 -0
  24. {plugin_scanner-2.0.102 → plugin_scanner-2.0.104}/.github/CODEOWNERS +0 -0
  25. {plugin_scanner-2.0.102 → plugin_scanner-2.0.104}/.github/ISSUE_TEMPLATE/bug-report.yml +0 -0
  26. {plugin_scanner-2.0.102 → plugin_scanner-2.0.104}/.github/ISSUE_TEMPLATE/config.yml +0 -0
  27. {plugin_scanner-2.0.102 → plugin_scanner-2.0.104}/.github/ISSUE_TEMPLATE/feature-request.yml +0 -0
  28. {plugin_scanner-2.0.102 → plugin_scanner-2.0.104}/.github/dependabot.yml +0 -0
  29. {plugin_scanner-2.0.102 → plugin_scanner-2.0.104}/.github/workflows/ci.yml +0 -0
  30. {plugin_scanner-2.0.102 → plugin_scanner-2.0.104}/.github/workflows/codeql.yml +0 -0
  31. {plugin_scanner-2.0.102 → plugin_scanner-2.0.104}/.github/workflows/dependabot-uv-lock.yml +0 -0
  32. {plugin_scanner-2.0.102 → plugin_scanner-2.0.104}/.github/workflows/fuzz.yml +0 -0
  33. {plugin_scanner-2.0.102 → plugin_scanner-2.0.104}/.github/workflows/harness-smoke.yml +0 -0
  34. {plugin_scanner-2.0.102 → plugin_scanner-2.0.104}/.github/workflows/publish.yml +0 -0
  35. {plugin_scanner-2.0.102 → plugin_scanner-2.0.104}/.github/workflows/scorecard.yml +0 -0
  36. {plugin_scanner-2.0.102 → plugin_scanner-2.0.104}/.gitignore +0 -0
  37. {plugin_scanner-2.0.102 → plugin_scanner-2.0.104}/.pre-commit-hooks.yaml +0 -0
  38. {plugin_scanner-2.0.102 → plugin_scanner-2.0.104}/CONTRIBUTING.md +0 -0
  39. {plugin_scanner-2.0.102 → plugin_scanner-2.0.104}/Dockerfile +0 -0
  40. {plugin_scanner-2.0.102 → plugin_scanner-2.0.104}/LICENSE +0 -0
  41. {plugin_scanner-2.0.102 → plugin_scanner-2.0.104}/README.md +0 -0
  42. {plugin_scanner-2.0.102 → plugin_scanner-2.0.104}/SECURITY.md +0 -0
  43. {plugin_scanner-2.0.102 → plugin_scanner-2.0.104}/dashboard/index.html +0 -0
  44. {plugin_scanner-2.0.102 → plugin_scanner-2.0.104}/dashboard/package.json +0 -0
  45. {plugin_scanner-2.0.102 → plugin_scanner-2.0.104}/dashboard/pnpm-lock.yaml +0 -0
  46. {plugin_scanner-2.0.102 → plugin_scanner-2.0.104}/dashboard/public/apple-touch-icon.png +0 -0
  47. {plugin_scanner-2.0.102 → plugin_scanner-2.0.104}/dashboard/public/brand/Logo_Icon_Dark.png +0 -0
  48. {plugin_scanner-2.0.102 → plugin_scanner-2.0.104}/dashboard/public/brand/Logo_Whole.png +0 -0
  49. {plugin_scanner-2.0.102 → plugin_scanner-2.0.104}/dashboard/public/favicon-16x16.png +0 -0
  50. {plugin_scanner-2.0.102 → plugin_scanner-2.0.104}/dashboard/public/favicon-32x32.png +0 -0
  51. {plugin_scanner-2.0.102 → plugin_scanner-2.0.104}/dashboard/public/favicon.ico +0 -0
  52. {plugin_scanner-2.0.102 → plugin_scanner-2.0.104}/dashboard/src/app.tsx +0 -0
  53. {plugin_scanner-2.0.102 → plugin_scanner-2.0.104}/dashboard/src/approval-center-primitives.tsx +0 -0
  54. {plugin_scanner-2.0.102 → plugin_scanner-2.0.104}/dashboard/src/fleet-workspace.tsx +0 -0
  55. {plugin_scanner-2.0.102 → plugin_scanner-2.0.104}/dashboard/src/guard-demo.ts +0 -0
  56. {plugin_scanner-2.0.102 → plugin_scanner-2.0.104}/dashboard/src/main.tsx +0 -0
  57. {plugin_scanner-2.0.102 → plugin_scanner-2.0.104}/dashboard/src/receipts-workspace.tsx +0 -0
  58. {plugin_scanner-2.0.102 → plugin_scanner-2.0.104}/dashboard/src/runtime-overview.tsx +0 -0
  59. {plugin_scanner-2.0.102 → plugin_scanner-2.0.104}/dashboard/src/settings-workspace.tsx +0 -0
  60. {plugin_scanner-2.0.102 → plugin_scanner-2.0.104}/dashboard/src/styles.css +0 -0
  61. {plugin_scanner-2.0.102 → plugin_scanner-2.0.104}/dashboard/src/vite-env.d.ts +0 -0
  62. {plugin_scanner-2.0.102 → plugin_scanner-2.0.104}/dashboard/tsconfig.json +0 -0
  63. {plugin_scanner-2.0.102 → plugin_scanner-2.0.104}/dashboard/vite.config.ts +0 -0
  64. {plugin_scanner-2.0.102 → plugin_scanner-2.0.104}/docker-requirements.txt +0 -0
  65. {plugin_scanner-2.0.102 → plugin_scanner-2.0.104}/docs/guard/approval-audit.md +0 -0
  66. {plugin_scanner-2.0.102 → plugin_scanner-2.0.104}/docs/guard/architecture.md +0 -0
  67. {plugin_scanner-2.0.102 → plugin_scanner-2.0.104}/docs/guard/get-started.md +0 -0
  68. {plugin_scanner-2.0.102 → plugin_scanner-2.0.104}/docs/guard/harness-support.md +0 -0
  69. {plugin_scanner-2.0.102 → plugin_scanner-2.0.104}/docs/guard/local-vs-cloud.md +0 -0
  70. {plugin_scanner-2.0.102 → plugin_scanner-2.0.104}/docs/guard/testing-matrix.md +0 -0
  71. {plugin_scanner-2.0.102 → plugin_scanner-2.0.104}/docs/trust/mcp-trust-draft.md +0 -0
  72. {plugin_scanner-2.0.102 → plugin_scanner-2.0.104}/docs/trust/plugin-trust-draft.md +0 -0
  73. {plugin_scanner-2.0.102 → plugin_scanner-2.0.104}/docs/trust/skill-trust-local.md +0 -0
  74. {plugin_scanner-2.0.102 → plugin_scanner-2.0.104}/fuzzers/manifest_fuzzer.py +0 -0
  75. {plugin_scanner-2.0.102 → plugin_scanner-2.0.104}/requirements.txt +0 -0
  76. {plugin_scanner-2.0.102 → plugin_scanner-2.0.104}/schemas/plugin-quality.v1.json +0 -0
  77. {plugin_scanner-2.0.102 → plugin_scanner-2.0.104}/schemas/scan-result.v1.json +0 -0
  78. {plugin_scanner-2.0.102 → plugin_scanner-2.0.104}/schemas/verify-result.v1.json +0 -0
  79. {plugin_scanner-2.0.102 → plugin_scanner-2.0.104}/src/codex_plugin_scanner/__init__.py +0 -0
  80. {plugin_scanner-2.0.102 → plugin_scanner-2.0.104}/src/codex_plugin_scanner/action_runner.py +0 -0
  81. {plugin_scanner-2.0.102 → plugin_scanner-2.0.104}/src/codex_plugin_scanner/argparse_utils.py +0 -0
  82. {plugin_scanner-2.0.102 → plugin_scanner-2.0.104}/src/codex_plugin_scanner/checks/__init__.py +0 -0
  83. {plugin_scanner-2.0.102 → plugin_scanner-2.0.104}/src/codex_plugin_scanner/checks/best_practices.py +0 -0
  84. {plugin_scanner-2.0.102 → plugin_scanner-2.0.104}/src/codex_plugin_scanner/checks/claude.py +0 -0
  85. {plugin_scanner-2.0.102 → plugin_scanner-2.0.104}/src/codex_plugin_scanner/checks/code_quality.py +0 -0
  86. {plugin_scanner-2.0.102 → plugin_scanner-2.0.104}/src/codex_plugin_scanner/checks/ecosystem_common.py +0 -0
  87. {plugin_scanner-2.0.102 → plugin_scanner-2.0.104}/src/codex_plugin_scanner/checks/gemini.py +0 -0
  88. {plugin_scanner-2.0.102 → plugin_scanner-2.0.104}/src/codex_plugin_scanner/checks/manifest.py +0 -0
  89. {plugin_scanner-2.0.102 → plugin_scanner-2.0.104}/src/codex_plugin_scanner/checks/manifest_support.py +0 -0
  90. {plugin_scanner-2.0.102 → plugin_scanner-2.0.104}/src/codex_plugin_scanner/checks/marketplace.py +0 -0
  91. {plugin_scanner-2.0.102 → plugin_scanner-2.0.104}/src/codex_plugin_scanner/checks/mcp_security.py +0 -0
  92. {plugin_scanner-2.0.102 → plugin_scanner-2.0.104}/src/codex_plugin_scanner/checks/opencode.py +0 -0
  93. {plugin_scanner-2.0.102 → plugin_scanner-2.0.104}/src/codex_plugin_scanner/checks/operational_security.py +0 -0
  94. {plugin_scanner-2.0.102 → plugin_scanner-2.0.104}/src/codex_plugin_scanner/checks/security.py +0 -0
  95. {plugin_scanner-2.0.102 → plugin_scanner-2.0.104}/src/codex_plugin_scanner/checks/skill_security.py +0 -0
  96. {plugin_scanner-2.0.102 → plugin_scanner-2.0.104}/src/codex_plugin_scanner/cli.py +0 -0
  97. {plugin_scanner-2.0.102 → plugin_scanner-2.0.104}/src/codex_plugin_scanner/cli_ui.py +0 -0
  98. {plugin_scanner-2.0.102 → plugin_scanner-2.0.104}/src/codex_plugin_scanner/config.py +0 -0
  99. {plugin_scanner-2.0.102 → plugin_scanner-2.0.104}/src/codex_plugin_scanner/ecosystems/__init__.py +0 -0
  100. {plugin_scanner-2.0.102 → plugin_scanner-2.0.104}/src/codex_plugin_scanner/ecosystems/base.py +0 -0
  101. {plugin_scanner-2.0.102 → plugin_scanner-2.0.104}/src/codex_plugin_scanner/ecosystems/claude.py +0 -0
  102. {plugin_scanner-2.0.102 → plugin_scanner-2.0.104}/src/codex_plugin_scanner/ecosystems/codex.py +0 -0
  103. {plugin_scanner-2.0.102 → plugin_scanner-2.0.104}/src/codex_plugin_scanner/ecosystems/detect.py +0 -0
  104. {plugin_scanner-2.0.102 → plugin_scanner-2.0.104}/src/codex_plugin_scanner/ecosystems/gemini.py +0 -0
  105. {plugin_scanner-2.0.102 → plugin_scanner-2.0.104}/src/codex_plugin_scanner/ecosystems/opencode.py +0 -0
  106. {plugin_scanner-2.0.102 → plugin_scanner-2.0.104}/src/codex_plugin_scanner/ecosystems/registry.py +0 -0
  107. {plugin_scanner-2.0.102 → plugin_scanner-2.0.104}/src/codex_plugin_scanner/ecosystems/types.py +0 -0
  108. {plugin_scanner-2.0.102 → plugin_scanner-2.0.104}/src/codex_plugin_scanner/github_reporting.py +0 -0
  109. {plugin_scanner-2.0.102 → plugin_scanner-2.0.104}/src/codex_plugin_scanner/guard/__init__.py +0 -0
  110. {plugin_scanner-2.0.102 → plugin_scanner-2.0.104}/src/codex_plugin_scanner/guard/adapters/__init__.py +0 -0
  111. {plugin_scanner-2.0.102 → plugin_scanner-2.0.104}/src/codex_plugin_scanner/guard/adapters/antigravity.py +0 -0
  112. {plugin_scanner-2.0.102 → plugin_scanner-2.0.104}/src/codex_plugin_scanner/guard/adapters/base.py +0 -0
  113. {plugin_scanner-2.0.102 → plugin_scanner-2.0.104}/src/codex_plugin_scanner/guard/adapters/claude_code.py +0 -0
  114. {plugin_scanner-2.0.102 → plugin_scanner-2.0.104}/src/codex_plugin_scanner/guard/adapters/cloud_identity.py +0 -0
  115. {plugin_scanner-2.0.102 → plugin_scanner-2.0.104}/src/codex_plugin_scanner/guard/adapters/codex.py +0 -0
  116. {plugin_scanner-2.0.102 → plugin_scanner-2.0.104}/src/codex_plugin_scanner/guard/adapters/copilot.py +0 -0
  117. {plugin_scanner-2.0.102 → plugin_scanner-2.0.104}/src/codex_plugin_scanner/guard/adapters/cursor.py +0 -0
  118. {plugin_scanner-2.0.102 → plugin_scanner-2.0.104}/src/codex_plugin_scanner/guard/adapters/gemini.py +0 -0
  119. {plugin_scanner-2.0.102 → plugin_scanner-2.0.104}/src/codex_plugin_scanner/guard/adapters/hermes.py +0 -0
  120. {plugin_scanner-2.0.102 → plugin_scanner-2.0.104}/src/codex_plugin_scanner/guard/adapters/mcp_servers.py +0 -0
  121. {plugin_scanner-2.0.102 → plugin_scanner-2.0.104}/src/codex_plugin_scanner/guard/adapters/openclaw.py +0 -0
  122. {plugin_scanner-2.0.102 → plugin_scanner-2.0.104}/src/codex_plugin_scanner/guard/adapters/openclaw_config.py +0 -0
  123. {plugin_scanner-2.0.102 → plugin_scanner-2.0.104}/src/codex_plugin_scanner/guard/adapters/openclaw_support.py +0 -0
  124. {plugin_scanner-2.0.102 → plugin_scanner-2.0.104}/src/codex_plugin_scanner/guard/adapters/opencode.py +0 -0
  125. {plugin_scanner-2.0.102 → plugin_scanner-2.0.104}/src/codex_plugin_scanner/guard/adapters/opencode_artifacts.py +0 -0
  126. {plugin_scanner-2.0.102 → plugin_scanner-2.0.104}/src/codex_plugin_scanner/guard/advisory_model.py +0 -0
  127. {plugin_scanner-2.0.102 → plugin_scanner-2.0.104}/src/codex_plugin_scanner/guard/approvals.py +0 -0
  128. {plugin_scanner-2.0.102 → plugin_scanner-2.0.104}/src/codex_plugin_scanner/guard/bridge/__init__.py +0 -0
  129. {plugin_scanner-2.0.102 → plugin_scanner-2.0.104}/src/codex_plugin_scanner/guard/capabilities.py +0 -0
  130. {plugin_scanner-2.0.102 → plugin_scanner-2.0.104}/src/codex_plugin_scanner/guard/cli/__init__.py +0 -0
  131. {plugin_scanner-2.0.102 → plugin_scanner-2.0.104}/src/codex_plugin_scanner/guard/cli/approval_commands.py +0 -0
  132. {plugin_scanner-2.0.102 → plugin_scanner-2.0.104}/src/codex_plugin_scanner/guard/cli/bootstrap.py +0 -0
  133. {plugin_scanner-2.0.102 → plugin_scanner-2.0.104}/src/codex_plugin_scanner/guard/cli/connect_flow.py +0 -0
  134. {plugin_scanner-2.0.102 → plugin_scanner-2.0.104}/src/codex_plugin_scanner/guard/cli/install_commands.py +0 -0
  135. {plugin_scanner-2.0.102 → plugin_scanner-2.0.104}/src/codex_plugin_scanner/guard/cli/product.py +0 -0
  136. {plugin_scanner-2.0.102 → plugin_scanner-2.0.104}/src/codex_plugin_scanner/guard/cli/prompt.py +0 -0
  137. {plugin_scanner-2.0.102 → plugin_scanner-2.0.104}/src/codex_plugin_scanner/guard/cli/render.py +0 -0
  138. {plugin_scanner-2.0.102 → plugin_scanner-2.0.104}/src/codex_plugin_scanner/guard/cli/update_commands.py +0 -0
  139. {plugin_scanner-2.0.102 → plugin_scanner-2.0.104}/src/codex_plugin_scanner/guard/codex_config.py +0 -0
  140. {plugin_scanner-2.0.102 → plugin_scanner-2.0.104}/src/codex_plugin_scanner/guard/consumer/__init__.py +0 -0
  141. {plugin_scanner-2.0.102 → plugin_scanner-2.0.104}/src/codex_plugin_scanner/guard/consumer/service.py +0 -0
  142. {plugin_scanner-2.0.102 → plugin_scanner-2.0.104}/src/codex_plugin_scanner/guard/daemon/__init__.py +0 -0
  143. {plugin_scanner-2.0.102 → plugin_scanner-2.0.104}/src/codex_plugin_scanner/guard/daemon/client.py +0 -0
  144. {plugin_scanner-2.0.102 → plugin_scanner-2.0.104}/src/codex_plugin_scanner/guard/daemon/manager.py +0 -0
  145. {plugin_scanner-2.0.102 → plugin_scanner-2.0.104}/src/codex_plugin_scanner/guard/daemon/server.py +0 -0
  146. {plugin_scanner-2.0.102 → plugin_scanner-2.0.104}/src/codex_plugin_scanner/guard/daemon/static/apple-touch-icon.png +0 -0
  147. {plugin_scanner-2.0.102 → plugin_scanner-2.0.104}/src/codex_plugin_scanner/guard/daemon/static/assets/index.css +0 -0
  148. {plugin_scanner-2.0.102 → plugin_scanner-2.0.104}/src/codex_plugin_scanner/guard/daemon/static/brand/Logo_Icon_Dark.png +0 -0
  149. {plugin_scanner-2.0.102 → plugin_scanner-2.0.104}/src/codex_plugin_scanner/guard/daemon/static/brand/Logo_Whole.png +0 -0
  150. {plugin_scanner-2.0.102 → plugin_scanner-2.0.104}/src/codex_plugin_scanner/guard/daemon/static/favicon-16x16.png +0 -0
  151. {plugin_scanner-2.0.102 → plugin_scanner-2.0.104}/src/codex_plugin_scanner/guard/daemon/static/favicon-32x32.png +0 -0
  152. {plugin_scanner-2.0.102 → plugin_scanner-2.0.104}/src/codex_plugin_scanner/guard/daemon/static/favicon.ico +0 -0
  153. {plugin_scanner-2.0.102 → plugin_scanner-2.0.104}/src/codex_plugin_scanner/guard/daemon/static/index.html +0 -0
  154. {plugin_scanner-2.0.102 → plugin_scanner-2.0.104}/src/codex_plugin_scanner/guard/edge_events.py +0 -0
  155. {plugin_scanner-2.0.102 → plugin_scanner-2.0.104}/src/codex_plugin_scanner/guard/incident.py +0 -0
  156. {plugin_scanner-2.0.102 → plugin_scanner-2.0.104}/src/codex_plugin_scanner/guard/launcher.py +0 -0
  157. {plugin_scanner-2.0.102 → plugin_scanner-2.0.104}/src/codex_plugin_scanner/guard/mcp_tool_calls.py +0 -0
  158. {plugin_scanner-2.0.102 → plugin_scanner-2.0.104}/src/codex_plugin_scanner/guard/models.py +0 -0
  159. {plugin_scanner-2.0.102 → plugin_scanner-2.0.104}/src/codex_plugin_scanner/guard/policy/__init__.py +0 -0
  160. {plugin_scanner-2.0.102 → plugin_scanner-2.0.104}/src/codex_plugin_scanner/guard/policy/engine.py +0 -0
  161. {plugin_scanner-2.0.102 → plugin_scanner-2.0.104}/src/codex_plugin_scanner/guard/protect.py +0 -0
  162. {plugin_scanner-2.0.102 → plugin_scanner-2.0.104}/src/codex_plugin_scanner/guard/proxy/__init__.py +0 -0
  163. {plugin_scanner-2.0.102 → plugin_scanner-2.0.104}/src/codex_plugin_scanner/guard/proxy/remote.py +0 -0
  164. {plugin_scanner-2.0.102 → plugin_scanner-2.0.104}/src/codex_plugin_scanner/guard/proxy/runtime_mcp.py +0 -0
  165. {plugin_scanner-2.0.102 → plugin_scanner-2.0.104}/src/codex_plugin_scanner/guard/proxy/stdio.py +0 -0
  166. {plugin_scanner-2.0.102 → plugin_scanner-2.0.104}/src/codex_plugin_scanner/guard/receipts/__init__.py +0 -0
  167. {plugin_scanner-2.0.102 → plugin_scanner-2.0.104}/src/codex_plugin_scanner/guard/receipts/manager.py +0 -0
  168. {plugin_scanner-2.0.102 → plugin_scanner-2.0.104}/src/codex_plugin_scanner/guard/redaction.py +0 -0
  169. {plugin_scanner-2.0.102 → plugin_scanner-2.0.104}/src/codex_plugin_scanner/guard/risk.py +0 -0
  170. {plugin_scanner-2.0.102 → plugin_scanner-2.0.104}/src/codex_plugin_scanner/guard/runtime/__init__.py +0 -0
  171. {plugin_scanner-2.0.102 → plugin_scanner-2.0.104}/src/codex_plugin_scanner/guard/runtime/actions.py +0 -0
  172. {plugin_scanner-2.0.102 → plugin_scanner-2.0.104}/src/codex_plugin_scanner/guard/runtime/decisions.py +0 -0
  173. {plugin_scanner-2.0.102 → plugin_scanner-2.0.104}/src/codex_plugin_scanner/guard/runtime/secret_file_requests.py +0 -0
  174. {plugin_scanner-2.0.102 → plugin_scanner-2.0.104}/src/codex_plugin_scanner/guard/runtime/signals.py +0 -0
  175. {plugin_scanner-2.0.102 → plugin_scanner-2.0.104}/src/codex_plugin_scanner/guard/runtime/surface_server.py +0 -0
  176. {plugin_scanner-2.0.102 → plugin_scanner-2.0.104}/src/codex_plugin_scanner/guard/schemas/__init__.py +0 -0
  177. {plugin_scanner-2.0.102 → plugin_scanner-2.0.104}/src/codex_plugin_scanner/guard/schemas/consumer_mode.py +0 -0
  178. {plugin_scanner-2.0.102 → plugin_scanner-2.0.104}/src/codex_plugin_scanner/guard/schemas/guard_event_v1.py +0 -0
  179. {plugin_scanner-2.0.102 → plugin_scanner-2.0.104}/src/codex_plugin_scanner/guard/schemas/surface_server.py +0 -0
  180. {plugin_scanner-2.0.102 → plugin_scanner-2.0.104}/src/codex_plugin_scanner/guard/shims.py +0 -0
  181. {plugin_scanner-2.0.102 → plugin_scanner-2.0.104}/src/codex_plugin_scanner/guard/store.py +0 -0
  182. {plugin_scanner-2.0.102 → plugin_scanner-2.0.104}/src/codex_plugin_scanner/guard/store_approvals.py +0 -0
  183. {plugin_scanner-2.0.102 → plugin_scanner-2.0.104}/src/codex_plugin_scanner/guard/store_connect.py +0 -0
  184. {plugin_scanner-2.0.102 → plugin_scanner-2.0.104}/src/codex_plugin_scanner/guard/types.py +0 -0
  185. {plugin_scanner-2.0.102 → plugin_scanner-2.0.104}/src/codex_plugin_scanner/integrations/__init__.py +0 -0
  186. {plugin_scanner-2.0.102 → plugin_scanner-2.0.104}/src/codex_plugin_scanner/integrations/cisco_mcp_scanner.py +0 -0
  187. {plugin_scanner-2.0.102 → plugin_scanner-2.0.104}/src/codex_plugin_scanner/integrations/cisco_skill_scanner.py +0 -0
  188. {plugin_scanner-2.0.102 → plugin_scanner-2.0.104}/src/codex_plugin_scanner/lint_fixes.py +0 -0
  189. {plugin_scanner-2.0.102 → plugin_scanner-2.0.104}/src/codex_plugin_scanner/marketplace_support.py +0 -0
  190. {plugin_scanner-2.0.102 → plugin_scanner-2.0.104}/src/codex_plugin_scanner/models.py +0 -0
  191. {plugin_scanner-2.0.102 → plugin_scanner-2.0.104}/src/codex_plugin_scanner/path_support.py +0 -0
  192. {plugin_scanner-2.0.102 → plugin_scanner-2.0.104}/src/codex_plugin_scanner/policy.py +0 -0
  193. {plugin_scanner-2.0.102 → plugin_scanner-2.0.104}/src/codex_plugin_scanner/quality_artifact.py +0 -0
  194. {plugin_scanner-2.0.102 → plugin_scanner-2.0.104}/src/codex_plugin_scanner/repo_detect.py +0 -0
  195. {plugin_scanner-2.0.102 → plugin_scanner-2.0.104}/src/codex_plugin_scanner/reporting.py +0 -0
  196. {plugin_scanner-2.0.102 → plugin_scanner-2.0.104}/src/codex_plugin_scanner/rules/__init__.py +0 -0
  197. {plugin_scanner-2.0.102 → plugin_scanner-2.0.104}/src/codex_plugin_scanner/rules/registry.py +0 -0
  198. {plugin_scanner-2.0.102 → plugin_scanner-2.0.104}/src/codex_plugin_scanner/rules/specs.py +0 -0
  199. {plugin_scanner-2.0.102 → plugin_scanner-2.0.104}/src/codex_plugin_scanner/scanner.py +0 -0
  200. {plugin_scanner-2.0.102 → plugin_scanner-2.0.104}/src/codex_plugin_scanner/submission.py +0 -0
  201. {plugin_scanner-2.0.102 → plugin_scanner-2.0.104}/src/codex_plugin_scanner/suppressions.py +0 -0
  202. {plugin_scanner-2.0.102 → plugin_scanner-2.0.104}/src/codex_plugin_scanner/trust_domain_scoring.py +0 -0
  203. {plugin_scanner-2.0.102 → plugin_scanner-2.0.104}/src/codex_plugin_scanner/trust_helpers.py +0 -0
  204. {plugin_scanner-2.0.102 → plugin_scanner-2.0.104}/src/codex_plugin_scanner/trust_mcp_scoring.py +0 -0
  205. {plugin_scanner-2.0.102 → plugin_scanner-2.0.104}/src/codex_plugin_scanner/trust_models.py +0 -0
  206. {plugin_scanner-2.0.102 → plugin_scanner-2.0.104}/src/codex_plugin_scanner/trust_plugin_scoring.py +0 -0
  207. {plugin_scanner-2.0.102 → plugin_scanner-2.0.104}/src/codex_plugin_scanner/trust_scoring.py +0 -0
  208. {plugin_scanner-2.0.102 → plugin_scanner-2.0.104}/src/codex_plugin_scanner/trust_skill_scoring.py +0 -0
  209. {plugin_scanner-2.0.102 → plugin_scanner-2.0.104}/src/codex_plugin_scanner/trust_specs.py +0 -0
  210. {plugin_scanner-2.0.102 → plugin_scanner-2.0.104}/src/codex_plugin_scanner/verification.py +0 -0
  211. {plugin_scanner-2.0.102 → plugin_scanner-2.0.104}/tests/__init__.py +0 -0
  212. {plugin_scanner-2.0.102 → plugin_scanner-2.0.104}/tests/conftest.py +0 -0
  213. {plugin_scanner-2.0.102 → plugin_scanner-2.0.104}/tests/fixtures/__init__.py +0 -0
  214. {plugin_scanner-2.0.102 → plugin_scanner-2.0.104}/tests/fixtures/bad-plugin/.codex-plugin/plugin.json +0 -0
  215. {plugin_scanner-2.0.102 → plugin_scanner-2.0.104}/tests/fixtures/bad-plugin/.mcp.json +0 -0
  216. {plugin_scanner-2.0.102 → plugin_scanner-2.0.104}/tests/fixtures/bad-plugin/secrets.js +0 -0
  217. {plugin_scanner-2.0.102 → plugin_scanner-2.0.104}/tests/fixtures/claude-plugin-good/.claude-plugin/plugin.json +0 -0
  218. {plugin_scanner-2.0.102 → plugin_scanner-2.0.104}/tests/fixtures/claude-plugin-good/LICENSE +0 -0
  219. {plugin_scanner-2.0.102 → plugin_scanner-2.0.104}/tests/fixtures/claude-plugin-good/README.md +0 -0
  220. {plugin_scanner-2.0.102 → plugin_scanner-2.0.104}/tests/fixtures/claude-plugin-good/SECURITY.md +0 -0
  221. {plugin_scanner-2.0.102 → plugin_scanner-2.0.104}/tests/fixtures/claude-plugin-good/hooks/hooks.json +0 -0
  222. {plugin_scanner-2.0.102 → plugin_scanner-2.0.104}/tests/fixtures/claude-plugin-good/skills/example/SKILL.md +0 -0
  223. {plugin_scanner-2.0.102 → plugin_scanner-2.0.104}/tests/fixtures/code-quality-bad/evil.js +0 -0
  224. {plugin_scanner-2.0.102 → plugin_scanner-2.0.104}/tests/fixtures/code-quality-bad/inject.js +0 -0
  225. {plugin_scanner-2.0.102 → plugin_scanner-2.0.104}/tests/fixtures/gemini-extension-good/GEMINI.md +0 -0
  226. {plugin_scanner-2.0.102 → plugin_scanner-2.0.104}/tests/fixtures/gemini-extension-good/LICENSE +0 -0
  227. {plugin_scanner-2.0.102 → plugin_scanner-2.0.104}/tests/fixtures/gemini-extension-good/README.md +0 -0
  228. {plugin_scanner-2.0.102 → plugin_scanner-2.0.104}/tests/fixtures/gemini-extension-good/SECURITY.md +0 -0
  229. {plugin_scanner-2.0.102 → plugin_scanner-2.0.104}/tests/fixtures/gemini-extension-good/commands/hello.toml +0 -0
  230. {plugin_scanner-2.0.102 → plugin_scanner-2.0.104}/tests/fixtures/gemini-extension-good/gemini-extension.json +0 -0
  231. {plugin_scanner-2.0.102 → plugin_scanner-2.0.104}/tests/fixtures/good-plugin/.codex-plugin/plugin.json +0 -0
  232. {plugin_scanner-2.0.102 → plugin_scanner-2.0.104}/tests/fixtures/good-plugin/.codexignore +0 -0
  233. {plugin_scanner-2.0.102 → plugin_scanner-2.0.104}/tests/fixtures/good-plugin/LICENSE +0 -0
  234. {plugin_scanner-2.0.102 → plugin_scanner-2.0.104}/tests/fixtures/good-plugin/README.md +0 -0
  235. {plugin_scanner-2.0.102 → plugin_scanner-2.0.104}/tests/fixtures/good-plugin/SECURITY.md +0 -0
  236. {plugin_scanner-2.0.102 → plugin_scanner-2.0.104}/tests/fixtures/good-plugin/assets/icon.svg +0 -0
  237. {plugin_scanner-2.0.102 → plugin_scanner-2.0.104}/tests/fixtures/good-plugin/assets/logo.svg +0 -0
  238. {plugin_scanner-2.0.102 → plugin_scanner-2.0.104}/tests/fixtures/good-plugin/assets/screenshot.svg +0 -0
  239. {plugin_scanner-2.0.102 → plugin_scanner-2.0.104}/tests/fixtures/good-plugin/skills/example/SKILL.md +0 -0
  240. {plugin_scanner-2.0.102 → plugin_scanner-2.0.104}/tests/fixtures/guard-codex-malicious-mcp/.codex/config.toml +0 -0
  241. {plugin_scanner-2.0.102 → plugin_scanner-2.0.104}/tests/fixtures/hermes-plugin-evil/config.yaml +0 -0
  242. {plugin_scanner-2.0.102 → plugin_scanner-2.0.104}/tests/fixtures/hermes-plugin-evil/mcp_servers.json +0 -0
  243. {plugin_scanner-2.0.102 → plugin_scanner-2.0.104}/tests/fixtures/hermes-plugin-evil/skills/security/malicious/SKILL.md +0 -0
  244. {plugin_scanner-2.0.102 → plugin_scanner-2.0.104}/tests/fixtures/hermes-plugin-evil/skills/stealth/sneaky/SKILL.md +0 -0
  245. {plugin_scanner-2.0.102 → plugin_scanner-2.0.104}/tests/fixtures/hermes-plugin-evil/skills/stealth/sneaky/references/api-setup.md +0 -0
  246. {plugin_scanner-2.0.102 → plugin_scanner-2.0.104}/tests/fixtures/hermes-plugin-evil/skills/stealth/sneaky/scripts/deploy.sh +0 -0
  247. {plugin_scanner-2.0.102 → plugin_scanner-2.0.104}/tests/fixtures/hermes-plugin-evil/skills/utils/benign/SKILL.md +0 -0
  248. {plugin_scanner-2.0.102 → plugin_scanner-2.0.104}/tests/fixtures/malformed-json/.codex-plugin/plugin.json +0 -0
  249. {plugin_scanner-2.0.102 → plugin_scanner-2.0.104}/tests/fixtures/malicious-skill-plugin/.codex-plugin/plugin.json +0 -0
  250. {plugin_scanner-2.0.102 → plugin_scanner-2.0.104}/tests/fixtures/malicious-skill-plugin/.codexignore +0 -0
  251. {plugin_scanner-2.0.102 → plugin_scanner-2.0.104}/tests/fixtures/malicious-skill-plugin/LICENSE +0 -0
  252. {plugin_scanner-2.0.102 → plugin_scanner-2.0.104}/tests/fixtures/malicious-skill-plugin/README.md +0 -0
  253. {plugin_scanner-2.0.102 → plugin_scanner-2.0.104}/tests/fixtures/malicious-skill-plugin/SECURITY.md +0 -0
  254. {plugin_scanner-2.0.102 → plugin_scanner-2.0.104}/tests/fixtures/malicious-skill-plugin/skills/leaky-skill/SKILL.md +0 -0
  255. {plugin_scanner-2.0.102 → plugin_scanner-2.0.104}/tests/fixtures/mcp-canary-server.py +0 -0
  256. {plugin_scanner-2.0.102 → plugin_scanner-2.0.104}/tests/fixtures/minimal-plugin/.codex-plugin/plugin.json +0 -0
  257. {plugin_scanner-2.0.102 → plugin_scanner-2.0.104}/tests/fixtures/missing-fields/.codex-plugin/plugin.json +0 -0
  258. {plugin_scanner-2.0.102 → plugin_scanner-2.0.104}/tests/fixtures/mit-license/LICENSE +0 -0
  259. {plugin_scanner-2.0.102 → plugin_scanner-2.0.104}/tests/fixtures/multi-ecosystem-repo/codex-plugin/.codex-plugin/plugin.json +0 -0
  260. {plugin_scanner-2.0.102 → plugin_scanner-2.0.104}/tests/fixtures/multi-ecosystem-repo/codex-plugin/LICENSE +0 -0
  261. {plugin_scanner-2.0.102 → plugin_scanner-2.0.104}/tests/fixtures/multi-ecosystem-repo/codex-plugin/README.md +0 -0
  262. {plugin_scanner-2.0.102 → plugin_scanner-2.0.104}/tests/fixtures/multi-ecosystem-repo/codex-plugin/SECURITY.md +0 -0
  263. {plugin_scanner-2.0.102 → plugin_scanner-2.0.104}/tests/fixtures/multi-ecosystem-repo/gemini-ext/README.md +0 -0
  264. {plugin_scanner-2.0.102 → plugin_scanner-2.0.104}/tests/fixtures/multi-ecosystem-repo/gemini-ext/gemini-extension.json +0 -0
  265. {plugin_scanner-2.0.102 → plugin_scanner-2.0.104}/tests/fixtures/multi-plugin-repo/.agents/plugins/marketplace.json +0 -0
  266. {plugin_scanner-2.0.102 → plugin_scanner-2.0.104}/tests/fixtures/multi-plugin-repo/plugins/alpha-plugin/.codex-plugin/plugin.json +0 -0
  267. {plugin_scanner-2.0.102 → plugin_scanner-2.0.104}/tests/fixtures/multi-plugin-repo/plugins/alpha-plugin/.codexignore +0 -0
  268. {plugin_scanner-2.0.102 → plugin_scanner-2.0.104}/tests/fixtures/multi-plugin-repo/plugins/alpha-plugin/LICENSE +0 -0
  269. {plugin_scanner-2.0.102 → plugin_scanner-2.0.104}/tests/fixtures/multi-plugin-repo/plugins/alpha-plugin/README.md +0 -0
  270. {plugin_scanner-2.0.102 → plugin_scanner-2.0.104}/tests/fixtures/multi-plugin-repo/plugins/alpha-plugin/SECURITY.md +0 -0
  271. {plugin_scanner-2.0.102 → plugin_scanner-2.0.104}/tests/fixtures/multi-plugin-repo/plugins/alpha-plugin/skills/example/SKILL.md +0 -0
  272. {plugin_scanner-2.0.102 → plugin_scanner-2.0.104}/tests/fixtures/multi-plugin-repo/plugins/beta-plugin/.codex-plugin/plugin.json +0 -0
  273. {plugin_scanner-2.0.102 → plugin_scanner-2.0.104}/tests/fixtures/multi-plugin-repo/plugins/beta-plugin/skills/example/SKILL.md +0 -0
  274. {plugin_scanner-2.0.102 → plugin_scanner-2.0.104}/tests/fixtures/no-version/.codex-plugin/plugin.json +0 -0
  275. {plugin_scanner-2.0.102 → plugin_scanner-2.0.104}/tests/fixtures/opencode-good/.opencode/commands/hello.md +0 -0
  276. {plugin_scanner-2.0.102 → plugin_scanner-2.0.104}/tests/fixtures/opencode-good/.opencode/plugins/example.ts +0 -0
  277. {plugin_scanner-2.0.102 → plugin_scanner-2.0.104}/tests/fixtures/opencode-good/LICENSE +0 -0
  278. {plugin_scanner-2.0.102 → plugin_scanner-2.0.104}/tests/fixtures/opencode-good/README.md +0 -0
  279. {plugin_scanner-2.0.102 → plugin_scanner-2.0.104}/tests/fixtures/opencode-good/SECURITY.md +0 -0
  280. {plugin_scanner-2.0.102 → plugin_scanner-2.0.104}/tests/fixtures/opencode-good/opencode.jsonc +0 -0
  281. {plugin_scanner-2.0.102 → plugin_scanner-2.0.104}/tests/fixtures/skills-missing-dir/.codex-plugin/plugin.json +0 -0
  282. {plugin_scanner-2.0.102 → plugin_scanner-2.0.104}/tests/fixtures/skills-no-frontmatter/.codex-plugin/plugin.json +0 -0
  283. {plugin_scanner-2.0.102 → plugin_scanner-2.0.104}/tests/fixtures/skills-no-frontmatter/skills/bad-skill/SKILL.md +0 -0
  284. {plugin_scanner-2.0.102 → plugin_scanner-2.0.104}/tests/fixtures/with-marketplace/.codex-plugin/plugin.json +0 -0
  285. {plugin_scanner-2.0.102 → plugin_scanner-2.0.104}/tests/fixtures/with-marketplace/marketplace-broken.json +0 -0
  286. {plugin_scanner-2.0.102 → plugin_scanner-2.0.104}/tests/fixtures/with-marketplace/marketplace.json +0 -0
  287. {plugin_scanner-2.0.102 → plugin_scanner-2.0.104}/tests/test-trust-scoring.py +0 -0
  288. {plugin_scanner-2.0.102 → plugin_scanner-2.0.104}/tests/test-trust-specs.py +0 -0
  289. {plugin_scanner-2.0.102 → plugin_scanner-2.0.104}/tests/test_action_runner.py +0 -0
  290. {plugin_scanner-2.0.102 → plugin_scanner-2.0.104}/tests/test_best_practices.py +0 -0
  291. {plugin_scanner-2.0.102 → plugin_scanner-2.0.104}/tests/test_cisco_install_surfaces.py +0 -0
  292. {plugin_scanner-2.0.102 → plugin_scanner-2.0.104}/tests/test_cli.py +0 -0
  293. {plugin_scanner-2.0.102 → plugin_scanner-2.0.104}/tests/test_code_quality.py +0 -0
  294. {plugin_scanner-2.0.102 → plugin_scanner-2.0.104}/tests/test_config.py +0 -0
  295. {plugin_scanner-2.0.102 → plugin_scanner-2.0.104}/tests/test_coverage_remaining.py +0 -0
  296. {plugin_scanner-2.0.102 → plugin_scanner-2.0.104}/tests/test_ecosystems.py +0 -0
  297. {plugin_scanner-2.0.102 → plugin_scanner-2.0.104}/tests/test_edge_cases.py +0 -0
  298. {plugin_scanner-2.0.102 → plugin_scanner-2.0.104}/tests/test_final_coverage.py +0 -0
  299. {plugin_scanner-2.0.102 → plugin_scanner-2.0.104}/tests/test_guard_approvals.py +0 -0
  300. {plugin_scanner-2.0.102 → plugin_scanner-2.0.104}/tests/test_guard_bootstrap.py +0 -0
  301. {plugin_scanner-2.0.102 → plugin_scanner-2.0.104}/tests/test_guard_capabilities.py +0 -0
  302. {plugin_scanner-2.0.102 → plugin_scanner-2.0.104}/tests/test_guard_claude_adapter.py +0 -0
  303. {plugin_scanner-2.0.102 → plugin_scanner-2.0.104}/tests/test_guard_cli.py +0 -0
  304. {plugin_scanner-2.0.102 → plugin_scanner-2.0.104}/tests/test_guard_codex_e2e.py +0 -0
  305. {plugin_scanner-2.0.102 → plugin_scanner-2.0.104}/tests/test_guard_codex_install.py +0 -0
  306. {plugin_scanner-2.0.102 → plugin_scanner-2.0.104}/tests/test_guard_codex_proxy.py +0 -0
  307. {plugin_scanner-2.0.102 → plugin_scanner-2.0.104}/tests/test_guard_connect_flow.py +0 -0
  308. {plugin_scanner-2.0.102 → plugin_scanner-2.0.104}/tests/test_guard_consumer_mode.py +0 -0
  309. {plugin_scanner-2.0.102 → plugin_scanner-2.0.104}/tests/test_guard_copilot_adapter.py +0 -0
  310. {plugin_scanner-2.0.102 → plugin_scanner-2.0.104}/tests/test_guard_copilot_proxy.py +0 -0
  311. {plugin_scanner-2.0.102 → plugin_scanner-2.0.104}/tests/test_guard_daemon_manager.py +0 -0
  312. {plugin_scanner-2.0.102 → plugin_scanner-2.0.104}/tests/test_guard_event_schema_v1.py +0 -0
  313. {plugin_scanner-2.0.102 → plugin_scanner-2.0.104}/tests/test_guard_events.py +0 -0
  314. {plugin_scanner-2.0.102 → plugin_scanner-2.0.104}/tests/test_guard_launch_env.py +0 -0
  315. {plugin_scanner-2.0.102 → plugin_scanner-2.0.104}/tests/test_guard_opencode_proxy.py +0 -0
  316. {plugin_scanner-2.0.102 → plugin_scanner-2.0.104}/tests/test_guard_product_flow.py +0 -0
  317. {plugin_scanner-2.0.102 → plugin_scanner-2.0.104}/tests/test_guard_protect.py +0 -0
  318. {plugin_scanner-2.0.102 → plugin_scanner-2.0.104}/tests/test_guard_render.py +0 -0
  319. {plugin_scanner-2.0.102 → plugin_scanner-2.0.104}/tests/test_guard_risk.py +0 -0
  320. {plugin_scanner-2.0.102 → plugin_scanner-2.0.104}/tests/test_guard_runtime_action_harnesses.py +0 -0
  321. {plugin_scanner-2.0.102 → plugin_scanner-2.0.104}/tests/test_guard_runtime_actions.py +0 -0
  322. {plugin_scanner-2.0.102 → plugin_scanner-2.0.104}/tests/test_guard_runtime_decisions.py +0 -0
  323. {plugin_scanner-2.0.102 → plugin_scanner-2.0.104}/tests/test_guard_runtime_signals.py +0 -0
  324. {plugin_scanner-2.0.102 → plugin_scanner-2.0.104}/tests/test_guard_store_migrations.py +0 -0
  325. {plugin_scanner-2.0.102 → plugin_scanner-2.0.104}/tests/test_guard_surface_server.py +0 -0
  326. {plugin_scanner-2.0.102 → plugin_scanner-2.0.104}/tests/test_guard_verdicts.py +0 -0
  327. {plugin_scanner-2.0.102 → plugin_scanner-2.0.104}/tests/test_hermes_adapter.py +0 -0
  328. {plugin_scanner-2.0.102 → plugin_scanner-2.0.104}/tests/test_integration.py +0 -0
  329. {plugin_scanner-2.0.102 → plugin_scanner-2.0.104}/tests/test_lint_fixes.py +0 -0
  330. {plugin_scanner-2.0.102 → plugin_scanner-2.0.104}/tests/test_live_cisco_smoke.py +0 -0
  331. {plugin_scanner-2.0.102 → plugin_scanner-2.0.104}/tests/test_manifest.py +0 -0
  332. {plugin_scanner-2.0.102 → plugin_scanner-2.0.104}/tests/test_marketplace.py +0 -0
  333. {plugin_scanner-2.0.102 → plugin_scanner-2.0.104}/tests/test_mcp_security.py +0 -0
  334. {plugin_scanner-2.0.102 → plugin_scanner-2.0.104}/tests/test_openclaw_adapter.py +0 -0
  335. {plugin_scanner-2.0.102 → plugin_scanner-2.0.104}/tests/test_operational_security.py +0 -0
  336. {plugin_scanner-2.0.102 → plugin_scanner-2.0.104}/tests/test_policy.py +0 -0
  337. {plugin_scanner-2.0.102 → plugin_scanner-2.0.104}/tests/test_quality_artifact.py +0 -0
  338. {plugin_scanner-2.0.102 → plugin_scanner-2.0.104}/tests/test_rule_registry.py +0 -0
  339. {plugin_scanner-2.0.102 → plugin_scanner-2.0.104}/tests/test_scanner.py +0 -0
  340. {plugin_scanner-2.0.102 → plugin_scanner-2.0.104}/tests/test_schema_contracts.py +0 -0
  341. {plugin_scanner-2.0.102 → plugin_scanner-2.0.104}/tests/test_security.py +0 -0
  342. {plugin_scanner-2.0.102 → plugin_scanner-2.0.104}/tests/test_security_ops.py +0 -0
  343. {plugin_scanner-2.0.102 → plugin_scanner-2.0.104}/tests/test_skill_security.py +0 -0
  344. {plugin_scanner-2.0.102 → plugin_scanner-2.0.104}/tests/test_submission.py +0 -0
  345. {plugin_scanner-2.0.102 → plugin_scanner-2.0.104}/tests/test_trust_scoring.py +0 -0
  346. {plugin_scanner-2.0.102 → plugin_scanner-2.0.104}/tests/test_trust_specs.py +0 -0
  347. {plugin_scanner-2.0.102 → plugin_scanner-2.0.104}/tests/test_verification.py +0 -0
  348. {plugin_scanner-2.0.102 → plugin_scanner-2.0.104}/tests/test_versioning.py +0 -0
  349. {plugin_scanner-2.0.102 → plugin_scanner-2.0.104}/uv.lock +0 -0
@@ -1,6 +1,6 @@
1
1
  Metadata-Version: 2.4
2
2
  Name: plugin-scanner
3
- Version: 2.0.102
3
+ Version: 2.0.104
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
@@ -35,7 +35,9 @@ import {
35
35
  buildTechnicalSummary,
36
36
  humanizeChangedFields,
37
37
  harnessDisplayName,
38
- resolveEnvelopeDisplayText
38
+ resolveDecisionV2Title,
39
+ resolveDecisionV2Detail,
40
+ resolveStoppedCommandText
39
41
  } from "./approval-center-utils";
40
42
  import type {
41
43
  GuardApprovalRequest,
@@ -782,6 +784,7 @@ function CopyCommandButton(props: { command: string }) {
782
784
 
783
785
  function BlockedActionCard(props: { item: GuardApprovalRequest }) {
784
786
  const launchText = actionLaunchText(props.item);
787
+ const decisionDetail = resolveDecisionV2Detail(props.item);
785
788
  const isBlocked = props.item.policy_action === "block";
786
789
  const bannerBg = isBlocked
787
790
  ? "bg-gradient-to-r from-brand-purple/90 to-brand-purple/75"
@@ -820,6 +823,11 @@ function BlockedActionCard(props: { item: GuardApprovalRequest }) {
820
823
  <p className="mt-2 text-sm leading-6 text-brand-dark/70">
821
824
  {harnessDisplayName(props.item.harness)} paused this because {buildQueueSummary(props.item).toLowerCase()}.
822
825
  </p>
826
+ {decisionDetail !== null ? (
827
+ <p className="mt-2 text-sm leading-6 text-brand-dark/80">
828
+ {decisionDetail}
829
+ </p>
830
+ ) : null}
823
831
  <div className="mt-4 rounded-[1.25rem] bg-[#090d1a] p-1 shadow-[0_14px_35px_rgba(9,13,26,0.18)]">
824
832
  <div className="flex items-center gap-1.5 border-b border-white/10 px-3 py-2">
825
833
  <span className="h-2.5 w-2.5 rounded-full bg-brand-purple" />
@@ -849,6 +857,10 @@ function BlockedActionCard(props: { item: GuardApprovalRequest }) {
849
857
  }
850
858
 
851
859
  function actionDisplayTitle(item: GuardApprovalRequest): string {
860
+ const v2Title = resolveDecisionV2Title(item);
861
+ if (v2Title !== null) {
862
+ return v2Title;
863
+ }
852
864
  const artifactName = displayArtifactName(item);
853
865
  if (item.artifact_type === "tool_action_request") {
854
866
  return `${harnessDisplayName(item.harness)} wants to run a tool`;
@@ -866,23 +878,7 @@ function actionDisplayTitle(item: GuardApprovalRequest): string {
866
878
  }
867
879
 
868
880
  function actionLaunchText(item: GuardApprovalRequest): string {
869
- if (item.action_envelope_json) {
870
- const envelopeText = resolveEnvelopeDisplayText(item.action_envelope_json);
871
- if (envelopeText !== null) {
872
- return envelopeText;
873
- }
874
- }
875
- if (item.launch_target?.trim()) {
876
- return item.launch_target;
877
- }
878
- if (item.launch_summary?.trim()) {
879
- const commandMatch = item.launch_summary.match(/`([^`]+)`/);
880
- if (commandMatch?.[1]) {
881
- return commandMatch[1];
882
- }
883
- return item.launch_summary;
884
- }
885
- return displayArtifactName(item);
881
+ return resolveStoppedCommandText(item);
886
882
  }
887
883
 
888
884
  function getRulePreviewText(
@@ -209,6 +209,36 @@ function capitalizeHarness(harness: string): string {
209
209
  return `${harness.charAt(0).toUpperCase()}${harness.slice(1)}`;
210
210
  }
211
211
 
212
+ export function resolveDecisionV2Title(item: GuardApprovalRequest): string | null {
213
+ const title = item.decision_v2_json?.user_title;
214
+ return title !== undefined && title.trim().length > 0 ? title : null;
215
+ }
216
+
217
+ export function resolveDecisionV2Detail(item: GuardApprovalRequest): string | null {
218
+ const detail = item.decision_v2_json?.dashboard_primary_detail;
219
+ return detail !== undefined && detail.trim().length > 0 ? detail : null;
220
+ }
221
+
222
+ export function resolveStoppedCommandText(item: GuardApprovalRequest): string {
223
+ if (item.action_envelope_json) {
224
+ const envelopeText = resolveEnvelopeDisplayText(item.action_envelope_json);
225
+ if (envelopeText !== null) {
226
+ return envelopeText;
227
+ }
228
+ }
229
+ if (item.launch_target?.trim()) {
230
+ return item.launch_target;
231
+ }
232
+ if (item.launch_summary?.trim()) {
233
+ const commandMatch = item.launch_summary.match(/`([^`]+)`/);
234
+ if (commandMatch?.[1]) {
235
+ return commandMatch[1];
236
+ }
237
+ return item.launch_summary;
238
+ }
239
+ return item.artifact_name.trim() || item.artifact_id;
240
+ }
241
+
212
242
  export function harnessDisplayName(harness: string): string {
213
243
  switch (harness) {
214
244
  case "claude-code":
@@ -1,6 +1,16 @@
1
- import { buildDemoRuntimeSnapshot, normalizeApprovalRequest, parseActionEnvelope } from "./guard-api";
2
- import { resolveEnvelopeDisplayText } from "./approval-center-utils";
3
- import type { GuardActionEnvelope, GuardApprovalRequest } from "./guard-types";
1
+ import {
2
+ buildDemoRuntimeSnapshot,
3
+ normalizeApprovalRequest,
4
+ parseActionEnvelope,
5
+ parseDecisionV2
6
+ } from "./guard-api";
7
+ import {
8
+ resolveDecisionV2Detail,
9
+ resolveDecisionV2Title,
10
+ resolveEnvelopeDisplayText,
11
+ resolveStoppedCommandText
12
+ } from "./approval-center-utils";
13
+ import type { GuardActionEnvelope, GuardApprovalRequest, GuardDecisionV2 } from "./guard-types";
4
14
 
5
15
  function assert(condition: boolean, message: string): void {
6
16
  if (!condition) {
@@ -146,3 +156,131 @@ assert(
146
156
  normalizedMalformedRequest.action_envelope_json === null,
147
157
  "T071: detail-route approval payloads normalize malformed envelopes before rendering"
148
158
  );
159
+
160
+ const BASE_DECISION_V2: GuardDecisionV2 = {
161
+ action: "block",
162
+ reason: "Credential file access detected",
163
+ user_title: "Wants to read a credential file",
164
+ user_body: "The agent is attempting to read a file that may contain secrets.",
165
+ harness_message: "BLOCKED: credential file read",
166
+ dashboard_primary_detail: "cat ~/.aws/credentials",
167
+ approval_scopes: ["artifact", "workspace"],
168
+ retry_instruction: null,
169
+ signals: [
170
+ {
171
+ signal_id: "secret:filesystem:env",
172
+ category: "secret",
173
+ severity: "high",
174
+ confidence: "strong",
175
+ detector: "guard-risk-v2",
176
+ title: "Secret file read",
177
+ plain_reason: "The action can read a credential file.",
178
+ technical_detail: null,
179
+ evidence_ref: "metadata.path_class",
180
+ redaction_level: "summary",
181
+ false_positive_hint: null,
182
+ advisory_id: null
183
+ }
184
+ ],
185
+ confidence: "strong"
186
+ };
187
+
188
+ assert(parseDecisionV2(undefined) === null, "T080: missing decision_v2_json falls back to null");
189
+ assert(parseDecisionV2(null) === null, "T080: null decision_v2_json falls back to null");
190
+ assert(parseDecisionV2({}) === null, "T080: empty object falls back to null");
191
+ assert(parseDecisionV2("block") === null, "T080: string decision_v2_json falls back to null");
192
+ assert(
193
+ parseDecisionV2({ ...BASE_DECISION_V2, action: "unknown_action" }) === null,
194
+ "T080: invalid action value falls back to null"
195
+ );
196
+ assert(
197
+ parseDecisionV2({ ...BASE_DECISION_V2, confidence: "unsure" }) === null,
198
+ "T080: invalid confidence value falls back to null"
199
+ );
200
+ assert(
201
+ parseDecisionV2({ ...BASE_DECISION_V2, approval_scopes: [42] }) === null,
202
+ "T080: non-string approval_scopes element falls back to null"
203
+ );
204
+ assert(
205
+ parseDecisionV2({ ...BASE_DECISION_V2, signals: [{ ...BASE_DECISION_V2.signals[0], signal_id: 1 }] }) === null,
206
+ "T080: invalid signal_id type falls back to null"
207
+ );
208
+ assert(
209
+ parseDecisionV2({ ...BASE_DECISION_V2, signals: [{ ...BASE_DECISION_V2.signals[0], severity: "extreme" }] }) === null,
210
+ "T080: invalid signal severity falls back to null"
211
+ );
212
+ assert(
213
+ parseDecisionV2({ ...BASE_DECISION_V2, signals: [{ ...BASE_DECISION_V2.signals[0], redaction_level: "full" }] }) ===
214
+ null,
215
+ "T080: invalid signal redaction level falls back to null"
216
+ );
217
+
218
+ const parsedDecisionV2 = parseDecisionV2(BASE_DECISION_V2);
219
+ assert(parsedDecisionV2 !== null, "T080: valid decision_v2 object parses correctly");
220
+ assert(parsedDecisionV2?.action === "block", "T080: parsed action matches source");
221
+ assert(parsedDecisionV2?.user_title === "Wants to read a credential file", "T080: parsed user_title matches source");
222
+ assert(parsedDecisionV2?.dashboard_primary_detail === "cat ~/.aws/credentials", "T080: parsed dashboard_primary_detail matches source");
223
+ assert(parsedDecisionV2?.confidence === "strong", "T080: parsed confidence matches source");
224
+ assert(parsedDecisionV2?.retry_instruction === null, "T080: null retry_instruction preserved");
225
+ assert(parsedDecisionV2?.signals.length === 1, "T080: signals array length preserved");
226
+ assert(parsedDecisionV2?.signals[0].signal_id === "secret:filesystem:env", "T080: signal_id preserved");
227
+
228
+ const normalizedWithV2 = normalizeApprovalRequest({ ...BASE_REQUEST, decision_v2_json: BASE_DECISION_V2 });
229
+ assert(normalizedWithV2.decision_v2_json !== null, "T081: valid decision_v2_json normalizes to non-null");
230
+ assert(
231
+ normalizedWithV2.decision_v2_json?.user_title === "Wants to read a credential file",
232
+ "T081: normalized user_title preserved"
233
+ );
234
+
235
+ const normalizedMalformedV2 = normalizeApprovalRequest({
236
+ ...BASE_REQUEST,
237
+ decision_v2_json: { action: "not-a-real-action" }
238
+ });
239
+ assert(normalizedMalformedV2.decision_v2_json === null, "T081: malformed decision_v2_json normalizes to null");
240
+
241
+ const normalizedMissingV2 = normalizeApprovalRequest({ ...BASE_REQUEST });
242
+ assert(normalizedMissingV2.decision_v2_json === null, "T081: absent decision_v2_json normalizes to null");
243
+
244
+ const requestWithV2: GuardApprovalRequest = {
245
+ ...BASE_REQUEST,
246
+ decision_v2_json: BASE_DECISION_V2
247
+ };
248
+
249
+ assert(
250
+ resolveDecisionV2Title(requestWithV2) === "Wants to read a credential file",
251
+ "T082: resolveDecisionV2Title returns user_title when decision_v2_json present"
252
+ );
253
+ assert(
254
+ resolveDecisionV2Detail(requestWithV2) === "cat ~/.aws/credentials",
255
+ "T082: resolveDecisionV2Detail returns dashboard_primary_detail when decision_v2_json present"
256
+ );
257
+ assert(
258
+ resolveStoppedCommandText(requestWithV2) === "git status",
259
+ "T082: stopped command remains launch target when decision detail is present"
260
+ );
261
+ assert(
262
+ resolveDecisionV2Title(BASE_REQUEST) === null,
263
+ "T082: resolveDecisionV2Title returns null when decision_v2_json absent"
264
+ );
265
+ assert(
266
+ resolveDecisionV2Detail(BASE_REQUEST) === null,
267
+ "T082: resolveDecisionV2Detail returns null when decision_v2_json absent"
268
+ );
269
+
270
+ const requestWithWhitespaceV2Title: GuardApprovalRequest = {
271
+ ...BASE_REQUEST,
272
+ decision_v2_json: { ...BASE_DECISION_V2, user_title: " " }
273
+ };
274
+ assert(
275
+ resolveDecisionV2Title(requestWithWhitespaceV2Title) === null,
276
+ "T082: resolveDecisionV2Title returns null for whitespace-only user_title"
277
+ );
278
+
279
+ const requestWithEmptyV2Detail: GuardApprovalRequest = {
280
+ ...BASE_REQUEST,
281
+ decision_v2_json: { ...BASE_DECISION_V2, dashboard_primary_detail: "" }
282
+ };
283
+ assert(
284
+ resolveDecisionV2Detail(requestWithEmptyV2Detail) === null,
285
+ "T082: resolveDecisionV2Detail returns null for empty dashboard_primary_detail"
286
+ );
@@ -1,15 +1,27 @@
1
- import { GUARD_ACTION_TYPES } from "./guard-types";
1
+ import {
2
+ GUARD_ACTION_TYPES,
3
+ GUARD_DECISION_V2_ACTIONS,
4
+ GUARD_DECISION_V2_CONFIDENCES,
5
+ GUARD_RISK_SIGNAL_V2_CATEGORIES,
6
+ GUARD_RISK_SIGNAL_V2_REDACTION_LEVELS,
7
+ GUARD_RISK_SIGNAL_V2_SEVERITIES
8
+ } from "./guard-types";
2
9
  import type {
3
10
  GuardActionEnvelope,
4
11
  GuardActionType,
5
12
  GuardApprovalRequest,
6
13
  GuardArtifactDiff,
14
+ GuardDecisionV2,
7
15
  GuardInventoryItem,
8
16
  GuardPolicyDecision,
9
17
  GuardReceipt,
10
18
  GuardRuntimeSnapshot,
11
19
  GuardSettingsPayload,
12
- GuardSettings
20
+ GuardSettings,
21
+ RiskSignalV2,
22
+ RiskSignalV2Category,
23
+ RiskSignalV2RedactionLevel,
24
+ RiskSignalV2Severity
13
25
  } from "./guard-types";
14
26
  import {
15
27
  getDemoDiff,
@@ -23,8 +35,9 @@ import {
23
35
  const GUARD_TOKEN_PARAM = "guard-token";
24
36
  const GUARD_DAEMON_PARAM = "guardDaemon";
25
37
 
26
- type RawGuardApprovalRequest = Omit<GuardApprovalRequest, "action_envelope_json"> & {
38
+ type RawGuardApprovalRequest = Omit<GuardApprovalRequest, "action_envelope_json" | "decision_v2_json"> & {
27
39
  action_envelope_json?: unknown;
40
+ decision_v2_json?: unknown;
28
41
  };
29
42
 
30
43
  type ApprovalRequestListPayload = {
@@ -158,6 +171,10 @@ function isStringArray(value: unknown): value is string[] {
158
171
  return Array.isArray(value) && value.every((item): item is string => typeof item === "string");
159
172
  }
160
173
 
174
+ function isNonEmptyString(value: unknown): value is string {
175
+ return typeof value === "string" && value.trim().length > 0;
176
+ }
177
+
161
178
  export function parseActionEnvelope(raw: unknown): GuardActionEnvelope | null {
162
179
  if (!isRecord(raw)) {
163
180
  return null;
@@ -231,8 +248,99 @@ export function parseActionEnvelope(raw: unknown): GuardActionEnvelope | null {
231
248
  };
232
249
  }
233
250
 
251
+ function isDecisionV2Action(value: unknown): value is GuardDecisionV2["action"] {
252
+ return typeof value === "string" && GUARD_DECISION_V2_ACTIONS.some((a) => a === value);
253
+ }
254
+
255
+ function isDecisionV2Confidence(value: unknown): value is GuardDecisionV2["confidence"] {
256
+ return typeof value === "string" && GUARD_DECISION_V2_CONFIDENCES.some((c) => c === value);
257
+ }
258
+
259
+ function isRiskSignalV2Category(value: unknown): value is RiskSignalV2Category {
260
+ return typeof value === "string" && GUARD_RISK_SIGNAL_V2_CATEGORIES.some((category) => category === value);
261
+ }
262
+
263
+ function isRiskSignalV2Severity(value: unknown): value is RiskSignalV2Severity {
264
+ return typeof value === "string" && GUARD_RISK_SIGNAL_V2_SEVERITIES.some((s) => s === value);
265
+ }
266
+
267
+ function isRiskSignalV2RedactionLevel(value: unknown): value is RiskSignalV2RedactionLevel {
268
+ return typeof value === "string" && GUARD_RISK_SIGNAL_V2_REDACTION_LEVELS.some((level) => level === value);
269
+ }
270
+
271
+ function isRiskSignalV2Array(value: unknown): value is RiskSignalV2[] {
272
+ if (!Array.isArray(value)) {
273
+ return false;
274
+ }
275
+ return value.every((item) => {
276
+ if (!isRecord(item)) {
277
+ return false;
278
+ }
279
+ return (
280
+ isNonEmptyString(item["signal_id"]) &&
281
+ isRiskSignalV2Category(item["category"]) &&
282
+ isRiskSignalV2Severity(item["severity"]) &&
283
+ isDecisionV2Confidence(item["confidence"]) &&
284
+ isNonEmptyString(item["detector"]) &&
285
+ isNonEmptyString(item["title"]) &&
286
+ isNonEmptyString(item["plain_reason"]) &&
287
+ isStringOrNull(item["technical_detail"]) &&
288
+ isStringOrNull(item["evidence_ref"]) &&
289
+ isRiskSignalV2RedactionLevel(item["redaction_level"]) &&
290
+ isStringOrNull(item["false_positive_hint"]) &&
291
+ isStringOrNull(item["advisory_id"])
292
+ );
293
+ });
294
+ }
295
+
296
+ export function parseDecisionV2(raw: unknown): GuardDecisionV2 | null {
297
+ if (!isRecord(raw)) {
298
+ return null;
299
+ }
300
+ const action = raw["action"];
301
+ const reason = raw["reason"];
302
+ const userTitle = raw["user_title"];
303
+ const userBody = raw["user_body"];
304
+ const harnessMessage = raw["harness_message"];
305
+ const dashboardPrimaryDetail = raw["dashboard_primary_detail"];
306
+ const approvalScopes = raw["approval_scopes"];
307
+ const retryInstruction = raw["retry_instruction"];
308
+ const signals = raw["signals"];
309
+ const confidence = raw["confidence"];
310
+ if (
311
+ !isDecisionV2Action(action) ||
312
+ !isNonEmptyString(reason) ||
313
+ !isNonEmptyString(userTitle) ||
314
+ !isNonEmptyString(userBody) ||
315
+ !isNonEmptyString(harnessMessage) ||
316
+ !isNonEmptyString(dashboardPrimaryDetail) ||
317
+ !isStringArray(approvalScopes) ||
318
+ !isStringOrNull(retryInstruction) ||
319
+ !isRiskSignalV2Array(signals) ||
320
+ !isDecisionV2Confidence(confidence)
321
+ ) {
322
+ return null;
323
+ }
324
+ return {
325
+ action,
326
+ reason,
327
+ user_title: userTitle,
328
+ user_body: userBody,
329
+ harness_message: harnessMessage,
330
+ dashboard_primary_detail: dashboardPrimaryDetail,
331
+ approval_scopes: approvalScopes,
332
+ retry_instruction: retryInstruction,
333
+ signals,
334
+ confidence
335
+ };
336
+ }
337
+
234
338
  export function normalizeApprovalRequest(item: RawGuardApprovalRequest): GuardApprovalRequest {
235
- return { ...item, action_envelope_json: parseActionEnvelope(item.action_envelope_json) };
339
+ return {
340
+ ...item,
341
+ action_envelope_json: parseActionEnvelope(item.action_envelope_json),
342
+ decision_v2_json: parseDecisionV2(item.decision_v2_json)
343
+ };
236
344
  }
237
345
 
238
346
  function normalizeApprovalRequests(items: RawGuardApprovalRequest[] | null | undefined): GuardApprovalRequest[] {
@@ -15,6 +15,62 @@ export const GUARD_ACTION_TYPES = [
15
15
 
16
16
  export type GuardActionType = (typeof GUARD_ACTION_TYPES)[number];
17
17
 
18
+ export const GUARD_DECISION_V2_ACTIONS = ["allow", "warn", "ask", "block"] as const;
19
+ export const GUARD_DECISION_V2_CONFIDENCES = ["weak", "likely", "strong"] as const;
20
+ export const GUARD_RISK_SIGNAL_V2_CATEGORIES = [
21
+ "secret",
22
+ "network",
23
+ "prompt",
24
+ "mcp",
25
+ "skill",
26
+ "supply_chain",
27
+ "encoded",
28
+ "persistence",
29
+ "bypass",
30
+ "false_positive",
31
+ "filesystem",
32
+ "execution",
33
+ "publisher",
34
+ "policy",
35
+ "provenance"
36
+ ] as const;
37
+ export const GUARD_RISK_SIGNAL_V2_SEVERITIES = ["info", "low", "medium", "high", "critical"] as const;
38
+ export const GUARD_RISK_SIGNAL_V2_REDACTION_LEVELS = ["none", "summary", "redacted"] as const;
39
+
40
+ export type GuardDecisionV2Action = (typeof GUARD_DECISION_V2_ACTIONS)[number];
41
+ export type GuardDecisionV2Confidence = (typeof GUARD_DECISION_V2_CONFIDENCES)[number];
42
+ export type RiskSignalV2Category = (typeof GUARD_RISK_SIGNAL_V2_CATEGORIES)[number];
43
+ export type RiskSignalV2Severity = (typeof GUARD_RISK_SIGNAL_V2_SEVERITIES)[number];
44
+ export type RiskSignalV2RedactionLevel = (typeof GUARD_RISK_SIGNAL_V2_REDACTION_LEVELS)[number];
45
+
46
+ export type RiskSignalV2 = {
47
+ signal_id: string;
48
+ category: RiskSignalV2Category;
49
+ severity: RiskSignalV2Severity;
50
+ confidence: GuardDecisionV2Confidence;
51
+ detector: string;
52
+ title: string;
53
+ plain_reason: string;
54
+ technical_detail: string | null;
55
+ evidence_ref: string | null;
56
+ redaction_level: RiskSignalV2RedactionLevel;
57
+ false_positive_hint: string | null;
58
+ advisory_id: string | null;
59
+ };
60
+
61
+ export type GuardDecisionV2 = {
62
+ action: GuardDecisionV2Action;
63
+ reason: string;
64
+ user_title: string;
65
+ user_body: string;
66
+ harness_message: string;
67
+ dashboard_primary_detail: string;
68
+ approval_scopes: string[];
69
+ retry_instruction: string | null;
70
+ signals: RiskSignalV2[];
71
+ confidence: GuardDecisionV2Confidence;
72
+ };
73
+
18
74
  export type GuardActionEnvelope = {
19
75
  schema_version: number;
20
76
  action_id: string;
@@ -74,6 +130,7 @@ export type GuardApprovalRequest = {
74
130
  created_at: string;
75
131
  resolved_at: string | null;
76
132
  action_envelope_json?: GuardActionEnvelope | null;
133
+ decision_v2_json?: GuardDecisionV2 | null;
77
134
  };
78
135
 
79
136
  export type GuardRuntimeState = {
@@ -4,7 +4,7 @@ build-backend = "hatchling.build"
4
4
 
5
5
  [project]
6
6
  name = "plugin-scanner"
7
- version = "2.0.102"
7
+ version = "2.0.104"
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.102"
7
+ version = "2.0.104"
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"
@@ -1912,12 +1912,11 @@ def run_guard_command(
1912
1912
  output_stream=output_stream,
1913
1913
  )
1914
1914
  return 0
1915
+ incoming_reason = _decision_v2_harness_message(payload) or payload.get("permission_decision_reason")
1915
1916
  if _should_emit_native_hook_exit_block(args, event_name=hook_event_name, policy_action=policy_action):
1916
- _emit_native_hook_block_stderr(
1917
- _native_hook_reason_for_harness(args.harness, payload.get("permission_decision_reason"))
1918
- )
1917
+ _emit_native_hook_block_stderr(_native_hook_reason_for_harness(args.harness, incoming_reason))
1919
1918
  return 2
1920
- reason = _native_hook_reason_for_harness(args.harness, payload.get("permission_decision_reason"))
1919
+ reason = _native_hook_reason_for_harness(args.harness, incoming_reason)
1921
1920
  if _should_emit_claude_native_pretooluse_notice(
1922
1921
  args,
1923
1922
  event_name=hook_event_name,
@@ -176,6 +176,9 @@ class GuardConfig:
176
176
  telemetry: bool = False
177
177
  sync: bool = False
178
178
  billing: bool = False
179
+ runtime_detector_registry: bool = False
180
+ runtime_detector_timeout_ms: int = 50
181
+ runtime_detector_disabled_ids: tuple[str, ...] = ()
179
182
  risk_actions: dict[str, GuardAction] | None = None
180
183
  harness_risk_actions: dict[str, dict[str, GuardAction]] | None = None
181
184
  harness_actions: dict[str, GuardAction] | None = None
@@ -252,6 +255,9 @@ def load_guard_config(guard_home: Path, workspace: Path | None = None) -> GuardC
252
255
  telemetry=bool(merged.get("telemetry", False)),
253
256
  sync=bool(merged.get("sync", False)),
254
257
  billing=bool(merged.get("billing", False)),
258
+ runtime_detector_registry=_coerce_loaded_bool(merged.get("runtime_detector_registry", False)),
259
+ runtime_detector_timeout_ms=_coerce_loaded_positive_int(merged.get("runtime_detector_timeout_ms", 50), 50),
260
+ runtime_detector_disabled_ids=_coerce_loaded_string_tuple(merged.get("runtime_detector_disabled_ids")),
255
261
  harness_actions=_coerce_action_map(merged.get("harnesses")),
256
262
  publisher_actions=_coerce_action_map(merged.get("publishers")),
257
263
  artifact_actions=_coerce_action_map(merged.get("artifacts")),
@@ -346,6 +352,22 @@ def _coerce_loaded_security_level(value: object) -> str:
346
352
  return DEFAULT_SECURITY_LEVEL
347
353
 
348
354
 
355
+ def _coerce_loaded_bool(value: object) -> bool:
356
+ return value if isinstance(value, bool) else False
357
+
358
+
359
+ def _coerce_loaded_positive_int(value: object, fallback: int) -> int:
360
+ if isinstance(value, int) and not isinstance(value, bool) and value > 0:
361
+ return value
362
+ return fallback
363
+
364
+
365
+ def _coerce_loaded_string_tuple(value: object) -> tuple[str, ...]:
366
+ if not isinstance(value, list):
367
+ return ()
368
+ return tuple(item for item in value if isinstance(item, str) and item.strip())
369
+
370
+
349
371
  def _coerce_risk_action_payload(value: object) -> dict[str, GuardAction]:
350
372
  if not isinstance(value, dict):
351
373
  raise ValueError("Risk actions must be a table.")