pactkit 2.7.0__tar.gz → 2.9.0__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 (315) hide show
  1. {pactkit-2.7.0 → pactkit-2.9.0}/.github/workflows/ci.yml +2 -2
  2. {pactkit-2.7.0 → pactkit-2.9.0}/.github/workflows/pactkit.yml +3 -3
  3. {pactkit-2.7.0 → pactkit-2.9.0}/.github/workflows/publish.yml +2 -2
  4. {pactkit-2.7.0 → pactkit-2.9.0}/.opencode/pactkit.yaml +4 -4
  5. {pactkit-2.7.0 → pactkit-2.9.0}/CHANGELOG.md +25 -0
  6. {pactkit-2.7.0 → pactkit-2.9.0}/PKG-INFO +42 -17
  7. {pactkit-2.7.0 → pactkit-2.9.0}/README.md +39 -15
  8. {pactkit-2.7.0 → pactkit-2.9.0}/pyproject.toml +3 -2
  9. {pactkit-2.7.0 → pactkit-2.9.0}/src/pactkit/__init__.py +1 -1
  10. {pactkit-2.7.0 → pactkit-2.9.0}/src/pactkit/cli.py +9 -9
  11. {pactkit-2.7.0 → pactkit-2.9.0}/src/pactkit/config.py +5 -27
  12. {pactkit-2.7.0 → pactkit-2.9.0}/src/pactkit/doctor.py +28 -25
  13. {pactkit-2.7.0 → pactkit-2.9.0}/src/pactkit/generators/deployer.py +41 -11
  14. {pactkit-2.7.0 → pactkit-2.9.0}/src/pactkit/profiles.py +2 -2
  15. {pactkit-2.7.0 → pactkit-2.9.0}/src/pactkit/prompts/commands.py +15 -4
  16. {pactkit-2.7.0 → pactkit-2.9.0}/tests/e2e/cli/test_cli_e2e.py +15 -15
  17. {pactkit-2.7.0 → pactkit-2.9.0}/tests/unit/test_bug013_config_single_source.py +4 -4
  18. {pactkit-2.7.0 → pactkit-2.9.0}/tests/unit/test_config.py +7 -3
  19. {pactkit-2.7.0 → pactkit-2.9.0}/tests/unit/test_config_auto_merge.py +6 -7
  20. {pactkit-2.7.0 → pactkit-2.9.0}/tests/unit/test_deployer_plugin.py +6 -6
  21. {pactkit-2.7.0 → pactkit-2.9.0}/tests/unit/test_selective_deploy.py +1 -1
  22. {pactkit-2.7.0 → pactkit-2.9.0}/tests/unit/test_story016_claude_md.py +3 -4
  23. {pactkit-2.7.0 → pactkit-2.9.0}/tests/unit/test_story033_config_backfill.py +3 -3
  24. {pactkit-2.7.0 → pactkit-2.9.0}/tests/unit/test_story059_codex_removal.py +2 -2
  25. {pactkit-2.7.0 → pactkit-2.9.0}/tests/unit/test_story063_prompt_slimming.py +2 -1
  26. {pactkit-2.7.0 → pactkit-2.9.0}/.github/ISSUE_TEMPLATE/bug_report.md +0 -0
  27. {pactkit-2.7.0 → pactkit-2.9.0}/.github/ISSUE_TEMPLATE/feature_request.md +0 -0
  28. {pactkit-2.7.0 → pactkit-2.9.0}/.github/PULL_REQUEST_TEMPLATE.md +0 -0
  29. {pactkit-2.7.0 → pactkit-2.9.0}/.github/dependabot.yml +0 -0
  30. {pactkit-2.7.0 → pactkit-2.9.0}/.gitignore +0 -0
  31. {pactkit-2.7.0 → pactkit-2.9.0}/AGENTS.md +0 -0
  32. {pactkit-2.7.0 → pactkit-2.9.0}/CODE_OF_CONDUCT.md +0 -0
  33. {pactkit-2.7.0 → pactkit-2.9.0}/CONTRIBUTING.md +0 -0
  34. {pactkit-2.7.0 → pactkit-2.9.0}/LICENSE +0 -0
  35. {pactkit-2.7.0 → pactkit-2.9.0}/SECURITY.md +0 -0
  36. {pactkit-2.7.0 → pactkit-2.9.0}/docs/assets/logo.png +0 -0
  37. {pactkit-2.7.0 → pactkit-2.9.0}/docs/guides/codex-integration-preresearch.md +0 -0
  38. {pactkit-2.7.0 → pactkit-2.9.0}/docs/guides/tool-integration-checklist.md +0 -0
  39. {pactkit-2.7.0 → pactkit-2.9.0}/docs/specs/BUG-001.md +0 -0
  40. {pactkit-2.7.0 → pactkit-2.9.0}/docs/specs/BUG-002.md +0 -0
  41. {pactkit-2.7.0 → pactkit-2.9.0}/docs/specs/BUG-003.md +0 -0
  42. {pactkit-2.7.0 → pactkit-2.9.0}/docs/specs/BUG-004.md +0 -0
  43. {pactkit-2.7.0 → pactkit-2.9.0}/docs/specs/BUG-005.md +0 -0
  44. {pactkit-2.7.0 → pactkit-2.9.0}/docs/specs/BUG-006.md +0 -0
  45. {pactkit-2.7.0 → pactkit-2.9.0}/docs/specs/BUG-007.md +0 -0
  46. {pactkit-2.7.0 → pactkit-2.9.0}/docs/specs/BUG-008.md +0 -0
  47. {pactkit-2.7.0 → pactkit-2.9.0}/docs/specs/BUG-009.md +0 -0
  48. {pactkit-2.7.0 → pactkit-2.9.0}/docs/specs/BUG-010.md +0 -0
  49. {pactkit-2.7.0 → pactkit-2.9.0}/docs/specs/BUG-011.md +0 -0
  50. {pactkit-2.7.0 → pactkit-2.9.0}/docs/specs/BUG-012.md +0 -0
  51. {pactkit-2.7.0 → pactkit-2.9.0}/docs/specs/BUG-013.md +0 -0
  52. {pactkit-2.7.0 → pactkit-2.9.0}/docs/specs/BUG-014.md +0 -0
  53. {pactkit-2.7.0 → pactkit-2.9.0}/docs/specs/BUG-015.md +0 -0
  54. {pactkit-2.7.0 → pactkit-2.9.0}/docs/specs/BUG-016.md +0 -0
  55. {pactkit-2.7.0 → pactkit-2.9.0}/docs/specs/BUG-017.md +0 -0
  56. {pactkit-2.7.0 → pactkit-2.9.0}/docs/specs/BUG-018.md +0 -0
  57. {pactkit-2.7.0 → pactkit-2.9.0}/docs/specs/BUG-019.md +0 -0
  58. {pactkit-2.7.0 → pactkit-2.9.0}/docs/specs/BUG-020.md +0 -0
  59. {pactkit-2.7.0 → pactkit-2.9.0}/docs/specs/BUG-021.md +0 -0
  60. {pactkit-2.7.0 → pactkit-2.9.0}/docs/specs/BUG-022.md +0 -0
  61. {pactkit-2.7.0 → pactkit-2.9.0}/docs/specs/BUG-023.md +0 -0
  62. {pactkit-2.7.0 → pactkit-2.9.0}/docs/specs/BUG-024.md +0 -0
  63. {pactkit-2.7.0 → pactkit-2.9.0}/docs/specs/BUG-025.md +0 -0
  64. {pactkit-2.7.0 → pactkit-2.9.0}/docs/specs/BUG-026.md +0 -0
  65. {pactkit-2.7.0 → pactkit-2.9.0}/docs/specs/BUG-027.md +0 -0
  66. {pactkit-2.7.0 → pactkit-2.9.0}/docs/specs/BUG-028.md +0 -0
  67. {pactkit-2.7.0 → pactkit-2.9.0}/docs/specs/BUG-029.md +0 -0
  68. {pactkit-2.7.0 → pactkit-2.9.0}/docs/specs/BUG-030.md +0 -0
  69. {pactkit-2.7.0 → pactkit-2.9.0}/docs/specs/BUG-031.md +0 -0
  70. {pactkit-2.7.0 → pactkit-2.9.0}/docs/specs/BUG-032.md +0 -0
  71. {pactkit-2.7.0 → pactkit-2.9.0}/docs/specs/BUG-033.md +0 -0
  72. {pactkit-2.7.0 → pactkit-2.9.0}/docs/specs/BUG-034.md +0 -0
  73. {pactkit-2.7.0 → pactkit-2.9.0}/docs/specs/BUG-035.md +0 -0
  74. {pactkit-2.7.0 → pactkit-2.9.0}/docs/specs/BUG-slim-001.md +0 -0
  75. {pactkit-2.7.0 → pactkit-2.9.0}/docs/specs/BUG-slim-002.md +0 -0
  76. {pactkit-2.7.0 → pactkit-2.9.0}/docs/specs/BUG-slim-003.md +0 -0
  77. {pactkit-2.7.0 → pactkit-2.9.0}/docs/specs/BUG-slim-004.md +0 -0
  78. {pactkit-2.7.0 → pactkit-2.9.0}/docs/specs/BUG-slim-005.md +0 -0
  79. {pactkit-2.7.0 → pactkit-2.9.0}/docs/specs/BUG-slim-006.md +0 -0
  80. {pactkit-2.7.0 → pactkit-2.9.0}/docs/specs/BUG-slim-007.md +0 -0
  81. {pactkit-2.7.0 → pactkit-2.9.0}/docs/test_cases/BUG-001_case.md +0 -0
  82. {pactkit-2.7.0 → pactkit-2.9.0}/docs/test_cases/BUG-002_case.md +0 -0
  83. {pactkit-2.7.0 → pactkit-2.9.0}/opencode.json +0 -0
  84. {pactkit-2.7.0 → pactkit-2.9.0}/src/pactkit/__main__.py +0 -0
  85. {pactkit-2.7.0 → pactkit-2.9.0}/src/pactkit/backfill.py +0 -0
  86. {pactkit-2.7.0 → pactkit-2.9.0}/src/pactkit/cleaners.py +0 -0
  87. {pactkit-2.7.0 → pactkit-2.9.0}/src/pactkit/context_gen.py +0 -0
  88. {pactkit-2.7.0 → pactkit-2.9.0}/src/pactkit/coverage_gate.py +0 -0
  89. {pactkit-2.7.0 → pactkit-2.9.0}/src/pactkit/generators/__init__.py +0 -0
  90. {pactkit-2.7.0 → pactkit-2.9.0}/src/pactkit/generators/adapter.py +0 -0
  91. {pactkit-2.7.0 → pactkit-2.9.0}/src/pactkit/generators/deploy_base.py +0 -0
  92. {pactkit-2.7.0 → pactkit-2.9.0}/src/pactkit/guards.py +0 -0
  93. {pactkit-2.7.0 → pactkit-2.9.0}/src/pactkit/id_generator.py +0 -0
  94. {pactkit-2.7.0 → pactkit-2.9.0}/src/pactkit/invariants.py +0 -0
  95. {pactkit-2.7.0 → pactkit-2.9.0}/src/pactkit/issue_sync.py +0 -0
  96. {pactkit-2.7.0 → pactkit-2.9.0}/src/pactkit/lazy_visualize.py +0 -0
  97. {pactkit-2.7.0 → pactkit-2.9.0}/src/pactkit/lessons.py +0 -0
  98. {pactkit-2.7.0 → pactkit-2.9.0}/src/pactkit/lint_runner.py +0 -0
  99. {pactkit-2.7.0 → pactkit-2.9.0}/src/pactkit/prompts/__init__.py +0 -0
  100. {pactkit-2.7.0 → pactkit-2.9.0}/src/pactkit/prompts/agents.py +0 -0
  101. {pactkit-2.7.0 → pactkit-2.9.0}/src/pactkit/prompts/references.py +0 -0
  102. {pactkit-2.7.0 → pactkit-2.9.0}/src/pactkit/prompts/rules.py +0 -0
  103. {pactkit-2.7.0 → pactkit-2.9.0}/src/pactkit/prompts/skills.py +0 -0
  104. {pactkit-2.7.0 → pactkit-2.9.0}/src/pactkit/prompts/workflows.py +0 -0
  105. {pactkit-2.7.0 → pactkit-2.9.0}/src/pactkit/regression.py +0 -0
  106. {pactkit-2.7.0 → pactkit-2.9.0}/src/pactkit/schemas.py +0 -0
  107. {pactkit-2.7.0 → pactkit-2.9.0}/src/pactkit/scripts.py +0 -0
  108. {pactkit-2.7.0 → pactkit-2.9.0}/src/pactkit/sec_scope.py +0 -0
  109. {pactkit-2.7.0 → pactkit-2.9.0}/src/pactkit/skills/__init__.py +0 -0
  110. {pactkit-2.7.0 → pactkit-2.9.0}/src/pactkit/skills/board.py +0 -0
  111. {pactkit-2.7.0 → pactkit-2.9.0}/src/pactkit/skills/scaffold.py +0 -0
  112. {pactkit-2.7.0 → pactkit-2.9.0}/src/pactkit/skills/spec_linter.py +0 -0
  113. {pactkit-2.7.0 → pactkit-2.9.0}/src/pactkit/skills/visualize.py +0 -0
  114. {pactkit-2.7.0 → pactkit-2.9.0}/src/pactkit/spec_status.py +0 -0
  115. {pactkit-2.7.0 → pactkit-2.9.0}/src/pactkit/test_mapper.py +0 -0
  116. {pactkit-2.7.0 → pactkit-2.9.0}/src/pactkit/utils.py +0 -0
  117. {pactkit-2.7.0 → pactkit-2.9.0}/src/pactkit/validators.py +0 -0
  118. {pactkit-2.7.0 → pactkit-2.9.0}/tests/conftest.py +0 -0
  119. {pactkit-2.7.0 → pactkit-2.9.0}/tests/e2e/__init__.py +0 -0
  120. {pactkit-2.7.0 → pactkit-2.9.0}/tests/e2e/cli/__init__.py +0 -0
  121. {pactkit-2.7.0 → pactkit-2.9.0}/tests/integration/__init__.py +0 -0
  122. {pactkit-2.7.0 → pactkit-2.9.0}/tests/integration/test_deploy_classic.py +0 -0
  123. {pactkit-2.7.0 → pactkit-2.9.0}/tests/unit/test_agent_features.py +0 -0
  124. {pactkit-2.7.0 → pactkit-2.9.0}/tests/unit/test_agent_frontmatter.py +0 -0
  125. {pactkit-2.7.0 → pactkit-2.9.0}/tests/unit/test_agents_enrichment.py +0 -0
  126. {pactkit-2.7.0 → pactkit-2.9.0}/tests/unit/test_board_bug027.py +0 -0
  127. {pactkit-2.7.0 → pactkit-2.9.0}/tests/unit/test_board_sections.py +0 -0
  128. {pactkit-2.7.0 → pactkit-2.9.0}/tests/unit/test_bug001_skill_path.py +0 -0
  129. {pactkit-2.7.0 → pactkit-2.9.0}/tests/unit/test_bug002_plugin_paths.py +0 -0
  130. {pactkit-2.7.0 → pactkit-2.9.0}/tests/unit/test_bug003_multi_import.py +0 -0
  131. {pactkit-2.7.0 → pactkit-2.9.0}/tests/unit/test_bug004_dead_set.py +0 -0
  132. {pactkit-2.7.0 → pactkit-2.9.0}/tests/unit/test_bug005_archive_taskless.py +0 -0
  133. {pactkit-2.7.0 → pactkit-2.9.0}/tests/unit/test_bug006_scan_excludes.py +0 -0
  134. {pactkit-2.7.0 → pactkit-2.9.0}/tests/unit/test_bug007_stale_trace_refs.py +0 -0
  135. {pactkit-2.7.0 → pactkit-2.9.0}/tests/unit/test_bug008_stale_command_refs.py +0 -0
  136. {pactkit-2.7.0 → pactkit-2.9.0}/tests/unit/test_bug009_project_config_backfill.py +0 -0
  137. {pactkit-2.7.0 → pactkit-2.9.0}/tests/unit/test_bug010_rewrite_yaml.py +0 -0
  138. {pactkit-2.7.0 → pactkit-2.9.0}/tests/unit/test_bug011_stale_refs.py +0 -0
  139. {pactkit-2.7.0 → pactkit-2.9.0}/tests/unit/test_bug012_call_graph_filter.py +0 -0
  140. {pactkit-2.7.0 → pactkit-2.9.0}/tests/unit/test_bug014_version_hygiene.py +0 -0
  141. {pactkit-2.7.0 → pactkit-2.9.0}/tests/unit/test_bug017_project_init_playbook.py +0 -0
  142. {pactkit-2.7.0 → pactkit-2.9.0}/tests/unit/test_bug018_issue_tracker_verification.py +0 -0
  143. {pactkit-2.7.0 → pactkit-2.9.0}/tests/unit/test_bug019_venv_deployment.py +0 -0
  144. {pactkit-2.7.0 → pactkit-2.9.0}/tests/unit/test_bug020_claude_md_backup.py +0 -0
  145. {pactkit-2.7.0 → pactkit-2.9.0}/tests/unit/test_bug025_release_delegation.py +0 -0
  146. {pactkit-2.7.0 → pactkit-2.9.0}/tests/unit/test_bug026_version_sync.py +0 -0
  147. {pactkit-2.7.0 → pactkit-2.9.0}/tests/unit/test_bug028_ghost_refs.py +0 -0
  148. {pactkit-2.7.0 → pactkit-2.9.0}/tests/unit/test_bug029_stack_detection_fallback.py +0 -0
  149. {pactkit-2.7.0 → pactkit-2.9.0}/tests/unit/test_bug030_spec_lint_cli.py +0 -0
  150. {pactkit-2.7.0 → pactkit-2.9.0}/tests/unit/test_bug031_docstring_accuracy.py +0 -0
  151. {pactkit-2.7.0 → pactkit-2.9.0}/tests/unit/test_bug034_plan_metadata_template.py +0 -0
  152. {pactkit-2.7.0 → pactkit-2.9.0}/tests/unit/test_bug_021.py +0 -0
  153. {pactkit-2.7.0 → pactkit-2.9.0}/tests/unit/test_bug_022.py +0 -0
  154. {pactkit-2.7.0 → pactkit-2.9.0}/tests/unit/test_bug_023.py +0 -0
  155. {pactkit-2.7.0 → pactkit-2.9.0}/tests/unit/test_bug_024.py +0 -0
  156. {pactkit-2.7.0 → pactkit-2.9.0}/tests/unit/test_bug_slim001_env_detection.py +0 -0
  157. {pactkit-2.7.0 → pactkit-2.9.0}/tests/unit/test_bug_slim002_instruction_collision.py +0 -0
  158. {pactkit-2.7.0 → pactkit-2.9.0}/tests/unit/test_bug_slim003.py +0 -0
  159. {pactkit-2.7.0 → pactkit-2.9.0}/tests/unit/test_bug_slim004.py +0 -0
  160. {pactkit-2.7.0 → pactkit-2.9.0}/tests/unit/test_bug_slim005.py +0 -0
  161. {pactkit-2.7.0 → pactkit-2.9.0}/tests/unit/test_bug_slim006.py +0 -0
  162. {pactkit-2.7.0 → pactkit-2.9.0}/tests/unit/test_check_command.py +0 -0
  163. {pactkit-2.7.0 → pactkit-2.9.0}/tests/unit/test_command_frontmatter.py +0 -0
  164. {pactkit-2.7.0 → pactkit-2.9.0}/tests/unit/test_command_visualize_modes.py +0 -0
  165. {pactkit-2.7.0 → pactkit-2.9.0}/tests/unit/test_constitution_sharpening.py +0 -0
  166. {pactkit-2.7.0 → pactkit-2.9.0}/tests/unit/test_create_skill.py +0 -0
  167. {pactkit-2.7.0 → pactkit-2.9.0}/tests/unit/test_cross_flow_matrix.py +0 -0
  168. {pactkit-2.7.0 → pactkit-2.9.0}/tests/unit/test_deploy_base.py +0 -0
  169. {pactkit-2.7.0 → pactkit-2.9.0}/tests/unit/test_deployer_cleanup.py +0 -0
  170. {pactkit-2.7.0 → pactkit-2.9.0}/tests/unit/test_design_command.py +0 -0
  171. {pactkit-2.7.0 → pactkit-2.9.0}/tests/unit/test_done_gates.py +0 -0
  172. {pactkit-2.7.0 → pactkit-2.9.0}/tests/unit/test_draw_prompt.py +0 -0
  173. {pactkit-2.7.0 → pactkit-2.9.0}/tests/unit/test_draw_references.py +0 -0
  174. {pactkit-2.7.0 → pactkit-2.9.0}/tests/unit/test_drawio_mcp.py +0 -0
  175. {pactkit-2.7.0 → pactkit-2.9.0}/tests/unit/test_home_path_fix.py +0 -0
  176. {pactkit-2.7.0 → pactkit-2.9.0}/tests/unit/test_hotfix_command.py +0 -0
  177. {pactkit-2.7.0 → pactkit-2.9.0}/tests/unit/test_init_guard.py +0 -0
  178. {pactkit-2.7.0 → pactkit-2.9.0}/tests/unit/test_lang_profiles.py +0 -0
  179. {pactkit-2.7.0 → pactkit-2.9.0}/tests/unit/test_list_stories.py +0 -0
  180. {pactkit-2.7.0 → pactkit-2.9.0}/tests/unit/test_mcp_integration.py +0 -0
  181. {pactkit-2.7.0 → pactkit-2.9.0}/tests/unit/test_model_config.py +0 -0
  182. {pactkit-2.7.0 → pactkit-2.9.0}/tests/unit/test_modular_constitution.py +0 -0
  183. {pactkit-2.7.0 → pactkit-2.9.0}/tests/unit/test_multi_prefix.py +0 -0
  184. {pactkit-2.7.0 → pactkit-2.9.0}/tests/unit/test_pdca_slim.py +0 -0
  185. {pactkit-2.7.0 → pactkit-2.9.0}/tests/unit/test_profiles.py +0 -0
  186. {pactkit-2.7.0 → pactkit-2.9.0}/tests/unit/test_project_visibility.py +0 -0
  187. {pactkit-2.7.0 → pactkit-2.9.0}/tests/unit/test_prompt_cli_refs.py +0 -0
  188. {pactkit-2.7.0 → pactkit-2.9.0}/tests/unit/test_prompt_structural_invariants.py +0 -0
  189. {pactkit-2.7.0 → pactkit-2.9.0}/tests/unit/test_prompts_package.py +0 -0
  190. {pactkit-2.7.0 → pactkit-2.9.0}/tests/unit/test_release.py +0 -0
  191. {pactkit-2.7.0 → pactkit-2.9.0}/tests/unit/test_release_field.py +0 -0
  192. {pactkit-2.7.0 → pactkit-2.9.0}/tests/unit/test_release_v110.py +0 -0
  193. {pactkit-2.7.0 → pactkit-2.9.0}/tests/unit/test_render_prompt.py +0 -0
  194. {pactkit-2.7.0 → pactkit-2.9.0}/tests/unit/test_review_command.py +0 -0
  195. {pactkit-2.7.0 → pactkit-2.9.0}/tests/unit/test_rules_enrichment.py +0 -0
  196. {pactkit-2.7.0 → pactkit-2.9.0}/tests/unit/test_scaffold.py +0 -0
  197. {pactkit-2.7.0 → pactkit-2.9.0}/tests/unit/test_scaffold_developer_prefix.py +0 -0
  198. {pactkit-2.7.0 → pactkit-2.9.0}/tests/unit/test_schemas.py +0 -0
  199. {pactkit-2.7.0 → pactkit-2.9.0}/tests/unit/test_script_extraction.py +0 -0
  200. {pactkit-2.7.0 → pactkit-2.9.0}/tests/unit/test_session_context.py +0 -0
  201. {pactkit-2.7.0 → pactkit-2.9.0}/tests/unit/test_skill_structure.py +0 -0
  202. {pactkit-2.7.0 → pactkit-2.9.0}/tests/unit/test_skills_enrichment.py +0 -0
  203. {pactkit-2.7.0 → pactkit-2.9.0}/tests/unit/test_smart_regression.py +0 -0
  204. {pactkit-2.7.0 → pactkit-2.9.0}/tests/unit/test_sprint_command.py +0 -0
  205. {pactkit-2.7.0 → pactkit-2.9.0}/tests/unit/test_stack_references.py +0 -0
  206. {pactkit-2.7.0 → pactkit-2.9.0}/tests/unit/test_status_command.py +0 -0
  207. {pactkit-2.7.0 → pactkit-2.9.0}/tests/unit/test_statusline.py +0 -0
  208. {pactkit-2.7.0 → pactkit-2.9.0}/tests/unit/test_story014_release.py +0 -0
  209. {pactkit-2.7.0 → pactkit-2.9.0}/tests/unit/test_story015_ci_lint_gate.py +0 -0
  210. {pactkit-2.7.0 → pactkit-2.9.0}/tests/unit/test_story017_init_claude_md.py +0 -0
  211. {pactkit-2.7.0 → pactkit-2.9.0}/tests/unit/test_story018_arch_staleness.py +0 -0
  212. {pactkit-2.7.0 → pactkit-2.9.0}/tests/unit/test_story019_bailout.py +0 -0
  213. {pactkit-2.7.0 → pactkit-2.9.0}/tests/unit/test_story020_horizon.py +0 -0
  214. {pactkit-2.7.0 → pactkit-2.9.0}/tests/unit/test_story021_rfc.py +0 -0
  215. {pactkit-2.7.0 → pactkit-2.9.0}/tests/unit/test_story022_decision_tree.py +0 -0
  216. {pactkit-2.7.0 → pactkit-2.9.0}/tests/unit/test_story023_test_quality.py +0 -0
  217. {pactkit-2.7.0 → pactkit-2.9.0}/tests/unit/test_story024_native_agent.py +0 -0
  218. {pactkit-2.7.0 → pactkit-2.9.0}/tests/unit/test_story025_ci_pipeline.py +0 -0
  219. {pactkit-2.7.0 → pactkit-2.9.0}/tests/unit/test_story026_issue_tracker.py +0 -0
  220. {pactkit-2.7.0 → pactkit-2.9.0}/tests/unit/test_story027_hooks.py +0 -0
  221. {pactkit-2.7.0 → pactkit-2.9.0}/tests/unit/test_story028_rule_scoping.py +0 -0
  222. {pactkit-2.7.0 → pactkit-2.9.0}/tests/unit/test_story029_doctor.py +0 -0
  223. {pactkit-2.7.0 → pactkit-2.9.0}/tests/unit/test_story030_lint.py +0 -0
  224. {pactkit-2.7.0 → pactkit-2.9.0}/tests/unit/test_story031_git_init_guard.py +0 -0
  225. {pactkit-2.7.0 → pactkit-2.9.0}/tests/unit/test_story032_greenfield_redirect.py +0 -0
  226. {pactkit-2.7.0 → pactkit-2.9.0}/tests/unit/test_story034_plan_config_refresh.py +0 -0
  227. {pactkit-2.7.0 → pactkit-2.9.0}/tests/unit/test_story035_readme_docs.py +0 -0
  228. {pactkit-2.7.0 → pactkit-2.9.0}/tests/unit/test_story037_regression_fix.py +0 -0
  229. {pactkit-2.7.0 → pactkit-2.9.0}/tests/unit/test_story038_call_graph_update.py +0 -0
  230. {pactkit-2.7.0 → pactkit-2.9.0}/tests/unit/test_story039_venv_config.py +0 -0
  231. {pactkit-2.7.0 → pactkit-2.9.0}/tests/unit/test_story040_layered_claude_md.py +0 -0
  232. {pactkit-2.7.0 → pactkit-2.9.0}/tests/unit/test_story042_spec_linter.py +0 -0
  233. {pactkit-2.7.0 → pactkit-2.9.0}/tests/unit/test_story043_active_clarify.py +0 -0
  234. {pactkit-2.7.0 → pactkit-2.9.0}/tests/unit/test_story044_consistency_check.py +0 -0
  235. {pactkit-2.7.0 → pactkit-2.9.0}/tests/unit/test_story045_auto_pr.py +0 -0
  236. {pactkit-2.7.0 → pactkit-2.9.0}/tests/unit/test_story046_agent_adapter.py +0 -0
  237. {pactkit-2.7.0 → pactkit-2.9.0}/tests/unit/test_story047_enterprise_flags.py +0 -0
  238. {pactkit-2.7.0 → pactkit-2.9.0}/tests/unit/test_story048_worktree_isolation.py +0 -0
  239. {pactkit-2.7.0 → pactkit-2.9.0}/tests/unit/test_story049_community_standards.py +0 -0
  240. {pactkit-2.7.0 → pactkit-2.9.0}/tests/unit/test_story050_doc_only_shortcut.py +0 -0
  241. {pactkit-2.7.0 → pactkit-2.9.0}/tests/unit/test_story051_workflow_streamlining.py +0 -0
  242. {pactkit-2.7.0 → pactkit-2.9.0}/tests/unit/test_story052_conditional_github_release.py +0 -0
  243. {pactkit-2.7.0 → pactkit-2.9.0}/tests/unit/test_story053_impact_regression.py +0 -0
  244. {pactkit-2.7.0 → pactkit-2.9.0}/tests/unit/test_story055_commands.py +0 -0
  245. {pactkit-2.7.0 → pactkit-2.9.0}/tests/unit/test_story055_config.py +0 -0
  246. {pactkit-2.7.0 → pactkit-2.9.0}/tests/unit/test_story055_spec_linter.py +0 -0
  247. {pactkit-2.7.0 → pactkit-2.9.0}/tests/unit/test_story056_commands.py +0 -0
  248. {pactkit-2.7.0 → pactkit-2.9.0}/tests/unit/test_story056_config.py +0 -0
  249. {pactkit-2.7.0 → pactkit-2.9.0}/tests/unit/test_story057_implicit_cleanup.py +0 -0
  250. {pactkit-2.7.0 → pactkit-2.9.0}/tests/unit/test_story058_opencode_extraction.py +0 -0
  251. {pactkit-2.7.0 → pactkit-2.9.0}/tests/unit/test_story058_routing_fix.py +0 -0
  252. {pactkit-2.7.0 → pactkit-2.9.0}/tests/unit/test_story060_init_hang.py +0 -0
  253. {pactkit-2.7.0 → pactkit-2.9.0}/tests/unit/test_story061_remove_thinking.py +0 -0
  254. {pactkit-2.7.0 → pactkit-2.9.0}/tests/unit/test_story062_mcp_recommendations.py +0 -0
  255. {pactkit-2.7.0 → pactkit-2.9.0}/tests/unit/test_story064_venv_local_md.py +0 -0
  256. {pactkit-2.7.0 → pactkit-2.9.0}/tests/unit/test_story065_sprint_model.py +0 -0
  257. {pactkit-2.7.0 → pactkit-2.9.0}/tests/unit/test_story072_developer_prefix.py +0 -0
  258. {pactkit-2.7.0 → pactkit-2.9.0}/tests/unit/test_story_slim009_lazy_rules.py +0 -0
  259. {pactkit-2.7.0 → pactkit-2.9.0}/tests/unit/test_story_slim010_dry_refactor.py +0 -0
  260. {pactkit-2.7.0 → pactkit-2.9.0}/tests/unit/test_story_slim011_command_rules.py +0 -0
  261. {pactkit-2.7.0 → pactkit-2.9.0}/tests/unit/test_story_slim012_ci.py +0 -0
  262. {pactkit-2.7.0 → pactkit-2.9.0}/tests/unit/test_story_slim014_clean.py +0 -0
  263. {pactkit-2.7.0 → pactkit-2.9.0}/tests/unit/test_story_slim014_context.py +0 -0
  264. {pactkit-2.7.0 → pactkit-2.9.0}/tests/unit/test_story_slim014_guard.py +0 -0
  265. {pactkit-2.7.0 → pactkit-2.9.0}/tests/unit/test_story_slim014_lazy_viz.py +0 -0
  266. {pactkit-2.7.0 → pactkit-2.9.0}/tests/unit/test_story_slim014_next_id.py +0 -0
  267. {pactkit-2.7.0 → pactkit-2.9.0}/tests/unit/test_story_slim014_regression.py +0 -0
  268. {pactkit-2.7.0 → pactkit-2.9.0}/tests/unit/test_story_slim014_sec_scope.py +0 -0
  269. {pactkit-2.7.0 → pactkit-2.9.0}/tests/unit/test_story_slim014_validators.py +0 -0
  270. {pactkit-2.7.0 → pactkit-2.9.0}/tests/unit/test_story_slim015_doctor.py +0 -0
  271. {pactkit-2.7.0 → pactkit-2.9.0}/tests/unit/test_story_slim016_testmap_lint.py +0 -0
  272. {pactkit-2.7.0 → pactkit-2.9.0}/tests/unit/test_story_slim017.py +0 -0
  273. {pactkit-2.7.0 → pactkit-2.9.0}/tests/unit/test_story_slim018.py +0 -0
  274. {pactkit-2.7.0 → pactkit-2.9.0}/tests/unit/test_story_slim019_plan_subphases.py +0 -0
  275. {pactkit-2.7.0 → pactkit-2.9.0}/tests/unit/test_story_slim020_explore_stall_fix.py +0 -0
  276. {pactkit-2.7.0 → pactkit-2.9.0}/tests/unit/test_story_slim021.py +0 -0
  277. {pactkit-2.7.0 → pactkit-2.9.0}/tests/unit/test_story_slim022.py +0 -0
  278. {pactkit-2.7.0 → pactkit-2.9.0}/tests/unit/test_story_slim023.py +0 -0
  279. {pactkit-2.7.0 → pactkit-2.9.0}/tests/unit/test_story_slim024.py +0 -0
  280. {pactkit-2.7.0 → pactkit-2.9.0}/tests/unit/test_story_slim025.py +0 -0
  281. {pactkit-2.7.0 → pactkit-2.9.0}/tests/unit/test_story_slim026.py +0 -0
  282. {pactkit-2.7.0 → pactkit-2.9.0}/tests/unit/test_story_slim027.py +0 -0
  283. {pactkit-2.7.0 → pactkit-2.9.0}/tests/unit/test_story_slim028.py +0 -0
  284. {pactkit-2.7.0 → pactkit-2.9.0}/tests/unit/test_story_slim029.py +0 -0
  285. {pactkit-2.7.0 → pactkit-2.9.0}/tests/unit/test_story_slim030.py +0 -0
  286. {pactkit-2.7.0 → pactkit-2.9.0}/tests/unit/test_story_slim031.py +0 -0
  287. {pactkit-2.7.0 → pactkit-2.9.0}/tests/unit/test_story_slim032.py +0 -0
  288. {pactkit-2.7.0 → pactkit-2.9.0}/tests/unit/test_story_slim033.py +0 -0
  289. {pactkit-2.7.0 → pactkit-2.9.0}/tests/unit/test_story_slim034.py +0 -0
  290. {pactkit-2.7.0 → pactkit-2.9.0}/tests/unit/test_story_slim035.py +0 -0
  291. {pactkit-2.7.0 → pactkit-2.9.0}/tests/unit/test_story_slim036.py +0 -0
  292. {pactkit-2.7.0 → pactkit-2.9.0}/tests/unit/test_story_slim037.py +0 -0
  293. {pactkit-2.7.0 → pactkit-2.9.0}/tests/unit/test_story_slim038.py +0 -0
  294. {pactkit-2.7.0 → pactkit-2.9.0}/tests/unit/test_story_slim039.py +0 -0
  295. {pactkit-2.7.0 → pactkit-2.9.0}/tests/unit/test_story_slim040.py +0 -0
  296. {pactkit-2.7.0 → pactkit-2.9.0}/tests/unit/test_story_slim041.py +0 -0
  297. {pactkit-2.7.0 → pactkit-2.9.0}/tests/unit/test_story_slim042.py +0 -0
  298. {pactkit-2.7.0 → pactkit-2.9.0}/tests/unit/test_story_slim043.py +0 -0
  299. {pactkit-2.7.0 → pactkit-2.9.0}/tests/unit/test_story_slim044.py +0 -0
  300. {pactkit-2.7.0 → pactkit-2.9.0}/tests/unit/test_story_slim045.py +0 -0
  301. {pactkit-2.7.0 → pactkit-2.9.0}/tests/unit/test_story_slim046.py +0 -0
  302. {pactkit-2.7.0 → pactkit-2.9.0}/tests/unit/test_story_slim047.py +0 -0
  303. {pactkit-2.7.0 → pactkit-2.9.0}/tests/unit/test_story_slim048.py +0 -0
  304. {pactkit-2.7.0 → pactkit-2.9.0}/tests/unit/test_story_slim049.py +0 -0
  305. {pactkit-2.7.0 → pactkit-2.9.0}/tests/unit/test_story_slim051.py +0 -0
  306. {pactkit-2.7.0 → pactkit-2.9.0}/tests/unit/test_story_slim052.py +0 -0
  307. {pactkit-2.7.0 → pactkit-2.9.0}/tests/unit/test_story_slim053.py +0 -0
  308. {pactkit-2.7.0 → pactkit-2.9.0}/tests/unit/test_story_slim054.py +0 -0
  309. {pactkit-2.7.0 → pactkit-2.9.0}/tests/unit/test_story_slim055.py +0 -0
  310. {pactkit-2.7.0 → pactkit-2.9.0}/tests/unit/test_story_slim056.py +0 -0
  311. {pactkit-2.7.0 → pactkit-2.9.0}/tests/unit/test_story_slim060_codex_profile.py +0 -0
  312. {pactkit-2.7.0 → pactkit-2.9.0}/tests/unit/test_story_slim063.py +0 -0
  313. {pactkit-2.7.0 → pactkit-2.9.0}/tests/unit/test_tools.py +0 -0
  314. {pactkit-2.7.0 → pactkit-2.9.0}/tests/unit/test_update_task.py +0 -0
  315. {pactkit-2.7.0 → pactkit-2.9.0}/tests/unit/test_visualize_modes.py +0 -0
