plugin-scanner 2.0.167__tar.gz → 2.0.169__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 (464) hide show
  1. {plugin_scanner-2.0.167 → plugin_scanner-2.0.169}/PKG-INFO +1 -1
  2. {plugin_scanner-2.0.167 → plugin_scanner-2.0.169}/dashboard/src/approval-center-layout.test.ts +17 -0
  3. {plugin_scanner-2.0.167 → plugin_scanner-2.0.169}/dashboard/src/approval-center-layout.tsx +40 -8
  4. {plugin_scanner-2.0.167 → plugin_scanner-2.0.169}/dashboard/src/approval-center-primitives.tsx +18 -14
  5. {plugin_scanner-2.0.167 → plugin_scanner-2.0.169}/dashboard/src/approval-center-utils.ts +4 -4
  6. {plugin_scanner-2.0.167 → plugin_scanner-2.0.169}/dashboard/src/home-dashboard.tsx +72 -13
  7. {plugin_scanner-2.0.167 → plugin_scanner-2.0.169}/dashboard/src/queue-state.ts +24 -0
  8. {plugin_scanner-2.0.167 → plugin_scanner-2.0.169}/dashboard/src/runtime-overview.tsx +4 -2
  9. {plugin_scanner-2.0.167 → plugin_scanner-2.0.169}/pyproject.toml +1 -1
  10. {plugin_scanner-2.0.167 → plugin_scanner-2.0.169}/pyproject.toml.bak +1 -1
  11. {plugin_scanner-2.0.167 → plugin_scanner-2.0.169}/src/codex_plugin_scanner/guard/approvals.py +24 -4
  12. {plugin_scanner-2.0.167 → plugin_scanner-2.0.169}/src/codex_plugin_scanner/guard/cli/commands.py +7 -0
  13. {plugin_scanner-2.0.167 → plugin_scanner-2.0.169}/src/codex_plugin_scanner/guard/daemon/static/assets/guard-dashboard.js +110 -29
  14. {plugin_scanner-2.0.167 → plugin_scanner-2.0.169}/src/codex_plugin_scanner/guard/store.py +32 -7
  15. {plugin_scanner-2.0.167 → plugin_scanner-2.0.169}/src/codex_plugin_scanner/version.py +1 -1
  16. {plugin_scanner-2.0.167 → plugin_scanner-2.0.169}/tests/test_guard_runtime.py +171 -1
  17. {plugin_scanner-2.0.167 → plugin_scanner-2.0.169}/.clusterfuzzlite/Dockerfile +0 -0
  18. {plugin_scanner-2.0.167 → plugin_scanner-2.0.169}/.clusterfuzzlite/build.sh +0 -0
  19. {plugin_scanner-2.0.167 → plugin_scanner-2.0.169}/.clusterfuzzlite/project.yaml +0 -0
  20. {plugin_scanner-2.0.167 → plugin_scanner-2.0.169}/.clusterfuzzlite/requirements-atheris.txt +0 -0
  21. {plugin_scanner-2.0.167 → plugin_scanner-2.0.169}/.dockerignore +0 -0
  22. {plugin_scanner-2.0.167 → plugin_scanner-2.0.169}/.github/CODEOWNERS +0 -0
  23. {plugin_scanner-2.0.167 → plugin_scanner-2.0.169}/.github/ISSUE_TEMPLATE/bug-report.yml +0 -0
  24. {plugin_scanner-2.0.167 → plugin_scanner-2.0.169}/.github/ISSUE_TEMPLATE/config.yml +0 -0
  25. {plugin_scanner-2.0.167 → plugin_scanner-2.0.169}/.github/ISSUE_TEMPLATE/feature-request.yml +0 -0
  26. {plugin_scanner-2.0.167 → plugin_scanner-2.0.169}/.github/dependabot.yml +0 -0
  27. {plugin_scanner-2.0.167 → plugin_scanner-2.0.169}/.github/workflows/ci.yml +0 -0
  28. {plugin_scanner-2.0.167 → plugin_scanner-2.0.169}/.github/workflows/codeql.yml +0 -0
  29. {plugin_scanner-2.0.167 → plugin_scanner-2.0.169}/.github/workflows/dependabot-uv-lock.yml +0 -0
  30. {plugin_scanner-2.0.167 → plugin_scanner-2.0.169}/.github/workflows/fuzz.yml +0 -0
  31. {plugin_scanner-2.0.167 → plugin_scanner-2.0.169}/.github/workflows/harness-smoke.yml +0 -0
  32. {plugin_scanner-2.0.167 → plugin_scanner-2.0.169}/.github/workflows/publish.yml +0 -0
  33. {plugin_scanner-2.0.167 → plugin_scanner-2.0.169}/.github/workflows/scorecard.yml +0 -0
  34. {plugin_scanner-2.0.167 → plugin_scanner-2.0.169}/.gitignore +0 -0
  35. {plugin_scanner-2.0.167 → plugin_scanner-2.0.169}/.pre-commit-hooks.yaml +0 -0
  36. {plugin_scanner-2.0.167 → plugin_scanner-2.0.169}/CONTRIBUTING.md +0 -0
  37. {plugin_scanner-2.0.167 → plugin_scanner-2.0.169}/Dockerfile +0 -0
  38. {plugin_scanner-2.0.167 → plugin_scanner-2.0.169}/LICENSE +0 -0
  39. {plugin_scanner-2.0.167 → plugin_scanner-2.0.169}/README.md +0 -0
  40. {plugin_scanner-2.0.167 → plugin_scanner-2.0.169}/SECURITY.md +0 -0
  41. {plugin_scanner-2.0.167 → plugin_scanner-2.0.169}/dashboard/index.html +0 -0
  42. {plugin_scanner-2.0.167 → plugin_scanner-2.0.169}/dashboard/package.json +0 -0
  43. {plugin_scanner-2.0.167 → plugin_scanner-2.0.169}/dashboard/pnpm-lock.yaml +0 -0
  44. {plugin_scanner-2.0.167 → plugin_scanner-2.0.169}/dashboard/public/apple-touch-icon.png +0 -0
  45. {plugin_scanner-2.0.167 → plugin_scanner-2.0.169}/dashboard/public/brand/Logo_Icon_Dark.png +0 -0
  46. {plugin_scanner-2.0.167 → plugin_scanner-2.0.169}/dashboard/public/brand/Logo_Whole.png +0 -0
  47. {plugin_scanner-2.0.167 → plugin_scanner-2.0.169}/dashboard/public/favicon-16x16.png +0 -0
  48. {plugin_scanner-2.0.167 → plugin_scanner-2.0.169}/dashboard/public/favicon-32x32.png +0 -0
  49. {plugin_scanner-2.0.167 → plugin_scanner-2.0.169}/dashboard/public/favicon.ico +0 -0
  50. {plugin_scanner-2.0.167 → plugin_scanner-2.0.169}/dashboard/src/app.tsx +0 -0
  51. {plugin_scanner-2.0.167 → plugin_scanner-2.0.169}/dashboard/src/approval-center-mobile.test.ts +0 -0
  52. {plugin_scanner-2.0.167 → plugin_scanner-2.0.169}/dashboard/src/approval-center-review-cards.tsx +0 -0
  53. {plugin_scanner-2.0.167 → plugin_scanner-2.0.169}/dashboard/src/data-flow-evidence-card.tsx +0 -0
  54. {plugin_scanner-2.0.167 → plugin_scanner-2.0.169}/dashboard/src/fleet-workspace.tsx +0 -0
  55. {plugin_scanner-2.0.167 → plugin_scanner-2.0.169}/dashboard/src/guard-api.test.ts +0 -0
  56. {plugin_scanner-2.0.167 → plugin_scanner-2.0.169}/dashboard/src/guard-api.ts +0 -0
  57. {plugin_scanner-2.0.167 → plugin_scanner-2.0.169}/dashboard/src/guard-demo.ts +0 -0
  58. {plugin_scanner-2.0.167 → plugin_scanner-2.0.169}/dashboard/src/guard-types.ts +0 -0
  59. {plugin_scanner-2.0.167 → plugin_scanner-2.0.169}/dashboard/src/home-dashboard.test.ts +0 -0
  60. {plugin_scanner-2.0.167 → plugin_scanner-2.0.169}/dashboard/src/main.tsx +0 -0
  61. {plugin_scanner-2.0.167 → plugin_scanner-2.0.169}/dashboard/src/queue-chip-filter.tsx +0 -0
  62. {plugin_scanner-2.0.167 → plugin_scanner-2.0.169}/dashboard/src/queue-state.test.ts +0 -0
  63. {plugin_scanner-2.0.167 → plugin_scanner-2.0.169}/dashboard/src/receipts-workspace.test.ts +0 -0
  64. {plugin_scanner-2.0.167 → plugin_scanner-2.0.169}/dashboard/src/receipts-workspace.tsx +0 -0
  65. {plugin_scanner-2.0.167 → plugin_scanner-2.0.169}/dashboard/src/risk-signal-cards.test.ts +0 -0
  66. {plugin_scanner-2.0.167 → plugin_scanner-2.0.169}/dashboard/src/risk-signal-cards.tsx +0 -0
  67. {plugin_scanner-2.0.167 → plugin_scanner-2.0.169}/dashboard/src/runtime-overview.test.ts +0 -0
  68. {plugin_scanner-2.0.167 → plugin_scanner-2.0.169}/dashboard/src/scanner-evidence-badge.tsx +0 -0
  69. {plugin_scanner-2.0.167 → plugin_scanner-2.0.169}/dashboard/src/settings-workspace.test.ts +0 -0
  70. {plugin_scanner-2.0.167 → plugin_scanner-2.0.169}/dashboard/src/settings-workspace.tsx +0 -0
  71. {plugin_scanner-2.0.167 → plugin_scanner-2.0.169}/dashboard/src/styles.css +0 -0
  72. {plugin_scanner-2.0.167 → plugin_scanner-2.0.169}/dashboard/src/vite-env.d.ts +0 -0
  73. {plugin_scanner-2.0.167 → plugin_scanner-2.0.169}/dashboard/src/watched-app-card.tsx +0 -0
  74. {plugin_scanner-2.0.167 → plugin_scanner-2.0.169}/dashboard/tsconfig.json +0 -0
  75. {plugin_scanner-2.0.167 → plugin_scanner-2.0.169}/dashboard/vite.config.ts +0 -0
  76. {plugin_scanner-2.0.167 → plugin_scanner-2.0.169}/docker-requirements.txt +0 -0
  77. {plugin_scanner-2.0.167 → plugin_scanner-2.0.169}/docs/guard/approval-audit.md +0 -0
  78. {plugin_scanner-2.0.167 → plugin_scanner-2.0.169}/docs/guard/architecture.md +0 -0
  79. {plugin_scanner-2.0.167 → plugin_scanner-2.0.169}/docs/guard/get-started.md +0 -0
  80. {plugin_scanner-2.0.167 → plugin_scanner-2.0.169}/docs/guard/harness-support.md +0 -0
  81. {plugin_scanner-2.0.167 → plugin_scanner-2.0.169}/docs/guard/local-vs-cloud.md +0 -0
  82. {plugin_scanner-2.0.167 → plugin_scanner-2.0.169}/docs/guard/release-checklist.md +0 -0
  83. {plugin_scanner-2.0.167 → plugin_scanner-2.0.169}/docs/guard/release-notes.md +0 -0
  84. {plugin_scanner-2.0.167 → plugin_scanner-2.0.169}/docs/guard/smoke-tests.md +0 -0
  85. {plugin_scanner-2.0.167 → plugin_scanner-2.0.169}/docs/guard/testing-matrix.md +0 -0
  86. {plugin_scanner-2.0.167 → plugin_scanner-2.0.169}/docs/trust/mcp-trust-draft.md +0 -0
  87. {plugin_scanner-2.0.167 → plugin_scanner-2.0.169}/docs/trust/plugin-trust-draft.md +0 -0
  88. {plugin_scanner-2.0.167 → plugin_scanner-2.0.169}/docs/trust/skill-trust-local.md +0 -0
  89. {plugin_scanner-2.0.167 → plugin_scanner-2.0.169}/fuzzers/manifest_fuzzer.py +0 -0
  90. {plugin_scanner-2.0.167 → plugin_scanner-2.0.169}/requirements.txt +0 -0
  91. {plugin_scanner-2.0.167 → plugin_scanner-2.0.169}/schemas/plugin-quality.v1.json +0 -0
  92. {plugin_scanner-2.0.167 → plugin_scanner-2.0.169}/schemas/scan-result.v1.json +0 -0
  93. {plugin_scanner-2.0.167 → plugin_scanner-2.0.169}/schemas/verify-result.v1.json +0 -0
  94. {plugin_scanner-2.0.167 → plugin_scanner-2.0.169}/src/codex_plugin_scanner/__init__.py +0 -0
  95. {plugin_scanner-2.0.167 → plugin_scanner-2.0.169}/src/codex_plugin_scanner/action_runner.py +0 -0
  96. {plugin_scanner-2.0.167 → plugin_scanner-2.0.169}/src/codex_plugin_scanner/argparse_utils.py +0 -0
  97. {plugin_scanner-2.0.167 → plugin_scanner-2.0.169}/src/codex_plugin_scanner/checks/__init__.py +0 -0
  98. {plugin_scanner-2.0.167 → plugin_scanner-2.0.169}/src/codex_plugin_scanner/checks/best_practices.py +0 -0
  99. {plugin_scanner-2.0.167 → plugin_scanner-2.0.169}/src/codex_plugin_scanner/checks/claude.py +0 -0
  100. {plugin_scanner-2.0.167 → plugin_scanner-2.0.169}/src/codex_plugin_scanner/checks/code_quality.py +0 -0
  101. {plugin_scanner-2.0.167 → plugin_scanner-2.0.169}/src/codex_plugin_scanner/checks/ecosystem_common.py +0 -0
  102. {plugin_scanner-2.0.167 → plugin_scanner-2.0.169}/src/codex_plugin_scanner/checks/gemini.py +0 -0
  103. {plugin_scanner-2.0.167 → plugin_scanner-2.0.169}/src/codex_plugin_scanner/checks/manifest.py +0 -0
  104. {plugin_scanner-2.0.167 → plugin_scanner-2.0.169}/src/codex_plugin_scanner/checks/manifest_support.py +0 -0
  105. {plugin_scanner-2.0.167 → plugin_scanner-2.0.169}/src/codex_plugin_scanner/checks/marketplace.py +0 -0
  106. {plugin_scanner-2.0.167 → plugin_scanner-2.0.169}/src/codex_plugin_scanner/checks/mcp_security.py +0 -0
  107. {plugin_scanner-2.0.167 → plugin_scanner-2.0.169}/src/codex_plugin_scanner/checks/opencode.py +0 -0
  108. {plugin_scanner-2.0.167 → plugin_scanner-2.0.169}/src/codex_plugin_scanner/checks/operational_security.py +0 -0
  109. {plugin_scanner-2.0.167 → plugin_scanner-2.0.169}/src/codex_plugin_scanner/checks/security.py +0 -0
  110. {plugin_scanner-2.0.167 → plugin_scanner-2.0.169}/src/codex_plugin_scanner/checks/skill_security.py +0 -0
  111. {plugin_scanner-2.0.167 → plugin_scanner-2.0.169}/src/codex_plugin_scanner/cli.py +0 -0
  112. {plugin_scanner-2.0.167 → plugin_scanner-2.0.169}/src/codex_plugin_scanner/cli_ui.py +0 -0
  113. {plugin_scanner-2.0.167 → plugin_scanner-2.0.169}/src/codex_plugin_scanner/config.py +0 -0
  114. {plugin_scanner-2.0.167 → plugin_scanner-2.0.169}/src/codex_plugin_scanner/ecosystems/__init__.py +0 -0
  115. {plugin_scanner-2.0.167 → plugin_scanner-2.0.169}/src/codex_plugin_scanner/ecosystems/base.py +0 -0
  116. {plugin_scanner-2.0.167 → plugin_scanner-2.0.169}/src/codex_plugin_scanner/ecosystems/claude.py +0 -0
  117. {plugin_scanner-2.0.167 → plugin_scanner-2.0.169}/src/codex_plugin_scanner/ecosystems/codex.py +0 -0
  118. {plugin_scanner-2.0.167 → plugin_scanner-2.0.169}/src/codex_plugin_scanner/ecosystems/detect.py +0 -0
  119. {plugin_scanner-2.0.167 → plugin_scanner-2.0.169}/src/codex_plugin_scanner/ecosystems/gemini.py +0 -0
  120. {plugin_scanner-2.0.167 → plugin_scanner-2.0.169}/src/codex_plugin_scanner/ecosystems/opencode.py +0 -0
  121. {plugin_scanner-2.0.167 → plugin_scanner-2.0.169}/src/codex_plugin_scanner/ecosystems/registry.py +0 -0
  122. {plugin_scanner-2.0.167 → plugin_scanner-2.0.169}/src/codex_plugin_scanner/ecosystems/types.py +0 -0
  123. {plugin_scanner-2.0.167 → plugin_scanner-2.0.169}/src/codex_plugin_scanner/github_reporting.py +0 -0
  124. {plugin_scanner-2.0.167 → plugin_scanner-2.0.169}/src/codex_plugin_scanner/guard/__init__.py +0 -0
  125. {plugin_scanner-2.0.167 → plugin_scanner-2.0.169}/src/codex_plugin_scanner/guard/access_graph_events.py +0 -0
  126. {plugin_scanner-2.0.167 → plugin_scanner-2.0.169}/src/codex_plugin_scanner/guard/adapters/__init__.py +0 -0
  127. {plugin_scanner-2.0.167 → plugin_scanner-2.0.169}/src/codex_plugin_scanner/guard/adapters/antigravity.py +0 -0
  128. {plugin_scanner-2.0.167 → plugin_scanner-2.0.169}/src/codex_plugin_scanner/guard/adapters/base.py +0 -0
  129. {plugin_scanner-2.0.167 → plugin_scanner-2.0.169}/src/codex_plugin_scanner/guard/adapters/claude_code.py +0 -0
  130. {plugin_scanner-2.0.167 → plugin_scanner-2.0.169}/src/codex_plugin_scanner/guard/adapters/cloud_identity.py +0 -0
  131. {plugin_scanner-2.0.167 → plugin_scanner-2.0.169}/src/codex_plugin_scanner/guard/adapters/codex.py +0 -0
  132. {plugin_scanner-2.0.167 → plugin_scanner-2.0.169}/src/codex_plugin_scanner/guard/adapters/contracts.py +0 -0
  133. {plugin_scanner-2.0.167 → plugin_scanner-2.0.169}/src/codex_plugin_scanner/guard/adapters/copilot.py +0 -0
  134. {plugin_scanner-2.0.167 → plugin_scanner-2.0.169}/src/codex_plugin_scanner/guard/adapters/cursor.py +0 -0
  135. {plugin_scanner-2.0.167 → plugin_scanner-2.0.169}/src/codex_plugin_scanner/guard/adapters/gemini.py +0 -0
  136. {plugin_scanner-2.0.167 → plugin_scanner-2.0.169}/src/codex_plugin_scanner/guard/adapters/hermes.py +0 -0
  137. {plugin_scanner-2.0.167 → plugin_scanner-2.0.169}/src/codex_plugin_scanner/guard/adapters/mcp_servers.py +0 -0
  138. {plugin_scanner-2.0.167 → plugin_scanner-2.0.169}/src/codex_plugin_scanner/guard/adapters/openclaw.py +0 -0
  139. {plugin_scanner-2.0.167 → plugin_scanner-2.0.169}/src/codex_plugin_scanner/guard/adapters/openclaw_config.py +0 -0
  140. {plugin_scanner-2.0.167 → plugin_scanner-2.0.169}/src/codex_plugin_scanner/guard/adapters/openclaw_support.py +0 -0
  141. {plugin_scanner-2.0.167 → plugin_scanner-2.0.169}/src/codex_plugin_scanner/guard/adapters/opencode.py +0 -0
  142. {plugin_scanner-2.0.167 → plugin_scanner-2.0.169}/src/codex_plugin_scanner/guard/adapters/opencode_artifacts.py +0 -0
  143. {plugin_scanner-2.0.167 → plugin_scanner-2.0.169}/src/codex_plugin_scanner/guard/advisory_model.py +0 -0
  144. {plugin_scanner-2.0.167 → plugin_scanner-2.0.169}/src/codex_plugin_scanner/guard/bridge/__init__.py +0 -0
  145. {plugin_scanner-2.0.167 → plugin_scanner-2.0.169}/src/codex_plugin_scanner/guard/capabilities.py +0 -0
  146. {plugin_scanner-2.0.167 → plugin_scanner-2.0.169}/src/codex_plugin_scanner/guard/cli/__init__.py +0 -0
  147. {plugin_scanner-2.0.167 → plugin_scanner-2.0.169}/src/codex_plugin_scanner/guard/cli/approval_commands.py +0 -0
  148. {plugin_scanner-2.0.167 → plugin_scanner-2.0.169}/src/codex_plugin_scanner/guard/cli/bootstrap.py +0 -0
  149. {plugin_scanner-2.0.167 → plugin_scanner-2.0.169}/src/codex_plugin_scanner/guard/cli/connect_flow.py +0 -0
  150. {plugin_scanner-2.0.167 → plugin_scanner-2.0.169}/src/codex_plugin_scanner/guard/cli/install_commands.py +0 -0
  151. {plugin_scanner-2.0.167 → plugin_scanner-2.0.169}/src/codex_plugin_scanner/guard/cli/product.py +0 -0
  152. {plugin_scanner-2.0.167 → plugin_scanner-2.0.169}/src/codex_plugin_scanner/guard/cli/prompt.py +0 -0
  153. {plugin_scanner-2.0.167 → plugin_scanner-2.0.169}/src/codex_plugin_scanner/guard/cli/render.py +0 -0
  154. {plugin_scanner-2.0.167 → plugin_scanner-2.0.169}/src/codex_plugin_scanner/guard/cli/update_commands.py +0 -0
  155. {plugin_scanner-2.0.167 → plugin_scanner-2.0.169}/src/codex_plugin_scanner/guard/codex_config.py +0 -0
  156. {plugin_scanner-2.0.167 → plugin_scanner-2.0.169}/src/codex_plugin_scanner/guard/config.py +0 -0
  157. {plugin_scanner-2.0.167 → plugin_scanner-2.0.169}/src/codex_plugin_scanner/guard/consumer/__init__.py +0 -0
  158. {plugin_scanner-2.0.167 → plugin_scanner-2.0.169}/src/codex_plugin_scanner/guard/consumer/service.py +0 -0
  159. {plugin_scanner-2.0.167 → plugin_scanner-2.0.169}/src/codex_plugin_scanner/guard/daemon/__init__.py +0 -0
  160. {plugin_scanner-2.0.167 → plugin_scanner-2.0.169}/src/codex_plugin_scanner/guard/daemon/client.py +0 -0
  161. {plugin_scanner-2.0.167 → plugin_scanner-2.0.169}/src/codex_plugin_scanner/guard/daemon/manager.py +0 -0
  162. {plugin_scanner-2.0.167 → plugin_scanner-2.0.169}/src/codex_plugin_scanner/guard/daemon/server.py +0 -0
  163. {plugin_scanner-2.0.167 → plugin_scanner-2.0.169}/src/codex_plugin_scanner/guard/daemon/static/apple-touch-icon.png +0 -0
  164. {plugin_scanner-2.0.167 → plugin_scanner-2.0.169}/src/codex_plugin_scanner/guard/daemon/static/assets/index.css +0 -0
  165. {plugin_scanner-2.0.167 → plugin_scanner-2.0.169}/src/codex_plugin_scanner/guard/daemon/static/brand/Logo_Icon_Dark.png +0 -0
  166. {plugin_scanner-2.0.167 → plugin_scanner-2.0.169}/src/codex_plugin_scanner/guard/daemon/static/brand/Logo_Whole.png +0 -0
  167. {plugin_scanner-2.0.167 → plugin_scanner-2.0.169}/src/codex_plugin_scanner/guard/daemon/static/favicon-16x16.png +0 -0
  168. {plugin_scanner-2.0.167 → plugin_scanner-2.0.169}/src/codex_plugin_scanner/guard/daemon/static/favicon-32x32.png +0 -0
  169. {plugin_scanner-2.0.167 → plugin_scanner-2.0.169}/src/codex_plugin_scanner/guard/daemon/static/favicon.ico +0 -0
  170. {plugin_scanner-2.0.167 → plugin_scanner-2.0.169}/src/codex_plugin_scanner/guard/daemon/static/index.html +0 -0
  171. {plugin_scanner-2.0.167 → plugin_scanner-2.0.169}/src/codex_plugin_scanner/guard/edge_events.py +0 -0
  172. {plugin_scanner-2.0.167 → plugin_scanner-2.0.169}/src/codex_plugin_scanner/guard/incident.py +0 -0
  173. {plugin_scanner-2.0.167 → plugin_scanner-2.0.169}/src/codex_plugin_scanner/guard/insights.py +0 -0
  174. {plugin_scanner-2.0.167 → plugin_scanner-2.0.169}/src/codex_plugin_scanner/guard/launcher.py +0 -0
  175. {plugin_scanner-2.0.167 → plugin_scanner-2.0.169}/src/codex_plugin_scanner/guard/mcp_tool_calls.py +0 -0
  176. {plugin_scanner-2.0.167 → plugin_scanner-2.0.169}/src/codex_plugin_scanner/guard/models.py +0 -0
  177. {plugin_scanner-2.0.167 → plugin_scanner-2.0.169}/src/codex_plugin_scanner/guard/policy/__init__.py +0 -0
  178. {plugin_scanner-2.0.167 → plugin_scanner-2.0.169}/src/codex_plugin_scanner/guard/policy/engine.py +0 -0
  179. {plugin_scanner-2.0.167 → plugin_scanner-2.0.169}/src/codex_plugin_scanner/guard/protect.py +0 -0
  180. {plugin_scanner-2.0.167 → plugin_scanner-2.0.169}/src/codex_plugin_scanner/guard/proxy/__init__.py +0 -0
  181. {plugin_scanner-2.0.167 → plugin_scanner-2.0.169}/src/codex_plugin_scanner/guard/proxy/remote.py +0 -0
  182. {plugin_scanner-2.0.167 → plugin_scanner-2.0.169}/src/codex_plugin_scanner/guard/proxy/runtime_mcp.py +0 -0
  183. {plugin_scanner-2.0.167 → plugin_scanner-2.0.169}/src/codex_plugin_scanner/guard/proxy/stdio.py +0 -0
  184. {plugin_scanner-2.0.167 → plugin_scanner-2.0.169}/src/codex_plugin_scanner/guard/receipts/__init__.py +0 -0
  185. {plugin_scanner-2.0.167 → plugin_scanner-2.0.169}/src/codex_plugin_scanner/guard/receipts/manager.py +0 -0
  186. {plugin_scanner-2.0.167 → plugin_scanner-2.0.169}/src/codex_plugin_scanner/guard/redaction.py +0 -0
  187. {plugin_scanner-2.0.167 → plugin_scanner-2.0.169}/src/codex_plugin_scanner/guard/risk.py +0 -0
  188. {plugin_scanner-2.0.167 → plugin_scanner-2.0.169}/src/codex_plugin_scanner/guard/runtime/__init__.py +0 -0
  189. {plugin_scanner-2.0.167 → plugin_scanner-2.0.169}/src/codex_plugin_scanner/guard/runtime/action_identity.py +0 -0
  190. {plugin_scanner-2.0.167 → plugin_scanner-2.0.169}/src/codex_plugin_scanner/guard/runtime/actions.py +0 -0
  191. {plugin_scanner-2.0.167 → plugin_scanner-2.0.169}/src/codex_plugin_scanner/guard/runtime/advisory_escalation.py +0 -0
  192. {plugin_scanner-2.0.167 → plugin_scanner-2.0.169}/src/codex_plugin_scanner/guard/runtime/advisory_matchers.py +0 -0
  193. {plugin_scanner-2.0.167 → plugin_scanner-2.0.169}/src/codex_plugin_scanner/guard/runtime/cisco_evidence.py +0 -0
  194. {plugin_scanner-2.0.167 → plugin_scanner-2.0.169}/src/codex_plugin_scanner/guard/runtime/cisco_preflight.py +0 -0
  195. {plugin_scanner-2.0.167 → plugin_scanner-2.0.169}/src/codex_plugin_scanner/guard/runtime/composition_rules.py +0 -0
  196. {plugin_scanner-2.0.167 → plugin_scanner-2.0.169}/src/codex_plugin_scanner/guard/runtime/data_flow.py +0 -0
  197. {plugin_scanner-2.0.167 → plugin_scanner-2.0.169}/src/codex_plugin_scanner/guard/runtime/data_flow_rules.py +0 -0
  198. {plugin_scanner-2.0.167 → plugin_scanner-2.0.169}/src/codex_plugin_scanner/guard/runtime/data_flow_variables.py +0 -0
  199. {plugin_scanner-2.0.167 → plugin_scanner-2.0.169}/src/codex_plugin_scanner/guard/runtime/decisions.py +0 -0
  200. {plugin_scanner-2.0.167 → plugin_scanner-2.0.169}/src/codex_plugin_scanner/guard/runtime/detectors.py +0 -0
  201. {plugin_scanner-2.0.167 → plugin_scanner-2.0.169}/src/codex_plugin_scanner/guard/runtime/false_positive_rules.py +0 -0
  202. {plugin_scanner-2.0.167 → plugin_scanner-2.0.169}/src/codex_plugin_scanner/guard/runtime/mcp_protection.py +0 -0
  203. {plugin_scanner-2.0.167 → plugin_scanner-2.0.169}/src/codex_plugin_scanner/guard/runtime/persistence_rules.py +0 -0
  204. {plugin_scanner-2.0.167 → plugin_scanner-2.0.169}/src/codex_plugin_scanner/guard/runtime/prompt_injection.py +0 -0
  205. {plugin_scanner-2.0.167 → plugin_scanner-2.0.169}/src/codex_plugin_scanner/guard/runtime/runner.py +0 -0
  206. {plugin_scanner-2.0.167 → plugin_scanner-2.0.169}/src/codex_plugin_scanner/guard/runtime/safe_decode.py +0 -0
  207. {plugin_scanner-2.0.167 → plugin_scanner-2.0.169}/src/codex_plugin_scanner/guard/runtime/sandbox.py +0 -0
  208. {plugin_scanner-2.0.167 → plugin_scanner-2.0.169}/src/codex_plugin_scanner/guard/runtime/scanner_cache.py +0 -0
  209. {plugin_scanner-2.0.167 → plugin_scanner-2.0.169}/src/codex_plugin_scanner/guard/runtime/secret_file_requests.py +0 -0
  210. {plugin_scanner-2.0.167 → plugin_scanner-2.0.169}/src/codex_plugin_scanner/guard/runtime/secret_sensitivity.py +0 -0
  211. {plugin_scanner-2.0.167 → plugin_scanner-2.0.169}/src/codex_plugin_scanner/guard/runtime/secret_sources.py +0 -0
  212. {plugin_scanner-2.0.167 → plugin_scanner-2.0.169}/src/codex_plugin_scanner/guard/runtime/shell_commands.py +0 -0
  213. {plugin_scanner-2.0.167 → plugin_scanner-2.0.169}/src/codex_plugin_scanner/guard/runtime/signals.py +0 -0
  214. {plugin_scanner-2.0.167 → plugin_scanner-2.0.169}/src/codex_plugin_scanner/guard/runtime/skill_protection.py +0 -0
  215. {plugin_scanner-2.0.167 → plugin_scanner-2.0.169}/src/codex_plugin_scanner/guard/runtime/supply_chain.py +0 -0
  216. {plugin_scanner-2.0.167 → plugin_scanner-2.0.169}/src/codex_plugin_scanner/guard/runtime/surface_server.py +0 -0
  217. {plugin_scanner-2.0.167 → plugin_scanner-2.0.169}/src/codex_plugin_scanner/guard/runtime/temp_files.py +0 -0
  218. {plugin_scanner-2.0.167 → plugin_scanner-2.0.169}/src/codex_plugin_scanner/guard/runtime/threat_intel.py +0 -0
  219. {plugin_scanner-2.0.167 → plugin_scanner-2.0.169}/src/codex_plugin_scanner/guard/schemas/__init__.py +0 -0
  220. {plugin_scanner-2.0.167 → plugin_scanner-2.0.169}/src/codex_plugin_scanner/guard/schemas/consumer_mode.py +0 -0
  221. {plugin_scanner-2.0.167 → plugin_scanner-2.0.169}/src/codex_plugin_scanner/guard/schemas/guard_event_v1.py +0 -0
  222. {plugin_scanner-2.0.167 → plugin_scanner-2.0.169}/src/codex_plugin_scanner/guard/schemas/surface_server.py +0 -0
  223. {plugin_scanner-2.0.167 → plugin_scanner-2.0.169}/src/codex_plugin_scanner/guard/shims.py +0 -0
  224. {plugin_scanner-2.0.167 → plugin_scanner-2.0.169}/src/codex_plugin_scanner/guard/store_approvals.py +0 -0
  225. {plugin_scanner-2.0.167 → plugin_scanner-2.0.169}/src/codex_plugin_scanner/guard/store_connect.py +0 -0
  226. {plugin_scanner-2.0.167 → plugin_scanner-2.0.169}/src/codex_plugin_scanner/guard/store_evidence.py +0 -0
  227. {plugin_scanner-2.0.167 → plugin_scanner-2.0.169}/src/codex_plugin_scanner/guard/store_threat_intel.py +0 -0
  228. {plugin_scanner-2.0.167 → plugin_scanner-2.0.169}/src/codex_plugin_scanner/guard/types.py +0 -0
  229. {plugin_scanner-2.0.167 → plugin_scanner-2.0.169}/src/codex_plugin_scanner/integrations/__init__.py +0 -0
  230. {plugin_scanner-2.0.167 → plugin_scanner-2.0.169}/src/codex_plugin_scanner/integrations/cisco_mcp_scanner.py +0 -0
  231. {plugin_scanner-2.0.167 → plugin_scanner-2.0.169}/src/codex_plugin_scanner/integrations/cisco_skill_scanner.py +0 -0
  232. {plugin_scanner-2.0.167 → plugin_scanner-2.0.169}/src/codex_plugin_scanner/lint_fixes.py +0 -0
  233. {plugin_scanner-2.0.167 → plugin_scanner-2.0.169}/src/codex_plugin_scanner/marketplace_support.py +0 -0
  234. {plugin_scanner-2.0.167 → plugin_scanner-2.0.169}/src/codex_plugin_scanner/models.py +0 -0
  235. {plugin_scanner-2.0.167 → plugin_scanner-2.0.169}/src/codex_plugin_scanner/path_support.py +0 -0
  236. {plugin_scanner-2.0.167 → plugin_scanner-2.0.169}/src/codex_plugin_scanner/policy.py +0 -0
  237. {plugin_scanner-2.0.167 → plugin_scanner-2.0.169}/src/codex_plugin_scanner/quality_artifact.py +0 -0
  238. {plugin_scanner-2.0.167 → plugin_scanner-2.0.169}/src/codex_plugin_scanner/repo_detect.py +0 -0
  239. {plugin_scanner-2.0.167 → plugin_scanner-2.0.169}/src/codex_plugin_scanner/reporting.py +0 -0
  240. {plugin_scanner-2.0.167 → plugin_scanner-2.0.169}/src/codex_plugin_scanner/rules/__init__.py +0 -0
  241. {plugin_scanner-2.0.167 → plugin_scanner-2.0.169}/src/codex_plugin_scanner/rules/registry.py +0 -0
  242. {plugin_scanner-2.0.167 → plugin_scanner-2.0.169}/src/codex_plugin_scanner/rules/specs.py +0 -0
  243. {plugin_scanner-2.0.167 → plugin_scanner-2.0.169}/src/codex_plugin_scanner/scanner.py +0 -0
  244. {plugin_scanner-2.0.167 → plugin_scanner-2.0.169}/src/codex_plugin_scanner/submission.py +0 -0
  245. {plugin_scanner-2.0.167 → plugin_scanner-2.0.169}/src/codex_plugin_scanner/suppressions.py +0 -0
  246. {plugin_scanner-2.0.167 → plugin_scanner-2.0.169}/src/codex_plugin_scanner/trust_domain_scoring.py +0 -0
  247. {plugin_scanner-2.0.167 → plugin_scanner-2.0.169}/src/codex_plugin_scanner/trust_helpers.py +0 -0
  248. {plugin_scanner-2.0.167 → plugin_scanner-2.0.169}/src/codex_plugin_scanner/trust_mcp_scoring.py +0 -0
  249. {plugin_scanner-2.0.167 → plugin_scanner-2.0.169}/src/codex_plugin_scanner/trust_models.py +0 -0
  250. {plugin_scanner-2.0.167 → plugin_scanner-2.0.169}/src/codex_plugin_scanner/trust_plugin_scoring.py +0 -0
  251. {plugin_scanner-2.0.167 → plugin_scanner-2.0.169}/src/codex_plugin_scanner/trust_scoring.py +0 -0
  252. {plugin_scanner-2.0.167 → plugin_scanner-2.0.169}/src/codex_plugin_scanner/trust_skill_scoring.py +0 -0
  253. {plugin_scanner-2.0.167 → plugin_scanner-2.0.169}/src/codex_plugin_scanner/trust_specs.py +0 -0
  254. {plugin_scanner-2.0.167 → plugin_scanner-2.0.169}/src/codex_plugin_scanner/verification.py +0 -0
  255. {plugin_scanner-2.0.167 → plugin_scanner-2.0.169}/tests/__init__.py +0 -0
  256. {plugin_scanner-2.0.167 → plugin_scanner-2.0.169}/tests/conftest.py +0 -0
  257. {plugin_scanner-2.0.167 → plugin_scanner-2.0.169}/tests/fixtures/__init__.py +0 -0
  258. {plugin_scanner-2.0.167 → plugin_scanner-2.0.169}/tests/fixtures/bad-plugin/.codex-plugin/plugin.json +0 -0
  259. {plugin_scanner-2.0.167 → plugin_scanner-2.0.169}/tests/fixtures/bad-plugin/.mcp.json +0 -0
  260. {plugin_scanner-2.0.167 → plugin_scanner-2.0.169}/tests/fixtures/bad-plugin/secrets.js +0 -0
  261. {plugin_scanner-2.0.167 → plugin_scanner-2.0.169}/tests/fixtures/claude-plugin-good/.claude-plugin/plugin.json +0 -0
  262. {plugin_scanner-2.0.167 → plugin_scanner-2.0.169}/tests/fixtures/claude-plugin-good/LICENSE +0 -0
  263. {plugin_scanner-2.0.167 → plugin_scanner-2.0.169}/tests/fixtures/claude-plugin-good/README.md +0 -0
  264. {plugin_scanner-2.0.167 → plugin_scanner-2.0.169}/tests/fixtures/claude-plugin-good/SECURITY.md +0 -0
  265. {plugin_scanner-2.0.167 → plugin_scanner-2.0.169}/tests/fixtures/claude-plugin-good/hooks/hooks.json +0 -0
  266. {plugin_scanner-2.0.167 → plugin_scanner-2.0.169}/tests/fixtures/claude-plugin-good/skills/example/SKILL.md +0 -0
  267. {plugin_scanner-2.0.167 → plugin_scanner-2.0.169}/tests/fixtures/code-quality-bad/evil.js +0 -0
  268. {plugin_scanner-2.0.167 → plugin_scanner-2.0.169}/tests/fixtures/code-quality-bad/inject.js +0 -0
  269. {plugin_scanner-2.0.167 → plugin_scanner-2.0.169}/tests/fixtures/gemini-extension-good/GEMINI.md +0 -0
  270. {plugin_scanner-2.0.167 → plugin_scanner-2.0.169}/tests/fixtures/gemini-extension-good/LICENSE +0 -0
  271. {plugin_scanner-2.0.167 → plugin_scanner-2.0.169}/tests/fixtures/gemini-extension-good/README.md +0 -0
  272. {plugin_scanner-2.0.167 → plugin_scanner-2.0.169}/tests/fixtures/gemini-extension-good/SECURITY.md +0 -0
  273. {plugin_scanner-2.0.167 → plugin_scanner-2.0.169}/tests/fixtures/gemini-extension-good/commands/hello.toml +0 -0
  274. {plugin_scanner-2.0.167 → plugin_scanner-2.0.169}/tests/fixtures/gemini-extension-good/gemini-extension.json +0 -0
  275. {plugin_scanner-2.0.167 → plugin_scanner-2.0.169}/tests/fixtures/good-plugin/.codex-plugin/plugin.json +0 -0
  276. {plugin_scanner-2.0.167 → plugin_scanner-2.0.169}/tests/fixtures/good-plugin/.codexignore +0 -0
  277. {plugin_scanner-2.0.167 → plugin_scanner-2.0.169}/tests/fixtures/good-plugin/LICENSE +0 -0
  278. {plugin_scanner-2.0.167 → plugin_scanner-2.0.169}/tests/fixtures/good-plugin/README.md +0 -0
  279. {plugin_scanner-2.0.167 → plugin_scanner-2.0.169}/tests/fixtures/good-plugin/SECURITY.md +0 -0
  280. {plugin_scanner-2.0.167 → plugin_scanner-2.0.169}/tests/fixtures/good-plugin/assets/icon.svg +0 -0
  281. {plugin_scanner-2.0.167 → plugin_scanner-2.0.169}/tests/fixtures/good-plugin/assets/logo.svg +0 -0
  282. {plugin_scanner-2.0.167 → plugin_scanner-2.0.169}/tests/fixtures/good-plugin/assets/screenshot.svg +0 -0
  283. {plugin_scanner-2.0.167 → plugin_scanner-2.0.169}/tests/fixtures/good-plugin/skills/example/SKILL.md +0 -0
  284. {plugin_scanner-2.0.167 → plugin_scanner-2.0.169}/tests/fixtures/guard-codex-malicious-mcp/.codex/config.toml +0 -0
  285. {plugin_scanner-2.0.167 → plugin_scanner-2.0.169}/tests/fixtures/guard-red-team/README.md +0 -0
  286. {plugin_scanner-2.0.167 → plugin_scanner-2.0.169}/tests/fixtures/guard-red-team/benign-docs-fake-token.py +0 -0
  287. {plugin_scanner-2.0.167 → plugin_scanner-2.0.169}/tests/fixtures/guard-red-team/benign-health-endpoint.py +0 -0
  288. {plugin_scanner-2.0.167 → plugin_scanner-2.0.169}/tests/fixtures/guard-red-team/benign-nvmrc-fake-creds.py +0 -0
  289. {plugin_scanner-2.0.167 → plugin_scanner-2.0.169}/tests/fixtures/guard-red-team/benign-source-search.py +0 -0
  290. {plugin_scanner-2.0.167 → plugin_scanner-2.0.169}/tests/fixtures/guard-red-team/canary-exfil-encoded.py +0 -0
  291. {plugin_scanner-2.0.167 → plugin_scanner-2.0.169}/tests/fixtures/guard-red-team/canary-exfil.py +0 -0
  292. {plugin_scanner-2.0.167 → plugin_scanner-2.0.169}/tests/fixtures/guard-red-team/expected-decisions.json +0 -0
  293. {plugin_scanner-2.0.167 → plugin_scanner-2.0.169}/tests/fixtures/guard-red-team/malicious-dockerfile.txt +0 -0
  294. {plugin_scanner-2.0.167 → plugin_scanner-2.0.169}/tests/fixtures/guard-red-team/malicious-encoded-shell-exfil.py +0 -0
  295. {plugin_scanner-2.0.167 → plugin_scanner-2.0.169}/tests/fixtures/guard-red-team/malicious-github-action.yml +0 -0
  296. {plugin_scanner-2.0.167 → plugin_scanner-2.0.169}/tests/fixtures/guard-red-team/malicious-mcp-delete.md +0 -0
  297. {plugin_scanner-2.0.167 → plugin_scanner-2.0.169}/tests/fixtures/guard-red-team/malicious-mcp-secret-read.md +0 -0
  298. {plugin_scanner-2.0.167 → plugin_scanner-2.0.169}/tests/fixtures/guard-red-team/malicious-mcp-skill-exfil.md +0 -0
  299. {plugin_scanner-2.0.167 → plugin_scanner-2.0.169}/tests/fixtures/guard-red-team/malicious-npm-postinstall.js +0 -0
  300. {plugin_scanner-2.0.167 → plugin_scanner-2.0.169}/tests/fixtures/guard-red-team/malicious-prompt-env-read.md +0 -0
  301. {plugin_scanner-2.0.167 → plugin_scanner-2.0.169}/tests/fixtures/guard-red-team/malicious-prompt-guard-bypass.md +0 -0
  302. {plugin_scanner-2.0.167 → plugin_scanner-2.0.169}/tests/fixtures/guard-red-team/malicious-prompt-npmrc-read.md +0 -0
  303. {plugin_scanner-2.0.167 → plugin_scanner-2.0.169}/tests/fixtures/guard-red-team/malicious-python-setup.py +0 -0
  304. {plugin_scanner-2.0.167 → plugin_scanner-2.0.169}/tests/fixtures/guard-red-team/smoke-evidence-template.json +0 -0
  305. {plugin_scanner-2.0.167 → plugin_scanner-2.0.169}/tests/fixtures/hermes-plugin-evil/config.yaml +0 -0
  306. {plugin_scanner-2.0.167 → plugin_scanner-2.0.169}/tests/fixtures/hermes-plugin-evil/mcp_servers.json +0 -0
  307. {plugin_scanner-2.0.167 → plugin_scanner-2.0.169}/tests/fixtures/hermes-plugin-evil/skills/security/malicious/SKILL.md +0 -0
  308. {plugin_scanner-2.0.167 → plugin_scanner-2.0.169}/tests/fixtures/hermes-plugin-evil/skills/stealth/sneaky/SKILL.md +0 -0
  309. {plugin_scanner-2.0.167 → plugin_scanner-2.0.169}/tests/fixtures/hermes-plugin-evil/skills/stealth/sneaky/references/api-setup.md +0 -0
  310. {plugin_scanner-2.0.167 → plugin_scanner-2.0.169}/tests/fixtures/hermes-plugin-evil/skills/stealth/sneaky/scripts/deploy.sh +0 -0
  311. {plugin_scanner-2.0.167 → plugin_scanner-2.0.169}/tests/fixtures/hermes-plugin-evil/skills/utils/benign/SKILL.md +0 -0
  312. {plugin_scanner-2.0.167 → plugin_scanner-2.0.169}/tests/fixtures/malformed-json/.codex-plugin/plugin.json +0 -0
  313. {plugin_scanner-2.0.167 → plugin_scanner-2.0.169}/tests/fixtures/malicious-skill-plugin/.codex-plugin/plugin.json +0 -0
  314. {plugin_scanner-2.0.167 → plugin_scanner-2.0.169}/tests/fixtures/malicious-skill-plugin/.codexignore +0 -0
  315. {plugin_scanner-2.0.167 → plugin_scanner-2.0.169}/tests/fixtures/malicious-skill-plugin/LICENSE +0 -0
  316. {plugin_scanner-2.0.167 → plugin_scanner-2.0.169}/tests/fixtures/malicious-skill-plugin/README.md +0 -0
  317. {plugin_scanner-2.0.167 → plugin_scanner-2.0.169}/tests/fixtures/malicious-skill-plugin/SECURITY.md +0 -0
  318. {plugin_scanner-2.0.167 → plugin_scanner-2.0.169}/tests/fixtures/malicious-skill-plugin/skills/leaky-skill/SKILL.md +0 -0
  319. {plugin_scanner-2.0.167 → plugin_scanner-2.0.169}/tests/fixtures/mcp-canary-server.py +0 -0
  320. {plugin_scanner-2.0.167 → plugin_scanner-2.0.169}/tests/fixtures/minimal-plugin/.codex-plugin/plugin.json +0 -0
  321. {plugin_scanner-2.0.167 → plugin_scanner-2.0.169}/tests/fixtures/missing-fields/.codex-plugin/plugin.json +0 -0
  322. {plugin_scanner-2.0.167 → plugin_scanner-2.0.169}/tests/fixtures/mit-license/LICENSE +0 -0
  323. {plugin_scanner-2.0.167 → plugin_scanner-2.0.169}/tests/fixtures/multi-ecosystem-repo/codex-plugin/.codex-plugin/plugin.json +0 -0
  324. {plugin_scanner-2.0.167 → plugin_scanner-2.0.169}/tests/fixtures/multi-ecosystem-repo/codex-plugin/LICENSE +0 -0
  325. {plugin_scanner-2.0.167 → plugin_scanner-2.0.169}/tests/fixtures/multi-ecosystem-repo/codex-plugin/README.md +0 -0
  326. {plugin_scanner-2.0.167 → plugin_scanner-2.0.169}/tests/fixtures/multi-ecosystem-repo/codex-plugin/SECURITY.md +0 -0
  327. {plugin_scanner-2.0.167 → plugin_scanner-2.0.169}/tests/fixtures/multi-ecosystem-repo/gemini-ext/README.md +0 -0
  328. {plugin_scanner-2.0.167 → plugin_scanner-2.0.169}/tests/fixtures/multi-ecosystem-repo/gemini-ext/gemini-extension.json +0 -0
  329. {plugin_scanner-2.0.167 → plugin_scanner-2.0.169}/tests/fixtures/multi-plugin-repo/.agents/plugins/marketplace.json +0 -0
  330. {plugin_scanner-2.0.167 → plugin_scanner-2.0.169}/tests/fixtures/multi-plugin-repo/plugins/alpha-plugin/.codex-plugin/plugin.json +0 -0
  331. {plugin_scanner-2.0.167 → plugin_scanner-2.0.169}/tests/fixtures/multi-plugin-repo/plugins/alpha-plugin/.codexignore +0 -0
  332. {plugin_scanner-2.0.167 → plugin_scanner-2.0.169}/tests/fixtures/multi-plugin-repo/plugins/alpha-plugin/LICENSE +0 -0
  333. {plugin_scanner-2.0.167 → plugin_scanner-2.0.169}/tests/fixtures/multi-plugin-repo/plugins/alpha-plugin/README.md +0 -0
  334. {plugin_scanner-2.0.167 → plugin_scanner-2.0.169}/tests/fixtures/multi-plugin-repo/plugins/alpha-plugin/SECURITY.md +0 -0
  335. {plugin_scanner-2.0.167 → plugin_scanner-2.0.169}/tests/fixtures/multi-plugin-repo/plugins/alpha-plugin/skills/example/SKILL.md +0 -0
  336. {plugin_scanner-2.0.167 → plugin_scanner-2.0.169}/tests/fixtures/multi-plugin-repo/plugins/beta-plugin/.codex-plugin/plugin.json +0 -0
  337. {plugin_scanner-2.0.167 → plugin_scanner-2.0.169}/tests/fixtures/multi-plugin-repo/plugins/beta-plugin/skills/example/SKILL.md +0 -0
  338. {plugin_scanner-2.0.167 → plugin_scanner-2.0.169}/tests/fixtures/no-version/.codex-plugin/plugin.json +0 -0
  339. {plugin_scanner-2.0.167 → plugin_scanner-2.0.169}/tests/fixtures/opencode-good/.opencode/commands/hello.md +0 -0
  340. {plugin_scanner-2.0.167 → plugin_scanner-2.0.169}/tests/fixtures/opencode-good/.opencode/plugins/example.ts +0 -0
  341. {plugin_scanner-2.0.167 → plugin_scanner-2.0.169}/tests/fixtures/opencode-good/LICENSE +0 -0
  342. {plugin_scanner-2.0.167 → plugin_scanner-2.0.169}/tests/fixtures/opencode-good/README.md +0 -0
  343. {plugin_scanner-2.0.167 → plugin_scanner-2.0.169}/tests/fixtures/opencode-good/SECURITY.md +0 -0
  344. {plugin_scanner-2.0.167 → plugin_scanner-2.0.169}/tests/fixtures/opencode-good/opencode.jsonc +0 -0
  345. {plugin_scanner-2.0.167 → plugin_scanner-2.0.169}/tests/fixtures/skills-missing-dir/.codex-plugin/plugin.json +0 -0
  346. {plugin_scanner-2.0.167 → plugin_scanner-2.0.169}/tests/fixtures/skills-no-frontmatter/.codex-plugin/plugin.json +0 -0
  347. {plugin_scanner-2.0.167 → plugin_scanner-2.0.169}/tests/fixtures/skills-no-frontmatter/skills/bad-skill/SKILL.md +0 -0
  348. {plugin_scanner-2.0.167 → plugin_scanner-2.0.169}/tests/fixtures/supply-chain/benign-npm-package.json +0 -0
  349. {plugin_scanner-2.0.167 → plugin_scanner-2.0.169}/tests/fixtures/supply-chain/benign-pnpm-package.json +0 -0
  350. {plugin_scanner-2.0.167 → plugin_scanner-2.0.169}/tests/fixtures/supply-chain/benign-pyproject.toml +0 -0
  351. {plugin_scanner-2.0.167 → plugin_scanner-2.0.169}/tests/fixtures/supply-chain/malicious-Dockerfile +0 -0
  352. {plugin_scanner-2.0.167 → plugin_scanner-2.0.169}/tests/fixtures/supply-chain/malicious-action.yml +0 -0
  353. {plugin_scanner-2.0.167 → plugin_scanner-2.0.169}/tests/fixtures/supply-chain/malicious-npm-package.json +0 -0
  354. {plugin_scanner-2.0.167 → plugin_scanner-2.0.169}/tests/fixtures/supply-chain/malicious-setup.py +0 -0
  355. {plugin_scanner-2.0.167 → plugin_scanner-2.0.169}/tests/fixtures/with-marketplace/.codex-plugin/plugin.json +0 -0
  356. {plugin_scanner-2.0.167 → plugin_scanner-2.0.169}/tests/fixtures/with-marketplace/marketplace-broken.json +0 -0
  357. {plugin_scanner-2.0.167 → plugin_scanner-2.0.169}/tests/fixtures/with-marketplace/marketplace.json +0 -0
  358. {plugin_scanner-2.0.167 → plugin_scanner-2.0.169}/tests/test-trust-scoring.py +0 -0
  359. {plugin_scanner-2.0.167 → plugin_scanner-2.0.169}/tests/test-trust-specs.py +0 -0
  360. {plugin_scanner-2.0.167 → plugin_scanner-2.0.169}/tests/test_action_runner.py +0 -0
  361. {plugin_scanner-2.0.167 → plugin_scanner-2.0.169}/tests/test_best_practices.py +0 -0
  362. {plugin_scanner-2.0.167 → plugin_scanner-2.0.169}/tests/test_cisco_install_surfaces.py +0 -0
  363. {plugin_scanner-2.0.167 → plugin_scanner-2.0.169}/tests/test_cli.py +0 -0
  364. {plugin_scanner-2.0.167 → plugin_scanner-2.0.169}/tests/test_code_quality.py +0 -0
  365. {plugin_scanner-2.0.167 → plugin_scanner-2.0.169}/tests/test_config.py +0 -0
  366. {plugin_scanner-2.0.167 → plugin_scanner-2.0.169}/tests/test_coverage_remaining.py +0 -0
  367. {plugin_scanner-2.0.167 → plugin_scanner-2.0.169}/tests/test_ecosystems.py +0 -0
  368. {plugin_scanner-2.0.167 → plugin_scanner-2.0.169}/tests/test_edge_cases.py +0 -0
  369. {plugin_scanner-2.0.167 → plugin_scanner-2.0.169}/tests/test_final_coverage.py +0 -0
  370. {plugin_scanner-2.0.167 → plugin_scanner-2.0.169}/tests/test_guard_access_graph.py +0 -0
  371. {plugin_scanner-2.0.167 → plugin_scanner-2.0.169}/tests/test_guard_action_identity.py +0 -0
  372. {plugin_scanner-2.0.167 → plugin_scanner-2.0.169}/tests/test_guard_advisory_escalation.py +0 -0
  373. {plugin_scanner-2.0.167 → plugin_scanner-2.0.169}/tests/test_guard_approval_continuity.py +0 -0
  374. {plugin_scanner-2.0.167 → plugin_scanner-2.0.169}/tests/test_guard_approval_copy_commands.py +0 -0
  375. {plugin_scanner-2.0.167 → plugin_scanner-2.0.169}/tests/test_guard_approval_store_dedup.py +0 -0
  376. {plugin_scanner-2.0.167 → plugin_scanner-2.0.169}/tests/test_guard_approval_store_scale.py +0 -0
  377. {plugin_scanner-2.0.167 → plugin_scanner-2.0.169}/tests/test_guard_approvals.py +0 -0
  378. {plugin_scanner-2.0.167 → plugin_scanner-2.0.169}/tests/test_guard_bootstrap.py +0 -0
  379. {plugin_scanner-2.0.167 → plugin_scanner-2.0.169}/tests/test_guard_bypass_detector.py +0 -0
  380. {plugin_scanner-2.0.167 → plugin_scanner-2.0.169}/tests/test_guard_canary_fixtures.py +0 -0
  381. {plugin_scanner-2.0.167 → plugin_scanner-2.0.169}/tests/test_guard_capabilities.py +0 -0
  382. {plugin_scanner-2.0.167 → plugin_scanner-2.0.169}/tests/test_guard_cisco_evidence.py +0 -0
  383. {plugin_scanner-2.0.167 → plugin_scanner-2.0.169}/tests/test_guard_cisco_runtime_cli.py +0 -0
  384. {plugin_scanner-2.0.167 → plugin_scanner-2.0.169}/tests/test_guard_claude_adapter.py +0 -0
  385. {plugin_scanner-2.0.167 → plugin_scanner-2.0.169}/tests/test_guard_cli.py +0 -0
  386. {plugin_scanner-2.0.167 → plugin_scanner-2.0.169}/tests/test_guard_cloud_local_sync.py +0 -0
  387. {plugin_scanner-2.0.167 → plugin_scanner-2.0.169}/tests/test_guard_codex_e2e.py +0 -0
  388. {plugin_scanner-2.0.167 → plugin_scanner-2.0.169}/tests/test_guard_codex_install.py +0 -0
  389. {plugin_scanner-2.0.167 → plugin_scanner-2.0.169}/tests/test_guard_codex_proxy.py +0 -0
  390. {plugin_scanner-2.0.167 → plugin_scanner-2.0.169}/tests/test_guard_config_paths.py +0 -0
  391. {plugin_scanner-2.0.167 → plugin_scanner-2.0.169}/tests/test_guard_connect_flow.py +0 -0
  392. {plugin_scanner-2.0.167 → plugin_scanner-2.0.169}/tests/test_guard_consumer_mode.py +0 -0
  393. {plugin_scanner-2.0.167 → plugin_scanner-2.0.169}/tests/test_guard_copilot_adapter.py +0 -0
  394. {plugin_scanner-2.0.167 → plugin_scanner-2.0.169}/tests/test_guard_copilot_proxy.py +0 -0
  395. {plugin_scanner-2.0.167 → plugin_scanner-2.0.169}/tests/test_guard_daemon_cli.py +0 -0
  396. {plugin_scanner-2.0.167 → plugin_scanner-2.0.169}/tests/test_guard_daemon_manager.py +0 -0
  397. {plugin_scanner-2.0.167 → plugin_scanner-2.0.169}/tests/test_guard_daemon_perf.py +0 -0
  398. {plugin_scanner-2.0.167 → plugin_scanner-2.0.169}/tests/test_guard_daemon_registry.py +0 -0
  399. {plugin_scanner-2.0.167 → plugin_scanner-2.0.169}/tests/test_guard_daemon_repair_perf.py +0 -0
  400. {plugin_scanner-2.0.167 → plugin_scanner-2.0.169}/tests/test_guard_daemon_wake.py +0 -0
  401. {plugin_scanner-2.0.167 → plugin_scanner-2.0.169}/tests/test_guard_data_flow.py +0 -0
  402. {plugin_scanner-2.0.167 → plugin_scanner-2.0.169}/tests/test_guard_decision_propagation.py +0 -0
  403. {plugin_scanner-2.0.167 → plugin_scanner-2.0.169}/tests/test_guard_detector_fp.py +0 -0
  404. {plugin_scanner-2.0.167 → plugin_scanner-2.0.169}/tests/test_guard_event_schema_v1.py +0 -0
  405. {plugin_scanner-2.0.167 → plugin_scanner-2.0.169}/tests/test_guard_events.py +0 -0
  406. {plugin_scanner-2.0.167 → plugin_scanner-2.0.169}/tests/test_guard_evidence_store.py +0 -0
  407. {plugin_scanner-2.0.167 → plugin_scanner-2.0.169}/tests/test_guard_harness_contracts.py +0 -0
  408. {plugin_scanner-2.0.167 → plugin_scanner-2.0.169}/tests/test_guard_harness_setup.py +0 -0
  409. {plugin_scanner-2.0.167 → plugin_scanner-2.0.169}/tests/test_guard_harness_smoke.py +0 -0
  410. {plugin_scanner-2.0.167 → plugin_scanner-2.0.169}/tests/test_guard_insights.py +0 -0
  411. {plugin_scanner-2.0.167 → plugin_scanner-2.0.169}/tests/test_guard_launch_env.py +0 -0
  412. {plugin_scanner-2.0.167 → plugin_scanner-2.0.169}/tests/test_guard_mcp_detectors.py +0 -0
  413. {plugin_scanner-2.0.167 → plugin_scanner-2.0.169}/tests/test_guard_mcp_protection.py +0 -0
  414. {plugin_scanner-2.0.167 → plugin_scanner-2.0.169}/tests/test_guard_opencode_proxy.py +0 -0
  415. {plugin_scanner-2.0.167 → plugin_scanner-2.0.169}/tests/test_guard_policy_dedup.py +0 -0
  416. {plugin_scanner-2.0.167 → plugin_scanner-2.0.169}/tests/test_guard_product_flow.py +0 -0
  417. {plugin_scanner-2.0.167 → plugin_scanner-2.0.169}/tests/test_guard_prompt_injection.py +0 -0
  418. {plugin_scanner-2.0.167 → plugin_scanner-2.0.169}/tests/test_guard_protect.py +0 -0
  419. {plugin_scanner-2.0.167 → plugin_scanner-2.0.169}/tests/test_guard_queue_api_contract.py +0 -0
  420. {plugin_scanner-2.0.167 → plugin_scanner-2.0.169}/tests/test_guard_queue_contract.py +0 -0
  421. {plugin_scanner-2.0.167 → plugin_scanner-2.0.169}/tests/test_guard_red_team.py +0 -0
  422. {plugin_scanner-2.0.167 → plugin_scanner-2.0.169}/tests/test_guard_red_team_e2e.py +0 -0
  423. {plugin_scanner-2.0.167 → plugin_scanner-2.0.169}/tests/test_guard_redaction.py +0 -0
  424. {plugin_scanner-2.0.167 → plugin_scanner-2.0.169}/tests/test_guard_render.py +0 -0
  425. {plugin_scanner-2.0.167 → plugin_scanner-2.0.169}/tests/test_guard_resolution_copy.py +0 -0
  426. {plugin_scanner-2.0.167 → plugin_scanner-2.0.169}/tests/test_guard_risk.py +0 -0
  427. {plugin_scanner-2.0.167 → plugin_scanner-2.0.169}/tests/test_guard_runtime_action_harnesses.py +0 -0
  428. {plugin_scanner-2.0.167 → plugin_scanner-2.0.169}/tests/test_guard_runtime_actions.py +0 -0
  429. {plugin_scanner-2.0.167 → plugin_scanner-2.0.169}/tests/test_guard_runtime_decisions.py +0 -0
  430. {plugin_scanner-2.0.167 → plugin_scanner-2.0.169}/tests/test_guard_runtime_detectors.py +0 -0
  431. {plugin_scanner-2.0.167 → plugin_scanner-2.0.169}/tests/test_guard_runtime_signals.py +0 -0
  432. {plugin_scanner-2.0.167 → plugin_scanner-2.0.169}/tests/test_guard_safe_decode.py +0 -0
  433. {plugin_scanner-2.0.167 → plugin_scanner-2.0.169}/tests/test_guard_sandbox.py +0 -0
  434. {plugin_scanner-2.0.167 → plugin_scanner-2.0.169}/tests/test_guard_settings_presets.py +0 -0
  435. {plugin_scanner-2.0.167 → plugin_scanner-2.0.169}/tests/test_guard_skill_protection.py +0 -0
  436. {plugin_scanner-2.0.167 → plugin_scanner-2.0.169}/tests/test_guard_store_migrations.py +0 -0
  437. {plugin_scanner-2.0.167 → plugin_scanner-2.0.169}/tests/test_guard_supply_chain.py +0 -0
  438. {plugin_scanner-2.0.167 → plugin_scanner-2.0.169}/tests/test_guard_surface_server.py +0 -0
  439. {plugin_scanner-2.0.167 → plugin_scanner-2.0.169}/tests/test_guard_threat_intel.py +0 -0
  440. {plugin_scanner-2.0.167 → plugin_scanner-2.0.169}/tests/test_guard_verdicts.py +0 -0
  441. {plugin_scanner-2.0.167 → plugin_scanner-2.0.169}/tests/test_guard_web_recovery.py +0 -0
  442. {plugin_scanner-2.0.167 → plugin_scanner-2.0.169}/tests/test_hermes_adapter.py +0 -0
  443. {plugin_scanner-2.0.167 → plugin_scanner-2.0.169}/tests/test_integration.py +0 -0
  444. {plugin_scanner-2.0.167 → plugin_scanner-2.0.169}/tests/test_lint_fixes.py +0 -0
  445. {plugin_scanner-2.0.167 → plugin_scanner-2.0.169}/tests/test_live_cisco_smoke.py +0 -0
  446. {plugin_scanner-2.0.167 → plugin_scanner-2.0.169}/tests/test_manifest.py +0 -0
  447. {plugin_scanner-2.0.167 → plugin_scanner-2.0.169}/tests/test_marketplace.py +0 -0
  448. {plugin_scanner-2.0.167 → plugin_scanner-2.0.169}/tests/test_mcp_security.py +0 -0
  449. {plugin_scanner-2.0.167 → plugin_scanner-2.0.169}/tests/test_openclaw_adapter.py +0 -0
  450. {plugin_scanner-2.0.167 → plugin_scanner-2.0.169}/tests/test_operational_security.py +0 -0
  451. {plugin_scanner-2.0.167 → plugin_scanner-2.0.169}/tests/test_policy.py +0 -0
  452. {plugin_scanner-2.0.167 → plugin_scanner-2.0.169}/tests/test_quality_artifact.py +0 -0
  453. {plugin_scanner-2.0.167 → plugin_scanner-2.0.169}/tests/test_rule_registry.py +0 -0
  454. {plugin_scanner-2.0.167 → plugin_scanner-2.0.169}/tests/test_scanner.py +0 -0
  455. {plugin_scanner-2.0.167 → plugin_scanner-2.0.169}/tests/test_schema_contracts.py +0 -0
  456. {plugin_scanner-2.0.167 → plugin_scanner-2.0.169}/tests/test_security.py +0 -0
  457. {plugin_scanner-2.0.167 → plugin_scanner-2.0.169}/tests/test_security_ops.py +0 -0
  458. {plugin_scanner-2.0.167 → plugin_scanner-2.0.169}/tests/test_skill_security.py +0 -0
  459. {plugin_scanner-2.0.167 → plugin_scanner-2.0.169}/tests/test_submission.py +0 -0
  460. {plugin_scanner-2.0.167 → plugin_scanner-2.0.169}/tests/test_trust_scoring.py +0 -0
  461. {plugin_scanner-2.0.167 → plugin_scanner-2.0.169}/tests/test_trust_specs.py +0 -0
  462. {plugin_scanner-2.0.167 → plugin_scanner-2.0.169}/tests/test_verification.py +0 -0
  463. {plugin_scanner-2.0.167 → plugin_scanner-2.0.169}/tests/test_versioning.py +0 -0
  464. {plugin_scanner-2.0.167 → plugin_scanner-2.0.169}/uv.lock +0 -0
