@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,1325 @@
1
+ """Sonden zu den Pruefungen 6 (Starter), 8 und 66 bis 80; Selbstprobe der
2
+ Beschreibungssaetze.
3
+
4
+ Teil des Sondenskripts probe-pruefungen.py, seit 1.19.1 in Module geteilt (K-174). Die
5
+ Einheiten melden sich beim Laden dieses Moduls an; der Einstieg laedt die Module in der
6
+ Reihenfolge ihrer Nummer, und das ist die Reihenfolge der Ausgabe (D-49). Ein Modul
7
+ liest nur aus dem Apparat und aus frueheren Teilen."""
8
+ from __future__ import annotations
9
+
10
+ import json
11
+ import os
12
+ import re
13
+ import shutil
14
+
15
+ from .apparat import (
16
+ aufraeumen, buendel, EINHEITEN, ersetze, ersetzt, gegenprobe, installation, kopie,
17
+ lies, melde, notiz, P, Praeparationsfehler, SATZ_MAX, SATZ_MIN, schreib, sonde,
18
+ unterprozess, validator_ausgabe, worte, zeile_nach)
19
+ from .teil03_pruefungen_26_bis_36 import _manifest_aendern
20
+
21
+
22
+ # --- 6: die Starter sind Traeger der Inhaltspruefung (D-365) ----------------------------
23
+
24
+ sonde("6s", "Eine IP-Adresse in install.cmd wird gemeldet (D-365)",
25
+ lambda root: schreib(os.path.join(root, "install.cmd"),
26
+ lies(os.path.join(root, "install.cmd"))
27
+ + "rem Server: 10.11.12.13\n"),
28
+ "FW-CONTENT-IP")
29
+ sonde("6s", "Eine IP-Adresse in install.command wird gemeldet (D-365)",
30
+ lambda root: schreib(os.path.join(root, "install.command"),
31
+ lies(os.path.join(root, "install.command"))
32
+ + "# Server: 10.11.12.13\n"),
33
+ "FW-CONTENT-IP")
34
+
35
+
36
+ # --- 8: der registrierte Traeger existiert (CR-2026-139, D-360) --------------------
37
+ #
38
+ # Bis 1.5.0 pruefte Pruefung 8 Schluessel und Aufzaehlungswerte des Overlay-Manifests,
39
+ # nicht aber, ob unter `path` etwas liegt. Die Sonden schreiben das Manifest aus der
40
+ # VERSIONIERTEN Vorlage (templates/project-overlay/) und setzen darin einen
41
+ # Beispieleintrag auf einen echten Pfad. Das Overlay des Quellrepositoriums selbst steht
42
+ # in der .gitignore - die erste Fassung dieser Sonden las es und brach an einer
43
+ # frischen Auscheckung ab (gefunden beim Gegenbeweis, CR-2026-139). Die Gegenprobe ist
44
+ # die wichtigere: Ein Eintrag, der auf eine vorhandene Datei zeigt, bleibt still - und
45
+ # die Beispiele der Vorlage mit Ausfuellschlitz im Pfad ebenso, sonst waere jedes
46
+ # frische Overlay rot.
47
+ M8_PFAD = "existiert nicht. Ein registriertes Dokument"
48
+ M8_REGEL = "Mit load rule trägt die Regeldatei"
49
+ P8_MANIFEST = ".koolie/project-overlay/overlay-manifest.yaml".replace("/", os.sep)
50
+ P8_VORLAGE = ".koolie/core/templates/project-overlay/overlay-manifest.yaml".replace("/", os.sep)
51
+ P8_BEISPIEL_ARCH = 'path: ".koolie/project-overlay/documents/architecture/<TBD>.md"'
52
+ P8_BEISPIEL_CG = 'path: ".koolie/project-overlay/documents/coding-guidelines/<TBD: datei>.md"'
53
+ P8_REGEL_CG = 'rule_file: "<RULES_DIR>/21-overlay-coding-guidelines.md"'
54
+ P8_VORHANDEN = 'path: ".koolie/core/templates/project-overlay/documents/README.md"'
55
+
56
+
57
+ def _8_setze(root: str, *paare) -> None:
58
+ """Das Manifest aus der Vorlage, mit den genannten Ersetzungen je genau einmal."""
59
+ text = lies(P(root, P8_VORLAGE))
60
+ for alt, neu in paare:
61
+ if text.count(alt) != 1:
62
+ raise Praeparationsfehler("Manifestvorlage fuehrt '%s' %dx statt 1x"
63
+ % (alt, text.count(alt)))
64
+ text = text.replace(alt, neu, 1)
65
+ os.makedirs(os.path.dirname(P(root, P8_MANIFEST)), exist_ok=True)
66
+ schreib(P(root, P8_MANIFEST), text)
67
+
68
+
69
+ sonde("8a", "Ein registriertes Dokument, dessen Pfad auf nichts zeigt, wird gemeldet - bis 1.5.0 bestand ein solches Register",
70
+ lambda r: _8_setze(r, (P8_BEISPIEL_ARCH,
71
+ 'path: ".koolie/project-overlay/documents/architecture/gibt-es-nicht.md"')),
72
+ M8_PFAD)
73
+
74
+ sonde("8b", "Ein Dokument mit load rule, dessen Regeldatei fehlt, wird gemeldet - es wirkt sonst nicht",
75
+ lambda r: _8_setze(r, (P8_BEISPIEL_CG, P8_VORHANDEN),
76
+ (P8_REGEL_CG, 'rule_file: ".koolie/project-overlay/gibt-es-nicht.md"')),
77
+ M8_REGEL)
78
+
79
+ gegenprobe("8a", "Ein Eintrag, der auf eine vorhandene Datei zeigt, bleibt still - und die Beispiele mit Ausfuellschlitz im Pfad ebenso",
80
+ lambda r: _8_setze(r, (P8_BEISPIEL_ARCH, P8_VORHANDEN)), M8_PFAD)
81
+
82
+
83
+ # --- 66: das verirrte Steuerzeichen (D-217) --------------------------------------
84
+ #
85
+ # Die Sonden setzen das Zeichen in den beiden Bauformen, in denen es gemessen wurde:
86
+ # am Ende eines Traegers und am Zeilenende einer Tabellenzeile - dort sassen dreizehn
87
+ # der vierzehn Fundstellen. Sie schreiben mit `schreib`, also ohne Umsetzung der
88
+ # Zeilenenden; eine Sonde, die ihren eigenen Gegenstand normalisiert, misst nichts.
89
+ #
90
+ # 🔴 DIE ZWEITE GEGENPROBE IST DIE WICHTIGERE. Sie stellt einen Traeger durchgehend
91
+ # auf LF - also auf die ANDERE Zeilenende-Form - und belegt damit, dass Pruefung 66
92
+ # das verirrte ZEICHEN misst und nicht die Form. Ohne sie waere aus der Meldung nicht
93
+ # zu erkennen, ob hier eine Zeichenpruefung steht oder eine Formatvorschrift, die
94
+ # niemand entschieden hat (K-81).
95
+ M66 = "verirrte(s) Steuerzeichen"
96
+ P66_TRAEGER = ".koolie/core/OWNERS.md".replace("/", os.sep)
97
+ P66_ANTRAG = (".koolie/core/governance/change-requests/"
98
+ "CR-2026-027-zeichenlimit-einstufung.md").replace("/", os.sep)
99
+
100
+
101
+ def _66_am_ende(root: str) -> None:
102
+ """Ein einzelnes CR am Ende eines Kerntraegers - die stillste Fundstelle."""
103
+ pfad = P(root, P66_TRAEGER)
104
+ schreib(pfad, lies(pfad) + chr(13))
105
+
106
+
107
+ def _66_in_der_tabelle(root: str) -> None:
108
+ """Dieselbe Bauform wie vierzehn der sechzehn gemessenen Fundstellen.
109
+
110
+ Ein CR unmittelbar vor dem Zeilenumbruch einer Tabellenzeile. Es rendert nicht,
111
+ es faellt in keinem Diff auf - und es hat elf Antraege dieses Verzeichnisses
112
+ von der Normalisierung ausgenommen.
113
+ """
114
+ pfad = P(root, P66_ANTRAG)
115
+ text = lies(pfad)
116
+ marke = "| Umsetzung |"
117
+ if marke not in text:
118
+ raise Praeparationsfehler(
119
+ "CR-2026-027 fuehrt die Zeile '%s' nicht mehr - die Sonde zu 66 haette "
120
+ "keinen Anker" % marke)
121
+ schreib(pfad, text.replace(marke, chr(13) + marke, 1))
122
+
123
+
124
+ def _66_auf_lf(root: str) -> None:
125
+ """Gegenprobe: ein Traeger durchgehend auf LF - die andere Form, kein Befund."""
126
+ pfad = P(root, P66_TRAEGER)
127
+ schreib(pfad, lies(pfad).replace(chr(13) + chr(10), chr(10)))
128
+
129
+
130
+ sonde("66a", "Ein einzelnes CR am Ende eines Kerntraegers - unsichtbar im Text und genug, damit git die Zeilenenden nicht mehr normalisiert",
131
+ _66_am_ende, M66)
132
+
133
+ sonde("66b", "Dasselbe Zeichen am Zeilenende einer Tabellenzeile - die Bauform von vierzehn der sechzehn gemessenen Fundstellen",
134
+ _66_in_der_tabelle, M66)
135
+
136
+ gegenprobe("66a", "Das unveraenderte Repositorium bleibt unbeanstandet - seit dieser Berichtigung traegt kein Traeger mehr ein verirrtes CR",
137
+ None, M66)
138
+
139
+ gegenprobe("66b", "Ein Traeger durchgehend auf LF wird NICHT gemeldet: gemessen wird das verirrte Zeichen, nicht die Zeilenende-Form",
140
+ _66_auf_lf, M66)
141
+
142
+
143
+ # --- 67: ENTFALLEN mit 1.4.1 (D-350) ----------------------------------------------
144
+ #
145
+ # Pruefung 67 hielt die Titelzeile der Uebergabe gegen VERSION. Seit 1.4.1 ist die
146
+ # Uebergabe nicht mehr versioniert, und mit der Pruefung entfallen ihre vier Sonden
147
+ # und zwei Gegenproben. Eine Sonde auf einen Traeger, den eine frische Auscheckung
148
+ # nicht fuehrt, belegte nur, was auf einem Arbeitsplatz liegt.
149
+
150
+
151
+ # --- 68: das Praefix, das mehr sperrt als sein Befehl (D-219) ----------------------
152
+ #
153
+ # Die dritte Sonde ist die Ankersonde: Ohne exec-Regel haette Pruefung 68 nichts zu
154
+ # rechnen und bestuende leise. Die zweite Gegenprobe belegt den ZUSCHNITT - eine
155
+ # Regel, deren Praefix ihrem Befehl gleicht, erfasst nicht ueber und wird nicht
156
+ # gemeldet, auch ohne Begruendungsfeld. Ohne dieses Paar waere nicht zu unterscheiden,
157
+ # ob die Pruefung die Uebererfassung sucht oder jede Regel ohne Feld.
158
+ M68 = "mehr, als ihr Befehl nennt"
159
+ M68_ANKER = "keine einzige exec-Regel gefunden"
160
+ P68_PERM = ".koolie/core/framework/runtime/permissions.json".replace("/", os.sep)
161
+
162
+
163
+ def _68_laden(root: str) -> dict:
164
+ return json.loads(lies(P(root, P68_PERM)))
165
+
166
+
167
+ def _68_schreiben(root: str, daten: dict) -> None:
168
+ schreib(P(root, P68_PERM), json.dumps(daten, indent=2, ensure_ascii=False))
169
+
170
+
171
+ def _68_feld_entfernen(root: str) -> None:
172
+ """Der gemessene Fall: die Begruendung an der git-branch-Regel faellt weg."""
173
+ daten = _68_laden(root)
174
+ getroffen = 0
175
+ for regel in daten.get("deny", []):
176
+ if regel.get("tool") == "exec" and "_uebererfasst" in regel:
177
+ del regel["_uebererfasst"]
178
+ getroffen += 1
179
+ if getroffen == 0:
180
+ raise Praeparationsfehler(
181
+ "keine exec-Regel mit Begruendungsfeld - die Sonde zu 68 haette keinen "
182
+ "Anker; entweder erfasst keine Regel mehr ueber, dann gehoert die Sonde "
183
+ "weg, oder das Feld heisst anders")
184
+ _68_schreiben(root, daten)
185
+
186
+
187
+ def _68_neue_regel(root: str) -> None:
188
+ """Eine ZWEITE Stelle: eine neue Regel mit kuerzerem Praefix und ohne Feld.
189
+
190
+ Sie belegt, dass die Pruefung an der Bauform haengt und nicht an einer Zeile.
191
+ """
192
+ daten = _68_laden(root)
193
+ daten.setdefault("deny", []).append(
194
+ {"tool": "exec", "command": "sondenbefehl --loeschen",
195
+ "prefix": "sondenbefehl"})
196
+ _68_schreiben(root, daten)
197
+
198
+
199
+ def _68_ohne_exec(root: str) -> None:
200
+ """Ankersonde: keine exec-Regel mehr - der verlorene Gegenstand."""
201
+ daten = _68_laden(root)
202
+ for korb in ("deny", "ask", "allow"):
203
+ daten[korb] = [r for r in daten.get(korb, []) if r.get("tool") != "exec"]
204
+ _68_schreiben(root, daten)
205
+
206
+
207
+ def _68_praefix_gleich_befehl(root: str) -> None:
208
+ """Gegenprobe: eine Regel OHNE Uebererfassung und ohne Feld - kein Befund.
209
+
210
+ 🔴 WER EINEN ERLAUBTEN FALL HERSTELLT, MUSS IHN VOLLSTAENDIG HERSTELLEN
211
+ (0.66.0). Eine neue Regel in der Kernquelle macht die lokale Testinstallation
212
+ unvollstaendig, und der Abgleich der Berechtigungsdatei meldet die fehlende
213
+ Regel - einen Fehler, den diese Gegenprobe nicht gemeint hat. Der gerenderte
214
+ Eintrag gehoert deshalb mit.
215
+ """
216
+ daten = _68_laden(root)
217
+ daten.setdefault("deny", []).append(
218
+ {"tool": "exec", "command": "sondenbefehl"})
219
+ _68_schreiben(root, daten)
220
+ inst = P(root, ".devin", "config.json")
221
+ if os.path.isfile(inst):
222
+ konf = json.loads(lies(inst))
223
+ konf["permissions"]["deny"].append("Exec(sondenbefehl)")
224
+ schreib(inst, json.dumps(konf, indent=2, ensure_ascii=False))
225
+
226
+
227
+ sonde("68a", "Eine exec-Regel sperrt ueber ihr Praefix mehr, als ihr Befehl nennt, und sagt es nicht - der Eintrag, der 25 Abweisungen erzeugt hat",
228
+ _68_feld_entfernen, M68)
229
+
230
+ sonde("68b", "Dieselbe Bauform an einer ZWEITEN Stelle: eine neu eingefuegte Regel mit kuerzerem Praefix wird ebenso gemeldet",
231
+ _68_neue_regel, M68)
232
+
233
+ sonde("68c", "Ohne exec-Regel meldet Pruefung 68 den verlorenen Gegenstand, statt leise zu bestehen",
234
+ _68_ohne_exec, M68_ANKER)
235
+
236
+ gegenprobe("68a", "Das unveraenderte Repositorium bleibt unbeanstandet - alle vier uebererfassenden Regeln tragen ihre Begruendung",
237
+ None, M68)
238
+
239
+
240
+ # --- 69: der Messapparat schreibt nicht in das Repositorium (D-222) ----------------
241
+ #
242
+ # Zwei Formen desselben Gegenstands: die Belegdatei (69a) und das Verzeichnis, das
243
+ # `lauf.py` selbst anlegen wuerde (69b). Die dritte ist die Ankersonde - eine leere
244
+ # Erhebungsablage haette nichts zu zaehlen und bestuende leise. Die Gegenprobe
245
+ # belegt den ZUSCHNITT: Eine weitere .py-Datei ist ein WERKZEUG und wird NICHT
246
+ # gemeldet; ohne sie waere nicht zu unterscheiden, ob die Pruefung die Art der
247
+ # Datei prueft oder jede Neuerung.
248
+ M69 = "Erhebungsablage des Kerns"
249
+ M69_ANKER = "kein einziges Werkzeug gefunden"
250
+ P69_ORDNER = ".koolie/core/tests/erhebungen".replace("/", os.sep)
251
+
252
+
253
+ def _69_beleg(root: str) -> None:
254
+ """Der gemessene Fall: ein Ergebnis-JSON eines Laufs landet im Repositorium."""
255
+ schreib(P(root, P69_ORDNER, "sk010n02-ergebnis.json"), '{"is_error": false}')
256
+
257
+
258
+ def _69_verzeichnis(root: str) -> None:
259
+ """Die zweite Form: das Belegverzeichnis, das lauf.py selbst anlegen wuerde."""
260
+ os.makedirs(P(root, P69_ORDNER, "belege"), exist_ok=True)
261
+ schreib(P(root, P69_ORDNER, "belege", "sk010n02-antwort.md"), "Antwort")
262
+
263
+
264
+ def _69_leer(root: str) -> None:
265
+ """Ankersonde: keine Werkzeuge mehr - der verlorene Gegenstand."""
266
+ ordner = P(root, P69_ORDNER)
267
+ if not os.path.isdir(ordner):
268
+ raise Praeparationsfehler(
269
+ "die Erhebungsablage fehlt - die Sonde zu 69 haette keinen Anker")
270
+ for name in os.listdir(ordner):
271
+ ziel = os.path.join(ordner, name)
272
+ if os.path.isfile(ziel):
273
+ os.remove(ziel)
274
+ else:
275
+ shutil.rmtree(ziel)
276
+
277
+
278
+ def _69_weiteres_werkzeug(root: str) -> None:
279
+ """Gegenprobe: ein weiteres Skript ist ein Werkzeug und kein Befund."""
280
+ schreib(P(root, P69_ORDNER, "sondenwerkzeug.py"), "# nichts" + chr(10))
281
+
282
+
283
+ sonde("69a", "Ein Ergebnis-JSON in der Erhebungsablage des Kerns wird gemeldet - der Fall, den die fuenf relativen Pfade nach dem Umzug erzeugt haetten",
284
+ _69_beleg, M69)
285
+
286
+ sonde("69b", "Dieselbe Bauform als VERZEICHNIS: das Belegverzeichnis, das lauf.py selbst anlegen wuerde, wird ebenso gemeldet",
287
+ _69_verzeichnis, M69)
288
+
289
+ sonde("69c", "Ohne ein einziges Werkzeug meldet Pruefung 69 den verlorenen Gegenstand, statt leise zu bestehen",
290
+ _69_leer, M69_ANKER)
291
+
292
+
293
+ def _69_beleg_im_paket(root: str) -> None:
294
+ """Seit 1.19.0 (D-473): ein Beleg IM zugelassenen Werkzeugpaket ist derselbe Befund."""
295
+ paket = P(root, P69_ORDNER, "apparat")
296
+ if not os.path.isdir(paket):
297
+ raise Praeparationsfehler("das Paket apparat/ fehlt - die Sonde 69d haette keinen Gegenstand")
298
+ schreib(os.path.join(paket, "reihe-sonde.json"), '{"name": "sonde"}')
299
+
300
+
301
+ def _69_modul_im_paket(root: str) -> None:
302
+ """Gegenprobe: ein weiteres Modul im Paket ist ein Werkzeug."""
303
+ schreib(P(root, P69_ORDNER, "apparat", "sondenmodul.py"), "# nichts" + chr(10))
304
+
305
+
306
+ sonde("69d", "Eine Reihe als JSON im Werkzeugpaket apparat/ wird gemeldet - das Paket ist fuer Quelltext zugelassen, nicht fuer Aufzeichnung",
307
+ _69_beleg_im_paket, M69)
308
+
309
+ gegenprobe("69b", "Ein weiteres Modul im Werkzeugpaket apparat/ bleibt unbeanstandet",
310
+ _69_modul_im_paket, M69)
311
+
312
+ gegenprobe("69a", "Ein weiteres .py-Skript ist ein Werkzeug und wird NICHT gemeldet - die Pruefung haengt an der Art der Datei, nicht an ihrer Neuheit",
313
+ _69_weiteres_werkzeug, M69)
314
+
315
+ gegenprobe("68b", "Eine Regel, deren Praefix ihrem Befehl gleicht, wird NICHT gemeldet - auch ohne Begruendungsfeld; gemessen wird die Uebererfassung, nicht das fehlende Feld",
316
+ _68_praefix_gleich_befehl, M68)
317
+
318
+
319
+ # --- 70: jedes Werkzeug des Kerns nennt nur Namen, die es gibt (D-229) -------------
320
+ #
321
+ # Drei Formen desselben Gegenstands: der gemessene NameError (70a), die Quelle, die
322
+ # der Interpreter gar nicht erst uebersetzt (70b), und die Ankersonde - ein
323
+ # Messapparat ohne ein einziges Werkzeug haette nichts zu pruefen und bestuende leise
324
+ # (70c). 70a setzt den Defekt WOERTLICH so, wie er am 2026-09-21 gefunden wurde: den
325
+ # Ablageort NEBEN dem Skript, den D-222 mit dem Umzug entfernt hat.
326
+ #
327
+ # ZWEI GEGENPROBEN, UND SIE BELEGEN DEN ZUSCHNITT. Die Pruefung haengt an der
328
+ # BINDUNG, nicht an der Schreibweise: Ein Werkzeug, das freie Variablen einer
329
+ # umschliessenden Funktion liest, eine Komprehension fuehrt, `__file__` nennt und
330
+ # einen Namen erst im `except`-Zweig bindet, ist gebunden und wird nicht gemeldet
331
+ # (70a). Und ein Name, der GEBUNDEN und falsch belegt ist, laeuft durch - das ist die
332
+ # angesagte Grenze, nicht ein Loch (70b).
333
+ M70 = "NameError, der auf seinen Lauf wartet"
334
+ M70_SYNTAX = "laedt nicht"
335
+ M70_ANKER = "kein einziges Werkzeug geprueft"
336
+ P70_STAND = ".koolie/core/tests/erhebungen/stand-b4.py".replace("/", os.sep)
337
+ P70_APPARAT = ".koolie/core/tests/erhebungen".replace("/", os.sep)
338
+
339
+
340
+ def _70_verschwundener_name(root: str) -> None:
341
+ """Der gemessene Fall: der Ablageort neben dem Skript, nach dem Umzug (D-222)."""
342
+ ersetze(P(root, P70_STAND),
343
+ ("PROMPTS = ablage.prompts(anlegen=False)",
344
+ 'PROMPTS = os.path.join(os.path.dirname(S), "prompts")'))
345
+
346
+
347
+ def _70_uebersetzt_nicht(root: str) -> None:
348
+ """Die zweite Form: ein Werkzeug, das der Interpreter nicht uebersetzt."""
349
+ schreib(P(root, P70_APPARAT, "sondenwerkzeug.py"),
350
+ "# -*- coding: utf-8 -*-" + chr(10) + "def offen(:" + chr(10))
351
+
352
+
353
+ def _70_apparat_ohne_werkzeug(root: str) -> None:
354
+ """Ankersonde: die Ablage steht, kein Werkzeug mehr darin."""
355
+ ordner = P(root, P70_APPARAT)
356
+ if not os.path.isdir(ordner):
357
+ raise Praeparationsfehler(
358
+ "die Erhebungsablage fehlt - die Sonde zu 70 haette keinen Anker")
359
+ geloescht = 0
360
+ for name in os.listdir(ordner):
361
+ ziel = os.path.join(ordner, name)
362
+ if os.path.isfile(ziel) and name.endswith(".py"):
363
+ os.remove(ziel)
364
+ geloescht += 1
365
+ if geloescht == 0:
366
+ raise Praeparationsfehler(
367
+ "in der Erhebungsablage lag kein einziges .py - der Anker traegt nicht")
368
+
369
+
370
+ def _70_gebundene_namen(root: str) -> None:
371
+ """Gegenprobe: jede Bindungsform, die es gibt - und keine davon ist ein Befund."""
372
+ schreib(P(root, P70_APPARAT, "sondenwerkzeug.py"), chr(10).join([
373
+ "# -*- coding: utf-8 -*-",
374
+ "import os",
375
+ "",
376
+ "WURZEL = os.path.dirname(os.path.abspath(__file__))",
377
+ "",
378
+ "",
379
+ "def aussen(grenze):",
380
+ " rest = [x for x in os.listdir(WURZEL) if x > grenze]",
381
+ "",
382
+ " def innen():",
383
+ " return grenze, rest",
384
+ "",
385
+ " try:",
386
+ " zahl = int(grenze)",
387
+ " except ValueError as fehler:",
388
+ " zahl = len(str(fehler))",
389
+ " with open(os.path.join(WURZEL, grenze)) as quelle:",
390
+ " inhalt = quelle.read()",
391
+ " return innen(), zahl, inhalt",
392
+ "",
393
+ "",
394
+ "class Traeger(object):",
395
+ " feld = WURZEL",
396
+ "",
397
+ " def hol(self):",
398
+ " return self.feld",
399
+ "",
400
+ ]))
401
+
402
+
403
+ def _70_gebunden_und_falsch(root: str) -> None:
404
+ """Gegenprobe: der Name IST gebunden - der Wert taugt nicht. Die angesagte Grenze."""
405
+ schreib(P(root, P70_APPARAT, "sondenwerkzeug.py"), chr(10).join([
406
+ "# -*- coding: utf-8 -*-",
407
+ "import os",
408
+ "",
409
+ "S = None",
410
+ "PROMPTS = os.path.join(os.path.dirname(S), 'prompts')",
411
+ "",
412
+ ]))
413
+
414
+
415
+ sonde("70a", "Der gemessene Fall: der Ablageort neben dem Skript ist mit D-222 verschwunden, seine zwei Lesestellen nicht - stand-b4.py war seit 0.79.0 tot",
416
+ _70_verschwundener_name, M70)
417
+
418
+ sonde("70b", "Dieselbe Bauform eine Stufe frueher: ein Werkzeug des Kerns, das der Interpreter nicht einmal uebersetzt, wird gemeldet",
419
+ _70_uebersetzt_nicht, M70_SYNTAX)
420
+
421
+ sonde("70c", "Ohne ein einziges Werkzeug im Messapparat meldet Pruefung 70 den verlorenen Gegenstand, statt leise zu bestehen",
422
+ _70_apparat_ohne_werkzeug, M70_ANKER)
423
+
424
+ gegenprobe("70a", "Freie Variable, Komprehension, except-Name, with-Ziel, Klassenfeld und __file__ sind gebunden und werden NICHT gemeldet - die Pruefung haengt an der Bindung",
425
+ _70_gebundene_namen, M70)
426
+
427
+ gegenprobe("70b", "Ein gebundener Name mit untauglichem Wert laeuft durch - das ist die angesagte Grenze der Pruefung und kein Loch",
428
+ _70_gebunden_und_falsch, M70)
429
+
430
+
431
+ # --- 71: kein Traeger des Kerns nennt einen Arbeitsplatz (D-231) -------------------
432
+ #
433
+ # Drei Formen desselben Gegenstands: der gemessene Fall in einem WERKZEUG (71a), die
434
+ # gleiche Bauform in einer CHECKLISTE - also ausserhalb der .py-Welt, weil die
435
+ # Pruefung nicht an der Dateiart haengt (71b) -, und die Ankersonde: ein Muster, das
436
+ # seinen Gegenstand nicht mehr trifft, bestuende leise (71c).
437
+ #
438
+ # DREI GEGENPROBEN, UND SIE BELEGEN DEN ZUSCHNITT. Ein Platzhalter nennt niemanden
439
+ # (71a). Die Marke `SYNTHETISCH` in derselben Zeile laeuft durch - dieselbe Bauform
440
+ # wie das Begruendungsfeld von Pruefung 68 (71b). Und eine AUFZEICHNUNG DES BESTANDS
441
+ # bleibt unbeanstandet: Ein Protokoll haelt fest, WO gemessen wurde, und wer es
442
+ # umschreibt, hat keines mehr (71c, D-141). Seit 1.20.3 ist das eine geschlossene Liste
443
+ # und keine Gattung mehr (D-508, `K-85`): Eine NEUE Aufzeichnung mit Kontonamen wird
444
+ # gemeldet (71d).
445
+ M71 = "nennt ein Benutzerprofil"
446
+ M71_ANKER = "das eigene Muster trifft"
447
+ P71_WERKZEUG = ".koolie/core/tests/erhebungen/stand-b4.py".replace("/", os.sep)
448
+ P71_CHECKLISTE = ".koolie/core/checklists/11-framework-release.md".replace("/", os.sep)
449
+ P71_PROTOKOLL = (".koolie/core/tests/protocols/"
450
+ "2026-09-21-wiederaufnahme-nachlauf-b4.md").replace("/", os.sep)
451
+ P71_BESTAND = (".koolie/core/tests/protocols/"
452
+ "2026-09-19-testblaetter-buendel-1.md").replace("/", os.sep)
453
+ P71_VALIDATOR = ".koolie/core/tests/scripts/pruefungen/werkzeuge.py".replace("/", os.sep)
454
+ P71_PFAD = "C:" + chr(92) + "Users" + chr(92) + "sondenkonto" + chr(92) + "devpacks"
455
+
456
+
457
+ def _71_werkzeug(root: str) -> None:
458
+ """Der gemessene Fall: ein Werkzeug des Kerns fuehrt einen Arbeitsplatzpfad."""
459
+ ersetze(P(root, P71_WERKZEUG),
460
+ ('BAEUME = r"C:' + chr(92) + 'lw-b4"',
461
+ 'BAEUME = r"' + P71_PFAD + chr(92) + 'lw-b4"'))
462
+
463
+
464
+ def _71_checkliste(root: str) -> None:
465
+ """Die zweite Form, ausserhalb der .py-Welt: derselbe Pfad in einer Checkliste."""
466
+ zeile_nach(P(root, P71_CHECKLISTE), "## Zweck",
467
+ "" + chr(10) + "Arbeitsstand liegt unter `" + P71_PFAD + "`.")
468
+
469
+
470
+ def _71_muster_verlieren(root: str) -> None:
471
+ """Ankersonde: das Muster trifft seinen eigenen Gegenstand nicht mehr."""
472
+ ersetze(P(root, P71_VALIDATOR),
473
+ ('r"(?:[A-Za-z]:[' + chr(92) + chr(92) + '/]{1,2}Users|/home|/Users)'
474
+ '[' + chr(92) + chr(92) + '/]{1,2}([A-Za-z0-9._-]+)"',
475
+ 'r"trifft-nichts-mehr([A-Za-z0-9._-]+)"'))
476
+
477
+
478
+ def _71_platzhalter(root: str) -> None:
479
+ """Gegenprobe: ein Platzhalter nennt niemanden."""
480
+ zeile_nach(P(root, P71_CHECKLISTE), "## Zweck",
481
+ "" + chr(10) + "Arbeitsstand liegt unter `C:" + chr(92)
482
+ + "Users" + chr(92) + "%USERNAME%" + chr(92) + "devpacks`.")
483
+
484
+
485
+ def _71_marke(root: str) -> None:
486
+ """Gegenprobe: die Marke in derselben Zeile laeuft durch (wie bei Pruefung 68)."""
487
+ zeile_nach(P(root, P71_CHECKLISTE), "## Zweck",
488
+ "" + chr(10) + "Beispielpfad `" + P71_PFAD + "` - SYNTHETISCH.")
489
+
490
+
491
+ def _71_aufzeichnung(root: str) -> None:
492
+ """Gegenprobe: eine Aufzeichnung des Bestands bleibt unbeanstandet (D-141, D-508)."""
493
+ zeile_nach(P(root, P71_BESTAND), "## 1. Der Meßaufbau",
494
+ "" + chr(10) + "Gemessen wurde ausserhalb von `" + P71_PFAD + "`.")
495
+
496
+
497
+ def _71_neue_aufzeichnung(root: str) -> None:
498
+ """Sonde: eine Aufzeichnung ausserhalb des Bestands wird geprueft (D-508, K-85)."""
499
+ zeile_nach(P(root, P71_PROTOKOLL), "## 1. Die Lage vor dem Durchgang",
500
+ "" + chr(10) + "Gemessen wurde ausserhalb von `" + P71_PFAD + "`.")
501
+
502
+
503
+ sonde("71a", "Ein Werkzeug des Kerns fuehrt einen Arbeitsplatzpfad im Quelltext - der gemessene Fall, den D-222 mit dem Apparat hereingetragen hat",
504
+ _71_werkzeug, M71)
505
+
506
+ sonde("71b", "Dieselbe Bauform ausserhalb der Skripte: derselbe Pfad in einer Checkliste wird ebenso gemeldet",
507
+ _71_checkliste, M71)
508
+
509
+ sonde("71c", "Trifft das eigene Muster seinen Gegenstand nicht mehr, meldet Pruefung 71 das, statt leise zu bestehen",
510
+ _71_muster_verlieren, M71_ANKER)
511
+
512
+ sonde("71d", "Eine neue Aufzeichnung mit Kontonamen wird gemeldet - ausgenommen ist seit 1.20.3 nur der Bestand der zehn, nicht die Gattung (D-508)",
513
+ _71_neue_aufzeichnung, M71)
514
+
515
+ gegenprobe("71a", "Ein Platzhalter als Kontosegment nennt niemanden und wird NICHT gemeldet - die Pruefung haengt am Namen, nicht an der Pfadform",
516
+ _71_platzhalter, M71)
517
+
518
+ gegenprobe("71b", "Die Marke SYNTHETISCH in derselben Zeile laeuft durch - dieselbe Bauform wie das Begruendungsfeld von Pruefung 68",
519
+ _71_marke, M71)
520
+
521
+ gegenprobe("71c", "Eine Aufzeichnung des Bestands bleibt unbeanstandet - ein Protokoll haelt fest, wo gemessen wurde, und wer es umschreibt, hat keines mehr (D-141)",
522
+ _71_aufzeichnung, M71)
523
+
524
+
525
+ # --- Pruefung 72: Ein aktiviertes Pack steht auch im Berechtigungskorb ------------
526
+ #
527
+ # WARUM DIESE EINHEIT EINE INSTALLATION BAUT statt den Repositoriumsbaum zu praeparieren:
528
+ # Ihr Gegenstand IST die Installation. Im Quellrepositorium gibt es keine Skillablage
529
+ # eines Client Packs, und die Pruefung schwiege dort zu Recht - eine Sonde auf einer
530
+ # Kopie des Repositoriums haette nichts zu treffen.
531
+ #
532
+ # DREI SONDEN, UND SIE BELEGEN BEIDE RICHTUNGEN UND DIE ANKERFRAGE. Der gemessene Fall
533
+ # ist 72a: ein Pack WORTGETREU nach `framework/role-packs/README.md` aktiviert - Skill
534
+ # kopiert -, und der Korb weiss nichts davon. 72b ist die Gegenrichtung: ein Eintrag
535
+ # ohne Skill ist eine Zusage ohne Gegenstand (D-81). 72c fragt das Manifest: Ein
536
+ # FEHLENDES Feld `permission_tools.skill` ist ein Befund - der Unterschied zwischen
537
+ # "nicht abgebildet" und "gibt es nicht" gehoert deklariert (D-155).
538
+ #
539
+ # ZWEI GEGENPROBEN, UND DIE ZWEITE IST DIE WICHTIGERE. 72a belegt, dass eine
540
+ # ausgelieferte Installation durchlaeuft - ohne sie meldete die Sonde nur, dass
541
+ # irgendetwas meldet. 72b belegt den ZUSCHNITT: Dieselbe Aktivierung in einer
542
+ # `devin-desktop`-Installation bleibt unbeanstandet, weil das Manifest dort
543
+ # `permission_tools.skill` als LEER deklariert (erhoben am 2026-09-14, D-89: Der
544
+ # Skillaufruf ist dort ein Werkzeugaufruf, aber es ist keine Schreibweise bekannt, mit
545
+ # der eine Regel ihn beim Namen nennt). Ohne sie waere das Schweigen der Pruefung bei
546
+ # diesem Pack nicht von einer stillen Null zu unterscheiden.
547
+ M72 = "wird aber von keinem Eintrag der Berechtigungsdatei genannt"
548
+ M72_RUECK = "nennt keinen Skill in"
549
+ M72_FELD = "Feld permission_tools.skill fehlt"
550
+ P72_PACKSKILL = (".koolie/core/framework/role-packs/requirements-engineering/"
551
+ "skills/role-re-ticket").replace("/", os.sep)
552
+
553
+
554
+ def _72_pack_aktivieren(root: str, pack_skills: str) -> str:
555
+ """Aktiviert das Role Pack wortgetreu nach README Punkt 4: Skill kopieren."""
556
+ quelle = os.path.join(root, P72_PACKSKILL)
557
+ name = os.path.basename(quelle)
558
+ shutil.copytree(quelle, os.path.join(root, *pack_skills.split("/"), name))
559
+ return name
560
+
561
+
562
+ def sonden_pack_im_korb() -> None:
563
+ """Wirkungsnachweis fuer Pruefung 72 (CR-2026-114, D-238)."""
564
+ for pack, skills, meldet in (("claude-code", ".claude/skills", True),
565
+ ("devin-desktop", ".devin/skills", False)):
566
+ root = installation(pack)
567
+ try:
568
+ if pack == "claude-code":
569
+ # --- Gegenprobe 72a: die ausgelieferte Installation ------------
570
+ melde("GEGENPROBE", "72a", M72 not in validator_ausgabe(root),
571
+ "Die ausgelieferte Installation deckt sich - zwoelf Skills, "
572
+ "zwoelf Eintraege, keine Meldung")
573
+
574
+ name = _72_pack_aktivieren(root, skills)
575
+ ausgabe = validator_ausgabe(root)
576
+ getroffen = M72 in ausgabe and name in ausgabe
577
+ if meldet:
578
+ melde("SONDE", "72a", getroffen,
579
+ "Ein aktiviertes Role Pack ohne Korbeintrag wird gemeldet - der "
580
+ "gemessene Fall aus dem Vorbedingungsdurchgang von Buendel 5")
581
+ if not getroffen:
582
+ notiz(" Ausgabe:", " | ".join(ausgabe.splitlines()[:6]))
583
+ else:
584
+ melde("GEGENPROBE", "72b", not getroffen,
585
+ "Dieselbe Aktivierung bei einem Pack mit leer DEKLARIERTEM "
586
+ "permission_tools.skill bleibt unbeanstandet (D-89)")
587
+
588
+ if pack != "claude-code":
589
+ continue
590
+
591
+ # --- Sonde 72b: die Gegenrichtung -------------------------------
592
+ # Der Eintrag bleibt, sein Skill geht - eine Freigabe ohne Gegenstand.
593
+ shutil.rmtree(os.path.join(root, *skills.split("/"), name))
594
+ shutil.rmtree(os.path.join(root, *skills.split("/"), "fw-plan"))
595
+ ausgabe = validator_ausgabe(root)
596
+ melde("SONDE", "72b", M72_RUECK in ausgabe and "fw-plan" in ausgabe,
597
+ "Ein Korbeintrag ohne Skill in der Ablage wird gemeldet - eine "
598
+ "Freigabe fuer einen Skill, den es nicht gibt (D-81)")
599
+
600
+ # --- Sonde 72c: das Manifest schweigt statt zu deklarieren -------
601
+ _manifest_aendern(root, "claude-code",
602
+ lambda m: m["permission_tools"].pop("skill", None))
603
+ melde("SONDE", "72c", M72_FELD in validator_ausgabe(root),
604
+ "Ein FEHLENDES Feld permission_tools.skill wird gemeldet - eine "
605
+ "leere Liste ist deklariert, ein fehlendes Feld ist geraten (D-155)")
606
+ finally:
607
+ aufraeumen(os.path.dirname(root))
608
+
609
+
610
+ buendel(sonden_pack_im_korb,
611
+ "Ein aktiviertes Pack steht auch im Berechtigungskorb - in beide Richtungen, "
612
+ "und nur bei einem Client, dessen Manifest eine Schreibweise deklariert")
613
+
614
+
615
+
616
+
617
+ # --- Pruefung 73: Jede [DOK]-Matrixzeile nennt ihre Quelle -------------------------
618
+ #
619
+ # VIER SONDEN, UND SIE BELEGEN DIE VIER WEGE, AUF DENEN EINE ZUORDNUNG VERSCHWINDET.
620
+ # 73a ist der gemessene Ausgangsfall: eine Zeile, deren Belegkopf die Kennung nicht
621
+ # nennt - am 2026-09-18 traf das auf 29 von 43 Zeilen zu. 73b ist der Fall, den keine
622
+ # Zaehlung ohne Verweisaufloesung sieht: Beim Pack devin-desktop haengen B4, B5, B6 und
623
+ # B8 an B3, eine davon ueber zwei Glieder - nimmt man B3 die Kennung, verlieren FUENF
624
+ # Zeilen ihren Beleg, und die Meldung nennt die Kette. 73c und 73d sind die beiden
625
+ # Richtungen der deklarierten Luecke: eine neue, die nicht in P73_OFFEN steht, und eine
626
+ # deklarierte, die aus der Zeile verschwunden ist. Die zweite ist der Fall "eine
627
+ # Ausnahme ohne Gegenstand" (0.57.1) - sie sieht wie Sorgfalt aus und ist tot.
628
+ #
629
+ # DREI GEGENPROBEN, UND DIE ZWEITE IST DIE WICHTIGERE. 73a belegt, dass der
630
+ # ausgelieferte Bestand durchlaeuft - ohne sie meldete die Sonde nur, dass irgendetwas
631
+ # meldet. 73b belegt DIE KOPFREGEL: Eine Nennung der Marke HINTER dem Belegkopf bleibt
632
+ # unbeanstandet. Ohne sie waere die Pruefung nicht von einer Textsuche zu
633
+ # unterscheiden, und Zeile R5 des Packs claude-code - "ein Dokumentenabgleich belegt
634
+ # [DOK], nicht [TECHNISCH]" - fiele als Befund an. 73c belegt den Zuschnitt zur
635
+ # Vorlage: clients/_template/ fuehrt <TBD> in jeder Belegzelle und wird nicht gemessen.
636
+ M73 = "nennt im Belegkopf keine Quellenkennung"
637
+ M73_KETTE = "ueber den Verweis"
638
+ M73_UNDEKLARIERT = "steht aber nicht in P73_OFFEN"
639
+ M73_TOT = "als ausgesprochene Luecke, die Zeile sagt es aber nicht"
640
+ P73_CC = ".koolie/core/clients/claude-code/CLIENT_PACK.md".replace("/", os.sep)
641
+ P73_DD = ".koolie/core/clients/devin-desktop/CLIENT_PACK.md".replace("/", os.sep)
642
+ P73_VORLAGE = ".koolie/core/clients/_template/CLIENT_PACK.md".replace("/", os.sep)
643
+
644
+
645
+ def _73_kennung_nehmen(root: str) -> None:
646
+ """Sonde: Zeile B1 des Packs claude-code verliert ihre Kennung."""
647
+ ersetze(P(root, P73_CC),
648
+ ("| `[DOK]` **`QC-5`** (Zuordnung `K-62`) |", "| `[DOK]` |"))
649
+
650
+
651
+ def _73_verweisziel_nehmen(root: str) -> None:
652
+ """Sonde: B3 verliert die Kennung - vier weitere Zeilen verweisen darauf."""
653
+ # Der Anker ist so kurz wie moeglich: Die Zeile B3 ist mit 0.86.0 neu geschrieben
654
+ # worden (Muster-Semantik, D-277), und der laengere Suchtext von 0.85.0 traf nicht
655
+ # mehr. Eine Sonde, deren Suchtext an der Prosa haengt, faellt bei jedem Messwert.
656
+ ersetze(P(root, P73_DD),
657
+ ("Mechanismus `[DOK]` **`QD-11`** (Zuordnung `K-62`)",
658
+ "Mechanismus `[DOK]` (ohne Quelle)"))
659
+
660
+
661
+ def _73_luecke_erfinden(root: str) -> None:
662
+ """Sonde: eine zweite ausgesprochene Luecke, die niemand deklariert hat."""
663
+ ersetze(P(root, P73_DD),
664
+ ("| `[DOK]` **`QD-12`** (Zuordnung `K-62`) |",
665
+ "| `[DOK]` - QUELLE NICHT ZUGEORDNET (synthetisch) |"))
666
+
667
+
668
+ def _73_luecke_schliessen(root: str) -> None:
669
+ """Sonde: die deklarierte Luecke verschwindet aus der Zeile, P73_OFFEN bleibt."""
670
+ ersetze(P(root, P73_CC),
671
+ ("🔴 **QUELLE NICHT ZUGEORDNET** (`K-62`, 2026-09-22)",
672
+ "**`QC-2`** (synthetisch)"))
673
+
674
+
675
+ def _73_nennung_hinter_dem_kopf(root: str) -> None:
676
+ """Gegenprobe: die Marke HINTER dem Belegkopf ist eine Nennung, kein Beleg."""
677
+ ersetze(P(root, P73_CC),
678
+ ("| `[DOK]` **`QC-5`** (Zuordnung `K-62`) |",
679
+ "| `[DOK]` **`QC-5`** (Zuordnung `K-62`). Zur Einordnung: Ein "
680
+ "Dokumentenabgleich belegt `[DOK]` und nie `[TECHNISCH]` (D-12) |"))
681
+
682
+
683
+ def _73_vorlage_leeren(root: str) -> None:
684
+ """Gegenprobe: die Vorlage fuehrt <TBD> und wird nicht gemessen."""
685
+ ersetze(P(root, P73_VORLAGE),
686
+ ("| R1 | Die Wurzel-Anweisungsdatei wird zu Beginn jeder Sitzung "
687
+ "ungefragt geladen | `.koolie/core/framework/runtime/root-instruction.md` "
688
+ "| `<TBD>` | `<TBD>` | `<TBD>` |",
689
+ "| R1 | Die Wurzel-Anweisungsdatei wird zu Beginn jeder Sitzung "
690
+ "ungefragt geladen | `.koolie/core/framework/runtime/root-instruction.md` "
691
+ "| `<TBD>` | `<TBD>` | `[DOK]` |"))
692
+
693
+
694
+ sonde("73a", "Eine [DOK]-Zeile ohne Quellenkennung im Belegkopf wird gemeldet - der "
695
+ "gemessene Ausgangsfall: 29 von 43 Zeilen am 2026-09-18",
696
+ _73_kennung_nehmen, M73)
697
+
698
+ sonde("73b", "Nimmt das Ziel eines Verweisbelegs seine Kennung, verlieren die "
699
+ "verweisenden Zeilen sie mit - und die Meldung nennt die Kette",
700
+ _73_verweisziel_nehmen, M73_KETTE)
701
+
702
+ sonde("73c", "Eine ausgesprochene Luecke, die nicht in P73_OFFEN steht, wird "
703
+ "gemeldet - sonst waere die Marke eine Hintertuer",
704
+ _73_luecke_erfinden, M73_UNDEKLARIERT)
705
+
706
+ sonde("73d", "Eine deklarierte Luecke, die aus der Zeile verschwunden ist, wird "
707
+ "gemeldet - eine Ausnahme ohne Gegenstand ist tot (0.57.1)",
708
+ _73_luecke_schliessen, M73_TOT)
709
+
710
+ gegenprobe("73a", "Der ausgelieferte Bestand laeuft durch - 46 Matrixzeilen, eine "
711
+ "deklarierte Luecke, keine Meldung",
712
+ None, M73)
713
+
714
+ gegenprobe("73b", "Eine Nennung der Marke HINTER dem Belegkopf bleibt unbeanstandet - "
715
+ "die Kopfregel, ohne die jede Erlaeuterung ein Befund waere",
716
+ _73_nennung_hinter_dem_kopf, M73)
717
+
718
+ gegenprobe("73c", "Die Vorlage clients/_template/ fuehrt <TBD> und wird nicht "
719
+ "gemessen - ein Pack ohne Client hat keine Quellenliste",
720
+ _73_vorlage_leeren, M73)
721
+
722
+
723
+ # --- Pruefung 74: Eine Matrixzeile steht in ihrer Tabelle --------------------------
724
+ #
725
+ # ZWEI SONDEN UND ZWEI GEGENPROBEN. 74a ist der gemessene Fall, wortgetreu: die
726
+ # Leerzeile zwischen M5 und M6 des Packs devin-desktop, die dort seit 0.26.0 stand und
727
+ # zwei Matrixzeilen zu Fliesstext gemacht hat - im Pack wie im Hauptdokument. 74b ist
728
+ # dieselbe Bauform mit Fremdtext statt Leerzeile: Ein Absatz mitten in der Tabelle
729
+ # bricht sie ebenso, und er sieht harmloser aus.
730
+ #
731
+ # DIE ZWEITE GEGENPROBE IST DIE WICHTIGERE, und sie schuetzt den ZUSCHNITT. Abschnitt 5
732
+ # des Packs claude-code fuehrt eine Tabelle "Bekannte Abweichungen im Verhalten", und
733
+ # ihre erste Zeile beginnt mit "| B6 |" - dieselbe Gestalt wie eine Matrixzeile, in
734
+ # einer anderen Tabelle und in einem anderen Abschnitt. Wer nur nach dem Muster sucht,
735
+ # meldet sie mit. Die Pruefung liest deshalb nur unterhalb von "## 2.", und diese
736
+ # Gegenprobe belegt es an einer Zeile, die dort WIRKLICH steht.
737
+ M74 = "sieht aus wie eine Matrixzeile und steht in keiner Tabelle"
738
+ P74_DD = P73_DD
739
+ P74_CC = P73_CC
740
+
741
+
742
+ def _74_leerzeile_setzen(root: str) -> None:
743
+ """Sonde: der gemessene Fall - eine Leerzeile vor M6, wie sie bis 0.84.0 stand."""
744
+ zeile_nach(P(root, P74_DD), "| M5 | Eigener Nur-Lese-Modus", "")
745
+
746
+
747
+ def _74_fremdtext_setzen(root: str) -> None:
748
+ """Sonde: ein Absatz mitten in der Tabelle bricht sie ebenso."""
749
+ zeile_nach(P(root, P74_DD), "| M5 | Eigener Nur-Lese-Modus",
750
+ "" + chr(10) + "Anmerkung zur Modusreihe - SYNTHETISCH." + chr(10))
751
+
752
+
753
+ def _74_abweichungstabelle_brechen(root: str) -> None:
754
+ """Gegenprobe: dieselbe Gestalt in Abschnitt 5 wird NICHT gemessen."""
755
+ zeile_nach(P(root, P74_CC), "## 5. Bekannte Abweichungen im Verhalten",
756
+ "" + chr(10) + "| B6 | synthetische Zeile ohne Tabelle | - |")
757
+
758
+
759
+ sonde("74a", "Eine Leerzeile vor einer Matrixzeile wird gemeldet - der gemessene "
760
+ "Fall, der seit 0.26.0 zwei Zeilen zu Fliesstext gemacht hat",
761
+ _74_leerzeile_setzen, M74)
762
+
763
+ sonde("74b", "Ein Absatz mitten in der Tabelle bricht sie ebenso und wird gemeldet",
764
+ _74_fremdtext_setzen, M74)
765
+
766
+ gegenprobe("74a", "Der ausgelieferte Bestand laeuft durch - beide Packs, jede "
767
+ "Matrixzeile in ihrer Tabelle",
768
+ None, M74)
769
+
770
+ gegenprobe("74b", "Dieselbe Gestalt in Abschnitt 5 bleibt unbeanstandet - die "
771
+ "Pruefung liest unterhalb von '## 2.', nicht nach dem Muster",
772
+ _74_abweichungstabelle_brechen, M74)
773
+
774
+
775
+ # --- Pruefung 75: Kein Restbestand des alten Namens (CR-2026-122, D-271) ------------
776
+ #
777
+ # EIN BUENDEL, WEIL DIE PRUEFUNG EIN REPOSITORIUM BRAUCHT. Sie liest `git ls-files`,
778
+ # und kopie() schliesst `.git` ausdruecklich aus - der Sondenbaum ist keins. Ohne
779
+ # `git init` haette Pruefung 75 in JEDER Sonde ihren dritten Ausgang genommen ("nicht
780
+ # messbar") und dabei ausgesehen wie eine, die nichts gefunden hat. Das ist derselbe
781
+ # Griff wie bei Gegenstand 2 der Pruefung 45, aus demselben Grund.
782
+ #
783
+ # VIER EINHEITEN, UND SIE MESSEN VIER VERSCHIEDENE DINGE:
784
+ # 75a (Gegenprobe) - der ausgelieferte Bestand laeuft durch. Sie belegt zugleich,
785
+ # dass die Pruefung ueberhaupt GELAUFEN ist: Ohne die Bedingung
786
+ # auf die Unmessbarkeitsmeldung bestuende sie auch ohne git.
787
+ # 75a (Sonde) - der alte Name in einem verfolgten Traeger ausserhalb der
788
+ # Ausnahmemenge wird gemeldet.
789
+ # 75b (Gegenprobe) - derselbe Text in einem datierten Protokoll bleibt unbeanstandet.
790
+ # Das ist der ZUSCHNITT: Die Chronik beschreibt einen vergangenen
791
+ # Zustand (D-273), und ein Pfad, den es nicht mehr gibt, ist dort
792
+ # richtig.
793
+ # 75b (Sonde) - die zweite Richtung: Eine Ausnahme, aus der die Fundstelle
794
+ # verschwunden ist, wird gemeldet. Ohne sie waere P75_AUSNAHMEN ein
795
+ # Sammelbecken, das nur waechst - eine Ausnahme, die nichts mehr
796
+ # ausnimmt, sieht wie Sorgfalt aus (0.57.1).
797
+ # 75c (Sonde) - der verlorene Anker: Trifft das eigene Muster den alten Namen
798
+ # nicht mehr, meldet die Pruefung das, statt leise zu bestehen.
799
+ #
800
+ # DIE SONDEN BRINGEN IHREN GEGENSTAND SELBST MIT. 75a und 75b schreiben den alten Namen
801
+ # in den Baum, statt einen vorhandenen vorauszusetzen - die Abhilfe aus 0.86.0
802
+ # Abschnitt 2a. Genau daran sind dort sieben Sonden gefallen, und hier ist der Fall
803
+ # schaerfer: Der Gegenstand dieser Pruefung ist der Name, den dieses Release ENTFERNT.
804
+ M75_REST = "nennt den alten Namen noch"
805
+ M75_LEER = "nimmt nichts mehr aus und gehört entfernt"
806
+ M75_ANKER = "das eigene Muster findet den alten Namen nicht mehr"
807
+ M75_UNMESSBAR = "ist an diesem Ort nicht prüfbar"
808
+
809
+ P75_OPFER = ".koolie/core/OWNERS.md"
810
+ P75_CHRONIKOPFER = ".koolie/core/CHANGELOG.md"
811
+ P75_AUSNAHMEOPFER = ".koolie/core/clientmap.py"
812
+ P75_VALIDATOR = ".koolie/core/tests/scripts/pruefungen/dokumente.py".replace("/", os.sep)
813
+
814
+ _ALT = "leitwerk" + "-core" # nicht als ein Literal: Pruefung 75 liest sich selbst
815
+
816
+
817
+ def sonden_altname() -> None:
818
+ """Wirkungsnachweis zu Pruefung 75 an einem echten Repositorium."""
819
+ root = kopie()
820
+ try:
821
+ if unterprozess(["git", "init", "-q", root]).returncode != 0:
822
+ melde("BUENDEL", "-", False, "sonden_altname [git nicht erreichbar]")
823
+ notiz(" Ohne git liest Pruefung 75 keinen Bestand; sie nimmt dann "
824
+ "ihren dritten Ausgang und ist nicht messbar.")
825
+ return
826
+ unterprozess(["git", "-C", root, "add", "-A"])
827
+
828
+ # --- Gegenprobe 75a: der ausgelieferte Bestand laeuft durch -----------------
829
+ aus = validator_ausgabe(root)
830
+ ok = (M75_REST not in aus and M75_LEER not in aus
831
+ and M75_UNMESSBAR not in aus and M75_ANKER not in aus)
832
+ melde("GEGENPROBE", "75a", ok,
833
+ "Der ausgelieferte Bestand laeuft durch - P75_AUSNAHMEN deckt sich in "
834
+ "BEIDE Richtungen mit dem Bestand, und die Pruefung ist dabei "
835
+ "nachweislich gelaufen")
836
+ if not ok:
837
+ notiz(" Ausgabe:", " | ".join(
838
+ z for z in aus.splitlines() if "75" in z or "Namen" in z)[:400])
839
+
840
+ # --- Sonde 75a: der alte Name in einem verfolgten Traeger -------------------
841
+ pfad = P(root, *P75_OPFER.split("/"))
842
+ schreib(pfad, lies(pfad) + "\r\n<!-- SYNTHETISCH: " + _ALT + " -->\r\n")
843
+ unterprozess(["git", "-C", root, "add", "-A"])
844
+ aus = validator_ausgabe(root)
845
+ getroffen = M75_REST in aus and P75_OPFER in aus
846
+ melde("SONDE", "75a", getroffen,
847
+ "Der alte Name in einem verfolgten Traeger ausserhalb der Ausnahmemenge "
848
+ "wird gemeldet - mit Traeger und Zahl")
849
+ if not getroffen:
850
+ notiz(" Ausgabe:", " | ".join(
851
+ z for z in aus.splitlines() if "FEHLER" in z)[:400])
852
+ schreib(pfad, lies(pfad).replace(
853
+ "\r\n<!-- SYNTHETISCH: " + _ALT + " -->\r\n", ""))
854
+
855
+ # --- Gegenprobe 75b: derselbe Text in der Chronik ---------------------------
856
+ pfad = P(root, *P75_CHRONIKOPFER.split("/"))
857
+ schreib(pfad, lies(pfad) + "\r\n<!-- SYNTHETISCH: " + _ALT + " -->\r\n")
858
+ unterprozess(["git", "-C", root, "add", "-A"])
859
+ aus = validator_ausgabe(root)
860
+ ok = M75_REST not in aus
861
+ melde("GEGENPROBE", "75b", ok,
862
+ "Derselbe Text in einem Chroniktraeger bleibt unbeanstandet - die Chronik "
863
+ "beschreibt einen vergangenen Zustand und wandert nicht mit (D-273)")
864
+ if not ok:
865
+ notiz(" Ausgabe:", " | ".join(
866
+ z for z in aus.splitlines() if "FEHLER" in z)[:400])
867
+ schreib(pfad, lies(pfad).replace(
868
+ "\r\n<!-- SYNTHETISCH: " + _ALT + " -->\r\n", ""))
869
+
870
+ # --- Sonde 75b: die zweite Richtung - eine leer gewordene Ausnahme ----------
871
+ pfad = P(root, *P75_AUSNAHMEOPFER.split("/"))
872
+ text = lies(pfad)
873
+ treffer = text.lower().count("leitwerk")
874
+ if treffer != 1:
875
+ melde("SONDE", "75b", False,
876
+ "Die zweite Richtung von Pruefung 75 [Praeparation gebrochen]")
877
+ notiz(" %s nennt den alten Namen %dmal, erwartet genau einmal - "
878
+ "die Sonde hat ihren Gegenstand verloren."
879
+ % (P75_AUSNAHMEOPFER, treffer))
880
+ else:
881
+ schreib(pfad, re.sub("(?i)leitwerk", "koolie", text))
882
+ unterprozess(["git", "-C", root, "add", "-A"])
883
+ aus = validator_ausgabe(root)
884
+ getroffen = M75_LEER in aus and P75_AUSNAHMEOPFER in aus
885
+ melde("SONDE", "75b", getroffen,
886
+ "Eine Ausnahme, aus der die Fundstelle verschwunden ist, wird "
887
+ "gemeldet - ohne diese Richtung waechst P75_AUSNAHMEN nur")
888
+ if not getroffen:
889
+ notiz(" Ausgabe:", " | ".join(
890
+ z for z in aus.splitlines() if "FEHLER" in z)[:400])
891
+ schreib(pfad, text)
892
+ unterprozess(["git", "-C", root, "add", "-A"])
893
+
894
+ # --- Sonde 75c: der verlorene Anker -----------------------------------------
895
+ pfad = P(root, P75_VALIDATOR)
896
+ text = lies(pfad)
897
+ alt = 'P75_ALTNAME = re.compile(r"(?i)leitwerk")'
898
+ if text.count(alt) != 1:
899
+ melde("SONDE", "75c", False,
900
+ "Der verlorene Anker von Pruefung 75 [Praeparation gebrochen]")
901
+ notiz(" Suchtext %r steht %dmal im Validator." % (alt, text.count(alt)))
902
+ else:
903
+ schreib(pfad, text.replace(
904
+ alt, 'P75_ALTNAME = re.compile(r"(?i)diesenamengibtesnicht")'))
905
+ aus = validator_ausgabe(root)
906
+ getroffen = M75_ANKER in aus
907
+ melde("SONDE", "75c", getroffen,
908
+ "Trifft das eigene Muster den alten Namen nicht mehr, meldet "
909
+ "Pruefung 75 das - statt jede Umbenennung als vollstaendig zu melden")
910
+ if not getroffen:
911
+ notiz(" Ausgabe:", " | ".join(
912
+ z for z in aus.splitlines() if "FEHLER" in z)[:400])
913
+ finally:
914
+ aufraeumen(os.path.dirname(root))
915
+
916
+
917
+ buendel(sonden_altname,
918
+ "Pruefung 75 an einem echten Repositorium: der Bestand, ein Restbestand, die "
919
+ "Chronik als Zuschnitt, die leer gewordene Ausnahme und der verlorene Anker")
920
+
921
+
922
+ # --- Pruefung 76: Die Lage des Kerns steht an vier Stellen (CR-2026-122, D-299) -----
923
+ #
924
+ # DREI SONDEN UND EINE GEGENPROBE, und die dritte Sonde ist die wichtigste: Sie legt
925
+ # die BASENAME-BINDUNG WIEDER AN, die dieses Release entfernt hat. Ohne sie waere der
926
+ # erste Gegenstand - "alle vier tragen denselben Wert" - erfuellbar, indem alle vier
927
+ # denselben Fehler machen. Genau das war der Zustand bis 0.87.0, und der Validator hat
928
+ # ihn nicht gemeldet, weil er ihn teilte.
929
+ #
930
+ # WARUM NICHT AN validate-framework.py PRAEPARIERT WIRD: Dessen KERN traegt die Lage,
931
+ # mit der der Validator seinen eigenen Baum findet. Wer ihn verstellt, misst nicht
932
+ # Pruefung 76, sondern einen Validator ohne Gegenstand.
933
+ M76_UNGLEICH = "nicht überall gleich"
934
+ M76_BASENAME = "bindet <CORE_DIR> über os.path.basename()"
935
+ M76_ANKER = "führt keine Angabe der Kernlage mehr"
936
+
937
+ P76_HOOK = ".koolie/core/tests/scripts/hook-check-secrets.py".replace("/", os.sep)
938
+ P76_CLIENTMAP = ".koolie/core/clientmap.py".replace("/", os.sep)
939
+ P76_ABLAGE = ".koolie/core/tests/erhebungen/ablage.py".replace("/", os.sep)
940
+
941
+
942
+ def _76_lage_verstellen(root: str) -> None:
943
+ """Sonde: der Schutz-Hook traegt eine andere Lage als die uebrigen drei."""
944
+ pfad = P(root, P76_HOOK)
945
+ schreib(pfad, ersetzt(lies(pfad),
946
+ ('CORE_REL = ".koolie/core"',
947
+ 'CORE_REL = ".koolie/anderswo"'),
948
+ quelle=os.path.basename(pfad)))
949
+
950
+
951
+ def _76_basename_wieder(root: str) -> None:
952
+ """Sonde: die Bindung ueber basename, die bis 0.87.0 an vier Stellen stand."""
953
+ pfad = P(root, P76_CLIENTMAP)
954
+ schreib(pfad, ersetzt(lies(pfad),
955
+ ('def core_dir_name(man: dict) -> str:',
956
+ '_sonde = {} # SYNTHETISCH\r\n'
957
+ '_sonde["<CORE_DIR>"] = os.path.basename("x")\r\n\r\n\r\n'
958
+ 'def core_dir_name(man: dict) -> str:'),
959
+ quelle=os.path.basename(pfad)))
960
+
961
+
962
+ def _76_anker_entfernen(root: str) -> None:
963
+ """Sonde: eine der vier Stellen fuehrt keine Lageangabe mehr."""
964
+ pfad = P(root, P76_ABLAGE)
965
+ schreib(pfad, ersetzt(lies(pfad),
966
+ ('CORE_REL = ".koolie/core"', '_lage = ".koolie/core"'),
967
+ ("CORE_REL.count", "_lage.count"),
968
+ quelle=os.path.basename(pfad)))
969
+
970
+
971
+ sonde("76a", "Traegt eine der vier Stellen eine andere Lage, wird es gemeldet - eine "
972
+ "Installation laege sonst je nach aufrufendem Werkzeug anderswo",
973
+ _76_lage_verstellen, M76_UNGLEICH)
974
+
975
+ sonde("76b", "Die Bindung ueber os.path.basename wird gemeldet - sie stand bis 0.87.0 "
976
+ "an vier Stellen und haette den Umzug nicht ueberlebt",
977
+ _76_basename_wieder, M76_BASENAME)
978
+
979
+ sonde("76c", "Verliert eine der vier Stellen ihre Lageangabe, meldet Pruefung 76 den "
980
+ "verlorenen Anker, statt drei von vier stillschweigend zu vergleichen",
981
+ _76_anker_entfernen, M76_ANKER)
982
+
983
+ gegenprobe("76a", "Der ausgelieferte Bestand laeuft durch - vier Stellen, ein Wert, "
984
+ "keine basename-Bindung",
985
+ None, M76_UNGLEICH)
986
+
987
+
988
+ # --- Pruefung 77: Der Stand des Hauptdokuments (CR-2026-124, D-312) ----------------
989
+ #
990
+ # DREI SONDEN UND EINE GEGENPROBE. Die zweite ist die, die man weglassen wuerde: Sie
991
+ # setzt in dieselbe Zeile zwei VERSCHIEDENE Staende. Ohne sie waere der Vergleich mit
992
+ # VERSION erfuellbar, indem die Zeile zwei Werte nennt und einer davon passt - und
993
+ # welcher gemeint ist, stuende nirgends.
994
+ #
995
+ # WARUM AN 00-kopf.md UND NICHT AN VERSION PRAEPARIERT WIRD: VERSION traegt der
996
+ # Validator selbst gegen die Artefaktversionen (Pruefung 13), bis 1.4.0 auch gegen
997
+ # die Uebergabe (Pruefung 67). Wer dort verstellt, loest mehrere Meldungen aus und
998
+ # misst keine davon.
999
+ M77_STAND = "die Kopfzeile nennt den Stand"
1000
+ M77_UNEINIG = "und das Framework-Release"
1001
+ M77_ANKER = "keine Zeile der Form"
1002
+
1003
+ P77_KOPF = ".koolie/core/build/doc/00-kopf.md".replace("/", os.sep)
1004
+
1005
+
1006
+ def _77_stand_verstellen(root: str) -> None:
1007
+ """Sonde: das Dokument bleibt auf einem aelteren Stand stehen."""
1008
+ pfad = P(root, P77_KOPF)
1009
+ schreib(pfad, ersetzt(lies(pfad),
1010
+ ("| Dokumentversion | ", "| Dokumentversion | 0.9.0 (entspricht "
1011
+ "Framework-Release 0.9.0) |\r\n| Dokumentversion frueher | "),
1012
+ quelle=os.path.basename(pfad)))
1013
+
1014
+
1015
+ def _77_zeile_uneinig(root: str) -> None:
1016
+ """Sonde: die Zeile nennt zwei verschiedene Staende."""
1017
+ pfad = P(root, P77_KOPF)
1018
+ text = lies(pfad)
1019
+ anfang = text.index("| Dokumentversion | ")
1020
+ ende = text.index("|", text.index("(entspricht Framework-Release", anfang)) + 1
1021
+ schreib(pfad, text[:anfang]
1022
+ + "| Dokumentversion | 0.89.0 (entspricht Framework-Release 0.88.1) |"
1023
+ + text[ende:])
1024
+
1025
+
1026
+ def _77_anker_entfernen(root: str) -> None:
1027
+ """Sonde: die Kopfzeile des Dokuments ist weg."""
1028
+ pfad = P(root, P77_KOPF)
1029
+ schreib(pfad, ersetzt(lies(pfad),
1030
+ ("| Dokumentversion | ", "| Fassung | "),
1031
+ quelle=os.path.basename(pfad)))
1032
+
1033
+
1034
+ sonde("77a", "Bleibt das Hauptdokument auf einem aelteren Stand stehen, wird es "
1035
+ "gemeldet - genau so ist es zweiundvierzig Releases zurueckgefallen",
1036
+ _77_stand_verstellen, M77_STAND)
1037
+
1038
+ sonde("77b", "Nennt dieselbe Zeile zwei verschiedene Staende, wird es gemeldet - sonst "
1039
+ "genuegte es, wenn einer der beiden Werte passt",
1040
+ _77_zeile_uneinig, M77_UNEINIG)
1041
+
1042
+ sonde("77c", "Verliert der Kopf seine Versionszeile, meldet Pruefung 77 den verlorenen "
1043
+ "Anker, statt still zu bestehen",
1044
+ _77_anker_entfernen, M77_ANKER)
1045
+
1046
+ gegenprobe("77a", "Der ausgelieferte Bestand laeuft durch - Dokumentversion, genanntes "
1047
+ "Release und VERSION tragen denselben Wert",
1048
+ None, M77_STAND)
1049
+
1050
+
1051
+ # --- Pruefung 78: Die zaehlbaren Aussagen des Hauptdokuments (CR-2026-125, D-315) --
1052
+ #
1053
+ # EIN BUENDEL, WEIL DIE PRUEFUNG EIN REPOSITORIUM BRAUCHT. Sie zaehlt die versionierten
1054
+ # Dateien des Kerns ueber `git ls-files`, und kopie() schliesst `.git` ausdruecklich aus.
1055
+ # Ohne `git init` naehme sie in JEDER Sonde ihren dritten Ausgang ("nicht messbar") und
1056
+ # saehe dabei aus wie eine, die nichts gefunden hat - derselbe Griff wie bei Pruefung 75
1057
+ # und 45, aus demselben Grund.
1058
+ #
1059
+ # 🔴 KEINE SONDE VERANKERT EINE ZAHL WOERTLICH, und das ist die Lehre von 0.89.0: Dort
1060
+ # sind zwei Sonden gebrochen, weil sie einen Wert als Suchtext hielten, den ein Release
1061
+ # berichtigt hat. Die Sonden hier LESEN die Zahl aus dem Traeger und verstellen sie
1062
+ # relativ. Eine Sonde, die eine Zahl mitpflegen muss, faellt bei der naechsten Aenderung
1063
+ # aus - und zwar als scheinbarer Befund.
1064
+ #
1065
+ # VIER EINHEITEN, UND SIE MESSEN VIER VERSCHIEDENE DINGE:
1066
+ # 78a (Gegenprobe) - der ausgelieferte Bestand laeuft durch, und die Pruefung ist dabei
1067
+ # nachweislich gelaufen (keine Unmessbarkeitsmeldung).
1068
+ # 78a (Sonde) - eine verstellte Zahl der Pruefungen wird gemeldet.
1069
+ # 78b (Sonde) - eine verstellte Zahl der versionierten Dateien wird gemeldet. Ohne
1070
+ # sie genuegte es, EINE der drei Zahlen zu treffen.
1071
+ # 78c (Sonde) - der verlorene Anker: Faellt der Satz weg, meldet die Pruefung das,
1072
+ # statt leise zu bestehen (D-23).
1073
+ # 78d, 78e - ENTFALLEN mit 1.4.1 (D-350): Sie maßen die Abnahmezeile der
1074
+ # Uebergabe, und die ist nicht mehr versioniert.
1075
+ M78_WERTE = "nennt nicht die gezählten Werte"
1076
+ M78_ANKER = "steht nicht genau einmal"
1077
+ M78_UNMESSBAR = "kein Git-Bestand lesbar"
1078
+
1079
+ P78_OPFER = ".koolie/core/build/doc/26-qs-test.md"
1080
+ P78_ANKER = "Der Validator führt **"
1081
+
1082
+
1083
+ def _78_zahl_verstellen(text: str, muster: str) -> str:
1084
+ """Die erste Zahl hinter `muster` um eins erhoehen - ohne sie woertlich zu kennen."""
1085
+ treffer = re.search(re.escape(muster) + r"(\d+)", text)
1086
+ if not treffer:
1087
+ raise Praeparationsfehler(
1088
+ "26-qs-test.md: %r mit folgender Zahl nicht gefunden - die Sonde zu "
1089
+ "Pruefung 78 haette nichts zu verstellen" % muster)
1090
+ neu = str(int(treffer.group(1)) + 1)
1091
+ return text[:treffer.start(1)] + neu + text[treffer.end(1):]
1092
+
1093
+
1094
+ def sonden_dokumentzahlen() -> None:
1095
+ """Wirkungsnachweis zu Pruefung 78 an einem echten Repositorium."""
1096
+ root = kopie()
1097
+ try:
1098
+ if unterprozess(["git", "init", "-q", root]).returncode != 0:
1099
+ melde("BUENDEL", "-", False, "sonden_dokumentzahlen [git nicht erreichbar]")
1100
+ notiz(" Ohne git zaehlt Pruefung 78 keine versionierten Dateien; sie "
1101
+ "nimmt dann ihren dritten Ausgang und ist nicht messbar.")
1102
+ return
1103
+ unterprozess(["git", "-C", root, "add", "-A"])
1104
+ pfad = P(root, *P78_OPFER.split("/"))
1105
+ urtext = lies(pfad)
1106
+
1107
+ # --- Gegenprobe 78a: der ausgelieferte Bestand laeuft durch ------------------
1108
+ aus = validator_ausgabe(root)
1109
+ ok = (M78_WERTE not in aus and M78_ANKER not in aus
1110
+ and M78_UNMESSBAR not in aus)
1111
+ melde("GEGENPROBE", "78a", ok,
1112
+ "Der ausgelieferte Bestand laeuft durch - die drei Zahlen des Satzes "
1113
+ "decken sich mit dem Bestand, und die Pruefung ist dabei nachweislich "
1114
+ "gelaufen")
1115
+ if not ok:
1116
+ notiz(" Ausgabe:", " | ".join(
1117
+ z for z in aus.splitlines() if "78" in z or "Prüfapparat" in z)[:400])
1118
+
1119
+ # --- Sonde 78a: die Zahl der Pruefungen verstellt ----------------------------
1120
+ schreib(pfad, _78_zahl_verstellen(urtext, P78_ANKER))
1121
+ unterprozess(["git", "-C", root, "add", "-A"])
1122
+ aus = validator_ausgabe(root)
1123
+ melde("SONDE", "78a", M78_WERTE in aus,
1124
+ "Eine verstellte Zahl der Pruefungen wird gemeldet - genau diese Zahl "
1125
+ "stand ein Release zu lang auf ihrem alten Wert")
1126
+ if M78_WERTE not in aus:
1127
+ notiz(" Ausgabe:", " | ".join(
1128
+ z for z in aus.splitlines() if "FEHLER" in z)[:400])
1129
+
1130
+ # --- Sonde 78b: die Zahl der versionierten Dateien verstellt -----------------
1131
+ schreib(pfad, _78_zahl_verstellen(urtext, "Prüfungen** über "))
1132
+ unterprozess(["git", "-C", root, "add", "-A"])
1133
+ aus = validator_ausgabe(root)
1134
+ melde("SONDE", "78b", M78_WERTE in aus,
1135
+ "Eine verstellte Zahl der versionierten Dateien wird ebenfalls gemeldet - "
1136
+ "sonst genuegte es, eine der drei Zahlen zu treffen")
1137
+ if M78_WERTE not in aus:
1138
+ notiz(" Ausgabe:", " | ".join(
1139
+ z for z in aus.splitlines() if "FEHLER" in z)[:400])
1140
+
1141
+ # --- Sonde 78c: der verlorene Anker ------------------------------------------
1142
+ schreib(pfad, urtext.replace(P78_ANKER, "Der Validator kennt **", 1))
1143
+ unterprozess(["git", "-C", root, "add", "-A"])
1144
+ aus = validator_ausgabe(root)
1145
+ melde("SONDE", "78c", M78_ANKER in aus,
1146
+ "Faellt der Satz ueber den Pruefapparat weg, meldet Pruefung 78 den "
1147
+ "verlorenen Anker, statt still zu bestehen")
1148
+ if M78_ANKER not in aus:
1149
+ notiz(" Ausgabe:", " | ".join(
1150
+ z for z in aus.splitlines() if "FEHLER" in z)[:400])
1151
+ schreib(pfad, urtext)
1152
+
1153
+ finally:
1154
+ aufraeumen(os.path.dirname(root))
1155
+
1156
+
1157
+ buendel(sonden_dokumentzahlen,
1158
+ "Pruefung 78 haelt die drei Gegenwartszahlen des Hauptdokuments gegen den "
1159
+ "gezaehlten Bestand, an einem echten Repositorium")
1160
+
1161
+
1162
+ # --- Pruefung 79: Die Lizenz an zwei Stellen (CR-2026-126, D-317) ------------------
1163
+ #
1164
+ # DREI SONDEN UND EINE GEGENPROBE. Die dritte ist die, die man weglassen wuerde: Sie
1165
+ # ersetzt BEIDE Dateien durch denselben Nicht-Lizenztext. Ohne sie belegte die Pruefung
1166
+ # nur, dass zwei Dateien gleich sind - und das sind zwei leere auch.
1167
+ M79_UNGLEICH = "trägt nicht denselben Inhalt wie"
1168
+ M79_FEHLT = "Die Lizenz MUSS an beiden Stellen liegen"
1169
+ M79_MARKE = "trägt nicht die GNU General Public License"
1170
+
1171
+ P79_KERNDATEI = ".koolie/core/LICENSE"
1172
+ P79_WURZELDATEI = "LICENSE"
1173
+
1174
+
1175
+ def _79_auseinander(root: str) -> None:
1176
+ """Sonde: die beiden Lizenzdateien laufen auseinander."""
1177
+ pfad = P(root, *P79_KERNDATEI.split("/"))
1178
+ schreib(pfad, lies(pfad) + "\n<!-- SYNTHETISCH: Zusatz nur in der Kernfassung -->\n")
1179
+
1180
+
1181
+ def _79_kernfassung_entfernen(root: str) -> None:
1182
+ """Sonde: die mitwandernde Fassung fehlt - genau der Fall von §4 GPL-3.0."""
1183
+ os.remove(P(root, *P79_KERNDATEI.split("/")))
1184
+
1185
+
1186
+ def _79_keine_lizenz(root: str) -> None:
1187
+ """Sonde: beide Dateien gleich, aber keine Lizenz - die Gleichheit allein traegt nicht."""
1188
+ ersatz = "SYNTHETISCH: hier stand einmal ein Lizenztext.\n"
1189
+ for rel in (P79_KERNDATEI, P79_WURZELDATEI):
1190
+ schreib(P(root, *rel.split("/")), ersatz)
1191
+
1192
+
1193
+ sonde("79a", "Laufen die beiden Lizenzdateien auseinander, wird es gemeldet - welche "
1194
+ "gilt, stuende sonst nirgends",
1195
+ _79_auseinander, M79_UNGLEICH)
1196
+
1197
+ sonde("79b", "Fehlt die mitwandernde Fassung im Kern, wird es gemeldet - ein Werk ohne "
1198
+ "seine Lizenz weiterzugeben ist unzulaessig",
1199
+ _79_kernfassung_entfernen, M79_FEHLT)
1200
+
1201
+ sonde("79c", "Zwei gleiche Dateien ohne Lizenztext werden gemeldet - Gleichheit allein "
1202
+ "erfuellen auch zwei leere Dateien",
1203
+ _79_keine_lizenz, M79_MARKE)
1204
+
1205
+ gegenprobe("79a", "Der ausgelieferte Bestand laeuft durch - beide Stellen, ein Inhalt, "
1206
+ "und dieser Inhalt ist die GPL-3.0",
1207
+ None, M79_UNGLEICH)
1208
+
1209
+
1210
+ # --- Pruefung 80: Die Gegenzeichnung der Abnahmeprotokolle (CR-2026-127, D-319) ----
1211
+ #
1212
+ # DREI SONDEN UND ZWEI GEGENPROBEN. Die zweite Gegenprobe ist die, die man weglassen
1213
+ # wuerde, und sie traegt die ganze Entscheidung: Ein offenes <TBD> im
1214
+ # Gegenzeichnungsabschnitt eines ARBEITSPROTOKOLLS muss unbeanstandet bleiben. Ohne sie
1215
+ # waere der Zuschnitt aus D-319 eine Behauptung im Kommentar statt eine gemessene
1216
+ # Eigenschaft - und die Pruefung verlangte still die Gegenzeichnung von 125 Protokollen
1217
+ # statt von zehn.
1218
+ #
1219
+ # 🔴 JEDE SONDE PRUEFT IHRE EIGENE FUNDSTELLE, nicht irgendeine Meldung. Der
1220
+ # ausgelieferte Bestand traegt sieben frisch gezeichnete Abnahmeprotokolle; eine Sonde,
1221
+ # die nur auf den Meldungstext prueft, bestuende auch ohne Praeparation. Der Erwartungs-
1222
+ # text nennt deshalb den DATEINAMEN des Opfers - dieselbe Bauform wie bei Sonde 75a.
1223
+ M80_FEHLT = "2026-09-10-FW-KO-02.md: kein Abschnitt"
1224
+ M80_TBD = "2026-09-10-FW-KO-02.md: der Abschnitt `Gegenzeichnung` trägt noch ein offenes"
1225
+ M80_ANKER = "kein einziges Abnahmeprotokoll des Testkatalogs gefunden"
1226
+
1227
+ P80_OPFER = ".koolie/core/tests/protocols/2026-09-10-FW-KO-02.md"
1228
+ P80_ARBEITSPROTOKOLL = ".koolie/core/tests/protocols/2026-09-13-B06-gegenpruefung.md"
1229
+
1230
+
1231
+ def _80_abschnitt_entfernen(root: str) -> None:
1232
+ """Sonde: einem Abnahmeprotokoll fehlt die Gegenzeichnung."""
1233
+ pfad = P(root, *P80_OPFER.split("/"))
1234
+ text = lies(pfad)
1235
+ anfang = text.find("## Gegenzeichnung")
1236
+ if anfang < 0:
1237
+ raise Praeparationsfehler(
1238
+ "2026-09-10-FW-KO-02.md: kein Abschnitt 'Gegenzeichnung' gefunden - die "
1239
+ "Sonde zu Pruefung 80 haette nichts zu entfernen")
1240
+ schreib(pfad, text[:anfang].rstrip("\r\n") + "\r\n")
1241
+
1242
+
1243
+ def _80_tbd_zurueck(root: str) -> None:
1244
+ """Sonde: der Abschnitt ist da und traegt wieder ein offenes <TBD>."""
1245
+ pfad = P(root, *P80_OPFER.split("/"))
1246
+ text = lies(pfad)
1247
+ anfang = text.find("## Gegenzeichnung")
1248
+ if anfang < 0:
1249
+ raise Praeparationsfehler(
1250
+ "2026-09-10-FW-KO-02.md: kein Abschnitt 'Gegenzeichnung' gefunden")
1251
+ schreib(pfad, text + "\r\n| Zweitpruefung | `<TBD: Rolle>` | | |\r\n")
1252
+
1253
+
1254
+ def _80_anker_entfernen(root: str) -> None:
1255
+ """Sonde: kein Traeger passt mehr auf das Namensmuster der Abnahmeprotokolle."""
1256
+ ablage = P(root, *".koolie/core/tests/protocols".split("/"))
1257
+ umbenannt = 0
1258
+ for name in sorted(os.listdir(ablage)):
1259
+ if "-FW-" in name and name.endswith(".md"):
1260
+ os.rename(os.path.join(ablage, name),
1261
+ os.path.join(ablage, name.replace("-FW-", "-fw", 1)))
1262
+ umbenannt += 1
1263
+ if not umbenannt:
1264
+ raise Praeparationsfehler(
1265
+ "tests/protocols/: kein Traeger mit '-FW-' im Namen - die Sonde zum "
1266
+ "verlorenen Anker haette nichts umzubenennen")
1267
+
1268
+
1269
+ def _80_arbeitsprotokoll_offen(root: str) -> None:
1270
+ """Gegenprobe: ein ARBEITSPROTOKOLL mit offenem Abschnitt - der Zuschnitt."""
1271
+ pfad = P(root, *P80_ARBEITSPROTOKOLL.split("/"))
1272
+ text = lies(pfad)
1273
+ if "<TBD" not in text:
1274
+ raise Praeparationsfehler(
1275
+ "2026-09-13-B06-gegenpruefung.md: traegt kein offenes <TBD> mehr - die "
1276
+ "Gegenprobe zum Zuschnitt von Pruefung 80 haette keinen Gegenstand")
1277
+ schreib(pfad, text + "\r\n| Zweitpruefung | `<TBD: Rolle>` | | |\r\n")
1278
+
1279
+
1280
+ sonde("80a", "Fehlt einem Abnahmeprotokoll die Gegenzeichnung, wird es mit Dateinamen "
1281
+ "gemeldet - fuenf von zehn hatten den Abschnitt nie",
1282
+ _80_abschnitt_entfernen, M80_FEHLT)
1283
+
1284
+ sonde("80b", "Ein offenes <TBD> im Abschnitt wird gemeldet - eine Gegenzeichnung ist "
1285
+ "eine Handlung und kein Feld, das ein Werkzeug fuellt",
1286
+ _80_tbd_zurueck, M80_TBD)
1287
+
1288
+ sonde("80c", "Passt kein Traeger mehr auf das Namensmuster, meldet Pruefung 80 den "
1289
+ "verlorenen Anker, statt still ueber null Protokolle zu bestehen",
1290
+ _80_anker_entfernen, M80_ANKER)
1291
+
1292
+ gegenprobe("80a", "Der ausgelieferte Bestand laeuft durch - alle zehn Abnahmeprotokolle "
1293
+ "tragen ihren Abschnitt ohne offenes <TBD>",
1294
+ None, M80_FEHLT)
1295
+
1296
+ gegenprobe("80b", "Ein offenes <TBD> in einem ARBEITSPROTOKOLL bleibt unbeanstandet - "
1297
+ "das ist der Zuschnitt aus D-319 und nicht bloss seine Behauptung",
1298
+ _80_arbeitsprotokoll_offen, "B06-gegenpruefung.md: der Abschnitt")
1299
+
1300
+
1301
+ # --- Selbstprobe: der Beschreibungssatz je Einheit (CR-2026-068, D-95) ------------
1302
+ #
1303
+ # Bis 0.45.0 trug jede Einzelsonde einen erklaerenden Text und jedes Buendel keinen. Wer
1304
+ # den Lauf las, sah eine Folge von Meldungen und nicht, was sie zusammen belegen sollten.
1305
+ # Seit 0.46.0 ist der Satz Pflicht - und eine Pflicht ohne Nachzaehlen ist eine Zusage
1306
+ # ohne Mechanismus, also genau der wiederkehrende Befundtyp dieses Projekts.
1307
+ #
1308
+ # GRENZE: Sie zaehlt WORTE, nicht Sinn. Ein Satz aus achtzehn Fuellwoertern besteht sie.
1309
+ # Die untere Grenze faengt die Kennung, die sich als Satz ausgibt ("Pack ohne
1310
+ # Auskunftsabschnitt"), die obere den Absatz, der sich in eine Zeile verirrt hat.
1311
+ # Dazwischen entscheidet der Mensch, und das ist Absicht.
1312
+ def selbstprobe_beschreibungen() -> None:
1313
+ """Jede angemeldete Einheit traegt ihren Satz in der vorgeschriebenen Laenge."""
1314
+ abweichend = [e for e in EINHEITEN if not SATZ_MIN <= worte(e.satz) <= SATZ_MAX]
1315
+ melde("SELBSTPROBE", "B1", not abweichend,
1316
+ "Alle %d Einheiten tragen einen Beschreibungssatz von %d bis %d Worten"
1317
+ % (len(EINHEITEN), SATZ_MIN, SATZ_MAX))
1318
+ for e in abweichend:
1319
+ notiz(" %s %s: %d Worte - %s"
1320
+ % (e.art, e.kennung, worte(e.satz), e.satz))
1321
+
1322
+
1323
+ buendel(selbstprobe_beschreibungen,
1324
+ "Zaehlt die Worte jedes Beschreibungssatzes dieses Laufs - eine Kennung ohne "
1325
+ "Satz und ein Absatz in einer Zeile fallen beide auf")