plugin-scanner 2.0.140__tar.gz → 2.0.142__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 (433) hide show
  1. {plugin_scanner-2.0.140 → plugin_scanner-2.0.142}/PKG-INFO +1 -1
  2. {plugin_scanner-2.0.140 → plugin_scanner-2.0.142}/dashboard/src/guard-types.ts +1 -0
  3. {plugin_scanner-2.0.140 → plugin_scanner-2.0.142}/dashboard/src/settings-workspace.tsx +60 -2
  4. plugin_scanner-2.0.142/docs/guard/release-notes.md +37 -0
  5. {plugin_scanner-2.0.140 → plugin_scanner-2.0.142}/pyproject.toml +1 -1
  6. {plugin_scanner-2.0.140 → plugin_scanner-2.0.142}/pyproject.toml.bak +1 -1
  7. {plugin_scanner-2.0.140 → plugin_scanner-2.0.142}/src/codex_plugin_scanner/guard/approvals.py +2 -0
  8. {plugin_scanner-2.0.140 → plugin_scanner-2.0.142}/src/codex_plugin_scanner/guard/daemon/static/assets/guard-dashboard.js +37 -0
  9. {plugin_scanner-2.0.140 → plugin_scanner-2.0.142}/src/codex_plugin_scanner/guard/daemon/static/assets/index.css +5 -0
  10. {plugin_scanner-2.0.140 → plugin_scanner-2.0.142}/src/codex_plugin_scanner/guard/runtime/runner.py +16 -1
  11. {plugin_scanner-2.0.140 → plugin_scanner-2.0.142}/src/codex_plugin_scanner/guard/store.py +13 -0
  12. {plugin_scanner-2.0.140 → plugin_scanner-2.0.142}/src/codex_plugin_scanner/version.py +1 -1
  13. {plugin_scanner-2.0.140 → plugin_scanner-2.0.142}/tests/test_guard_daemon_manager.py +74 -0
  14. {plugin_scanner-2.0.140 → plugin_scanner-2.0.142}/tests/test_guard_daemon_perf.py +116 -0
  15. {plugin_scanner-2.0.140 → plugin_scanner-2.0.142}/.clusterfuzzlite/Dockerfile +0 -0
  16. {plugin_scanner-2.0.140 → plugin_scanner-2.0.142}/.clusterfuzzlite/build.sh +0 -0
  17. {plugin_scanner-2.0.140 → plugin_scanner-2.0.142}/.clusterfuzzlite/project.yaml +0 -0
  18. {plugin_scanner-2.0.140 → plugin_scanner-2.0.142}/.clusterfuzzlite/requirements-atheris.txt +0 -0
  19. {plugin_scanner-2.0.140 → plugin_scanner-2.0.142}/.dockerignore +0 -0
  20. {plugin_scanner-2.0.140 → plugin_scanner-2.0.142}/.github/CODEOWNERS +0 -0
  21. {plugin_scanner-2.0.140 → plugin_scanner-2.0.142}/.github/ISSUE_TEMPLATE/bug-report.yml +0 -0
  22. {plugin_scanner-2.0.140 → plugin_scanner-2.0.142}/.github/ISSUE_TEMPLATE/config.yml +0 -0
  23. {plugin_scanner-2.0.140 → plugin_scanner-2.0.142}/.github/ISSUE_TEMPLATE/feature-request.yml +0 -0
  24. {plugin_scanner-2.0.140 → plugin_scanner-2.0.142}/.github/dependabot.yml +0 -0
  25. {plugin_scanner-2.0.140 → plugin_scanner-2.0.142}/.github/workflows/ci.yml +0 -0
  26. {plugin_scanner-2.0.140 → plugin_scanner-2.0.142}/.github/workflows/codeql.yml +0 -0
  27. {plugin_scanner-2.0.140 → plugin_scanner-2.0.142}/.github/workflows/dependabot-uv-lock.yml +0 -0
  28. {plugin_scanner-2.0.140 → plugin_scanner-2.0.142}/.github/workflows/fuzz.yml +0 -0
  29. {plugin_scanner-2.0.140 → plugin_scanner-2.0.142}/.github/workflows/harness-smoke.yml +0 -0
  30. {plugin_scanner-2.0.140 → plugin_scanner-2.0.142}/.github/workflows/publish.yml +0 -0
  31. {plugin_scanner-2.0.140 → plugin_scanner-2.0.142}/.github/workflows/scorecard.yml +0 -0
  32. {plugin_scanner-2.0.140 → plugin_scanner-2.0.142}/.gitignore +0 -0
  33. {plugin_scanner-2.0.140 → plugin_scanner-2.0.142}/.pre-commit-hooks.yaml +0 -0
  34. {plugin_scanner-2.0.140 → plugin_scanner-2.0.142}/CONTRIBUTING.md +0 -0
  35. {plugin_scanner-2.0.140 → plugin_scanner-2.0.142}/Dockerfile +0 -0
  36. {plugin_scanner-2.0.140 → plugin_scanner-2.0.142}/LICENSE +0 -0
  37. {plugin_scanner-2.0.140 → plugin_scanner-2.0.142}/README.md +0 -0
  38. {plugin_scanner-2.0.140 → plugin_scanner-2.0.142}/SECURITY.md +0 -0
  39. {plugin_scanner-2.0.140 → plugin_scanner-2.0.142}/dashboard/index.html +0 -0
  40. {plugin_scanner-2.0.140 → plugin_scanner-2.0.142}/dashboard/package.json +0 -0
  41. {plugin_scanner-2.0.140 → plugin_scanner-2.0.142}/dashboard/pnpm-lock.yaml +0 -0
  42. {plugin_scanner-2.0.140 → plugin_scanner-2.0.142}/dashboard/public/apple-touch-icon.png +0 -0
  43. {plugin_scanner-2.0.140 → plugin_scanner-2.0.142}/dashboard/public/brand/Logo_Icon_Dark.png +0 -0
  44. {plugin_scanner-2.0.140 → plugin_scanner-2.0.142}/dashboard/public/brand/Logo_Whole.png +0 -0
  45. {plugin_scanner-2.0.140 → plugin_scanner-2.0.142}/dashboard/public/favicon-16x16.png +0 -0
  46. {plugin_scanner-2.0.140 → plugin_scanner-2.0.142}/dashboard/public/favicon-32x32.png +0 -0
  47. {plugin_scanner-2.0.140 → plugin_scanner-2.0.142}/dashboard/public/favicon.ico +0 -0
  48. {plugin_scanner-2.0.140 → plugin_scanner-2.0.142}/dashboard/src/app.tsx +0 -0
  49. {plugin_scanner-2.0.140 → plugin_scanner-2.0.142}/dashboard/src/approval-center-layout.test.ts +0 -0
  50. {plugin_scanner-2.0.140 → plugin_scanner-2.0.142}/dashboard/src/approval-center-layout.tsx +0 -0
  51. {plugin_scanner-2.0.140 → plugin_scanner-2.0.142}/dashboard/src/approval-center-primitives.tsx +0 -0
  52. {plugin_scanner-2.0.140 → plugin_scanner-2.0.142}/dashboard/src/approval-center-review-cards.tsx +0 -0
  53. {plugin_scanner-2.0.140 → plugin_scanner-2.0.142}/dashboard/src/approval-center-utils.ts +0 -0
  54. {plugin_scanner-2.0.140 → plugin_scanner-2.0.142}/dashboard/src/data-flow-evidence-card.tsx +0 -0
  55. {plugin_scanner-2.0.140 → plugin_scanner-2.0.142}/dashboard/src/fleet-workspace.tsx +0 -0
  56. {plugin_scanner-2.0.140 → plugin_scanner-2.0.142}/dashboard/src/guard-api.test.ts +0 -0
  57. {plugin_scanner-2.0.140 → plugin_scanner-2.0.142}/dashboard/src/guard-api.ts +0 -0
  58. {plugin_scanner-2.0.140 → plugin_scanner-2.0.142}/dashboard/src/guard-demo.ts +0 -0
  59. {plugin_scanner-2.0.140 → plugin_scanner-2.0.142}/dashboard/src/main.tsx +0 -0
  60. {plugin_scanner-2.0.140 → plugin_scanner-2.0.142}/dashboard/src/receipts-workspace.test.ts +0 -0
  61. {plugin_scanner-2.0.140 → plugin_scanner-2.0.142}/dashboard/src/receipts-workspace.tsx +0 -0
  62. {plugin_scanner-2.0.140 → plugin_scanner-2.0.142}/dashboard/src/risk-signal-cards.test.ts +0 -0
  63. {plugin_scanner-2.0.140 → plugin_scanner-2.0.142}/dashboard/src/risk-signal-cards.tsx +0 -0
  64. {plugin_scanner-2.0.140 → plugin_scanner-2.0.142}/dashboard/src/runtime-overview.test.ts +0 -0
  65. {plugin_scanner-2.0.140 → plugin_scanner-2.0.142}/dashboard/src/runtime-overview.tsx +0 -0
  66. {plugin_scanner-2.0.140 → plugin_scanner-2.0.142}/dashboard/src/settings-workspace.test.ts +0 -0
  67. {plugin_scanner-2.0.140 → plugin_scanner-2.0.142}/dashboard/src/styles.css +0 -0
  68. {plugin_scanner-2.0.140 → plugin_scanner-2.0.142}/dashboard/src/vite-env.d.ts +0 -0
  69. {plugin_scanner-2.0.140 → plugin_scanner-2.0.142}/dashboard/tsconfig.json +0 -0
  70. {plugin_scanner-2.0.140 → plugin_scanner-2.0.142}/dashboard/vite.config.ts +0 -0
  71. {plugin_scanner-2.0.140 → plugin_scanner-2.0.142}/docker-requirements.txt +0 -0
  72. {plugin_scanner-2.0.140 → plugin_scanner-2.0.142}/docs/guard/approval-audit.md +0 -0
  73. {plugin_scanner-2.0.140 → plugin_scanner-2.0.142}/docs/guard/architecture.md +0 -0
  74. {plugin_scanner-2.0.140 → plugin_scanner-2.0.142}/docs/guard/get-started.md +0 -0
  75. {plugin_scanner-2.0.140 → plugin_scanner-2.0.142}/docs/guard/harness-support.md +0 -0
  76. {plugin_scanner-2.0.140 → plugin_scanner-2.0.142}/docs/guard/local-vs-cloud.md +0 -0
  77. {plugin_scanner-2.0.140 → plugin_scanner-2.0.142}/docs/guard/release-checklist.md +0 -0
  78. {plugin_scanner-2.0.140 → plugin_scanner-2.0.142}/docs/guard/smoke-tests.md +0 -0
  79. {plugin_scanner-2.0.140 → plugin_scanner-2.0.142}/docs/guard/testing-matrix.md +0 -0
  80. {plugin_scanner-2.0.140 → plugin_scanner-2.0.142}/docs/trust/mcp-trust-draft.md +0 -0
  81. {plugin_scanner-2.0.140 → plugin_scanner-2.0.142}/docs/trust/plugin-trust-draft.md +0 -0
  82. {plugin_scanner-2.0.140 → plugin_scanner-2.0.142}/docs/trust/skill-trust-local.md +0 -0
  83. {plugin_scanner-2.0.140 → plugin_scanner-2.0.142}/fuzzers/manifest_fuzzer.py +0 -0
  84. {plugin_scanner-2.0.140 → plugin_scanner-2.0.142}/requirements.txt +0 -0
  85. {plugin_scanner-2.0.140 → plugin_scanner-2.0.142}/schemas/plugin-quality.v1.json +0 -0
  86. {plugin_scanner-2.0.140 → plugin_scanner-2.0.142}/schemas/scan-result.v1.json +0 -0
  87. {plugin_scanner-2.0.140 → plugin_scanner-2.0.142}/schemas/verify-result.v1.json +0 -0
  88. {plugin_scanner-2.0.140 → plugin_scanner-2.0.142}/src/codex_plugin_scanner/__init__.py +0 -0
  89. {plugin_scanner-2.0.140 → plugin_scanner-2.0.142}/src/codex_plugin_scanner/action_runner.py +0 -0
  90. {plugin_scanner-2.0.140 → plugin_scanner-2.0.142}/src/codex_plugin_scanner/argparse_utils.py +0 -0
  91. {plugin_scanner-2.0.140 → plugin_scanner-2.0.142}/src/codex_plugin_scanner/checks/__init__.py +0 -0
  92. {plugin_scanner-2.0.140 → plugin_scanner-2.0.142}/src/codex_plugin_scanner/checks/best_practices.py +0 -0
  93. {plugin_scanner-2.0.140 → plugin_scanner-2.0.142}/src/codex_plugin_scanner/checks/claude.py +0 -0
  94. {plugin_scanner-2.0.140 → plugin_scanner-2.0.142}/src/codex_plugin_scanner/checks/code_quality.py +0 -0
  95. {plugin_scanner-2.0.140 → plugin_scanner-2.0.142}/src/codex_plugin_scanner/checks/ecosystem_common.py +0 -0
  96. {plugin_scanner-2.0.140 → plugin_scanner-2.0.142}/src/codex_plugin_scanner/checks/gemini.py +0 -0
  97. {plugin_scanner-2.0.140 → plugin_scanner-2.0.142}/src/codex_plugin_scanner/checks/manifest.py +0 -0
  98. {plugin_scanner-2.0.140 → plugin_scanner-2.0.142}/src/codex_plugin_scanner/checks/manifest_support.py +0 -0
  99. {plugin_scanner-2.0.140 → plugin_scanner-2.0.142}/src/codex_plugin_scanner/checks/marketplace.py +0 -0
  100. {plugin_scanner-2.0.140 → plugin_scanner-2.0.142}/src/codex_plugin_scanner/checks/mcp_security.py +0 -0
  101. {plugin_scanner-2.0.140 → plugin_scanner-2.0.142}/src/codex_plugin_scanner/checks/opencode.py +0 -0
  102. {plugin_scanner-2.0.140 → plugin_scanner-2.0.142}/src/codex_plugin_scanner/checks/operational_security.py +0 -0
  103. {plugin_scanner-2.0.140 → plugin_scanner-2.0.142}/src/codex_plugin_scanner/checks/security.py +0 -0
  104. {plugin_scanner-2.0.140 → plugin_scanner-2.0.142}/src/codex_plugin_scanner/checks/skill_security.py +0 -0
  105. {plugin_scanner-2.0.140 → plugin_scanner-2.0.142}/src/codex_plugin_scanner/cli.py +0 -0
  106. {plugin_scanner-2.0.140 → plugin_scanner-2.0.142}/src/codex_plugin_scanner/cli_ui.py +0 -0
  107. {plugin_scanner-2.0.140 → plugin_scanner-2.0.142}/src/codex_plugin_scanner/config.py +0 -0
  108. {plugin_scanner-2.0.140 → plugin_scanner-2.0.142}/src/codex_plugin_scanner/ecosystems/__init__.py +0 -0
  109. {plugin_scanner-2.0.140 → plugin_scanner-2.0.142}/src/codex_plugin_scanner/ecosystems/base.py +0 -0
  110. {plugin_scanner-2.0.140 → plugin_scanner-2.0.142}/src/codex_plugin_scanner/ecosystems/claude.py +0 -0
  111. {plugin_scanner-2.0.140 → plugin_scanner-2.0.142}/src/codex_plugin_scanner/ecosystems/codex.py +0 -0
  112. {plugin_scanner-2.0.140 → plugin_scanner-2.0.142}/src/codex_plugin_scanner/ecosystems/detect.py +0 -0
  113. {plugin_scanner-2.0.140 → plugin_scanner-2.0.142}/src/codex_plugin_scanner/ecosystems/gemini.py +0 -0
  114. {plugin_scanner-2.0.140 → plugin_scanner-2.0.142}/src/codex_plugin_scanner/ecosystems/opencode.py +0 -0
  115. {plugin_scanner-2.0.140 → plugin_scanner-2.0.142}/src/codex_plugin_scanner/ecosystems/registry.py +0 -0
  116. {plugin_scanner-2.0.140 → plugin_scanner-2.0.142}/src/codex_plugin_scanner/ecosystems/types.py +0 -0
  117. {plugin_scanner-2.0.140 → plugin_scanner-2.0.142}/src/codex_plugin_scanner/github_reporting.py +0 -0
  118. {plugin_scanner-2.0.140 → plugin_scanner-2.0.142}/src/codex_plugin_scanner/guard/__init__.py +0 -0
  119. {plugin_scanner-2.0.140 → plugin_scanner-2.0.142}/src/codex_plugin_scanner/guard/access_graph_events.py +0 -0
  120. {plugin_scanner-2.0.140 → plugin_scanner-2.0.142}/src/codex_plugin_scanner/guard/adapters/__init__.py +0 -0
  121. {plugin_scanner-2.0.140 → plugin_scanner-2.0.142}/src/codex_plugin_scanner/guard/adapters/antigravity.py +0 -0
  122. {plugin_scanner-2.0.140 → plugin_scanner-2.0.142}/src/codex_plugin_scanner/guard/adapters/base.py +0 -0
  123. {plugin_scanner-2.0.140 → plugin_scanner-2.0.142}/src/codex_plugin_scanner/guard/adapters/claude_code.py +0 -0
  124. {plugin_scanner-2.0.140 → plugin_scanner-2.0.142}/src/codex_plugin_scanner/guard/adapters/cloud_identity.py +0 -0
  125. {plugin_scanner-2.0.140 → plugin_scanner-2.0.142}/src/codex_plugin_scanner/guard/adapters/codex.py +0 -0
  126. {plugin_scanner-2.0.140 → plugin_scanner-2.0.142}/src/codex_plugin_scanner/guard/adapters/contracts.py +0 -0
  127. {plugin_scanner-2.0.140 → plugin_scanner-2.0.142}/src/codex_plugin_scanner/guard/adapters/copilot.py +0 -0
  128. {plugin_scanner-2.0.140 → plugin_scanner-2.0.142}/src/codex_plugin_scanner/guard/adapters/cursor.py +0 -0
  129. {plugin_scanner-2.0.140 → plugin_scanner-2.0.142}/src/codex_plugin_scanner/guard/adapters/gemini.py +0 -0
  130. {plugin_scanner-2.0.140 → plugin_scanner-2.0.142}/src/codex_plugin_scanner/guard/adapters/hermes.py +0 -0
  131. {plugin_scanner-2.0.140 → plugin_scanner-2.0.142}/src/codex_plugin_scanner/guard/adapters/mcp_servers.py +0 -0
  132. {plugin_scanner-2.0.140 → plugin_scanner-2.0.142}/src/codex_plugin_scanner/guard/adapters/openclaw.py +0 -0
  133. {plugin_scanner-2.0.140 → plugin_scanner-2.0.142}/src/codex_plugin_scanner/guard/adapters/openclaw_config.py +0 -0
  134. {plugin_scanner-2.0.140 → plugin_scanner-2.0.142}/src/codex_plugin_scanner/guard/adapters/openclaw_support.py +0 -0
  135. {plugin_scanner-2.0.140 → plugin_scanner-2.0.142}/src/codex_plugin_scanner/guard/adapters/opencode.py +0 -0
  136. {plugin_scanner-2.0.140 → plugin_scanner-2.0.142}/src/codex_plugin_scanner/guard/adapters/opencode_artifacts.py +0 -0
  137. {plugin_scanner-2.0.140 → plugin_scanner-2.0.142}/src/codex_plugin_scanner/guard/advisory_model.py +0 -0
  138. {plugin_scanner-2.0.140 → plugin_scanner-2.0.142}/src/codex_plugin_scanner/guard/bridge/__init__.py +0 -0
  139. {plugin_scanner-2.0.140 → plugin_scanner-2.0.142}/src/codex_plugin_scanner/guard/capabilities.py +0 -0
  140. {plugin_scanner-2.0.140 → plugin_scanner-2.0.142}/src/codex_plugin_scanner/guard/cli/__init__.py +0 -0
  141. {plugin_scanner-2.0.140 → plugin_scanner-2.0.142}/src/codex_plugin_scanner/guard/cli/approval_commands.py +0 -0
  142. {plugin_scanner-2.0.140 → plugin_scanner-2.0.142}/src/codex_plugin_scanner/guard/cli/bootstrap.py +0 -0
  143. {plugin_scanner-2.0.140 → plugin_scanner-2.0.142}/src/codex_plugin_scanner/guard/cli/commands.py +0 -0
  144. {plugin_scanner-2.0.140 → plugin_scanner-2.0.142}/src/codex_plugin_scanner/guard/cli/connect_flow.py +0 -0
  145. {plugin_scanner-2.0.140 → plugin_scanner-2.0.142}/src/codex_plugin_scanner/guard/cli/install_commands.py +0 -0
  146. {plugin_scanner-2.0.140 → plugin_scanner-2.0.142}/src/codex_plugin_scanner/guard/cli/product.py +0 -0
  147. {plugin_scanner-2.0.140 → plugin_scanner-2.0.142}/src/codex_plugin_scanner/guard/cli/prompt.py +0 -0
  148. {plugin_scanner-2.0.140 → plugin_scanner-2.0.142}/src/codex_plugin_scanner/guard/cli/render.py +0 -0
  149. {plugin_scanner-2.0.140 → plugin_scanner-2.0.142}/src/codex_plugin_scanner/guard/cli/update_commands.py +0 -0
  150. {plugin_scanner-2.0.140 → plugin_scanner-2.0.142}/src/codex_plugin_scanner/guard/codex_config.py +0 -0
  151. {plugin_scanner-2.0.140 → plugin_scanner-2.0.142}/src/codex_plugin_scanner/guard/config.py +0 -0
  152. {plugin_scanner-2.0.140 → plugin_scanner-2.0.142}/src/codex_plugin_scanner/guard/consumer/__init__.py +0 -0
  153. {plugin_scanner-2.0.140 → plugin_scanner-2.0.142}/src/codex_plugin_scanner/guard/consumer/service.py +0 -0
  154. {plugin_scanner-2.0.140 → plugin_scanner-2.0.142}/src/codex_plugin_scanner/guard/daemon/__init__.py +0 -0
  155. {plugin_scanner-2.0.140 → plugin_scanner-2.0.142}/src/codex_plugin_scanner/guard/daemon/client.py +0 -0
  156. {plugin_scanner-2.0.140 → plugin_scanner-2.0.142}/src/codex_plugin_scanner/guard/daemon/manager.py +0 -0
  157. {plugin_scanner-2.0.140 → plugin_scanner-2.0.142}/src/codex_plugin_scanner/guard/daemon/server.py +0 -0
  158. {plugin_scanner-2.0.140 → plugin_scanner-2.0.142}/src/codex_plugin_scanner/guard/daemon/static/apple-touch-icon.png +0 -0
  159. {plugin_scanner-2.0.140 → plugin_scanner-2.0.142}/src/codex_plugin_scanner/guard/daemon/static/brand/Logo_Icon_Dark.png +0 -0
  160. {plugin_scanner-2.0.140 → plugin_scanner-2.0.142}/src/codex_plugin_scanner/guard/daemon/static/brand/Logo_Whole.png +0 -0
  161. {plugin_scanner-2.0.140 → plugin_scanner-2.0.142}/src/codex_plugin_scanner/guard/daemon/static/favicon-16x16.png +0 -0
  162. {plugin_scanner-2.0.140 → plugin_scanner-2.0.142}/src/codex_plugin_scanner/guard/daemon/static/favicon-32x32.png +0 -0
  163. {plugin_scanner-2.0.140 → plugin_scanner-2.0.142}/src/codex_plugin_scanner/guard/daemon/static/favicon.ico +0 -0
  164. {plugin_scanner-2.0.140 → plugin_scanner-2.0.142}/src/codex_plugin_scanner/guard/daemon/static/index.html +0 -0
  165. {plugin_scanner-2.0.140 → plugin_scanner-2.0.142}/src/codex_plugin_scanner/guard/edge_events.py +0 -0
  166. {plugin_scanner-2.0.140 → plugin_scanner-2.0.142}/src/codex_plugin_scanner/guard/incident.py +0 -0
  167. {plugin_scanner-2.0.140 → plugin_scanner-2.0.142}/src/codex_plugin_scanner/guard/launcher.py +0 -0
  168. {plugin_scanner-2.0.140 → plugin_scanner-2.0.142}/src/codex_plugin_scanner/guard/mcp_tool_calls.py +0 -0
  169. {plugin_scanner-2.0.140 → plugin_scanner-2.0.142}/src/codex_plugin_scanner/guard/models.py +0 -0
  170. {plugin_scanner-2.0.140 → plugin_scanner-2.0.142}/src/codex_plugin_scanner/guard/policy/__init__.py +0 -0
  171. {plugin_scanner-2.0.140 → plugin_scanner-2.0.142}/src/codex_plugin_scanner/guard/policy/engine.py +0 -0
  172. {plugin_scanner-2.0.140 → plugin_scanner-2.0.142}/src/codex_plugin_scanner/guard/protect.py +0 -0
  173. {plugin_scanner-2.0.140 → plugin_scanner-2.0.142}/src/codex_plugin_scanner/guard/proxy/__init__.py +0 -0
  174. {plugin_scanner-2.0.140 → plugin_scanner-2.0.142}/src/codex_plugin_scanner/guard/proxy/remote.py +0 -0
  175. {plugin_scanner-2.0.140 → plugin_scanner-2.0.142}/src/codex_plugin_scanner/guard/proxy/runtime_mcp.py +0 -0
  176. {plugin_scanner-2.0.140 → plugin_scanner-2.0.142}/src/codex_plugin_scanner/guard/proxy/stdio.py +0 -0
  177. {plugin_scanner-2.0.140 → plugin_scanner-2.0.142}/src/codex_plugin_scanner/guard/receipts/__init__.py +0 -0
  178. {plugin_scanner-2.0.140 → plugin_scanner-2.0.142}/src/codex_plugin_scanner/guard/receipts/manager.py +0 -0
  179. {plugin_scanner-2.0.140 → plugin_scanner-2.0.142}/src/codex_plugin_scanner/guard/redaction.py +0 -0
  180. {plugin_scanner-2.0.140 → plugin_scanner-2.0.142}/src/codex_plugin_scanner/guard/risk.py +0 -0
  181. {plugin_scanner-2.0.140 → plugin_scanner-2.0.142}/src/codex_plugin_scanner/guard/runtime/__init__.py +0 -0
  182. {plugin_scanner-2.0.140 → plugin_scanner-2.0.142}/src/codex_plugin_scanner/guard/runtime/action_identity.py +0 -0
  183. {plugin_scanner-2.0.140 → plugin_scanner-2.0.142}/src/codex_plugin_scanner/guard/runtime/actions.py +0 -0
  184. {plugin_scanner-2.0.140 → plugin_scanner-2.0.142}/src/codex_plugin_scanner/guard/runtime/advisory_escalation.py +0 -0
  185. {plugin_scanner-2.0.140 → plugin_scanner-2.0.142}/src/codex_plugin_scanner/guard/runtime/advisory_matchers.py +0 -0
  186. {plugin_scanner-2.0.140 → plugin_scanner-2.0.142}/src/codex_plugin_scanner/guard/runtime/data_flow.py +0 -0
  187. {plugin_scanner-2.0.140 → plugin_scanner-2.0.142}/src/codex_plugin_scanner/guard/runtime/data_flow_rules.py +0 -0
  188. {plugin_scanner-2.0.140 → plugin_scanner-2.0.142}/src/codex_plugin_scanner/guard/runtime/data_flow_variables.py +0 -0
  189. {plugin_scanner-2.0.140 → plugin_scanner-2.0.142}/src/codex_plugin_scanner/guard/runtime/decisions.py +0 -0
  190. {plugin_scanner-2.0.140 → plugin_scanner-2.0.142}/src/codex_plugin_scanner/guard/runtime/detectors.py +0 -0
  191. {plugin_scanner-2.0.140 → plugin_scanner-2.0.142}/src/codex_plugin_scanner/guard/runtime/mcp_protection.py +0 -0
  192. {plugin_scanner-2.0.140 → plugin_scanner-2.0.142}/src/codex_plugin_scanner/guard/runtime/prompt_injection.py +0 -0
  193. {plugin_scanner-2.0.140 → plugin_scanner-2.0.142}/src/codex_plugin_scanner/guard/runtime/safe_decode.py +0 -0
  194. {plugin_scanner-2.0.140 → plugin_scanner-2.0.142}/src/codex_plugin_scanner/guard/runtime/sandbox.py +0 -0
  195. {plugin_scanner-2.0.140 → plugin_scanner-2.0.142}/src/codex_plugin_scanner/guard/runtime/secret_file_requests.py +0 -0
  196. {plugin_scanner-2.0.140 → plugin_scanner-2.0.142}/src/codex_plugin_scanner/guard/runtime/secret_sensitivity.py +0 -0
  197. {plugin_scanner-2.0.140 → plugin_scanner-2.0.142}/src/codex_plugin_scanner/guard/runtime/secret_sources.py +0 -0
  198. {plugin_scanner-2.0.140 → plugin_scanner-2.0.142}/src/codex_plugin_scanner/guard/runtime/shell_commands.py +0 -0
  199. {plugin_scanner-2.0.140 → plugin_scanner-2.0.142}/src/codex_plugin_scanner/guard/runtime/signals.py +0 -0
  200. {plugin_scanner-2.0.140 → plugin_scanner-2.0.142}/src/codex_plugin_scanner/guard/runtime/skill_protection.py +0 -0
  201. {plugin_scanner-2.0.140 → plugin_scanner-2.0.142}/src/codex_plugin_scanner/guard/runtime/supply_chain.py +0 -0
  202. {plugin_scanner-2.0.140 → plugin_scanner-2.0.142}/src/codex_plugin_scanner/guard/runtime/surface_server.py +0 -0
  203. {plugin_scanner-2.0.140 → plugin_scanner-2.0.142}/src/codex_plugin_scanner/guard/runtime/temp_files.py +0 -0
  204. {plugin_scanner-2.0.140 → plugin_scanner-2.0.142}/src/codex_plugin_scanner/guard/runtime/threat_intel.py +0 -0
  205. {plugin_scanner-2.0.140 → plugin_scanner-2.0.142}/src/codex_plugin_scanner/guard/schemas/__init__.py +0 -0
  206. {plugin_scanner-2.0.140 → plugin_scanner-2.0.142}/src/codex_plugin_scanner/guard/schemas/consumer_mode.py +0 -0
  207. {plugin_scanner-2.0.140 → plugin_scanner-2.0.142}/src/codex_plugin_scanner/guard/schemas/guard_event_v1.py +0 -0
  208. {plugin_scanner-2.0.140 → plugin_scanner-2.0.142}/src/codex_plugin_scanner/guard/schemas/surface_server.py +0 -0
  209. {plugin_scanner-2.0.140 → plugin_scanner-2.0.142}/src/codex_plugin_scanner/guard/shims.py +0 -0
  210. {plugin_scanner-2.0.140 → plugin_scanner-2.0.142}/src/codex_plugin_scanner/guard/store_approvals.py +0 -0
  211. {plugin_scanner-2.0.140 → plugin_scanner-2.0.142}/src/codex_plugin_scanner/guard/store_connect.py +0 -0
  212. {plugin_scanner-2.0.140 → plugin_scanner-2.0.142}/src/codex_plugin_scanner/guard/store_evidence.py +0 -0
  213. {plugin_scanner-2.0.140 → plugin_scanner-2.0.142}/src/codex_plugin_scanner/guard/store_threat_intel.py +0 -0
  214. {plugin_scanner-2.0.140 → plugin_scanner-2.0.142}/src/codex_plugin_scanner/guard/types.py +0 -0
  215. {plugin_scanner-2.0.140 → plugin_scanner-2.0.142}/src/codex_plugin_scanner/integrations/__init__.py +0 -0
  216. {plugin_scanner-2.0.140 → plugin_scanner-2.0.142}/src/codex_plugin_scanner/integrations/cisco_mcp_scanner.py +0 -0
  217. {plugin_scanner-2.0.140 → plugin_scanner-2.0.142}/src/codex_plugin_scanner/integrations/cisco_skill_scanner.py +0 -0
  218. {plugin_scanner-2.0.140 → plugin_scanner-2.0.142}/src/codex_plugin_scanner/lint_fixes.py +0 -0
  219. {plugin_scanner-2.0.140 → plugin_scanner-2.0.142}/src/codex_plugin_scanner/marketplace_support.py +0 -0
  220. {plugin_scanner-2.0.140 → plugin_scanner-2.0.142}/src/codex_plugin_scanner/models.py +0 -0
  221. {plugin_scanner-2.0.140 → plugin_scanner-2.0.142}/src/codex_plugin_scanner/path_support.py +0 -0
  222. {plugin_scanner-2.0.140 → plugin_scanner-2.0.142}/src/codex_plugin_scanner/policy.py +0 -0
  223. {plugin_scanner-2.0.140 → plugin_scanner-2.0.142}/src/codex_plugin_scanner/quality_artifact.py +0 -0
  224. {plugin_scanner-2.0.140 → plugin_scanner-2.0.142}/src/codex_plugin_scanner/repo_detect.py +0 -0
  225. {plugin_scanner-2.0.140 → plugin_scanner-2.0.142}/src/codex_plugin_scanner/reporting.py +0 -0
  226. {plugin_scanner-2.0.140 → plugin_scanner-2.0.142}/src/codex_plugin_scanner/rules/__init__.py +0 -0
  227. {plugin_scanner-2.0.140 → plugin_scanner-2.0.142}/src/codex_plugin_scanner/rules/registry.py +0 -0
  228. {plugin_scanner-2.0.140 → plugin_scanner-2.0.142}/src/codex_plugin_scanner/rules/specs.py +0 -0
  229. {plugin_scanner-2.0.140 → plugin_scanner-2.0.142}/src/codex_plugin_scanner/scanner.py +0 -0
  230. {plugin_scanner-2.0.140 → plugin_scanner-2.0.142}/src/codex_plugin_scanner/submission.py +0 -0
  231. {plugin_scanner-2.0.140 → plugin_scanner-2.0.142}/src/codex_plugin_scanner/suppressions.py +0 -0
  232. {plugin_scanner-2.0.140 → plugin_scanner-2.0.142}/src/codex_plugin_scanner/trust_domain_scoring.py +0 -0
  233. {plugin_scanner-2.0.140 → plugin_scanner-2.0.142}/src/codex_plugin_scanner/trust_helpers.py +0 -0
  234. {plugin_scanner-2.0.140 → plugin_scanner-2.0.142}/src/codex_plugin_scanner/trust_mcp_scoring.py +0 -0
  235. {plugin_scanner-2.0.140 → plugin_scanner-2.0.142}/src/codex_plugin_scanner/trust_models.py +0 -0
  236. {plugin_scanner-2.0.140 → plugin_scanner-2.0.142}/src/codex_plugin_scanner/trust_plugin_scoring.py +0 -0
  237. {plugin_scanner-2.0.140 → plugin_scanner-2.0.142}/src/codex_plugin_scanner/trust_scoring.py +0 -0
  238. {plugin_scanner-2.0.140 → plugin_scanner-2.0.142}/src/codex_plugin_scanner/trust_skill_scoring.py +0 -0
  239. {plugin_scanner-2.0.140 → plugin_scanner-2.0.142}/src/codex_plugin_scanner/trust_specs.py +0 -0
  240. {plugin_scanner-2.0.140 → plugin_scanner-2.0.142}/src/codex_plugin_scanner/verification.py +0 -0
  241. {plugin_scanner-2.0.140 → plugin_scanner-2.0.142}/tests/__init__.py +0 -0
  242. {plugin_scanner-2.0.140 → plugin_scanner-2.0.142}/tests/conftest.py +0 -0
  243. {plugin_scanner-2.0.140 → plugin_scanner-2.0.142}/tests/fixtures/__init__.py +0 -0
  244. {plugin_scanner-2.0.140 → plugin_scanner-2.0.142}/tests/fixtures/bad-plugin/.codex-plugin/plugin.json +0 -0
  245. {plugin_scanner-2.0.140 → plugin_scanner-2.0.142}/tests/fixtures/bad-plugin/.mcp.json +0 -0
  246. {plugin_scanner-2.0.140 → plugin_scanner-2.0.142}/tests/fixtures/bad-plugin/secrets.js +0 -0
  247. {plugin_scanner-2.0.140 → plugin_scanner-2.0.142}/tests/fixtures/claude-plugin-good/.claude-plugin/plugin.json +0 -0
  248. {plugin_scanner-2.0.140 → plugin_scanner-2.0.142}/tests/fixtures/claude-plugin-good/LICENSE +0 -0
  249. {plugin_scanner-2.0.140 → plugin_scanner-2.0.142}/tests/fixtures/claude-plugin-good/README.md +0 -0
  250. {plugin_scanner-2.0.140 → plugin_scanner-2.0.142}/tests/fixtures/claude-plugin-good/SECURITY.md +0 -0
  251. {plugin_scanner-2.0.140 → plugin_scanner-2.0.142}/tests/fixtures/claude-plugin-good/hooks/hooks.json +0 -0
  252. {plugin_scanner-2.0.140 → plugin_scanner-2.0.142}/tests/fixtures/claude-plugin-good/skills/example/SKILL.md +0 -0
  253. {plugin_scanner-2.0.140 → plugin_scanner-2.0.142}/tests/fixtures/code-quality-bad/evil.js +0 -0
  254. {plugin_scanner-2.0.140 → plugin_scanner-2.0.142}/tests/fixtures/code-quality-bad/inject.js +0 -0
  255. {plugin_scanner-2.0.140 → plugin_scanner-2.0.142}/tests/fixtures/gemini-extension-good/GEMINI.md +0 -0
  256. {plugin_scanner-2.0.140 → plugin_scanner-2.0.142}/tests/fixtures/gemini-extension-good/LICENSE +0 -0
  257. {plugin_scanner-2.0.140 → plugin_scanner-2.0.142}/tests/fixtures/gemini-extension-good/README.md +0 -0
  258. {plugin_scanner-2.0.140 → plugin_scanner-2.0.142}/tests/fixtures/gemini-extension-good/SECURITY.md +0 -0
  259. {plugin_scanner-2.0.140 → plugin_scanner-2.0.142}/tests/fixtures/gemini-extension-good/commands/hello.toml +0 -0
  260. {plugin_scanner-2.0.140 → plugin_scanner-2.0.142}/tests/fixtures/gemini-extension-good/gemini-extension.json +0 -0
  261. {plugin_scanner-2.0.140 → plugin_scanner-2.0.142}/tests/fixtures/good-plugin/.codex-plugin/plugin.json +0 -0
  262. {plugin_scanner-2.0.140 → plugin_scanner-2.0.142}/tests/fixtures/good-plugin/.codexignore +0 -0
  263. {plugin_scanner-2.0.140 → plugin_scanner-2.0.142}/tests/fixtures/good-plugin/LICENSE +0 -0
  264. {plugin_scanner-2.0.140 → plugin_scanner-2.0.142}/tests/fixtures/good-plugin/README.md +0 -0
  265. {plugin_scanner-2.0.140 → plugin_scanner-2.0.142}/tests/fixtures/good-plugin/SECURITY.md +0 -0
  266. {plugin_scanner-2.0.140 → plugin_scanner-2.0.142}/tests/fixtures/good-plugin/assets/icon.svg +0 -0
  267. {plugin_scanner-2.0.140 → plugin_scanner-2.0.142}/tests/fixtures/good-plugin/assets/logo.svg +0 -0
  268. {plugin_scanner-2.0.140 → plugin_scanner-2.0.142}/tests/fixtures/good-plugin/assets/screenshot.svg +0 -0
  269. {plugin_scanner-2.0.140 → plugin_scanner-2.0.142}/tests/fixtures/good-plugin/skills/example/SKILL.md +0 -0
  270. {plugin_scanner-2.0.140 → plugin_scanner-2.0.142}/tests/fixtures/guard-codex-malicious-mcp/.codex/config.toml +0 -0
  271. {plugin_scanner-2.0.140 → plugin_scanner-2.0.142}/tests/fixtures/guard-red-team/README.md +0 -0
  272. {plugin_scanner-2.0.140 → plugin_scanner-2.0.142}/tests/fixtures/guard-red-team/benign-docs-fake-token.py +0 -0
  273. {plugin_scanner-2.0.140 → plugin_scanner-2.0.142}/tests/fixtures/guard-red-team/benign-health-endpoint.py +0 -0
  274. {plugin_scanner-2.0.140 → plugin_scanner-2.0.142}/tests/fixtures/guard-red-team/benign-nvmrc-fake-creds.py +0 -0
  275. {plugin_scanner-2.0.140 → plugin_scanner-2.0.142}/tests/fixtures/guard-red-team/benign-source-search.py +0 -0
  276. {plugin_scanner-2.0.140 → plugin_scanner-2.0.142}/tests/fixtures/guard-red-team/canary-exfil-encoded.py +0 -0
  277. {plugin_scanner-2.0.140 → plugin_scanner-2.0.142}/tests/fixtures/guard-red-team/canary-exfil.py +0 -0
  278. {plugin_scanner-2.0.140 → plugin_scanner-2.0.142}/tests/fixtures/guard-red-team/expected-decisions.json +0 -0
  279. {plugin_scanner-2.0.140 → plugin_scanner-2.0.142}/tests/fixtures/guard-red-team/malicious-dockerfile.txt +0 -0
  280. {plugin_scanner-2.0.140 → plugin_scanner-2.0.142}/tests/fixtures/guard-red-team/malicious-encoded-shell-exfil.py +0 -0
  281. {plugin_scanner-2.0.140 → plugin_scanner-2.0.142}/tests/fixtures/guard-red-team/malicious-github-action.yml +0 -0
  282. {plugin_scanner-2.0.140 → plugin_scanner-2.0.142}/tests/fixtures/guard-red-team/malicious-mcp-delete.md +0 -0
  283. {plugin_scanner-2.0.140 → plugin_scanner-2.0.142}/tests/fixtures/guard-red-team/malicious-mcp-secret-read.md +0 -0
  284. {plugin_scanner-2.0.140 → plugin_scanner-2.0.142}/tests/fixtures/guard-red-team/malicious-mcp-skill-exfil.md +0 -0
  285. {plugin_scanner-2.0.140 → plugin_scanner-2.0.142}/tests/fixtures/guard-red-team/malicious-npm-postinstall.js +0 -0
  286. {plugin_scanner-2.0.140 → plugin_scanner-2.0.142}/tests/fixtures/guard-red-team/malicious-prompt-env-read.md +0 -0
  287. {plugin_scanner-2.0.140 → plugin_scanner-2.0.142}/tests/fixtures/guard-red-team/malicious-prompt-guard-bypass.md +0 -0
  288. {plugin_scanner-2.0.140 → plugin_scanner-2.0.142}/tests/fixtures/guard-red-team/malicious-prompt-npmrc-read.md +0 -0
  289. {plugin_scanner-2.0.140 → plugin_scanner-2.0.142}/tests/fixtures/guard-red-team/malicious-python-setup.py +0 -0
  290. {plugin_scanner-2.0.140 → plugin_scanner-2.0.142}/tests/fixtures/guard-red-team/smoke-evidence-template.json +0 -0
  291. {plugin_scanner-2.0.140 → plugin_scanner-2.0.142}/tests/fixtures/hermes-plugin-evil/config.yaml +0 -0
  292. {plugin_scanner-2.0.140 → plugin_scanner-2.0.142}/tests/fixtures/hermes-plugin-evil/mcp_servers.json +0 -0
  293. {plugin_scanner-2.0.140 → plugin_scanner-2.0.142}/tests/fixtures/hermes-plugin-evil/skills/security/malicious/SKILL.md +0 -0
  294. {plugin_scanner-2.0.140 → plugin_scanner-2.0.142}/tests/fixtures/hermes-plugin-evil/skills/stealth/sneaky/SKILL.md +0 -0
  295. {plugin_scanner-2.0.140 → plugin_scanner-2.0.142}/tests/fixtures/hermes-plugin-evil/skills/stealth/sneaky/references/api-setup.md +0 -0
  296. {plugin_scanner-2.0.140 → plugin_scanner-2.0.142}/tests/fixtures/hermes-plugin-evil/skills/stealth/sneaky/scripts/deploy.sh +0 -0
  297. {plugin_scanner-2.0.140 → plugin_scanner-2.0.142}/tests/fixtures/hermes-plugin-evil/skills/utils/benign/SKILL.md +0 -0
  298. {plugin_scanner-2.0.140 → plugin_scanner-2.0.142}/tests/fixtures/malformed-json/.codex-plugin/plugin.json +0 -0
  299. {plugin_scanner-2.0.140 → plugin_scanner-2.0.142}/tests/fixtures/malicious-skill-plugin/.codex-plugin/plugin.json +0 -0
  300. {plugin_scanner-2.0.140 → plugin_scanner-2.0.142}/tests/fixtures/malicious-skill-plugin/.codexignore +0 -0
  301. {plugin_scanner-2.0.140 → plugin_scanner-2.0.142}/tests/fixtures/malicious-skill-plugin/LICENSE +0 -0
  302. {plugin_scanner-2.0.140 → plugin_scanner-2.0.142}/tests/fixtures/malicious-skill-plugin/README.md +0 -0
  303. {plugin_scanner-2.0.140 → plugin_scanner-2.0.142}/tests/fixtures/malicious-skill-plugin/SECURITY.md +0 -0
  304. {plugin_scanner-2.0.140 → plugin_scanner-2.0.142}/tests/fixtures/malicious-skill-plugin/skills/leaky-skill/SKILL.md +0 -0
  305. {plugin_scanner-2.0.140 → plugin_scanner-2.0.142}/tests/fixtures/mcp-canary-server.py +0 -0
  306. {plugin_scanner-2.0.140 → plugin_scanner-2.0.142}/tests/fixtures/minimal-plugin/.codex-plugin/plugin.json +0 -0
  307. {plugin_scanner-2.0.140 → plugin_scanner-2.0.142}/tests/fixtures/missing-fields/.codex-plugin/plugin.json +0 -0
  308. {plugin_scanner-2.0.140 → plugin_scanner-2.0.142}/tests/fixtures/mit-license/LICENSE +0 -0
  309. {plugin_scanner-2.0.140 → plugin_scanner-2.0.142}/tests/fixtures/multi-ecosystem-repo/codex-plugin/.codex-plugin/plugin.json +0 -0
  310. {plugin_scanner-2.0.140 → plugin_scanner-2.0.142}/tests/fixtures/multi-ecosystem-repo/codex-plugin/LICENSE +0 -0
  311. {plugin_scanner-2.0.140 → plugin_scanner-2.0.142}/tests/fixtures/multi-ecosystem-repo/codex-plugin/README.md +0 -0
  312. {plugin_scanner-2.0.140 → plugin_scanner-2.0.142}/tests/fixtures/multi-ecosystem-repo/codex-plugin/SECURITY.md +0 -0
  313. {plugin_scanner-2.0.140 → plugin_scanner-2.0.142}/tests/fixtures/multi-ecosystem-repo/gemini-ext/README.md +0 -0
  314. {plugin_scanner-2.0.140 → plugin_scanner-2.0.142}/tests/fixtures/multi-ecosystem-repo/gemini-ext/gemini-extension.json +0 -0
  315. {plugin_scanner-2.0.140 → plugin_scanner-2.0.142}/tests/fixtures/multi-plugin-repo/.agents/plugins/marketplace.json +0 -0
  316. {plugin_scanner-2.0.140 → plugin_scanner-2.0.142}/tests/fixtures/multi-plugin-repo/plugins/alpha-plugin/.codex-plugin/plugin.json +0 -0
  317. {plugin_scanner-2.0.140 → plugin_scanner-2.0.142}/tests/fixtures/multi-plugin-repo/plugins/alpha-plugin/.codexignore +0 -0
  318. {plugin_scanner-2.0.140 → plugin_scanner-2.0.142}/tests/fixtures/multi-plugin-repo/plugins/alpha-plugin/LICENSE +0 -0
  319. {plugin_scanner-2.0.140 → plugin_scanner-2.0.142}/tests/fixtures/multi-plugin-repo/plugins/alpha-plugin/README.md +0 -0
  320. {plugin_scanner-2.0.140 → plugin_scanner-2.0.142}/tests/fixtures/multi-plugin-repo/plugins/alpha-plugin/SECURITY.md +0 -0
  321. {plugin_scanner-2.0.140 → plugin_scanner-2.0.142}/tests/fixtures/multi-plugin-repo/plugins/alpha-plugin/skills/example/SKILL.md +0 -0
  322. {plugin_scanner-2.0.140 → plugin_scanner-2.0.142}/tests/fixtures/multi-plugin-repo/plugins/beta-plugin/.codex-plugin/plugin.json +0 -0
  323. {plugin_scanner-2.0.140 → plugin_scanner-2.0.142}/tests/fixtures/multi-plugin-repo/plugins/beta-plugin/skills/example/SKILL.md +0 -0
  324. {plugin_scanner-2.0.140 → plugin_scanner-2.0.142}/tests/fixtures/no-version/.codex-plugin/plugin.json +0 -0
  325. {plugin_scanner-2.0.140 → plugin_scanner-2.0.142}/tests/fixtures/opencode-good/.opencode/commands/hello.md +0 -0
  326. {plugin_scanner-2.0.140 → plugin_scanner-2.0.142}/tests/fixtures/opencode-good/.opencode/plugins/example.ts +0 -0
  327. {plugin_scanner-2.0.140 → plugin_scanner-2.0.142}/tests/fixtures/opencode-good/LICENSE +0 -0
  328. {plugin_scanner-2.0.140 → plugin_scanner-2.0.142}/tests/fixtures/opencode-good/README.md +0 -0
  329. {plugin_scanner-2.0.140 → plugin_scanner-2.0.142}/tests/fixtures/opencode-good/SECURITY.md +0 -0
  330. {plugin_scanner-2.0.140 → plugin_scanner-2.0.142}/tests/fixtures/opencode-good/opencode.jsonc +0 -0
  331. {plugin_scanner-2.0.140 → plugin_scanner-2.0.142}/tests/fixtures/skills-missing-dir/.codex-plugin/plugin.json +0 -0
  332. {plugin_scanner-2.0.140 → plugin_scanner-2.0.142}/tests/fixtures/skills-no-frontmatter/.codex-plugin/plugin.json +0 -0
  333. {plugin_scanner-2.0.140 → plugin_scanner-2.0.142}/tests/fixtures/skills-no-frontmatter/skills/bad-skill/SKILL.md +0 -0
  334. {plugin_scanner-2.0.140 → plugin_scanner-2.0.142}/tests/fixtures/supply-chain/benign-npm-package.json +0 -0
  335. {plugin_scanner-2.0.140 → plugin_scanner-2.0.142}/tests/fixtures/supply-chain/benign-pnpm-package.json +0 -0
  336. {plugin_scanner-2.0.140 → plugin_scanner-2.0.142}/tests/fixtures/supply-chain/benign-pyproject.toml +0 -0
  337. {plugin_scanner-2.0.140 → plugin_scanner-2.0.142}/tests/fixtures/supply-chain/malicious-Dockerfile +0 -0
  338. {plugin_scanner-2.0.140 → plugin_scanner-2.0.142}/tests/fixtures/supply-chain/malicious-action.yml +0 -0
  339. {plugin_scanner-2.0.140 → plugin_scanner-2.0.142}/tests/fixtures/supply-chain/malicious-npm-package.json +0 -0
  340. {plugin_scanner-2.0.140 → plugin_scanner-2.0.142}/tests/fixtures/supply-chain/malicious-setup.py +0 -0
  341. {plugin_scanner-2.0.140 → plugin_scanner-2.0.142}/tests/fixtures/with-marketplace/.codex-plugin/plugin.json +0 -0
  342. {plugin_scanner-2.0.140 → plugin_scanner-2.0.142}/tests/fixtures/with-marketplace/marketplace-broken.json +0 -0
  343. {plugin_scanner-2.0.140 → plugin_scanner-2.0.142}/tests/fixtures/with-marketplace/marketplace.json +0 -0
  344. {plugin_scanner-2.0.140 → plugin_scanner-2.0.142}/tests/test-trust-scoring.py +0 -0
  345. {plugin_scanner-2.0.140 → plugin_scanner-2.0.142}/tests/test-trust-specs.py +0 -0
  346. {plugin_scanner-2.0.140 → plugin_scanner-2.0.142}/tests/test_action_runner.py +0 -0
  347. {plugin_scanner-2.0.140 → plugin_scanner-2.0.142}/tests/test_best_practices.py +0 -0
  348. {plugin_scanner-2.0.140 → plugin_scanner-2.0.142}/tests/test_cisco_install_surfaces.py +0 -0
  349. {plugin_scanner-2.0.140 → plugin_scanner-2.0.142}/tests/test_cli.py +0 -0
  350. {plugin_scanner-2.0.140 → plugin_scanner-2.0.142}/tests/test_code_quality.py +0 -0
  351. {plugin_scanner-2.0.140 → plugin_scanner-2.0.142}/tests/test_config.py +0 -0
  352. {plugin_scanner-2.0.140 → plugin_scanner-2.0.142}/tests/test_coverage_remaining.py +0 -0
  353. {plugin_scanner-2.0.140 → plugin_scanner-2.0.142}/tests/test_ecosystems.py +0 -0
  354. {plugin_scanner-2.0.140 → plugin_scanner-2.0.142}/tests/test_edge_cases.py +0 -0
  355. {plugin_scanner-2.0.140 → plugin_scanner-2.0.142}/tests/test_final_coverage.py +0 -0
  356. {plugin_scanner-2.0.140 → plugin_scanner-2.0.142}/tests/test_guard_access_graph.py +0 -0
  357. {plugin_scanner-2.0.140 → plugin_scanner-2.0.142}/tests/test_guard_action_identity.py +0 -0
  358. {plugin_scanner-2.0.140 → plugin_scanner-2.0.142}/tests/test_guard_advisory_escalation.py +0 -0
  359. {plugin_scanner-2.0.140 → plugin_scanner-2.0.142}/tests/test_guard_approval_continuity.py +0 -0
  360. {plugin_scanner-2.0.140 → plugin_scanner-2.0.142}/tests/test_guard_approval_copy_commands.py +0 -0
  361. {plugin_scanner-2.0.140 → plugin_scanner-2.0.142}/tests/test_guard_approval_store_dedup.py +0 -0
  362. {plugin_scanner-2.0.140 → plugin_scanner-2.0.142}/tests/test_guard_approval_store_scale.py +0 -0
  363. {plugin_scanner-2.0.140 → plugin_scanner-2.0.142}/tests/test_guard_approvals.py +0 -0
  364. {plugin_scanner-2.0.140 → plugin_scanner-2.0.142}/tests/test_guard_bootstrap.py +0 -0
  365. {plugin_scanner-2.0.140 → plugin_scanner-2.0.142}/tests/test_guard_canary_fixtures.py +0 -0
  366. {plugin_scanner-2.0.140 → plugin_scanner-2.0.142}/tests/test_guard_capabilities.py +0 -0
  367. {plugin_scanner-2.0.140 → plugin_scanner-2.0.142}/tests/test_guard_claude_adapter.py +0 -0
  368. {plugin_scanner-2.0.140 → plugin_scanner-2.0.142}/tests/test_guard_cli.py +0 -0
  369. {plugin_scanner-2.0.140 → plugin_scanner-2.0.142}/tests/test_guard_cloud_local_sync.py +0 -0
  370. {plugin_scanner-2.0.140 → plugin_scanner-2.0.142}/tests/test_guard_codex_e2e.py +0 -0
  371. {plugin_scanner-2.0.140 → plugin_scanner-2.0.142}/tests/test_guard_codex_install.py +0 -0
  372. {plugin_scanner-2.0.140 → plugin_scanner-2.0.142}/tests/test_guard_codex_proxy.py +0 -0
  373. {plugin_scanner-2.0.140 → plugin_scanner-2.0.142}/tests/test_guard_config_paths.py +0 -0
  374. {plugin_scanner-2.0.140 → plugin_scanner-2.0.142}/tests/test_guard_connect_flow.py +0 -0
  375. {plugin_scanner-2.0.140 → plugin_scanner-2.0.142}/tests/test_guard_consumer_mode.py +0 -0
  376. {plugin_scanner-2.0.140 → plugin_scanner-2.0.142}/tests/test_guard_copilot_adapter.py +0 -0
  377. {plugin_scanner-2.0.140 → plugin_scanner-2.0.142}/tests/test_guard_copilot_proxy.py +0 -0
  378. {plugin_scanner-2.0.140 → plugin_scanner-2.0.142}/tests/test_guard_daemon_repair_perf.py +0 -0
  379. {plugin_scanner-2.0.140 → plugin_scanner-2.0.142}/tests/test_guard_data_flow.py +0 -0
  380. {plugin_scanner-2.0.140 → plugin_scanner-2.0.142}/tests/test_guard_decision_propagation.py +0 -0
  381. {plugin_scanner-2.0.140 → plugin_scanner-2.0.142}/tests/test_guard_event_schema_v1.py +0 -0
  382. {plugin_scanner-2.0.140 → plugin_scanner-2.0.142}/tests/test_guard_events.py +0 -0
  383. {plugin_scanner-2.0.140 → plugin_scanner-2.0.142}/tests/test_guard_evidence_store.py +0 -0
  384. {plugin_scanner-2.0.140 → plugin_scanner-2.0.142}/tests/test_guard_harness_contracts.py +0 -0
  385. {plugin_scanner-2.0.140 → plugin_scanner-2.0.142}/tests/test_guard_launch_env.py +0 -0
  386. {plugin_scanner-2.0.140 → plugin_scanner-2.0.142}/tests/test_guard_mcp_protection.py +0 -0
  387. {plugin_scanner-2.0.140 → plugin_scanner-2.0.142}/tests/test_guard_opencode_proxy.py +0 -0
  388. {plugin_scanner-2.0.140 → plugin_scanner-2.0.142}/tests/test_guard_policy_dedup.py +0 -0
  389. {plugin_scanner-2.0.140 → plugin_scanner-2.0.142}/tests/test_guard_product_flow.py +0 -0
  390. {plugin_scanner-2.0.140 → plugin_scanner-2.0.142}/tests/test_guard_prompt_injection.py +0 -0
  391. {plugin_scanner-2.0.140 → plugin_scanner-2.0.142}/tests/test_guard_protect.py +0 -0
  392. {plugin_scanner-2.0.140 → plugin_scanner-2.0.142}/tests/test_guard_red_team.py +0 -0
  393. {plugin_scanner-2.0.140 → plugin_scanner-2.0.142}/tests/test_guard_render.py +0 -0
  394. {plugin_scanner-2.0.140 → plugin_scanner-2.0.142}/tests/test_guard_resolution_copy.py +0 -0
  395. {plugin_scanner-2.0.140 → plugin_scanner-2.0.142}/tests/test_guard_risk.py +0 -0
  396. {plugin_scanner-2.0.140 → plugin_scanner-2.0.142}/tests/test_guard_runtime.py +0 -0
  397. {plugin_scanner-2.0.140 → plugin_scanner-2.0.142}/tests/test_guard_runtime_action_harnesses.py +0 -0
  398. {plugin_scanner-2.0.140 → plugin_scanner-2.0.142}/tests/test_guard_runtime_actions.py +0 -0
  399. {plugin_scanner-2.0.140 → plugin_scanner-2.0.142}/tests/test_guard_runtime_decisions.py +0 -0
  400. {plugin_scanner-2.0.140 → plugin_scanner-2.0.142}/tests/test_guard_runtime_detectors.py +0 -0
  401. {plugin_scanner-2.0.140 → plugin_scanner-2.0.142}/tests/test_guard_runtime_signals.py +0 -0
  402. {plugin_scanner-2.0.140 → plugin_scanner-2.0.142}/tests/test_guard_safe_decode.py +0 -0
  403. {plugin_scanner-2.0.140 → plugin_scanner-2.0.142}/tests/test_guard_sandbox.py +0 -0
  404. {plugin_scanner-2.0.140 → plugin_scanner-2.0.142}/tests/test_guard_skill_protection.py +0 -0
  405. {plugin_scanner-2.0.140 → plugin_scanner-2.0.142}/tests/test_guard_store_migrations.py +0 -0
  406. {plugin_scanner-2.0.140 → plugin_scanner-2.0.142}/tests/test_guard_supply_chain.py +0 -0
  407. {plugin_scanner-2.0.140 → plugin_scanner-2.0.142}/tests/test_guard_surface_server.py +0 -0
  408. {plugin_scanner-2.0.140 → plugin_scanner-2.0.142}/tests/test_guard_threat_intel.py +0 -0
  409. {plugin_scanner-2.0.140 → plugin_scanner-2.0.142}/tests/test_guard_verdicts.py +0 -0
  410. {plugin_scanner-2.0.140 → plugin_scanner-2.0.142}/tests/test_guard_web_recovery.py +0 -0
  411. {plugin_scanner-2.0.140 → plugin_scanner-2.0.142}/tests/test_hermes_adapter.py +0 -0
  412. {plugin_scanner-2.0.140 → plugin_scanner-2.0.142}/tests/test_integration.py +0 -0
  413. {plugin_scanner-2.0.140 → plugin_scanner-2.0.142}/tests/test_lint_fixes.py +0 -0
  414. {plugin_scanner-2.0.140 → plugin_scanner-2.0.142}/tests/test_live_cisco_smoke.py +0 -0
  415. {plugin_scanner-2.0.140 → plugin_scanner-2.0.142}/tests/test_manifest.py +0 -0
  416. {plugin_scanner-2.0.140 → plugin_scanner-2.0.142}/tests/test_marketplace.py +0 -0
  417. {plugin_scanner-2.0.140 → plugin_scanner-2.0.142}/tests/test_mcp_security.py +0 -0
  418. {plugin_scanner-2.0.140 → plugin_scanner-2.0.142}/tests/test_openclaw_adapter.py +0 -0
  419. {plugin_scanner-2.0.140 → plugin_scanner-2.0.142}/tests/test_operational_security.py +0 -0
  420. {plugin_scanner-2.0.140 → plugin_scanner-2.0.142}/tests/test_policy.py +0 -0
  421. {plugin_scanner-2.0.140 → plugin_scanner-2.0.142}/tests/test_quality_artifact.py +0 -0
  422. {plugin_scanner-2.0.140 → plugin_scanner-2.0.142}/tests/test_rule_registry.py +0 -0
  423. {plugin_scanner-2.0.140 → plugin_scanner-2.0.142}/tests/test_scanner.py +0 -0
  424. {plugin_scanner-2.0.140 → plugin_scanner-2.0.142}/tests/test_schema_contracts.py +0 -0
  425. {plugin_scanner-2.0.140 → plugin_scanner-2.0.142}/tests/test_security.py +0 -0
  426. {plugin_scanner-2.0.140 → plugin_scanner-2.0.142}/tests/test_security_ops.py +0 -0
  427. {plugin_scanner-2.0.140 → plugin_scanner-2.0.142}/tests/test_skill_security.py +0 -0
  428. {plugin_scanner-2.0.140 → plugin_scanner-2.0.142}/tests/test_submission.py +0 -0
  429. {plugin_scanner-2.0.140 → plugin_scanner-2.0.142}/tests/test_trust_scoring.py +0 -0
  430. {plugin_scanner-2.0.140 → plugin_scanner-2.0.142}/tests/test_trust_specs.py +0 -0
  431. {plugin_scanner-2.0.140 → plugin_scanner-2.0.142}/tests/test_verification.py +0 -0
  432. {plugin_scanner-2.0.140 → plugin_scanner-2.0.142}/tests/test_versioning.py +0 -0
  433. {plugin_scanner-2.0.140 → plugin_scanner-2.0.142}/uv.lock +0 -0
