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,286 @@
1
+ from __future__ import annotations
2
+
3
+ from dataclasses import dataclass, field
4
+ from enum import Enum
5
+
6
+ CURRENT_HANDOFF_MUTATION = "update docs/handoff/CURRENT_HANDOFF.md"
7
+ CURRENT_HANDOFF_TARGET_PATH = "docs/handoff/CURRENT_HANDOFF.md"
8
+ DPA_ACTION_SURFACE_WRITER_ID = "WRT-CH-004"
9
+ DPA_SELECTED_CURRENT_HANDOFF_WRITERS = frozenset(
10
+ {
11
+ "WRT-CH-001",
12
+ "WRT-CH-002",
13
+ "WRT-CH-003",
14
+ }
15
+ )
16
+ DPA_CURRENT_HANDOFF_ACTION_IDS = frozenset(
17
+ {
18
+ "release-prepare",
19
+ "doi-record",
20
+ "finalize-release",
21
+ }
22
+ )
23
+
24
+
25
+ class SafetyClass(str, Enum):
26
+ READ_ONLY = "read_only"
27
+ LOCAL_ONLY = "local_only"
28
+ REMOTE_MUTATION = "remote_mutation"
29
+ DESTRUCTIVE = "destructive"
30
+
31
+ @dataclass(frozen=True)
32
+ class ParameterSpec:
33
+ name: str
34
+ description: str
35
+ required: bool = True
36
+ example: str = ""
37
+
38
+ @dataclass(frozen=True)
39
+ class ActionSpec:
40
+ action_id: str
41
+ title: str
42
+ safety_class: SafetyClass
43
+ purpose: str
44
+ parameters: tuple[ParameterSpec, ...] = field(default_factory=tuple)
45
+ allowed_mutations: tuple[str, ...] = field(default_factory=tuple)
46
+ preconditions: tuple[str, ...] = field(default_factory=tuple)
47
+ postconditions: tuple[str, ...] = field(default_factory=tuple)
48
+ evidence: tuple[str, ...] = field(default_factory=tuple)
49
+ dry_run_default: bool = True
50
+ dpa_surface_writer_id: str = ""
51
+ dpa_target_path: str = ""
52
+ dpa_selected_writer_ids: tuple[str, ...] = field(default_factory=tuple)
53
+ dpa_lifecycle_route: tuple[str, ...] = field(default_factory=tuple)
54
+
55
+ def built_in_action_specs() -> dict[str, ActionSpec]:
56
+ specs = [
57
+ ActionSpec(
58
+ action_id="pr-check-merge",
59
+ title="Check and optionally merge a pull request",
60
+ safety_class=SafetyClass.REMOTE_MUTATION,
61
+ purpose=(
62
+ "Replace ad-hoc PR check/merge terminal blocks with a parameterized action "
63
+ "contract."
64
+ ),
65
+ parameters=(ParameterSpec("pr_number", "GitHub pull request number.", example="346"),),
66
+ allowed_mutations=(
67
+ "squash merge selected PR when explicit execute mode is later added",
68
+ "delete merged branch when GitHub merge action does so",
69
+ ),
70
+ preconditions=(
71
+ "state OPEN",
72
+ "mergeStateStatus CLEAN",
73
+ "pending_count 0",
74
+ "non_success_count 0",
75
+ "expected CI checks present",
76
+ ),
77
+ postconditions=(
78
+ "main fast-forwards to merge commit",
79
+ "local gates pass after sync",
80
+ "repo-backed evidence log exists",
81
+ ),
82
+ evidence=("gh pr JSON state", "CI rollup", "terminal log", "post-merge local gate report"),
83
+ ),
84
+ ActionSpec(
85
+ action_id="release-verify",
86
+ title="Verify an already published release",
87
+ safety_class=SafetyClass.READ_ONLY,
88
+ purpose="Verify tag, GitHub Release, Release workflow, assets, and Zenodo DOI state.",
89
+ parameters=(
90
+ ParameterSpec("version", "Release version without leading v.", example="0.3.24"),
91
+ ),
92
+ preconditions=("version is present", "local repository is on a clean branch"),
93
+ postconditions=("GitHub Release exists", "release assets exist", "post-release check passes"),
94
+ evidence=("release-verify terminal log", "post-release-check output"),
95
+ ),
96
+ ActionSpec(
97
+ action_id="release-prepare",
98
+ title="Prepare release metadata",
99
+ safety_class=SafetyClass.LOCAL_ONLY,
100
+ purpose="Prepare local release metadata through the governed release-preparation writer.",
101
+ parameters=(ParameterSpec("version", "Release version.", example="0.3.24"),),
102
+ allowed_mutations=(
103
+ "update CHANGELOG.md",
104
+ "update docs/STATUS.md",
105
+ CURRENT_HANDOFF_MUTATION,
106
+ "write release summary evidence",
107
+ ),
108
+ preconditions=(
109
+ "release readiness PASS",
110
+ "DPA CURRENT_HANDOFF lifecycle is fresh or blocks before metadata writes",
111
+ ),
112
+ postconditions=(
113
+ "release metadata files reflect requested version",
114
+ "CURRENT_HANDOFF.md mutation is accepted through WRT-CH-002 when DPA is active",
115
+ "no tag, release or DOI is published",
116
+ ),
117
+ evidence=(
118
+ "release-ready output",
119
+ "release-prepare terminal log",
120
+ "DPA acceptance-state record",
121
+ ),
122
+ dpa_surface_writer_id=DPA_ACTION_SURFACE_WRITER_ID,
123
+ dpa_target_path=CURRENT_HANDOFF_TARGET_PATH,
124
+ dpa_selected_writer_ids=("WRT-CH-002",),
125
+ dpa_lifecycle_route=(
126
+ "agentic-kit release prepare --write",
127
+ "agentic-kit release-prep",
128
+ ),
129
+ ),
130
+ ActionSpec(
131
+ action_id="doi-record",
132
+ title="Record verified DOI metadata",
133
+ safety_class=SafetyClass.LOCAL_ONLY,
134
+ purpose="Prepare DOI metadata changes after release verification.",
135
+ parameters=(
136
+ ParameterSpec("version", "Release version.", example="0.3.24"),
137
+ ParameterSpec(
138
+ "doi",
139
+ "Verified Zenodo version DOI.",
140
+ example="10.5281/zenodo.20270197",
141
+ ),
142
+ ),
143
+ allowed_mutations=(
144
+ "update CHANGELOG.md",
145
+ "update docs/STATUS.md",
146
+ CURRENT_HANDOFF_MUTATION,
147
+ "write terminal evidence log",
148
+ ),
149
+ preconditions=(
150
+ "post-release check PASS",
151
+ "DOI belongs to requested version",
152
+ "DPA CURRENT_HANDOFF lifecycle is fresh or blocks before DOI metadata writes",
153
+ ),
154
+ postconditions=(
155
+ "docs mention DOI once",
156
+ "CURRENT_HANDOFF.md mutation is accepted through WRT-CH-003 when DPA is active",
157
+ "local gates pass",
158
+ "PR is opened for DOI metadata",
159
+ ),
160
+ evidence=(
161
+ "post-release-check output",
162
+ "DOI metadata terminal log",
163
+ "DPA acceptance-state record",
164
+ ),
165
+ dpa_surface_writer_id=DPA_ACTION_SURFACE_WRITER_ID,
166
+ dpa_target_path=CURRENT_HANDOFF_TARGET_PATH,
167
+ dpa_selected_writer_ids=("WRT-CH-003",),
168
+ dpa_lifecycle_route=("agentic-kit post-release-doi-closeout --write",),
169
+ ),
170
+ ActionSpec(
171
+ action_id="finalize-release",
172
+ title="Finalize repository state after release closeout",
173
+ safety_class=SafetyClass.LOCAL_ONLY,
174
+ purpose="Update state and handoff after release and DOI metadata are complete.",
175
+ parameters=(ParameterSpec("version", "Release version.", example="0.3.24"),),
176
+ allowed_mutations=(
177
+ "update docs/STATUS.md",
178
+ CURRENT_HANDOFF_MUTATION,
179
+ "update .agentic/handoff_state.yaml",
180
+ "write terminal evidence log",
181
+ ),
182
+ preconditions=(
183
+ "release metadata PR merged",
184
+ "main gates pass",
185
+ "handoff state has no obsolete next instruction",
186
+ "CURRENT_HANDOFF.md mutation dispatches through the administrative handoff writer",
187
+ ),
188
+ postconditions=(
189
+ "state docs point to next allowed task",
190
+ "CURRENT_HANDOFF.md mutation is accepted through WRT-CH-001 when DPA is active",
191
+ "handoff prompt is current",
192
+ "local gates pass",
193
+ ),
194
+ evidence=(
195
+ "finalize terminal log",
196
+ "handoff-check output",
197
+ "doctor output",
198
+ "DPA acceptance-state record",
199
+ ),
200
+ dpa_surface_writer_id=DPA_ACTION_SURFACE_WRITER_ID,
201
+ dpa_target_path=CURRENT_HANDOFF_TARGET_PATH,
202
+ dpa_selected_writer_ids=("WRT-CH-001",),
203
+ dpa_lifecycle_route=(
204
+ "agentic-kit transfer post-merge-settle",
205
+ "agentic-kit transfer pr-closeout-complete",
206
+ ),
207
+ ),
208
+ ]
209
+ return {spec.action_id: spec for spec in specs}
210
+
211
+ def get_action_spec(action_id: str) -> ActionSpec:
212
+ specs = built_in_action_specs()
213
+ if action_id not in specs:
214
+ known = ", ".join(sorted(specs))
215
+ raise KeyError(f"unknown action spec: {action_id}; known: {known}")
216
+ return specs[action_id]
217
+
218
+ def validate_current_handoff_action_surfaces(
219
+ specs: dict[str, ActionSpec] | None = None,
220
+ ) -> tuple[str, ...]:
221
+ selected = specs if specs is not None else built_in_action_specs()
222
+ errors: list[str] = []
223
+ for spec in selected.values():
224
+ if CURRENT_HANDOFF_MUTATION not in spec.allowed_mutations:
225
+ continue
226
+ if spec.action_id not in DPA_CURRENT_HANDOFF_ACTION_IDS:
227
+ errors.append(
228
+ f"{spec.action_id}: CURRENT_HANDOFF mutation is not an approved action surface"
229
+ )
230
+ if spec.dpa_surface_writer_id != DPA_ACTION_SURFACE_WRITER_ID:
231
+ errors.append(f"{spec.action_id}: missing WRT-CH-004 DPA action-surface classification")
232
+ if spec.dpa_target_path != CURRENT_HANDOFF_TARGET_PATH:
233
+ errors.append(f"{spec.action_id}: missing DPA CURRENT_HANDOFF target path")
234
+ if not spec.dpa_selected_writer_ids:
235
+ errors.append(f"{spec.action_id}: missing selected DPA lifecycle writer route")
236
+ for writer_id in spec.dpa_selected_writer_ids:
237
+ if writer_id not in DPA_SELECTED_CURRENT_HANDOFF_WRITERS:
238
+ errors.append(f"{spec.action_id}: unknown selected DPA writer route {writer_id}")
239
+ if not spec.dpa_lifecycle_route:
240
+ errors.append(f"{spec.action_id}: missing DPA lifecycle route command")
241
+ for action_id in sorted(DPA_CURRENT_HANDOFF_ACTION_IDS):
242
+ if action_id not in selected:
243
+ errors.append(f"{action_id}: approved CURRENT_HANDOFF action surface is missing")
244
+ return tuple(errors)
245
+
246
+ def render_action_spec(spec: ActionSpec) -> str:
247
+ lines = [
248
+ f"Action: {spec.action_id}",
249
+ f"Title: {spec.title}",
250
+ f"Safety: {spec.safety_class.value}",
251
+ f"Dry-run default: {spec.dry_run_default}",
252
+ "",
253
+ "Purpose:",
254
+ spec.purpose,
255
+ "",
256
+ "Parameters:",
257
+ ]
258
+ for parameter in spec.parameters:
259
+ required = "required" if parameter.required else "optional"
260
+ example = f"; example: {parameter.example}" if parameter.example else ""
261
+ lines.append(f"- {parameter.name} ({required}): {parameter.description}{example}")
262
+ sections = [
263
+ ("Allowed mutations", spec.allowed_mutations),
264
+ ("Preconditions", spec.preconditions),
265
+ ("Postconditions", spec.postconditions),
266
+ ("Evidence", spec.evidence),
267
+ ]
268
+ for title, items in sections:
269
+ lines.extend(["", f"{title}:"])
270
+ if items:
271
+ lines.extend(f"- {item}" for item in items)
272
+ else:
273
+ lines.append("- none")
274
+ if spec.dpa_target_path or spec.dpa_selected_writer_ids or spec.dpa_lifecycle_route:
275
+ lines.extend(["", "DPA current handoff routing:"])
276
+ lines.append(f"- surface writer: {spec.dpa_surface_writer_id or 'none'}")
277
+ lines.append(f"- target path: {spec.dpa_target_path or 'none'}")
278
+ writer_ids = (
279
+ ", ".join(spec.dpa_selected_writer_ids) if spec.dpa_selected_writer_ids else "none"
280
+ )
281
+ lines.append(f"- selected lifecycle writers: {writer_ids}")
282
+ if spec.dpa_lifecycle_route:
283
+ lines.extend(f"- route: {route}" for route in spec.dpa_lifecycle_route)
284
+ else:
285
+ lines.append("- route: none")
286
+ return "\n".join(lines)