@@ -24,8 +24,8 @@ jobs:
24
24
  - name: Install dependencies
25
25
  run: |
26
26
  python -m pip install --upgrade pip
27
- pip install -e ".[multilang]"
28
- pip install pytest ruff==0.15.1
27
+ pip install --no-deps -e ".[multilang]"
28
+ pip install pyyaml pytest ruff==0.15.1
29
29
 
30
30
  - name: Lint with ruff
31
31
  run: ruff check src/ tests/
@@ -20,9 +20,9 @@ jobs:
20
20
  - name: Install dependencies
21
21
  run: |
22
22
  python -m pip install --upgrade pip
23
- pip install -e ".[dev]" || pip install -e .
24
- pip install pytest ruff
25
- pactkit init
23
+ pip install --no-deps -e ".[dev]" || pip install --no-deps -e .
24
+ pip install pyyaml pytest ruff
25
+ pactkit init --format classic
26
26
 
27
27
  - name: Lint
28
28
  run: ruff check src/ tests/
@@ -27,8 +27,8 @@ jobs:
27
27
  - name: Install dependencies
28
28
  run: |
29
29
  python -m pip install --upgrade pip
30
- pip install -e ".[dev]" || pip install -e .
31
- pip install pytest ruff
30
+ pip install --no-deps -e ".[dev]" || pip install --no-deps -e .
31
+ pip install pyyaml pytest ruff
32
32
 
