oacp-cli 0.3.2__tar.gz → 0.3.3__tar.gz
This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
- {oacp_cli-0.3.2 → oacp_cli-0.3.3}/CHANGELOG.md +23 -0
- {oacp_cli-0.3.2 → oacp_cli-0.3.3}/PKG-INFO +2 -2
- {oacp_cli-0.3.2 → oacp_cli-0.3.3}/QUICKSTART.md +5 -2
- {oacp_cli-0.3.2 → oacp_cli-0.3.3}/README.md +1 -1
- {oacp_cli-0.3.2 → oacp_cli-0.3.3}/docs/from-claude-p.md +5 -5
- {oacp_cli-0.3.2 → oacp_cli-0.3.3}/docs/guides/prompt_caching.md +8 -6
- {oacp_cli-0.3.2 → oacp_cli-0.3.3}/docs/guides/runtime_capability_matrix.md +34 -21
- {oacp_cli-0.3.2 → oacp_cli-0.3.3}/docs/protocol/task_negotiation.md +4 -1
- {oacp_cli-0.3.2 → oacp_cli-0.3.3}/pyproject.toml +1 -1
- {oacp_cli-0.3.2 → oacp_cli-0.3.3}/scripts/oacp_inbox.py +8 -4
- {oacp_cli-0.3.2 → oacp_cli-0.3.3}/scripts/oacp_watch.py +24 -1
- {oacp_cli-0.3.2 → oacp_cli-0.3.3}/scripts/send_inbox_message.py +28 -5
- {oacp_cli-0.3.2 → oacp_cli-0.3.3}/tests/test_memory_archive.py +2 -0
- {oacp_cli-0.3.2 → oacp_cli-0.3.3}/tests/test_oacp_inbox.py +37 -0
- {oacp_cli-0.3.2 → oacp_cli-0.3.3}/tests/test_oacp_watch.py +63 -0
- {oacp_cli-0.3.2 → oacp_cli-0.3.3}/tests/test_send_inbox_message.py +129 -0
- {oacp_cli-0.3.2 → oacp_cli-0.3.3}/.github/workflows/ci.yml +0 -0
- {oacp_cli-0.3.2 → oacp_cli-0.3.3}/.github/workflows/release.yml +0 -0
- {oacp_cli-0.3.2 → oacp_cli-0.3.3}/.gitignore +0 -0
- {oacp_cli-0.3.2 → oacp_cli-0.3.3}/CONTRIBUTING.md +0 -0
- {oacp_cli-0.3.2 → oacp_cli-0.3.3}/LICENSE +0 -0
- {oacp_cli-0.3.2 → oacp_cli-0.3.3}/Makefile +0 -0
- {oacp_cli-0.3.2 → oacp_cli-0.3.3}/SECURITY.md +0 -0
- {oacp_cli-0.3.2 → oacp_cli-0.3.3}/SPEC.md +0 -0
- {oacp_cli-0.3.2 → oacp_cli-0.3.3}/docs/guides/adoption.md +0 -0
- {oacp_cli-0.3.2 → oacp_cli-0.3.3}/docs/guides/doctor.md +0 -0
- {oacp_cli-0.3.2 → oacp_cli-0.3.3}/docs/guides/setup.md +0 -0
- {oacp_cli-0.3.2 → oacp_cli-0.3.3}/docs/guides/unified_skill_spec.md +0 -0
- {oacp_cli-0.3.2 → oacp_cli-0.3.3}/docs/guides/versioning.md +0 -0
- {oacp_cli-0.3.2 → oacp_cli-0.3.3}/docs/img/oacp-cli-demo.png +0 -0
- {oacp_cli-0.3.2 → oacp_cli-0.3.3}/docs/img/oacp-filesystem-tree.png +0 -0
- {oacp_cli-0.3.2 → oacp_cli-0.3.3}/docs/img/oacp-fleet-thread.png +0 -0
- {oacp_cli-0.3.2 → oacp_cli-0.3.3}/docs/protocol/agent_profiles.md +0 -0
- {oacp_cli-0.3.2 → oacp_cli-0.3.3}/docs/protocol/agent_safety_defaults.md +0 -0
- {oacp_cli-0.3.2 → oacp_cli-0.3.3}/docs/protocol/autonomy.md +0 -0
- {oacp_cli-0.3.2 → oacp_cli-0.3.3}/docs/protocol/credential_scoping.md +0 -0
- {oacp_cli-0.3.2 → oacp_cli-0.3.3}/docs/protocol/cross_runtime_sync.md +0 -0
- {oacp_cli-0.3.2 → oacp_cli-0.3.3}/docs/protocol/dispatch_states.yaml +0 -0
- {oacp_cli-0.3.2 → oacp_cli-0.3.3}/docs/protocol/inbox_outbox.md +0 -0
- {oacp_cli-0.3.2 → oacp_cli-0.3.3}/docs/protocol/mcp_integration.md +0 -0
- {oacp_cli-0.3.2 → oacp_cli-0.3.3}/docs/protocol/multi_agent_shared_workspace.md +0 -0
- {oacp_cli-0.3.2 → oacp_cli-0.3.3}/docs/protocol/org_memory.md +0 -0
- {oacp_cli-0.3.2 → oacp_cli-0.3.3}/docs/protocol/packet_states.yaml +0 -0
- {oacp_cli-0.3.2 → oacp_cli-0.3.3}/docs/protocol/review_loop.md +0 -0
- {oacp_cli-0.3.2 → oacp_cli-0.3.3}/docs/protocol/runtime_capabilities.md +0 -0
- {oacp_cli-0.3.2 → oacp_cli-0.3.3}/docs/protocol/session_init.md +0 -0
- {oacp_cli-0.3.2 → oacp_cli-0.3.3}/docs/protocol/skills_manifest.yaml +0 -0
- {oacp_cli-0.3.2 → oacp_cli-0.3.3}/examples/quickstart/README.md +0 -0
- {oacp_cli-0.3.2 → oacp_cli-0.3.3}/mcp_servers/oacp_coordinator.py +0 -0
- {oacp_cli-0.3.2 → oacp_cli-0.3.3}/oacp/__init__.py +0 -0
- {oacp_cli-0.3.2 → oacp_cli-0.3.3}/oacp/cli.py +0 -0
- {oacp_cli-0.3.2 → oacp_cli-0.3.3}/scripts/_oacp_constants.py +0 -0
- {oacp_cli-0.3.2 → oacp_cli-0.3.3}/scripts/_oacp_env.py +0 -0
- {oacp_cli-0.3.2 → oacp_cli-0.3.3}/scripts/add_agent.py +0 -0
- {oacp_cli-0.3.2 → oacp_cli-0.3.3}/scripts/agent_profile.py +0 -0
- {oacp_cli-0.3.2 → oacp_cli-0.3.3}/scripts/autonomy_gate.py +0 -0
- {oacp_cli-0.3.2 → oacp_cli-0.3.3}/scripts/check_quality_gate.py +0 -0
- {oacp_cli-0.3.2 → oacp_cli-0.3.3}/scripts/codex_session_init.py +0 -0
- {oacp_cli-0.3.2 → oacp_cli-0.3.3}/scripts/create_handoff_packet.py +0 -0
- {oacp_cli-0.3.2 → oacp_cli-0.3.3}/scripts/handoff_schema.py +0 -0
- {oacp_cli-0.3.2 → oacp_cli-0.3.3}/scripts/init_org_memory.py +0 -0
- {oacp_cli-0.3.2 → oacp_cli-0.3.3}/scripts/init_packet.sh +0 -0
- {oacp_cli-0.3.2 → oacp_cli-0.3.3}/scripts/init_project_workspace.py +0 -0
- {oacp_cli-0.3.2 → oacp_cli-0.3.3}/scripts/init_project_workspace.sh +0 -0
- {oacp_cli-0.3.2 → oacp_cli-0.3.3}/scripts/memory_archive_common.py +0 -0
- {oacp_cli-0.3.2 → oacp_cli-0.3.3}/scripts/memory_cli.py +0 -0
- {oacp_cli-0.3.2 → oacp_cli-0.3.3}/scripts/memory_sync.py +0 -0
- {oacp_cli-0.3.2 → oacp_cli-0.3.3}/scripts/normalize_findings.py +0 -0
- {oacp_cli-0.3.2 → oacp_cli-0.3.3}/scripts/oacp_doctor.py +0 -0
- {oacp_cli-0.3.2 → oacp_cli-0.3.3}/scripts/preflight.py +0 -0
- {oacp_cli-0.3.2 → oacp_cli-0.3.3}/scripts/promote_to_archive.py +0 -0
- {oacp_cli-0.3.2 → oacp_cli-0.3.3}/scripts/restore_from_archive.py +0 -0
- {oacp_cli-0.3.2 → oacp_cli-0.3.3}/scripts/session_lifecycle_hooks.py +0 -0
- {oacp_cli-0.3.2 → oacp_cli-0.3.3}/scripts/setup_runtime.py +0 -0
- {oacp_cli-0.3.2 → oacp_cli-0.3.3}/scripts/update_workspace.sh +0 -0
- {oacp_cli-0.3.2 → oacp_cli-0.3.3}/scripts/validate_agent_card.py +0 -0
- {oacp_cli-0.3.2 → oacp_cli-0.3.3}/scripts/validate_message.py +0 -0
- {oacp_cli-0.3.2 → oacp_cli-0.3.3}/scripts/write_event.py +0 -0
- {oacp_cli-0.3.2 → oacp_cli-0.3.3}/templates/agent_card.template.yaml +0 -0
- {oacp_cli-0.3.2 → oacp_cli-0.3.3}/templates/agent_profile.template.yaml +0 -0
- {oacp_cli-0.3.2 → oacp_cli-0.3.3}/templates/agent_status.template.yaml +0 -0
- {oacp_cli-0.3.2 → oacp_cli-0.3.3}/templates/checkpoint.template.md +0 -0
- {oacp_cli-0.3.2 → oacp_cli-0.3.3}/templates/claude/agents/role_agent.template.md +0 -0
- {oacp_cli-0.3.2 → oacp_cli-0.3.3}/templates/claude/rules/guardrail.template.md +0 -0
- {oacp_cli-0.3.2 → oacp_cli-0.3.3}/templates/findings_packet.template.yaml +0 -0
- {oacp_cli-0.3.2 → oacp_cli-0.3.3}/templates/github_actions_quality_gate.yaml +0 -0
- {oacp_cli-0.3.2 → oacp_cli-0.3.3}/templates/guardrails/coding_standards.template.md +0 -0
- {oacp_cli-0.3.2 → oacp_cli-0.3.3}/templates/guardrails/safe_commands.template.md +0 -0
- {oacp_cli-0.3.2 → oacp_cli-0.3.3}/templates/guardrails/secrets_rules.template.md +0 -0
- {oacp_cli-0.3.2 → oacp_cli-0.3.3}/templates/handoff_packet.template.yaml +0 -0
- {oacp_cli-0.3.2 → oacp_cli-0.3.3}/templates/inbox_message.template.yaml +0 -0
- {oacp_cli-0.3.2 → oacp_cli-0.3.3}/templates/manual_validation.template.md +0 -0
- {oacp_cli-0.3.2 → oacp_cli-0.3.3}/templates/merge_decision.template.md +0 -0
- {oacp_cli-0.3.2 → oacp_cli-0.3.3}/templates/org-memory/decisions.md +0 -0
- {oacp_cli-0.3.2 → oacp_cli-0.3.3}/templates/org-memory/events/.gitkeep +0 -0
- {oacp_cli-0.3.2 → oacp_cli-0.3.3}/templates/org-memory/events/20260317-170120-example-api-convention.md +0 -0
- {oacp_cli-0.3.2 → oacp_cli-0.3.3}/templates/org-memory/recent.md +0 -0
- {oacp_cli-0.3.2 → oacp_cli-0.3.3}/templates/org-memory/rules.md +0 -0
- {oacp_cli-0.3.2 → oacp_cli-0.3.3}/templates/receiver_config.template.yaml +0 -0
- {oacp_cli-0.3.2 → oacp_cli-0.3.3}/templates/review_packet.template.md +0 -0
- {oacp_cli-0.3.2 → oacp_cli-0.3.3}/templates/roles/role_baseline.template.md +0 -0
- {oacp_cli-0.3.2 → oacp_cli-0.3.3}/templates/roles/role_definition.template.yaml +0 -0
- {oacp_cli-0.3.2 → oacp_cli-0.3.3}/templates/runtime_capabilities.yaml +0 -0
- {oacp_cli-0.3.2 → oacp_cli-0.3.3}/templates/skills_manifest.template.yaml +0 -0
- {oacp_cli-0.3.2 → oacp_cli-0.3.3}/templates/test_packet.template.md +0 -0
- {oacp_cli-0.3.2 → oacp_cli-0.3.3}/tests/conformance/autonomy/README.md +0 -0
- {oacp_cli-0.3.2 → oacp_cli-0.3.3}/tests/conformance/autonomy/actuals/checkpoint_breach.yaml +0 -0
- {oacp_cli-0.3.2 → oacp_cli-0.3.3}/tests/conformance/autonomy/actuals/continuation_drift.yaml +0 -0
- {oacp_cli-0.3.2 → oacp_cli-0.3.3}/tests/conformance/autonomy/actuals/continuation_within.yaml +0 -0
- {oacp_cli-0.3.2 → oacp_cli-0.3.3}/tests/conformance/autonomy/actuals/top_level_side_effect_keys.yaml +0 -0
- {oacp_cli-0.3.2 → oacp_cli-0.3.3}/tests/conformance/autonomy/configs/always_pause.yaml +0 -0
- {oacp_cli-0.3.2 → oacp_cli-0.3.3}/tests/conformance/autonomy/configs/auto_review_continuation_enabled.yaml +0 -0
- {oacp_cli-0.3.2 → oacp_cli-0.3.3}/tests/conformance/autonomy/configs/auto_review_standard.yaml +0 -0
- {oacp_cli-0.3.2 → oacp_cli-0.3.3}/tests/conformance/autonomy/configs/auto_review_tight.yaml +0 -0
- {oacp_cli-0.3.2 → oacp_cli-0.3.3}/tests/conformance/autonomy/configs/malformed_config.yaml +0 -0
- {oacp_cli-0.3.2 → oacp_cli-0.3.3}/tests/conformance/autonomy/expected/always_pause_task.yaml +0 -0
- {oacp_cli-0.3.2 → oacp_cli-0.3.3}/tests/conformance/autonomy/expected/ambiguous_scope_pauses.yaml +0 -0
- {oacp_cli-0.3.2 → oacp_cli-0.3.3}/tests/conformance/autonomy/expected/brainstorm_destructive_pauses.yaml +0 -0
- {oacp_cli-0.3.2 → oacp_cli-0.3.3}/tests/conformance/autonomy/expected/brainstorm_side_effect_verbs_auto_accepts.yaml +0 -0
- {oacp_cli-0.3.2 → oacp_cli-0.3.3}/tests/conformance/autonomy/expected/brainstorm_without_profile_auto_accepts.yaml +0 -0
- {oacp_cli-0.3.2 → oacp_cli-0.3.3}/tests/conformance/autonomy/expected/checkpoint_breach_pauses.yaml +0 -0
- {oacp_cli-0.3.2 → oacp_cli-0.3.3}/tests/conformance/autonomy/expected/clean_auto_review_task.yaml +0 -0
- {oacp_cli-0.3.2 → oacp_cli-0.3.3}/tests/conformance/autonomy/expected/continuation_grant_destructive_pauses.yaml +0 -0
- {oacp_cli-0.3.2 → oacp_cli-0.3.3}/tests/conformance/autonomy/expected/continuation_grant_disabled_pauses.yaml +0 -0
- {oacp_cli-0.3.2 → oacp_cli-0.3.3}/tests/conformance/autonomy/expected/continuation_grant_drift_pauses.yaml +0 -0
- {oacp_cli-0.3.2 → oacp_cli-0.3.3}/tests/conformance/autonomy/expected/continuation_grant_enabled_auto_accepts.yaml +0 -0
- {oacp_cli-0.3.2 → oacp_cli-0.3.3}/tests/conformance/autonomy/expected/continuation_grant_external_uncovered_pauses.yaml +0 -0
- {oacp_cli-0.3.2 → oacp_cli-0.3.3}/tests/conformance/autonomy/expected/hard_stop_dangerously_skip_permissions_pauses.yaml +0 -0
- {oacp_cli-0.3.2 → oacp_cli-0.3.3}/tests/conformance/autonomy/expected/hard_stop_external_side_effects_pauses.yaml +0 -0
- {oacp_cli-0.3.2 → oacp_cli-0.3.3}/tests/conformance/autonomy/expected/hard_stop_force_pauses.yaml +0 -0
- {oacp_cli-0.3.2 → oacp_cli-0.3.3}/tests/conformance/autonomy/expected/hard_stop_no_verify_pauses.yaml +0 -0
- {oacp_cli-0.3.2 → oacp_cli-0.3.3}/tests/conformance/autonomy/expected/hard_stop_no_verify_upper_pauses.yaml +0 -0
- {oacp_cli-0.3.2 → oacp_cli-0.3.3}/tests/conformance/autonomy/expected/hard_stop_rm_rf_pauses.yaml +0 -0
- {oacp_cli-0.3.2 → oacp_cli-0.3.3}/tests/conformance/autonomy/expected/hard_stop_sensitive_scope_pauses.yaml +0 -0
- {oacp_cli-0.3.2 → oacp_cli-0.3.3}/tests/conformance/autonomy/expected/malformed_config_pauses.yaml +0 -0
- {oacp_cli-0.3.2 → oacp_cli-0.3.3}/tests/conformance/autonomy/expected/missing_task_profile_pauses.yaml +0 -0
- {oacp_cli-0.3.2 → oacp_cli-0.3.3}/tests/conformance/autonomy/expected/path_like_deploy_auto_accepts.yaml +0 -0
- {oacp_cli-0.3.2 → oacp_cli-0.3.3}/tests/conformance/autonomy/expected/risk_obvious_no_profile_pauses.yaml +0 -0
- {oacp_cli-0.3.2 → oacp_cli-0.3.3}/tests/conformance/autonomy/expected/side_effect_booleans_pause.yaml +0 -0
- {oacp_cli-0.3.2 → oacp_cli-0.3.3}/tests/conformance/autonomy/expected/threshold_breach_pauses.yaml +0 -0
- {oacp_cli-0.3.2 → oacp_cli-0.3.3}/tests/conformance/autonomy/expected/tight_threshold_pauses.yaml +0 -0
- {oacp_cli-0.3.2 → oacp_cli-0.3.3}/tests/conformance/autonomy/expected/top_level_side_effect_actuals_ignored.yaml +0 -0
- {oacp_cli-0.3.2 → oacp_cli-0.3.3}/tests/conformance/autonomy/expected/unparsable_task_profile_pauses.yaml +0 -0
- {oacp_cli-0.3.2 → oacp_cli-0.3.3}/tests/conformance/autonomy/messages/ambiguous_scope.yaml +0 -0
- {oacp_cli-0.3.2 → oacp_cli-0.3.3}/tests/conformance/autonomy/messages/brainstorm_destructive.yaml +0 -0
- {oacp_cli-0.3.2 → oacp_cli-0.3.3}/tests/conformance/autonomy/messages/brainstorm_side_effect_verbs.yaml +0 -0
- {oacp_cli-0.3.2 → oacp_cli-0.3.3}/tests/conformance/autonomy/messages/brainstorm_without_profile.yaml +0 -0
- {oacp_cli-0.3.2 → oacp_cli-0.3.3}/tests/conformance/autonomy/messages/clean_task.yaml +0 -0
- {oacp_cli-0.3.2 → oacp_cli-0.3.3}/tests/conformance/autonomy/messages/continuation_grant.yaml +0 -0
- {oacp_cli-0.3.2 → oacp_cli-0.3.3}/tests/conformance/autonomy/messages/continuation_grant_destructive.yaml +0 -0
- {oacp_cli-0.3.2 → oacp_cli-0.3.3}/tests/conformance/autonomy/messages/continuation_grant_external_uncovered.yaml +0 -0
- {oacp_cli-0.3.2 → oacp_cli-0.3.3}/tests/conformance/autonomy/messages/hard_stop_dangerously_skip_permissions.yaml +0 -0
- {oacp_cli-0.3.2 → oacp_cli-0.3.3}/tests/conformance/autonomy/messages/hard_stop_external_side_effects.yaml +0 -0
- {oacp_cli-0.3.2 → oacp_cli-0.3.3}/tests/conformance/autonomy/messages/hard_stop_force.yaml +0 -0
- {oacp_cli-0.3.2 → oacp_cli-0.3.3}/tests/conformance/autonomy/messages/hard_stop_no_verify.yaml +0 -0
- {oacp_cli-0.3.2 → oacp_cli-0.3.3}/tests/conformance/autonomy/messages/hard_stop_no_verify_upper.yaml +0 -0
- {oacp_cli-0.3.2 → oacp_cli-0.3.3}/tests/conformance/autonomy/messages/hard_stop_rm_rf.yaml +0 -0
- {oacp_cli-0.3.2 → oacp_cli-0.3.3}/tests/conformance/autonomy/messages/hard_stop_sensitive_scope.yaml +0 -0
- {oacp_cli-0.3.2 → oacp_cli-0.3.3}/tests/conformance/autonomy/messages/missing_task_profile.yaml +0 -0
- {oacp_cli-0.3.2 → oacp_cli-0.3.3}/tests/conformance/autonomy/messages/path_like_deploy.yaml +0 -0
- {oacp_cli-0.3.2 → oacp_cli-0.3.3}/tests/conformance/autonomy/messages/risk_obvious_no_profile.yaml +0 -0
- {oacp_cli-0.3.2 → oacp_cli-0.3.3}/tests/conformance/autonomy/messages/side_effect_booleans.yaml +0 -0
- {oacp_cli-0.3.2 → oacp_cli-0.3.3}/tests/conformance/autonomy/messages/threshold_breach.yaml +0 -0
- {oacp_cli-0.3.2 → oacp_cli-0.3.3}/tests/conformance/autonomy/messages/unparsable_task_profile.yaml +0 -0
- {oacp_cli-0.3.2 → oacp_cli-0.3.3}/tests/test_add_agent.py +0 -0
- {oacp_cli-0.3.2 → oacp_cli-0.3.3}/tests/test_agent_profile.py +0 -0
- {oacp_cli-0.3.2 → oacp_cli-0.3.3}/tests/test_autonomy_conformance_fixtures.py +0 -0
- {oacp_cli-0.3.2 → oacp_cli-0.3.3}/tests/test_autonomy_gate.py +0 -0
- {oacp_cli-0.3.2 → oacp_cli-0.3.3}/tests/test_codex_session_init.py +0 -0
- {oacp_cli-0.3.2 → oacp_cli-0.3.3}/tests/test_create_handoff_packet.py +0 -0
- {oacp_cli-0.3.2 → oacp_cli-0.3.3}/tests/test_github_workflows.py +0 -0
- {oacp_cli-0.3.2 → oacp_cli-0.3.3}/tests/test_handoff_schema.py +0 -0
- {oacp_cli-0.3.2 → oacp_cli-0.3.3}/tests/test_init_project_workspace.py +0 -0
- {oacp_cli-0.3.2 → oacp_cli-0.3.3}/tests/test_oacp_cli.py +0 -0
- {oacp_cli-0.3.2 → oacp_cli-0.3.3}/tests/test_oacp_constants.py +0 -0
- {oacp_cli-0.3.2 → oacp_cli-0.3.3}/tests/test_oacp_coordinator.py +0 -0
- {oacp_cli-0.3.2 → oacp_cli-0.3.3}/tests/test_oacp_doctor.py +0 -0
- {oacp_cli-0.3.2 → oacp_cli-0.3.3}/tests/test_oacp_env.py +0 -0
- {oacp_cli-0.3.2 → oacp_cli-0.3.3}/tests/test_preflight.py +0 -0
- {oacp_cli-0.3.2 → oacp_cli-0.3.3}/tests/test_review_loop.py +0 -0
- {oacp_cli-0.3.2 → oacp_cli-0.3.3}/tests/test_session_lifecycle_hooks.py +0 -0
- {oacp_cli-0.3.2 → oacp_cli-0.3.3}/tests/test_setup_runtime.py +0 -0
- {oacp_cli-0.3.2 → oacp_cli-0.3.3}/tests/test_update_workspace.py +0 -0
- {oacp_cli-0.3.2 → oacp_cli-0.3.3}/tests/test_validate_agent_card.py +0 -0
- {oacp_cli-0.3.2 → oacp_cli-0.3.3}/tests/test_validate_message.py +0 -0
- {oacp_cli-0.3.2 → oacp_cli-0.3.3}/tests/test_workspace_discovery.py +0 -0
- {oacp_cli-0.3.2 → oacp_cli-0.3.3}/tests/test_write_event.py +0 -0
|
@@ -5,6 +5,28 @@ 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.3.3] - 2026-06-11
|
|
9
|
+
|
|
10
|
+
### Added
|
|
11
|
+
|
|
12
|
+
- `oacp watch --state-id <id>` for per-subscriber cursor files, allowing
|
|
13
|
+
concurrent watchers of the same agent inbox to receive the same new-message
|
|
14
|
+
events without sharing a cursor.
|
|
15
|
+
|
|
16
|
+
### Changed
|
|
17
|
+
|
|
18
|
+
- Docs: refreshed the runtime capability matrix and prompt-caching guidance
|
|
19
|
+
for current runtime releases.
|
|
20
|
+
|
|
21
|
+
### Fixed
|
|
22
|
+
|
|
23
|
+
- `oacp send --oacp-dir` and `oacp inbox --oacp-dir` now expand `~` through the
|
|
24
|
+
shared OACP home resolver instead of treating it as a literal path component.
|
|
25
|
+
- Inbox and outbox delivery writes now use same-directory temp files plus
|
|
26
|
+
atomic replace so readers do not observe partial `.yaml` messages.
|
|
27
|
+
- Memory archive tests now isolate git config while preserving test identities,
|
|
28
|
+
so local commit-signing settings do not break the suite.
|
|
29
|
+
|
|
8
30
|
## [0.3.2] - 2026-05-26
|
|
9
31
|
|
|
10
32
|
### Added
|
|
@@ -158,6 +180,7 @@ and this project adheres to [Semantic Versioning](https://semver.org/spec/v2.0.0
|
|
|
158
180
|
- Checkout step in github-release workflow job (#19)
|
|
159
181
|
- Pre-release audit fixes: SHA-pinned actions, dangling doc refs (#15, #16)
|
|
160
182
|
|
|
183
|
+
[0.3.3]: https://github.com/kiloloop/oacp/compare/v0.3.2...v0.3.3
|
|
161
184
|
[0.3.2]: https://github.com/kiloloop/oacp/compare/v0.3.1...v0.3.2
|
|
162
185
|
[0.3.1]: https://github.com/kiloloop/oacp/compare/v0.3.0...v0.3.1
|
|
163
186
|
[0.3.0]: https://github.com/kiloloop/oacp/compare/v0.2.3...v0.3.0
|
|
@@ -1,6 +1,6 @@
|
|
|
1
1
|
Metadata-Version: 2.4
|
|
2
2
|
Name: oacp-cli
|
|
3
|
-
Version: 0.3.
|
|
3
|
+
Version: 0.3.3
|
|
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
|
|
@@ -270,7 +270,7 @@ uv tool install .
|
|
|
270
270
|
|
|
271
271
|
**`oacp send`**: `--in-reply-to`, `--expires`, `--body-file`, `--channel`, `--dry-run`, `--json`, `--quiet`
|
|
272
272
|
|
|
273
|
-
**`oacp watch`**: `--agent`, repeatable `--project`, `--all-projects`, `--json`, `--since` (default `now`), `--show-archived`
|
|
273
|
+
**`oacp watch`**: `--agent`, repeatable `--project`, `--all-projects`, `--json`, `--since` (default `now`), `--state-id <id>` for per-subscriber cursors, `--show-archived`
|
|
274
274
|
|
|
275
275
|
**`oacp doctor`**: `--fix` (auto-fix safe issues), `--memory`, `--json`, `-o/--output`
|
|
276
276
|
|
|
@@ -157,11 +157,14 @@ body: |
|
|
|
157
157
|
|
|
158
158
|
To watch for new messages from a standing runtime or Monitor, use `oacp watch`.
|
|
159
159
|
A single `oacp watch` run scans once and exits, so keep re-running it when you
|
|
160
|
-
want a persistent worker
|
|
160
|
+
want a persistent worker. If more than one watcher follows the same agent
|
|
161
|
+
inbox, give each watcher a stable `--state-id` so each subscriber has its own
|
|
162
|
+
cursor:
|
|
161
163
|
|
|
162
164
|
```bash
|
|
165
|
+
OACP_WATCH_STATE_ID="${OACP_WATCH_STATE_ID:-$(uuidgen 2>/dev/null || python3 -c 'import uuid; print(uuid.uuid4())')}"
|
|
163
166
|
while true; do
|
|
164
|
-
oacp watch --project my-first-project --agent codex || true
|
|
167
|
+
oacp watch --project my-first-project --agent codex --state-id "$OACP_WATCH_STATE_ID" || true
|
|
165
168
|
sleep 120
|
|
166
169
|
done
|
|
167
170
|
```
|
|
@@ -244,7 +244,7 @@ uv tool install .
|
|
|
244
244
|
|
|
245
245
|
**`oacp send`**: `--in-reply-to`, `--expires`, `--body-file`, `--channel`, `--dry-run`, `--json`, `--quiet`
|
|
246
246
|
|
|
247
|
-
**`oacp watch`**: `--agent`, repeatable `--project`, `--all-projects`, `--json`, `--since` (default `now`), `--show-archived`
|
|
247
|
+
**`oacp watch`**: `--agent`, repeatable `--project`, `--all-projects`, `--json`, `--since` (default `now`), `--state-id <id>` for per-subscriber cursors, `--show-archived`
|
|
248
248
|
|
|
249
249
|
**`oacp doctor`**: `--fix` (auto-fix safe issues), `--memory`, `--json`, `-o/--output`
|
|
250
250
|
|
|
@@ -79,10 +79,9 @@ Set me up as an async OACP worker for this repo.
|
|
|
79
79
|
--project form checks this workspace's inbox, schema, and status.
|
|
80
80
|
6. Start a Monitor that keeps oacp watch re-running for the claude
|
|
81
81
|
agent on this project. A single oacp watch does one scan and exits,
|
|
82
|
-
so it has to run on a loop
|
|
83
|
-
|
|
84
|
-
|
|
85
|
-
tell me the exact oacp send command I use to dispatch a task to you.
|
|
82
|
+
so it has to run on a loop. Use a stable --state-id for that Monitor
|
|
83
|
+
so concurrent watchers each keep their own cursor. Then tell me the
|
|
84
|
+
exact oacp send command I use to dispatch a task to you.
|
|
86
85
|
|
|
87
86
|
Protocol reference: https://github.com/kiloloop/oacp/blob/main/QUICKSTART.md
|
|
88
87
|
~~~
|
|
@@ -116,8 +115,9 @@ oacp doctor --project my-project
|
|
|
116
115
|
Then, in a Claude Code session, arm the watcher in a Monitor. `oacp watch` does one scan and exits, so it has to run on a loop:
|
|
117
116
|
|
|
118
117
|
```
|
|
118
|
+
OACP_WATCH_STATE_ID="${OACP_WATCH_STATE_ID:-$(uuidgen 2>/dev/null || python3 -c 'import uuid; print(uuid.uuid4())')}"
|
|
119
119
|
while true; do
|
|
120
|
-
oacp watch --project my-project --agent claude || true
|
|
120
|
+
oacp watch --project my-project --agent claude --state-id "$OACP_WATCH_STATE_ID" || true
|
|
121
121
|
sleep 120
|
|
122
122
|
done
|
|
123
123
|
```
|
|
@@ -5,8 +5,8 @@ How to maximize prompt cache hits across Claude, Codex, and Gemini to reduce cos
|
|
|
5
5
|
## Why It Matters
|
|
6
6
|
|
|
7
7
|
Prompt caching avoids reprocessing static context (system prompts, CLAUDE.md, project facts) on every turn. In practice:
|
|
8
|
-
- **Cache read**: 10x cheaper than uncached input ($
|
|
9
|
-
- **Cache write**: 1.25x input price (one-time cost, amortized over subsequent reads)
|
|
8
|
+
- **Cache read**: 10x cheaper than uncached input ($0.50/MTok vs $5.00/MTok for Opus 4.8)
|
|
9
|
+
- **Cache write**: 1.25x input price for the default 5-minute TTL, 2x for the 1-hour TTL (one-time cost, amortized over subsequent reads)
|
|
10
10
|
- **Observed savings**: 83-95% cost reduction on cached input in multi-turn agent sessions
|
|
11
11
|
|
|
12
12
|
## Claude
|
|
@@ -127,13 +127,14 @@ Gemini supports implicit context caching for large prompts. The API automaticall
|
|
|
127
127
|
|
|
128
128
|
## Cost Comparison
|
|
129
129
|
|
|
130
|
-
Approximate pricing as of
|
|
130
|
+
Approximate pricing as of June 2026 (per million tokens). Cache read is 0.1x input; cache write is shown at the default 5-minute TTL (1.25x input) — the 1-hour TTL costs 2x input. Check each provider's current pricing page for up-to-date rates:
|
|
131
131
|
|
|
132
132
|
| Runtime | Input | Cached Read | Cache Write | Output |
|
|
133
133
|
|---------|------:|------------:|------------:|-------:|
|
|
134
|
-
| Claude
|
|
135
|
-
| Claude
|
|
136
|
-
| Claude
|
|
134
|
+
| Claude Fable 5 | $10.00 | $1.00 | $12.50 | $50.00 |
|
|
135
|
+
| Claude Opus (4.6/4.7/4.8) | $5.00 | $0.50 | $6.25 | $25.00 |
|
|
136
|
+
| Claude Sonnet 4.6 | $3.00 | $0.30 | $3.75 | $15.00 |
|
|
137
|
+
| Claude Haiku 4.5 | $1.00 | $0.10 | $1.25 | $5.00 |
|
|
137
138
|
| Codex | varies | N/A | N/A | varies |
|
|
138
139
|
| Gemini Pro | $1.25 | $0.31 | — | $10.00 |
|
|
139
140
|
|
|
@@ -146,3 +147,4 @@ Approximate pricing as of early 2026 (per million tokens). Check each provider's
|
|
|
146
147
|
- Injecting timestamps or random IDs into system prompts
|
|
147
148
|
- Reordering tool definitions between turns
|
|
148
149
|
- Changing the user message prefix frequently
|
|
150
|
+
5. **Mind the minimum cacheable prefix** — prefixes below the model minimum silently don't cache (no error; `cache_creation_input_tokens` stays 0). The minimum is 2,048 tokens on Fable 5 and Sonnet 4.6, and 4,096 tokens on Opus 4.8/4.7/4.6 and Haiku 4.5.
|
|
@@ -1,12 +1,12 @@
|
|
|
1
1
|
# Cross-Runtime Parity Matrix
|
|
2
2
|
|
|
3
|
-
**Date**: 2026-
|
|
3
|
+
**Date**: 2026-06-09
|
|
4
4
|
|
|
5
5
|
This is a capability comparison across the currently profiled agent runtimes (Claude Code, Codex, Gemini), compiled from each runtime's self-report and current runtime changelogs. Cursor support is scaffold-only until Cursor-owned onboarding lands, so Cursor is intentionally excluded from this comparison table; see `docs/protocol/runtime_capabilities.md` for its conservative scaffold defaults.
|
|
6
6
|
|
|
7
|
-
Claude was last checked against Claude Code `v2.1.
|
|
7
|
+
Claude was last checked against Claude Code `v2.1.170` with Claude Fable 5 (`claude-fable-5`, serving model verified in-session on the 1M-context variant). Fable 5 (released 2026-06-09, first Mythos-class model) is included at no extra cost on Pro/Max/Team/Enterprise plans Jun 9–22, 2026, with usage credits required after; Opus 4.8 remains available and serves as Fable 5's safeguard-fallback model.
|
|
8
8
|
|
|
9
|
-
Codex was last checked against app update `26.
|
|
9
|
+
Codex was last checked against app update `26.602`, CLI `0.137.0`, OpenAI's GPT-5.5 launch note from 2026-04-23, and the June 2026 Codex/API entries for Sites and Amazon Bedrock.
|
|
10
10
|
|
|
11
11
|
---
|
|
12
12
|
|
|
@@ -15,19 +15,19 @@ Codex was last checked against app update `26.415`, CLI `0.123.0`, and OpenAI's
|
|
|
15
15
|
| Capability | Claude (Claude Code CLI) | Codex (Desktop App) | Gemini |
|
|
16
16
|
| ---------------------- | -------------------------------------------------------------------------- | ---------------------------------------------------------------------------------------------- | --------------------------------------------------------------------- |
|
|
17
17
|
| Spawn background tasks | Yes — Task tool + Bash `run_in_background` | Yes — shell background processes | Yes — `run_command` async mode |
|
|
18
|
-
| Spawn subagents | Yes — typed agents (Explore, Plan, general-purpose, code-reviewer, etc.) | Yes — native
|
|
18
|
+
| Spawn subagents | Yes — typed agents (Explore, Plan, general-purpose, code-reviewer, etc.) | Yes — native multi-agent lifecycle with runtime metadata and follow-up defaults | Partial — `browser_subagent` only |
|
|
19
19
|
| Parallel agent teams | Yes — TeamCreate, task lists, SendMessage, broadcast | Partial — parallel spawned agents are supported, but there is no team/task-list primitive | No — parallel tool calls but no independent agent instances |
|
|
20
|
-
| MCP tools | Yes — extensible via MCP servers | Yes — MCP/plugin support with `/mcp verbose
|
|
21
|
-
| Web search | Yes — native WebSearch tool | Yes — web search/fetch tools
|
|
22
|
-
| Browser interaction | Partial — WebFetch (read-only, HTML→markdown) | Partial —
|
|
23
|
-
| File system access | Sandboxed — configurable read/write allowlists | Policy-dependent per session;
|
|
20
|
+
| MCP tools | Yes — extensible via MCP servers | Yes — MCP/plugin support with `/mcp verbose`, per-server environment targeting, read-only MCP parallelism, and scriptable plugin inventory | Yes — MCP server support |
|
|
21
|
+
| Web search | Yes — native WebSearch tool | Yes — web search/fetch tools; hosted web tools are expanding in code-mode flows | Yes — native `search_web` tool |
|
|
22
|
+
| Browser interaction | Partial — WebFetch (read-only, HTML→markdown) | Partial — in-app browser and Chrome extension can inspect local/public and approved browser contexts, with faster asset extraction and read-only JS structured-data extraction; not full browser automation | Yes — full browser control (click, type, navigate, screenshot, video) |
|
|
23
|
+
| File system access | Sandboxed — configurable read/write allowlists | Policy-dependent per session; named permission profiles can include deny-read rules and managed requirements | Full — unrestricted |
|
|
24
24
|
| Git operations | Yes — via Bash (may need sandbox configuration) | Yes — native | Yes — via shell |
|
|
25
25
|
| GitHub CLI (gh) | Yes — via Bash (may need sandbox configuration) | Yes — authenticated | Yes — native |
|
|
26
26
|
| Session memory | Strong — auto-loaded MEMORY.md + optional MCP memory | Partial — app memories where available plus OACP file memory; app memories are not protocol SSOT | Partial — Knowledge Items (not directly writable), conversation logs |
|
|
27
|
-
| Interactive mode | Yes — CLI chat with permissions, plan mode | Yes — desktop app and CLI/TUI, including Plan Mode
|
|
28
|
-
| Context window | ~1M with Opus 4.
|
|
29
|
-
| Cost model | Token-based, visible in statusline
|
|
30
|
-
| Sandbox restrictions | Yes — configurable allowlists | Session-dependent; supports deny-read policies, isolated `codex exec`,
|
|
27
|
+
| Interactive mode | Yes — CLI chat with permissions, plan mode | Yes — desktop app and CLI/TUI, including Plan Mode, Goal mode, side conversations, and archive/unarchive flows | Yes — chat with task UI, artifacts |
|
|
28
|
+
| Context window | ~1M with Fable 5 or Opus 4.8 (auto-compaction extends indefinitely) | Model-dependent; GPT-5.5 in Codex is documented at 400K, with no auto-compaction guarantee | ~1M tokens |
|
|
29
|
+
| Cost model | Token-based, visible in statusline; Fable 5 API rate is $10/$50 per MTok (2× Opus 4.8's $5/$25) | Not surfaced per session; GPT-5.5 Fast mode trades 2.5x cost for 1.5x token generation speed | Token-based |
|
|
30
|
+
| Sandbox restrictions | Yes — configurable allowlists | Session-dependent; supports deny-read policies, isolated `codex exec`, named permission profiles, managed requirements, and explicit approval policies | None — full system access |
|
|
31
31
|
|
|
32
32
|
---
|
|
33
33
|
|
|
@@ -37,6 +37,7 @@ Codex was last checked against app update `26.415`, CLI `0.123.0`, and OpenAI's
|
|
|
37
37
|
| -------------------------------- | ------------- | ---------------------------------------------------------------------------- |
|
|
38
38
|
| Typed subagent orchestration | Claude | Multiple agent types with scoped tools and model selection |
|
|
39
39
|
| Team coordination primitive | Claude | TeamCreate + task lists + assignment + broadcast + shutdown |
|
|
40
|
+
| Dynamic multi-agent workflows | Claude | Workflow tool orchestrates tens–hundreds of agents; `/workflows` to view |
|
|
40
41
|
| Plan mode | Claude, Codex | Claude has structured explore → plan → approve → implement; Codex CLI can move from planning into fresh-context implementation |
|
|
41
42
|
| Auto-compaction | Claude | Context auto-compresses, enabling unlimited session length |
|
|
42
43
|
| Cross-session semantic search | Claude | MCP-based searchable memory (optional) |
|
|
@@ -48,8 +49,14 @@ Codex was last checked against app update `26.415`, CLI `0.123.0`, and OpenAI's
|
|
|
48
49
|
| PTY / terminal stdin | Codex, Gemini | Codex: native PTY; Gemini: `send_command_input` (Claude lacks stdin support) |
|
|
49
50
|
| `apply_patch` editing | Codex | Grammar-based file edits |
|
|
50
51
|
| App-level computer use | Codex | macOS app, simulator, and GUI-only workflows; unavailable in EEA, UK, and Switzerland at launch |
|
|
52
|
+
| Windows computer use | Codex | Codex app can operate Windows desktop apps in the foreground when available |
|
|
53
|
+
| Remote host control | Codex | Mobile or desktop remote control can run work on connected Mac or Windows hosts with host-local files, credentials, plugins, skills, and config |
|
|
51
54
|
| App-level artifact review | Codex | Sidebar preview for generated PDFs, spreadsheets, documents, and presentations |
|
|
52
55
|
| App-level PR review | Codex | PR sidebar can inspect changed files, review comments, and follow-up fixes |
|
|
56
|
+
| App-server automation | Codex | JSON-RPC app-server, SDK, schema generation, thread APIs, and websocket/Unix-socket transports for custom clients |
|
|
57
|
+
| Hosted site deployment | Codex | Sites preview can create, deploy, inspect, and manage hosted websites or internal tools through the Codex app |
|
|
58
|
+
| Plugin marketplace inventory | Codex | Plugin directory plus `codex plugin list --json` for installed plugin inventory and marketplace-aware diagnostics |
|
|
59
|
+
| Goal mode | Codex | Stable long-running objective mode with dedicated state; candidate for OACP wait/review-loop experiments |
|
|
53
60
|
|
|
54
61
|
---
|
|
55
62
|
|
|
@@ -71,9 +78,9 @@ Scope: skills shipped in [`kiloloop/oacp-skills`](https://github.com/kiloloop/oa
|
|
|
71
78
|
|
|
72
79
|
| Dimension | Claude | Codex | Gemini |
|
|
73
80
|
| --------------- | ---------------------------------------------------------------------- | ----------------------------------------------------------------------- | -------------------------------------------------------------------- |
|
|
74
|
-
| Best at | Orchestration, multi-agent teams, persistent memory, plan-then-execute | Terminal-native execution, GPT-5.5 agentic coding, fast iterative patching, plan-to-implementation handoff, app-assisted PR/artifact review, protocol discipline | Web research, browser automation, visual verification, large context |
|
|
75
|
-
| Ideal task type | Team coordination, complex multi-file refactors, long-running sessions | Shell-heavy workflows, long-horizon coding, targeted file edits, deterministic scripts, PR follow-up, artifact review, CLI planning passes | External research, UI testing, document review, MCP integrations |
|
|
76
|
-
| Cost profile | Flexible (haiku subagents for cheap tasks, opus for complex)
|
|
81
|
+
| Best at | Orchestration, multi-agent teams, persistent memory, plan-then-execute | Terminal-native execution, GPT-5.5 agentic coding, fast iterative patching, plan-to-implementation handoff, app-assisted PR/artifact review, app-server automation, protocol discipline | Web research, browser automation, visual verification, large context |
|
|
82
|
+
| Ideal task type | Team coordination, complex multi-file refactors, long-running sessions | Shell-heavy workflows, long-horizon coding, targeted file edits, deterministic scripts, PR follow-up, artifact review, CLI planning passes, plugin/app-server automation prototypes | External research, UI testing, document review, MCP integrations |
|
|
83
|
+
| Cost profile | Flexible (haiku subagents for cheap tasks, opus for complex, Fable 5 at 2× Opus API rates for the hardest work) | Per-session cost not visible; GPT-5.5 is described as more token-efficient than GPT-5.4 for Codex tasks | Token-based, web search has additional costs |
|
|
77
84
|
|
|
78
85
|
---
|
|
79
86
|
|
|
@@ -82,7 +89,7 @@ Scope: skills shipped in [`kiloloop/oacp-skills`](https://github.com/kiloloop/oa
|
|
|
82
89
|
| Limitation | Claude | Codex | Gemini |
|
|
83
90
|
| ----------------------------- | ----------------------------- | -------------------------------------------------------------- | ---------------------- |
|
|
84
91
|
| No subagents | — | Yes | Partial (browser only) |
|
|
85
|
-
| No browser automation | Yes (read-only) | Partial (in-app browser
|
|
92
|
+
| No browser automation | Yes (read-only) | Partial (in-app browser and Chrome extension are useful for review/verification, but not a general full-browser automation substitute) | — |
|
|
86
93
|
| No image generation | Yes | — | — |
|
|
87
94
|
| No persistent writable memory | — | Partial (app memories are not a replacement for OACP durable memory) | Yes |
|
|
88
95
|
| Sandbox friction | Yes (configurable) | Session-dependent | — |
|
|
@@ -90,6 +97,7 @@ Scope: skills shipped in [`kiloloop/oacp-skills`](https://github.com/kiloloop/oa
|
|
|
90
97
|
| Context limits | Auto-compaction mitigates | Model-dependent; GPT-5.5 in Codex is 400K, but there is no documented auto-compaction behavior | Large but finite |
|
|
91
98
|
| No terminal stdin | Yes | — | — |
|
|
92
99
|
| Cost not surfaced | — | Yes | — |
|
|
100
|
+
| Serving model can change mid-session | Yes (Fable 5 only — cyber/bio-chem/distillation classifiers fall back to Opus 4.8; default and non-configurable in Claude interfaces incl. Claude Code, with a session event emitted; <5% of sessions — system card §1.5) | — | — |
|
|
93
101
|
|
|
94
102
|
---
|
|
95
103
|
|
|
@@ -102,7 +110,7 @@ These are the highest-impact gaps where one runtime's limitation blocks effectiv
|
|
|
102
110
|
| No team orchestration | Codex, Gemini | Cannot run parallel agent teams | Agent cards — let runtimes discover and delegate to capable peers |
|
|
103
111
|
| Memory asymmetry | Codex (partial), Gemini (KIs only) | Cross-session context degrades without MEMORY.md equivalent | Standardize memory protocol; each runtime implements its own persistence layer |
|
|
104
112
|
| Sandbox blocks git/gh | Claude | Every git/gh call needs sandbox configuration | Configure sandbox allowlists or disable sandbox for specific commands |
|
|
105
|
-
| Full browser automation gap | Claude, Codex | Claude is read-only; Codex has
|
|
113
|
+
| Full browser automation gap | Claude, Codex | Claude is read-only; Codex has stronger browser review and Chrome-extension support but not full autonomous browser automation | Delegate full browser tasks to Gemini; use Codex browser/Chrome workflows for local, public, or approved signed-in page review |
|
|
106
114
|
| Reviewer cost | All (especially Claude) | High cost for single PR review with polling pattern | Stateless reviewer rounds — one round per invocation |
|
|
107
115
|
| Public skill coverage | Gemini | `kiloloop/oacp-skills` ships `claude/` and `codex/` variants for all 5 public skills; no `gemini/` variants — Gemini users must rely on convention-based adoption | Add `gemini/` variants to each public skill, or document the convention-based pattern as a first-class install path |
|
|
108
116
|
|
|
@@ -114,25 +122,30 @@ These are the highest-impact gaps where one runtime's limitation blocks effectiv
|
|
|
114
122
|
| ---------------------------- | -------------------------------- | ------------------------------------------ | --------------------------------------------- |
|
|
115
123
|
| Max parallel tool calls | ~10+ | Yes (parallel independent calls) | ~10 (practical) |
|
|
116
124
|
| Side conversations | No | Yes (`/side` in CLI/TUI) | No |
|
|
117
|
-
| Hooks system | Yes (pre/post tool call hooks) |
|
|
118
|
-
| Automation scheduling | Yes (`CronCreate`, `ScheduleWakeup`, `/loop`, `/schedule` skills) | Yes (desktop app thread automations
|
|
125
|
+
| Hooks system | Yes (pre/post tool call hooks) | Yes (stable hooks and extension lifecycle hooks; plugin-bundled hooks are configuration-dependent) | No |
|
|
126
|
+
| Automation scheduling | Yes (`CronCreate`, `ScheduleWakeup`, `/loop`, `/schedule` skills) | Yes (desktop app thread automations, Goal mode, and app-server/SDK automation surfaces) | No |
|
|
119
127
|
| Notebook editing | Yes (NotebookEdit tool) | No | No |
|
|
120
128
|
| PDF reading | Yes (max 20 pages/request) | No native tool | Via `read_url_content` |
|
|
121
129
|
| Image reading (multimodal) | Yes | Yes (desktop app local image/view support) | Yes |
|
|
122
130
|
| Artifact system | No | Yes (sidebar preview for generated files) | Yes (task.md, implementation plans) |
|
|
123
131
|
| Video recording | No | No | Yes (WebP via browser) |
|
|
124
132
|
| Image generation | No | Yes (enabled by default in CLI) | Yes |
|
|
125
|
-
| MCP diagnostics | Partial | Yes (`/mcp verbose
|
|
133
|
+
| MCP diagnostics | Partial | Yes (`/mcp verbose`, per-server environment targeting, read-only MCP parallelism, plugin JSON inventory) | Partial |
|
|
126
134
|
| Multi-file editing primitive | Edit tool (one file at a time) | `apply_patch` (one file) | `multi_replace_file_content` (non-contiguous) |
|
|
127
135
|
| Workflow file format | SKILL.md with YAML frontmatter | SKILL.md with YAML frontmatter | Markdown with YAML frontmatter |
|
|
128
|
-
| Policy visibility at runtime | Partial (sandbox config visible) | Yes (session policy
|
|
136
|
+
| Policy visibility at runtime | Partial (sandbox config visible) | Yes (session policy, approval policy, sandbox, and named permission profiles) | Yes (`SafeToAutoRun` flags) |
|
|
129
137
|
| Long-running shell sessions | Bash tool (no stdin) | Yes (PTY + stdin; multiple terminals in app) | Yes (`send_command_input`) |
|
|
138
|
+
| App-server / SDK | No | Yes (JSON-RPC app-server, Python SDK, archive/thread APIs, schema generation) | No |
|
|
139
|
+
| Hosted site deployment | No | Yes (Sites preview, app-only/cloud-hosted with separate secret management) | No |
|
|
130
140
|
|
|
131
141
|
---
|
|
132
142
|
|
|
133
143
|
## 8. Source Notes
|
|
134
144
|
|
|
135
145
|
- GPT-5.5 Codex availability, 400K context, Fast mode, token-efficiency, and API timing come from OpenAI's 2026-04-23 release note: <https://openai.com/index/introducing-gpt-5-5/>.
|
|
146
|
+
- Codex app/CLI capability changes through app `26.602` and CLI `0.137.0` come from OpenAI's Codex changelog: <https://developers.openai.com/codex/changelog>.
|
|
147
|
+
- Sites, Amazon Bedrock, app-server, plugin, and permissions details come from the official Codex docs under <https://developers.openai.com/codex/>.
|
|
148
|
+
- Claude Fable 5 release date, pricing, and plan-inclusion window come from Anthropic's 2026-06-09 announcement: <https://www.anthropic.com/news/claude-fable-5-mythos-5>. Safeguard-fallback behavior comes from the Fable 5 / Mythos 5 system card §1.5 ("Novel safeguards"): client apps and Claude interfaces auto-fall back to Opus 4.8 (default and non-configurable in interfaces, session event emitted), while the Messages API blocks by default with a structured refusal category and offers opt-in server-side fallback. The serving model in the header was verified in-session by the Claude runtime.
|
|
136
149
|
|
|
137
150
|
---
|
|
138
151
|
|
|
@@ -153,7 +153,10 @@ Agents that lack headless mode (e.g., Gemini in some configurations):
|
|
|
153
153
|
|
|
154
154
|
### Codex
|
|
155
155
|
|
|
156
|
-
- Codex
|
|
156
|
+
- Codex can run interactively, from the desktop app or CLI, or through
|
|
157
|
+
explicit automation flows. Do not assume legacy `--full-auto` behavior;
|
|
158
|
+
set the intended approval policy, sandbox, and permission profile for the
|
|
159
|
+
receiving environment.
|
|
157
160
|
- Codex can both propose and receive proposals.
|
|
158
161
|
- When Codex receives a proposal, it processes the inbox at session start per the inbox/outbox polling convention.
|
|
159
162
|
|
|
@@ -21,7 +21,7 @@ import datetime as dt
|
|
|
21
21
|
import json
|
|
22
22
|
import sys
|
|
23
23
|
from pathlib import Path
|
|
24
|
-
from typing import Any, Dict, List, Optional, Sequence
|
|
24
|
+
from typing import Any, Dict, List, Optional, Sequence, Union
|
|
25
25
|
|
|
26
26
|
try:
|
|
27
27
|
import yaml
|
|
@@ -35,6 +35,10 @@ def _resolve_oacp_home(explicit: Optional[str] = None) -> Path:
|
|
|
35
35
|
return resolve_oacp_home(explicit)
|
|
36
36
|
|
|
37
37
|
|
|
38
|
+
def _coerce_oacp_home(explicit: Optional[Union[str, Path]]) -> Path:
|
|
39
|
+
return _resolve_oacp_home(str(explicit)) if explicit is not None else _resolve_oacp_home()
|
|
40
|
+
|
|
41
|
+
|
|
38
42
|
def _load_yaml_mapping(path: Path) -> Dict[str, Any]:
|
|
39
43
|
raw = path.read_text(encoding="utf-8")
|
|
40
44
|
if yaml is not None:
|
|
@@ -134,14 +138,14 @@ def list_inbox(
|
|
|
134
138
|
*,
|
|
135
139
|
agent: Optional[str] = None,
|
|
136
140
|
list_all: bool = False,
|
|
137
|
-
oacp_dir: Optional[Path] = None,
|
|
141
|
+
oacp_dir: Optional[Union[str, Path]] = None,
|
|
138
142
|
now: Optional[dt.datetime] = None,
|
|
139
143
|
) -> Dict[str, Any]:
|
|
140
144
|
"""Return inbox metadata for one agent or all project agents."""
|
|
141
145
|
if agent is None and not list_all:
|
|
142
146
|
raise ValueError("either --agent or --all is required")
|
|
143
147
|
|
|
144
|
-
oacp_root = oacp_dir
|
|
148
|
+
oacp_root = _coerce_oacp_home(oacp_dir)
|
|
145
149
|
project_dir = oacp_root / "projects" / project
|
|
146
150
|
if not project_dir.is_dir():
|
|
147
151
|
raise ValueError(f"project '{project}' not found under {oacp_root / 'projects'}")
|
|
@@ -228,7 +232,7 @@ def main(argv: Optional[Sequence[str]] = None) -> int:
|
|
|
228
232
|
args.project,
|
|
229
233
|
agent=args.agent,
|
|
230
234
|
list_all=args.list_all,
|
|
231
|
-
oacp_dir=
|
|
235
|
+
oacp_dir=args.oacp_dir if args.oacp_dir else None,
|
|
232
236
|
)
|
|
233
237
|
except ValueError as exc:
|
|
234
238
|
print(f"ERROR: {exc}", file=sys.stderr)
|
|
@@ -17,6 +17,7 @@ from __future__ import annotations
|
|
|
17
17
|
|
|
18
18
|
import argparse
|
|
19
19
|
import json
|
|
20
|
+
import re
|
|
20
21
|
import sys
|
|
21
22
|
import time
|
|
22
23
|
from dataclasses import dataclass
|
|
@@ -33,6 +34,7 @@ except ImportError: # pragma: no cover
|
|
|
33
34
|
STATE_VERSION = 1
|
|
34
35
|
|
|
35
36
|
_DURATION_UNITS = {"s": 1, "m": 60, "h": 3600, "d": 86400}
|
|
37
|
+
_STATE_ID_RE = re.compile(r"^[A-Za-z0-9._-]{1,64}$")
|
|
36
38
|
|
|
37
39
|
|
|
38
40
|
def _parse_since(spec: str, *, now: float) -> float:
|
|
@@ -70,6 +72,7 @@ class WatchTarget:
|
|
|
70
72
|
agent: str
|
|
71
73
|
inbox_dir: Path
|
|
72
74
|
state_file: Path
|
|
75
|
+
state_id: Optional[str] = None
|
|
73
76
|
|
|
74
77
|
|
|
75
78
|
def _resolve_oacp_home(explicit: Optional[str] = None) -> Path:
|
|
@@ -183,12 +186,18 @@ def _dedupe_keep_order(values: Iterable[str]) -> List[str]:
|
|
|
183
186
|
return result
|
|
184
187
|
|
|
185
188
|
|
|
189
|
+
def _watch_state_file(project_dir: Path, agent: str, state_id: Optional[str]) -> Path:
|
|
190
|
+
state_name = f"{agent}.json" if state_id is None else f"{agent}.{state_id}.json"
|
|
191
|
+
return project_dir / "state" / "watch" / state_name
|
|
192
|
+
|
|
193
|
+
|
|
186
194
|
def _resolve_targets(
|
|
187
195
|
*,
|
|
188
196
|
projects: Optional[List[str]],
|
|
189
197
|
all_projects: bool,
|
|
190
198
|
agent: str,
|
|
191
199
|
oacp_root: Path,
|
|
200
|
+
state_id: Optional[str] = None,
|
|
192
201
|
) -> tuple[List[WatchTarget], List[Dict[str, Any]]]:
|
|
193
202
|
errors: List[Dict[str, Any]] = []
|
|
194
203
|
if all_projects:
|
|
@@ -243,13 +252,14 @@ def _resolve_targets(
|
|
|
243
252
|
)
|
|
244
253
|
)
|
|
245
254
|
continue
|
|
246
|
-
state_file = project_dir
|
|
255
|
+
state_file = _watch_state_file(project_dir, agent, state_id)
|
|
247
256
|
targets.append(
|
|
248
257
|
WatchTarget(
|
|
249
258
|
project=project,
|
|
250
259
|
agent=agent,
|
|
251
260
|
inbox_dir=inbox_dir,
|
|
252
261
|
state_file=state_file,
|
|
262
|
+
state_id=state_id,
|
|
253
263
|
)
|
|
254
264
|
)
|
|
255
265
|
return targets, errors
|
|
@@ -373,6 +383,14 @@ def main(argv: Optional[Sequence[str]] = None) -> int:
|
|
|
373
383
|
parser.add_argument("--agent", required=True, help="Agent inbox name to watch")
|
|
374
384
|
parser.add_argument("--oacp-dir", default=None, help="Override OACP home directory")
|
|
375
385
|
parser.add_argument("--json", action="store_true", dest="json_output", help="Emit JSON Lines")
|
|
386
|
+
parser.add_argument(
|
|
387
|
+
"--state-id",
|
|
388
|
+
default=None,
|
|
389
|
+
help=(
|
|
390
|
+
"Use a per-subscriber cursor file state/watch/<agent>.<state-id>.json. "
|
|
391
|
+
"Omit for the legacy shared state/watch/<agent>.json cursor."
|
|
392
|
+
),
|
|
393
|
+
)
|
|
376
394
|
parser.add_argument(
|
|
377
395
|
"--since",
|
|
378
396
|
default="now",
|
|
@@ -394,6 +412,8 @@ def main(argv: Optional[Sequence[str]] = None) -> int:
|
|
|
394
412
|
)
|
|
395
413
|
|
|
396
414
|
args = parser.parse_args(list(argv) if argv is not None else None)
|
|
415
|
+
if args.state_id is not None and not _STATE_ID_RE.fullmatch(args.state_id):
|
|
416
|
+
parser.error("--state-id must match [A-Za-z0-9._-]{1,64}")
|
|
397
417
|
try:
|
|
398
418
|
since_epoch = _parse_since(args.since, now=time.time())
|
|
399
419
|
except argparse.ArgumentTypeError as exc:
|
|
@@ -405,6 +425,7 @@ def main(argv: Optional[Sequence[str]] = None) -> int:
|
|
|
405
425
|
all_projects=args.all_projects,
|
|
406
426
|
agent=args.agent,
|
|
407
427
|
oacp_root=oacp_root,
|
|
428
|
+
state_id=args.state_id,
|
|
408
429
|
)
|
|
409
430
|
had_errors = False
|
|
410
431
|
if target_errors:
|
|
@@ -457,6 +478,8 @@ def main(argv: Optional[Sequence[str]] = None) -> int:
|
|
|
457
478
|
"agent": target.agent,
|
|
458
479
|
"messages": current_messages,
|
|
459
480
|
}
|
|
481
|
+
if target.state_id is not None:
|
|
482
|
+
payload["state_id"] = target.state_id
|
|
460
483
|
try:
|
|
461
484
|
_write_state(target.state_file, payload)
|
|
462
485
|
except Exception as exc:
|
|
@@ -408,8 +408,8 @@ def write_message_files(
|
|
|
408
408
|
inbox_path = inbox_dir / filename
|
|
409
409
|
outbox_path = outbox_dir / filename
|
|
410
410
|
|
|
411
|
-
inbox_path
|
|
412
|
-
outbox_path
|
|
411
|
+
_atomic_write_text(inbox_path, yaml_content)
|
|
412
|
+
_atomic_write_text(outbox_path, yaml_content)
|
|
413
413
|
|
|
414
414
|
return inbox_path, outbox_path
|
|
415
415
|
|
|
@@ -431,19 +431,34 @@ def write_broadcast_files(
|
|
|
431
431
|
outbox_dir = project_dir / "agents" / sender / "outbox"
|
|
432
432
|
outbox_dir.mkdir(parents=True, exist_ok=True)
|
|
433
433
|
outbox_path = outbox_dir / filename
|
|
434
|
-
outbox_path
|
|
434
|
+
_atomic_write_text(outbox_path, yaml_content)
|
|
435
435
|
|
|
436
436
|
inbox_paths: List[Path] = []
|
|
437
437
|
for recipient in recipients:
|
|
438
438
|
inbox_dir = project_dir / "agents" / recipient / "inbox"
|
|
439
439
|
inbox_dir.mkdir(parents=True, exist_ok=True)
|
|
440
440
|
inbox_path = inbox_dir / filename
|
|
441
|
-
inbox_path
|
|
441
|
+
_atomic_write_text(inbox_path, yaml_content)
|
|
442
442
|
inbox_paths.append(inbox_path)
|
|
443
443
|
|
|
444
444
|
return inbox_paths, outbox_path
|
|
445
445
|
|
|
446
446
|
|
|
447
|
+
def _atomic_write_text(path: Path, content: str) -> None:
|
|
448
|
+
"""Write content via a same-directory temp file, then atomically replace."""
|
|
449
|
+
temp_name = f".{path.name}.tmp-{os.getpid()}-{secrets.token_hex(3)}"
|
|
450
|
+
temp_path = path.with_name(temp_name)
|
|
451
|
+
try:
|
|
452
|
+
temp_path.write_text(content, encoding="utf-8")
|
|
453
|
+
os.replace(temp_path, path)
|
|
454
|
+
finally:
|
|
455
|
+
try:
|
|
456
|
+
if temp_path.exists():
|
|
457
|
+
temp_path.unlink()
|
|
458
|
+
except OSError:
|
|
459
|
+
pass
|
|
460
|
+
|
|
461
|
+
|
|
447
462
|
def _parse_status_yaml(raw: str) -> Optional[str]:
|
|
448
463
|
"""Extract the 'status' field value from a status.yaml file.
|
|
449
464
|
|
|
@@ -521,7 +536,10 @@ def send_message(
|
|
|
521
536
|
"""
|
|
522
537
|
if oacp_dir is None:
|
|
523
538
|
from _oacp_env import resolve_oacp_home
|
|
539
|
+
|
|
524
540
|
oacp_dir = resolve_oacp_home()
|
|
541
|
+
else:
|
|
542
|
+
oacp_dir = Path(oacp_dir).expanduser()
|
|
525
543
|
|
|
526
544
|
# Parse recipient(s)
|
|
527
545
|
recipients_list = [r.strip() for r in recipient.split(",") if r.strip()]
|
|
@@ -738,7 +756,12 @@ def main() -> int:
|
|
|
738
756
|
parser.add_argument("--quiet", action="store_true", help="Suppress success output")
|
|
739
757
|
|
|
740
758
|
args = parser.parse_args()
|
|
741
|
-
|
|
759
|
+
if args.oacp_dir:
|
|
760
|
+
from _oacp_env import resolve_oacp_home
|
|
761
|
+
|
|
762
|
+
oacp_dir = resolve_oacp_home(args.oacp_dir)
|
|
763
|
+
else:
|
|
764
|
+
oacp_dir = None
|
|
742
765
|
|
|
743
766
|
try:
|
|
744
767
|
sender = infer_sender(args.project, args.sender, oacp_dir=oacp_dir)
|
|
@@ -51,6 +51,8 @@ class TestMemoryArchiveScripts(unittest.TestCase):
|
|
|
51
51
|
"GIT_AUTHOR_EMAIL": "oacp-test@example.com",
|
|
52
52
|
"GIT_COMMITTER_NAME": "OACP Test",
|
|
53
53
|
"GIT_COMMITTER_EMAIL": "oacp-test@example.com",
|
|
54
|
+
"GIT_CONFIG_GLOBAL": os.devnull,
|
|
55
|
+
"GIT_CONFIG_SYSTEM": os.devnull,
|
|
54
56
|
"OACP_AGENT": "codex",
|
|
55
57
|
},
|
|
56
58
|
):
|
|
@@ -7,10 +7,12 @@ from __future__ import annotations
|
|
|
7
7
|
import datetime as dt
|
|
8
8
|
import io
|
|
9
9
|
import json
|
|
10
|
+
import os
|
|
10
11
|
import sys
|
|
11
12
|
import tempfile
|
|
12
13
|
import unittest
|
|
13
14
|
from pathlib import Path
|
|
15
|
+
from unittest import mock
|
|
14
16
|
|
|
15
17
|
sys.path.insert(0, str(Path(__file__).resolve().parent.parent / "scripts"))
|
|
16
18
|
|
|
@@ -156,6 +158,41 @@ class TestMainCli(unittest.TestCase):
|
|
|
156
158
|
self.assertEqual(payload["project"], "demo")
|
|
157
159
|
self.assertEqual(payload["agents"][0]["messages"][0]["type"], "task_request")
|
|
158
160
|
|
|
161
|
+
def test_cli_oacp_dir_expands_tilde(self) -> None:
|
|
162
|
+
with tempfile.TemporaryDirectory() as tmpdir:
|
|
163
|
+
home = Path(tmpdir) / "home"
|
|
164
|
+
cwd = Path(tmpdir) / "cwd"
|
|
165
|
+
root = home / "oacp-tilde-test"
|
|
166
|
+
home.mkdir()
|
|
167
|
+
cwd.mkdir()
|
|
168
|
+
_write_message(
|
|
169
|
+
root,
|
|
170
|
+
"demo",
|
|
171
|
+
"claude",
|
|
172
|
+
"20260319120000_codex_task_request.yaml",
|
|
173
|
+
sender="codex",
|
|
174
|
+
msg_type="task_request",
|
|
175
|
+
priority="P1",
|
|
176
|
+
subject="Implement feature",
|
|
177
|
+
created_at_utc="2026-03-19T12:00:00Z",
|
|
178
|
+
)
|
|
179
|
+
old_cwd = Path.cwd()
|
|
180
|
+
try:
|
|
181
|
+
os.chdir(cwd)
|
|
182
|
+
with mock.patch.dict(os.environ, {"HOME": str(home)}, clear=False):
|
|
183
|
+
code, stdout, stderr = self._run_main(
|
|
184
|
+
["demo", "--agent", "claude", "--oacp-dir", "~/oacp-tilde-test", "--json"]
|
|
185
|
+
)
|
|
186
|
+
finally:
|
|
187
|
+
os.chdir(old_cwd)
|
|
188
|
+
|
|
189
|
+
self.assertEqual(code, 0)
|
|
190
|
+
self.assertEqual(stderr, "")
|
|
191
|
+
payload = json.loads(stdout)
|
|
192
|
+
self.assertEqual(payload["agents"][0]["message_count"], 1)
|
|
193
|
+
self.assertTrue(payload["agents"][0]["inbox_path"].startswith(str(home)))
|
|
194
|
+
self.assertFalse((cwd / "~").exists())
|
|
195
|
+
|
|
159
196
|
def test_missing_project_returns_error(self) -> None:
|
|
160
197
|
code, stdout, stderr = self._run_main(["missing", "--all"])
|
|
161
198
|
self.assertEqual(code, 1)
|