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 @@
1
+ __version__ = "1.0.1"
@@ -0,0 +1,241 @@
1
+ from __future__ import annotations
2
+
3
+ from dataclasses import asdict, dataclass
4
+ from pathlib import Path
5
+ import re
6
+
7
+
8
+ ABSOLUTE_PATH_PATTERNS = (
9
+ re.compile(r"/Users/[A-Za-z0-9._-]+/[^\s`\"')]+"),
10
+ re.compile(r"/home/[A-Za-z0-9._-]+/[^\s`\"')]+"),
11
+ re.compile(r"(?<![\w.-])/tmp/[^\s`\"')]+"),
12
+ re.compile(r"/var/folders/[^\s`\"')]+"),
13
+ re.compile(r"/mnt/data/[^\s`\"')]+"),
14
+ )
15
+
16
+ TEXT_SUFFIXES = {
17
+ ".md",
18
+ ".rst",
19
+ ".txt",
20
+ ".py",
21
+ ".toml",
22
+ ".yaml",
23
+ ".yml",
24
+ ".json",
25
+ ".cff",
26
+ ".sh",
27
+ }
28
+
29
+ SKIP_DIR_PARTS = {
30
+ ".git",
31
+ ".venv",
32
+ "__pycache__",
33
+ ".pytest_cache",
34
+ ".ruff_cache",
35
+ ".mypy_cache",
36
+ "node_modules",
37
+ "tmp",
38
+ "dist",
39
+ "build",
40
+ }
41
+
42
+ SKIP_DIR_PREFIXES = (
43
+ ".venv",
44
+ )
45
+
46
+ SKIP_FILENAMES = {
47
+ "Screen-Control_Output.txt",
48
+ }
49
+
50
+ SKIP_PATH_PREFIXES = (
51
+ "docs/reports/",
52
+ ".agentic/transfer/outbox/",
53
+ )
54
+
55
+ SAFE_PATH_PREFIXES = (
56
+ "tests/",
57
+ "docs/reports/",
58
+ )
59
+
60
+ SAFE_PATHS = {
61
+ "README.md",
62
+ "docs/STATUS.md",
63
+ "docs/handoff/CURRENT_HANDOFF.md",
64
+ }
65
+
66
+ HISTORICAL_MARKERS = (
67
+ "historical",
68
+ "legacy",
69
+ "obsolete",
70
+ "removed",
71
+ "deprecated",
72
+ "archived",
73
+ "archive",
74
+ "example",
75
+ "fixture",
76
+ "test",
77
+ "log",
78
+ "evidence",
79
+ "sandbox",
80
+ )
81
+
82
+
83
+ @dataclass(frozen=True)
84
+ class AbsolutePathReference:
85
+ path: str
86
+ line: int
87
+ text: str
88
+ match: str
89
+ classification: str
90
+ reason: str
91
+
92
+ def as_dict(self) -> dict[str, object]:
93
+ return asdict(self)
94
+
95
+
96
+ @dataclass(frozen=True)
97
+ class AbsolutePathAuditResult:
98
+ root: str
99
+ references: tuple[AbsolutePathReference, ...]
100
+ blockers: tuple[AbsolutePathReference, ...]
101
+
102
+ @property
103
+ def ok(self) -> bool:
104
+ return not self.blockers
105
+
106
+ @property
107
+ def status(self) -> str:
108
+ return "PASS" if self.ok else "FAIL"
109
+
110
+ @property
111
+ def returncode(self) -> int:
112
+ return 0 if self.ok else 1
113
+
114
+ def as_dict(self) -> dict[str, object]:
115
+ return {
116
+ "schema_version": 1,
117
+ "kind": "absolute_path_portability_audit",
118
+ "root": self.root,
119
+ "status": self.status,
120
+ "reference_count": len(self.references),
121
+ "blocker_count": len(self.blockers),
122
+ "references": [item.as_dict() for item in self.references],
123
+ "blockers": [item.as_dict() for item in self.blockers],
124
+ }
125
+
126
+
127
+ def _is_text_file(path: Path) -> bool:
128
+ return path.suffix in TEXT_SUFFIXES
129
+
130
+
131
+ def _iter_candidate_files(root: Path) -> list[Path]:
132
+ files: list[Path] = []
133
+ for path in root.rglob("*"):
134
+ if not path.is_file():
135
+ continue
136
+ relative = path.relative_to(root).as_posix()
137
+ relative_parts = path.relative_to(root).parts
138
+ if path.name in SKIP_FILENAMES:
139
+ continue
140
+ if any(part in SKIP_DIR_PARTS for part in relative_parts):
141
+ continue
142
+ if any(part.startswith(prefix) for part in relative_parts for prefix in SKIP_DIR_PREFIXES):
143
+ continue
144
+ if any(relative.startswith(prefix) for prefix in SKIP_PATH_PREFIXES):
145
+ continue
146
+ if not _is_text_file(path):
147
+ continue
148
+ files.append(path)
149
+ return sorted(files)
150
+
151
+
152
+ def _classify(relative: str, line: str, match: str) -> tuple[str, str]:
153
+ lowered = line.lower()
154
+
155
+ if relative == "src/agentic_project_kit/absolute_path_portability_audit.py":
156
+ return "audit_implementation", "absolute path tokens are classifier patterns, not user-facing paths"
157
+
158
+ if relative.startswith(SAFE_PATH_PREFIXES):
159
+ return "safe_generated_or_test_context", "test/generated context"
160
+
161
+ if relative.startswith("tests/"):
162
+ return "test_fixture", "test fixture"
163
+
164
+ if relative.startswith(("src/", "tools/")):
165
+ return "absolute_path_blocker", (
166
+ "source/tool files must not contain user-specific absolute paths; "
167
+ "line-level historical words are not enough to downgrade this"
168
+ )
169
+
170
+ if relative in SAFE_PATHS and any(marker in lowered for marker in HISTORICAL_MARKERS):
171
+ return "historical_or_example_context", "stable doc with historical/example marker"
172
+
173
+ if any(marker in lowered for marker in HISTORICAL_MARKERS):
174
+ return "historical_or_example_context", "line contains historical/example/evidence marker"
175
+
176
+ if match.startswith("/tmp/") or match.startswith("/mnt/data/") or match.startswith("/var/folders/"):
177
+ return "transient_path_reference", "transient local path should not be current repo contract"
178
+
179
+ return "absolute_path_blocker", "absolute local path may break portability"
180
+
181
+
182
+ def audit_absolute_path_portability(root: Path = Path(".")) -> AbsolutePathAuditResult:
183
+ root = root.resolve()
184
+ references: list[AbsolutePathReference] = []
185
+
186
+ for path in _iter_candidate_files(root):
187
+ relative = path.relative_to(root).as_posix()
188
+ try:
189
+ lines = path.read_text(encoding="utf-8").splitlines()
190
+ except UnicodeDecodeError:
191
+ continue
192
+
193
+ for number, line in enumerate(lines, start=1):
194
+ for pattern in ABSOLUTE_PATH_PATTERNS:
195
+ for match in pattern.finditer(line):
196
+ matched = match.group(0)
197
+ classification, reason = _classify(relative, line, matched)
198
+ references.append(
199
+ AbsolutePathReference(
200
+ path=relative,
201
+ line=number,
202
+ text=line.strip(),
203
+ match=matched,
204
+ classification=classification,
205
+ reason=reason,
206
+ )
207
+ )
208
+
209
+ blockers = tuple(
210
+ ref
211
+ for ref in references
212
+ if ref.classification in {"absolute_path_blocker", "transient_path_reference"}
213
+ )
214
+ return AbsolutePathAuditResult(
215
+ root=root.as_posix(),
216
+ references=tuple(references),
217
+ blockers=blockers,
218
+ )
219
+
220
+
221
+ def render_absolute_path_portability_audit(result: AbsolutePathAuditResult) -> str:
222
+ lines = [
223
+ "ABSOLUTE_PATH_PORTABILITY_AUDIT",
224
+ f"STATUS={result.status}",
225
+ f"REFERENCE_COUNT={len(result.references)}",
226
+ f"BLOCKER_COUNT={len(result.blockers)}",
227
+ ]
228
+
229
+ for ref in result.blockers:
230
+ lines.append(
231
+ "BLOCKER="
232
+ f"{ref.classification}|{ref.path}:{ref.line}|{ref.match}|{ref.text}"
233
+ )
234
+
235
+ for ref in result.references:
236
+ lines.append(
237
+ "REFERENCE="
238
+ f"{ref.classification}|{ref.path}:{ref.line}|{ref.match}|{ref.text}"
239
+ )
240
+
241
+ return "\n".join(lines) + "\n"
@@ -0,0 +1,14 @@
1
+ from __future__ import annotations
2
+
3
+ from collections.abc import Iterable
4
+
5
+ from agentic_project_kit.access_levels import AccessLevel, meets_min_access
6
+ from agentic_project_kit.cockpit import CockpitAction
7
+
8
+
9
+ def can_show_action(action: CockpitAction, level: AccessLevel) -> bool:
10
+ return meets_min_access(level, action.min_access_level)
11
+
12
+
13
+ def visible_actions(actions: Iterable[CockpitAction], level: AccessLevel) -> list[CockpitAction]:
14
+ return [action for action in actions if can_show_action(action, level)]
@@ -0,0 +1,22 @@
1
+ from __future__ import annotations
2
+
3
+ from typing import Literal
4
+
5
+ AccessLevel = Literal["basic", "advanced", "maintainer"]
6
+
7
+ ACCESS_LEVEL_ORDER: tuple[AccessLevel, ...] = ("basic", "advanced", "maintainer")
8
+ DEFAULT_ACCESS_LEVEL: AccessLevel = "basic"
9
+
10
+
11
+ def access_level_rank(level: AccessLevel) -> int:
12
+ return ACCESS_LEVEL_ORDER.index(level)
13
+
14
+
15
+ def meets_min_access(current: AccessLevel, required: AccessLevel) -> bool:
16
+ return access_level_rank(current) >= access_level_rank(required)
17
+
18
+
19
+ def normalize_access_level(value: str | None) -> AccessLevel:
20
+ if value in ACCESS_LEVEL_ORDER:
21
+ return value
22
+ return DEFAULT_ACCESS_LEVEL
@@ -0,0 +1,195 @@
1
+ """Static action metadata for local workflow and cockpit readiness.
2
+
3
+ This module is intentionally read-only: it describes known local actions but
4
+ does not execute shell commands, mutate git state, call GitHub, or publish releases.
5
+ """
6
+
7
+ from __future__ import annotations
8
+
9
+ from dataclasses import dataclass
10
+ from enum import Enum
11
+
12
+
13
+ class SafetyClass(str, Enum):
14
+ """Coarse safety class for a local action."""
15
+
16
+ READ_ONLY = "read-only"
17
+ LOCAL_ONLY = "local-only"
18
+ REMOTE_MUTATION = "remote-mutation"
19
+ RELEASE_TAG_PUBLISH = "release-tag-publish"
20
+ MERGE_DELETE_CLOSE = "merge-delete-close"
21
+
22
+
23
+ @dataclass(frozen=True)
24
+ class ActionMetadata:
25
+ """Static metadata for one repo-local action."""
26
+
27
+ name: str
28
+ safety_class: SafetyClass
29
+ mutation_scope: str
30
+ dry_run_supported: bool
31
+ outcome_contract: tuple[str, ...]
32
+ summary: str
33
+
34
+
35
+ ACTIONS: tuple[ActionMetadata, ...] = (
36
+ ActionMetadata(
37
+ name="dev",
38
+ safety_class=SafetyClass.READ_ONLY,
39
+ mutation_scope="none",
40
+ dry_run_supported=True,
41
+ outcome_contract=("PASS", "FAIL"),
42
+ summary="Run local deterministic development gates.",
43
+ ),
44
+ ActionMetadata(
45
+ name="pr-cleanup",
46
+ safety_class=SafetyClass.READ_ONLY,
47
+ mutation_scope="none",
48
+ dry_run_supported=True,
49
+ outcome_contract=("PASS", "FAIL"),
50
+ summary="Classify open pull requests without mutating them.",
51
+ ),
52
+ ActionMetadata(
53
+ name="release-verify",
54
+ safety_class=SafetyClass.READ_ONLY,
55
+ mutation_scope="none",
56
+ dry_run_supported=True,
57
+ outcome_contract=("PASS", "FAIL"),
58
+ summary="Verify an existing release and metadata state.",
59
+ ),
60
+ ActionMetadata(
61
+ name="clean-evidence",
62
+ safety_class=SafetyClass.LOCAL_ONLY,
63
+ mutation_scope="working-tree-files",
64
+ dry_run_supported=False,
65
+ outcome_contract=("PASS", "FAIL"),
66
+ summary="Clean local evidence or generated files according to repo policy.",
67
+ ),
68
+ ActionMetadata(
69
+ name="release-prep",
70
+ safety_class=SafetyClass.LOCAL_ONLY,
71
+ mutation_scope="version-and-release-metadata-files",
72
+ dry_run_supported=False,
73
+ outcome_contract=("PASS", "FAIL"),
74
+ summary="Prepare local release metadata before a release PR.",
75
+ ),
76
+ ActionMetadata(
77
+ name="release-gate",
78
+ safety_class=SafetyClass.READ_ONLY,
79
+ mutation_scope="none",
80
+ dry_run_supported=True,
81
+ outcome_contract=("PASS", "FAIL"),
82
+ summary="Verify release readiness without tagging or publishing.",
83
+ ),
84
+ ActionMetadata(
85
+ name="finalize-guard",
86
+ safety_class=SafetyClass.READ_ONLY,
87
+ mutation_scope="none",
88
+ dry_run_supported=True,
89
+ outcome_contract=("PASS_ALREADY_ON_MAIN", "PASS_NOOP_BRANCH", "PASS_SUPERSEDED", "PASS_NEEDS_PR", "FAIL_CONFLICT_RELEVANT", "FAIL_NEEDS_HUMAN_REVIEW"),
90
+ summary="Classify branch finalization state without merging or deleting.",
91
+ ),
92
+ ActionMetadata(
93
+ name="doctor",
94
+ safety_class=SafetyClass.READ_ONLY,
95
+ mutation_scope="none",
96
+ dry_run_supported=True,
97
+ outcome_contract=("PASS", "FAIL"),
98
+ summary="Run compact project health checks without mutating repository state.",
99
+ ),
100
+
101
+ ActionMetadata(
102
+ name="check-docs",
103
+ safety_class=SafetyClass.READ_ONLY,
104
+ mutation_scope="none",
105
+ dry_run_supported=True,
106
+ outcome_contract=("PASS", "FAIL"),
107
+ summary="Run documentation coverage and lifecycle gates without mutating repository state.",
108
+ ),
109
+
110
+ ActionMetadata(
111
+ name="cockpit-readiness",
112
+ safety_class=SafetyClass.READ_ONLY,
113
+ mutation_scope="none",
114
+ dry_run_supported=True,
115
+ outcome_contract=("PASS", "FAIL"),
116
+ summary="Render static cockpit readiness metadata without executing actions.",
117
+ ),
118
+
119
+ ActionMetadata(
120
+ name="agent-next",
121
+ safety_class=SafetyClass.REMOTE_MUTATION,
122
+ mutation_scope="docs/reports/command_runs and docs/reports/terminal",
123
+ dry_run_supported=False,
124
+ outcome_contract=(
125
+ "PASS_EXECUTED",
126
+ "FAIL_NO_COMMAND",
127
+ "FAIL_AMBIGUOUS_COMMANDS",
128
+ "FAIL_PULL",
129
+ "FAIL_ALREADY_EXECUTED",
130
+ "FAIL_INVALID_COMMAND",
131
+ "FAIL_SHELL_SYNTAX",
132
+ "FAIL_COMMAND",
133
+ "FAIL_UPLOAD",
134
+ "FAIL_POSTCONDITION",
135
+ ),
136
+ summary="Pull and execute exactly one pending repo-backed agent command.",
137
+ ),
138
+
139
+ ActionMetadata(
140
+ name="agent-run",
141
+ safety_class=SafetyClass.REMOTE_MUTATION,
142
+ mutation_scope="docs/reports/command_runs and docs/reports/terminal",
143
+ dry_run_supported=False,
144
+ outcome_contract=("PASS_EXECUTED", "FAIL_NO_COMMAND", "FAIL_ALREADY_EXECUTED", "FAIL_INVALID_COMMAND", "FAIL_SHELL_SYNTAX", "FAIL_COMMAND", "FAIL_UPLOAD"),
145
+ summary="Pull-safe repo command runner for agent handoff without copy-and-paste terminal blocks.",
146
+ ),
147
+ ActionMetadata(
148
+ name="run-logged",
149
+ safety_class=SafetyClass.LOCAL_ONLY,
150
+ mutation_scope="docs/reports/terminal",
151
+ dry_run_supported=False,
152
+ outcome_contract=("PASS", "FAIL", "FAIL_NO_COMMAND", "FAIL_MISSING_SEPARATOR"),
153
+ summary="Run a local command while teeing output to a terminal log.",
154
+ ),
155
+ ActionMetadata(
156
+ name="terminal-status",
157
+ safety_class=SafetyClass.READ_ONLY,
158
+ mutation_scope="none",
159
+ dry_run_supported=True,
160
+ outcome_contract=("PASS_LOG_READY", "PASS_NO_LOG", "FAIL_INVALID_POINTER"),
161
+ summary="Inspect the latest terminal log pointer without mutating state.",
162
+ ),
163
+ ActionMetadata(
164
+ name="terminal-clean-check",
165
+ safety_class=SafetyClass.READ_ONLY,
166
+ mutation_scope="none",
167
+ dry_run_supported=True,
168
+ outcome_contract=("PASS_CLEAN", "PASS_ONLY_TERMINAL_LOG_DIRTY", "FAIL_DIRTY_NON_LOG_FILES"),
169
+ summary="Check whether only terminal-log artifacts are dirty during logged runs.",
170
+ ),
171
+ ActionMetadata(
172
+ name="terminal-upload",
173
+ safety_class=SafetyClass.REMOTE_MUTATION,
174
+ mutation_scope="docs/reports/terminal only",
175
+ dry_run_supported=False,
176
+ outcome_contract=("PASS_UPLOADED", "PASS_ALREADY_UPLOADED", "FAIL_NO_LOG", "FAIL_DIRTY_NON_LOG_FILES", "FAIL_PUSH_FAILED"),
177
+ summary="Commit and push only terminal-log artifacts for failure handoff.",
178
+ ),
179
+
180
+ )
181
+
182
+
183
+ def list_actions() -> tuple[ActionMetadata, ...]:
184
+ """Return all known action metadata entries."""
185
+
186
+ return ACTIONS
187
+
188
+
189
+ def get_action(name: str) -> ActionMetadata | None:
190
+ """Return metadata for one action name, if known."""
191
+
192
+ for action in ACTIONS:
193
+ if action.name == name:
194
+ return action
195
+ return None