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,310 @@
1
+ from __future__ import annotations
2
+
3
+ from dataclasses import dataclass
4
+ from pathlib import Path
5
+ import json
6
+ import re
7
+ from typing import Any
8
+
9
+ import yaml
10
+
11
+ from agentic_project_kit.checks import check_docs
12
+ from agentic_project_kit.doc_lifecycle import build_doc_lifecycle_report
13
+ from agentic_project_kit.doc_mesh import build_doc_mesh_report
14
+ from agentic_project_kit.documentation_registry import build_documentation_registry_summary
15
+ from agentic_project_kit.workspace import KitConfig, Workspace, load_workspace
16
+
17
+
18
+ _LEGACY_WORKSPACE = Workspace(root=Path("."), config=KitConfig())
19
+
20
+ STATUS_HEADROOM_WORD_LIMIT = 4968
21
+
22
+
23
+ def _workspace_path_text(ws: Workspace, path: Path) -> str:
24
+ try:
25
+ return path.relative_to(ws.root).as_posix()
26
+ except ValueError:
27
+ return path.as_posix()
28
+
29
+
30
+ def _mandatory_order(ws: Workspace) -> tuple[str, ...]:
31
+ return (
32
+ _workspace_path_text(ws, ws.compiled_agent_context_path()),
33
+ _workspace_path_text(ws, ws.governance_file("FINAL_SUMMARY_CONTRACT.md")),
34
+ _workspace_path_text(ws, ws.governance_file("CHAT_COMMUNICATION_CONTRACT.md")),
35
+ _workspace_path_text(ws, ws.governance_file("PORTABLE_CHAT_EXECUTION_CONTRACT.md")),
36
+ _workspace_path_text(ws, ws.governance_file("CHAT_BOOTSTRAP_AND_DRIFT_CONTRACT.md")),
37
+ _workspace_path_text(ws, ws.test_gates_path()),
38
+ _workspace_path_text(ws, ws.status_path()),
39
+ _workspace_path_text(ws, ws.handoff_file("CURRENT_HANDOFF.md")),
40
+ )
41
+
42
+
43
+ def _required_docs(ws: Workspace) -> tuple[str, ...]:
44
+ return (
45
+ _workspace_path_text(ws, ws.root_file("README.md")),
46
+ _workspace_path_text(ws, ws.root_file("AGENTS.md")),
47
+ _workspace_path_text(ws, ws.status_path()),
48
+ _workspace_path_text(ws, ws.test_gates_path()),
49
+ _workspace_path_text(ws, ws.handoff_file("CURRENT_HANDOFF.md")),
50
+ _workspace_path_text(ws, ws.documentation_coverage_path()),
51
+ _workspace_path_text(ws, ws.doc_registry_path()),
52
+ _workspace_path_text(ws, ws.root_file("sentinel.yaml")),
53
+ _workspace_path_text(ws, ws.compiled_agent_context_path()),
54
+ _workspace_path_text(ws, ws.governance_file("FINAL_SUMMARY_CONTRACT.md")),
55
+ _workspace_path_text(ws, ws.governance_file("CHAT_COMMUNICATION_CONTRACT.md")),
56
+ _workspace_path_text(ws, ws.governance_file("PORTABLE_CHAT_EXECUTION_CONTRACT.md")),
57
+ _workspace_path_text(ws, ws.governance_file("CHAT_BOOTSTRAP_AND_DRIFT_CONTRACT.md")),
58
+ _workspace_path_text(ws, ws.governance_file("DOCUMENTATION_REGISTRY_CONTRACT.md")),
59
+ _workspace_path_text(ws, ws.architecture_file("ARCHITECTURE_CONTRACT.md")),
60
+ _workspace_path_text(ws, ws.architecture_file("DOCUMENTATION_INFORMATION_ARCHITECTURE.md")),
61
+ )
62
+
63
+
64
+ MANDATORY_ORDER = _mandatory_order(_LEGACY_WORKSPACE)
65
+ REQUIRED_DOCS = _required_docs(_LEGACY_WORKSPACE)
66
+
67
+
68
+ @dataclass(frozen=True)
69
+ class DocumentationAuditDimension:
70
+ name: str
71
+ ok: bool
72
+ findings: tuple[str, ...]
73
+ review_only: bool = False
74
+
75
+ def to_dict(self) -> dict[str, Any]:
76
+ return {
77
+ "name": self.name,
78
+ "ok": self.ok,
79
+ "review_only": self.review_only,
80
+ "findings": list(self.findings),
81
+ }
82
+
83
+
84
+ @dataclass(frozen=True)
85
+ class DocumentationSystemAuditReport:
86
+ dimensions: tuple[DocumentationAuditDimension, ...]
87
+
88
+ @property
89
+ def ok(self) -> bool:
90
+ return all(dimension.ok for dimension in self.dimensions if not dimension.review_only)
91
+
92
+ def to_dict(self) -> dict[str, Any]:
93
+ return {
94
+ "ok": self.ok,
95
+ "dimensions": [dimension.to_dict() for dimension in self.dimensions],
96
+ }
97
+
98
+
99
+ def build_documentation_system_audit(project_root: Path) -> DocumentationSystemAuditReport:
100
+ project_root = project_root.resolve()
101
+ ws = load_workspace(project_root)
102
+ check_doc_errors = tuple(check_docs(project_root))
103
+ mesh_report = build_doc_mesh_report(project_root)
104
+ lifecycle_report = build_doc_lifecycle_report(project_root)
105
+ dimensions = (
106
+ _freshness_dimension(ws, mesh_report),
107
+ _completeness_dimension(ws, check_doc_errors),
108
+ _correctness_dimension(check_doc_errors, mesh_report, lifecycle_report),
109
+ _redundancy_dimension(ws),
110
+ _document_order_dimension(ws),
111
+ _registry_dimension(project_root),
112
+ _consistency_dimension(mesh_report, lifecycle_report),
113
+ )
114
+ return DocumentationSystemAuditReport(dimensions=dimensions)
115
+
116
+
117
+ def render_documentation_system_audit(report: DocumentationSystemAuditReport) -> str:
118
+ lines = ["Documentation system audit", ""]
119
+ for dimension in report.dimensions:
120
+ status = "PASS" if dimension.ok else "FAIL"
121
+ suffix = " (review-only boundary)" if dimension.review_only else ""
122
+ lines.append(f"[{status}] {dimension.name}{suffix}")
123
+ if dimension.findings:
124
+ for finding in dimension.findings:
125
+ lines.append(f"- {finding}")
126
+ else:
127
+ lines.append("- no deterministic findings")
128
+ lines.append("")
129
+ lines.append(f"Overall: {'PASS' if report.ok else 'FAIL'}")
130
+ return "\n".join(lines)
131
+
132
+
133
+ def write_documentation_system_audit_json(
134
+ report: DocumentationSystemAuditReport,
135
+ output_path: Path,
136
+ ) -> None:
137
+ output_path.parent.mkdir(parents=True, exist_ok=True)
138
+ output_path.write_text(json.dumps(report.to_dict(), indent=2, sort_keys=True) + "\n", encoding="utf-8")
139
+
140
+
141
+ def _freshness_dimension(ws: Workspace, mesh_report: Any) -> DocumentationAuditDimension:
142
+ freshness_codes = {"stale-current-state-marker", "version-mismatch", "release-doi-list-mismatch"}
143
+ findings = [
144
+ f"{finding.path}: {finding.message}"
145
+ for finding in mesh_report.findings
146
+ if finding.code in freshness_codes
147
+ ]
148
+ findings.extend(_status_handoff_sync_findings(ws))
149
+ findings.extend(_status_headroom_findings(ws))
150
+ return DocumentationAuditDimension("Aktualität", ok=not findings, findings=tuple(findings))
151
+
152
+
153
+ def _completeness_dimension(ws: Workspace, check_doc_errors: tuple[str, ...]) -> DocumentationAuditDimension:
154
+ missing = [path for path in _required_docs(ws) if not (ws.root / path).exists()]
155
+ findings = [f"missing required documentation file: {path}" for path in missing]
156
+ findings.extend(error for error in check_doc_errors if "missing" in error.lower())
157
+ return DocumentationAuditDimension("Vollständigkeit", ok=not findings, findings=tuple(findings))
158
+
159
+
160
+ def _correctness_dimension(
161
+ check_doc_errors: tuple[str, ...],
162
+ mesh_report: Any,
163
+ lifecycle_report: Any,
164
+ ) -> DocumentationAuditDimension:
165
+ findings = list(check_doc_errors)
166
+ findings.extend(f"doc-mesh:{finding.code}:{finding.path}: {finding.message}" for finding in mesh_report.findings)
167
+ findings.extend(_blocking_lifecycle_findings(lifecycle_report))
168
+ return DocumentationAuditDimension("Korrektheit", ok=not findings, findings=tuple(findings))
169
+
170
+
171
+ def _redundancy_dimension(ws: Workspace) -> DocumentationAuditDimension:
172
+ findings: list[str] = []
173
+ test_gates = _read_optional(ws.test_gates_path())
174
+ if _contains_long_rule_duplication(test_gates):
175
+ findings.append(f"{_workspace_path_text(ws, ws.test_gates_path())} appears to duplicate long rule-book content")
176
+ status = _read_optional(ws.status_path())
177
+ handoff = _read_optional(ws.handoff_file("CURRENT_HANDOFF.md"))
178
+ for path, text in (
179
+ (_workspace_path_text(ws, ws.status_path()), status),
180
+ (_workspace_path_text(ws, ws.handoff_file("CURRENT_HANDOFF.md")), handoff),
181
+ ):
182
+ if "concise pointers, not duplicate rule books" not in text and len(text.split()) > 3500:
183
+ findings.append(f"{path} is long but does not state the concise-pointer boundary")
184
+ boundary = (
185
+ "semantic redundancy-free prose still requires advisory review; "
186
+ "this hard check only catches known structural duplication patterns"
187
+ )
188
+ if not findings:
189
+ findings.append(boundary)
190
+ return DocumentationAuditDimension(
191
+ "Redundanzfreiheit",
192
+ ok=True if findings == [boundary] else False,
193
+ findings=tuple(findings),
194
+ review_only=findings == [boundary],
195
+ )
196
+
197
+
198
+
199
+ def _status_headroom_findings(ws: Workspace) -> tuple[str, ...]:
200
+ status_path = ws.status_path()
201
+ status = _read_optional(status_path)
202
+ words = len(status.split())
203
+ if words > STATUS_HEADROOM_WORD_LIMIT:
204
+ return (f"{_workspace_path_text(ws, status_path)} exceeds headroom limit: {words}/{STATUS_HEADROOM_WORD_LIMIT} words",)
205
+ return ()
206
+
207
+
208
+ def _status_handoff_sync_findings(ws: Workspace) -> tuple[str, ...]:
209
+ status_path = ws.status_path()
210
+ handoff_path = ws.handoff_file("CURRENT_HANDOFF.md")
211
+ status_name = _workspace_path_text(ws, status_path)
212
+ handoff_name = _workspace_path_text(ws, handoff_path)
213
+ status = _read_optional(status_path)
214
+ handoff = _read_optional(handoff_path)
215
+ findings: list[str] = []
216
+ status_prs = set(re.findall(r"PR #\d+ merged", status))
217
+ handoff_prs = set(re.findall(r"PR #\d+ merged", handoff))
218
+ for item in sorted(status_prs - handoff_prs):
219
+ findings.append(f"{handoff_name} missing current closeout marker from STATUS.md: {item}")
220
+ for item in sorted(handoff_prs - status_prs):
221
+ findings.append(f"{status_name} missing current closeout marker from CURRENT_HANDOFF.md: {item}")
222
+ required_handoff_terms = (
223
+ _workspace_path_text(ws, ws.compiled_agent_context_path()),
224
+ "FINAL_SUMMARY_CONTRACT.md",
225
+ "CHAT_COMMUNICATION_CONTRACT.md",
226
+ "CHAT_BOOTSTRAP_AND_DRIFT_CONTRACT.md",
227
+ )
228
+ for term in required_handoff_terms:
229
+ if term not in handoff:
230
+ findings.append(f"{handoff_name} missing mandatory successor-chat source pointer: {term}")
231
+ return tuple(findings)
232
+
233
+
234
+ def _document_order_dimension(ws: Workspace) -> DocumentationAuditDimension:
235
+ findings: list[str] = []
236
+ context = _load_yaml(ws.compiled_agent_context_path())
237
+ configured = tuple(context.get("mandatory_successor_chat_sources", []) or [])
238
+ mandatory_order = _mandatory_order(ws)
239
+ if configured[: len(mandatory_order)] != mandatory_order:
240
+ findings.append("compiled agent context does not preserve the mandatory successor-chat source order")
241
+ for source in mandatory_order:
242
+ if source not in configured:
243
+ findings.append(f"mandatory successor-chat source missing from compiled context: {source}")
244
+ if not (ws.root / source).exists():
245
+ findings.append(f"mandatory successor-chat source file missing: {source}")
246
+ return DocumentationAuditDimension("Stringenz der Dokumentenordnung", ok=not findings, findings=tuple(findings))
247
+
248
+
249
+ def _registry_dimension(project_root: Path) -> DocumentationAuditDimension:
250
+ try:
251
+ summary = build_documentation_registry_summary(project_root)
252
+ except (OSError, ValueError, yaml.YAMLError) as exc:
253
+ return DocumentationAuditDimension(
254
+ "Dokumentationsregistry",
255
+ ok=False,
256
+ findings=(f"registry summary unavailable: {exc}",),
257
+ )
258
+
259
+ findings = [
260
+ f"registry={summary['registry_path']}",
261
+ f"version={summary['version']}",
262
+ f"documents={summary['document_count']}",
263
+ f"broad_migration_allowed={summary['broad_migration_allowed']}",
264
+ ]
265
+ class_counts = summary.get("class_counts", {})
266
+ if isinstance(class_counts, dict):
267
+ for class_name, count in class_counts.items():
268
+ findings.append(f"class:{class_name}={count}")
269
+ return DocumentationAuditDimension(
270
+ "Dokumentationsregistry",
271
+ ok=summary.get("version") == 1 and bool(summary.get("document_count")),
272
+ findings=tuple(findings),
273
+ )
274
+
275
+
276
+ def _consistency_dimension(mesh_report: Any, lifecycle_report: Any) -> DocumentationAuditDimension:
277
+ findings = [
278
+ f"doc-mesh:{finding.code}:{finding.path}: {finding.message}" for finding in mesh_report.findings
279
+ ]
280
+ findings.extend(_blocking_lifecycle_findings(lifecycle_report))
281
+ return DocumentationAuditDimension("Konsistenz", ok=not findings, findings=tuple(findings))
282
+
283
+
284
+ def _blocking_lifecycle_findings(lifecycle_report: Any) -> list[str]:
285
+ return [
286
+ f"doc-lifecycle:{finding.code}:{finding.path}: {finding.message}"
287
+ for finding in lifecycle_report.findings
288
+ if getattr(finding, "severity", "FAIL") in {"FAIL", "BLOCK"}
289
+ ]
290
+
291
+
292
+ def _contains_long_rule_duplication(text: str) -> bool:
293
+ if "## LLM Communication and Bootstrap Gate" not in text:
294
+ return False
295
+ section = text.split("## LLM Communication and Bootstrap Gate", 1)[1]
296
+ next_section = section.split("\n## ", 1)[0]
297
+ return len(next_section.split()) > 450
298
+
299
+
300
+ def _read_optional(path: Path) -> str:
301
+ if not path.exists():
302
+ return ""
303
+ return path.read_text(encoding="utf-8")
304
+
305
+
306
+ def _load_yaml(path: Path) -> dict[str, Any]:
307
+ if not path.exists():
308
+ return {}
309
+ content = yaml.safe_load(path.read_text(encoding="utf-8"))
310
+ return content if isinstance(content, dict) else {}