@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,957 @@
1
+ """Die Werkzeuge des Kerns und ihre Lieferung: Bytecode, Erzeugnisse in .gitignore,
2
+ Praefixerfassung, Erhebungsablage, Werkzeugnamen, Arbeitsplatzpfade, Kernlage,
3
+ Lieferumfang und die Paketquellen.
4
+
5
+ Pruefungen 45, 68, 69, 70, 71, 76, 90, 107 und 112. Teil des Validators validate-framework.py,
6
+ seit 1.19.1 nach Gegenstand in Module geteilt (K-174). Das Register aller Pruefungen
7
+ steht im Kopfkommentar des Einstiegs, die Grenze jeder einzelnen in ihrem Kopfkommentar
8
+ hier."""
9
+ from __future__ import annotations
10
+
11
+ import ast
12
+ import builtins
13
+ import json
14
+ import os
15
+ import re
16
+ import symtable
17
+ import sys
18
+
19
+ from .gemeinsam import (
20
+ _clientmap, _verfolgte_dateien, err, hinweis, ist_quellrepositorium,
21
+ iter_text_files, KERN, nicht_geliefert, PAKET_JE_SKRIPT, read, warn)
22
+
23
+
24
+ # --- 45: Der Bytecode des Kerns gehoert nicht in die Versionierung (D-97) -----------
25
+ #
26
+ # ANLASS. Abgezaehlt am 2026-09-15 an **beiden** Projekten, die dieses Framework benutzen:
27
+ # Der Pilot fuehrte sechs .pyc-Dateien unter .koolie/core/ in der Versionierung, das
28
+ # Uebungsrepositorium zwei. Zwei von zwei. Der Uebernahmeleitfaden sagte zur .gitignore
29
+ # nur, welche Zeilen man **weglassen** soll - die vier, die im Framework-Repositorium die
30
+ # Wurzelbestandteile ausschliessen. Welche Zeile man **braucht**, sagte er nicht.
31
+ #
32
+ # **Das ist dieselbe Bauform wie der Befund von 0.45.0:** eine Anweisung, die die halbe
33
+ # Migration beschreibt, ist gefaehrlicher als keine. Wer dem Leitfaden woertlich folgt,
34
+ # schreibt eine eigene .gitignore - und versioniert danach den Bytecode eines Werkzeugs,
35
+ # das bei jedem Lauf neuen erzeugt.
36
+ #
37
+ # ZWEI GEGENSTAENDE, und der zweite ist der, der den Fall wirklich faengt:
38
+ #
39
+ # 1. DIE REGEL. Die .gitignore des Projekts deckt __pycache__ ab. Geprueft wird gegen
40
+ # eine kleine Liste gebraeuchlicher Schreibweisen (GITIGNORE_DECKUNG), nicht gegen
41
+ # eine einzige - ein Projekt, das `*.pyc` schreibt, ist richtig, und eine Pruefung,
42
+ # die es meldete, waere zu eng. Genau der Fehler, den Pruefung 37 einmal gemacht hat.
43
+ # 2. DER BESTAND. Wo git erreichbar und die Wurzel ein Repositorium ist: keine Datei
44
+ # unter <CORE_DIR>/ mit der Endung .pyc oder im Pfad __pycache__ darf verfolgt sein.
45
+ #
46
+ # WARUM BEIDE. Die Regel allein waere die halbe Migration ein zweites Mal: **git liest
47
+ # die .gitignore fuer bereits verfolgte Dateien nicht.** Wer die Zeile nachtraegt und
48
+ # `git rm --cached` vergisst, bekaeme einen gruenen Lauf und haette die sechs Dateien
49
+ # weiter im Repositorium. Der Bestand allein wiederum sagt dem Projekt nicht, wie es die
50
+ # Wiederholung verhindert - beim naechsten `git add` waeren sie zurueck.
51
+ #
52
+ # GRENZE. Gegenstand 2 laeuft nur, wo git erreichbar ist und die Wurzel ein Repositorium
53
+ # ist. Wo nicht, sagt die Pruefung das als **Warnung** - dieselbe Bauform, die dieses
54
+ # Skript fuer das fehlende PyYAML schon hat. Eine Pruefhaelfte, die stumm ausfaellt, waere
55
+ # genau der Befundtyp, gegen den D-23 gebaut ist.
56
+ # Und: Fehlt die .gitignore ganz, ist das eine **Warnung** und kein Fehler. Ob ein Projekt
57
+ # ueberhaupt versioniert, kann dieses Skript nicht wissen; Gegenstand 2 faengt den echten
58
+ # Fall ohnehin, sobald git da ist.
59
+ GITIGNORE_DECKUNG = ("__pycache__/", "__pycache__", "**/__pycache__/",
60
+ "*.pyc", "**/*.pyc")
61
+ BYTECODE_MARKER = "__pycache__"
62
+
63
+
64
+ def check_bytecode_versioniert(root: str) -> None:
65
+ """Pruefung 45 (D-97): Der Bytecode des Kerns steht nicht in der Versionierung."""
66
+ # --- Gegenstand 1: die Regel ---------------------------------------------------
67
+ pfad = os.path.join(root, ".gitignore")
68
+ if not os.path.exists(pfad):
69
+ warn(".gitignore: nicht vorhanden. Prüfung 45 kann die Regel gegen den Bytecode "
70
+ "des Kerns nicht prüfen. Versioniert dieses Projekt, gehört `__pycache__/` "
71
+ "dort hinein – die Python-Werkzeuge des Kerns erzeugen bei jedem Lauf "
72
+ "Bytecode unter " + KERN + "/ (D-97)")
73
+ else:
74
+ zeilen = [z.strip() for z in read(pfad).splitlines()]
75
+ if not any(z in GITIGNORE_DECKUNG for z in zeilen):
76
+ err(f".gitignore: deckt den Bytecode des Kerns nicht ab. Die Python-Werkzeuge "
77
+ f"unter {KERN}/ erzeugen bei jedem Lauf `.pyc`-Dateien; versioniert, "
78
+ f"ändern sie sich mit jedem Lauf und überleben den Kern, aus dem sie "
79
+ f"entstanden sind. Eine dieser Zeilen gehört in die Datei: "
80
+ f"{', '.join('`%s`' % m for m in GITIGNORE_DECKUNG)} "
81
+ f"(docs/ADOPTION_GUIDE.md Abschnitt 2, D-97)")
82
+
83
+ # --- Gegenstand 2: der Bestand ---------------------------------------------------
84
+ verfolgt = _verfolgte_dateien(root)
85
+ if verfolgt is None:
86
+ warn(f"Gegenstand 2 der Prüfung 45 ist nicht gelaufen – git ist nicht erreichbar "
87
+ f"oder {root} ist kein Repositorium. Ob unter {KERN}/ Bytecode versioniert "
88
+ f"ist, sagt dieser Lauf damit **nicht**; die Regel in der .gitignore allein "
89
+ f"entfernt bereits verfolgte Dateien nicht (D-97)")
90
+ return
91
+ bytecode = sorted(p for p in verfolgt
92
+ if p.endswith(".pyc") or BYTECODE_MARKER in p)
93
+ if bytecode:
94
+ gezeigt = ", ".join(bytecode[:4]) + (" …" if len(bytecode) > 4 else "")
95
+ err(f"{len(bytecode)} Bytecode-Datei(en) unter {KERN}/ sind versioniert: "
96
+ f"{gezeigt}. **Die Regel in der .gitignore entfernt sie nicht** – git liest "
97
+ f"sie für bereits verfolgte Dateien nicht. Der Weg ist "
98
+ f"`git rm -r --cached {KERN}/**/__pycache__` und danach die Regel (D-97)")
99
+
100
+
101
+
102
+ # --- 45, Gegenstand 3: Die Erzeugnisse der Packs im Quellrepositorium (D-383, K-124) --
103
+ #
104
+ # Im Quellrepositorium sind Wurzel-Anweisungsdatei, Laufzeitschicht und Overlay
105
+ # ERZEUGNISSE von install.py und werden nicht versioniert (README, Abschnitt "Arbeiten an
106
+ # diesem Repository"). Bis 1.9.0 schloss die .gitignore nur die Erzeugnisse EINES Packs
107
+ # aus; nach `install.py --client` mit einem der anderen beiden waeren deren Dateien
108
+ # versionierbar gewesen (K-124).
109
+ #
110
+ # ABGELEITET, NICHT AUFGEZAEHLT: Was ein Pack in die Wurzel schreibt, steht in seinem
111
+ # Manifest (shared_core, shared_seed). Verlangt wird je Ziel der erste Pfadbestandteil
112
+ # (unter .koolie/ die ersten zwei - der Kern selbst ist versioniert). Ein neues Pack
113
+ # bringt seine Zeilen damit als Befund mit, statt still versionierbar zu sein.
114
+ # Nur im Quellrepositorium: In einem Projekt gilt das Gegenteil (D-383).
115
+ GITIGNORE_ERZEUGNIS_LISTEN = ("shared_core", "shared_seed")
116
+
117
+
118
+ def _erzeugnis_wurzeln(root: str) -> dict:
119
+ """{Wurzelbestandteil: [Packs]} aller Ziele, die install.py im Quellrepositorium anlegt."""
120
+ kern = os.path.join(root, KERN)
121
+ if kern not in sys.path:
122
+ sys.path.insert(0, kern)
123
+ try:
124
+ import clientmap
125
+ except ImportError:
126
+ warn("clientmap.py nicht gefunden – Gegenstand 3 der Prüfung 45 ist nicht "
127
+ "gelaufen (D-383)")
128
+ return {}
129
+ wurzeln: dict = {}
130
+ clients = os.path.join(root, KERN, "clients")
131
+ for pack in sorted(os.listdir(clients)):
132
+ pfad = os.path.join(clients, pack, "manifest.json")
133
+ if pack.startswith("_") or not os.path.isfile(pfad):
134
+ continue
135
+ man = json.loads(read(pfad))
136
+ for liste in GITIGNORE_ERZEUGNIS_LISTEN:
137
+ for eintrag in man.get(liste, []):
138
+ ziel = clientmap.resolve_placeholders(eintrag["dst"], man).strip("/")
139
+ teile = ziel.split("/")
140
+ if teile[0] == ".koolie":
141
+ if len(teile) < 2 or teile[1] == "core":
142
+ continue
143
+ teile = teile[:2]
144
+ else:
145
+ teile = teile[:1]
146
+ wurzeln.setdefault("/".join(teile), []).append(pack)
147
+ return wurzeln
148
+
149
+
150
+ def check_gitignore_erzeugnisse(root: str) -> None:
151
+ """Pruefung 45, Gegenstand 3 (D-383): Die .gitignore des Quellrepositoriums schliesst
152
+ die Wurzelerzeugnisse jedes Packs aus."""
153
+ if not ist_quellrepositorium(root):
154
+ return
155
+ pfad = os.path.join(root, ".gitignore")
156
+ if not os.path.isfile(pfad):
157
+ return # Gegenstand 1 meldet die fehlende Datei
158
+ zeilen = {z.strip().strip("/") for z in read(pfad).splitlines()
159
+ if z.strip() and not z.strip().startswith(("#", "!"))}
160
+ for wurzel, packs in sorted(_erzeugnis_wurzeln(root).items()):
161
+ if wurzel not in zeilen:
162
+ err(f".gitignore: schließt das Erzeugnis `/{wurzel}` nicht aus "
163
+ f"({', '.join(sorted(set(packs)))}). Im Quellrepositorium sind "
164
+ f"Wurzel-Anweisungsdatei, Laufzeitschicht und Overlay Erzeugnisse von "
165
+ f"install.py und werden nicht versioniert (Prüfung 45, D-383)")
166
+
167
+
168
+ def check_lieferumfang(root: str) -> None:
169
+ """Pruefung 90 (D-367): Die Angabe des Lieferumfangs stimmt."""
170
+ cm = _clientmap(root)
171
+ if cm is None:
172
+ return # ohne clientmap.py meldet Pruefung 1 die fehlende Pflichtdatei
173
+ kern = os.path.join(root, KERN)
174
+ datei = f"{KERN}/{cm.LIEFERUMFANG_DATEI}"
175
+ vorhanden = os.path.isfile(os.path.join(kern, cm.LIEFERUMFANG_DATEI))
176
+ if ist_quellrepositorium(root):
177
+ if vorhanden:
178
+ err(f"{datei}: liegt im Quellrepositorium. Die Datei schreibt install.py in "
179
+ f"ein Projekt; hier behauptete sie eine Installation, und eine Quelle mit "
180
+ f"'nutzung' lieferte keinen vollen Kern mehr (D-367)")
181
+ return
182
+ wert = cm.lieferumfang(kern)
183
+ if wert not in cm.LIEFERUMFAENGE:
184
+ err(f"{datei}: trägt '{wert}' – bekannt sind {', '.join(cm.LIEFERUMFAENGE)}. "
185
+ f"Das nächste Heben hält daran an (D-367)")
186
+ return
187
+ if wert != "nutzung":
188
+ return
189
+ da = [a for a in cm.NACHWEIS_ABLAGEN if os.path.exists(os.path.join(kern, *a.split("/")))]
190
+ if da:
191
+ err(f"{datei}: sagt 'nutzung', aber {', '.join(f'{KERN}/{a}/' for a in da)} "
192
+ f"liegt da. Das nächste Heben mit diesem Umfang löscht es; wer den ganzen "
193
+ f"Kern will, hebt mit --lieferumfang voll (D-367)")
194
+ return
195
+ hinweis(f"Lieferumfang 'nutzung' ({datei}): ohne die Nachweisschicht "
196
+ f"({', '.join(cm.NACHWEIS_ABLAGEN)}). Verweise dorthin sind Herkunftsangaben "
197
+ f"und werden nicht gemeldet; Belege stehen im Release-Archiv (D-367)")
198
+
199
+
200
+ # --- Pruefung 68: Das Praefix, das mehr sperrt als sein Befehl ----------------------
201
+ #
202
+ # ANLASS, UND ER IST GEMESSEN. permissions.json fuehrt je exec-Regel einen `command`
203
+ # (die woertliche Form) und optional einen `prefix` (die Form fuer Clients, die ueber
204
+ # ein Praefix sperren). Ist der `prefix` kuerzer, sperrt die Regel MEHR, als ihr
205
+ # Befehl nennt. Am 2026-09-20 hat genau das gekostet: Der Eintrag mit dem command
206
+ # "git branch -D" traegt den prefix "git branch" und sperrt damit auch das blosse
207
+ # Auflisten. Gemessen ueber 50 Laeufe des vierten Testblattbuendels: 25 Abweisungen
208
+ # in 23 Laeufen, elf davon auf "git branch" - und zwei Skills schreiben in
209
+ # Arbeitsschritt 1 und in ihrer Fehlerbehandlung eine Kandidatenliste vorhandener
210
+ # Branches vor, die sie damit nicht liefern koennen (D-219).
211
+ #
212
+ # WARUM DIE SPERRE TROTZDEM BLEIBT, UND WARUM DAS EINE PRUEFUNG BRAUCHT. Der
213
+ # allow-Korb dieser Datei ist praefixbasiert, und clientmap.py verbietet dort ein
214
+ # kuerzeres Praefix als der Befehl ("bei allow waere das eine Lockerung"). Er traegt
215
+ # deshalb bisher ausschliesslich Verben OHNE schreibende Form - git status, diff,
216
+ # log, show, blame. `git branch` waere das erste mit einer. Die Uebererfassung ist
217
+ # hier also GEWOLLT; was fehlte, war, dass sie irgendwo steht. Eine Schranke, die
218
+ # mehr sperrt als sie sagt, ist die Schwester des wiederkehrenden Befundtyps dieses
219
+ # Projekts mit umgekehrtem Vorzeichen - und sie faellt niemandem auf, weil ein
220
+ # ueberschiessendes Verbot wie Sorgfalt aussieht.
221
+ #
222
+ # DER WAECHTER, DER ES NICHT SAH. clientmap.py prueft, ob der prefix ein Praefix des
223
+ # command IST - sonst waere die Praefixform "nicht nachweislich breiter als die
224
+ # woertliche". Er prueft die Richtung, nicht das Mass. Das ist D-205 an vierter
225
+ # Stelle: ein Muster, das seinen Gegenstand enthaelt und mehr.
226
+ #
227
+ # GRENZE, UND SIE STEHT HIER. Geprueft wird die NENNUNG, nicht ihre Richtigkeit: Eine
228
+ # Begruendung, die nicht traegt, laeuft durch - dieselbe Enthaltung, die Pruefung 65
229
+ # fuer den Protokollverweis zieht und Pruefung 61 fuer das Pruefmittelwort.
230
+ P68_FELD = "_uebererfasst"
231
+
232
+
233
+ def check_praefix_uebererfassung(root: str) -> None:
234
+ """Pruefung 68 (D-219): Ein Praefix, das mehr sperrt als sein Befehl, sagt es."""
235
+ rel = f"{KERN}/framework/runtime/permissions.json"
236
+ pfad = os.path.join(root, KERN, "framework", "runtime", "permissions.json")
237
+ if not os.path.isfile(pfad):
238
+ return # Pruefung 1 und 39 melden die fehlende Kernquelle bereits
239
+ try:
240
+ quelle = json.loads(read(pfad))
241
+ except ValueError:
242
+ return # Pruefung 39 meldet die unlesbare Datei bereits
243
+ exec_regeln = 0
244
+ for korb in ("deny", "ask", "allow"):
245
+ eintraege = quelle.get(korb)
246
+ if not isinstance(eintraege, list):
247
+ continue
248
+ for regel in eintraege:
249
+ if not isinstance(regel, dict) or regel.get("tool") != "exec":
250
+ continue
251
+ exec_regeln += 1
252
+ befehl = str(regel.get("command", "")).strip()
253
+ praefix = str(regel.get("prefix", befehl)).strip()
254
+ if not befehl or praefix == befehl:
255
+ continue
256
+ if str(regel.get(P68_FELD, "")).strip():
257
+ continue
258
+ err(f"{rel}: die {korb}-Regel `{befehl}` sperrt über das Präfix "
259
+ f"`{praefix}` mehr, als ihr Befehl nennt – und sagt es nicht. Ein "
260
+ f"Feld `{P68_FELD}` mit der Begründung gehört dazu: Genau diese "
261
+ f"Bauform hat am 2026-09-20 fünfundzwanzig Abweisungen erzeugt und "
262
+ f"zwei Skills eine Zusage unmöglich gemacht, die sie selbst "
263
+ f"vorschreiben. Eine Schranke, die mehr sperrt als sie sagt, ist "
264
+ f"nicht weniger ein Befund als eine, die weniger hält (D-219)")
265
+ if exec_regeln == 0:
266
+ err(f"{rel}: keine einzige exec-Regel gefunden – Prüfung 68 rechnet ihre "
267
+ f"Präfixe gegen ihre Befehle und hat ihren Gegenstand verloren; sie "
268
+ f"bestünde sonst leise (D-23)")
269
+
270
+
271
+ # --- Pruefung 69: Der Messapparat schreibt nicht in das Repositorium ----------------
272
+ #
273
+ # ANLASS, UND ER IST GEMESSEN - ER KOSTETE NICHTS, WEIL ER VOR DEM LAUF KAM. D-222
274
+ # hat die Skripte der Erhebungen mit 0.79.0 ins Repositorium geholt und ihre Belege
275
+ # ausdruecklich DRAUSSEN gelassen: "203 Dateien, darunter fuenfzig
276
+ # Sitzungstranskripte mit Werkzeugeingaben; sie sind AUFZEICHNUNG, nicht Anweisung".
277
+ # Fuenf dieser Skripte legten ihre Belege aber schlicht NEBEN SICH ab:
278
+ #
279
+ # BELEGE = os.path.join(os.path.dirname(os.path.abspath(__file__)), "belege")
280
+ #
281
+ # Solange das Skript daneben lag, war das richtig. Seit es im Kern liegt, zeigt
282
+ # derselbe Ausdruck HINEIN - und lauf.py legt das Verzeichnis selbst an. Ein
283
+ # Nachlauf haette die Mitschriften seiner Laeufe versioniert, ohne dass jemand es
284
+ # entschieden haette. Gefunden am 2026-09-20 im Vorbedingungsdurchgang des
285
+ # Nachlaufs, vor dem ersten bezahlten Lauf.
286
+ #
287
+ # Wer einen Apparat umzieht, zieht seine relativen Pfade mit um - oder er
288
+ # verschiebt ihr Ziel, ohne es zu merken.
289
+ #
290
+ # WAS GEPRUEFT WIRD, UND WARUM SO. Nicht die Quelltexte (ein Zaehler, der Ausdruecke
291
+ # liest, prueft die Schreibweise statt der Sache, D-223), sondern das ERGEBNIS: In
292
+ # <CORE_DIR>/tests/erhebungen/ liegen Skripte und eine README - sonst nichts. Eine
293
+ # Belegdatei, eine Zustandsaufnahme oder ein Promptverzeichnis dort ist der Befund
294
+ # selbst, unabhaengig davon, welcher Ausdruck sie erzeugt hat.
295
+ #
296
+ # GRENZE, UND SIE STEHT HIER. Die Pruefung sieht nur, was schon geschrieben IST.
297
+ # Den Wächter davor traegt `ablage.py`: Er verlangt die Erhebungsablage als Angabe
298
+ # und weist einen Pfad im Repositorium ab. Zwei Haelften desselben Gegenstands -
299
+ # dieselbe Aufteilung wie bei D-205 zwischen Schnitt und Waechter.
300
+ #
301
+ # SEIT 1.19.0 EIN VERZEICHNIS, BENANNT (D-473): Der Messapparat ist ein Paket
302
+ # (`apparat/`). Zugelassen ist genau dieser Name, und darin nur Python-Quelltext - ein
303
+ # Beleg, eine Reihe oder ein Unterverzeichnis dort ist derselbe Befund wie daneben.
304
+ P69_ERLAUBT_DATEI = (".py", ".md")
305
+ P69_PAKETE = ("apparat",)
306
+
307
+
308
+ def _p69_paket_rest(pfad: str) -> list:
309
+ """Was in einem zugelassenen Paket liegt und kein Python-Quelltext ist."""
310
+ rest = []
311
+ for name in sorted(os.listdir(pfad)):
312
+ voll = os.path.join(pfad, name)
313
+ if name == "__pycache__" and os.path.isdir(voll):
314
+ continue
315
+ if os.path.isdir(voll) or not name.endswith(".py"):
316
+ rest.append(name)
317
+ return rest
318
+
319
+
320
+ def check_erhebungen_sauber(root: str) -> None:
321
+ """Pruefung 69 (D-222): In der Erhebungsablage des Kerns liegen nur Werkzeuge."""
322
+ rel = f"{KERN}/tests/erhebungen"
323
+ ordner = os.path.join(root, KERN, "tests", "erhebungen")
324
+ if not os.path.isdir(ordner):
325
+ return # ein uebernehmendes Projekt bekommt diese Ablage nicht ausgeliefert
326
+ gesehen = 0
327
+ for name in sorted(os.listdir(ordner)):
328
+ pfad = os.path.join(ordner, name)
329
+ if os.path.isdir(pfad):
330
+ if name == "__pycache__":
331
+ continue
332
+ if name in P69_PAKETE:
333
+ for fremd in _p69_paket_rest(pfad):
334
+ err(f"{rel}/{name}/{fremd}: im Werkzeugpaket der Erhebungsablage des "
335
+ f"Kerns liegt nur Python-Quelltext - Belege, Reihen und Prompts sind "
336
+ f"Aufzeichnung und gehoeren neben das Repositorium (D-222, D-473)")
337
+ continue
338
+ err(f"{rel}/{name}/: ein VERZEICHNIS in der Erhebungsablage des Kerns. "
339
+ f"Hier liegen Werkzeuge; Belege, Prompts und Zustandsaufnahmen sind "
340
+ f"Aufzeichnung und gehoeren neben das Repositorium (D-222). Die "
341
+ f"Ablage wird ueber LW_ERHEBUNG gesagt, nicht abgeleitet")
342
+ continue
343
+ gesehen += 1
344
+ if not name.endswith(P69_ERLAUBT_DATEI):
345
+ err(f"{rel}/{name}: keine Datei der zugelassenen Art "
346
+ f"({', '.join(P69_ERLAUBT_DATEI)}) in der Erhebungsablage des "
347
+ f"Kerns. Eine Belegdatei, ein Ergebnis-JSON oder eine "
348
+ f"Zustandsaufnahme ist hier der Befund selbst - unabhaengig davon, "
349
+ f"welcher Ausdruck sie erzeugt hat (D-222)")
350
+ if gesehen == 0:
351
+ err(f"{rel}: kein einziges Werkzeug gefunden – Prüfung 69 zaehlt den Inhalt "
352
+ f"dieser Ablage und hat ihren Gegenstand verloren; sie bestuende sonst "
353
+ f"leise (D-23)")
354
+
355
+
356
+ # --- Pruefung 70: Jedes Werkzeug des Kerns nennt nur Namen, die es gibt -------------
357
+ #
358
+ # ANLASS, UND ER IST GEMESSEN - ER KOSTETE NICHTS, WEIL ER VOR DEM LAUF KAM. Der
359
+ # Wiederaufnahmepunkt des halb gefahrenen Messtags fuehrte `stand-b4.py` als Befehl 1
360
+ # von 4 auf: das Skript, dessen Kopfkommentar sagt "EINE ZAHL IN EINER UEBERGABE IST
361
+ # EINE MOMENTAUFNAHME, DIESES SKRIPT IST DER STAND". Es brach beim Import ab:
362
+ #
363
+ # PROMPTS = os.path.join(os.path.dirname(S), "prompts")
364
+ #
365
+ # `S` trug bis D-222 den Ablageort NEBEN dem Skript. Der Umzug in den Kern hat ihn
366
+ # entfernt und zwei Lesestellen stehen lassen - eine im Modulrumpf, eine in `main()`.
367
+ # Seit 0.79.0 war das Werkzeug damit tot, und der Befund lag genau auf dem Weg der
368
+ # Wiederaufnahme. Gefunden am 2026-09-21, vor dem ersten bezahlten Kontrollauf.
369
+ #
370
+ # Ein Werkzeug, das niemand faehrt, verfaellt lautlos - und der Tag, an dem es
371
+ # gebraucht wird, ist der Tag, an dem es fehlt.
372
+ #
373
+ # WARUM KEINE DER 69 ES SAH, UND DAS IST DER EIGENTLICHE BEFUND. Pruefung 45 prueft,
374
+ # dass KEIN Bytecode versioniert ist - also die Abwesenheit einer Datei. Pruefung 69
375
+ # prueft die ART der Dateien in der Erhebungsablage - .py und .md, sonst nichts. Der
376
+ # Apparat hatte damit zwei Waechter ueber seinen Ablageort und keinen einzigen
377
+ # darueber, ob seine Werkzeuge laufen.
378
+ #
379
+ # WAS GEPRUEFT WIRD, UND WARUM SO. Nicht `import` - das fuehrt den Modulrumpf aus,
380
+ # und Werkzeuge dieses Kerns brechen dabei mit Absicht ab (`ablage.py` ohne
381
+ # LW_ERHEBUNG), waehrend `lauf.py` sein Belegverzeichnis anlegen wuerde: genau das,
382
+ # was D-222 verworfen hat. Eine Pruefung, die ihren Gegenstand veraendert, misst ihn
383
+ # nicht. Geprueft wird deshalb die SYMBOLTABELLE, die der Interpreter selbst baut:
384
+ # Sie kennt jede Bindung und jeden Gueltigkeitsbereich - Modul, Funktion, Klasse,
385
+ # Komprehension - und sagt je Name, ob er zugewiesen, importiert, Parameter, frei
386
+ # oder global ist. Ein global gelesener Name, den weder der Modulrumpf noch die
387
+ # eingebauten Namen binden, ist ein NameError, der auf seinen Lauf wartet.
388
+ #
389
+ # GRENZE, UND SIE STEHT HIER. Geprueft wird der NAME, nicht der WERT. Wer `S = None`
390
+ # schreibt und `os.path.dirname(S)` aufruft, laeuft durch - dieselbe Enthaltung wie
391
+ # bei Pruefung 68. Und ein Lauf des Werkzeugs bliebe der staerkere Nachweis; er
392
+ # kostet Kontingent und legt Dateien an, diese Pruefung nicht.
393
+ P70_EINGEBAUT = frozenset(dir(builtins))
394
+
395
+
396
+ def _p70_offene_namen(quelle: str, name: str) -> list:
397
+ """Die global gelesenen Namen einer Quelle, die nirgends gebunden sind."""
398
+ top = symtable.symtable(quelle, name, "exec")
399
+ modul = {sym.get_name() for sym in top.get_symbols()
400
+ if sym.is_assigned() or sym.is_imported() or sym.is_parameter()}
401
+ offen = []
402
+
403
+ def geh(tab) -> None:
404
+ for sym in tab.get_symbols():
405
+ n = sym.get_name()
406
+ if not sym.is_referenced():
407
+ continue
408
+ if sym.is_assigned() or sym.is_imported() or sym.is_parameter():
409
+ continue
410
+ # Die Modulglobalen, die der Interpreter selbst setzt (__file__,
411
+ # __name__, und was eine Python-Fassung sonst hinzufuegt). Ohne diese
412
+ # Ausnahme meldete die Pruefung zwoelf Werkzeuge dieses Kerns, und alle
413
+ # zwoelf laufen - ein Waechter, der bei jedem Lauf meldet, wird
414
+ # abgeschaltet.
415
+ if n.startswith("__") and n.endswith("__"):
416
+ continue
417
+ if n in P70_EINGEBAUT or n in modul:
418
+ continue
419
+ # Nur, was im Modulrumpf steht oder ausdruecklich global gelesen wird.
420
+ # Eine freie Variable aus einer umschliessenden Funktion ist gebunden,
421
+ # nur nicht hier - `is_global()` unterscheidet das.
422
+ if tab is top or sym.is_global():
423
+ offen.append((tab.get_name(), n))
424
+ for kind in tab.get_children():
425
+ geh(kind)
426
+
427
+ geh(top)
428
+ return offen
429
+
430
+
431
+ def check_werkzeugnamen(root: str) -> None:
432
+ """Pruefung 70 (D-229): Kein Werkzeug des Kerns liest einen Namen, den es nicht gibt."""
433
+ kern = os.path.join(root, KERN)
434
+ if not os.path.isdir(kern):
435
+ return
436
+ apparat = os.path.join(kern, "tests", "erhebungen")
437
+ im_apparat = 0
438
+ for basis, ordner, dateien in os.walk(kern):
439
+ ordner[:] = [o for o in ordner if o != "__pycache__"]
440
+ for name in sorted(dateien):
441
+ if not name.endswith(".py"):
442
+ continue
443
+ pfad = os.path.join(basis, name)
444
+ rel = os.path.relpath(pfad, root).replace(os.sep, "/")
445
+ if basis == apparat:
446
+ im_apparat += 1
447
+ try:
448
+ with open(pfad, encoding="utf-8") as f:
449
+ quelle = f.read()
450
+ except (OSError, UnicodeDecodeError) as e:
451
+ err(f"{rel}: nicht lesbar ({e}) - ein Werkzeug des Kerns, das sich "
452
+ f"nicht lesen laesst, laeuft auch nicht (D-229)")
453
+ continue
454
+ try:
455
+ offen = _p70_offene_namen(quelle, name)
456
+ except SyntaxError as e:
457
+ err(f"{rel}: laedt nicht - {e.msg} (Zeile {e.lineno}). Ein Werkzeug "
458
+ f"des Kerns, das der Interpreter nicht uebersetzt, ist tot, und "
459
+ f"es faellt erst an dem Tag auf, an dem es gebraucht wird (D-229)")
460
+ continue
461
+ for bereich, offener in offen:
462
+ wo = "im Modulrumpf" if bereich == name else f"in `{bereich}`"
463
+ err(f"{rel}: der Name `{offener}` wird {wo} gelesen und nirgends "
464
+ f"gebunden - weder als Zuweisung noch als Import, Parameter "
465
+ f"oder eingebauter Name. Das ist ein NameError, der auf seinen "
466
+ f"Lauf wartet; genau so war `stand-b4.py` seit dem Umzug nach "
467
+ f"D-222 tot (D-229)")
468
+ # DER ANKER, UND ER HAENGT AM MESSAPPARAT, NICHT AM KERN. Ein Anker `keine
469
+ # einzige .py-Datei im Kern` waere durch Konstruktion nie erreichbar: Dieses
470
+ # Skript ist selbst eine, und ohne es laeuft keine Pruefung. Eine Null durch
471
+ # Konstruktion sieht aus wie eine gemessene Null (0.59.1). Erreichbar - und der
472
+ # Gegenstand, um den es geht - ist der Messapparat: Steht seine Ablage und ist
473
+ # kein Werkzeug mehr darin, hat diese Pruefung den Anlass verloren, aus dem sie
474
+ # entstanden ist, und bestuende leise.
475
+ if os.path.isdir(apparat) and im_apparat == 0:
476
+ err(f"{KERN}/tests/erhebungen/: kein einziges Werkzeug geprueft - Pruefung "
477
+ f"70 hat den Gegenstand verloren, aus dem sie entstanden ist; sie "
478
+ f"bestuende sonst leise (D-23, D-229)")
479
+
480
+
481
+ # --- Pruefung 71: Kein Traeger des Kerns nennt einen Arbeitsplatz -------------------
482
+ #
483
+ # ANLASS, UND ER IST GEMESSEN. Am 2026-09-21, beim Bauen der Dossiers des Nachlaufs,
484
+ # brach `dossier-b4.py` ab - und im selben Blick fiel auf, was in seiner Zeile 33 stand:
485
+ #
486
+ # KERN = os.path.join(r"C:\Users\<konto>\Documents\devpacks\koolie", ...)
487
+ #
488
+ # Neun Werkzeuge des Messapparats fuehrten einen Pfad dieses Arbeitsplatzes, acht davon
489
+ # mit dem Ziel `...\devpacks\test-devin-framework`. Solange der Apparat NEBEN dem
490
+ # Repositorium lag, stand das in einer unversionierten Ablage. Mit D-222 ist er
491
+ # HINEINgewandert und hat die Pfade mitgebracht - in dasselbe Repositorium, fuer das
492
+ # `0.78.1` eigens `UEBERGABE.local.md` eingefuehrt hat, weil eine Uebergabe mit
493
+ # Servername und Konto den Validator mit drei Fehlern und drei Warnungen beantwortet.
494
+ #
495
+ # Wer einen Apparat umzieht, zieht seine Arbeitsplatzpfade mit um - und
496
+ # veroeffentlicht sie, ohne es zu entscheiden.
497
+ #
498
+ # WARUM KEINE DER SIEBZIG ES SAH. Pruefung 6 kennt Secret-Muster, E-Mail-Adressen,
499
+ # IP-Adressen, interne Hostnamen und URLs ausserhalb der Allowlist. Ein Pfad in ein
500
+ # Benutzerprofil ist nichts davon - und er traegt trotzdem den Namen eines Menschen.
501
+ #
502
+ # WAS GEPRUEFT WIRD, UND WARUM SO. Ein absoluter Pfad in ein Benutzerprofil, dessen
503
+ # Kontosegment KEIN Platzhalter ist. `<KONTO>`, `%USERNAME%` und `$HOME` laufen durch -
504
+ # sie nennen niemanden. Eine Zeile mit der Marke `SYNTHETISCH` laeuft ebenso durch:
505
+ # Dieselbe Bauform wie das Feld `_uebererfasst` von Pruefung 68 - wer einen solchen
506
+ # Pfad braucht, sagt es in derselben Zeile, statt dass die Pruefung raet.
507
+ #
508
+ # GRENZE, UND SIE STEHT HIER: DER BESTAND DER AUFZEICHNUNGEN IST AUSGENOMMEN, NICHT DIE
509
+ # GATTUNG (seit 1.20.3, D-508, `K-85`). `tests/protocols/` und
510
+ # `governance/change-requests/` halten fest, WO gemessen wurde; ein Protokoll, das man
511
+ # umschreibt, ist keines mehr (D-141). Zehn von ihnen tragen den Kontonamen des Owners
512
+ # weiter, und dabei bleibt es - der Name steht nach D-323 ohnehin im Lizenzhinweis.
513
+ # Bis 1.20.2 nahm die Pruefung aber die ganzen beiden Ordner aus und liess damit jede
514
+ # KUENFTIGE Aufzeichnung ungeprueft. Seither ist die Ausnahme eine geschlossene Liste:
515
+ # Wer eine neue Aufzeichnung schreibt, schreibt `<konto>` oder die Marke.
516
+ P71_MUSTER = re.compile(
517
+ r"(?:[A-Za-z]:[\\/]{1,2}Users|/home|/Users)[\\/]{1,2}([A-Za-z0-9._-]+)")
518
+ P71_AUSNAHME_ORDNER = (f"{KERN}/tests/protocols/",
519
+ f"{KERN}/governance/change-requests/")
520
+ P71_BESTAND = frozenset(f"{KERN}/{rel}" for rel in (
521
+ "governance/change-requests/CR-2026-076-erster-sitzungstest.md",
522
+ "governance/change-requests/CR-2026-077-sitzungstest-schranken.md",
523
+ "tests/protocols/2026-09-11-erhebungen-K21-K26.md",
524
+ "tests/protocols/2026-09-13-B06-gegenpruefung.md",
525
+ "tests/protocols/2026-09-17-sitzungstest-pi-ds.md",
526
+ "tests/protocols/2026-09-17-sitzungstest-schranken.md",
527
+ "tests/protocols/2026-09-18-sitzungstest-5.md",
528
+ "tests/protocols/2026-09-18-sitzungstest-ne-sc.md",
529
+ "tests/protocols/2026-09-18-sitzungstest-pi-ds-2.md",
530
+ "tests/protocols/2026-09-19-testblaetter-buendel-1.md"))
531
+ P71_MARKE = "SYNTHETISCH"
532
+ # Die Selbstprobe des Musters: Ohne sie koennte ein Ausdruck, der nichts mehr trifft,
533
+ # still bestehen - eine Null durch Konstruktion sieht aus wie eine gemessene Null
534
+ # (0.59.1). Der Anker haengt deshalb am MUSTER, nicht am Bestand: Der Bestand kann
535
+ # nicht verschwinden, solange dieses Skript selbst im Kern liegt.
536
+ P71_SELBSTPROBE = ("C:" + chr(92) + "Users" + chr(92) + "kontoname" + chr(92) + "x", # SYNTHETISCH
537
+ "/home/kontoname/x", # SYNTHETISCH
538
+ "/Users/kontoname/x") # SYNTHETISCH
539
+
540
+
541
+ def check_arbeitsplatzpfad(root: str) -> None:
542
+ """Pruefung 71 (D-231): Kein Traeger des Kerns nennt einen Arbeitsplatz."""
543
+ kern = os.path.join(root, KERN)
544
+ if not os.path.isdir(kern):
545
+ return
546
+ for probe in P71_SELBSTPROBE:
547
+ if not P71_MUSTER.search(probe):
548
+ err(f"Pruefung 71: das eigene Muster trifft {probe!r} nicht mehr - sie "
549
+ f"haette ihren Gegenstand verloren und bestuende leise (D-23, D-231)")
550
+ return
551
+ for pfad in iter_text_files(root):
552
+ rel = os.path.relpath(pfad, root).replace(os.sep, "/")
553
+ if not rel.startswith(f"{KERN}/"):
554
+ continue
555
+ if rel.startswith(P71_AUSNAHME_ORDNER) and rel in P71_BESTAND:
556
+ continue
557
+ text = read(pfad)
558
+ for zeile in text.splitlines():
559
+ if P71_MARKE in zeile:
560
+ continue
561
+ for m in P71_MUSTER.finditer(zeile):
562
+ konto = m.group(1)
563
+ # Ein Platzhalter nennt niemanden. Die drei Schreibweisen, die
564
+ # dieses Repositorium und die beiden Betriebssysteme kennen.
565
+ davor = zeile[:m.start(1)]
566
+ if (konto.startswith(("<", "%", "$"))
567
+ or davor.endswith(("<", "%", "$", "{"))
568
+ or konto.upper() in ("USER", "USERNAME", "USERPROFILE")):
569
+ continue
570
+ err(f"{rel}: der Pfad {m.group(0)!r} nennt ein Benutzerprofil mit "
571
+ f"dem Kontosegment {konto!r}. Ein Arbeitsplatz gehoert nicht in "
572
+ f"den Kern - der Ort wird gesagt (LW_ERHEBUNG, LW_UEBUNG) oder "
573
+ f"abgeleitet (ablage.WURZEL). Ein Platzhalter oder die Marke "
574
+ f"{P71_MARKE} in derselben Zeile laeuft durch (D-231)")
575
+
576
+
577
+ # --- Pruefung 76: Die Lage des Kerns steht an vier Stellen - und ueberall gleich ----
578
+ #
579
+ # ANLASS (D-299). Bis 0.87.0 war der Kern EIN Verzeichnissegment, und vier Werkzeuge
580
+ # haben <CORE_DIR> deshalb mit os.path.basename() aus dem eigenen Ort gebunden -
581
+ # install.py, build/assemble.py, dieser Validator und der Schutz-Hook. In install.py
582
+ # stand dabei woertlich, die Zeile stehe dort, "damit eine spaetere Umbenennung nur
583
+ # eine Stelle beruehrt". Sie haette die Umbenennung nicht ueberlebt: os.path.basename
584
+ # liefert fuer ".koolie/core" den Wert "core".
585
+ #
586
+ # WARUM DAS KEIN VALIDATORFEHLER GEWESEN WAERE: Dieser Validator bindet <CORE_DIR> an
587
+ # derselben Stelle auf dieselbe Weise. Er haette denselben falschen Wert eingesetzt wie
588
+ # install.py - und deshalb nichts gemeldet. Zwei Stellen, die einander decken (0.57.0),
589
+ # diesmal ueber Werkzeuggrenzen hinweg.
590
+ #
591
+ # ZWEI GEGENSTAENDE, und sie sind dieselbe Frage aus zwei Richtungen:
592
+ # (1) Alle vier Angaben der Lage tragen denselben Wert.
593
+ # (2) Keine von ihnen leitet ihn ueber os.path.basename ab.
594
+ # Ohne (2) waere (1) erfuellbar, indem alle vier denselben Fehler machen - und genau
595
+ # das war der Zustand bis 0.87.0.
596
+ #
597
+ # WARUM VIER STELLEN UND NICHT EINE: Der Schutz-Hook darf nichts aus dem Kern
598
+ # importieren - er muss auch dann entscheiden, wenn eine Installation unvollstaendig
599
+ # ist (D-31). ablage.py laeuft ausserhalb des Kerns gegen fremde Messbaeume. Die
600
+ # Doppelung ist gewollt; diese Pruefung ist ihr Preis.
601
+ P76_WERT_RE = re.compile(r"^(?:CORE_REL|KERN)\s*=\s*\"([^\"]+)\"", re.M)
602
+
603
+ P76_STELLEN = (
604
+ "clientmap.py",
605
+ "tests/scripts/pruefungen/gemeinsam.py",
606
+ "tests/scripts/hook-check-secrets.py",
607
+ "tests/erhebungen/ablage.py",
608
+ )
609
+
610
+ P76_BASENAME_RE = re.compile(r"<CORE_DIR>\"\]\s*=\s*os\.path\.basename")
611
+
612
+
613
+ def check_kernlage(root: str) -> None:
614
+ """Pruefung 76 (D-299): Die Lage des Kerns steht ueberall gleich - und nirgends
615
+ als basename eines Pfades."""
616
+ if not P76_WERT_RE.search("CORE_REL = \"x/y\"\n"):
617
+ err("Prüfung 76: das eigene Muster liest keine Lageangabe mehr – sie bestünde "
618
+ "leise, während die vier Werkzeuge auseinanderlaufen (D-23)")
619
+ return
620
+ werte = {}
621
+ for rel in P76_STELLEN:
622
+ pfad = os.path.join(root, KERN, *rel.split("/"))
623
+ if not os.path.isfile(pfad) and nicht_geliefert(root, f"{KERN}/{rel}"):
624
+ hinweis(f"Prüfung 76 hält die Kernlage an drei statt vier Stellen: "
625
+ f"{KERN}/{rel} gehört zur Nachweisschicht und ist nicht geliefert (D-367)")
626
+ continue
627
+ if not os.path.isfile(pfad):
628
+ err(f"{KERN}/{rel}: fehlt – Prüfung 76 hätte dort einen ihrer vier "
629
+ f"Gegenstände verloren (D-23)")
630
+ continue
631
+ text = read(pfad)
632
+ treffer = P76_WERT_RE.search(text)
633
+ if not treffer:
634
+ err(f"{KERN}/{rel}: führt keine Angabe der Kernlage mehr. Prüfung 76 hat "
635
+ f"dort ihren Anker verloren und bestünde sonst leise (D-23)")
636
+ else:
637
+ werte[rel] = treffer.group(1)
638
+ if P76_BASENAME_RE.search(text):
639
+ err(f"{KERN}/{rel}: bindet <CORE_DIR> über os.path.basename(). Der Kern "
640
+ f"liegt seit 0.88.0 zwei Segmente tief; basename() liefert davon nur "
641
+ f"das letzte, und jede gerenderte Regeldatei trüge einen Pfad, den es "
642
+ f"nicht gibt – ohne dass eine Prüfung es meldete (D-299)")
643
+ if len(set(werte.values())) > 1:
644
+ zeilen = ", ".join(f"{r} = '{w}'" for r, w in sorted(werte.items()))
645
+ err(f"Die Lage des Kerns steht in {len(werte)} Werkzeugen und nicht überall "
646
+ f"gleich: {zeilen}. Eine Installation läge dann je nach aufrufendem "
647
+ f"Werkzeug an einem anderen Ort (D-299)")
648
+
649
+
650
+ # ---------------------------------------------------------------------------
651
+ # Pruefung 104: Die Verdrahtung der Pruefwerkzeuge (CR-2026-161, D-481)
652
+ # ---------------------------------------------------------------------------
653
+ #
654
+ # ANLASS. Seit 1.19.1 liegen die Pruefungen in einem Paket, und der Einstieg ruft sie;
655
+ # die Sonden liegen in Teilen, die der Einstieg des Sondenlaufs laedt (D-479). Eine
656
+ # Pruefung, die in ein Modul wandert und von niemandem gerufen wird, laeuft nie - und
657
+ # der Lauf endet mit "0 Fehler". Ein Sondenteil, den niemand laedt, meldet seine
658
+ # Einheiten nie an - und der Sondenlauf endet mit "alle bestanden". Beides ist die
659
+ # Null durch Konstruktion (0.59.1).
660
+ #
661
+ # WAS SIE PRUEFT, AM SYNTAXBAUM, OHNE ETWAS AUSZUFUEHREN:
662
+ # (1) Jede Funktion check_* der obersten Ebene eines Moduls unter pruefungen/ wird
663
+ # gerufen - von main() im Einstieg oder von einer anderen Funktion des Pakets
664
+ # (check_skills ruft check_skills_in) -, und main() ruft keine zweimal und keine,
665
+ # die es nicht gibt.
666
+ # (2) Jeder Teil unter sonden/ wird vom Einstieg des Sondenlaufs geladen, und zwar in
667
+ # der Reihenfolge seiner Nummer: Die Reihenfolge des Ladens ist die der Ausgabe
668
+ # (D-49).
669
+ #
670
+ # GRENZE: Sie prueft die Verdrahtung, nicht, was eine Pruefung tut - das tun ihre
671
+ # Sonden. Sie sieht nur Funktionen mit dem Praefix check_ und Teile mit dem Praefix
672
+ # teil; eine Pruefung unter anderem Namen faellt durch.
673
+ P104_VALIDATOR = "tests/scripts/validate-framework.py"
674
+ P104_SONDEN = "tests/scripts/probe-pruefungen.py"
675
+ P104_TEIL_RE = re.compile(r"^teil(\d+)_\w+\.py$")
676
+
677
+
678
+ def _p104_baum(root: str, rel: str):
679
+ """Der Syntaxbaum einer Datei unter dem Kern - oder None, dann ist gemeldet."""
680
+ pfad = os.path.join(root, KERN, *rel.split("/"))
681
+ if not os.path.isfile(pfad):
682
+ err(f"{KERN}/{rel}: fehlt - Pruefung 104 haelt dort die Verdrahtung der "
683
+ f"Pruefwerkzeuge (D-481)")
684
+ return None
685
+ try:
686
+ return ast.parse(read(pfad))
687
+ except SyntaxError as e:
688
+ err(f"{KERN}/{rel}: laedt nicht - {e.msg} (Zeile {e.lineno}); Pruefung 104 kann "
689
+ f"die Verdrahtung dort nicht lesen (D-481)")
690
+ return None
691
+
692
+
693
+ def _p104_aufrufe(knoten) -> dict:
694
+ """{Name: Anzahl} der Aufrufe von check_* unterhalb eines Knotens."""
695
+ anzahl: dict = {}
696
+ for n in ast.walk(knoten):
697
+ if isinstance(n, ast.Call) and isinstance(n.func, ast.Name) and \
698
+ n.func.id.startswith("check_"):
699
+ anzahl[n.func.id] = anzahl.get(n.func.id, 0) + 1
700
+ return anzahl
701
+
702
+
703
+ def check_verdrahtung(root: str) -> None:
704
+ """Pruefung 104 (D-481): Jede Pruefung wird gerufen, jeder Sondenteil geladen."""
705
+ # --- Gegenstand 1: die Pruefungen -------------------------------------------------
706
+ einstieg = _p104_baum(root, P104_VALIDATOR)
707
+ paket = PAKET_JE_SKRIPT[P104_VALIDATOR]
708
+ ordner = os.path.join(root, KERN, *paket.split("/"))
709
+ definiert, im_paket = {}, {}
710
+ for name in sorted(os.listdir(ordner)) if os.path.isdir(ordner) else []:
711
+ if not name.endswith(".py"):
712
+ continue
713
+ modul = _p104_baum(root, f"{paket}/{name}")
714
+ if modul is None:
715
+ continue
716
+ for n in modul.body:
717
+ if isinstance(n, ast.FunctionDef) and n.name.startswith("check_"):
718
+ definiert[n.name] = f"{paket}/{name}"
719
+ for name_, zahl in _p104_aufrufe(modul).items():
720
+ im_paket[name_] = im_paket.get(name_, 0) + zahl
721
+ haupt = None if einstieg is None else next(
722
+ (n for n in einstieg.body if isinstance(n, ast.FunctionDef) and n.name == "main"),
723
+ None)
724
+ if not definiert or haupt is None:
725
+ err(f"Pruefung 104: {'keine Funktion check_* unter ' + KERN + '/' + paket + '/' if not definiert else 'keine Funktion main() in ' + KERN + '/' + P104_VALIDATOR} - "
726
+ f"sie hat ihren Gegenstand verloren und bestuende sonst leise (D-23, D-481)")
727
+ else:
728
+ in_main = _p104_aufrufe(haupt)
729
+ for name, wo in sorted(definiert.items()):
730
+ if not in_main.get(name) and not im_paket.get(name):
731
+ err(f"{KERN}/{wo}: {name}() wird von niemandem gerufen - weder von main() "
732
+ f"in {P104_VALIDATOR} noch im Paket. Eine Pruefung, die niemand ruft, "
733
+ f"laeuft nie, und der Lauf endet trotzdem mit 0 Fehlern (D-481)")
734
+ elif in_main.get(name, 0) > 1:
735
+ err(f"{KERN}/{P104_VALIDATOR}: main() ruft {name}() {in_main[name]}mal - "
736
+ f"jede Pruefung laeuft genau einmal, sonst meldet sie jeden Befund "
737
+ f"doppelt (D-481)")
738
+ for name in sorted(set(in_main) - set(definiert)):
739
+ err(f"{KERN}/{P104_VALIDATOR}: main() ruft {name}(), und kein Modul unter "
740
+ f"{paket}/ definiert sie (D-481)")
741
+
742
+ # --- Gegenstand 2: die Sondenteile ------------------------------------------------
743
+ einstieg = _p104_baum(root, P104_SONDEN)
744
+ paket = PAKET_JE_SKRIPT[P104_SONDEN]
745
+ ordner = os.path.join(root, KERN, *paket.split("/"))
746
+ teile = sorted((n[:-3] for n in (os.listdir(ordner) if os.path.isdir(ordner) else [])
747
+ if P104_TEIL_RE.match(n)),
748
+ key=lambda t: int(P104_TEIL_RE.match(t + ".py").group(1)))
749
+ if not teile:
750
+ err(f"Pruefung 104: kein Sondenteil teil<Nummer>_*.py unter {KERN}/{paket}/ - sie "
751
+ f"hat ihren Gegenstand verloren und bestuende sonst leise (D-23, D-481)")
752
+ return
753
+ if einstieg is None:
754
+ return
755
+ geladen = [a.name for n in einstieg.body if isinstance(n, ast.ImportFrom)
756
+ and n.module == os.path.basename(paket) for a in n.names]
757
+ for teil in teile:
758
+ if teil not in geladen:
759
+ err(f"{KERN}/{paket}/{teil}.py: wird von {P104_SONDEN} nicht geladen - seine "
760
+ f"Einheiten melden sich nie an, und der Sondenlauf endet trotzdem mit "
761
+ f"'alle bestanden' (D-481)")
762
+ for teil in geladen:
763
+ if teil not in teile:
764
+ err(f"{KERN}/{P104_SONDEN}: laedt {teil}, und unter {paket}/ gibt es keinen "
765
+ f"Teil dieses Namens (D-481)")
766
+ reihe = [t for t in geladen if t in teile]
767
+ if reihe != [t for t in teile if t in reihe]:
768
+ err(f"{KERN}/{P104_SONDEN}: laedt die Sondenteile nicht in der Reihenfolge ihrer "
769
+ f"Nummer. Die Reihenfolge des Ladens ist die Reihenfolge der Ausgabe, und die "
770
+ f"ist die zeilengleiche Abnahmeform (D-49, D-481)")
771
+
772
+
773
+ # Pruefung 107: Die Wirksamkeitsprobe haelt ihre Gegenfaelle (K-195, D-488, D-490).
774
+ #
775
+ # ANLASS. Die Hook-Vorpruefung des Messapparats hat seit 1.19.0 jeden Baum bestanden -
776
+ # auch einen ohne Hook-Skript: Unter Windows loeste 'cmd' $CLAUDE_PROJECT_DIR nicht auf,
777
+ # Python endete mit Exit 2, und Exit 2 galt als Sperre (D-490). Eine Probe, die auch das
778
+ # Fehlen ihres Gegenstands bestaetigt, ist die Null durch Konstruktion. Die Pruefung baut
779
+ # deshalb einen Wegwerfbaum mit der erzeugten Hook-Konfiguration von claude-code und
780
+ # verlangt von wirksamkeit.pruefe_hook drei Urteile:
781
+ # (a) intakter Baum: keine fehlende Muss-Kontrolle;
782
+ # (b) ohne Hook-Skript: H3 und H4 fehlen - Exit 2 ohne Sperrhinweis ist keine Sperre;
783
+ # (c) Matcher ohne die Klasse mcp: H2 fehlt.
784
+ # GRENZE: der Hook-Teil der Probe am Pack claude-code. Startmeldung und Vertrauen braucht
785
+ # einen Client und sind an der Messung belegt (Protokoll 2026-09-29-schutzschicht).
786
+ def check_wirksamkeitsprobe(root: str) -> None:
787
+ """Pruefung 107 (K-195, D-488, D-490): Die Probe unterscheidet Wirkung von Fehlen."""
788
+ import importlib.util
789
+ import shutil
790
+ import tempfile
791
+ kern = os.path.join(root, *KERN.split("/"))
792
+ modul = os.path.join(kern, "wirksamkeit.py")
793
+ skript = os.path.join(kern, "tests", "scripts", "hook-check-secrets.py")
794
+ manifest = os.path.join(kern, "clients", "claude-code", "manifest.json")
795
+ if not all(os.path.isfile(p) for p in (modul, skript, manifest)):
796
+ return
797
+ try:
798
+ cm = _clientmap(root)
799
+ spec = importlib.util.spec_from_file_location("koolie_wirksamkeit_p107", modul)
800
+ wk = importlib.util.module_from_spec(spec)
801
+ spec.loader.exec_module(wk)
802
+ man = json.loads(read(manifest))
803
+ quelle = cm.load_source(kern, "hooks.json")
804
+ hooks = cm._hooks_objekt(quelle, man)
805
+ verben = [v for e in json.loads(quelle).get("PreToolUse", []) for v in e.get("on", [])
806
+ if any(h.get("enforcing") for h in e.get("hooks", []))]
807
+ except Exception as fehler: # noqa: BLE001 - jeder Ladefehler ist der Befund
808
+ err(f"Pruefung 107: Die Wirksamkeitsprobe laesst sich nicht laden "
809
+ f"({type(fehler).__name__}) - install.py --probe liefe nicht (K-195)")
810
+ return
811
+
812
+ def urteil(ohne_skript: bool = False, matcher_ohne_mcp: bool = False) -> set:
813
+ with tempfile.TemporaryDirectory(prefix="koolie-p107-") as w:
814
+ ziel = os.path.join(w, *KERN.split("/"), "tests", "scripts")
815
+ os.makedirs(ziel)
816
+ if not ohne_skript:
817
+ shutil.copy2(skript, ziel)
818
+ pack = os.path.join(w, *KERN.split("/"), "clients", "claude-code")
819
+ os.makedirs(pack)
820
+ shutil.copy2(manifest, pack)
821
+ h = json.loads(json.dumps(hooks))
822
+ if matcher_ohne_mcp:
823
+ for e in h.get("PreToolUse", []):
824
+ e["matcher"] = "|".join(x for x in e["matcher"].split("|")
825
+ if not x.startswith("mcp"))
826
+ os.makedirs(os.path.join(w, ".claude"))
827
+ with open(os.path.join(w, ".claude", "settings.json"), "w", encoding="utf-8") as fh:
828
+ json.dump({"hooks": h}, fh)
829
+ with open(os.path.join(w, "README.md"), "w", encoding="utf-8") as fh:
830
+ fh.write("# Wegwerfbaum\n")
831
+ erg = wk.Ergebnis()
832
+ wk.pruefe_hook(w, man, verben, erg)
833
+ return {k.split()[0] for _, k, _ in erg.verletzt}
834
+
835
+ intakt = urteil()
836
+ if intakt:
837
+ err(f"Pruefung 107: Die Wirksamkeitsprobe meldet an einem intakten Baum fehlende "
838
+ f"Kontrollen ({', '.join(sorted(intakt))}) - sie truege keinen Befund (K-195)")
839
+ ohne = urteil(ohne_skript=True)
840
+ if not {"H3", "H4"} <= ohne:
841
+ err(f"Pruefung 107: Die Wirksamkeitsprobe besteht einen Baum ohne Hook-Skript "
842
+ f"(gemeldet: {', '.join(sorted(ohne)) or 'nichts'}) - ein Exit 2 ohne "
843
+ f"Sperrhinweis ist keine Sperre (D-490)")
844
+ alt = urteil(matcher_ohne_mcp=True)
845
+ if "H2" not in alt:
846
+ err("Pruefung 107: Die Wirksamkeitsprobe erkennt einen Matcher ohne die "
847
+ "Werkzeugklasse mcp nicht - ein veralteter Matcher fiele nicht auf (K-184, D-488)")
848
+
849
+
850
+ # --- Pruefung 112: Die Paketquellen und das Banner (CR-2026-168, D-518 bis D-521, K-155) --
851
+ #
852
+ # ANLASS, GEMESSEN (2026-09-30): Eine Paketquelle legt Koolie auf den Rechner, ins Projekt
853
+ # kommt es erst durch den Befehl `koolie` - und nur dieser Aufruf laeuft bei jeder
854
+ # Paketquelle im Terminal des Nutzers. pip fuehrt beim Installieren eines Wheels nichts
855
+ # aus, npm verschluckt die Ausgabe eines Installationsskripts, Chocolatey gibt ihm kein
856
+ # Terminal. Das Banner, das der Owner auf diesen Wegen verlangt, steht deshalb im Befehl
857
+ # (D-519), und die Pakete entstehen aus dem Release-Archiv mit paketquellen/bauen.py
858
+ # (D-520). Beides kann still brechen: ein Befehl, der install.py ohne Banner startet, und
859
+ # ein Bau, dessen Paket auf eine Datei zeigt, die es nicht traegt.
860
+ #
861
+ # GEPRUEFT, nur im Quellrepositorium (Projekte bekommen paketquellen/ nicht):
862
+ # (a) die vier Dateien unter paketquellen/ liegen da;
863
+ # (b) der Befehl: `--version` nennt die Version aus VERSION; ueber eine Pipe steht vor
864
+ # der Ausgabe von install.py die Textvariante des Banners mit dieser Version; mit
865
+ # KOOLIE_NO_BANNER=1 steht sie nicht da; ohne Argumente nimmt der Dialog das
866
+ # Verzeichnis des Aufrufs mit Enter als Projekt (seit 1.24.1, D-532);
867
+ # (c) der Bau: bauen.py baut aus einem Wegwerfarchiv mit den Dateien unter
868
+ # paketquellen/ ohne Befund - seine Nachpruefung haelt Dateimenge, Version, RECORD,
869
+ # die Ziele der Befehle, das Fehlen eines npm-Installationsskripts und die
870
+ # Pruefsumme in beiden Manifesten; seit 1.24.0 auch die Beschreibung fuer PyPI und
871
+ # npm ohne relativen Link (D-528) - und dasselbe fuer die Vorabversion --vorab 1 (D-529).
872
+ # GRENZE: Ob eine Paketquelle dem Befehl ein Terminal gibt, prueft keine Pruefung - das ist
873
+ # gemessen (Protokoll 2026-09-30-paketquellen: pip, uv, npm, Scoop). Die Homebrew-Formel ist
874
+ # gebaut, nicht gemessen. Die Veroeffentlichung erreicht keine Pruefung (D-521); ob die
875
+ # Paketseite die Beschreibung darstellt, ist gemessen (Protokoll 2026-10-01-erste-veroeffentlichung).
876
+ P112_DATEIEN = ("paketquellen/bauen.py", "paketquellen/koolie_befehl.py",
877
+ "paketquellen/koolie.cmd", "paketquellen/npm/koolie.js")
878
+
879
+
880
+ def _p112_befehl(root: str, *argv: str, ohne_banner: bool = False, cwd: str | None = None,
881
+ eingabe: str | None = None) -> str:
882
+ import subprocess
883
+ umgebung = {k: v for k, v in os.environ.items()
884
+ if k not in ("KOOLIE_NO_BANNER", "NO_COLOR", "COLUMNS")}
885
+ umgebung["PYTHONIOENCODING"] = "utf-8"
886
+ if ohne_banner:
887
+ umgebung["KOOLIE_NO_BANNER"] = "1"
888
+ p = subprocess.run([sys.executable, os.path.join(root, "paketquellen", "koolie_befehl.py"),
889
+ *argv], capture_output=True, encoding="utf-8", errors="replace",
890
+ env=umgebung, timeout=120, cwd=cwd, input=eingabe)
891
+ return p.stdout or ""
892
+
893
+
894
+ def check_paketquellen(root: str) -> None:
895
+ """Pruefung 112 (D-519, D-520, K-155): Der Befehl gibt das Banner aus, der Bau traegt."""
896
+ if not ist_quellrepositorium(root):
897
+ return
898
+ fehlend = [rel for rel in P112_DATEIEN if not os.path.isfile(os.path.join(root, *rel.split("/")))]
899
+ if fehlend:
900
+ err(f"{fehlend[0]}: fehlt - ohne diese Datei baut keine Paketquelle den Befehl "
901
+ f"'koolie' (Pruefung 112, D-520)")
902
+ return
903
+ version = read(os.path.join(root, *KERN.split("/"), "VERSION")).strip()
904
+ try:
905
+ aus = _p112_befehl(root, "--version")
906
+ if aus.strip() != f"koolie {version}":
907
+ err(f"paketquellen/koolie_befehl.py: '--version' liefert {aus.strip()[:40]!r} statt "
908
+ f"'koolie {version}' (Pruefung 112)")
909
+ aus = _p112_befehl(root, "--help")
910
+ b, u = aus.find(f"KOOLIE v{version}"), aus.find("usage:")
911
+ if b < 0 or u < 0 or b > u:
912
+ err("paketquellen/koolie_befehl.py: startet install.py ohne das Banner davor - auf "
913
+ "den Wegen der Paketquellen erschiene es nicht (Pruefung 112, D-519)")
914
+ aus = _p112_befehl(root, "--help", ohne_banner=True)
915
+ if "KOOLIE v" in aus or "usage:" not in aus:
916
+ err("paketquellen/koolie_befehl.py: KOOLIE_NO_BANNER=1 schaltet das Banner nicht ab "
917
+ "oder unterdrueckt install.py mit (Pruefung 112, D-506)")
918
+ import tempfile as _tf
919
+ with _tf.TemporaryDirectory(prefix="koolie-p112-hier-") as hier:
920
+ aus = _p112_befehl(root, ohne_banner=True, cwd=hier, eingabe="\nq\n")
921
+ if "Welcher KI-Client" not in aus:
922
+ err("paketquellen/koolie_befehl.py: der Dialog nimmt das Verzeichnis des Aufrufs "
923
+ "nicht mit Enter als Projekt - uvx, pipx run und npx starten ihn dort "
924
+ "(Pruefung 112, D-532)")
925
+ except Exception as fehler: # noqa: BLE001 - jeder Startfehler ist der Befund
926
+ err(f"paketquellen/koolie_befehl.py: laesst sich nicht starten ({type(fehler).__name__}) "
927
+ f"(Pruefung 112)")
928
+ import contextlib
929
+ import importlib.util
930
+ import io
931
+ import tarfile
932
+ import tempfile
933
+ with tempfile.TemporaryDirectory(prefix="koolie-p112-") as w:
934
+ archiv = os.path.join(w, f"koolie-{version}.tar.gz")
935
+ with tarfile.open(archiv, "w:gz") as tf:
936
+ for rel in P112_DATEIEN + (f"{KERN}/VERSION", "LICENSE", "README.en.md"):
937
+ tf.add(os.path.join(root, *rel.split("/")), arcname=f"koolie-{version}/{rel}")
938
+ # einmal die Version der Marke, einmal die Vorabversion fuer TestPyPI (D-529)
939
+ for art, zusatz in (("", []), (", als Vorabversion gebaut", ["--vorab", "1"])):
940
+ puffer = io.StringIO()
941
+ try:
942
+ spec = importlib.util.spec_from_file_location(
943
+ "koolie_bauen_p112", os.path.join(root, "paketquellen", "bauen.py"))
944
+ bauen = importlib.util.module_from_spec(spec)
945
+ spec.loader.exec_module(bauen)
946
+ with contextlib.redirect_stdout(puffer), contextlib.redirect_stderr(puffer):
947
+ rc = bauen.main(["--archiv", archiv, "--aus", os.path.join(w, "aus"), *zusatz])
948
+ except Exception as fehler: # noqa: BLE001
949
+ rc, puffer = 1, io.StringIO(f"{type(fehler).__name__}: {fehler}")
950
+ if rc != 0:
951
+ text = puffer.getvalue()
952
+ befunde = ([z.strip() for z in text.split("BEFUNDE:", 1)[1].splitlines()
953
+ if z.strip()]
954
+ if "BEFUNDE:" in text else text.strip().splitlines()[-1:])[:3]
955
+ err(f"paketquellen/bauen.py: baut aus einem Wegwerfarchiv nicht ohne Befund{art} "
956
+ f"({' | '.join(befunde)}) (Pruefung 112, D-520)")
957
+ return