33
33
  - name: Lint
34
34
  run: ruff check src/ tests/
@@ -2,7 +2,7 @@
2
2
  # Edit this file to customize which components are deployed.
3
3
  # Remove items from a list to disable them. Default: all enabled.
4
4
 
5
- version: "2.6.1"
5
+ version: "2.8.0"
6
6
  stack: python
7
7
  root: .
8
8
  developer: "slim"
@@ -23,18 +23,19 @@ agents:
23
23
  commands:
24
24
  - project-act
25
25
  - project-check
26
+ - project-clarify
26
27
  - project-design
27
28
  - project-done
28
29
  - project-hotfix
29
30
  - project-init
30
31
  - project-plan
31
- - project-sprint
32
- - project-clarify
33
32
  - project-pr
34
33
  - project-release
34
+ - project-sprint
35
35
 
36
36
  # Skills — tool scripts
37
37
  skills:
38
+ - pactkit-analyze
38
39
  - pactkit-board
39
40
  - pactkit-doctor
40
41
  - pactkit-draw
@@ -44,7 +45,6 @@ skills:
44
45
  - pactkit-status
45
46
  - pactkit-trace
46
47
  - pactkit-visualize
47
- - pactkit-analyze
48
48
  - project-act
49
49
  - project-check
50
50
  - project-clarify
