mineproductivity 2.0.0__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 (344) hide show
  1. mineproductivity/README.md +31 -0
  2. mineproductivity/__init__.py +50 -0
  3. mineproductivity/agents/README.md +27 -0
  4. mineproductivity/agents/__init__.py +85 -0
  5. mineproductivity/agents/_registry.py +84 -0
  6. mineproductivity/agents/abstractions.py +113 -0
  7. mineproductivity/agents/approval.py +56 -0
  8. mineproductivity/agents/audit.py +102 -0
  9. mineproductivity/agents/capability.py +91 -0
  10. mineproductivity/agents/communication.py +82 -0
  11. mineproductivity/agents/conversation.py +61 -0
  12. mineproductivity/agents/discovery.py +78 -0
  13. mineproductivity/agents/exceptions.py +60 -0
  14. mineproductivity/agents/executor.py +273 -0
  15. mineproductivity/agents/goal.py +41 -0
  16. mineproductivity/agents/memory.py +43 -0
  17. mineproductivity/agents/metadata.py +78 -0
  18. mineproductivity/agents/persistence.py +23 -0
  19. mineproductivity/agents/policy.py +228 -0
  20. mineproductivity/agents/result.py +57 -0
  21. mineproductivity/agents/state.py +50 -0
  22. mineproductivity/agents/task.py +87 -0
  23. mineproductivity/agents/tool.py +107 -0
  24. mineproductivity/agents/workflow.py +114 -0
  25. mineproductivity/analytics/README.md +90 -0
  26. mineproductivity/analytics/__init__.py +206 -0
  27. mineproductivity/analytics/_registry.py +75 -0
  28. mineproductivity/analytics/abstractions.py +99 -0
  29. mineproductivity/analytics/aggregation.py +214 -0
  30. mineproductivity/analytics/anomaly.py +62 -0
  31. mineproductivity/analytics/baseline.py +130 -0
  32. mineproductivity/analytics/batch.py +67 -0
  33. mineproductivity/analytics/benchmarking.py +258 -0
  34. mineproductivity/analytics/exceptions.py +40 -0
  35. mineproductivity/analytics/forecasting.py +56 -0
  36. mineproductivity/analytics/incremental.py +127 -0
  37. mineproductivity/analytics/metadata.py +74 -0
  38. mineproductivity/analytics/outliers.py +72 -0
  39. mineproductivity/analytics/pipeline.py +136 -0
  40. mineproductivity/analytics/quality.py +312 -0
  41. mineproductivity/analytics/result.py +275 -0
  42. mineproductivity/analytics/rolling.py +138 -0
  43. mineproductivity/analytics/statistics.py +348 -0
  44. mineproductivity/analytics/streaming.py +144 -0
  45. mineproductivity/analytics/timeseries.py +126 -0
  46. mineproductivity/analytics/trend.py +124 -0
  47. mineproductivity/analytics/windowing.py +48 -0
  48. mineproductivity/benchmark/README.md +38 -0
  49. mineproductivity/benchmark/__init__.py +7 -0
  50. mineproductivity/certification/README.md +38 -0
  51. mineproductivity/certification/__init__.py +7 -0
  52. mineproductivity/cli/README.md +38 -0
  53. mineproductivity/cli/__init__.py +7 -0
  54. mineproductivity/config/README.md +39 -0
  55. mineproductivity/config/__init__.py +7 -0
  56. mineproductivity/connectors/README.md +224 -0
  57. mineproductivity/connectors/__init__.py +77 -0
  58. mineproductivity/connectors/_registry.py +30 -0
  59. mineproductivity/connectors/auth.py +74 -0
  60. mineproductivity/connectors/base.py +109 -0
  61. mineproductivity/connectors/contract_tests.py +89 -0
  62. mineproductivity/connectors/exceptions.py +39 -0
  63. mineproductivity/connectors/file/__init__.py +8 -0
  64. mineproductivity/connectors/file/_common.py +125 -0
  65. mineproductivity/connectors/file/csv_connector.py +122 -0
  66. mineproductivity/connectors/file/excel_connector.py +131 -0
  67. mineproductivity/connectors/health.py +33 -0
  68. mineproductivity/connectors/network/__init__.py +8 -0
  69. mineproductivity/connectors/network/graphql_connector.py +143 -0
  70. mineproductivity/connectors/network/rest_connector.py +152 -0
  71. mineproductivity/connectors/normalization.py +109 -0
  72. mineproductivity/connectors/oem/__init__.py +33 -0
  73. mineproductivity/connectors/oem/dispatch_shape.py +61 -0
  74. mineproductivity/connectors/oem/hexagon_shape.py +61 -0
  75. mineproductivity/connectors/oem/minestar_shape.py +64 -0
  76. mineproductivity/connectors/oem/modular_shape.py +61 -0
  77. mineproductivity/connectors/oem/wenco_shape.py +63 -0
  78. mineproductivity/connectors/retry.py +108 -0
  79. mineproductivity/connectors/streaming/__init__.py +8 -0
  80. mineproductivity/connectors/streaming/_common.py +64 -0
  81. mineproductivity/connectors/streaming/kafka_connector.py +90 -0
  82. mineproductivity/connectors/streaming/mqtt_connector.py +87 -0
  83. mineproductivity/core/README.md +350 -0
  84. mineproductivity/core/__init__.py +99 -0
  85. mineproductivity/core/builder.py +56 -0
  86. mineproductivity/core/configuration.py +49 -0
  87. mineproductivity/core/entity.py +70 -0
  88. mineproductivity/core/exceptions.py +74 -0
  89. mineproductivity/core/factory.py +47 -0
  90. mineproductivity/core/identifier.py +68 -0
  91. mineproductivity/core/maybe.py +117 -0
  92. mineproductivity/core/metadata.py +62 -0
  93. mineproductivity/core/repository.py +123 -0
  94. mineproductivity/core/result.py +142 -0
  95. mineproductivity/core/serialization.py +140 -0
  96. mineproductivity/core/service.py +30 -0
  97. mineproductivity/core/specification.py +116 -0
  98. mineproductivity/core/typing.py +72 -0
  99. mineproductivity/core/validator.py +118 -0
  100. mineproductivity/core/value_object.py +85 -0
  101. mineproductivity/core/versioning.py +47 -0
  102. mineproductivity/datasets/README.md +40 -0
  103. mineproductivity/datasets/__init__.py +7 -0
  104. mineproductivity/decision/README.md +65 -0
  105. mineproductivity/decision/__init__.py +181 -0
  106. mineproductivity/decision/_registry.py +66 -0
  107. mineproductivity/decision/abstractions.py +146 -0
  108. mineproductivity/decision/alerting.py +103 -0
  109. mineproductivity/decision/audit.py +130 -0
  110. mineproductivity/decision/batch.py +99 -0
  111. mineproductivity/decision/exceptions.py +50 -0
  112. mineproductivity/decision/explanation.py +117 -0
  113. mineproductivity/decision/metadata.py +73 -0
  114. mineproductivity/decision/pipeline.py +131 -0
  115. mineproductivity/decision/planning.py +166 -0
  116. mineproductivity/decision/policy.py +197 -0
  117. mineproductivity/decision/prioritization.py +85 -0
  118. mineproductivity/decision/ranking.py +111 -0
  119. mineproductivity/decision/realtime.py +236 -0
  120. mineproductivity/decision/recommendation.py +80 -0
  121. mineproductivity/decision/result.py +321 -0
  122. mineproductivity/decision/root_cause.py +55 -0
  123. mineproductivity/decision/rules.py +117 -0
  124. mineproductivity/decision/scoring.py +139 -0
  125. mineproductivity/decision/strategy.py +212 -0
  126. mineproductivity/decision/thresholds.py +61 -0
  127. mineproductivity/decision/what_if.py +57 -0
  128. mineproductivity/digital_twin/README.md +57 -0
  129. mineproductivity/digital_twin/__init__.py +115 -0
  130. mineproductivity/digital_twin/_registry.py +71 -0
  131. mineproductivity/digital_twin/abstractions.py +140 -0
  132. mineproductivity/digital_twin/caching.py +82 -0
  133. mineproductivity/digital_twin/categories.py +164 -0
  134. mineproductivity/digital_twin/discovery.py +64 -0
  135. mineproductivity/digital_twin/exceptions.py +50 -0
  136. mineproductivity/digital_twin/lifecycle.py +31 -0
  137. mineproductivity/digital_twin/metadata.py +100 -0
  138. mineproductivity/digital_twin/persistence.py +32 -0
  139. mineproductivity/digital_twin/result.py +112 -0
  140. mineproductivity/digital_twin/simulation.py +64 -0
  141. mineproductivity/digital_twin/snapshot.py +58 -0
  142. mineproductivity/digital_twin/state.py +77 -0
  143. mineproductivity/digital_twin/synchronization.py +230 -0
  144. mineproductivity/digital_twin/telemetry.py +50 -0
  145. mineproductivity/events/README.md +203 -0
  146. mineproductivity/events/__init__.py +83 -0
  147. mineproductivity/events/base_event.py +44 -0
  148. mineproductivity/events/bus.py +98 -0
  149. mineproductivity/events/canonical/__init__.py +60 -0
  150. mineproductivity/events/canonical/consumption_event.py +53 -0
  151. mineproductivity/events/canonical/cycle_event.py +74 -0
  152. mineproductivity/events/canonical/delay_event.py +46 -0
  153. mineproductivity/events/canonical/maintenance_event.py +51 -0
  154. mineproductivity/events/canonical/production_event.py +46 -0
  155. mineproductivity/events/canonical/safety_event.py +54 -0
  156. mineproductivity/events/envelope.py +88 -0
  157. mineproductivity/events/exceptions.py +48 -0
  158. mineproductivity/events/identifier.py +69 -0
  159. mineproductivity/events/replay.py +63 -0
  160. mineproductivity/events/schema.py +73 -0
  161. mineproductivity/events/serialization/__init__.py +16 -0
  162. mineproductivity/events/serialization/arrow_codec.py +91 -0
  163. mineproductivity/events/serialization/json_codec.py +126 -0
  164. mineproductivity/events/serialization/parquet_codec.py +100 -0
  165. mineproductivity/events/snapshot.py +38 -0
  166. mineproductivity/events/store.py +219 -0
  167. mineproductivity/events/validation.py +118 -0
  168. mineproductivity/events/versioning.py +31 -0
  169. mineproductivity/exceptions/README.md +39 -0
  170. mineproductivity/exceptions/__init__.py +7 -0
  171. mineproductivity/io/README.md +39 -0
  172. mineproductivity/io/__init__.py +7 -0
  173. mineproductivity/kpis/README.md +245 -0
  174. mineproductivity/kpis/__init__.py +96 -0
  175. mineproductivity/kpis/_registry.py +61 -0
  176. mineproductivity/kpis/aggregation.py +63 -0
  177. mineproductivity/kpis/backends/__init__.py +44 -0
  178. mineproductivity/kpis/backends/base_backend.py +78 -0
  179. mineproductivity/kpis/backends/duckdb_backend.py +59 -0
  180. mineproductivity/kpis/backends/numpy_backend.py +83 -0
  181. mineproductivity/kpis/backends/pandas_backend.py +48 -0
  182. mineproductivity/kpis/backends/polars_backend.py +55 -0
  183. mineproductivity/kpis/base_kpi.py +72 -0
  184. mineproductivity/kpis/caching.py +79 -0
  185. mineproductivity/kpis/categories/__init__.py +30 -0
  186. mineproductivity/kpis/categories/_common.py +38 -0
  187. mineproductivity/kpis/categories/cost_kpi.py +18 -0
  188. mineproductivity/kpis/categories/delay_kpi.py +31 -0
  189. mineproductivity/kpis/categories/energy_kpi.py +19 -0
  190. mineproductivity/kpis/categories/haulage_kpi.py +18 -0
  191. mineproductivity/kpis/categories/maintenance_kpi.py +18 -0
  192. mineproductivity/kpis/categories/production_kpi.py +20 -0
  193. mineproductivity/kpis/categories/quality_kpi.py +18 -0
  194. mineproductivity/kpis/categories/safety_kpi.py +19 -0
  195. mineproductivity/kpis/categories/utilization_kpi.py +20 -0
  196. mineproductivity/kpis/certification.py +57 -0
  197. mineproductivity/kpis/composite.py +61 -0
  198. mineproductivity/kpis/dependency_graph.py +93 -0
  199. mineproductivity/kpis/engine.py +223 -0
  200. mineproductivity/kpis/exceptions.py +42 -0
  201. mineproductivity/kpis/inheritance.py +54 -0
  202. mineproductivity/kpis/lifecycle.py +20 -0
  203. mineproductivity/kpis/metadata.py +151 -0
  204. mineproductivity/kpis/naming.py +97 -0
  205. mineproductivity/kpis/result.py +61 -0
  206. mineproductivity/kpis/standard_library/__init__.py +46 -0
  207. mineproductivity/kpis/standard_library/cost.py +70 -0
  208. mineproductivity/kpis/standard_library/delay.py +48 -0
  209. mineproductivity/kpis/standard_library/energy.py +50 -0
  210. mineproductivity/kpis/standard_library/haulage.py +51 -0
  211. mineproductivity/kpis/standard_library/maintenance.py +46 -0
  212. mineproductivity/kpis/standard_library/production.py +53 -0
  213. mineproductivity/kpis/standard_library/quality.py +49 -0
  214. mineproductivity/kpis/standard_library/safety.py +54 -0
  215. mineproductivity/kpis/standard_library/utilization.py +211 -0
  216. mineproductivity/kpis/validation.py +67 -0
  217. mineproductivity/kpis/windowing.py +68 -0
  218. mineproductivity/ontology/README.md +242 -0
  219. mineproductivity/ontology/__init__.py +119 -0
  220. mineproductivity/ontology/cost/__init__.py +7 -0
  221. mineproductivity/ontology/cost/cost_center.py +56 -0
  222. mineproductivity/ontology/entity_type.py +241 -0
  223. mineproductivity/ontology/environmental/__init__.py +7 -0
  224. mineproductivity/ontology/environmental/emissions.py +65 -0
  225. mineproductivity/ontology/equipment/__init__.py +35 -0
  226. mineproductivity/ontology/equipment/ancillary.py +57 -0
  227. mineproductivity/ontology/equipment/drill.py +27 -0
  228. mineproductivity/ontology/equipment/equipment_type.py +53 -0
  229. mineproductivity/ontology/equipment/fixed_plant.py +56 -0
  230. mineproductivity/ontology/equipment/haul_truck.py +53 -0
  231. mineproductivity/ontology/equipment/loading_unit.py +61 -0
  232. mineproductivity/ontology/exceptions.py +23 -0
  233. mineproductivity/ontology/graph_projection.py +53 -0
  234. mineproductivity/ontology/location/__init__.py +10 -0
  235. mineproductivity/ontology/location/mine.py +45 -0
  236. mineproductivity/ontology/location/pit.py +68 -0
  237. mineproductivity/ontology/location/route.py +72 -0
  238. mineproductivity/ontology/location/underground.py +77 -0
  239. mineproductivity/ontology/maintenance/__init__.py +7 -0
  240. mineproductivity/ontology/maintenance/failure_mode.py +73 -0
  241. mineproductivity/ontology/material/__init__.py +8 -0
  242. mineproductivity/ontology/material/commodity.py +44 -0
  243. mineproductivity/ontology/material/material_type.py +15 -0
  244. mineproductivity/ontology/organization/__init__.py +9 -0
  245. mineproductivity/ontology/organization/business_unit.py +45 -0
  246. mineproductivity/ontology/organization/crew.py +61 -0
  247. mineproductivity/ontology/organization/fleet.py +43 -0
  248. mineproductivity/ontology/production/__init__.py +7 -0
  249. mineproductivity/ontology/production/shift.py +95 -0
  250. mineproductivity/ontology/quality/__init__.py +7 -0
  251. mineproductivity/ontology/quality/grade.py +74 -0
  252. mineproductivity/ontology/reference/__init__.py +12 -0
  253. mineproductivity/ontology/reference/delay_taxonomy.py +47 -0
  254. mineproductivity/ontology/relationship.py +50 -0
  255. mineproductivity/ontology/safety/__init__.py +7 -0
  256. mineproductivity/ontology/safety/hazard.py +86 -0
  257. mineproductivity/ontology/validation.py +75 -0
  258. mineproductivity/optimization/README.md +34 -0
  259. mineproductivity/optimization/__init__.py +112 -0
  260. mineproductivity/optimization/_registry.py +47 -0
  261. mineproductivity/optimization/abstractions.py +109 -0
  262. mineproductivity/optimization/comparison.py +64 -0
  263. mineproductivity/optimization/constraint_programming.py +38 -0
  264. mineproductivity/optimization/discovery.py +80 -0
  265. mineproductivity/optimization/evolutionary.py +49 -0
  266. mineproductivity/optimization/exceptions.py +49 -0
  267. mineproductivity/optimization/executor.py +234 -0
  268. mineproductivity/optimization/linear_programming.py +44 -0
  269. mineproductivity/optimization/metadata.py +72 -0
  270. mineproductivity/optimization/mixed_integer_programming.py +43 -0
  271. mineproductivity/optimization/multi_objective.py +43 -0
  272. mineproductivity/optimization/network_optimization.py +43 -0
  273. mineproductivity/optimization/persistence.py +23 -0
  274. mineproductivity/optimization/problem.py +238 -0
  275. mineproductivity/optimization/result.py +61 -0
  276. mineproductivity/optimization/run.py +71 -0
  277. mineproductivity/optimization/sensitivity.py +130 -0
  278. mineproductivity/optimization/state.py +48 -0
  279. mineproductivity/plugins/README.md +148 -0
  280. mineproductivity/plugins/__init__.py +33 -0
  281. mineproductivity/plugins/dependency.py +70 -0
  282. mineproductivity/plugins/exceptions.py +18 -0
  283. mineproductivity/plugins/lifecycle.py +140 -0
  284. mineproductivity/plugins/loader.py +53 -0
  285. mineproductivity/plugins/manifest.py +57 -0
  286. mineproductivity/py.typed +0 -0
  287. mineproductivity/registry/README.md +172 -0
  288. mineproductivity/registry/__init__.py +43 -0
  289. mineproductivity/registry/caching.py +55 -0
  290. mineproductivity/registry/decorators.py +63 -0
  291. mineproductivity/registry/entry_point.py +80 -0
  292. mineproductivity/registry/exceptions.py +34 -0
  293. mineproductivity/registry/registry.py +141 -0
  294. mineproductivity/registry/version_compat.py +75 -0
  295. mineproductivity/simulation/README.md +62 -0
  296. mineproductivity/simulation/__init__.py +115 -0
  297. mineproductivity/simulation/_registry.py +63 -0
  298. mineproductivity/simulation/abstractions.py +127 -0
  299. mineproductivity/simulation/caching.py +80 -0
  300. mineproductivity/simulation/calibration.py +55 -0
  301. mineproductivity/simulation/clock.py +82 -0
  302. mineproductivity/simulation/comparison.py +95 -0
  303. mineproductivity/simulation/discovery.py +104 -0
  304. mineproductivity/simulation/discrete_event.py +50 -0
  305. mineproductivity/simulation/exceptions.py +52 -0
  306. mineproductivity/simulation/executor.py +275 -0
  307. mineproductivity/simulation/experiment.py +117 -0
  308. mineproductivity/simulation/metadata.py +92 -0
  309. mineproductivity/simulation/montecarlo.py +58 -0
  310. mineproductivity/simulation/persistence.py +29 -0
  311. mineproductivity/simulation/replay.py +73 -0
  312. mineproductivity/simulation/result.py +66 -0
  313. mineproductivity/simulation/run.py +93 -0
  314. mineproductivity/simulation/scenario.py +156 -0
  315. mineproductivity/simulation/sensitivity.py +92 -0
  316. mineproductivity/simulation/state.py +70 -0
  317. mineproductivity/simulation/system_dynamics.py +49 -0
  318. mineproductivity/typing/why.txt +15 -0
  319. mineproductivity/utils/README.md +39 -0
  320. mineproductivity/utils/__init__.py +7 -0
  321. mineproductivity/validation/README.md +39 -0
  322. mineproductivity/validation/__init__.py +7 -0
  323. mineproductivity/visualization/README.md +27 -0
  324. mineproductivity/visualization/__init__.py +84 -0
  325. mineproductivity/visualization/_registry.py +85 -0
  326. mineproductivity/visualization/abstractions.py +179 -0
  327. mineproductivity/visualization/dashboard.py +64 -0
  328. mineproductivity/visualization/dashboard_builder.py +107 -0
  329. mineproductivity/visualization/discovery.py +46 -0
  330. mineproductivity/visualization/exceptions.py +42 -0
  331. mineproductivity/visualization/export.py +62 -0
  332. mineproductivity/visualization/layout.py +44 -0
  333. mineproductivity/visualization/persistence.py +26 -0
  334. mineproductivity/visualization/pipeline.py +88 -0
  335. mineproductivity/visualization/presentation.py +56 -0
  336. mineproductivity/visualization/renderer.py +90 -0
  337. mineproductivity/visualization/report.py +47 -0
  338. mineproductivity/visualization/report_builder.py +63 -0
  339. mineproductivity/visualization/theme.py +44 -0
  340. mineproductivity/visualization/widget.py +49 -0
  341. mineproductivity-2.0.0.dist-info/METADATA +445 -0
  342. mineproductivity-2.0.0.dist-info/RECORD +344 -0
  343. mineproductivity-2.0.0.dist-info/WHEEL +4 -0
  344. mineproductivity-2.0.0.dist-info/licenses/LICENSE +201 -0
