agentic-project-kit 1.0.1__py3-none-any.whl

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 (310) hide show
  1. agentic_project_kit/__init__.py +1 -0
  2. agentic_project_kit/absolute_path_portability_audit.py +241 -0
  3. agentic_project_kit/access_level_policy.py +14 -0
  4. agentic_project_kit/access_levels.py +22 -0
  5. agentic_project_kit/action_registry.py +195 -0
  6. agentic_project_kit/action_specs.py +286 -0
  7. agentic_project_kit/agent_command_runner.py +516 -0
  8. agentic_project_kit/audit_test_matrix.py +36 -0
  9. agentic_project_kit/audit_test_matrix_cli.py +43 -0
  10. agentic_project_kit/chat_bootloader.py +257 -0
  11. agentic_project_kit/chat_entrypoint_contract.py +297 -0
  12. agentic_project_kit/checks.py +511 -0
  13. agentic_project_kit/ci_readiness.py +211 -0
  14. agentic_project_kit/cli.py +147 -0
  15. agentic_project_kit/cli_commands/__init__.py +1 -0
  16. agentic_project_kit/cli_commands/absolute_path_audit.py +25 -0
  17. agentic_project_kit/cli_commands/actions.py +21 -0
  18. agentic_project_kit/cli_commands/artifact_gc.py +240 -0
  19. agentic_project_kit/cli_commands/boot.py +55 -0
  20. agentic_project_kit/cli_commands/chat.py +34 -0
  21. agentic_project_kit/cli_commands/checks.py +305 -0
  22. agentic_project_kit/cli_commands/cockpit.py +103 -0
  23. agentic_project_kit/cli_commands/command_taxonomy.py +25 -0
  24. agentic_project_kit/cli_commands/commands.py +129 -0
  25. agentic_project_kit/cli_commands/dev.py +23 -0
  26. agentic_project_kit/cli_commands/direction.py +92 -0
  27. agentic_project_kit/cli_commands/doc_currency_audit.py +25 -0
  28. agentic_project_kit/cli_commands/doc_registry.py +126 -0
  29. agentic_project_kit/cli_commands/docs.py +223 -0
  30. agentic_project_kit/cli_commands/dpa.py +1338 -0
  31. agentic_project_kit/cli_commands/evidence.py +251 -0
  32. agentic_project_kit/cli_commands/github.py +34 -0
  33. agentic_project_kit/cli_commands/governance.py +14 -0
  34. agentic_project_kit/cli_commands/gui.py +23 -0
  35. agentic_project_kit/cli_commands/gui_readiness_gate.py +27 -0
  36. agentic_project_kit/cli_commands/handoff.py +183 -0
  37. agentic_project_kit/cli_commands/human_workflows.py +430 -0
  38. agentic_project_kit/cli_commands/init.py +132 -0
  39. agentic_project_kit/cli_commands/instruction.py +75 -0
  40. agentic_project_kit/cli_commands/mutation_lock_audit.py +24 -0
  41. agentic_project_kit/cli_commands/ns_legacy_audit.py +25 -0
  42. agentic_project_kit/cli_commands/pass_already_done.py +66 -0
  43. agentic_project_kit/cli_commands/patch_failure_discipline_audit.py +26 -0
  44. agentic_project_kit/cli_commands/patch_preflight.py +37 -0
  45. agentic_project_kit/cli_commands/path_literal_audit.py +39 -0
  46. agentic_project_kit/cli_commands/patterns.py +40 -0
  47. agentic_project_kit/cli_commands/planning_docs_audit.py +25 -0
  48. agentic_project_kit/cli_commands/pr.py +133 -0
  49. agentic_project_kit/cli_commands/pr_hygiene.py +27 -0
  50. agentic_project_kit/cli_commands/profiles.py +26 -0
  51. agentic_project_kit/cli_commands/program_redundancy_audit.py +25 -0
  52. agentic_project_kit/cli_commands/project_direction.py +25 -0
  53. agentic_project_kit/cli_commands/release.py +392 -0
  54. agentic_project_kit/cli_commands/release_publish_orchestration.py +36 -0
  55. agentic_project_kit/cli_commands/remote_branch_hygiene.py +152 -0
  56. agentic_project_kit/cli_commands/remote_next.py +57 -0
  57. agentic_project_kit/cli_commands/removed_ns_commands.py +65 -0
  58. agentic_project_kit/cli_commands/rule_registry.py +129 -0
  59. agentic_project_kit/cli_commands/rules.py +222 -0
  60. agentic_project_kit/cli_commands/scaffold.py +46 -0
  61. agentic_project_kit/cli_commands/slice.py +21 -0
  62. agentic_project_kit/cli_commands/standard_gates_audit_suite.py +27 -0
  63. agentic_project_kit/cli_commands/state.py +51 -0
  64. agentic_project_kit/cli_commands/status_current_state_audit.py +30 -0
  65. agentic_project_kit/cli_commands/todo.py +53 -0
  66. agentic_project_kit/cli_commands/transfer.py +19 -0
  67. agentic_project_kit/cli_commands/transfer_context_flow.py +398 -0
  68. agentic_project_kit/cli_commands/transfer_context_helpers.py +398 -0
  69. agentic_project_kit/cli_commands/transfer_diagnostics.py +767 -0
  70. agentic_project_kit/cli_commands/transfer_evidence_flow.py +368 -0
  71. agentic_project_kit/cli_commands/transfer_handoff_flow.py +594 -0
  72. agentic_project_kit/cli_commands/transfer_order_contract.py +74 -0
  73. agentic_project_kit/cli_commands/transfer_post_merge_complete.py +442 -0
  74. agentic_project_kit/cli_commands/transfer_post_merge_settle.py +171 -0
  75. agentic_project_kit/cli_commands/transfer_pr_closeout_complete.py +124 -0
  76. agentic_project_kit/cli_commands/transfer_pr_create_flow.py +743 -0
  77. agentic_project_kit/cli_commands/transfer_pr_merge_flow.py +547 -0
  78. agentic_project_kit/cli_commands/transfer_repo_after_pr.py +160 -0
  79. agentic_project_kit/cli_commands/transfer_repo_pre_pr.py +664 -0
  80. agentic_project_kit/cli_commands/transfer_runner_flow.py +131 -0
  81. agentic_project_kit/cli_commands/transfer_runtime_initial.py +194 -0
  82. agentic_project_kit/cli_commands/transfer_shared.py +274 -0
  83. agentic_project_kit/cli_commands/validation.py +200 -0
  84. agentic_project_kit/cli_commands/version.py +27 -0
  85. agentic_project_kit/cli_commands/work_orders.py +219 -0
  86. agentic_project_kit/cli_commands/workflow.py +471 -0
  87. agentic_project_kit/cli_commands/workflow_guard.py +26 -0
  88. agentic_project_kit/cli_commands/workspace.py +252 -0
  89. agentic_project_kit/cockpit.py +608 -0
  90. agentic_project_kit/cockpit_readiness.py +67 -0
  91. agentic_project_kit/command_authority_audit.py +192 -0
  92. agentic_project_kit/command_inbox_check.py +103 -0
  93. agentic_project_kit/command_manifest.py +591 -0
  94. agentic_project_kit/command_queue_contract.py +161 -0
  95. agentic_project_kit/command_selector.py +245 -0
  96. agentic_project_kit/command_taxonomy.py +264 -0
  97. agentic_project_kit/commit_guard.py +67 -0
  98. agentic_project_kit/communication_artifact_gc.py +495 -0
  99. agentic_project_kit/communication_rule_context.py +437 -0
  100. agentic_project_kit/communication_state.py +115 -0
  101. agentic_project_kit/composed_wrapper_invariants.py +97 -0
  102. agentic_project_kit/composite_short_circuit.py +140 -0
  103. agentic_project_kit/contract.py +251 -0
  104. agentic_project_kit/control_state.py +83 -0
  105. agentic_project_kit/doc_currency_audit.py +536 -0
  106. agentic_project_kit/doc_lifecycle.py +1179 -0
  107. agentic_project_kit/doc_lifecycle_signals.py +446 -0
  108. agentic_project_kit/doc_lifecycle_sweep.py +639 -0
  109. agentic_project_kit/doc_mesh.py +491 -0
  110. agentic_project_kit/doctor.py +379 -0
  111. agentic_project_kit/documentation_registry.py +1122 -0
  112. agentic_project_kit/documentation_system_audit.py +310 -0
  113. agentic_project_kit/dpa_current_handoff_lifecycle.py +549 -0
  114. agentic_project_kit/dpa_dp2_decision_readiness.py +362 -0
  115. agentic_project_kit/dpa_dp3_dp4_adjudication.py +604 -0
  116. agentic_project_kit/dpa_dp5_block_new_gate.py +294 -0
  117. agentic_project_kit/dpa_dp5_stage_adoption.py +615 -0
  118. agentic_project_kit/dpa_dp5_strict_gate.py +187 -0
  119. agentic_project_kit/dpa_final_closeout.py +627 -0
  120. agentic_project_kit/dpa_fixture_evidence.py +680 -0
  121. agentic_project_kit/dpa_maintainer_record_check.py +711 -0
  122. agentic_project_kit/dpa_post_dp2_scope_assessment.py +734 -0
  123. agentic_project_kit/dpa_probe_002_readiness.py +509 -0
  124. agentic_project_kit/dpa_probe_003_readiness.py +417 -0
  125. agentic_project_kit/dpa_probe_004_readiness.py +437 -0
  126. agentic_project_kit/dpa_readiness.py +505 -0
  127. agentic_project_kit/dpa_readonly_probe_execution.py +500 -0
  128. agentic_project_kit/dpa_registry_contracts.py +312 -0
  129. agentic_project_kit/dpa_renderer_readiness.py +407 -0
  130. agentic_project_kit/dpa_repo_adoption_assessment.py +574 -0
  131. agentic_project_kit/dpa_stable_readiness.py +743 -0
  132. agentic_project_kit/dpa_successor_projection.py +168 -0
  133. agentic_project_kit/dpa_workspace_init_projection.py +93 -0
  134. agentic_project_kit/dpa_wrt_ch001_evidence.py +327 -0
  135. agentic_project_kit/entrypoint_slice_runner.py +153 -0
  136. agentic_project_kit/evidence_clean.py +152 -0
  137. agentic_project_kit/evidence_commit_paths.py +214 -0
  138. agentic_project_kit/evidence_finalize_log.py +204 -0
  139. agentic_project_kit/evidence_guard.py +114 -0
  140. agentic_project_kit/evidence_inspector.py +507 -0
  141. agentic_project_kit/evidence_state_contract.py +99 -0
  142. agentic_project_kit/execution_mode_state.py +148 -0
  143. agentic_project_kit/final_summary_contract.py +85 -0
  144. agentic_project_kit/finalize_guard.py +139 -0
  145. agentic_project_kit/gatekeeper_core.py +232 -0
  146. agentic_project_kit/github.py +25 -0
  147. agentic_project_kit/governance.py +59 -0
  148. agentic_project_kit/gui_action_execution.py +105 -0
  149. agentic_project_kit/gui_action_renderer.py +81 -0
  150. agentic_project_kit/gui_action_run_intent.py +98 -0
  151. agentic_project_kit/gui_action_views.py +195 -0
  152. agentic_project_kit/gui_activity_log.py +76 -0
  153. agentic_project_kit/gui_button_catalog.py +605 -0
  154. agentic_project_kit/gui_cockpit.py +365 -0
  155. agentic_project_kit/gui_cockpit_actions.py +695 -0
  156. agentic_project_kit/gui_cockpit_common.py +172 -0
  157. agentic_project_kit/gui_cockpit_header.py +501 -0
  158. agentic_project_kit/gui_cockpit_sidebar.py +387 -0
  159. agentic_project_kit/gui_cockpit_task.py +748 -0
  160. agentic_project_kit/gui_command_projection.py +355 -0
  161. agentic_project_kit/gui_communication_modes.py +130 -0
  162. agentic_project_kit/gui_dry_run.py +219 -0
  163. agentic_project_kit/gui_gatekeeper_status.py +259 -0
  164. agentic_project_kit/gui_layout_plan.py +148 -0
  165. agentic_project_kit/gui_open_folder.py +18 -0
  166. agentic_project_kit/gui_output_status_panel.py +61 -0
  167. agentic_project_kit/gui_panel_state.py +47 -0
  168. agentic_project_kit/gui_presenter.py +62 -0
  169. agentic_project_kit/gui_readiness_gate.py +206 -0
  170. agentic_project_kit/gui_release_flow.py +59 -0
  171. agentic_project_kit/gui_task_editor.py +1077 -0
  172. agentic_project_kit/gui_tk_widgets.py +177 -0
  173. agentic_project_kit/gui_tkinter_renderer.py +87 -0
  174. agentic_project_kit/gui_tkinter_shell.py +1176 -0
  175. agentic_project_kit/gui_transfer_contract.py +28 -0
  176. agentic_project_kit/gui_viewmodel.py +698 -0
  177. agentic_project_kit/gui_window_guard.py +46 -0
  178. agentic_project_kit/handoff_freshness.py +390 -0
  179. agentic_project_kit/handoff_prompt.py +180 -0
  180. agentic_project_kit/handoff_state.py +254 -0
  181. agentic_project_kit/instruction_lint.py +455 -0
  182. agentic_project_kit/llm_context_carriers.py +66 -0
  183. agentic_project_kit/llm_execution_context.py +285 -0
  184. agentic_project_kit/local_command_stack.py +133 -0
  185. agentic_project_kit/local_feature_gate.py +82 -0
  186. agentic_project_kit/local_garbage_collector.py +269 -0
  187. agentic_project_kit/models.py +18 -0
  188. agentic_project_kit/mutation_lock_audit.py +421 -0
  189. agentic_project_kit/next_turn_evidence.py +253 -0
  190. agentic_project_kit/next_turn_merge_if_green.py +459 -0
  191. agentic_project_kit/next_turn_pr_status.py +255 -0
  192. agentic_project_kit/next_turn_result.py +183 -0
  193. agentic_project_kit/next_turn_runner.py +159 -0
  194. agentic_project_kit/next_turn_slot.py +107 -0
  195. agentic_project_kit/next_turn_status.py +274 -0
  196. agentic_project_kit/ns_legacy_reference_audit.py +258 -0
  197. agentic_project_kit/ns_slice_runner.py +16 -0
  198. agentic_project_kit/operational_handoff_projection.py +124 -0
  199. agentic_project_kit/output_contract.py +80 -0
  200. agentic_project_kit/output_repair.py +61 -0
  201. agentic_project_kit/pass_already_done.py +216 -0
  202. agentic_project_kit/patch_artifact_preflight.py +147 -0
  203. agentic_project_kit/patch_cycle_workflow.py +440 -0
  204. agentic_project_kit/patch_failure_discipline_audit.py +223 -0
  205. agentic_project_kit/patch_preflight.py +215 -0
  206. agentic_project_kit/path_literal_audit.py +612 -0
  207. agentic_project_kit/patterns.py +99 -0
  208. agentic_project_kit/planning_docs_consolidation_audit.py +313 -0
  209. agentic_project_kit/portability_shell_gate.py +40 -0
  210. agentic_project_kit/post_merge_handoff_refresh.py +56 -0
  211. agentic_project_kit/post_release.py +252 -0
  212. agentic_project_kit/post_release_closeout.py +616 -0
  213. agentic_project_kit/pr_cleanup.py +172 -0
  214. agentic_project_kit/pr_closeout.py +50 -0
  215. agentic_project_kit/pr_closeout_complete.py +344 -0
  216. agentic_project_kit/pr_create_or_skip.py +71 -0
  217. agentic_project_kit/pr_hygiene.py +210 -0
  218. agentic_project_kit/program_redundancy_audit.py +251 -0
  219. agentic_project_kit/project_direction.py +840 -0
  220. agentic_project_kit/protected_change_planner.py +194 -0
  221. agentic_project_kit/release.py +401 -0
  222. agentic_project_kit/release_doi_safety.py +24 -0
  223. agentic_project_kit/release_gate_core.py +174 -0
  224. agentic_project_kit/release_metadata_authority_gate.py +328 -0
  225. agentic_project_kit/release_metadata_prep.py +43 -0
  226. agentic_project_kit/release_notes.py +823 -0
  227. agentic_project_kit/release_prep_core.py +204 -0
  228. agentic_project_kit/release_prepare.py +369 -0
  229. agentic_project_kit/release_process_guardrails.py +247 -0
  230. agentic_project_kit/release_publish_core.py +114 -0
  231. agentic_project_kit/release_publish_orchestration.py +469 -0
  232. agentic_project_kit/release_state.py +552 -0
  233. agentic_project_kit/release_verify_core.py +175 -0
  234. agentic_project_kit/remote_branch_hygiene.py +223 -0
  235. agentic_project_kit/remote_next.py +89 -0
  236. agentic_project_kit/remote_next_closeout.py +101 -0
  237. agentic_project_kit/remote_next_order_contract.py +391 -0
  238. agentic_project_kit/removed_ns_commands.py +458 -0
  239. agentic_project_kit/removed_source_audit.py +225 -0
  240. agentic_project_kit/rendering.py +13 -0
  241. agentic_project_kit/repair_report.py +79 -0
  242. agentic_project_kit/repo_identity.py +59 -0
  243. agentic_project_kit/result_report_classifier.py +57 -0
  244. agentic_project_kit/rule_ack.py +105 -0
  245. agentic_project_kit/rule_preservation.py +58 -0
  246. agentic_project_kit/rule_refresh.py +174 -0
  247. agentic_project_kit/rule_registry_registration.py +322 -0
  248. agentic_project_kit/rule_registry_report.py +206 -0
  249. agentic_project_kit/rule_registry_validator.py +704 -0
  250. agentic_project_kit/rule_snapshot.py +98 -0
  251. agentic_project_kit/rule_source_validator.py +133 -0
  252. agentic_project_kit/run_summary.py +68 -0
  253. agentic_project_kit/run_summary_renderer.py +238 -0
  254. agentic_project_kit/runtime_validator.py +68 -0
  255. agentic_project_kit/safe_file_replace.py +35 -0
  256. agentic_project_kit/safe_patch.py +47 -0
  257. agentic_project_kit/safe_push.py +218 -0
  258. agentic_project_kit/safe_remove_diagnostic.py +51 -0
  259. agentic_project_kit/scaffold.py +69 -0
  260. agentic_project_kit/site_claims.py +444 -0
  261. agentic_project_kit/site_generator.py +1140 -0
  262. agentic_project_kit/slice_gate.py +225 -0
  263. agentic_project_kit/slice_runner.py +75 -0
  264. agentic_project_kit/standard_gates_audit_suite.py +167 -0
  265. agentic_project_kit/state_freshness.py +135 -0
  266. agentic_project_kit/status_current_state_audit.py +762 -0
  267. agentic_project_kit/successor_handoff_package.py +1763 -0
  268. agentic_project_kit/templates.py +292 -0
  269. agentic_project_kit/terminal_block_guard.py +166 -0
  270. agentic_project_kit/terminal_logging.py +275 -0
  271. agentic_project_kit/todo.py +97 -0
  272. agentic_project_kit/transfer_closeout.py +136 -0
  273. agentic_project_kit/transfer_continue.py +215 -0
  274. agentic_project_kit/transfer_local_runner.py +101 -0
  275. agentic_project_kit/transfer_operation_monitor.py +236 -0
  276. agentic_project_kit/transfer_post_merge_lifecycle.py +356 -0
  277. agentic_project_kit/transfer_post_merge_settle.py +383 -0
  278. agentic_project_kit/transfer_pr_actions.py +164 -0
  279. agentic_project_kit/transfer_remote_next.py +959 -0
  280. agentic_project_kit/transfer_repo_actions.py +2253 -0
  281. agentic_project_kit/transfer_runner.py +347 -0
  282. agentic_project_kit/transfer_safety_context.py +291 -0
  283. agentic_project_kit/transfer_state.py +483 -0
  284. agentic_project_kit/transfer_uplink.py +471 -0
  285. agentic_project_kit/transfer_workflow_next.py +148 -0
  286. agentic_project_kit/typed_work_order_evidence.py +58 -0
  287. agentic_project_kit/typed_work_order_queue.py +166 -0
  288. agentic_project_kit/typed_work_order_runner.py +168 -0
  289. agentic_project_kit/work_cycle.py +317 -0
  290. agentic_project_kit/work_discard_changes.py +129 -0
  291. agentic_project_kit/work_order_patch.py +199 -0
  292. agentic_project_kit/work_order_runner.py +120 -0
  293. agentic_project_kit/work_order_uploader.py +220 -0
  294. agentic_project_kit/work_order_validator.py +185 -0
  295. agentic_project_kit/work_orders.py +246 -0
  296. agentic_project_kit/workflow_guard.py +262 -0
  297. agentic_project_kit/workflow_summary_runner.py +124 -0
  298. agentic_project_kit/workspace.py +665 -0
  299. agentic_project_kit/workspace_adopt.py +471 -0
  300. agentic_project_kit/workspace_dpa_intake.py +406 -0
  301. agentic_project_kit/workspace_init.py +487 -0
  302. agentic_project_kit/workspace_lock.py +129 -0
  303. agentic_project_kit/workspace_remove.py +381 -0
  304. agentic_project_kit/workspace_upgrade.py +324 -0
  305. agentic_project_kit/wrapper_live_status.py +104 -0
  306. agentic_project_kit-1.0.1.dist-info/METADATA +724 -0
  307. agentic_project_kit-1.0.1.dist-info/RECORD +310 -0
  308. agentic_project_kit-1.0.1.dist-info/WHEEL +4 -0
  309. agentic_project_kit-1.0.1.dist-info/entry_points.txt +3 -0
  310. agentic_project_kit-1.0.1.dist-info/licenses/LICENSE +10 -0