@@ -4,6 +4,31 @@ All notable changes to PactKit will be documented in this file.
4
4
 
5
5
  Format follows [Keep a Changelog](https://keepachangelog.com/).
6
6
 
7
+ ## [2.9.0] - 2026-03-28
8
+
9
+ ### Added
10
+ - **`pactkit init` deploys all IDEs by default** — `--format all` is now the CLI default, deploying Claude Code + OpenCode + Codex configs in one shot. No need to specify `--format` per IDE. Packaging modes (plugin, marketplace) excluded from "all".
11
+
12
+ ### Fixed
13
+ - **Entry_point deployer circular import** — Lazy-load entry_point deployers to fix `ValueError` when running `pactkit init` via pipx. Module-level `ep.load()` caused circular import between deployer.py and adapter packages.
14
+
15
+ ## [2.8.0] - 2026-03-27
16
+
17
+ ### Added
18
+ - **3-IDE default install** — `pip install pactkit` now installs all three IDE adapters (Claude Code + OpenCode + Codex) out of the box.
19
+
20
+ ### Fixed
21
+ - **OpenCode command architecture** — Reverted OpenCode from skills-only back to `commands/` + `skills/` dual architecture. OpenCode auto-discovers commands from `commands/*.md` (invoked via `/project-plan`), while embedded skills in `skills/` are loaded by AI agent on demand. `opencode.json` command entries now only contain model routing (no `template` field — it was incorrectly treated as file path, but is actually inline text).
22
+ - **Spec version confusion** — `/project-plan` Phase 3.2a no longer reads version from `pactkit.yaml` (PactKit toolkit version). Now explicitly reads from project's package manifest (`pyproject.toml`, `package.json`, `Cargo.toml`).
23
+ - **OpenCode path isolation** — All deployed OpenCode files reference `~/.config/opencode/` paths, CLI commands replaced with `python3 ~/.config/opencode/skills/*/scripts/*.py` invocations.
24
+ - **pactkit.yaml simplification** — Removed redundant component lists (agents/commands/skills/rules) from yaml template. Absence = deploy all from `VALID_*` sets. `pactkit doctor` drift check skips absent keys.
25
+
26
+ ### Changed
27
+ - **Cross-IDE command architecture**:
28
+ - Claude Code: skills-only (`skills/project-*/SKILL.md`), prefix `/`
29
+ - OpenCode: commands + skills (`commands/project-*.md` + `skills/pactkit-*/SKILL.md`), prefix `/`
30
+ - Codex: skills-only (`skills/project-*/SKILL.md`), prefix `$`
31
+
7
32
  ## [2.7.0] - 2026-03-27
8
33
 
9
34
  ### Added
@@ -1,6 +1,6 @@
1
1
  Metadata-Version: 2.4
2
2
  Name: pactkit
3
- Version: 2.7.0
3
+ Version: 2.9.0
4
4
  Summary: Spec-driven agentic DevOps toolkit for AI coding assistants
5
5
  Project-URL: Homepage, https://pactkit.dev
6
6
  Project-URL: Repository, https://github.com/pactkit/pactkit-public
@@ -21,7 +21,8 @@ Classifier: Programming Language :: Python :: 3.13
21
21
  Classifier: Topic :: Software Development :: Build Tools
22
22
  Classifier: Topic :: Software Development :: Quality Assurance
23
23
  Requires-Python: >=3.10
24
- Requires-Dist: pactkit-opencode>=2.6.0
24
+ Requires-Dist: pactkit-codex>=2.9.0
25
+ Requires-Dist: pactkit-opencode>=2.9.0
25
26
  Requires-Dist: pyyaml>=6.0
26
27
  Provides-Extra: multilang
27
28
  Requires-Dist: tree-sitter-go>=0.25; extra == 'multilang'
@@ -45,7 +46,7 @@ Description-Content-Type: text/markdown
45
46
 
46
47
  > **PactKit** (Pact 契约 + Kit) is a governance framework that enforces the **P.A.C.T.** contract between humans and AI agents. Deterministic operations run as code, not prompts. Decisions are grounded in data, not memory. AI does what it's best at — creativity and language — while code handles everything that must be repeatable and correct.
47
48
  >
48
- > 25 CLI subcommands, 9 specialized agents, 11 commands, 10 skills, and a full Plan-Act-Check-Done lifecycle. One `pip install` and your AI assistant follows the contract.
49
+ > 25 CLI subcommands, 9 specialized agents, 11 commands, 10 skills, and a full Plan-Act-Check-Done lifecycle. One `pip install` deploys to all 3 supported IDEs.
49
50
 
50
51
  ### Supported AI Tools
51
52
 
@@ -53,6 +54,7 @@ Description-Content-Type: text/markdown
53
54
  |------|--------|---------|
54
55
  | **Claude Code** | Classic | `pactkit init` |
55
56
  | **OpenCode** | OpenCode | `pactkit init --format opencode` |
57
+ | **Codex CLI** | Codex | `pactkit init --format codex` |
56
58
 
57
59
  ### What it looks like
58
60
 
@@ -89,7 +91,7 @@ T Truth Data is the Truth Factual basis for all judgment — no memory,
89
91
  - **Multi-Agent Ensemble** — 9 specialized agents collaborate, each with constrained tools
90
92
  - **Full PDCA Lifecycle** — Plan -> Act -> Check -> Done, with quality gates at every stage
91
93
  - **Safe by Design** — TDD-first, safe regression, pre-existing test protection
92
- - **Multi-Tool Support** — Works with Claude Code and OpenCode
94
+ - **Multi-Tool Support** — Works with Claude Code, OpenCode, and Codex CLI
93
95
 
94
96
  ## Installation
95
97
 
@@ -100,6 +102,9 @@ pip install pactkit
100
102
  Requires Python 3.10+ and one of:
101
103
  - [Claude Code](https://docs.anthropic.com/en/docs/claude-code)
102
104
  - [OpenCode](https://opencode.ai)
105
+ - [Codex CLI](https://github.com/openai/codex)
106
+
107
+ > `pip install pactkit` automatically installs adapters for all 3 IDEs.
103
108
 
104
109
  ## Quick Start
105
110
 
@@ -123,6 +128,16 @@ pactkit init --format opencode
123
128
  pactkit upgrade --format opencode
124
129
  ```
125
130
 
131
+ ### Codex CLI
132
+
133
+ ```bash
134
+ # Deploy to Codex CLI (global: ~/.codex/)
135
+ pactkit init --format codex
136
+
137
+ # Update existing deployment
138
+ pactkit-codex update
139
+ ```
140
+
126
141
  Then in any project:
127
142
 
128
143
  ```bash
@@ -277,7 +292,7 @@ PactKit ships 25 deterministic CLI subcommands — operations that were previous
277
292
 
278
293
  ## Deployment Architecture
279
294
 
280
- PactKit supports two deployment formats:
295
+ PactKit supports three deployment formats:
281
296
 
282
297
  ### Claude Code (Classic)
283
298
 
@@ -285,29 +300,38 @@ PactKit supports two deployment formats:
285
300
  ~/.claude/
286
301
  ├── CLAUDE.md <- Project context entry point
287
302
  ├── rules/ <- 8 rule modules (loaded per-command, not globally)
288
- ├── commands/ <- 11 command playbooks (with per-command rule @imports)
289
- ├── agents/ <- 9 agent definitions
290
- └── skills/ <- 10 skill packages
303
+ ├── skills/ <- 21 skill packages (11 commands + 10 embedded)
304
+ └── agents/ <- 9 agent definitions
291
305
  ```
292
306
 
307
+ Commands are deployed as skills (`skills/project-*/SKILL.md`), invoked with `/project-plan`.
308
+
293
309
  ### OpenCode
294
310
 
295
311
  ```
296
312
  ~/.config/opencode/
297
313
  ├── AGENTS.md <- On-demand @reference index (lazy rule loading)
298
314
  ├── rules/ <- 8 rule modules (3 core always-load + 6 on-demand)
299
- ├── commands/ <- 11 command playbooks (with model: routing)
315
+ ├── commands/ <- 11 command playbooks (auto-discovered, invoked via /)
300
316
  ├── agents/ <- 9 agent definitions (mode: subagent)
301
- ├── skills/ <- 10 skill packages (with SKILL.md frontmatter)
302
- └── opencode.json <- Global config (instructions, provider preserved)
317
+ ├── skills/ <- 10 skill packages (AI agent loads on demand)
318
+ └── opencode.json <- Global config (model routing, instructions)
319
+ ```
320
+
321
+ OpenCode uses dual mechanism: `commands/` for user-facing PDCA entry points, `skills/` for AI-invoked tools.
322
+
323
+ ### Codex CLI
324
+
325
+ ```
326
+ ~/.codex/
327
+ ├── AGENTS.md <- Global constitution
328
+ ├── config.toml <- Model, sandbox, MCP config
329
+ ├── rules/ <- 8 rule modules
330
+ ├── skills/ <- 21 skill packages (11 commands + 10 embedded)
331
+ └── .pactkit-version <- Version marker for updates
303
332
  ```
304
333
 
305
- Key OpenCode differences:
306
- - **Rules**: Per-command inline embedding; credential safety always loaded via `instructions` (context-aware loading, -20% to -83% tokens per command)
307
- - **Agents**: `mode: subagent`, no `name` field, tools as record format
308
- - **Commands**: `agent: build` + `model: provider/model-id` (model routing)
309
- - **Config**: `pactkit.yaml` in `.opencode/` (not `.claude/`)
310
- - **Model routing**: Commands auto-route to Sonnet for implementation, inherit main model for planning
334
+ Commands are deployed as skills (`skills/project-*/SKILL.md`), invoked with `$project-plan`.
311
335
 
312
336
  ## Multi-Developer Collaboration
313
337
 
@@ -399,6 +423,7 @@ All MCP instructions are conditional — gracefully skipped when unavailable.
399
423
  pip install --upgrade pactkit
400
424
  pactkit update # Claude Code
401
425
  pactkit upgrade --format opencode # OpenCode
426
+ pactkit-codex update # Codex CLI
402
427
  ```
403
428
 
404
429
  ## Contributing
@@ -13,7 +13,7 @@
13
13
 
14
14
  > **PactKit** (Pact 契约 + Kit) is a governance framework that enforces the **P.A.C.T.** contract between humans and AI agents. Deterministic operations run as code, not prompts. Decisions are grounded in data, not memory. AI does what it's best at — creativity and language — while code handles everything that must be repeatable and correct.
15
15
  >
16
- > 25 CLI subcommands, 9 specialized agents, 11 commands, 10 skills, and a full Plan-Act-Check-Done lifecycle. One `pip install` and your AI assistant follows the contract.
16
+ > 25 CLI subcommands, 9 specialized agents, 11 commands, 10 skills, and a full Plan-Act-Check-Done lifecycle. One `pip install` deploys to all 3 supported IDEs.
17
17
 
18
18
  ### Supported AI Tools
19
19
 
@@ -21,6 +21,7 @@
21
21
  |------|--------|---------|
22
22
  | **Claude Code** | Classic | `pactkit init` |
23
23
  | **OpenCode** | OpenCode | `pactkit init --format opencode` |
24
+ | **Codex CLI** | Codex | `pactkit init --format codex` |
24
25
 
25
26
  ### What it looks like
26
27
 
@@ -57,7 +58,7 @@ T Truth Data is the Truth Factual basis for all judgment — no memory,
57
58
  - **Multi-Agent Ensemble** — 9 specialized agents collaborate, each with constrained tools
58
59
  - **Full PDCA Lifecycle** — Plan -> Act -> Check -> Done, with quality gates at every stage
59
60
  - **Safe by Design** — TDD-first, safe regression, pre-existing test protection
60
- - **Multi-Tool Support** — Works with Claude Code and OpenCode
61
+ - **Multi-Tool Support** — Works with Claude Code, OpenCode, and Codex CLI
61
62
 
62
63
  ## Installation
63
64
 
@@ -68,6 +69,9 @@ pip install pactkit
68
69
  Requires Python 3.10+ and one of:
69
70
  - [Claude Code](https://docs.anthropic.com/en/docs/claude-code)
70
71
  - [OpenCode](https://opencode.ai)
72
+ - [Codex CLI](https://github.com/openai/codex)
73
+
74
+ > `pip install pactkit` automatically installs adapters for all 3 IDEs.
71
75
 
72
76
  ## Quick Start
73
77
 
@@ -91,6 +95,16 @@ pactkit init --format opencode
91
95
  pactkit upgrade --format opencode
92
96
  ```
93
97
 
98
+ ### Codex CLI
99
+
100
+ ```bash
101
+ # Deploy to Codex CLI (global: ~/.codex/)
102
+ pactkit init --format codex
103
+
104
+ # Update existing deployment
105
+ pactkit-codex update
106
+ ```
107
+
94
108
  Then in any project:
95
109
 
96
110
  ```bash
@@ -245,7 +259,7 @@ PactKit ships 25 deterministic CLI subcommands — operations that were previous
245
259
 
246
260
  ## Deployment Architecture
247
261
 
248
- PactKit supports two deployment formats:
262
+ PactKit supports three deployment formats:
249
263
 
250
264
  ### Claude Code (Classic)
251
265
 
@@ -253,29 +267,38 @@ PactKit supports two deployment formats:
253
267
  ~/.claude/
254
268
  ├── CLAUDE.md <- Project context entry point
255
269
  ├── rules/ <- 8 rule modules (loaded per-command, not globally)
256
- ├── commands/ <- 11 command playbooks (with per-command rule @imports)
257
- ├── agents/ <- 9 agent definitions
258
- └── skills/ <- 10 skill packages
270
+ ├── skills/ <- 21 skill packages (11 commands + 10 embedded)
271
+ └── agents/ <- 9 agent definitions
259
272
  ```
260
273
 
274
+ Commands are deployed as skills (`skills/project-*/SKILL.md`), invoked with `/project-plan`.
275
+
261
276
  ### OpenCode
262
277
 
263
278
  ```
264
279
  ~/.config/opencode/
265
280
  ├── AGENTS.md <- On-demand @reference index (lazy rule loading)
266
281
  ├── rules/ <- 8 rule modules (3 core always-load + 6 on-demand)
267
- ├── commands/ <- 11 command playbooks (with model: routing)
282
+ ├── commands/ <- 11 command playbooks (auto-discovered, invoked via /)
268
283
  ├── agents/ <- 9 agent definitions (mode: subagent)
269
- ├── skills/ <- 10 skill packages (with SKILL.md frontmatter)
270
- └── opencode.json <- Global config (instructions, provider preserved)
284
+ ├── skills/ <- 10 skill packages (AI agent loads on demand)
285
+ └── opencode.json <- Global config (model routing, instructions)
286
+ ```
287
+
288
+ OpenCode uses dual mechanism: `commands/` for user-facing PDCA entry points, `skills/` for AI-invoked tools.
289
+
290
+ ### Codex CLI
291
+
292
+ ```
293
+ ~/.codex/
294
+ ├── AGENTS.md <- Global constitution
295
+ ├── config.toml <- Model, sandbox, MCP config
296
+ ├── rules/ <- 8 rule modules
297
+ ├── skills/ <- 21 skill packages (11 commands + 10 embedded)
298
+ └── .pactkit-version <- Version marker for updates
271
299
  ```
272
300
 
273
- Key OpenCode differences:
274
- - **Rules**: Per-command inline embedding; credential safety always loaded via `instructions` (context-aware loading, -20% to -83% tokens per command)
275
- - **Agents**: `mode: subagent`, no `name` field, tools as record format
276
- - **Commands**: `agent: build` + `model: provider/model-id` (model routing)
277
- - **Config**: `pactkit.yaml` in `.opencode/` (not `.claude/`)
278
- - **Model routing**: Commands auto-route to Sonnet for implementation, inherit main model for planning
301
+ Commands are deployed as skills (`skills/project-*/SKILL.md`), invoked with `$project-plan`.
279
302
 
280
303
  ## Multi-Developer Collaboration
281
304
 
@@ -367,6 +390,7 @@ All MCP instructions are conditional — gracefully skipped when unavailable.
367
390
  pip install --upgrade pactkit
368
391
  pactkit update # Claude Code
369
392
  pactkit upgrade --format opencode # OpenCode
393
+ pactkit-codex update # Codex CLI
370
394
  ```
371
395
 
372
396
  ## Contributing
@@ -4,14 +4,15 @@ build-backend = "hatchling.build"
4
4
 
5
5
  [project]
6
6
  name = "pactkit"
7
- version = "2.7.0"
7
+ version = "2.9.0"
8
8
  description = "Spec-driven agentic DevOps toolkit for AI coding assistants"
9
9
  readme = "README.md"
10
10
  license = "MIT"
11
11
  requires-python = ">=3.10"
12
12
  dependencies = [
13
13
  "pyyaml>=6.0",
14
- "pactkit-opencode>=2.6.0",
14
+ "pactkit-opencode>=2.9.0",
15
+ "pactkit-codex>=2.9.0",
15
16
  ]
16
17
 
17
18
  authors = [
@@ -1,3 +1,3 @@
1
1
  """PactKit - Spec-driven agentic DevOps toolkit."""
2
2
 
3
- __version__ = "2.7.0"
3
+ __version__ = "2.9.0"
@@ -64,9 +64,9 @@ def main():
64
64
  init_parser.add_argument(
65
65
  "--format",
66
66
  type=str,
67
- choices=["classic", "plugin", "marketplace", "opencode"],
68
- default="classic",
69
- help="Output format: classic (default), plugin, marketplace, or opencode",
67
+ choices=["all", "classic", "plugin", "marketplace", "opencode", "codex"],
68
+ default="all",
69
+ help="Output format: all (default, deploy all installed IDEs), or a specific format",
70
70
  )
71
71
  init_parser.add_argument(
72
72
  "--agent",
@@ -107,9 +107,9 @@ def main():
107
107
  update_parser.add_argument(
108
108
  "--format",
109
109
  type=str,
110
- choices=["classic", "plugin", "marketplace", "opencode"],
111
- default="classic",
112
- help="Output format: classic (default), plugin, marketplace, or opencode",
110
+ choices=["all", "classic", "plugin", "marketplace", "opencode", "codex"],
111
+ default="all",
112
+ help="Output format: all (default, deploy all installed IDEs), or a specific format",
113
113
  )
114
114
  update_parser.add_argument(
115
115
  "--agent",
@@ -157,9 +157,9 @@ def main():
157
157
  upgrade_parser.add_argument(
158
158
  "--format",
159
159
  type=str,
160
- choices=["classic", "plugin", "marketplace", "opencode"],
161
- default="classic",
162
- help="Output format: classic (default), plugin, marketplace, or opencode",
160
+ choices=["all", "classic", "plugin", "marketplace", "opencode", "codex"],
161
+ default="all",
162
+ help="Output format: all (default, deploy all installed IDEs), or a specific format",
163
163
  )
164
164
  upgrade_parser.add_argument(
165
165
  "--agent",
@@ -448,14 +448,12 @@ def auto_merge_config_file(path: Union[Path, str]) -> list[str]:
448
448
  added: list[str] = []
449
449
 
450
450
  # --- List-type keys: merge new items ---
451
+ # If a list key is absent from yaml, it means "deploy all" (VALID_* default).
452
+ # Only merge if the user explicitly provides a list (opt-in customization).
451
453
  for key, valid_set in _REGISTRY.items():
452
454
  user_list = user_data.get(key)
453
455
  if user_list is None:
454
- # BUG-013: key missing from user yaml backfill full default list
455
- excluded_items = set(exclude.get(key, []) or [])
456
- new_items = sorted(item for item in valid_set if item not in excluded_items)
457
- user_data[key] = new_items
458
- added.append(f"section: {key}")
456
+ # Key absent = deploy all by default. No backfill needed.
459
457
  continue
460
458
  if not isinstance(user_list, list):
461
459
  continue
@@ -900,34 +898,14 @@ def generate_default_yaml() -> str:
900
898
  cfg = get_default_config()
901
899
  lines = [
902
900
  "# PactKit Configuration",
903
- "# Edit this file to customize which components are deployed.",
904
- "# Remove items from a list to disable them. Default: all enabled.",
901
+ "# All agents, commands, skills, and rules are deployed by default.",
902
+ "# To exclude specific items, add an exclude list (e.g., exclude_skills: [pactkit-draw]).",
905
903
  "",
906
904
  f'version: "{cfg["version"]}"',
907
905
  f"stack: {cfg['stack']}",
908
906
  f"root: {cfg['root']}",
909
907
  f'developer: "{cfg["developer"]}"',
910
- "",
911
- "# Agents — AI role definitions",
912
- "agents:",
913
908
  ]
914
- for a in cfg["agents"]:
915
- lines.append(f" - {a}")
916
-
917
- lines.extend(["", "# Commands — PDCA playbooks"])
918
- lines.append("commands:")
919
- for c in cfg["commands"]:
920
- lines.append(f" - {c}")
921
-
922
- lines.extend(["", "# Skills — tool scripts"])
923
- lines.append("skills:")
924
- for s in cfg["skills"]:
925
- lines.append(f" - {s}")
926
-
927
- lines.extend(["", "# Rules — constitution modules"])
928
- lines.append("rules:")
929
- for r in cfg["rules"]:
930
- lines.append(f" - {r}")
931
909
 
932
910
  ci = cfg.get("ci", {})
933
911
  lines.extend(["", "# CI/CD — set provider to github or gitlab to generate pipeline config"])
@@ -55,6 +55,10 @@ def check_orphaned_specs(project_root: Path) -> dict:
55
55
  def check_config_drift(project_root: Path) -> dict:
56
56
  """Compare pactkit.yaml declared items vs deployed files.
57
57
 
58
+ Only checks deployment drift when the yaml explicitly declares
59
+ component lists (agents, commands, skills, rules). Default behavior
60
+ (no lists) means "deploy all from VALID_* sets" — no drift possible.
61
+
58
62
  Returns:
59
63
  {"missing_deployments": [{"type": ..., "name": ...}]}
60
64
  """
@@ -69,33 +73,32 @@ def check_config_drift(project_root: Path) -> dict:
69
73
  with open(yaml_path, encoding="utf-8") as f:
70
74
  data = yaml.safe_load(f) or {}
71
75
 
72
- config_dir = yaml_path.parent # .claude/ or .opencode/
76
+ config_dir = yaml_path.parent # .claude/ or .opencode/ or .codex/
73
77
  missing: list[dict] = []
74
78
 
75
- # Check agents
76
- for agent in data.get("agents", []):
77
- agent_file = config_dir / "agents" / f"{agent}.md"
78
- if not agent_file.exists():
79
- missing.append({"type": "agent", "name": agent})
80
-
81
- # Check commands
82
- for cmd in data.get("commands", []):
83
- cmd_file = config_dir / "commands" / f"{cmd}.md"
84
- if not cmd_file.exists():
85
- missing.append({"type": "command", "name": cmd})
86
-
87
- # Check skills
88
- for skill in data.get("skills", []):
89
- skill_dir = config_dir / "skills" / skill
90
- skill_file = config_dir / "skills" / f"{skill}.md"
91
- if not skill_dir.is_dir() and not skill_file.exists():
92
- missing.append({"type": "skill", "name": skill})
93
-
94
- # Check rules
95
- for rule in data.get("rules", []):
96
- rule_file = config_dir / "rules" / f"{rule}.md"
97
- if not rule_file.exists():
98
- missing.append({"type": "rule", "name": rule})
79
+ # Only check drift for explicitly declared lists.
80
+ # If the key is absent, it means "deploy all" — no drift to check.
81
+ _CHECKS = [
82
+ ("agents", "agents", ".md"),
83
+ ("commands", "commands", ".md"),
84
+ ("rules", "rules", ".md"),
85
+ ]
86
+ for key, subdir, suffix in _CHECKS:
87
+ declared = data.get(key)
88
+ if not isinstance(declared, list):
89
+ continue
90
+ for item in declared:
91
+ if not (config_dir / subdir / f"{item}{suffix}").exists():
92
+ missing.append({"type": key.rstrip("s"), "name": item})
93
+
94
+ # Skills: check as directory or .md file
95
+ declared_skills = data.get("skills")
96
+ if isinstance(declared_skills, list):
97
+ for skill in declared_skills:
98
+ skill_dir = config_dir / "skills" / skill
99
+ skill_file = config_dir / "skills" / f"{skill}.md"
100
+ if not skill_dir.is_dir() and not skill_file.exists():
101
+ missing.append({"type": "skill", "name": skill})
99
102
 
100
103
  return {"missing_deployments": missing}
101
104
 
@@ -204,16 +204,28 @@ def _load_entry_point_deployers():
204
204
  eps = entry_points(group="pactkit.deployers")
205
205
  for ep in eps:
206
206
  if ep.name in _DEPLOYER_REGISTRY:
207
- continue # built-in or already registered
207
+ continue # built-in or already loaded via self-registration
208
208
  try:
209
209
  deployer_cls = ep.load()
210
- register_deployer(ep.name, deployer_cls)
210
+ # ep.load() may trigger adapter's self-registration (force=True).
211
+ # Re-check registry — adapter may have registered itself during import.
212
+ if ep.name not in _DEPLOYER_REGISTRY:
213
+ register_deployer(ep.name, deployer_cls)
211
214
  except Exception:
212
215
  pass # graceful degradation — adapter package may be broken
213
216
 
214
217
 
215
- # Auto-discover adapter packages at import time
216
- _load_entry_point_deployers()
218
+ # Lazy discovery: avoid module-level ep.load() which triggers circular imports
219
+ # when adapter packages (pactkit-opencode, pactkit-codex) import from deployer.py.
220
+ _ep_loaded = False
221
+
222
+
223
+ def _ensure_entry_point_deployers():
224
+ """Lazy wrapper — loads entry_point deployers on first deploy() call."""
225
+ global _ep_loaded
226
+ if not _ep_loaded:
227
+ _load_entry_point_deployers()
228
+ _ep_loaded = True
217
229
 
218
230
 
219
231
  def deploy(
@@ -224,15 +236,33 @@ def deploy(
224
236
 
225
237
  Args:
226
238
  config: Optional config dict. If None, loads from pactkit.yaml or defaults.
227
- target: Optional target directory. If None, uses ~/.claude (classic) or
228
- ./pactkit-plugin (plugin) or ./pactkit-marketplace (marketplace).
229
- format: Output format — 'classic', 'plugin', or 'marketplace'.
239
+ target: Optional target directory. If None, uses format-specific default.
240
+ format: Output format — 'classic' (default for Python API), 'all'
241
+ (deploy all installed IDEs, CLI default), or a specific format
242
+ ('opencode', 'codex', 'plugin', 'marketplace').
230
243
  agent: Target agent format (claude, cursor, copilot, generic, all).
231
244
  no_git: Disable all git operations (enterprise: air-gapped environments).
232
245
  no_external: Disable external network calls (enterprise).
233
246
  non_interactive: Non-interactive mode: auto-accept defaults (CI/CD).
234
247
  mode: Deprecated, ignored. Kept for backward compatibility.
235
248
  """
249
+ _ensure_entry_point_deployers()
250
+
251
+ # "all" deploys every IDE environment (classic + installed adapters).
252
+ # Skips packaging modes (plugin, marketplace) — those are distribution
253
+ # formats, not IDE targets.
254
+ _PACKAGING_MODES = {"plugin", "marketplace"}
255
+ if format == "all":
256
+ for fmt_name in sorted(_DEPLOYER_REGISTRY):
257
+ if fmt_name in _PACKAGING_MODES:
258
+ continue
259
+ deployer_cls = _DEPLOYER_REGISTRY[fmt_name]
260
+ deployer_instance = deployer_cls()
261
+ # Classic respects -t target; adapters always deploy to their own default
262
+ fmt_target = target if fmt_name == "classic" else None
263
+ deployer_instance.deploy(config=config, target=fmt_target)
264
+ return
265
+
236
266
  if format not in VALID_FORMATS:
237
267
  raise ValueError(f"Unknown format: {format!r}. Valid: {', '.join(VALID_FORMATS)}")
238
268
 
@@ -301,10 +331,10 @@ def _deploy_classic(config=None, target=None):
301
331
  d.mkdir(parents=True, exist_ok=True)
302
332
 
303
333
  # Deploy components filtered by config
304
- enabled_skills = config.get("skills", [])
305
- enabled_rules = config.get("rules", [])
306
- enabled_agents = config.get("agents", [])
307
- enabled_commands = config.get("commands", [])
334
+ enabled_skills = config.get("skills", sorted(VALID_SKILLS))
335
+ enabled_rules = config.get("rules", sorted(VALID_RULES))
336
+ enabled_agents = config.get("agents", sorted(VALID_AGENTS))
337
+ enabled_commands = config.get("commands", sorted(VALID_COMMANDS))
308
338
 
309
339
  classic_profile = get_profile("classic")
310
340
  n_skills = _deploy_skills(skills_dir, enabled_skills, profile=classic_profile)
@@ -171,8 +171,8 @@ FORMAT_PROFILES: dict[str, FormatProfile] = {
171
171
  # Deployment modes that are not environment formats
172
172
  _DEPLOYMENT_MODES: frozenset[str] = frozenset({"plugin", "marketplace"})
173
173
 
174
- # All valid --format values: environment profiles + deployment modes
175
- VALID_FORMATS: frozenset[str] = frozenset(FORMAT_PROFILES.keys()) | _DEPLOYMENT_MODES
174
+ # All valid --format values: "all" + environment profiles + deployment modes
175
+ VALID_FORMATS: frozenset[str] = frozenset({"all"}) | frozenset(FORMAT_PROFILES.keys()) | _DEPLOYMENT_MODES
176
176
 
177
177
  # Ordered candidate paths for pactkit.yaml discovery (first existing wins)
178
178
  # Order = preference: OpenCode > Codex > Classic