@@ -0,0 +1,31 @@
1
+ # mineproductivity (package root)
2
+
3
+ ## Purpose
4
+
5
+ The single installable Python package containing every MineProductivity subsystem, organized as independently documented sub-packages with an enforced, inward-pointing dependency direction.
6
+
7
+ ## Scope
8
+
9
+ The `src/` layout root for the `mineproductivity` distribution. Contains 24 subsystem packages plus the package-level `__init__.py` exposing `__version__`. Does not contain tests (see `tests/`), datasets (see `datasets/`), or documentation (see `docs/`).
10
+
11
+ ## Responsibilities
12
+
13
+ - Expose the package version and top-level public API surface (currently empty).
14
+ - House all subsystem sub-packages listed below, each independently documented.
15
+
16
+ ## Contents
17
+
18
+ - `core/`, `events/`, `ontology/`, `kpis/`, `datasets/`, `connectors/`, `analytics/`, `optimization/`, `simulation/`, `digital_twin/`, `decision/`, `agents/`, `visualization/`, `benchmark/`, `certification/`, `config/`, `io/`, `utils/`, `typing/`, `cli/`, `exceptions/`, `registry/`, `plugins/`, `validation/`
19
+
20
+ ## Dependencies
21
+
22
+ No third-party runtime dependencies are declared yet (see pyproject.toml). Internal dependency direction between sub-packages is documented in the root README.md.
23
+
24
+ ## Future Work
25
+
26
+ Implement each sub-package per the phasing in ROADMAP.md, always starting with tests and metadata before behavior.
27
+
28
+ ## References
29
+
30
+ - Master Architecture Handbook v1.0
31
+ - Reference Implementation Blueprint v1.0
@@ -0,0 +1,50 @@
1
+ """MineProductivity — a metadata-first, ontology-driven, event-sourced
2
+ platform for mining productivity intelligence.
3
+
4
+ The ``mineproductivity.core`` package contains the platform's foundational
5
+ framework primitives (entities, value objects, identifiers, specifications,
6
+ repositories, and friends). The ``mineproductivity.events`` package
7
+ implements the immutable, append-only event model (Event Sourcing) built on
8
+ it, per the locked Event Framework Design Specification. The
9
+ ``mineproductivity.ontology`` package implements the full typed,
10
+ machine-readable domain vocabulary (ten sub-ontology families,
11
+ relationships, contextual validation, and the Knowledge Graph projection
12
+ contract) per the locked Ontology Framework Design Specification. The
13
+ ``mineproductivity.registry`` and ``mineproductivity.plugins`` packages
14
+ implement the plugin-first discovery-and-lifecycle backbone (the generic
15
+ ``Registry`` mechanism, entry-point discovery, and version-gated,
16
+ isolation-guaranteed plugin activation) per the locked Registry Framework
17
+ Design Specification. The ``mineproductivity.connectors`` package
18
+ implements the vendor-neutral ingestion boundary (the ``FMSConnector``
19
+ contract, reference file/network/streaming connectors, and
20
+ documentation-only OEM adapter shapes) per the locked Connector Framework
21
+ Design Specification. The ``mineproductivity.kpis`` package now implements
22
+ the metric backbone -- the metadata-first, self-describing KPI Engine (the
23
+ ``BaseKPI``/``CompositeKPI`` object model, dependency-graph orchestration,
24
+ pluggable execution backends, and the 12-KPI Standard Library reference
25
+ implementation) per the locked KPI Engine Design Specification. The
26
+ ``mineproductivity.analytics`` package implements the statistical and
27
+ analytical computation layer built directly on ``kpis`` -- trend, baseline,
28
+ and benchmark analysis, rolling and aggregate statistics, data-quality
29
+ scoring, batch/streaming/incremental execution modes, and the plugin
30
+ registry -- per the locked Analytics Engine Design Specification. The
31
+ ``mineproductivity.decision`` package implements the platform's
32
+ prescriptive layer built directly on ``analytics`` -- rule/policy-driven
33
+ decision strategies, ranking, explanation, prioritization, action
34
+ planning, alerting, real-time and batch decision execution, and an
35
+ append-only decision audit trail -- per the locked Decision Intelligence
36
+ Design Specification. The ``mineproductivity.digital_twin``,
37
+ ``mineproductivity.simulation``, and ``mineproductivity.optimization``
38
+ packages implement the stateful representation, projection, and
39
+ prescriptive-search layers respectively, ``mineproductivity.agents``
40
+ implements the model-independent agent-orchestration layer, and
41
+ ``mineproductivity.visualization`` implements the presentation layer --
42
+ the final package in the architecture -- each per its own locked design
43
+ specification. Every package in the locked dependency chain is now
44
+ implemented. See the root README.md and docs/architecture/README.md for
45
+ the governing architecture, and ROADMAP.md for the implementation
46
+ phasing.
47
+ """
48
+
49
+ __version__ = "2.0.0"
50
+ __all__ = ["__version__"]
@@ -0,0 +1,27 @@
1
+ # mineproductivity.agents
2
+
3
+ ## Purpose
4
+
5
+ The AI-agent orchestration layer (design spec 11) — a model-independent orchestration layer for autonomous and semi-autonomous work, built directly above `optimization`. It defines *how* agent work is governed (`AgentPolicy`/`PolicyEngine`/`AgentCapabilitySet`), gated (`ApprovalRequest`), executed (`Task`/`TaskExecutor`), decomposed and delegated (`Goal`/`WorkflowEngine`/`AgentMessage`/`DelegationRequest`), and audited (`AgentAuditTrail`) — while `Agent`, `Tool`, and `AgentMemory` remain interface-only extension points: choosing a reasoning backend is exactly the implementation decision this package excludes.
6
+
7
+ ## Governing documents
8
+
9
+ - [`docs/architecture/11_AI_Agents_Design_Specification.md`](../../../docs/architecture/11_AI_Agents_Design_Specification.md)
10
+ - [`docs/design/11_AI_Agents_Implementation_Checklist.md`](../../../docs/design/11_AI_Agents_Implementation_Checklist.md)
11
+ - [`docs/adr/ADR-0011-AI-Agents.md`](../../../docs/adr/ADR-0011-AI-Agents.md)
12
+
13
+ ## Scope
14
+
15
+ **What belongs here:** agent/task/policy/approval/workflow/audit orchestration contracts and their reference execution path.
16
+
17
+ **What must never belong here:** a concrete `Agent`, `Tool`, or `AgentMemory` implementation; any LLM-provider SDK coupling; any recomputation of a KPI, statistical, decision, twin-state, simulation, or optimization fact a lower package already owns.
18
+
19
+ ## Dependencies
20
+
21
+ **Depends on:** `core`, `events` (transport for `AgentMessage`, composed by callers), `registry`, `connectors` (`RetryPolicy` as the retry-configuration shape, per spec 11 §12), `kpis`, `analytics`, `decision` (`Explanation` reused directly), `digital_twin`, `simulation`, `optimization`.
22
+
23
+ **Depended on by:** `visualization` (future). No lower package imports `agents`.
24
+
25
+ ## Extension points
26
+
27
+ Register a concrete `Agent` with `@register` (entry-point group `mineproductivity.agents`) and a concrete `Tool` with `@register_tool` (group `mineproductivity.agents.tools`); implement a `TaskRepository` backend as a `core.BaseRepository[Task, str]`; subclass `AgentMemory` for a memory backend (wired per-agent, not globally discovered).
@@ -0,0 +1,85 @@
1
+ """``mineproductivity.agents`` -- the AI-agent orchestration layer
2
+ (design spec 11): a model-independent orchestration layer for
3
+ autonomous and semi-autonomous work, built directly above
4
+ ``optimization``. Defines *how* agent work is governed, gated,
5
+ executed, delegated, and audited -- ``Agent``/``Tool``/``AgentMemory``
6
+ are interface-only extension points; choosing a reasoning backend is
7
+ exactly the implementation decision this package excludes (§3.1, §4).
8
+
9
+ Public API (design spec §7) -- every name stable once implementation
10
+ begins.
11
+ """
12
+
13
+ from __future__ import annotations
14
+
15
+ from mineproductivity.agents._registry import REGISTRY, TOOLS, register, register_tool
16
+ from mineproductivity.agents.abstractions import Agent, AgentContext
17
+ from mineproductivity.agents.approval import ApprovalRequest, ApprovalStatus
18
+ from mineproductivity.agents.audit import AgentAuditEntry, AgentAuditTrail
19
+ from mineproductivity.agents.capability import AgentCapabilitySet, Permission
20
+ from mineproductivity.agents.communication import AgentMessage, DelegationRequest
21
+ from mineproductivity.agents.conversation import ConversationContext, ConversationTurn
22
+ from mineproductivity.agents.discovery import by_category, by_scope
23
+ from mineproductivity.agents.exceptions import (
24
+ AgentExecutionError,
25
+ AgentValidationError,
26
+ AgentVersionConflictError,
27
+ PermissionDeniedError,
28
+ PolicyConflictError,
29
+ TaskNotFoundError,
30
+ )
31
+ from mineproductivity.agents.executor import TaskExecutor
32
+ from mineproductivity.agents.goal import Goal
33
+ from mineproductivity.agents.memory import AgentMemory
34
+ from mineproductivity.agents.metadata import AgentCategory, AgentMetadata
35
+ from mineproductivity.agents.persistence import TaskRepository
36
+ from mineproductivity.agents.policy import AgentPolicy, PolicyEngine, PolicyStatus
37
+ from mineproductivity.agents.result import AgentResult
38
+ from mineproductivity.agents.state import TaskState
39
+ from mineproductivity.agents.task import Task, TaskStatus
40
+ from mineproductivity.agents.tool import Tool, ToolInvocation, ToolMetadata
41
+ from mineproductivity.agents.workflow import WorkflowEngine
42
+
43
+ __all__ = [
44
+ "Agent",
45
+ "AgentAuditEntry",
46
+ "AgentAuditTrail",
47
+ "AgentCapabilitySet",
48
+ "AgentCategory",
49
+ "AgentContext",
50
+ "AgentExecutionError",
51
+ "AgentMemory",
52
+ "AgentMessage",
53
+ "AgentMetadata",
54
+ "AgentPolicy",
55
+ "AgentResult",
56
+ "AgentValidationError",
57
+ "AgentVersionConflictError",
58
+ "ApprovalRequest",
59
+ "ApprovalStatus",
60
+ "ConversationContext",
61
+ "ConversationTurn",
62
+ "DelegationRequest",
63
+ "Goal",
64
+ "Permission",
65
+ "PermissionDeniedError",
66
+ "PolicyConflictError",
67
+ "PolicyEngine",
68
+ "PolicyStatus",
69
+ "REGISTRY",
70
+ "TOOLS",
71
+ "Task",
72
+ "TaskExecutor",
73
+ "TaskNotFoundError",
74
+ "TaskRepository",
75
+ "TaskState",
76
+ "TaskStatus",
77
+ "Tool",
78
+ "ToolInvocation",
79
+ "ToolMetadata",
80
+ "WorkflowEngine",
81
+ "by_category",
82
+ "by_scope",
83
+ "register",
84
+ "register_tool",
85
+ ]
@@ -0,0 +1,84 @@
1
+ """The Agent Registry and the Tool Registry (design spec §22) -- two
2
+ typed specializations of ``registry.Registry``, the first package in
3
+ this series to hold two distinct ``Registry`` instances rather than
4
+ one, since an ``Agent`` type and a ``Tool`` type are orthogonal
5
+ registrable concepts (§22): an ``Agent`` decides; a ``Tool`` acts at
6
+ an ``Agent``'s direction. The two are never merged. Both answer the
7
+ type-level question ("which types are known"), never conflated with
8
+ ``TaskRepository`` (instance-level) or ``discovery.py`` (query
9
+ facade). Entry-point discovery uses ``registry.EntryPointDiscovery``
10
+ with ``EntryPointSpec(group="mineproductivity.agents",
11
+ target_registry="agents")`` and
12
+ ``EntryPointSpec(group="mineproductivity.agents.tools",
13
+ target_registry="agents.tools")`` (design spec §31), exactly as every
14
+ prior domain package already wires its own group.
15
+ """
16
+
17
+ from __future__ import annotations
18
+
19
+ from mineproductivity.registry import Registry
20
+
21
+ from mineproductivity.agents.abstractions import Agent
22
+ from mineproductivity.agents.exceptions import (
23
+ AgentValidationError,
24
+ AgentVersionConflictError,
25
+ )
26
+ from mineproductivity.agents.tool import Tool
27
+
28
+ __all__ = ["REGISTRY", "TOOLS", "register", "register_tool"]
29
+
30
+ REGISTRY: Registry[str, type[Agent]] = Registry(name="agents")
31
+ TOOLS: Registry[str, type[Tool]] = Registry(name="agents.tools")
32
+
33
+
34
+ def register(cls: type[Agent]) -> type[Agent]:
35
+ """Register ``cls`` into :data:`REGISTRY`, keyed by
36
+ ``cls.meta.code``.
37
+
38
+ Raises
39
+ ------
40
+ AgentValidationError
41
+ If ``cls.meta.code`` is empty (defensive, redundant guard --
42
+ ``AgentMetadata.validate()`` already rejects it).
43
+ AgentVersionConflictError
44
+ If ``cls.meta.code`` is already registered -- add-only, raised
45
+ at registration time, never deferred (design spec §26).
46
+ """
47
+ if not cls.meta.code:
48
+ raise AgentValidationError(f"{cls.__name__}.meta.code must not be empty")
49
+
50
+ result = REGISTRY.register(cls.meta.code, cls, metadata=cls.meta)
51
+ if result.is_err:
52
+ raise AgentVersionConflictError(
53
+ f"Agent code {cls.meta.code!r} is already registered; changing what it "
54
+ f"means requires a new code or a reviewed version bump, not "
55
+ f"re-registration"
56
+ )
57
+
58
+ return cls
59
+
60
+
61
+ def register_tool(cls: type[Tool]) -> type[Tool]:
62
+ """Register ``cls`` into :data:`TOOLS`, keyed by ``cls.meta.code``
63
+ -- identical shape and identical error semantics as
64
+ :func:`register`, specialized for ``Tool`` (design spec §22).
65
+
66
+ Raises
67
+ ------
68
+ AgentValidationError
69
+ If ``cls.meta.code`` is empty.
70
+ AgentVersionConflictError
71
+ If ``cls.meta.code`` is already registered in :data:`TOOLS`.
72
+ """
73
+ if not cls.meta.code:
74
+ raise AgentValidationError(f"{cls.__name__}.meta.code must not be empty")
75
+
76
+ result = TOOLS.register(cls.meta.code, cls, metadata=cls.meta)
77
+ if result.is_err:
78
+ raise AgentVersionConflictError(
79
+ f"Tool code {cls.meta.code!r} is already registered; changing what it "
80
+ f"means requires a new code or a reviewed version bump, not "
81
+ f"re-registration"
82
+ )
83
+
84
+ return cls
@@ -0,0 +1,113 @@
1
+ """``Agent``: the "Agent-as-object" root, and ``AgentContext``, the
2
+ collaborator/evidence bundle a concrete agent reasons over (design
3
+ spec §8).
4
+
5
+ Reuse audit: ``AgentContext`` mirrors
6
+ ``optimization.OptimizationContext`` (spec 10 §8) one layer up,
7
+ extended with ``optimization_results`` -- an agent may read an
8
+ already-solved plan a not-yet-solved ``OptimizationProblem`` could
9
+ never reference. Evidence is read, never re-derived (§3.2), and
10
+ assembly happens once, at construction -- never re-fetched per retry
11
+ or per delegation (§27, §36). Per ``decision.DecisionContext``'s own
12
+ established convention (spec 07 §8), the caller-assembles pattern is
13
+ used exclusively. ``Agent`` shares one abstract method (``_act``)
14
+ across all ten categories, mirroring ``decision.DecisionModel``'s
15
+ shared-``_decide`` posture (spec 07 §8) rather than ``simulation``'s/
16
+ ``optimization``'s no-shared-method posture: every category answers
17
+ the same underlying question -- given a task and context, decide what
18
+ should happen next. THIS MODULE SHIPS NO CONCRETE SUBCLASS --
19
+ choosing a specific reasoning backend (a hosted large-language-model
20
+ service, a local model, a rule engine) is exactly the kind of
21
+ implementation decision this package's charter (§3.1, §3.5, §4)
22
+ excludes.
23
+ """
24
+
25
+ from __future__ import annotations
26
+
27
+ from abc import ABC, abstractmethod
28
+ from collections.abc import Sequence
29
+ from typing import TYPE_CHECKING, ClassVar
30
+
31
+ from mineproductivity.analytics import AnalyticsResult
32
+ from mineproductivity.decision import DecisionResult
33
+ from mineproductivity.digital_twin import TwinSnapshot
34
+ from mineproductivity.kpis import KPIResult
35
+ from mineproductivity.optimization import OptimizationResult
36
+ from mineproductivity.simulation import SimulationResult
37
+
38
+ from mineproductivity.agents.metadata import AgentMetadata
39
+
40
+ if TYPE_CHECKING:
41
+ from mineproductivity.agents.result import AgentResult
42
+ from mineproductivity.agents.task import Task
43
+
44
+ __all__ = ["Agent", "AgentContext"]
45
+
46
+
47
+ class AgentContext:
48
+ """Bundles the evidence an ``Agent`` may need (design spec §8) --
49
+ carried once, at construction; every fact an agent reasons over
50
+ has a stable, structured home in a lower package, never a
51
+ re-derivation of its own.
52
+
53
+ Examples
54
+ --------
55
+ >>> context = AgentContext()
56
+ >>> context.kpi_results
57
+ ()
58
+ >>> context.twin_snapshot is None
59
+ True
60
+ """
61
+
62
+ def __init__(
63
+ self,
64
+ *,
65
+ kpi_results: Sequence[KPIResult] = (),
66
+ analytics_results: Sequence[AnalyticsResult] = (),
67
+ decision_results: Sequence[DecisionResult] = (),
68
+ twin_snapshot: TwinSnapshot | None = None,
69
+ simulation_results: Sequence[SimulationResult] = (),
70
+ optimization_results: Sequence[OptimizationResult] = (),
71
+ ) -> None:
72
+ self.kpi_results = tuple(kpi_results)
73
+ self.analytics_results = tuple(analytics_results)
74
+ self.decision_results = tuple(decision_results)
75
+ self.twin_snapshot = twin_snapshot
76
+ self.simulation_results = tuple(simulation_results)
77
+ self.optimization_results = tuple(optimization_results)
78
+
79
+ def __repr__(self) -> str:
80
+ return (
81
+ f"{type(self).__name__}(kpi_results={self.kpi_results!r}, "
82
+ f"analytics_results={self.analytics_results!r}, "
83
+ f"decision_results={self.decision_results!r}, "
84
+ f"twin_snapshot={self.twin_snapshot!r}, "
85
+ f"simulation_results={self.simulation_results!r}, "
86
+ f"optimization_results={self.optimization_results!r})"
87
+ )
88
+
89
+
90
+ class Agent(ABC):
91
+ """The root of every registrable agent type (design spec §8) --
92
+ the direct counterpart of ``optimization.OptimizationModel`` one
93
+ layer down, whose category members (§29) are domain roles rather
94
+ than algorithmic paradigms.
95
+
96
+ **Statelessness.** Every subclass, of every category, is stateless
97
+ -- no instance attribute is mutated by any ``_act`` implementation
98
+ (§29, §32); statefulness lives entirely in ``Task`` (§11), so the
99
+ same registered ``Agent`` type can execute many concurrent
100
+ ``Task``\\ s safely.
101
+
102
+ **Qualify, don't coerce** (§30): no ``_act`` implementation raises
103
+ for a legitimately incomplete or ambiguous task -- it returns an
104
+ ``AgentResult`` carrying a warning instead.
105
+ """
106
+
107
+ meta: ClassVar[AgentMetadata]
108
+
109
+ @abstractmethod
110
+ def _act(self, task: Task, *, context: AgentContext) -> AgentResult:
111
+ """Given ``task`` and ``context``, decide what should happen
112
+ next -- the one shared reasoning call every category answers
113
+ (design spec §8)."""
@@ -0,0 +1,56 @@
1
+ """``ApprovalRequest``/``ApprovalStatus``: the human-in-the-loop gate
2
+ (design spec §16).
3
+
4
+ Reuse audit: ``core.BaseValueObject`` reused verbatim. Genuinely new
5
+ to this series: no package below ``agents`` pauses mid-execution for a
6
+ human decision. An ``ApprovalRequest`` resolving to ``APPROVED``
7
+ transitions its ``Task`` from ``AWAITING_APPROVAL`` back to
8
+ ``RUNNING``; a resolution to ``REJECTED`` transitions it directly to
9
+ ``FAILED``, carrying the rejection as a warning on the eventual
10
+ ``AgentResult`` (§16, §11). ``TaskExecutor`` never resolves an
11
+ ``ApprovalRequest`` itself -- resolution is exclusively a caller
12
+ (human-supervisor-facing) action.
13
+ """
14
+
15
+ from __future__ import annotations
16
+
17
+ import dataclasses
18
+ from datetime import datetime
19
+ from enum import Enum
20
+
21
+ from mineproductivity.core import BaseValueObject
22
+
23
+ __all__ = ["ApprovalRequest", "ApprovalStatus"]
24
+
25
+
26
+ class ApprovalStatus(Enum):
27
+ """The three-state approval lifecycle a ``Task`` pauses on when
28
+ ``PolicyEngine`` (design spec §10) requires it -- closed; a new
29
+ approval *policy* (who must approve what) is an ``AgentPolicy``
30
+ concern, not a change here."""
31
+
32
+ PENDING = "pending"
33
+ APPROVED = "approved"
34
+ REJECTED = "rejected"
35
+
36
+
37
+ @dataclasses.dataclass(frozen=True, slots=True)
38
+ class ApprovalRequest(BaseValueObject):
39
+ """One pending, approved, or rejected request for a human to
40
+ authorize a ``Task`` before ``TaskExecutor`` (design spec §12)
41
+ resumes it.
42
+
43
+ Examples
44
+ --------
45
+ >>> request = ApprovalRequest(task_id="TASK-1", requested_action="approve_shutdown")
46
+ >>> request.status
47
+ <ApprovalStatus.PENDING: 'pending'>
48
+ >>> request.approver is None
49
+ True
50
+ """
51
+
52
+ task_id: str
53
+ requested_action: str
54
+ status: ApprovalStatus = dataclasses.field(default=ApprovalStatus.PENDING, kw_only=True)
55
+ approver: str | None = dataclasses.field(default=None, kw_only=True)
56
+ resolved_at: datetime | None = dataclasses.field(default=None, kw_only=True)
@@ -0,0 +1,102 @@
1
+ """``AgentAuditTrail``/``AgentAuditEntry``: accountability for
2
+ autonomous action (design spec §21), mirroring
3
+ ``decision.DecisionAuditTrail``'s pattern and rationale (spec 07 §27)
4
+ -- the accountability mechanism an autonomous-action system requires
5
+ even more urgently than a purely recommending one does.
6
+
7
+ Thread safety (design spec §32): :meth:`AgentAuditTrail.record`
8
+ serializes concurrent appends internally via one ``threading.Lock``,
9
+ so many concurrently-executing ``Task``\\ s can share one trail
10
+ instance safely; :meth:`AgentAuditTrail.query` reads a snapshot taken
11
+ under the same lock, then filters outside it, so it never blocks on a
12
+ concurrent ``record()`` beyond the snapshot itself. Every
13
+ ``AgentResult``'s ``explanation`` and every ``ToolInvocation`` it
14
+ carries are preserved verbatim in the recorded entry -- an agent's
15
+ audit record is never a summary, always the full, structured outcome.
16
+ """
17
+
18
+ from __future__ import annotations
19
+
20
+ import dataclasses
21
+ import threading
22
+ from collections.abc import Mapping, Sequence
23
+ from datetime import datetime
24
+ from types import MappingProxyType
25
+
26
+ from mineproductivity.core import BaseValueObject
27
+
28
+ from mineproductivity.agents.result import AgentResult
29
+
30
+ __all__ = ["AgentAuditEntry", "AgentAuditTrail"]
31
+
32
+
33
+ @dataclasses.dataclass(frozen=True, slots=True)
34
+ class AgentAuditEntry(BaseValueObject):
35
+ """One append-only record: which agent produced which result, for
36
+ what scope, when (design spec §21).
37
+
38
+ Examples
39
+ --------
40
+ >>> from datetime import timezone
41
+ >>> entry = AgentAuditEntry(
42
+ ... recorded_at=datetime(2026, 7, 1, tzinfo=timezone.utc),
43
+ ... result=AgentResult(task_id="TASK-1"),
44
+ ... agent_code="FLEET.ReassignmentAdvisor", scope={"pit": "north"},
45
+ ... )
46
+ >>> dict(entry.scope)
47
+ {'pit': 'north'}
48
+ """
49
+
50
+ recorded_at: datetime
51
+ result: AgentResult
52
+ agent_code: str
53
+ scope: Mapping[str, str]
54
+
55
+ def _normalize(self) -> None:
56
+ super(AgentAuditEntry, self)._normalize()
57
+ object.__setattr__(self, "scope", MappingProxyType(dict(self.scope)))
58
+
59
+
60
+ class AgentAuditTrail:
61
+ """Append-only record of every terminal ``AgentResult`` produced
62
+ by any ``TaskExecutor`` run in this process (design spec §21).
63
+ Serializes via ``core.serialization`` exactly as every other value
64
+ object in this platform does.
65
+
66
+ Examples
67
+ --------
68
+ >>> from datetime import timezone
69
+ >>> trail = AgentAuditTrail()
70
+ >>> trail.record(AgentAuditEntry(
71
+ ... recorded_at=datetime(2026, 7, 1, tzinfo=timezone.utc),
72
+ ... result=AgentResult(task_id="TASK-1"),
73
+ ... agent_code="FLEET.ReassignmentAdvisor", scope={"pit": "north"},
74
+ ... ))
75
+ >>> len(trail.query())
76
+ 1
77
+ >>> len(trail.query(scope={"pit": "south"}))
78
+ 0
79
+ """
80
+
81
+ def __init__(self) -> None:
82
+ self._entries: list[AgentAuditEntry] = []
83
+ self._lock = threading.Lock()
84
+
85
+ def record(self, entry: AgentAuditEntry) -> None:
86
+ with self._lock:
87
+ self._entries.append(entry)
88
+
89
+ def query(self, *, scope: Mapping[str, str] | None = None) -> Sequence[AgentAuditEntry]:
90
+ with self._lock:
91
+ snapshot = tuple(self._entries)
92
+ if scope is None:
93
+ return snapshot
94
+ return tuple(
95
+ entry
96
+ for entry in snapshot
97
+ if all(entry.scope.get(key) == value for key, value in scope.items())
98
+ )
99
+
100
+ def __repr__(self) -> str:
101
+ with self._lock:
102
+ return f"{type(self).__name__}(entries={len(self._entries)})"
@@ -0,0 +1,91 @@
1
+ """``Permission``/``AgentCapabilitySet``: authorization for autonomous
2
+ action (design spec §9).
3
+
4
+ Reuse audit: ``core.BaseValueObject`` and the
5
+ ``MappingProxyType``-freezing convention reused verbatim; ``scope``
6
+ carries the same ontology-expressed vocabulary (equipment, pit, shift)
7
+ ``digital_twin.Twin.scope`` already carries (spec 08 §9), held as
8
+ plain strings per Documentation Governance Rule #005. Genuinely new to
9
+ this series: no package below ``agents`` models authorization, since
10
+ none of them acts autonomously in the first place.
11
+
12
+ Governance: an ``AgentCapabilitySet`` is always an explicit, authored,
13
+ and governed artifact -- never inferred from an ``Agent`` subclass's
14
+ own code at runtime (design spec §9). :func:`publish_capabilities`/
15
+ :func:`published_capabilities` mirror ``optimization.publish_problem``'s
16
+ process-wide governed store, keyed by ``agent_code``; neither is
17
+ re-exported from the package's top-level ``__all__`` (design spec §7
18
+ names ``Permission``/``AgentCapabilitySet`` only).
19
+ """
20
+
21
+ from __future__ import annotations
22
+
23
+ import dataclasses
24
+ import threading
25
+ from collections.abc import Mapping
26
+ from types import MappingProxyType
27
+
28
+ from mineproductivity.core import BaseValueObject
29
+
30
+ __all__ = ["AgentCapabilitySet", "Permission"]
31
+
32
+ _capabilities: dict[str, AgentCapabilitySet] = {}
33
+ _lock = threading.Lock()
34
+
35
+
36
+ @dataclasses.dataclass(frozen=True, slots=True)
37
+ class Permission(BaseValueObject):
38
+ """One capability a registered ``Agent`` is authorized to
39
+ exercise, scoped the same way ``digital_twin.Twin.scope`` already
40
+ is (design spec §9).
41
+
42
+ Examples
43
+ --------
44
+ >>> Permission(capability="approve_shutdown", scope={"pit": "north"}).capability
45
+ 'approve_shutdown'
46
+ """
47
+
48
+ capability: str
49
+ scope: Mapping[str, str] = dataclasses.field(default_factory=dict, kw_only=True)
50
+
51
+ def _normalize(self) -> None:
52
+ super(Permission, self)._normalize()
53
+ object.__setattr__(self, "scope", MappingProxyType(dict(self.scope)))
54
+
55
+
56
+ @dataclasses.dataclass(frozen=True, slots=True)
57
+ class AgentCapabilitySet(BaseValueObject):
58
+ """The full set of ``Permission``\\ s a registered ``Agent`` type
59
+ carries -- authored and governed, never inferred from an agent's
60
+ own code (design spec §9).
61
+
62
+ Examples
63
+ --------
64
+ >>> caps = AgentCapabilitySet(
65
+ ... agent_code="FLEET.ReassignmentAdvisor",
66
+ ... permissions=(Permission(capability="reassign_truck"),),
67
+ ... )
68
+ >>> caps.permissions[0].capability
69
+ 'reassign_truck'
70
+ """
71
+
72
+ agent_code: str
73
+ permissions: tuple[Permission, ...]
74
+
75
+
76
+ def publish_capabilities(capabilities: AgentCapabilitySet) -> AgentCapabilitySet:
77
+ """Publish ``capabilities`` into the process-wide governed store,
78
+ keyed by ``capabilities.agent_code`` (design spec §9, §31) -- the
79
+ explicit authoring step that makes a capability grant a
80
+ reviewable artifact."""
81
+ with _lock:
82
+ _capabilities[capabilities.agent_code] = capabilities
83
+ return capabilities
84
+
85
+
86
+ def published_capabilities(agent_code: str) -> AgentCapabilitySet | None:
87
+ """Non-raising lookup of the currently-published capability set
88
+ for ``agent_code``, or ``None`` -- an agent with no published set
89
+ holds no permissions at all."""
90
+ with _lock:
91
+ return _capabilities.get(agent_code)