@@ -1,6 +1,6 @@
1
1
  Metadata-Version: 2.4
2
2
  Name: plugin-scanner
3
- Version: 2.0.167
3
+ Version: 2.0.169
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
@@ -5,6 +5,8 @@ import {
5
5
  displayArtifactName,
6
6
  EMPTY_QUEUE_TITLE,
7
7
  STALE_REQUEST_COPY,
8
+ buildRecommendation,
9
+ scopeLabel,
8
10
  } from "./approval-center-utils";
9
11
  import type { GuardActionEnvelope, GuardApprovalRequest } from "./guard-types";
10
12
 
@@ -208,3 +210,18 @@ assert(
208
210
  STALE_REQUEST_COPY.toLowerCase().includes("already decided"),
209
211
  'C6: Stale request copy contains "already decided" — not approve/block buttons'
210
212
  );
213
+
214
+ assert(
215
+ scopeLabel("artifact") === "This retry only",
216
+ "C7: Artifact scope copy makes one-retry behavior clear"
217
+ );
218
+
219
+ assert(
220
+ scopeLabel("workspace") === "Same action in this project",
221
+ "C8: Workspace scope copy makes same-action project behavior clear"
222
+ );
223
+
224
+ assert(
225
+ buildRecommendation(BASE_REQUEST).includes("Project approval remembers this same action"),
226
+ "C9: Recommendation explains project approval does not trust new sensitive actions"
227
+ );
@@ -59,6 +59,7 @@ import {
59
59
  } from "./approval-center-review-cards";
