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.
Files changed (364) hide show
  1. {oacp_cli-0.4.1 → oacp_cli-0.4.2}/.github/workflows/release.yml +1 -1
  2. {oacp_cli-0.4.1 → oacp_cli-0.4.2}/CHANGELOG.md +130 -0
  3. {oacp_cli-0.4.1 → oacp_cli-0.4.2}/PKG-INFO +1 -1
  4. {oacp_cli-0.4.1 → oacp_cli-0.4.2}/docs/guides/doctor.md +4 -0
  5. {oacp_cli-0.4.1 → oacp_cli-0.4.2}/docs/protocol/autonomy.md +149 -15
  6. {oacp_cli-0.4.1 → oacp_cli-0.4.2}/docs/protocol/inbox_outbox.md +5 -3
  7. {oacp_cli-0.4.1 → oacp_cli-0.4.2}/docs/protocol/message_signing.md +159 -13
  8. {oacp_cli-0.4.1 → oacp_cli-0.4.2}/pyproject.toml +2 -1
  9. {oacp_cli-0.4.1 → oacp_cli-0.4.2}/scripts/_oacp_constants.py +6 -1
  10. {oacp_cli-0.4.1 → oacp_cli-0.4.2}/scripts/agent_profile.py +9 -3
  11. {oacp_cli-0.4.1 → oacp_cli-0.4.2}/scripts/autonomy_gate.py +325 -18
  12. {oacp_cli-0.4.1 → oacp_cli-0.4.2}/scripts/claude_envelope_hook.py +162 -14
  13. {oacp_cli-0.4.1 → oacp_cli-0.4.2}/scripts/envelope_compiler.py +252 -5
  14. {oacp_cli-0.4.1 → oacp_cli-0.4.2}/scripts/message_signing.py +67 -19
  15. {oacp_cli-0.4.1 → oacp_cli-0.4.2}/scripts/message_verify.py +312 -31
  16. {oacp_cli-0.4.1 → oacp_cli-0.4.2}/scripts/oacp_doctor.py +109 -10
  17. {oacp_cli-0.4.1 → oacp_cli-0.4.2}/scripts/oacp_inbox.py +108 -25
  18. {oacp_cli-0.4.1 → oacp_cli-0.4.2}/scripts/oacp_watch.py +67 -13
  19. oacp_cli-0.4.2/scripts/policy_signing.py +643 -0
  20. {oacp_cli-0.4.1 → oacp_cli-0.4.2}/scripts/send_inbox_message.py +48 -10
  21. {oacp_cli-0.4.1 → oacp_cli-0.4.2}/scripts/trust_cli.py +120 -6
  22. {oacp_cli-0.4.1 → oacp_cli-0.4.2}/scripts/trust_root.py +198 -22
  23. {oacp_cli-0.4.1 → oacp_cli-0.4.2}/tests/conformance/autonomy/expected/brainstorm_side_effect_verbs_auto_accepts.yaml +1 -0
  24. {oacp_cli-0.4.1 → oacp_cli-0.4.2}/tests/conformance/autonomy/expected/brainstorm_without_profile_auto_accepts.yaml +1 -0
  25. {oacp_cli-0.4.1 → oacp_cli-0.4.2}/tests/conformance/autonomy/messages/negated_guardrails.yaml +9 -3
  26. oacp_cli-0.4.2/tests/conformance/intake/README.md +26 -0
  27. oacp_cli-0.4.2/tests/conformance/intake/configs/enforce.yaml +17 -0
  28. oacp_cli-0.4.2/tests/conformance/intake/configs/off.yaml +17 -0
  29. oacp_cli-0.4.2/tests/conformance/intake/configs/warn.yaml +17 -0
  30. oacp_cli-0.4.2/tests/conformance/intake/expected/signed_basic__enforce.yaml +9 -0
  31. oacp_cli-0.4.2/tests/conformance/intake/expected/signed_revoked__enforce.yaml +9 -0
  32. oacp_cli-0.4.2/tests/conformance/intake/expected/signed_revoked__off.yaml +9 -0
  33. oacp_cli-0.4.2/tests/conformance/intake/expected/signed_revoked__warn.yaml +9 -0
  34. oacp_cli-0.4.2/tests/conformance/intake/expected/tamper_body_flip__enforce.yaml +9 -0
  35. oacp_cli-0.4.2/tests/conformance/intake/expected/tamper_body_flip__off.yaml +9 -0
  36. oacp_cli-0.4.2/tests/conformance/intake/expected/tamper_body_flip__warn.yaml +9 -0
  37. oacp_cli-0.4.2/tests/conformance/intake/expected/tamper_kid_unknown__enforce.yaml +9 -0
  38. oacp_cli-0.4.2/tests/conformance/intake/expected/tamper_kid_unknown__off.yaml +9 -0
  39. oacp_cli-0.4.2/tests/conformance/intake/expected/tamper_kid_unknown__warn.yaml +9 -0
  40. oacp_cli-0.4.2/tests/conformance/intake/expected/unsigned_notification__enforce.yaml +9 -0
  41. oacp_cli-0.4.2/tests/conformance/intake/expected/unsigned_notification__off.yaml +9 -0
  42. oacp_cli-0.4.2/tests/conformance/intake/expected/unsigned_notification__warn.yaml +9 -0
  43. {oacp_cli-0.4.1 → oacp_cli-0.4.2}/tests/test_autonomy_gate.py +310 -1
  44. {oacp_cli-0.4.1 → oacp_cli-0.4.2}/tests/test_claude_envelope_hook.py +183 -0
  45. oacp_cli-0.4.2/tests/test_default_envelope.py +173 -0
  46. oacp_cli-0.4.2/tests/test_envelope_public_admission.py +394 -0
  47. oacp_cli-0.4.2/tests/test_inbox_verify.py +424 -0
  48. oacp_cli-0.4.2/tests/test_intake_conformance.py +133 -0
  49. {oacp_cli-0.4.1 → oacp_cli-0.4.2}/tests/test_message_verify.py +2 -2
  50. {oacp_cli-0.4.1 → oacp_cli-0.4.2}/tests/test_oacp_constants.py +23 -1
  51. {oacp_cli-0.4.1 → oacp_cli-0.4.2}/tests/test_oacp_doctor.py +35 -0
  52. oacp_cli-0.4.2/tests/test_policy_signing.py +555 -0
  53. {oacp_cli-0.4.1 → oacp_cli-0.4.2}/tests/test_trust_root.py +21 -0
  54. {oacp_cli-0.4.1 → oacp_cli-0.4.2}/.gitattributes +0 -0
  55. {oacp_cli-0.4.1 → oacp_cli-0.4.2}/.github/workflows/ci.yml +0 -0
  56. {oacp_cli-0.4.1 → oacp_cli-0.4.2}/.gitignore +0 -0
  57. {oacp_cli-0.4.1 → oacp_cli-0.4.2}/CONTRIBUTING.md +0 -0
  58. {oacp_cli-0.4.1 → oacp_cli-0.4.2}/LICENSE +0 -0
  59. {oacp_cli-0.4.1 → oacp_cli-0.4.2}/Makefile +0 -0
  60. {oacp_cli-0.4.1 → oacp_cli-0.4.2}/QUICKSTART.md +0 -0
  61. {oacp_cli-0.4.1 → oacp_cli-0.4.2}/README.md +0 -0
  62. {oacp_cli-0.4.1 → oacp_cli-0.4.2}/SECURITY.md +0 -0
  63. {oacp_cli-0.4.1 → oacp_cli-0.4.2}/SPEC.md +0 -0
  64. {oacp_cli-0.4.1 → oacp_cli-0.4.2}/docs/from-claude-p.md +0 -0
  65. {oacp_cli-0.4.1 → oacp_cli-0.4.2}/docs/guides/adoption.md +0 -0
  66. {oacp_cli-0.4.1 → oacp_cli-0.4.2}/docs/guides/prompt_caching.md +0 -0
  67. {oacp_cli-0.4.1 → oacp_cli-0.4.2}/docs/guides/runtime_capability_matrix.md +0 -0
  68. {oacp_cli-0.4.1 → oacp_cli-0.4.2}/docs/guides/setup.md +0 -0
  69. {oacp_cli-0.4.1 → oacp_cli-0.4.2}/docs/guides/unified_skill_spec.md +0 -0
  70. {oacp_cli-0.4.1 → oacp_cli-0.4.2}/docs/guides/versioning.md +0 -0
  71. {oacp_cli-0.4.1 → oacp_cli-0.4.2}/docs/img/oacp-cli-demo.png +0 -0
  72. {oacp_cli-0.4.1 → oacp_cli-0.4.2}/docs/img/oacp-filesystem-tree.png +0 -0
  73. {oacp_cli-0.4.1 → oacp_cli-0.4.2}/docs/img/oacp-fleet-thread.png +0 -0
  74. {oacp_cli-0.4.1 → oacp_cli-0.4.2}/docs/protocol/agent_profiles.md +0 -0
  75. {oacp_cli-0.4.1 → oacp_cli-0.4.2}/docs/protocol/agent_safety_defaults.md +0 -0
  76. {oacp_cli-0.4.1 → oacp_cli-0.4.2}/docs/protocol/credential_scoping.md +0 -0
  77. {oacp_cli-0.4.1 → oacp_cli-0.4.2}/docs/protocol/cross_runtime_sync.md +0 -0
  78. {oacp_cli-0.4.1 → oacp_cli-0.4.2}/docs/protocol/dispatch_states.yaml +0 -0
  79. {oacp_cli-0.4.1 → oacp_cli-0.4.2}/docs/protocol/mcp_integration.md +0 -0
  80. {oacp_cli-0.4.1 → oacp_cli-0.4.2}/docs/protocol/multi_agent_shared_workspace.md +0 -0
  81. {oacp_cli-0.4.1 → oacp_cli-0.4.2}/docs/protocol/org_memory.md +0 -0
  82. {oacp_cli-0.4.1 → oacp_cli-0.4.2}/docs/protocol/packet_states.yaml +0 -0
  83. {oacp_cli-0.4.1 → oacp_cli-0.4.2}/docs/protocol/review_loop.md +0 -0
  84. {oacp_cli-0.4.1 → oacp_cli-0.4.2}/docs/protocol/runtime_capabilities.md +0 -0
  85. {oacp_cli-0.4.1 → oacp_cli-0.4.2}/docs/protocol/session_init.md +0 -0
  86. {oacp_cli-0.4.1 → oacp_cli-0.4.2}/docs/protocol/skills_manifest.yaml +0 -0
  87. {oacp_cli-0.4.1 → oacp_cli-0.4.2}/docs/protocol/task_negotiation.md +0 -0
  88. {oacp_cli-0.4.1 → oacp_cli-0.4.2}/examples/demo-workspace/README.md +0 -0
  89. {oacp_cli-0.4.1 → oacp_cli-0.4.2}/examples/demo-workspace/org-memory/decisions.md +0 -0
  90. {oacp_cli-0.4.1 → oacp_cli-0.4.2}/examples/demo-workspace/org-memory/events/20260504-093015-postgres-over-dynamodb.md +0 -0
  91. {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
  92. {oacp_cli-0.4.1 → oacp_cli-0.4.2}/examples/demo-workspace/org-memory/events/20260515-102045-utc-timestamps-webhooks.md +0 -0
  93. {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
  94. {oacp_cli-0.4.1 → oacp_cli-0.4.2}/examples/demo-workspace/org-memory/events/20260527-110500-idempotency-keys-merged.md +0 -0
  95. {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
  96. {oacp_cli-0.4.1 → oacp_cli-0.4.2}/examples/demo-workspace/org-memory/recent.md +0 -0
  97. {oacp_cli-0.4.1 → oacp_cli-0.4.2}/examples/demo-workspace/org-memory/rules.md +0 -0
  98. {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
  99. {oacp_cli-0.4.1 → oacp_cli-0.4.2}/examples/demo-workspace/projects/parcel-api/memory/decision_log.md +0 -0
  100. {oacp_cli-0.4.1 → oacp_cli-0.4.2}/examples/demo-workspace/projects/parcel-api/memory/known_debt.md +0 -0
  101. {oacp_cli-0.4.1 → oacp_cli-0.4.2}/examples/demo-workspace/projects/parcel-api/memory/open_threads.md +0 -0
  102. {oacp_cli-0.4.1 → oacp_cli-0.4.2}/examples/demo-workspace/projects/parcel-api/memory/project_facts.md +0 -0
  103. {oacp_cli-0.4.1 → oacp_cli-0.4.2}/examples/quickstart/README.md +0 -0
  104. {oacp_cli-0.4.1 → oacp_cli-0.4.2}/mcp_servers/oacp_coordinator.py +0 -0
  105. {oacp_cli-0.4.1 → oacp_cli-0.4.2}/oacp/__init__.py +0 -0
  106. {oacp_cli-0.4.1 → oacp_cli-0.4.2}/oacp/cli.py +0 -0
  107. {oacp_cli-0.4.1 → oacp_cli-0.4.2}/oacp/envelope_hook.py +0 -0
  108. {oacp_cli-0.4.1 → oacp_cli-0.4.2}/scripts/_oacp_env.py +0 -0
  109. {oacp_cli-0.4.1 → oacp_cli-0.4.2}/scripts/add_agent.py +0 -0
  110. {oacp_cli-0.4.1 → oacp_cli-0.4.2}/scripts/check_quality_gate.py +0 -0
  111. {oacp_cli-0.4.1 → oacp_cli-0.4.2}/scripts/codex_session_init.py +0 -0
  112. {oacp_cli-0.4.1 → oacp_cli-0.4.2}/scripts/create_handoff_packet.py +0 -0
  113. {oacp_cli-0.4.1 → oacp_cli-0.4.2}/scripts/handoff_schema.py +0 -0
  114. {oacp_cli-0.4.1 → oacp_cli-0.4.2}/scripts/init_org_memory.py +0 -0
  115. {oacp_cli-0.4.1 → oacp_cli-0.4.2}/scripts/init_packet.sh +0 -0
  116. {oacp_cli-0.4.1 → oacp_cli-0.4.2}/scripts/init_project_workspace.py +0 -0
  117. {oacp_cli-0.4.1 → oacp_cli-0.4.2}/scripts/init_project_workspace.sh +0 -0
  118. {oacp_cli-0.4.1 → oacp_cli-0.4.2}/scripts/key_cli.py +0 -0
  119. {oacp_cli-0.4.1 → oacp_cli-0.4.2}/scripts/memory_archive_common.py +0 -0
  120. {oacp_cli-0.4.1 → oacp_cli-0.4.2}/scripts/memory_cli.py +0 -0
  121. {oacp_cli-0.4.1 → oacp_cli-0.4.2}/scripts/memory_sync.py +0 -0
  122. {oacp_cli-0.4.1 → oacp_cli-0.4.2}/scripts/normalize_findings.py +0 -0
  123. {oacp_cli-0.4.1 → oacp_cli-0.4.2}/scripts/preflight.py +0 -0
  124. {oacp_cli-0.4.1 → oacp_cli-0.4.2}/scripts/promote_to_archive.py +0 -0
  125. {oacp_cli-0.4.1 → oacp_cli-0.4.2}/scripts/record_autonomy_outcome.py +0 -0
  126. {oacp_cli-0.4.1 → oacp_cli-0.4.2}/scripts/restore_from_archive.py +0 -0
  127. {oacp_cli-0.4.1 → oacp_cli-0.4.2}/scripts/session_lifecycle_hooks.py +0 -0
  128. {oacp_cli-0.4.1 → oacp_cli-0.4.2}/scripts/setup_runtime.py +0 -0
  129. {oacp_cli-0.4.1 → oacp_cli-0.4.2}/scripts/update_workspace.sh +0 -0
  130. {oacp_cli-0.4.1 → oacp_cli-0.4.2}/scripts/validate_agent_card.py +0 -0
  131. {oacp_cli-0.4.1 → oacp_cli-0.4.2}/scripts/validate_message.py +0 -0
  132. {oacp_cli-0.4.1 → oacp_cli-0.4.2}/scripts/write_event.py +0 -0
  133. {oacp_cli-0.4.1 → oacp_cli-0.4.2}/templates/agent_card.template.yaml +0 -0
  134. {oacp_cli-0.4.1 → oacp_cli-0.4.2}/templates/agent_profile.template.yaml +0 -0
  135. {oacp_cli-0.4.1 → oacp_cli-0.4.2}/templates/agent_status.template.yaml +0 -0
  136. {oacp_cli-0.4.1 → oacp_cli-0.4.2}/templates/checkpoint.template.md +0 -0
  137. {oacp_cli-0.4.1 → oacp_cli-0.4.2}/templates/claude/agents/role_agent.template.md +0 -0
  138. {oacp_cli-0.4.1 → oacp_cli-0.4.2}/templates/claude/rules/guardrail.template.md +0 -0
  139. {oacp_cli-0.4.1 → oacp_cli-0.4.2}/templates/findings_packet.template.yaml +0 -0
  140. {oacp_cli-0.4.1 → oacp_cli-0.4.2}/templates/github_actions_quality_gate.yaml +0 -0
  141. {oacp_cli-0.4.1 → oacp_cli-0.4.2}/templates/guardrails/coding_standards.template.md +0 -0
  142. {oacp_cli-0.4.1 → oacp_cli-0.4.2}/templates/guardrails/safe_commands.template.md +0 -0
  143. {oacp_cli-0.4.1 → oacp_cli-0.4.2}/templates/guardrails/secrets_rules.template.md +0 -0
  144. {oacp_cli-0.4.1 → oacp_cli-0.4.2}/templates/handoff_packet.template.yaml +0 -0
  145. {oacp_cli-0.4.1 → oacp_cli-0.4.2}/templates/inbox_message.template.yaml +0 -0
  146. {oacp_cli-0.4.1 → oacp_cli-0.4.2}/templates/manual_validation.template.md +0 -0
  147. {oacp_cli-0.4.1 → oacp_cli-0.4.2}/templates/merge_decision.template.md +0 -0
  148. {oacp_cli-0.4.1 → oacp_cli-0.4.2}/templates/org-memory/decisions.md +0 -0
  149. {oacp_cli-0.4.1 → oacp_cli-0.4.2}/templates/org-memory/events/.gitkeep +0 -0
  150. {oacp_cli-0.4.1 → oacp_cli-0.4.2}/templates/org-memory/events/20260317-170120-example-api-convention.md +0 -0
  151. {oacp_cli-0.4.1 → oacp_cli-0.4.2}/templates/org-memory/recent.md +0 -0
  152. {oacp_cli-0.4.1 → oacp_cli-0.4.2}/templates/org-memory/rules.md +0 -0
  153. {oacp_cli-0.4.1 → oacp_cli-0.4.2}/templates/receiver_config.template.yaml +0 -0
  154. {oacp_cli-0.4.1 → oacp_cli-0.4.2}/templates/review_packet.template.md +0 -0
  155. {oacp_cli-0.4.1 → oacp_cli-0.4.2}/templates/roles/role_baseline.template.md +0 -0
  156. {oacp_cli-0.4.1 → oacp_cli-0.4.2}/templates/roles/role_definition.template.yaml +0 -0
  157. {oacp_cli-0.4.1 → oacp_cli-0.4.2}/templates/runtime_capabilities.yaml +0 -0
  158. {oacp_cli-0.4.1 → oacp_cli-0.4.2}/templates/skills_manifest.template.yaml +0 -0
  159. {oacp_cli-0.4.1 → oacp_cli-0.4.2}/templates/test_packet.template.md +0 -0
  160. {oacp_cli-0.4.1 → oacp_cli-0.4.2}/tests/conformance/autonomy/README.md +0 -0
  161. {oacp_cli-0.4.1 → oacp_cli-0.4.2}/tests/conformance/autonomy/actuals/checkpoint_breach.yaml +0 -0
  162. {oacp_cli-0.4.1 → oacp_cli-0.4.2}/tests/conformance/autonomy/actuals/continuation_drift.yaml +0 -0
  163. {oacp_cli-0.4.1 → oacp_cli-0.4.2}/tests/conformance/autonomy/actuals/continuation_within.yaml +0 -0
  164. {oacp_cli-0.4.1 → oacp_cli-0.4.2}/tests/conformance/autonomy/actuals/declaration_error.yaml +0 -0
  165. {oacp_cli-0.4.1 → oacp_cli-0.4.2}/tests/conformance/autonomy/actuals/declaration_intent.yaml +0 -0
  166. {oacp_cli-0.4.1 → oacp_cli-0.4.2}/tests/conformance/autonomy/actuals/top_level_side_effect_keys.yaml +0 -0
  167. {oacp_cli-0.4.1 → oacp_cli-0.4.2}/tests/conformance/autonomy/audits/prior_thread_grant_approved.yaml +0 -0
  168. {oacp_cli-0.4.1 → oacp_cli-0.4.2}/tests/conformance/autonomy/configs/always_pause.yaml +0 -0
  169. {oacp_cli-0.4.1 → oacp_cli-0.4.2}/tests/conformance/autonomy/configs/auto_review_continuation_enabled.yaml +0 -0
  170. {oacp_cli-0.4.1 → oacp_cli-0.4.2}/tests/conformance/autonomy/configs/auto_review_external_pause.yaml +0 -0
  171. {oacp_cli-0.4.1 → oacp_cli-0.4.2}/tests/conformance/autonomy/configs/auto_review_standard.yaml +0 -0
  172. {oacp_cli-0.4.1 → oacp_cli-0.4.2}/tests/conformance/autonomy/configs/auto_review_tight.yaml +0 -0
  173. {oacp_cli-0.4.1 → oacp_cli-0.4.2}/tests/conformance/autonomy/configs/malformed_config.yaml +0 -0
  174. {oacp_cli-0.4.1 → oacp_cli-0.4.2}/tests/conformance/autonomy/expected/always_pause_task.yaml +0 -0
  175. {oacp_cli-0.4.1 → oacp_cli-0.4.2}/tests/conformance/autonomy/expected/ambiguous_scope_pauses.yaml +0 -0
  176. {oacp_cli-0.4.1 → oacp_cli-0.4.2}/tests/conformance/autonomy/expected/brainstorm_destructive_pauses.yaml +0 -0
  177. {oacp_cli-0.4.1 → oacp_cli-0.4.2}/tests/conformance/autonomy/expected/checkpoint_breach_pauses.yaml +0 -0
  178. {oacp_cli-0.4.1 → oacp_cli-0.4.2}/tests/conformance/autonomy/expected/clean_auto_review_task.yaml +0 -0
  179. {oacp_cli-0.4.1 → oacp_cli-0.4.2}/tests/conformance/autonomy/expected/continuation_grant_destructive_pauses.yaml +0 -0
  180. {oacp_cli-0.4.1 → oacp_cli-0.4.2}/tests/conformance/autonomy/expected/continuation_grant_disabled_pauses.yaml +0 -0
  181. {oacp_cli-0.4.1 → oacp_cli-0.4.2}/tests/conformance/autonomy/expected/continuation_grant_drift_pauses.yaml +0 -0
  182. {oacp_cli-0.4.1 → oacp_cli-0.4.2}/tests/conformance/autonomy/expected/continuation_grant_enabled_auto_accepts.yaml +0 -0
  183. {oacp_cli-0.4.1 → oacp_cli-0.4.2}/tests/conformance/autonomy/expected/continuation_grant_external_uncovered_pauses.yaml +0 -0
  184. {oacp_cli-0.4.1 → oacp_cli-0.4.2}/tests/conformance/autonomy/expected/declaration_error_pauses.yaml +0 -0
  185. {oacp_cli-0.4.1 → oacp_cli-0.4.2}/tests/conformance/autonomy/expected/declaration_intent_checkpoint_pauses.yaml +0 -0
  186. {oacp_cli-0.4.1 → oacp_cli-0.4.2}/tests/conformance/autonomy/expected/declared_destructive_ops_pauses.yaml +0 -0
  187. {oacp_cli-0.4.1 → oacp_cli-0.4.2}/tests/conformance/autonomy/expected/expired_message_pauses.yaml +0 -0
  188. {oacp_cli-0.4.1 → oacp_cli-0.4.2}/tests/conformance/autonomy/expected/guardrails_fence_auto_accepts.yaml +0 -0
  189. {oacp_cli-0.4.1 → oacp_cli-0.4.2}/tests/conformance/autonomy/expected/hard_stop_dangerously_skip_permissions_pauses.yaml +0 -0
  190. {oacp_cli-0.4.1 → oacp_cli-0.4.2}/tests/conformance/autonomy/expected/hard_stop_external_side_effects_pauses.yaml +0 -0
  191. {oacp_cli-0.4.1 → oacp_cli-0.4.2}/tests/conformance/autonomy/expected/hard_stop_force_pauses.yaml +0 -0
  192. {oacp_cli-0.4.1 → oacp_cli-0.4.2}/tests/conformance/autonomy/expected/hard_stop_masking_threshold_pauses.yaml +0 -0
  193. {oacp_cli-0.4.1 → oacp_cli-0.4.2}/tests/conformance/autonomy/expected/hard_stop_no_verify_pauses.yaml +0 -0
  194. {oacp_cli-0.4.1 → oacp_cli-0.4.2}/tests/conformance/autonomy/expected/hard_stop_no_verify_upper_pauses.yaml +0 -0
  195. {oacp_cli-0.4.1 → oacp_cli-0.4.2}/tests/conformance/autonomy/expected/hard_stop_rm_rf_pauses.yaml +0 -0
  196. {oacp_cli-0.4.1 → oacp_cli-0.4.2}/tests/conformance/autonomy/expected/hard_stop_sensitive_commercial_pauses.yaml +0 -0
  197. {oacp_cli-0.4.1 → oacp_cli-0.4.2}/tests/conformance/autonomy/expected/hard_stop_sensitive_config_pauses.yaml +0 -0
  198. {oacp_cli-0.4.1 → oacp_cli-0.4.2}/tests/conformance/autonomy/expected/hard_stop_sensitive_credentials_pauses.yaml +0 -0
  199. {oacp_cli-0.4.1 → oacp_cli-0.4.2}/tests/conformance/autonomy/expected/hard_stop_sensitive_memory_ssot_pauses.yaml +0 -0
  200. {oacp_cli-0.4.1 → oacp_cli-0.4.2}/tests/conformance/autonomy/expected/hard_stop_sensitive_pricing_pauses.yaml +0 -0
  201. {oacp_cli-0.4.1 → oacp_cli-0.4.2}/tests/conformance/autonomy/expected/hard_stop_sensitive_public_repo_pauses.yaml +0 -0
  202. {oacp_cli-0.4.1 → oacp_cli-0.4.2}/tests/conformance/autonomy/expected/hard_stop_sensitive_scope_pauses.yaml +0 -0
  203. {oacp_cli-0.4.1 → oacp_cli-0.4.2}/tests/conformance/autonomy/expected/hard_stop_sensitive_secret_pauses.yaml +0 -0
  204. {oacp_cli-0.4.1 → oacp_cli-0.4.2}/tests/conformance/autonomy/expected/hard_stop_side_effect_before_sensitive_pauses.yaml +0 -0
  205. {oacp_cli-0.4.1 → oacp_cli-0.4.2}/tests/conformance/autonomy/expected/invalid_message_pauses.yaml +0 -0
  206. {oacp_cli-0.4.1 → oacp_cli-0.4.2}/tests/conformance/autonomy/expected/lexical_declared_false_auto_accepts.yaml +0 -0
  207. {oacp_cli-0.4.1 → oacp_cli-0.4.2}/tests/conformance/autonomy/expected/malformed_config_pauses.yaml +0 -0
  208. {oacp_cli-0.4.1 → oacp_cli-0.4.2}/tests/conformance/autonomy/expected/minutes_45_auto_accepts.yaml +0 -0
  209. {oacp_cli-0.4.1 → oacp_cli-0.4.2}/tests/conformance/autonomy/expected/minutes_46_pauses.yaml +0 -0
  210. {oacp_cli-0.4.1 → oacp_cli-0.4.2}/tests/conformance/autonomy/expected/missing_task_profile_pauses.yaml +0 -0
  211. {oacp_cli-0.4.1 → oacp_cli-0.4.2}/tests/conformance/autonomy/expected/negated_guardrails_auto_accepts.yaml +0 -0
  212. {oacp_cli-0.4.1 → oacp_cli-0.4.2}/tests/conformance/autonomy/expected/path_like_deploy_auto_accepts.yaml +0 -0
  213. {oacp_cli-0.4.1 → oacp_cli-0.4.2}/tests/conformance/autonomy/expected/private_issue_artifacts_auto_accepts.yaml +0 -0
  214. {oacp_cli-0.4.1 → oacp_cli-0.4.2}/tests/conformance/autonomy/expected/private_pr_artifacts_auto_accepts.yaml +0 -0
  215. {oacp_cli-0.4.1 → oacp_cli-0.4.2}/tests/conformance/autonomy/expected/private_pr_with_merge_pauses.yaml +0 -0
  216. {oacp_cli-0.4.1 → oacp_cli-0.4.2}/tests/conformance/autonomy/expected/public_pr_artifacts_pause.yaml +0 -0
  217. {oacp_cli-0.4.1 → oacp_cli-0.4.2}/tests/conformance/autonomy/expected/risk_obvious_no_profile_pauses.yaml +0 -0
  218. {oacp_cli-0.4.1 → oacp_cli-0.4.2}/tests/conformance/autonomy/expected/side_effect_booleans_pause.yaml +0 -0
  219. {oacp_cli-0.4.1 → oacp_cli-0.4.2}/tests/conformance/autonomy/expected/threshold_breach_pauses.yaml +0 -0
  220. {oacp_cli-0.4.1 → oacp_cli-0.4.2}/tests/conformance/autonomy/expected/tight_threshold_pauses.yaml +0 -0
  221. {oacp_cli-0.4.1 → oacp_cli-0.4.2}/tests/conformance/autonomy/expected/top_level_side_effect_actuals_ignored.yaml +0 -0
  222. {oacp_cli-0.4.1 → oacp_cli-0.4.2}/tests/conformance/autonomy/expected/unparsable_task_profile_pauses.yaml +0 -0
  223. {oacp_cli-0.4.1 → oacp_cli-0.4.2}/tests/conformance/autonomy/messages/ambiguous_scope.yaml +0 -0
  224. {oacp_cli-0.4.1 → oacp_cli-0.4.2}/tests/conformance/autonomy/messages/brainstorm_destructive.yaml +0 -0
  225. {oacp_cli-0.4.1 → oacp_cli-0.4.2}/tests/conformance/autonomy/messages/brainstorm_side_effect_verbs.yaml +0 -0
  226. {oacp_cli-0.4.1 → oacp_cli-0.4.2}/tests/conformance/autonomy/messages/brainstorm_without_profile.yaml +0 -0
  227. {oacp_cli-0.4.1 → oacp_cli-0.4.2}/tests/conformance/autonomy/messages/clean_task.yaml +0 -0
  228. {oacp_cli-0.4.1 → oacp_cli-0.4.2}/tests/conformance/autonomy/messages/continuation_grant.yaml +0 -0
  229. {oacp_cli-0.4.1 → oacp_cli-0.4.2}/tests/conformance/autonomy/messages/continuation_grant_destructive.yaml +0 -0
  230. {oacp_cli-0.4.1 → oacp_cli-0.4.2}/tests/conformance/autonomy/messages/continuation_grant_external_uncovered.yaml +0 -0
  231. {oacp_cli-0.4.1 → oacp_cli-0.4.2}/tests/conformance/autonomy/messages/declared_destructive_ops.yaml +0 -0
  232. {oacp_cli-0.4.1 → oacp_cli-0.4.2}/tests/conformance/autonomy/messages/expired_message.yaml +0 -0
  233. {oacp_cli-0.4.1 → oacp_cli-0.4.2}/tests/conformance/autonomy/messages/guardrails_fence.yaml +0 -0
  234. {oacp_cli-0.4.1 → oacp_cli-0.4.2}/tests/conformance/autonomy/messages/hard_stop_dangerously_skip_permissions.yaml +0 -0
  235. {oacp_cli-0.4.1 → oacp_cli-0.4.2}/tests/conformance/autonomy/messages/hard_stop_external_side_effects.yaml +0 -0
  236. {oacp_cli-0.4.1 → oacp_cli-0.4.2}/tests/conformance/autonomy/messages/hard_stop_force.yaml +0 -0
  237. {oacp_cli-0.4.1 → oacp_cli-0.4.2}/tests/conformance/autonomy/messages/hard_stop_masking_threshold.yaml +0 -0
  238. {oacp_cli-0.4.1 → oacp_cli-0.4.2}/tests/conformance/autonomy/messages/hard_stop_no_verify.yaml +0 -0
  239. {oacp_cli-0.4.1 → oacp_cli-0.4.2}/tests/conformance/autonomy/messages/hard_stop_no_verify_upper.yaml +0 -0
  240. {oacp_cli-0.4.1 → oacp_cli-0.4.2}/tests/conformance/autonomy/messages/hard_stop_rm_rf.yaml +0 -0
  241. {oacp_cli-0.4.1 → oacp_cli-0.4.2}/tests/conformance/autonomy/messages/hard_stop_sensitive_scope.yaml +0 -0
  242. {oacp_cli-0.4.1 → oacp_cli-0.4.2}/tests/conformance/autonomy/messages/invalid_message.yaml +0 -0
  243. {oacp_cli-0.4.1 → oacp_cli-0.4.2}/tests/conformance/autonomy/messages/lexical_declared_false.yaml +0 -0
  244. {oacp_cli-0.4.1 → oacp_cli-0.4.2}/tests/conformance/autonomy/messages/minutes_45.yaml +0 -0
  245. {oacp_cli-0.4.1 → oacp_cli-0.4.2}/tests/conformance/autonomy/messages/minutes_46.yaml +0 -0
  246. {oacp_cli-0.4.1 → oacp_cli-0.4.2}/tests/conformance/autonomy/messages/missing_task_profile.yaml +0 -0
  247. {oacp_cli-0.4.1 → oacp_cli-0.4.2}/tests/conformance/autonomy/messages/path_like_deploy.yaml +0 -0
  248. {oacp_cli-0.4.1 → oacp_cli-0.4.2}/tests/conformance/autonomy/messages/private_issue_artifacts.yaml +0 -0
  249. {oacp_cli-0.4.1 → oacp_cli-0.4.2}/tests/conformance/autonomy/messages/private_pr_artifacts.yaml +0 -0
  250. {oacp_cli-0.4.1 → oacp_cli-0.4.2}/tests/conformance/autonomy/messages/private_pr_with_merge.yaml +0 -0
  251. {oacp_cli-0.4.1 → oacp_cli-0.4.2}/tests/conformance/autonomy/messages/public_pr_artifacts.yaml +0 -0
  252. {oacp_cli-0.4.1 → oacp_cli-0.4.2}/tests/conformance/autonomy/messages/risk_obvious_no_profile.yaml +0 -0
  253. {oacp_cli-0.4.1 → oacp_cli-0.4.2}/tests/conformance/autonomy/messages/sensitive_commercial.yaml +0 -0
  254. {oacp_cli-0.4.1 → oacp_cli-0.4.2}/tests/conformance/autonomy/messages/sensitive_config.yaml +0 -0
  255. {oacp_cli-0.4.1 → oacp_cli-0.4.2}/tests/conformance/autonomy/messages/sensitive_credentials.yaml +0 -0
  256. {oacp_cli-0.4.1 → oacp_cli-0.4.2}/tests/conformance/autonomy/messages/sensitive_memory_ssot.yaml +0 -0
  257. {oacp_cli-0.4.1 → oacp_cli-0.4.2}/tests/conformance/autonomy/messages/sensitive_pricing.yaml +0 -0
  258. {oacp_cli-0.4.1 → oacp_cli-0.4.2}/tests/conformance/autonomy/messages/sensitive_public_repo.yaml +0 -0
  259. {oacp_cli-0.4.1 → oacp_cli-0.4.2}/tests/conformance/autonomy/messages/sensitive_secret.yaml +0 -0
  260. {oacp_cli-0.4.1 → oacp_cli-0.4.2}/tests/conformance/autonomy/messages/side_effect_before_sensitive.yaml +0 -0
  261. {oacp_cli-0.4.1 → oacp_cli-0.4.2}/tests/conformance/autonomy/messages/side_effect_booleans.yaml +0 -0
  262. {oacp_cli-0.4.1 → oacp_cli-0.4.2}/tests/conformance/autonomy/messages/threshold_breach.yaml +0 -0
  263. {oacp_cli-0.4.1 → oacp_cli-0.4.2}/tests/conformance/autonomy/messages/unparsable_task_profile.yaml +0 -0
  264. {oacp_cli-0.4.1 → oacp_cli-0.4.2}/tests/conformance/envelope/README.md +0 -0
  265. {oacp_cli-0.4.1 → oacp_cli-0.4.2}/tests/conformance/envelope/configs/auto_review_standard.yaml +0 -0
  266. {oacp_cli-0.4.1 → oacp_cli-0.4.2}/tests/conformance/envelope/configs/malformed.yaml +0 -0
  267. {oacp_cli-0.4.1 → oacp_cli-0.4.2}/tests/conformance/envelope/expected/clean_pr_task_compiles.yaml +0 -0
  268. {oacp_cli-0.4.1 → oacp_cli-0.4.2}/tests/conformance/envelope/expected/docs_only_task_compiles.yaml +0 -0
  269. {oacp_cli-0.4.1 → oacp_cli-0.4.2}/tests/conformance/envelope/expected/granular_capabilities_compile.yaml +0 -0
  270. {oacp_cli-0.4.1 → oacp_cli-0.4.2}/tests/conformance/envelope/expected/invalid_numeric_fails.yaml +0 -0
  271. {oacp_cli-0.4.1 → oacp_cli-0.4.2}/tests/conformance/envelope/expected/malformed_config_fails.yaml +0 -0
  272. {oacp_cli-0.4.1 → oacp_cli-0.4.2}/tests/conformance/envelope/expected/missing_profile_fails.yaml +0 -0
  273. {oacp_cli-0.4.1 → oacp_cli-0.4.2}/tests/conformance/envelope/expected/unparsable_profile_fails.yaml +0 -0
  274. {oacp_cli-0.4.1 → oacp_cli-0.4.2}/tests/conformance/envelope/messages/clean_pr_task.yaml +0 -0
  275. {oacp_cli-0.4.1 → oacp_cli-0.4.2}/tests/conformance/envelope/messages/docs_only_task.yaml +0 -0
  276. {oacp_cli-0.4.1 → oacp_cli-0.4.2}/tests/conformance/envelope/messages/granular_capabilities_task.yaml +0 -0
  277. {oacp_cli-0.4.1 → oacp_cli-0.4.2}/tests/conformance/envelope/messages/invalid_numeric.yaml +0 -0
  278. {oacp_cli-0.4.1 → oacp_cli-0.4.2}/tests/conformance/envelope/messages/missing_profile.yaml +0 -0
  279. {oacp_cli-0.4.1 → oacp_cli-0.4.2}/tests/conformance/envelope/messages/unparsable_profile.yaml +0 -0
  280. {oacp_cli-0.4.1 → oacp_cli-0.4.2}/tests/conformance/signing/README.md +0 -0
  281. {oacp_cli-0.4.1 → oacp_cli-0.4.2}/tests/conformance/signing/expected/signed_basic.yaml +0 -0
  282. {oacp_cli-0.4.1 → oacp_cli-0.4.2}/tests/conformance/signing/expected/signed_lookalike.yaml +0 -0
  283. {oacp_cli-0.4.1 → oacp_cli-0.4.2}/tests/conformance/signing/expected/signed_multisig.yaml +0 -0
  284. {oacp_cli-0.4.1 → oacp_cli-0.4.2}/tests/conformance/signing/expected/signed_revoked.yaml +0 -0
  285. {oacp_cli-0.4.1 → oacp_cli-0.4.2}/tests/conformance/signing/expected/tamper_auth_alias.yaml +0 -0
  286. {oacp_cli-0.4.1 → oacp_cli-0.4.2}/tests/conformance/signing/expected/tamper_body_flip.yaml +0 -0
  287. {oacp_cli-0.4.1 → oacp_cli-0.4.2}/tests/conformance/signing/expected/tamper_container_reformat.yaml +0 -0
  288. {oacp_cli-0.4.1 → oacp_cli-0.4.2}/tests/conformance/signing/expected/tamper_crlf_trailer.yaml +0 -0
  289. {oacp_cli-0.4.1 → oacp_cli-0.4.2}/tests/conformance/signing/expected/tamper_header_reencode.yaml +0 -0
  290. {oacp_cli-0.4.1 → oacp_cli-0.4.2}/tests/conformance/signing/expected/tamper_identity_mismatch.yaml +0 -0
  291. {oacp_cli-0.4.1 → oacp_cli-0.4.2}/tests/conformance/signing/expected/tamper_indented_trailer.yaml +0 -0
  292. {oacp_cli-0.4.1 → oacp_cli-0.4.2}/tests/conformance/signing/expected/tamper_kid_alias.yaml +0 -0
  293. {oacp_cli-0.4.1 → oacp_cli-0.4.2}/tests/conformance/signing/expected/tamper_kid_cross_agent.yaml +0 -0
  294. {oacp_cli-0.4.1 → oacp_cli-0.4.2}/tests/conformance/signing/expected/tamper_kid_unknown.yaml +0 -0
  295. {oacp_cli-0.4.1 → oacp_cli-0.4.2}/tests/conformance/signing/expected/tamper_missing_final_lf.yaml +0 -0
  296. {oacp_cli-0.4.1 → oacp_cli-0.4.2}/tests/conformance/signing/expected/tamper_padded_b64.yaml +0 -0
  297. {oacp_cli-0.4.1 → oacp_cli-0.4.2}/tests/conformance/signing/expected/tamper_sig_alias.yaml +0 -0
  298. {oacp_cli-0.4.1 → oacp_cli-0.4.2}/tests/conformance/signing/expected/tamper_sig_corrupt.yaml +0 -0
  299. {oacp_cli-0.4.1 → oacp_cli-0.4.2}/tests/conformance/signing/expected/tamper_trailer_transplant.yaml +0 -0
  300. {oacp_cli-0.4.1 → oacp_cli-0.4.2}/tests/conformance/signing/expected/tamper_trailing_blank_line.yaml +0 -0
  301. {oacp_cli-0.4.1 → oacp_cli-0.4.2}/tests/conformance/signing/expected/tamper_trailing_space.yaml +0 -0
  302. {oacp_cli-0.4.1 → oacp_cli-0.4.2}/tests/conformance/signing/expected/unsigned_notification.yaml +0 -0
  303. {oacp_cli-0.4.1 → oacp_cli-0.4.2}/tests/conformance/signing/keys/alice.json +0 -0
  304. {oacp_cli-0.4.1 → oacp_cli-0.4.2}/tests/conformance/signing/keys/bob.json +0 -0
  305. {oacp_cli-0.4.1 → oacp_cli-0.4.2}/tests/conformance/signing/keys/carol.json +0 -0
  306. {oacp_cli-0.4.1 → oacp_cli-0.4.2}/tests/conformance/signing/messages/signed_basic.prefix.yaml +0 -0
  307. {oacp_cli-0.4.1 → oacp_cli-0.4.2}/tests/conformance/signing/messages/signed_basic.yaml +0 -0
  308. {oacp_cli-0.4.1 → oacp_cli-0.4.2}/tests/conformance/signing/messages/signed_lookalike.prefix.yaml +0 -0
  309. {oacp_cli-0.4.1 → oacp_cli-0.4.2}/tests/conformance/signing/messages/signed_lookalike.yaml +0 -0
  310. {oacp_cli-0.4.1 → oacp_cli-0.4.2}/tests/conformance/signing/messages/signed_multisig.prefix.yaml +0 -0
  311. {oacp_cli-0.4.1 → oacp_cli-0.4.2}/tests/conformance/signing/messages/signed_multisig.yaml +0 -0
  312. {oacp_cli-0.4.1 → oacp_cli-0.4.2}/tests/conformance/signing/messages/signed_revoked.prefix.yaml +0 -0
  313. {oacp_cli-0.4.1 → oacp_cli-0.4.2}/tests/conformance/signing/messages/signed_revoked.yaml +0 -0
  314. {oacp_cli-0.4.1 → oacp_cli-0.4.2}/tests/conformance/signing/messages/tamper_auth_alias.yaml +0 -0
  315. {oacp_cli-0.4.1 → oacp_cli-0.4.2}/tests/conformance/signing/messages/tamper_body_flip.yaml +0 -0
  316. {oacp_cli-0.4.1 → oacp_cli-0.4.2}/tests/conformance/signing/messages/tamper_container_reformat.yaml +0 -0
  317. {oacp_cli-0.4.1 → oacp_cli-0.4.2}/tests/conformance/signing/messages/tamper_crlf_trailer.yaml +0 -0
  318. {oacp_cli-0.4.1 → oacp_cli-0.4.2}/tests/conformance/signing/messages/tamper_header_reencode.yaml +0 -0
  319. {oacp_cli-0.4.1 → oacp_cli-0.4.2}/tests/conformance/signing/messages/tamper_identity_mismatch.prefix.yaml +0 -0
  320. {oacp_cli-0.4.1 → oacp_cli-0.4.2}/tests/conformance/signing/messages/tamper_identity_mismatch.yaml +0 -0
  321. {oacp_cli-0.4.1 → oacp_cli-0.4.2}/tests/conformance/signing/messages/tamper_indented_trailer.yaml +0 -0
  322. {oacp_cli-0.4.1 → oacp_cli-0.4.2}/tests/conformance/signing/messages/tamper_kid_alias.yaml +0 -0
  323. {oacp_cli-0.4.1 → oacp_cli-0.4.2}/tests/conformance/signing/messages/tamper_kid_cross_agent.yaml +0 -0
  324. {oacp_cli-0.4.1 → oacp_cli-0.4.2}/tests/conformance/signing/messages/tamper_kid_unknown.yaml +0 -0
  325. {oacp_cli-0.4.1 → oacp_cli-0.4.2}/tests/conformance/signing/messages/tamper_missing_final_lf.yaml +0 -0
  326. {oacp_cli-0.4.1 → oacp_cli-0.4.2}/tests/conformance/signing/messages/tamper_padded_b64.yaml +0 -0
  327. {oacp_cli-0.4.1 → oacp_cli-0.4.2}/tests/conformance/signing/messages/tamper_sig_alias.yaml +0 -0
  328. {oacp_cli-0.4.1 → oacp_cli-0.4.2}/tests/conformance/signing/messages/tamper_sig_corrupt.yaml +0 -0
  329. {oacp_cli-0.4.1 → oacp_cli-0.4.2}/tests/conformance/signing/messages/tamper_trailer_transplant.yaml +0 -0
  330. {oacp_cli-0.4.1 → oacp_cli-0.4.2}/tests/conformance/signing/messages/tamper_trailing_blank_line.yaml +0 -0
  331. {oacp_cli-0.4.1 → oacp_cli-0.4.2}/tests/conformance/signing/messages/tamper_trailing_space.yaml +0 -0
  332. {oacp_cli-0.4.1 → oacp_cli-0.4.2}/tests/conformance/signing/messages/unsigned_notification.yaml +0 -0
  333. {oacp_cli-0.4.1 → oacp_cli-0.4.2}/tests/conformance/signing/pins/allowed_signers.yaml +0 -0
  334. {oacp_cli-0.4.1 → oacp_cli-0.4.2}/tests/conformance/signing/regen_fixtures.py +0 -0
  335. {oacp_cli-0.4.1 → oacp_cli-0.4.2}/tests/test_add_agent.py +0 -0
  336. {oacp_cli-0.4.1 → oacp_cli-0.4.2}/tests/test_agent_profile.py +0 -0
  337. {oacp_cli-0.4.1 → oacp_cli-0.4.2}/tests/test_autonomy_conformance_fixtures.py +0 -0
  338. {oacp_cli-0.4.1 → oacp_cli-0.4.2}/tests/test_codex_session_init.py +0 -0
  339. {oacp_cli-0.4.1 → oacp_cli-0.4.2}/tests/test_create_handoff_packet.py +0 -0
  340. {oacp_cli-0.4.1 → oacp_cli-0.4.2}/tests/test_envelope_compiler.py +0 -0
  341. {oacp_cli-0.4.1 → oacp_cli-0.4.2}/tests/test_envelope_conformance_fixtures.py +0 -0
  342. {oacp_cli-0.4.1 → oacp_cli-0.4.2}/tests/test_github_workflows.py +0 -0
  343. {oacp_cli-0.4.1 → oacp_cli-0.4.2}/tests/test_handoff_schema.py +0 -0
  344. {oacp_cli-0.4.1 → oacp_cli-0.4.2}/tests/test_init_project_workspace.py +0 -0
  345. {oacp_cli-0.4.1 → oacp_cli-0.4.2}/tests/test_memory_archive.py +0 -0
  346. {oacp_cli-0.4.1 → oacp_cli-0.4.2}/tests/test_memory_sync.py +0 -0
  347. {oacp_cli-0.4.1 → oacp_cli-0.4.2}/tests/test_message_signing.py +0 -0
  348. {oacp_cli-0.4.1 → oacp_cli-0.4.2}/tests/test_oacp_cli.py +0 -0
  349. {oacp_cli-0.4.1 → oacp_cli-0.4.2}/tests/test_oacp_coordinator.py +0 -0
  350. {oacp_cli-0.4.1 → oacp_cli-0.4.2}/tests/test_oacp_env.py +0 -0
  351. {oacp_cli-0.4.1 → oacp_cli-0.4.2}/tests/test_oacp_inbox.py +0 -0
  352. {oacp_cli-0.4.1 → oacp_cli-0.4.2}/tests/test_oacp_watch.py +0 -0
  353. {oacp_cli-0.4.1 → oacp_cli-0.4.2}/tests/test_preflight.py +0 -0
  354. {oacp_cli-0.4.1 → oacp_cli-0.4.2}/tests/test_record_autonomy_outcome.py +0 -0
  355. {oacp_cli-0.4.1 → oacp_cli-0.4.2}/tests/test_review_loop.py +0 -0
  356. {oacp_cli-0.4.1 → oacp_cli-0.4.2}/tests/test_send_inbox_message.py +0 -0
  357. {oacp_cli-0.4.1 → oacp_cli-0.4.2}/tests/test_session_lifecycle_hooks.py +0 -0
  358. {oacp_cli-0.4.1 → oacp_cli-0.4.2}/tests/test_setup_runtime.py +0 -0
  359. {oacp_cli-0.4.1 → oacp_cli-0.4.2}/tests/test_signing_conformance.py +0 -0
  360. {oacp_cli-0.4.1 → oacp_cli-0.4.2}/tests/test_update_workspace.py +0 -0
  361. {oacp_cli-0.4.1 → oacp_cli-0.4.2}/tests/test_validate_agent_card.py +0 -0
  362. {oacp_cli-0.4.1 → oacp_cli-0.4.2}/tests/test_validate_message.py +0 -0
  363. {oacp_cli-0.4.1 → oacp_cli-0.4.2}/tests/test_workspace_discovery.py +0 -0
  364. {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.1
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`, or `do not`.
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.1"
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, so comments and YAML formatting do not produce false drift.
319
- `spec_version: "0.4.1"` pins everything 0.4.0 pinned — Gate 1 integrity
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, and the outcome block shown above — plus
322
- session-scoped envelope enforcement, the enforce-mode trust-pin completeness
323
- gate, and preserved `always_pause` defaults for configs without an `autonomy`
324
- block. Audit `schema_version: 2` adds thread identity and
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. Records written before this pin carry mixed
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`, `mode_always_pause`,
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.1",
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 (no adapter for the
840
- runtime yet). Degradation must never be silent.
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 runs in warn mode (identity recorded, no authority
79
- granted); the trust root — receiver pins, the zero-authority project
80
- catalog, `oacp trust import`, and key management — is documented in
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 (v0.4.0, warn mode)
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. The normative authority-doctrine amendment ships with the
8
- first authority-bearing knob (a later 0.4.x/0.5 release) as its own
9
- reviewed change.
7
+ management.
10
8
 
11
- ## Warn-mode seam (v0.4.0)
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. Enforce mode (rejection, receipt
19
- ledger, quarantine activation) lands in **a later release**, activated only
20
- after a warn soak on live fleet traffic and an explicit enforcement ruling;
21
- the seams exist in v0.4.0 and none activate.
22
-
23
- Receivers opt in per-agent via `signing.verify_mode: off | warn` in
24
- `agents/<receiver>/config.yaml`. An early `enforce` value degrades to
25
- `warn`; anything else degrades to `off`.
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.