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,1142 @@
1
+ # src/body/atomic/fix_actions.py
2
+
3
+ """
4
+ Atomic Fix Actions - Code Remediation
5
+
6
+ Each action does ONE thing and returns ActionResult.
7
+ Actions are composable, auditable, and constitutionally governed.
8
+
9
+ Constitutional Alignment:
10
+ - Boundary: Uses CoreContext for repo_path (no direct settings access)
11
+ - Circularity Fix: Feature-level imports are performed inside functions.
12
+ - Remediation: Each action declares which audit check_ids it fixes via remediates=[].
13
+ ViolationRemediatorWorker uses this to close the autonomous audit loop.
14
+ """
15
+
16
+ from __future__ import annotations
17
+
18
+ import re
19
+ import time
20
+ from pathlib import Path
21
+ from typing import TYPE_CHECKING, Any
22
+
23
+ from body.atomic.registry import ActionCategory, register_action
24
+ from mind.governance.violation_report import ConstitutionalViolationError
25
+ from shared.action_types import ActionImpact, ActionResult
26
+ from shared.atomic_action import atomic_action
27
+ from shared.logger import getLogger
28
+
29
+
30
+ if TYPE_CHECKING:
31
+ from shared.context import CoreContext
32
+
33
+ logger = getLogger(__name__)
34
+
35
+ _RUNTIME_DIR_PATTERN = re.compile(
36
+ r"""["'](?:reports|logs)/|/\s*["'](?:reports|logs)["']"""
37
+ )
38
+
39
+
40
+ def _error_data(exc: Exception, **extra: Any) -> dict[str, Any]:
41
+ """Build ActionResult.data for an exception, preserving structure when available.
42
+
43
+ ConstitutionalViolationError carries the full list[ViolationReport] that
44
+ IntentGuard produced; we serialize it via to_dict() so rule_name, path,
45
+ and source_policy survive the persistence hop into proposal.execution_results.
46
+ Any other exception type degrades cleanly to the legacy flat {"error": str(e)}
47
+ shape, so this helper is safe to adopt per-action without coordinated changes
48
+ elsewhere.
49
+ """
50
+ if isinstance(exc, ConstitutionalViolationError):
51
+ return {**exc.to_dict(), **extra}
52
+ return {"error": str(exc), **extra}
53
+
54
+
55
+ @register_action(
56
+ action_id="fix.format",
57
+ description="Format code with ruff format and ruff check",
58
+ category=ActionCategory.FIX,
59
+ policies=["rules/code/purity"],
60
+ remediates=["style.formatter_required"],
61
+ )
62
+ @atomic_action(
63
+ action_id="fix.format",
64
+ intent="Atomic action for action_format_code",
65
+ impact=ActionImpact.WRITE_CODE,
66
+ policies=["atomic_actions"],
67
+ )
68
+ # ID: 5c3ede6c-23e1-4b92-8a00-7b2046eac121
69
+ async def action_format_code(
70
+ file_path: str | None = None, write: bool = False, **kwargs
71
+ ) -> ActionResult:
72
+ """Format code using ruff format and ruff check."""
73
+ start = time.time()
74
+ from body.self_healing.code_style_service import format_code
75
+
76
+ try:
77
+ format_code(path=file_path, write=write)
78
+ except Exception as e:
79
+ return ActionResult(
80
+ action_id="fix.format",
81
+ ok=False,
82
+ data={"error": str(e), "write": write},
83
+ duration_sec=time.time() - start,
84
+ )
85
+ return ActionResult(
86
+ action_id="fix.format",
87
+ ok=True,
88
+ data={"formatted": True, "write": write},
89
+ duration_sec=time.time() - start,
90
+ )
91
+
92
+
93
+ @register_action(
94
+ action_id="fix.imports",
95
+ description="Sort and group imports according to PEP 8 / Constitutional standards",
96
+ category=ActionCategory.FIX,
97
+ policies=["rules/code/purity"],
98
+ remediates=["style.import_order", "style.no_unused_imports"],
99
+ )
100
+ @atomic_action(
101
+ action_id="fix.imports",
102
+ intent="Standardize Python import blocks using Ruff",
103
+ impact=ActionImpact.WRITE_METADATA,
104
+ policies=["atomic_actions"],
105
+ )
106
+ # ID: d5879178-fdfe-4d8b-b6a6-f887f8e9500b
107
+ async def action_fix_imports(write: bool = False, **kwargs) -> ActionResult:
108
+ """Sort and group Python imports according to constitutional style policy."""
109
+ start = time.time()
110
+ from shared.utils.subprocess_utils import run_poetry_command
111
+
112
+ target_path = "src/"
113
+ try:
114
+ cmd = ["ruff", "check", target_path, "--select", "I"]
115
+ if write:
116
+ cmd.append("--fix")
117
+ cmd.append("--exit-zero")
118
+
119
+ run_poetry_command(f"Sorting imports in {target_path}", cmd)
120
+
121
+ return ActionResult(
122
+ action_id="fix.imports",
123
+ ok=True,
124
+ data={"status": "completed", "target": target_path, "write": write},
125
+ duration_sec=time.time() - start,
126
+ )
127
+ except Exception as e:
128
+ return ActionResult(
129
+ action_id="fix.imports",
130
+ ok=False,
131
+ data={"error": str(e)},
132
+ duration_sec=time.time() - start,
133
+ )
134
+
135
+
136
+ @register_action(
137
+ action_id="fix.headers",
138
+ description="Fix file headers to match constitutional standards",
139
+ category=ActionCategory.FIX,
140
+ policies=["rules/code/purity"],
141
+ remediates=["layout.src_module_header"],
142
+ )
143
+ @atomic_action(
144
+ action_id="fix.headers",
145
+ intent="Atomic action for action_fix_headers",
146
+ impact=ActionImpact.WRITE_CODE,
147
+ policies=["atomic_actions"],
148
+ )
149
+ # ID: 7d43d782-739a-47d3-ae3e-c36047ad9867
150
+ async def action_fix_headers(
151
+ core_context: CoreContext, write: bool = False, **kwargs
152
+ ) -> ActionResult:
153
+ """Fix file headers."""
154
+ from body.self_healing.header_service import fix_headers_internal
155
+
156
+ return await fix_headers_internal(core_context, write=write)
157
+
158
+
159
+ @register_action(
160
+ action_id="fix.ids",
161
+ description="Add missing ID tags to functions and classes",
162
+ category=ActionCategory.FIX,
163
+ policies=["rules/code/purity"],
164
+ remediates=["purity.stable_id_anchor", "linkage.assign_ids"],
165
+ )
166
+ @atomic_action(
167
+ action_id="fix.ids",
168
+ intent="Atomic action for action_fix_ids",
169
+ impact=ActionImpact.WRITE_CODE,
170
+ policies=["atomic_actions"],
171
+ )
172
+ # ID: 854f5010-aaec-4f14-8d72-3e3070334c54
173
+ async def action_fix_ids(
174
+ core_context: CoreContext, write: bool = False, **kwargs
175
+ ) -> ActionResult:
176
+ """Fix missing ID tags."""
177
+ from body.self_healing.id_tagging_service import fix_ids_internal
178
+
179
+ return await fix_ids_internal(core_context, write=write)
180
+
181
+
182
+ @register_action(
183
+ action_id="fix.duplicate_ids",
184
+ description="Resolve duplicate UUID collisions across source files",
185
+ category=ActionCategory.FIX,
186
+ policies=["rules/code/linkage"],
187
+ remediates=["linkage.duplicate_ids"],
188
+ )
189
+ @atomic_action(
190
+ action_id="fix.duplicate_ids",
191
+ intent="Resolve duplicate ID conflicts by regenerating UUIDs",
192
+ impact=ActionImpact.WRITE_METADATA,
193
+ policies=["id_uniqueness_check"],
194
+ )
195
+ # ID: 2e7f8a1b-c3d4-4e5f-96a0-b1d2e3f4a5b6
196
+ async def action_fix_duplicate_ids(
197
+ core_context: CoreContext, write: bool = False, **kwargs
198
+ ) -> ActionResult:
199
+ """Resolve duplicate UUID collisions in source files."""
200
+ from body.self_healing.duplicate_id_service import fix_duplicate_ids_internal
201
+
202
+ return await fix_duplicate_ids_internal(core_context, write=write)
203
+
204
+
205
+ @register_action(
206
+ action_id="fix.logging",
207
+ description="Replace print statements with proper logging",
208
+ category=ActionCategory.FIX,
209
+ policies=["rules/code/purity"],
210
+ remediates=["logic.logging.standard_only"],
211
+ )
212
+ @atomic_action(
213
+ action_id="fix.logging",
214
+ intent="Atomic action for action_fix_logging",
215
+ impact=ActionImpact.WRITE_CODE,
216
+ policies=["atomic_actions"],
217
+ )
218
+ # ID: 7661f20f-3d41-4501-a0ab-c30804d29ad0
219
+ async def action_fix_logging(
220
+ core_context: CoreContext, write: bool = False, **kwargs
221
+ ) -> ActionResult:
222
+ """Fix logging violations."""
223
+ start = time.time()
224
+ from body.self_healing.logging_service import LoggingFixer
225
+
226
+ if core_context.file_handler is None:
227
+ return ActionResult(
228
+ action_id="fix.logging",
229
+ ok=False,
230
+ data={"error": "file_handler not initialized"},
231
+ duration_sec=time.time() - start,
232
+ )
233
+ fixer = LoggingFixer(
234
+ repo_root=core_context.git_service.repo_path,
235
+ file_handler=core_context.file_handler,
236
+ dry_run=not write,
237
+ )
238
+ try:
239
+ result = fixer.fix_all()
240
+ except Exception as e:
241
+ return ActionResult(
242
+ action_id="fix.logging",
243
+ ok=False,
244
+ data={"error": str(e)},
245
+ duration_sec=time.time() - start,
246
+ )
247
+ return ActionResult(
248
+ action_id="fix.logging",
249
+ ok=True,
250
+ data=result,
251
+ duration_sec=time.time() - start,
252
+ )
253
+
254
+
255
+ @register_action(
256
+ action_id="fix.placeholders",
257
+ description="Replace FUTURE/PENDING placeholders",
258
+ category=ActionCategory.FIX,
259
+ policies=["rules/code/purity"],
260
+ remediates=["caps.no_placeholder_text"],
261
+ )
262
+ @atomic_action(
263
+ action_id="fix.placeholders",
264
+ intent="Atomic action for action_fix_placeholders",
265
+ impact=ActionImpact.WRITE_CODE,
266
+ policies=["atomic_actions"],
267
+ )
268
+ # ID: fc997ae2-05e6-4823-81dd-e645afee2a7e
269
+ async def action_fix_placeholders(
270
+ core_context: CoreContext, write: bool = False, **kwargs
271
+ ) -> ActionResult:
272
+ """Replace placeholder comments.
273
+
274
+ Two invocation modes:
275
+
276
+ 1. Targeted (autonomous loop): caller supplies ``file_path`` in kwargs
277
+ (ViolationRemediatorWorker threads this through ``ProposalAction.parameters``).
278
+ The action operates on exactly that file. This matches the action's
279
+ ``"safe"`` classification — bounded scope per invocation.
280
+
281
+ 2. Sweep (legacy CLI): no ``file_path`` supplied. The action walks every
282
+ ``*.py`` under ``src/``. This mode is preserved for backwards
283
+ compatibility with ``cli.commands.fix_placeholders`` but emits a
284
+ warning so any remaining unbounded autonomous callers are visible.
285
+
286
+ On IntentGuard rejection the handler uses ``_error_data`` to persist the
287
+ structured ``ConstitutionalViolationError.to_dict()`` payload — ``rule_name``,
288
+ ``path``, ``source_policy`` survive into ``proposal.execution_results``
289
+ instead of collapsing to a flat error string.
290
+ """
291
+ start = time.time()
292
+ from body.self_healing.placeholder_fixer_service import (
293
+ fix_placeholders_in_content,
294
+ )
295
+
296
+ repo_root: Path = core_context.git_service.repo_path
297
+ file_path = kwargs.get("file_path")
298
+
299
+ # ---- Targeted mode ------------------------------------------------------
300
+ if file_path:
301
+ try:
302
+ target_rel = str(file_path).lstrip("./")
303
+ target_abs = (repo_root / target_rel).resolve()
304
+
305
+ # Keep the action bounded to src/ — refuse anything outside it.
306
+ src_root = (repo_root / "src").resolve()
307
+ try:
308
+ target_abs.relative_to(src_root)
309
+ except ValueError:
310
+ return ActionResult(
311
+ action_id="fix.placeholders",
312
+ ok=False,
313
+ data={
314
+ "error": f"Target outside src/ scope: {target_rel}",
315
+ "file_path": target_rel,
316
+ },
317
+ duration_sec=time.time() - start,
318
+ )
319
+
320
+ if not target_abs.is_file() or target_abs.suffix != ".py":
321
+ return ActionResult(
322
+ action_id="fix.placeholders",
323
+ ok=False,
324
+ data={
325
+ "error": f"Target is not a .py file: {target_rel}",
326
+ "file_path": target_rel,
327
+ },
328
+ duration_sec=time.time() - start,
329
+ )
330
+
331
+ original = target_abs.read_text(encoding="utf-8")
332
+ fixed = fix_placeholders_in_content(original)
333
+
334
+ if fixed == original:
335
+ return ActionResult(
336
+ action_id="fix.placeholders",
337
+ ok=True,
338
+ data={
339
+ "files_affected": 0,
340
+ "written": False,
341
+ "file_path": target_rel,
342
+ "note": "no placeholders found",
343
+ },
344
+ duration_sec=time.time() - start,
345
+ )
346
+
347
+ if write:
348
+ core_context.file_handler.write_runtime_text(target_rel, fixed)
349
+
350
+ return ActionResult(
351
+ action_id="fix.placeholders",
352
+ ok=True,
353
+ data={
354
+ "files_affected": 1,
355
+ "written": write,
356
+ "file_path": target_rel,
357
+ },
358
+ duration_sec=time.time() - start,
359
+ )
360
+ except Exception as e:
361
+ return ActionResult(
362
+ action_id="fix.placeholders",
363
+ ok=False,
364
+ data=_error_data(e, file_path=str(file_path)),
365
+ duration_sec=time.time() - start,
366
+ )
367
+
368
+ # ---- Sweep mode (CLI callers only) -------------------------------------
369
+ logger.warning(
370
+ "fix.placeholders invoked in sweep mode (no file_path). "
371
+ "This mode is reserved for CLI callers; autonomous callers MUST "
372
+ "supply file_path to stay within their declared impact scope."
373
+ )
374
+
375
+ files_modified = 0
376
+ try:
377
+ src_dir = repo_root / "src"
378
+ for py_file in src_dir.rglob("*.py"):
379
+ original = py_file.read_text(encoding="utf-8")
380
+ fixed = fix_placeholders_in_content(original)
381
+ if fixed != original:
382
+ if write:
383
+ rel_path = str(py_file.relative_to(repo_root))
384
+ core_context.file_handler.write_runtime_text(rel_path, fixed)
385
+ files_modified += 1
386
+ return ActionResult(
387
+ action_id="fix.placeholders",
388
+ ok=True,
389
+ data={"files_affected": files_modified, "written": write, "mode": "sweep"},
390
+ duration_sec=time.time() - start,
391
+ )
392
+ except Exception as e:
393
+ return ActionResult(
394
+ action_id="fix.placeholders",
395
+ ok=False,
396
+ data=_error_data(e, mode="sweep"),
397
+ duration_sec=time.time() - start,
398
+ )
399
+
400
+
401
+ @register_action(
402
+ action_id="fix.atomic_actions",
403
+ description="Fix atomic actions pattern violations",
404
+ category=ActionCategory.FIX,
405
+ policies=["rules/architecture/atomic_actions"],
406
+ remediates=["architecture.atomic_actions.must_return_action_result"],
407
+ )
408
+ @atomic_action(
409
+ action_id="fix.atomic_actions",
410
+ intent="Atomic action for action_fix_atomic_actions",
411
+ impact=ActionImpact.WRITE_CODE,
412
+ policies=["atomic_actions"],
413
+ )
414
+ # ID: 525fff82-3c87-4847-83a5-346ad9c78534
415
+ async def action_fix_atomic_actions(
416
+ core_context: CoreContext, write: bool = False, **kwargs
417
+ ) -> ActionResult:
418
+ """Fix atomic action patterns."""
419
+ from body.evaluators.atomic_actions_evaluator import AtomicActionsEvaluator
420
+ from body.evaluators.atomic_actions_rules import AtomicActionViolation
421
+ from body.self_healing.atomic_actions_fixer import fix_file_violations
422
+
423
+ start_time = time.time()
424
+ root_path = core_context.git_service.repo_path
425
+
426
+ evaluator = AtomicActionsEvaluator(context=core_context)
427
+ try:
428
+ result_wrapper = await evaluator.execute(repo_root=root_path)
429
+ data = result_wrapper.data
430
+ except Exception as e:
431
+ return ActionResult(
432
+ action_id="fix.atomic_actions",
433
+ ok=False,
434
+ data={"error": str(e)},
435
+ duration_sec=time.time() - start_time,
436
+ )
437
+
438
+ if not data["violations"]:
439
+ return ActionResult(
440
+ action_id="fix.atomic_actions", ok=True, data={"violations_fixed": 0}
441
+ )
442
+
443
+ violations = [
444
+ AtomicActionViolation(
445
+ file_path=root_path / v["file"],
446
+ function_name=v["function"],
447
+ rule_id=v["rule"],
448
+ message=v["message"],
449
+ severity=v["severity"],
450
+ line_number=v["line"],
451
+ suggested_fix=v.get("suggested_fix"),
452
+ )
453
+ for v in data["violations"]
454
+ ]
455
+
456
+ violations_by_file = {}
457
+ for v in violations:
458
+ violations_by_file.setdefault(v.file_path, []).append(v)
459
+
460
+ fixes_applied = 0
461
+ files_modified = 0
462
+ files_failed = 0
463
+
464
+ for file_path, file_violations in violations_by_file.items():
465
+ try:
466
+ source = file_path.read_text(encoding="utf-8")
467
+ modified_source = fix_file_violations(source, file_violations, file_path)
468
+ if modified_source != source:
469
+ if write:
470
+ rel_path = str(file_path.relative_to(root_path))
471
+ core_context.file_handler.write_runtime_text(
472
+ rel_path, modified_source
473
+ )
474
+ files_modified += 1
475
+ fixes_applied += len(file_violations)
476
+ except Exception as e:
477
+ logger.error("Error fixing %s: %s", file_path, e)
478
+ files_failed += 1
479
+
480
+ return ActionResult(
481
+ action_id="fix.atomic_actions",
482
+ ok=files_failed == 0,
483
+ data={
484
+ "files_modified": files_modified,
485
+ "violations_fixed": fixes_applied,
486
+ "files_failed": files_failed,
487
+ },
488
+ duration_sec=time.time() - start_time,
489
+ )
490
+
491
+
492
+ @register_action(
493
+ action_id="fix.docstrings",
494
+ description="Generate and inject missing docstrings using AI",
495
+ category=ActionCategory.FIX,
496
+ policies=["rules/code/purity"],
497
+ remediates=["purity.docstrings.required"],
498
+ )
499
+ @atomic_action(
500
+ action_id="fix.docstrings",
501
+ intent="Autonomously generate missing docstrings via Coder LLM role",
502
+ impact=ActionImpact.WRITE_CODE,
503
+ policies=["atomic_actions"],
504
+ )
505
+ # ID: a3f91c7d-5e2b-4d8a-b6f0-c1e2d3f4a5b7
506
+ async def action_fix_docstrings(
507
+ core_context: CoreContext,
508
+ file_path: str | None = None,
509
+ write: bool = False,
510
+ limit: int = 0,
511
+ **kwargs,
512
+ ) -> ActionResult:
513
+ """Generate and inject missing docstrings using the Coder LLM role.
514
+
515
+ Two invocation modes:
516
+
517
+ 1. Targeted (autonomous loop): caller supplies ``file_path`` in kwargs,
518
+ e.g. via ProposalExecutor expanding ``actions[i].parameters.file_path``.
519
+ Only symbols inside that file are evaluated. Mirrors the pattern
520
+ used by ``action_format_code`` and ``action_fix_modularity``.
521
+ 2. Sweep (legacy CLI): no ``file_path`` supplied. The action walks every
522
+ symbol in the knowledge graph, as before. ``limit`` caps the symbol
523
+ count in sweep mode; 0 means unlimited and is ignored when
524
+ ``file_path`` is set (matches body's fix_docstrings contract).
525
+
526
+ Before this change the action discarded ``**kwargs``, so every targeted
527
+ proposal silently degraded to a full-tree sweep — one proposal hammered
528
+ Ollama for the whole codebase regardless of its declared scope.
529
+ """
530
+ start = time.time()
531
+ from body.self_healing.docstring_service import fix_docstrings
532
+
533
+ try:
534
+ await fix_docstrings(
535
+ context=core_context, write=write, limit=limit, file_path=file_path
536
+ )
537
+ except Exception as e:
538
+ return ActionResult(
539
+ action_id="fix.docstrings",
540
+ ok=False,
541
+ data={
542
+ "error": str(e),
543
+ "write": write,
544
+ "file_path": file_path,
545
+ "limit": limit,
546
+ },
547
+ duration_sec=time.time() - start,
548
+ )
549
+ return ActionResult(
550
+ action_id="fix.docstrings",
551
+ ok=True,
552
+ data={"write": write, "file_path": file_path, "limit": limit},
553
+ duration_sec=time.time() - start,
554
+ )
555
+
556
+
557
+ @register_action(
558
+ action_id="fix.purge_legacy_tags",
559
+ description="Remove obsolete tag formats (e.g. legacy '# owner:', '# Tag:' lines)",
560
+ category=ActionCategory.FIX,
561
+ policies=["tag_hygiene"],
562
+ remediates=["metadata.no_legacy_tags"],
563
+ )
564
+ @atomic_action(
565
+ action_id="fix.purge_legacy_tags",
566
+ intent="Remove legacy tag formats from source files",
567
+ impact=ActionImpact.WRITE_METADATA,
568
+ policies=["atomic_actions"],
569
+ )
570
+ # ID: 3c8d2f15-7e94-4a6b-b1c5-9d3f7e2a4b8d
571
+ async def action_fix_purge_legacy_tags(
572
+ core_context: CoreContext,
573
+ write: bool = False,
574
+ **kwargs,
575
+ ) -> ActionResult:
576
+ """Wrap body.self_healing.purge_legacy_tags_service.purge_legacy_tags."""
577
+ start = time.time()
578
+ from body.self_healing.purge_legacy_tags_service import purge_legacy_tags
579
+
580
+ try:
581
+ removed = await purge_legacy_tags(core_context, dry_run=not write)
582
+ except Exception as e:
583
+ return ActionResult(
584
+ action_id="fix.purge_legacy_tags",
585
+ ok=False,
586
+ data={"error": str(e), "write": write},
587
+ duration_sec=time.time() - start,
588
+ )
589
+ return ActionResult(
590
+ action_id="fix.purge_legacy_tags",
591
+ ok=True,
592
+ data={"removed": removed, "write": write},
593
+ duration_sec=time.time() - start,
594
+ )
595
+
596
+
597
+ @register_action(
598
+ action_id="fix.capability_tagging",
599
+ description="Tag untagged public capabilities using LLM-suggested names",
600
+ category=ActionCategory.FIX,
601
+ policies=["capability_tagging"],
602
+ remediates=["symbols.capability_required"],
603
+ )
604
+ @atomic_action(
605
+ action_id="fix.capability_tagging",
606
+ intent="Tag untagged capabilities via LLM",
607
+ impact=ActionImpact.WRITE_METADATA,
608
+ policies=["atomic_actions"],
609
+ )
610
+ # ID: 7b3c8d51-9e2a-4f7b-a1e6-5c4d8b2f9a3e
611
+ async def action_fix_capability_tagging(
612
+ core_context: CoreContext,
613
+ write: bool = False,
614
+ limit: int = 0,
615
+ **kwargs,
616
+ ) -> ActionResult:
617
+ """Tag untagged capabilities via the will-layer naming agent.
618
+
619
+ Wraps will.self_healing.capability_tagging_service.main_async. The
620
+ body→will lazy import matches the precedent in
621
+ proposal_lifecycle_actions.py — capability_tagging's CapabilityTaggerAgent
622
+ legitimately depends on will/orchestration, so it stays in will/.
623
+ """
624
+ start = time.time()
625
+ from shared.infrastructure.database.session_manager import get_session
626
+ from will.self_healing.capability_tagging_service import main_async as tag
627
+
628
+ try:
629
+ await tag(
630
+ session_factory=get_session,
631
+ cognitive_service=core_context.cognitive_service,
632
+ knowledge_service=core_context.knowledge_service,
633
+ write=write,
634
+ dry_run=not write,
635
+ limit=limit,
636
+ )
637
+ except Exception as e:
638
+ return ActionResult(
639
+ action_id="fix.capability_tagging",
640
+ ok=False,
641
+ data={"error": str(e), "write": write, "limit": limit},
642
+ duration_sec=time.time() - start,
643
+ )
644
+ return ActionResult(
645
+ action_id="fix.capability_tagging",
646
+ ok=True,
647
+ data={"write": write, "limit": limit},
648
+ duration_sec=time.time() - start,
649
+ )
650
+
651
+
652
+ @register_action(
653
+ action_id="fix.vulture_heal",
654
+ description="Surgically remove Vulture-identified dead code using LLM analysis",
655
+ category=ActionCategory.FIX,
656
+ policies=["dead_code"],
657
+ remediates=["workflow.dead_code_check"],
658
+ )
659
+ @atomic_action(
660
+ action_id="fix.vulture_heal",
661
+ intent="Remove dead code findings via LLM",
662
+ impact=ActionImpact.WRITE_CODE,
663
+ policies=["atomic_actions"],
664
+ )
665
+ # ID: 5a2e9c4f-1b8d-43a7-92e6-7f3c1d4b8e5a
666
+ async def action_fix_vulture_heal(
667
+ core_context: CoreContext,
668
+ write: bool = False,
669
+ **kwargs,
670
+ ) -> ActionResult:
671
+ """Surgical dead-code cleanup via the relocated body.self_healing.vulture_healer."""
672
+ start = time.time()
673
+ from body.self_healing.vulture_healer import heal_dead_code
674
+
675
+ try:
676
+ await heal_dead_code(
677
+ context=core_context,
678
+ file_handler=core_context.file_handler,
679
+ repo_root=core_context.git_service.repo_path,
680
+ write=write,
681
+ )
682
+ except Exception as e:
683
+ return ActionResult(
684
+ action_id="fix.vulture_heal",
685
+ ok=False,
686
+ data={"error": str(e), "write": write},
687
+ duration_sec=time.time() - start,
688
+ )
689
+ return ActionResult(
690
+ action_id="fix.vulture_heal",
691
+ ok=True,
692
+ data={"write": write},
693
+ duration_sec=time.time() - start,
694
+ )
695
+
696
+
697
+ @register_action(
698
+ action_id="fix.settings_access",
699
+ description="Refactor settings.* imports to dependency injection via CoreContext",
700
+ category=ActionCategory.FIX,
701
+ policies=["dependency_injection"],
702
+ remediates=["architecture.body.no_settings_import"],
703
+ )
704
+ @atomic_action(
705
+ action_id="fix.settings_access",
706
+ intent="Refactor settings imports to DI via CoreContext",
707
+ impact=ActionImpact.WRITE_CODE,
708
+ policies=["atomic_actions"],
709
+ )
710
+ # ID: 9e8d2c1f-3a6b-4d57-b9e2-1f4a8c5d3e0b
711
+ async def action_fix_settings_access(
712
+ core_context: CoreContext,
713
+ write: bool = False,
714
+ layers: list[str] | None = None,
715
+ **kwargs,
716
+ ) -> ActionResult:
717
+ """Refactor settings imports to dependency injection across given layers.
718
+
719
+ Wraps body.maintenance.refactor_settings_access; translates the
720
+ atomic-action convention (`write`) to the wrapped function's
721
+ (`dry_run = not write`), passes repo_path from CoreContext, and
722
+ surfaces the per-layer summary on data.results.
723
+ """
724
+ start = time.time()
725
+ from body.maintenance.refactor_settings_access import refactor_settings_access
726
+
727
+ try:
728
+ results = await refactor_settings_access(
729
+ repo_path=core_context.git_service.repo_path,
730
+ layers=layers,
731
+ dry_run=not write,
732
+ )
733
+ except Exception as e:
734
+ return ActionResult(
735
+ action_id="fix.settings_access",
736
+ ok=False,
737
+ data={"error": str(e), "write": write, "layers": layers},
738
+ duration_sec=time.time() - start,
739
+ )
740
+ return ActionResult(
741
+ action_id="fix.settings_access",
742
+ ok=True,
743
+ data={"results": results, "write": write, "layers": layers},
744
+ duration_sec=time.time() - start,
745
+ )
746
+
747
+
748
+ _PATH_RESOLVER_PROPS: dict[str, str] = {"reports": "reports_dir", "logs": "logs_dir"}
749
+
750
+
751
+ def _is_target_constant(node: Any) -> bool:
752
+ import ast as _ast
753
+
754
+ return (
755
+ isinstance(node, _ast.Constant)
756
+ and isinstance(node.value, str)
757
+ and node.value in _PATH_RESOLVER_PROPS
758
+ )
759
+
760
+
761
+ def _is_embedded_target_constant(node: Any) -> tuple[bool, str, str]:
762
+ """Detect a Constant str whose value starts with ``reports/`` or ``logs/``.
763
+
764
+ Returns ``(matched, prop_name, remainder)`` where ``prop_name`` is the
765
+ matching PathResolver property (``reports_dir``/``logs_dir``) and
766
+ ``remainder`` is the substring after the prefix-and-slash. ``remainder``
767
+ may be empty for bare cases where only the prefix-and-slash is present.
768
+ """
769
+ import ast as _ast
770
+
771
+ if not (isinstance(node, _ast.Constant) and isinstance(node.value, str)):
772
+ return False, "", ""
773
+ for prefix, prop_name in _PATH_RESOLVER_PROPS.items():
774
+ head = f"{prefix}/"
775
+ if node.value.startswith(head):
776
+ return True, prop_name, node.value[len(head) :]
777
+ return False, "", ""
778
+
779
+
780
+ def _has_target_descendant(node: Any) -> bool:
781
+ """True if `node` or any descendant BinOp has a matching constant operand.
782
+
783
+ Used to skip outer BinOps in chained path-division expressions where the
784
+ runtime directory name appears as an intermediate operand. Detects both
785
+ leaf-target forms and embedded-target forms (where the runtime directory
786
+ name is the prefix of a longer Constant) so nested rewrites do not overlap.
787
+ """
788
+ import ast as _ast
789
+
790
+ for sub in _ast.walk(node):
791
+ if isinstance(sub, _ast.BinOp) and isinstance(sub.op, _ast.Div):
792
+ if _is_target_constant(sub.left) or _is_target_constant(sub.right):
793
+ return True
794
+ if _is_embedded_target_constant(sub.right)[0]:
795
+ return True
796
+ return False
797
+
798
+
799
+ def _insert_path_resolver_import(source: str) -> str:
800
+ """Insert ``from shared.path_resolver import PathResolver`` into the module.
801
+
802
+ Idempotent — returns `source` unchanged if the import is already present.
803
+ Inserts in alphabetically correct position within the existing first-party
804
+ import block (CORE roots: api, body, cli, mind, shared, will). Falls back
805
+ to appending after the last top-level Import/ImportFrom, or after a module
806
+ docstring if no imports exist.
807
+ """
808
+ import ast as _ast
809
+
810
+ import_line = "from shared.path_resolver import PathResolver"
811
+ if import_line in source:
812
+ return source
813
+
814
+ try:
815
+ import asttokens as _asttokens
816
+
817
+ atok = _asttokens.ASTTokens(source, parse=True)
818
+ except (SyntaxError, ImportError):
819
+ return source
820
+ tree = atok.tree
821
+
822
+ new_module = "shared.path_resolver"
823
+ first_party_roots = {"api", "body", "cli", "mind", "shared", "will"}
824
+
825
+ # Absolute first-party ImportFrom siblings — same isort group as the new
826
+ # import. Relative imports (level > 0) are excluded; they form a separate
827
+ # group below first-party.
828
+ siblings: list[Any] = []
829
+ for node in tree.body:
830
+ if (
831
+ isinstance(node, _ast.ImportFrom)
832
+ and node.module
833
+ and node.level == 0
834
+ and node.module.split(".")[0] in first_party_roots
835
+ ):
836
+ siblings.append(node)
837
+
838
+ if siblings:
839
+ insert_after = None
840
+ insert_before = None
841
+ for node in siblings:
842
+ if node.module < new_module:
843
+ insert_after = node
844
+ else:
845
+ insert_before = node
846
+ break
847
+ if insert_after is not None:
848
+ _, end = atok.get_text_range(insert_after)
849
+ return source[:end] + "\n" + import_line + source[end:]
850
+ if insert_before is not None:
851
+ start, _ = atok.get_text_range(insert_before)
852
+ return source[:start] + import_line + "\n" + source[start:]
853
+
854
+ # No first-party siblings — fall back to appending after the last import.
855
+ last_import = None
856
+ for node in tree.body:
857
+ if isinstance(node, (_ast.Import, _ast.ImportFrom)):
858
+ last_import = node
859
+
860
+ if last_import is not None:
861
+ _, end = atok.get_text_range(last_import)
862
+ return source[:end] + "\n" + import_line + source[end:]
863
+
864
+ # No imports: insert after module docstring if present, else at top.
865
+ insert_at = 0
866
+ if (
867
+ tree.body
868
+ and isinstance(tree.body[0], _ast.Expr)
869
+ and isinstance(tree.body[0].value, _ast.Constant)
870
+ and isinstance(tree.body[0].value.value, str)
871
+ ):
872
+ _, insert_at = atok.get_text_range(tree.body[0])
873
+
874
+ return source[:insert_at] + "\n\n" + import_line + "\n" + source[insert_at:]
875
+
876
+
877
+ def _transform_path_resolver(source: str) -> tuple[str, int]:
878
+ """Deterministic AST rewrite of hardcoded runtime dir literals.
879
+
880
+ Walks the source for ``BinOp(op=Div)`` nodes where one operand is a
881
+ ``Constant("reports")`` or ``Constant("logs")``. Each leaf match is
882
+ replaced with ``PathResolver.from_repo(<other operand>).<dir>`` where
883
+ ``<dir>`` is ``reports_dir`` or ``logs_dir`` respectively. Outer BinOps
884
+ that contain a deeper match are skipped (leaf-only strategy) so source
885
+ edits never overlap. Chained path-division expressions with a runtime
886
+ directory name as an intermediate operand are handled by the leaf
887
+ rewrite alone.
888
+
889
+ Returns ``(new_source, replacement_count)``. If the source fails to
890
+ parse, returns ``(source, 0)``.
891
+ """
892
+ import ast as _ast
893
+
894
+ try:
895
+ import asttokens as _asttokens
896
+
897
+ atok = _asttokens.ASTTokens(source, parse=True)
898
+ except (SyntaxError, ImportError):
899
+ return source, 0
900
+ tree = atok.tree
901
+
902
+ replacements: list[tuple[int, int, str]] = []
903
+ for node in _ast.walk(tree):
904
+ if not (isinstance(node, _ast.BinOp) and isinstance(node.op, _ast.Div)):
905
+ continue
906
+
907
+ # Form 0 — leaf target: runtime directory name as a standalone Constant operand.
908
+ if _is_target_constant(node.right):
909
+ target, other = node.right, node.left
910
+ prop_name = _PATH_RESOLVER_PROPS[target.value]
911
+ remainder = ""
912
+ elif _is_target_constant(node.left):
913
+ target, other = node.left, node.right
914
+ prop_name = _PATH_RESOLVER_PROPS[target.value]
915
+ remainder = ""
916
+ else:
917
+ # Form 1 — embedded target: runtime directory name as the prefix of
918
+ # a longer Constant on the right operand.
919
+ matched, prop_name, remainder = _is_embedded_target_constant(node.right)
920
+ if not matched:
921
+ continue
922
+ other = node.left
923
+
924
+ if _has_target_descendant(other):
925
+ continue
926
+
927
+ other_text = atok.get_text(other)
928
+ base = f"PathResolver.from_repo({other_text}).{prop_name}"
929
+ replacement_text = f'{base} / "{remainder}"' if remainder else base
930
+ start, end = atok.get_text_range(node)
931
+ replacements.append((start, end, replacement_text))
932
+
933
+ if not replacements:
934
+ return source, 0
935
+
936
+ replacements.sort(key=lambda r: r[0], reverse=True)
937
+ new_source = source
938
+ for start, end, text in replacements:
939
+ new_source = new_source[:start] + text + new_source[end:]
940
+
941
+ new_source = _insert_path_resolver_import(new_source)
942
+ return new_source, len(replacements)
943
+
944
+
945
+ @register_action(
946
+ action_id="fix.path_resolver",
947
+ description="Rewrite hardcoded runtime directory literals to PathResolver accesses",
948
+ category=ActionCategory.FIX,
949
+ policies=["rules/architecture/path_access"],
950
+ remediates=["architecture.path_access.no_hardcoded_runtime_dirs"],
951
+ )
952
+ @atomic_action(
953
+ action_id="fix.path_resolver",
954
+ intent="Rewrite hardcoded runtime directory path construction to PathResolver",
955
+ impact=ActionImpact.WRITE_CODE,
956
+ policies=["atomic_actions"],
957
+ )
958
+ # ID: f5c8e2a4-9b7d-4a1e-b0f3-6c2d4e8a9b15
959
+ async def action_fix_path_resolver(
960
+ core_context: CoreContext, write: bool = False, **kwargs
961
+ ) -> ActionResult:
962
+ """Rewrite hardcoded runtime directory string literals to use PathResolver.
963
+
964
+ Two invocation modes (mirrors action_fix_placeholders):
965
+
966
+ 1. Targeted (autonomous loop): caller supplies ``file_path`` in kwargs.
967
+ The action operates on exactly that file. Bounded scope per
968
+ invocation — matches the action's per-file impact contract.
969
+
970
+ 2. Sweep (CLI / debugging): no ``file_path`` supplied. The action walks
971
+ every ``*.py`` under ``src/`` containing a runtime directory path literal
972
+ that the rule's regex flags, and rewrites each.
973
+
974
+ The rewrite is fully deterministic — no LLM call. ``_transform_path_resolver``
975
+ parses the file with ``ast``/``asttokens`` and replaces leaf
976
+ ``BinOp(op=Div)`` nodes whose operand is ``Constant("reports")`` or
977
+ ``Constant("logs")`` with ``PathResolver.from_repo(<other>).<dir>``.
978
+ The required ``from shared.path_resolver import PathResolver`` is
979
+ inserted into the file's imports if not already present.
980
+
981
+ Dry-run (``write=False``): returns a unified diff in ``data["diff"]``.
982
+ """
983
+ import difflib
984
+
985
+ start = time.time()
986
+ repo_root: Path = core_context.git_service.repo_path
987
+ file_path = kwargs.get("file_path")
988
+
989
+ def _build_diff(original: str, rewritten: str, rel: str) -> str:
990
+ return "".join(
991
+ difflib.unified_diff(
992
+ original.splitlines(keepends=True),
993
+ rewritten.splitlines(keepends=True),
994
+ fromfile=f"a/{rel}",
995
+ tofile=f"b/{rel}",
996
+ n=3,
997
+ )
998
+ )
999
+
1000
+ # ---- Targeted mode ------------------------------------------------------
1001
+ if file_path:
1002
+ try:
1003
+ target_rel = str(file_path).lstrip("./")
1004
+ target_abs = (repo_root / target_rel).resolve()
1005
+
1006
+ src_root = (repo_root / "src").resolve()
1007
+ try:
1008
+ target_abs.relative_to(src_root)
1009
+ except ValueError:
1010
+ return ActionResult(
1011
+ action_id="fix.path_resolver",
1012
+ ok=False,
1013
+ data={
1014
+ "error": f"Target outside src/ scope: {target_rel}",
1015
+ "file_path": target_rel,
1016
+ },
1017
+ duration_sec=time.time() - start,
1018
+ )
1019
+
1020
+ if not target_abs.is_file() or target_abs.suffix != ".py":
1021
+ return ActionResult(
1022
+ action_id="fix.path_resolver",
1023
+ ok=False,
1024
+ data={
1025
+ "error": f"Target is not a .py file: {target_rel}",
1026
+ "file_path": target_rel,
1027
+ },
1028
+ duration_sec=time.time() - start,
1029
+ )
1030
+
1031
+ original = target_abs.read_text(encoding="utf-8")
1032
+
1033
+ if not _RUNTIME_DIR_PATTERN.search(original):
1034
+ return ActionResult(
1035
+ action_id="fix.path_resolver",
1036
+ ok=True,
1037
+ data={
1038
+ "files_affected": 0,
1039
+ "written": False,
1040
+ "file_path": target_rel,
1041
+ "note": "no path_access literals matched",
1042
+ },
1043
+ duration_sec=time.time() - start,
1044
+ )
1045
+
1046
+ rewritten, n_replacements = _transform_path_resolver(original)
1047
+
1048
+ if n_replacements == 0 or rewritten == original:
1049
+ return ActionResult(
1050
+ action_id="fix.path_resolver",
1051
+ ok=True,
1052
+ data={
1053
+ "files_affected": 0,
1054
+ "written": False,
1055
+ "file_path": target_rel,
1056
+ "note": (
1057
+ "regex matched but no AST-level path-construction "
1058
+ "BinOp/Div sites — likely string literal in a "
1059
+ "non-path-construction context (e.g. exclude list, "
1060
+ "docstring example)"
1061
+ ),
1062
+ },
1063
+ duration_sec=time.time() - start,
1064
+ )
1065
+
1066
+ if write:
1067
+ core_context.file_handler.write_runtime_text(target_rel, rewritten)
1068
+
1069
+ return ActionResult(
1070
+ action_id="fix.path_resolver",
1071
+ ok=True,
1072
+ data={
1073
+ "files_affected": 1,
1074
+ "replacements": n_replacements,
1075
+ "written": write,
1076
+ "file_path": target_rel,
1077
+ "diff": _build_diff(original, rewritten, target_rel),
1078
+ },
1079
+ duration_sec=time.time() - start,
1080
+ )
1081
+ except Exception as e:
1082
+ return ActionResult(
1083
+ action_id="fix.path_resolver",
1084
+ ok=False,
1085
+ data=_error_data(e, file_path=str(file_path)),
1086
+ duration_sec=time.time() - start,
1087
+ )
1088
+
1089
+ # ---- Sweep mode ---------------------------------------------------------
1090
+ logger.warning(
1091
+ "fix.path_resolver invoked in sweep mode (no file_path). "
1092
+ "This mode is reserved for CLI callers; autonomous callers MUST "
1093
+ "supply file_path to stay within their declared impact scope."
1094
+ )
1095
+
1096
+ files_modified = 0
1097
+ total_replacements = 0
1098
+ files_failed = 0
1099
+ files_skipped_no_match = 0
1100
+
1101
+ try:
1102
+ src_dir = repo_root / "src"
1103
+ for py_file in src_dir.rglob("*.py"):
1104
+ try:
1105
+ content = py_file.read_text(encoding="utf-8")
1106
+ if not _RUNTIME_DIR_PATTERN.search(content):
1107
+ files_skipped_no_match += 1
1108
+ continue
1109
+
1110
+ rewritten, n_replacements = _transform_path_resolver(content)
1111
+ if n_replacements == 0 or rewritten == content:
1112
+ continue
1113
+
1114
+ rel_path = str(py_file.relative_to(repo_root))
1115
+ if write:
1116
+ core_context.file_handler.write_runtime_text(rel_path, rewritten)
1117
+ files_modified += 1
1118
+ total_replacements += n_replacements
1119
+ except Exception as e:
1120
+ logger.warning("fix.path_resolver: failed on %s: %s", py_file, e)
1121
+ files_failed += 1
1122
+
1123
+ return ActionResult(
1124
+ action_id="fix.path_resolver",
1125
+ ok=files_failed == 0,
1126
+ data={
1127
+ "files_affected": files_modified,
1128
+ "replacements": total_replacements,
1129
+ "files_failed": files_failed,
1130
+ "files_skipped_no_match": files_skipped_no_match,
1131
+ "written": write,
1132
+ "mode": "sweep",
1133
+ },
1134
+ duration_sec=time.time() - start,
1135
+ )
1136
+ except Exception as e:
1137
+ return ActionResult(
1138
+ action_id="fix.path_resolver",
1139
+ ok=False,
1140
+ data=_error_data(e, mode="sweep"),
1141
+ duration_sec=time.time() - start,
1142
+ )