runlayer 0.31.2__tar.gz → 0.31.3__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 (871) hide show
  1. {runlayer-0.31.2 → runlayer-0.31.3}/AGENTS.md +1 -0
  2. {runlayer-0.31.2 → runlayer-0.31.3}/PKG-INFO +1 -1
  3. {runlayer-0.31.2 → runlayer-0.31.3}/pyproject.toml +1 -1
  4. {runlayer-0.31.2 → runlayer-0.31.3}/runlayer_cli/commands/aiwatch_config.py +22 -1
  5. {runlayer-0.31.2 → runlayer-0.31.3}/runlayer_cli/commands/scan.py +41 -0
  6. {runlayer-0.31.2 → runlayer-0.31.3}/runlayer_cli/commands/setup.py +1 -1
  7. {runlayer-0.31.2 → runlayer-0.31.3}/runlayer_cli/error_classification.py +4 -16
  8. {runlayer-0.31.2 → runlayer-0.31.3}/runlayer_cli/flow_contract.py +19 -0
  9. {runlayer-0.31.2 → runlayer-0.31.3}/runlayer_cli/hook/clients.py +2 -2
  10. {runlayer-0.31.2 → runlayer-0.31.3}/runlayer_cli/hook/dispatch.py +55 -23
  11. runlayer-0.31.3/runlayer_cli/hook/failure.py +205 -0
  12. {runlayer-0.31.2 → runlayer-0.31.3}/runlayer_cli/hook/messages.py +102 -12
  13. {runlayer-0.31.2 → runlayer-0.31.3}/runlayer_cli/hook/plugin_context.py +6 -5
  14. {runlayer-0.31.2 → runlayer-0.31.3}/runlayer_cli/hook/relay.py +18 -3
  15. {runlayer-0.31.2 → runlayer-0.31.3}/runlayer_cli/hook_install/clients.py +1 -1
  16. {runlayer-0.31.2 → runlayer-0.31.3}/runlayer_cli/main.py +36 -2
  17. {runlayer-0.31.2 → runlayer-0.31.3}/runlayer_cli/scan/launcher_inspection.py +1 -1
  18. {runlayer-0.31.2 → runlayer-0.31.3}/runlayer_cli/scan/service.py +150 -9
  19. runlayer-0.31.3/tests/fixtures/managed_secret_display_cases.json +26 -0
  20. {runlayer-0.31.2 → runlayer-0.31.3}/tests/test_aiwatch_config_command.py +65 -15
  21. {runlayer-0.31.2 → runlayer-0.31.3}/tests/test_cli.py +168 -8
  22. {runlayer-0.31.2 → runlayer-0.31.3}/tests/test_daemon_runtime.py +28 -9
  23. {runlayer-0.31.2 → runlayer-0.31.3}/tests/test_hook_credential_rejection.py +144 -20
  24. runlayer-0.31.3/tests/test_hook_failure_origin.py +168 -0
  25. {runlayer-0.31.2 → runlayer-0.31.3}/tests/test_hook_flow.py +33 -0
  26. {runlayer-0.31.2 → runlayer-0.31.3}/tests/test_hook_install_module.py +18 -0
  27. {runlayer-0.31.2 → runlayer-0.31.3}/tests/test_hook_messages.py +92 -0
  28. {runlayer-0.31.2 → runlayer-0.31.3}/tests/test_hook_plugin_context.py +32 -16
  29. runlayer-0.31.3/tests/test_main_stdio_env.py +112 -0
  30. runlayer-0.31.3/tests/test_main_stdio_env_spawn.py +70 -0
  31. {runlayer-0.31.2 → runlayer-0.31.3}/tests/test_scan_service.py +167 -0
  32. {runlayer-0.31.2 → runlayer-0.31.3}/tests/test_scan_skills.py +93 -3
  33. runlayer-0.31.2/runlayer_cli/hook/failure.py +0 -80
  34. {runlayer-0.31.2 → runlayer-0.31.3}/.gitignore +0 -0
  35. {runlayer-0.31.2 → runlayer-0.31.3}/.python-version +0 -0
  36. {runlayer-0.31.2 → runlayer-0.31.3}/CLAUDE.md +0 -0
  37. {runlayer-0.31.2 → runlayer-0.31.3}/LICENSE +0 -0
  38. {runlayer-0.31.2 → runlayer-0.31.3}/Makefile +0 -0
  39. {runlayer-0.31.2 → runlayer-0.31.3}/README.md +0 -0
  40. {runlayer-0.31.2 → runlayer-0.31.3}/development.md +0 -0
  41. {runlayer-0.31.2 → runlayer-0.31.3}/hooks/README.md +0 -0
  42. {runlayer-0.31.2 → runlayer-0.31.3}/hooks/__init__.py +0 -0
  43. {runlayer-0.31.2 → runlayer-0.31.3}/hooks/debug_hook_binary.py +0 -0
  44. {runlayer-0.31.2 → runlayer-0.31.3}/hooks/runlayer-hook.sh +0 -0
  45. {runlayer-0.31.2 → runlayer-0.31.3}/packaging/DEPLOYMENT.md +0 -0
  46. {runlayer-0.31.2 → runlayer-0.31.3}/packaging/README.md +0 -0
  47. {runlayer-0.31.2 → runlayer-0.31.3}/packaging/_version_file.py +0 -0
  48. {runlayer-0.31.2 → runlayer-0.31.3}/packaging/aiwatch.spec +0 -0
  49. {runlayer-0.31.2 → runlayer-0.31.3}/packaging/aiwatch_uninstall.spec +0 -0
  50. {runlayer-0.31.2 → runlayer-0.31.3}/packaging/assets/aiwatch-icon-512.png +0 -0
  51. {runlayer-0.31.2 → runlayer-0.31.3}/packaging/assets/aiwatch.ico +0 -0
  52. {runlayer-0.31.2 → runlayer-0.31.3}/packaging/container/Dockerfile +0 -0
  53. {runlayer-0.31.2 → runlayer-0.31.3}/packaging/container/Dockerfile.dockerignore +0 -0
  54. {runlayer-0.31.2 → runlayer-0.31.3}/packaging/container/k8s/README.md +0 -0
  55. {runlayer-0.31.2 → runlayer-0.31.3}/packaging/container/k8s/configmap.yaml +0 -0
  56. {runlayer-0.31.2 → runlayer-0.31.3}/packaging/container/k8s/cronjob.yaml +0 -0
  57. {runlayer-0.31.2 → runlayer-0.31.3}/packaging/container/k8s/daemonset.yaml +0 -0
  58. {runlayer-0.31.2 → runlayer-0.31.3}/packaging/container/k8s/kustomization.yaml +0 -0
  59. {runlayer-0.31.2 → runlayer-0.31.3}/packaging/container/k8s/namespace.yaml +0 -0
  60. {runlayer-0.31.2 → runlayer-0.31.3}/packaging/container/k8s/secret.example.yaml +0 -0
  61. {runlayer-0.31.2 → runlayer-0.31.3}/packaging/container/scan-host-users.sh +0 -0
  62. {runlayer-0.31.2 → runlayer-0.31.3}/packaging/container/tests/README.md +0 -0
  63. {runlayer-0.31.2 → runlayer-0.31.3}/packaging/container/tests/assert_inside_container.sh +0 -0
  64. {runlayer-0.31.2 → runlayer-0.31.3}/packaging/container/tests/run_smoke_test.sh +0 -0
  65. {runlayer-0.31.2 → runlayer-0.31.3}/packaging/container/tests/stub-aiwatch.sh +0 -0
  66. {runlayer-0.31.2 → runlayer-0.31.3}/packaging/install/install.ps1 +0 -0
  67. {runlayer-0.31.2 → runlayer-0.31.3}/packaging/install/install.sh +0 -0
  68. {runlayer-0.31.2 → runlayer-0.31.3}/packaging/install/tests/Install.Tests.ps1 +0 -0
  69. {runlayer-0.31.2 → runlayer-0.31.3}/packaging/install/tests/Invoke-Tests.ps1 +0 -0
  70. {runlayer-0.31.2 → runlayer-0.31.3}/packaging/install/tests/fixtures/targets-glibc2.17.json +0 -0
  71. {runlayer-0.31.2 → runlayer-0.31.3}/packaging/install/tests/fixtures/targets.json +0 -0
  72. {runlayer-0.31.2 → runlayer-0.31.3}/packaging/install/tests/test_install_sh.sh +0 -0
  73. {runlayer-0.31.2 → runlayer-0.31.3}/packaging/linux/aiwatch-config.json +0 -0
  74. {runlayer-0.31.2 → runlayer-0.31.3}/packaging/linux/aiwatch-credentials.example +0 -0
  75. {runlayer-0.31.2 → runlayer-0.31.3}/packaging/linux/build_aiwatch_packages.sh +0 -0
  76. {runlayer-0.31.2 → runlayer-0.31.3}/packaging/linux/build_onedir_manylinux.sh +0 -0
  77. {runlayer-0.31.2 → runlayer-0.31.3}/packaging/linux/build_packages.sh +0 -0
  78. {runlayer-0.31.2 → runlayer-0.31.3}/packaging/linux/cron.d-runlayer-aiwatch +0 -0
  79. {runlayer-0.31.2 → runlayer-0.31.3}/packaging/linux/cron.d-runlayer-cli +0 -0
  80. {runlayer-0.31.2 → runlayer-0.31.3}/packaging/linux/nfpm-aiwatch.yaml +0 -0
  81. {runlayer-0.31.2 → runlayer-0.31.3}/packaging/linux/nfpm.yaml +0 -0
  82. {runlayer-0.31.2 → runlayer-0.31.3}/packaging/linux/run-aiwatch-scan.sh +0 -0
  83. {runlayer-0.31.2 → runlayer-0.31.3}/packaging/linux/run-aiwatch-update.sh +0 -0
  84. {runlayer-0.31.2 → runlayer-0.31.3}/packaging/linux/run-cli-schedule.sh +0 -0
  85. {runlayer-0.31.2 → runlayer-0.31.3}/packaging/linux/run-cli-update.sh +0 -0
  86. {runlayer-0.31.2 → runlayer-0.31.3}/packaging/linux/salt/README.md +0 -0
  87. {runlayer-0.31.2 → runlayer-0.31.3}/packaging/linux/salt/pillar.example.sls +0 -0
  88. {runlayer-0.31.2 → runlayer-0.31.3}/packaging/linux/salt/runlayer-aiwatch/init.sls +0 -0
  89. {runlayer-0.31.2 → runlayer-0.31.3}/packaging/linux/salt/runlayer-aiwatch/templates/config.json.jinja +0 -0
  90. {runlayer-0.31.2 → runlayer-0.31.3}/packaging/linux/salt/runlayer-aiwatch/templates/credentials.jinja +0 -0
  91. {runlayer-0.31.2 → runlayer-0.31.3}/packaging/linux/tests/README.md +0 -0
  92. {runlayer-0.31.2 → runlayer-0.31.3}/packaging/linux/tests/assert_inside_container.sh +0 -0
  93. {runlayer-0.31.2 → runlayer-0.31.3}/packaging/linux/tests/build_stub_packages.sh +0 -0
  94. {runlayer-0.31.2 → runlayer-0.31.3}/packaging/linux/tests/check_package_markers.sh +0 -0
  95. {runlayer-0.31.2 → runlayer-0.31.3}/packaging/linux/tests/ensure_host_nfpm.sh +0 -0
  96. {runlayer-0.31.2 → runlayer-0.31.3}/packaging/linux/tests/run_smoke_tests.sh +0 -0
  97. {runlayer-0.31.2 → runlayer-0.31.3}/packaging/linux/tests/test_variant_suffix.sh +0 -0
  98. {runlayer-0.31.2 → runlayer-0.31.3}/packaging/macos/adopt_keychain.sh +0 -0
  99. {runlayer-0.31.2 → runlayer-0.31.3}/packaging/macos/build_pkg.sh +0 -0
  100. {runlayer-0.31.2 → runlayer-0.31.3}/packaging/macos/build_pkg_runlayer.sh +0 -0
  101. {runlayer-0.31.2 → runlayer-0.31.3}/packaging/macos/build_uninstall_pkg.sh +0 -0
  102. {runlayer-0.31.2 → runlayer-0.31.3}/packaging/macos/com.runlayer.aiwatch.bootstrap.plist +0 -0
  103. {runlayer-0.31.2 → runlayer-0.31.3}/packaging/macos/com.runlayer.aiwatch.daemon.plist +0 -0
  104. {runlayer-0.31.2 → runlayer-0.31.3}/packaging/macos/com.runlayer.aiwatch.enroll.plist +0 -0
  105. {runlayer-0.31.2 → runlayer-0.31.3}/packaging/macos/com.runlayer.aiwatch.firefox-native-messaging-host.json +0 -0
  106. {runlayer-0.31.2 → runlayer-0.31.3}/packaging/macos/com.runlayer.aiwatch.jamf.schema.json +0 -0
  107. {runlayer-0.31.2 → runlayer-0.31.3}/packaging/macos/com.runlayer.aiwatch.mobileconfig +0 -0
  108. {runlayer-0.31.2 → runlayer-0.31.3}/packaging/macos/com.runlayer.aiwatch.native-messaging-host.json +0 -0
  109. {runlayer-0.31.2 → runlayer-0.31.3}/packaging/macos/com.runlayer.aiwatch.plist +0 -0
  110. {runlayer-0.31.2 → runlayer-0.31.3}/packaging/macos/com.runlayer.aiwatch.update.plist +0 -0
  111. {runlayer-0.31.2 → runlayer-0.31.3}/packaging/macos/com.runlayer.aiwatch.ws1.mobileconfig +0 -0
  112. {runlayer-0.31.2 → runlayer-0.31.3}/packaging/macos/com.runlayer.cli.mobileconfig +0 -0
  113. {runlayer-0.31.2 → runlayer-0.31.3}/packaging/macos/com.runlayer.cli.schedule.plist +0 -0
  114. {runlayer-0.31.2 → runlayer-0.31.3}/packaging/macos/com.runlayer.cli.update.plist +0 -0
  115. {runlayer-0.31.2 → runlayer-0.31.3}/packaging/macos/distribution.runlayer.xml +0 -0
  116. {runlayer-0.31.2 → runlayer-0.31.3}/packaging/macos/distribution.xml +0 -0
  117. {runlayer-0.31.2 → runlayer-0.31.3}/packaging/macos/entitlements.plist +0 -0
  118. {runlayer-0.31.2 → runlayer-0.31.3}/packaging/macos/scripts/postinstall +0 -0
  119. {runlayer-0.31.2 → runlayer-0.31.3}/packaging/macos/scripts/postinstall-runlayer +0 -0
  120. {runlayer-0.31.2 → runlayer-0.31.3}/packaging/macos/scripts/preinstall +0 -0
  121. {runlayer-0.31.2 → runlayer-0.31.3}/packaging/macos/scripts/preinstall-runlayer +0 -0
  122. {runlayer-0.31.2 → runlayer-0.31.3}/packaging/macos/uninstall-pkg/postinstall +0 -0
  123. {runlayer-0.31.2 → runlayer-0.31.3}/packaging/macos/uninstall-runlayer.sh +0 -0
  124. {runlayer-0.31.2 → runlayer-0.31.3}/packaging/macos/uninstall.sh +0 -0
  125. {runlayer-0.31.2 → runlayer-0.31.3}/packaging/py2exe/setup_py2exe.py +0 -0
  126. {runlayer-0.31.2 → runlayer-0.31.3}/packaging/runlayer.spec +0 -0
  127. {runlayer-0.31.2 → runlayer-0.31.3}/packaging/windows/aiwatch-native-messaging-host.bat +0 -0
  128. {runlayer-0.31.2 → runlayer-0.31.3}/packaging/windows/aiwatch.wxs +0 -0
  129. {runlayer-0.31.2 → runlayer-0.31.3}/packaging/windows/build_hook_shim.ps1 +0 -0
  130. {runlayer-0.31.2 → runlayer-0.31.3}/packaging/windows/build_intunewin.ps1 +0 -0
  131. {runlayer-0.31.2 → runlayer-0.31.3}/packaging/windows/build_intunewin_runlayer.ps1 +0 -0
  132. {runlayer-0.31.2 → runlayer-0.31.3}/packaging/windows/build_msi.ps1 +0 -0
  133. {runlayer-0.31.2 → runlayer-0.31.3}/packaging/windows/build_msi_runlayer.ps1 +0 -0
  134. {runlayer-0.31.2 → runlayer-0.31.3}/packaging/windows/cli-schedule-task/register-tasks.ps1 +0 -0
  135. {runlayer-0.31.2 → runlayer-0.31.3}/packaging/windows/cli-schedule-task/unregister-tasks.ps1 +0 -0
  136. {runlayer-0.31.2 → runlayer-0.31.3}/packaging/windows/cli-update-task/register-tasks.ps1 +0 -0
  137. {runlayer-0.31.2 → runlayer-0.31.3}/packaging/windows/cli-update-task/unregister-tasks.ps1 +0 -0
  138. {runlayer-0.31.2 → runlayer-0.31.3}/packaging/windows/custom-detection/detect-install.ps1 +0 -0
  139. {runlayer-0.31.2 → runlayer-0.31.3}/packaging/windows/custom-detection/tests/DetectInstall.Tests.ps1 +0 -0
  140. {runlayer-0.31.2 → runlayer-0.31.3}/packaging/windows/custom-detection/tests/Invoke-Tests.ps1 +0 -0
  141. {runlayer-0.31.2 → runlayer-0.31.3}/packaging/windows/handoff-exec-test/emit_handoff_script.py +0 -0
  142. {runlayer-0.31.2 → runlayer-0.31.3}/packaging/windows/handoff-exec-test/run-handoff-exec-test.ps1 +0 -0
  143. {runlayer-0.31.2 → runlayer-0.31.3}/packaging/windows/native-host-chromium.json +0 -0
  144. {runlayer-0.31.2 → runlayer-0.31.3}/packaging/windows/native-host-firefox.json +0 -0
  145. {runlayer-0.31.2 → runlayer-0.31.3}/packaging/windows/runlayer.wxs +0 -0
  146. {runlayer-0.31.2 → runlayer-0.31.3}/packaging/windows/scheduled-task/RunlayerTaskCommon.ps1 +0 -0
  147. {runlayer-0.31.2 → runlayer-0.31.3}/packaging/windows/scheduled-task/register-tasks.ps1 +0 -0
  148. {runlayer-0.31.2 → runlayer-0.31.3}/packaging/windows/scheduled-task/remove-hooks.ps1 +0 -0
  149. {runlayer-0.31.2 → runlayer-0.31.3}/packaging/windows/scheduled-task/tests/CliScheduleTasks.Tests.ps1 +0 -0
  150. {runlayer-0.31.2 → runlayer-0.31.3}/packaging/windows/scheduled-task/tests/CliUpdateTasks.Tests.ps1 +0 -0
  151. {runlayer-0.31.2 → runlayer-0.31.3}/packaging/windows/scheduled-task/tests/Invoke-Tests.ps1 +0 -0
  152. {runlayer-0.31.2 → runlayer-0.31.3}/packaging/windows/scheduled-task/tests/RemoveHooks.Tests.ps1 +0 -0
  153. {runlayer-0.31.2 → runlayer-0.31.3}/packaging/windows/scheduled-task/tests/ScheduledTasks.Tests.ps1 +0 -0
  154. {runlayer-0.31.2 → runlayer-0.31.3}/packaging/windows/scheduled-task/unregister-tasks.ps1 +0 -0
  155. {runlayer-0.31.2 → runlayer-0.31.3}/packaging/windows/scripts/bootstrap.ps1 +0 -0
  156. {runlayer-0.31.2 → runlayer-0.31.3}/regex-engine-allowlist.txt +0 -0
  157. {runlayer-0.31.2 → runlayer-0.31.3}/runlayer_cli/__init__.py +0 -0
  158. {runlayer-0.31.2 → runlayer-0.31.3}/runlayer_cli/aiwatch.py +0 -0
  159. {runlayer-0.31.2 → runlayer-0.31.3}/runlayer_cli/aiwatch_checkin.py +0 -0
  160. {runlayer-0.31.2 → runlayer-0.31.3}/runlayer_cli/aiwatch_config_cache.py +0 -0
  161. {runlayer-0.31.2 → runlayer-0.31.3}/runlayer_cli/aiwatch_config_sync.py +0 -0
  162. {runlayer-0.31.2 → runlayer-0.31.3}/runlayer_cli/aiwatch_credential.py +0 -0
  163. {runlayer-0.31.2 → runlayer-0.31.3}/runlayer_cli/aiwatch_uninstall.py +0 -0
  164. {runlayer-0.31.2 → runlayer-0.31.3}/runlayer_cli/api.py +0 -0
  165. {runlayer-0.31.2 → runlayer-0.31.3}/runlayer_cli/catalog_client.py +0 -0
  166. {runlayer-0.31.2 → runlayer-0.31.3}/runlayer_cli/catalog_enrichment.py +0 -0
  167. {runlayer-0.31.2 → runlayer-0.31.3}/runlayer_cli/cli_persistence.py +0 -0
  168. {runlayer-0.31.2 → runlayer-0.31.3}/runlayer_cli/command_contract.py +0 -0
  169. {runlayer-0.31.2 → runlayer-0.31.3}/runlayer_cli/command_metrics.py +0 -0
  170. {runlayer-0.31.2 → runlayer-0.31.3}/runlayer_cli/commands/__init__.py +0 -0
  171. {runlayer-0.31.2 → runlayer-0.31.3}/runlayer_cli/commands/aiwatch_setup.py +0 -0
  172. {runlayer-0.31.2 → runlayer-0.31.3}/runlayer_cli/commands/aiwatch_update.py +0 -0
  173. {runlayer-0.31.2 → runlayer-0.31.3}/runlayer_cli/commands/auth.py +0 -0
  174. {runlayer-0.31.2 → runlayer-0.31.3}/runlayer_cli/commands/bootstrap.py +0 -0
  175. {runlayer-0.31.2 → runlayer-0.31.3}/runlayer_cli/commands/cache.py +0 -0
  176. {runlayer-0.31.2 → runlayer-0.31.3}/runlayer_cli/commands/catalog/__init__.py +0 -0
  177. {runlayer-0.31.2 → runlayer-0.31.3}/runlayer_cli/commands/catalog/commands.py +0 -0
  178. {runlayer-0.31.2 → runlayer-0.31.3}/runlayer_cli/commands/catalog/display.py +0 -0
  179. {runlayer-0.31.2 → runlayer-0.31.3}/runlayer_cli/commands/catalog/kinds.py +0 -0
  180. {runlayer-0.31.2 → runlayer-0.31.3}/runlayer_cli/commands/catalog/resolve.py +0 -0
  181. {runlayer-0.31.2 → runlayer-0.31.3}/runlayer_cli/commands/cli_update.py +0 -0
  182. {runlayer-0.31.2 → runlayer-0.31.3}/runlayer_cli/commands/credentials.py +0 -0
  183. {runlayer-0.31.2 → runlayer-0.31.3}/runlayer_cli/commands/decide_approval.py +0 -0
  184. {runlayer-0.31.2 → runlayer-0.31.3}/runlayer_cli/commands/deploy.py +0 -0
  185. {runlayer-0.31.2 → runlayer-0.31.3}/runlayer_cli/commands/doctor.py +0 -0
  186. {runlayer-0.31.2 → runlayer-0.31.3}/runlayer_cli/commands/enroll.py +0 -0
  187. {runlayer-0.31.2 → runlayer-0.31.3}/runlayer_cli/commands/hooks.py +0 -0
  188. {runlayer-0.31.2 → runlayer-0.31.3}/runlayer_cli/commands/interactive_find.py +0 -0
  189. {runlayer-0.31.2 → runlayer-0.31.3}/runlayer_cli/commands/keychain.py +0 -0
  190. {runlayer-0.31.2 → runlayer-0.31.3}/runlayer_cli/commands/logs.py +0 -0
  191. {runlayer-0.31.2 → runlayer-0.31.3}/runlayer_cli/commands/org_api_key.py +0 -0
  192. {runlayer-0.31.2 → runlayer-0.31.3}/runlayer_cli/commands/plugins.py +0 -0
  193. {runlayer-0.31.2 → runlayer-0.31.3}/runlayer_cli/commands/reconnect_account.py +0 -0
  194. {runlayer-0.31.2 → runlayer-0.31.3}/runlayer_cli/commands/reject_access_request.py +0 -0
  195. {runlayer-0.31.2 → runlayer-0.31.3}/runlayer_cli/commands/schedule.py +0 -0
  196. {runlayer-0.31.2 → runlayer-0.31.3}/runlayer_cli/commands/skills.py +0 -0
  197. {runlayer-0.31.2 → runlayer-0.31.3}/runlayer_cli/commands/status.py +0 -0
  198. {runlayer-0.31.2 → runlayer-0.31.3}/runlayer_cli/commands/terraform.py +0 -0
  199. {runlayer-0.31.2 → runlayer-0.31.3}/runlayer_cli/commands/update.py +0 -0
  200. {runlayer-0.31.2 → runlayer-0.31.3}/runlayer_cli/commands/update_privilege.py +0 -0
  201. {runlayer-0.31.2 → runlayer-0.31.3}/runlayer_cli/commands/update_scheduler.py +0 -0
  202. {runlayer-0.31.2 → runlayer-0.31.3}/runlayer_cli/commands/url_handler.py +0 -0
  203. {runlayer-0.31.2 → runlayer-0.31.3}/runlayer_cli/config.py +0 -0
  204. {runlayer-0.31.2 → runlayer-0.31.3}/runlayer_cli/console.py +0 -0
  205. {runlayer-0.31.2 → runlayer-0.31.3}/runlayer_cli/credential_store.py +0 -0
  206. {runlayer-0.31.2 → runlayer-0.31.3}/runlayer_cli/daemon/__init__.py +0 -0
  207. {runlayer-0.31.2 → runlayer-0.31.3}/runlayer_cli/daemon/runtime.py +0 -0
  208. {runlayer-0.31.2 → runlayer-0.31.3}/runlayer_cli/daemon/server.py +0 -0
  209. {runlayer-0.31.2 → runlayer-0.31.3}/runlayer_cli/daemon/status.py +0 -0
  210. {runlayer-0.31.2 → runlayer-0.31.3}/runlayer_cli/daemon/windows_pipe.py +0 -0
  211. {runlayer-0.31.2 → runlayer-0.31.3}/runlayer_cli/daemon/windows_scm.py +0 -0
  212. {runlayer-0.31.2 → runlayer-0.31.3}/runlayer_cli/daemon/windows_service.py +0 -0
  213. {runlayer-0.31.2 → runlayer-0.31.3}/runlayer_cli/deploy/__init__.py +0 -0
  214. {runlayer-0.31.2 → runlayer-0.31.3}/runlayer_cli/deploy/config.py +0 -0
  215. {runlayer-0.31.2 → runlayer-0.31.3}/runlayer_cli/deploy/docker_builder.py +0 -0
  216. {runlayer-0.31.2 → runlayer-0.31.3}/runlayer_cli/deploy/schema_validation.py +0 -0
  217. {runlayer-0.31.2 → runlayer-0.31.3}/runlayer_cli/deploy/service.py +0 -0
  218. {runlayer-0.31.2 → runlayer-0.31.3}/runlayer_cli/enrollment.py +0 -0
  219. {runlayer-0.31.2 → runlayer-0.31.3}/runlayer_cli/env_substitution.py +0 -0
  220. {runlayer-0.31.2 → runlayer-0.31.3}/runlayer_cli/flow_delivery.py +0 -0
  221. {runlayer-0.31.2 → runlayer-0.31.3}/runlayer_cli/flow_spool.py +0 -0
  222. {runlayer-0.31.2 → runlayer-0.31.3}/runlayer_cli/flow_summary.py +0 -0
  223. {runlayer-0.31.2 → runlayer-0.31.3}/runlayer_cli/flow_trace.py +0 -0
  224. {runlayer-0.31.2 → runlayer-0.31.3}/runlayer_cli/hook/__init__.py +0 -0
  225. {runlayer-0.31.2 → runlayer-0.31.3}/runlayer_cli/hook/__main__.py +0 -0
  226. {runlayer-0.31.2 → runlayer-0.31.3}/runlayer_cli/hook/_transcript_stream_worker.py +0 -0
  227. {runlayer-0.31.2 → runlayer-0.31.3}/runlayer_cli/hook/copilot_cli_mcp_lookup.py +0 -0
  228. {runlayer-0.31.2 → runlayer-0.31.3}/runlayer_cli/hook/credential_state.py +0 -0
  229. {runlayer-0.31.2 → runlayer-0.31.3}/runlayer_cli/hook/daemon_client.py +0 -0
  230. {runlayer-0.31.2 → runlayer-0.31.3}/runlayer_cli/hook/daemon_protocol.py +0 -0
  231. {runlayer-0.31.2 → runlayer-0.31.3}/runlayer_cli/hook/file_policy.py +0 -0
  232. {runlayer-0.31.2 → runlayer-0.31.3}/runlayer_cli/hook/hook_io.py +0 -0
  233. {runlayer-0.31.2 → runlayer-0.31.3}/runlayer_cli/hook/host_override.py +0 -0
  234. {runlayer-0.31.2 → runlayer-0.31.3}/runlayer_cli/hook/log_silence.py +0 -0
  235. {runlayer-0.31.2 → runlayer-0.31.3}/runlayer_cli/hook/mcp_lookup.py +0 -0
  236. {runlayer-0.31.2 → runlayer-0.31.3}/runlayer_cli/hook/mcp_types.py +0 -0
  237. {runlayer-0.31.2 → runlayer-0.31.3}/runlayer_cli/hook/transcript_stream.py +0 -0
  238. {runlayer-0.31.2 → runlayer-0.31.3}/runlayer_cli/hook/windsurf_payload.py +0 -0
  239. {runlayer-0.31.2 → runlayer-0.31.3}/runlayer_cli/hook_install/__init__.py +0 -0
  240. {runlayer-0.31.2 → runlayer-0.31.3}/runlayer_cli/hook_install/artifact_paths.py +0 -0
  241. {runlayer-0.31.2 → runlayer-0.31.3}/runlayer_cli/hook_install/browser_extension.py +0 -0
  242. {runlayer-0.31.2 → runlayer-0.31.3}/runlayer_cli/hook_install/browser_extensions.py +0 -0
  243. {runlayer-0.31.2 → runlayer-0.31.3}/runlayer_cli/hook_install/browser_policy.py +0 -0
  244. {runlayer-0.31.2 → runlayer-0.31.3}/runlayer_cli/hook_install/check.py +0 -0
  245. {runlayer-0.31.2 → runlayer-0.31.3}/runlayer_cli/hook_install/chromium_profile_health.py +0 -0
  246. {runlayer-0.31.2 → runlayer-0.31.3}/runlayer_cli/hook_install/config_backup.py +0 -0
  247. {runlayer-0.31.2 → runlayer-0.31.3}/runlayer_cli/hook_install/console_user.py +0 -0
  248. {runlayer-0.31.2 → runlayer-0.31.3}/runlayer_cli/hook_install/credential_gate.py +0 -0
  249. {runlayer-0.31.2 → runlayer-0.31.3}/runlayer_cli/hook_install/daemon_lifecycle.py +0 -0
  250. {runlayer-0.31.2 → runlayer-0.31.3}/runlayer_cli/hook_install/edge_extension.py +0 -0
  251. {runlayer-0.31.2 → runlayer-0.31.3}/runlayer_cli/hook_install/firefox_extension.py +0 -0
  252. {runlayer-0.31.2 → runlayer-0.31.3}/runlayer_cli/hook_install/llm_routing.py +0 -0
  253. {runlayer-0.31.2 → runlayer-0.31.3}/runlayer_cli/hook_install/paths.py +0 -0
  254. {runlayer-0.31.2 → runlayer-0.31.3}/runlayer_cli/hook_install/presence.py +0 -0
  255. {runlayer-0.31.2 → runlayer-0.31.3}/runlayer_cli/hook_install/safe_fs.py +0 -0
  256. {runlayer-0.31.2 → runlayer-0.31.3}/runlayer_cli/hook_install/windows_browser_policy.py +0 -0
  257. {runlayer-0.31.2 → runlayer-0.31.3}/runlayer_cli/http_error_utils.py +0 -0
  258. {runlayer-0.31.2 → runlayer-0.31.3}/runlayer_cli/identity_forward.py +0 -0
  259. {runlayer-0.31.2 → runlayer-0.31.3}/runlayer_cli/index.html +0 -0
  260. {runlayer-0.31.2 → runlayer-0.31.3}/runlayer_cli/install_window.py +0 -0
  261. {runlayer-0.31.2 → runlayer-0.31.3}/runlayer_cli/installer_common.py +0 -0
  262. {runlayer-0.31.2 → runlayer-0.31.3}/runlayer_cli/linux_installer.py +0 -0
  263. {runlayer-0.31.2 → runlayer-0.31.3}/runlayer_cli/logging.py +0 -0
  264. {runlayer-0.31.2 → runlayer-0.31.3}/runlayer_cli/macos_installer.py +0 -0
  265. {runlayer-0.31.2 → runlayer-0.31.3}/runlayer_cli/macos_test_device_config.py +0 -0
  266. {runlayer-0.31.2 → runlayer-0.31.3}/runlayer_cli/managed_policy_publication.py +0 -0
  267. {runlayer-0.31.2 → runlayer-0.31.3}/runlayer_cli/mdm_config.py +0 -0
  268. {runlayer-0.31.2 → runlayer-0.31.3}/runlayer_cli/metrics.py +0 -0
  269. {runlayer-0.31.2 → runlayer-0.31.3}/runlayer_cli/metrics_flush.py +0 -0
  270. {runlayer-0.31.2 → runlayer-0.31.3}/runlayer_cli/middleware.py +0 -0
  271. {runlayer-0.31.2 → runlayer-0.31.3}/runlayer_cli/models.py +0 -0
  272. {runlayer-0.31.2 → runlayer-0.31.3}/runlayer_cli/models_api.py +0 -0
  273. {runlayer-0.31.2 → runlayer-0.31.3}/runlayer_cli/models_mcp.py +0 -0
  274. {runlayer-0.31.2 → runlayer-0.31.3}/runlayer_cli/native_messaging.py +0 -0
  275. {runlayer-0.31.2 → runlayer-0.31.3}/runlayer_cli/oauth.py +0 -0
  276. {runlayer-0.31.2 → runlayer-0.31.3}/runlayer_cli/oauth_callback.py +0 -0
  277. {runlayer-0.31.2 → runlayer-0.31.3}/runlayer_cli/oauth_guidance.py +0 -0
  278. {runlayer-0.31.2 → runlayer-0.31.3}/runlayer_cli/paths.py +0 -0
  279. {runlayer-0.31.2 → runlayer-0.31.3}/runlayer_cli/platform_installers.py +0 -0
  280. {runlayer-0.31.2 → runlayer-0.31.3}/runlayer_cli/plugins/__init__.py +0 -0
  281. {runlayer-0.31.2 → runlayer-0.31.3}/runlayer_cli/plugins/claude_manifest.py +0 -0
  282. {runlayer-0.31.2 → runlayer-0.31.3}/runlayer_cli/plugins/constants.py +0 -0
  283. {runlayer-0.31.2 → runlayer-0.31.3}/runlayer_cli/plugins/discovery.py +0 -0
  284. {runlayer-0.31.2 → runlayer-0.31.3}/runlayer_cli/plugins/installer.py +0 -0
  285. {runlayer-0.31.2 → runlayer-0.31.3}/runlayer_cli/plugins/layouts.py +0 -0
  286. {runlayer-0.31.2 → runlayer-0.31.3}/runlayer_cli/plugins/models.py +0 -0
  287. {runlayer-0.31.2 → runlayer-0.31.3}/runlayer_cli/plugins/sync_engine.py +0 -0
  288. {runlayer-0.31.2 → runlayer-0.31.3}/runlayer_cli/product.py +0 -0
  289. {runlayer-0.31.2 → runlayer-0.31.3}/runlayer_cli/regex_safe.py +0 -0
  290. {runlayer-0.31.2 → runlayer-0.31.3}/runlayer_cli/runtime.py +0 -0
  291. {runlayer-0.31.2 → runlayer-0.31.3}/runlayer_cli/safe_parse.py +0 -0
  292. {runlayer-0.31.2 → runlayer-0.31.3}/runlayer_cli/scan/__init__.py +0 -0
  293. {runlayer-0.31.2 → runlayer-0.31.3}/runlayer_cli/scan/agent_definition_scanner.py +0 -0
  294. {runlayer-0.31.2 → runlayer-0.31.3}/runlayer_cli/scan/agent_scan.py +0 -0
  295. {runlayer-0.31.2 → runlayer-0.31.3}/runlayer_cli/scan/agents/__init__.py +0 -0
  296. {runlayer-0.31.2 → runlayer-0.31.3}/runlayer_cli/scan/agents/detect.py +0 -0
  297. {runlayer-0.31.2 → runlayer-0.31.3}/runlayer_cli/scan/agents/discover.py +0 -0
  298. {runlayer-0.31.2 → runlayer-0.31.3}/runlayer_cli/scan/agents/install.py +0 -0
  299. {runlayer-0.31.2 → runlayer-0.31.3}/runlayer_cli/scan/agents/languages.py +0 -0
  300. {runlayer-0.31.2 → runlayer-0.31.3}/runlayer_cli/scan/agents/manifests/__init__.py +0 -0
  301. {runlayer-0.31.2 → runlayer-0.31.3}/runlayer_cli/scan/agents/manifests/_common.py +0 -0
  302. {runlayer-0.31.2 → runlayer-0.31.3}/runlayer_cli/scan/agents/manifests/cargo.py +0 -0
  303. {runlayer-0.31.2 → runlayer-0.31.3}/runlayer_cli/scan/agents/manifests/dotnet.py +0 -0
  304. {runlayer-0.31.2 → runlayer-0.31.3}/runlayer_cli/scan/agents/manifests/go.py +0 -0
  305. {runlayer-0.31.2 → runlayer-0.31.3}/runlayer_cli/scan/agents/manifests/jvm.py +0 -0
  306. {runlayer-0.31.2 → runlayer-0.31.3}/runlayer_cli/scan/agents/manifests/npm.py +0 -0
  307. {runlayer-0.31.2 → runlayer-0.31.3}/runlayer_cli/scan/agents/manifests/python.py +0 -0
  308. {runlayer-0.31.2 → runlayer-0.31.3}/runlayer_cli/scan/agents/openclaw_detector.py +0 -0
  309. {runlayer-0.31.2 → runlayer-0.31.3}/runlayer_cli/scan/agents/redact.py +0 -0
  310. {runlayer-0.31.2 → runlayer-0.31.3}/runlayer_cli/scan/agents/registry.py +0 -0
  311. {runlayer-0.31.2 → runlayer-0.31.3}/runlayer_cli/scan/agents/report.py +0 -0
  312. {runlayer-0.31.2 → runlayer-0.31.3}/runlayer_cli/scan/agents/signatures.json +0 -0
  313. {runlayer-0.31.2 → runlayer-0.31.3}/runlayer_cli/scan/artifact_cache.py +0 -0
  314. {runlayer-0.31.2 → runlayer-0.31.3}/runlayer_cli/scan/bin_shims.py +0 -0
  315. {runlayer-0.31.2 → runlayer-0.31.3}/runlayer_cli/scan/claude_code_plugins.py +0 -0
  316. {runlayer-0.31.2 → runlayer-0.31.3}/runlayer_cli/scan/cli_binaries.py +0 -0
  317. {runlayer-0.31.2 → runlayer-0.31.3}/runlayer_cli/scan/client_presence.py +0 -0
  318. {runlayer-0.31.2 → runlayer-0.31.3}/runlayer_cli/scan/clients.py +0 -0
  319. {runlayer-0.31.2 → runlayer-0.31.3}/runlayer_cli/scan/codex_plugins.py +0 -0
  320. {runlayer-0.31.2 → runlayer-0.31.3}/runlayer_cli/scan/completeness.py +0 -0
  321. {runlayer-0.31.2 → runlayer-0.31.3}/runlayer_cli/scan/concurrency.py +0 -0
  322. {runlayer-0.31.2 → runlayer-0.31.3}/runlayer_cli/scan/config_parser.py +0 -0
  323. {runlayer-0.31.2 → runlayer-0.31.3}/runlayer_cli/scan/config_redact.py +0 -0
  324. {runlayer-0.31.2 → runlayer-0.31.3}/runlayer_cli/scan/container_command.py +0 -0
  325. {runlayer-0.31.2 → runlayer-0.31.3}/runlayer_cli/scan/container_limits.py +0 -0
  326. {runlayer-0.31.2 → runlayer-0.31.3}/runlayer_cli/scan/containers/__init__.py +0 -0
  327. {runlayer-0.31.2 → runlayer-0.31.3}/runlayer_cli/scan/containers/collect.py +0 -0
  328. {runlayer-0.31.2 → runlayer-0.31.3}/runlayer_cli/scan/containers/collector.py +0 -0
  329. {runlayer-0.31.2 → runlayer-0.31.3}/runlayer_cli/scan/containers/docker_cli.py +0 -0
  330. {runlayer-0.31.2 → runlayer-0.31.3}/runlayer_cli/scan/containers/docker_socket.py +0 -0
  331. {runlayer-0.31.2 → runlayer-0.31.3}/runlayer_cli/scan/containers/inspect_parse.py +0 -0
  332. {runlayer-0.31.2 → runlayer-0.31.3}/runlayer_cli/scan/containers/k3s_cli.py +0 -0
  333. {runlayer-0.31.2 → runlayer-0.31.3}/runlayer_cli/scan/containers/proc_walk.py +0 -0
  334. {runlayer-0.31.2 → runlayer-0.31.3}/runlayer_cli/scan/containers/tar_walk.py +0 -0
  335. {runlayer-0.31.2 → runlayer-0.31.3}/runlayer_cli/scan/containers/windows_named_pipe.py +0 -0
  336. {runlayer-0.31.2 → runlayer-0.31.3}/runlayer_cli/scan/copilot_plugins.py +0 -0
  337. {runlayer-0.31.2 → runlayer-0.31.3}/runlayer_cli/scan/cursor_plugins.py +0 -0
  338. {runlayer-0.31.2 → runlayer-0.31.3}/runlayer_cli/scan/device.py +0 -0
  339. {runlayer-0.31.2 → runlayer-0.31.3}/runlayer_cli/scan/disguised_skills.py +0 -0
  340. {runlayer-0.31.2 → runlayer-0.31.3}/runlayer_cli/scan/file_collector.py +0 -0
  341. {runlayer-0.31.2 → runlayer-0.31.3}/runlayer_cli/scan/gemini_extensions.py +0 -0
  342. {runlayer-0.31.2 → runlayer-0.31.3}/runlayer_cli/scan/hidden_space_sweep.py +0 -0
  343. {runlayer-0.31.2 → runlayer-0.31.3}/runlayer_cli/scan/jetbrains_plugins.py +0 -0
  344. {runlayer-0.31.2 → runlayer-0.31.3}/runlayer_cli/scan/npm_global.py +0 -0
  345. {runlayer-0.31.2 → runlayer-0.31.3}/runlayer_cli/scan/opencode_plugins.py +0 -0
  346. {runlayer-0.31.2 → runlayer-0.31.3}/runlayer_cli/scan/orchestrator.py +0 -0
  347. {runlayer-0.31.2 → runlayer-0.31.3}/runlayer_cli/scan/pip_global.py +0 -0
  348. {runlayer-0.31.2 → runlayer-0.31.3}/runlayer_cli/scan/plugin_scanner.py +0 -0
  349. {runlayer-0.31.2 → runlayer-0.31.3}/runlayer_cli/scan/processes/__init__.py +0 -0
  350. {runlayer-0.31.2 → runlayer-0.31.3}/runlayer_cli/scan/processes/classify.py +0 -0
  351. {runlayer-0.31.2 → runlayer-0.31.3}/runlayer_cli/scan/processes/enumerate.py +0 -0
  352. {runlayer-0.31.2 → runlayer-0.31.3}/runlayer_cli/scan/processes/models.py +0 -0
  353. {runlayer-0.31.2 → runlayer-0.31.3}/runlayer_cli/scan/processes/probes.py +0 -0
  354. {runlayer-0.31.2 → runlayer-0.31.3}/runlayer_cli/scan/processes/redact.py +0 -0
  355. {runlayer-0.31.2 → runlayer-0.31.3}/runlayer_cli/scan/processes/settings_override.py +0 -0
  356. {runlayer-0.31.2 → runlayer-0.31.3}/runlayer_cli/scan/processes/windows_owner.py +0 -0
  357. {runlayer-0.31.2 → runlayer-0.31.3}/runlayer_cli/scan/project_scanner.py +0 -0
  358. {runlayer-0.31.2 → runlayer-0.31.3}/runlayer_cli/scan/project_tree_match.py +0 -0
  359. {runlayer-0.31.2 → runlayer-0.31.3}/runlayer_cli/scan/renamed_plugin_caches.py +0 -0
  360. {runlayer-0.31.2 → runlayer-0.31.3}/runlayer_cli/scan/resource_governor.py +0 -0
  361. {runlayer-0.31.2 → runlayer-0.31.3}/runlayer_cli/scan/run_lock.py +0 -0
  362. {runlayer-0.31.2 → runlayer-0.31.3}/runlayer_cli/scan/scan_state.py +0 -0
  363. {runlayer-0.31.2 → runlayer-0.31.3}/runlayer_cli/scan/scanner_primitives.py +0 -0
  364. {runlayer-0.31.2 → runlayer-0.31.3}/runlayer_cli/scan/skill_presence.py +0 -0
  365. {runlayer-0.31.2 → runlayer-0.31.3}/runlayer_cli/scan/skill_scanner.py +0 -0
  366. {runlayer-0.31.2 → runlayer-0.31.3}/runlayer_cli/scan/skip_dirs.py +0 -0
  367. {runlayer-0.31.2 → runlayer-0.31.3}/runlayer_cli/scan/symlink_follow.py +0 -0
  368. {runlayer-0.31.2 → runlayer-0.31.3}/runlayer_cli/scan/symlink_identity.py +0 -0
  369. {runlayer-0.31.2 → runlayer-0.31.3}/runlayer_cli/scan/timing.py +0 -0
  370. {runlayer-0.31.2 → runlayer-0.31.3}/runlayer_cli/scan/vscode_extensions.py +0 -0
  371. {runlayer-0.31.2 → runlayer-0.31.3}/runlayer_cli/scan/warp_sqlite.py +0 -0
  372. {runlayer-0.31.2 → runlayer-0.31.3}/runlayer_cli/scan/windows_users.py +0 -0
  373. {runlayer-0.31.2 → runlayer-0.31.3}/runlayer_cli/scan/wsl_exec.py +0 -0
  374. {runlayer-0.31.2 → runlayer-0.31.3}/runlayer_cli/scan/wsl_limits.py +0 -0
  375. {runlayer-0.31.2 → runlayer-0.31.3}/runlayer_cli/scan/wsl_paths.py +0 -0
  376. {runlayer-0.31.2 → runlayer-0.31.3}/runlayer_cli/scan/wsl_presence.py +0 -0
  377. {runlayer-0.31.2 → runlayer-0.31.3}/runlayer_cli/scan/wsl_projects.py +0 -0
  378. {runlayer-0.31.2 → runlayer-0.31.3}/runlayer_cli/scan/wsl_runtime_signals.py +0 -0
  379. {runlayer-0.31.2 → runlayer-0.31.3}/runlayer_cli/skill_identifier/AGENTS.md +0 -0
  380. {runlayer-0.31.2 → runlayer-0.31.3}/runlayer_cli/skill_identifier/CLAUDE.md +0 -0
  381. {runlayer-0.31.2 → runlayer-0.31.3}/runlayer_cli/skill_identifier/README.md +0 -0
  382. {runlayer-0.31.2 → runlayer-0.31.3}/runlayer_cli/skill_identifier/__init__.py +0 -0
  383. {runlayer-0.31.2 → runlayer-0.31.3}/runlayer_cli/skill_identifier/hashing.py +0 -0
  384. {runlayer-0.31.2 → runlayer-0.31.3}/runlayer_cli/skill_identifier/merkle.py +0 -0
  385. {runlayer-0.31.2 → runlayer-0.31.3}/runlayer_cli/skill_identifier/skill_id.py +0 -0
  386. {runlayer-0.31.2 → runlayer-0.31.3}/runlayer_cli/skill_identifier/types.py +0 -0
  387. {runlayer-0.31.2 → runlayer-0.31.3}/runlayer_cli/skills/__init__.py +0 -0
  388. {runlayer-0.31.2 → runlayer-0.31.3}/runlayer_cli/skills/device_sync.py +0 -0
  389. {runlayer-0.31.2 → runlayer-0.31.3}/runlayer_cli/skills/discovery.py +0 -0
  390. {runlayer-0.31.2 → runlayer-0.31.3}/runlayer_cli/skills/frontmatter.py +0 -0
  391. {runlayer-0.31.2 → runlayer-0.31.3}/runlayer_cli/skills/installer.py +0 -0
  392. {runlayer-0.31.2 → runlayer-0.31.3}/runlayer_cli/skills/installer_core.py +0 -0
  393. {runlayer-0.31.2 → runlayer-0.31.3}/runlayer_cli/skills/marker.py +0 -0
  394. {runlayer-0.31.2 → runlayer-0.31.3}/runlayer_cli/skills/models.py +0 -0
  395. {runlayer-0.31.2 → runlayer-0.31.3}/runlayer_cli/skills/names.py +0 -0
  396. {runlayer-0.31.2 → runlayer-0.31.3}/runlayer_cli/skills/scan_summary.py +0 -0
  397. {runlayer-0.31.2 → runlayer-0.31.3}/runlayer_cli/skills/sync_engine.py +0 -0
  398. {runlayer-0.31.2 → runlayer-0.31.3}/runlayer_cli/symbols.py +0 -0
  399. {runlayer-0.31.2 → runlayer-0.31.3}/runlayer_cli/sync.py +0 -0
  400. {runlayer-0.31.2 → runlayer-0.31.3}/runlayer_cli/telemetry.py +0 -0
  401. {runlayer-0.31.2 → runlayer-0.31.3}/runlayer_cli/terraform_export.py +0 -0
  402. {runlayer-0.31.2 → runlayer-0.31.3}/runlayer_cli/tls.py +0 -0
  403. {runlayer-0.31.2 → runlayer-0.31.3}/runlayer_cli/tolerant_json.py +0 -0
  404. {runlayer-0.31.2 → runlayer-0.31.3}/runlayer_cli/truststore_init.py +0 -0
  405. {runlayer-0.31.2 → runlayer-0.31.3}/runlayer_cli/update_contract.py +0 -0
  406. {runlayer-0.31.2 → runlayer-0.31.3}/runlayer_cli/update_source.py +0 -0
  407. {runlayer-0.31.2 → runlayer-0.31.3}/runlayer_cli/updater.py +0 -0
  408. {runlayer-0.31.2 → runlayer-0.31.3}/runlayer_cli/uuid_utils.py +0 -0
  409. {runlayer-0.31.2 → runlayer-0.31.3}/runlayer_cli/uv_tool_cleanup.py +0 -0
  410. {runlayer-0.31.2 → runlayer-0.31.3}/runlayer_cli/variant.py +0 -0
  411. {runlayer-0.31.2 → runlayer-0.31.3}/runlayer_cli/verified_local_proxy/README.md +0 -0
  412. {runlayer-0.31.2 → runlayer-0.31.3}/runlayer_cli/verified_local_proxy/__init__.py +0 -0
  413. {runlayer-0.31.2 → runlayer-0.31.3}/runlayer_cli/verified_local_proxy/config.py +0 -0
  414. {runlayer-0.31.2 → runlayer-0.31.3}/runlayer_cli/verified_local_proxy/exceptions.py +0 -0
  415. {runlayer-0.31.2 → runlayer-0.31.3}/runlayer_cli/verified_local_proxy/proxy.py +0 -0
  416. {runlayer-0.31.2 → runlayer-0.31.3}/runlayer_cli/verified_local_proxy/verification/__init__.py +0 -0
  417. {runlayer-0.31.2 → runlayer-0.31.3}/runlayer_cli/verified_local_proxy/verification/base.py +0 -0
  418. {runlayer-0.31.2 → runlayer-0.31.3}/runlayer_cli/verified_local_proxy/verification/macos.py +0 -0
  419. {runlayer-0.31.2 → runlayer-0.31.3}/runlayer_cli/verified_local_proxy/verification/windows.py +0 -0
  420. {runlayer-0.31.2 → runlayer-0.31.3}/runlayer_cli/windows_installer.py +0 -0
  421. {runlayer-0.31.2 → runlayer-0.31.3}/runlayer_cli/windows_installer_verifier.py +0 -0
  422. {runlayer-0.31.2 → runlayer-0.31.3}/runlayer_cli/windows_update_handoff.py +0 -0
  423. {runlayer-0.31.2 → runlayer-0.31.3}/scripts/check_published_hook_transport.py +0 -0
  424. {runlayer-0.31.2 → runlayer-0.31.3}/scripts/check_regex_engine.py +0 -0
  425. {runlayer-0.31.2 → runlayer-0.31.3}/scripts/smoke_installed_hooks.py +0 -0
  426. {runlayer-0.31.2 → runlayer-0.31.3}/tests/conftest.py +0 -0
  427. {runlayer-0.31.2 → runlayer-0.31.3}/tests/daemon_frame_helpers.py +0 -0
  428. {runlayer-0.31.2 → runlayer-0.31.3}/tests/e2e/__init__.py +0 -0
  429. {runlayer-0.31.2 → runlayer-0.31.3}/tests/e2e/cache/__init__.py +0 -0
  430. {runlayer-0.31.2 → runlayer-0.31.3}/tests/e2e/cache/test_cache.py +0 -0
  431. {runlayer-0.31.2 → runlayer-0.31.3}/tests/e2e/conftest.py +0 -0
  432. {runlayer-0.31.2 → runlayer-0.31.3}/tests/e2e/credentials/__init__.py +0 -0
  433. {runlayer-0.31.2 → runlayer-0.31.3}/tests/e2e/credentials/test_credentials.py +0 -0
  434. {runlayer-0.31.2 → runlayer-0.31.3}/tests/e2e/deploy/__init__.py +0 -0
  435. {runlayer-0.31.2 → runlayer-0.31.3}/tests/e2e/deploy/test_lifecycle.py +0 -0
  436. {runlayer-0.31.2 → runlayer-0.31.3}/tests/e2e/deploy/test_validate.py +0 -0
  437. {runlayer-0.31.2 → runlayer-0.31.3}/tests/e2e/fixtures/client_specs/antigravity.md +0 -0
  438. {runlayer-0.31.2 → runlayer-0.31.3}/tests/e2e/fixtures/client_specs/claude_code.md +0 -0
  439. {runlayer-0.31.2 → runlayer-0.31.3}/tests/e2e/fixtures/client_specs/claude_desktop.md +0 -0
  440. {runlayer-0.31.2 → runlayer-0.31.3}/tests/e2e/fixtures/client_specs/cline.md +0 -0
  441. {runlayer-0.31.2 → runlayer-0.31.3}/tests/e2e/fixtures/client_specs/cline_cli.md +0 -0
  442. {runlayer-0.31.2 → runlayer-0.31.3}/tests/e2e/fixtures/client_specs/codex.md +0 -0
  443. {runlayer-0.31.2 → runlayer-0.31.3}/tests/e2e/fixtures/client_specs/cursor.md +0 -0
  444. {runlayer-0.31.2 → runlayer-0.31.3}/tests/e2e/fixtures/client_specs/gemini_cli.md +0 -0
  445. {runlayer-0.31.2 → runlayer-0.31.3}/tests/e2e/fixtures/client_specs/github_copilot_cli.md +0 -0
  446. {runlayer-0.31.2 → runlayer-0.31.3}/tests/e2e/fixtures/client_specs/goose.md +0 -0
  447. {runlayer-0.31.2 → runlayer-0.31.3}/tests/e2e/fixtures/client_specs/opencode.md +0 -0
  448. {runlayer-0.31.2 → runlayer-0.31.3}/tests/e2e/fixtures/client_specs/vscode.md +0 -0
  449. {runlayer-0.31.2 → runlayer-0.31.3}/tests/e2e/fixtures/client_specs/windsurf.md +0 -0
  450. {runlayer-0.31.2 → runlayer-0.31.3}/tests/e2e/fixtures/client_specs/zed.md +0 -0
  451. {runlayer-0.31.2 → runlayer-0.31.3}/tests/e2e/fixtures/full_plugin/.claude-plugin/marketplace.json +0 -0
  452. {runlayer-0.31.2 → runlayer-0.31.3}/tests/e2e/fixtures/full_plugin/.claude-plugin/plugin.json +0 -0
  453. {runlayer-0.31.2 → runlayer-0.31.3}/tests/e2e/fixtures/full_plugin/.lsp.json +0 -0
  454. {runlayer-0.31.2 → runlayer-0.31.3}/tests/e2e/fixtures/full_plugin/.mcp.json +0 -0
  455. {runlayer-0.31.2 → runlayer-0.31.3}/tests/e2e/fixtures/full_plugin/README.md +0 -0
  456. {runlayer-0.31.2 → runlayer-0.31.3}/tests/e2e/fixtures/full_plugin/agents/README.md +0 -0
  457. {runlayer-0.31.2 → runlayer-0.31.3}/tests/e2e/fixtures/full_plugin/agents/code-reviewer.md +0 -0
  458. {runlayer-0.31.2 → runlayer-0.31.3}/tests/e2e/fixtures/full_plugin/commands/review.md +0 -0
  459. {runlayer-0.31.2 → runlayer-0.31.3}/tests/e2e/fixtures/full_plugin/config.json +0 -0
  460. {runlayer-0.31.2 → runlayer-0.31.3}/tests/e2e/fixtures/full_plugin/hooks/hooks.json +0 -0
  461. {runlayer-0.31.2 → runlayer-0.31.3}/tests/e2e/fixtures/full_plugin/hooks/validate.sh +0 -0
  462. {runlayer-0.31.2 → runlayer-0.31.3}/tests/e2e/fixtures/full_plugin/notes.txt +0 -0
  463. {runlayer-0.31.2 → runlayer-0.31.3}/tests/e2e/fixtures/full_plugin/scripts/deploy.sh +0 -0
  464. {runlayer-0.31.2 → runlayer-0.31.3}/tests/e2e/fixtures/full_plugin/settings.json +0 -0
  465. {runlayer-0.31.2 → runlayer-0.31.3}/tests/e2e/fixtures/full_plugin/skills/code-review/SKILL.md +0 -0
  466. {runlayer-0.31.2 → runlayer-0.31.3}/tests/e2e/fixtures/full_plugin/skills/code-review/prompts.md +0 -0
  467. {runlayer-0.31.2 → runlayer-0.31.3}/tests/e2e/fixtures/full_plugin/skills/ticket-triage/SKILL.md +0 -0
  468. {runlayer-0.31.2 → runlayer-0.31.3}/tests/e2e/fixtures/full_plugin/skills/ticket-triage/helper.py +0 -0
  469. {runlayer-0.31.2 → runlayer-0.31.3}/tests/e2e/fixtures/full_plugin/skills-v2/notes.md +0 -0
  470. {runlayer-0.31.2 → runlayer-0.31.3}/tests/e2e/fixtures/full_plugin/skillsets/reference.md +0 -0
  471. {runlayer-0.31.2 → runlayer-0.31.3}/tests/e2e/fixtures/full_plugin/tool.ts +0 -0
  472. {runlayer-0.31.2 → runlayer-0.31.3}/tests/e2e/hooks/__init__.py +0 -0
  473. {runlayer-0.31.2 → runlayer-0.31.3}/tests/e2e/hooks/test_install_hooks.py +0 -0
  474. {runlayer-0.31.2 → runlayer-0.31.3}/tests/e2e/hooks/test_relay.py +0 -0
  475. {runlayer-0.31.2 → runlayer-0.31.3}/tests/e2e/org_api_key/__init__.py +0 -0
  476. {runlayer-0.31.2 → runlayer-0.31.3}/tests/e2e/org_api_key/test_org_api_key.py +0 -0
  477. {runlayer-0.31.2 → runlayer-0.31.3}/tests/e2e/plugins/__init__.py +0 -0
  478. {runlayer-0.31.2 → runlayer-0.31.3}/tests/e2e/plugins/test_add.py +0 -0
  479. {runlayer-0.31.2 → runlayer-0.31.3}/tests/e2e/plugins/test_mcp_fallback.py +0 -0
  480. {runlayer-0.31.2 → runlayer-0.31.3}/tests/e2e/plugins/test_push.py +0 -0
  481. {runlayer-0.31.2 → runlayer-0.31.3}/tests/e2e/run/__init__.py +0 -0
  482. {runlayer-0.31.2 → runlayer-0.31.3}/tests/e2e/run/test_run.py +0 -0
  483. {runlayer-0.31.2 → runlayer-0.31.3}/tests/e2e/scan/__init__.py +0 -0
  484. {runlayer-0.31.2 → runlayer-0.31.3}/tests/e2e/scan/conftest.py +0 -0
  485. {runlayer-0.31.2 → runlayer-0.31.3}/tests/e2e/scan/test_scan.py +0 -0
  486. {runlayer-0.31.2 → runlayer-0.31.3}/tests/e2e/scan/test_scan_lock_isolation.py +0 -0
  487. {runlayer-0.31.2 → runlayer-0.31.3}/tests/e2e/scan/test_scan_submit.py +0 -0
  488. {runlayer-0.31.2 → runlayer-0.31.3}/tests/e2e/setup/test_install_opencode.py +0 -0
  489. {runlayer-0.31.2 → runlayer-0.31.3}/tests/e2e/skills/__init__.py +0 -0
  490. {runlayer-0.31.2 → runlayer-0.31.3}/tests/e2e/skills/test_lifecycle.py +0 -0
  491. {runlayer-0.31.2 → runlayer-0.31.3}/tests/e2e/terraform/__init__.py +0 -0
  492. {runlayer-0.31.2 → runlayer-0.31.3}/tests/e2e/test_help_matrix.py +0 -0
  493. {runlayer-0.31.2 → runlayer-0.31.3}/tests/e2e/version/__init__.py +0 -0
  494. {runlayer-0.31.2 → runlayer-0.31.3}/tests/e2e/version/test_version.py +0 -0
  495. {runlayer-0.31.2 → runlayer-0.31.3}/tests/fixtures/agent_detection/labels.json +0 -0
  496. {runlayer-0.31.2 → runlayer-0.31.3}/tests/fixtures/agent_detection/non_agent/debug_adapter/adapter.py +0 -0
  497. {runlayer-0.31.2 → runlayer-0.31.3}/tests/fixtures/agent_detection/non_agent/debug_adapter/pyproject.toml +0 -0
  498. {runlayer-0.31.2 → runlayer-0.31.3}/tests/fixtures/agent_detection/non_agent/flask_api/app.py +0 -0
  499. {runlayer-0.31.2 → runlayer-0.31.3}/tests/fixtures/agent_detection/non_agent/flask_api/requirements.txt +0 -0
  500. {runlayer-0.31.2 → runlayer-0.31.3}/tests/fixtures/agent_detection/non_agent/go_cli/go.mod +0 -0
  501. {runlayer-0.31.2 → runlayer-0.31.3}/tests/fixtures/agent_detection/non_agent/go_cli/main.go +0 -0
  502. {runlayer-0.31.2 → runlayer-0.31.3}/tests/fixtures/agent_detection/non_agent/node_web/package.json +0 -0
  503. {runlayer-0.31.2 → runlayer-0.31.3}/tests/fixtures/agent_detection/non_agent/node_web/server.js +0 -0
  504. {runlayer-0.31.2 → runlayer-0.31.3}/tests/fixtures/agent_detection/samples/sample_01/agent.py +0 -0
  505. {runlayer-0.31.2 → runlayer-0.31.3}/tests/fixtures/agent_detection/samples/sample_01/pyproject.toml +0 -0
  506. {runlayer-0.31.2 → runlayer-0.31.3}/tests/fixtures/agent_detection/samples/sample_02/agent.py +0 -0
  507. {runlayer-0.31.2 → runlayer-0.31.3}/tests/fixtures/agent_detection/samples/sample_02/pyproject.toml +0 -0
  508. {runlayer-0.31.2 → runlayer-0.31.3}/tests/fixtures/agent_detection/samples/sample_03/agent.py +0 -0
  509. {runlayer-0.31.2 → runlayer-0.31.3}/tests/fixtures/agent_detection/samples/sample_03/pyproject.toml +0 -0
  510. {runlayer-0.31.2 → runlayer-0.31.3}/tests/fixtures/agent_detection/samples/sample_04/agent.py +0 -0
  511. {runlayer-0.31.2 → runlayer-0.31.3}/tests/fixtures/agent_detection/samples/sample_04/pyproject.toml +0 -0
  512. {runlayer-0.31.2 → runlayer-0.31.3}/tests/fixtures/agent_detection/samples/sample_05/agent.py +0 -0
  513. {runlayer-0.31.2 → runlayer-0.31.3}/tests/fixtures/agent_detection/samples/sample_05/pyproject.toml +0 -0
  514. {runlayer-0.31.2 → runlayer-0.31.3}/tests/fixtures/agent_detection/samples/sample_06/agent.py +0 -0
  515. {runlayer-0.31.2 → runlayer-0.31.3}/tests/fixtures/agent_detection/samples/sample_06/pyproject.toml +0 -0
  516. {runlayer-0.31.2 → runlayer-0.31.3}/tests/fixtures/agent_detection/samples/sample_07/agent.py +0 -0
  517. {runlayer-0.31.2 → runlayer-0.31.3}/tests/fixtures/agent_detection/samples/sample_07/pyproject.toml +0 -0
  518. {runlayer-0.31.2 → runlayer-0.31.3}/tests/fixtures/agent_detection/samples/sample_08/agent.py +0 -0
  519. {runlayer-0.31.2 → runlayer-0.31.3}/tests/fixtures/agent_detection/samples/sample_08/pyproject.toml +0 -0
  520. {runlayer-0.31.2 → runlayer-0.31.3}/tests/fixtures/agent_detection/samples/sample_09/agent.ts +0 -0
  521. {runlayer-0.31.2 → runlayer-0.31.3}/tests/fixtures/agent_detection/samples/sample_09/package.json +0 -0
  522. {runlayer-0.31.2 → runlayer-0.31.3}/tests/fixtures/agent_detection/samples/sample_10/agent.ts +0 -0
  523. {runlayer-0.31.2 → runlayer-0.31.3}/tests/fixtures/agent_detection/samples/sample_10/package.json +0 -0
  524. {runlayer-0.31.2 → runlayer-0.31.3}/tests/fixtures/agent_detection/samples/sample_11/agent.ts +0 -0
  525. {runlayer-0.31.2 → runlayer-0.31.3}/tests/fixtures/agent_detection/samples/sample_11/package.json +0 -0
  526. {runlayer-0.31.2 → runlayer-0.31.3}/tests/fixtures/agent_detection/samples/sample_12/agent.ts +0 -0
  527. {runlayer-0.31.2 → runlayer-0.31.3}/tests/fixtures/agent_detection/samples/sample_12/package.json +0 -0
  528. {runlayer-0.31.2 → runlayer-0.31.3}/tests/fixtures/agent_detection/samples/sample_13/Cargo.toml +0 -0
  529. {runlayer-0.31.2 → runlayer-0.31.3}/tests/fixtures/agent_detection/samples/sample_13/main.rs +0 -0
  530. {runlayer-0.31.2 → runlayer-0.31.3}/tests/fixtures/agent_detection/samples/sample_14/go.mod +0 -0
  531. {runlayer-0.31.2 → runlayer-0.31.3}/tests/fixtures/agent_detection/samples/sample_14/main.go +0 -0
  532. {runlayer-0.31.2 → runlayer-0.31.3}/tests/fixtures/agent_detection/samples/sample_15/Main.java +0 -0
  533. {runlayer-0.31.2 → runlayer-0.31.3}/tests/fixtures/agent_detection/samples/sample_15/pom.xml +0 -0
  534. {runlayer-0.31.2 → runlayer-0.31.3}/tests/fixtures/agent_detection/samples/sample_16/Main.java +0 -0
  535. {runlayer-0.31.2 → runlayer-0.31.3}/tests/fixtures/agent_detection/samples/sample_16/pom.xml +0 -0
  536. {runlayer-0.31.2 → runlayer-0.31.3}/tests/fixtures/agent_detection/samples/sample_17/Program.cs +0 -0
  537. {runlayer-0.31.2 → runlayer-0.31.3}/tests/fixtures/agent_detection/samples/sample_17/SemanticKernelAgent.csproj +0 -0
  538. {runlayer-0.31.2 → runlayer-0.31.3}/tests/fixtures/agent_detection/samples/sample_18/package.json +0 -0
  539. {runlayer-0.31.2 → runlayer-0.31.3}/tests/fixtures/agent_detection/samples/sample_18/server.ts +0 -0
  540. {runlayer-0.31.2 → runlayer-0.31.3}/tests/fixtures/claude_code_config.json +0 -0
  541. {runlayer-0.31.2 → runlayer-0.31.3}/tests/fixtures/claude_desktop_config.json +0 -0
  542. {runlayer-0.31.2 → runlayer-0.31.3}/tests/fixtures/container_command_cases.json +0 -0
  543. {runlayer-0.31.2 → runlayer-0.31.3}/tests/fixtures/container_label_normalization_cases.json +0 -0
  544. {runlayer-0.31.2 → runlayer-0.31.3}/tests/fixtures/cursor_config.json +0 -0
  545. {runlayer-0.31.2 → runlayer-0.31.3}/tests/fixtures/devin_cli_config.json +0 -0
  546. {runlayer-0.31.2 → runlayer-0.31.3}/tests/fixtures/empty_config.json +0 -0
  547. {runlayer-0.31.2 → runlayer-0.31.3}/tests/fixtures/goose_config.yaml +0 -0
  548. {runlayer-0.31.2 → runlayer-0.31.3}/tests/fixtures/hook_dispatch/devin_cli/imported_claude_hook_guard.json +0 -0
  549. {runlayer-0.31.2 → runlayer-0.31.3}/tests/fixtures/hook_dispatch/devin_cli/lifecycle_events.json +0 -0
  550. {runlayer-0.31.2 → runlayer-0.31.3}/tests/fixtures/hook_dispatch/devin_cli/pre_tool_use_exec.json +0 -0
  551. {runlayer-0.31.2 → runlayer-0.31.3}/tests/fixtures/hook_dispatch/devin_cli/pre_tool_use_file_tools.json +0 -0
  552. {runlayer-0.31.2 → runlayer-0.31.3}/tests/fixtures/hook_dispatch/devin_cli/pre_tool_use_mcp.json +0 -0
  553. {runlayer-0.31.2 → runlayer-0.31.3}/tests/fixtures/hook_replay/claude_code/event_hooks_matrix.json +0 -0
  554. {runlayer-0.31.2 → runlayer-0.31.3}/tests/fixtures/hook_replay/claude_code/post_tool_failure_allow.json +0 -0
  555. {runlayer-0.31.2 → runlayer-0.31.3}/tests/fixtures/hook_replay/claude_code/post_tool_failure_output_block.json +0 -0
  556. {runlayer-0.31.2 → runlayer-0.31.3}/tests/fixtures/hook_replay/claude_code/post_tool_output_allow.json +0 -0
  557. {runlayer-0.31.2 → runlayer-0.31.3}/tests/fixtures/hook_replay/claude_code/post_tool_output_block.json +0 -0
  558. {runlayer-0.31.2 → runlayer-0.31.3}/tests/fixtures/hook_replay/claude_code/pre_tool_mcp_local_stdio_deny.json +0 -0
  559. {runlayer-0.31.2 → runlayer-0.31.3}/tests/fixtures/hook_replay/claude_code/pre_tool_mcp_managed_proxy_allow.json +0 -0
  560. {runlayer-0.31.2 → runlayer-0.31.3}/tests/fixtures/hook_replay/claude_code/pre_tool_native_bash_allow.json +0 -0
  561. {runlayer-0.31.2 → runlayer-0.31.3}/tests/fixtures/hook_replay/claude_code/pre_tool_native_bash_deny.json +0 -0
  562. {runlayer-0.31.2 → runlayer-0.31.3}/tests/fixtures/hook_replay/claude_code/pre_tool_read_env_deny.json +0 -0
  563. {runlayer-0.31.2 → runlayer-0.31.3}/tests/fixtures/hook_replay/claude_code/user_prompt_submit_event.json +0 -0
  564. {runlayer-0.31.2 → runlayer-0.31.3}/tests/fixtures/hook_replay/codex/event_hooks_matrix.json +0 -0
  565. {runlayer-0.31.2 → runlayer-0.31.3}/tests/fixtures/hook_replay/codex/permission_request_allow.json +0 -0
  566. {runlayer-0.31.2 → runlayer-0.31.3}/tests/fixtures/hook_replay/codex/permission_request_env_deny.json +0 -0
  567. {runlayer-0.31.2 → runlayer-0.31.3}/tests/fixtures/hook_replay/codex/post_tool_event_allow.json +0 -0
  568. {runlayer-0.31.2 → runlayer-0.31.3}/tests/fixtures/hook_replay/codex/post_tool_failure_allow.json +0 -0
  569. {runlayer-0.31.2 → runlayer-0.31.3}/tests/fixtures/hook_replay/codex/post_tool_failure_output_block.json +0 -0
  570. {runlayer-0.31.2 → runlayer-0.31.3}/tests/fixtures/hook_replay/codex/post_tool_output_block.json +0 -0
  571. {runlayer-0.31.2 → runlayer-0.31.3}/tests/fixtures/hook_replay/codex/pre_tool_mcp_local_stdio_deny.json +0 -0
  572. {runlayer-0.31.2 → runlayer-0.31.3}/tests/fixtures/hook_replay/codex/pre_tool_mcp_managed_proxy_allow.json +0 -0
  573. {runlayer-0.31.2 → runlayer-0.31.3}/tests/fixtures/hook_replay/codex/pre_tool_native_bash_allow.json +0 -0
  574. {runlayer-0.31.2 → runlayer-0.31.3}/tests/fixtures/hook_replay/codex/pre_tool_native_bash_deny.json +0 -0
  575. {runlayer-0.31.2 → runlayer-0.31.3}/tests/fixtures/hook_replay/cursor/after_file_edit_event.json +0 -0
  576. {runlayer-0.31.2 → runlayer-0.31.3}/tests/fixtures/hook_replay/cursor/before_mcp_direct_url_allow.json +0 -0
  577. {runlayer-0.31.2 → runlayer-0.31.3}/tests/fixtures/hook_replay/cursor/before_mcp_local_stdio_deny.json +0 -0
  578. {runlayer-0.31.2 → runlayer-0.31.3}/tests/fixtures/hook_replay/cursor/before_mcp_managed_proxy_allow.json +0 -0
  579. {runlayer-0.31.2 → runlayer-0.31.3}/tests/fixtures/hook_replay/cursor/before_read_file_allow.json +0 -0
  580. {runlayer-0.31.2 → runlayer-0.31.3}/tests/fixtures/hook_replay/cursor/before_read_file_env_deny.json +0 -0
  581. {runlayer-0.31.2 → runlayer-0.31.3}/tests/fixtures/hook_replay/cursor/before_shell_execution_allow.json +0 -0
  582. {runlayer-0.31.2 → runlayer-0.31.3}/tests/fixtures/hook_replay/cursor/before_shell_execution_env_deny.json +0 -0
  583. {runlayer-0.31.2 → runlayer-0.31.3}/tests/fixtures/hook_replay/cursor/before_tab_file_read_allow.json +0 -0
  584. {runlayer-0.31.2 → runlayer-0.31.3}/tests/fixtures/hook_replay/cursor/before_tab_file_read_mcp_config_deny.json +0 -0
  585. {runlayer-0.31.2 → runlayer-0.31.3}/tests/fixtures/hook_replay/cursor/event_hooks_matrix.json +0 -0
  586. {runlayer-0.31.2 → runlayer-0.31.3}/tests/fixtures/hook_replay/cursor/post_tool_use_allow.json +0 -0
  587. {runlayer-0.31.2 → runlayer-0.31.3}/tests/fixtures/hook_replay/cursor/post_tool_use_failure_allow.json +0 -0
  588. {runlayer-0.31.2 → runlayer-0.31.3}/tests/fixtures/hook_replay/cursor/post_tool_use_failure_output_block.json +0 -0
  589. {runlayer-0.31.2 → runlayer-0.31.3}/tests/fixtures/hook_replay/cursor/post_tool_use_output_block.json +0 -0
  590. {runlayer-0.31.2 → runlayer-0.31.3}/tests/fixtures/hook_replay/cursor/pre_tool_native_bash_allow_modified.json +0 -0
  591. {runlayer-0.31.2 → runlayer-0.31.3}/tests/fixtures/hook_replay/cursor/pre_tool_native_bash_deny.json +0 -0
  592. {runlayer-0.31.2 → runlayer-0.31.3}/tests/fixtures/hook_replay/cursor/stop_session_end_event.json +0 -0
  593. {runlayer-0.31.2 → runlayer-0.31.3}/tests/fixtures/invalid_json.txt +0 -0
  594. {runlayer-0.31.2 → runlayer-0.31.3}/tests/fixtures/junie_config.json +0 -0
  595. {runlayer-0.31.2 → runlayer-0.31.3}/tests/fixtures/kilo_code_config.jsonc +0 -0
  596. {runlayer-0.31.2 → runlayer-0.31.3}/tests/fixtures/kimi_code_config.json +0 -0
  597. {runlayer-0.31.2 → runlayer-0.31.3}/tests/fixtures/macos_policy_reader.c +0 -0
  598. {runlayer-0.31.2 → runlayer-0.31.3}/tests/fixtures/pi_config.json +0 -0
  599. {runlayer-0.31.2 → runlayer-0.31.3}/tests/fixtures/roo_code_config.json +0 -0
  600. {runlayer-0.31.2 → runlayer-0.31.3}/tests/fixtures/sse_server_config.json +0 -0
  601. {runlayer-0.31.2 → runlayer-0.31.3}/tests/fixtures/vscode_config.json +0 -0
  602. {runlayer-0.31.2 → runlayer-0.31.3}/tests/fixtures/warp_config.json +0 -0
  603. {runlayer-0.31.2 → runlayer-0.31.3}/tests/frozen/__init__.py +0 -0
  604. {runlayer-0.31.2 → runlayer-0.31.3}/tests/frozen/conftest.py +0 -0
  605. {runlayer-0.31.2 → runlayer-0.31.3}/tests/frozen/test_frozen_credential.py +0 -0
  606. {runlayer-0.31.2 → runlayer-0.31.3}/tests/frozen/test_frozen_install.py +0 -0
  607. {runlayer-0.31.2 → runlayer-0.31.3}/tests/frozen/test_frozen_policy_publication.py +0 -0
  608. {runlayer-0.31.2 → runlayer-0.31.3}/tests/frozen/test_frozen_runlayer.py +0 -0
  609. {runlayer-0.31.2 → runlayer-0.31.3}/tests/hostile_inputs.py +0 -0
  610. {runlayer-0.31.2 → runlayer-0.31.3}/tests/macos_installer_helpers.py +0 -0
  611. {runlayer-0.31.2 → runlayer-0.31.3}/tests/platform_installer_helpers.py +0 -0
  612. {runlayer-0.31.2 → runlayer-0.31.3}/tests/plugin_installer_helpers.py +0 -0
  613. {runlayer-0.31.2 → runlayer-0.31.3}/tests/scan/__init__.py +0 -0
  614. {runlayer-0.31.2 → runlayer-0.31.3}/tests/scan/agents/__init__.py +0 -0
  615. {runlayer-0.31.2 → runlayer-0.31.3}/tests/scan/agents/harness.py +0 -0
  616. {runlayer-0.31.2 → runlayer-0.31.3}/tests/scan/agents/test_agent_scan.py +0 -0
  617. {runlayer-0.31.2 → runlayer-0.31.3}/tests/scan/agents/test_detect.py +0 -0
  618. {runlayer-0.31.2 → runlayer-0.31.3}/tests/scan/agents/test_discover.py +0 -0
  619. {runlayer-0.31.2 → runlayer-0.31.3}/tests/scan/agents/test_eval.py +0 -0
  620. {runlayer-0.31.2 → runlayer-0.31.3}/tests/scan/agents/test_manifests.py +0 -0
  621. {runlayer-0.31.2 → runlayer-0.31.3}/tests/scan/agents/test_redact.py +0 -0
  622. {runlayer-0.31.2 → runlayer-0.31.3}/tests/scan/agents/test_registry.py +0 -0
  623. {runlayer-0.31.2 → runlayer-0.31.3}/tests/scan/agents/test_report.py +0 -0
  624. {runlayer-0.31.2 → runlayer-0.31.3}/tests/scan/conftest.py +0 -0
  625. {runlayer-0.31.2 → runlayer-0.31.3}/tests/scan/processes/__init__.py +0 -0
  626. {runlayer-0.31.2 → runlayer-0.31.3}/tests/scan/processes/test_classify.py +0 -0
  627. {runlayer-0.31.2 → runlayer-0.31.3}/tests/scan/processes/test_discovery.py +0 -0
  628. {runlayer-0.31.2 → runlayer-0.31.3}/tests/scan/processes/test_enumerate.py +0 -0
  629. {runlayer-0.31.2 → runlayer-0.31.3}/tests/scan/processes/test_probes.py +0 -0
  630. {runlayer-0.31.2 → runlayer-0.31.3}/tests/scan/processes/test_redact.py +0 -0
  631. {runlayer-0.31.2 → runlayer-0.31.3}/tests/scan/processes/test_settings_override.py +0 -0
  632. {runlayer-0.31.2 → runlayer-0.31.3}/tests/scan/test_agent_definition_scanner.py +0 -0
  633. {runlayer-0.31.2 → runlayer-0.31.3}/tests/scan/test_agent_scan.py +0 -0
  634. {runlayer-0.31.2 → runlayer-0.31.3}/tests/scan/test_completeness.py +0 -0
  635. {runlayer-0.31.2 → runlayer-0.31.3}/tests/scan/test_config_redact.py +0 -0
  636. {runlayer-0.31.2 → runlayer-0.31.3}/tests/scan/test_container_command.py +0 -0
  637. {runlayer-0.31.2 → runlayer-0.31.3}/tests/scan/test_containers.py +0 -0
  638. {runlayer-0.31.2 → runlayer-0.31.3}/tests/scan/test_docker_socket.py +0 -0
  639. {runlayer-0.31.2 → runlayer-0.31.3}/tests/scan/test_k3s.py +0 -0
  640. {runlayer-0.31.2 → runlayer-0.31.3}/tests/scan/test_phase_isolation.py +0 -0
  641. {runlayer-0.31.2 → runlayer-0.31.3}/tests/scan/test_presence_decode_hardening.py +0 -0
  642. {runlayer-0.31.2 → runlayer-0.31.3}/tests/scan/test_runtime_decode_hardening.py +0 -0
  643. {runlayer-0.31.2 → runlayer-0.31.3}/tests/scan/test_skip_dirs.py +0 -0
  644. {runlayer-0.31.2 → runlayer-0.31.3}/tests/scan/test_windows_named_pipe.py +0 -0
  645. {runlayer-0.31.2 → runlayer-0.31.3}/tests/scan/test_wsl_exec.py +0 -0
  646. {runlayer-0.31.2 → runlayer-0.31.3}/tests/scan/test_wsl_paths.py +0 -0
  647. {runlayer-0.31.2 → runlayer-0.31.3}/tests/scan/test_wsl_presence.py +0 -0
  648. {runlayer-0.31.2 → runlayer-0.31.3}/tests/scan/test_wsl_projects.py +0 -0
  649. {runlayer-0.31.2 → runlayer-0.31.3}/tests/scan/test_wsl_runtime_signals.py +0 -0
  650. {runlayer-0.31.2 → runlayer-0.31.3}/tests/sign_shards_smoke.ps1 +0 -0
  651. {runlayer-0.31.2 → runlayer-0.31.3}/tests/skill_identifier/__init__.py +0 -0
  652. {runlayer-0.31.2 → runlayer-0.31.3}/tests/skill_identifier/test_merkle.py +0 -0
  653. {runlayer-0.31.2 → runlayer-0.31.3}/tests/skill_identifier/test_skill_id.py +0 -0
  654. {runlayer-0.31.2 → runlayer-0.31.3}/tests/test_aiwatch_basename_dispatch.py +0 -0
  655. {runlayer-0.31.2 → runlayer-0.31.3}/tests/test_aiwatch_bootstrap.py +0 -0
  656. {runlayer-0.31.2 → runlayer-0.31.3}/tests/test_aiwatch_checkin.py +0 -0
  657. {runlayer-0.31.2 → runlayer-0.31.3}/tests/test_aiwatch_checkin_batch.py +0 -0
  658. {runlayer-0.31.2 → runlayer-0.31.3}/tests/test_aiwatch_config_cache.py +0 -0
  659. {runlayer-0.31.2 → runlayer-0.31.3}/tests/test_aiwatch_config_isolation.py +0 -0
  660. {runlayer-0.31.2 → runlayer-0.31.3}/tests/test_aiwatch_config_sync.py +0 -0
  661. {runlayer-0.31.2 → runlayer-0.31.3}/tests/test_aiwatch_credential.py +0 -0
  662. {runlayer-0.31.2 → runlayer-0.31.3}/tests/test_aiwatch_daemon_dispatch.py +0 -0
  663. {runlayer-0.31.2 → runlayer-0.31.3}/tests/test_aiwatch_hook_shim_packaging.py +0 -0
  664. {runlayer-0.31.2 → runlayer-0.31.3}/tests/test_aiwatch_hook_version.py +0 -0
  665. {runlayer-0.31.2 → runlayer-0.31.3}/tests/test_aiwatch_imports.py +0 -0
  666. {runlayer-0.31.2 → runlayer-0.31.3}/tests/test_aiwatch_setup_hooks.py +0 -0
  667. {runlayer-0.31.2 → runlayer-0.31.3}/tests/test_aiwatch_uninstall.py +0 -0
  668. {runlayer-0.31.2 → runlayer-0.31.3}/tests/test_aiwatch_uninstall_packaging.py +0 -0
  669. {runlayer-0.31.2 → runlayer-0.31.3}/tests/test_aiwatch_update_command.py +0 -0
  670. {runlayer-0.31.2 → runlayer-0.31.3}/tests/test_api.py +0 -0
  671. {runlayer-0.31.2 → runlayer-0.31.3}/tests/test_artifact_cache.py +0 -0
  672. {runlayer-0.31.2 → runlayer-0.31.3}/tests/test_auth.py +0 -0
  673. {runlayer-0.31.2 → runlayer-0.31.3}/tests/test_backwards_compatibility.py +0 -0
  674. {runlayer-0.31.2 → runlayer-0.31.3}/tests/test_bin_shims.py +0 -0
  675. {runlayer-0.31.2 → runlayer-0.31.3}/tests/test_browser_extension_install.py +0 -0
  676. {runlayer-0.31.2 → runlayer-0.31.3}/tests/test_browser_extensions.py +0 -0
  677. {runlayer-0.31.2 → runlayer-0.31.3}/tests/test_cache.py +0 -0
  678. {runlayer-0.31.2 → runlayer-0.31.3}/tests/test_catalog_commands.py +0 -0
  679. {runlayer-0.31.2 → runlayer-0.31.3}/tests/test_catalog_enrichment.py +0 -0
  680. {runlayer-0.31.2 → runlayer-0.31.3}/tests/test_chromium_profile_health.py +0 -0
  681. {runlayer-0.31.2 → runlayer-0.31.3}/tests/test_claude_code_plugins.py +0 -0
  682. {runlayer-0.31.2 → runlayer-0.31.3}/tests/test_claude_json_integration.py +0 -0
  683. {runlayer-0.31.2 → runlayer-0.31.3}/tests/test_claude_output_replacement.py +0 -0
  684. {runlayer-0.31.2 → runlayer-0.31.3}/tests/test_cli_backwards_compat.py +0 -0
  685. {runlayer-0.31.2 → runlayer-0.31.3}/tests/test_cli_binaries.py +0 -0
  686. {runlayer-0.31.2 → runlayer-0.31.3}/tests/test_cli_linux_schedule_assets.py +0 -0
  687. {runlayer-0.31.2 → runlayer-0.31.3}/tests/test_cli_update_schedule_assets.py +0 -0
  688. {runlayer-0.31.2 → runlayer-0.31.3}/tests/test_client_presence.py +0 -0
  689. {runlayer-0.31.2 → runlayer-0.31.3}/tests/test_client_presence_evasion.py +0 -0
  690. {runlayer-0.31.2 → runlayer-0.31.3}/tests/test_command_contract.py +0 -0
  691. {runlayer-0.31.2 → runlayer-0.31.3}/tests/test_command_metrics.py +0 -0
  692. {runlayer-0.31.2 → runlayer-0.31.3}/tests/test_config.py +0 -0
  693. {runlayer-0.31.2 → runlayer-0.31.3}/tests/test_config_backup.py +0 -0
  694. {runlayer-0.31.2 → runlayer-0.31.3}/tests/test_container_label_contract.py +0 -0
  695. {runlayer-0.31.2 → runlayer-0.31.3}/tests/test_copilot_plugins.py +0 -0
  696. {runlayer-0.31.2 → runlayer-0.31.3}/tests/test_credential_store.py +0 -0
  697. {runlayer-0.31.2 → runlayer-0.31.3}/tests/test_credential_store_macos.py +0 -0
  698. {runlayer-0.31.2 → runlayer-0.31.3}/tests/test_credentials_commands.py +0 -0
  699. {runlayer-0.31.2 → runlayer-0.31.3}/tests/test_cursor_plugins.py +0 -0
  700. {runlayer-0.31.2 → runlayer-0.31.3}/tests/test_daemon_client.py +0 -0
  701. {runlayer-0.31.2 → runlayer-0.31.3}/tests/test_daemon_lifecycle.py +0 -0
  702. {runlayer-0.31.2 → runlayer-0.31.3}/tests/test_daemon_protocol.py +0 -0
  703. {runlayer-0.31.2 → runlayer-0.31.3}/tests/test_daemon_server.py +0 -0
  704. {runlayer-0.31.2 → runlayer-0.31.3}/tests/test_daemon_status.py +0 -0
  705. {runlayer-0.31.2 → runlayer-0.31.3}/tests/test_daemon_windows_pipe.py +0 -0
  706. {runlayer-0.31.2 → runlayer-0.31.3}/tests/test_debug_hook_binary.py +0 -0
  707. {runlayer-0.31.2 → runlayer-0.31.3}/tests/test_decide_approval.py +0 -0
  708. {runlayer-0.31.2 → runlayer-0.31.3}/tests/test_deploy_service.py +0 -0
  709. {runlayer-0.31.2 → runlayer-0.31.3}/tests/test_desktop_release_workflow.py +0 -0
  710. {runlayer-0.31.2 → runlayer-0.31.3}/tests/test_disguised_skills.py +0 -0
  711. {runlayer-0.31.2 → runlayer-0.31.3}/tests/test_dispatch_decode_hardening.py +0 -0
  712. {runlayer-0.31.2 → runlayer-0.31.3}/tests/test_docker_builder.py +0 -0
  713. {runlayer-0.31.2 → runlayer-0.31.3}/tests/test_docs_client_sync.py +0 -0
  714. {runlayer-0.31.2 → runlayer-0.31.3}/tests/test_doctor.py +0 -0
  715. {runlayer-0.31.2 → runlayer-0.31.3}/tests/test_edge_extension_install.py +0 -0
  716. {runlayer-0.31.2 → runlayer-0.31.3}/tests/test_endpoint_modes.py +0 -0
  717. {runlayer-0.31.2 → runlayer-0.31.3}/tests/test_enroll_checkins.py +0 -0
  718. {runlayer-0.31.2 → runlayer-0.31.3}/tests/test_enroll_command.py +0 -0
  719. {runlayer-0.31.2 → runlayer-0.31.3}/tests/test_enrollment.py +0 -0
  720. {runlayer-0.31.2 → runlayer-0.31.3}/tests/test_env_substitution.py +0 -0
  721. {runlayer-0.31.2 → runlayer-0.31.3}/tests/test_error_classification.py +0 -0
  722. {runlayer-0.31.2 → runlayer-0.31.3}/tests/test_firefox_extension_install.py +0 -0
  723. {runlayer-0.31.2 → runlayer-0.31.3}/tests/test_flow_contract.py +0 -0
  724. {runlayer-0.31.2 → runlayer-0.31.3}/tests/test_flow_delivery.py +0 -0
  725. {runlayer-0.31.2 → runlayer-0.31.3}/tests/test_flow_spool.py +0 -0
  726. {runlayer-0.31.2 → runlayer-0.31.3}/tests/test_flow_trace.py +0 -0
  727. {runlayer-0.31.2 → runlayer-0.31.3}/tests/test_gemini_extensions.py +0 -0
  728. {runlayer-0.31.2 → runlayer-0.31.3}/tests/test_hidden_space_sweep.py +0 -0
  729. {runlayer-0.31.2 → runlayer-0.31.3}/tests/test_hook_binary_convergence.py +0 -0
  730. {runlayer-0.31.2 → runlayer-0.31.3}/tests/test_hook_dispatch_replay.py +0 -0
  731. {runlayer-0.31.2 → runlayer-0.31.3}/tests/test_hook_flow_departed_harness.py +0 -0
  732. {runlayer-0.31.2 → runlayer-0.31.3}/tests/test_hook_flow_harness_closed_stdout.py +0 -0
  733. {runlayer-0.31.2 → runlayer-0.31.3}/tests/test_hook_flow_operations.py +0 -0
  734. {runlayer-0.31.2 → runlayer-0.31.3}/tests/test_hook_host_override.py +0 -0
  735. {runlayer-0.31.2 → runlayer-0.31.3}/tests/test_hook_install_console_user.py +0 -0
  736. {runlayer-0.31.2 → runlayer-0.31.3}/tests/test_hook_install_mdm_scope.py +0 -0
  737. {runlayer-0.31.2 → runlayer-0.31.3}/tests/test_hook_install_safe_fs.py +0 -0
  738. {runlayer-0.31.2 → runlayer-0.31.3}/tests/test_hook_install_windows_safe_fs.py +0 -0
  739. {runlayer-0.31.2 → runlayer-0.31.3}/tests/test_hook_io.py +0 -0
  740. {runlayer-0.31.2 → runlayer-0.31.3}/tests/test_hook_python.py +0 -0
  741. {runlayer-0.31.2 → runlayer-0.31.3}/tests/test_hook_replay_fixtures.py +0 -0
  742. {runlayer-0.31.2 → runlayer-0.31.3}/tests/test_hook_script.py +0 -0
  743. {runlayer-0.31.2 → runlayer-0.31.3}/tests/test_hook_shim_protocol.py +0 -0
  744. {runlayer-0.31.2 → runlayer-0.31.3}/tests/test_hooks_relay.py +0 -0
  745. {runlayer-0.31.2 → runlayer-0.31.3}/tests/test_identity_forward.py +0 -0
  746. {runlayer-0.31.2 → runlayer-0.31.3}/tests/test_install_window.py +0 -0
  747. {runlayer-0.31.2 → runlayer-0.31.3}/tests/test_interactive_find.py +0 -0
  748. {runlayer-0.31.2 → runlayer-0.31.3}/tests/test_jetbrains_plugins.py +0 -0
  749. {runlayer-0.31.2 → runlayer-0.31.3}/tests/test_keychain_adopt.py +0 -0
  750. {runlayer-0.31.2 → runlayer-0.31.3}/tests/test_keychain_guard.py +0 -0
  751. {runlayer-0.31.2 → runlayer-0.31.3}/tests/test_launcher_inspection.py +0 -0
  752. {runlayer-0.31.2 → runlayer-0.31.3}/tests/test_lazy_enrollment.py +0 -0
  753. {runlayer-0.31.2 → runlayer-0.31.3}/tests/test_legacy_re2_tag_coupling.py +0 -0
  754. {runlayer-0.31.2 → runlayer-0.31.3}/tests/test_linux_cron_assets.py +0 -0
  755. {runlayer-0.31.2 → runlayer-0.31.3}/tests/test_linux_installer.py +0 -0
  756. {runlayer-0.31.2 → runlayer-0.31.3}/tests/test_llm_routing.py +0 -0
  757. {runlayer-0.31.2 → runlayer-0.31.3}/tests/test_llm_routing_probe.py +0 -0
  758. {runlayer-0.31.2 → runlayer-0.31.3}/tests/test_llm_routing_reconcile.py +0 -0
  759. {runlayer-0.31.2 → runlayer-0.31.3}/tests/test_logging.py +0 -0
  760. {runlayer-0.31.2 → runlayer-0.31.3}/tests/test_logs.py +0 -0
  761. {runlayer-0.31.2 → runlayer-0.31.3}/tests/test_macos_config_profile_assets.py +0 -0
  762. {runlayer-0.31.2 → runlayer-0.31.3}/tests/test_macos_installer.py +0 -0
  763. {runlayer-0.31.2 → runlayer-0.31.3}/tests/test_macos_managed_policy_publication.py +0 -0
  764. {runlayer-0.31.2 → runlayer-0.31.3}/tests/test_macos_mdm_mode_compatibility.py +0 -0
  765. {runlayer-0.31.2 → runlayer-0.31.3}/tests/test_macos_plists.py +0 -0
  766. {runlayer-0.31.2 → runlayer-0.31.3}/tests/test_main_hook_dispatch.py +0 -0
  767. {runlayer-0.31.2 → runlayer-0.31.3}/tests/test_managed_policy_publication.py +0 -0
  768. {runlayer-0.31.2 → runlayer-0.31.3}/tests/test_manual_oauth.py +0 -0
  769. {runlayer-0.31.2 → runlayer-0.31.3}/tests/test_manylinux2014_lock_floor.py +0 -0
  770. {runlayer-0.31.2 → runlayer-0.31.3}/tests/test_mcp_lookup_decode_hardening.py +0 -0
  771. {runlayer-0.31.2 → runlayer-0.31.3}/tests/test_mdm_config.py +0 -0
  772. {runlayer-0.31.2 → runlayer-0.31.3}/tests/test_metrics.py +0 -0
  773. {runlayer-0.31.2 → runlayer-0.31.3}/tests/test_middleware.py +0 -0
  774. {runlayer-0.31.2 → runlayer-0.31.3}/tests/test_native_messaging.py +0 -0
  775. {runlayer-0.31.2 → runlayer-0.31.3}/tests/test_npm_global.py +0 -0
  776. {runlayer-0.31.2 → runlayer-0.31.3}/tests/test_oauth_browser_lock.py +0 -0
  777. {runlayer-0.31.2 → runlayer-0.31.3}/tests/test_oauth_callback_lifecycle.py +0 -0
  778. {runlayer-0.31.2 → runlayer-0.31.3}/tests/test_oauth_callback_port.py +0 -0
  779. {runlayer-0.31.2 → runlayer-0.31.3}/tests/test_oauth_error_guidance.py +0 -0
  780. {runlayer-0.31.2 → runlayer-0.31.3}/tests/test_oauth_sibling_wait.py +0 -0
  781. {runlayer-0.31.2 → runlayer-0.31.3}/tests/test_oauth_token_storage.py +0 -0
  782. {runlayer-0.31.2 → runlayer-0.31.3}/tests/test_opencode_plugins.py +0 -0
  783. {runlayer-0.31.2 → runlayer-0.31.3}/tests/test_org_api_key_commands.py +0 -0
  784. {runlayer-0.31.2 → runlayer-0.31.3}/tests/test_pip_global.py +0 -0
  785. {runlayer-0.31.2 → runlayer-0.31.3}/tests/test_platform_installers.py +0 -0
  786. {runlayer-0.31.2 → runlayer-0.31.3}/tests/test_plugin_layouts.py +0 -0
  787. {runlayer-0.31.2 → runlayer-0.31.3}/tests/test_plugin_scanner.py +0 -0
  788. {runlayer-0.31.2 → runlayer-0.31.3}/tests/test_plugins_commands.py +0 -0
  789. {runlayer-0.31.2 → runlayer-0.31.3}/tests/test_plugins_discovery.py +0 -0
  790. {runlayer-0.31.2 → runlayer-0.31.3}/tests/test_plugins_installer.py +0 -0
  791. {runlayer-0.31.2 → runlayer-0.31.3}/tests/test_plugins_installer_cursor_layout.py +0 -0
  792. {runlayer-0.31.2 → runlayer-0.31.3}/tests/test_plugins_sync.py +0 -0
  793. {runlayer-0.31.2 → runlayer-0.31.3}/tests/test_product.py +0 -0
  794. {runlayer-0.31.2 → runlayer-0.31.3}/tests/test_published_hook_transport.py +0 -0
  795. {runlayer-0.31.2 → runlayer-0.31.3}/tests/test_py310_compat.py +0 -0
  796. {runlayer-0.31.2 → runlayer-0.31.3}/tests/test_regex_parity.py +0 -0
  797. {runlayer-0.31.2 → runlayer-0.31.3}/tests/test_regex_safe_mirror_drift.py +0 -0
  798. {runlayer-0.31.2 → runlayer-0.31.3}/tests/test_renamed_plugin_caches.py +0 -0
  799. {runlayer-0.31.2 → runlayer-0.31.3}/tests/test_resource_governor.py +0 -0
  800. {runlayer-0.31.2 → runlayer-0.31.3}/tests/test_safe_parse.py +0 -0
  801. {runlayer-0.31.2 → runlayer-0.31.3}/tests/test_scan_clients.py +0 -0
  802. {runlayer-0.31.2 → runlayer-0.31.3}/tests/test_scan_concurrency.py +0 -0
  803. {runlayer-0.31.2 → runlayer-0.31.3}/tests/test_scan_detect_error_checkin.py +0 -0
  804. {runlayer-0.31.2 → runlayer-0.31.3}/tests/test_scan_device.py +0 -0
  805. {runlayer-0.31.2 → runlayer-0.31.3}/tests/test_scan_memory_caps.py +0 -0
  806. {runlayer-0.31.2 → runlayer-0.31.3}/tests/test_scan_no_findings.py +0 -0
  807. {runlayer-0.31.2 → runlayer-0.31.3}/tests/test_scan_openclaw.py +0 -0
  808. {runlayer-0.31.2 → runlayer-0.31.3}/tests/test_scan_parser.py +0 -0
  809. {runlayer-0.31.2 → runlayer-0.31.3}/tests/test_scan_project.py +0 -0
  810. {runlayer-0.31.2 → runlayer-0.31.3}/tests/test_scan_run_lock.py +0 -0
  811. {runlayer-0.31.2 → runlayer-0.31.3}/tests/test_scan_summary.py +0 -0
  812. {runlayer-0.31.2 → runlayer-0.31.3}/tests/test_scan_timing.py +0 -0
  813. {runlayer-0.31.2 → runlayer-0.31.3}/tests/test_scan_verbose.py +0 -0
  814. {runlayer-0.31.2 → runlayer-0.31.3}/tests/test_scan_windows_profile.py +0 -0
  815. {runlayer-0.31.2 → runlayer-0.31.3}/tests/test_scanner_primitives.py +0 -0
  816. {runlayer-0.31.2 → runlayer-0.31.3}/tests/test_schedule_command.py +0 -0
  817. {runlayer-0.31.2 → runlayer-0.31.3}/tests/test_setup_hooks.py +0 -0
  818. {runlayer-0.31.2 → runlayer-0.31.3}/tests/test_setup_install_claude_desktop.py +0 -0
  819. {runlayer-0.31.2 → runlayer-0.31.3}/tests/test_setup_install_config_formats.py +0 -0
  820. {runlayer-0.31.2 → runlayer-0.31.3}/tests/test_setup_install_local_servers.py +0 -0
  821. {runlayer-0.31.2 → runlayer-0.31.3}/tests/test_setup_sync.py +0 -0
  822. {runlayer-0.31.2 → runlayer-0.31.3}/tests/test_skill_names.py +0 -0
  823. {runlayer-0.31.2 → runlayer-0.31.3}/tests/test_skill_presence.py +0 -0
  824. {runlayer-0.31.2 → runlayer-0.31.3}/tests/test_skill_sync_credentials.py +0 -0
  825. {runlayer-0.31.2 → runlayer-0.31.3}/tests/test_skills_commands.py +0 -0
  826. {runlayer-0.31.2 → runlayer-0.31.3}/tests/test_skills_device_sync.py +0 -0
  827. {runlayer-0.31.2 → runlayer-0.31.3}/tests/test_skills_discovery.py +0 -0
  828. {runlayer-0.31.2 → runlayer-0.31.3}/tests/test_skills_installer.py +0 -0
  829. {runlayer-0.31.2 → runlayer-0.31.3}/tests/test_skills_installer_core.py +0 -0
  830. {runlayer-0.31.2 → runlayer-0.31.3}/tests/test_skills_marker.py +0 -0
  831. {runlayer-0.31.2 → runlayer-0.31.3}/tests/test_skills_sync.py +0 -0
  832. {runlayer-0.31.2 → runlayer-0.31.3}/tests/test_skills_sync_command.py +0 -0
  833. {runlayer-0.31.2 → runlayer-0.31.3}/tests/test_status.py +0 -0
  834. {runlayer-0.31.2 → runlayer-0.31.3}/tests/test_symbols.py +0 -0
  835. {runlayer-0.31.2 → runlayer-0.31.3}/tests/test_sync.py +0 -0
  836. {runlayer-0.31.2 → runlayer-0.31.3}/tests/test_telemetry.py +0 -0
  837. {runlayer-0.31.2 → runlayer-0.31.3}/tests/test_terraform_commands.py +0 -0
  838. {runlayer-0.31.2 → runlayer-0.31.3}/tests/test_test_device_config.py +0 -0
  839. {runlayer-0.31.2 → runlayer-0.31.3}/tests/test_tls.py +0 -0
  840. {runlayer-0.31.2 → runlayer-0.31.3}/tests/test_transcript_decode_hardening.py +0 -0
  841. {runlayer-0.31.2 → runlayer-0.31.3}/tests/test_truststore_init.py +0 -0
  842. {runlayer-0.31.2 → runlayer-0.31.3}/tests/test_update_commands.py +0 -0
  843. {runlayer-0.31.2 → runlayer-0.31.3}/tests/test_update_contract.py +0 -0
  844. {runlayer-0.31.2 → runlayer-0.31.3}/tests/test_update_privilege.py +0 -0
  845. {runlayer-0.31.2 → runlayer-0.31.3}/tests/test_update_source.py +0 -0
  846. {runlayer-0.31.2 → runlayer-0.31.3}/tests/test_updater.py +0 -0
  847. {runlayer-0.31.2 → runlayer-0.31.3}/tests/test_url_handler.py +0 -0
  848. {runlayer-0.31.2 → runlayer-0.31.3}/tests/test_uv_tool_cleanup.py +0 -0
  849. {runlayer-0.31.2 → runlayer-0.31.3}/tests/test_variant.py +0 -0
  850. {runlayer-0.31.2 → runlayer-0.31.3}/tests/test_variant_packaging_contract.py +0 -0
  851. {runlayer-0.31.2 → runlayer-0.31.3}/tests/test_version_file.py +0 -0
  852. {runlayer-0.31.2 → runlayer-0.31.3}/tests/test_vscode_extensions.py +0 -0
  853. {runlayer-0.31.2 → runlayer-0.31.3}/tests/test_warp_sqlite.py +0 -0
  854. {runlayer-0.31.2 → runlayer-0.31.3}/tests/test_windows_browser_policy.py +0 -0
  855. {runlayer-0.31.2 → runlayer-0.31.3}/tests/test_windows_daemon_service.py +0 -0
  856. {runlayer-0.31.2 → runlayer-0.31.3}/tests/test_windows_installer.py +0 -0
  857. {runlayer-0.31.2 → runlayer-0.31.3}/tests/test_windows_installer_verifier.py +0 -0
  858. {runlayer-0.31.2 → runlayer-0.31.3}/tests/test_windows_msi_sequencing.py +0 -0
  859. {runlayer-0.31.2 → runlayer-0.31.3}/tests/test_windows_native_messaging_packaging.py +0 -0
  860. {runlayer-0.31.2 → runlayer-0.31.3}/tests/test_windows_ps1_gates.py +0 -0
  861. {runlayer-0.31.2 → runlayer-0.31.3}/tests/test_windows_scan_all_users.py +0 -0
  862. {runlayer-0.31.2 → runlayer-0.31.3}/tests/test_windows_sign_shards.py +0 -0
  863. {runlayer-0.31.2 → runlayer-0.31.3}/tests/test_windows_update_handoff.py +0 -0
  864. {runlayer-0.31.2 → runlayer-0.31.3}/tests/verified_local_proxy/__init__.py +0 -0
  865. {runlayer-0.31.2 → runlayer-0.31.3}/tests/verified_local_proxy/test_config.py +0 -0
  866. {runlayer-0.31.2 → runlayer-0.31.3}/tests/verified_local_proxy/test_proxy.py +0 -0
  867. {runlayer-0.31.2 → runlayer-0.31.3}/tests/verified_local_proxy/test_verification/__init__.py +0 -0
  868. {runlayer-0.31.2 → runlayer-0.31.3}/tests/verified_local_proxy/test_verification/test_base.py +0 -0
  869. {runlayer-0.31.2 → runlayer-0.31.3}/tests/verified_local_proxy/test_verification/test_macos.py +0 -0
  870. {runlayer-0.31.2 → runlayer-0.31.3}/tests/verified_local_proxy/test_verification/test_windows.py +0 -0
  871. {runlayer-0.31.2 → runlayer-0.31.3}/tests/windows_installer_helpers.py +0 -0
