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
cli/commands/daemon.py ADDED
@@ -0,0 +1,908 @@
1
+ # src/cli/commands/daemon.py
2
+ """
3
+ Daemon Command - Background Worker Lifecycle Management.
4
+
5
+ Provides CLI entry points for starting long-running background workers.
6
+ Sanctuary (bootstrap) calls `start` once on system initialisation; systemd
7
+ invokes `core-admin daemon start` as the entry for `core-daemon.service`.
8
+
9
+ Constitutional standing:
10
+ - This module IS the activation boundary for self-scheduling workers.
11
+ - Workers started here manage their own asyncio loops via run_loop().
12
+ - This module does not schedule — it starts and monitors.
13
+
14
+ LAYER: cli/commands — CLI entry point for Will orchestration.
15
+
16
+ Bootstrap path — the `start` command and `_run_daemon` import body/shared
17
+ directly because this is what systemd executes to bring the daemon (and
18
+ therefore the API) into existence. A thin-client implementation would be
19
+ a chicken-and-egg deadlock — the daemon must be running for
20
+ /v1/daemon/start to be reachable. Per ADR-058 D3, the API's
21
+ POST /v1/daemon/start (operator-triggered remote restart) and this CLI's
22
+ `daemon start` (systemd-triggered bootstrap) are deliberately separate
23
+ paths.
24
+ """
25
+
26
+ from __future__ import annotations
27
+
28
+ import asyncio
29
+ import fcntl
30
+ import importlib
31
+ import logging
32
+ import os
33
+ import re
34
+ import signal
35
+ import subprocess
36
+ import sys
37
+ from pathlib import Path
38
+ from typing import Any
39
+
40
+ import typer
41
+ from rich.console import Console
42
+ from rich.table import Table
43
+
44
+ # Bootstrap imports — see module docstring.
45
+ from cli.utils import async_command
46
+ from shared.infrastructure.intent.operational_config import load_operational_config
47
+ from shared.logger import getLogger
48
+
49
+
50
+ logger = getLogger(__name__)
51
+ console = Console()
52
+
53
+ daemon_app = typer.Typer(help="Background worker daemon management.")
54
+
55
+ # Default interval for one-shot workers that lack run_loop (seconds).
56
+ _CFG = load_operational_config().daemon
57
+
58
+ # Singleton-instance machinery.
59
+ # var/run/core-daemon.pid holds the PID of the running daemon; an exclusive
60
+ # fcntl lock on the same fd is the actual mutex (the file's contents are
61
+ # advisory — kernel-released flock is the source of truth, so crashes never
62
+ # leave stale locks).
63
+ _PID_FILE_REL = Path("var/run/core-daemon.pid")
64
+ # ADR-081 Step 2c — the unit list is computed dynamically (see _systemd_units).
65
+ # Base set always present.
66
+ _SYSTEMD_BASE_UNITS = ("core-daemon", "core-api")
67
+
68
+ # Match core-daemon-worker@<stem>.service or shortened core-daemon-worker@<stem>.
69
+ _TEMPLATE_UNIT_RE = re.compile(r"core-daemon-worker@([^.\s]+)(?:\.service)?")
70
+
71
+
72
+ # ID: 7c0c1eef-3a86-4f0b-86f1-e84f81e2a4fa
73
+ def _heavy_worker_stems() -> list[str]:
74
+ """Stems of active workers declaring requires_dedicated_process: true.
75
+
76
+ Source of truth for which dedicated daemons systemd is expected to host
77
+ (ADR-081 D6). Reads .intent/workers/*.yaml each call so the wrappers
78
+ pick up YAML changes without a CLI restart. Sorted for deterministic
79
+ output.
80
+ """
81
+ import yaml
82
+
83
+ from shared.infrastructure.bootstrap_registry import BootstrapRegistry
84
+
85
+ workers_dir = BootstrapRegistry.get_repo_path() / ".intent" / "workers"
86
+ stems: list[str] = []
87
+ for f in sorted(workers_dir.glob("*.yaml")):
88
+ try:
89
+ decl = yaml.safe_load(f.read_text()) or {}
90
+ except Exception:
91
+ continue
92
+ if decl.get("metadata", {}).get("status") != "active":
93
+ continue
94
+ if decl.get("implementation", {}).get("requires_dedicated_process"):
95
+ stems.append(f.stem)
96
+ return stems
97
+
98
+
99
+ # ID: 4d2f15a9-9e4c-4c3e-bf2a-7e0b30c7da11
100
+ def _systemd_units() -> list[str]:
101
+ """Full systemd unit list this CLI manages (ADR-081 D6).
102
+
103
+ Lightweight core-daemon + core-api + one core-daemon-worker@<stem>.service
104
+ per active worker declaring requires_dedicated_process: true. Order is
105
+ base units first, then dedicated units in stem-sorted order.
106
+ """
107
+ units = list(_SYSTEMD_BASE_UNITS)
108
+ units.extend(f"core-daemon-worker@{s}.service" for s in _heavy_worker_stems())
109
+ return units
110
+
111
+
112
+ # ID: 8a3b1c4d-6e7f-4a2b-9c1d-5e2f3a4b5c6d
113
+ def _enabled_template_stems() -> set[str]:
114
+ """Stems of currently-enabled core-daemon-worker@<stem>.service instances.
115
+
116
+ Used by `daemon status` to surface drift between .intent/workers/ state
117
+ and systemd-enabled state (ADR-081 D6). Best-effort — returns an empty
118
+ set if the wants directory is missing, so drift detection degrades to
119
+ silent rather than blocking the status command.
120
+
121
+ Probes the user-systemd wants directory directly because
122
+ ``systemctl --user list-unit-files --state=enabled`` enumerates only
123
+ the template unit file itself, not its enabled instances. The enabled
124
+ instances live as symlinks under ``~/.config/systemd/user/default.target.wants/``
125
+ (the canonical user-systemd location), so listing those is the source
126
+ of truth.
127
+ """
128
+ wants_dir = Path.home() / ".config" / "systemd" / "user" / "default.target.wants"
129
+ if not wants_dir.is_dir():
130
+ return set()
131
+ stems: set[str] = set()
132
+ try:
133
+ for entry in wants_dir.glob("core-daemon-worker@*.service"):
134
+ m = _TEMPLATE_UNIT_RE.match(entry.name)
135
+ if m:
136
+ stems.add(m.group(1))
137
+ except OSError:
138
+ return set()
139
+ return stems
140
+
141
+
142
+ # ID: 0b1ce63d-8b46-4d8b-b1d7-2c5b6a93e0a9
143
+ def _pid_file_for(only: str | None) -> Path:
144
+ """Repo-relative PID file path for this daemon invocation.
145
+
146
+ Default mode (``only is None``): the lightweight core-daemon PID file.
147
+ Dedicated mode (``--only <stem>``): a per-stem PID file under
148
+ ``var/run/core-daemon-worker-<stem>.pid``. Per-stem files mean an
149
+ operator can run the lightweight daemon and one or more dedicated
150
+ daemons simultaneously without lock contention. Per ADR-081 D4.
151
+ """
152
+ if only is None:
153
+ return _PID_FILE_REL
154
+ return Path("var/run") / f"core-daemon-worker-{only}.pid"
155
+
156
+
157
+ async def _run_one_shot_loop(worker: Any, stem: str, interval: int) -> None:
158
+ """
159
+ Wraps a one-shot worker (has start() but no run_loop()) in a periodic loop.
160
+ Re-instantiation is not needed — start() is idempotent per the Worker contract.
161
+ """
162
+ import time
163
+
164
+ logger.info("CORE daemon: one-shot loop for '%s' (interval=%ds)", stem, interval)
165
+ while True:
166
+ cycle_start = time.monotonic()
167
+ try:
168
+ await worker.start()
169
+ except Exception as e:
170
+ logger.error(
171
+ "CORE daemon: one-shot worker '%s' failed: %s", stem, e, exc_info=True
172
+ )
173
+ elapsed = time.monotonic() - cycle_start
174
+ await asyncio.sleep(max(interval - elapsed, 0))
175
+
176
+
177
+ @daemon_app.command("start")
178
+ @async_command
179
+ # ID: f3d2e3cd-7e95-473a-89d8-4af5438490ea
180
+ async def start(
181
+ only: str | None = typer.Option(
182
+ None,
183
+ "--only",
184
+ help=(
185
+ "Run exactly one worker declared requires_dedicated_process: true, "
186
+ "alone in its own asyncio loop. Stem is the .intent/workers/<stem>.yaml "
187
+ "filename without extension. Without --only, the daemon excludes "
188
+ "every worker with requires_dedicated_process: true and runs the "
189
+ "remaining lightweight set. Per ADR-081 D5."
190
+ ),
191
+ ),
192
+ ) -> None:
193
+ """
194
+ Start background workers (systemd entry point).
195
+
196
+ Default mode (no ``--only``): discovers active workers dynamically from
197
+ .intent/workers/*.yaml, excludes every worker that declares
198
+ ``requires_dedicated_process: true``, and runs the lightweight set in a
199
+ shared asyncio loop. This is the unit systemd starts as ``core-daemon``.
200
+
201
+ Dedicated mode (``--only <stem>``): loads exactly that one worker and
202
+ runs it alone in its own asyncio loop. The stem must be active and must
203
+ declare ``requires_dedicated_process: true`` — refuses otherwise. This
204
+ is the unit shape systemd starts as ``core-daemon-worker@<stem>.service``
205
+ (template unit lands in Step 2c). Per ADR-081 D3 / D5.
206
+
207
+ Each invocation acquires a singleton PID lock — default mode uses
208
+ ``var/run/core-daemon.pid``; dedicated mode uses
209
+ ``var/run/core-daemon-worker-<stem>.pid`` — so the lightweight daemon
210
+ and N dedicated daemons can run simultaneously without contention.
211
+
212
+ **Humans should use ``core-admin daemon up`` instead** — it goes
213
+ through systemctl, returns immediately, and ensures the supervisor
214
+ (not your shell) owns the process lifecycle.
215
+ """
216
+ await _run_daemon(only=only)
217
+
218
+
219
+ # ID: eeac9460-6a08-45d1-8194-e77660355120
220
+ def _systemctl(verb: str) -> int:
221
+ """Run ``systemctl --user <verb>`` against every CORE unit.
222
+
223
+ The unit list is computed dynamically per ADR-081 D6 — lightweight
224
+ core-daemon + core-api + one core-daemon-worker@<stem>.service instance
225
+ per active worker declaring requires_dedicated_process: true.
226
+ """
227
+ units = _systemd_units()
228
+ cmd = ["systemctl", "--user", verb, *units]
229
+ result = subprocess.run(cmd, capture_output=True, text=True)
230
+ if result.stdout:
231
+ console.print(result.stdout.rstrip())
232
+ if result.stderr:
233
+ console.print(f"[yellow]{result.stderr.rstrip()}[/yellow]")
234
+ return result.returncode
235
+
236
+
237
+ @daemon_app.command("up")
238
+ # ID: 6d9e21bf-a63d-4658-b7bb-a0cb470e7c49
239
+ def up() -> None:
240
+ """Start all CORE units via systemd (the supported way).
241
+
242
+ Covers core-daemon, core-api, and every enabled
243
+ core-daemon-worker@<stem>.service instance (ADR-081 D6).
244
+ """
245
+ rc = _systemctl("start")
246
+ if rc == 0:
247
+ console.print("[green]CORE units up.[/green]")
248
+ raise typer.Exit(code=rc)
249
+
250
+
251
+ @daemon_app.command("down")
252
+ # ID: 7231666c-a6b8-4e71-8060-4447468f6b85
253
+ def down() -> None:
254
+ """Stop all CORE units via systemd.
255
+
256
+ Covers core-daemon, core-api, and every enabled
257
+ core-daemon-worker@<stem>.service instance (ADR-081 D6).
258
+ """
259
+ rc = _systemctl("stop")
260
+ if rc == 0:
261
+ console.print("[green]CORE units down.[/green]")
262
+ raise typer.Exit(code=rc)
263
+
264
+
265
+ @daemon_app.command("restart")
266
+ # ID: e6b00ede-7cf5-4c02-b6b0-f2137a0ddecb
267
+ def restart() -> None:
268
+ """Restart all CORE units via systemd.
269
+
270
+ Covers core-daemon, core-api, and every enabled
271
+ core-daemon-worker@<stem>.service instance (ADR-081 D6).
272
+ """
273
+ rc = _systemctl("restart")
274
+ if rc == 0:
275
+ console.print("[green]CORE units restarted.[/green]")
276
+ raise typer.Exit(code=rc)
277
+
278
+
279
+ @daemon_app.command("status")
280
+ # ID: ad62cbef-7f06-4d8e-9c3c-1b8d0f5a4c52
281
+ def status() -> None:
282
+ """Show CORE service state and scan for stray (orphan) python processes.
283
+
284
+ Unit list is dynamic per ADR-081 D6 — lightweight core-daemon + core-api
285
+ plus one row per enabled core-daemon-worker@<stem>.service instance.
286
+ Drift between .intent/workers/ classification and enabled systemd state
287
+ is surfaced as a separate panel below the unit table.
288
+ """
289
+ table = Table(title="CORE services", show_header=True, header_style="bold")
290
+ table.add_column("unit")
291
+ table.add_column("active")
292
+ table.add_column("MainPID")
293
+ table.add_column("since")
294
+
295
+ units = _systemd_units()
296
+ systemd_pids: set[int] = set()
297
+ for unit in units:
298
+ is_active = subprocess.run(
299
+ ["systemctl", "--user", "is-active", unit],
300
+ capture_output=True,
301
+ text=True,
302
+ ).stdout.strip()
303
+ show = subprocess.run(
304
+ [
305
+ "systemctl",
306
+ "--user",
307
+ "show",
308
+ unit,
309
+ "--property=MainPID,ActiveEnterTimestamp",
310
+ ],
311
+ capture_output=True,
312
+ text=True,
313
+ ).stdout
314
+ props = dict(
315
+ line.split("=", 1) for line in show.strip().splitlines() if "=" in line
316
+ )
317
+ main_pid = props.get("MainPID", "0").strip()
318
+ since = props.get("ActiveEnterTimestamp", "").strip() or "—"
319
+ try:
320
+ pid_int = int(main_pid)
321
+ if pid_int > 0:
322
+ systemd_pids.add(pid_int)
323
+ except ValueError:
324
+ pass
325
+ color = "green" if is_active == "active" else "red"
326
+ table.add_row(unit, f"[{color}]{is_active}[/{color}]", main_pid, since)
327
+
328
+ console.print(table)
329
+
330
+ # ADR-081 D6 — drift between .intent/workers/ classification and enabled
331
+ # systemd state. Both directions are surfaced so operators can see when a
332
+ # heavy YAML worker was added without enabling its template instance, or
333
+ # when a stale template instance was left enabled after the YAML was
334
+ # demoted / retired.
335
+ expected_heavy = set(_heavy_worker_stems())
336
+ enabled_templates = _enabled_template_stems()
337
+ missing_enable = sorted(expected_heavy - enabled_templates)
338
+ orphan_enable = sorted(enabled_templates - expected_heavy)
339
+ if missing_enable or orphan_enable:
340
+ console.print()
341
+ drift_table = Table(
342
+ title="ADR-081 worker / systemd drift",
343
+ show_header=True,
344
+ header_style="bold yellow",
345
+ )
346
+ drift_table.add_column("class")
347
+ drift_table.add_column("stem")
348
+ drift_table.add_column("remediation")
349
+ for stem in missing_enable:
350
+ drift_table.add_row(
351
+ "[yellow]expected unit, not enabled[/yellow]",
352
+ stem,
353
+ f"systemctl --user enable --now core-daemon-worker@{stem}.service",
354
+ )
355
+ for stem in orphan_enable:
356
+ drift_table.add_row(
357
+ "[red]enabled unit, not in YAML[/red]",
358
+ stem,
359
+ f"systemctl --user disable --now core-daemon-worker@{stem}.service",
360
+ )
361
+ console.print(drift_table)
362
+
363
+ # Stray scan: any python process under the repo venv that systemd doesn't
364
+ # own. The orphan-daemon trap that motivated this command — a `daemon
365
+ # start` whose shell exited and got adopted by PID 1 — shows up here.
366
+ # Per ADR-081 D6, daemon invocations with `--only <stem>` for a known
367
+ # heavy worker are recognised as legitimate even if systemd isn't tracking
368
+ # their MainPID (e.g. governor ran a foreground daemon for testing).
369
+ from shared.infrastructure.bootstrap_registry import BootstrapRegistry
370
+
371
+ venv_python = f"{BootstrapRegistry.get_repo_path()}/.venv/bin/python"
372
+ ps = subprocess.run(
373
+ ["ps", "-eo", "pid,ppid,lstart,cmd"],
374
+ capture_output=True,
375
+ text=True,
376
+ ).stdout
377
+
378
+ strays: list[str] = []
379
+ skip_tokens = ("pytest", "ruff", "mypy", "core-admin daemon status")
380
+ only_re = re.compile(r"--only\s+(\S+)")
381
+ for line in ps.splitlines()[1:]:
382
+ parts = line.split(None, 6)
383
+ if len(parts) < 7:
384
+ continue
385
+ try:
386
+ pid = int(parts[0])
387
+ except ValueError:
388
+ continue
389
+ cmd = parts[6]
390
+ if venv_python not in cmd:
391
+ continue
392
+ if pid in systemd_pids or pid == os.getpid():
393
+ continue
394
+ if any(tok in cmd for tok in skip_tokens):
395
+ continue
396
+ # Recognise dedicated-worker daemons by their --only <stem> signature
397
+ # when the stem is a known heavy worker. These are legitimate, not strays.
398
+ m = only_re.search(cmd)
399
+ if m and m.group(1) in expected_heavy:
400
+ continue
401
+ strays.append(line)
402
+
403
+ if strays:
404
+ console.print()
405
+ console.print(
406
+ "[red bold]Stray CORE python processes detected (not tracked by systemd):[/red bold]"
407
+ )
408
+ for line in strays:
409
+ console.print(f" {line}")
410
+ console.print(
411
+ "[yellow]Inspect with `ps -fp <pid>`; "
412
+ "kill confirmed orphans with `kill -TERM <pid>`.[/yellow]"
413
+ )
414
+ else:
415
+ console.print("[green]No stray CORE processes.[/green]")
416
+
417
+
418
+ def _instantiate_worker(
419
+ WorkerClass: Any,
420
+ kwargs: dict[str, Any],
421
+ requires_ctx: bool,
422
+ ctx: Any,
423
+ cog_svc: Any,
424
+ stem: str,
425
+ ) -> Any | None:
426
+ """
427
+ Attempt to instantiate a worker with progressively simpler kwargs.
428
+
429
+ Instantiation order:
430
+ 1. Full kwargs (declaration_name + rule_namespace + params + core_context/nothing)
431
+ 2. Standard kwargs only (declaration_name + rule_namespace, no extra params)
432
+ 3. Bare instantiation (no kwargs at all) — for workers with hardcoded
433
+ declaration_name class attributes that predate the daemon kwarg contract
434
+ 4. Cognitive service fallback (for workers that need it but don't take core_context)
435
+
436
+ Returns the instantiated worker, or None if all attempts fail.
437
+ """
438
+ standard_keys = {"declaration_name", "rule_namespace"}
439
+ standard_kwargs = {k: v for k, v in kwargs.items() if k in standard_keys}
440
+
441
+ attempts: list[tuple[str, Any]]
442
+
443
+ if requires_ctx:
444
+ attempts = [
445
+ ("full + core_context", lambda: WorkerClass(core_context=ctx, **kwargs)),
446
+ (
447
+ "standard + core_context",
448
+ lambda: WorkerClass(core_context=ctx, **standard_kwargs),
449
+ ),
450
+ ("bare + core_context", lambda: WorkerClass(core_context=ctx)),
451
+ ]
452
+ else:
453
+ attempts = [
454
+ ("full kwargs", lambda: WorkerClass(**kwargs)),
455
+ ("standard kwargs", lambda: WorkerClass(**standard_kwargs)),
456
+ ("bare", lambda: WorkerClass()),
457
+ ]
458
+ if cog_svc is not None:
459
+ attempts.append(
460
+ (
461
+ "cognitive_service",
462
+ lambda: WorkerClass(cognitive_service=cog_svc, **kwargs),
463
+ )
464
+ )
465
+
466
+ for label, attempt in attempts:
467
+ try:
468
+ worker = attempt()
469
+ if label != "full kwargs" and label != "full + core_context":
470
+ logger.info(
471
+ "CORE daemon: '%s' instantiated via fallback '%s'.",
472
+ stem,
473
+ label,
474
+ )
475
+ return worker
476
+ except TypeError:
477
+ continue
478
+ except Exception as exc:
479
+ logger.error(
480
+ "CORE daemon: '%s' instantiation failed unexpectedly (%s): %s",
481
+ stem,
482
+ label,
483
+ exc,
484
+ exc_info=True,
485
+ )
486
+ return None
487
+
488
+ return None
489
+
490
+
491
+ # ID: c6908afb-8ab5-4df2-92eb-43896b3cfbc1
492
+ def _acquire_singleton_lock(pid_file_rel: Path) -> int:
493
+ """Acquire exclusive flock on the daemon PID file.
494
+
495
+ Returns the open file descriptor — caller MUST keep it open for the
496
+ daemon's lifetime, since closing the fd releases the lock. On failure
497
+ (another instance holds the lock), logs the holder PID and exits with
498
+ code 1.
499
+
500
+ ``pid_file_rel`` is repo-relative — caller passes ``_pid_file_for(only)``
501
+ so default and dedicated daemons each acquire their own lock (ADR-081 D4).
502
+ """
503
+ from shared.infrastructure.bootstrap_registry import BootstrapRegistry
504
+ from shared.infrastructure.storage.file_handler import FileHandler
505
+
506
+ repo_path = BootstrapRegistry.get_repo_path()
507
+ pid_file = repo_path / pid_file_rel
508
+ FileHandler(str(repo_path)).ensure_dir(str(pid_file_rel.parent))
509
+ fd = os.open(str(pid_file), os.O_CREAT | os.O_RDWR, 0o644)
510
+ try:
511
+ fcntl.flock(fd, fcntl.LOCK_EX | fcntl.LOCK_NB)
512
+ except BlockingIOError:
513
+ try:
514
+ with open(pid_file) as f:
515
+ holder_pid = f.read().strip() or "<unknown>"
516
+ except OSError:
517
+ holder_pid = "<unknown>"
518
+ os.close(fd)
519
+ logger.error(
520
+ "CORE daemon: another instance already running (PID %s, lock=%s). "
521
+ "Use `core-admin daemon down` or `systemctl --user stop core-daemon core-api`.",
522
+ holder_pid,
523
+ pid_file,
524
+ )
525
+ sys.exit(1)
526
+ os.ftruncate(fd, 0)
527
+ os.write(fd, f"{os.getpid()}\n".encode())
528
+ os.fsync(fd)
529
+ logger.info(
530
+ "CORE daemon: acquired singleton lock (%s, PID %d)", pid_file, os.getpid()
531
+ )
532
+ return fd
533
+
534
+
535
+ # ID: 00438b47-4d36-465d-ae6c-b512a4725be6
536
+ def _release_singleton_lock(fd: int, pid_file_rel: Path) -> None:
537
+ """Release the singleton lock and unlink the PID file (both best-effort).
538
+
539
+ ``pid_file_rel`` is repo-relative — caller passes the same value used at
540
+ acquisition so the matching PID file is removed (ADR-081 D4).
541
+ """
542
+ from shared.infrastructure.bootstrap_registry import BootstrapRegistry
543
+ from shared.infrastructure.storage.file_handler import FileHandler
544
+
545
+ repo_path = BootstrapRegistry.get_repo_path()
546
+ try:
547
+ fcntl.flock(fd, fcntl.LOCK_UN)
548
+ except OSError:
549
+ pass
550
+ try:
551
+ os.close(fd)
552
+ except OSError:
553
+ pass
554
+ try:
555
+ FileHandler(str(repo_path)).remove_file(str(pid_file_rel))
556
+ except OSError:
557
+ pass
558
+
559
+
560
+ # ID: ea1f2f3a-280e-4d88-a120-4b310a2ef31f
561
+ async def _run_daemon(only: str | None = None) -> None:
562
+ """
563
+ Async entry point. Discovers all active workers from .intent/workers/,
564
+ instantiates each one, starts their run_loop (or one-shot loop) as
565
+ asyncio tasks, and waits for shutdown signal.
566
+
567
+ Constructor kwargs are resolved from the declaration in this order:
568
+ 1. declaration_name — always included (stem of the YAML file)
569
+ 2. rule_namespace — from mandate.scope.rule_namespace if present
570
+ 3. core_context — if implementation.requires_core_context is true
571
+ 4. implementation.params — arbitrary extra kwargs merged last
572
+
573
+ Instantiation is tried with progressively simpler kwargs when TypeError
574
+ occurs, so workers with hardcoded declaration_name class attributes and
575
+ plain __init__(self) signatures are still started correctly.
576
+
577
+ When ``only`` is set, runs exactly that one heavy worker (ADR-081 D3/D5)
578
+ against a per-stem PID lock; otherwise excludes every heavy worker and
579
+ runs the lightweight set against the default daemon PID lock.
580
+ """
581
+ pid_file_rel = _pid_file_for(only)
582
+ lock_fd = _acquire_singleton_lock(pid_file_rel)
583
+ try:
584
+ await _run_daemon_locked(only=only)
585
+ finally:
586
+ _release_singleton_lock(lock_fd, pid_file_rel)
587
+
588
+
589
+ # ID: be19aae3-d399-4955-8ff7-f65aa5267aaf
590
+ async def _run_daemon_locked(only: str | None = None) -> None:
591
+ """Body of _run_daemon, executed under the singleton lock.
592
+
593
+ ``only`` mirrors the ``--only`` CLI flag (ADR-081 D5). When set, exactly
594
+ one heavy worker is loaded; when None, every worker with
595
+ ``requires_dedicated_process: true`` is excluded.
596
+ """
597
+ # Bootstrap-only imports — see _run_daemon docstring.
598
+ import yaml
599
+
600
+ from body.services.service_registry import service_registry
601
+ from shared.context import CoreContext
602
+ from shared.infrastructure.bootstrap_registry import BootstrapRegistry
603
+ from shared.infrastructure.knowledge.knowledge_service import KnowledgeService
604
+
605
+ logger.info("CORE daemon starting...")
606
+
607
+ ctx = CoreContext(registry=service_registry)
608
+
609
+ cog_svc: Any = None
610
+ try:
611
+ cog_svc = await service_registry.get_cognitive_service()
612
+ ctx.cognitive_service = cog_svc
613
+ except Exception as e:
614
+ logger.warning(
615
+ "CORE daemon: CognitiveService unavailable — workers requiring it will be skipped: %s",
616
+ e,
617
+ )
618
+
619
+ try:
620
+ ctx.qdrant_service = await service_registry.get_qdrant_service()
621
+ except Exception as e:
622
+ logger.warning("CORE daemon: QdrantService unavailable: %s", e)
623
+
624
+ try:
625
+ ctx.auditor_context = await service_registry.get_auditor_context()
626
+ except Exception as e:
627
+ logger.warning("CORE daemon: AuditorContext unavailable: %s", e)
628
+
629
+ ctx.knowledge_service = KnowledgeService(
630
+ repo_path=BootstrapRegistry.get_repo_path()
631
+ )
632
+
633
+ # Bootstrap-only — daemon constructs its own GitService (no API yet to call).
634
+ from shared.infrastructure.git_service import GitService
635
+
636
+ try:
637
+ ctx.git_service = GitService(repo_path=BootstrapRegistry.get_repo_path())
638
+ # ADR-071 D2.2 Phase 1: reclaim sandbox worktrees leaked by crashes.
639
+ try:
640
+ swept = ctx.git_service.sweep_orphan_worktrees()
641
+ if swept:
642
+ logger.info(
643
+ "CORE daemon: cleared %d orphan action sandbox(es) from prior runs",
644
+ swept,
645
+ )
646
+ except Exception as sweep_err:
647
+ logger.warning(
648
+ "CORE daemon: orphan worktree sweep failed (non-fatal): %s",
649
+ sweep_err,
650
+ )
651
+ except Exception as e:
652
+ logger.warning("CORE daemon: GitService unavailable: %s", e)
653
+
654
+ ctx.file_handler = service_registry.get_file_handler()
655
+
656
+ # ADR-081 Step 0 — loop-hold instrumentation (Option 1, permanent telemetry).
657
+ # Gated on operational_config.daemon.set_debug. When enabled, the asyncio
658
+ # event loop emits a `logger.warning` on the "asyncio" logger whenever a
659
+ # single handle executes for longer than `slow_callback_duration`. Step 3a
660
+ # subscribes a structured handler to those emissions; the warnings are the
661
+ # only low-level loop-hold source CPython provides.
662
+ loop = asyncio.get_running_loop()
663
+ if _CFG.set_debug:
664
+ loop.set_debug(True)
665
+ loop.slow_callback_duration = _CFG.slow_callback_duration_sec
666
+ logger.info(
667
+ "CORE daemon: asyncio debug mode enabled "
668
+ "(slow_callback_duration=%.3fs) — ADR-081 Step 0",
669
+ _CFG.slow_callback_duration_sec,
670
+ )
671
+
672
+ workers_dir = BootstrapRegistry.get_repo_path() / ".intent" / "workers"
673
+
674
+ # ADR-081 D5 — daemon discovery contract.
675
+ # --only <stem>: load exactly that stem, must be active AND heavy.
676
+ # --only absent: discover all active workers, exclude every heavy one.
677
+ if only is not None:
678
+ if "/" in only or ".." in only or only != Path(only).name:
679
+ logger.error(
680
+ "CORE daemon: --only stem %r contains path separators or "
681
+ "traversal — refusing.",
682
+ only,
683
+ )
684
+ return
685
+ yaml_files = [workers_dir / f"{only}.yaml"]
686
+ if not yaml_files[0].exists():
687
+ logger.error(
688
+ "CORE daemon: --only stem '%s' has no declaration at %s.",
689
+ only,
690
+ yaml_files[0],
691
+ )
692
+ return
693
+ only_decl = yaml.safe_load(yaml_files[0].read_text())
694
+ only_status = only_decl.get("metadata", {}).get("status", "")
695
+ if only_status != "active":
696
+ logger.error(
697
+ "CORE daemon: --only stem '%s' is not active "
698
+ "(metadata.status=%r). Refusing.",
699
+ only,
700
+ only_status,
701
+ )
702
+ return
703
+ if not only_decl.get("implementation", {}).get(
704
+ "requires_dedicated_process", False
705
+ ):
706
+ logger.error(
707
+ "CORE daemon: --only stem '%s' declares "
708
+ "requires_dedicated_process=false. Run it under the lightweight "
709
+ "daemon via `core-admin daemon start` without --only.",
710
+ only,
711
+ )
712
+ return
713
+ logger.info(
714
+ "CORE daemon: dedicated mode — running only '%s' "
715
+ "(requires_dedicated_process: true).",
716
+ only,
717
+ )
718
+ else:
719
+ yaml_files = sorted(workers_dir.glob("*.yaml"))
720
+
721
+ tasks: list[asyncio.Task[Any]] = []
722
+ excluded_heavy: list[str] = []
723
+ # ADR-081 Step 3a — stem → Worker registry for loop-hold telemetry
724
+ # attribution. Populated alongside worker instantiation below; consumed
725
+ # by the drain coroutine after the loop completes.
726
+ workers_by_stem: dict[str, Any] = {}
727
+
728
+ for yaml_file in yaml_files:
729
+ stem = yaml_file.stem
730
+
731
+ try:
732
+ declaration = yaml.safe_load(yaml_file.read_text())
733
+
734
+ status = declaration.get("metadata", {}).get("status", "")
735
+ if status != "active":
736
+ logger.debug("CORE daemon: skipping '%s' — status=%s", stem, status)
737
+ continue
738
+
739
+ impl = declaration.get("implementation", {})
740
+
741
+ # ADR-081 D3 — in default mode, never host a worker that declares
742
+ # requires_dedicated_process: true. Its dedicated systemd unit
743
+ # runs it alone. --only mode passed the heavy-worker check above.
744
+ if only is None and impl.get("requires_dedicated_process", False):
745
+ excluded_heavy.append(stem)
746
+ logger.info(
747
+ "CORE daemon: excluding heavy worker '%s' "
748
+ "(requires_dedicated_process: true) — runs in a dedicated daemon.",
749
+ stem,
750
+ )
751
+ continue
752
+ module_path = impl["module"]
753
+ class_name = impl["class"]
754
+ requires_ctx = impl.get("requires_core_context", False)
755
+
756
+ # Build constructor kwargs.
757
+ # declaration_name is always included — enables one class to back
758
+ # multiple namespace declarations with distinct UUIDs.
759
+ kwargs: dict[str, Any] = {"declaration_name": stem}
760
+
761
+ rule_namespace = (
762
+ declaration.get("mandate", {})
763
+ .get("scope", {})
764
+ .get("rule_namespace", "")
765
+ )
766
+ if rule_namespace:
767
+ kwargs["rule_namespace"] = rule_namespace
768
+
769
+ # implementation.params — arbitrary extra constructor kwargs.
770
+ # Protected standard fields cannot be overridden via params.
771
+ extra_params = impl.get("params") or {}
772
+ if extra_params:
773
+ protected = {
774
+ "declaration_name",
775
+ "rule_namespace",
776
+ "core_context",
777
+ "cognitive_service",
778
+ }
779
+ clashes = set(extra_params) & protected
780
+ if clashes:
781
+ logger.warning(
782
+ "CORE daemon: '%s' implementation.params contains protected "
783
+ "keys %s — they will be ignored.",
784
+ stem,
785
+ clashes,
786
+ )
787
+ extra_params = {
788
+ k: v for k, v in extra_params.items() if k not in protected
789
+ }
790
+ kwargs.update(extra_params)
791
+
792
+ module = importlib.import_module(module_path)
793
+ WorkerClass = getattr(module, class_name)
794
+
795
+ worker = _instantiate_worker(
796
+ WorkerClass=WorkerClass,
797
+ kwargs=kwargs,
798
+ requires_ctx=requires_ctx,
799
+ ctx=ctx,
800
+ cog_svc=cog_svc,
801
+ stem=stem,
802
+ )
803
+
804
+ if worker is None:
805
+ logger.error(
806
+ "CORE daemon: could not instantiate '%s' — all attempts failed. "
807
+ "Worker will not be started.",
808
+ stem,
809
+ )
810
+ continue
811
+
812
+ # Use run_loop() if the worker defines it; otherwise wrap start() in a loop.
813
+ if hasattr(worker, "run_loop"):
814
+ coro = worker.run_loop()
815
+ else:
816
+ interval = (
817
+ declaration.get("mandate", {})
818
+ .get("schedule", {})
819
+ .get("max_interval", _CFG.one_shot_interval_sec)
820
+ )
821
+ coro = _run_one_shot_loop(worker, stem, interval)
822
+
823
+ task = asyncio.create_task(coro, name=f"{stem}_worker")
824
+ tasks.append(task)
825
+ workers_by_stem[stem] = worker
826
+ logger.info(
827
+ "CORE daemon: started worker '%s' (%s.%s)",
828
+ stem,
829
+ module_path,
830
+ class_name,
831
+ )
832
+
833
+ except Exception as e:
834
+ logger.error(
835
+ "CORE daemon: failed to load worker '%s': %s",
836
+ stem,
837
+ e,
838
+ exc_info=True,
839
+ )
840
+
841
+ logger.info("CORE daemon: %d worker(s) started.", len(tasks))
842
+ if excluded_heavy:
843
+ logger.info(
844
+ "CORE daemon: excluded %d heavy worker(s) requiring dedicated "
845
+ "processes (ADR-081 D3): %s",
846
+ len(excluded_heavy),
847
+ ", ".join(excluded_heavy),
848
+ )
849
+
850
+ # ADR-081 Step 3a-telemetry — install slow-callback blackboard handler
851
+ # alongside the loop.set_debug(True) instrumentation from Step 0. The
852
+ # handler runs in lockstep with asyncio's slow-callback warnings (only
853
+ # emitted when set_debug is on), so it costs nothing when set_debug is
854
+ # off and the drain task self-cancels on shutdown.
855
+ telemetry_task: asyncio.Task[Any] | None = None
856
+ telemetry_handler: logging.Handler | None = None
857
+ if _CFG.set_debug and workers_by_stem:
858
+ from shared.workers.loop_hold_telemetry import (
859
+ SlowCallbackBlackboardHandler,
860
+ drain_loop_hold_samples,
861
+ make_sample_queue,
862
+ )
863
+
864
+ sample_queue = make_sample_queue()
865
+ telemetry_handler = SlowCallbackBlackboardHandler(sample_queue)
866
+ logging.getLogger("asyncio").addHandler(telemetry_handler)
867
+ telemetry_task = asyncio.create_task(
868
+ drain_loop_hold_samples(sample_queue, workers_by_stem),
869
+ name="loop_hold_telemetry_drain",
870
+ )
871
+ logger.info(
872
+ "CORE daemon: loop-hold telemetry handler installed "
873
+ "(ADR-081 Step 3a) — %d worker(s) registered for attribution.",
874
+ len(workers_by_stem),
875
+ )
876
+
877
+ # loop is acquired above (ADR-081 Step 0); reuse it for signal handling.
878
+ stop_event = asyncio.Event()
879
+
880
+ def _handle_signal() -> None:
881
+ logger.info("CORE daemon: shutdown signal received.")
882
+ stop_event.set()
883
+
884
+ for sig in (signal.SIGTERM, signal.SIGINT):
885
+ loop.add_signal_handler(sig, _handle_signal)
886
+
887
+ await stop_event.wait()
888
+
889
+ logger.info("CORE daemon: cancelling workers...")
890
+ for task in tasks:
891
+ task.cancel()
892
+
893
+ await asyncio.gather(*tasks, return_exceptions=True)
894
+
895
+ # ADR-081 Step 3a — tear down telemetry after the worker tasks have
896
+ # finished cancelling. Removing the handler first stops further
897
+ # samples landing in the queue; cancelling the drain task lets it
898
+ # exit cleanly via its CancelledError handler.
899
+ if telemetry_handler is not None:
900
+ logging.getLogger("asyncio").removeHandler(telemetry_handler)
901
+ if telemetry_task is not None:
902
+ telemetry_task.cancel()
903
+ try:
904
+ await telemetry_task
905
+ except asyncio.CancelledError:
906
+ pass
907
+
908
+ logger.info("CORE daemon: stopped cleanly.")