@renoxar/koolie 1.25.0

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 (693) hide show
  1. package/.gitattributes +16 -0
  2. package/.gitignore +51 -0
  3. package/.koolie/QUELLREPOSITORIUM.md +18 -0
  4. package/.koolie/core/CHANGELOG.md +11832 -0
  5. package/.koolie/core/LICENSE +674 -0
  6. package/.koolie/core/LICENSE-HINWEIS.md +98 -0
  7. package/.koolie/core/OWNERS.md +36 -0
  8. package/.koolie/core/VERSION +1 -0
  9. package/.koolie/core/banner.py +397 -0
  10. package/.koolie/core/build/README.md +34 -0
  11. package/.koolie/core/build/assemble.py +354 -0
  12. package/.koolie/core/build/build-docx.py +194 -0
  13. package/.koolie/core/build/doc/00-kopf.md +18 -0
  14. package/.koolie/core/build/doc/01-executive-summary.md +24 -0
  15. package/.koolie/core/build/doc/02-zielbild.md +13 -0
  16. package/.koolie/core/build/doc/03-ziele-nichtziele.md +28 -0
  17. package/.koolie/core/build/doc/04-geltungsbereich.md +25 -0
  18. package/.koolie/core/build/doc/05-glossar.md +47 -0
  19. package/.koolie/core/build/doc/06-leitprinzipien.md +5 -0
  20. package/.koolie/core/build/doc/07-architektur.md +60 -0
  21. package/.koolie/core/build/doc/07a-abbildungsschicht.md +66 -0
  22. package/.koolie/core/build/doc/08-trennung.md +24 -0
  23. package/.koolie/core/build/doc/09-betriebsmodi.md +18 -0
  24. package/.koolie/core/build/doc/10-arbeitsablauf.md +5 -0
  25. package/.koolie/core/build/doc/11-datenschutz.md +5 -0
  26. package/.koolie/core/build/doc/12-sicherheit.md +5 -0
  27. package/.koolie/core/build/doc/13-risiko.md +5 -0
  28. package/.koolie/core/build/doc/14-rollen.md +9 -0
  29. package/.koolie/core/build/doc/15-referenzstruktur.md +124 -0
  30. package/.koolie/core/build/doc/16-agentenanweisung.md +8 -0
  31. package/.koolie/core/build/doc/17-overlay.md +29 -0
  32. package/.koolie/core/build/doc/18-skill-standard.md +5 -0
  33. package/.koolie/core/build/doc/19-skill-template.md +5 -0
  34. package/.koolie/core/build/doc/20-referenz-skills.md +70 -0
  35. package/.koolie/core/build/doc/21-prompts.md +53 -0
  36. package/.koolie/core/build/doc/22-checklisten.md +49 -0
  37. package/.koolie/core/build/doc/23-entscheidungsbaeume.md +29 -0
  38. package/.koolie/core/build/doc/24-onboarding.md +33 -0
  39. package/.koolie/core/build/doc/25-governance.md +35 -0
  40. package/.koolie/core/build/doc/26-qs-test.md +9 -0
  41. package/.koolie/core/build/doc/27-pilot.md +13 -0
  42. package/.koolie/core/build/doc/28-uebernahme.md +5 -0
  43. package/.koolie/core/build/doc/29-grenzen.md +87 -0
  44. package/.koolie/core/build/doc/30-roadmap.md +5 -0
  45. package/.koolie/core/build/doc/31-anhaenge.md +151 -0
  46. package/.koolie/core/build/doc/32-abschluss.md +92 -0
  47. package/.koolie/core/build/ref-a4.docx +0 -0
  48. package/.koolie/core/checklists/01-preflight.md +54 -0
  49. package/.koolie/core/checklists/02-privacy-context.md +51 -0
  50. package/.koolie/core/checklists/03-before-code-change.md +51 -0
  51. package/.koolie/core/checklists/04-review-ai-code.md +58 -0
  52. package/.koolie/core/checklists/05-testing.md +48 -0
  53. package/.koolie/core/checklists/06-security.md +50 -0
  54. package/.koolie/core/checklists/07-new-dependency.md +57 -0
  55. package/.koolie/core/checklists/08-merge-request.md +47 -0
  56. package/.koolie/core/checklists/09-onboarding.md +52 -0
  57. package/.koolie/core/checklists/10-project-adoption.md +74 -0
  58. package/.koolie/core/checklists/11-framework-release.md +71 -0
  59. package/.koolie/core/checklists/README.md +28 -0
  60. package/.koolie/core/clientmap.py +1358 -0
  61. package/.koolie/core/clients/README.md +113 -0
  62. package/.koolie/core/clients/_template/CLIENT_PACK.md +197 -0
  63. package/.koolie/core/clients/claude-code/CLIENT_PACK.md +383 -0
  64. package/.koolie/core/clients/claude-code/manifest.json +232 -0
  65. package/.koolie/core/clients/claude-code/root-template/.claude/README.md +127 -0
  66. package/.koolie/core/clients/cursor/CLIENT_PACK.md +229 -0
  67. package/.koolie/core/clients/cursor/manifest.json +330 -0
  68. package/.koolie/core/clients/cursor/root-template/.cursor/README.md +36 -0
  69. package/.koolie/core/clients/devin-desktop/CLIENT_PACK.md +251 -0
  70. package/.koolie/core/clients/devin-desktop/manifest.json +163 -0
  71. package/.koolie/core/clients/devin-desktop/root-template/.devin/README.md +79 -0
  72. package/.koolie/core/clients/kiro/CLIENT_PACK.md +223 -0
  73. package/.koolie/core/clients/kiro/manifest.json +300 -0
  74. package/.koolie/core/clients/kiro/root-template/.kiro/README.md +37 -0
  75. package/.koolie/core/clients/openai-codex/CLIENT_PACK.md +257 -0
  76. package/.koolie/core/clients/openai-codex/manifest.json +208 -0
  77. package/.koolie/core/clients/openai-codex/root-template/.codex/README.md +35 -0
  78. package/.koolie/core/decision-trees/01-context-allowed.md +46 -0
  79. package/.koolie/core/decision-trees/02-may-ai-do-task.md +47 -0
  80. package/.koolie/core/decision-trees/03-analyze-or-modify.md +50 -0
  81. package/.koolie/core/decision-trees/04-required-review.md +49 -0
  82. package/.koolie/core/decision-trees/05-stop-or-escalate.md +47 -0
  83. package/.koolie/core/decision-trees/06-rule-placement.md +58 -0
  84. package/.koolie/core/decision-trees/README.md +14 -0
  85. package/.koolie/core/docs/ADOPTION_GUIDE.md +582 -0
  86. package/.koolie/core/docs/DOCUMENTATION_STANDARD.md +91 -0
  87. package/.koolie/core/docs/PLACEHOLDER_REGISTRY.md +79 -0
  88. package/.koolie/core/docs/ROADMAP.md +848 -0
  89. package/.koolie/core/docs/RUNTIME_GLOSSARY.md +113 -0
  90. package/.koolie/core/examples/README.md +11 -0
  91. package/.koolie/core/examples/example-ergebnisbericht.md +31 -0
  92. package/.koolie/core/examples/example-mr-description.md +31 -0
  93. package/.koolie/core/examples/example-overlay-runtime.md +48 -0
  94. package/.koolie/core/framework/core/00-principles.md +93 -0
  95. package/.koolie/core/framework/core/01-governance.md +58 -0
  96. package/.koolie/core/framework/core/02-privacy.md +141 -0
  97. package/.koolie/core/framework/core/03-security.md +86 -0
  98. package/.koolie/core/framework/core/04-quality.md +48 -0
  99. package/.koolie/core/framework/core/05-working-model.md +199 -0
  100. package/.koolie/core/framework/core/06-prompting-rules.md +51 -0
  101. package/.koolie/core/framework/core/07-review-rules.md +52 -0
  102. package/.koolie/core/framework/core/08-skill-conventions.md +115 -0
  103. package/.koolie/core/framework/core/09-risk-model.md +87 -0
  104. package/.koolie/core/framework/core/10-error-escalation.md +53 -0
  105. package/.koolie/core/framework/org-policies/MAPPING_CLASSIFICATION.md +16 -0
  106. package/.koolie/core/framework/org-policies/README.md +29 -0
  107. package/.koolie/core/framework/overlay-patterns/general/documents/branching-strategy/muster-general.md +43 -0
  108. package/.koolie/core/framework/overlay-patterns/general/documents/coding-guidelines/muster-general.md +82 -0
  109. package/.koolie/core/framework/overlay-patterns/general/documents/definition-of-done/muster-general.md +52 -0
  110. package/.koolie/core/framework/overlay-patterns/general/documents/definition-of-ready/muster-general.md +54 -0
  111. package/.koolie/core/framework/overlay-patterns/general/documents/quality/muster-general.md +59 -0
  112. package/.koolie/core/framework/overlay-patterns/general/documents/security/muster-general.md +52 -0
  113. package/.koolie/core/framework/overlay-patterns/general.md +150 -0
  114. package/.koolie/core/framework/role-packs/README.md +63 -0
  115. package/.koolie/core/framework/role-packs/_template/ROLE_PACK.md +58 -0
  116. package/.koolie/core/framework/role-packs/requirements-engineering/ROLE_PACK.md +158 -0
  117. package/.koolie/core/framework/role-packs/requirements-engineering/runtime/30-role-requirements-engineering.md +88 -0
  118. package/.koolie/core/framework/role-packs/requirements-engineering/skills/role-re-ticket/CHANGELOG.md +10 -0
  119. package/.koolie/core/framework/role-packs/requirements-engineering/skills/role-re-ticket/EXAMPLES.md +148 -0
  120. package/.koolie/core/framework/role-packs/requirements-engineering/skills/role-re-ticket/SKILL.md +195 -0
  121. package/.koolie/core/framework/role-packs/requirements-engineering/skills/role-re-ticket/TESTS.md +22 -0
  122. package/.koolie/core/framework/role-packs/software-development/ROLE_PACK.md +95 -0
  123. package/.koolie/core/framework/role-packs/software-development/runtime/30-role-software-development.md +26 -0
  124. package/.koolie/core/framework/runtime/agents/fw-reviewer.md +34 -0
  125. package/.koolie/core/framework/runtime/client-settings.json +3 -0
  126. package/.koolie/core/framework/runtime/hooks.json +20 -0
  127. package/.koolie/core/framework/runtime/mcp-config.example.json +4 -0
  128. package/.koolie/core/framework/runtime/permissions.json +106 -0
  129. package/.koolie/core/framework/runtime/root-instruction-local.example.md +19 -0
  130. package/.koolie/core/framework/runtime/root-instruction.md +116 -0
  131. package/.koolie/core/framework/runtime/rules/00-framework-core.md +49 -0
  132. package/.koolie/core/framework/runtime/rules/10-privacy-security.md +49 -0
  133. package/.koolie/core/framework/runtime/rules/15-development-rules.md +41 -0
  134. package/.koolie/core/framework/runtime/rules/16-plan-spezifikation.md +32 -0
  135. package/.koolie/core/framework/runtime/rules/20-project-overlay.md +60 -0
  136. package/.koolie/core/framework/skills/fw-bugfix-prepare/CHANGELOG.md +14 -0
  137. package/.koolie/core/framework/skills/fw-bugfix-prepare/EXAMPLES.md +57 -0
  138. package/.koolie/core/framework/skills/fw-bugfix-prepare/SKILL.md +177 -0
  139. package/.koolie/core/framework/skills/fw-bugfix-prepare/TESTS.md +15 -0
  140. package/.koolie/core/framework/skills/fw-change-analyze/CHANGELOG.md +12 -0
  141. package/.koolie/core/framework/skills/fw-change-analyze/EXAMPLES.md +66 -0
  142. package/.koolie/core/framework/skills/fw-change-analyze/SKILL.md +167 -0
  143. package/.koolie/core/framework/skills/fw-change-analyze/TESTS.md +16 -0
  144. package/.koolie/core/framework/skills/fw-change-small/CHANGELOG.md +13 -0
  145. package/.koolie/core/framework/skills/fw-change-small/EXAMPLES.md +68 -0
  146. package/.koolie/core/framework/skills/fw-change-small/SKILL.md +175 -0
  147. package/.koolie/core/framework/skills/fw-change-small/TESTS.md +13 -0
  148. package/.koolie/core/framework/skills/fw-code-explain/CHANGELOG.md +11 -0
  149. package/.koolie/core/framework/skills/fw-code-explain/EXAMPLES.md +61 -0
  150. package/.koolie/core/framework/skills/fw-code-explain/SKILL.md +163 -0
  151. package/.koolie/core/framework/skills/fw-code-explain/TESTS.md +11 -0
  152. package/.koolie/core/framework/skills/fw-docs-update/CHANGELOG.md +10 -0
  153. package/.koolie/core/framework/skills/fw-docs-update/EXAMPLES.md +59 -0
  154. package/.koolie/core/framework/skills/fw-docs-update/SKILL.md +160 -0
  155. package/.koolie/core/framework/skills/fw-docs-update/TESTS.md +12 -0
  156. package/.koolie/core/framework/skills/fw-error-analyze/CHANGELOG.md +10 -0
  157. package/.koolie/core/framework/skills/fw-error-analyze/EXAMPLES.md +67 -0
  158. package/.koolie/core/framework/skills/fw-error-analyze/SKILL.md +160 -0
  159. package/.koolie/core/framework/skills/fw-error-analyze/TESTS.md +12 -0
  160. package/.koolie/core/framework/skills/fw-mr-description/CHANGELOG.md +12 -0
  161. package/.koolie/core/framework/skills/fw-mr-description/EXAMPLES.md +69 -0
  162. package/.koolie/core/framework/skills/fw-mr-description/SKILL.md +170 -0
  163. package/.koolie/core/framework/skills/fw-mr-description/TESTS.md +12 -0
  164. package/.koolie/core/framework/skills/fw-overlay-pflege/CHANGELOG.md +7 -0
  165. package/.koolie/core/framework/skills/fw-overlay-pflege/EXAMPLES.md +48 -0
  166. package/.koolie/core/framework/skills/fw-overlay-pflege/SKILL.md +147 -0
  167. package/.koolie/core/framework/skills/fw-overlay-pflege/TESTS.md +13 -0
  168. package/.koolie/core/framework/skills/fw-plan/CHANGELOG.md +14 -0
  169. package/.koolie/core/framework/skills/fw-plan/EXAMPLES.md +69 -0
  170. package/.koolie/core/framework/skills/fw-plan/SKILL.md +168 -0
  171. package/.koolie/core/framework/skills/fw-plan/TESTS.md +14 -0
  172. package/.koolie/core/framework/skills/fw-refactor/CHANGELOG.md +10 -0
  173. package/.koolie/core/framework/skills/fw-refactor/EXAMPLES.md +70 -0
  174. package/.koolie/core/framework/skills/fw-refactor/SKILL.md +173 -0
  175. package/.koolie/core/framework/skills/fw-refactor/TESTS.md +14 -0
  176. package/.koolie/core/framework/skills/fw-repo-analyze/CHANGELOG.md +10 -0
  177. package/.koolie/core/framework/skills/fw-repo-analyze/EXAMPLES.md +52 -0
  178. package/.koolie/core/framework/skills/fw-repo-analyze/SKILL.md +149 -0
  179. package/.koolie/core/framework/skills/fw-repo-analyze/TESTS.md +11 -0
  180. package/.koolie/core/framework/skills/fw-review-support/CHANGELOG.md +12 -0
  181. package/.koolie/core/framework/skills/fw-review-support/EXAMPLES.md +69 -0
  182. package/.koolie/core/framework/skills/fw-review-support/SKILL.md +179 -0
  183. package/.koolie/core/framework/skills/fw-review-support/TESTS.md +13 -0
  184. package/.koolie/core/framework/skills/fw-tests/CHANGELOG.md +9 -0
  185. package/.koolie/core/framework/skills/fw-tests/EXAMPLES.md +65 -0
  186. package/.koolie/core/framework/skills/fw-tests/SKILL.md +169 -0
  187. package/.koolie/core/framework/skills/fw-tests/TESTS.md +12 -0
  188. package/.koolie/core/framework/tech-packs/README.md +15 -0
  189. package/.koolie/core/framework/tech-packs/_template/TECH_PACK.md +61 -0
  190. package/.koolie/core/governance/ADOPTION_REGISTRY.md +89 -0
  191. package/.koolie/core/governance/CHANGE_REQUEST_TEMPLATE.md +60 -0
  192. package/.koolie/core/governance/DECISION_LOG.md +779 -0
  193. package/.koolie/core/governance/EXCEPTION_PROCESS.md +31 -0
  194. package/.koolie/core/governance/FEEDBACK_PROCESS.md +34 -0
  195. package/.koolie/core/governance/FRAMEWORK_DEV_PROFILE.md +135 -0
  196. package/.koolie/core/governance/INCIDENT_HANDLING.md +47 -0
  197. package/.koolie/core/governance/PRIORITY_HIERARCHY.md +61 -0
  198. package/.koolie/core/governance/RACI.md +37 -0
  199. package/.koolie/core/governance/RELEASE_PROCESS.md +183 -0
  200. package/.koolie/core/governance/change-requests/CR-2026-001-definition-release-1-0-0.md +67 -0
  201. package/.koolie/core/governance/change-requests/CR-2026-002-client-packs.md +63 -0
  202. package/.koolie/core/governance/change-requests/CR-2026-003-install-client-schalter.md +70 -0
  203. package/.koolie/core/governance/change-requests/CR-2026-004-client-pack-claude-code.md +82 -0
  204. package/.koolie/core/governance/change-requests/CR-2026-005-kern-neutralisierung.md +75 -0
  205. package/.koolie/core/governance/change-requests/CR-2026-006-gemeinsame-skill-quelle.md +77 -0
  206. package/.koolie/core/governance/change-requests/CR-2026-007-geteilte-kernbestandteile.md +80 -0
  207. package/.koolie/core/governance/change-requests/CR-2026-008-berechtigungen-und-hooks.md +85 -0
  208. package/.koolie/core/governance/change-requests/CR-2026-009-umbenennung-leitwerk.md +77 -0
  209. package/.koolie/core/governance/change-requests/CR-2026-010-restduplikation.md +73 -0
  210. package/.koolie/core/governance/change-requests/CR-2026-011-hauptdokument.md +72 -0
  211. package/.koolie/core/governance/change-requests/CR-2026-012-schreibschutz-kernverzeichnis.md +106 -0
  212. package/.koolie/core/governance/change-requests/CR-2026-013-validator-blindstellen.md +128 -0
  213. package/.koolie/core/governance/change-requests/CR-2026-014-kurzform-langform.md +125 -0
  214. package/.koolie/core/governance/change-requests/CR-2026-015-versionskette.md +150 -0
  215. package/.koolie/core/governance/change-requests/CR-2026-016-ap2-claude-code.md +127 -0
  216. package/.koolie/core/governance/change-requests/CR-2026-017-ladebedingungen-claude-code.md +173 -0
  217. package/.koolie/core/governance/change-requests/CR-2026-018-quellenliste-claude-code.md +121 -0
  218. package/.koolie/core/governance/change-requests/CR-2026-019-strukturentscheidungen-fortschreiben.md +143 -0
  219. package/.koolie/core/governance/change-requests/CR-2026-020-akteursbezeichnung.md +118 -0
  220. package/.koolie/core/governance/change-requests/CR-2026-021-hook-interpreter.md +113 -0
  221. package/.koolie/core/governance/change-requests/CR-2026-022-artefaktversionen.md +73 -0
  222. package/.koolie/core/governance/change-requests/CR-2026-023-shell-lesesperre.md +128 -0
  223. package/.koolie/core/governance/change-requests/CR-2026-024-clientbindungen.md +78 -0
  224. package/.koolie/core/governance/change-requests/CR-2026-025-betriebsmodi.md +110 -0
  225. package/.koolie/core/governance/change-requests/CR-2026-026-fail-closed.md +134 -0
  226. package/.koolie/core/governance/change-requests/CR-2026-027-zeichenlimit-einstufung.md +105 -0
  227. package/.koolie/core/governance/change-requests/CR-2026-028-berechtigungsmodi.md +130 -0
  228. package/.koolie/core/governance/change-requests/CR-2026-029-hook-ablageort.md +115 -0
  229. package/.koolie/core/governance/change-requests/CR-2026-030-lesende-werkzeuge.md +143 -0
  230. package/.koolie/core/governance/change-requests/CR-2026-031-regelquellen-ausserhalb.md +182 -0
  231. package/.koolie/core/governance/change-requests/CR-2026-032-fremde-skill-ablage.md +151 -0
  232. package/.koolie/core/governance/change-requests/CR-2026-033-modusabhaengige-durchsetzung.md +131 -0
  233. package/.koolie/core/governance/change-requests/CR-2026-034-nachweisbedingungen.md +116 -0
  234. package/.koolie/core/governance/change-requests/CR-2026-035-readme-in-der-regelablage.md +115 -0
  235. package/.koolie/core/governance/change-requests/CR-2026-036-ortsangaben-hook-konfiguration.md +108 -0
  236. package/.koolie/core/governance/change-requests/CR-2026-037-meldender-hook-clientgebunden.md +133 -0
  237. package/.koolie/core/governance/change-requests/CR-2026-038-importsteuerung.md +159 -0
  238. package/.koolie/core/governance/change-requests/CR-2026-039-normative-saetze-in-kommentaren.md +124 -0
  239. package/.koolie/core/governance/change-requests/CR-2026-040-erh01-ist-clientgebunden.md +115 -0
  240. package/.koolie/core/governance/change-requests/CR-2026-041-s5-nicht-abbildbar.md +128 -0
  241. package/.koolie/core/governance/change-requests/CR-2026-042-abwesenheitsnachweis-suchwerkzeug.md +102 -0
  242. package/.koolie/core/governance/change-requests/CR-2026-043-validator-gibt-trefferwerte-aus.md +135 -0
  243. package/.koolie/core/governance/change-requests/CR-2026-044-aktivierungspruefung-clientgebunden.md +112 -0
  244. package/.koolie/core/governance/change-requests/CR-2026-045-update-verliert-die-clientwahl.md +116 -0
  245. package/.koolie/core/governance/change-requests/CR-2026-046-erstinstallation-ueberschreibt-projektdatei.md +125 -0
  246. package/.koolie/core/governance/change-requests/CR-2026-047-zusagen-je-zugriffskanal.md +133 -0
  247. package/.koolie/core/governance/change-requests/CR-2026-048-modusgrenze-ohne-durchsetzung.md +137 -0
  248. package/.koolie/core/governance/change-requests/CR-2026-049-sondenlauf-kodierungsabhaengig.md +126 -0
  249. package/.koolie/core/governance/change-requests/CR-2026-050-allowed-tools-und-verworfene-permissions.md +110 -0
  250. package/.koolie/core/governance/change-requests/CR-2026-051-quellenkarte-und-ueberholter-stand.md +110 -0
  251. package/.koolie/core/governance/change-requests/CR-2026-052-drei-regelkonflikte.md +166 -0
  252. package/.koolie/core/governance/change-requests/CR-2026-053-lesesperre-und-entwicklungsprofil.md +144 -0
  253. package/.koolie/core/governance/change-requests/CR-2026-054-aktivierung-verlangt-aktivitaet.md +124 -0
  254. package/.koolie/core/governance/change-requests/CR-2026-055-domain-ausnahme-ohne-mechanismus.md +173 -0
  255. package/.koolie/core/governance/change-requests/CR-2026-056-eingabeschema-und-pfadidentitaet.md +245 -0
  256. package/.koolie/core/governance/change-requests/CR-2026-057-disallowed-tools-und-s3.md +148 -0
  257. package/.koolie/core/governance/change-requests/CR-2026-058-unteragent-reichweite.md +203 -0
  258. package/.koolie/core/governance/change-requests/CR-2026-059-unteragent-tiefe-und-widerspruch.md +125 -0
  259. package/.koolie/core/governance/change-requests/CR-2026-060-stumme-brueche.md +170 -0
  260. package/.koolie/core/governance/change-requests/CR-2026-061-berechtigungsdatei-ohne-pruefung.md +169 -0
  261. package/.koolie/core/governance/change-requests/CR-2026-062-werkzeugabbildung-des-frontmatters.md +178 -0
  262. package/.koolie/core/governance/change-requests/CR-2026-063-skillaufruf-ohne-freigabe.md +207 -0
  263. package/.koolie/core/governance/change-requests/CR-2026-064-pruefregister-nicht-nachgezaehlt.md +141 -0
  264. package/.koolie/core/governance/change-requests/CR-2026-065-devin-suchwerkzeuge-erhoben.md +170 -0
  265. package/.koolie/core/governance/change-requests/CR-2026-066-schlitzdeckung-ohne-abgleich.md +153 -0
  266. package/.koolie/core/governance/change-requests/CR-2026-067-hookblock-und-praeparationsregister.md +140 -0
  267. package/.koolie/core/governance/change-requests/CR-2026-068-sondenlauf-nebenlaeufig.md +106 -0
  268. package/.koolie/core/governance/change-requests/CR-2026-069-bytecode-des-kerns.md +108 -0
  269. package/.koolie/core/governance/change-requests/CR-2026-070-d11-zaehler.md +114 -0
  270. package/.koolie/core/governance/change-requests/CR-2026-071-strukturentscheidungen-bestaetigen.md +322 -0
  271. package/.koolie/core/governance/change-requests/CR-2026-072-modulstatus-heben.md +315 -0
  272. package/.koolie/core/governance/change-requests/CR-2026-073-nicht-skill-traeger-heben.md +246 -0
  273. package/.koolie/core/governance/change-requests/CR-2026-074-restliche-nicht-skill-traeger-heben.md +271 -0
  274. package/.koolie/core/governance/change-requests/CR-2026-075-ap2-zielversion-devin-desktop.md +335 -0
  275. package/.koolie/core/governance/change-requests/CR-2026-076-erster-sitzungstest.md +455 -0
  276. package/.koolie/core/governance/change-requests/CR-2026-077-sitzungstest-schranken.md +425 -0
  277. package/.koolie/core/governance/change-requests/CR-2026-078-planung-nach-1-0-0.md +294 -0
  278. package/.koolie/core/governance/change-requests/CR-2026-079-umbenennung-vorziehen.md +233 -0
  279. package/.koolie/core/governance/change-requests/CR-2026-080-clientbindung-des-kerns.md +321 -0
  280. package/.koolie/core/governance/change-requests/CR-2026-081-produktnamen-im-kern.md +297 -0
  281. package/.koolie/core/governance/change-requests/CR-2026-082-sitzungstest-pi-ds-2.md +145 -0
  282. package/.koolie/core/governance/change-requests/CR-2026-083-sitzungstest-ne-sc.md +300 -0
  283. package/.koolie/core/governance/change-requests/CR-2026-084-trockenlauf-gegen-den-committeten-stand.md +117 -0
  284. package/.koolie/core/governance/change-requests/CR-2026-085-vorbedingungen-sitzungstest-5.md +182 -0
  285. package/.koolie/core/governance/change-requests/CR-2026-086-grenzfaelle-gegen-die-fassungen.md +164 -0
  286. package/.koolie/core/governance/change-requests/CR-2026-087-produktbeobachtung-quellenliste.md +206 -0
  287. package/.koolie/core/governance/change-requests/CR-2026-088-vorbedingungen-testblaetter.md +127 -0
  288. package/.koolie/core/governance/change-requests/CR-2026-089-herrichtung-uebungsrepositorium.md +226 -0
  289. package/.koolie/core/governance/change-requests/CR-2026-090-vorbedingungen-sitzungstest-5-zweiter-durchgang.md +255 -0
  290. package/.koolie/core/governance/change-requests/CR-2026-091-sitzungstest-5.md +163 -0
  291. package/.koolie/core/governance/change-requests/CR-2026-092-pruefmittelwort-und-buendelschnitt.md +226 -0
  292. package/.koolie/core/governance/change-requests/CR-2026-093-sechzehnte-praeparation.md +151 -0
  293. package/.koolie/core/governance/change-requests/CR-2026-094-testblaetter-buendel-1.md +113 -0
  294. package/.koolie/core/governance/change-requests/CR-2026-095-pruefapparat-filter.md +65 -0
  295. package/.koolie/core/governance/change-requests/CR-2026-096-vorbedingungen-buendel-2.md +225 -0
  296. package/.koolie/core/governance/change-requests/CR-2026-097-testblaetter-buendel-2.md +162 -0
  297. package/.koolie/core/governance/change-requests/CR-2026-098-anforderungen-auslieferung.md +93 -0
  298. package/.koolie/core/governance/change-requests/CR-2026-099-k74-und-vorbedingungen-buendel-3.md +119 -0
  299. package/.koolie/core/governance/change-requests/CR-2026-100-testblaetter-buendel-3.md +120 -0
  300. package/.koolie/core/governance/change-requests/CR-2026-101-k77-eigener-posten.md +165 -0
  301. package/.koolie/core/governance/change-requests/CR-2026-102-k77-entschieden.md +118 -0
  302. package/.koolie/core/governance/change-requests/CR-2026-103-vorbedingungen-buendel-4.md +76 -0
  303. package/.koolie/core/governance/change-requests/CR-2026-104-herrichtung-buendel-4.md +82 -0
  304. package/.koolie/core/governance/change-requests/CR-2026-105-messapparat-buendel-4.md +227 -0
  305. package/.koolie/core/governance/change-requests/CR-2026-106-uebergabe-einchecken.md +91 -0
  306. package/.koolie/core/governance/change-requests/CR-2026-107-uebergabe-im-release-commit.md +111 -0
  307. package/.koolie/core/governance/change-requests/CR-2026-108-testblaetter-buendel-4.md +118 -0
  308. package/.koolie/core/governance/change-requests/CR-2026-109-berichtsweg-des-aufraeumers.md +108 -0
  309. package/.koolie/core/governance/change-requests/CR-2026-110-vorbedingungen-des-nachlaufs.md +184 -0
  310. package/.koolie/core/governance/change-requests/CR-2026-111-der-apparat-auf-dem-weg-der-wiederaufnahme.md +127 -0
  311. package/.koolie/core/governance/change-requests/CR-2026-112-der-arbeitsplatz-im-kern.md +103 -0
  312. package/.koolie/core/governance/change-requests/CR-2026-113-nachlauf-buendel-4.md +103 -0
  313. package/.koolie/core/governance/change-requests/CR-2026-114-vorbedingungen-buendel-5.md +317 -0
  314. package/.koolie/core/governance/change-requests/CR-2026-115-herrichtung-buendel-5.md +244 -0
  315. package/.koolie/core/governance/change-requests/CR-2026-116-messtag-buendel-5.md +178 -0
  316. package/.koolie/core/governance/change-requests/CR-2026-117-sammelzellen-zentraler-katalog.md +251 -0
  317. package/.koolie/core/governance/change-requests/CR-2026-118-quellenzuordnung-matrixzeilen.md +115 -0
  318. package/.koolie/core/governance/change-requests/CR-2026-119-umbenennung-koolie.md +204 -0
  319. package/.koolie/core/governance/change-requests/CR-2026-120-ap2-rest-devin-desktop.md +96 -0
  320. package/.koolie/core/governance/change-requests/CR-2026-121-verify-marker-abschaffen.md +185 -0
  321. package/.koolie/core/governance/change-requests/CR-2026-122-umbenennung-koolie-lauf.md +131 -0
  322. package/.koolie/core/governance/change-requests/CR-2026-123-vortrag-und-namensabsatz.md +170 -0
  323. package/.koolie/core/governance/change-requests/CR-2026-124-hauptdokument-ap11.md +237 -0
  324. package/.koolie/core/governance/change-requests/CR-2026-125-word-fassung-und-blinder-fleck.md +204 -0
  325. package/.koolie/core/governance/change-requests/CR-2026-126-lizenz-gpl3.md +112 -0
  326. package/.koolie/core/governance/change-requests/CR-2026-127-gegenzeichnung-rollenfrage.md +96 -0
  327. package/.koolie/core/governance/change-requests/CR-2026-128-freigabelauf-1.0.0.md +278 -0
  328. package/.koolie/core/governance/change-requests/CR-2026-129-archiv-zeilenenden.md +90 -0
  329. package/.koolie/core/governance/change-requests/CR-2026-130-reihenfolge-des-hebens.md +204 -0
  330. package/.koolie/core/governance/change-requests/CR-2026-131-chronik-und-vorlage.md +194 -0
  331. package/.koolie/core/governance/change-requests/CR-2026-132-erhebung-openai-codex.md +185 -0
  332. package/.koolie/core/governance/change-requests/CR-2026-133-bau-openai-codex.md +97 -0
  333. package/.koolie/core/governance/change-requests/CR-2026-134-uebergabe-lokal.md +117 -0
  334. package/.koolie/core/governance/change-requests/CR-2026-135-pfadlisten-nul-getrennt.md +139 -0
  335. package/.koolie/core/governance/change-requests/CR-2026-136-overlay-werte-einordnung.md +156 -0
  336. package/.koolie/core/governance/change-requests/CR-2026-137-kopierweg-kern.md +144 -0
  337. package/.koolie/core/governance/change-requests/CR-2026-138-overlay-muster-general.md +118 -0
  338. package/.koolie/core/governance/change-requests/CR-2026-139-overlay-muster-dokumente.md +105 -0
  339. package/.koolie/core/governance/change-requests/CR-2026-140-installer-je-zielsystem.md +120 -0
  340. package/.koolie/core/governance/change-requests/CR-2026-141-lieferumfang.md +123 -0
  341. package/.koolie/core/governance/change-requests/CR-2026-142-dokumentationsstandard.md +90 -0
  342. package/.koolie/core/governance/change-requests/CR-2026-143-klasse-b-core-laufzeit.md +89 -0
  343. package/.koolie/core/governance/change-requests/CR-2026-144-klasse-b-governance.md +90 -0
  344. package/.koolie/core/governance/change-requests/CR-2026-145-klasse-b-skills.md +81 -0
  345. package/.koolie/core/governance/change-requests/CR-2026-146-code-pack-posten.md +84 -0
  346. package/.koolie/core/governance/change-requests/CR-2026-147-regel-register-posten.md +78 -0
  347. package/.koolie/core/governance/change-requests/CR-2026-148-mehrprojekt-tokenlast.md +70 -0
  348. package/.koolie/core/governance/change-requests/CR-2026-149-regelablage-pfadtoken.md +71 -0
  349. package/.koolie/core/governance/change-requests/CR-2026-150-client-pack-kiro.md +76 -0
  350. package/.koolie/core/governance/change-requests/CR-2026-151-skill-anweisungen.md +71 -0
  351. package/.koolie/core/governance/change-requests/CR-2026-152-testblaetter-modellwechsel.md +78 -0
  352. package/.koolie/core/governance/change-requests/CR-2026-153-attributionszeile.md +88 -0
  353. package/.koolie/core/governance/change-requests/CR-2026-154-auffindbarkeit.md +102 -0
  354. package/.koolie/core/governance/change-requests/CR-2026-155-client-pack-cursor.md +80 -0
  355. package/.koolie/core/governance/change-requests/CR-2026-156-mandat-und-reibung.md +100 -0
  356. package/.koolie/core/governance/change-requests/CR-2026-157-mcp-anbindung.md +93 -0
  357. package/.koolie/core/governance/change-requests/CR-2026-158-registerpflege.md +69 -0
  358. package/.koolie/core/governance/change-requests/CR-2026-159-powershell.md +49 -0
  359. package/.koolie/core/governance/change-requests/CR-2026-160-messapparat.md +59 -0
  360. package/.koolie/core/governance/change-requests/CR-2026-161-pruefwerkzeuge.md +52 -0
  361. package/.koolie/core/governance/change-requests/CR-2026-162-schutzschicht.md +65 -0
  362. package/.koolie/core/governance/change-requests/CR-2026-163-pfadsemantik.md +61 -0
  363. package/.koolie/core/governance/change-requests/CR-2026-164-modi-ausnahmen.md +65 -0
  364. package/.koolie/core/governance/change-requests/CR-2026-165-installer-banner.md +406 -0
  365. package/.koolie/core/governance/change-requests/CR-2026-166-nachlauf-aufzeichnungen.md +59 -0
  366. package/.koolie/core/governance/change-requests/CR-2026-167-einsatzarchitektur.md +60 -0
  367. package/.koolie/core/governance/change-requests/CR-2026-168-paketquellen.md +64 -0
  368. package/.koolie/core/governance/change-requests/CR-2026-169-modusbindung-messfragen.md +58 -0
  369. package/.koolie/core/governance/change-requests/CR-2026-170-erste-veroeffentlichung.md +62 -0
  370. package/.koolie/core/governance/change-requests/CR-2026-171-befehl-im-projektverzeichnis.md +57 -0
  371. package/.koolie/core/governance/change-requests/CR-2026-172-auftritt-npm-suche.md +58 -0
  372. package/.koolie/core/install.py +2402 -0
  373. package/.koolie/core/install_dialog.py +227 -0
  374. package/.koolie/core/koexistenz.py +112 -0
  375. package/.koolie/core/mandat.py +605 -0
  376. package/.koolie/core/onboarding/COMPLETION_CRITERIA.md +37 -0
  377. package/.koolie/core/onboarding/GUIDE.md +103 -0
  378. package/.koolie/core/onboarding/KNOWLEDGE_CHECK.md +48 -0
  379. package/.koolie/core/onboarding/MENTOR_CHECKLIST.md +40 -0
  380. package/.koolie/core/onboarding/QUICKSTART.md +50 -0
  381. package/.koolie/core/onboarding/REFERENCE.md +69 -0
  382. package/.koolie/core/onboarding/exercises/EXERCISES.md +78 -0
  383. package/.koolie/core/onboarding/exercises/README.md +120 -0
  384. package/.koolie/core/pilot/METRICS.md +59 -0
  385. package/.koolie/core/pilot/PILOT_CONCEPT.md +42 -0
  386. package/.koolie/core/prompts/01-understand-codebase.md +99 -0
  387. package/.koolie/core/prompts/02-impact-analysis.md +104 -0
  388. package/.koolie/core/prompts/03-implementation-planning.md +102 -0
  389. package/.koolie/core/prompts/04-code-generation.md +100 -0
  390. package/.koolie/core/prompts/05-test-generation.md +103 -0
  391. package/.koolie/core/prompts/06-refactoring.md +102 -0
  392. package/.koolie/core/prompts/07-debugging.md +97 -0
  393. package/.koolie/core/prompts/08-security-review.md +92 -0
  394. package/.koolie/core/prompts/09-performance-analysis.md +89 -0
  395. package/.koolie/core/prompts/10-documentation.md +91 -0
  396. package/.koolie/core/prompts/11-merge-request-review.md +94 -0
  397. package/.koolie/core/prompts/12-developer-training.md +90 -0
  398. package/.koolie/core/prompts/README.md +88 -0
  399. package/.koolie/core/templates/MR_AI_DISCLOSURE.md +37 -0
  400. package/.koolie/core/templates/PLAN_TEMPLATE.md +57 -0
  401. package/.koolie/core/templates/SKILL_TEMPLATE.md +159 -0
  402. package/.koolie/core/templates/project-overlay/OVERLAY.md +315 -0
  403. package/.koolie/core/templates/project-overlay/documents/README.md +43 -0
  404. package/.koolie/core/templates/project-overlay/documents/ai-governance/.gitkeep.md +3 -0
  405. package/.koolie/core/templates/project-overlay/documents/ai-process-model/.gitkeep.md +3 -0
  406. package/.koolie/core/templates/project-overlay/documents/architecture/.gitkeep.md +3 -0
  407. package/.koolie/core/templates/project-overlay/documents/architecture/decisions/README.md +3 -0
  408. package/.koolie/core/templates/project-overlay/documents/branching-strategy/.gitkeep.md +3 -0
  409. package/.koolie/core/templates/project-overlay/documents/coding-guidelines/.gitkeep.md +3 -0
  410. package/.koolie/core/templates/project-overlay/documents/definition-of-done/.gitkeep.md +3 -0
  411. package/.koolie/core/templates/project-overlay/documents/definition-of-ready/.gitkeep.md +3 -0
  412. package/.koolie/core/templates/project-overlay/documents/deployment/.gitkeep.md +3 -0
  413. package/.koolie/core/templates/project-overlay/documents/glossary/.gitkeep.md +3 -0
  414. package/.koolie/core/templates/project-overlay/documents/quality/.gitkeep.md +3 -0
  415. package/.koolie/core/templates/project-overlay/documents/roadmap/.gitkeep.md +3 -0
  416. package/.koolie/core/templates/project-overlay/documents/roles/.gitkeep.md +3 -0
  417. package/.koolie/core/templates/project-overlay/documents/security/.gitkeep.md +3 -0
  418. package/.koolie/core/templates/project-overlay/exceptions/EXCEPTIONS.md +9 -0
  419. package/.koolie/core/templates/project-overlay/forbidden-terms.txt +8 -0
  420. package/.koolie/core/templates/project-overlay/overlay-manifest.yaml +73 -0
  421. package/.koolie/core/templates/rules/21-overlay-TEMPLATE.md.template +28 -0
  422. package/.koolie/core/templates/rules/40-tech-TEMPLATE.md.template +33 -0
  423. package/.koolie/core/tests/EDGE_CASES.md +67 -0
  424. package/.koolie/core/tests/TEST_CATALOG.md +170 -0
  425. package/.koolie/core/tests/erhebungen/README.md +326 -0
  426. package/.koolie/core/tests/erhebungen/ablage.py +357 -0
  427. package/.koolie/core/tests/erhebungen/apparat/__init__.py +22 -0
  428. package/.koolie/core/tests/erhebungen/apparat/baum.py +214 -0
  429. package/.koolie/core/tests/erhebungen/apparat/belege.py +91 -0
  430. package/.koolie/core/tests/erhebungen/apparat/clients.py +321 -0
  431. package/.koolie/core/tests/erhebungen/apparat/freigabe.py +74 -0
  432. package/.koolie/core/tests/erhebungen/apparat/kontingent.py +64 -0
  433. package/.koolie/core/tests/erhebungen/apparat/laeufer.py +155 -0
  434. package/.koolie/core/tests/erhebungen/apparat/reihe.py +202 -0
  435. package/.koolie/core/tests/erhebungen/apparat/selbsttest.py +280 -0
  436. package/.koolie/core/tests/erhebungen/apparat/stand.py +30 -0
  437. package/.koolie/core/tests/erhebungen/apparat/vorpruefung.py +70 -0
  438. package/.koolie/core/tests/erhebungen/auswerten-b4.py +468 -0
  439. package/.koolie/core/tests/erhebungen/auswerten-b5.py +517 -0
  440. package/.koolie/core/tests/erhebungen/auswerten-dd.py +172 -0
  441. package/.koolie/core/tests/erhebungen/baeume-b4.py +334 -0
  442. package/.koolie/core/tests/erhebungen/baeume-b5.py +339 -0
  443. package/.koolie/core/tests/erhebungen/baeume_loeschen.py +138 -0
  444. package/.koolie/core/tests/erhebungen/cc-overlay-fuellen.py +277 -0
  445. package/.koolie/core/tests/erhebungen/dossier-b4.py +178 -0
  446. package/.koolie/core/tests/erhebungen/dossier-b5.py +202 -0
  447. package/.koolie/core/tests/erhebungen/historie-bauen-b4.py +642 -0
  448. package/.koolie/core/tests/erhebungen/k-bauen-b3.py +841 -0
  449. package/.koolie/core/tests/erhebungen/lauf-dd.py +146 -0
  450. package/.koolie/core/tests/erhebungen/lauf.py +114 -0
  451. package/.koolie/core/tests/erhebungen/mcp-waechter.py +278 -0
  452. package/.koolie/core/tests/erhebungen/messbaum-schnitt.py +256 -0
  453. package/.koolie/core/tests/erhebungen/messen.py +72 -0
  454. package/.koolie/core/tests/erhebungen/node-waechter.py +74 -0
  455. package/.koolie/core/tests/erhebungen/packaktivierung.py +403 -0
  456. package/.koolie/core/tests/erhebungen/prompts-schreiben-b4.py +210 -0
  457. package/.koolie/core/tests/erhebungen/prompts-schreiben-b5.py +251 -0
  458. package/.koolie/core/tests/erhebungen/reihe-b4.py +171 -0
  459. package/.koolie/core/tests/erhebungen/reihe-b5.py +172 -0
  460. package/.koolie/core/tests/erhebungen/stand-b4.py +135 -0
  461. package/.koolie/core/tests/erhebungen/stand-b5.py +137 -0
  462. package/.koolie/core/tests/erhebungen/trust-b4.py +56 -0
  463. package/.koolie/core/tests/erhebungen/trust-b5.py +56 -0
  464. package/.koolie/core/tests/erhebungen/turn2-schreiben-b4.py +105 -0
  465. package/.koolie/core/tests/erhebungen/umgebungen-bauen-b4.py +377 -0
  466. package/.koolie/core/tests/erhebungen/umgebungen-bauen-b5.py +363 -0
  467. package/.koolie/core/tests/erhebungen/zaehlen46.py +74 -0
  468. package/.koolie/core/tests/erhebungen/zustand-b4.py +82 -0
  469. package/.koolie/core/tests/erhebungen/zustand-b5.py +82 -0
  470. package/.koolie/core/tests/protocols/2026-09-10-AP2-claude-code-wirkungsnachweise.md +194 -0
  471. package/.koolie/core/tests/protocols/2026-09-10-AP2-claude-code.md +468 -0
  472. package/.koolie/core/tests/protocols/2026-09-10-CR-2026-020-akteursbezeichnung.md +99 -0
  473. package/.koolie/core/tests/protocols/2026-09-10-CR-2026-021-hook-interpreter.md +138 -0
  474. package/.koolie/core/tests/protocols/2026-09-10-CR-2026-022-artefaktversionen.md +87 -0
  475. package/.koolie/core/tests/protocols/2026-09-10-CR-2026-023-shell-lesesperre.md +135 -0
  476. package/.koolie/core/tests/protocols/2026-09-10-CR-2026-024-clientbindungen.md +98 -0
  477. package/.koolie/core/tests/protocols/2026-09-10-FW-DS-03.md +90 -0
  478. package/.koolie/core/tests/protocols/2026-09-10-FW-KO-01.md +105 -0
  479. package/.koolie/core/tests/protocols/2026-09-10-FW-KO-02.md +123 -0
  480. package/.koolie/core/tests/protocols/2026-09-10-FW-KO-04.md +73 -0
  481. package/.koolie/core/tests/protocols/2026-09-10-FW-RE-02.md +99 -0
  482. package/.koolie/core/tests/protocols/2026-09-10-FW-VN-01-wiederholung.md +108 -0
  483. package/.koolie/core/tests/protocols/2026-09-10-FW-VN-01.md +249 -0
  484. package/.koolie/core/tests/protocols/2026-09-10-FW-ZA-05.md +99 -0
  485. package/.koolie/core/tests/protocols/2026-09-11-AP2-devin-desktop.md +257 -0
  486. package/.koolie/core/tests/protocols/2026-09-11-CR-2026-026-fail-closed.md +113 -0
  487. package/.koolie/core/tests/protocols/2026-09-11-erhebungen-K21-K26.md +243 -0
  488. package/.koolie/core/tests/protocols/2026-09-11-wirkungsnachweise-0.26.0.md +101 -0
  489. package/.koolie/core/tests/protocols/2026-09-12-B01-allowed-tools.md +152 -0
  490. package/.koolie/core/tests/protocols/2026-09-12-B04-B05-gegenpruefung.md +204 -0
  491. package/.koolie/core/tests/protocols/2026-09-12-erhebungen-K28-S5-B9-bypass.md +268 -0
  492. package/.koolie/core/tests/protocols/2026-09-12-mehrprojekt-arbeitsbereich.md +154 -0
  493. package/.koolie/core/tests/protocols/2026-09-12-wirkungsnachweise-0.26.1.md +126 -0
  494. package/.koolie/core/tests/protocols/2026-09-12-wirkungsnachweise-0.27.0.md +114 -0
  495. package/.koolie/core/tests/protocols/2026-09-12-wirkungsnachweise-0.28.0.md +129 -0
  496. package/.koolie/core/tests/protocols/2026-09-12-wirkungsnachweise-0.29.0.md +121 -0
  497. package/.koolie/core/tests/protocols/2026-09-12-wirkungsnachweise-0.30.0.md +112 -0
  498. package/.koolie/core/tests/protocols/2026-09-12-wirkungsnachweise-0.31.0.md +107 -0
  499. package/.koolie/core/tests/protocols/2026-09-13-B06-gegenpruefung.md +370 -0
  500. package/.koolie/core/tests/protocols/2026-09-13-B07-B09-gegenpruefung.md +211 -0
  501. package/.koolie/core/tests/protocols/2026-09-13-B08-B11-gegenpruefung.md +179 -0
  502. package/.koolie/core/tests/protocols/2026-09-13-erhebung-disallowed-tools.md +147 -0
  503. package/.koolie/core/tests/protocols/2026-09-13-erhebung-unteragent-tiefe.md +139 -0
  504. package/.koolie/core/tests/protocols/2026-09-13-erhebung-unteragent.md +214 -0
  505. package/.koolie/core/tests/protocols/2026-09-13-gegenpruefung-berechtigungsdatei.md +253 -0
  506. package/.koolie/core/tests/protocols/2026-09-13-gegenpruefung-stumme-brueche.md +202 -0
  507. package/.koolie/core/tests/protocols/2026-09-13-gegenpruefung-werkzeugabbildung.md +219 -0
  508. package/.koolie/core/tests/protocols/2026-09-13-wirkungsnachweise-0.32.0.md +133 -0
  509. package/.koolie/core/tests/protocols/2026-09-13-wirkungsnachweise-0.33.0.md +169 -0
  510. package/.koolie/core/tests/protocols/2026-09-13-wirkungsnachweise-0.34.0.md +187 -0
  511. package/.koolie/core/tests/protocols/2026-09-13-wirkungsnachweise-0.35.0.md +187 -0
  512. package/.koolie/core/tests/protocols/2026-09-13-wirkungsnachweise-0.36.0.md +137 -0
  513. package/.koolie/core/tests/protocols/2026-09-13-wirkungsnachweise-0.37.0.md +112 -0
  514. package/.koolie/core/tests/protocols/2026-09-13-wirkungsnachweise-0.38.0.md +154 -0
  515. package/.koolie/core/tests/protocols/2026-09-13-wirkungsnachweise-0.39.0.md +188 -0
  516. package/.koolie/core/tests/protocols/2026-09-13-wirkungsnachweise-0.40.0.md +214 -0
  517. package/.koolie/core/tests/protocols/2026-09-14-erhebung-devin-werkzeuge.md +267 -0
  518. package/.koolie/core/tests/protocols/2026-09-14-erhebung-skillaufruf.md +238 -0
  519. package/.koolie/core/tests/protocols/2026-09-14-gegenpruefung-pruefregister.md +156 -0
  520. package/.koolie/core/tests/protocols/2026-09-14-gegenpruefung-schlitzdeckung.md +206 -0
  521. package/.koolie/core/tests/protocols/2026-09-14-gegenpruefung-skillwahl.md +127 -0
  522. package/.koolie/core/tests/protocols/2026-09-14-migrationslauf-pilot.md +134 -0
  523. package/.koolie/core/tests/protocols/2026-09-14-wirkungsnachweise-0.41.0.md +175 -0
  524. package/.koolie/core/tests/protocols/2026-09-14-wirkungsnachweise-0.42.0.md +180 -0
  525. package/.koolie/core/tests/protocols/2026-09-14-wirkungsnachweise-0.43.0.md +165 -0
  526. package/.koolie/core/tests/protocols/2026-09-14-wirkungsnachweise-0.44.0.md +130 -0
  527. package/.koolie/core/tests/protocols/2026-09-15-gegenpruefung-d11-zaehlregeln.md +311 -0
  528. package/.koolie/core/tests/protocols/2026-09-15-gegenpruefung-modulstatus.md +524 -0
  529. package/.koolie/core/tests/protocols/2026-09-15-gegenpruefung-nicht-skill-traeger.md +225 -0
  530. package/.koolie/core/tests/protocols/2026-09-15-gegenpruefung-restliche-nicht-skill-traeger.md +345 -0
  531. package/.koolie/core/tests/protocols/2026-09-15-gegenpruefung-strukturentscheidungen.md +392 -0
  532. package/.koolie/core/tests/protocols/2026-09-15-herrichtung-uebungsrepositorium.md +213 -0
  533. package/.koolie/core/tests/protocols/2026-09-15-migrationslauf-pilot-0.46.0.md +143 -0
  534. package/.koolie/core/tests/protocols/2026-09-15-wirkungsnachweise-0.45.0.md +127 -0
  535. package/.koolie/core/tests/protocols/2026-09-15-wirkungsnachweise-0.46.0.md +193 -0
  536. package/.koolie/core/tests/protocols/2026-09-15-wirkungsnachweise-0.47.0.md +149 -0
  537. package/.koolie/core/tests/protocols/2026-09-15-wirkungsnachweise-0.49.0.md +202 -0
  538. package/.koolie/core/tests/protocols/2026-09-15-wirkungsnachweise-0.50.0.md +183 -0
  539. package/.koolie/core/tests/protocols/2026-09-15-wirkungsnachweise-0.51.0.md +202 -0
  540. package/.koolie/core/tests/protocols/2026-09-15-wirkungsnachweise-0.52.0.md +168 -0
  541. package/.koolie/core/tests/protocols/2026-09-16-AP2-zielversion-devin-desktop.md +231 -0
  542. package/.koolie/core/tests/protocols/2026-09-16-wirkungsnachweise-0.53.0.md +350 -0
  543. package/.koolie/core/tests/protocols/2026-09-17-nachtrag-migrationshinweis-0.54.1.md +121 -0
  544. package/.koolie/core/tests/protocols/2026-09-17-sitzungstest-pi-ds.md +523 -0
  545. package/.koolie/core/tests/protocols/2026-09-17-sitzungstest-schranken.md +433 -0
  546. package/.koolie/core/tests/protocols/2026-09-17-wirkungsnachweise-0.54.0.md +159 -0
  547. package/.koolie/core/tests/protocols/2026-09-18-FW-AK-01.md +442 -0
  548. package/.koolie/core/tests/protocols/2026-09-18-FW-KO-05.md +231 -0
  549. package/.koolie/core/tests/protocols/2026-09-18-herrichtung-uebungsrepositorium.md +273 -0
  550. package/.koolie/core/tests/protocols/2026-09-18-nachtrag-preis-umbenennung-0.56.1.md +102 -0
  551. package/.koolie/core/tests/protocols/2026-09-18-sitzungstest-5.md +349 -0
  552. package/.koolie/core/tests/protocols/2026-09-18-sitzungstest-ne-sc.md +430 -0
  553. package/.koolie/core/tests/protocols/2026-09-18-sitzungstest-pi-ds-2.md +499 -0
  554. package/.koolie/core/tests/protocols/2026-09-18-vorbedingungen-sitzungstest-5-zweiter-durchgang.md +170 -0
  555. package/.koolie/core/tests/protocols/2026-09-18-vorbedingungen-testblaetter.md +184 -0
  556. package/.koolie/core/tests/protocols/2026-09-18-wirkungsnachweise-0.55.0.md +202 -0
  557. package/.koolie/core/tests/protocols/2026-09-18-wirkungsnachweise-0.56.0.md +135 -0
  558. package/.koolie/core/tests/protocols/2026-09-18-wirkungsnachweise-0.56.2.md +154 -0
  559. package/.koolie/core/tests/protocols/2026-09-18-wirkungsnachweise-0.57.0.md +228 -0
  560. package/.koolie/core/tests/protocols/2026-09-18-wirkungsnachweise-0.57.1.md +262 -0
  561. package/.koolie/core/tests/protocols/2026-09-18-wirkungsnachweise-0.58.0.md +135 -0
  562. package/.koolie/core/tests/protocols/2026-09-18-wirkungsnachweise-0.59.0.md +150 -0
  563. package/.koolie/core/tests/protocols/2026-09-18-wirkungsnachweise-0.60.0.md +340 -0
  564. package/.koolie/core/tests/protocols/2026-09-19-herrichtung-buendel-4.md +235 -0
  565. package/.koolie/core/tests/protocols/2026-09-19-k77-zurechenbarkeit.md +236 -0
  566. package/.koolie/core/tests/protocols/2026-09-19-pruefapparat-filter.md +50 -0
  567. package/.koolie/core/tests/protocols/2026-09-19-pruefmittelwort-und-buendelschnitt.md +239 -0
  568. package/.koolie/core/tests/protocols/2026-09-19-sechzehnte-praeparation.md +135 -0
  569. package/.koolie/core/tests/protocols/2026-09-19-testblaetter-buendel-1.md +250 -0
  570. package/.koolie/core/tests/protocols/2026-09-19-testblaetter-buendel-2.md +229 -0
  571. package/.koolie/core/tests/protocols/2026-09-19-testblaetter-buendel-3.md +293 -0
  572. package/.koolie/core/tests/protocols/2026-09-19-vorbedingungen-buendel-2.md +236 -0
  573. package/.koolie/core/tests/protocols/2026-09-19-vorbedingungen-buendel-3.md +253 -0
  574. package/.koolie/core/tests/protocols/2026-09-19-vorbedingungen-buendel-4.md +138 -0
  575. package/.koolie/core/tests/protocols/2026-09-20-messapparat-buendel-4.md +433 -0
  576. package/.koolie/core/tests/protocols/2026-09-20-testblaetter-buendel-4.md +321 -0
  577. package/.koolie/core/tests/protocols/2026-09-20-uebergabe-im-release-commit.md +146 -0
  578. package/.koolie/core/tests/protocols/2026-09-20-vorbedingungen-nachlauf-b4.md +259 -0
  579. package/.koolie/core/tests/protocols/2026-09-21-arbeitsplatz-im-kern.md +127 -0
  580. package/.koolie/core/tests/protocols/2026-09-21-nachlauf-buendel-4.md +157 -0
  581. package/.koolie/core/tests/protocols/2026-09-21-vorbedingungen-buendel-5.md +247 -0
  582. package/.koolie/core/tests/protocols/2026-09-21-wiederaufnahme-nachlauf-b4.md +190 -0
  583. package/.koolie/core/tests/protocols/2026-09-22-ap2-rest-devin-desktop.md +614 -0
  584. package/.koolie/core/tests/protocols/2026-09-22-hauptdokument-ap11.md +443 -0
  585. package/.koolie/core/tests/protocols/2026-09-22-herrichtung-buendel-5.md +224 -0
  586. package/.koolie/core/tests/protocols/2026-09-22-messtag-buendel-5.md +327 -0
  587. package/.koolie/core/tests/protocols/2026-09-22-quellenzuordnung-matrixzeilen.md +230 -0
  588. package/.koolie/core/tests/protocols/2026-09-22-sammelzellen-zentraler-katalog.md +354 -0
  589. package/.koolie/core/tests/protocols/2026-09-22-umbenennung-koolie.md +296 -0
  590. package/.koolie/core/tests/protocols/2026-09-22-verify-marker-abschaffen.md +283 -0
  591. package/.koolie/core/tests/protocols/2026-09-22-vortrag-und-name.md +261 -0
  592. package/.koolie/core/tests/protocols/2026-09-22-wirkungsnachweise-0.86.0.md +158 -0
  593. package/.koolie/core/tests/protocols/2026-09-23-archiv-zeilenenden.md +113 -0
  594. package/.koolie/core/tests/protocols/2026-09-23-bau-openai-codex.md +168 -0
  595. package/.koolie/core/tests/protocols/2026-09-23-chronik-und-vorlage.md +224 -0
  596. package/.koolie/core/tests/protocols/2026-09-23-erhebung-openai-codex.md +309 -0
  597. package/.koolie/core/tests/protocols/2026-09-23-freigabelauf-1.0.0-vorbereitung.md +119 -0
  598. package/.koolie/core/tests/protocols/2026-09-23-freigabelauf-1.0.0.md +150 -0
  599. package/.koolie/core/tests/protocols/2026-09-23-gegenzeichnung-rollenfrage.md +198 -0
  600. package/.koolie/core/tests/protocols/2026-09-23-reihenfolge-des-hebens.md +220 -0
  601. package/.koolie/core/tests/protocols/2026-09-23-word-fassung-und-blinder-fleck.md +307 -0
  602. package/.koolie/core/tests/protocols/2026-09-24-kopierweg-kern.md +98 -0
  603. package/.koolie/core/tests/protocols/2026-09-24-overlay-werte-einordnung.md +111 -0
  604. package/.koolie/core/tests/protocols/2026-09-24-pfadlisten-nul-getrennt.md +128 -0
  605. package/.koolie/core/tests/protocols/2026-09-24-uebergabe-lokal.md +85 -0
  606. package/.koolie/core/tests/protocols/2026-09-25-code-pack-posten.md +86 -0
  607. package/.koolie/core/tests/protocols/2026-09-25-dokumentationsstandard.md +101 -0
  608. package/.koolie/core/tests/protocols/2026-09-25-installer-je-zielsystem.md +134 -0
  609. package/.koolie/core/tests/protocols/2026-09-25-klasse-b-core-laufzeit.md +126 -0
  610. package/.koolie/core/tests/protocols/2026-09-25-klasse-b-governance.md +133 -0
  611. package/.koolie/core/tests/protocols/2026-09-25-klasse-b-skills.md +91 -0
  612. package/.koolie/core/tests/protocols/2026-09-25-lieferumfang.md +76 -0
  613. package/.koolie/core/tests/protocols/2026-09-25-overlay-muster-dokumente.md +107 -0
  614. package/.koolie/core/tests/protocols/2026-09-25-overlay-muster-general.md +100 -0
  615. package/.koolie/core/tests/protocols/2026-09-25-regel-register-posten.md +87 -0
  616. package/.koolie/core/tests/protocols/2026-09-26-attributionszeile.md +83 -0
  617. package/.koolie/core/tests/protocols/2026-09-26-auffindbarkeit.md +85 -0
  618. package/.koolie/core/tests/protocols/2026-09-26-bau-cursor.md +68 -0
  619. package/.koolie/core/tests/protocols/2026-09-26-bau-kiro.md +75 -0
  620. package/.koolie/core/tests/protocols/2026-09-26-mehrprojekt-tokenlast.md +174 -0
  621. package/.koolie/core/tests/protocols/2026-09-26-regelablage-pfadtoken.md +133 -0
  622. package/.koolie/core/tests/protocols/2026-09-26-skill-anweisungen.md +111 -0
  623. package/.koolie/core/tests/protocols/2026-09-26-testblaetter-modellwechsel.md +106 -0
  624. package/.koolie/core/tests/protocols/2026-09-27-mandat-und-reibung.md +58 -0
  625. package/.koolie/core/tests/protocols/2026-09-28-mcp-anbindung.md +72 -0
  626. package/.koolie/core/tests/protocols/2026-09-29-messapparat.md +75 -0
  627. package/.koolie/core/tests/protocols/2026-09-29-powershell.md +58 -0
  628. package/.koolie/core/tests/protocols/2026-09-29-pruefwerkzeuge.md +64 -0
  629. package/.koolie/core/tests/protocols/2026-09-29-registerpflege.md +228 -0
  630. package/.koolie/core/tests/protocols/2026-09-29-schutzschicht.md +95 -0
  631. package/.koolie/core/tests/protocols/2026-09-30-einsatzarchitektur.md +104 -0
  632. package/.koolie/core/tests/protocols/2026-09-30-modi-ausnahmen.md +77 -0
  633. package/.koolie/core/tests/protocols/2026-09-30-nachlauf-banner.md +85 -0
  634. package/.koolie/core/tests/protocols/2026-09-30-paketquellen.md +65 -0
  635. package/.koolie/core/tests/protocols/2026-09-30-pfadsemantik.md +79 -0
  636. package/.koolie/core/tests/protocols/2026-10-01-auftritt-und-suche.md +58 -0
  637. package/.koolie/core/tests/protocols/2026-10-01-befehl-im-projektverzeichnis.md +47 -0
  638. package/.koolie/core/tests/protocols/2026-10-01-erste-veroeffentlichung.md +60 -0
  639. package/.koolie/core/tests/protocols/2026-10-01-modusbindung-messfragen.md +107 -0
  640. package/.koolie/core/tests/protocols/README.md +14 -0
  641. package/.koolie/core/tests/scripts/hook-check-secrets.py +1307 -0
  642. package/.koolie/core/tests/scripts/hook-overlay-status.py +120 -0
  643. package/.koolie/core/tests/scripts/mermaid_renderer.py +67 -0
  644. package/.koolie/core/tests/scripts/overlay_status.py +130 -0
  645. package/.koolie/core/tests/scripts/probe-pruefungen.py +110 -0
  646. package/.koolie/core/tests/scripts/pruefungen/__init__.py +4 -0
  647. package/.koolie/core/tests/scripts/pruefungen/berechtigungen.py +1559 -0
  648. package/.koolie/core/tests/scripts/pruefungen/bestand.py +1433 -0
  649. package/.koolie/core/tests/scripts/pruefungen/dokumente.py +1262 -0
  650. package/.koolie/core/tests/scripts/pruefungen/gemeinsam.py +784 -0
  651. package/.koolie/core/tests/scripts/pruefungen/hooks.py +1188 -0
  652. package/.koolie/core/tests/scripts/pruefungen/overlay.py +1251 -0
  653. package/.koolie/core/tests/scripts/pruefungen/packs.py +1314 -0
  654. package/.koolie/core/tests/scripts/pruefungen/register.py +950 -0
  655. package/.koolie/core/tests/scripts/pruefungen/testkatalog.py +1202 -0
  656. package/.koolie/core/tests/scripts/pruefungen/werkzeuge.py +957 -0
  657. package/.koolie/core/tests/scripts/sonden/__init__.py +4 -0
  658. package/.koolie/core/tests/scripts/sonden/apparat.py +653 -0
  659. package/.koolie/core/tests/scripts/sonden/teil01_grundbestand_und_installation.py +999 -0
  660. package/.koolie/core/tests/scripts/sonden/teil02_packs_mandat_mcp.py +942 -0
  661. package/.koolie/core/tests/scripts/sonden/teil03_pruefungen_26_bis_36.py +1184 -0
  662. package/.koolie/core/tests/scripts/sonden/teil04_pruefungen_37_bis_45.py +1491 -0
  663. package/.koolie/core/tests/scripts/sonden/teil05_pruefungen_46_bis_55.py +1447 -0
  664. package/.koolie/core/tests/scripts/sonden/teil06_pruefungen_57_bis_65.py +739 -0
  665. package/.koolie/core/tests/scripts/sonden/teil07_overlay_und_lieferung.py +1014 -0
  666. package/.koolie/core/tests/scripts/sonden/teil08_pruefungen_66_bis_80.py +1325 -0
  667. package/.koolie/core/tests/scripts/sonden/teil09_pruefmittel_81_und_82.py +505 -0
  668. package/.koolie/core/tests/scripts/sonden/teil10_pruefungen_83_bis_95.py +1218 -0
  669. package/.koolie/core/tests/scripts/sonden/teil11_pruefungen_104_und_105.py +149 -0
  670. package/.koolie/core/tests/scripts/sonden/teil12_pruefungen_106_und_107.py +136 -0
  671. package/.koolie/core/tests/scripts/sonden/teil13_pfad_und_mustersemantik.py +150 -0
  672. package/.koolie/core/tests/scripts/sonden/teil14_modi_ausnahmen_skills.py +204 -0
  673. package/.koolie/core/tests/scripts/sonden/teil15_banner_und_nachlauf.py +193 -0
  674. package/.koolie/core/tests/scripts/sonden/teil16_koexistenz.py +114 -0
  675. package/.koolie/core/tests/scripts/sonden/teil17_paketquellen.py +115 -0
  676. package/.koolie/core/tests/scripts/sonden/teil18_modusbindung_m3_m5.py +113 -0
  677. package/.koolie/core/tests/scripts/validate-framework.py +1104 -0
  678. package/.koolie/core/tests/scripts/validate-output.py +296 -0
  679. package/.koolie/core/wirksamkeit.py +430 -0
  680. package/CONTRIBUTING.md +119 -0
  681. package/LICENSE +674 -0
  682. package/QUICKSTART.en.md +135 -0
  683. package/QUICKSTART.md +129 -0
  684. package/README.en.md +108 -0
  685. package/README.md +107 -0
  686. package/install.cmd +44 -0
  687. package/install.command +46 -0
  688. package/package.json +21 -0
  689. package/paketquellen/README.md +41 -0
  690. package/paketquellen/bauen.py +411 -0
  691. package/paketquellen/koolie.cmd +23 -0
  692. package/paketquellen/koolie_befehl.py +82 -0
  693. package/paketquellen/npm/koolie.js +26 -0