@@ -1,6 +1,6 @@
1
1
  Metadata-Version: 2.4
2
2
  Name: plugin-scanner
3
- Version: 2.0.140
3
+ Version: 2.0.142
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
@@ -171,6 +171,7 @@ export type GuardRuntimeSnapshot = {
171
171
  headline_state: GuardHeadlineState;
172
172
  headline_label: string;
173
173
  headline_detail: string;
174
+ thread_count?: number;
174
175
  sync_configured: boolean;
175
176
  cloud_state: "local_only" | "paired_waiting" | "paired_active";
176
177
  cloud_state_label: string;
@@ -13,9 +13,9 @@ import {
13
13
  SectionLabel,
14
14
  Tag
15
15
  } from "./approval-center-primitives";
16
- import { clearEvidence, exportDiagnostics, fetchSettings, updateSettings, clearPolicy, repairApprovalCenter } from "./guard-api";
16
+ import { clearEvidence, exportDiagnostics, fetchRuntimeSnapshot, fetchSettings, updateSettings, clearPolicy, repairApprovalCenter } from "./guard-api";
17
17
  import { resolveProtectionLevelCopy } from "./runtime-overview";
18
- import type { GuardSettings, GuardSettingsPayload } from "./guard-types";
18
+ import type { GuardRuntimeSnapshot, GuardSettings, GuardSettingsPayload } from "./guard-types";
19
19
 
20
20
  type SettingsState =
21
21
  | { kind: "loading" }
@@ -165,6 +165,7 @@ export function SettingsWorkspace() {
165
165
  const [exporting, setExporting] = useState(false);
166
166
  const [repairing, setRepairing] = useState(false);
167
167
  const [actionMessage, setActionMessage] = useState<string | null>(null);
168
+ const [perfSnapshot, setPerfSnapshot] = useState<GuardRuntimeSnapshot | null>(null);
168
169
  const saveSuccessTimerRef = useRef<ReturnType<typeof setTimeout> | null>(null);
169
170
 
170
171
  useEffect(() => {
@@ -190,6 +191,20 @@ export function SettingsWorkspace() {
190
191
  };
191
192
  }, []);
192
193
 
194
+ useEffect(() => {
195
+ let cancelled = false;
196
+ fetchRuntimeSnapshot()
197
+ .then((snapshot) => {
198
+ if (!cancelled) setPerfSnapshot(snapshot);
199
+ })
200
+ .catch((error: unknown) => {
201
+ console.error("Failed to fetch runtime snapshot:", error);
202
+ });
203
+ return () => {
204
+ cancelled = true;
205
+ };
206
+ }, []);
207
+
193
208
  useEffect(() => {
194
209
  return () => {
195
210
  if (saveSuccessTimerRef.current !== null) {
@@ -610,6 +625,14 @@ export function SettingsWorkspace() {
610
625
  <SettingToggle label="Billing features" checked={draft.billing} onChange={handleBooleanChange("billing")} />
611
626
  </div>
612
627
  </div>
628
+ {perfSnapshot !== null ? (
629
+ <div className="rounded-[1.75rem] border border-slate-200/70 bg-white/80 p-5 shadow-sm">
630
+ <SectionLabel>Runtime diagnostics</SectionLabel>
631
+ <div className="mt-4">
632
+ <DiagnosticsPerfCard snapshot={perfSnapshot} />
633
+ </div>
634
+ </div>
635
+ ) : null}
613
636
  <div className="rounded-[1.75rem] border border-red-100 bg-red-50/50 p-5 shadow-sm">
614
637
  <SectionLabel>Data management</SectionLabel>
615
638
  <div className="mt-4 space-y-3">
@@ -682,6 +705,41 @@ export function SettingsWorkspace() {
682
705
  );
683
706
  }
684
707
 
708
+ function DiagnosticsPerfCard(props: { snapshot: GuardRuntimeSnapshot }) {
709
+ const { snapshot } = props;
710
+ const threadCount = snapshot.thread_count;
711
+ const daemonPort = snapshot.runtime_state?.daemon_port ?? null;
712
+ const startedAt = snapshot.runtime_state?.started_at ?? null;
713
+ return (
714
+ <div>
715
+ <h3 className="text-sm font-semibold text-brand-dark">Runtime performance</h3>
716
+ <p className="mt-1 text-xs leading-relaxed text-muted-foreground">
717
+ Live process metrics for this Guard daemon session.
718
+ </p>
719
+ <dl className="mt-3 grid grid-cols-2 gap-2">
720
+ {threadCount !== undefined ? (
721
+ <PerfMetric label="Total interpreter threads" value={String(threadCount)} />
722
+ ) : null}
723
+ {daemonPort !== null ? (
724
+ <PerfMetric label="Daemon port" value={String(daemonPort)} />
725
+ ) : null}
726
+ {startedAt !== null ? (
727
+ <PerfMetric label="Started" value={new Date(startedAt).toLocaleTimeString()} />
728
+ ) : null}
729
+ </dl>
730
+ </div>
731
+ );
732
+ }
733
+
734
+ function PerfMetric(props: { label: string; value: string }) {
735
+ return (
736
+ <div className="rounded-xl bg-surface-1 px-3 py-2">
737
+ <dt className="text-[10px] font-semibold uppercase tracking-[0.14em] text-muted-foreground">{props.label}</dt>
738
+ <dd className="mt-0.5 font-mono text-sm font-semibold text-brand-dark">{props.value}</dd>
739
+ </div>
740
+ );
741
+ }
742
+
685
743
  function SettingSelect(props: {
686
744
  label: string;
687
745
  value: string;
@@ -0,0 +1,37 @@
1
+ # HOL Guard Release Notes
2
+
3
+ Release notes document user-visible changes, false-positive improvements, and paid-feature additions.
4
+ Update this file for every release that touches a Guard integration path.
5
+
6
+ ---
7
+
8
+ ## Unreleased
9
+
10
+ ### False-positive improvements (T647)
11
+
12
+ - **Supply-chain artifact fallback** — `SupplyChainRiskCard` now matches `package_request`
13
+ and any `*_package` artifact type in addition to the original `supply_chain` value,
14
+ eliminating spurious "no risk signals" cards for npm/PyPI requests.
15
+ - **Encoded-layer count** — `DecodedLayerCard` now reads the true layer count from the
16
+ detector `plain_reason` field (e.g., "Decoded 3 encoding layer(s)") instead of counting
17
+ signal list length, so multi-layer exfil is accurately reported rather than shown as
18
+ "0 additional layers".
19
+ - **Detector registry cached across hook calls** — The default detector registry is now
20
+ lazily initialised once per process and reused, reducing per-hook construction overhead.
21
+
22
+ ### Cloud advisory paid sync (T648)
23
+
24
+ Advisory bundles are signed by the HOL advisory service and verified locally before use.
25
+ The free plan receives a graceful 403 fallback with a local-only warning; no advisory data
26
+ is sent to the server during sync. Run `hol-guard advisories sync` to pull the latest bundle.
27
+
28
+ ### Settings presets (T649)
29
+
30
+ Four one-click security presets — **Gentle**, **Balanced**, **Strict**, and **Paranoid** —
31
+ are available from the Settings page. Choosing a preset applies a curated `risk_actions`
32
+ profile. Custom overrides survive a preset switch unless explicitly cleared.
33
+
34
+ ### Dashboard scale (T650)
35
+
36
+ The approval center and evidence log now paginate at 50 items per page. Large workspaces
37
+ with thousands of receipts will no longer cause the dashboard to stall on load.
@@ -4,7 +4,7 @@ build-backend = "hatchling.build"
4
4
 
5
5
  [project]
6
6
  name = "plugin-scanner"
7
- version = "2.0.140"
7
+ version = "2.0.142"
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.140"
7
+ version = "2.0.142"
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"
@@ -2,6 +2,7 @@
2
2
 
3
3
  from __future__ import annotations
4
4
 
5
+ import threading
5
6
  import time
6
7
  import uuid
7
8
  from collections.abc import Mapping
@@ -215,6 +216,7 @@ def build_runtime_snapshot(
215
216
  "headline_state": headline_state,
216
217
  "headline_label": _runtime_headline_label(headline_state),
217
218
  "headline_detail": _runtime_headline_detail(headline_state),
219
+ "thread_count": threading.active_count(),
218
220
  "items": pending_requests,
219
221
  "latest_receipts": latest_receipts,
220
222
  "managed_installs": store.list_managed_installs(),
@@ -15562,6 +15562,7 @@ function SettingsWorkspace() {
15562
15562
  const [exporting, setExporting] = reactExports.useState(false);
15563
15563
  const [repairing, setRepairing] = reactExports.useState(false);
15564
15564
  const [actionMessage, setActionMessage] = reactExports.useState(null);
15565
+ const [perfSnapshot, setPerfSnapshot] = reactExports.useState(null);
15565
15566
  const saveSuccessTimerRef = reactExports.useRef(null);
15566
15567
  reactExports.useEffect(() => {
15567
15568
  let cancelled = false;
@@ -15583,6 +15584,17 @@ function SettingsWorkspace() {
15583
15584
  cancelled = true;
15584
15585
  };
15585
15586
  }, []);
15587
+ reactExports.useEffect(() => {
15588
+ let cancelled = false;
15589
+ fetchRuntimeSnapshot().then((snapshot) => {
15590
+ if (!cancelled) setPerfSnapshot(snapshot);
15591
+ }).catch((error) => {
15592
+ console.error("Failed to fetch runtime snapshot:", error);
15593
+ });
15594
+ return () => {
15595
+ cancelled = true;
15596
+ };
15597
+ }, []);
15586
15598
  reactExports.useEffect(() => {
15587
15599
  return () => {
15588
15600
  if (saveSuccessTimerRef.current !== null) {
@@ -15942,6 +15954,10 @@ function SettingsWorkspace() {
15942
15954
  /* @__PURE__ */ jsxRuntimeExports.jsx(SettingToggle, { label: "Billing features", checked: draft.billing, onChange: handleBooleanChange("billing") })
15943
15955
  ] })
15944
15956
  ] }),
15957
+ perfSnapshot !== null ? /* @__PURE__ */ jsxRuntimeExports.jsxs("div", { className: "rounded-[1.75rem] border border-slate-200/70 bg-white/80 p-5 shadow-sm", children: [
15958
+ /* @__PURE__ */ jsxRuntimeExports.jsx(SectionLabel, { children: "Runtime diagnostics" }),
15959
+ /* @__PURE__ */ jsxRuntimeExports.jsx("div", { className: "mt-4", children: /* @__PURE__ */ jsxRuntimeExports.jsx(DiagnosticsPerfCard, { snapshot: perfSnapshot }) })
15960
+ ] }) : null,
15945
15961
  /* @__PURE__ */ jsxRuntimeExports.jsxs("div", { className: "rounded-[1.75rem] border border-red-100 bg-red-50/50 p-5 shadow-sm", children: [
15946
15962
  /* @__PURE__ */ jsxRuntimeExports.jsx(SectionLabel, { children: "Data management" }),
15947
15963
  /* @__PURE__ */ jsxRuntimeExports.jsxs("div", { className: "mt-4 space-y-3", children: [
@@ -15976,6 +15992,27 @@ function SettingsWorkspace() {
15976
15992
  ] })
15977
15993
  ] });
15978
15994
  }
15995
+ function DiagnosticsPerfCard(props) {
15996
+ const { snapshot } = props;
15997
+ const threadCount = snapshot.thread_count;
15998
+ const daemonPort = snapshot.runtime_state?.daemon_port ?? null;
15999
+ const startedAt = snapshot.runtime_state?.started_at ?? null;
16000
+ return /* @__PURE__ */ jsxRuntimeExports.jsxs("div", { children: [
16001
+ /* @__PURE__ */ jsxRuntimeExports.jsx("h3", { className: "text-sm font-semibold text-brand-dark", children: "Runtime performance" }),
16002
+ /* @__PURE__ */ jsxRuntimeExports.jsx("p", { className: "mt-1 text-xs leading-relaxed text-muted-foreground", children: "Live process metrics for this Guard daemon session." }),
16003
+ /* @__PURE__ */ jsxRuntimeExports.jsxs("dl", { className: "mt-3 grid grid-cols-2 gap-2", children: [
16004
+ threadCount !== void 0 ? /* @__PURE__ */ jsxRuntimeExports.jsx(PerfMetric, { label: "Total interpreter threads", value: String(threadCount) }) : null,
16005
+ daemonPort !== null ? /* @__PURE__ */ jsxRuntimeExports.jsx(PerfMetric, { label: "Daemon port", value: String(daemonPort) }) : null,
16006
+ startedAt !== null ? /* @__PURE__ */ jsxRuntimeExports.jsx(PerfMetric, { label: "Started", value: new Date(startedAt).toLocaleTimeString() }) : null
16007
+ ] })
16008
+ ] });
16009
+ }
16010
+ function PerfMetric(props) {
16011
+ return /* @__PURE__ */ jsxRuntimeExports.jsxs("div", { className: "rounded-xl bg-surface-1 px-3 py-2", children: [
16012
+ /* @__PURE__ */ jsxRuntimeExports.jsx("dt", { className: "text-[10px] font-semibold uppercase tracking-[0.14em] text-muted-foreground", children: props.label }),
16013
+ /* @__PURE__ */ jsxRuntimeExports.jsx("dd", { className: "mt-0.5 font-mono text-sm font-semibold text-brand-dark", children: props.value })
16014
+ ] });
16015
+ }
15979
16016
  function SettingSelect(props) {
15980
16017
  return /* @__PURE__ */ jsxRuntimeExports.jsxs("label", { className: "block", children: [
15981
16018
  /* @__PURE__ */ jsxRuntimeExports.jsx("span", { className: "font-mono text-[11px] font-semibold uppercase tracking-[0.18em] text-muted-foreground", children: props.label }),
@@ -2164,6 +2164,11 @@
2164
2164
  letter-spacing: .2em;
2165
2165
  }
2166
2166
 
2167
+ .tracking-\[0\.14em\] {
2168
+ --tw-tracking: .14em;
2169
+ letter-spacing: .14em;
2170
+ }
2171
+
2167
2172
  .tracking-\[0\.18em\] {
2168
2173
  --tw-tracking: .18em;
2169
2174
  letter-spacing: .18em;
@@ -8,6 +8,7 @@ import os
8
8
  import re
9
9
  import socket
10
10
  import subprocess
11
+ import threading
11
12
  import urllib.error
12
13
  import urllib.parse
13
14
  import urllib.request
@@ -40,8 +41,22 @@ _APPROVAL_METADATA_KEYS = (
40
41
  )
41
42
 
42
43
 
44
+ _DEFAULT_DETECTOR_REGISTRY: tuple[Callable[[], tuple[Any, ...]], DetectorRegistry] | None = None
45
+ _DEFAULT_DETECTOR_REGISTRY_LOCK = threading.Lock()
46
+
47
+
43
48
  def _get_default_detector_registry() -> DetectorRegistry:
44
- return DetectorRegistry(register_default_detectors())
49
+ global _DEFAULT_DETECTOR_REGISTRY
50
+ factory = register_default_detectors
51
+ cached = _DEFAULT_DETECTOR_REGISTRY
52
+ if cached is not None and cached[0] is factory:
53
+ return cached[1]
54
+ with _DEFAULT_DETECTOR_REGISTRY_LOCK:
55
+ cached = _DEFAULT_DETECTOR_REGISTRY
56
+ if cached is None or cached[0] is not factory:
57
+ cached = (factory, DetectorRegistry(factory()))
58
+ _DEFAULT_DETECTOR_REGISTRY = cached
59
+ return cached[1]
45
60
 
46
61
 
47
62
  _PAIN_SIGNAL_EVENTS = frozenset(
@@ -4,9 +4,11 @@ from __future__ import annotations
4
4
 
5
5
  import base64
6
6
  import json
7
+ import logging
7
8
  import os
8
9
  import sqlite3
9
10
  import subprocess
11
+ import time
10
12
  from collections.abc import Iterator
11
13
  from contextlib import contextmanager
12
14
  from datetime import datetime, timedelta, timezone
@@ -353,6 +355,10 @@ def _build_secret_store(guard_home: Path) -> SecretStore:
353
355
  return fallback_store
354
356
 
355
357
 
358
+ _SLOW_QUERY_THRESHOLD_MS: int = 200
359
+ _store_logger = logging.getLogger(__name__)
360
+
361
+
356
362
  class GuardStore:
357
363
  """Local SQLite store for Guard state."""
358
364
 
@@ -403,11 +409,18 @@ class GuardStore:
403
409
  def _connect(self) -> Iterator[sqlite3.Connection]:
404
410
  connection = sqlite3.connect(self.path)
405
411
  connection.row_factory = sqlite3.Row
412
+ start = time.monotonic()
406
413
  try:
407
414
  yield connection
408
415
  connection.commit()
409
416
  finally:
410
417
  connection.close()
418
+ elapsed_ms = (time.monotonic() - start) * 1000
419
+ if elapsed_ms >= _SLOW_QUERY_THRESHOLD_MS:
420
+ _store_logger.warning(
421
+ "Guard store slow transaction (%.0fms); consider indexing hot query paths.",
422
+ elapsed_ms,
423
+ )
411
424
 
412
425
  def _initialize(self) -> None:
413
426
  statements = (
@@ -1,3 +1,3 @@
1
1
  """Single source of truth for tool version."""
2
2
 
3
- __version__ = "2.0.140"
3
+ __version__ = "2.0.142"
@@ -585,3 +585,77 @@ def test_guard_daemon_pid_matches_command_validates_guard_home_on_windows(tmp_pa
585
585
  12345,
586
586
  expected_guard_home=tmp_path / "other-home",
587
587
  )
588
+
589
+
590
+ def test_guard_daemon_start_lock_prevents_concurrent_starts(tmp_path):
591
+ guard_home = tmp_path / "guard-home"
592
+ guard_home.mkdir(parents=True)
593
+
594
+ events: list[str] = []
595
+ errors: list[Exception] = []
596
+ t1_entered = threading.Event()
597
+ release_holder = threading.Event()
598
+
599
+ def holder() -> None:
600
+ try:
601
+ with daemon_manager_module._guard_daemon_start_lock(guard_home):
602
+ events.append("t1-entered")
603
+ t1_entered.set()
604
+ release_holder.wait(timeout=5)
605
+ events.append("t1-exited")
606
+ except Exception as exc:
607
+ errors.append(exc)
608
+
609
+ def waiter() -> None:
610
+ try:
611
+ with daemon_manager_module._guard_daemon_start_lock(guard_home):
612
+ events.append("t2-entered")
613
+ except Exception as exc:
614
+ errors.append(exc)
615
+
616
+ t1 = threading.Thread(target=holder)
617
+ t1.start()
618
+ t1_entered.wait(timeout=5)
619
+ t2 = threading.Thread(target=waiter)
620
+ t2.start()
621
+ release_holder.set()
622
+ t1.join(timeout=10)
623
+ t2.join(timeout=10)
624
+
625
+ assert not errors, f"Lock worker raised: {errors}"
626
+ assert events.index("t1-exited") < events.index("t2-entered"), (
627
+ "Second thread entered before first released the lock"
628
+ )
629
+
630
+
631
+ def test_guard_daemon_start_lock_file_created_and_released(tmp_path):
632
+ guard_home = tmp_path / "guard-home"
633
+ guard_home.mkdir(parents=True)
634
+ lock_path = guard_home / "daemon-start.lock"
635
+
636
+ assert not lock_path.exists()
637
+
638
+ with daemon_manager_module._guard_daemon_start_lock(guard_home):
639
+ assert lock_path.exists()
640
+
641
+ assert lock_path.exists()
642
+
643
+
644
+ def test_guard_daemon_start_lock_recovers_after_exception(tmp_path):
645
+ guard_home = tmp_path / "guard-home"
646
+ guard_home.mkdir(parents=True)
647
+
648
+ raised = False
649
+ try:
650
+ with daemon_manager_module._guard_daemon_start_lock(guard_home):
651
+ raised = True
652
+ raise RuntimeError("simulated crash")
653
+ except RuntimeError:
654
+ pass
655
+
656
+ assert raised
657
+
658
+ acquired = False
659
+ with daemon_manager_module._guard_daemon_start_lock(guard_home):
660
+ acquired = True
661
+ assert acquired, "Lock was not released after exception; stale lock not recoverable"
@@ -2,6 +2,8 @@
2
2
 
3
3
  from __future__ import annotations
4
4
 
5
+ import threading
6
+ import time
5
7
  from pathlib import Path
6
8
 
7
9
  import pytest
@@ -176,3 +178,117 @@ class TestDoctorPerfPayload:
176
178
  for item in perf:
177
179
  expected_slow = int(item["elapsed_ms"]) >= _SLOW_DETECTOR_THRESHOLD_MS
178
180
  assert item["slow"] == expected_slow
181
+
182
+
183
+ class TestProcessCountBound:
184
+ """T620 — 100 safe hook evaluations must not spawn persistent threads."""
185
+
186
+ @pytest.mark.slow
187
+ def test_100_harness_start_evaluations_do_not_spawn_threads(self, tmp_path: Path) -> None:
188
+ action = _make_harness_start_action()
189
+ context = _make_detector_context(tmp_path)
190
+ registry = _get_default_detector_registry()
191
+ baseline_threads = threading.active_count()
192
+ for _ in range(100):
193
+ registry.run(action, context, timeout_ms=500)
194
+ after_threads = threading.active_count()
195
+ assert after_threads - baseline_threads <= 5, (
196
+ f"Thread count grew by {after_threads - baseline_threads} after 100 evaluations; "
197
+ "detectors must not leak persistent threads."
198
+ )
199
+
200
+ def test_100_harness_start_evaluations_complete_without_error(self, tmp_path: Path) -> None:
201
+ action = _make_harness_start_action()
202
+ context = _make_detector_context(tmp_path)
203
+ registry = _get_default_detector_registry()
204
+ results = [registry.run(action, context, timeout_ms=500) for _ in range(100)]
205
+ assert all(isinstance(r, DetectorRunResult) for r in results)
206
+
207
+
208
+ @pytest.mark.slow
209
+ class TestCPUBenchmark:
210
+ """T622 — 100 safe hook evaluations must complete in under 10 seconds."""
211
+
212
+ def test_100_safe_hook_calls_complete_within_budget(self, tmp_path: Path) -> None:
213
+ action = _make_harness_start_action()
214
+ context = _make_detector_context(tmp_path)
215
+ registry = _get_default_detector_registry()
216
+ start = time.monotonic()
217
+ for _ in range(100):
218
+ registry.run(action, context, timeout_ms=500)
219
+ elapsed_s = time.monotonic() - start
220
+ assert elapsed_s < 10.0, f"100 safe hook evaluations took {elapsed_s:.2f}s; budget is 10s."
221
+
222
+
223
+ class TestMemoryBenchmark:
224
+ """T621 — Guard module import stays under 50 MB RSS budget."""
225
+
226
+ def test_guard_config_import_does_not_import_heavy_deps(self) -> None:
227
+ import subprocess
228
+ import sys
229
+
230
+ result = subprocess.run(
231
+ [
232
+ sys.executable,
233
+ "-c",
234
+ (
235
+ "import codex_plugin_scanner.guard.config as _c;"
236
+ " import sys;"
237
+ " heavy = {'matplotlib', 'numpy', 'pandas', 'scipy', 'torch', 'tensorflow'};"
238
+ " leaked = heavy & set(sys.modules);"
239
+ " print(repr(leaked))"
240
+ ),
241
+ ],
242
+ capture_output=True,
243
+ text=True,
244
+ timeout=30,
245
+ )
246
+ assert result.returncode == 0, f"Subprocess failed: {result.stderr}"
247
+ import ast
248
+ leaked = ast.literal_eval(result.stdout.strip())
249
+ assert not leaked, f"Guard import leaked heavy dependencies: {leaked}"
250
+
251
+
252
+ class TestSlowSQLiteTelemetry:
253
+ """T624 — Slow store transactions emit a warning via the logging module."""
254
+
255
+ def test_slow_query_threshold_is_200ms(self) -> None:
256
+ from codex_plugin_scanner.guard.store import _SLOW_QUERY_THRESHOLD_MS
257
+
258
+ assert _SLOW_QUERY_THRESHOLD_MS == 200
259
+
260
+ def test_fast_transaction_does_not_warn(
261
+ self, tmp_path: Path, caplog: pytest.LogCaptureFixture, monkeypatch: pytest.MonkeyPatch
262
+ ) -> None:
263
+ import logging
264
+
265
+ import codex_plugin_scanner.guard.store as store_module
266
+ from codex_plugin_scanner.guard.store import GuardStore
267
+
268
+ monkeypatch.setattr(store_module, "_SLOW_QUERY_THRESHOLD_MS", 10_000)
269
+ store = GuardStore(guard_home=tmp_path / "guard-home")
270
+ with caplog.at_level(logging.WARNING, logger="codex_plugin_scanner.guard.store"):
271
+ _ = store.list_approval_requests()
272
+ slow_warnings = [r for r in caplog.records if "slow transaction" in r.getMessage().lower()]
273
+ assert len(slow_warnings) == 0, "Fast transaction must not emit slow transaction warning"
274
+
275
+ def test_slow_transaction_emits_warning(
276
+ self, tmp_path: Path, caplog: pytest.LogCaptureFixture, monkeypatch: pytest.MonkeyPatch
277
+ ) -> None:
278
+ import logging
279
+
280
+ import codex_plugin_scanner.guard.store as store_module
281
+ from codex_plugin_scanner.guard.store import GuardStore
282
+
283
+ monkeypatch.setattr(store_module, "_SLOW_QUERY_THRESHOLD_MS", 0)
284
+ store = GuardStore(guard_home=tmp_path / "guard-home")
285
+ with caplog.at_level(logging.WARNING, logger="codex_plugin_scanner.guard.store"):
286
+ _ = store.list_approval_requests()
287
+ slow_warnings = [r for r in caplog.records if "slow transaction" in r.getMessage().lower()]
288
+ assert len(slow_warnings) > 0, "Slow transaction (threshold=0ms) must emit a slow transaction warning"
289
+
290
+ def test_store_has_slow_query_threshold_constant(self) -> None:
291
+ from codex_plugin_scanner.guard.store import _SLOW_QUERY_THRESHOLD_MS
292
+
293
+ assert isinstance(_SLOW_QUERY_THRESHOLD_MS, int)
294
+ assert _SLOW_QUERY_THRESHOLD_MS > 0