oacp-cli 0.4.1__tar.gz → 0.4.2__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.
- {oacp_cli-0.4.1 → oacp_cli-0.4.2}/.github/workflows/release.yml +1 -1
- {oacp_cli-0.4.1 → oacp_cli-0.4.2}/CHANGELOG.md +130 -0
- {oacp_cli-0.4.1 → oacp_cli-0.4.2}/PKG-INFO +1 -1
- {oacp_cli-0.4.1 → oacp_cli-0.4.2}/docs/guides/doctor.md +4 -0
- {oacp_cli-0.4.1 → oacp_cli-0.4.2}/docs/protocol/autonomy.md +149 -15
- {oacp_cli-0.4.1 → oacp_cli-0.4.2}/docs/protocol/inbox_outbox.md +5 -3
- {oacp_cli-0.4.1 → oacp_cli-0.4.2}/docs/protocol/message_signing.md +159 -13
- {oacp_cli-0.4.1 → oacp_cli-0.4.2}/pyproject.toml +2 -1
- {oacp_cli-0.4.1 → oacp_cli-0.4.2}/scripts/_oacp_constants.py +6 -1
- {oacp_cli-0.4.1 → oacp_cli-0.4.2}/scripts/agent_profile.py +9 -3
- {oacp_cli-0.4.1 → oacp_cli-0.4.2}/scripts/autonomy_gate.py +325 -18
- {oacp_cli-0.4.1 → oacp_cli-0.4.2}/scripts/claude_envelope_hook.py +162 -14
- {oacp_cli-0.4.1 → oacp_cli-0.4.2}/scripts/envelope_compiler.py +252 -5
- {oacp_cli-0.4.1 → oacp_cli-0.4.2}/scripts/message_signing.py +67 -19
- {oacp_cli-0.4.1 → oacp_cli-0.4.2}/scripts/message_verify.py +312 -31
- {oacp_cli-0.4.1 → oacp_cli-0.4.2}/scripts/oacp_doctor.py +109 -10
- {oacp_cli-0.4.1 → oacp_cli-0.4.2}/scripts/oacp_inbox.py +108 -25
- {oacp_cli-0.4.1 → oacp_cli-0.4.2}/scripts/oacp_watch.py +67 -13
- oacp_cli-0.4.2/scripts/policy_signing.py +643 -0
- {oacp_cli-0.4.1 → oacp_cli-0.4.2}/scripts/send_inbox_message.py +48 -10
- {oacp_cli-0.4.1 → oacp_cli-0.4.2}/scripts/trust_cli.py +120 -6
- {oacp_cli-0.4.1 → oacp_cli-0.4.2}/scripts/trust_root.py +198 -22
- {oacp_cli-0.4.1 → oacp_cli-0.4.2}/tests/conformance/autonomy/expected/brainstorm_side_effect_verbs_auto_accepts.yaml +1 -0
- {oacp_cli-0.4.1 → oacp_cli-0.4.2}/tests/conformance/autonomy/expected/brainstorm_without_profile_auto_accepts.yaml +1 -0
- {oacp_cli-0.4.1 → oacp_cli-0.4.2}/tests/conformance/autonomy/messages/negated_guardrails.yaml +9 -3
- oacp_cli-0.4.2/tests/conformance/intake/README.md +26 -0
- oacp_cli-0.4.2/tests/conformance/intake/configs/enforce.yaml +17 -0
- oacp_cli-0.4.2/tests/conformance/intake/configs/off.yaml +17 -0
- oacp_cli-0.4.2/tests/conformance/intake/configs/warn.yaml +17 -0
- oacp_cli-0.4.2/tests/conformance/intake/expected/signed_basic__enforce.yaml +9 -0
- oacp_cli-0.4.2/tests/conformance/intake/expected/signed_revoked__enforce.yaml +9 -0
- oacp_cli-0.4.2/tests/conformance/intake/expected/signed_revoked__off.yaml +9 -0
- oacp_cli-0.4.2/tests/conformance/intake/expected/signed_revoked__warn.yaml +9 -0
- oacp_cli-0.4.2/tests/conformance/intake/expected/tamper_body_flip__enforce.yaml +9 -0
- oacp_cli-0.4.2/tests/conformance/intake/expected/tamper_body_flip__off.yaml +9 -0
- oacp_cli-0.4.2/tests/conformance/intake/expected/tamper_body_flip__warn.yaml +9 -0
- oacp_cli-0.4.2/tests/conformance/intake/expected/tamper_kid_unknown__enforce.yaml +9 -0
- oacp_cli-0.4.2/tests/conformance/intake/expected/tamper_kid_unknown__off.yaml +9 -0
- oacp_cli-0.4.2/tests/conformance/intake/expected/tamper_kid_unknown__warn.yaml +9 -0
- oacp_cli-0.4.2/tests/conformance/intake/expected/unsigned_notification__enforce.yaml +9 -0
- oacp_cli-0.4.2/tests/conformance/intake/expected/unsigned_notification__off.yaml +9 -0
- oacp_cli-0.4.2/tests/conformance/intake/expected/unsigned_notification__warn.yaml +9 -0
- {oacp_cli-0.4.1 → oacp_cli-0.4.2}/tests/test_autonomy_gate.py +310 -1
- {oacp_cli-0.4.1 → oacp_cli-0.4.2}/tests/test_claude_envelope_hook.py +183 -0
- oacp_cli-0.4.2/tests/test_default_envelope.py +173 -0
- oacp_cli-0.4.2/tests/test_envelope_public_admission.py +394 -0
- oacp_cli-0.4.2/tests/test_inbox_verify.py +424 -0
- oacp_cli-0.4.2/tests/test_intake_conformance.py +133 -0
- {oacp_cli-0.4.1 → oacp_cli-0.4.2}/tests/test_message_verify.py +2 -2
- {oacp_cli-0.4.1 → oacp_cli-0.4.2}/tests/test_oacp_constants.py +23 -1
- {oacp_cli-0.4.1 → oacp_cli-0.4.2}/tests/test_oacp_doctor.py +35 -0
- oacp_cli-0.4.2/tests/test_policy_signing.py +555 -0
- {oacp_cli-0.4.1 → oacp_cli-0.4.2}/tests/test_trust_root.py +21 -0
- {oacp_cli-0.4.1 → oacp_cli-0.4.2}/.gitattributes +0 -0
- {oacp_cli-0.4.1 → oacp_cli-0.4.2}/.github/workflows/ci.yml +0 -0
- {oacp_cli-0.4.1 → oacp_cli-0.4.2}/.gitignore +0 -0
- {oacp_cli-0.4.1 → oacp_cli-0.4.2}/CONTRIBUTING.md +0 -0
- {oacp_cli-0.4.1 → oacp_cli-0.4.2}/LICENSE +0 -0
- {oacp_cli-0.4.1 → oacp_cli-0.4.2}/Makefile +0 -0
- {oacp_cli-0.4.1 → oacp_cli-0.4.2}/QUICKSTART.md +0 -0
- {oacp_cli-0.4.1 → oacp_cli-0.4.2}/README.md +0 -0
- {oacp_cli-0.4.1 → oacp_cli-0.4.2}/SECURITY.md +0 -0
- {oacp_cli-0.4.1 → oacp_cli-0.4.2}/SPEC.md +0 -0
- {oacp_cli-0.4.1 → oacp_cli-0.4.2}/docs/from-claude-p.md +0 -0
- {oacp_cli-0.4.1 → oacp_cli-0.4.2}/docs/guides/adoption.md +0 -0
- {oacp_cli-0.4.1 → oacp_cli-0.4.2}/docs/guides/prompt_caching.md +0 -0
- {oacp_cli-0.4.1 → oacp_cli-0.4.2}/docs/guides/runtime_capability_matrix.md +0 -0
- {oacp_cli-0.4.1 → oacp_cli-0.4.2}/docs/guides/setup.md +0 -0
- {oacp_cli-0.4.1 → oacp_cli-0.4.2}/docs/guides/unified_skill_spec.md +0 -0
- {oacp_cli-0.4.1 → oacp_cli-0.4.2}/docs/guides/versioning.md +0 -0
- {oacp_cli-0.4.1 → oacp_cli-0.4.2}/docs/img/oacp-cli-demo.png +0 -0
- {oacp_cli-0.4.1 → oacp_cli-0.4.2}/docs/img/oacp-filesystem-tree.png +0 -0
- {oacp_cli-0.4.1 → oacp_cli-0.4.2}/docs/img/oacp-fleet-thread.png +0 -0
- {oacp_cli-0.4.1 → oacp_cli-0.4.2}/docs/protocol/agent_profiles.md +0 -0
- {oacp_cli-0.4.1 → oacp_cli-0.4.2}/docs/protocol/agent_safety_defaults.md +0 -0
- {oacp_cli-0.4.1 → oacp_cli-0.4.2}/docs/protocol/credential_scoping.md +0 -0
- {oacp_cli-0.4.1 → oacp_cli-0.4.2}/docs/protocol/cross_runtime_sync.md +0 -0
- {oacp_cli-0.4.1 → oacp_cli-0.4.2}/docs/protocol/dispatch_states.yaml +0 -0
- {oacp_cli-0.4.1 → oacp_cli-0.4.2}/docs/protocol/mcp_integration.md +0 -0
- {oacp_cli-0.4.1 → oacp_cli-0.4.2}/docs/protocol/multi_agent_shared_workspace.md +0 -0
- {oacp_cli-0.4.1 → oacp_cli-0.4.2}/docs/protocol/org_memory.md +0 -0
- {oacp_cli-0.4.1 → oacp_cli-0.4.2}/docs/protocol/packet_states.yaml +0 -0
- {oacp_cli-0.4.1 → oacp_cli-0.4.2}/docs/protocol/review_loop.md +0 -0
- {oacp_cli-0.4.1 → oacp_cli-0.4.2}/docs/protocol/runtime_capabilities.md +0 -0
- {oacp_cli-0.4.1 → oacp_cli-0.4.2}/docs/protocol/session_init.md +0 -0
- {oacp_cli-0.4.1 → oacp_cli-0.4.2}/docs/protocol/skills_manifest.yaml +0 -0
- {oacp_cli-0.4.1 → oacp_cli-0.4.2}/docs/protocol/task_negotiation.md +0 -0
- {oacp_cli-0.4.1 → oacp_cli-0.4.2}/examples/demo-workspace/README.md +0 -0
- {oacp_cli-0.4.1 → oacp_cli-0.4.2}/examples/demo-workspace/org-memory/decisions.md +0 -0
- {oacp_cli-0.4.1 → oacp_cli-0.4.2}/examples/demo-workspace/org-memory/events/20260504-093015-postgres-over-dynamodb.md +0 -0
- {oacp_cli-0.4.1 → oacp_cli-0.4.2}/examples/demo-workspace/org-memory/events/20260508-141220-utc-timestamps-pr-review.md +0 -0
- {oacp_cli-0.4.1 → oacp_cli-0.4.2}/examples/demo-workspace/org-memory/events/20260515-102045-utc-timestamps-webhooks.md +0 -0
- {oacp_cli-0.4.1 → oacp_cli-0.4.2}/examples/demo-workspace/org-memory/events/20260521-163330-utc-timestamps-rule-proposal.md +0 -0
- {oacp_cli-0.4.1 → oacp_cli-0.4.2}/examples/demo-workspace/org-memory/events/20260527-110500-idempotency-keys-merged.md +0 -0
- {oacp_cli-0.4.1 → oacp_cli-0.4.2}/examples/demo-workspace/org-memory/events/20260602-090210-parcel-api-v020-released.md +0 -0
- {oacp_cli-0.4.1 → oacp_cli-0.4.2}/examples/demo-workspace/org-memory/recent.md +0 -0
- {oacp_cli-0.4.1 → oacp_cli-0.4.2}/examples/demo-workspace/org-memory/rules.md +0 -0
- {oacp_cli-0.4.1 → oacp_cli-0.4.2}/examples/demo-workspace/projects/parcel-api/memory/archive/2026-05-21-csv-export-timeouts.md +0 -0
- {oacp_cli-0.4.1 → oacp_cli-0.4.2}/examples/demo-workspace/projects/parcel-api/memory/decision_log.md +0 -0
- {oacp_cli-0.4.1 → oacp_cli-0.4.2}/examples/demo-workspace/projects/parcel-api/memory/known_debt.md +0 -0
- {oacp_cli-0.4.1 → oacp_cli-0.4.2}/examples/demo-workspace/projects/parcel-api/memory/open_threads.md +0 -0
- {oacp_cli-0.4.1 → oacp_cli-0.4.2}/examples/demo-workspace/projects/parcel-api/memory/project_facts.md +0 -0
- {oacp_cli-0.4.1 → oacp_cli-0.4.2}/examples/quickstart/README.md +0 -0
- {oacp_cli-0.4.1 → oacp_cli-0.4.2}/mcp_servers/oacp_coordinator.py +0 -0
- {oacp_cli-0.4.1 → oacp_cli-0.4.2}/oacp/__init__.py +0 -0
- {oacp_cli-0.4.1 → oacp_cli-0.4.2}/oacp/cli.py +0 -0
- {oacp_cli-0.4.1 → oacp_cli-0.4.2}/oacp/envelope_hook.py +0 -0
- {oacp_cli-0.4.1 → oacp_cli-0.4.2}/scripts/_oacp_env.py +0 -0
- {oacp_cli-0.4.1 → oacp_cli-0.4.2}/scripts/add_agent.py +0 -0
- {oacp_cli-0.4.1 → oacp_cli-0.4.2}/scripts/check_quality_gate.py +0 -0
- {oacp_cli-0.4.1 → oacp_cli-0.4.2}/scripts/codex_session_init.py +0 -0
- {oacp_cli-0.4.1 → oacp_cli-0.4.2}/scripts/create_handoff_packet.py +0 -0
- {oacp_cli-0.4.1 → oacp_cli-0.4.2}/scripts/handoff_schema.py +0 -0
- {oacp_cli-0.4.1 → oacp_cli-0.4.2}/scripts/init_org_memory.py +0 -0
- {oacp_cli-0.4.1 → oacp_cli-0.4.2}/scripts/init_packet.sh +0 -0
- {oacp_cli-0.4.1 → oacp_cli-0.4.2}/scripts/init_project_workspace.py +0 -0
- {oacp_cli-0.4.1 → oacp_cli-0.4.2}/scripts/init_project_workspace.sh +0 -0
- {oacp_cli-0.4.1 → oacp_cli-0.4.2}/scripts/key_cli.py +0 -0
- {oacp_cli-0.4.1 → oacp_cli-0.4.2}/scripts/memory_archive_common.py +0 -0
- {oacp_cli-0.4.1 → oacp_cli-0.4.2}/scripts/memory_cli.py +0 -0
- {oacp_cli-0.4.1 → oacp_cli-0.4.2}/scripts/memory_sync.py +0 -0
- {oacp_cli-0.4.1 → oacp_cli-0.4.2}/scripts/normalize_findings.py +0 -0
- {oacp_cli-0.4.1 → oacp_cli-0.4.2}/scripts/preflight.py +0 -0
- {oacp_cli-0.4.1 → oacp_cli-0.4.2}/scripts/promote_to_archive.py +0 -0
- {oacp_cli-0.4.1 → oacp_cli-0.4.2}/scripts/record_autonomy_outcome.py +0 -0
- {oacp_cli-0.4.1 → oacp_cli-0.4.2}/scripts/restore_from_archive.py +0 -0
- {oacp_cli-0.4.1 → oacp_cli-0.4.2}/scripts/session_lifecycle_hooks.py +0 -0
- {oacp_cli-0.4.1 → oacp_cli-0.4.2}/scripts/setup_runtime.py +0 -0
- {oacp_cli-0.4.1 → oacp_cli-0.4.2}/scripts/update_workspace.sh +0 -0
- {oacp_cli-0.4.1 → oacp_cli-0.4.2}/scripts/validate_agent_card.py +0 -0
- {oacp_cli-0.4.1 → oacp_cli-0.4.2}/scripts/validate_message.py +0 -0
- {oacp_cli-0.4.1 → oacp_cli-0.4.2}/scripts/write_event.py +0 -0
- {oacp_cli-0.4.1 → oacp_cli-0.4.2}/templates/agent_card.template.yaml +0 -0
- {oacp_cli-0.4.1 → oacp_cli-0.4.2}/templates/agent_profile.template.yaml +0 -0
- {oacp_cli-0.4.1 → oacp_cli-0.4.2}/templates/agent_status.template.yaml +0 -0
- {oacp_cli-0.4.1 → oacp_cli-0.4.2}/templates/checkpoint.template.md +0 -0
- {oacp_cli-0.4.1 → oacp_cli-0.4.2}/templates/claude/agents/role_agent.template.md +0 -0
- {oacp_cli-0.4.1 → oacp_cli-0.4.2}/templates/claude/rules/guardrail.template.md +0 -0
- {oacp_cli-0.4.1 → oacp_cli-0.4.2}/templates/findings_packet.template.yaml +0 -0
- {oacp_cli-0.4.1 → oacp_cli-0.4.2}/templates/github_actions_quality_gate.yaml +0 -0
- {oacp_cli-0.4.1 → oacp_cli-0.4.2}/templates/guardrails/coding_standards.template.md +0 -0
- {oacp_cli-0.4.1 → oacp_cli-0.4.2}/templates/guardrails/safe_commands.template.md +0 -0
- {oacp_cli-0.4.1 → oacp_cli-0.4.2}/templates/guardrails/secrets_rules.template.md +0 -0
- {oacp_cli-0.4.1 → oacp_cli-0.4.2}/templates/handoff_packet.template.yaml +0 -0
- {oacp_cli-0.4.1 → oacp_cli-0.4.2}/templates/inbox_message.template.yaml +0 -0
- {oacp_cli-0.4.1 → oacp_cli-0.4.2}/templates/manual_validation.template.md +0 -0
- {oacp_cli-0.4.1 → oacp_cli-0.4.2}/templates/merge_decision.template.md +0 -0
- {oacp_cli-0.4.1 → oacp_cli-0.4.2}/templates/org-memory/decisions.md +0 -0
- {oacp_cli-0.4.1 → oacp_cli-0.4.2}/templates/org-memory/events/.gitkeep +0 -0
- {oacp_cli-0.4.1 → oacp_cli-0.4.2}/templates/org-memory/events/20260317-170120-example-api-convention.md +0 -0
- {oacp_cli-0.4.1 → oacp_cli-0.4.2}/templates/org-memory/recent.md +0 -0
- {oacp_cli-0.4.1 → oacp_cli-0.4.2}/templates/org-memory/rules.md +0 -0
- {oacp_cli-0.4.1 → oacp_cli-0.4.2}/templates/receiver_config.template.yaml +0 -0
- {oacp_cli-0.4.1 → oacp_cli-0.4.2}/templates/review_packet.template.md +0 -0
- {oacp_cli-0.4.1 → oacp_cli-0.4.2}/templates/roles/role_baseline.template.md +0 -0
- {oacp_cli-0.4.1 → oacp_cli-0.4.2}/templates/roles/role_definition.template.yaml +0 -0
- {oacp_cli-0.4.1 → oacp_cli-0.4.2}/templates/runtime_capabilities.yaml +0 -0
- {oacp_cli-0.4.1 → oacp_cli-0.4.2}/templates/skills_manifest.template.yaml +0 -0
- {oacp_cli-0.4.1 → oacp_cli-0.4.2}/templates/test_packet.template.md +0 -0
- {oacp_cli-0.4.1 → oacp_cli-0.4.2}/tests/conformance/autonomy/README.md +0 -0
- {oacp_cli-0.4.1 → oacp_cli-0.4.2}/tests/conformance/autonomy/actuals/checkpoint_breach.yaml +0 -0
- {oacp_cli-0.4.1 → oacp_cli-0.4.2}/tests/conformance/autonomy/actuals/continuation_drift.yaml +0 -0
- {oacp_cli-0.4.1 → oacp_cli-0.4.2}/tests/conformance/autonomy/actuals/continuation_within.yaml +0 -0
- {oacp_cli-0.4.1 → oacp_cli-0.4.2}/tests/conformance/autonomy/actuals/declaration_error.yaml +0 -0
- {oacp_cli-0.4.1 → oacp_cli-0.4.2}/tests/conformance/autonomy/actuals/declaration_intent.yaml +0 -0
- {oacp_cli-0.4.1 → oacp_cli-0.4.2}/tests/conformance/autonomy/actuals/top_level_side_effect_keys.yaml +0 -0
- {oacp_cli-0.4.1 → oacp_cli-0.4.2}/tests/conformance/autonomy/audits/prior_thread_grant_approved.yaml +0 -0
- {oacp_cli-0.4.1 → oacp_cli-0.4.2}/tests/conformance/autonomy/configs/always_pause.yaml +0 -0
- {oacp_cli-0.4.1 → oacp_cli-0.4.2}/tests/conformance/autonomy/configs/auto_review_continuation_enabled.yaml +0 -0
- {oacp_cli-0.4.1 → oacp_cli-0.4.2}/tests/conformance/autonomy/configs/auto_review_external_pause.yaml +0 -0
- {oacp_cli-0.4.1 → oacp_cli-0.4.2}/tests/conformance/autonomy/configs/auto_review_standard.yaml +0 -0
- {oacp_cli-0.4.1 → oacp_cli-0.4.2}/tests/conformance/autonomy/configs/auto_review_tight.yaml +0 -0
- {oacp_cli-0.4.1 → oacp_cli-0.4.2}/tests/conformance/autonomy/configs/malformed_config.yaml +0 -0
- {oacp_cli-0.4.1 → oacp_cli-0.4.2}/tests/conformance/autonomy/expected/always_pause_task.yaml +0 -0
- {oacp_cli-0.4.1 → oacp_cli-0.4.2}/tests/conformance/autonomy/expected/ambiguous_scope_pauses.yaml +0 -0
- {oacp_cli-0.4.1 → oacp_cli-0.4.2}/tests/conformance/autonomy/expected/brainstorm_destructive_pauses.yaml +0 -0
- {oacp_cli-0.4.1 → oacp_cli-0.4.2}/tests/conformance/autonomy/expected/checkpoint_breach_pauses.yaml +0 -0
- {oacp_cli-0.4.1 → oacp_cli-0.4.2}/tests/conformance/autonomy/expected/clean_auto_review_task.yaml +0 -0
- {oacp_cli-0.4.1 → oacp_cli-0.4.2}/tests/conformance/autonomy/expected/continuation_grant_destructive_pauses.yaml +0 -0
- {oacp_cli-0.4.1 → oacp_cli-0.4.2}/tests/conformance/autonomy/expected/continuation_grant_disabled_pauses.yaml +0 -0
- {oacp_cli-0.4.1 → oacp_cli-0.4.2}/tests/conformance/autonomy/expected/continuation_grant_drift_pauses.yaml +0 -0
- {oacp_cli-0.4.1 → oacp_cli-0.4.2}/tests/conformance/autonomy/expected/continuation_grant_enabled_auto_accepts.yaml +0 -0
- {oacp_cli-0.4.1 → oacp_cli-0.4.2}/tests/conformance/autonomy/expected/continuation_grant_external_uncovered_pauses.yaml +0 -0
- {oacp_cli-0.4.1 → oacp_cli-0.4.2}/tests/conformance/autonomy/expected/declaration_error_pauses.yaml +0 -0
- {oacp_cli-0.4.1 → oacp_cli-0.4.2}/tests/conformance/autonomy/expected/declaration_intent_checkpoint_pauses.yaml +0 -0
- {oacp_cli-0.4.1 → oacp_cli-0.4.2}/tests/conformance/autonomy/expected/declared_destructive_ops_pauses.yaml +0 -0
- {oacp_cli-0.4.1 → oacp_cli-0.4.2}/tests/conformance/autonomy/expected/expired_message_pauses.yaml +0 -0
- {oacp_cli-0.4.1 → oacp_cli-0.4.2}/tests/conformance/autonomy/expected/guardrails_fence_auto_accepts.yaml +0 -0
- {oacp_cli-0.4.1 → oacp_cli-0.4.2}/tests/conformance/autonomy/expected/hard_stop_dangerously_skip_permissions_pauses.yaml +0 -0
- {oacp_cli-0.4.1 → oacp_cli-0.4.2}/tests/conformance/autonomy/expected/hard_stop_external_side_effects_pauses.yaml +0 -0
- {oacp_cli-0.4.1 → oacp_cli-0.4.2}/tests/conformance/autonomy/expected/hard_stop_force_pauses.yaml +0 -0
- {oacp_cli-0.4.1 → oacp_cli-0.4.2}/tests/conformance/autonomy/expected/hard_stop_masking_threshold_pauses.yaml +0 -0
- {oacp_cli-0.4.1 → oacp_cli-0.4.2}/tests/conformance/autonomy/expected/hard_stop_no_verify_pauses.yaml +0 -0
- {oacp_cli-0.4.1 → oacp_cli-0.4.2}/tests/conformance/autonomy/expected/hard_stop_no_verify_upper_pauses.yaml +0 -0
- {oacp_cli-0.4.1 → oacp_cli-0.4.2}/tests/conformance/autonomy/expected/hard_stop_rm_rf_pauses.yaml +0 -0
- {oacp_cli-0.4.1 → oacp_cli-0.4.2}/tests/conformance/autonomy/expected/hard_stop_sensitive_commercial_pauses.yaml +0 -0
- {oacp_cli-0.4.1 → oacp_cli-0.4.2}/tests/conformance/autonomy/expected/hard_stop_sensitive_config_pauses.yaml +0 -0
- {oacp_cli-0.4.1 → oacp_cli-0.4.2}/tests/conformance/autonomy/expected/hard_stop_sensitive_credentials_pauses.yaml +0 -0
- {oacp_cli-0.4.1 → oacp_cli-0.4.2}/tests/conformance/autonomy/expected/hard_stop_sensitive_memory_ssot_pauses.yaml +0 -0
- {oacp_cli-0.4.1 → oacp_cli-0.4.2}/tests/conformance/autonomy/expected/hard_stop_sensitive_pricing_pauses.yaml +0 -0
- {oacp_cli-0.4.1 → oacp_cli-0.4.2}/tests/conformance/autonomy/expected/hard_stop_sensitive_public_repo_pauses.yaml +0 -0
- {oacp_cli-0.4.1 → oacp_cli-0.4.2}/tests/conformance/autonomy/expected/hard_stop_sensitive_scope_pauses.yaml +0 -0
- {oacp_cli-0.4.1 → oacp_cli-0.4.2}/tests/conformance/autonomy/expected/hard_stop_sensitive_secret_pauses.yaml +0 -0
- {oacp_cli-0.4.1 → oacp_cli-0.4.2}/tests/conformance/autonomy/expected/hard_stop_side_effect_before_sensitive_pauses.yaml +0 -0
- {oacp_cli-0.4.1 → oacp_cli-0.4.2}/tests/conformance/autonomy/expected/invalid_message_pauses.yaml +0 -0
- {oacp_cli-0.4.1 → oacp_cli-0.4.2}/tests/conformance/autonomy/expected/lexical_declared_false_auto_accepts.yaml +0 -0
- {oacp_cli-0.4.1 → oacp_cli-0.4.2}/tests/conformance/autonomy/expected/malformed_config_pauses.yaml +0 -0
- {oacp_cli-0.4.1 → oacp_cli-0.4.2}/tests/conformance/autonomy/expected/minutes_45_auto_accepts.yaml +0 -0
- {oacp_cli-0.4.1 → oacp_cli-0.4.2}/tests/conformance/autonomy/expected/minutes_46_pauses.yaml +0 -0
- {oacp_cli-0.4.1 → oacp_cli-0.4.2}/tests/conformance/autonomy/expected/missing_task_profile_pauses.yaml +0 -0
- {oacp_cli-0.4.1 → oacp_cli-0.4.2}/tests/conformance/autonomy/expected/negated_guardrails_auto_accepts.yaml +0 -0
- {oacp_cli-0.4.1 → oacp_cli-0.4.2}/tests/conformance/autonomy/expected/path_like_deploy_auto_accepts.yaml +0 -0
- {oacp_cli-0.4.1 → oacp_cli-0.4.2}/tests/conformance/autonomy/expected/private_issue_artifacts_auto_accepts.yaml +0 -0
- {oacp_cli-0.4.1 → oacp_cli-0.4.2}/tests/conformance/autonomy/expected/private_pr_artifacts_auto_accepts.yaml +0 -0
- {oacp_cli-0.4.1 → oacp_cli-0.4.2}/tests/conformance/autonomy/expected/private_pr_with_merge_pauses.yaml +0 -0
- {oacp_cli-0.4.1 → oacp_cli-0.4.2}/tests/conformance/autonomy/expected/public_pr_artifacts_pause.yaml +0 -0
- {oacp_cli-0.4.1 → oacp_cli-0.4.2}/tests/conformance/autonomy/expected/risk_obvious_no_profile_pauses.yaml +0 -0
- {oacp_cli-0.4.1 → oacp_cli-0.4.2}/tests/conformance/autonomy/expected/side_effect_booleans_pause.yaml +0 -0
- {oacp_cli-0.4.1 → oacp_cli-0.4.2}/tests/conformance/autonomy/expected/threshold_breach_pauses.yaml +0 -0
- {oacp_cli-0.4.1 → oacp_cli-0.4.2}/tests/conformance/autonomy/expected/tight_threshold_pauses.yaml +0 -0
- {oacp_cli-0.4.1 → oacp_cli-0.4.2}/tests/conformance/autonomy/expected/top_level_side_effect_actuals_ignored.yaml +0 -0
- {oacp_cli-0.4.1 → oacp_cli-0.4.2}/tests/conformance/autonomy/expected/unparsable_task_profile_pauses.yaml +0 -0
- {oacp_cli-0.4.1 → oacp_cli-0.4.2}/tests/conformance/autonomy/messages/ambiguous_scope.yaml +0 -0
- {oacp_cli-0.4.1 → oacp_cli-0.4.2}/tests/conformance/autonomy/messages/brainstorm_destructive.yaml +0 -0
- {oacp_cli-0.4.1 → oacp_cli-0.4.2}/tests/conformance/autonomy/messages/brainstorm_side_effect_verbs.yaml +0 -0
- {oacp_cli-0.4.1 → oacp_cli-0.4.2}/tests/conformance/autonomy/messages/brainstorm_without_profile.yaml +0 -0
- {oacp_cli-0.4.1 → oacp_cli-0.4.2}/tests/conformance/autonomy/messages/clean_task.yaml +0 -0
- {oacp_cli-0.4.1 → oacp_cli-0.4.2}/tests/conformance/autonomy/messages/continuation_grant.yaml +0 -0
- {oacp_cli-0.4.1 → oacp_cli-0.4.2}/tests/conformance/autonomy/messages/continuation_grant_destructive.yaml +0 -0
- {oacp_cli-0.4.1 → oacp_cli-0.4.2}/tests/conformance/autonomy/messages/continuation_grant_external_uncovered.yaml +0 -0
- {oacp_cli-0.4.1 → oacp_cli-0.4.2}/tests/conformance/autonomy/messages/declared_destructive_ops.yaml +0 -0
- {oacp_cli-0.4.1 → oacp_cli-0.4.2}/tests/conformance/autonomy/messages/expired_message.yaml +0 -0
- {oacp_cli-0.4.1 → oacp_cli-0.4.2}/tests/conformance/autonomy/messages/guardrails_fence.yaml +0 -0
- {oacp_cli-0.4.1 → oacp_cli-0.4.2}/tests/conformance/autonomy/messages/hard_stop_dangerously_skip_permissions.yaml +0 -0
- {oacp_cli-0.4.1 → oacp_cli-0.4.2}/tests/conformance/autonomy/messages/hard_stop_external_side_effects.yaml +0 -0
- {oacp_cli-0.4.1 → oacp_cli-0.4.2}/tests/conformance/autonomy/messages/hard_stop_force.yaml +0 -0
- {oacp_cli-0.4.1 → oacp_cli-0.4.2}/tests/conformance/autonomy/messages/hard_stop_masking_threshold.yaml +0 -0
- {oacp_cli-0.4.1 → oacp_cli-0.4.2}/tests/conformance/autonomy/messages/hard_stop_no_verify.yaml +0 -0
- {oacp_cli-0.4.1 → oacp_cli-0.4.2}/tests/conformance/autonomy/messages/hard_stop_no_verify_upper.yaml +0 -0
- {oacp_cli-0.4.1 → oacp_cli-0.4.2}/tests/conformance/autonomy/messages/hard_stop_rm_rf.yaml +0 -0
- {oacp_cli-0.4.1 → oacp_cli-0.4.2}/tests/conformance/autonomy/messages/hard_stop_sensitive_scope.yaml +0 -0
- {oacp_cli-0.4.1 → oacp_cli-0.4.2}/tests/conformance/autonomy/messages/invalid_message.yaml +0 -0
- {oacp_cli-0.4.1 → oacp_cli-0.4.2}/tests/conformance/autonomy/messages/lexical_declared_false.yaml +0 -0
- {oacp_cli-0.4.1 → oacp_cli-0.4.2}/tests/conformance/autonomy/messages/minutes_45.yaml +0 -0
- {oacp_cli-0.4.1 → oacp_cli-0.4.2}/tests/conformance/autonomy/messages/minutes_46.yaml +0 -0
- {oacp_cli-0.4.1 → oacp_cli-0.4.2}/tests/conformance/autonomy/messages/missing_task_profile.yaml +0 -0
- {oacp_cli-0.4.1 → oacp_cli-0.4.2}/tests/conformance/autonomy/messages/path_like_deploy.yaml +0 -0
- {oacp_cli-0.4.1 → oacp_cli-0.4.2}/tests/conformance/autonomy/messages/private_issue_artifacts.yaml +0 -0
- {oacp_cli-0.4.1 → oacp_cli-0.4.2}/tests/conformance/autonomy/messages/private_pr_artifacts.yaml +0 -0
- {oacp_cli-0.4.1 → oacp_cli-0.4.2}/tests/conformance/autonomy/messages/private_pr_with_merge.yaml +0 -0
- {oacp_cli-0.4.1 → oacp_cli-0.4.2}/tests/conformance/autonomy/messages/public_pr_artifacts.yaml +0 -0
- {oacp_cli-0.4.1 → oacp_cli-0.4.2}/tests/conformance/autonomy/messages/risk_obvious_no_profile.yaml +0 -0
- {oacp_cli-0.4.1 → oacp_cli-0.4.2}/tests/conformance/autonomy/messages/sensitive_commercial.yaml +0 -0
- {oacp_cli-0.4.1 → oacp_cli-0.4.2}/tests/conformance/autonomy/messages/sensitive_config.yaml +0 -0
- {oacp_cli-0.4.1 → oacp_cli-0.4.2}/tests/conformance/autonomy/messages/sensitive_credentials.yaml +0 -0
- {oacp_cli-0.4.1 → oacp_cli-0.4.2}/tests/conformance/autonomy/messages/sensitive_memory_ssot.yaml +0 -0
- {oacp_cli-0.4.1 → oacp_cli-0.4.2}/tests/conformance/autonomy/messages/sensitive_pricing.yaml +0 -0
- {oacp_cli-0.4.1 → oacp_cli-0.4.2}/tests/conformance/autonomy/messages/sensitive_public_repo.yaml +0 -0
- {oacp_cli-0.4.1 → oacp_cli-0.4.2}/tests/conformance/autonomy/messages/sensitive_secret.yaml +0 -0
- {oacp_cli-0.4.1 → oacp_cli-0.4.2}/tests/conformance/autonomy/messages/side_effect_before_sensitive.yaml +0 -0
- {oacp_cli-0.4.1 → oacp_cli-0.4.2}/tests/conformance/autonomy/messages/side_effect_booleans.yaml +0 -0
- {oacp_cli-0.4.1 → oacp_cli-0.4.2}/tests/conformance/autonomy/messages/threshold_breach.yaml +0 -0
- {oacp_cli-0.4.1 → oacp_cli-0.4.2}/tests/conformance/autonomy/messages/unparsable_task_profile.yaml +0 -0
- {oacp_cli-0.4.1 → oacp_cli-0.4.2}/tests/conformance/envelope/README.md +0 -0
- {oacp_cli-0.4.1 → oacp_cli-0.4.2}/tests/conformance/envelope/configs/auto_review_standard.yaml +0 -0
- {oacp_cli-0.4.1 → oacp_cli-0.4.2}/tests/conformance/envelope/configs/malformed.yaml +0 -0
- {oacp_cli-0.4.1 → oacp_cli-0.4.2}/tests/conformance/envelope/expected/clean_pr_task_compiles.yaml +0 -0
- {oacp_cli-0.4.1 → oacp_cli-0.4.2}/tests/conformance/envelope/expected/docs_only_task_compiles.yaml +0 -0
- {oacp_cli-0.4.1 → oacp_cli-0.4.2}/tests/conformance/envelope/expected/granular_capabilities_compile.yaml +0 -0
- {oacp_cli-0.4.1 → oacp_cli-0.4.2}/tests/conformance/envelope/expected/invalid_numeric_fails.yaml +0 -0
- {oacp_cli-0.4.1 → oacp_cli-0.4.2}/tests/conformance/envelope/expected/malformed_config_fails.yaml +0 -0
- {oacp_cli-0.4.1 → oacp_cli-0.4.2}/tests/conformance/envelope/expected/missing_profile_fails.yaml +0 -0
- {oacp_cli-0.4.1 → oacp_cli-0.4.2}/tests/conformance/envelope/expected/unparsable_profile_fails.yaml +0 -0
- {oacp_cli-0.4.1 → oacp_cli-0.4.2}/tests/conformance/envelope/messages/clean_pr_task.yaml +0 -0
- {oacp_cli-0.4.1 → oacp_cli-0.4.2}/tests/conformance/envelope/messages/docs_only_task.yaml +0 -0
- {oacp_cli-0.4.1 → oacp_cli-0.4.2}/tests/conformance/envelope/messages/granular_capabilities_task.yaml +0 -0
- {oacp_cli-0.4.1 → oacp_cli-0.4.2}/tests/conformance/envelope/messages/invalid_numeric.yaml +0 -0
- {oacp_cli-0.4.1 → oacp_cli-0.4.2}/tests/conformance/envelope/messages/missing_profile.yaml +0 -0
- {oacp_cli-0.4.1 → oacp_cli-0.4.2}/tests/conformance/envelope/messages/unparsable_profile.yaml +0 -0
- {oacp_cli-0.4.1 → oacp_cli-0.4.2}/tests/conformance/signing/README.md +0 -0
- {oacp_cli-0.4.1 → oacp_cli-0.4.2}/tests/conformance/signing/expected/signed_basic.yaml +0 -0
- {oacp_cli-0.4.1 → oacp_cli-0.4.2}/tests/conformance/signing/expected/signed_lookalike.yaml +0 -0
- {oacp_cli-0.4.1 → oacp_cli-0.4.2}/tests/conformance/signing/expected/signed_multisig.yaml +0 -0
- {oacp_cli-0.4.1 → oacp_cli-0.4.2}/tests/conformance/signing/expected/signed_revoked.yaml +0 -0
- {oacp_cli-0.4.1 → oacp_cli-0.4.2}/tests/conformance/signing/expected/tamper_auth_alias.yaml +0 -0
- {oacp_cli-0.4.1 → oacp_cli-0.4.2}/tests/conformance/signing/expected/tamper_body_flip.yaml +0 -0
- {oacp_cli-0.4.1 → oacp_cli-0.4.2}/tests/conformance/signing/expected/tamper_container_reformat.yaml +0 -0
- {oacp_cli-0.4.1 → oacp_cli-0.4.2}/tests/conformance/signing/expected/tamper_crlf_trailer.yaml +0 -0
- {oacp_cli-0.4.1 → oacp_cli-0.4.2}/tests/conformance/signing/expected/tamper_header_reencode.yaml +0 -0
- {oacp_cli-0.4.1 → oacp_cli-0.4.2}/tests/conformance/signing/expected/tamper_identity_mismatch.yaml +0 -0
- {oacp_cli-0.4.1 → oacp_cli-0.4.2}/tests/conformance/signing/expected/tamper_indented_trailer.yaml +0 -0
- {oacp_cli-0.4.1 → oacp_cli-0.4.2}/tests/conformance/signing/expected/tamper_kid_alias.yaml +0 -0
- {oacp_cli-0.4.1 → oacp_cli-0.4.2}/tests/conformance/signing/expected/tamper_kid_cross_agent.yaml +0 -0
- {oacp_cli-0.4.1 → oacp_cli-0.4.2}/tests/conformance/signing/expected/tamper_kid_unknown.yaml +0 -0
- {oacp_cli-0.4.1 → oacp_cli-0.4.2}/tests/conformance/signing/expected/tamper_missing_final_lf.yaml +0 -0
- {oacp_cli-0.4.1 → oacp_cli-0.4.2}/tests/conformance/signing/expected/tamper_padded_b64.yaml +0 -0
- {oacp_cli-0.4.1 → oacp_cli-0.4.2}/tests/conformance/signing/expected/tamper_sig_alias.yaml +0 -0
- {oacp_cli-0.4.1 → oacp_cli-0.4.2}/tests/conformance/signing/expected/tamper_sig_corrupt.yaml +0 -0
- {oacp_cli-0.4.1 → oacp_cli-0.4.2}/tests/conformance/signing/expected/tamper_trailer_transplant.yaml +0 -0
- {oacp_cli-0.4.1 → oacp_cli-0.4.2}/tests/conformance/signing/expected/tamper_trailing_blank_line.yaml +0 -0
- {oacp_cli-0.4.1 → oacp_cli-0.4.2}/tests/conformance/signing/expected/tamper_trailing_space.yaml +0 -0
- {oacp_cli-0.4.1 → oacp_cli-0.4.2}/tests/conformance/signing/expected/unsigned_notification.yaml +0 -0
- {oacp_cli-0.4.1 → oacp_cli-0.4.2}/tests/conformance/signing/keys/alice.json +0 -0
- {oacp_cli-0.4.1 → oacp_cli-0.4.2}/tests/conformance/signing/keys/bob.json +0 -0
- {oacp_cli-0.4.1 → oacp_cli-0.4.2}/tests/conformance/signing/keys/carol.json +0 -0
- {oacp_cli-0.4.1 → oacp_cli-0.4.2}/tests/conformance/signing/messages/signed_basic.prefix.yaml +0 -0
- {oacp_cli-0.4.1 → oacp_cli-0.4.2}/tests/conformance/signing/messages/signed_basic.yaml +0 -0
- {oacp_cli-0.4.1 → oacp_cli-0.4.2}/tests/conformance/signing/messages/signed_lookalike.prefix.yaml +0 -0
- {oacp_cli-0.4.1 → oacp_cli-0.4.2}/tests/conformance/signing/messages/signed_lookalike.yaml +0 -0
- {oacp_cli-0.4.1 → oacp_cli-0.4.2}/tests/conformance/signing/messages/signed_multisig.prefix.yaml +0 -0
- {oacp_cli-0.4.1 → oacp_cli-0.4.2}/tests/conformance/signing/messages/signed_multisig.yaml +0 -0
- {oacp_cli-0.4.1 → oacp_cli-0.4.2}/tests/conformance/signing/messages/signed_revoked.prefix.yaml +0 -0
- {oacp_cli-0.4.1 → oacp_cli-0.4.2}/tests/conformance/signing/messages/signed_revoked.yaml +0 -0
- {oacp_cli-0.4.1 → oacp_cli-0.4.2}/tests/conformance/signing/messages/tamper_auth_alias.yaml +0 -0
- {oacp_cli-0.4.1 → oacp_cli-0.4.2}/tests/conformance/signing/messages/tamper_body_flip.yaml +0 -0
- {oacp_cli-0.4.1 → oacp_cli-0.4.2}/tests/conformance/signing/messages/tamper_container_reformat.yaml +0 -0
- {oacp_cli-0.4.1 → oacp_cli-0.4.2}/tests/conformance/signing/messages/tamper_crlf_trailer.yaml +0 -0
- {oacp_cli-0.4.1 → oacp_cli-0.4.2}/tests/conformance/signing/messages/tamper_header_reencode.yaml +0 -0
- {oacp_cli-0.4.1 → oacp_cli-0.4.2}/tests/conformance/signing/messages/tamper_identity_mismatch.prefix.yaml +0 -0
- {oacp_cli-0.4.1 → oacp_cli-0.4.2}/tests/conformance/signing/messages/tamper_identity_mismatch.yaml +0 -0
- {oacp_cli-0.4.1 → oacp_cli-0.4.2}/tests/conformance/signing/messages/tamper_indented_trailer.yaml +0 -0
- {oacp_cli-0.4.1 → oacp_cli-0.4.2}/tests/conformance/signing/messages/tamper_kid_alias.yaml +0 -0
- {oacp_cli-0.4.1 → oacp_cli-0.4.2}/tests/conformance/signing/messages/tamper_kid_cross_agent.yaml +0 -0
- {oacp_cli-0.4.1 → oacp_cli-0.4.2}/tests/conformance/signing/messages/tamper_kid_unknown.yaml +0 -0
- {oacp_cli-0.4.1 → oacp_cli-0.4.2}/tests/conformance/signing/messages/tamper_missing_final_lf.yaml +0 -0
- {oacp_cli-0.4.1 → oacp_cli-0.4.2}/tests/conformance/signing/messages/tamper_padded_b64.yaml +0 -0
- {oacp_cli-0.4.1 → oacp_cli-0.4.2}/tests/conformance/signing/messages/tamper_sig_alias.yaml +0 -0
- {oacp_cli-0.4.1 → oacp_cli-0.4.2}/tests/conformance/signing/messages/tamper_sig_corrupt.yaml +0 -0
- {oacp_cli-0.4.1 → oacp_cli-0.4.2}/tests/conformance/signing/messages/tamper_trailer_transplant.yaml +0 -0
- {oacp_cli-0.4.1 → oacp_cli-0.4.2}/tests/conformance/signing/messages/tamper_trailing_blank_line.yaml +0 -0
- {oacp_cli-0.4.1 → oacp_cli-0.4.2}/tests/conformance/signing/messages/tamper_trailing_space.yaml +0 -0
- {oacp_cli-0.4.1 → oacp_cli-0.4.2}/tests/conformance/signing/messages/unsigned_notification.yaml +0 -0
- {oacp_cli-0.4.1 → oacp_cli-0.4.2}/tests/conformance/signing/pins/allowed_signers.yaml +0 -0
- {oacp_cli-0.4.1 → oacp_cli-0.4.2}/tests/conformance/signing/regen_fixtures.py +0 -0
- {oacp_cli-0.4.1 → oacp_cli-0.4.2}/tests/test_add_agent.py +0 -0
- {oacp_cli-0.4.1 → oacp_cli-0.4.2}/tests/test_agent_profile.py +0 -0
- {oacp_cli-0.4.1 → oacp_cli-0.4.2}/tests/test_autonomy_conformance_fixtures.py +0 -0
- {oacp_cli-0.4.1 → oacp_cli-0.4.2}/tests/test_codex_session_init.py +0 -0
- {oacp_cli-0.4.1 → oacp_cli-0.4.2}/tests/test_create_handoff_packet.py +0 -0
- {oacp_cli-0.4.1 → oacp_cli-0.4.2}/tests/test_envelope_compiler.py +0 -0
- {oacp_cli-0.4.1 → oacp_cli-0.4.2}/tests/test_envelope_conformance_fixtures.py +0 -0
- {oacp_cli-0.4.1 → oacp_cli-0.4.2}/tests/test_github_workflows.py +0 -0
- {oacp_cli-0.4.1 → oacp_cli-0.4.2}/tests/test_handoff_schema.py +0 -0
- {oacp_cli-0.4.1 → oacp_cli-0.4.2}/tests/test_init_project_workspace.py +0 -0
- {oacp_cli-0.4.1 → oacp_cli-0.4.2}/tests/test_memory_archive.py +0 -0
- {oacp_cli-0.4.1 → oacp_cli-0.4.2}/tests/test_memory_sync.py +0 -0
- {oacp_cli-0.4.1 → oacp_cli-0.4.2}/tests/test_message_signing.py +0 -0
- {oacp_cli-0.4.1 → oacp_cli-0.4.2}/tests/test_oacp_cli.py +0 -0
- {oacp_cli-0.4.1 → oacp_cli-0.4.2}/tests/test_oacp_coordinator.py +0 -0
- {oacp_cli-0.4.1 → oacp_cli-0.4.2}/tests/test_oacp_env.py +0 -0
- {oacp_cli-0.4.1 → oacp_cli-0.4.2}/tests/test_oacp_inbox.py +0 -0
- {oacp_cli-0.4.1 → oacp_cli-0.4.2}/tests/test_oacp_watch.py +0 -0
- {oacp_cli-0.4.1 → oacp_cli-0.4.2}/tests/test_preflight.py +0 -0
- {oacp_cli-0.4.1 → oacp_cli-0.4.2}/tests/test_record_autonomy_outcome.py +0 -0
- {oacp_cli-0.4.1 → oacp_cli-0.4.2}/tests/test_review_loop.py +0 -0
- {oacp_cli-0.4.1 → oacp_cli-0.4.2}/tests/test_send_inbox_message.py +0 -0
- {oacp_cli-0.4.1 → oacp_cli-0.4.2}/tests/test_session_lifecycle_hooks.py +0 -0
- {oacp_cli-0.4.1 → oacp_cli-0.4.2}/tests/test_setup_runtime.py +0 -0
- {oacp_cli-0.4.1 → oacp_cli-0.4.2}/tests/test_signing_conformance.py +0 -0
- {oacp_cli-0.4.1 → oacp_cli-0.4.2}/tests/test_update_workspace.py +0 -0
- {oacp_cli-0.4.1 → oacp_cli-0.4.2}/tests/test_validate_agent_card.py +0 -0
- {oacp_cli-0.4.1 → oacp_cli-0.4.2}/tests/test_validate_message.py +0 -0
- {oacp_cli-0.4.1 → oacp_cli-0.4.2}/tests/test_workspace_discovery.py +0 -0
- {oacp_cli-0.4.1 → oacp_cli-0.4.2}/tests/test_write_event.py +0 -0
|
@@ -32,7 +32,7 @@ jobs:
|
|
|
32
32
|
- name: Install Python dependencies
|
|
33
33
|
run: |
|
|
34
34
|
python -m pip install --upgrade pip
|
|
35
|
-
python -m pip install -e . build pytest ruff
|
|
35
|
+
python -m pip install -e ".[crypto]" build pytest ruff
|
|
36
36
|
|
|
37
37
|
- name: Run quality gate
|
|
38
38
|
run: make preflight ARGS="--full"
|
|
@@ -5,6 +5,134 @@ All notable changes to this project will be documented in this file.
|
|
|
5
5
|
The format is based on [Keep a Changelog](https://keepachangelog.com/en/1.1.0/),
|
|
6
6
|
and this project adheres to [Semantic Versioning](https://semver.org/spec/v2.0.0.html).
|
|
7
7
|
|
|
8
|
+
## [0.4.2] - 2026-08-07
|
|
9
|
+
|
|
10
|
+
### Added
|
|
11
|
+
|
|
12
|
+
- Profileless admitted requests now receive a documented **default scope
|
|
13
|
+
envelope** instead of running unbounded: 25 minutes / 2 files /
|
|
14
|
+
reply-only, every capability and risk flag false, `risk_tier` mirroring
|
|
15
|
+
the message's declared priority (else `P2`). `allow_without_task_profile`
|
|
16
|
+
is thereby an admission-only exemption — the sender needn't author a
|
|
17
|
+
profile, but the bound always exists, and the post-accept threshold
|
|
18
|
+
checkpoint is always evaluable. A sender-attached voluntary profile on an
|
|
19
|
+
exempt type is the documented override path and replaces the default
|
|
20
|
+
entirely. Every decision names its envelope origin in the new
|
|
21
|
+
`scope_envelope_source` field (`task_profile` / `default_profileless`),
|
|
22
|
+
and `scope_envelope: null` on an admitted record is now a schema
|
|
23
|
+
violation the audit writer refuses to persist. Protocol spec version
|
|
24
|
+
bumps to 0.4.2.
|
|
25
|
+
- Admitted public-visibility tasks gain an explicit, recorded enforcement
|
|
26
|
+
branch: `oacp envelope compile --audit <admission-record>` on a
|
|
27
|
+
`public_visibility: true` task whose record carries a human admission
|
|
28
|
+
approval deliberately does **not** compile (a compiled public envelope
|
|
29
|
+
denies the entire approved chain) and instead stamps
|
|
30
|
+
`envelope_enforcement: none` with the named reason
|
|
31
|
+
`public_visibility_admission_approved` into the audit record — the
|
|
32
|
+
degradation is a documented mode with the human as the bound, not a
|
|
33
|
+
silent absence. The approval record is treated as authorization:
|
|
34
|
+
`--audit` must resolve inside the receiver's canonical admission audit
|
|
35
|
+
directory, the record must be an admission-paused record bound to the
|
|
36
|
+
exact verified message snapshot (`message_sha256`) with a recorded
|
|
37
|
+
`approved`/`modified` outcome, eligibility and the stamp consume one
|
|
38
|
+
locked read, and the branch fails closed while any envelope is active
|
|
39
|
+
for the receiver. Unapproved public tasks and all private tasks are
|
|
40
|
+
unaffected and keep the fail-closed compile path.
|
|
41
|
+
- `signing.verify_mode: enforce` is now a real mode with a real caller.
|
|
42
|
+
The autonomy gate invokes verification at message intake, before any
|
|
43
|
+
evaluation: under enforce, only a `signed-verified` message proceeds —
|
|
44
|
+
every other outcome (unsigned, INVALID, unknown-kid, revoked,
|
|
45
|
+
unverifiable) quarantines a mode-600 evidence copy into the receiver's
|
|
46
|
+
`dead_letter/`, evaluates nothing, and exits `3` with an
|
|
47
|
+
`intake_rejected` decision object. Rejection is mechanism, not
|
|
48
|
+
per-receiver diligence; previously the mode silently degraded to warn
|
|
49
|
+
and nothing on the receive path consumed it. Warn and off behavior are
|
|
50
|
+
unchanged. The receive-path contract is pinned by a new executable
|
|
51
|
+
conformance corpus at `tests/conformance/intake/` (four failure classes
|
|
52
|
+
under each mode, plus a signed-verified positive control).
|
|
53
|
+
- Policy-file signing: `oacp trust sign-policy` signs a receiver's
|
|
54
|
+
`config.yaml` and `trust/allowed_signers.yaml` with the receiver's own
|
|
55
|
+
local key, under a distinct JOSE profile (`oacp-policy+yaml` /
|
|
56
|
+
`urn:oacp:policy:v1`) so message and policy signatures can never be
|
|
57
|
+
exchanged. Loaders verify at load time: audit records now carry a
|
|
58
|
+
`policy_auth` block binding `policy_sha256` to an authorized signer; a
|
|
59
|
+
tampered `config.yaml` fails closed with the new pinned reason code
|
|
60
|
+
`policy_auth_invalid` before anything — including its own
|
|
61
|
+
`verify_mode` — reads it, and a tampered `allowed_signers.yaml` makes
|
|
62
|
+
the trust root unusable (under enforce, everything then rejects).
|
|
63
|
+
Unsigned policy files remain loadable with the unsigned state recorded
|
|
64
|
+
(bootstrap: init → key gen → sign-policy).
|
|
65
|
+
- Policy signatures bind their target context — `{project, receiver,
|
|
66
|
+
kind}` in the protected header — so a signed policy can never be
|
|
67
|
+
replayed across projects, receivers, or between `config.yaml` and
|
|
68
|
+
`allowed_signers.yaml`. `sign-policy` also enrolls each target in a
|
|
69
|
+
machine-local registry (`$OACP_HOME/keys/policy_enrollment.json`):
|
|
70
|
+
once enrolled, a policy file without a verifiable signature is
|
|
71
|
+
`invalid`, never `unsigned` — stripping a trailer stops being a
|
|
72
|
+
downgrade path. Trust mutations (`trust import` / `revoke`)
|
|
73
|
+
atomically re-sign an enrolled trust root or refuse the write.
|
|
74
|
+
- Single-read snapshot discipline on every receiver read path: the gate,
|
|
75
|
+
the trust-root load, and all policy consumers (envelope compiler, send
|
|
76
|
+
helper, trust mutations, inbox lister) verify and parse ONE bounded
|
|
77
|
+
read of each security-sensitive file, closing the window where a
|
|
78
|
+
config, message, or pins file could be swapped between its
|
|
79
|
+
verification and its use. The audit record's `message_sha256` now
|
|
80
|
+
names the verified snapshot bytes.
|
|
81
|
+
- Every non-gate inbox read path goes through one shared receive
|
|
82
|
+
boundary (verify one bounded snapshot before parsing it): the `oacp
|
|
83
|
+
inbox` lister, the `oacp watch` event emitter, the send helper's
|
|
84
|
+
parent-message lookup, and the trust drift report's traffic probe.
|
|
85
|
+
Under `enforce`, an unverified message surfaces as a held row/event
|
|
86
|
+
built from filesystem metadata only (no attacker-controlled field is
|
|
87
|
+
parsed or surfaced), never donates thread identity to replies, and
|
|
88
|
+
never counts as sender liveness; under `warn` rows and events carry
|
|
89
|
+
the verification status. A receiver config that fails policy
|
|
90
|
+
authorization cannot choose a weaker mode — these paths fail closed
|
|
91
|
+
to enforce. The envelope compiler refuses to compile from a message
|
|
92
|
+
that is not signed-verified under enforce, and the envelope's
|
|
93
|
+
`message_sha256` names the verified snapshot. `oacp trust list` and
|
|
94
|
+
doctor readiness calculations load policy files through the
|
|
95
|
+
authorized loader; `oacp doctor` reports per-receiver policy-file
|
|
96
|
+
authorization status.
|
|
97
|
+
|
|
98
|
+
### Fixed
|
|
99
|
+
|
|
100
|
+
- Intake conformance tests now skip goldens that pin a
|
|
101
|
+
signature-evaluation outcome when the optional cryptography dependency
|
|
102
|
+
is not installed, restoring the suite's graceful degradation without
|
|
103
|
+
the `[crypto]` extra. The release quality gate installs the extra so
|
|
104
|
+
the full signing matrix runs before publishing.
|
|
105
|
+
- Agent enumeration now consistently ignores hidden directories under
|
|
106
|
+
`agents/`, preventing runtime scaffolding such as `.claude/.cc-writes` from
|
|
107
|
+
appearing as phantom agents in doctor, inbox, profile, and trust workflows.
|
|
108
|
+
- Autonomy-gate negation demotion now recognizes common scope language and
|
|
109
|
+
carries unambiguous negation headings over their immediately following,
|
|
110
|
+
bounded block. Blank lines and subsequent headings end that scope, while
|
|
111
|
+
non-demotable side-effect and content-sensitivity hard stops remain hard.
|
|
112
|
+
- Claude envelope enforcement now allows a reconstructed Edit/Write change
|
|
113
|
+
confined to the project's own `[project] version` string in
|
|
114
|
+
`pyproject.toml` under `touches_dependencies: false`, while counting the
|
|
115
|
+
file and continuing to deny real dependency, mixed, ambiguous, and
|
|
116
|
+
Bash-side manifest edits.
|
|
117
|
+
- The foreign-session read-only `oacp envelope show` exemption now recognizes
|
|
118
|
+
argparse-equivalent `--option=value` spellings, unambiguous long-option
|
|
119
|
+
abbreviations, and help flags without weakening its fail-closed handling of
|
|
120
|
+
unknown options.
|
|
121
|
+
- Autonomy audit records now resolve `runtime.model` at the writer instead
|
|
122
|
+
of defaulting to a silent null. The serving model resolves caller-first
|
|
123
|
+
(an explicit `runtime.model` on the decision), then from the
|
|
124
|
+
`OACP_RUNTIME_MODEL` environment variable exported by the invoking
|
|
125
|
+
session, and is normalized at write time: case variants fold to
|
|
126
|
+
lowercase, and `[context]` suffixes split into the base id plus a
|
|
127
|
+
separate `model_context` field. `model_source` names the provenance and
|
|
128
|
+
`model_raw` preserves any input the normalization changed. Records with
|
|
129
|
+
no signal carry an explicit `model_unknown_reason` — never a silent
|
|
130
|
+
null — and the requested model (harness configuration) is never used as
|
|
131
|
+
a fallback. Historical records are not backfilled.
|
|
132
|
+
- The autonomy audit writer now validates `result.completion_kind` against
|
|
133
|
+
the pinned enum at write time, refusing to persist decisions that carry
|
|
134
|
+
a caller-composed off-enum kind.
|
|
135
|
+
|
|
8
136
|
## [0.4.1] - 2026-08-04
|
|
9
137
|
|
|
10
138
|
### Fixed
|
|
@@ -574,6 +702,8 @@ and this project adheres to [Semantic Versioning](https://semver.org/spec/v2.0.0
|
|
|
574
702
|
- Checkout step in github-release workflow job (#19)
|
|
575
703
|
- Pre-release audit fixes: SHA-pinned actions, dangling doc refs (#15, #16)
|
|
576
704
|
|
|
705
|
+
[0.4.2]: https://github.com/kiloloop/oacp/compare/v0.4.1...v0.4.2
|
|
706
|
+
[0.4.1]: https://github.com/kiloloop/oacp/compare/v0.4.0...v0.4.1
|
|
577
707
|
[0.4.0]: https://github.com/kiloloop/oacp/compare/v0.3.5...v0.4.0
|
|
578
708
|
[0.3.5]: https://github.com/kiloloop/oacp/compare/v0.3.4...v0.3.5
|
|
579
709
|
[0.3.4]: https://github.com/kiloloop/oacp/compare/v0.3.3...v0.3.4
|
|
@@ -1,6 +1,6 @@
|
|
|
1
1
|
Metadata-Version: 2.4
|
|
2
2
|
Name: oacp-cli
|
|
3
|
-
Version: 0.4.
|
|
3
|
+
Version: 0.4.2
|
|
4
4
|
Summary: Open Agent Coordination Protocol CLI for file-based multi-agent workflows
|
|
5
5
|
Project-URL: Homepage, https://github.com/kiloloop/oacp
|
|
6
6
|
Project-URL: Repository, https://github.com/kiloloop/oacp
|
|
@@ -35,6 +35,10 @@ Checks the project directory structure under `$OACP_HOME/projects/<name>/`.
|
|
|
35
35
|
- **workspace.json** — must exist and contain valid JSON
|
|
36
36
|
- **agents/ directory** — must exist; reports the number of registered agents
|
|
37
37
|
|
|
38
|
+
Agent discovery ignores hidden directories directly under `agents/`. Tooling
|
|
39
|
+
scaffolding such as `agents/.claude/.cc-writes/` is therefore not counted or
|
|
40
|
+
checked as a phantom agent if a runtime creates it in that location.
|
|
41
|
+
|
|
38
42
|
### 3. Inbox Health
|
|
39
43
|
|
|
40
44
|
Scans each agent's `inbox/` directory for pending messages and staleness.
|
|
@@ -106,6 +106,35 @@ schema-invalid profile pauses with `task_profile_unparsable`; it is not a fatal
|
|
|
106
106
|
message-schema error. Message types listed in `allow_without_task_profile`, such
|
|
107
107
|
as `brainstorm_request`, may auto-accept without the block.
|
|
108
108
|
|
|
109
|
+
### Default scope envelope (profileless admissions)
|
|
110
|
+
|
|
111
|
+
`allow_without_task_profile` is an **admission-only exemption**: the sender
|
|
112
|
+
needn't author a profile, but the bound always exists — a grant removes
|
|
113
|
+
friction, never the bound. A profileless admitted request receives the
|
|
114
|
+
documented default envelope instead of running unbounded:
|
|
115
|
+
|
|
116
|
+
- `estimated_minutes: 25`, `expected_files_touched: 2`, reply-only
|
|
117
|
+
(`sends_oacp_reply_only: true`); every other capability and risk flag
|
|
118
|
+
`false`; `target_repo` empty; no continuation grants.
|
|
119
|
+
- `risk_tier` mirrors the message's own declared `priority` when it is a
|
|
120
|
+
valid tier (`P0`–`P3`) — it is the sender's severity claim — else `P2`.
|
|
121
|
+
|
|
122
|
+
The default envelope binds the post-accept threshold checkpoint exactly
|
|
123
|
+
like a declared one: a genuinely long profileless task may
|
|
124
|
+
checkpoint-pause against it — that is the bound existing, by design, not a
|
|
125
|
+
regression. A sender that legitimately needs more attaches a **voluntary
|
|
126
|
+
`task_profile` on the exempt type** — a documented, supported path; the
|
|
127
|
+
profile's envelope then replaces the default entirely (and is the only way
|
|
128
|
+
an exempt type reaches continuation-grant evaluation, since a default
|
|
129
|
+
envelope declares nothing).
|
|
130
|
+
|
|
131
|
+
Every decision names its envelope's origin in `scope_envelope_source`
|
|
132
|
+
(`task_profile` or `default_profileless`; null only on a pause taken
|
|
133
|
+
before envelope construction). No admitted message type is
|
|
134
|
+
envelope-exempt — the exempt set is empty — and `scope_envelope: null` on
|
|
135
|
+
an admitted record is a **schema violation**: the audit writer refuses to
|
|
136
|
+
persist it rather than recording an unbounded admission.
|
|
137
|
+
|
|
109
138
|
The core declaration is complete only when it includes the two numeric fields,
|
|
110
139
|
`risk_tier`, and all five legacy risk booleans shown above. Granular side-effect
|
|
111
140
|
booleans are optional but must agree with `external_side_effects`; a profile
|
|
@@ -178,7 +207,16 @@ If any required gate is missing or uncertain, the receiver pauses.
|
|
|
178
207
|
- Path-like tokens such as `packets/deploy/` are not deploy verbs.
|
|
179
208
|
- Exclude sender-marked `oacp-guardrails` fences from demotable pause
|
|
180
209
|
classification while logging their matches as advisories. Suppress
|
|
181
|
-
demotable matches in clauses headed by `no`, `not`, `never`,
|
|
210
|
+
demotable matches in clauses headed by `no`, `not`, `never`, `do not`,
|
|
211
|
+
`does not`, `don't`, `doesn't`, `out of scope`, `exclude`/`excluded`,
|
|
212
|
+
`excludes`, `avoid`, `refrain from`, `prohibited`, `forbidden`, `skip`, or
|
|
213
|
+
`without`. A classic negation or scope-oriented form in a Markdown heading
|
|
214
|
+
or colon-terminated heading also scopes over the following block;
|
|
215
|
+
`skip` and `without` remain same-clause only because their ordinary prose
|
|
216
|
+
uses are ambiguous. Heading scope ends at the first blank line or next
|
|
217
|
+
heading, so the first governed line must follow the heading directly.
|
|
218
|
+
Non-demotable hard stops remain hard even when they appear in such a
|
|
219
|
+
clause or block.
|
|
182
220
|
- With a complete profile, demote side-effect or sensitive-scope lexical
|
|
183
221
|
matches to a logged `lexical_advisory` when the corresponding declaration
|
|
184
222
|
is `false`. Missing/unparsable profiles and contradictory declarations do
|
|
@@ -225,7 +263,7 @@ Every autonomy decision writes one YAML file:
|
|
|
225
263
|
|
|
226
264
|
```yaml
|
|
227
265
|
schema_version: 2
|
|
228
|
-
spec_version: "0.4.
|
|
266
|
+
spec_version: "0.4.2"
|
|
229
267
|
created_at_utc: "2026-05-12T13:23:25Z"
|
|
230
268
|
receiver: codex
|
|
231
269
|
sender: iris
|
|
@@ -267,7 +305,8 @@ breached: []
|
|
|
267
305
|
co_occurring_reason_codes: []
|
|
268
306
|
runtime:
|
|
269
307
|
agent: codex
|
|
270
|
-
model: gpt-5
|
|
308
|
+
model: gpt-5 # serving model, normalized at the writer; null only with a reason
|
|
309
|
+
model_source: "env:OACP_RUNTIME_MODEL"
|
|
271
310
|
evaluator:
|
|
272
311
|
source: scripts/autonomy_gate.py
|
|
273
312
|
content_sha256: "<sha256 of the evaluator file bytes>"
|
|
@@ -315,13 +354,26 @@ result:
|
|
|
315
354
|
missing or malformed config. `sender` is normally traceability metadata and
|
|
316
355
|
also binds an enabled standing grant to the sender that received approval.
|
|
317
356
|
`policy_sha256` is the SHA-256 of a canonical, key-sorted serialization of the
|
|
318
|
-
parsed policy
|
|
319
|
-
|
|
357
|
+
parsed policy (excluding any `auth` trailer key), so comments, YAML
|
|
358
|
+
formatting, and signing state do not produce false drift. Records written
|
|
359
|
+
through the gate CLI additionally carry a `policy_auth` block —
|
|
360
|
+
`{status: unsigned | verified | invalid | unsupported, signer_agent,
|
|
361
|
+
signer_kid, reason}` — the policy-file authorization outcome (see
|
|
362
|
+
`message_signing.md` → "Policy-file signing"): together with
|
|
363
|
+
`policy_sha256` the record commits to an *authorized* policy identity,
|
|
364
|
+
not just which bytes ran. An `invalid` status fails closed with reason
|
|
365
|
+
code `policy_auth_invalid` before any gate consumes the config.
|
|
366
|
+
`spec_version: "0.4.2"` pins everything 0.4.1 pinned — Gate 1 integrity
|
|
320
367
|
enforcement, the recalibrated Gate 2/3 policy, full task-profile capture, the
|
|
321
|
-
explicit `breached` list,
|
|
322
|
-
|
|
323
|
-
|
|
324
|
-
|
|
368
|
+
explicit `breached` list, the outcome block shown above, session-scoped
|
|
369
|
+
envelope enforcement, the enforce-mode trust-pin completeness gate, and
|
|
370
|
+
preserved `always_pause` defaults for configs without an `autonomy` block —
|
|
371
|
+
plus intake verification as mechanism (`verify_mode: enforce` rejects at
|
|
372
|
+
the gate), the `policy_auth` authorized-policy block, the default scope
|
|
373
|
+
envelope for profileless admissions (with `scope_envelope_source` and the
|
|
374
|
+
null-on-admitted writer refusal), and the recorded none-by-rule
|
|
375
|
+
enforcement branch for approved public-visibility tasks. Audit
|
|
376
|
+
`schema_version: 2` adds thread identity and
|
|
325
377
|
the structured `result.human_outcome` block. Recorders may upgrade a v1 audit
|
|
326
378
|
to v2 when the first human outcome is written; standing grants trust only v2
|
|
327
379
|
records.
|
|
@@ -337,6 +389,25 @@ non-checkout install all record `null` rather than a SHA that names code
|
|
|
337
389
|
which did not run. The only evaluator block a receiver ever authors by
|
|
338
390
|
hand is the no-executed-gate case: `executed: false` with no hashes.
|
|
339
391
|
|
|
392
|
+
`runtime.model` is resolved **at the writer and never backfilled**. The
|
|
393
|
+
serving model resolves caller-first (an explicit `runtime.model` already on
|
|
394
|
+
the decision), then from the `OACP_RUNTIME_MODEL` environment variable the
|
|
395
|
+
invoking session exports — the variable names the model actually serving
|
|
396
|
+
that session, not the model a configuration requested. Values are
|
|
397
|
+
normalized at write time: case variants fold to lowercase, and a
|
|
398
|
+
`[context]` suffix (same weights, different serving context window) splits
|
|
399
|
+
into the base id plus a separate `model_context` field so per-model
|
|
400
|
+
grouping never divides one model across suffix variants. `model_source`
|
|
401
|
+
names the provenance (`caller` or `env:OACP_RUNTIME_MODEL`) and
|
|
402
|
+
`model_raw` preserves any input the normalization changed. A record with
|
|
403
|
+
no signal carries an explicit unknown — `model: null` plus a
|
|
404
|
+
`model_unknown_reason` — never a silent null. The *requested* model
|
|
405
|
+
(harness configuration, settings files) is deliberately never consulted,
|
|
406
|
+
and historical records are never rewritten: a request can be silently
|
|
407
|
+
served by a different model, alias, or context variant, and filling the
|
|
408
|
+
field from it would reintroduce exactly the confound the field exists to
|
|
409
|
+
remove.
|
|
410
|
+
|
|
340
411
|
`breached` is always an ordered list, but its entries intentionally reflect the
|
|
341
412
|
evaluation phase. Admission-time pauses record pinned gate reason codes (for
|
|
342
413
|
example `estimated_minutes_exceeds_threshold`); post-accept checkpoint pauses
|
|
@@ -373,7 +444,9 @@ Receivers copy the evaluator's `completion_kind` verbatim and never overwrite
|
|
|
373
444
|
it at terminal update time — a paused-then-approved task keeps
|
|
374
445
|
`admission_paused` while `final_state` moves to `done` and `human_outcome`
|
|
375
446
|
records the approval. Receiver-composed values outside this enum are
|
|
376
|
-
non-conforming
|
|
447
|
+
non-conforming, and the audit writer enforces the pin at write time: a
|
|
448
|
+
decision whose `result.completion_kind` is missing or outside the enum is
|
|
449
|
+
refused rather than persisted. Records written before this pin carry mixed
|
|
377
450
|
cause/event/state values (`hard_stop`, bare `paused`, fused decision+state
|
|
378
451
|
kinds) and cannot be bucketed against the pinned enum.
|
|
379
452
|
|
|
@@ -449,7 +522,10 @@ that malformed request can be approved or modified.
|
|
|
449
522
|
Evaluator implementations must reject unpinned reason codes. The canonical
|
|
450
523
|
families are:
|
|
451
524
|
|
|
452
|
-
- integrity/config: `config_malformed`, `
|
|
525
|
+
- integrity/config: `config_malformed`, `policy_auth_invalid` (the
|
|
526
|
+
receiver config carries a policy signature that fails verification —
|
|
527
|
+
the gate refuses to evaluate a tampered policy, distinguishably from a
|
|
528
|
+
merely malformed or absent one), `mode_always_pause`,
|
|
453
529
|
`message_invalid`, `message_expired`, `message_replayed`,
|
|
454
530
|
`task_profile_missing`, `task_profile_unparsable`,
|
|
455
531
|
`risk_obvious_no_profile`, `envelope_compile_error`;
|
|
@@ -623,13 +699,54 @@ autonomy config into a runtime envelope:
|
|
|
623
699
|
oacp envelope compile <message.yaml> --receiver <agent>
|
|
624
700
|
```
|
|
625
701
|
|
|
702
|
+
**Admitted public-visibility tasks are the one explicit exception.** A
|
|
703
|
+
compiled `public_visibility: true` envelope denies the entire chain the
|
|
704
|
+
human just approved — the runtime adapter has no post-approval carve-out —
|
|
705
|
+
so for a public task whose admission audit records a human outcome of
|
|
706
|
+
`approved`/`modified`, the receiver passes that record to the compiler:
|
|
707
|
+
|
|
708
|
+
```
|
|
709
|
+
oacp envelope compile <message.yaml> --receiver <agent> \
|
|
710
|
+
--audit <admission-record.yaml>
|
|
711
|
+
```
|
|
712
|
+
|
|
713
|
+
and the compiler takes the **none-by-rule branch**: it does **not**
|
|
714
|
+
compile, and it stamps `result.envelope_enforcement: none` plus
|
|
715
|
+
`result.envelope_enforcement_reason: public_visibility_admission_approved`
|
|
716
|
+
into the audit record under the audit lock. Degradation is the documented
|
|
717
|
+
mode, not silence — the human admission approval plus live supervision is
|
|
718
|
+
the named control, and the record says so.
|
|
719
|
+
|
|
720
|
+
The approval record is authorization, so eligibility is strict: the
|
|
721
|
+
`--audit` path must resolve inside the receiver's canonical admission
|
|
722
|
+
audit directory (`agents/<receiver>/audit/autonomy_decisions/` — an
|
|
723
|
+
arbitrary readable YAML never qualifies), and the record must be an
|
|
724
|
+
admission-**paused** record carrying a `schema_version`, content-matched
|
|
725
|
+
on `message_id` + `receiver` (in the record itself, never the filename),
|
|
726
|
+
bound to the exact verified message snapshot via `message_sha256`, with
|
|
727
|
+
a recorded human outcome of `approved` or `modified`. Eligibility and
|
|
728
|
+
the marker write consume ONE locked read of the record. A none-by-rule
|
|
729
|
+
result must also MEAN none: the branch holds the envelope lock, fails
|
|
730
|
+
closed if any envelope is active for the receiver (its normal lifecycle
|
|
731
|
+
clears it — never a silent delete, never a false `none`), and consumes
|
|
732
|
+
the compiling session's pending claim so a deliberate no-envelope
|
|
733
|
+
success cannot bind a later, unrelated compile.
|
|
734
|
+
|
|
735
|
+
This is a deliberate, recorded exception to "a grant removes friction,
|
|
736
|
+
never the bound": for approved public work the **human is the bound**,
|
|
737
|
+
and the exception retires when a post-approval envelope path (compile
|
|
738
|
+
consuming the recorded approval into a workable public envelope) ships.
|
|
739
|
+
Private tasks, and public tasks without a matching eligible record, are
|
|
740
|
+
entirely unaffected: the fail-closed compile below still runs, and an
|
|
741
|
+
unapproved public envelope still denies at the hook.
|
|
742
|
+
|
|
626
743
|
The envelope is written to
|
|
627
744
|
`agents/<receiver>/state/active_envelope.json`:
|
|
628
745
|
|
|
629
746
|
```json
|
|
630
747
|
{
|
|
631
748
|
"envelope_version": 1,
|
|
632
|
-
"spec_version": "0.4.
|
|
749
|
+
"spec_version": "0.4.2",
|
|
633
750
|
"compiler": "envelope_compiler.py",
|
|
634
751
|
"compiled_at_utc": "2026-07-12T02:00:00Z",
|
|
635
752
|
"project": "my-project",
|
|
@@ -705,7 +822,11 @@ dispatched task's constraints nor consumes its file budget. The scope never
|
|
|
705
822
|
silently narrows: an unbound envelope enforces every session in the
|
|
706
823
|
(project, agent) workspace exactly as before, and a caller the harness gave
|
|
707
824
|
no session id is enforced even under a bound envelope (it cannot be proven
|
|
708
|
-
foreign).
|
|
825
|
+
foreign). A foreign session still cannot mutate the shared envelope state;
|
|
826
|
+
only provably read-only inspection is exempt. The `oacp envelope show`
|
|
827
|
+
inspection grammar recognizes argparse-equivalent value options in both
|
|
828
|
+
`--option value` and `--option=value` forms, plus unambiguous long-option
|
|
829
|
+
abbreviations and help flags, while unknown options continue to fail closed.
|
|
709
830
|
|
|
710
831
|
Runtime decisions:
|
|
711
832
|
|
|
@@ -762,6 +883,14 @@ Runtime decisions:
|
|
|
762
883
|
- Determinable Bash write targets feed the same distinct-file counter as
|
|
763
884
|
Edit/Write calls (`/dev/*` excluded), so shell writes cannot bypass
|
|
764
885
|
`expected_files_touched`.
|
|
886
|
+
- A `pyproject.toml` Edit or Write under `touches_dependencies: false` is
|
|
887
|
+
exempt from the dependency-manifest denial only when the hook can
|
|
888
|
+
reconstruct both complete documents and prove that every byte outside the
|
|
889
|
+
sole `[project] version` string literal is unchanged. The file still counts
|
|
890
|
+
toward `expected_files_touched`. Dependency, optional-dependency, and
|
|
891
|
+
build-system changes remain denied, as do mixed edits, ambiguous or
|
|
892
|
+
unsupported file-tool inputs, and every Bash-side manifest write whose
|
|
893
|
+
resulting content cannot be proven before execution.
|
|
765
894
|
- Protocol bookkeeping never consumes the file budget. The receiver's own
|
|
766
895
|
`audit/`, `inbox/`, and `outbox/` directories and the runtime scratchpad
|
|
767
896
|
(reply/body-file composition) are the enforcement layer's instrumentation
|
|
@@ -836,8 +965,13 @@ envelope compile --extend`, which preserves accumulated counters.
|
|
|
836
965
|
|
|
837
966
|
The audit `result` block records `envelope_enforcement: hooks | none`.
|
|
838
967
|
Receivers set `hooks` after a successful compile on an adapter-equipped
|
|
839
|
-
runtime; `none` means pickup-gate-only enforcement
|
|
840
|
-
|
|
968
|
+
runtime; `none` means pickup-gate-only enforcement. Degradation must never
|
|
969
|
+
be silent: when `none` is a **rule** rather than a runtime gap, the record
|
|
970
|
+
carries the named reason alongside it —
|
|
971
|
+
`envelope_enforcement_reason: public_visibility_admission_approved` for
|
|
972
|
+
the admitted-public branch above, stamped by the compiler itself. A bare
|
|
973
|
+
`none` with no reason means an adapterless runtime (the historical
|
|
974
|
+
pickup-gate-only state), distinguishable from the rule-based mode.
|
|
841
975
|
|
|
842
976
|
Enforcement boundary: hooks constrain every tool call inside the session,
|
|
843
977
|
including subagent tool calls, and fire before sandbox/permission
|
|
@@ -75,9 +75,11 @@ named by `kid` (RFC 7638 thumbprint) and never carried in the message.
|
|
|
75
75
|
Sender signing is config-gated off by default (`signing.sign_messages`);
|
|
76
76
|
receivers without a `verify_mode` knob treat the trailer as an ordinary
|
|
77
77
|
optional field.
|
|
78
|
-
Receiver verification
|
|
79
|
-
|
|
80
|
-
|
|
78
|
+
Receiver verification is mode-gated (`off` / `warn` / `enforce`): warn
|
|
79
|
+
records identity and grants no authority; enforce rejects any message
|
|
80
|
+
that does not verify, at intake, with a quarantined evidence copy. The
|
|
81
|
+
modes, the trust root — receiver pins, the zero-authority project
|
|
82
|
+
catalog, `oacp trust import`, and key management — are documented in
|
|
81
83
|
[`message_signing.md`](message_signing.md).
|
|
82
84
|
|
|
83
85
|
## Message Types
|
|
@@ -1,28 +1,84 @@
|
|
|
1
|
-
# Message Signing — Trust Root & Key Management
|
|
1
|
+
# Message Signing — Trust Root & Key Management
|
|
2
2
|
|
|
3
3
|
Status: **non-normative** companion to the message-signing wire format.
|
|
4
4
|
The wire format itself — the raw-prefix detached-JWS `auth` trailer — is
|
|
5
5
|
specified in [`inbox_outbox.md` → "Signed messages"](inbox_outbox.md);
|
|
6
6
|
this document covers the trust root, verification modes, and key
|
|
7
|
-
management.
|
|
8
|
-
first authority-bearing knob (a later 0.4.x/0.5 release) as its own
|
|
9
|
-
reviewed change.
|
|
7
|
+
management.
|
|
10
8
|
|
|
11
|
-
##
|
|
9
|
+
## Verify modes
|
|
10
|
+
|
|
11
|
+
Receivers opt in per-agent via `signing.verify_mode: off | warn | enforce`
|
|
12
|
+
in `agents/<receiver>/config.yaml`; any other value degrades to `off`.
|
|
12
13
|
|
|
13
14
|
**Warn mode records identity and grants no authority.** Every verification
|
|
14
15
|
outcome — `unsigned`, `signed-verified`, `signed-unknown-kid`,
|
|
15
16
|
`signed-INVALID`, `signed-REVOKED` — produces an annotation and a
|
|
16
17
|
`message_auth` audit block; none of them rejects, quarantines-as-rejection,
|
|
17
18
|
or changes how a message is processed. A verified signature is a recorded
|
|
18
|
-
fact about who signed, not a permission.
|
|
19
|
-
|
|
20
|
-
|
|
21
|
-
|
|
22
|
-
|
|
23
|
-
|
|
24
|
-
|
|
25
|
-
|
|
19
|
+
fact about who signed, not a permission.
|
|
20
|
+
|
|
21
|
+
**Enforce mode makes rejection mechanism, not receiver diligence.** The
|
|
22
|
+
autonomy gate invokes verification at message intake, before any
|
|
23
|
+
evaluation, parse, or gate runs. Only `signed-verified` proceeds; every
|
|
24
|
+
other outcome — unsigned, INVALID, unknown-kid, revoked, and
|
|
25
|
+
unverifiable-without-crypto — is rejected: a mode-600 evidence copy is
|
|
26
|
+
quarantined into the receiver's `dead_letter/` (exclusive-create; the
|
|
27
|
+
original inbox artifact is never touched), nothing is evaluated, and the
|
|
28
|
+
gate exits `3` with an `intake_rejected` decision object. An unusable or
|
|
29
|
+
tampered trust root fails closed the same way: with no loadable pins,
|
|
30
|
+
nothing verifies, so everything rejects.
|
|
31
|
+
|
|
32
|
+
### Receiver intake contract
|
|
33
|
+
|
|
34
|
+
What a receiver's inbox-processing flow does with each annotation, by mode:
|
|
35
|
+
|
|
36
|
+
| Annotation | `off` | `warn` | `enforce` |
|
|
37
|
+
|---|---|---|---|
|
|
38
|
+
| (none — verification skipped) | process | — | — |
|
|
39
|
+
| `unsigned` | — | process; annotation recorded | rejected at intake (quarantined, unprocessed) |
|
|
40
|
+
| `signed-verified` | — | process; identity recorded | process |
|
|
41
|
+
| `signed-unknown-kid` | — | process; annotation recorded | rejected at intake |
|
|
42
|
+
| `signed-INVALID` | — | process; evidence quarantine available (`--quarantine`) | rejected at intake |
|
|
43
|
+
| `signed-REVOKED` | — | process; annotation recorded | rejected at intake |
|
|
44
|
+
| `signed-unverifiable (crypto unavailable)` | — | process; annotation recorded | rejected at intake (fail closed) |
|
|
45
|
+
|
|
46
|
+
Under `enforce` the rejection happens inside the gate CLI — a receiver
|
|
47
|
+
flow that never explicitly runs `oacp verify` still cannot process an
|
|
48
|
+
unverified message, because admission itself refuses. The quarantined
|
|
49
|
+
evidence copy plus the gate's `intake_rejected` output are the record of
|
|
50
|
+
the rejection; no admission audit record is written for a message that
|
|
51
|
+
never reached admission. Receivers surface the rejection to their
|
|
52
|
+
operator and may notify the sender; they never process or silently delete
|
|
53
|
+
the quarantined evidence.
|
|
54
|
+
|
|
55
|
+
Every receiver read path verifies before it parses. The gate is the
|
|
56
|
+
admission choke point; every other CLI surface that reads inbox
|
|
57
|
+
artifacts goes through one shared receive boundary (resolve the
|
|
58
|
+
authorized receiver config, load policy-checked pins, verify one
|
|
59
|
+
bounded snapshot, and only then parse those bytes): the `oacp inbox`
|
|
60
|
+
lister, the `oacp watch` event emitter, the send helper's
|
|
61
|
+
parent-message lookup (a held message can never donate
|
|
62
|
+
`conversation_id` to an outgoing reply), and the trust drift report's
|
|
63
|
+
inbox traffic probe (a forged `from:` line cannot manufacture a
|
|
64
|
+
liveness signal). Under `enforce`, a message that is not
|
|
65
|
+
`signed-verified` surfaces as a HELD row or event built from
|
|
66
|
+
filesystem metadata only — none of its (attacker-controlled) fields
|
|
67
|
+
are parsed or surfaced; under `warn` rows and events carry the
|
|
68
|
+
verification status; under `off` behavior is unchanged. These read
|
|
69
|
+
paths are read-only, so they never quarantine — dispositioning a held
|
|
70
|
+
message belongs to the processing path. The envelope compiler is a
|
|
71
|
+
processing step and fails closed instead: under `enforce` it refuses
|
|
72
|
+
to compile an envelope from a message that is not signed-verified,
|
|
73
|
+
and the envelope's `message_sha256` names the verified snapshot.
|
|
74
|
+
|
|
75
|
+
**Verified bytes are the processed bytes.** Verification and any
|
|
76
|
+
subsequent parse, hash, or evaluation of the same artifact consume one
|
|
77
|
+
bounded read — a single snapshot. A verifier that approves one read and a
|
|
78
|
+
consumer that then re-reads the path would leave a swap window between
|
|
79
|
+
them; the gate, the inbox lister, and the policy loaders all parse the
|
|
80
|
+
exact bytes they verified, and the audit record's `message_sha256` names
|
|
81
|
+
that snapshot.
|
|
26
82
|
|
|
27
83
|
## Enforce-mode preparation
|
|
28
84
|
|
|
@@ -188,6 +244,90 @@ Warn-mode semantics carry through unchanged: the block records identity
|
|
|
188
244
|
and grants no authority — gates and instrumentation consume it as
|
|
189
245
|
telemetry only.
|
|
190
246
|
|
|
247
|
+
## Policy-file signing
|
|
248
|
+
|
|
249
|
+
The autonomy audit record's `policy_sha256` proves **which** policy ran;
|
|
250
|
+
policy-file signing proves it was **authorized**. The receiver's two
|
|
251
|
+
policy files — `config.yaml` and `trust/allowed_signers.yaml` — carry the
|
|
252
|
+
same raw-prefix detached-JWS auth trailer as messages, under a distinct
|
|
253
|
+
JOSE profile (`typ: oacp-policy+yaml`, domain `urn:oacp:policy:v1`) so a
|
|
254
|
+
message signature can never authorize a policy file and a policy signature
|
|
255
|
+
can never authenticate a message.
|
|
256
|
+
|
|
257
|
+
- **Trust anchor**: the machine-local keystore under `$OACP_HOME/keys/`.
|
|
258
|
+
A policy file for receiver X verifies only against agent X's own public
|
|
259
|
+
keys (the `<kid>.pub.json` stubs written by `oacp key gen`); a valid
|
|
260
|
+
signature by a *different* local agent's key is a receiver-binding
|
|
261
|
+
failure, not authorization. Tampering with a policy file on disk
|
|
262
|
+
therefore requires the 0600 private key material, not just filesystem
|
|
263
|
+
write access. (The trust root cannot anchor its own signature — the
|
|
264
|
+
keystore is the separate root that breaks that cycle.)
|
|
265
|
+
- **Context binding**: every policy signature commits to its target —
|
|
266
|
+
`{project, receiver, kind}` (`receiver_config` or `allowed_signers`) —
|
|
267
|
+
inside the protected header's `oacp.policy` claim, and verification
|
|
268
|
+
requires an exact match against the file's canonical workspace
|
|
269
|
+
location. A signature over one project's policy never authorizes a
|
|
270
|
+
byte-identical file in another project, a config signature never
|
|
271
|
+
authorizes a trust root (or vice versa), and a signed policy file
|
|
272
|
+
copied outside its canonical location does not verify at all.
|
|
273
|
+
- **Sign and re-sign**:
|
|
274
|
+
|
|
275
|
+
```bash
|
|
276
|
+
oacp trust sign-policy --project <name> --agent <receiver>
|
|
277
|
+
```
|
|
278
|
+
|
|
279
|
+
signs both files with the receiver's own local key and round-trip
|
|
280
|
+
verifies them. Unlike messages (append-once, immutable), policy files
|
|
281
|
+
are long-lived and edited: signing strips any existing trailer and signs
|
|
282
|
+
the current content — run it again after every policy edit.
|
|
283
|
+
- **Enrollment (downgrade resistance)**: the first successful
|
|
284
|
+
`sign-policy` run enrolls each target in the machine-local registry
|
|
285
|
+
`$OACP_HOME/keys/policy_enrollment.json` (part of the keystore trust
|
|
286
|
+
anchor, outside every project workspace). From then on, that policy
|
|
287
|
+
file without a verifiable signature — trailer stripped, or crypto
|
|
288
|
+
unavailable — is `invalid`, never `unsigned`: stripping a signature is
|
|
289
|
+
tampering, not a path back to bootstrap. Enrollment is recorded only
|
|
290
|
+
after every target round-trip verifies, so a partial signing failure
|
|
291
|
+
never strands an unsigned file behind downgrade resistance.
|
|
292
|
+
- **Writers re-sign or refuse**: trust mutations that re-emit
|
|
293
|
+
`allowed_signers.yaml` (`oacp trust import` / `revoke`) atomically
|
|
294
|
+
re-sign an enrolled trust root with the receiver's own key. If the
|
|
295
|
+
signing key is unavailable, the mutation is refused before anything is
|
|
296
|
+
written — a writer never strips an enrolled file's signature as a side
|
|
297
|
+
effect, and a fleet-wide revoke either fully lands signed or leaves
|
|
298
|
+
zero pins changed.
|
|
299
|
+
- **One authorized read path**: consumers load policy files through a
|
|
300
|
+
single loader that reads the file once (bounded at 1 MiB), verifies
|
|
301
|
+
those bytes, and parses the policy from the same snapshot — the bytes
|
|
302
|
+
evaluated are always the bytes verified. This covers the autonomy gate,
|
|
303
|
+
intake's trust-root load, the envelope compiler, the send helper's
|
|
304
|
+
signing-intent read, trust mutations, and the inbox lister; `oacp
|
|
305
|
+
doctor` reports each policy file's authorization status per receiver
|
|
306
|
+
(verified / unsigned-bootstrap / invalid / unsupported) without
|
|
307
|
+
blocking diagnostics.
|
|
308
|
+
- **Verified at load, fail closed on tamper**: loaders check the signature
|
|
309
|
+
wherever the policy is consumed. The gate records the outcome in every
|
|
310
|
+
decision as a `policy_auth` block (`status`, `signer_agent`,
|
|
311
|
+
`signer_kid`, `reason`); together with `policy_sha256` the record
|
|
312
|
+
commits to an authorized policy identity, not just bytes. A **tampered**
|
|
313
|
+
`config.yaml` pauses the decision with reason code `policy_auth_invalid`
|
|
314
|
+
before anything reads the config — including its own `verify_mode`, so a
|
|
315
|
+
tamper cannot switch enforcement off. A **tampered**
|
|
316
|
+
`allowed_signers.yaml` makes the trust root unusable exactly like an
|
|
317
|
+
unreadable one: no pins load, and under `enforce` every inbound message
|
|
318
|
+
consequently rejects. Both failures are distinguishable in the record
|
|
319
|
+
from a policy that is merely *absent* (absent config is a usage error
|
|
320
|
+
with no record; absent pins simply mean no pins).
|
|
321
|
+
- **Bootstrap**: a fresh workspace's policy files are unsigned and load
|
|
322
|
+
normally with `policy_auth.status: unsigned` recorded — signing requires
|
|
323
|
+
a key, so the order is `oacp init` → `oacp key gen --agent <receiver>` →
|
|
324
|
+
`oacp trust sign-policy`. Unsigned is a visible, recorded state, never a
|
|
325
|
+
silent one. On a host without the crypto extra, a signed but
|
|
326
|
+
*unenrolled* policy file records `unsupported` and loads (signing
|
|
327
|
+
itself always requires the extra); an *enrolled* one is `invalid` —
|
|
328
|
+
fail closed, because that host's registry proves a signature is
|
|
329
|
+
required.
|
|
330
|
+
|
|
191
331
|
## Key management
|
|
192
332
|
|
|
193
333
|
- **Keys are per-machine and never leave `$OACP_HOME/keys/`.** They are
|
|
@@ -235,3 +375,9 @@ signed prefix bytes, and JWS preimages, plus a tamper-detection suite
|
|
|
235
375
|
cases). Implementations of the framing or the verify flow should run
|
|
236
376
|
against it; the corpus README defines which expected fields are
|
|
237
377
|
normative and why regenerating goldens requires a ruling.
|
|
378
|
+
|
|
379
|
+
The receive-path behavior — what a receiver *does* with each verification
|
|
380
|
+
outcome under each verify mode — is pinned separately by the intake corpus
|
|
381
|
+
at `tests/conformance/intake/`: four failure classes (unsigned /
|
|
382
|
+
signed-INVALID / unknown-kid / revoked) under `off`/`warn`/`enforce`, plus
|
|
383
|
+
a signed-verified positive control, executed against the real gate CLI.
|