controlzero 1.11.5__tar.gz → 1.11.6__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.
- {controlzero-1.11.5 → controlzero-1.11.6}/CHANGELOG.md +38 -0
- {controlzero-1.11.5 → controlzero-1.11.6}/PKG-INFO +1 -1
- {controlzero-1.11.5 → controlzero-1.11.6}/controlzero/__init__.py +1 -1
- controlzero-1.11.6/controlzero/__main__.py +23 -0
- {controlzero-1.11.5 → controlzero-1.11.6}/controlzero/cli/__main__.py +6 -1
- {controlzero-1.11.5 → controlzero-1.11.6}/controlzero/cli/hosts/antigravity.py +67 -19
- {controlzero-1.11.5 → controlzero-1.11.6}/controlzero/cli/kiro_adapter.py +52 -6
- {controlzero-1.11.5 → controlzero-1.11.6}/controlzero/cli/main.py +497 -10
- {controlzero-1.11.5 → controlzero-1.11.6}/controlzero/cli/templates/antigravity.yaml +14 -0
- {controlzero-1.11.5 → controlzero-1.11.6}/controlzero/cli/templates/claude-code.yaml +14 -0
- {controlzero-1.11.5 → controlzero-1.11.6}/controlzero/cli/templates/codex-cli.yaml +14 -0
- {controlzero-1.11.5 → controlzero-1.11.6}/controlzero/cli/templates/cursor.yaml +14 -0
- {controlzero-1.11.5 → controlzero-1.11.6}/controlzero/cli/templates/gemini-cli.yaml +14 -0
- {controlzero-1.11.5 → controlzero-1.11.6}/controlzero/cli/templates/generic.yaml +14 -0
- {controlzero-1.11.5 → controlzero-1.11.6}/controlzero/cli/templates/kiro/kiro.yaml +14 -0
- {controlzero-1.11.5 → controlzero-1.11.6}/pyproject.toml +1 -1
- {controlzero-1.11.5 → controlzero-1.11.6}/tests/test_adapter_interface.py +7 -1
- controlzero-1.11.6/tests/test_agy_docs_no_exit2_1373.py +131 -0
- {controlzero-1.11.5 → controlzero-1.11.6}/tests/test_antigravity_adapter.py +182 -3
- {controlzero-1.11.5 → controlzero-1.11.6}/tests/test_antigravity_hook_check.py +4 -3
- controlzero-1.11.6/tests/test_capability_matrix_doc.py +175 -0
- controlzero-1.11.6/tests/test_cli_hook_entry.py +189 -0
- {controlzero-1.11.5 → controlzero-1.11.6}/tests/test_kiro_adapter.py +98 -7
- {controlzero-1.11.5 → controlzero-1.11.6}/tests/test_kiro_cli_hook_pin_1265.py +13 -1
- controlzero-1.11.6/tests/test_kiro_install.py +463 -0
- controlzero-1.11.6/tests/test_probe_audit_isolation.py +177 -0
- controlzero-1.11.5/controlzero/__main__.py +0 -12
- controlzero-1.11.5/tests/test_cli_hook_entry.py +0 -81
- controlzero-1.11.5/tests/test_kiro_install.py +0 -75
- {controlzero-1.11.5 → controlzero-1.11.6}/.gitignore +0 -0
- {controlzero-1.11.5 → controlzero-1.11.6}/Dockerfile.test +0 -0
- {controlzero-1.11.5 → controlzero-1.11.6}/LICENSE +0 -0
- {controlzero-1.11.5 → controlzero-1.11.6}/README.md +0 -0
- {controlzero-1.11.5 → controlzero-1.11.6}/controlzero/_internal/__init__.py +0 -0
- {controlzero-1.11.5 → controlzero-1.11.6}/controlzero/_internal/action_aliases.py +0 -0
- {controlzero-1.11.5 → controlzero-1.11.6}/controlzero/_internal/action_validator.py +0 -0
- {controlzero-1.11.5 → controlzero-1.11.6}/controlzero/_internal/bundle.py +0 -0
- {controlzero-1.11.5 → controlzero-1.11.6}/controlzero/_internal/credential_hook.py +0 -0
- {controlzero-1.11.5 → controlzero-1.11.6}/controlzero/_internal/credential_scanner.py +0 -0
- {controlzero-1.11.5 → controlzero-1.11.6}/controlzero/_internal/credentials_data/__init__.py +0 -0
- {controlzero-1.11.5 → controlzero-1.11.6}/controlzero/_internal/credentials_data/built_in.yaml +0 -0
- {controlzero-1.11.5 → controlzero-1.11.6}/controlzero/_internal/dlp_scanner.py +0 -0
- {controlzero-1.11.5 → controlzero-1.11.6}/controlzero/_internal/enforcer.py +0 -0
- {controlzero-1.11.5 → controlzero-1.11.6}/controlzero/_internal/hook_extractors.py +0 -0
- {controlzero-1.11.5 → controlzero-1.11.6}/controlzero/_internal/tool_extractors.json +0 -0
- {controlzero-1.11.5 → controlzero-1.11.6}/controlzero/_internal/types.py +0 -0
- {controlzero-1.11.5 → controlzero-1.11.6}/controlzero/audit_local.py +0 -0
- {controlzero-1.11.5 → controlzero-1.11.6}/controlzero/audit_remote.py +0 -0
- {controlzero-1.11.5 → controlzero-1.11.6}/controlzero/canonical.py +0 -0
- {controlzero-1.11.5 → controlzero-1.11.6}/controlzero/cli/__init__.py +0 -0
- {controlzero-1.11.5 → controlzero-1.11.6}/controlzero/cli/_secrets.py +0 -0
- {controlzero-1.11.5 → controlzero-1.11.6}/controlzero/cli/console.py +0 -0
- {controlzero-1.11.5 → controlzero-1.11.6}/controlzero/cli/debug_bundle.py +0 -0
- {controlzero-1.11.5 → controlzero-1.11.6}/controlzero/cli/doctor.py +0 -0
- {controlzero-1.11.5 → controlzero-1.11.6}/controlzero/cli/exec_cmd.py +0 -0
- {controlzero-1.11.5 → controlzero-1.11.6}/controlzero/cli/hook_entry.py +0 -0
- {controlzero-1.11.5 → controlzero-1.11.6}/controlzero/cli/hosts/__init__.py +0 -0
- {controlzero-1.11.5 → controlzero-1.11.6}/controlzero/cli/hosts/base.py +0 -0
- {controlzero-1.11.5 → controlzero-1.11.6}/controlzero/cli/hosts/claude_code.py +0 -0
- {controlzero-1.11.5 → controlzero-1.11.6}/controlzero/cli/hosts/codex_cli.py +0 -0
- {controlzero-1.11.5 → controlzero-1.11.6}/controlzero/cli/hosts/cursor.py +0 -0
- {controlzero-1.11.5 → controlzero-1.11.6}/controlzero/cli/hosts/cursor_cli.py +0 -0
- {controlzero-1.11.5 → controlzero-1.11.6}/controlzero/cli/hosts/gemini_cli.py +0 -0
- {controlzero-1.11.5 → controlzero-1.11.6}/controlzero/cli/hosts/kiro.py +0 -0
- {controlzero-1.11.5 → controlzero-1.11.6}/controlzero/cli/hosts/unknown.py +0 -0
- {controlzero-1.11.5 → controlzero-1.11.6}/controlzero/cli/migrate.py +0 -0
- {controlzero-1.11.5 → controlzero-1.11.6}/controlzero/cli/spool_cmd.py +0 -0
- {controlzero-1.11.5 → controlzero-1.11.6}/controlzero/cli/telemetry_consent.py +0 -0
- {controlzero-1.11.5 → controlzero-1.11.6}/controlzero/cli/templates/antigravity/hooks.json +0 -0
- {controlzero-1.11.5 → controlzero-1.11.6}/controlzero/cli/templates/autogen.yaml +0 -0
- {controlzero-1.11.5 → controlzero-1.11.6}/controlzero/cli/templates/cost-cap.yaml +0 -0
- {controlzero-1.11.5 → controlzero-1.11.6}/controlzero/cli/templates/crewai.yaml +0 -0
- {controlzero-1.11.5 → controlzero-1.11.6}/controlzero/cli/templates/kiro/ide-file-save.kiro.hook +0 -0
- {controlzero-1.11.5 → controlzero-1.11.6}/controlzero/cli/templates/kiro/ide-pre-tool-use.kiro.hook +0 -0
- {controlzero-1.11.5 → controlzero-1.11.6}/controlzero/cli/templates/kiro/ide-prompt-submit.kiro.hook +0 -0
- {controlzero-1.11.5 → controlzero-1.11.6}/controlzero/cli/templates/langchain.yaml +0 -0
- {controlzero-1.11.5 → controlzero-1.11.6}/controlzero/cli/templates/mcp.yaml +0 -0
- {controlzero-1.11.5 → controlzero-1.11.6}/controlzero/cli/templates/rag.yaml +0 -0
- {controlzero-1.11.5 → controlzero-1.11.6}/controlzero/cli/update_cmd.py +0 -0
- {controlzero-1.11.5 → controlzero-1.11.6}/controlzero/client.py +0 -0
- {controlzero-1.11.5 → controlzero-1.11.6}/controlzero/device.py +0 -0
- {controlzero-1.11.5 → controlzero-1.11.6}/controlzero/enrollment.py +0 -0
- {controlzero-1.11.5 → controlzero-1.11.6}/controlzero/error_codes.py +0 -0
- {controlzero-1.11.5 → controlzero-1.11.6}/controlzero/error_codes.yaml +0 -0
- {controlzero-1.11.5 → controlzero-1.11.6}/controlzero/errors.py +0 -0
- {controlzero-1.11.5 → controlzero-1.11.6}/controlzero/hitl/__init__.py +0 -0
- {controlzero-1.11.5 → controlzero-1.11.6}/controlzero/hitl/grant_protocol.py +0 -0
- {controlzero-1.11.5 → controlzero-1.11.6}/controlzero/hitl/mock.py +0 -0
- {controlzero-1.11.5 → controlzero-1.11.6}/controlzero/hitl/pending_approval.py +0 -0
- {controlzero-1.11.5 → controlzero-1.11.6}/controlzero/hitl/secret_leak_guard.py +0 -0
- {controlzero-1.11.5 → controlzero-1.11.6}/controlzero/hitl/status.py +0 -0
- {controlzero-1.11.5 → controlzero-1.11.6}/controlzero/hooks/__init__.py +0 -0
- {controlzero-1.11.5 → controlzero-1.11.6}/controlzero/hooks/tool_output_handler.py +0 -0
- {controlzero-1.11.5 → controlzero-1.11.6}/controlzero/hosted_policy.py +0 -0
- {controlzero-1.11.5 → controlzero-1.11.6}/controlzero/integrations/__init__.py +0 -0
- {controlzero-1.11.5 → controlzero-1.11.6}/controlzero/integrations/anthropic.py +0 -0
- {controlzero-1.11.5 → controlzero-1.11.6}/controlzero/integrations/autogen.py +0 -0
- {controlzero-1.11.5 → controlzero-1.11.6}/controlzero/integrations/braintrust.py +0 -0
- {controlzero-1.11.5 → controlzero-1.11.6}/controlzero/integrations/crewai/__init__.py +0 -0
- {controlzero-1.11.5 → controlzero-1.11.6}/controlzero/integrations/crewai/agent.py +0 -0
- {controlzero-1.11.5 → controlzero-1.11.6}/controlzero/integrations/crewai/crew.py +0 -0
- {controlzero-1.11.5 → controlzero-1.11.6}/controlzero/integrations/crewai/task.py +0 -0
- {controlzero-1.11.5 → controlzero-1.11.6}/controlzero/integrations/crewai/tool.py +0 -0
- {controlzero-1.11.5 → controlzero-1.11.6}/controlzero/integrations/google.py +0 -0
- {controlzero-1.11.5 → controlzero-1.11.6}/controlzero/integrations/google_adk/__init__.py +0 -0
- {controlzero-1.11.5 → controlzero-1.11.6}/controlzero/integrations/google_adk/agent.py +0 -0
- {controlzero-1.11.5 → controlzero-1.11.6}/controlzero/integrations/google_adk/tool.py +0 -0
- {controlzero-1.11.5 → controlzero-1.11.6}/controlzero/integrations/langchain/__init__.py +0 -0
- {controlzero-1.11.5 → controlzero-1.11.6}/controlzero/integrations/langchain/agent.py +0 -0
- {controlzero-1.11.5 → controlzero-1.11.6}/controlzero/integrations/langchain/callbacks.py +0 -0
- {controlzero-1.11.5 → controlzero-1.11.6}/controlzero/integrations/langchain/chain.py +0 -0
- {controlzero-1.11.5 → controlzero-1.11.6}/controlzero/integrations/langchain/graph.py +0 -0
- {controlzero-1.11.5 → controlzero-1.11.6}/controlzero/integrations/langchain/modern.py +0 -0
- {controlzero-1.11.5 → controlzero-1.11.6}/controlzero/integrations/langchain/tool.py +0 -0
- {controlzero-1.11.5 → controlzero-1.11.6}/controlzero/integrations/langfuse.py +0 -0
- {controlzero-1.11.5 → controlzero-1.11.6}/controlzero/integrations/litellm.py +0 -0
- {controlzero-1.11.5 → controlzero-1.11.6}/controlzero/integrations/openai.py +0 -0
- {controlzero-1.11.5 → controlzero-1.11.6}/controlzero/integrations/pydantic_ai.py +0 -0
- {controlzero-1.11.5 → controlzero-1.11.6}/controlzero/integrations/vercel_ai.py +0 -0
- {controlzero-1.11.5 → controlzero-1.11.6}/controlzero/layout_migration.py +0 -0
- {controlzero-1.11.5 → controlzero-1.11.6}/controlzero/policy_loader.py +0 -0
- {controlzero-1.11.5 → controlzero-1.11.6}/controlzero/secrets/__init__.py +0 -0
- {controlzero-1.11.5 → controlzero-1.11.6}/controlzero/secrets/reference.py +0 -0
- {controlzero-1.11.5 → controlzero-1.11.6}/controlzero/secrets/resolver.py +0 -0
- {controlzero-1.11.5 → controlzero-1.11.6}/controlzero/secrets/secretstr.py +0 -0
- {controlzero-1.11.5 → controlzero-1.11.6}/controlzero/spool/__init__.py +0 -0
- {controlzero-1.11.5 → controlzero-1.11.6}/controlzero/spool/_compress.py +0 -0
- {controlzero-1.11.5 → controlzero-1.11.6}/controlzero/spool/_constants.py +0 -0
- {controlzero-1.11.5 → controlzero-1.11.6}/controlzero/spool/_crc32c.py +0 -0
- {controlzero-1.11.5 → controlzero-1.11.6}/controlzero/spool/_crypto.py +0 -0
- {controlzero-1.11.5 → controlzero-1.11.6}/controlzero/spool/_frame.py +0 -0
- {controlzero-1.11.5 → controlzero-1.11.6}/controlzero/spool/_keyring.py +0 -0
- {controlzero-1.11.5 → controlzero-1.11.6}/controlzero/spool/_metrics.py +0 -0
- {controlzero-1.11.5 → controlzero-1.11.6}/controlzero/spool/_spool.py +0 -0
- {controlzero-1.11.5 → controlzero-1.11.6}/controlzero/spool/_state.py +0 -0
- {controlzero-1.11.5 → controlzero-1.11.6}/controlzero/spool/_uploader.py +0 -0
- {controlzero-1.11.5 → controlzero-1.11.6}/controlzero/spool/cz-audit-v1.dict +0 -0
- {controlzero-1.11.5 → controlzero-1.11.6}/controlzero/tamper.py +0 -0
- {controlzero-1.11.5 → controlzero-1.11.6}/controlzero/tracecontext.py +0 -0
- {controlzero-1.11.5 → controlzero-1.11.6}/examples/hello_world.py +0 -0
- {controlzero-1.11.5 → controlzero-1.11.6}/tests/_fixtures/antigravity-envelope-expected.json +0 -0
- {controlzero-1.11.5 → controlzero-1.11.6}/tests/_fixtures/jcs_args_hash_vectors.json +0 -0
- {controlzero-1.11.5 → controlzero-1.11.6}/tests/conftest.py +0 -0
- {controlzero-1.11.5 → controlzero-1.11.6}/tests/integrations/__init__.py +0 -0
- {controlzero-1.11.5 → controlzero-1.11.6}/tests/integrations/test_google.py +0 -0
- {controlzero-1.11.5 → controlzero-1.11.6}/tests/parity/action_aliases.json +0 -0
- {controlzero-1.11.5 → controlzero-1.11.6}/tests/spool/__init__.py +0 -0
- {controlzero-1.11.5 → controlzero-1.11.6}/tests/spool/conftest.py +0 -0
- {controlzero-1.11.5 → controlzero-1.11.6}/tests/spool/test_spool_cli.py +0 -0
- {controlzero-1.11.5 → controlzero-1.11.6}/tests/spool/test_spool_concurrency.py +0 -0
- {controlzero-1.11.5 → controlzero-1.11.6}/tests/spool/test_spool_conformance.py +0 -0
- {controlzero-1.11.5 → controlzero-1.11.6}/tests/spool/test_spool_core.py +0 -0
- {controlzero-1.11.5 → controlzero-1.11.6}/tests/spool/test_spool_crash.py +0 -0
- {controlzero-1.11.5 → controlzero-1.11.6}/tests/spool/test_spool_diskfull.py +0 -0
- {controlzero-1.11.5 → controlzero-1.11.6}/tests/spool/test_spool_durable_default_tamper.py +0 -0
- {controlzero-1.11.5 → controlzero-1.11.6}/tests/spool/test_spool_keychain_dek.py +0 -0
- {controlzero-1.11.5 → controlzero-1.11.6}/tests/spool/test_spool_sink_wiring.py +0 -0
- {controlzero-1.11.5 → controlzero-1.11.6}/tests/spool/test_spool_transcript_localack.py +0 -0
- {controlzero-1.11.5 → controlzero-1.11.6}/tests/spool/test_spool_uploader.py +0 -0
- {controlzero-1.11.5 → controlzero-1.11.6}/tests/test_action_aliases.py +0 -0
- {controlzero-1.11.5 → controlzero-1.11.6}/tests/test_action_canonicalization.py +0 -0
- {controlzero-1.11.5 → controlzero-1.11.6}/tests/test_action_validator_t86.py +0 -0
- {controlzero-1.11.5 → controlzero-1.11.6}/tests/test_agent_name_env.py +0 -0
- {controlzero-1.11.5 → controlzero-1.11.6}/tests/test_antigravity_envelope_parity.py +0 -0
- {controlzero-1.11.5 → controlzero-1.11.6}/tests/test_antigravity_ga_blockers_1248.py +0 -0
- {controlzero-1.11.5 → controlzero-1.11.6}/tests/test_antigravity_install.py +0 -0
- {controlzero-1.11.5 → controlzero-1.11.6}/tests/test_antigravity_posttooluse_observe_58.py +0 -0
- {controlzero-1.11.5 → controlzero-1.11.6}/tests/test_antigravity_tool_vocab_1303.py +0 -0
- {controlzero-1.11.5 → controlzero-1.11.6}/tests/test_api_key_mask.py +0 -0
- {controlzero-1.11.5 → controlzero-1.11.6}/tests/test_audit_remote.py +0 -0
- {controlzero-1.11.5 → controlzero-1.11.6}/tests/test_audit_remote_sdk_version.py +0 -0
- {controlzero-1.11.5 → controlzero-1.11.6}/tests/test_audit_sink_isolation.py +0 -0
- {controlzero-1.11.5 → controlzero-1.11.6}/tests/test_bundle_cache_freshness_1303.py +0 -0
- {controlzero-1.11.5 → controlzero-1.11.6}/tests/test_bundle_parser.py +0 -0
- {controlzero-1.11.5 → controlzero-1.11.6}/tests/test_bundle_translate.py +0 -0
- {controlzero-1.11.5 → controlzero-1.11.6}/tests/test_canonical_phase1a.py +0 -0
- {controlzero-1.11.5 → controlzero-1.11.6}/tests/test_cli_carve_out.py +0 -0
- {controlzero-1.11.5 → controlzero-1.11.6}/tests/test_cli_debug_bundle.py +0 -0
- {controlzero-1.11.5 → controlzero-1.11.6}/tests/test_cli_extractor_integration.py +0 -0
- {controlzero-1.11.5 → controlzero-1.11.6}/tests/test_cli_hook.py +0 -0
- {controlzero-1.11.5 → controlzero-1.11.6}/tests/test_cli_hosted_refresh.py +0 -0
- {controlzero-1.11.5 → controlzero-1.11.6}/tests/test_cli_init.py +0 -0
- {controlzero-1.11.5 → controlzero-1.11.6}/tests/test_cli_init_templates.py +0 -0
- {controlzero-1.11.5 → controlzero-1.11.6}/tests/test_cli_tail.py +0 -0
- {controlzero-1.11.5 → controlzero-1.11.6}/tests/test_cli_test.py +0 -0
- {controlzero-1.11.5 → controlzero-1.11.6}/tests/test_cli_validate.py +0 -0
- {controlzero-1.11.5 → controlzero-1.11.6}/tests/test_coding_agent_hooks.py +0 -0
- {controlzero-1.11.5 → controlzero-1.11.6}/tests/test_conditions.py +0 -0
- {controlzero-1.11.5 → controlzero-1.11.6}/tests/test_config_format_parity_1303.py +0 -0
- {controlzero-1.11.5 → controlzero-1.11.6}/tests/test_conformance.py +0 -0
- {controlzero-1.11.5 → controlzero-1.11.6}/tests/test_console.py +0 -0
- {controlzero-1.11.5 → controlzero-1.11.6}/tests/test_credential_hook.py +0 -0
- {controlzero-1.11.5 → controlzero-1.11.6}/tests/test_cursor_adapter.py +0 -0
- {controlzero-1.11.5 → controlzero-1.11.6}/tests/test_default_action.py +0 -0
- {controlzero-1.11.5 → controlzero-1.11.6}/tests/test_device.py +0 -0
- {controlzero-1.11.5 → controlzero-1.11.6}/tests/test_dlp_scanner.py +0 -0
- {controlzero-1.11.5 → controlzero-1.11.6}/tests/test_doctor.py +0 -0
- {controlzero-1.11.5 → controlzero-1.11.6}/tests/test_engine_version_consistency.py +0 -0
- {controlzero-1.11.5 → controlzero-1.11.6}/tests/test_enrollment.py +0 -0
- {controlzero-1.11.5 → controlzero-1.11.6}/tests/test_env_dump_438.py +0 -0
- {controlzero-1.11.5 → controlzero-1.11.6}/tests/test_epic_1247_bryan_acceptance.py +0 -0
- {controlzero-1.11.5 → controlzero-1.11.6}/tests/test_error_codes.py +0 -0
- {controlzero-1.11.5 → controlzero-1.11.6}/tests/test_errors_e_codes.py +0 -0
- {controlzero-1.11.5 → controlzero-1.11.6}/tests/test_fail_closed_eval.py +0 -0
- {controlzero-1.11.5 → controlzero-1.11.6}/tests/test_failopen_1303.py +0 -0
- {controlzero-1.11.5 → controlzero-1.11.6}/tests/test_glob_matching.py +0 -0
- {controlzero-1.11.5 → controlzero-1.11.6}/tests/test_hitl_5d_email_install.py +0 -0
- {controlzero-1.11.5 → controlzero-1.11.6}/tests/test_hitl_6a_cli_flag.py +0 -0
- {controlzero-1.11.5 → controlzero-1.11.6}/tests/test_hitl_6a_exceptions.py +0 -0
- {controlzero-1.11.5 → controlzero-1.11.6}/tests/test_hitl_6a_get_secret_hitl.py +0 -0
- {controlzero-1.11.5 → controlzero-1.11.6}/tests/test_hitl_6a_mock_backend.py +0 -0
- {controlzero-1.11.5 → controlzero-1.11.6}/tests/test_hitl_6a_pending_approval.py +0 -0
- {controlzero-1.11.5 → controlzero-1.11.6}/tests/test_hitl_6a_request_approval.py +0 -0
- {controlzero-1.11.5 → controlzero-1.11.6}/tests/test_hitl_6a_secret_leak_guard.py +0 -0
- {controlzero-1.11.5 → controlzero-1.11.6}/tests/test_hitl_6a_wait.py +0 -0
- {controlzero-1.11.5 → controlzero-1.11.6}/tests/test_hitl_conformance.py +0 -0
- {controlzero-1.11.5 → controlzero-1.11.6}/tests/test_hitl_phase2b_protocol.py +0 -0
- {controlzero-1.11.5 → controlzero-1.11.6}/tests/test_hitl_reason_codes.py +0 -0
- {controlzero-1.11.5 → controlzero-1.11.6}/tests/test_hitl_validator_keys.py +0 -0
- {controlzero-1.11.5 → controlzero-1.11.6}/tests/test_hook_extractors.py +0 -0
- {controlzero-1.11.5 → controlzero-1.11.6}/tests/test_hosted_local_audit_1247.py +0 -0
- {controlzero-1.11.5 → controlzero-1.11.6}/tests/test_hosted_local_shadow_warn_1265.py +0 -0
- {controlzero-1.11.5 → controlzero-1.11.6}/tests/test_hosted_policy_e2e.py +0 -0
- {controlzero-1.11.5 → controlzero-1.11.6}/tests/test_hosts_adapter.py +0 -0
- {controlzero-1.11.5 → controlzero-1.11.6}/tests/test_hybrid_mode_strict.py +0 -0
- {controlzero-1.11.5 → controlzero-1.11.6}/tests/test_hybrid_mode_warn.py +0 -0
- {controlzero-1.11.5 → controlzero-1.11.6}/tests/test_install_hook_command.py +0 -0
- {controlzero-1.11.5 → controlzero-1.11.6}/tests/test_install_hooks.py +0 -0
- {controlzero-1.11.5 → controlzero-1.11.6}/tests/test_kiro_cli_e2e.py +0 -0
- {controlzero-1.11.5 → controlzero-1.11.6}/tests/test_kiro_hook_templates.py +0 -0
- {controlzero-1.11.5 → controlzero-1.11.6}/tests/test_layout_migration_t101.py +0 -0
- {controlzero-1.11.5 → controlzero-1.11.6}/tests/test_layout_parity_t102.py +0 -0
- {controlzero-1.11.5 → controlzero-1.11.6}/tests/test_local_mode_dict.py +0 -0
- {controlzero-1.11.5 → controlzero-1.11.6}/tests/test_local_mode_file_json.py +0 -0
- {controlzero-1.11.5 → controlzero-1.11.6}/tests/test_local_mode_file_yaml.py +0 -0
- {controlzero-1.11.5 → controlzero-1.11.6}/tests/test_log_fallback_stderr.py +0 -0
- {controlzero-1.11.5 → controlzero-1.11.6}/tests/test_log_options_ignored_hosted.py +0 -0
- {controlzero-1.11.5 → controlzero-1.11.6}/tests/test_log_rotation.py +0 -0
- {controlzero-1.11.5 → controlzero-1.11.6}/tests/test_migrate.py +0 -0
- {controlzero-1.11.5 → controlzero-1.11.6}/tests/test_min_sdk_version_gate.py +0 -0
- {controlzero-1.11.5 → controlzero-1.11.6}/tests/test_multi_client_per_project_175.py +0 -0
- {controlzero-1.11.5 → controlzero-1.11.6}/tests/test_no_policy_no_key.py +0 -0
- {controlzero-1.11.5 → controlzero-1.11.6}/tests/test_observe_mode_1247.py +0 -0
- {controlzero-1.11.5 → controlzero-1.11.6}/tests/test_package_rename_shim.py +0 -0
- {controlzero-1.11.5 → controlzero-1.11.6}/tests/test_part3_active_policy_count_1303.py +0 -0
- {controlzero-1.11.5 → controlzero-1.11.6}/tests/test_policy_engine_version_phase1b.py +0 -0
- {controlzero-1.11.5 → controlzero-1.11.6}/tests/test_policy_freshness.py +0 -0
- {controlzero-1.11.5 → controlzero-1.11.6}/tests/test_policy_load_failclosed_f3.py +0 -0
- {controlzero-1.11.5 → controlzero-1.11.6}/tests/test_policy_settings.py +0 -0
- {controlzero-1.11.5 → controlzero-1.11.6}/tests/test_policy_source_audit.py +0 -0
- {controlzero-1.11.5 → controlzero-1.11.6}/tests/test_quarantine.py +0 -0
- {controlzero-1.11.5 → controlzero-1.11.6}/tests/test_reason_code.py +0 -0
- {controlzero-1.11.5 → controlzero-1.11.6}/tests/test_refresh.py +0 -0
- {controlzero-1.11.5 → controlzero-1.11.6}/tests/test_secrets.py +0 -0
- {controlzero-1.11.5 → controlzero-1.11.6}/tests/test_secrets_reference_resolver.py +0 -0
- {controlzero-1.11.5 → controlzero-1.11.6}/tests/test_sql_semantic_class.py +0 -0
- {controlzero-1.11.5 → controlzero-1.11.6}/tests/test_synthetic_policy_id_t79.py +0 -0
- {controlzero-1.11.5 → controlzero-1.11.6}/tests/test_t103_precedence.py +0 -0
- {controlzero-1.11.5 → controlzero-1.11.6}/tests/test_t104_cache_gc.py +0 -0
- {controlzero-1.11.5 → controlzero-1.11.6}/tests/test_t108_local_override_audit.py +0 -0
- {controlzero-1.11.5 → controlzero-1.11.6}/tests/test_t96_single_audit_log.py +0 -0
- {controlzero-1.11.5 → controlzero-1.11.6}/tests/test_t99_install_prefetch_bundle.py +0 -0
- {controlzero-1.11.5 → controlzero-1.11.6}/tests/test_tamper.py +0 -0
- {controlzero-1.11.5 → controlzero-1.11.6}/tests/test_tamper_behavior.py +0 -0
- {controlzero-1.11.5 → controlzero-1.11.6}/tests/test_tamper_hook.py +0 -0
- {controlzero-1.11.5 → controlzero-1.11.6}/tests/test_telemetry_consent.py +0 -0
- {controlzero-1.11.5 → controlzero-1.11.6}/tests/test_tracecontext.py +0 -0
- {controlzero-1.11.5 → controlzero-1.11.6}/tests/test_unsafe_int_boundary.py +0 -0
- {controlzero-1.11.5 → controlzero-1.11.6}/tests/test_update_cmd.py +0 -0
- {controlzero-1.11.5 → controlzero-1.11.6}/tests/test_upgrade_nudge.py +0 -0
- {controlzero-1.11.5 → controlzero-1.11.6}/tools/cz-kiro-adapter +0 -0
|
@@ -1,5 +1,43 @@
|
|
|
1
1
|
# Changelog
|
|
2
2
|
|
|
3
|
+
## 1.11.6 -- 2026-06-21 (cross-surface enforcement hardening: Kiro v3 + Antigravity honesty + warn-mode)
|
|
4
|
+
|
|
5
|
+
Ships the #1373 / #65 cross-surface enforcement work and follow-ups that landed
|
|
6
|
+
after 1.11.5 was published.
|
|
7
|
+
|
|
8
|
+
### Fixed
|
|
9
|
+
|
|
10
|
+
- **Kiro CLI v3 enforcement (#1375 / #1378).** The shipping kiro-cli (>= 2.8.x)
|
|
11
|
+
enforces ONLY via an agent-config `hooks.preToolUse` block on the default
|
|
12
|
+
agent. `controlzero install kiro` now writes `~/.kiro/agents/controlzero.json`
|
|
13
|
+
(matchers `execute_bash` / `fs_write` / `fs_read` / `use_aws`, interpreter-
|
|
14
|
+
pinned `hook-check --strict`) and sets it as the default agent. The legacy v2
|
|
15
|
+
embedded `settings.json` hooks and standalone `.kiro/hooks/*.json` are ignored
|
|
16
|
+
by the shipping CLI. Host-verified on kiro-cli 2.8.1: a denied bash command is
|
|
17
|
+
blocked; an allowed file read proceeds.
|
|
18
|
+
- **Crash-proof hook entry (#1189 / #1377).** `python -m controlzero` and the
|
|
19
|
+
console scripts route through the crash-proof `hook_entry`, so a broken
|
|
20
|
+
install fails CLOSED, not open.
|
|
21
|
+
- **Kiro deciding-gate fail-close (#1377).** A non-{0,2} hook exit is treated as
|
|
22
|
+
a block, not a silent allow.
|
|
23
|
+
- **Antigravity #202 honesty (#1373 / #1377).** The agy adapter is `observe`
|
|
24
|
+
(covered families `file_read` / `file_search`), not a false `enforced` claim;
|
|
25
|
+
it emits the documented stdout `{"decision":...}` envelope. agy default-mode
|
|
26
|
+
enforcement is host-side (COMING SOON), not SDK-fixable.
|
|
27
|
+
- **Audit-probe isolation (#1375 / #1377).** kiro/cursor init + verify self-test
|
|
28
|
+
probes run with an isolated HOME, so synthetic denies never pollute
|
|
29
|
+
`~/.controlzero/audit.log`.
|
|
30
|
+
|
|
31
|
+
### Added
|
|
32
|
+
|
|
33
|
+
- **`default_action` posture toggle is first-class (#1374).** The no-rule-match
|
|
34
|
+
posture (`deny` default | `warn` | `allow`) is documented + surfaced in the
|
|
35
|
+
init templates, with a new deny-list recipe. Comment-only in templates; the
|
|
36
|
+
default stays `deny`.
|
|
37
|
+
- **Kiro sub-agent bypass warning (#7671).** `controlzero install kiro` warns
|
|
38
|
+
that Kiro does not fire preToolUse hooks for sub-agent tool calls (upstream
|
|
39
|
+
kiro #7671) -- direct tool calls are governed, subagent calls are not.
|
|
40
|
+
|
|
3
41
|
## 1.11.5 -- 2026-06-19 (cross-surface CONTROLZERO_CLIENT foreign-pin fail-open)
|
|
4
42
|
|
|
5
43
|
Closes a routing fail-open where an explicit `CONTROLZERO_CLIENT` pin -- set by
|
|
@@ -1,6 +1,6 @@
|
|
|
1
1
|
Metadata-Version: 2.4
|
|
2
2
|
Name: controlzero
|
|
3
|
-
Version: 1.11.
|
|
3
|
+
Version: 1.11.6
|
|
4
4
|
Summary: AI agent governance: policies, audit, and observability for tool calls. Works locally with no signup.
|
|
5
5
|
Project-URL: Homepage, https://controlzero.ai
|
|
6
6
|
Project-URL: Documentation, https://docs.controlzero.ai
|
|
@@ -0,0 +1,23 @@
|
|
|
1
|
+
"""Enable ``python -m controlzero`` to run the CLI.
|
|
2
|
+
|
|
3
|
+
The Kiro CLI / Cursor hook commands pin the interpreter as
|
|
4
|
+
``"<sys.executable>" -m controlzero hook-check --strict`` (#1265) so the host
|
|
5
|
+
invokes the exact, importable controlzero the user installed, never a bare
|
|
6
|
+
``controlzero`` that PATH might resolve to a broken or shadowing install.
|
|
7
|
+
|
|
8
|
+
CRITICAL (#1373 / re-opens #1189): this entry MUST route through the crash-proof
|
|
9
|
+
``hook_entry.cli`` shim, NOT ``controlzero.cli.main:cli`` directly. The
|
|
10
|
+
interpreter-pin made every Kiro/Cursor hook run ``python -m controlzero
|
|
11
|
+
hook-check`` -> this module. A direct unguarded ``from controlzero.cli.main
|
|
12
|
+
import cli`` raises a bare nonzero traceback on a broken/partial install (missing
|
|
13
|
+
transitive dep, packaging defect); Kiro reads any exit code that is neither 0
|
|
14
|
+
nor 2 as "warn / proceed" -> the tool RUNS while audit may log a deny. Routing
|
|
15
|
+
through ``hook_entry.cli`` fails SAFE (exit 2 = block) on an import crash for a
|
|
16
|
+
hook invocation -- closing the exact #1189 fail-open the console script already
|
|
17
|
+
fixed but ``-m controlzero`` had silently bypassed.
|
|
18
|
+
"""
|
|
19
|
+
|
|
20
|
+
from controlzero.cli.hook_entry import cli
|
|
21
|
+
|
|
22
|
+
if __name__ == "__main__":
|
|
23
|
+
cli()
|
|
@@ -3,11 +3,16 @@
|
|
|
3
3
|
Mirrors the ``controlzero`` console-script entry point. Used by
|
|
4
4
|
``controlzero kiro verify`` to invoke hook-check as a subprocess in a way
|
|
5
5
|
that works even when the console script is not on PATH (e.g. CI, venvs).
|
|
6
|
+
|
|
7
|
+
Routes through the crash-proof ``hook_entry.cli`` shim (#1189 / #1373): this is
|
|
8
|
+
a hook-invocation path, so an import crash on a broken install must fail SAFE
|
|
9
|
+
(exit 2 = block), never escape as a bare nonzero traceback that a host reads as
|
|
10
|
+
"warn / proceed".
|
|
6
11
|
"""
|
|
7
12
|
|
|
8
13
|
from __future__ import annotations
|
|
9
14
|
|
|
10
|
-
from controlzero.cli.
|
|
15
|
+
from controlzero.cli.hook_entry import cli
|
|
11
16
|
|
|
12
17
|
if __name__ == "__main__":
|
|
13
18
|
cli()
|
|
@@ -183,26 +183,51 @@ def _resolve_hitl_decision(env: Mapping[str, str] | None = None) -> str:
|
|
|
183
183
|
|
|
184
184
|
class AntigravityAdapter(HostAdapter):
|
|
185
185
|
name = "antigravity"
|
|
186
|
-
# Antigravity
|
|
187
|
-
#
|
|
188
|
-
#
|
|
189
|
-
#
|
|
186
|
+
# Antigravity's documented block contract is the stdout JSON
|
|
187
|
+
# ``{"decision":"deny"}``, NOT the exit code -- so ``decision_via_exit_code``
|
|
188
|
+
# stays False (the base exit-code folding does not apply; this adapter owns
|
|
189
|
+
# its own exit-code rule via ``_exit_code_for`` below).
|
|
190
190
|
decision_via_exit_code = False
|
|
191
191
|
|
|
192
|
-
# Coverage-as-data (#202).
|
|
193
|
-
#
|
|
194
|
-
#
|
|
195
|
-
#
|
|
196
|
-
#
|
|
197
|
-
#
|
|
192
|
+
# Coverage-as-data (#202, #1373). HONESTY: shipped Antigravity (1.0.1 /
|
|
193
|
+
# 1.0.3) does NOT route the run_command / Bash / file-WRITE family through
|
|
194
|
+
# the user PreToolUse hook -- it uses a NATIVE confirmation dialog. Our
|
|
195
|
+
# adapter is therefore never invoked for those destructive calls, so even a
|
|
196
|
+
# perfect deny verdict is never consulted: we CANNOT enforce them. Claiming
|
|
197
|
+
# tier="enforced" over ``covered_tool_families=("*",)`` was a #202 false
|
|
198
|
+
# claim (issue #1373).
|
|
199
|
+
#
|
|
200
|
+
# So the tier is ``observe`` (the not-functional-end-to-end posture this
|
|
201
|
+
# adapter-tier enum carries; mirrors how kiro_ide declares the bounded IDE
|
|
202
|
+
# surface). The maturity story for the shell/file family on the public
|
|
203
|
+
# surfaces is COMING SOON -- not GA/BETA -- until Antigravity ships a real
|
|
204
|
+
# shell-blocking hook path (partner-integration track). ``covered_tool_
|
|
205
|
+
# families`` is narrowed to the families agy actually ROUTES to the hook
|
|
206
|
+
# (reads / observe: file_read, file_search; PostToolUse observe) -- NOT the
|
|
207
|
+
# shell/Bash/file_write family. ``block_mechanism`` is ``stdout_decision``:
|
|
208
|
+
# agy's documented contract is the stdout ``{"decision":"deny"}`` token, and
|
|
209
|
+
# ``decision_via_exit_code=False`` so the exit code stays 0 (a deliberate
|
|
210
|
+
# #1248 decision -- a non-zero hook exit on agy is risky / unverified, so we
|
|
211
|
+
# rely on the documented stdout deny, which blocks).
|
|
212
|
+
#
|
|
213
|
+
# CRITICAL still holds: agy reads an empty / decision-less stdout as
|
|
214
|
+
# invalid_args -> DENY, so empty_stdout_is="deny" and the render envelope
|
|
215
|
+
# ALWAYS carries an explicit decision.
|
|
198
216
|
coverage = CoverageDecl(
|
|
199
|
-
tier="
|
|
217
|
+
tier="observe",
|
|
200
218
|
block_mechanism="stdout_decision",
|
|
201
219
|
deciding_events=("PreToolUse",),
|
|
202
220
|
observe_events=("PostToolUse", "PostInvocation", "Stop"),
|
|
203
221
|
delivers_tool_args=True,
|
|
204
222
|
empty_stdout_is="deny",
|
|
205
|
-
|
|
223
|
+
# ONLY the families agy actually routes to the hook today: read /
|
|
224
|
+
# discovery tools (observed). The shell (run_command -> Bash) and the
|
|
225
|
+
# file-WRITE family (write_to_file / replace_file_content) are
|
|
226
|
+
# intentionally ABSENT -- agy never calls our hook for them, so we
|
|
227
|
+
# cannot enforce them (#1373). Adding them back here would re-open the
|
|
228
|
+
# #202 false claim guarded by TestAntigravityCoverageHonesty1373 in
|
|
229
|
+
# tests/test_antigravity_adapter.py.
|
|
230
|
+
covered_tool_families=("file_read", "file_search"),
|
|
206
231
|
min_core_version="1.9.0",
|
|
207
232
|
adapter_contract_version="1",
|
|
208
233
|
)
|
|
@@ -257,6 +282,33 @@ class AntigravityAdapter(HostAdapter):
|
|
|
257
282
|
normalized["tool_input"] = args if isinstance(args, dict) else {}
|
|
258
283
|
return normalized
|
|
259
284
|
|
|
285
|
+
def _verdict(self, decision: CZDecision) -> str:
|
|
286
|
+
"""Single source of truth for the agy decision TOKEN.
|
|
287
|
+
|
|
288
|
+
The stdout envelope (``render_envelope``) derives from THIS method.
|
|
289
|
+
agy decides from this stdout token (the exit code stays 0 per #1248):
|
|
290
|
+
|
|
291
|
+
* HITL (``requires_approval`` deny) -> ``_resolve_hitl_decision()``
|
|
292
|
+
(``force_ask`` by default; ``ask``/``deny``/``allow`` only via an
|
|
293
|
+
explicit ``CZ_ANTIGRAVITY_HITL_DECISION`` override).
|
|
294
|
+
* hard deny -> ``"deny"``.
|
|
295
|
+
* allow / warn -> ``"allow"``.
|
|
296
|
+
"""
|
|
297
|
+
if decision.is_hitl:
|
|
298
|
+
return _resolve_hitl_decision()
|
|
299
|
+
if decision.is_deny:
|
|
300
|
+
return "deny"
|
|
301
|
+
return "allow"
|
|
302
|
+
|
|
303
|
+
# NOTE (#1373): agy intentionally does NOT override the exit code. agy's
|
|
304
|
+
# documented block contract is the stdout ``{"decision":"deny"}`` token, and
|
|
305
|
+
# ``decision_via_exit_code=False`` keeps the exit code 0 for every decision
|
|
306
|
+
# (the deliberate #1248 design -- a non-zero hook exit on agy is unverified
|
|
307
|
+
# / risky, so we rely on the stdout deny, which blocks). An exit-2 backstop
|
|
308
|
+
# was considered (finding F1) and dropped: it could not be validated against
|
|
309
|
+
# a live agy and would contradict #1248. The honest posture is the
|
|
310
|
+
# CoverageDecl above (tier=observe; shell/file COMING SOON).
|
|
311
|
+
|
|
260
312
|
def render_envelope(self, decision: CZDecision) -> dict:
|
|
261
313
|
"""Render to Antigravity's PreToolUse stdout-JSON contract.
|
|
262
314
|
|
|
@@ -265,14 +317,10 @@ class AntigravityAdapter(HostAdapter):
|
|
|
265
317
|
(cmux#5358), so silence-that-still-prints-{} is never produced here.
|
|
266
318
|
camelCase per the external contract; Control Zero diagnostic
|
|
267
319
|
metadata is namespaced under ``controlzero`` so it cannot collide
|
|
268
|
-
with agy's reserved output keys.
|
|
320
|
+
with agy's reserved output keys. The decision token comes from the
|
|
321
|
+
single-source ``_verdict``.
|
|
269
322
|
"""
|
|
270
|
-
|
|
271
|
-
verdict = _resolve_hitl_decision()
|
|
272
|
-
elif decision.is_deny:
|
|
273
|
-
verdict = "deny"
|
|
274
|
-
else:
|
|
275
|
-
verdict = "allow"
|
|
323
|
+
verdict = self._verdict(decision)
|
|
276
324
|
|
|
277
325
|
envelope: dict = {
|
|
278
326
|
"decision": verdict,
|
|
@@ -24,6 +24,13 @@ crashes the IDE -- on an unparseable / empty payload it applies
|
|
|
24
24
|
CZ_KIRO_UNKNOWN_PAYLOAD (default ``closed`` = block, governance-safe; set to
|
|
25
25
|
``open`` to allow).
|
|
26
26
|
|
|
27
|
+
The shim re-execs the SAME interpreter that installed it
|
|
28
|
+
(``sys.executable -m controlzero hook-check``), not a bare ``controlzero`` on
|
|
29
|
+
PATH, so a venv/renamed-bin/broken-global cannot make it ENOENT. If the engine
|
|
30
|
+
still cannot be spawned, a DECIDING event (preToolUse / promptSubmit) FAILS
|
|
31
|
+
CLOSED (block, exit 2) -- never a silent allow (#1373 / F2); a post-write file
|
|
32
|
+
event stays observe-only (allow, exit 0).
|
|
33
|
+
|
|
27
34
|
KNOWN UPSTREAM BUG (kiro #7375 / #7408 / #7500): IDE ``preToolUse`` currently
|
|
28
35
|
delivers ``USER_PROMPT={}`` with no tool context, so argument-level pre-tool
|
|
29
36
|
policy is bounded until upstream ships the fix. prompt-submit and post-tool-use
|
|
@@ -138,16 +145,39 @@ def main(argv: list[str] | None = None) -> int:
|
|
|
138
145
|
env["CZ_KIRO_SURFACE"] = "ide"
|
|
139
146
|
env.setdefault("CONTROLZERO_CLIENT", "kiro-ide")
|
|
140
147
|
try:
|
|
148
|
+
# #1373 / F2 INTERPRETER RE-EXEC + FAIL CLOSED: re-exec the SAME
|
|
149
|
+
# interpreter that installed this shim (sys.executable) against the
|
|
150
|
+
# controlzero module, NOT a bare `controlzero` looked up on PATH. The
|
|
151
|
+
# interpreter that imported this module provably imports controlzero, so
|
|
152
|
+
# `-m controlzero hook-check` cannot ENOENT on a venv/renamed-bin/broken
|
|
153
|
+
# global the way a PATH lookup of `controlzero` can. On a spawn failure
|
|
154
|
+
# we now FAIL CLOSED for a deciding event (block, exit 2) instead of the
|
|
155
|
+
# old silent allow (exit 0) -- that allow was a fail-OPEN: every tool
|
|
156
|
+
# call slipped through unguarded while the audit still recorded the
|
|
157
|
+
# intended decision.
|
|
141
158
|
proc = subprocess.run(
|
|
142
|
-
["controlzero", "hook-check"],
|
|
159
|
+
[sys.executable, "-m", "controlzero", "hook-check"],
|
|
143
160
|
input=json.dumps(payload),
|
|
144
161
|
text=True,
|
|
145
162
|
env=env,
|
|
146
163
|
)
|
|
147
|
-
except FileNotFoundError:
|
|
148
|
-
|
|
149
|
-
|
|
150
|
-
|
|
164
|
+
except (FileNotFoundError, OSError) as e:
|
|
165
|
+
if event in _FILE_EVENTS:
|
|
166
|
+
# A post-write file save is observe-only -- there is nothing to
|
|
167
|
+
# block, so a spawn failure cannot become a fail-open here.
|
|
168
|
+
print(
|
|
169
|
+
"controlzero(kiro): could not start the hook-check engine "
|
|
170
|
+
f"({e}); file event is observe-only, allowing the save",
|
|
171
|
+
file=sys.stderr,
|
|
172
|
+
)
|
|
173
|
+
return 0
|
|
174
|
+
# Deciding gate (preToolUse / promptSubmit): FAIL CLOSED, block.
|
|
175
|
+
print(
|
|
176
|
+
"controlzero(kiro): could not start the hook-check engine "
|
|
177
|
+
f"({e}); failing CLOSED for the deciding gate (blocking)",
|
|
178
|
+
file=sys.stderr,
|
|
179
|
+
)
|
|
180
|
+
return 2
|
|
151
181
|
|
|
152
182
|
if event in _FILE_EVENTS:
|
|
153
183
|
# OBSERVE-ONLY: a file event is post-write -- the file is already
|
|
@@ -162,7 +192,23 @@ def main(argv: list[str] | None = None) -> int:
|
|
|
162
192
|
)
|
|
163
193
|
return 0
|
|
164
194
|
|
|
165
|
-
|
|
195
|
+
# Deciding gate (preToolUse / promptSubmit): collapse the engine exit to a
|
|
196
|
+
# BINARY decision (#1373). hook-check emits 0 (allow) or 2 (deny) on a clean
|
|
197
|
+
# decision; ANY OTHER exit means the spawned engine CRASHED after starting
|
|
198
|
+
# (uncaught exception, OOM-kill 137, signal 128+n, a stray sys.exit(1)).
|
|
199
|
+
# Kiro reads any non-{0,2} exit as "warn / proceed" -> the tool RUNS while
|
|
200
|
+
# audit may already have logged a deny: the exact #1373 fail-open. So only a
|
|
201
|
+
# clean exit 0 allows; everything else fails CLOSED (block, exit 2).
|
|
202
|
+
if proc.returncode == 0:
|
|
203
|
+
return 0
|
|
204
|
+
if proc.returncode != 2:
|
|
205
|
+
print(
|
|
206
|
+
"controlzero(kiro): the hook-check engine exited with an unexpected "
|
|
207
|
+
f"code ({proc.returncode}); failing CLOSED for the deciding gate "
|
|
208
|
+
"(blocking) rather than letting the tool proceed",
|
|
209
|
+
file=sys.stderr,
|
|
210
|
+
)
|
|
211
|
+
return 2
|
|
166
212
|
|
|
167
213
|
|
|
168
214
|
if __name__ == "__main__":
|