@@ -0,0 +1,950 @@
1
+ """Die Register der Governance: Decision-Log-Zellen, Pruefregister, 1.0.0-Stand,
2
+ Statusvokabular, Klaerungsregister und seine Form, Releaseplan, Decision-Register und
3
+ Roadmapstand.
4
+
5
+ Pruefungen 36, 40, 46, 47, 50, 53, 58, 91 und 102. Teil des Validators validate-
6
+ framework.py, seit 1.19.1 nach Gegenstand in Module geteilt (K-174). Das Register aller
7
+ Pruefungen steht im Kopfkommentar des Einstiegs, die Grenze jeder einzelnen in ihrem
8
+ Kopfkommentar hier."""
9
+ from __future__ import annotations
10
+
11
+ import os
12
+ import re
13
+
14
+ from .gemeinsam import (
15
+ DOK_WURZEL, err, ist_quellrepositorium, iter_text_files, KERN, paketquelltext, read,
16
+ REGISTER_ANKER, REGISTER_ENDE, SKILL_STATUS, tabellenzellen)
17
+
18
+
19
+ # Pruefung 36: Jede Tabellenzeile des Decision Logs fuehrt so viele Zellen wie der
20
+ # Kopf ihrer Tabelle (CR-2026-060 E4, D-75).
21
+ #
22
+ # Anlass: Vier zerrissene Zeilen in 0.34.0 - D-61 bis D-63 mit fuenf Zellen statt sechs,
23
+ # D-29 mit acht, dort teilte ein unmaskierter Strich in einem Codespan die Zeile. In der
24
+ # gerenderten Tabelle stand die Herkunft unter "Begruendung", das Datum unter
25
+ # "Alternativen", die Rolle unter "Status". D-29 stand so seit 0.10.x. Gefunden hat die
26
+ # Zeilen jedes Mal ein Mensch beim Eintragen einer anderen.
27
+ #
28
+ # WAS SIE HEUTE FAENGT: nichts. Alle Zeilen sind seit 0.35.0 in Ordnung, von Hand
29
+ # berichtigt. Das ist eine VERANKERUNG, keine Behebung - wie Pruefung 35 und der fuenfte
30
+ # Gegenstand der Pruefung 32. Der Unterschied: Ihr Gegenbeweis ist ein Abzaehlen und
31
+ # keine Konstruktion. Gegen 0.34.0 meldet sie vier Fundstellen, gegen 0.32.0 und 0.33.0
32
+ # je eine.
33
+ #
34
+ # WAS SIE NICHT LEISTET: Sie prueft die Anzahl, nicht den Inhalt. Eine Zeile, in der
35
+ # Begruendung und Alternativen vertauscht sind, besteht sie - dieselbe Grenze, die
36
+ # Pruefung 31 fuer ihre Arithmetik benennt. Und sie prueft nur diese eine Datei: Die
37
+ # uebrigen Tabellen des Repositoriums haben ihre eigenen Pruefungen (30, 31) oder keine.
38
+ DECISION_LOG_DATEI = KERN + "/governance/DECISION_LOG.md"
39
+
40
+
41
+ def check_decision_log_zellen(root: str) -> None:
42
+ """Pruefung 36 (D-75): Die Tabellen des Decision Logs sind nicht zerrissen."""
43
+ pfad = os.path.join(root, DECISION_LOG_DATEI.replace("/", os.sep))
44
+ if not os.path.isfile(pfad):
45
+ err(f"{DECISION_LOG_DATEI}: fehlt. Ohne das Decision Log ist keine Entscheidung "
46
+ f"dieses Frameworks belegt")
47
+ return
48
+ zeilen = read(pfad).replace("\r\n", "\n").split("\n")
49
+ soll = None
50
+ ueberschrift = "(vor der ersten Ueberschrift)"
51
+ kopfzeile = 0
52
+ gesehen = 0
53
+ for nr, zeile in enumerate(zeilen, 1):
54
+ z = zeile.strip()
55
+ if z.startswith("## "):
56
+ ueberschrift = z[3:].strip()
57
+ soll = None
58
+ continue
59
+ if not z.startswith("|"):
60
+ # Eine Leerzeile beendet die Tabelle; Fliesstext zwischen zwei Tabellen
61
+ # darf die Zellenzahl nicht von der einen auf die andere uebertragen.
62
+ if not z:
63
+ soll = None
64
+ continue
65
+ zellen = tabellenzellen(z)
66
+ if soll is None:
67
+ soll = len(zellen)
68
+ kopfzeile = nr
69
+ gesehen += 1
70
+ continue
71
+ if len(zellen) != soll:
72
+ err(f"{DECISION_LOG_DATEI}:{nr}: Die Zeile fuehrt {len(zellen)} Zellen, der "
73
+ f"Kopf ihrer Tabelle ({ueberschrift}, Zeile {kopfzeile}) fuehrt {soll}. "
74
+ f"Eine zerrissene Zeile rendert die Werte unter den falschen Spalten; "
75
+ f"ein Strich innerhalb einer Zelle gehoert maskiert (\\|)")
76
+ if not gesehen:
77
+ err(f"{DECISION_LOG_DATEI}: keine Tabellenzeile gefunden. Der Anker dieser "
78
+ f"Pruefung ist die Zeilenform '| ... |'; ohne sie prueft sie nichts und "
79
+ f"bestuende leise (D-23)")
80
+ NACHWEIS_SATZ = "Der Wirksamkeitsnachweis nach D-23 fuer die Pruefungen {} laeuft"
81
+ SONDEN_SATZ = "Wirkungsnachweis nach D-23 fuer die Pruefungen {}"
82
+ KATALOG_SPANNE = "für die Prüfungen {} als Skript"
83
+ KATALOG_GRENZFAELLE = "Die {} Grenzfälle einzeln"
84
+ REGISTER_DATEIEN = ("tests/scripts/validate-framework.py",
85
+ "tests/scripts/probe-pruefungen.py",
86
+ "tests/TEST_CATALOG.md",
87
+ "tests/EDGE_CASES.md")
88
+
89
+
90
+ def nummernspanne(zahlen) -> str:
91
+ """Kanonische Schreibweise einer Nummernmenge: '6 und 18 bis 40'.
92
+
93
+ Eine einzelne Nummer steht allein, eine luckenlose Folge als 'a bis b', mehrere
94
+ Bloecke durch Komma und ein abschliessendes 'und' getrennt. Diese Funktion ist die
95
+ einzige Quelle der Schreibweise; die drei Traeger vergleichen woertlich gegen sie.
96
+ """
97
+ folge = sorted(zahlen)
98
+ bloecke, lauf = [], [folge[0]]
99
+ for z in folge[1:]:
100
+ if z == lauf[-1] + 1:
101
+ lauf.append(z)
102
+ else:
103
+ bloecke.append(lauf)
104
+ lauf = [z]
105
+ bloecke.append(lauf)
106
+ teile = [str(b[0]) if len(b) == 1 else f"{b[0]} bis {b[-1]}" for b in bloecke]
107
+ if len(teile) == 1:
108
+ return teile[0]
109
+ return ", ".join(teile[:-1]) + " und " + teile[-1]
110
+
111
+
112
+ def genannte_pruefungen(*texte: str) -> set:
113
+ """Jede Pruefungsnummer, die ein Text als 'Pruefung N' oder 'Pruefungen N bis M' nennt.
114
+
115
+ Der Zuschnitt ist Absicht (CR-2026-064 E2): Ein Querverweis auf eine kleinere Nummer
116
+ stoert nicht, weil nur die hoechste zaehlt - und eine neue Pruefung nennt ihre Nummer
117
+ zwangslaeufig, spaetestens in ihrem eigenen Kopfkommentar.
118
+ """
119
+ gefunden = set()
120
+ muster = re.compile(r"Pr[uü]efung(?:en)?\s+(\d+(?:\s*(?:,|und|bis)\s*\d+)*)")
121
+ for text in texte:
122
+ for treffer in muster.finditer(text):
123
+ teile = re.split(r"\s*(,|und|bis)\s*", treffer.group(1))
124
+ for i, teil in enumerate(teile):
125
+ if teil == "bis" and 0 < i < len(teile) - 1:
126
+ gefunden |= set(range(int(teile[i - 1]), int(teile[i + 1]) + 1))
127
+ elif teil.isdigit():
128
+ gefunden.add(int(teil))
129
+ return gefunden
130
+
131
+
132
+ def check_pruefregister(root: str) -> None:
133
+ """Pruefung 40 (D-85, D-86): Register und Bestand des Pruefapparats decken sich."""
134
+ texte = {}
135
+ for rel in REGISTER_DATEIEN:
136
+ pfad = os.path.join(root, KERN, *rel.split("/"))
137
+ if not os.path.exists(pfad):
138
+ err(f"{KERN}/{rel}: fehlt. Prüfung 40 hält dort das Register des "
139
+ f"Prüfapparats gegen den Bestand (D-85)")
140
+ return
141
+ texte[rel] = read(pfad) + paketquelltext(root, rel)
142
+ validator = texte["tests/scripts/validate-framework.py"]
143
+ sonden = texte["tests/scripts/probe-pruefungen.py"]
144
+ katalog = texte["tests/TEST_CATALOG.md"]
145
+ kanten = texte["tests/EDGE_CASES.md"]
146
+
147
+ # --- Gegenstand 1: die Anker ------------------------------------------------------
148
+ doc = validator.split('"""')[1] if validator.count('"""') >= 2 else ""
149
+ sondendoc = sonden.split('"""')[1] if sonden.count('"""') >= 2 else ""
150
+ if REGISTER_ANKER not in doc or REGISTER_ENDE not in doc:
151
+ err(f"{KERN}/tests/scripts/validate-framework.py: der Kopfkommentar führt kein "
152
+ f"Register mehr (gesucht: '{REGISTER_ANKER}' und '{REGISTER_ENDE}') – "
153
+ f"Prüfung 40 hat ihren Gegenstand verloren und würde sonst leise bestehen")
154
+ return
155
+ fwko01 = [z for z in katalog.splitlines() if z.startswith("| FW-KO-01")]
156
+ fwko05 = [z for z in katalog.splitlines() if z.startswith("| FW-KO-05")]
157
+ if len(fwko01) != 1 or len(fwko05) != 1:
158
+ err(f"{KERN}/tests/TEST_CATALOG.md: die Zeile FW-KO-01 oder FW-KO-05 steht nicht "
159
+ f"genau einmal (gefunden: {len(fwko01)} und {len(fwko05)}) – Prüfung 40 misst "
160
+ f"dort die Sondenmenge und die Grenzfallanzahl (D-85)")
161
+ return
162
+
163
+ # --- Gegenstand 2: das Register ist lueckenlos und vollstaendig --------------------
164
+ liste = doc.split(REGISTER_ANKER, 1)[1].split(REGISTER_ENDE, 1)[0]
165
+ gefuehrt = sorted({int(n) for n in re.findall(r"^\s{0,2}(\d+)[a-z]?\. ", liste, re.M)})
166
+ if not gefuehrt:
167
+ err(f"{KERN}/tests/scripts/validate-framework.py: das Register im Kopfkommentar "
168
+ f"führt keinen einzigen nummerierten Eintrag – Prüfung 40 hätte nichts zu "
169
+ f"vergleichen und bestünde leise")
170
+ return
171
+ luecken = [n for n in range(1, gefuehrt[-1] + 1) if n not in gefuehrt]
172
+ if luecken:
173
+ err(f"{KERN}/tests/scripts/validate-framework.py: das Register im Kopfkommentar "
174
+ f"hat Lücken – es fehlt {', '.join(str(n) for n in luecken)}. Eine Nummer "
175
+ f"ohne Eintrag ist eine Prüfung, die niemand findet (D-85)")
176
+ genannt = genannte_pruefungen(validator, sonden)
177
+ hoechste = max(genannt) if genannt else 0
178
+ if hoechste > gefuehrt[-1]:
179
+ err(f"{KERN}/tests/scripts/validate-framework.py: das Register im Kopfkommentar "
180
+ f"endet bei Prüfung {gefuehrt[-1]}; die Prüfskripte nennen Prüfung "
181
+ f"{hoechste}. Eine neue Prüfung ohne Registereintrag ist genau der Fall vom "
182
+ f"2026-09-14 – das Register ist die einzige Stelle, die sagt, was dieser "
183
+ f"Lauf prüft (D-85)")
184
+ elif hoechste and hoechste < gefuehrt[-1]:
185
+ err(f"{KERN}/tests/scripts/validate-framework.py: das Register im Kopfkommentar "
186
+ f"führt Prüfung {gefuehrt[-1]}; in den Prüfskripten wird sie nirgends bei "
187
+ f"ihrer Nummer genannt. Ein Eintrag ohne Prüfung verspricht mehr, als der "
188
+ f"Lauf leistet (D-85)")
189
+
190
+ # --- Gegenstand 3: die Sondenmenge an drei Stellen, wortgleich ---------------------
191
+ kennungen = (re.findall(r'\bsonde\("([^"]+)"', sonden)
192
+ + re.findall(r'melde\("SONDE", "([^"]+)"', sonden))
193
+ mit_sonde = {int(m.group(1)) for m in (re.match(r"(\d+)", k) for k in kennungen) if m}
194
+ if not mit_sonde:
195
+ err(f"{KERN}/tests/scripts/probe-pruefungen.py: keine einzige Sonde mit einer "
196
+ f"Prüfungsnummer gefunden – Prüfung 40 rechnet daraus die Sondenmenge aus "
197
+ f"und hat ihren Gegenstand verloren")
198
+ return
199
+ spanne = nummernspanne(mit_sonde)
200
+ for rel, text, soll in (
201
+ ("tests/scripts/validate-framework.py", doc, NACHWEIS_SATZ.format(spanne)),
202
+ ("tests/scripts/probe-pruefungen.py", sondendoc, SONDEN_SATZ.format(spanne)),
203
+ ("tests/TEST_CATALOG.md", fwko01[0], KATALOG_SPANNE.format(spanne))):
204
+ if soll not in text:
205
+ err(f"{KERN}/{rel}: die Sondenmenge ist dort nicht in der ausgerechneten "
206
+ f"Schreibweise genannt. Erwartet wörtlich: '{soll}'. "
207
+ f"probe-pruefungen.py führt Sonden für die Prüfungen {spanne} – eine "
208
+ f"gepflegte Zahl über den Prüfapparat lag am 2026-09-14 an allen drei "
209
+ f"Stellen daneben (D-86)")
210
+
211
+ # --- Gegenstand 4: die Grenzfallanzahl ausserhalb ihrer Quelle ---------------------
212
+ grenzfaelle = set(re.findall(r"\bG-(\d\d)\b", kanten))
213
+ if not grenzfaelle:
214
+ err(f"{KERN}/tests/EDGE_CASES.md: keine einzige Grenzfallkennung der Form G-NN "
215
+ f"gefunden – Prüfung 40 zählt sie dort und hat ihren Gegenstand verloren")
216
+ return
217
+ soll_gf = KATALOG_GRENZFAELLE.format(len(grenzfaelle))
218
+ if soll_gf not in fwko05[0]:
219
+ err(f"{KERN}/tests/TEST_CATALOG.md: FW-KO-05 nennt nicht die gezählte Anzahl der "
220
+ f"Grenzfälle. Erwartet wörtlich: '{soll_gf}'. Die Zeile ist eine "
221
+ f"Arbeitsanweisung für eine Sitzung; sie stand von 0.33.0 bis 0.41.0 auf "
222
+ f"zwölf, während der Bestand auf zwanzig wuchs – wer sie so fährt, prüft "
223
+ f"einen Teil und meldet das Ganze (D-86)")
224
+
225
+
226
+ # ---------------------------------------------------------------------------
227
+ # Pruefung 46: Der 1.0.0-Stand wird ausgerechnet, nicht gepflegt
228
+ # ---------------------------------------------------------------------------
229
+ #
230
+ # ANLASS. D-11 nennt fuenf Kriterien fuer 1.0.0; vier davon sind maschinell zaehlbar.
231
+ # Die Roadmap fuehrte dafuer seit 0.42.0 ausdruecklich KEINE Zahlen, sondern "die
232
+ # Befehle, die sie ausrechnen" - die richtige Lehre aus fuenf falschen Zahlen ueber den
233
+ # Pruefapparat. Am 2026-09-15 wurden diese Befehle zum ersten Mal ausgefuehrt
234
+ # (CR-2026-070, tests/protocols/2026-09-15-gegenpruefung-d11-zaehlregeln.md):
235
+ #
236
+ # Kriterium 1 geglaubt 27 gezaehlt 29 der grep kannte EINE von ZWEI registrierten
237
+ # Markerschreibweisen; die clientgebundene
238
+ # Altform (Produktname statt CLIENT) traegt
239
+ # allein im Pack devin-desktop sieben
240
+ # Fundstellen und zwei in dessen root-template
241
+ # Kriterium 2 geglaubt 103 gezaehlt 118 "die dezentralen TESTS.md je Skill" wurde als
242
+ # zwoelf Dateien gelesen; es sind dreizehn
243
+ # Kriterium 3 geglaubt 16 gezaehlt 69 die genannte Ablagenliste deckt ein Viertel
244
+ # des Bestands - und framework/core/ ist
245
+ # genannt und traegt gar keine Statuszeile
246
+ # Kriterium 4 geglaubt 16 gezaehlt 9 ein roher grep zaehlte die Legende, fuenf
247
+ # Klaerungspunkte und D-11 selbst mit
248
+ #
249
+ # Vier von vier. Keine der Zahlen ist je falsch geschrieben worden - jede ist das
250
+ # richtige Ergebnis einer Regel, die weniger kann als ihr Kriterium verlangt. Ein
251
+ # Befehl, den niemand ausfuehrt, ist keine Ausrechnung, sondern eine Zahl mit einem
252
+ # Zwischenschritt; und weil ihn niemand ausfuehrt, faellt auch nicht auf, dass er das
253
+ # Falsche zaehlt.
254
+ #
255
+ # BAUFORM (E1). Die von Pruefung 40 und 31: Der Stand steht AUSGERECHNET an genau einer
256
+ # Stelle - der Standzeile in docs/ROADMAP.md -, und diese Pruefung haelt die geschriebene
257
+ # Zahl gegen die gezaehlte. Nicht der offene Punkt ist der Fehler, sondern die falsche
258
+ # Zahl. Ein Zaehler, der jeden offenen Punkt meldete, ergaebe heute 225 Fehler, machte
259
+ # jeden Lauf rot und waere binnen eines Releases abgeschaltet; ein Zaehler, der nur
260
+ # berichtet, ist keine Pruefung. Der Preis dieser Bauform steht im Antrag und ist
261
+ # gewollt: JEDER Fortschritt macht den Lauf rot, bis die Zahl nachgezogen ist. Genau
262
+ # dieses Nachziehen ist der Vorgang, der bis 0.47.0 unterblieben ist.
263
+ #
264
+ # ZAEHLBEREICH (E2). Nur <CORE_DIR>/, ohne build/ (Erzeugnis), CHANGELOG.md,
265
+ # governance/change-requests/ und tests/protocols/ (datierte, abgeschlossene
266
+ # Aufzeichnungen). Der Kern ist in jeder Installation derselbe - install.py --check ist
267
+ # genau dafuer da -, also ist die Zahl installationsunabhaengig und dieselbe Standzeile
268
+ # gilt in jedem uebernehmenden Projekt. Fundstellen ausserhalb des Kerns zaehlen nicht,
269
+ # auch echte: README.md:165 war so eine und ist per Hand berichtigt.
270
+ #
271
+ # DER FALLSTRICK, DER BEIM BAUEN ZUSCHNAPPTE (E7). Die erste Fassung lief ueber
272
+ # glob.glob(..., recursive=True). glob ueberspringt Pfadbestandteile, die mit einem Punkt
273
+ # beginnen - damit fehlten fuenfzehn Dateien des Kerns, darunter genau die zwei Traeger
274
+ # clients/*/root-template/.devin/README.md und .../.claude/README.md, die den Befund zu
275
+ # Kriterium 1 tragen. Der Zaehler haette 27 gemeldet und damit zufaellig die geglaubte
276
+ # Zahl bestaetigt. Eine Zaehlregel, die einen Traeger still ueberspringt, war der Anlass
277
+ # dieses Antrags; sie ist beim Bauen der Abhilfe ein zweites Mal entstanden. Deshalb
278
+ # os.walk, und deshalb misst die Selbstprobe C1 des Sondenskripts beide Verfahren
279
+ # gegeneinander.
280
+ #
281
+ # WAS SIE NICHT LEISTET.
282
+ # * Kriterium 5 von D-11 ("Uebernahme in ein zweites Projekt nachgewiesen") zaehlt sie
283
+ # NICHT. Das ist keine Zahl, sondern eine Feststellung. Eine ENTHALTUNG, und sie
284
+ # steht hier statt in einem Gegenstand, der nichts misst.
285
+ # * Sie misst Zahlen, nicht Fortschritt. Ein Modulstatus, der von `entwurf` auf `pilot`
286
+ # gehoben wird, ohne dass jemand das Modul angesehen hat, senkt Kriterium 3 um eins.
287
+ # Die fachliche Abnahme ist nicht maschinell, und diese Pruefung behauptet es nicht.
288
+ # * Kriterium 1 zaehlt auch die Fundstellen, die den Marker nur NENNEN - Registerzeile,
289
+ # Glossarzeile, Arbeitsanweisung (E3). Die Zahl ist ein PEGEL, kein Arbeitsvorrat,
290
+ # und sie kann nicht auf null gehen, solange der Marker sein eigenes Register hat.
291
+ # Das ist richtig so: PLACEHOLDER_REGISTRY.md schreibt beiden Markerformen in der
292
+ # Spalte "Ersetzung/Frist" ausdruecklich "vor Version 1.0.0" vor. Ein Platzhalter,
293
+ # dessen letzte Aussage verifiziert ist, gehoert aus dem Register - sonst fuehrt das
294
+ # Repositorium einen Platzhalter ohne Gegenstand.
295
+ # * Sie sagt nicht "1.0.0-reif" (E8). Stehen alle vier Zahlen auf 0 und der Lauf ist
296
+ # gruen, IST das die Meldung - erzwungen statt behauptet, und ohne einen fuenften
297
+ # Gegenstand, der heute nichts faengt.
298
+ D11_DATEI = KERN + "/docs/ROADMAP.md"
299
+ D11_SATZ = ("Gezählt von Prüfung 46: Kriterium 1 = {}, Kriterium 2 = {}, "
300
+ "Kriterium 3 = {}, Kriterium 4 = {}")
301
+ D11_ANKER = "Gezählt von Prüfung 46: Kriterium 1 = "
302
+ # Beide Schreibweisen (E4). Bis 0.86.1 waren sie registriert; die Altform war nur im
303
+ # Client Pack devin-desktop zulaessig (Pruefung 14 setzte das durch) und trug dieselbe
304
+ # Frist "vor Version 1.0.0". Wer nur die neutrale Form zaehlt, haelt ein Client Pack mit
305
+ # sieben offenen Verifikationsbedarfen fuer fertig.
306
+ #
307
+ # MIT 0.87.0 SIND BEIDE FORMEN ABGESCHAFFT (CR-2026-121, D-291), und dieser Ausdruck
308
+ # bleibt unveraendert stehen. Was er zaehlt, hat sich nicht geaendert; wozu die Zahl
309
+ # dient, schon: Sie war ein Arbeitsvorrat und ist jetzt eine RUECKFALLSPERRE. Ausgebaut
310
+ # wird sie nicht - D-11 verloere damit seinen einzigen maschinellen Zaehler fuer
311
+ # Kriterium 1, die Standzeile fiele von vier Zahlen auf drei, und eine Wiedereinfuehrung
312
+ # der Form fiele niemandem auf. DER PREIS IST BENANNT: Eine Zahl, die dauerhaft auf null
313
+ # steht, wird nicht mehr gelesen; sie traegt nur, solange ihre Sonde laeuft.
314
+ D11_MARKER_RE = re.compile(r"<VERIFY AGAINST CURRENT (?:CLIENT|DEVIN) DOCUMENTATION>")
315
+ D11_AUSSER = ("build/", "CHANGELOG.md", "governance/change-requests/",
316
+ "tests/protocols/")
317
+ D11_MARKER_ENDUNGEN = (".md", ".json", ".py")
318
+ D11_STECKBRIEF_RE = re.compile(r"^\|\s*Status\s*\|\s*(.+?)\s*\|$")
319
+ # Die Steckbriefzeile steht im Kopf des Dokuments. Sechzig Zeilen sind grosszuegig
320
+ # gemessen (der spaeteste Treffer im Bestand steht auf Zeile 41) und halten zugleich die
321
+ # Lebenszyklustabelle aus 08-skill-conventions.md (Zeile 92) und die Vorfalltabelle aus
322
+ # INCIDENT_HANDLING.md (Zeile 37) draussen - beides Tabellen MIT einer Statusspalte, die
323
+ # keinen Modulstatus fuehren.
324
+ D11_STECKBRIEF_KOPF = 60
325
+ D11_KRITERIEN = ("kein unbearbeiteter VERIFY-Marker",
326
+ "Testkatalog und dezentrale Testblätter ohne `offen`",
327
+ "Modulstatus über `entwurf`",
328
+ "Decision Records ohne `entschieden (Vorschlag)`")
329
+
330
+
331
+ def _d11_kerndateien(root: str, endungen: tuple):
332
+ """(absoluter Pfad, Pfad unter <CORE_DIR>/) je Kerndatei im Zaehlbereich.
333
+
334
+ os.walk und NICHT glob: glob ueberspringt Pfadbestandteile, die mit einem Punkt
335
+ beginnen, und genau dort liegen zwei Traeger des Kerns (E7, Selbstprobe C1).
336
+ """
337
+ wurzel = os.path.join(root, KERN)
338
+ for ordner, _, dateien in os.walk(wurzel):
339
+ for name in sorted(dateien):
340
+ if not name.endswith(endungen):
341
+ continue
342
+ pfad = os.path.join(ordner, name)
343
+ rest = os.path.relpath(pfad, wurzel).replace(os.sep, "/")
344
+ if any(rest == a or rest.startswith(a) for a in D11_AUSSER):
345
+ continue
346
+ yield pfad, rest
347
+
348
+
349
+ def _d11_offene_zellen(text: str, praefix: str) -> int:
350
+ """Tabellenzeilen mit `praefix`, deren letzte Zelle mit 'offen' beginnt."""
351
+ treffer = 0
352
+ for zeile in text.replace("\r\n", "\n").split("\n"):
353
+ z = zeile.strip()
354
+ if not z.startswith(praefix) or z.startswith("|---"):
355
+ continue
356
+ zellen = tabellenzellen(z)
357
+ if zellen and zellen[-1].startswith("offen"):
358
+ treffer += 1
359
+ return treffer
360
+
361
+
362
+ def _d11_zaehlen(root: str) -> list:
363
+ """Die vier maschinell zaehlbaren Kriterien von D-11, in ihrer Reihenfolge."""
364
+ # --- 1: Markerfundstellen, beide Schreibweisen -----------------------------------
365
+ k1 = 0
366
+ for pfad, _ in _d11_kerndateien(root, D11_MARKER_ENDUNGEN):
367
+ k1 += len(D11_MARKER_RE.findall(read(pfad)))
368
+
369
+ # --- 2: offene Ergebniszellen im Katalog UND in jedem Testblatt -------------------
370
+ # Gefunden durch Baumdurchlauf, nicht durch eine Ablagenliste (E5): Eine Liste kann
371
+ # eine dreizehnte Datei uebersehen, und sie hat es.
372
+ katalog = os.path.join(root, KERN, "tests", "TEST_CATALOG.md")
373
+ k2 = _d11_offene_zellen(read(katalog), "| FW-") if os.path.isfile(katalog) else 0
374
+ for pfad, _ in _d11_kerndateien(root, ("TESTS.md",)):
375
+ k2 += _d11_offene_zellen(read(pfad), "| ")
376
+
377
+ # --- 3: Steckbriefe auf `entwurf`, im ganzen Bestand ------------------------------
378
+ # Verglichen wird das ERSTE WORT des Werts: role-packs/software-development traegt
379
+ # "entwurf (Referenzpack der Erstfassung)", und ein Gleichheitsvergleich saehe sie
380
+ # nicht (E6).
381
+ k3 = 0
382
+ for pfad, _ in _d11_kerndateien(root, (".md",)):
383
+ for zeile in read(pfad).replace("\r\n", "\n").split("\n")[:D11_STECKBRIEF_KOPF]:
384
+ treffer = D11_STECKBRIEF_RE.match(zeile.strip())
385
+ if not treffer:
386
+ continue
387
+ wert = treffer.group(1).strip().strip("`").strip()
388
+ if wert.split()[:1] == ["entwurf"]:
389
+ k3 += 1
390
+ break
391
+
392
+ # --- 4: Decision Records auf `entschieden (Vorschlag)` ----------------------------
393
+ # NUR Zeilen der Form | D-NN |. Nicht die Legende, nicht die Klaerungspunkte K-NN,
394
+ # nicht D-11 selbst: D-11 sagt "Decision Records", und ein Klaerungspunkt ist keiner.
395
+ log = os.path.join(root, KERN, "governance", "DECISION_LOG.md")
396
+ k4 = 0
397
+ if os.path.isfile(log):
398
+ for zeile in read(log).replace("\r\n", "\n").split("\n"):
399
+ z = zeile.strip()
400
+ if not re.match(r"^\|\s*D-\d+\s*\|", z):
401
+ continue
402
+ zellen = tabellenzellen(z)
403
+ if len(zellen) > 4 and zellen[4].startswith("entschieden (Vorschlag)"):
404
+ k4 += 1
405
+ return [k1, k2, k3, k4]
406
+
407
+
408
+ # --- Gegenstand 6 (seit 1.19.1, K-98, D-483): die Markerform AUSSERHALB des
409
+ # Zaehlbereichs. Kriterium 1 zaehlt die Marker im Kern (D-11). Die Einstiegsdokumente
410
+ # der Wurzel und die Quellen des Hauptdokuments unter build/doc/ liegen ausserhalb -
411
+ # Traeger, die der Zaehler nie gesehen hat; 0.87.0 hat dort sechs Fundstellen von Hand
412
+ # entfernt, und keine Pruefung hielt es fest (CR-2026-121, D-295). Eine Fundstelle dort
413
+ # ist ein FEHLER und zaehlt NICHT in Kriterium 1: Die Zahl bliebe sonst nicht die, die
414
+ # D-11 meint, und die Standzeile stiege, ohne dass der Kern sich bewegt hat.
415
+ # Die Wurzeldokumente nur im Quellrepositorium - in einem Projekt gehoeren sie dem
416
+ # Projekt (D-299).
417
+ def _d11_ausserhalb(root: str) -> None:
418
+ """Markerform in den Wurzeldokumenten und unter build/doc/ - je Fundstelle."""
419
+ traeger = list(DOK_WURZEL) if ist_quellrepositorium(root) else []
420
+ doc = os.path.join(root, KERN, "build", "doc")
421
+ if os.path.isdir(doc):
422
+ traeger += [f"{KERN}/build/doc/{n}" for n in sorted(os.listdir(doc))
423
+ if n.endswith(".md")]
424
+ for rel in traeger:
425
+ pfad = os.path.join(root, *rel.split("/"))
426
+ if not os.path.isfile(pfad):
427
+ continue
428
+ treffer = len(D11_MARKER_RE.findall(read(pfad)))
429
+ if treffer:
430
+ err(f"{rel}: traegt die Markerform einer unverifizierten Aussage "
431
+ f"{treffer}x. Die Stelle liegt ausserhalb des Zaehlbereichs von "
432
+ f"Kriterium 1 und wird dort nie gezaehlt - deshalb meldet Pruefung 46 "
433
+ f"sie einzeln: verifizieren oder die Aussage streichen (K-98, D-295)")
434
+
435
+
436
+ def check_d11_stand(root: str) -> None:
437
+ """Pruefung 46 (D-98, D-99): Der 1.0.0-Stand ist ausgerechnet, nicht gepflegt."""
438
+ _d11_ausserhalb(root)
439
+ pfad = os.path.join(root, D11_DATEI.replace("/", os.sep))
440
+ if not os.path.isfile(pfad):
441
+ err(f"{D11_DATEI}: fehlt. Prüfung 46 hält dort den ausgerechneten 1.0.0-Stand "
442
+ f"gegen die geschriebene Standzeile (D-98)")
443
+ return
444
+ text = read(pfad)
445
+
446
+ # --- Gegenstand 1: der Anker ------------------------------------------------------
447
+ # Die Bauform der Pruefungen 28, 29, 31 und 40: Eine Konsistenzpruefung findet ihren
448
+ # Gegenstand ueber einen Suchtext. Geht er verloren, bestuende sie LEISE - und
449
+ # niemand saehe, dass der 1.0.0-Stand nicht mehr geprueft wird.
450
+ wie_oft = text.count(D11_ANKER)
451
+ if wie_oft != 1:
452
+ err(f"{D11_DATEI}: die Standzeile steht {wie_oft}x statt genau einmal "
453
+ f"(gesucht: '{D11_ANKER}…'). Prüfung 46 hat ihren Gegenstand verloren und "
454
+ f"würde sonst leise bestehen. Erwartet wörtlich, in einer Zeile: "
455
+ f"'{D11_SATZ.format(*_d11_zaehlen(root))}' (D-98)")
456
+ return
457
+
458
+ # --- Gegenstand 2 bis 5: die vier Zahlen -----------------------------------------
459
+ # Verglichen werden die ZAHLEN, nicht die Zeichenkette. Ein Vergleich per `in`
460
+ # bestuende bei jedem Praefix: "Kriterium 4 = 9" steckt in "Kriterium 4 = 99", und
461
+ # die Sonde 46a ist genau daran gefallen, bevor sie es meldete.
462
+ gezaehlt = _d11_zaehlen(root)
463
+ soll = D11_SATZ.format(*gezaehlt)
464
+ zeile = next((z.strip() for z in text.replace("\r\n", "\n").split("\n")
465
+ if D11_ANKER in z), "")
466
+ geschrieben = [int(n) for n in re.findall(r"Kriterium \d+ = (\d+)", zeile)]
467
+ if geschrieben == gezaehlt:
468
+ return
469
+ # Die Meldung nennt die gezaehlte Zahl je Kriterium einzeln - wer nur "stimmt nicht"
470
+ # liest, sucht selbst nach, und genau dieses Nachsuchen ist der Vorgang, der bis
471
+ # 0.47.0 unterblieben ist.
472
+ for i, (name, ist) in enumerate(zip(D11_KRITERIEN, gezaehlt)):
473
+ war = geschrieben[i] if i < len(geschrieben) else None
474
+ if war == ist:
475
+ continue
476
+ richtung = ("die Standzeile nennt keine Zahl dafür" if war is None else
477
+ f"die Standzeile nennt {war}" +
478
+ (" – entweder ist der Bestand zurückgefallen, oder der "
479
+ "Zählbereich sieht erstmals, was er vorher nicht sah; "
480
+ "ohne einen Vorstandsvergleich trennt der Zähler die beiden "
481
+ "Lesarten nicht (K-38)" if ist > war else
482
+ " – der Fortschritt ist nicht nachgezogen"))
483
+ err(f"{D11_DATEI}: Kriterium {i + 1} von D-11 ({name}) ist gezählt **{ist}**, "
484
+ f"{richtung}. Der 1.0.0-Stand gehört ausgerechnet und nicht gepflegt; am "
485
+ f"2026-09-15 lagen alle vier Zahlen daneben, ohne dass eine je falsch "
486
+ f"geschrieben worden wäre (CR-2026-070, D-98)")
487
+ if len(geschrieben) != len(gezaehlt):
488
+ err(f"{D11_DATEI}: die Standzeile führt {len(geschrieben)} Zahlen statt "
489
+ f"{len(gezaehlt)}. Erwartet wörtlich: '{soll}' (D-98)")
490
+
491
+ # ---------------------------------------------------------------------------
492
+ # Pruefung 47: Das Statusvokabular jedes Modultraegers
493
+ # ---------------------------------------------------------------------------
494
+ #
495
+ # ANLASS (CR-2026-073 E5, D-108). Das Lebenszyklusmodell gilt seit 0.50.0 fuer JEDEN
496
+ # Modultraeger (D-102) - durchgesetzt war das Vokabular fuer genau einen Dateityp. Die
497
+ # Skillpruefung meldet seit 0.12.0 einen unbekannten Statuswert, aber nur in einer
498
+ # SKILL.md; fuer die uebrigen 56 der 69 Statustraeger war jede Zeichenfolge
499
+ # zulaessig, und "| Status | banane |" waere durch jeden Lauf gelaufen. Genau
500
+ # dieser Fall stand fuer Skills bis 0.12.0 offen und ist mit FW-VN-01
501
+ # geschlossen worden - fuer die anderen Ablagen nie. Solange kein Nicht-Skill gehoben war, hatte die Luecke keinen
502
+ # Gegenstand; mit dem ersten gehobenen Nicht-Skill-Traeger hat sie einen (D-102, E5).
503
+ #
504
+ # DER ZWEITE ANLASS, UND ER IST DER GROESSERE (K-36, D-105). D-102 definierte den
505
+ # Modultraeger ueber das Merkmal, das er tragen soll: "jede versionierte Datei mit
506
+ # einer Steckbriefzeile Status". Eine solche Definition laesst jeden Traeger
507
+ # entkommen, indem er die Zeile weglaesst - und zwoelf taten das, darunter die elf
508
+ # normativen Kernmodule, fuer die checklists/11-framework-release.md unter Abschluss
509
+ # ausdruecklich einen Status oberhalb von entwurf verlangt. Ein Pruefpunkt ohne
510
+ # Gegenstand, in der Checkliste, die 1.0.0 freigibt. Gegenstand 2 dieser Pruefung
511
+ # schliesst das Loch: Wer einen Steckbrief fuehrt, fuehrt eine Statuszeile.
512
+ #
513
+ # WIE EIN STECKBRIEF ERKANNT WIRD (E5). Als die ERSTE Tabelle des Dokuments, die VOR
514
+ # der ersten Ueberschrift der Ebene 2 steht und die Kopfzeile "| Attribut | Wert |"
515
+ # traegt. Der Zuschnitt ist gemessen und nicht geraten: Eine blosse Suche nach dieser
516
+ # Kopfzeile in den ersten sechzig Zeilen trifft auch templates/PLAN_TEMPLATE.md, wo
517
+ # sie im KOERPER der Vorlage steht - hinter einer H2, als Formular fuer den Plan, der
518
+ # aus ihr entsteht. Das ist kein Steckbrief, und die Datei fuehrt zu Recht keinen
519
+ # Status. Gegen den Bestand gemessen erkennt die Regel 81 Steckbriefe (69 mit und 12
520
+ # ohne Statuszeile) und keinen Fehltreffer.
521
+ #
522
+ # VIER GEGENSTAENDE:
523
+ # 1. Der verlorene Anker. Findet der Lauf ueberhaupt keinen Steckbrief, bestuende
524
+ # diese Pruefung leise. Sie meldet es deshalb selbst - die Bauform der Pruefungen
525
+ # 28, 29, 31, 40 und 46 (D-23).
526
+ # 2. Vollstaendigkeit. Jeder Steckbrief fuehrt eine Statuszeile. Das ist der
527
+ # Mechanismus zu D-105; ohne ihn entkaeme der naechste Traeger genauso.
528
+ # 3. Vokabular. Das erste Wort des Werts ist einer der fuenf Statuswerte aus
529
+ # 08-skill-conventions.md Abschnitt 7. Das ERSTE WORT, weil
530
+ # role-packs/software-development einen Verlaufszusatz traegt ("entwurf
531
+ # (Referenzpack der Erstfassung)") - dieselbe Leseregel wie Pruefung 46 (E6 von
532
+ # CR-2026-070).
533
+ # 4. Der Ausfuellschlitz gehoert der Vorlage, und nur ihr (D-104). Eine Vorlage
534
+ # traegt in der Statuszelle einen Schlitz und KEINEN echten Wert - ein echter
535
+ # ginge unveraendert in jede Kopie ueber und waere damit unveraenderlich, ohne
536
+ # dass jemand das entschieden hat; genau dieser Defekt machte Kriterium 3 von
537
+ # D-11 unerreichbar. Umgekehrt traegt ein Traeger, der keine Vorlage ist, keinen
538
+ # Schlitz: Das ist der Preis, den D-104 benannt und nicht abgesichert hat - "wer
539
+ # eine Vorlage kopiert und den Schlitz nicht fuellt, hat ein Pack ohne
540
+ # Statuswert; bei einem Skill faengt das SKILL_STATUS, bei Client-, Role- und
541
+ # Technology-Pack heute nichts".
542
+ #
543
+ # WAS SIE NICHT LEISTET.
544
+ # * Sie prueft das VOKABULAR, nicht die BERECHTIGUNG. Ob ein Traeger auf pilot
545
+ # stehen darf, entscheidet das Review nach 01-governance.md Abschnitt 5 Punkt 3 -
546
+ # ein Protokoll, das ihn namentlich nennt. Das ist ausdruecklich nicht maschinell
547
+ # (D-102), und diese Pruefung behauptet es nicht.
548
+ # * Sie zaehlt nicht. Den Stand haelt Pruefung 46; hier geht es um die Frage, ob ein
549
+ # Wert ueberhaupt zum Vokabular gehoert.
550
+ # * Vorlagen erkennt sie am Ablageort (templates/ oder ein Verzeichnis _template),
551
+ # also an der Unterstrich-Konvention, die auch Pruefung 31 benutzt - nicht an einem
552
+ # Namen und nicht an einer gepflegten Liste.
553
+ STATUS_KOPF_RE = re.compile(r"^\|\s*Attribut\s*\|\s*Wert\s*\|$")
554
+ STATUS_ZEILE_RE = re.compile(r"^\|\s*Status\s*\|\s*(.+?)\s*\|$")
555
+ # Der Ausfuellhinweis einer Vorlage in der Form, die D-104 gesetzt hat: die Marke, ein
556
+ # Semikolon und der Satz, mit welchem Wert die Kopie beginnt.
557
+ STATUS_SCHLITZ_RE = re.compile(r"^<TBD: Status; .*\bbeginnt auf entwurf>$")
558
+ STATUS_ZELLE = "\\| Status \\| … \\|"
559
+
560
+
561
+ def _status_steckbrief(text: str):
562
+ """Die Zeilen des Steckbriefs eines Dokuments, oder None.
563
+
564
+ Der Steckbrief ist die erste Tabelle des Dokuments; sie steht vor der ersten
565
+ Ueberschrift der Ebene 2 und traegt die Kopfzeile "| Attribut | Wert |". Eine
566
+ erste Tabelle mit anderer Kopfzeile bedeutet: kein Steckbrief - und eine Tabelle
567
+ weiter unten ist keiner, auch wenn sie so aussieht (PLAN_TEMPLATE.md).
568
+ """
569
+ zeilen = text.replace("\r\n", "\n").split("\n")
570
+ for nr, roh in enumerate(zeilen):
571
+ z = roh.strip()
572
+ if z.startswith("## "):
573
+ return None
574
+ if not z.startswith("|"):
575
+ continue
576
+ if not STATUS_KOPF_RE.match(z):
577
+ return None
578
+ raus = []
579
+ for weiter in zeilen[nr:]:
580
+ if not weiter.strip().startswith("|"):
581
+ break
582
+ raus.append(weiter.strip())
583
+ return raus
584
+ return None
585
+
586
+
587
+ def _status_ist_vorlage(rest: str) -> bool:
588
+ """Liegt die Datei in einer Vorlagenablage? Unterstrich-Konvention wie Pruefung 31."""
589
+ return rest.startswith("templates/") or "/_template/" in rest
590
+
591
+
592
+ def check_status_vokabular(root: str) -> None:
593
+ """Pruefung 47 (D-105, D-108): Jeder Steckbrief fuehrt einen gueltigen Statuswert."""
594
+ gefunden = 0
595
+ for pfad, rest in _d11_kerndateien(root, (".md",)):
596
+ steckbrief = _status_steckbrief(read(pfad))
597
+ if steckbrief is None:
598
+ continue
599
+ gefunden += 1
600
+ werte = [m.group(1).strip() for m in
601
+ (STATUS_ZEILE_RE.match(z) for z in steckbrief) if m]
602
+
603
+ # --- Gegenstand 2: Vollstaendigkeit -------------------------------------------
604
+ if not werte:
605
+ err(f"{KERN}/{rest}: der Steckbrief führt keine Zeile `{STATUS_ZELLE}`. "
606
+ f"Jeder Träger mit einem Steckbrief durchläuft den Lebenszyklus "
607
+ f"(D-102); bis 0.50.0 definierte sich der Modulträger über genau diese "
608
+ f"Zeile und ließ damit jeden entkommen, der sie wegließ – zwölf taten "
609
+ f"es, darunter die elf normativen Kernmodule, für die FW-CL-11 einen "
610
+ f"Status oberhalb von `entwurf` verlangt (K-36, D-105)")
611
+ continue
612
+
613
+ wert = werte[0].strip("`").strip()
614
+ schlitz = wert.startswith("<TBD")
615
+ vorlage = _status_ist_vorlage(rest)
616
+
617
+ # --- Gegenstand 4: der Schlitz gehoert der Vorlage, und nur ihr ---------------
618
+ if schlitz and not vorlage:
619
+ err(f"{KERN}/{rest}: die Statuszelle trägt den Ausfüllschlitz '{wert}', "
620
+ f"obwohl die Datei keine Vorlage ist. Wer eine Vorlage kopiert, füllt "
621
+ f"den Schlitz – sonst steht ein Pack ohne Statuswert im Bestand. Das "
622
+ f"ist der Preis, den D-104 benannt und nicht abgesichert hat (D-108)")
623
+ continue
624
+ if vorlage and not schlitz:
625
+ err(f"{KERN}/{rest}: die Statuszelle einer Vorlage trägt den echten Wert "
626
+ f"'{wert}' statt eines Ausfüllschlitzes. Der Steckbrief einer Vorlage "
627
+ f"beschreibt die KOPIE; ein echter Wert geht unverändert in jede Kopie "
628
+ f"über und ist damit unveränderlich, ohne dass jemand das entschieden "
629
+ f"hätte. Genau so war Kriterium 3 von D-11 unerreichbar (D-104). "
630
+ f"Erwartet: '<TBD: Status; … beginnt auf entwurf>'")
631
+ continue
632
+ if schlitz:
633
+ if not STATUS_SCHLITZ_RE.match(wert):
634
+ err(f"{KERN}/{rest}: der Ausfüllschlitz '{wert}' folgt nicht der Form "
635
+ f"'<TBD: Status; … beginnt auf entwurf>'. Ein Schlitz, der den "
636
+ f"Anfangswert nicht nennt, lässt die Kopie raten (D-104)")
637
+ continue
638
+
639
+ # --- Gegenstand 3: das Vokabular ---------------------------------------------
640
+ erstes = wert.split()[:1]
641
+ if erstes and erstes[0] not in SKILL_STATUS:
642
+ err(f"{KERN}/{rest}: Statuswert '{wert}' gehört nicht zum Vokabular. "
643
+ f"Zulässig sind die fünf Werte aus "
644
+ f"framework/core/08-skill-conventions.md Abschnitt 7 "
645
+ f"({', '.join(sorted(SKILL_STATUS))}); verglichen wird das erste Wort, "
646
+ f"ein Verlaufszusatz in Klammern ist zulässig. Bis 0.50.0 griff diese "
647
+ f"Regel nur in einer SKILL.md – für 56 der 69 Statusträger war jede "
648
+ f"Zeichenfolge erlaubt (D-108)")
649
+
650
+ # --- Gegenstand 1: der Anker ------------------------------------------------------
651
+ if not gefunden:
652
+ err(f"{KERN}/: kein einziger Steckbrief gefunden (erste Tabelle des Dokuments "
653
+ f"vor der ersten Überschrift der Ebene 2, Kopfzeile `| Attribut | Wert |`). "
654
+ f"Prüfung 47 hat ihren Gegenstand verloren und würde sonst leise bestehen "
655
+ f"(D-108)")
656
+
657
+
658
+ # --- Pruefung 50 -------------------------------------------------------------------
659
+ # Die Ausnahmemenge steht in dem Dokument, das die REGEL traegt - nicht hier. Eine
660
+ # Ausnahme im Kopfkommentar einer Pruefung findet niemand, der die Regel liest (0.57.0).
661
+ SYNTH_ANKER = "**Belegte synthetische Kennungen"
662
+ KLAERUNG_RE = re.compile(r"\bK-\d+\b")
663
+ KLAERUNG_ZEILE_RE = re.compile(r"^\|\s*(K-\d+)\s*\|", re.M)
664
+
665
+
666
+ def _synthetische_kennungen(logtext: str) -> set:
667
+ """Die belegten synthetischen Kennungen - aus dem Absatz des Decision Logs.
668
+
669
+ Sie gehoeren keinem Klaerungspunkt: Sonden und Gegenproben des Pruefapparats
670
+ brauchen Kennungen, die nie echt vergeben werden (D-23-Nachweis ohne Kollision).
671
+ Leere Menge heisst: der Anker ist verloren - der Aufrufer meldet das.
672
+ """
673
+ for zeile in logtext.splitlines():
674
+ if zeile.lstrip().startswith(SYNTH_ANKER):
675
+ return set(re.findall(r"`([A-Z]+-\d+)`", zeile))
676
+ return set()
677
+
678
+
679
+ def check_klaerungsregister(root: str) -> None:
680
+ """Pruefung 50 (D-147): Jede im Kern genannte Klaerungspunktkennung steht im Register."""
681
+ logpfad = os.path.join(root, KERN, "governance", "DECISION_LOG.md")
682
+ if not os.path.exists(logpfad):
683
+ err(f"{KERN}/governance/DECISION_LOG.md fehlt – Prüfung 50 hat ihren Gegenstand "
684
+ f"verloren; sie bestünde sonst leise (D-23)")
685
+ return
686
+ logtext = read(logpfad)
687
+ synth = _synthetische_kennungen(logtext)
688
+ if not synth:
689
+ err(f"{KERN}/governance/DECISION_LOG.md: der Absatz '{SYNTH_ANKER}…' fehlt oder "
690
+ f"nennt keine Kennung in Backticks – Prüfung 50 leitet ihre Ausnahmemenge "
691
+ f"daraus ab und hat ihren Anker verloren (D-23)")
692
+ return
693
+ gefuehrt = set(KLAERUNG_ZEILE_RE.findall(logtext))
694
+ if not gefuehrt:
695
+ err(f"{KERN}/governance/DECISION_LOG.md: keine Registerzeile '| K-NN |' gefunden – "
696
+ f"Prüfung 50 hat ihren Gegenstand verloren (D-23)")
697
+ return
698
+ fundorte: dict = {}
699
+ for path in iter_text_files(root):
700
+ rel = os.path.relpath(path, root).replace(os.sep, "/")
701
+ if not rel.startswith(KERN + "/"):
702
+ continue
703
+ if not path.endswith((".md", ".py", ".json", ".template")):
704
+ continue
705
+ for kennung in set(KLAERUNG_RE.findall(read(path))):
706
+ fundorte.setdefault(kennung, set()).add(rel)
707
+ for kennung in sorted(set(fundorte) - gefuehrt - synth,
708
+ key=lambda k: int(k.split("-")[1])):
709
+ traeger = sorted(fundorte[kennung])
710
+ err(f"{KERN}/governance/DECISION_LOG.md: '{kennung}' wird in "
711
+ f"{len(traeger)} Träger(n) genannt ({', '.join(traeger[:3])}"
712
+ f"{' …' if len(traeger) > 3 else ''}) und steht in keiner Registerzeile. "
713
+ f"Ein Register, das seinen Gegenstand nicht führt, ist keine Liste offener "
714
+ f"Punkte, sondern eine Auswahl (D-147)")
715
+
716
+ # --- Pruefung 102: die Form des Klaerungsregisters (CR-2026-158, D-465) -------------------
717
+ # ANLASS, NACHGEZAEHLT am 2026-09-29: 114 von 184 Klaerungspunkten standen in der
718
+ # Entscheidungstabelle (K-100 nannte 27), eine Leerzeile teilte die Klaerungstabelle, und elf
719
+ # erledigte Punkte trugen weiter "offen". Pruefung 50 fragt nur, OB eine Kennung eine Zeile
720
+ # hat - nicht, wo sie steht und womit ihr Status beginnt.
721
+ #
722
+ # ABGELEITET, NICHT GEPFLEGT: Das Vokabular steht in der Legende des Decision Logs, hinter
723
+ # '*Klärungspunkte:*' bis zum Satz 'Diese Aufzählung ist vollständig', je Wert in Backticks.
724
+ # Ein Wert mit Auslassungszeichen ('eingeplant (…)', 'zusammengelegt mit K-…') gilt als
725
+ # Praefix bis dorthin.
726
+ #
727
+ # WAS SIE NICHT LEISTET: Sie sieht den ANFANG der Statuszelle, nicht, ob er stimmt. Ein
728
+ # erledigter Punkt, der "offen" traegt, bleibt eine Frage der Durchsicht (D-465).
729
+ # AUSGENOMMEN wie in Pruefung 50: die belegten synthetischen Kennungen des Pruefapparats. Die
730
+ # Gegenprobe 46b braucht einen Klaerungspunkt mit dem Wert eines Decision Records - ein
731
+ # Sondenfall, kein Registerfall; der erste Abnahmelauf von 1.18.1 hat ihn gemeldet.
732
+ P102_LEGENDE = "*Klärungspunkte:*"
733
+ P102_LEGENDE_ENDE = "Diese Aufzählung ist vollständig"
734
+ P102_ABSCHNITT = "## 1. "
735
+ P102_ZUSAMMEN_RE = re.compile(r"^zusammengelegt mit (K-\d+)")
736
+
737
+
738
+ def _p102_vokabular(logtext: str) -> list:
739
+ for zeile in logtext.splitlines():
740
+ if P102_LEGENDE in zeile:
741
+ teil = zeile.split(P102_LEGENDE, 1)[1].split(P102_LEGENDE_ENDE, 1)[0]
742
+ return [w.split("…", 1)[0] for w in re.findall(r"`([^`]+)`", teil)]
743
+ return []
744
+
745
+
746
+ def _p102_kopf(zelle: str) -> str:
747
+ """Der Anfang einer Statuszelle ohne Auszeichnung und ohne vorangestellte Zeichen."""
748
+ return re.sub(r"^[^\w(]+", "", re.sub(r"[*`]", "", zelle))
749
+
750
+
751
+ def check_klaerungsregister_form(root: str) -> None:
752
+ """Pruefung 102 (D-465): Lage und Statusanfang jedes Klaerungspunkts."""
753
+ logpfad = os.path.join(root, KERN, "governance", "DECISION_LOG.md")
754
+ if not os.path.exists(logpfad):
755
+ return # Pruefung 50 meldet das bereits
756
+ rel = f"{KERN}/governance/DECISION_LOG.md"
757
+ logtext = read(logpfad).replace("\r\n", "\n")
758
+ vokabular = _p102_vokabular(logtext)
759
+ synth = _synthetische_kennungen(logtext)
760
+ if not vokabular:
761
+ err(f"{rel}: die Legende nennt hinter '{P102_LEGENDE}' keinen Statuswert in Backticks – "
762
+ f"Prüfung 102 leitet ihr Vokabular daraus ab und hat ihren Anker verloren (D-23)")
763
+ return
764
+ abschnitt = ""
765
+ status = {}
766
+ for nr, zeile in enumerate(logtext.split("\n"), 1):
767
+ if zeile.startswith("## "):
768
+ abschnitt = zeile
769
+ continue
770
+ m = KLAERUNG_ZEILE_RE.match(zeile)
771
+ if not m:
772
+ continue
773
+ kennung = m.group(1)
774
+ if kennung in synth:
775
+ continue
776
+ if not abschnitt.startswith(P102_ABSCHNITT):
777
+ err(f"{rel}:{nr}: '{kennung}' steht unter '{abschnitt[3:].strip() or 'keiner Überschrift'}' "
778
+ f"statt in der Klärungstabelle (Abschnitt 1). Dort rendert die Zeile unter fremden "
779
+ f"Spaltenköpfen, und wer die offenen Punkte zählt, zählt eine Tabelle zu wenig (D-465)")
780
+ zellen = tabellenzellen(zeile.strip())
781
+ kopf = _p102_kopf(zellen[-1]) if zellen else ""
782
+ status[kennung] = (nr, kopf)
783
+ if not any(kopf.startswith(w) for w in vokabular):
784
+ err(f"{rel}:{nr}: die Statuszelle von '{kennung}' beginnt mit „{kopf[:40]}“ – kein Wert "
785
+ f"der Legende ({', '.join(vokabular)}). Ein Status außerhalb des Vokabulars "
786
+ f"zählt niemand richtig: bis 1.18.1 trugen elf erledigte Punkte „offen“ (D-465)")
787
+ elif re.match(r"^eingeplant \(\s*\)", kopf):
788
+ err(f"{rel}:{nr}: '{kennung}' ist eingeplant, nennt aber kein Ziel in der Klammer (D-465)")
789
+ for kennung, (nr, kopf) in status.items():
790
+ m = P102_ZUSAMMEN_RE.match(kopf)
791
+ if not m:
792
+ continue
793
+ ziel = m.group(1)
794
+ if ziel not in status:
795
+ err(f"{rel}:{nr}: '{kennung}' ist mit '{ziel}' zusammengelegt, das keine Registerzeile "
796
+ f"hat – der Gegenstand wird nirgends geführt (D-465)")
797
+ elif P102_ZUSAMMEN_RE.match(status[ziel][1]):
798
+ err(f"{rel}:{nr}: '{kennung}' ist mit '{ziel}' zusammengelegt, das selbst "
799
+ f"zusammengelegt ist – eine Kette statt eines Ortes (D-465)")
800
+
801
+
802
+ # --- Pruefung 53 -------------------------------------------------------------------
803
+ # Der Releaseplan sagt je Posten voraus, wohin Kriterium 2 geht. Die Vorhersagen bilden
804
+ # eine KETTE: Was ein Posten erreicht, ist der Ausgangswert des naechsten. Bis 0.60.0 hat
805
+ # niemand sie nachgerechnet - und das Protokoll zu 0.56.0 hatte ausdruecklich entschieden,
806
+ # das nicht zu tun ("die Zwischenstaende sind Vorhersagen und tragen keinen Anspruch, den
807
+ # eine Pruefung einloesen muesste").
808
+ #
809
+ # DIE ENTSCHEIDUNG IST MIT 0.61.0 UMGEKEHRT, UND DER GRUND IST GEMESSEN (D-153): 0.60.0 hat
810
+ # eine Zelle aus einem Posten herausgenommen, die Zahl des Postens nachgezogen und die des
811
+ # FOLGEPOSTENS stehen lassen. Die Kette riss um eins, der Plan war in sich widerspruechlich,
812
+ # und er ist so gemergt worden.
813
+ #
814
+ # DIE PRUEFUNG BEURTEILT NICHT, OB EINE VORHERSAGE STIMMT - das kann sie nicht. Sie prueft,
815
+ # ob die Tabelle mit sich selbst uebereinstimmt: Kette geschlossen, und der letzte Wert ist
816
+ # null, weil Kriterium 2 dort ankommen muss (D-11).
817
+ #
818
+ # WAS SIE NICHT LEISTET: Die zweite Haelfte desselben Befundes war PROSA - die Zeile nannte
819
+ # weiter eine Klasse, die ihre eigene Zahl nicht mehr enthielt. Das ist nicht mechanisch zu
820
+ # finden und bleibt Gegenstand des Durchgangs vor dem Commit.
821
+ P53_ROADMAP = KERN + "/docs/ROADMAP.md"
822
+ P53_UEBERSCHRIFT = "#### Der Releaseplan bis 1.0.0 und darüber hinaus"
823
+ P53_KETTE_RE = re.compile(r"Kriterium 2:\s*\*\*(\d+)\s*→\s*(\d+)\*\*")
824
+
825
+
826
+ def check_releaseplan_kette(root: str) -> None:
827
+ """Pruefung 53 (D-153): Die Kriterium-2-Kette des Releaseplans schliesst und endet bei 0."""
828
+ pfad = os.path.join(root, P53_ROADMAP.replace("/", os.sep))
829
+ if not os.path.isfile(pfad):
830
+ err(f"{P53_ROADMAP} fehlt – Prüfung 53 hat ihren Gegenstand verloren; sie bestünde "
831
+ f"sonst leise (D-23)")
832
+ return
833
+ text = read(pfad).replace("\r\n", "\n")
834
+ if P53_UEBERSCHRIFT not in text:
835
+ err(f"{P53_ROADMAP}: die Überschrift '{P53_UEBERSCHRIFT}' ist nicht mehr "
836
+ f"auffindbar. Prüfung 53 liest den Releaseplan darunter und hätte ohne sie "
837
+ f"nichts zu prüfen (D-23)")
838
+ return
839
+ rest = text.split(P53_UEBERSCHRIFT, 1)[1]
840
+ glieder = []
841
+ for zeile in rest.split("\n"):
842
+ if not zeile.startswith("|"):
843
+ if glieder and not zeile.strip():
844
+ continue
845
+ m = P53_KETTE_RE.search(zeile)
846
+ if m:
847
+ glieder.append((int(m.group(1)), int(m.group(2)), zeile.split("|")[1].strip()))
848
+ if len(glieder) < 2:
849
+ err(f"{P53_ROADMAP}: der Releaseplan führt weniger als zwei Vorhersagen zu "
850
+ f"Kriterium 2. Prüfung 53 rechnet eine Kette nach und hätte damit keinen "
851
+ f"Gegenstand mehr (D-23)")
852
+ return
853
+ for (_, ende, posten), (start, _, folge) in zip(glieder, glieder[1:]):
854
+ if ende != start:
855
+ err(f"{P53_ROADMAP}: Die Kriterium-2-Kette des Releaseplans reißt zwischen "
856
+ f"{posten} (endet bei {ende}) und {folge} (beginnt bei {start}). Was ein "
857
+ f"Posten erreicht, ist der Ausgangswert des nächsten; eine Tabelle, die "
858
+ f"sich selbst widerspricht, ist keine Vorhersage (D-153)")
859
+ if glieder[-1][1] != 0:
860
+ err(f"{P53_ROADMAP}: Die Kriterium-2-Kette des Releaseplans endet bei "
861
+ f"{glieder[-1][1]} statt bei 0 ({glieder[-1][2]}). Kriterium 2 von D-11 ist "
862
+ f"erfüllt, wenn der Testkatalog keine offene Zelle mehr führt – ein Plan, der "
863
+ f"nicht dort ankommt, führt nicht bis 1.0.0 (D-153)")
864
+
865
+ # --- Pruefung 58: Vollstaendigkeit des Decision-Record-Registers -------------------
866
+ #
867
+ # DIE SCHWESTER VON PRUEFUNG 50, eine Kennungsfamilie weiter. Der gemessene Fall stammt
868
+ # aus dem eigenen Pruefapparat: Die Registereintraege der Pruefungen 55 und 56 trugen
869
+ # seit 0.63.0 einen Platzhalter an der Stelle der Nummer, waehrend die Meldungen
870
+ # derselben Pruefungen die richtige Kennung nannten.
871
+ #
872
+ # WARUM DAS MUSTER EINEN SCHWANZ HAT. Ein Muster der Form D-\d+ mit abschliessender
873
+ # Wortgrenze findet den gemessenen Fall NICHT: Zwischen der letzten Ziffer und dem
874
+ # Platzhalterzeichen steht keine Wortgrenze. Deshalb wird alles gelesen, was auf die
875
+ # erste Ziffer folgt - und danach geprueft, ob die Form ueberhaupt stimmt. Eine Kennung,
876
+ # die die Form knapp verfehlt, ist fuer einen Zaehler sonst unsichtbar, und das ist die
877
+ # gefaehrlichere Haelfte: Sie sieht im Fliesstext wie eine Kennung aus.
878
+ D58_ERWAEHNUNG_RE = re.compile(r"(?<![\w-])D-\d[\w+]*")
879
+ D58_ZEILE_RE = re.compile(r"^\|\s*(D-\d+)\s*\|", re.M)
880
+
881
+
882
+ def check_decisionregister(root: str) -> None:
883
+ """Pruefung 58 (D-169): Jede genannte D-Kennung steht im Register des Decision Logs."""
884
+ logpfad = os.path.join(root, KERN, "governance", "DECISION_LOG.md")
885
+ if not os.path.exists(logpfad):
886
+ return # Pruefung 50 meldet den fehlenden Traeger bereits
887
+ logtext = read(logpfad)
888
+ synth = _synthetische_kennungen(logtext)
889
+ gefuehrt = set(D58_ZEILE_RE.findall(logtext))
890
+ if not gefuehrt:
891
+ err(f"{KERN}/governance/DECISION_LOG.md: keine Registerzeile '| D-NNN |' "
892
+ f"gefunden - Prüfung 58 hat ihren Gegenstand verloren; sie bestünde sonst "
893
+ f"leise (D-23, D-169)")
894
+ return
895
+ fundorte: dict = {}
896
+ for path in iter_text_files(root):
897
+ rel = os.path.relpath(path, root).replace(os.sep, "/")
898
+ if not rel.startswith(KERN + "/"):
899
+ continue
900
+ if not path.endswith((".md", ".py", ".json", ".template")):
901
+ continue
902
+ for kennung in set(D58_ERWAEHNUNG_RE.findall(read(path))):
903
+ fundorte.setdefault(kennung, set()).add(rel)
904
+ for kennung in sorted(set(fundorte) - gefuehrt - synth):
905
+ traeger = sorted(fundorte[kennung])
906
+ ort = (f"{len(traeger)} Träger(n) ({', '.join(traeger[:3])}"
907
+ f"{' …' if len(traeger) > 3 else ''})")
908
+ if re.fullmatch(r"D-\d+", kennung) is None:
909
+ err(f"{KERN}/governance/DECISION_LOG.md: '{kennung}' wird in {ort} genannt "
910
+ f"und ist keine Kennung der Form D-NNN. Eine Kennung, die die Form knapp "
911
+ f"verfehlt, ist für jeden Zähler unsichtbar und liest sich im Fließtext "
912
+ f"trotzdem wie eine (D-169)")
913
+ else:
914
+ err(f"{KERN}/governance/DECISION_LOG.md: '{kennung}' wird in {ort} genannt "
915
+ f"und steht in keiner Registerzeile. Ein Register, das seinen Gegenstand "
916
+ f"nicht führt, ist keine Liste, sondern eine Auswahl (D-169)")
917
+
918
+
919
+ # --- Pruefung 91: die Standueberschrift der Roadmap (D-372) -------------------------
920
+ #
921
+ # ANLASS, gemessen beim Bau von 1.8.0: "## Stand nach Release 1.4.4" - vier Releases
922
+ # alt, direkt ueber "Wird mit jedem Release fortgeschrieben". Bis 0.88.1 stand sie auf
923
+ # 0.56.0, zweiunddreissig Releases lang. Eine Ueberschrift, die sagt, von wann sie ist,
924
+ # ist eine Zahl mit einem Gegenstand - und der liegt in VERSION.
925
+ # GRENZE: Sie prueft die ZAHL der Ueberschrift, nicht den Abschnitt darunter - dieselbe
926
+ # Bauform wie 77 (Version, nicht Inhalt). Das Datum in Klammern prueft sie nicht.
927
+ P91_ROADMAP = KERN + "/docs/ROADMAP.md"
928
+ P91_ANKER = "## Stand nach Release "
929
+ P91_RE = re.compile(r"^## Stand nach Release `?(\d+\.\d+\.\d+)`?", re.M)
930
+
931
+
932
+ def check_roadmapstand(root: str) -> None:
933
+ """Pruefung 91 (D-372): Die Standueberschrift der Roadmap nennt VERSION."""
934
+ rpfad = os.path.join(root, *P91_ROADMAP.split("/"))
935
+ vpfad = os.path.join(root, KERN, "VERSION")
936
+ if not os.path.isfile(rpfad) or not os.path.isfile(vpfad):
937
+ return # Pruefungen 1 und 85 melden den fehlenden Traeger bereits
938
+ text = read(rpfad)
939
+ treffer = P91_RE.findall(text)
940
+ if len(treffer) != 1:
941
+ err(f"{P91_ROADMAP}: die Überschrift '{P91_ANKER}X.Y.Z' steht "
942
+ f"{len(treffer)}-mal statt genau einmal. Prüfung 91 hält sie gegen "
943
+ f"{KERN}/VERSION und bestünde ohne sie leise (D-23, D-372)")
944
+ return
945
+ stand = read(vpfad).strip()
946
+ if treffer[0] != stand:
947
+ err(f"{P91_ROADMAP}: die Standüberschrift nennt Release {treffer[0]}, "
948
+ f"{KERN}/VERSION führt {stand}. Die Überschrift sagt, von wann der Abschnitt "
949
+ f"darunter ist – bei 1.8.0 stand sie vier Releases zurück, direkt über dem "
950
+ f"Satz 'Wird mit jedem Release fortgeschrieben' (D-372)")