@@ -342,6 +342,7 @@ uv run runlayer run test_uuid --secret test_key --host http://localhost:8000
342
342
 
343
343
  - Never log API keys or tokens
344
344
  - Validate all inputs
345
+ - `runlayer run` stdio children get a minimal environment (`main.py:_build_stdio_env`): the backend-configured `env` plus a short proxy/TLS/locale allowlist, on top of mcp's platform base set. Never pass `os.environ` through — the AI client's env carries cloud credentials.
345
346
  - Use HTTPS by default
346
347
  - Provide clear security guidance in docs
347
348
 
@@ -1,6 +1,6 @@
1
1
  Metadata-Version: 2.5
2
2
  Name: runlayer
3
- Version: 0.31.2
3
+ Version: 0.31.3
4
4
  Summary: A command-line interface for running MCP servers via HTTP transport
5
5
  Project-URL: Homepage, https://runlayer.com
6
6
  Project-URL: Documentation, https://docs.runlayer.com/
@@ -1,6 +1,6 @@
1
1
  [project]
2
2
  name = "runlayer"
3
- version = "0.31.2"
3
+ version = "0.31.3"
4
4
  description = "A command-line interface for running MCP servers via HTTP transport"
5
5
  readme = "README.md"
6
6
  requires-python = ">=3.10"
