core-runtime 0.1.1__py3-none-any.whl

This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
Files changed (962) hide show
  1. api/__init__.py +4 -0
  2. api/cli/__init__.py +10 -0
  3. api/cli/audit_client.py +92 -0
  4. api/cli/census_client.py +77 -0
  5. api/cli/client.py +508 -0
  6. api/cli/coverage_client.py +121 -0
  7. api/cli/daemon_client.py +42 -0
  8. api/cli/fix_client.py +101 -0
  9. api/cli/inspect_client.py +143 -0
  10. api/cli/integration_client.py +42 -0
  11. api/cli/integrity_client.py +45 -0
  12. api/cli/proposals_client.py +101 -0
  13. api/cli/quality_client.py +83 -0
  14. api/cli/refactor_client.py +82 -0
  15. api/cli/sync_client.py +106 -0
  16. api/dependencies.py +37 -0
  17. api/errors.py +74 -0
  18. api/main.py +88 -0
  19. api/v1/__init__.py +4 -0
  20. api/v1/audit_routes.py +302 -0
  21. api/v1/census_routes.py +207 -0
  22. api/v1/coverage_routes.py +352 -0
  23. api/v1/daemon_routes.py +86 -0
  24. api/v1/development_routes.py +70 -0
  25. api/v1/fix_routes.py +428 -0
  26. api/v1/inspect_routes.py +220 -0
  27. api/v1/integration_routes.py +56 -0
  28. api/v1/integrity_routes.py +72 -0
  29. api/v1/knowledge_routes.py +36 -0
  30. api/v1/lint_routes.py +40 -0
  31. api/v1/proposals_routes.py +267 -0
  32. api/v1/quality_routes.py +272 -0
  33. api/v1/refactor_routes.py +225 -0
  34. api/v1/sync_routes.py +261 -0
  35. body/__init__.py +4 -0
  36. body/analyzers/__init__.py +25 -0
  37. body/analyzers/base_analyzer.py +28 -0
  38. body/analyzers/constitutional_path_analyzer.py +63 -0
  39. body/analyzers/file_analyzer.py +211 -0
  40. body/analyzers/knowledge_graph_analyzer.py +86 -0
  41. body/analyzers/prompt_analyzer.py +155 -0
  42. body/analyzers/symbol_extractor.py +280 -0
  43. body/atomic/__init__.py +74 -0
  44. body/atomic/build_tests_action.py +354 -0
  45. body/atomic/check_actions.py +142 -0
  46. body/atomic/crate_ops.py +59 -0
  47. body/atomic/executor.py +470 -0
  48. body/atomic/file_ops.py +153 -0
  49. body/atomic/fix_actions.py +1142 -0
  50. body/atomic/import_resolver.py +200 -0
  51. body/atomic/metadata_ops.py +161 -0
  52. body/atomic/modularity_fix.py +839 -0
  53. body/atomic/modularity_splitter.py +521 -0
  54. body/atomic/proposal_lifecycle_actions.py +171 -0
  55. body/atomic/registry.py +326 -0
  56. body/atomic/remediate_cognitive_role.py +104 -0
  57. body/atomic/sandbox_lifecycle.py +252 -0
  58. body/atomic/split_plan.py +155 -0
  59. body/atomic/sync_actions/__init__.py +22 -0
  60. body/atomic/sync_actions/chunking_helpers.py +218 -0
  61. body/atomic/sync_actions/sync_actions.py +431 -0
  62. body/atomic/test_actions.py +47 -0
  63. body/autonomy/__init__.py +16 -0
  64. body/autonomy/audit_analyzer.py +343 -0
  65. body/autonomy/micro_proposal_executor.py +316 -0
  66. body/crate_processing/canary_executor.py +144 -0
  67. body/evaluators/__init__.py +27 -0
  68. body/evaluators/atomic_actions_evaluator.py +162 -0
  69. body/evaluators/atomic_actions_format.py +45 -0
  70. body/evaluators/atomic_actions_rules.py +278 -0
  71. body/evaluators/base_evaluator.py +67 -0
  72. body/evaluators/clarity_evaluator.py +83 -0
  73. body/evaluators/constitutional_evaluator.py +227 -0
  74. body/evaluators/failure_evaluator.py +136 -0
  75. body/evaluators/performance_evaluator.py +341 -0
  76. body/evaluators/security_evaluator.py +393 -0
  77. body/flows/__init__.py +33 -0
  78. body/flows/executor.py +275 -0
  79. body/flows/registry.py +272 -0
  80. body/flows/result.py +113 -0
  81. body/governance/__init__.py +29 -0
  82. body/governance/body_contracts_service.py +317 -0
  83. body/governance/code_validator.py +118 -0
  84. body/governance/engine_dispatcher.py +128 -0
  85. body/governance/intent_guard.py +592 -0
  86. body/governance/intent_pattern_validators.py +197 -0
  87. body/governance/key_management_service.py +100 -0
  88. body/governance/path_validator.py +187 -0
  89. body/governance/remediation_service.py +263 -0
  90. body/governance/runtime_validator.py +184 -0
  91. body/infrastructure/bootstrap.py +135 -0
  92. body/infrastructure/lifespan.py +85 -0
  93. body/infrastructure/repositories/__init__.py +1 -0
  94. body/infrastructure/repositories/decision_trace_repository.py +210 -0
  95. body/infrastructure/repositories/refusal_repository.py +294 -0
  96. body/introspection/__init__.py +4 -0
  97. body/introspection/capability_discovery_service.py +107 -0
  98. body/introspection/discovery/from_kgb.py +33 -0
  99. body/introspection/discovery/from_source_scan.py +40 -0
  100. body/introspection/discovery/loader.py +62 -0
  101. body/introspection/discovery/registry.py +22 -0
  102. body/introspection/discovery/semantics.py +21 -0
  103. body/introspection/discovery/sync.py +47 -0
  104. body/introspection/drift_detector.py +81 -0
  105. body/introspection/drift_service.py +48 -0
  106. body/introspection/export_vectors.py +133 -0
  107. body/introspection/generate_capability_docs.py +130 -0
  108. body/introspection/generate_correction_map.py +98 -0
  109. body/introspection/graph_analysis_service.py +66 -0
  110. body/introspection/knowledge_graph_service.py +170 -0
  111. body/introspection/semantic_clusterer.py +128 -0
  112. body/introspection/symbol_index_builder.py +244 -0
  113. body/introspection/sync/engine.py +92 -0
  114. body/introspection/sync/scanner.py +56 -0
  115. body/introspection/sync/visitor.py +83 -0
  116. body/introspection/sync_service.py +62 -0
  117. body/invokers/__init__.py +4 -0
  118. body/invokers/capability_invoker.py +4 -0
  119. body/maintenance/command_sync_service.py +73 -0
  120. body/maintenance/dotenv_sync_service.py +99 -0
  121. body/maintenance/idempotency_harness.py +70 -0
  122. body/maintenance/maintenance_service.py +123 -0
  123. body/maintenance/memory_cleanup_service.py +131 -0
  124. body/maintenance/refactor_settings_access.py +274 -0
  125. body/maintenance/scripts/__init__.py +5 -0
  126. body/maintenance/scripts/context_export.py +278 -0
  127. body/maintenance/scripts/vector_verify.py +73 -0
  128. body/maintenance/sync_vectors.py +338 -0
  129. body/models/__init__.py +4 -0
  130. body/project_lifecycle/__init__.py +4 -0
  131. body/project_lifecycle/bootstrap_service.py +157 -0
  132. body/project_lifecycle/definition_service.py +264 -0
  133. body/project_lifecycle/integration_service.py +113 -0
  134. body/project_lifecycle/scaffolding_service.py +187 -0
  135. body/quality/coverage_analyzer.py +177 -0
  136. body/repositories/__init__.py +4 -0
  137. body/self_healing/atomic_actions_fixer.py +113 -0
  138. body/self_healing/body_ui_fixer.py +193 -0
  139. body/self_healing/capability_parser.py +65 -0
  140. body/self_healing/code_style_service.py +51 -0
  141. body/self_healing/complexity_filter.py +70 -0
  142. body/self_healing/docstring_service.py +345 -0
  143. body/self_healing/duplicate_id_service.py +407 -0
  144. body/self_healing/duplicates_service.py +165 -0
  145. body/self_healing/handlers/__init__.py +1 -0
  146. body/self_healing/handlers/id_assignment_handler.py +201 -0
  147. body/self_healing/handlers/import_sorting_handler.py +181 -0
  148. body/self_healing/header_service.py +308 -0
  149. body/self_healing/id_tagging_service.py +227 -0
  150. body/self_healing/knowledge_consolidation_service.py +80 -0
  151. body/self_healing/logging_service.py +292 -0
  152. body/self_healing/owner_tagging_service.py +5 -0
  153. body/self_healing/placeholder_fixer_service.py +27 -0
  154. body/self_healing/prune_private_capabilities.py +144 -0
  155. body/self_healing/purge_legacy_tags_service.py +146 -0
  156. body/self_healing/remediation_models.py +238 -0
  157. body/self_healing/test_context/__init__.py +10 -0
  158. body/self_healing/test_context/detectors.py +74 -0
  159. body/self_healing/test_context/examples.py +53 -0
  160. body/self_healing/test_context/formatter.py +65 -0
  161. body/self_healing/test_context/metrics.py +62 -0
  162. body/self_healing/test_context/models.py +83 -0
  163. body/self_healing/test_context/parsers.py +70 -0
  164. body/self_healing/test_context_analyzer.py +79 -0
  165. body/self_healing/test_failure_analyzer.py +259 -0
  166. body/self_healing/test_target_analyzer.py +118 -0
  167. body/self_healing/vulture_healer.py +161 -0
  168. body/services/__init__.py +4 -0
  169. body/services/artifact_service.py +155 -0
  170. body/services/blackboard_service/__init__.py +22 -0
  171. body/services/blackboard_service/blackboard_claim_service.py +216 -0
  172. body/services/blackboard_service/blackboard_proposal_service.py +305 -0
  173. body/services/blackboard_service/blackboard_query_service.py +333 -0
  174. body/services/blackboard_service/blackboard_service.py +602 -0
  175. body/services/capabilities.py +51 -0
  176. body/services/cim/__init__.py +22 -0
  177. body/services/cim/baselines.py +102 -0
  178. body/services/cim/census_service.py +190 -0
  179. body/services/cim/cim_constants.py +116 -0
  180. body/services/cim/cim_path_utils.py +123 -0
  181. body/services/cim/diff.py +152 -0
  182. body/services/cim/history.py +94 -0
  183. body/services/cim/models.py +319 -0
  184. body/services/cim/policy.py +149 -0
  185. body/services/cim/scanners.py +332 -0
  186. body/services/coherence_service.py +552 -0
  187. body/services/consequence_log_service.py +189 -0
  188. body/services/constitutional_rule_loader.py +141 -0
  189. body/services/constitutional_validator.py +366 -0
  190. body/services/crate_creation_service.py +217 -0
  191. body/services/crate_processing_service.py +279 -0
  192. body/services/crawl_service/__init__.py +10 -0
  193. body/services/crawl_service/main_module.py +531 -0
  194. body/services/crawl_service/orchestrator.py +452 -0
  195. body/services/crawl_service/symbol_processing.py +279 -0
  196. body/services/database_service.py +242 -0
  197. body/services/doc_service.py +57 -0
  198. body/services/file_service.py +260 -0
  199. body/services/governance_claims_service.py +240 -0
  200. body/services/governance_init.py +41 -0
  201. body/services/health_log_service.py +167 -0
  202. body/services/intent_schema_validator.py +211 -0
  203. body/services/llm_client.py +87 -0
  204. body/services/mind_state_service.py +129 -0
  205. body/services/policy_expression_evaluator.py +154 -0
  206. body/services/proposal_supervision_service.py +187 -0
  207. body/services/representation_coherence_service.py +209 -0
  208. body/services/service_registry.py +431 -0
  209. body/services/session_attached_service.py +51 -0
  210. body/services/symbol_query_service.py +218 -0
  211. body/services/symbol_service.py +94 -0
  212. body/services/validation/__init__.py +14 -0
  213. body/services/validation/python_validator.py +89 -0
  214. body/services/validation/validation_policies.py +121 -0
  215. body/services/worker_registry_service.py +184 -0
  216. body/validators/__init__.py +1 -0
  217. body/validators/logic_conservation_validator.py +201 -0
  218. body/workers/call_site_rewriter.py +527 -0
  219. body/workers/prompt_artifact_writer.py +323 -0
  220. cli/__init__.py +4 -0
  221. cli/admin_cli.py +98 -0
  222. cli/cli_user.py +121 -0
  223. cli/commands/__init__.py +4 -0
  224. cli/commands/audit_reporter.py +272 -0
  225. cli/commands/check/__init__.py +115 -0
  226. cli/commands/check/audit.py +130 -0
  227. cli/commands/check/converters.py +129 -0
  228. cli/commands/check/diagnostics_commands.py +70 -0
  229. cli/commands/check/formatters.py +310 -0
  230. cli/commands/check/imports.py +73 -0
  231. cli/commands/check/quality.py +71 -0
  232. cli/commands/check/quality_gates.py +107 -0
  233. cli/commands/check/rule.py +136 -0
  234. cli/commands/check/utils.py +28 -0
  235. cli/commands/check_atomic_actions.py +167 -0
  236. cli/commands/components.py +66 -0
  237. cli/commands/coverage/__init__.py +22 -0
  238. cli/commands/coverage/analysis_commands.py +87 -0
  239. cli/commands/coverage/check_commands.py +173 -0
  240. cli/commands/coverage/generation_commands.py +155 -0
  241. cli/commands/coverage/services/__init__.py +15 -0
  242. cli/commands/coverage/services/coverage_checker.py +50 -0
  243. cli/commands/coverage/services/coverage_reporter.py +81 -0
  244. cli/commands/coverage/services/gaps_analyzer.py +114 -0
  245. cli/commands/daemon.py +908 -0
  246. cli/commands/develop.py +127 -0
  247. cli/commands/diagnostics.py +32 -0
  248. cli/commands/fix/__init__.py +84 -0
  249. cli/commands/fix/all_commands.py +94 -0
  250. cli/commands/fix/atomic_actions.py +48 -0
  251. cli/commands/fix/audit.py +146 -0
  252. cli/commands/fix/body_ui.py +93 -0
  253. cli/commands/fix/code_style.py +52 -0
  254. cli/commands/fix/db_tools.py +90 -0
  255. cli/commands/fix/fix_ir.py +79 -0
  256. cli/commands/fix/handler_discovery.py +54 -0
  257. cli/commands/fix/imports.py +55 -0
  258. cli/commands/fix/list_commands.py +54 -0
  259. cli/commands/fix/metadata.py +160 -0
  260. cli/commands/fix/modularity.py +88 -0
  261. cli/commands/fix/settings_access.py +65 -0
  262. cli/commands/fix_governed.py +103 -0
  263. cli/commands/fix_logging.py +24 -0
  264. cli/commands/governance.py +294 -0
  265. cli/commands/guard.py +125 -0
  266. cli/commands/inspect/__init__.py +79 -0
  267. cli/commands/inspect/_helpers.py +226 -0
  268. cli/commands/inspect/analysis.py +158 -0
  269. cli/commands/inspect/decisions.py +140 -0
  270. cli/commands/inspect/diagnostics.py +126 -0
  271. cli/commands/inspect/drift.py +100 -0
  272. cli/commands/inspect/patterns.py +102 -0
  273. cli/commands/inspect/refusals.py +211 -0
  274. cli/commands/inspect/repo_census.py +175 -0
  275. cli/commands/inspect/status.py +48 -0
  276. cli/commands/interactive_test.py +85 -0
  277. cli/commands/mind.py +49 -0
  278. cli/commands/refactor.py +234 -0
  279. cli/commands/refactor_support/__init__.py +7 -0
  280. cli/commands/refactor_support/analyzer.py +107 -0
  281. cli/commands/refactor_support/config.py +67 -0
  282. cli/commands/refactor_support/display.py +170 -0
  283. cli/commands/refactor_support/recommendations.py +55 -0
  284. cli/commands/run.py +60 -0
  285. cli/commands/search.py +103 -0
  286. cli/commands/status.py +86 -0
  287. cli/commands/submit.py +23 -0
  288. cli/interactive.py +177 -0
  289. cli/logic/__init__.py +7 -0
  290. cli/logic/agent.py +110 -0
  291. cli/logic/audit_capability_domains.py +106 -0
  292. cli/logic/audit_renderer.py +150 -0
  293. cli/logic/autonomy/actions.py +36 -0
  294. cli/logic/autonomy/views.py +116 -0
  295. cli/logic/body_contracts_checker.py +23 -0
  296. cli/logic/build.py +27 -0
  297. cli/logic/byor.py +148 -0
  298. cli/logic/capability.py +27 -0
  299. cli/logic/cli_utils.py +210 -0
  300. cli/logic/context.py +7 -0
  301. cli/logic/db.py +154 -0
  302. cli/logic/db_manage.py +22 -0
  303. cli/logic/decision_inspect_logic.py +62 -0
  304. cli/logic/diagnostics.py +148 -0
  305. cli/logic/diagnostics_policy.py +100 -0
  306. cli/logic/diagnostics_registry.py +165 -0
  307. cli/logic/duplicates.py +19 -0
  308. cli/logic/embeddings_cli.py +43 -0
  309. cli/logic/governance/__init__.py +16 -0
  310. cli/logic/governance/engine.py +216 -0
  311. cli/logic/governance/forensics_service.py +67 -0
  312. cli/logic/governance/limb_status_service.py +83 -0
  313. cli/logic/governance/renderer.py +115 -0
  314. cli/logic/governance/traceability_service.py +78 -0
  315. cli/logic/governance_logic.py +33 -0
  316. cli/logic/hub/__init__.py +14 -0
  317. cli/logic/hub/app.py +107 -0
  318. cli/logic/hub/formatter.py +29 -0
  319. cli/logic/hub/introspection.py +20 -0
  320. cli/logic/hub/repository.py +17 -0
  321. cli/logic/init.py +22 -0
  322. cli/logic/interactive_test/__init__.py +21 -0
  323. cli/logic/interactive_test/session.py +102 -0
  324. cli/logic/interactive_test/steps/__init__.py +23 -0
  325. cli/logic/interactive_test/steps/execution.py +53 -0
  326. cli/logic/interactive_test/steps/generation.py +88 -0
  327. cli/logic/interactive_test/steps/healing.py +79 -0
  328. cli/logic/interactive_test/steps/utils.py +31 -0
  329. cli/logic/interactive_test/steps/verification.py +71 -0
  330. cli/logic/interactive_test/ui.py +203 -0
  331. cli/logic/interactive_test/workflow.py +168 -0
  332. cli/logic/interactive_test_logic.py +41 -0
  333. cli/logic/knowledge.py +47 -0
  334. cli/logic/legacy_scan_logic.py +306 -0
  335. cli/logic/list_audits.py +49 -0
  336. cli/logic/log_audit.py +53 -0
  337. cli/logic/new.py +8 -0
  338. cli/logic/project_docs.py +28 -0
  339. cli/logic/reconcile.py +127 -0
  340. cli/logic/refusal_inspect_logic.py +208 -0
  341. cli/logic/report.py +47 -0
  342. cli/logic/status.py +47 -0
  343. cli/logic/symbol_drift.py +77 -0
  344. cli/logic/sync.py +48 -0
  345. cli/logic/sync_domains.py +72 -0
  346. cli/logic/sync_manifest.py +31 -0
  347. cli/logic/tools.py +133 -0
  348. cli/logic/utils_migration.py +43 -0
  349. cli/logic/validate.py +107 -0
  350. cli/logic/vector_drift.py +109 -0
  351. cli/logic/yaml_processor.py +5 -0
  352. cli/renderers/audit_detail.py +37 -0
  353. cli/renderers/audit_overview.py +39 -0
  354. cli/resources/__init__.py +27 -0
  355. cli/resources/admin/__init__.py +23 -0
  356. cli/resources/admin/coverage.py +63 -0
  357. cli/resources/admin/debt_scan.py +195 -0
  358. cli/resources/admin/forensics.py +97 -0
  359. cli/resources/admin/health.py +66 -0
  360. cli/resources/admin/hub.py +9 -0
  361. cli/resources/admin/meta.py +47 -0
  362. cli/resources/admin/patterns.py +28 -0
  363. cli/resources/admin/refusals.py +31 -0
  364. cli/resources/admin/self_check.py +175 -0
  365. cli/resources/admin/status.py +66 -0
  366. cli/resources/admin/summary.py +67 -0
  367. cli/resources/admin/traces.py +46 -0
  368. cli/resources/admin/validate_env.py +56 -0
  369. cli/resources/code/__init__.py +31 -0
  370. cli/resources/code/actions.py +48 -0
  371. cli/resources/code/audit.py +416 -0
  372. cli/resources/code/audit_duplicates.py +22 -0
  373. cli/resources/code/check_imports.py +75 -0
  374. cli/resources/code/check_ui.py +62 -0
  375. cli/resources/code/clarity.py +51 -0
  376. cli/resources/code/complexity.py +55 -0
  377. cli/resources/code/docstrings.py +51 -0
  378. cli/resources/code/fix_atomic.py +51 -0
  379. cli/resources/code/format.py +62 -0
  380. cli/resources/code/hub.py +10 -0
  381. cli/resources/code/integrity.py +75 -0
  382. cli/resources/code/lint.py +37 -0
  383. cli/resources/code/logging.py +49 -0
  384. cli/resources/code/refactor.py +32 -0
  385. cli/resources/code/test.py +30 -0
  386. cli/resources/coherence/__init__.py +13 -0
  387. cli/resources/coherence/check.py +111 -0
  388. cli/resources/coherence/hub.py +13 -0
  389. cli/resources/coherence/repair_counts.py +73 -0
  390. cli/resources/coherence/report.py +144 -0
  391. cli/resources/coherence/seed.py +297 -0
  392. cli/resources/coherence/supersede.py +124 -0
  393. cli/resources/coherence/triage.py +81 -0
  394. cli/resources/constitution/__init__.py +19 -0
  395. cli/resources/constitution/audit.py +49 -0
  396. cli/resources/constitution/query.py +45 -0
  397. cli/resources/constitution/status.py +34 -0
  398. cli/resources/constitution/validate.py +36 -0
  399. cli/resources/context/__init__.py +21 -0
  400. cli/resources/context/build.py +374 -0
  401. cli/resources/context/cache.py +156 -0
  402. cli/resources/context/explain.py +140 -0
  403. cli/resources/context/hub.py +11 -0
  404. cli/resources/context/search.py +114 -0
  405. cli/resources/database/__init__.py +13 -0
  406. cli/resources/database/cleanup.py +107 -0
  407. cli/resources/database/export.py +61 -0
  408. cli/resources/database/hub.py +11 -0
  409. cli/resources/database/migrate.py +57 -0
  410. cli/resources/database/status.py +101 -0
  411. cli/resources/database/sync.py +84 -0
  412. cli/resources/database/sync_env.py +76 -0
  413. cli/resources/database/sync_registry.py +48 -0
  414. cli/resources/dev/__init__.py +14 -0
  415. cli/resources/dev/hub.py +11 -0
  416. cli/resources/dev/refactor.py +92 -0
  417. cli/resources/dev/stability.py +60 -0
  418. cli/resources/dev/strategic_audit.py +113 -0
  419. cli/resources/dev/sync.py +51 -0
  420. cli/resources/dev/test.py +34 -0
  421. cli/resources/intent/__init__.py +11 -0
  422. cli/resources/intent/hub.py +9 -0
  423. cli/resources/intent/sync_vocabulary.py +396 -0
  424. cli/resources/project/__init__.py +19 -0
  425. cli/resources/project/docs.py +41 -0
  426. cli/resources/project/new.py +40 -0
  427. cli/resources/project/onboard.py +31 -0
  428. cli/resources/proposals/__init__.py +28 -0
  429. cli/resources/proposals/create.py +82 -0
  430. cli/resources/proposals/integrate.py +49 -0
  431. cli/resources/proposals/list.py +76 -0
  432. cli/resources/proposals/manage.py +117 -0
  433. cli/resources/runtime/__init__.py +9 -0
  434. cli/resources/runtime/health.py +925 -0
  435. cli/resources/secrets/__init__.py +10 -0
  436. cli/resources/secrets/hub.py +9 -0
  437. cli/resources/secrets/manage.py +309 -0
  438. cli/resources/symbols/__init__.py +13 -0
  439. cli/resources/symbols/audit.py +46 -0
  440. cli/resources/symbols/fix_ids.py +43 -0
  441. cli/resources/symbols/hub.py +11 -0
  442. cli/resources/symbols/resolve_duplicates.py +30 -0
  443. cli/resources/symbols/sync.py +39 -0
  444. cli/resources/symbols/tag.py +47 -0
  445. cli/resources/vectors/__init__.py +11 -0
  446. cli/resources/vectors/cleanup.py +95 -0
  447. cli/resources/vectors/hub.py +9 -0
  448. cli/resources/vectors/query.py +105 -0
  449. cli/resources/vectors/status.py +30 -0
  450. cli/resources/vectors/sync.py +57 -0
  451. cli/resources/vectors/sync_code.py +67 -0
  452. cli/resources/workers/__init__.py +13 -0
  453. cli/resources/workers/blackboard.py +253 -0
  454. cli/resources/workers/remediate.py +337 -0
  455. cli/resources/workers/run.py +140 -0
  456. cli/utils/__init__.py +32 -0
  457. cli/utils/annotation_formatter.py +154 -0
  458. cli/utils/decorators.py +184 -0
  459. cli/utils/display.py +79 -0
  460. cli/utils/exit_codes.py +59 -0
  461. cli/utils/helpers.py +34 -0
  462. cli/utils/prompts.py +21 -0
  463. core_runtime-0.1.1.dist-info/LICENSE +21 -0
  464. core_runtime-0.1.1.dist-info/METADATA +346 -0
  465. core_runtime-0.1.1.dist-info/RECORD +962 -0
  466. core_runtime-0.1.1.dist-info/WHEEL +4 -0
  467. core_runtime-0.1.1.dist-info/entry_points.txt +4 -0
  468. mind/__init__.py +4 -0
  469. mind/coherence/__init__.py +1 -0
  470. mind/coherence/checker.py +314 -0
  471. mind/coherence/checks/__init__.py +4 -0
  472. mind/coherence/checks/base.py +34 -0
  473. mind/coherence/checks/r1_scoped.py +228 -0
  474. mind/coherence/checks/row2_grounding.py +69 -0
  475. mind/coherence/checks/row3_citation.py +119 -0
  476. mind/coherence/checks/row4_naming.py +126 -0
  477. mind/coherence/checks/sameconcern.py +136 -0
  478. mind/coherence/checks/specgap.py +233 -0
  479. mind/coherence/checks/vocabulary.py +112 -0
  480. mind/coherence/llm_judge.py +207 -0
  481. mind/enforcement/audit.py +78 -0
  482. mind/governance/__init__.py +22 -0
  483. mind/governance/assumption_extractor.py +326 -0
  484. mind/governance/audit_context.py +520 -0
  485. mind/governance/audit_postprocessor.py +36 -0
  486. mind/governance/audit_report_writer.py +46 -0
  487. mind/governance/audit_types.py +98 -0
  488. mind/governance/auditor.py +179 -0
  489. mind/governance/authority_package_builder.py +502 -0
  490. mind/governance/constitutional_auditor_dynamic.py +362 -0
  491. mind/governance/enforcement/__init__.py +24 -0
  492. mind/governance/enforcement_loader.py +245 -0
  493. mind/governance/enforcement_methods.py +28 -0
  494. mind/governance/entry_point_policy.py +62 -0
  495. mind/governance/executable_rule.py +127 -0
  496. mind/governance/filtered_audit.py +272 -0
  497. mind/governance/finding_processor.py +76 -0
  498. mind/governance/meta_validator.py +259 -0
  499. mind/governance/micro_proposal_validator.py +169 -0
  500. mind/governance/policy_coverage_service.py +183 -0
  501. mind/governance/policy_rule.py +94 -0
  502. mind/governance/rule_conflict_detector.py +127 -0
  503. mind/governance/rule_executor.py +306 -0
  504. mind/governance/rule_extractor.py +376 -0
  505. mind/governance/stateless_audit.py +206 -0
  506. mind/governance/violation_report.py +136 -0
  507. mind/logic/engines/_knowledge_gate_duplication.py +117 -0
  508. mind/logic/engines/action_gate.py +76 -0
  509. mind/logic/engines/artifact_gate.py +1168 -0
  510. mind/logic/engines/ast_gate/__init__.py +9 -0
  511. mind/logic/engines/ast_gate/base.py +263 -0
  512. mind/logic/engines/ast_gate/checks/__init__.py +35 -0
  513. mind/logic/engines/ast_gate/checks/async_checks.py +276 -0
  514. mind/logic/engines/ast_gate/checks/capability_checks.py +197 -0
  515. mind/logic/engines/ast_gate/checks/conservation_checks.py +126 -0
  516. mind/logic/engines/ast_gate/checks/generic_checks.py +244 -0
  517. mind/logic/engines/ast_gate/checks/import_checks.py +164 -0
  518. mind/logic/engines/ast_gate/checks/knowledge_source_check.py +88 -0
  519. mind/logic/engines/ast_gate/checks/logging_checks.py +133 -0
  520. mind/logic/engines/ast_gate/checks/metadata_checks.py +242 -0
  521. mind/logic/engines/ast_gate/checks/modularity_checks.py +436 -0
  522. mind/logic/engines/ast_gate/checks/naming_checks.py +120 -0
  523. mind/logic/engines/ast_gate/checks/prompt_model_checks.py +83 -0
  524. mind/logic/engines/ast_gate/checks/protected_namespace_access_check.py +298 -0
  525. mind/logic/engines/ast_gate/checks/purity_checks.py +421 -0
  526. mind/logic/engines/ast_gate/checks/purity_enforcement_check.py +56 -0
  527. mind/logic/engines/ast_gate/checks/runtime_import_boundary.py +198 -0
  528. mind/logic/engines/ast_gate/checks/schema_conformance_checks.py +130 -0
  529. mind/logic/engines/ast_gate/engine.py +317 -0
  530. mind/logic/engines/ast_gate.py +19 -0
  531. mind/logic/engines/base.py +106 -0
  532. mind/logic/engines/cli_gate/__init__.py +25 -0
  533. mind/logic/engines/cli_gate/base_check.py +45 -0
  534. mind/logic/engines/cli_gate/checks/__init__.py +31 -0
  535. mind/logic/engines/cli_gate/checks/async_execution.py +65 -0
  536. mind/logic/engines/cli_gate/checks/dangerous_explicit.py +60 -0
  537. mind/logic/engines/cli_gate/checks/discovery_strict.py +167 -0
  538. mind/logic/engines/cli_gate/checks/help_required.py +43 -0
  539. mind/logic/engines/cli_gate/checks/no_duplicates.py +57 -0
  540. mind/logic/engines/cli_gate/checks/no_layer_exposure.py +48 -0
  541. mind/logic/engines/cli_gate/checks/resource_first.py +58 -0
  542. mind/logic/engines/cli_gate/checks/standard_verbs.py +50 -0
  543. mind/logic/engines/cli_gate/engine.py +211 -0
  544. mind/logic/engines/glob_gate.py +214 -0
  545. mind/logic/engines/knowledge_gate.py +410 -0
  546. mind/logic/engines/llm_gate.py +407 -0
  547. mind/logic/engines/llm_gate_stub.py +67 -0
  548. mind/logic/engines/passive_gate.py +45 -0
  549. mind/logic/engines/regex_gate.py +97 -0
  550. mind/logic/engines/registry.py +134 -0
  551. mind/logic/engines/runtime_gate.py +265 -0
  552. mind/logic/engines/taxonomy_gate.py +229 -0
  553. mind/logic/engines/workflow_gate/__init__.py +22 -0
  554. mind/logic/engines/workflow_gate/base_check.py +42 -0
  555. mind/logic/engines/workflow_gate/checks/__init__.py +32 -0
  556. mind/logic/engines/workflow_gate/checks/alignment.py +93 -0
  557. mind/logic/engines/workflow_gate/checks/audit.py +80 -0
  558. mind/logic/engines/workflow_gate/checks/canary.py +47 -0
  559. mind/logic/engines/workflow_gate/checks/coverage.py +74 -0
  560. mind/logic/engines/workflow_gate/checks/dead_code.py +53 -0
  561. mind/logic/engines/workflow_gate/checks/import_resolution.py +97 -0
  562. mind/logic/engines/workflow_gate/checks/linter.py +104 -0
  563. mind/logic/engines/workflow_gate/checks/quality.py +49 -0
  564. mind/logic/engines/workflow_gate/checks/ruff_format.py +99 -0
  565. mind/logic/engines/workflow_gate/checks/tests.py +81 -0
  566. mind/logic/engines/workflow_gate/engine.py +207 -0
  567. shared/__init__.py +32 -0
  568. shared/action_logger.py +61 -0
  569. shared/action_types.py +199 -0
  570. shared/activity_logging.py +149 -0
  571. shared/ai/constitutional_envelope.py +341 -0
  572. shared/ai/prompt_model.py +585 -0
  573. shared/ai/response_parser.py +191 -0
  574. shared/ast_utility.py +279 -0
  575. shared/atomic_action.py +117 -0
  576. shared/cli/__init__.py +6 -0
  577. shared/cli/app_introspection.py +134 -0
  578. shared/cli/command_meta.py +224 -0
  579. shared/cli_types.py +92 -0
  580. shared/component_primitive.py +216 -0
  581. shared/config.py +216 -0
  582. shared/config_loader.py +54 -0
  583. shared/context.py +113 -0
  584. shared/exceptions.py +100 -0
  585. shared/governance/__init__.py +9 -0
  586. shared/governance/coherence_harvester.py +258 -0
  587. shared/governance_token.py +77 -0
  588. shared/infrastructure/__init__.py +5 -0
  589. shared/infrastructure/adapters/__init__.py +5 -0
  590. shared/infrastructure/adapters/embedding_provider.py +66 -0
  591. shared/infrastructure/bootstrap_registry.py +57 -0
  592. shared/infrastructure/clients/__init__.py +5 -0
  593. shared/infrastructure/clients/qdrant_client.py +455 -0
  594. shared/infrastructure/config_service.py +382 -0
  595. shared/infrastructure/config_validator.py +70 -0
  596. shared/infrastructure/context/__init__.py +45 -0
  597. shared/infrastructure/context/builder.py +804 -0
  598. shared/infrastructure/context/cache.py +101 -0
  599. shared/infrastructure/context/database.py +205 -0
  600. shared/infrastructure/context/limb_workspace.py +134 -0
  601. shared/infrastructure/context/models.py +65 -0
  602. shared/infrastructure/context/providers/__init__.py +18 -0
  603. shared/infrastructure/context/providers/ast.py +211 -0
  604. shared/infrastructure/context/providers/db.py +165 -0
  605. shared/infrastructure/context/providers/vectors.py +195 -0
  606. shared/infrastructure/context/redactor.py +109 -0
  607. shared/infrastructure/context/serializers.py +144 -0
  608. shared/infrastructure/context/service.py +271 -0
  609. shared/infrastructure/context/validator.py +247 -0
  610. shared/infrastructure/database/models/__init__.py +80 -0
  611. shared/infrastructure/database/models/autonomous_proposals.py +83 -0
  612. shared/infrastructure/database/models/decision_traces.py +129 -0
  613. shared/infrastructure/database/models/governance.py +183 -0
  614. shared/infrastructure/database/models/knowledge.py +205 -0
  615. shared/infrastructure/database/models/learning.py +99 -0
  616. shared/infrastructure/database/models/llm_config.py +274 -0
  617. shared/infrastructure/database/models/operations.py +152 -0
  618. shared/infrastructure/database/models/refusals.py +147 -0
  619. shared/infrastructure/database/models/system.py +124 -0
  620. shared/infrastructure/database/models/vectors.py +113 -0
  621. shared/infrastructure/database/models/workers.py +96 -0
  622. shared/infrastructure/database/session_manager.py +166 -0
  623. shared/infrastructure/diagnostic_service.py +103 -0
  624. shared/infrastructure/events/__init__.py +5 -0
  625. shared/infrastructure/events/base.py +44 -0
  626. shared/infrastructure/events/bus.py +76 -0
  627. shared/infrastructure/git_service.py +385 -0
  628. shared/infrastructure/intent/action_risk.py +135 -0
  629. shared/infrastructure/intent/audit_verdict.py +131 -0
  630. shared/infrastructure/intent/autonomy_dirty_tree.py +104 -0
  631. shared/infrastructure/intent/canonical_enums.py +116 -0
  632. shared/infrastructure/intent/cognitive_roles.py +96 -0
  633. shared/infrastructure/intent/errors.py +13 -0
  634. shared/infrastructure/intent/filesystem_operations.py +359 -0
  635. shared/infrastructure/intent/intent_connector.py +157 -0
  636. shared/infrastructure/intent/intent_repository.py +707 -0
  637. shared/infrastructure/intent/intent_validator.py +248 -0
  638. shared/infrastructure/intent/operational_capabilities.py +470 -0
  639. shared/infrastructure/intent/operational_config.py +1343 -0
  640. shared/infrastructure/intent/operational_mode.py +66 -0
  641. shared/infrastructure/intent/task_type_phases.py +180 -0
  642. shared/infrastructure/intent/test_coverage_paths.py +181 -0
  643. shared/infrastructure/intent/vocabulary_projection.py +241 -0
  644. shared/infrastructure/knowledge/knowledge_service.py +155 -0
  645. shared/infrastructure/knowledge_graph_service.py +214 -0
  646. shared/infrastructure/llm/client.py +448 -0
  647. shared/infrastructure/llm/client_registry.py +153 -0
  648. shared/infrastructure/llm/fallback_client.py +144 -0
  649. shared/infrastructure/llm/providers/anthropic.py +113 -0
  650. shared/infrastructure/llm/providers/base.py +130 -0
  651. shared/infrastructure/llm/providers/ollama.py +265 -0
  652. shared/infrastructure/llm/providers/openai.py +168 -0
  653. shared/infrastructure/repositories/__init__.py +5 -0
  654. shared/infrastructure/repositories/db/__init__.py +5 -0
  655. shared/infrastructure/repositories/db/common.py +138 -0
  656. shared/infrastructure/repositories/db/engine.py +26 -0
  657. shared/infrastructure/repositories/db/migration_service.py +75 -0
  658. shared/infrastructure/repositories/db/status_service.py +61 -0
  659. shared/infrastructure/repositories/memory_repository.py +134 -0
  660. shared/infrastructure/repositories/symbol_definition_repository.py +170 -0
  661. shared/infrastructure/repositories/task_repository.py +59 -0
  662. shared/infrastructure/repositories/vector_link_repository.py +83 -0
  663. shared/infrastructure/rooted_repository.py +50 -0
  664. shared/infrastructure/secrets_service.py +317 -0
  665. shared/infrastructure/specs/__init__.py +9 -0
  666. shared/infrastructure/specs/specs_repository.py +100 -0
  667. shared/infrastructure/storage/file_classifier.py +32 -0
  668. shared/infrastructure/storage/file_handler.py +330 -0
  669. shared/infrastructure/storage/file_provider.py +233 -0
  670. shared/infrastructure/storage/integrity_service.py +108 -0
  671. shared/infrastructure/validation/black_formatter.py +41 -0
  672. shared/infrastructure/validation/quality.py +46 -0
  673. shared/infrastructure/validation/ruff_linter.py +104 -0
  674. shared/infrastructure/validation/syntax_checker.py +45 -0
  675. shared/infrastructure/validation/test_runner.py +167 -0
  676. shared/infrastructure/validation/yaml_validator.py +45 -0
  677. shared/infrastructure/vector/__init__.py +15 -0
  678. shared/infrastructure/vector/adapters/__init__.py +20 -0
  679. shared/infrastructure/vector/adapters/constitutional/__init__.py +26 -0
  680. shared/infrastructure/vector/adapters/constitutional/chunker.py +246 -0
  681. shared/infrastructure/vector/adapters/constitutional/doc_key_resolver.py +109 -0
  682. shared/infrastructure/vector/adapters/constitutional/item_builder.py +158 -0
  683. shared/infrastructure/vector/adapters/constitutional/utils.py +39 -0
  684. shared/infrastructure/vector/adapters/constitutional_adapter.py +309 -0
  685. shared/infrastructure/vector/adapters/specs_adapter.py +171 -0
  686. shared/infrastructure/vector/cognitive_adapter.py +119 -0
  687. shared/infrastructure/vector/vector_index_service.py +230 -0
  688. shared/logger.py +195 -0
  689. shared/models/__init__.py +47 -0
  690. shared/models/action_result.py +77 -0
  691. shared/models/audit_models.py +106 -0
  692. shared/models/audit_rendering.py +30 -0
  693. shared/models/capability_models.py +22 -0
  694. shared/models/constitutional_validation.py +185 -0
  695. shared/models/drift_models.py +24 -0
  696. shared/models/embedding_payload.py +45 -0
  697. shared/models/execution_models.py +71 -0
  698. shared/models/pattern_graph.py +62 -0
  699. shared/models/prompt_model.py +244 -0
  700. shared/models/refusal_result.py +294 -0
  701. shared/models/remediation.py +35 -0
  702. shared/models/validation_result.py +34 -0
  703. shared/models/vector_models.py +62 -0
  704. shared/models/workflow_models.py +242 -0
  705. shared/path_resolver.py +408 -0
  706. shared/path_utils.py +60 -0
  707. shared/processors/base_processor.py +171 -0
  708. shared/processors/yaml_processor.py +72 -0
  709. shared/protocols/__init__.py +21 -0
  710. shared/protocols/brain_services.py +35 -0
  711. shared/protocols/cognitive.py +35 -0
  712. shared/protocols/executor.py +47 -0
  713. shared/protocols/interpreter.py +24 -0
  714. shared/protocols/knowledge.py +21 -0
  715. shared/protocols/llm.py +25 -0
  716. shared/protocols/typer_protocols.py +37 -0
  717. shared/time.py +18 -0
  718. shared/universal.py +43 -0
  719. shared/utils/__init__.py +81 -0
  720. shared/utils/audit_grouping.py +50 -0
  721. shared/utils/common_knowledge.py +82 -0
  722. shared/utils/domain_mapper.py +61 -0
  723. shared/utils/embedding_utils.py +182 -0
  724. shared/utils/glob_match.py +93 -0
  725. shared/utils/header_tools.py +177 -0
  726. shared/utils/parallel_processor.py +60 -0
  727. shared/utils/parsing.py +189 -0
  728. shared/utils/path_utils.py +268 -0
  729. shared/utils/subprocess_utils.py +87 -0
  730. shared/workers/__init__.py +19 -0
  731. shared/workers/base.py +533 -0
  732. shared/workers/declaration_validator.py +124 -0
  733. shared/workers/loop_hold_telemetry.py +210 -0
  734. shared/workers/schedule.py +123 -0
  735. will/__init__.py +4 -0
  736. will/agents/__init__.py +4 -0
  737. will/agents/base_planner.py +133 -0
  738. will/agents/code_generation/__init__.py +15 -0
  739. will/agents/code_generation/code_generator.py +247 -0
  740. will/agents/code_generation/context_formatters.py +99 -0
  741. will/agents/code_generation/correction_engine.py +157 -0
  742. will/agents/code_generation/extraction.py +165 -0
  743. will/agents/code_generation/pattern_validator.py +264 -0
  744. will/agents/code_generation/prompt_builders.py +209 -0
  745. will/agents/coder_agent.py +229 -0
  746. will/agents/coder_agent_refusal_handler.py +168 -0
  747. will/agents/cognitive_orchestrator.py +152 -0
  748. will/agents/conversational/__init__.py +13 -0
  749. will/agents/conversational/agent.py +271 -0
  750. will/agents/conversational/factory.py +72 -0
  751. will/agents/conversational/helpers.py +116 -0
  752. will/agents/execution_agent.py +294 -0
  753. will/agents/governance_mixin.py +132 -0
  754. will/agents/planner_agent.py +261 -0
  755. will/agents/resource_selector.py +228 -0
  756. will/agents/strategic_auditor/__init__.py +15 -0
  757. will/agents/strategic_auditor/agent.py +199 -0
  758. will/agents/strategic_auditor/context_gatherer.py +586 -0
  759. will/agents/strategic_auditor/effects.py +136 -0
  760. will/agents/strategic_auditor/models.py +61 -0
  761. will/agents/strategic_auditor/reasoning.py +169 -0
  762. will/agents/tagger_agent.py +294 -0
  763. will/agents/traced_agent_mixin.py +33 -0
  764. will/autonomy/__init__.py +20 -0
  765. will/autonomy/autonomous_developer.py +127 -0
  766. will/autonomy/proposal.py +585 -0
  767. will/autonomy/proposal_execution_pipeline.py +264 -0
  768. will/autonomy/proposal_executor.py +410 -0
  769. will/autonomy/proposal_mapper.py +187 -0
  770. will/autonomy/proposal_repository.py +118 -0
  771. will/autonomy/proposal_service.py +251 -0
  772. will/autonomy/proposal_state_manager.py +239 -0
  773. will/deciders/__init__.py +9 -0
  774. will/deciders/governance_decider.py +207 -0
  775. will/governance/__init__.py +13 -0
  776. will/governance/audit_remediation_runner.py +197 -0
  777. will/governance/audit_runner.py +368 -0
  778. will/governance/census_runner.py +278 -0
  779. will/governance/coverage_runner.py +489 -0
  780. will/governance/daemon_runner.py +164 -0
  781. will/governance/fix_runner.py +693 -0
  782. will/governance/inspect_runner.py +521 -0
  783. will/governance/integrity_runner.py +66 -0
  784. will/governance/lint_runner.py +93 -0
  785. will/governance/refactor_runner.py +372 -0
  786. will/governance/sync_runner.py +186 -0
  787. will/interpreters/__init__.py +44 -0
  788. will/interpreters/cli_args_interpreter.py +106 -0
  789. will/interpreters/natural_language_interpreter.py +276 -0
  790. will/interpreters/request_interpreter.py +126 -0
  791. will/lifecycle/__init__.py +12 -0
  792. will/lifecycle/integration_runner.py +54 -0
  793. will/maintenance/metadata_scribe_service.py +64 -0
  794. will/orchestration/__init__.py +4 -0
  795. will/orchestration/cognitive_service.py +185 -0
  796. will/orchestration/decision_tracer.py +257 -0
  797. will/orchestration/intent_alignment.py +59 -0
  798. will/orchestration/intent_guard.py +20 -0
  799. will/orchestration/phase_registry.py +92 -0
  800. will/orchestration/process_orchestrator.py +270 -0
  801. will/orchestration/prompt_pipeline.py +174 -0
  802. will/orchestration/remediation_orchestrator.py +292 -0
  803. will/orchestration/self_correction_engine.py +154 -0
  804. will/orchestration/validation_pipeline.py +45 -0
  805. will/orchestration/workflow_orchestrator.py +277 -0
  806. will/phases/__init__.py +24 -0
  807. will/phases/audit_phase.py +152 -0
  808. will/phases/canary/pytest_runner.py +156 -0
  809. will/phases/canary/result_builder.py +130 -0
  810. will/phases/canary/test_discovery.py +104 -0
  811. will/phases/canary_validation_phase.py +188 -0
  812. will/phases/code_generation/artifact_saver.py +175 -0
  813. will/phases/code_generation/code_sensor.py +117 -0
  814. will/phases/code_generation/file_path_extractor.py +53 -0
  815. will/phases/code_generation/work_directory_manager.py +83 -0
  816. will/phases/code_generation_phase.py +480 -0
  817. will/phases/execution_phase.py +179 -0
  818. will/phases/interpret_phase.py +266 -0
  819. will/phases/load_phase.py +102 -0
  820. will/phases/parse_phase.py +117 -0
  821. will/phases/planning_phase.py +182 -0
  822. will/phases/runtime_phase.py +112 -0
  823. will/phases/sandbox_validation_phase.py +130 -0
  824. will/phases/style_check_phase.py +209 -0
  825. will/phases/test_generation_phase.py +159 -0
  826. will/self_healing/alignment/persistence.py +53 -0
  827. will/self_healing/alignment/sandbox.py +51 -0
  828. will/self_healing/alignment/specialists.py +165 -0
  829. will/self_healing/alignment_orchestrator.py +140 -0
  830. will/self_healing/audit_remediation_service.py +199 -0
  831. will/self_healing/batch_remediation_service.py +280 -0
  832. will/self_healing/capability_reconciliation_service.py +96 -0
  833. will/self_healing/capability_tagging_service.py +224 -0
  834. will/self_healing/clarity_service.py +204 -0
  835. will/self_healing/complexity_service.py +260 -0
  836. will/self_healing/context_aware_test_generator.py +298 -0
  837. will/self_healing/coverage_remediation_service.py +97 -0
  838. will/self_healing/coverage_watcher.py +192 -0
  839. will/self_healing/enrichment_service.py +211 -0
  840. will/self_healing/linelength_service.py +168 -0
  841. will/self_healing/modularity_remediation_service.py +203 -0
  842. will/self_healing/remediation_evidence_writer.py +144 -0
  843. will/self_healing/remediation_executor.py +113 -0
  844. will/self_healing/remediation_interpretation/__init__.py +1 -0
  845. will/self_healing/remediation_interpretation/file_context_assembler.py +383 -0
  846. will/self_healing/remediation_interpretation/file_role_detector.py +599 -0
  847. will/self_healing/remediation_interpretation/finding_normalizer.py +221 -0
  848. will/self_healing/remediation_interpretation/models.py +198 -0
  849. will/self_healing/remediation_interpretation/reasoning_brief_builder.py +235 -0
  850. will/self_healing/remediation_interpretation/responsibility_extractor.py +421 -0
  851. will/self_healing/remediation_interpretation/service.py +202 -0
  852. will/self_healing/remediation_interpretation/strategy_catalog.py +252 -0
  853. will/self_healing/remediation_interpretation/strategy_selector.py +395 -0
  854. will/self_healing/remediation_pattern_matcher.py +126 -0
  855. will/self_healing/simple_test_generator.py +252 -0
  856. will/self_healing/single_file_remediation.py +137 -0
  857. will/self_healing/test_generation/automatic_repair.py +377 -0
  858. will/self_healing/test_generation/code_extractor.py +238 -0
  859. will/self_healing/test_generation/context_builder.py +140 -0
  860. will/self_healing/test_generation/executor.py +64 -0
  861. will/self_healing/test_generation/failure_parser.py +37 -0
  862. will/self_healing/test_generation/generation_workflow.py +140 -0
  863. will/self_healing/test_generation/generator.py +283 -0
  864. will/self_healing/test_generation/llm_correction.py +160 -0
  865. will/self_healing/test_generation/repair_workflow.py +128 -0
  866. will/self_healing/test_generation/single_test_fixer.py +77 -0
  867. will/self_healing/test_generation/test_extractor.py +50 -0
  868. will/self_healing/test_generation/test_scorer.py +53 -0
  869. will/self_healing/test_generation/test_validator.py +64 -0
  870. will/self_healing/test_generator.py +12 -0
  871. will/strategists/__init__.py +46 -0
  872. will/strategists/base_strategist.py +29 -0
  873. will/strategists/clarity_strategist.py +55 -0
  874. will/strategists/complexity_strategist.py +55 -0
  875. will/strategists/fix_strategist.py +467 -0
  876. will/strategists/sync_strategist.py +369 -0
  877. will/strategists/test_strategist.py +140 -0
  878. will/strategists/validation_strategist.py +315 -0
  879. will/test_generation/__init__.py +46 -0
  880. will/test_generation/adaptive_test_generator.py +123 -0
  881. will/test_generation/artifacts.py +102 -0
  882. will/test_generation/harness_detection.py +103 -0
  883. will/test_generation/helpers/__init__.py +14 -0
  884. will/test_generation/helpers/context_extractor.py +100 -0
  885. will/test_generation/helpers/test_executor.py +230 -0
  886. will/test_generation/llm_output.py +62 -0
  887. will/test_generation/models.py +25 -0
  888. will/test_generation/persistence.py +248 -0
  889. will/test_generation/phases/__init__.py +16 -0
  890. will/test_generation/phases/generation_phase.py +150 -0
  891. will/test_generation/phases/load_phase.py +53 -0
  892. will/test_generation/phases/parse_phase.py +50 -0
  893. will/test_generation/prompt_engine.py +123 -0
  894. will/test_generation/result_aggregator.py +73 -0
  895. will/test_generation/sandbox.py +203 -0
  896. will/test_generation/strategy_link.py +56 -0
  897. will/test_generation/test_extractor.py +140 -0
  898. will/test_generation/validation.py +89 -0
  899. will/tools/__init__.py +13 -0
  900. will/tools/anchor_builder.py +111 -0
  901. will/tools/anchor_search.py +73 -0
  902. will/tools/anchors/discovery.py +55 -0
  903. will/tools/anchors/storage.py +32 -0
  904. will/tools/architectural_context_builder.py +94 -0
  905. will/tools/cognitive_toolbox.py +47 -0
  906. will/tools/context/code_snippet_extractor.py +83 -0
  907. will/tools/context/embedding_search.py +76 -0
  908. will/tools/context/formatter.py +87 -0
  909. will/tools/context/models.py +38 -0
  910. will/tools/context/query_builder.py +42 -0
  911. will/tools/context/retriever.py +182 -0
  912. will/tools/context/standards.py +53 -0
  913. will/tools/file_navigator.py +180 -0
  914. will/tools/layers.py +31 -0
  915. will/tools/module_anchor_generator.py +137 -0
  916. will/tools/module_descriptor.py +154 -0
  917. will/tools/policy_vectorizer.py +184 -0
  918. will/tools/symbol_finder.py +188 -0
  919. will/tools/tool_generator.py +103 -0
  920. will/workers/audit_ingest_worker.py +207 -0
  921. will/workers/audit_violation_filter.py +108 -0
  922. will/workers/audit_violation_normalizer.py +108 -0
  923. will/workers/audit_violation_sensor.py +370 -0
  924. will/workers/blackboard_shop_manager.py +280 -0
  925. will/workers/capability_tagger.py +153 -0
  926. will/workers/circuit_breaker.py +335 -0
  927. will/workers/coherence_sensor.py +212 -0
  928. will/workers/commit_reachability_auditor.py +135 -0
  929. will/workers/db_sync_worker.py +96 -0
  930. will/workers/governance_embedding/__init__.py +9 -0
  931. will/workers/governance_embedding/governance_embedder_worker.py +189 -0
  932. will/workers/intent_inspector.py +599 -0
  933. will/workers/observer_worker.py +158 -0
  934. will/workers/prompt_extractor_worker.py +241 -0
  935. will/workers/proposal_consumer_effects.py +216 -0
  936. will/workers/proposal_consumer_revival.py +131 -0
  937. will/workers/proposal_consumer_worker.py +271 -0
  938. will/workers/proposal_pipeline_shop_manager.py +273 -0
  939. will/workers/repo_crawler.py +171 -0
  940. will/workers/repo_embedding/__init__.py +18 -0
  941. will/workers/repo_embedding/helpers.py +245 -0
  942. will/workers/repo_embedding/repo_embedder_workers.py +163 -0
  943. will/workers/test_coverage_sensor.py +208 -0
  944. will/workers/test_remediator/__init__.py +12 -0
  945. will/workers/test_remediator/_operations.py +295 -0
  946. will/workers/test_remediator/worker.py +187 -0
  947. will/workers/test_runner_sensor.py +430 -0
  948. will/workers/violation_executor.py +496 -0
  949. will/workers/violation_remediator.py +394 -0
  950. will/workers/violation_remediator_blackboard.py +225 -0
  951. will/workers/violation_remediator_body/__init__.py +12 -0
  952. will/workers/violation_remediator_body/blackboard.py +139 -0
  953. will/workers/violation_remediator_body/ceremony.py +154 -0
  954. will/workers/violation_remediator_body/context.py +70 -0
  955. will/workers/violation_remediator_body/llm.py +112 -0
  956. will/workers/violation_remediator_body/models.py +35 -0
  957. will/workers/violation_remediator_body/worker.py +518 -0
  958. will/workers/violation_remediator_proposal.py +328 -0
  959. will/workers/worker_shop_manager.py +244 -0
  960. will/workflows/__init__.py +23 -0
  961. will/workflows/dev_sync_reporter.py +274 -0
  962. will/workflows/dev_sync_workflow.py +118 -0