60
60
  import {
61
61
  buildProgressCopy,
62
+ buildNextUpChipText,
62
63
  sortQueue,
63
64
  searchQueue,
64
65
  groupDuplicates,
@@ -130,8 +131,16 @@ type LayoutProps = {
130
131
  };
131
132
 
132
133
  const scopeOptions: Array<{ value: DecisionScope; label: string; description: string }> = [
133
- { value: "artifact", label: "This exact action", description: "Ask again if the command or tool details change." },
134
- { value: "workspace", label: "This project folder", description: "Remember this choice only for this project." },
134
+ {
135
+ value: "artifact",
136
+ label: "This retry only",
137
+ description: "Remember this exact prompt, command, tool, path, or host fingerprint."
138
+ },
139
+ {
140
+ value: "workspace",
141
+ label: "Same action in this project",
142
+ description: "Skip the next prompt for this same action here; different sensitive actions still ask."
143
+ },
135
144
  { value: "publisher", label: "This source", description: "Trust future actions from the same source in this app." },
136
145
  { value: "harness", label: "This app", description: "Trust matching actions from this app." },
137
146
  { value: "global", label: "Every project", description: "Use this choice across this machine." }
@@ -279,15 +288,25 @@ function QueueWorkspace(props: {
279
288
  if (props.requests.kind === "error") {
280
289
  const approvalUrl =
281
290
  props.runtime.kind === "ready" ? props.runtime.snapshot.approval_center_url : null;
291
+ const handleOpenDaemon = () => {
292
+ if (approvalUrl !== null) {
293
+ window.open(approvalUrl, "_blank", "noopener,noreferrer");
294
+ } else {
295
+ void handleRepair();
296
+ }
297
+ };
282
298
  return (
283
299
  <div className="space-y-4">
284
300
  <Surface tone="danger">
285
- <p className="text-sm font-semibold text-brand-purple">Guard connection lost. Check if the daemon is running.</p>
301
+ <p className="text-sm font-semibold text-brand-purple">Guard daemon not responding click to reconnect.</p>
286
302
  <p className="mt-1 text-sm text-brand-purple/80">{props.requests.message}</p>
287
303
  <div className="mt-4 flex flex-wrap gap-3">
304
+ <ActionButton onClick={handleOpenDaemon}>
305
+ Repair
306
+ </ActionButton>
288
307
  {props.onRepair !== undefined && (
289
- <ActionButton onClick={handleRepair} disabled={repairing}>
290
- {repairing ? "Repairing…" : "Repair"}
308
+ <ActionButton onClick={handleRepair} disabled={repairing} variant="outline">
309
+ {repairing ? "Repairing…" : "Reconnect"}
291
310
  </ActionButton>
292
311
  )}
293
312
  <code className="inline-flex min-h-10 items-center rounded-lg border border-brand-purple/30 bg-slate-50 px-3 py-2 font-mono text-sm text-brand-purple select-all">hol-guard start</code>
@@ -515,7 +534,7 @@ function QueueBrowser(props: {
515
534
  className="min-h-11 w-full rounded-lg border border-slate-200 bg-white px-3 text-sm text-brand-dark placeholder:text-slate-400 transition-colors duration-150 focus:border-brand-blue focus:outline-none focus:ring-2 focus:ring-brand-blue/20"
516
535
  />
517
536
  </label>
518
- {harnesses.length > 0 && (
537
+ {harnesses.length >= 2 && (
519
538
  <QueueChipFilter
520
539
  harnesses={harnesses}
521
540
  activeFilter={harnessFilter}
@@ -589,8 +608,8 @@ function QueueCardRow(props: {
589
608
  {props.nextUpItem !== null && (
590
609
  <div className="border-t border-slate-100 bg-slate-50/60 px-4 py-2">
591
610
  <p className="truncate text-[11px] text-muted-foreground">
592
- <span className="font-semibold">Next up:</span>{" "}
593
- {displayArtifactName(props.nextUpItem)}
611
+ <span className="font-semibold">Next:</span>{" "}
612
+ {buildNextUpChipText(props.nextUpItem)}
594
613
  </p>
595
614
  </div>
596
615
  )}
@@ -687,6 +706,7 @@ function DecisionWorkspace(props: {
687
706
  const [errorMessage, setErrorMessage] = useState<string | null>(null);
688
707
  const [confirmPending, setConfirmPending] = useState<"allow" | "block" | null>(null);
689
708
  const [resolvedBanner, setResolvedBanner] = useState<"allow" | "block" | null>(null);
709
+ const [resolvedState, setResolvedState] = useState<"idle" | "decided" | "loaded">("idle");
690
710
  const bannerTimerRef = useRef<ReturnType<typeof setTimeout> | null>(null);
691
711
  const prevRequestIdRef = useRef<string | null>(null);
692
712
 
@@ -696,6 +716,7 @@ function DecisionWorkspace(props: {
696
716
  prevRequestIdRef.current = props.detail.item.request_id;
697
717
  if (isNewItem) {
698
718
  setResolvedBanner(null);
719
+ setResolvedState("loaded");
699
720
  if (bannerTimerRef.current !== null) {
700
721
  clearTimeout(bannerTimerRef.current);
701
722
  bannerTimerRef.current = null;
@@ -731,6 +752,7 @@ function DecisionWorkspace(props: {
731
752
  reason,
732
753
  workspace: scope === "workspace" ? readyWorkspace : undefined,
733
754
  });
755
+ setResolvedState("decided");
734
756
  setResolvedBanner(action);
735
757
  bannerTimerRef.current = setTimeout(() => {
736
758
  setResolvedBanner(null);
@@ -800,6 +822,16 @@ function DecisionWorkspace(props: {
800
822
  if (props.detail.kind === "loading") {
801
823
  return (
802
824
  <div className="space-y-4">
825
+ {resolvedState === "decided" && (
826
+ <div
827
+ className="flex items-center gap-3 rounded-2xl border border-brand-green/25 bg-brand-green-bg/30 px-4 py-3"
828
+ role="status"
829
+ aria-live="polite"
830
+ >
831
+ <HiMiniCheckCircle className="h-4 w-4 shrink-0 text-brand-green" aria-hidden="true" />
832
+ <p className="text-sm font-medium text-brand-green-text">Decided — loading next…</p>
833
+ </div>
834
+ )}
803
835
  <div className="guard-skeleton h-8 w-48" />
804
836
  <div className="guard-skeleton h-40 w-full" />
805
837
  <div className="guard-skeleton h-56 w-full" />
@@ -1,4 +1,4 @@
1
- import type { ChangeEvent, ReactNode } from "react";
1
+ import type { ButtonHTMLAttributes, ChangeEvent, ReactNode } from "react";
2
2
  import {
3
3
  HiMiniArrowTopRightOnSquare,
4
4
  HiMiniCloud,
@@ -92,11 +92,13 @@ export function ShellHeader(props: {
92
92
  <button
93
93
  type="button"
94
94
  onClick={props.onOpenMobileQueue}
95
- aria-label="Open queue list"
95
+ aria-label={`Open queue list — ${props.queuedCount} decisions waiting`}
96
96
  className="inline-flex min-h-11 shrink-0 items-center gap-1.5 rounded-full border border-white/25 bg-white/10 px-3 py-2 text-sm font-semibold text-white no-underline transition-colors duration-150 hover:bg-white/15"
97
97
  >
98
98
  <HiBars3 className="h-4 w-4" aria-hidden="true" />
99
- {props.queuedCount > 99 ? "99+" : props.queuedCount}
99
+ {props.queuedCount > 1
100
+ ? `${props.queuedCount > 99 ? "99+" : props.queuedCount} decisions waiting`
101
+ : props.queuedCount}
100
102
  </button>
101
103
  )}
102
104
  {(!props.onOpenMobileQueue || props.view !== "inbox" || props.queuedCount === 0) && (
@@ -294,29 +296,31 @@ export function EmptyState(props: {
294
296
  );
295
297
  }
296
298
 
297
- export function ActionButton(props: {
299
+ type ActionButtonProps = {
298
300
  children: ReactNode;
299
301
  onClick?: () => void;
300
302
  href?: string;
301
303
  variant?: "primary" | "secondary" | "danger" | "outline" | "ghost" | "success";
302
304
  disabled?: boolean;
303
- }) {
304
- const className = actionButtonClass(props.variant);
305
- if (props.href) {
305
+ } & Omit<ButtonHTMLAttributes<HTMLButtonElement>, "children" | "className" | "onClick" | "type">;
306
+
307
+ export function ActionButton({ children, href, variant, disabled, onClick, ...buttonProps }: ActionButtonProps) {
308
+ const className = actionButtonClass(variant);
309
+ if (href) {
306
310
  return (
307
311
  <a
308
- href={guardAwareHref(props.href)}
309
- target={props.href.startsWith("https://") ? "_blank" : undefined}
310
- rel={props.href.startsWith("https://") ? "noreferrer" : undefined}
312
+ href={guardAwareHref(href)}
313
+ target={href.startsWith("https://") ? "_blank" : undefined}
314
+ rel={href.startsWith("https://") ? "noreferrer" : undefined}
311
315
  className={className}
312
316
  >
313
- {props.children}
317
+ {children}
314
318
  </a>
315
319
  );
316
320
  }
317
321
  return (
318
- <button type="button" className={className} onClick={props.onClick} disabled={props.disabled}>
319
- {props.children}
322
+ <button type="button" className={className} onClick={onClick} disabled={disabled} {...buttonProps}>
323
+ {children}
320
324
  </button>
321
325
  );
322
326
  }
@@ -541,7 +545,7 @@ export function WelcomeState(props: {
541
545
  </div>
542
546
  <h2 className="text-2xl font-semibold tracking-tight text-brand-dark sm:text-3xl">{EMPTY_QUEUE_TITLE}</h2>
543
547
  <p className="mx-auto mt-4 max-w-lg text-[15px] leading-relaxed text-muted-foreground">
544
- Guard is still watching your apps. You'll be notified here if something needs your approval.
548
+ Guard is still watching your apps.
545
549
  </p>
546
550
 
547
551
  <div className="mt-12 text-left w-full max-w-3xl">
@@ -131,12 +131,12 @@ export function buildPauseLine(item: GuardApprovalRequest): string {
131
131
 
132
132
  export function buildRecommendation(item: GuardApprovalRequest): string {
133
133
  if (item.changed_fields.length === 1 && item.changed_fields[0] === "first_seen") {
134
- return "If this is what you expected, approve the exact action. Use broader trust only when you deliberately want Guard to ask less often.";
134
+ return "If this is what you expected, approve this retry. Project approval remembers this same action here without trusting new sensitive actions.";
135
135
  }
136
136
  if (item.policy_action === "block") {
137
137
  return "Keep it blocked unless you are sure this action is safe and expected.";
138
138
  }
139
- return "Approve the smallest choice that matches what you meant to do. Broader trust should be a deliberate second step.";
139
+ return "Approve the smallest choice that matches what you meant to do. Different commands, prompts, paths, hosts, or tools should ask again.";
140
140
  }
141
141
 
142
142
  export function buildQueueSummary(item: GuardApprovalRequest): string {
@@ -162,9 +162,9 @@ export function buildMemorySummary(
162
162
  export function scopeLabel(scope: string): string {
163
163
  switch (scope) {
164
164
  case "artifact":
165
- return "This exact action";
165
+ return "This retry only";
166
166
  case "workspace":
167
- return "This project folder";
167
+ return "Same action in this project";
168
168
  case "publisher":
169
169
  return "This source in this app";
170
170
  case "harness":
@@ -4,6 +4,7 @@ import {
4
4
  HiMiniCheckCircle,
5
5
  HiMiniExclamationCircle,
6
6
  HiMiniMinusCircle,
7
+ HiMiniArrowTopRightOnSquare,
7
8
  } from "react-icons/hi2";
8
9
  import {
9
10
  ActionButton,
@@ -50,6 +51,55 @@ function heroBackgroundClass(status: HomeProtectionStatus): string {
50
51
  return "bg-[radial-gradient(circle_at_top_left,rgba(85,153,254,0.12),transparent_32%),linear-gradient(135deg,#ffffff_0%,#ffffff_58%,rgba(72,223,123,0.10)_100%)]";
51
52
  }
52
53
 
54
+ const KNOWN_HARNESSES = [
55
+ "codex",
56
+ "claude-code",
57
+ "opencode",
58
+ "copilot",
59
+ "gemini",
60
+ "cursor",
61
+ "hermes",
62
+ "openclaw",
63
+ ] as const;
64
+
65
+ type SetupSuggestionRowProps = {
66
+ harness: string;
67
+ };
68
+
69
+ function SetupSuggestionRow(props: SetupSuggestionRowProps) {
70
+ return (
71
+ <li className="flex items-center justify-between gap-3 border-b border-slate-200/70 px-4 py-3 last:border-b-0">
72
+ <p className="text-sm text-brand-dark">
73
+ Set up <span className="font-medium">{harnessDisplayName(props.harness)}</span> →{" "}
74
+ <span className="font-mono text-xs text-brand-blue">
75
+ hol-guard apps connect {props.harness}
76
+ </span>
77
+ </p>
78
+ </li>
79
+ );
80
+ }
81
+
82
+ type SetupSuggestionsSectionProps = {
83
+ configuredHarnesses: string[];
84
+ };
85
+
86
+ function SetupSuggestionsSection(props: SetupSuggestionsSectionProps) {
87
+ const unconfigured = KNOWN_HARNESSES.filter(
88
+ (h) => !props.configuredHarnesses.includes(h)
89
+ );
90
+ if (unconfigured.length === 0) return null;
91
+ return (
92
+ <section className="rounded-[1.75rem] border border-slate-200/70 bg-white/80 p-5 shadow-sm sm:p-6">
93
+ <SectionLabel>Connect more apps</SectionLabel>
94
+ <ul className="mt-3 overflow-hidden rounded-[1.25rem] border border-slate-200/70">
95
+ {unconfigured.slice(0, 4).map((harness) => (
96
+ <SetupSuggestionRow key={harness} harness={harness} />
97
+ ))}
98
+ </ul>
99
+ </section>
100
+ );
101
+ }
102
+
53
103
  function ClearHarnessButton(props: {
54
104
  harness: string;
55
105
  onClearPolicies: (scope: { harness?: string; all?: boolean }) => Promise<void>;
@@ -126,8 +176,6 @@ export function HomeWorkspace(props: {
126
176
  cloudState={snapshot.cloud_state}
127
177
  connectUrl={snapshot.connect_url}
128
178
  fleetUrl={snapshot.fleet_url}
129
- activeInstallsCount={activeInstalls.length}
130
- latestReceiptsCount={snapshot.latest_receipts.length}
131
179
  onOpenInbox={props.onOpenInbox}
132
180
  onOpenFleet={props.onOpenFleet}
133
181
  />
@@ -145,6 +193,10 @@ export function HomeWorkspace(props: {
145
193
  observedHarnesses={observedHarnesses}
146
194
  />
147
195
 
196
+ {primaryState.status === "setup_needed" && (
197
+ <SetupSuggestionsSection configuredHarnesses={observedHarnesses} />
198
+ )}
199
+
148
200
  {snapshot.latest_receipts.length > 0 && (
149
201
  <RecentProtectionSection receipts={snapshot.latest_receipts} />
150
202
  )}
@@ -185,8 +237,6 @@ function ProtectionHero(props: {
185
237
  cloudState: "local_only" | "paired_waiting" | "paired_active";
186
238
  connectUrl: string;
187
239
  fleetUrl: string;
188
- activeInstallsCount: number;
189
- latestReceiptsCount: number;
190
240
  onOpenInbox: () => void;
191
241
  onOpenFleet: () => void;
192
242
  }) {
@@ -211,34 +261,43 @@ function ProtectionHero(props: {
211
261
  const showConnectCta =
212
262
  props.cloudState === "local_only" && !props.syncConfigured;
213
263
 
214
- const showTestProtection =
215
- props.activeInstallsCount > 0 && props.latestReceiptsCount === 0;
264
+ const showGuardCloud = props.cloudState !== "local_only";
216
265
 
217
266
  return (
218
267
  <section
219
268
  className={`guard-surface-in relative overflow-hidden rounded-[2rem] border border-brand-blue/15 ${heroBg} p-5 shadow-[0_20px_60px_rgba(63,65,116,0.08)] sm:p-6 lg:p-7`}
269
+ role="region"
270
+ aria-label="Protection status"
220
271
  >
221
272
  <div className="pointer-events-none absolute right-10 top-8 h-24 w-24 rounded-full bg-brand-blue/20 blur-3xl" />
222
273
  <div className="relative space-y-4">
223
274
  <div className="flex flex-wrap items-center gap-2">
224
275
  <SectionLabel>Protection status</SectionLabel>
225
276
  {statusBadge}
226
- {props.cloudState !== "local_only" && <Tag tone="blue">Cloud synced</Tag>}
277
+ {props.cloudState !== "local_only" && <Tag tone="blue">Cloud backup up to date</Tag>}
227
278
  </div>
228
279
  <h2 className="text-xl font-semibold tracking-tight text-brand-dark">{props.copy}</h2>
229
280
  <div className="flex flex-wrap gap-3">
230
- <ActionButton onClick={handlePrimaryCta}>{props.ctaLabel}</ActionButton>
231
- {showTestProtection && (
232
- <ActionButton href={props.fleetUrl} variant="secondary">
233
- Test protection
234
- </ActionButton>
235
- )}
281
+ <ActionButton onClick={handlePrimaryCta} data-primary="true" aria-label={props.ctaLabel}>
282
+ {props.ctaLabel}
283
+ </ActionButton>
236
284
  {showConnectCta && props.status !== "needs_decision" && (
237
285
  <ActionButton href={props.connectUrl} variant="secondary">
238
286
  Connect this machine
239
287
  </ActionButton>
240
288
  )}
241
289
  </div>
290
+ {showGuardCloud && (
291
+ <a
292
+ href={props.fleetUrl}
293
+ target="_blank"
294
+ rel="noreferrer"
295
+ className="inline-flex items-center gap-1 text-sm font-medium text-brand-blue transition-colors hover:text-brand-blue/70"
296
+ >
297
+ Open Guard Cloud
298
+ <HiMiniArrowTopRightOnSquare className="h-3.5 w-3.5" aria-hidden="true" />
299
+ </a>
300
+ )}
242
301
  </div>
243
302
  </section>
244
303
  );
@@ -1,3 +1,4 @@
1
+ import { useRef, useCallback } from "react";
1
2
  import type { GuardApprovalRequest, GuardQueueResolutionResult } from "./guard-types";
2
3
 
3
4
  export type QueueSortDirection = "newest" | "oldest";
@@ -163,6 +164,29 @@ export function resolveStaleRequestRecovery(
163
164
  return items[0]?.request_id ?? null;
164
165
  }
165
166
 
167
+ export type IsResolvingGuard = {
168
+ isResolvingRef: React.RefObject<boolean>;
169
+ setResolving: (value: boolean) => void;
170
+ };
171
+
172
+ export function useIsResolving(): IsResolvingGuard {
173
+ const isResolvingRef = useRef(false);
174
+ const setResolving = useCallback((value: boolean) => {
175
+ isResolvingRef.current = value;
176
+ }, []);
177
+ return { isResolvingRef, setResolving };
178
+ }
179
+
180
+ export function buildNextUpChipText(item: GuardApprovalRequest): string {
181
+ const envelope = item.action_envelope_json;
182
+ const preview =
183
+ envelope?.command?.slice(0, 40) ??
184
+ envelope?.mcp_tool ??
185
+ envelope?.prompt_excerpt?.slice(0, 40) ??
186
+ item.artifact_type;
187
+ return `${item.harness} — ${preview}`;
188
+ }
189
+
166
190
  export function buildHomePrimaryState(
167
191
  pendingCount: number,
168
192
  watchedAppsCount: number
@@ -120,7 +120,9 @@ function cloudSyncHealthTone(state: GuardCloudSyncHealth["state"]): "blue" | "sl
120
120
 
121
121
  function humanizeCloudSyncHealthLabel(label: string): string {
122
122
  const labels: Record<string, string> = {
123
- "Cloud sync stale": "Your protection history hasn't synced recently",
123
+ "Cloud sync stale": "Cloud backup is out of date",
124
+ "Cloud sync healthy": "Cloud backup up to date",
125
+ "First shared proof": "First cloud backup",
124
126
  };
125
127
  return labels[label] ?? label;
126
128
  }
@@ -131,7 +133,7 @@ function CloudSyncHealthCard(props: { health: GuardCloudSyncHealth }) {
131
133
  <div className="rounded-xl border border-border bg-white px-5 py-4">
132
134
  <div className="flex flex-wrap items-center justify-between gap-2">
133
135
  <p className="text-xs font-semibold uppercase tracking-[0.18em] text-brand-blue">
134
- Cloud sync health
136
+ Guard cloud backup
135
137
  </p>
136
138
  <Tag tone={cloudSyncHealthTone(props.health.state)}>{humanizeCloudSyncHealthLabel(copy.label)}</Tag>
137
139
  </div>
@@ -4,7 +4,7 @@ build-backend = "hatchling.build"
4
4
 
5
5
  [project]
6
6
  name = "plugin-scanner"
7
- version = "2.0.167"
7
+ version = "2.0.169"
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.167"
7
+ version = "2.0.169"
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"
@@ -23,6 +23,13 @@ GUARD_DASHBOARD_URL = "https://hol.org/guard"
23
23
  GUARD_INBOX_URL = f"{GUARD_DASHBOARD_URL}/inbox"
24
24
  GUARD_FLEET_URL = f"{GUARD_DASHBOARD_URL}/fleet"
25
25
  GUARD_CONNECT_URL = f"{GUARD_DASHBOARD_URL}/connect"
26
+ _WORKSPACE_SCOPED_RUNTIME_ARTIFACT_TYPES = frozenset(
27
+ {
28
+ "file_read_request",
29
+ "prompt_request",
30
+ "tool_action_request",
31
+ }
32
+ )
26
33
 
27
34
 
28
35
  class ApprovalRequestNotFoundError(ValueError):
@@ -133,12 +140,13 @@ def apply_approval_resolution(
133
140
  raise ValueError(f"Approval request {request_id} requires --workspace for workspace scope.")
134
141
  if scope == "publisher" and not isinstance(request.get("publisher"), str):
135
142
  raise ValueError(f"Approval request {request_id} has no publisher scope to approve.")
143
+ workspace_artifact_id, workspace_artifact_hash = _workspace_policy_artifact_keys(request, scope)
136
144
  decision = PolicyDecision(
137
145
  harness="*" if scope == "global" else str(request["harness"]),
138
146
  scope=scope,
139
147
  action="allow" if action == "allow" else "block",
140
- artifact_id=str(request["artifact_id"]) if scope == "artifact" else None,
141
- artifact_hash=str(request["artifact_hash"]) if scope == "artifact" else None,
148
+ artifact_id=str(request["artifact_id"]) if scope == "artifact" else workspace_artifact_id,
149
+ artifact_hash=str(request["artifact_hash"]) if scope == "artifact" else workspace_artifact_hash,
142
150
  workspace=workspace if scope == "workspace" else None,
143
151
  publisher=str(request["publisher"]) if scope == "publisher" else None,
144
152
  reason=reason,
@@ -164,7 +172,7 @@ def apply_approval_resolution(
164
172
  resolved_scope_ids = store.resolve_matching_approval_requests(
165
173
  harness=resolution_harness,
166
174
  scope=scope,
167
- artifact_id=str(request["artifact_id"]) if scope == "artifact" else None,
175
+ artifact_id=str(request["artifact_id"]) if scope == "artifact" else workspace_artifact_id,
168
176
  workspace=workspace if scope == "workspace" else None,
169
177
  publisher=(
170
178
  str(request["publisher"])
@@ -184,7 +192,7 @@ def apply_approval_resolution(
184
192
  resolved_ids = store.resolve_matching_approval_requests(
185
193
  harness=resolution_harness,
186
194
  scope=scope,
187
- artifact_id=str(request["artifact_id"]) if scope == "artifact" else None,
195
+ artifact_id=str(request["artifact_id"]) if scope == "artifact" else workspace_artifact_id,
188
196
  workspace=workspace if scope == "workspace" else None,
189
197
  publisher=(
190
198
  str(request["publisher"])
@@ -210,6 +218,18 @@ def apply_approval_resolution(
210
218
  return updated
211
219
 
212
220
 
221
+ def _workspace_policy_artifact_keys(request: Mapping[str, object], scope: str) -> tuple[str | None, str | None]:
222
+ if scope != "workspace" or request.get("artifact_type") not in _WORKSPACE_SCOPED_RUNTIME_ARTIFACT_TYPES:
223
+ return None, None
224
+ artifact_id = request.get("artifact_id")
225
+ artifact_hash = request.get("artifact_hash")
226
+ if not isinstance(artifact_id, str) or not artifact_id:
227
+ return None, None
228
+ if not isinstance(artifact_hash, str) or not artifact_hash:
229
+ return artifact_id, None
230
+ return artifact_id, artifact_hash
231
+
232
+
213
233
  def _refresh_queue_result(
214
234
  store: GuardStore,
215
235
  result: dict[str, object],
@@ -3399,6 +3399,13 @@ def _runtime_stored_policy_action(
3399
3399
  and scope in {"workspace", "publisher", "harness", "global"}
3400
3400
  and _runtime_artifact_risk_classes(artifact)
3401
3401
  ):
3402
+ if scope == "workspace":
3403
+ decision_artifact_id = _optional_string(decision.get("artifact_id"))
3404
+ decision_artifact_hash = _optional_string(decision.get("artifact_hash"))
3405
+ if decision_artifact_id == artifact_id and (
3406
+ decision_artifact_hash is None or decision_artifact_hash == artifact_hash
3407
+ ):
3408
+ return action
3402
3409
  return None
3403
3410
  return action
3404
3411