@@ -48,12 +48,33 @@ def _config_callback(ctx: typer.Context) -> None:
48
48
  raise typer.Exit()
49
49
 
50
50
 
51
+ _UNRECOGNIZED_SECRET = "set (unrecognized format)"
52
+
53
+
54
+ def _redact_secret(field: str, value: str) -> str:
55
+ # Recognized keys render the way the dashboard shows that key type, so an
56
+ # operator can match a device to a key by eye (pinned by
57
+ # tests/fixtures/managed_secret_display_cases.json). Anything else is
58
+ # masked outright: `config show` output gets pasted into tickets, and a
59
+ # wrong-type or truncated value must not echo more than the old
60
+ # `****<last4>` did.
61
+ if field == "enrollment_key":
62
+ if value.startswith("rl_enroll_") and len(value) > 14:
63
+ return f"{value[:10]}...{value[-4:]}"
64
+ return _UNRECOGNIZED_SECRET
65
+ if value.startswith("rl_org_") and len(value) > 14:
66
+ return f"{value[:14]}..."
67
+ return _UNRECOGNIZED_SECRET
68
+
69
+
51
70
  def _redact_config(config: mdm_config.ManagedConfig) -> dict[str, object]:
52
71
  redacted: dict[str, object] = {}
53
72
  for key, value in config.items():