@@ -0,0 +1,591 @@
1
+ from __future__ import annotations
2
+
3
+ import hashlib
4
+ import json
5
+ from dataclasses import asdict, dataclass
6
+ from pathlib import Path
7
+ from typing import Any
8
+
9
+ from typer.main import get_command
10
+
11
+ from agentic_project_kit.workspace import LEGACY_DEFAULTS, load_workspace
12
+
13
+ JSON_PATH = Path(LEGACY_DEFAULTS.reference_root) / "agentic-kit-commands.json"
14
+ MD_PATH = Path(LEGACY_DEFAULTS.reference_root) / "AGENTIC_KIT_COMMANDS.md"
15
+ SAFETY_VALUES = {"READ_ONLY", "BOUNDED", "DESTRUCTIVE"}
16
+ SURFACE_VALUES = {"orchestrator", "diagnostic", "primitive"}
17
+
18
+ RAW_REPLACEMENTS: dict[str, tuple[str, ...]] = {
19
+ "agentic-kit transfer push-current": ("git push",),
20
+ "agentic-kit transfer commit": ("git commit",),
21
+ "agentic-kit transfer branch-create": ("git switch -c", "git checkout -b"),
22
+ "agentic-kit transfer pr-create-complete": ("gh pr create",),
23
+ "agentic-kit transfer pr-merge-safe": ("gh pr merge",),
24
+ "agentic-kit transfer delete-merged-work-branch": ("git push --delete", "git branch -D"),
25
+ "agentic-kit release ready": ("git tag", "gh release create"),
26
+ }
27
+
28
+ LIFECYCLE_RANKS: dict[str, int] = {
29
+ "agentic-kit init": 0,
30
+ "agentic-kit workspace adopt": 10,
31
+ "agentic-kit workspace init": 20,
32
+ "agentic-kit workspace dpa-intake": 21,
33
+ "agentic-kit workspace upgrade": 25,
34
+ "agentic-kit work start": 30,
35
+ "agentic-kit work recover": 35,
36
+ "agentic-kit workflow go": 40,
37
+ "agentic-kit transfer remote-work-start": 45,
38
+ "agentic-kit transfer remote-next": 46,
39
+ "agentic-kit work finish": 50,
40
+ "agentic-kit transfer pr-create-complete": 55,
41
+ "agentic-kit transfer pr-complete": 56,
42
+ "agentic-kit transfer pr-closeout-complete": 57,
43
+ "agentic-kit transfer post-merge-settle": 60,
44
+ "agentic-kit transfer post-merge-complete": 61,
45
+ "agentic-kit transfer chat-switch-complete": 62,
46
+ "agentic-kit transfer admin-refresh-pr": 63,
47
+ "agentic-kit release ready": 70,
48
+ "agentic-kit release prepare": 71,
49
+ "agentic-kit release-prep": 72,
50
+ "agentic-kit release-publish": 73,
51
+ "agentic-kit post-release-doi-closeout": 74,
52
+ "agentic-kit docs lifecycle sweep": 80,
53
+ "agentic-kit dpa final-closeout-check": 90,
54
+ "agentic-kit workspace remove": 95,
55
+ "agentic-kit artifact-gc": 100,
56
+ "agentic-kit github-create": 110,
57
+ }
58
+
59
+
60
+ @dataclass(frozen=True)
61
+ class CommandManifestFinding:
62
+ severity: str
63
+ code: str
64
+ message: str
65
+
66
+ def as_dict(self) -> dict[str, str]:
67
+ return asdict(self)
68
+
69
+
70
+ @dataclass(frozen=True)
71
+ class CommandManifestAudit:
72
+ root: str
73
+ findings: tuple[CommandManifestFinding, ...]
74
+
75
+ @property
76
+ def blockers(self) -> tuple[CommandManifestFinding, ...]:
77
+ return tuple(finding for finding in self.findings if finding.severity == "BLOCK")
78
+
79
+ @property
80
+ def ok(self) -> bool:
81
+ return not self.blockers
82
+
83
+ @property
84
+ def status(self) -> str:
85
+ return "PASS" if self.ok else "BLOCK"
86
+
87
+ @property
88
+ def returncode(self) -> int:
89
+ return 0 if self.ok else 2
90
+
91
+ def as_dict(self) -> dict[str, object]:
92
+ return {
93
+ "schema_version": 1,
94
+ "kind": "command_manifest_audit",
95
+ "root": self.root,
96
+ "status": self.status,
97
+ "finding_count": len(self.findings),
98
+ "blocker_count": len(self.blockers),
99
+ "findings": [finding.as_dict() for finding in self.findings],
100
+ }
101
+
102
+
103
+ def manifest_sha(commands: list[dict[str, Any]]) -> str:
104
+ canonical = json.dumps(commands, sort_keys=True, separators=(",", ":")).encode("utf-8")
105
+ return hashlib.sha256(canonical).hexdigest()[:12]
106
+
107
+
108
+ def _jsonable(value: Any) -> Any:
109
+ if value is None or isinstance(value, (str, int, float, bool)):
110
+ return value
111
+ if isinstance(value, (list, tuple)):
112
+ return [_jsonable(item) for item in value]
113
+ if isinstance(value, dict):
114
+ return {str(k): _jsonable(v) for k, v in value.items()}
115
+ return repr(value)
116
+
117
+
118
+ def _param_record(param: Any) -> dict[str, Any]:
119
+ record: dict[str, Any] = {
120
+ "name": param.name,
121
+ "param_type": param.__class__.__name__,
122
+ "required": bool(getattr(param, "required", False)),
123
+ "default": _jsonable(getattr(param, "default", None)),
124
+ "metavar": getattr(param, "metavar", None),
125
+ }
126
+ if hasattr(param, "opts"):
127
+ record["opts"] = list(getattr(param, "opts", []))
128
+ record["secondary_opts"] = list(getattr(param, "secondary_opts", []))
129
+ record["help"] = getattr(param, "help", None) or ""
130
+ record["is_flag"] = bool(getattr(param, "is_flag", False))
131
+ record["multiple"] = bool(getattr(param, "multiple", False))
132
+ return record
133
+
134
+
135
+ def _record_for(path: list[str], command: Any) -> dict[str, Any]:
136
+ group = "root" if len(path) == 1 else " ".join(path[:-1])
137
+ qualified_name = "agentic-kit " + " ".join(path)
138
+ params = [_param_record(param) for param in command.params]
139
+ command_record: dict[str, Any] = {
140
+ "group": group,
141
+ "name": path[-1],
142
+ "path": path,
143
+ "qualified_name": qualified_name,
144
+ "help": command.help or "",
145
+ "params": params,
146
+ }
147
+ return _with_manifest_fields(command_record)
148
+
149
+
150
+ def _walk(path: list[str], command: Any) -> list[dict[str, Any]]:
151
+ commands = getattr(command, "commands", None)
152
+ if isinstance(commands, dict):
153
+ records: list[dict[str, Any]] = []
154
+ for name in sorted(commands):
155
+ records.extend(_walk([*path, name], commands[name]))
156
+ return records
157
+ return [_record_for(path, command)]
158
+
159
+
160
+ def _leaf(command: dict[str, Any]) -> str:
161
+ path = command.get("path")
162
+ if isinstance(path, list) and path:
163
+ return str(path[-1])
164
+ return str(command.get("name") or command.get("qualified_name") or "").rsplit(" ", 1)[-1]
165
+
166
+
167
+ def _all_opts(command: dict[str, Any]) -> set[str]:
168
+ opts: set[str] = set()
169
+ for param in command.get("params") or []:
170
+ if not isinstance(param, dict):
171
+ continue
172
+ opts.update(str(opt) for opt in param.get("opts") or [])
173
+ opts.update(str(opt) for opt in param.get("secondary_opts") or [])
174
+ return opts
175
+
176
+
177
+ def infer_safety(command: dict[str, Any]) -> str:
178
+ qualified = str(command.get("qualified_name") or "")
179
+ group = str(command.get("group") or "")
180
+ leaf = _leaf(command)
181
+
182
+ exact_read_only_commands = {
183
+ "agentic-kit handoff post-merge-refresh-status",
184
+ "agentic-kit transfer post-merge-check",
185
+ "agentic-kit workspace adopt",
186
+ }
187
+ if qualified in exact_read_only_commands:
188
+ return "READ_ONLY"
189
+
190
+ destructive_terms = (
191
+ "delete",
192
+ "merge",
193
+ "publish",
194
+ "release-publish",
195
+ "branch-delete",
196
+ "delete-merged-work-branch",
197
+ )
198
+ if any(term in qualified for term in destructive_terms):
199
+ return "DESTRUCTIVE"
200
+
201
+ read_only_leafs = {
202
+ "check",
203
+ "check-docs",
204
+ "check-todo",
205
+ "doctor",
206
+ "status",
207
+ "state",
208
+ "list",
209
+ "show",
210
+ "report",
211
+ "inspect",
212
+ "head-sha",
213
+ "lint",
214
+ "repo-log",
215
+ "repo-diff",
216
+ "divergence-status",
217
+ "require-fresh-llm-context",
218
+ "verify-llm-context-refresh",
219
+ "command-reference-check",
220
+ "command-taxonomy-check",
221
+ "standard-gates-audit-suite",
222
+ "protected-diff-plan",
223
+ "post-merge-check",
224
+ "command-for",
225
+ "refresher",
226
+ "render-md",
227
+ "session-start",
228
+ }
229
+ read_only_prefixes = (
230
+ "agentic-kit audit-",
231
+ "agentic-kit direction audit-",
232
+ "agentic-kit docs lifecycle plan",
233
+ "agentic-kit docs lifecycle triage",
234
+ "agentic-kit docs removed-source-audit",
235
+ "agentic-kit governance check",
236
+ "agentic-kit actions list",
237
+ "agentic-kit actions show",
238
+ "agentic-kit cockpit status",
239
+ "agentic-kit cockpit gatekeeper-status",
240
+ "agentic-kit cockpit actions",
241
+ )
242
+ if leaf in read_only_leafs or qualified.startswith(read_only_prefixes):
243
+ return "READ_ONLY"
244
+ if leaf.startswith("audit-") or leaf.endswith("-audit") or leaf.startswith("validate"):
245
+ return "READ_ONLY"
246
+ if group in {"actions", "patterns"} and leaf in {"list", "show"}:
247
+ return "READ_ONLY"
248
+
249
+ return "BOUNDED"
250
+
251
+
252
+ def infer_surface(command: dict[str, Any]) -> str:
253
+ qualified = str(command.get("qualified_name") or "")
254
+ path = command.get("path")
255
+ path_parts = [str(part) for part in path] if isinstance(path, list) else []
256
+ group = str(command.get("group") or (path_parts[0] if path_parts else "root"))
257
+ leaf = _leaf(command)
258
+
259
+ orchestrator_commands = {
260
+ "agentic-kit artifact-gc",
261
+ "agentic-kit chat session-start",
262
+ "agentic-kit docs lifecycle sweep",
263
+ "agentic-kit dpa final-closeout-check",
264
+ "agentic-kit github-create",
265
+ "agentic-kit init",
266
+ "agentic-kit post-release-doi-closeout",
267
+ "agentic-kit release prepare",
268
+ "agentic-kit release ready",
269
+ "agentic-kit release-prep",
270
+ "agentic-kit release-publish",
271
+ "agentic-kit transfer admin-refresh-pr",
272
+ "agentic-kit transfer chat-switch-complete",
273
+ "agentic-kit transfer evidence-pr-complete",
274
+ "agentic-kit transfer post-merge-complete",
275
+ "agentic-kit transfer post-merge-settle",
276
+ "agentic-kit transfer pr-closeout-complete",
277
+ "agentic-kit transfer pr-complete",
278
+ "agentic-kit transfer pr-create-complete",
279
+ "agentic-kit transfer remote-next",
280
+ "agentic-kit transfer remote-work-start",
281
+ "agentic-kit transfer sync-main",
282
+ "agentic-kit work finish",
283
+ "agentic-kit work recover",
284
+ "agentic-kit work start",
285
+ "agentic-kit workflow go",
286
+ "agentic-kit workspace adopt",
287
+ "agentic-kit workspace dpa-intake",
288
+ "agentic-kit workspace init",
289
+ "agentic-kit workspace remove",
290
+ "agentic-kit workspace upgrade",
291
+ }
292
+ if qualified in orchestrator_commands:
293
+ return "orchestrator"
294
+
295
+ primitive_exact = {
296
+ "agentic-kit transfer publish-last-report",
297
+ }
298
+ diagnostic_leaf_terms = (
299
+ "audit",
300
+ "check",
301
+ "status",
302
+ "inspect",
303
+ "list",
304
+ "show",
305
+ "validate",
306
+ "readiness",
307
+ "doctor",
308
+ "render",
309
+ "report",
310
+ "summary",
311
+ "diff",
312
+ "plan",
313
+ "diagnose",
314
+ "classify",
315
+ )
316
+ diagnostic_exact = {
317
+ "agentic-kit check",
318
+ "agentic-kit check-docs",
319
+ "agentic-kit check-todo",
320
+ "agentic-kit command-for",
321
+ }
322
+ if qualified in primitive_exact:
323
+ return "primitive"
324
+ if qualified in diagnostic_exact:
325
+ return "diagnostic"
326
+ if any(term in leaf for term in diagnostic_leaf_terms):
327
+ return "diagnostic"
328
+ if group == "dpa" and any(term in qualified for term in ("assessment", "closeout", "stage", "gate")):
329
+ return "diagnostic"
330
+ if infer_safety(command) == "READ_ONLY" and group not in {"workspace"}:
331
+ return "diagnostic"
332
+ return "primitive"
333
+
334
+
335
+ def _task_tags(command: dict[str, Any]) -> list[str]:
336
+ tags = []
337
+ group = str(command.get("group") or "")
338
+ if group and group != "root":
339
+ tags.append(group.replace(" ", "-"))
340
+ safety = str(command.get("safety") or infer_safety(command)).lower()
341
+ tags.append(safety.replace("_", "-"))
342
+ return sorted(dict.fromkeys(tags))
343
+
344
+
345
+ def _when_to_use(command: dict[str, Any]) -> str:
346
+ help_text = str(command.get("help") or "").strip()
347
+ if help_text:
348
+ return help_text.splitlines()[0].strip()
349
+ return f"Run {command.get('qualified_name')}."
350
+
351
+
352
+ def _dry_run_available(command: dict[str, Any]) -> bool:
353
+ opts = _all_opts(command)
354
+ return "--dry-run" in opts or "--execute" in opts
355
+
356
+
357
+ def _with_manifest_fields(command: dict[str, Any]) -> dict[str, Any]:
358
+ enriched = dict(command)
359
+ qualified_name = str(enriched.get("qualified_name") or "")
360
+ enriched["safety"] = str(enriched.get("safety") or infer_safety(enriched))
361
+ enriched["surface"] = str(enriched.get("surface") or infer_surface(enriched))
362
+ enriched["task_tags"] = list(enriched.get("task_tags") or _task_tags(enriched))
363
+ enriched["when_to_use"] = str(enriched.get("when_to_use") or _when_to_use(enriched))
364
+ if qualified_name in LIFECYCLE_RANKS:
365
+ enriched["lifecycle_rank"] = LIFECYCLE_RANKS[qualified_name]
366
+ enriched["replaces_raw"] = list(
367
+ enriched.get("replaces_raw") or RAW_REPLACEMENTS.get(qualified_name, ())
368
+ )
369
+ enriched["dry_run_available"] = bool(
370
+ enriched.get("dry_run_available")
371
+ if "dry_run_available" in enriched
372
+ else _dry_run_available(enriched)
373
+ )
374
+ return enriched
375
+
376
+
377
+ def build_reference_from_app(app: Any) -> dict[str, Any]:
378
+ root = get_command(app)
379
+ commands: list[dict[str, Any]] = []
380
+ if not hasattr(root, "commands"):
381
+ command_name = str(getattr(root, "name", None) or "root")
382
+ commands.append(_record_for([command_name], root))
383
+ sha = manifest_sha(commands)
384
+ return {
385
+ "schema_version": 2,
386
+ "kind": "agentic_kit_command_reference",
387
+ "source": "generated_from_typer_click_registry",
388
+ "generated_by": "scripts/generate_agentic_kit_command_reference.py",
389
+ "successor_execution_contract": "docs/reports/handoff-packages/latest/execution_contract.json",
390
+ "meta": {
391
+ "schema_version": 1,
392
+ "manifest_sha": sha,
393
+ "generated_md": MD_PATH.as_posix(),
394
+ },
395
+ "commands": commands,
396
+ }
397
+ for name, command in sorted(root.commands.items()):
398
+ nested = getattr(command, "commands", None)
399
+ if isinstance(nested, dict):
400
+ commands.extend(_walk([name], command))
401
+ else:
402
+ commands.append(_record_for([name], command))
403
+
404
+ commands = sorted(commands, key=lambda item: item["qualified_name"])
405
+ sha = manifest_sha(commands)
406
+ return {
407
+ "schema_version": 2,
408
+ "kind": "agentic_kit_command_reference",
409
+ "source": "generated_from_typer_click_registry",
410
+ "generated_by": "scripts/generate_agentic_kit_command_reference.py",
411
+ "successor_execution_contract": "docs/reports/handoff-packages/latest/execution_contract.json",
412
+ "meta": {
413
+ "schema_version": 1,
414
+ "manifest_sha": sha,
415
+ "generated_md": MD_PATH.as_posix(),
416
+ },
417
+ "commands": commands,
418
+ }
419
+
420
+
421
+ def build_current_reference() -> dict[str, Any]:
422
+ from agentic_project_kit.cli import app
423
+
424
+ return build_reference_from_app(app)
425
+
426
+
427
+ def render_markdown(data: dict[str, Any]) -> str:
428
+ commands = data.get("commands") or []
429
+ meta = data.get("meta") if isinstance(data.get("meta"), dict) else {}
430
+ sha = str(meta.get("manifest_sha") or manifest_sha(commands))
431
+ lines = [
432
+ "# Agentic-kit command reference",
433
+ "",
434
+ f"GENERATED FROM agentic-kit-commands.json — do not edit; manifest_sha: {sha}",
435
+ "",
436
+ "> Successor handoff contract note: the machine-readable successor execution contract is written to `docs/reports/handoff-packages/latest/execution_contract.json`. This generated command reference points to the contract instead of duplicating local-command rules.",
437
+ "",
438
+ f"- Schema version: `{data['schema_version']}`",
439
+ f"- Source: `{data['source']}`",
440
+ f"- Command count: `{len(commands)}`",
441
+ "",
442
+ "## Commands",
443
+ "",
444
+ ]
445
+ for command in commands:
446
+ lines.append(f"### `{command['qualified_name']}`")
447
+ lines.append("")
448
+ lines.append(f"- Safety: `{command.get('safety', '')}`")
449
+ lines.append(f"- Surface: `{command.get('surface', '')}`")
450
+ lines.append(f"- When to use: {command.get('when_to_use', '')}")
451
+ lines.append(f"- Dry-run available: `{bool(command.get('dry_run_available'))}`")
452
+ replaces = command.get("replaces_raw") or []
453
+ if replaces:
454
+ lines.append("- Replaces raw: " + ", ".join(f"`{item}`" for item in replaces))
455
+ lines.append("")
456
+ if command.get("help"):
457
+ lines.append(str(command["help"]).strip())
458
+ lines.append("")
459
+ if command.get("params"):
460
+ lines.append("| Parameter | Type | Options | Required | Default | Help |")
461
+ lines.append("|---|---:|---|---:|---|---|")
462
+ for param in command["params"]:
463
+ opts = ", ".join(param.get("opts", []) + param.get("secondary_opts", []))
464
+ default = "" if param.get("default") is None else f"`{param.get('default')}`"
465
+ help_text = (param.get("help") or "").replace("\n", " ")
466
+ lines.append(
467
+ f"| `{param.get('name')}` | `{param.get('param_type')}` | "
468
+ f"{opts} | `{param.get('required')}` | {default} | {help_text} |"
469
+ )
470
+ lines.append("")
471
+ else:
472
+ lines.append("_No parameters._")
473
+ lines.append("")
474
+ return "\n".join(lines).rstrip() + "\n"
475
+
476
+
477
+ def write_reference(root: Path) -> dict[str, Any]:
478
+ data = build_current_reference()
479
+ json_path = load_workspace(root).reference_file("agentic-kit-commands.json")
480
+ md_path = load_workspace(root).reference_file("AGENTIC_KIT_COMMANDS.md")
481
+ json_path.parent.mkdir(parents=True, exist_ok=True)
482
+ json_path.write_text(json.dumps(data, indent=2, sort_keys=True) + "\n", encoding="utf-8")
483
+ md_path.write_text(render_markdown(data), encoding="utf-8")
484
+ return data
485
+
486
+
487
+ def load_manifest(root: Path) -> dict[str, Any]:
488
+ return json.loads(load_workspace(root).reference_file("agentic-kit-commands.json").read_text(encoding="utf-8"))
489
+
490
+
491
+ def evaluate_command_manifest(root: Path = Path(".")) -> CommandManifestAudit:
492
+ root = root.resolve()
493
+ findings: list[CommandManifestFinding] = []
494
+ json_path = load_workspace(root).reference_file("agentic-kit-commands.json")
495
+ md_path = load_workspace(root).reference_file("AGENTIC_KIT_COMMANDS.md")
496
+
497
+ try:
498
+ committed = load_manifest(root)
499
+ except Exception as exc:
500
+ return CommandManifestAudit(
501
+ root=root.as_posix(),
502
+ findings=(CommandManifestFinding("BLOCK", "JSON_UNREADABLE", str(exc)),),
503
+ )
504
+
505
+ commands = committed.get("commands")
506
+ if not isinstance(commands, list):
507
+ findings.append(CommandManifestFinding("BLOCK", "COMMANDS_NOT_LIST", "commands is not a list"))
508
+ commands = []
509
+
510
+ current = build_current_reference()
511
+ committed_names = {str(item.get("qualified_name")) for item in commands if isinstance(item, dict)}
512
+ current_names = {
513
+ str(item.get("qualified_name"))
514
+ for item in current.get("commands", [])
515
+ if isinstance(item, dict)
516
+ }
517
+ for name in sorted(current_names - committed_names):
518
+ findings.append(CommandManifestFinding("BLOCK", "CLI_WITHOUT_JSON", name))
519
+ for name in sorted(committed_names - current_names):
520
+ findings.append(CommandManifestFinding("BLOCK", "JSON_WITHOUT_CLI", name))
521
+
522
+ for command in commands:
523
+ if not isinstance(command, dict):
524
+ findings.append(CommandManifestFinding("BLOCK", "COMMAND_NOT_OBJECT", repr(command)))
525
+ continue
526
+ qualified = str(command.get("qualified_name") or "<unknown>")
527
+ safety = command.get("safety")
528
+ if safety not in SAFETY_VALUES:
529
+ findings.append(
530
+ CommandManifestFinding("BLOCK", "SAFETY_INVALID", f"{qualified}: {safety!r}")
531
+ )
532
+ surface = command.get("surface")
533
+ if surface not in SURFACE_VALUES:
534
+ findings.append(
535
+ CommandManifestFinding("BLOCK", "SURFACE_INVALID", f"{qualified}: {surface!r}")
536
+ )
537
+ replaces_raw = command.get("replaces_raw", [])
538
+ if replaces_raw is None:
539
+ replaces_raw = []
540
+ if not isinstance(replaces_raw, list) or any(not str(item).strip() for item in replaces_raw):
541
+ findings.append(
542
+ CommandManifestFinding("BLOCK", "REPLACES_RAW_INVALID", f"{qualified}: {replaces_raw!r}")
543
+ )
544
+
545
+ meta = committed.get("meta") if isinstance(committed.get("meta"), dict) else {}
546
+ expected_sha = manifest_sha(commands)
547
+ if meta.get("manifest_sha") != expected_sha:
548
+ findings.append(
549
+ CommandManifestFinding(
550
+ "BLOCK",
551
+ "MANIFEST_SHA_MISMATCH",
552
+ f"expected {expected_sha}, found {meta.get('manifest_sha')!r}",
553
+ )
554
+ )
555
+ if meta.get("generated_md") != MD_PATH.as_posix():
556
+ findings.append(
557
+ CommandManifestFinding(
558
+ "BLOCK",
559
+ "GENERATED_MD_MISMATCH",
560
+ f"expected {MD_PATH.as_posix()}, found {meta.get('generated_md')!r}",
561
+ )
562
+ )
563
+
564
+ if committed != current:
565
+ findings.append(
566
+ CommandManifestFinding("BLOCK", "JSON_DRIFT", f"{json_path.as_posix()} differs from CLI")
567
+ )
568
+ expected_md = render_markdown(committed)
569
+ actual_md = md_path.read_text(encoding="utf-8") if md_path.exists() else ""
570
+ if actual_md != expected_md:
571
+ findings.append(
572
+ CommandManifestFinding("BLOCK", "MD_DRIFT", f"{md_path.as_posix()} differs from generator")
573
+ )
574
+ from agentic_project_kit.chat_entrypoint_contract import audit_entrypoint_manifest_references
575
+
576
+ for finding in audit_entrypoint_manifest_references(root, committed):
577
+ findings.append(CommandManifestFinding("BLOCK", finding["code"], finding["message"]))
578
+
579
+ return CommandManifestAudit(root=root.as_posix(), findings=tuple(findings))
580
+
581
+
582
+ def render_command_manifest_audit(audit: CommandManifestAudit) -> str:
583
+ lines = [
584
+ "COMMAND_MANIFEST_AUDIT",
585
+ f"STATUS={audit.status}",
586
+ f"FINDING_COUNT={len(audit.findings)}",
587
+ f"BLOCKER_COUNT={len(audit.blockers)}",
588
+ ]
589
+ for finding in audit.findings:
590
+ lines.append(f"FINDING={finding.severity}|{finding.code}|{finding.message}")
591
+ return "\n".join(lines) + "\n"