@@ -0,0 +1,1168 @@
1
+ # src/mind/logic/engines/artifact_gate.py
2
+
3
+ """
4
+ Constitutional Artifact Gate — PromptModel manifest validator.
5
+
6
+ Enforces structural and abstraction-boundary rules on var/prompts/*/model.yaml
7
+ files. Every check is deterministic: no LLM, no I/O beyond reading the file
8
+ already provided by the auditor.
9
+
10
+ Rules enforced:
11
+ - ai.prompt.artifact.required_fields — id, version, role, input.required,
12
+ output.format, success_criteria
13
+ - ai.prompt.artifact.no_provider_leak — model.preference must not name an
14
+ infrastructure provider
15
+ - ai.prompt.artifact.role_abstraction — role field must reference a cognitive
16
+ role, not a product or tool name
17
+
18
+ Vocabulary checks (ADR-023) operate on .specs/papers/CORE-Vocabulary.md and
19
+ .intent/META/vocabulary.json, not on YAML manifests. They are dispatched
20
+ before the YAML load so the engine never tries to parse Markdown as YAML.
21
+ """
22
+
23
+ from __future__ import annotations
24
+
25
+ import builtins
26
+ import importlib
27
+ import inspect
28
+ import re
29
+ import sys
30
+ from pathlib import Path
31
+ from typing import TYPE_CHECKING, Any
32
+
33
+ import yaml
34
+
35
+ from shared.infrastructure.intent.cognitive_roles import load_cognitive_roles
36
+ from shared.infrastructure.intent.errors import GovernanceError
37
+ from shared.infrastructure.intent.filesystem_operations import (
38
+ FilesystemOperationTaxonomyError,
39
+ load_filesystem_operations,
40
+ )
41
+ from shared.infrastructure.intent.intent_repository import get_intent_repository
42
+ from shared.infrastructure.intent.vocabulary_projection import (
43
+ VOCABULARY_JSON_REL,
44
+ VOCABULARY_PAPER_REL,
45
+ VocabularyProjection,
46
+ VocabularyProjectionError,
47
+ compute_canonical_section_hash,
48
+ load_vocabulary_projection,
49
+ locate_canonical_section,
50
+ normalize_vocabulary_cell,
51
+ )
52
+ from shared.logger import getLogger
53
+ from shared.models import AuditFinding, AuditSeverity
54
+
55
+ from .base import BaseEngine, EngineResult
56
+
57
+
58
+ if TYPE_CHECKING:
59
+ from mind.governance.audit_context import AuditorContext
60
+
61
+
62
+ logger = getLogger(__name__)
63
+
64
+ # Providers are infrastructure. They must not appear in model.yaml.
65
+ _KNOWN_PROVIDERS = {"anthropic", "openai", "deepseek", "ollama", "azure", "mistral"}
66
+
67
+ # Cognitive role names are loaded fail-closed from
68
+ # .intent/taxonomies/cognitive_roles.yaml (ADR-068 taxonomy pattern). See
69
+ # load_cognitive_roles for the contract; the gate never carries a literal
70
+ # role set, so role declarations land by editing the taxonomy, not this file.
71
+
72
+ _REQUIRED_TOP_LEVEL = {"id", "version", "role", "success_criteria"}
73
+ _REQUIRED_INPUT_SUBFIELDS = {"required"}
74
+ _REQUIRED_OUTPUT_SUBFIELDS = {"format"}
75
+
76
+ _VOCABULARY_CHECK_TYPES = frozenset(
77
+ {
78
+ "vocabulary_projection_consistency",
79
+ "vocabulary_canonical_format",
80
+ "vocabulary_authoritative_paths",
81
+ }
82
+ )
83
+
84
+ _GOVERNANCE_CHECK_TYPES = frozenset(
85
+ {
86
+ "all_rules_mapped",
87
+ "namespace_has_drainer",
88
+ "namespace_manifest_completeness",
89
+ "fs_operations_completeness",
90
+ }
91
+ )
92
+
93
+ _AUTO_REMEDIATION_REL = ".intent/enforcement/remediation/auto_remediation.yaml"
94
+ _RULES_DIR_REL = ".intent/rules"
95
+ _DRAINER_REGISTRY_REL = ".intent/enforcement/quarantine/drainer_registry.yaml"
96
+ _NAMESPACE_MANIFEST_REL = ".intent/governance/namespace_manifest.yaml"
97
+ _NAMESPACE_GOVERNED_ROOTS = (".intent", ".specs")
98
+ _MAPPING_KEY_RE = re.compile(r"^ ([a-z][a-z0-9_.]+):$", re.MULTILINE)
99
+
100
+ _REQUIRED_VOCAB_COLUMNS = ("term", "definition", "not", "authoritative_paper")
101
+ _GOVERNED_ROOTS = (".specs", ".intent")
102
+ _TABLE_SEPARATOR_RE = re.compile(r"^\|[\s\-|]+\|$")
103
+
104
+
105
+ def _split_table_row(row: str) -> list[str]:
106
+ """Parse one Markdown pipe-table row into stripped cells.
107
+
108
+ ``"| foo | bar |"`` → ``["foo", "bar"]``. Leading/trailing whitespace and
109
+ the outer pipes are stripped before splitting on ``|``.
110
+ """
111
+ stripped = row.strip().strip("|")
112
+ return [cell.strip() for cell in stripped.split("|")]
113
+
114
+
115
+ def _parse_canonical_terms(
116
+ paper: Path,
117
+ ) -> tuple[list[dict[str, str]], str | None]:
118
+ """Parse the canonical-section table into a list of term dicts.
119
+
120
+ Returns ``(terms, error)``. On any parse failure returns ``([], error)``.
121
+ Each term dict has the four required column keys; rows with fewer than
122
+ four cells are skipped (the canonical_format check reports them).
123
+ """
124
+ if not paper.is_file():
125
+ return [], f"Canonical paper missing: {paper}"
126
+ try:
127
+ text = paper.read_text(encoding="utf-8")
128
+ except OSError as exc:
129
+ return [], f"Cannot read canonical paper {paper}: {exc}"
130
+
131
+ rng = locate_canonical_section(text)
132
+ if rng is None:
133
+ return [], f"Canonical heading not found in {paper}"
134
+ start, end = rng
135
+ section_lines = text.splitlines()[start:end]
136
+ table_rows = [line for line in section_lines if line.lstrip().startswith("|")]
137
+ if len(table_rows) < 3:
138
+ return [], (
139
+ f"Canonical table needs header, separator, and at least one data "
140
+ f"row; found {len(table_rows)} pipe row(s)."
141
+ )
142
+
143
+ sep_indices = [
144
+ i for i, row in enumerate(table_rows) if _TABLE_SEPARATOR_RE.match(row.strip())
145
+ ]
146
+ if not sep_indices:
147
+ return [], "Canonical table has no separator row."
148
+ sep_idx = sep_indices[0]
149
+ if sep_idx == 0:
150
+ return [], "Separator row precedes header in canonical table."
151
+
152
+ terms: list[dict[str, str]] = []
153
+ for row in table_rows[sep_idx + 1 :]:
154
+ cells = _split_table_row(row)
155
+ if len(cells) < len(_REQUIRED_VOCAB_COLUMNS):
156
+ continue
157
+ terms.append(
158
+ {
159
+ "term": cells[0],
160
+ "definition": cells[1],
161
+ "not": cells[2],
162
+ "authoritative_paper": normalize_vocabulary_cell(cells[3]),
163
+ }
164
+ )
165
+ return terms, None
166
+
167
+
168
+ # -----------------------------------------------------------------------------
169
+ # Vocabulary check functions (module-level — pure, no instance state).
170
+ # Kept out of ArtifactGateEngine so the class stays under modularity limits.
171
+ # -----------------------------------------------------------------------------
172
+
173
+ _ENGINE_ID = "artifact_gate"
174
+
175
+
176
+ # ID: 7e3b9c2f-4a18-4d65-b083-1f5a8c6e2d40
177
+ def _result_to_findings(
178
+ result: EngineResult, check_type: str, engine_id: str
179
+ ) -> list[AuditFinding]:
180
+ """Convert an EngineResult into AuditFindings for context-level dispatch.
181
+
182
+ ADR-076 D3. The repo-level check_* functions return EngineResult
183
+ (their per-file dispatch shape); ``verify_context`` must return
184
+ ``list[AuditFinding]`` per the rule_executor contract for
185
+ context-level rules. Severity is a placeholder — rule_executor
186
+ overwrites it from the rule's declared enforcement.
187
+ """
188
+ if result.ok:
189
+ return []
190
+ findings: list[AuditFinding] = []
191
+ for v in result.violations:
192
+ if isinstance(v, dict):
193
+ msg = str(v.get("message", ""))
194
+ details = dict(v.get("details") or {})
195
+ else:
196
+ msg = str(v)
197
+ details = {}
198
+ findings.append(
199
+ AuditFinding(
200
+ check_id=f"{engine_id}.{check_type}",
201
+ severity=AuditSeverity.INFO,
202
+ message=msg,
203
+ file_path="repo",
204
+ context=details,
205
+ )
206
+ )
207
+ return findings
208
+
209
+
210
+ def _vocab_result(check: str, violations: list[str]) -> EngineResult:
211
+ """EngineResult builder for vocabulary checks.
212
+
213
+ Vocabulary checks span multiple files (paper + projection) so the
214
+ message references the check_type, not a single file_path.
215
+ """
216
+ if not violations:
217
+ return EngineResult(
218
+ ok=True,
219
+ message=f"artifact_gate[{check}]: passed.",
220
+ violations=[],
221
+ engine_id=_ENGINE_ID,
222
+ )
223
+ return EngineResult(
224
+ ok=False,
225
+ message=f"artifact_gate[{check}]: {len(violations)} violation(s).",
226
+ violations=violations,
227
+ engine_id=_ENGINE_ID,
228
+ )
229
+
230
+
231
+ def _validate_authoritative_path(
232
+ term: str, path: str, repo_root: Path, source: str
233
+ ) -> list[str]:
234
+ """Return violation strings for a single term's authoritative_paper value."""
235
+ if not path:
236
+ return [f"{source} term '{term}': authoritative_paper is empty."]
237
+ if not any(path.startswith(root + "/") for root in _GOVERNED_ROOTS):
238
+ return [
239
+ f"{source} term '{term}': authoritative_paper '{path}' must "
240
+ f"start with one of {list(_GOVERNED_ROOTS)} followed by '/'."
241
+ ]
242
+ if not (repo_root / path).is_file():
243
+ return [
244
+ f"{source} term '{term}': authoritative_paper '{path}' does not "
245
+ "resolve to an existing file."
246
+ ]
247
+ return []
248
+
249
+
250
+ def _check_projection_consistency(repo_root: Path, check: str) -> EngineResult:
251
+ """Cross-check canonical Markdown section against the JSON projection."""
252
+ proj = load_vocabulary_projection(repo_root)
253
+ if isinstance(proj, VocabularyProjectionError):
254
+ return _vocab_result(check, [f"Projection broken: {proj.reason}"])
255
+ assert isinstance(proj, VocabularyProjection)
256
+
257
+ paper = repo_root / VOCABULARY_PAPER_REL
258
+ canonical_terms, parse_err = _parse_canonical_terms(paper)
259
+ if parse_err:
260
+ return _vocab_result(check, [parse_err])
261
+
262
+ canonical_names = {t["term"] for t in canonical_terms}
263
+ projection_names = {t.term for t in proj.terms}
264
+
265
+ violations: list[str] = []
266
+ for name in sorted(canonical_names - projection_names):
267
+ violations.append(
268
+ f"Canonical term '{name}' is absent from projection {VOCABULARY_JSON_REL}."
269
+ )
270
+ for name in sorted(projection_names - canonical_names):
271
+ violations.append(
272
+ f"Projection term '{name}' is absent from canonical section "
273
+ f"in {VOCABULARY_PAPER_REL}."
274
+ )
275
+
276
+ recomputed = compute_canonical_section_hash(repo_root)
277
+ if recomputed is not None and recomputed != proj.source_hash:
278
+ violations.append(
279
+ "source_hash mismatch: projection has "
280
+ f"'{proj.source_hash[:12]}', canonical section currently hashes "
281
+ f"to '{recomputed[:12]}'. Regenerate the projection via "
282
+ "sync_vocabulary."
283
+ )
284
+
285
+ return _vocab_result(check, violations)
286
+
287
+
288
+ def _check_canonical_format(repo_root: Path, check: str) -> EngineResult:
289
+ """Validate the structural shape of the canonical-section Markdown table."""
290
+ from shared.infrastructure.intent.vocabulary_projection import CANONICAL_HEADING
291
+
292
+ paper = repo_root / VOCABULARY_PAPER_REL
293
+ if not paper.is_file():
294
+ return _vocab_result(
295
+ check, [f"Canonical paper missing: {VOCABULARY_PAPER_REL}"]
296
+ )
297
+
298
+ text = paper.read_text(encoding="utf-8")
299
+ lines = text.splitlines()
300
+
301
+ violations: list[str] = []
302
+ heading_count = sum(1 for line in lines if line.rstrip() == CANONICAL_HEADING)
303
+ if heading_count == 0:
304
+ violations.append(f"Canonical heading '{CANONICAL_HEADING}' not found.")
305
+ return _vocab_result(check, violations)
306
+ if heading_count > 1:
307
+ violations.append(
308
+ f"Canonical heading appears {heading_count} times; expected exactly 1."
309
+ )
310
+
311
+ rng = locate_canonical_section(text)
312
+ if rng is None:
313
+ violations.append("Canonical section could not be located.")
314
+ return _vocab_result(check, violations)
315
+ start, end = rng
316
+ section_lines = lines[start:end]
317
+
318
+ table_rows = [line for line in section_lines if line.lstrip().startswith("|")]
319
+ if not table_rows:
320
+ violations.append(
321
+ "No Markdown table found in canonical section (no rows starting with '|')."
322
+ )
323
+ return _vocab_result(check, violations)
324
+
325
+ sep_indices = [
326
+ i for i, row in enumerate(table_rows) if _TABLE_SEPARATOR_RE.match(row.strip())
327
+ ]
328
+ if not sep_indices:
329
+ violations.append("No separator row matching r'^\\|[\\s\\-|]+\\|$' found.")
330
+ return _vocab_result(check, violations)
331
+ if len(sep_indices) > 1:
332
+ violations.append(
333
+ f"Found {len(sep_indices)} separator rows in canonical section; "
334
+ "expected exactly 1 (nested table not allowed)."
335
+ )
336
+
337
+ sep_idx = sep_indices[0]
338
+ if sep_idx == 0:
339
+ violations.append("Separator row precedes any header row.")
340
+ return _vocab_result(check, violations)
341
+
342
+ header_cells = _split_table_row(table_rows[sep_idx - 1])
343
+ first_four = [c.lower() for c in header_cells[: len(_REQUIRED_VOCAB_COLUMNS)]]
344
+ if first_four != list(_REQUIRED_VOCAB_COLUMNS):
345
+ violations.append(
346
+ "Header columns must start with "
347
+ f"{list(_REQUIRED_VOCAB_COLUMNS)} in that order; "
348
+ f"got {first_four}."
349
+ )
350
+
351
+ data_rows = table_rows[sep_idx + 1 :]
352
+ for i, row in enumerate(data_rows, start=1):
353
+ cells = _split_table_row(row)
354
+ if len(cells) < len(_REQUIRED_VOCAB_COLUMNS):
355
+ violations.append(
356
+ f"Row {i}: has {len(cells)} cell(s); requires at least "
357
+ f"{len(_REQUIRED_VOCAB_COLUMNS)}."
358
+ )
359
+ continue
360
+ for col_idx, col_name in enumerate(_REQUIRED_VOCAB_COLUMNS):
361
+ if not cells[col_idx]:
362
+ violations.append(f"Row {i}: column '{col_name}' is empty.")
363
+ for cell in cells:
364
+ if "<" in cell and ">" in cell:
365
+ violations.append(f"Row {i}: cell contains HTML markup: '{cell[:60]}'.")
366
+ break
367
+ if "![" in cell:
368
+ violations.append(
369
+ f"Row {i}: cell contains an inline image: '{cell[:60]}'."
370
+ )
371
+ break
372
+
373
+ return _vocab_result(check, violations)
374
+
375
+
376
+ def _check_authoritative_paths(repo_root: Path, check: str) -> EngineResult:
377
+ """Verify each term's authoritative_paper resolves under a governed root."""
378
+ paper = repo_root / VOCABULARY_PAPER_REL
379
+ canonical_terms, parse_err = _parse_canonical_terms(paper)
380
+ if parse_err:
381
+ return _vocab_result(check, [parse_err])
382
+ canonical_paths = {t["term"]: t["authoritative_paper"] for t in canonical_terms}
383
+
384
+ proj = load_vocabulary_projection(repo_root)
385
+ violations: list[str] = []
386
+ projection_paths: dict[str, str] = {}
387
+ if isinstance(proj, VocabularyProjectionError):
388
+ violations.append(f"Projection broken: {proj.reason}")
389
+ else:
390
+ assert isinstance(proj, VocabularyProjection)
391
+ projection_paths = {t.term: t.authoritative_paper for t in proj.terms}
392
+
393
+ for term, path in canonical_paths.items():
394
+ violations.extend(
395
+ _validate_authoritative_path(term, path, repo_root, "canonical")
396
+ )
397
+ for term, path in projection_paths.items():
398
+ violations.extend(
399
+ _validate_authoritative_path(term, path, repo_root, "projection")
400
+ )
401
+
402
+ for term in sorted(set(canonical_paths) & set(projection_paths)):
403
+ if canonical_paths[term] != projection_paths[term]:
404
+ violations.append(
405
+ f"Term '{term}': projection authoritative_paper "
406
+ f"'{projection_paths[term]}' != canonical "
407
+ f"'{canonical_paths[term]}'."
408
+ )
409
+
410
+ return _vocab_result(check, violations)
411
+
412
+
413
+ # ID: 7d1a2c8e-4b3f-4d52-a6e1-9c2b8d4e1f7a
414
+ def _check_all_rules_mapped(repo_root: Path, check: str) -> EngineResult:
415
+ """Verify every active reporting rule has an entry in auto_remediation.yaml.
416
+
417
+ ADR-066: rules with no remediation-map entry produce a silent
418
+ abandoned-finding re-emission loop. Scope is reporting rules only
419
+ — blocking rules fire pre-commit and do not enter the audit loop.
420
+ """
421
+ map_file = repo_root / _AUTO_REMEDIATION_REL
422
+ rules_dir = repo_root / _RULES_DIR_REL
423
+
424
+ if not map_file.exists():
425
+ return EngineResult(
426
+ ok=False,
427
+ message=f"artifact_gate[{check}]: auto_remediation.yaml missing at {map_file}",
428
+ violations=[f"Configuration error: {_AUTO_REMEDIATION_REL} not found"],
429
+ engine_id=_ENGINE_ID,
430
+ )
431
+ if not rules_dir.is_dir():
432
+ return EngineResult(
433
+ ok=False,
434
+ message=f"artifact_gate[{check}]: rules dir missing at {rules_dir}",
435
+ violations=[f"Configuration error: {_RULES_DIR_REL} not found"],
436
+ engine_id=_ENGINE_ID,
437
+ )
438
+
439
+ repo = get_intent_repository()
440
+ mapped_ids: set[str] = set(
441
+ _MAPPING_KEY_RE.findall(
442
+ repo.load_text(_AUTO_REMEDIATION_REL.removeprefix(".intent/"))
443
+ )
444
+ )
445
+
446
+ unmapped: list[str] = []
447
+ for ref in sorted(repo.list_policies(), key=lambda r: r.policy_id):
448
+ if not ref.policy_id.startswith("rules/"):
449
+ continue
450
+ if ref.path.suffix != ".json":
451
+ continue
452
+ try:
453
+ doc = repo.load_document(ref.path)
454
+ except GovernanceError:
455
+ # Defensive: a malformed rule document is a separate failure mode,
456
+ # not this rule's concern. Skip silently — other validators flag it.
457
+ continue
458
+ if not isinstance(doc, dict):
459
+ continue
460
+ if doc.get("metadata", {}).get("status") != "active":
461
+ continue
462
+ for r in doc.get("rules", []) or []:
463
+ if not isinstance(r, dict):
464
+ continue
465
+ rid = r.get("id")
466
+ if not isinstance(rid, str) or not rid:
467
+ continue
468
+ if r.get("enforcement") != "reporting":
469
+ continue
470
+ if rid in mapped_ids:
471
+ continue
472
+ unmapped.append(rid)
473
+
474
+ if not unmapped:
475
+ return _vocab_result(check, [])
476
+
477
+ violations = [
478
+ f"Active reporting rule '{rid}' has no entry in {_AUTO_REMEDIATION_REL}"
479
+ for rid in sorted(unmapped)
480
+ ]
481
+ return _vocab_result(check, violations)
482
+
483
+
484
+ # ID: 5b8c2d1e-7a4f-4609-bc3a-d8e9f0a1b234
485
+ async def _check_namespace_has_drainer(
486
+ repo_root: Path,
487
+ check: str,
488
+ params: dict[str, Any],
489
+ ) -> EngineResult:
490
+ """Verify every awaiting_reaudit subject namespace has a registered drainer.
491
+
492
+ ADR-072. The check enumerates DISTINCT subject prefixes currently
493
+ held in ``awaiting_reaudit`` and compares them to the prefixes
494
+ registered in ``drainer_registry.yaml``. A prefix present in the
495
+ DB but absent from the registry is an unmapped quarantine namespace.
496
+
497
+ DB access uses the audit-driver-injected session via
498
+ ``params['_context'].db_session`` (mirrors llm_gate's pattern —
499
+ Mind layer cannot open sessions itself). If no session is injected
500
+ (e.g. IntentGuard pre-commit path), the check returns ok=True with
501
+ a deferred-to-audit-time message rather than failing — the check
502
+ is meaningful only when the live blackboard state is accessible.
503
+ """
504
+ from sqlalchemy import text
505
+
506
+ registry_file = repo_root / _DRAINER_REGISTRY_REL
507
+ if not registry_file.exists():
508
+ return EngineResult(
509
+ ok=False,
510
+ message=(
511
+ f"artifact_gate[{check}]: drainer_registry.yaml missing at "
512
+ f"{registry_file}"
513
+ ),
514
+ violations=[f"Configuration error: {_DRAINER_REGISTRY_REL} not found"],
515
+ engine_id=_ENGINE_ID,
516
+ )
517
+
518
+ repo = get_intent_repository()
519
+ try:
520
+ registry_doc = repo.load_document(
521
+ repo.resolve_rel(_DRAINER_REGISTRY_REL.removeprefix(".intent/"))
522
+ )
523
+ except GovernanceError as exc:
524
+ return EngineResult(
525
+ ok=False,
526
+ message=f"artifact_gate[{check}]: cannot load drainer_registry.yaml: {exc}",
527
+ violations=[f"Configuration error: {_DRAINER_REGISTRY_REL} unloadable"],
528
+ engine_id=_ENGINE_ID,
529
+ )
530
+
531
+ if not isinstance(registry_doc, dict):
532
+ return EngineResult(
533
+ ok=False,
534
+ message=f"artifact_gate[{check}]: drainer_registry.yaml not a mapping",
535
+ violations=[
536
+ f"Configuration error: {_DRAINER_REGISTRY_REL} top-level "
537
+ "must be a YAML mapping"
538
+ ],
539
+ engine_id=_ENGINE_ID,
540
+ )
541
+
542
+ raw_entries = registry_doc.get("namespaces") or []
543
+ registered_normalized: set[str] = set()
544
+ for entry in raw_entries:
545
+ if not isinstance(entry, dict):
546
+ continue
547
+ prefix = entry.get("prefix")
548
+ if isinstance(prefix, str) and prefix:
549
+ # Normalise by stripping trailing colons so both "audit.violation::"
550
+ # and "audit.violation" registry forms match the bare namespace
551
+ # returned by SPLIT_PART.
552
+ registered_normalized.add(prefix.rstrip(":"))
553
+
554
+ # DB session is injected by the audit driver; absence is a
555
+ # degraded-mode signal, not a check failure (see docstring).
556
+ auditor_context = params.get("_context")
557
+ session = getattr(auditor_context, "db_session", None)
558
+ if session is None:
559
+ return EngineResult(
560
+ ok=True,
561
+ message=(
562
+ f"artifact_gate[{check}]: DB session not injected — check "
563
+ "deferred to audit-time run that injects auditor_context.db_session."
564
+ ),
565
+ violations=[],
566
+ engine_id=_ENGINE_ID,
567
+ )
568
+
569
+ result = await session.execute(
570
+ text(
571
+ """
572
+ SELECT DISTINCT SPLIT_PART(subject, '::', 1) AS namespace
573
+ FROM core.blackboard_entries
574
+ WHERE entry_type = 'finding'
575
+ AND status = 'awaiting_reaudit'
576
+ AND resolved_at IS NULL
577
+ """
578
+ )
579
+ )
580
+ quarantine_namespaces = {row[0] for row in result.fetchall() if row[0]}
581
+
582
+ unmapped = sorted(quarantine_namespaces - registered_normalized)
583
+ if not unmapped:
584
+ return EngineResult(
585
+ ok=True,
586
+ message=f"artifact_gate[{check}]: all quarantine namespaces have registered drainers.",
587
+ violations=[],
588
+ engine_id=_ENGINE_ID,
589
+ )
590
+
591
+ violations = [
592
+ f"Subject namespace '{ns}' has rows in awaiting_reaudit but no "
593
+ f"drainer is registered in {_DRAINER_REGISTRY_REL}"
594
+ for ns in unmapped
595
+ ]
596
+ return EngineResult(
597
+ ok=False,
598
+ message=(
599
+ f"artifact_gate[{check}]: {len(unmapped)} unmapped quarantine "
600
+ "namespace(s) — ADR-072 invariant violated."
601
+ ),
602
+ violations=violations,
603
+ engine_id=_ENGINE_ID,
604
+ )
605
+
606
+
607
+ # ID: 742276f9-7865-4073-a345-1256089d91c8
608
+ def _check_namespace_manifest_completeness(repo_root: Path, check: str) -> EngineResult:
609
+ """Verify every file under .intent/ and .specs/ has a manifest entry.
610
+
611
+ ADR-075 D7. The check is a structural set-difference between the
612
+ filesystem walk under the governed roots (.intent/ + .specs/) and the
613
+ paths declared in .intent/governance/namespace_manifest.yaml's
614
+ ``classifications`` list. A file present on disk with no manifest
615
+ entry is unclassified and surfaces as a violation under this rule.
616
+ """
617
+ manifest_file = repo_root / _NAMESPACE_MANIFEST_REL
618
+ if not manifest_file.exists():
619
+ return EngineResult(
620
+ ok=False,
621
+ message=(
622
+ f"artifact_gate[{check}]: namespace_manifest.yaml missing at "
623
+ f"{manifest_file}"
624
+ ),
625
+ violations=[f"Configuration error: {_NAMESPACE_MANIFEST_REL} not found"],
626
+ engine_id=_ENGINE_ID,
627
+ )
628
+
629
+ try:
630
+ manifest_doc = yaml.safe_load(manifest_file.read_text(encoding="utf-8")) or {}
631
+ except yaml.YAMLError as exc:
632
+ return EngineResult(
633
+ ok=False,
634
+ message=f"artifact_gate[{check}]: cannot parse namespace_manifest.yaml: {exc}",
635
+ violations=[f"Configuration error: {_NAMESPACE_MANIFEST_REL} unparseable"],
636
+ engine_id=_ENGINE_ID,
637
+ )
638
+
639
+ if not isinstance(manifest_doc, dict):
640
+ return EngineResult(
641
+ ok=False,
642
+ message=f"artifact_gate[{check}]: namespace_manifest.yaml not a mapping",
643
+ violations=[
644
+ f"Configuration error: {_NAMESPACE_MANIFEST_REL} top-level "
645
+ "must be a YAML mapping"
646
+ ],
647
+ engine_id=_ENGINE_ID,
648
+ )
649
+
650
+ classified: set[str] = set()
651
+ for entry in manifest_doc.get("classifications") or []:
652
+ if not isinstance(entry, dict):
653
+ continue
654
+ path = entry.get("path")
655
+ if isinstance(path, str) and path:
656
+ classified.add(path)
657
+
658
+ fs_paths: set[str] = set()
659
+ for root_name in _NAMESPACE_GOVERNED_ROOTS:
660
+ root_dir = repo_root / root_name
661
+ if not root_dir.is_dir():
662
+ continue
663
+ for p in root_dir.rglob("*"):
664
+ if p.is_file():
665
+ fs_paths.add(str(p.relative_to(repo_root)))
666
+
667
+ unclassified = sorted(fs_paths - classified)
668
+ if not unclassified:
669
+ return _vocab_result(check, [])
670
+
671
+ violations = [
672
+ f"File '{path}' has no entry in {_NAMESPACE_MANIFEST_REL}"
673
+ for path in unclassified
674
+ ]
675
+ return _vocab_result(check, violations)
676
+
677
+
678
+ # ID: f68dc080-017d-42ee-8580-095b44bf668d
679
+ def _check_fs_operations_completeness(repo_root: Path, check: str) -> EngineResult:
680
+ """Verify the filesystem-operation taxonomy covers the runtime FS surface.
681
+
682
+ ADR-077 §3. Three-part introspective set-difference against the loaded
683
+ taxonomy:
684
+
685
+ - Every public method on pathlib.Path must appear in operations.pathlib_path
686
+ (auto-discovery; absence is a finding). Stale declarations whose names no
687
+ longer resolve to runtime Path methods are also surfaced.
688
+ - Every entry in operations.watched must still resolve to a callable in its
689
+ module (catches stdlib rename/removal or third-party absence). Mixed
690
+ namespaces (os/shutil/tempfile/builtin open) are not auto-discovered —
691
+ §3 explicitly excludes that.
692
+ - The taxonomy's declared python_version must match runtime major.minor
693
+ (§5 determinism anchor).
694
+
695
+ Remediation is manual_review per §3: classifying a newly surfaced call is a
696
+ governance decision (read vs write), not auto-remediation territory.
697
+ """
698
+ try:
699
+ taxonomy = load_filesystem_operations(repo_root)
700
+ except FilesystemOperationTaxonomyError as exc:
701
+ return EngineResult(
702
+ ok=False,
703
+ message=(
704
+ f"artifact_gate[{check}]: filesystem-operation taxonomy failed to load."
705
+ ),
706
+ violations=[f"Taxonomy load error: {exc}"],
707
+ engine_id=_ENGINE_ID,
708
+ )
709
+
710
+ violations: list[str] = []
711
+
712
+ declared_pathlib = {entry.name for entry in taxonomy.pathlib_path}
713
+ discovered_pathlib = {
714
+ name
715
+ for name, _ in inspect.getmembers(Path, predicate=callable)
716
+ if not name.startswith("_")
717
+ }
718
+ for name in sorted(discovered_pathlib - declared_pathlib):
719
+ violations.append(
720
+ f"pathlib.Path public method '{name}' is present in the runtime "
721
+ f"but absent from filesystem_operations.yaml "
722
+ f"operations.pathlib_path — classify it (manual_review)."
723
+ )
724
+ for name in sorted(declared_pathlib - discovered_pathlib):
725
+ violations.append(
726
+ f"filesystem_operations.yaml operations.pathlib_path declares "
727
+ f"'{name}' which is not a public method on pathlib.Path in this "
728
+ f"runtime — remove the stale entry or re-verify against the "
729
+ f"declared python_version (ADR-077 §5)."
730
+ )
731
+
732
+ for entry in sorted(taxonomy.watched, key=lambda e: e.name):
733
+ ok, reason = _resolve_watched_call(entry.name)
734
+ if not ok:
735
+ violations.append(
736
+ f"watched filesystem operation '{entry.name}' does not resolve "
737
+ f"to a callable: {reason} — update the taxonomy or restore the "
738
+ f"sanctioned import (manual_review)."
739
+ )
740
+
741
+ runtime_version = f"{sys.version_info.major}.{sys.version_info.minor}"
742
+ if taxonomy.python_version != runtime_version:
743
+ violations.append(
744
+ f"filesystem_operations.yaml declares python_version "
745
+ f"'{taxonomy.python_version}' but runtime is '{runtime_version}'; "
746
+ f"re-verify classifications against {runtime_version} and update "
747
+ f"the taxonomy header (ADR-077 §5)."
748
+ )
749
+
750
+ return _vocab_result(check, violations)
751
+
752
+
753
+ # ID: 269e97f0-0707-479c-b005-a3c23cd8a017
754
+ def _resolve_watched_call(qualified: str) -> tuple[bool, str]:
755
+ """Resolve a dotted module.attr name (or bare builtin) to a callable.
756
+
757
+ Returns ``(True, "")`` on success; ``(False, reason)`` on any failure.
758
+ Bare names (no dot) resolve against ``builtins`` — e.g. ``"open"`` →
759
+ ``builtins.open``. Dotted names import the leftmost segment and walk
760
+ ``getattr`` through the remainder.
761
+ """
762
+ if "." not in qualified:
763
+ target = getattr(builtins, qualified, None)
764
+ if target is None:
765
+ return False, f"builtins.{qualified} not found"
766
+ if not callable(target):
767
+ return False, f"builtins.{qualified} is not callable"
768
+ return True, ""
769
+
770
+ head, _, rest = qualified.partition(".")
771
+ try:
772
+ module = importlib.import_module(head)
773
+ except ImportError as exc:
774
+ return False, f"cannot import module '{head}': {exc}"
775
+
776
+ obj: Any = module
777
+ path_so_far = head
778
+ for part in rest.split("."):
779
+ obj = getattr(obj, part, None)
780
+ path_so_far = f"{path_so_far}.{part}"
781
+ if obj is None:
782
+ return False, f"{path_so_far} not found"
783
+ if not callable(obj):
784
+ return False, f"{qualified} is not callable"
785
+ return True, ""
786
+
787
+
788
+ # ID: 69841a82-0920-480c-94cb-d5e4b6cb50dd
789
+ class ArtifactGateEngine(BaseEngine):
790
+ """
791
+ Constitutional validator for PromptModel artifact manifests.
792
+
793
+ Checks model.yaml files for structural completeness and abstraction
794
+ boundary compliance. All checks are purely mechanical — no LLM involved.
795
+ """
796
+
797
+ engine_id = "artifact_gate"
798
+
799
+ @classmethod
800
+ # ID: 3c7b9d12-58a4-4e6f-8c1d-2a9e6b4f3d70
801
+ def is_context_level_for(cls, check_type: str | None) -> bool:
802
+ """
803
+ ADR-076 D1/D2/D3: artifact_gate is mixed-mode.
804
+
805
+ Seven repo-level check_types (vocabulary projection/canonical_format/
806
+ authoritative_paths + governance all_rules_mapped/namespace_has_drainer/
807
+ namespace_manifest_completeness/fs_operations_completeness) dispatch
808
+ context-level. The three PromptModel check_types (required_fields,
809
+ no_provider_leak, role_abstraction) dispatch per-file over
810
+ var/prompts/**/model.yaml.
811
+ """
812
+ if check_type is None:
813
+ return False
814
+ return (
815
+ check_type in _VOCABULARY_CHECK_TYPES
816
+ or check_type in _GOVERNANCE_CHECK_TYPES
817
+ )
818
+
819
+ # ID: 46226873-bc5a-4258-b3c8-476b0cfc878a
820
+ async def verify(self, file_path: Path, params: dict[str, Any]) -> EngineResult:
821
+ """
822
+ Validate a model.yaml file against constitutional artifact rules.
823
+
824
+ Dispatches to a specific check based on params['check_type'].
825
+ Supported check types:
826
+ - required_fields — structural completeness
827
+ - no_provider_leak — preference field abstraction boundary
828
+ - role_abstraction — role field must be a cognitive role
829
+
830
+ Args:
831
+ file_path: Absolute path to the model.yaml being audited.
832
+ params: Rule parameters from enforcement mapping.
833
+
834
+ Returns:
835
+ EngineResult with violations list; ok=True means compliant.
836
+ """
837
+ check_type = params.get("check_type", "required_fields")
838
+
839
+ if not file_path.exists():
840
+ return EngineResult(
841
+ ok=False,
842
+ message=f"Artifact file not found: {file_path}",
843
+ violations=[f"Missing file: {file_path}"],
844
+ engine_id=self.engine_id,
845
+ )
846
+
847
+ # Dispatch vocabulary checks BEFORE the YAML load. They operate on
848
+ # Markdown + JSON, not on PromptModel manifests, and pass through
849
+ # repo-level walks rather than reading file_path as YAML.
850
+ if check_type in _VOCABULARY_CHECK_TYPES:
851
+ return self._check_vocabulary(file_path, check_type)
852
+
853
+ # Governance meta-checks (ADR-066, ADR-072): repo-level invariants
854
+ # over .intent/ content and blackboard state. Dispatched before YAML
855
+ # load for the same reason.
856
+ if check_type in _GOVERNANCE_CHECK_TYPES:
857
+ return await self._check_governance(file_path, check_type, params)
858
+
859
+ try:
860
+ raw = yaml.safe_load(file_path.read_text(encoding="utf-8")) or {}
861
+ except Exception as exc:
862
+ return EngineResult(
863
+ ok=False,
864
+ message=f"Cannot parse model.yaml: {exc}",
865
+ violations=[f"YAML parse error in {file_path}: {exc}"],
866
+ engine_id=self.engine_id,
867
+ )
868
+
869
+ if check_type == "required_fields":
870
+ return self._check_required_fields(file_path, raw)
871
+ if check_type == "no_provider_leak":
872
+ return self._check_no_provider_leak(file_path, raw)
873
+ if check_type == "role_abstraction":
874
+ return self._check_role_abstraction(file_path, raw)
875
+
876
+ return EngineResult(
877
+ ok=False,
878
+ message=f"Unknown artifact_gate check_type: {check_type}",
879
+ violations=[f"Configuration error: unknown check_type '{check_type}'"],
880
+ engine_id=self.engine_id,
881
+ )
882
+
883
+ # -------------------------------------------------------------------------
884
+ # Checks
885
+ # -------------------------------------------------------------------------
886
+
887
+ # ID: 48ae4ead-2944-4c5a-8c8f-1423aad53497
888
+ def _check_required_fields(
889
+ self, file_path: Path, manifest: dict[str, Any]
890
+ ) -> EngineResult:
891
+ """
892
+ Verify all mandatory top-level and nested fields are present and
893
+ non-empty in a model.yaml manifest.
894
+ """
895
+ violations: list[str] = []
896
+
897
+ for field in _REQUIRED_TOP_LEVEL:
898
+ if not manifest.get(field):
899
+ violations.append(f"Missing or empty required field: '{field}'")
900
+
901
+ input_block = manifest.get("input", {})
902
+ if not isinstance(input_block, dict):
903
+ violations.append("'input' must be a mapping")
904
+ else:
905
+ for sub in _REQUIRED_INPUT_SUBFIELDS:
906
+ if sub not in input_block:
907
+ violations.append(f"Missing required field: 'input.{sub}'")
908
+
909
+ output_block = manifest.get("output", {})
910
+ if not isinstance(output_block, dict):
911
+ violations.append("'output' must be a mapping")
912
+ else:
913
+ for sub in _REQUIRED_OUTPUT_SUBFIELDS:
914
+ if sub not in output_block:
915
+ violations.append(f"Missing required field: 'output.{sub}'")
916
+
917
+ return self._result(file_path, violations, "required_fields")
918
+
919
+ # ID: 33aaf189-b193-4fd9-bf4f-951098928e29
920
+ def _check_no_provider_leak(
921
+ self, file_path: Path, manifest: dict[str, Any]
922
+ ) -> EngineResult:
923
+ """
924
+ Ensure model.yaml does not reference infrastructure providers in the
925
+ model.preference field. Preference must name a capability class
926
+ (e.g. 'local', 'fast') or be absent — never a product name.
927
+ """
928
+ violations: list[str] = []
929
+
930
+ model_block = manifest.get("model", {})
931
+ if isinstance(model_block, dict):
932
+ preference = str(model_block.get("preference", "")).lower().strip()
933
+ if preference in _KNOWN_PROVIDERS:
934
+ violations.append(
935
+ f"model.preference '{preference}' names an infrastructure provider. "
936
+ "Use a capability class (e.g. 'local', 'fast') or remove the field. "
937
+ "Provider routing belongs in CognitiveService role configuration, "
938
+ "not in a prompt artifact."
939
+ )
940
+
941
+ return self._result(file_path, violations, "no_provider_leak")
942
+
943
+ # ID: b984e44a-819b-4bc7-a0d9-e4272757002c
944
+ def _check_role_abstraction(
945
+ self, file_path: Path, manifest: dict[str, Any]
946
+ ) -> EngineResult:
947
+ """
948
+ Verify the role field references a declared cognitive role, not a
949
+ product, tool, or arbitrary string.
950
+ """
951
+ violations: list[str] = []
952
+
953
+ role = str(manifest.get("role", "")).strip()
954
+ if not role:
955
+ violations.append("'role' field is missing or empty.")
956
+ else:
957
+ known_roles = load_cognitive_roles()
958
+ if role not in known_roles:
959
+ violations.append(
960
+ f"role '{role}' is not a declared cognitive role. "
961
+ f"Known roles: {sorted(known_roles)}. "
962
+ "If this is a new role, declare it in .intent/ first."
963
+ )
964
+
965
+ return self._result(file_path, violations, "role_abstraction")
966
+
967
+ # -------------------------------------------------------------------------
968
+ # Helpers
969
+ # -------------------------------------------------------------------------
970
+
971
+ def _result(
972
+ self, file_path: Path, violations: list[str], check: str
973
+ ) -> EngineResult:
974
+ """Build a standardised EngineResult for an artifact_gate check."""
975
+ if not violations:
976
+ return EngineResult(
977
+ ok=True,
978
+ message=f"artifact_gate[{check}]: {file_path.name} passed.",
979
+ violations=[],
980
+ engine_id=self.engine_id,
981
+ )
982
+ return EngineResult(
983
+ ok=False,
984
+ message=f"artifact_gate[{check}]: {len(violations)} violation(s) in {file_path.name}.",
985
+ violations=violations,
986
+ engine_id=self.engine_id,
987
+ )
988
+
989
+ # -------------------------------------------------------------------------
990
+ # Vocabulary checks (ADR-023)
991
+ # Dispatch only — the actual check functions live at module level so the
992
+ # class stays under modularity.class_too_large limits.
993
+ # -------------------------------------------------------------------------
994
+
995
+ def _check_vocabulary(self, file_path: Path, check_type: str) -> EngineResult:
996
+ """Locate the repo root from file_path and dispatch the vocabulary check."""
997
+ repo_root: Path | None = None
998
+ for parent in file_path.resolve().parents:
999
+ if (parent / ".intent").is_dir() and (parent / ".specs").is_dir():
1000
+ repo_root = parent
1001
+ break
1002
+ if repo_root is None:
1003
+ return EngineResult(
1004
+ ok=False,
1005
+ message=f"artifact_gate[{check_type}]: cannot locate repo root.",
1006
+ violations=[
1007
+ f"Configuration error: walked up from {file_path} but found "
1008
+ "no directory containing both .intent/ and .specs/."
1009
+ ],
1010
+ engine_id=self.engine_id,
1011
+ )
1012
+
1013
+ if check_type == "vocabulary_projection_consistency":
1014
+ return _check_projection_consistency(repo_root, check_type)
1015
+ if check_type == "vocabulary_canonical_format":
1016
+ return _check_canonical_format(repo_root, check_type)
1017
+ if check_type == "vocabulary_authoritative_paths":
1018
+ return _check_authoritative_paths(repo_root, check_type)
1019
+
1020
+ # Should never reach here — verify() filters check_type — but keep
1021
+ # a defensive return in case the dispatch table drifts.
1022
+ return EngineResult(
1023
+ ok=False,
1024
+ message=f"artifact_gate[{check_type}]: dispatch fall-through.",
1025
+ violations=[f"Unknown vocabulary check_type '{check_type}'"],
1026
+ engine_id=self.engine_id,
1027
+ )
1028
+
1029
+ # -------------------------------------------------------------------------
1030
+ # Governance meta-checks (ADR-066)
1031
+ # Dispatch only — the actual check functions live at module level so the
1032
+ # class stays under modularity.class_too_large limits.
1033
+ # -------------------------------------------------------------------------
1034
+
1035
+ async def _check_governance(
1036
+ self, file_path: Path, check_type: str, params: dict[str, Any]
1037
+ ) -> EngineResult:
1038
+ """Locate the repo root from file_path and dispatch the governance check.
1039
+
1040
+ Dispatcher is async because ``namespace_has_drainer`` (ADR-072 D4)
1041
+ runs a DB query via the injected auditor_context.db_session.
1042
+ ``all_rules_mapped`` remains synchronous internally.
1043
+ """
1044
+ repo_root: Path | None = None
1045
+ for parent in file_path.resolve().parents:
1046
+ if (parent / ".intent").is_dir() and (parent / ".specs").is_dir():
1047
+ repo_root = parent
1048
+ break
1049
+ if repo_root is None:
1050
+ return EngineResult(
1051
+ ok=False,
1052
+ message=f"artifact_gate[{check_type}]: cannot locate repo root.",
1053
+ violations=[
1054
+ f"Configuration error: walked up from {file_path} but found "
1055
+ "no directory containing both .intent/ and .specs/."
1056
+ ],
1057
+ engine_id=self.engine_id,
1058
+ )
1059
+
1060
+ if check_type == "all_rules_mapped":
1061
+ return _check_all_rules_mapped(repo_root, check_type)
1062
+ if check_type == "namespace_has_drainer":
1063
+ return await _check_namespace_has_drainer(repo_root, check_type, params)
1064
+ if check_type == "namespace_manifest_completeness":
1065
+ return _check_namespace_manifest_completeness(repo_root, check_type)
1066
+ if check_type == "fs_operations_completeness":
1067
+ return _check_fs_operations_completeness(repo_root, check_type)
1068
+
1069
+ return EngineResult(
1070
+ ok=False,
1071
+ message=f"artifact_gate[{check_type}]: dispatch fall-through.",
1072
+ violations=[f"Unknown governance check_type '{check_type}'"],
1073
+ engine_id=self.engine_id,
1074
+ )
1075
+
1076
+ # -------------------------------------------------------------------------
1077
+ # Context-level dispatch (ADR-076 D3)
1078
+ # -------------------------------------------------------------------------
1079
+
1080
+ # ID: 5a8d2f17-3e6b-4f12-9a47-c1b8e0d5f3a9
1081
+ async def verify_context(
1082
+ self, context: AuditorContext, params: dict[str, Any]
1083
+ ) -> list[AuditFinding]:
1084
+ """Dispatch the six repo-level check_types over AuditorContext.
1085
+
1086
+ ADR-076 D3. The three vocabulary checks and three governance
1087
+ meta-checks (ADR-066/072/075) walk the whole repository — they
1088
+ ignore ``file_path`` in their per-file form. This entry point
1089
+ runs them once per audit with ``context.repo_path`` as the
1090
+ repo root, instead of forcing the dispatcher to walk a synthetic
1091
+ file just so ``verify(file_path, ...)`` could parent-traverse
1092
+ back to the repo root.
1093
+
1094
+ Returns ``list[AuditFinding]`` (the rule_executor contract for
1095
+ context-level), not ``EngineResult``. ``rule_executor`` overwrites
1096
+ severity per the rule's enforcement; check_id is derived from the
1097
+ check_type so the audit verdict surfaces the right rule.
1098
+ """
1099
+ check_type = params.get("check_type")
1100
+ if check_type is None:
1101
+ return [
1102
+ AuditFinding(
1103
+ check_id=f"{self.engine_id}.error",
1104
+ severity=AuditSeverity.BLOCK,
1105
+ message=(
1106
+ f"{self.engine_id}.verify_context invoked without "
1107
+ "params['check_type']."
1108
+ ),
1109
+ file_path="none",
1110
+ )
1111
+ ]
1112
+
1113
+ repo_root = context.repo_path
1114
+
1115
+ if check_type in _VOCABULARY_CHECK_TYPES:
1116
+ if check_type == "vocabulary_projection_consistency":
1117
+ result = _check_projection_consistency(repo_root, check_type)
1118
+ elif check_type == "vocabulary_canonical_format":
1119
+ result = _check_canonical_format(repo_root, check_type)
1120
+ elif check_type == "vocabulary_authoritative_paths":
1121
+ result = _check_authoritative_paths(repo_root, check_type)
1122
+ else:
1123
+ result = EngineResult(
1124
+ ok=False,
1125
+ message=f"{self.engine_id}[{check_type}]: dispatch fall-through.",
1126
+ violations=[f"Unknown vocabulary check_type '{check_type}'"],
1127
+ engine_id=self.engine_id,
1128
+ )
1129
+ elif check_type in _GOVERNANCE_CHECK_TYPES:
1130
+ if check_type == "all_rules_mapped":
1131
+ result = _check_all_rules_mapped(repo_root, check_type)
1132
+ elif check_type == "namespace_has_drainer":
1133
+ merged_params = {**params, "_context": context}
1134
+ result = await _check_namespace_has_drainer(
1135
+ repo_root, check_type, merged_params
1136
+ )
1137
+ elif check_type == "namespace_manifest_completeness":
1138
+ result = _check_namespace_manifest_completeness(repo_root, check_type)
1139
+ elif check_type == "fs_operations_completeness":
1140
+ result = _check_fs_operations_completeness(repo_root, check_type)
1141
+ else:
1142
+ result = EngineResult(
1143
+ ok=False,
1144
+ message=f"{self.engine_id}[{check_type}]: dispatch fall-through.",
1145
+ violations=[f"Unknown governance check_type '{check_type}'"],
1146
+ engine_id=self.engine_id,
1147
+ )
1148
+ else:
1149
+ return [
1150
+ AuditFinding(
1151
+ check_id=f"{self.engine_id}.{check_type}.error",
1152
+ severity=AuditSeverity.BLOCK,
1153
+ message=(
1154
+ f"{self.engine_id}.verify_context received non-context-level "
1155
+ f"check_type '{check_type}'. Per-file check_types route "
1156
+ "through verify(file_path, ...)."
1157
+ ),
1158
+ file_path="none",
1159
+ )
1160
+ ]
1161
+
1162
+ return _result_to_findings(result, check_type, self.engine_id)
1163
+
1164
+ # The actual vocabulary check implementations live as module-level
1165
+ # functions (_check_projection_consistency, _check_canonical_format,
1166
+ # _check_authoritative_paths, _validate_authoritative_path, _vocab_result)
1167
+ # above the class declaration. Keeping them out of the class keeps it
1168
+ # under the modularity.class_too_large threshold.