54
73
  if key in mdm_config.SECRET_FIELDS:
55
74
  redacted[key] = (
56
- f"****{value[-4:]}" if isinstance(value, str) and value else "not set"
75
+ _redact_secret(key, value)
76
+ if isinstance(value, str) and value
77
+ else "not set"
57
78
  )
58
79
  else:
59
80
  redacted[key] = value
@@ -737,6 +737,47 @@ def _run_scan(
737
737
  fg=typer.colors.YELLOW,
738
738
  )
739
739
 
740
+ if submission.manifest_regressed:
741
+ scopes = ", ".join(
742
+ scope for scope, _last_accepted_at in submission.manifest_regressed
743
+ )
744
+ # ISO-8601 UTC strings from one backend sort lexicographically.
745
+ last_accepted_at = max(
746
+ accepted_at for _scope, accepted_at in submission.manifest_regressed
747
+ )
748
+ typer.secho(
749
+ f"{WARN} Scan manifest rejected: {scopes} predate the last "
750
+ f"accepted scan (started {last_accepted_at})",
751
+ fg=typer.colors.YELLOW,
752
+ )
753
+
754
+ if submission.manifest_superseded and not quiet:
755
+ scopes = ", ".join(
756
+ scope for scope, _last_accepted_at in submission.manifest_superseded
757
+ )
758
+ last_accepted_at = max(
759
+ accepted_at for _scope, accepted_at in submission.manifest_superseded
760
+ )
761
+ typer.echo(
762
+ f"Manifest superseded by a newer scan (started {last_accepted_at}) "
763
+ f"for {scopes}"
764
+ )
765
+
766
+ if submission.positives_superseded and not quiet:
767
+ identifiers = [
768
+ identifier for _kind, identifier in submission.positives_superseded
769
+ ]
770
+ shown = ", ".join(identifiers[:5])
771
+ if len(identifiers) > 5:
772
+ shown += f", +{len(identifiers) - 5} more"
773
+ count = len(identifiers)
774
+ noun = "finding" if count == 1 else "findings"
775
+ typer.secho(
776
+ f"{WARN} {count} device-scoped {noun} superseded by a newer scan "
777
+ f"on this device and not recorded: {shown}",
778
+ fg=typer.colors.YELLOW,
779
+ )
780
+
740
781
  # The WARN lines above already told the user what happened; here we only
741
782
  # act on the exit-code policy the orchestrator computed.
742
783
  exit_code = submission.exit_code
@@ -490,7 +490,7 @@ _CODEX_HOOK_MATCHERS = {
490
490
  "PostToolUse": "",
491
491
  "PostToolUseFailure": "",
492
492
  "PermissionRequest": "Bash",
493
- "SessionStart": "startup|resume",
493
+ "SessionStart": "startup|resume|clear|compact",
494
494
  }
495
495
 
496
496
  _HERMES_ENFORCEMENT_HOOKS = [
@@ -29,6 +29,8 @@ from collections.abc import Iterator
29
29
 
30
30
  import httpx
31
31
 
32
+ from runlayer_cli.flow_contract import status_category
33
+
32
34
  if sys.version_info >= (3, 11):
33
35
  import builtins
34
36
 
@@ -92,20 +94,6 @@ def iter_exception_tree(
92
94
  queue.extend(link for link in links if id(link) not in seen)
93
95
 
94
96
 
95
- def _status_category(status_code: int) -> str:
96
- if status_code == 401:
97
- return "http_401"
98
- if status_code == 403:
99
- return "http_403"
100
- if status_code == 404:
101
- return "http_404"
102
- if 400 <= status_code < 500:
103
- return "http_4xx"
104
- if 500 <= status_code < 600:
105
- return "http_5xx"
106
- return "other"
107
-
108
-
109
97
  def _classify_single(exc: BaseException) -> tuple[str, int | None]:
110
98
  """Classify exactly one exception object (no chain or group walking)."""
111
99
  # OAuth first: these subclass generic errors (OAuthCallbackTimeoutError is
@@ -121,7 +109,7 @@ def _classify_single(exc: BaseException) -> tuple[str, int | None]:
121
109
  return ("other", None)
122
110
  if 400 <= status_code < 500:
123
111
  return ("oauth_registration_rejected", status_code)
124
- return (_status_category(status_code), status_code)
112
+ return (status_category(status_code), status_code)
125
113
  if isinstance(exc, OAuthCallbackTimeoutError):
126
114
  return ("oauth_flow_timeout", None)
127
115
  # Device-local listener failures (occupied cached port, loopback policy)
@@ -138,7 +126,7 @@ def _classify_single(exc: BaseException) -> tuple[str, int | None]:
138
126
 
139
127
  if isinstance(exc, httpx.HTTPStatusError):
140
128
  status_code = exc.response.status_code
141
- return (_status_category(status_code), status_code)
129
+ return (status_category(status_code), status_code)
142
130
 
143
131
  if isinstance(exc, httpx.ConnectTimeout):
144
132
  return ("connect_timeout", None)
@@ -144,6 +144,25 @@ CLIENT_FLOW_HOOK_EVENTS: frozenset[str] = frozenset(
144
144
  )
145
145
 
146
146
 
147
+ def status_category(status_code: int) -> str:
148
+ """Map an HTTP status to its ``CLIENT_FLOW_ERROR_CATEGORIES`` member. Lives
149
+ here (stdlib-only, already inside the hook import closure) rather than in
150
+ ``error_classification`` so the relay's non-2xx path does not drag the MCP
151
+ client stack into the packaged hook."""
152
+ category = "other"
153
+ if status_code == 401:
154
+ category = "http_401"
155
+ elif status_code == 403:
156
+ category = "http_403"
157
+ elif status_code == 404:
158
+ category = "http_404"
159
+ elif 400 <= status_code < 500:
160
+ category = "http_4xx"
161
+ elif 500 <= status_code < 600:
162
+ category = "http_5xx"
163
+ return category
164
+
165
+
147
166
  def build_envelope(flows: list[dict[str, Any]], dropped: int) -> dict[str, Any]:
148
167
  """Wire envelope attached to existing request bodies as ``client_flows``.
149
168
 
@@ -124,7 +124,7 @@ def normalize_event_name(event: str) -> str:
124
124
  _POST_TOOL_EVENTS = frozenset({"PostToolUse", "PostToolUseFailure"})
125
125
 
126
126
  # Session events whose hook output may add model-visible context.
127
- _CONTEXT_EVENTS = frozenset({"SessionStart", "UserPromptSubmit"})
127
+ _CONTEXT_EVENTS = frozenset({"SessionStart"})
128
128
  _CONTEXT_CLIENTS = frozenset({Client.CLAUDE_CODE, Client.CODEX})
129
129
 
130
130
  # Cline parses stdout by scanning for lines prefixed ``HOOK_CONTROL\t`` (last one
@@ -762,7 +762,7 @@ class HookResponse:
762
762
  """Allow a session event and add model-visible context.
763
763
 
764
764
  Claude Code and Codex share the ``hookSpecificOutput.additionalContext``
765
- contract on session start and prompt submit.
765
+ contract on session start.
766
766
  """
767
767
  if self._client in _CONTEXT_CLIENTS and self._event in _CONTEXT_EVENTS:
768
768
  return json.dumps(
@@ -9,7 +9,7 @@ import time
9
9
  from collections.abc import Callable
10
10
  from dataclasses import dataclass
11
11
  from pathlib import Path
12
- from typing import Any, NoReturn, cast
12
+ from typing import Any, NoReturn, cast, Literal
13
13
 
14
14
  from runlayer_cli import __version__, flow_spool, flow_trace, regex_safe
15
15
  from runlayer_cli.hook import credential_state, hook_io, host_override, messages
@@ -52,6 +52,7 @@ from runlayer_cli.hook.mcp_lookup import (
52
52
  resolve_hermes_mcp_tool,
53
53
  )
54
54
  from runlayer_cli.hook.failure import FailureContext
55
+ from runlayer_cli.flow_contract import status_category
55
56
  from runlayer_cli.hook.relay import (
56
57
  RelayError,
57
58
  check_tool_lifecycle,
@@ -173,18 +174,52 @@ def _policy_violation(check: Callable[[], None]) -> FilePolicyViolation | None:
173
174
  return None
174
175
 
175
176
 
176
- def _credential_deny_kwargs(failure: FailureContext | None) -> dict[str, Any]:
177
- """Hostname + credential kind for the 401 deny only; empty otherwise."""
177
+ def _device_deny_kwargs(failure: FailureContext | None) -> dict[str, Any]:
178
+ """Device context for denies that name the device: hostname + credential
179
+ kind for Runlayer's 401, hostname alone for a network rejection (the block
180
+ is per device, so IT needs the hostname; no credential was judged)."""
181
+ kwargs: dict[str, Any] = {}
182
+ if failure is not None and failure.kind == "http":
183
+ if failure.is_network_rejection:
184
+ kwargs = {"hostname": device_hostname()}
185
+ elif failure.status_code == credential_state.CREDENTIAL_REJECTED_STATUS:
186
+ kwargs = {
187
+ "hostname": device_hostname(),
188
+ "managed_credential": uses_managed_credential(),
189
+ }
190
+ return kwargs
191
+
192
+
193
+ _InfraDenyErrorType = Literal["HookNetworkDeny", "HookInfraDeny"]
194
+
195
+
196
+ def _mark_infra_deny(failure: FailureContext | None, *, override: bool) -> None:
197
+ """Mark the flow for a fail-closed relay deny. This is where the flow
198
+ learns the HTTP category of a deny. The relay marks only Runlayer's own
199
+ 401 (the credential verdict, see ``relay._note_credential_rejection``);
200
+ every other non-2xx is left unmarked there because some are recovered
201
+ (gzip identity retry) or swallowed by best-effort callers and must not
202
+ count as failed flows in the hook-reliability alerts."""
203
+ kwargs: dict[str, Any] = {}
178
204
  if (
179
- failure is None
180
- or failure.kind != "http"
181
- or failure.status_code != credential_state.CREDENTIAL_REJECTED_STATUS
205
+ failure is not None
206
+ and failure.kind == "http"
207
+ and failure.status_code is not None
182
208
  ):
183
- return {}
184
- return {
185
- "hostname": device_hostname(),
186
- "managed_credential": uses_managed_credential(),
187
- }
209
+ kwargs = {
210
+ "category": status_category(failure.status_code),
211
+ "http_status": failure.status_code,
212
+ }
213
+ flow_trace.mark_error(_infra_deny_error_type(failure), override=override, **kwargs)
214
+
215
+
216
+ def _infra_deny_error_type(failure: FailureContext | None) -> _InfraDenyErrorType:
217
+ """Flow error type for a fail-closed relay deny: ``HookNetworkDeny`` when
218
+ an intermediary rejected the request (nothing reached Runlayer), else
219
+ ``HookInfraDeny``. Log-only labels (see the hook-reliability alert rules),
220
+ so per-customer triage can split "our 4xx" from "their edge 4xx"."""
221
+ is_network = failure is not None and failure.is_network_rejection
222
+ return "HookNetworkDeny" if is_network else "HookInfraDeny"
188
223
 
189
224
 
190
225
  # Flow error type for "Monitor device, credentials rejected, call allowed".
@@ -790,11 +825,11 @@ def _check_tool_lifecycle(
790
825
  flow_trace.mark_error("HookAuthRequired", override=True)
791
826
  u, a = messages.tool_auth_required(tool_name=tool_name)
792
827
  else:
793
- flow_trace.mark_error("HookInfraDeny", override=True)
828
+ _mark_infra_deny(e.failure, override=True)
794
829
  u, a = messages.tool_api_unreachable(
795
830
  tool_name=tool_name,
796
831
  failure=e.failure,
797
- **_credential_deny_kwargs(e.failure),
832
+ **_device_deny_kwargs(e.failure),
798
833
  )
799
834
  if target == "tool-post":
800
835
  _write(
@@ -1149,15 +1184,12 @@ _PLUGIN_CONTEXT_CLIENTS = frozenset({Client.CLAUDE_CODE, Client.CODEX})
1149
1184
 
1150
1185
 
1151
1186
  def _plugin_context_output(ctx: _DispatchCtx) -> str | None:
1152
- """Session/prompt output carrying Runlayer Plugin routing rules.
1187
+ """Session-start output carrying Runlayer Plugin routing rules.
1153
1188
 
1154
- None when the client or event has no context slot, or the built-in plugin
1155
- is not configured for this session, so callers fall back to plain allow.
1189
+ None when the client has no context slot, or the built-in plugin is not
1190
+ configured for this session, so the caller falls back to plain output.
1156
1191
  """
1157
- if ctx.client not in _PLUGIN_CONTEXT_CLIENTS or ctx.hook_type not in (
1158
- "SessionStart",
1159
- "UserPromptSubmit",
1160
- ):
1192
+ if ctx.client not in _PLUGIN_CONTEXT_CLIENTS:
1161
1193
  return None
1162
1194
  cwd = ctx.input_data.get("cwd", "") or hook_io.getcwd()
1163
1195
  context = build_plugin_context(ctx.client, cwd)
@@ -1182,7 +1214,7 @@ def _handle_session_event(ctx: _DispatchCtx) -> None:
1182
1214
  forward_event(
1183
1215
  ctx.client.value, ctx.original_hook_type, ctx.input_data, debug=ctx.debug
1184
1216
  )
1185
- _write(_plugin_context_output(ctx) or ctx.resp.allow())
1217
+ _write(ctx.resp.allow())
1186
1218
 
1187
1219
 
1188
1220
  def _handle_post_tool_use(ctx: _DispatchCtx) -> None:
@@ -1557,7 +1589,7 @@ def _mcp_enforce_and_respond(
1557
1589
  elif mode is AIWatchMode.PROTECT:
1558
1590
  flow_trace.mark_error("HookInfraFailOpen")
1559
1591
  else:
1560
- flow_trace.mark_error("HookInfraDeny")
1592
+ _mark_infra_deny(e.failure, override=False)
1561
1593
  if mode is AIWatchMode.PROTECT:
1562
1594
  return _allow_protect_failure()
1563
1595
  if e.exit_code == 1:
@@ -1566,7 +1598,7 @@ def _mcp_enforce_and_respond(
1566
1598
  u, a = messages.api_unreachable(
1567
1599
  tool_name=tool_name,
1568
1600
  failure=e.failure,
1569
- **_credential_deny_kwargs(e.failure),
1601
+ **_device_deny_kwargs(e.failure),
1570
1602
  )
1571
1603
  _deny_and_exit(resp, u, a)
1572
1604
 
@@ -0,0 +1,205 @@
1
+ """Relay failure classification shared by the relay and deny-message rendering.
2
+
3
+ Extracted from ``hook/relay.py`` (ENG-5365) so ``messages.py`` can import the
4
+ context type at runtime without pulling the whole relay module. Keep this
5
+ module stdlib + httpx only.
6
+ """
7
+
8
+ from __future__ import annotations
9
+
10
+ import json
11
+ from dataclasses import dataclass
12
+ from typing import Any, Literal, NamedTuple
13
+
14
+ import httpx
15
+
16
+ # Closed vocabulary for FailureContext.kind. messages._unreachable_cause has a
17
+ # rendering branch per kind (contract-tested); a kind added here without one
18
+ # falls back to the generic legacy message.
19
+ FailureKind = Literal["connect", "upload_timeout", "upload_failed", "timeout", "http"]
20
+
21
+ # Who answered a non-2xx. ``"runlayer"``: the Runlayer application (its error
22
+ # responses carry ``X-Runlayer-Origin`` and ``X-Request-ID`` and a JSON
23
+ # ``{"detail": ...}`` body). ``"intermediary"``: something in front of it — an
24
+ # AWS WAF IP-allowlist block, an ALB error page, a corporate proxy — which
25
+ # returns the same status codes with an HTML body and neither header. The
26
+ # distinction decides both wording (a WAF 403 is a network rejection, not a
27
+ # Runlayer policy decision) and whether a 401 may touch the credential caches
28
+ # (an intermediary 401 says nothing about the Runlayer credential).
29
+ ResponseOrigin = Literal["runlayer", "intermediary"]
30
+
31
+ # Header names the backend stamps on every error response it answers. The
32
+ # origin header's value is a fixed literal; only its presence is inspected.
33
+ ORIGIN_HEADER_NAME = "X-Runlayer-Origin"
34
+ REQUEST_ID_HEADER_NAME = "X-Request-ID"
35
+
36
+ # Statuses an intermediary can answer that would otherwise read as a Runlayer
37
+ # credential (401) or policy (403) decision. Other intermediary statuses (an
38
+ # ALB 5xx with no healthy target, a proxy 429) keep the generic
39
+ # answered-request wording, which blames the request, not Runlayer.
40
+ NETWORK_REJECT_STATUSES = frozenset({401, 403})
41
+
42
+ # Server-supplied text is rendered into the deny reason, so it is bounded and
43
+ # reduced to printable characters; a request id is only echoed when it looks
44
+ # like one.
45
+ _MAX_DETAIL_CHARS = 200
46
+ _MAX_REQUEST_ID_CHARS = 64
47
+ _REQUEST_ID_CHARS = frozenset(
48
+ "ABCDEFGHIJKLMNOPQRSTUVWXYZabcdefghijklmnopqrstuvwxyz0123456789._:-"
49
+ )
50
+
51
+
52
+ @dataclass(frozen=True, slots=True)
53
+ class FailureContext:
54
+ """What a failed relay POST knew at the moment it failed (ENG-5197).
55
+
56
+ ``kind``: ``"connect"`` (no connection acquired — includes pool
57
+ exhaustion), ``"upload_timeout"`` (body still uploading when the write
58
+ timed out), ``"upload_failed"`` (connection dropped while the body was
59
+ uploading), ``"timeout"`` (request sent, no response in time), ``"http"``
60
+ (non-2xx, see ``status_code``), or ``None`` (unclassified). ``payload_bytes``
61
+ is the UTF-8 wire size of the request body; ``elapsed_s`` is time spent in
62
+ the POST before it failed (all attempts, retries included);
63
+ ``attempts`` is how many attempts ran before giving up (1 = no retry).
64
+ Carried whole on ``RelayError`` so new fields never need re-threading
65
+ through call sites.
66
+ """
67
+
68
+ kind: FailureKind | None = None
69
+ payload_bytes: int | None = None
70
+ elapsed_s: float | None = None
71
+ status_code: int | None = None
72
+ attempts: int = 1
73
+ # ``kind == "http"`` only. ``None`` = unclassified (a transport without
74
+ # headers, or callers that predate classification): status-only wording,
75
+ # treated as Runlayer.
76
+ origin: ResponseOrigin | None = None
77
+ # Echoed only for a Runlayer-origin response, so support can find the
78
+ # server-side log line. Already shape-checked and bounded.
79
+ request_id: str | None = None
80
+ # The backend's ``detail`` string, sanitized and bounded; never set for an
81
+ # intermediary (its body is untrusted HTML and is not rendered).
82
+ detail: str | None = None
83
+
84
+ @property
85
+ def is_network_rejection(self) -> bool:
86
+ """An HTTP 401/403 attributed to an intermediary: worded as a network
87
+ rejection, and no credential state may be touched."""
88
+ return (
89
+ self.kind == "http"
90
+ and self.origin == "intermediary"
91
+ and self.status_code in NETWORK_REJECT_STATUSES
92
+ )
93
+
94
+
95
+ class ResponseOriginInfo(NamedTuple):
96
+ origin: ResponseOrigin | None
97
+ request_id: str | None
98
+ detail: str | None
99
+
100
+
101
+ _UNCLASSIFIED = ResponseOriginInfo(None, None, None)
102
+ _INTERMEDIARY = ResponseOriginInfo("intermediary", None, None)
103
+
104
+
105
+ def _sanitize_detail(value: Any) -> str | None:
106
+ if not isinstance(value, str):
107
+ return None
108
+ printable = "".join(c if c.isprintable() else " " for c in value)
109
+ cleaned = " ".join(printable.split())
110
+ if len(cleaned) > _MAX_DETAIL_CHARS:
111
+ cleaned = cleaned[: _MAX_DETAIL_CHARS - 1].rstrip() + "…"
112
+ return cleaned or None
113
+
114
+
115
+ def _request_id(headers: Any) -> str | None:
116
+ value = headers.get(REQUEST_ID_HEADER_NAME)
117
+ if not isinstance(value, str):
118
+ return None
119
+ value = value.strip()
120
+ is_token = (
121
+ 0 < len(value) <= _MAX_REQUEST_ID_CHARS and set(value) <= _REQUEST_ID_CHARS
122
+ )
123
+ return value if is_token else None
124
+
125
+
126
+ def _error_envelope(text: Any) -> dict[str, Any] | None:
127
+ """The backend's ``{"detail": ...}`` body, or ``None`` for anything else
128
+ (HTML, non-object JSON, unparseable). ``detail`` may be a list (422); the
129
+ envelope shape is what proves the origin, the caller decides what to
130
+ render. ``json.loads`` can raise more than ``ValueError`` on hostile input
131
+ (``RecursionError`` on deep nesting), so anything it raises means "not an
132
+ envelope"."""
133
+ if not isinstance(text, str) or not text:
134
+ return None
135
+ try:
136
+ body = json.loads(text)
137
+ except Exception:
138
+ return None
139
+ return body if isinstance(body, dict) and "detail" in body else None
140
+
141
+
142
+ def classify_response_origin(resp: Any) -> ResponseOriginInfo:
143
+ """Decide who produced a non-2xx response.
144
+
145
+ Runlayer when the origin header is present, or — for backends predating
146
+ it — when the response carries a request id *and* the JSON error envelope
147
+ (both come from the same handler, so either alone is not enough: proxies
148
+ add request-id headers of their own, and any hop can answer JSON).
149
+ Anything else with headers is an intermediary; a response object without
150
+ headers at all is unclassified. Never raises: classification is garnish
151
+ on a deny that must still be emitted, so any failure inside it also
152
+ yields "unclassified" (the pre-classification behaviour).
153
+ """
154
+ headers = getattr(resp, "headers", None)
155
+ if headers is None:
156
+ return _UNCLASSIFIED
157
+ try:
158
+ request_id = _request_id(headers)
159
+ envelope = _error_envelope(getattr(resp, "text", None))
160
+ marked = headers.get(ORIGIN_HEADER_NAME) is not None
161
+ except Exception:
162
+ return _UNCLASSIFIED
163
+ if marked or (request_id is not None and envelope is not None):
164
+ detail = _sanitize_detail(envelope.get("detail")) if envelope else None
165
+ return ResponseOriginInfo("runlayer", request_id, detail)
166
+ return _INTERMEDIARY
167
+
168
+
169
+ def _safe_wire_size(payload: str | bytes) -> int | None:
170
+ """Byte size of the body as sent (UTF-8, post-compression when compressed),
171
+ or ``None`` if the encode itself fails.
172
+
173
+ A compressed body is already bytes, so sizing it is O(1). The str encode
174
+ allocates a full copy of a potentially multi-MB body; under memory
175
+ pressure it can raise. Size is diagnostic garnish — it must never be the
176
+ reason a deny path stops denying (fail-closed depends on ``RelayError``
177
+ actually being raised).
178
+ """
179
+ try:
180
+ if isinstance(payload, bytes):
181
+ return len(payload)
182
+ return len(payload.encode("utf-8"))
183
+ except Exception:
184
+ return None
185
+
186
+
187
+ def _classify_network_failure(exc: Exception) -> FailureKind | None:
188
+ """Map an httpx transport exception to a ``FailureContext.kind``.
189
+
190
+ ``WriteTimeout``/``WriteError`` both prove the body was still in flight
191
+ (timed out vs connection dropped — the latter is the signature of the
192
+ stalled uploads the ALB reaps). ``PoolTimeout`` means no connection was
193
+ ever acquired (shared-client saturation), so it is "connect", not
194
+ "timeout": only read timeouts mean the request was sent with no response
195
+ in time. Non-httpx exceptions stay unclassified rather than guessing.
196
+ """
197
+ if isinstance(exc, httpx.WriteTimeout):
198
+ return "upload_timeout"
199
+ if isinstance(exc, httpx.WriteError):
200
+ return "upload_failed"
201
+ if isinstance(exc, httpx.ConnectError | httpx.ConnectTimeout | httpx.PoolTimeout):
202
+ return "connect"
203
+ if isinstance(exc, httpx.TimeoutException):
204
+ return "timeout"
205
+ return None