plm-engine-core 1.0.4__tar.gz → 1.2.0__tar.gz

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 (153) hide show
  1. {plm_engine_core-1.0.4 → plm_engine_core-1.2.0}/PKG-INFO +197 -191
  2. {plm_engine_core-1.0.4 → plm_engine_core-1.2.0}/README.md +162 -162
  3. {plm_engine_core-1.0.4 → plm_engine_core-1.2.0}/plm_engine_core/__init__.py +24 -24
  4. {plm_engine_core-1.0.4 → plm_engine_core-1.2.0}/plm_engine_core/agent_runtime/__init__.py +31 -31
  5. {plm_engine_core-1.0.4 → plm_engine_core-1.2.0}/plm_engine_core/agent_runtime/dispatcher.py +343 -343
  6. {plm_engine_core-1.0.4 → plm_engine_core-1.2.0}/plm_engine_core/agent_runtime/selector.py +154 -154
  7. {plm_engine_core-1.0.4 → plm_engine_core-1.2.0}/plm_engine_core/cli/__init__.py +64 -64
  8. {plm_engine_core-1.0.4 → plm_engine_core-1.2.0}/plm_engine_core/cli/__main__.py +15 -15
  9. {plm_engine_core-1.0.4 → plm_engine_core-1.2.0}/plm_engine_core/cli/auth.py +125 -125
  10. {plm_engine_core-1.0.4 → plm_engine_core-1.2.0}/plm_engine_core/control_plane/__init__.py +52 -52
  11. {plm_engine_core-1.0.4 → plm_engine_core-1.2.0}/plm_engine_core/control_plane/_lint_fixtures/__init__.py +16 -16
  12. {plm_engine_core-1.0.4 → plm_engine_core-1.2.0}/plm_engine_core/control_plane/_lint_fixtures/violation_demo.py +28 -28
  13. {plm_engine_core-1.0.4 → plm_engine_core-1.2.0}/plm_engine_core/control_plane/capability_registry/__init__.py +45 -45
  14. {plm_engine_core-1.0.4 → plm_engine_core-1.2.0}/plm_engine_core/control_plane/capability_registry/errors.py +71 -71
  15. {plm_engine_core-1.0.4 → plm_engine_core-1.2.0}/plm_engine_core/control_plane/capability_registry/registry.py +403 -403
  16. {plm_engine_core-1.0.4 → plm_engine_core-1.2.0}/plm_engine_core/control_plane/connectors/__init__.py +71 -53
  17. {plm_engine_core-1.0.4 → plm_engine_core-1.2.0}/plm_engine_core/control_plane/connectors/dispatcher.py +148 -148
  18. {plm_engine_core-1.0.4 → plm_engine_core-1.2.0}/plm_engine_core/control_plane/connectors/runtime.py +214 -214
  19. {plm_engine_core-1.0.4 → plm_engine_core-1.2.0}/plm_engine_core/control_plane/dispatch.py +180 -180
  20. {plm_engine_core-1.0.4 → plm_engine_core-1.2.0}/plm_engine_core/control_plane/hitl/__init__.py +45 -45
  21. {plm_engine_core-1.0.4 → plm_engine_core-1.2.0}/plm_engine_core/control_plane/hitl/errors.py +74 -74
  22. {plm_engine_core-1.0.4 → plm_engine_core-1.2.0}/plm_engine_core/control_plane/hitl/gate.py +555 -555
  23. {plm_engine_core-1.0.4 → plm_engine_core-1.2.0}/plm_engine_core/control_plane/hitl/sql_store.py +380 -380
  24. {plm_engine_core-1.0.4 → plm_engine_core-1.2.0}/plm_engine_core/control_plane/identity/__init__.py +46 -46
  25. {plm_engine_core-1.0.4 → plm_engine_core-1.2.0}/plm_engine_core/control_plane/identity/middleware.py +349 -349
  26. {plm_engine_core-1.0.4 → plm_engine_core-1.2.0}/plm_engine_core/control_plane/identity/provider.py +249 -249
  27. {plm_engine_core-1.0.4 → plm_engine_core-1.2.0}/plm_engine_core/control_plane/identity/system_identity.py +92 -92
  28. {plm_engine_core-1.0.4 → plm_engine_core-1.2.0}/plm_engine_core/control_plane/identity/telemetry.py +146 -146
  29. {plm_engine_core-1.0.4 → plm_engine_core-1.2.0}/plm_engine_core/control_plane/knowledge/__init__.py +79 -79
  30. {plm_engine_core-1.0.4 → plm_engine_core-1.2.0}/plm_engine_core/control_plane/knowledge/curation_index.py +119 -119
  31. {plm_engine_core-1.0.4 → plm_engine_core-1.2.0}/plm_engine_core/control_plane/knowledge/envelope.py +358 -358
  32. {plm_engine_core-1.0.4 → plm_engine_core-1.2.0}/plm_engine_core/control_plane/knowledge/runtime.py +205 -205
  33. {plm_engine_core-1.0.4 → plm_engine_core-1.2.0}/plm_engine_core/control_plane/policies/__init__.py +74 -74
  34. {plm_engine_core-1.0.4 → plm_engine_core-1.2.0}/plm_engine_core/control_plane/policies/authorization.py +192 -192
  35. {plm_engine_core-1.0.4 → plm_engine_core-1.2.0}/plm_engine_core/control_plane/policies/autonomy_gating.py +273 -273
  36. {plm_engine_core-1.0.4 → plm_engine_core-1.2.0}/plm_engine_core/control_plane/policies/base.py +174 -174
  37. {plm_engine_core-1.0.4 → plm_engine_core-1.2.0}/plm_engine_core/control_plane/policies/cost_budget.py +490 -490
  38. {plm_engine_core-1.0.4 → plm_engine_core-1.2.0}/plm_engine_core/control_plane/policies/rate_limit.py +369 -369
  39. {plm_engine_core-1.0.4 → plm_engine_core-1.2.0}/plm_engine_core/control_plane/retry_policy.py +288 -288
  40. {plm_engine_core-1.0.4 → plm_engine_core-1.2.0}/plm_engine_core/control_plane/run_task_tracker.py +262 -262
  41. {plm_engine_core-1.0.4 → plm_engine_core-1.2.0}/plm_engine_core/core_host/__init__.py +21 -21
  42. {plm_engine_core-1.0.4 → plm_engine_core-1.2.0}/plm_engine_core/core_host/__main__.py +11 -11
  43. plm_engine_core-1.2.0/plm_engine_core/core_host/agent_run/__init__.py +45 -0
  44. plm_engine_core-1.2.0/plm_engine_core/core_host/agent_run/bundle.py +187 -0
  45. plm_engine_core-1.2.0/plm_engine_core/core_host/agent_run/dto.py +175 -0
  46. plm_engine_core-1.2.0/plm_engine_core/core_host/agent_run/event_bus.py +290 -0
  47. plm_engine_core-1.2.0/plm_engine_core/core_host/agent_run/executor.py +732 -0
  48. plm_engine_core-1.2.0/plm_engine_core/core_host/agent_run/governance.py +250 -0
  49. plm_engine_core-1.2.0/plm_engine_core/core_host/agent_run/hitl.py +73 -0
  50. plm_engine_core-1.2.0/plm_engine_core/core_host/agent_run/lifecycle.py +144 -0
  51. plm_engine_core-1.2.0/plm_engine_core/core_host/agent_run/mcrc.py +219 -0
  52. plm_engine_core-1.2.0/plm_engine_core/core_host/agent_run/registry.py +426 -0
  53. plm_engine_core-1.2.0/plm_engine_core/core_host/agent_run/snapshot.py +192 -0
  54. plm_engine_core-1.2.0/plm_engine_core/core_host/agent_run/taxonomy.py +211 -0
  55. {plm_engine_core-1.0.4 → plm_engine_core-1.2.0}/plm_engine_core/core_host/main.py +454 -411
  56. plm_engine_core-1.2.0/plm_engine_core/core_host/readiness.py +195 -0
  57. {plm_engine_core-1.0.4 → plm_engine_core-1.2.0}/plm_engine_core/core_host/routers/__init__.py +1 -1
  58. plm_engine_core-1.2.0/plm_engine_core/core_host/routers/agent_runs.py +390 -0
  59. {plm_engine_core-1.0.4 → plm_engine_core-1.2.0}/plm_engine_core/core_host/routers/config.py +72 -72
  60. {plm_engine_core-1.0.4 → plm_engine_core-1.2.0}/plm_engine_core/core_host/routers/health.py +141 -105
  61. {plm_engine_core-1.0.4 → plm_engine_core-1.2.0}/plm_engine_core/core_host/settings.py +98 -88
  62. {plm_engine_core-1.0.4 → plm_engine_core-1.2.0}/plm_engine_core/llm_catalog/__init__.py +37 -37
  63. {plm_engine_core-1.0.4 → plm_engine_core-1.2.0}/plm_engine_core/llm_catalog/loader.py +363 -363
  64. {plm_engine_core-1.0.4 → plm_engine_core-1.2.0}/plm_engine_core/llm_catalog/model_list.yaml +57 -57
  65. {plm_engine_core-1.0.4 → plm_engine_core-1.2.0}/plm_engine_core/mcp/__init__.py +63 -63
  66. {plm_engine_core-1.0.4 → plm_engine_core-1.2.0}/plm_engine_core/mcp/asgi.py +195 -195
  67. {plm_engine_core-1.0.4 → plm_engine_core-1.2.0}/plm_engine_core/mcp/errors.py +41 -41
  68. {plm_engine_core-1.0.4 → plm_engine_core-1.2.0}/plm_engine_core/mcp/manifest.py +170 -170
  69. {plm_engine_core-1.0.4 → plm_engine_core-1.2.0}/plm_engine_core/mcp/openapi.py +605 -605
  70. {plm_engine_core-1.0.4 → plm_engine_core-1.2.0}/plm_engine_core/mcp/server.py +219 -219
  71. {plm_engine_core-1.0.4 → plm_engine_core-1.2.0}/plm_engine_core/mcp/tools.py +544 -544
  72. {plm_engine_core-1.0.4 → plm_engine_core-1.2.0}/plm_engine_core/runtime/__init__.py +23 -23
  73. {plm_engine_core-1.0.4 → plm_engine_core-1.2.0}/plm_engine_core/runtime/agent_telemetry_service.py +407 -407
  74. {plm_engine_core-1.0.4 → plm_engine_core-1.2.0}/plm_engine_core/runtime/database.py +447 -447
  75. {plm_engine_core-1.0.4 → plm_engine_core-1.2.0}/plm_engine_core/runtime/database_service.py +538 -538
  76. {plm_engine_core-1.0.4 → plm_engine_core-1.2.0}/plm_engine_core/runtime/default_bindings.py +302 -290
  77. {plm_engine_core-1.0.4 → plm_engine_core-1.2.0}/plm_engine_core/runtime/invocation_context.py +249 -249
  78. {plm_engine_core-1.0.4 → plm_engine_core-1.2.0}/plm_engine_core/runtime/invocation_lifecycle.py +145 -145
  79. {plm_engine_core-1.0.4 → plm_engine_core-1.2.0}/plm_engine_core/runtime/invocation_telemetry.py +155 -155
  80. {plm_engine_core-1.0.4 → plm_engine_core-1.2.0}/plm_engine_core/runtime/llm_env.py +25 -25
  81. {plm_engine_core-1.0.4 → plm_engine_core-1.2.0}/plm_engine_core/runtime/llm_service.py +682 -682
  82. {plm_engine_core-1.0.4 → plm_engine_core-1.2.0}/plm_engine_core/runtime/plan_analysis_service.py +681 -643
  83. {plm_engine_core-1.0.4 → plm_engine_core-1.2.0}/plm_engine_core/runtime/pricing_service.py +147 -147
  84. {plm_engine_core-1.0.4 → plm_engine_core-1.2.0}/plm_engine_core/runtime/retry_orchestrator.py +212 -212
  85. {plm_engine_core-1.0.4 → plm_engine_core-1.2.0}/plm_engine_core/runtime/retry_policy.py +55 -55
  86. {plm_engine_core-1.0.4 → plm_engine_core-1.2.0}/plm_engine_core/runtime/run_task_tracker.py +98 -98
  87. {plm_engine_core-1.0.4 → plm_engine_core-1.2.0}/plm_engine_core/runtime/scoped_state.py +126 -126
  88. {plm_engine_core-1.0.4 → plm_engine_core-1.2.0}/plm_engine_core/runtime/token_estimator.py +50 -50
  89. {plm_engine_core-1.0.4 → plm_engine_core-1.2.0}/plm_engine_core/runtime/workspace_port.py +485 -485
  90. {plm_engine_core-1.0.4 → plm_engine_core-1.2.0}/plm_engine_core/studio/__init__.py +11 -11
  91. {plm_engine_core-1.0.4 → plm_engine_core-1.2.0}/plm_engine_core/studio/readers/__init__.py +25 -25
  92. {plm_engine_core-1.0.4 → plm_engine_core-1.2.0}/plm_engine_core/studio/readers/mcrc_v1.py +260 -221
  93. {plm_engine_core-1.0.4 → plm_engine_core-1.2.0}/plm_engine_core.egg-info/PKG-INFO +197 -191
  94. {plm_engine_core-1.0.4 → plm_engine_core-1.2.0}/plm_engine_core.egg-info/SOURCES.txt +40 -0
  95. {plm_engine_core-1.0.4 → plm_engine_core-1.2.0}/plm_engine_core.egg-info/requires.txt +12 -2
  96. {plm_engine_core-1.0.4 → plm_engine_core-1.2.0}/pyproject.toml +73 -15
  97. {plm_engine_core-1.0.4 → plm_engine_core-1.2.0}/setup.cfg +4 -4
  98. plm_engine_core-1.2.0/tests/test_agent_run_contract.py +185 -0
  99. plm_engine_core-1.2.0/tests/test_agent_run_feature_flag.py +67 -0
  100. plm_engine_core-1.2.0/tests/test_agent_run_hitl_contract.py +215 -0
  101. plm_engine_core-1.2.0/tests/test_agent_snapshot.py +174 -0
  102. plm_engine_core-1.2.0/tests/test_agent_turn_execution.py +249 -0
  103. {plm_engine_core-1.0.4 → plm_engine_core-1.2.0}/tests/test_authorization_policy.py +352 -352
  104. {plm_engine_core-1.0.4 → plm_engine_core-1.2.0}/tests/test_autonomy_gating_policy.py +491 -491
  105. {plm_engine_core-1.0.4 → plm_engine_core-1.2.0}/tests/test_capability_registry.py +462 -462
  106. {plm_engine_core-1.0.4 → plm_engine_core-1.2.0}/tests/test_cli_auth.py +248 -248
  107. {plm_engine_core-1.0.4 → plm_engine_core-1.2.0}/tests/test_connector_dispatcher.py +374 -374
  108. plm_engine_core-1.2.0/tests/test_contract_bundle.py +98 -0
  109. {plm_engine_core-1.0.4 → plm_engine_core-1.2.0}/tests/test_core_host_build_app.py +118 -118
  110. {plm_engine_core-1.0.4 → plm_engine_core-1.2.0}/tests/test_core_host_wave9_parity_smoke.py +260 -260
  111. {plm_engine_core-1.0.4 → plm_engine_core-1.2.0}/tests/test_cost_budget_policy.py +386 -386
  112. {plm_engine_core-1.0.4 → plm_engine_core-1.2.0}/tests/test_error_code_mirror.py +135 -135
  113. plm_engine_core-1.2.0/tests/test_error_taxonomy.py +108 -0
  114. plm_engine_core-1.2.0/tests/test_evidence_pack.py +230 -0
  115. plm_engine_core-1.2.0/tests/test_evidence_pack_cli.py +116 -0
  116. plm_engine_core-1.2.0/tests/test_execution_error_normalization.py +191 -0
  117. plm_engine_core-1.2.0/tests/test_g8_conformance.py +242 -0
  118. plm_engine_core-1.2.0/tests/test_gate_verdict.py +178 -0
  119. plm_engine_core-1.2.0/tests/test_governance_chain.py +127 -0
  120. plm_engine_core-1.2.0/tests/test_health_readiness.py +130 -0
  121. {plm_engine_core-1.0.4 → plm_engine_core-1.2.0}/tests/test_hitl_gate.py +517 -517
  122. plm_engine_core-1.2.0/tests/test_hitl_resume.py +132 -0
  123. {plm_engine_core-1.0.4 → plm_engine_core-1.2.0}/tests/test_identity_middleware.py +435 -435
  124. {plm_engine_core-1.0.4 → plm_engine_core-1.2.0}/tests/test_identity_provider.py +286 -286
  125. {plm_engine_core-1.0.4 → plm_engine_core-1.2.0}/tests/test_import_linter.py +216 -216
  126. {plm_engine_core-1.0.4 → plm_engine_core-1.2.0}/tests/test_imports.py +137 -130
  127. {plm_engine_core-1.0.4 → plm_engine_core-1.2.0}/tests/test_knowledge_curation_index.py +75 -73
  128. {plm_engine_core-1.0.4 → plm_engine_core-1.2.0}/tests/test_knowledge_envelope.py +278 -278
  129. {plm_engine_core-1.0.4 → plm_engine_core-1.2.0}/tests/test_knowledge_runtime_adapter.py +198 -198
  130. {plm_engine_core-1.0.4 → plm_engine_core-1.2.0}/tests/test_mcp_asgi.py +181 -181
  131. {plm_engine_core-1.0.4 → plm_engine_core-1.2.0}/tests/test_mcp_server.py +400 -400
  132. plm_engine_core-1.2.0/tests/test_mcrc_trace.py +190 -0
  133. {plm_engine_core-1.0.4 → plm_engine_core-1.2.0}/tests/test_mcrc_v1_reader.py +81 -74
  134. plm_engine_core-1.2.0/tests/test_model_dispatch.py +55 -0
  135. {plm_engine_core-1.0.4 → plm_engine_core-1.2.0}/tests/test_openapi.py +238 -238
  136. plm_engine_core-1.2.0/tests/test_pf012_measure.py +140 -0
  137. plm_engine_core-1.2.0/tests/test_plm_skill_kernel_optional.py +338 -0
  138. {plm_engine_core-1.0.4 → plm_engine_core-1.2.0}/tests/test_policy_pipeline_order.py +549 -549
  139. plm_engine_core-1.2.0/tests/test_promotion_gate.py +104 -0
  140. plm_engine_core-1.2.0/tests/test_proof_driver.py +153 -0
  141. {plm_engine_core-1.0.4 → plm_engine_core-1.2.0}/tests/test_rate_limit_policy.py +430 -430
  142. {plm_engine_core-1.0.4 → plm_engine_core-1.2.0}/tests/test_retry_policy.py +236 -236
  143. plm_engine_core-1.2.0/tests/test_run_lifecycle.py +134 -0
  144. {plm_engine_core-1.0.4 → plm_engine_core-1.2.0}/tests/test_run_task_tracker.py +359 -359
  145. plm_engine_core-1.2.0/tests/test_skill_dispatch_turn.py +197 -0
  146. {plm_engine_core-1.0.4 → plm_engine_core-1.2.0}/tests/test_skill_selector.py +319 -319
  147. plm_engine_core-1.2.0/tests/test_sse_backpressure.py +123 -0
  148. plm_engine_core-1.2.0/tests/test_sse_event_stream.py +127 -0
  149. plm_engine_core-1.2.0/tests/test_sse_reconnect.py +159 -0
  150. {plm_engine_core-1.0.4 → plm_engine_core-1.2.0}/tests/test_system_identity.py +111 -111
  151. {plm_engine_core-1.0.4 → plm_engine_core-1.2.0}/plm_engine_core.egg-info/dependency_links.txt +0 -0
  152. {plm_engine_core-1.0.4 → plm_engine_core-1.2.0}/plm_engine_core.egg-info/entry_points.txt +0 -0
  153. {plm_engine_core-1.0.4 → plm_engine_core-1.2.0}/plm_engine_core.egg-info/top_level.txt +0 -0
@@ -1,191 +1,197 @@
1
- Metadata-Version: 2.4
2
- Name: plm-engine-core
3
- Version: 1.0.4
4
- Summary: TracePulse PLM Engine Core — control_plane (governance, autonomy, HITL, run lifecycle, trace propagation) + agent_runtime (selector, dispatcher, retry, escalation). US-CR.1 scaffold; behaviour lands in US-CR.0+. Internal one-way import contract: control_plane MUST NOT import from agent_runtime (mechanical enforcement in US-CR.2).
5
- Author: TracePulse
6
- License: Proprietary
7
- Requires-Python: >=3.12
8
- Description-Content-Type: text/markdown
9
- Requires-Dist: plm-shared
10
- Requires-Dist: PyJWT<3,>=2.8
11
- Requires-Dist: plm-knowledge
12
- Requires-Dist: fastapi>=0.110
13
- Requires-Dist: uvicorn>=0.27
14
- Requires-Dist: pydantic-settings>=2.0
15
- Requires-Dist: litellm>=1.0.0
16
- Requires-Dist: httpx>=0.27.0
17
- Requires-Dist: SQLAlchemy>=2.0
18
- Requires-Dist: sqlmodel>=0.0.16
19
- Requires-Dist: PyYAML>=6.0
20
- Requires-Dist: pydantic>=2.5.0
21
- Requires-Dist: starlette<1.0,>=0.27
22
- Requires-Dist: plm-connector-sdk
23
- Provides-Extra: test
24
- Requires-Dist: pytest; extra == "test"
25
- Requires-Dist: pytest-asyncio; extra == "test"
26
- Requires-Dist: fastapi; extra == "test"
27
- Requires-Dist: httpx; extra == "test"
28
- Requires-Dist: import-linter<3,>=2.0; extra == "test"
29
-
30
- # plm-engine-core
31
-
32
- TracePulse PLM Engine Core package. Lives next to `plm-shared` in the
33
- monorepo; shipped editable for Wave 1 (`pip install -e ../plm-engine-core`),
34
- internal PyPI publication deferred to Wave 5.
35
-
36
- US-CR.1 ships this package as **empty scaffolding**. Every other
37
- US-CR.* story in FTR-607 lands its implementation inside the two
38
- sub-packages declared here, on top of contracts published by
39
- `plm-shared` (US-W1.0).
40
-
41
- ## Internal layout
42
-
43
- | Sub-package | Owns | Stories landing here |
44
- |------------------|----------------------------------------------------------------|-----------------------------------------------|
45
- | `control_plane/` | governance, autonomy, HITL, run lifecycle, trace propagation | CR.0, CR.3, CR.4, CR.5, CR.6, CR.10, CR.13 |
46
- | `agent_runtime/` | selector, dispatcher, retry, escalation | CR.10, CR.11 |
47
-
48
- The split implements target architecture invariant **#5** — *execution
49
- separated from expertise* and decision **D-LOCKED-13**. The physical
50
- repo split is deferred to V1.1; Wave 1 delivers the **logical**
51
- boundary.
52
-
53
- ## One-way import contract
54
-
55
- ```
56
- control_plane ─────► plm_shared.* (frozen contracts)
57
- agent_runtime ─────► plm_shared.* (frozen contracts)
58
- agent_runtime ─────► control_plane (asks for verdicts)
59
- control_plane ──╳──► agent_runtime (FORBIDDEN)
60
- plm_engine_core ─╳──► plm_accelerators (FORBIDDEN)
61
- ```
62
-
63
- `control_plane` decides *what is allowed*; `agent_runtime` asks
64
- *how do I run this*. Reversing the dependency (control_plane reading
65
- runtime state) couples policy to execution and breaks the V1.1 repo
66
- split. **plm-engine-core MUST NOT import from the Workbench /
67
- Accelerators** package; reversing this absorption would dissolve
68
- the platform / product-line boundary (anti-pattern #8).
69
-
70
- **Mechanical enforcement (US-CR.2 / Conv F sub-story 3):** two
71
- `import-linter` contracts in `pyproject.toml` fail CI on any
72
- violation:
73
-
74
- | Contract | Source | Forbidden |
75
- |-----------------------------------------------------------|------------------------------|---------------------------------|
76
- | `control_plane-must-not-depend-on-agent_runtime` | `plm_engine_core.control_plane` | `plm_engine_core.agent_runtime` |
77
- | `plm_engine_core-must-not-depend-on-workbench` | `plm_engine_core` | `plm_accelerators` |
78
-
79
- `if TYPE_CHECKING:` imports across the boundary are **blocked by
80
- default** (CR.2 AC-6) — TYPE_CHECKING leakage is the most common
81
- way the boundary erodes silently. `tests/` lives outside the
82
- package and is naturally excluded.
83
-
84
- The CR.1-era by-convention guard in `tests/test_imports.py` STAYS
85
- alongside the mechanical contract. Both fire if either rule trips
86
- belt-and-braces protection if the linter contract has to be
87
- relaxed for a transient reason.
88
-
89
- ### Negative-fixture toggling test
90
-
91
- A permanent sandbox lives at
92
- `plm_engine_core/control_plane/_lint_fixtures/violation_demo.py`.
93
- The `tests/test_import_linter.py::test_negative_fixture_trips_*`
94
- tests (gated by `RUN_LINTER_NEGATIVE=1`) materialise a temporary
95
- sibling file with an offending import, run `lint-imports`, assert
96
- the contract trips with the right name + file:line, then delete
97
- the temp file and verify the clean state passes again. Run with:
98
-
99
- ```bash
100
- RUN_LINTER_NEGATIVE=1 pytest tests/test_import_linter.py -v
101
- ```
102
-
103
- ### Exemption process
104
-
105
- Genuine exceptions go through an ADR signed off by the
106
- architecture team. ADRs live under
107
- [`02_App/plm-engine-core/docs/adr/`](docs/adr/). Each ADR records
108
- the contract relaxed, the scope of the relaxation
109
- (typically a specific `ignore_imports` entry on one contract),
110
- the rationale, and the cross-link to D-LOCKED-13 + invariant #5.
111
- The contract / `ignore_imports` edit MUST cite the ADR file path
112
- in a comment so a future reader finds the authority for the
113
- exemption.
114
-
115
- ### Known limitations
116
-
117
- - **Transitive imports via `plm-shared` are not caught** (CR.2 §9 +
118
- Edge cases). A control_plane file importing a plm-shared helper
119
- that itself transitively imports agent_runtime is invisible to
120
- the contract. Intentional — limits blast radius of a single
121
- PR's contract scope.
122
- - **Dynamic imports (`importlib`, string-based) are not caught**.
123
- Static analysis only.
124
- - **The contracts are scoped to plm-engine-core**. Cross-product-
125
- line contracts (e.g. `agent_runtime connectors`,
126
- `agent_runtime workbench`) land with Epic 6 / Epic 8.
127
-
128
- ## `with_system_identity` allowlist (CR.2 Decision #24)
129
-
130
- `plm_engine_core.control_plane.identity.with_system_identity` is a
131
- context manager that binds an `actor_kind="system"` identity for
132
- in-process callers without an inbound JWT (cron, BackgroundTask,
133
- GC). It bypasses JWT validation by design and MUST NOT be invoked
134
- from arbitrary call sites.
135
-
136
- The path-based BL6 guardrail in
137
- [`02_App/backend/scripts/architecture_guardrails.py`](../backend/scripts/architecture_guardrails.py)
138
- restricts the importer set. Initial allowlist:
139
-
140
- - `plm_engine_core/control_plane/identity/system_identity.py` defining module.
141
- - `plm_engine_core/control_plane/identity/__init__.py` — re-export site.
142
- - `plm_engine_core/cli/` — `plm-cli` future subcommands may bind a
143
- system identity for offline operations.
144
- - `tests/` fixtures may import freely.
145
-
146
- Adding a new module to the allowlist requires an ADR.
147
-
148
- ## Install (developer)
149
-
150
- ```bash
151
- cd 02_App/backend
152
- pip install -e ../plm-engine-core
153
- ```
154
-
155
- The editable install puts `plm_engine_core.*` on the sys.path of the
156
- backend venv. Like `plm-shared`, **`pip install` MUST run from
157
- `02_App/backend/`** because pip resolves `-e ../plm-engine-core`
158
- relative to the invocation CWD.
159
-
160
- ## Tests
161
-
162
- ```bash
163
- cd 02_App/plm-engine-core
164
- python -m pytest tests/ -v
165
- ```
166
-
167
- The smoke test verifies:
168
- - Both sub-packages import cleanly.
169
- - `__all__` placeholders match the documented public surface.
170
- - No `control_plane` module imports from `agent_runtime` (one-way
171
- contract guard, AC-10).
172
- - No business logic has snuck in beyond `__init__.py` files (AC-9
173
- scope-creep guard).
174
-
175
- ## CI
176
-
177
- `.github/workflows/test.yml` runs a `plm-engine-core-tests` job
178
- mirroring `plm-shared-tests` editable-install + pytest on every
179
- push to `main` / `FTR575-Codebase-Split` and on every PR touching
180
- `02_App/**`.
181
-
182
- ## Status
183
-
184
- - **US-CR.1**: scaffold (Conv E close `822c415`). Ships placeholders only.
185
- - **US-CR.0** (Wave 1 Conv E + Conv F): `IdentityMiddleware`,
186
- `Hs256JwtIdentityProvider`, `with_system_identity`, `audit_log`
187
- migration 0013, and `plm-cli auth issue-token` all land. 16/16 ACs
188
- covered; story closed Conv F (3/3 PRs).
189
- - **US-CR.2** (Wave 1 Conv F): two import-linter Forbidden contracts +
190
- permanent negative-fixture toggling test + BL6 path-based guardrail
191
- for `with_system_identity` + ADR exemption process.
1
+ Metadata-Version: 2.4
2
+ Name: plm-engine-core
3
+ Version: 1.2.0
4
+ Summary: TracePulse PLM Engine Core — control_plane (governance, autonomy, HITL, run lifecycle, trace propagation) + agent_runtime (selector, dispatcher, retry, escalation). US-CR.1 scaffold; behaviour lands in US-CR.0+. Internal one-way import contract: control_plane MUST NOT import from agent_runtime (mechanical enforcement in US-CR.2).
5
+ Author: TracePulse
6
+ License: Proprietary
7
+ Requires-Python: >=3.12
8
+ Description-Content-Type: text/markdown
9
+ Requires-Dist: plm-shared[db]<2.0,>=1.0
10
+ Requires-Dist: PyJWT<3,>=2.8
11
+ Requires-Dist: fastapi>=0.110
12
+ Requires-Dist: uvicorn>=0.27
13
+ Requires-Dist: pydantic-settings>=2.0
14
+ Requires-Dist: litellm>=1.0.0
15
+ Requires-Dist: httpx>=0.27.0
16
+ Requires-Dist: SQLAlchemy>=2.0
17
+ Requires-Dist: sqlmodel>=0.0.16
18
+ Requires-Dist: PyYAML>=6.0
19
+ Requires-Dist: pydantic>=2.5.0
20
+ Requires-Dist: starlette<1.0,>=0.27
21
+ Provides-Extra: test
22
+ Requires-Dist: pytest; extra == "test"
23
+ Requires-Dist: pytest-asyncio; extra == "test"
24
+ Requires-Dist: fastapi; extra == "test"
25
+ Requires-Dist: httpx; extra == "test"
26
+ Requires-Dist: import-linter<3,>=2.0; extra == "test"
27
+ Provides-Extra: docs
28
+ Requires-Dist: pdoc>=14.0; extra == "docs"
29
+ Provides-Extra: skills
30
+ Requires-Dist: plm-skill-kernel; extra == "skills"
31
+ Provides-Extra: knowledge
32
+ Requires-Dist: plm-knowledge; extra == "knowledge"
33
+ Provides-Extra: connectors
34
+ Requires-Dist: plm-connector-sdk; extra == "connectors"
35
+
36
+ # plm-engine-core
37
+
38
+ TracePulse PLM Engine Core package. Lives next to `plm-shared` in the
39
+ monorepo; shipped editable for Wave 1 (`pip install -e ../plm-engine-core`),
40
+ internal PyPI publication deferred to Wave 5.
41
+
42
+ US-CR.1 ships this package as **empty scaffolding**. Every other
43
+ US-CR.* story in FTR-607 lands its implementation inside the two
44
+ sub-packages declared here, on top of contracts published by
45
+ `plm-shared` (US-W1.0).
46
+
47
+ ## Internal layout
48
+
49
+ | Sub-package | Owns | Stories landing here |
50
+ |------------------|----------------------------------------------------------------|-----------------------------------------------|
51
+ | `control_plane/` | governance, autonomy, HITL, run lifecycle, trace propagation | CR.0, CR.3, CR.4, CR.5, CR.6, CR.10, CR.13 |
52
+ | `agent_runtime/` | selector, dispatcher, retry, escalation | CR.10, CR.11 |
53
+
54
+ The split implements target architecture invariant **#5** — *execution
55
+ separated from expertise* — and decision **D-LOCKED-13**. The physical
56
+ repo split is deferred to V1.1; Wave 1 delivers the **logical**
57
+ boundary.
58
+
59
+ ## One-way import contract
60
+
61
+ ```
62
+ control_plane ─────► plm_shared.* (frozen contracts)
63
+ agent_runtime ─────► plm_shared.* (frozen contracts)
64
+ agent_runtime ─────► control_plane (asks for verdicts)
65
+ control_plane ──╳──► agent_runtime (FORBIDDEN)
66
+ plm_engine_core ─╳──► plm_accelerators (FORBIDDEN)
67
+ ```
68
+
69
+ `control_plane` decides *what is allowed*; `agent_runtime` asks
70
+ *how do I run this*. Reversing the dependency (control_plane reading
71
+ runtime state) couples policy to execution and breaks the V1.1 repo
72
+ split. **plm-engine-core MUST NOT import from the Workbench /
73
+ Accelerators** package; reversing this absorption would dissolve
74
+ the platform / product-line boundary (anti-pattern #8).
75
+
76
+ **Mechanical enforcement (US-CR.2 / Conv F sub-story 3):** two
77
+ `import-linter` contracts in `pyproject.toml` fail CI on any
78
+ violation:
79
+
80
+ | Contract | Source | Forbidden |
81
+ |-----------------------------------------------------------|------------------------------|---------------------------------|
82
+ | `control_plane-must-not-depend-on-agent_runtime` | `plm_engine_core.control_plane` | `plm_engine_core.agent_runtime` |
83
+ | `plm_engine_core-must-not-depend-on-workbench` | `plm_engine_core` | `plm_accelerators` |
84
+
85
+ `if TYPE_CHECKING:` imports across the boundary are **blocked by
86
+ default** (CR.2 AC-6) TYPE_CHECKING leakage is the most common
87
+ way the boundary erodes silently. `tests/` lives outside the
88
+ package and is naturally excluded.
89
+
90
+ The CR.1-era by-convention guard in `tests/test_imports.py` STAYS
91
+ alongside the mechanical contract. Both fire if either rule trips
92
+ — belt-and-braces protection if the linter contract has to be
93
+ relaxed for a transient reason.
94
+
95
+ ### Negative-fixture toggling test
96
+
97
+ A permanent sandbox lives at
98
+ `plm_engine_core/control_plane/_lint_fixtures/violation_demo.py`.
99
+ The `tests/test_import_linter.py::test_negative_fixture_trips_*`
100
+ tests (gated by `RUN_LINTER_NEGATIVE=1`) materialise a temporary
101
+ sibling file with an offending import, run `lint-imports`, assert
102
+ the contract trips with the right name + file:line, then delete
103
+ the temp file and verify the clean state passes again. Run with:
104
+
105
+ ```bash
106
+ RUN_LINTER_NEGATIVE=1 pytest tests/test_import_linter.py -v
107
+ ```
108
+
109
+ ### Exemption process
110
+
111
+ Genuine exceptions go through an ADR signed off by the
112
+ architecture team. ADRs live under
113
+ [`docs/adr/`](../docs/adr/). Each ADR records
114
+ the contract relaxed, the scope of the relaxation
115
+ (typically a specific `ignore_imports` entry on one contract),
116
+ the rationale, and the cross-link to D-LOCKED-13 + invariant #5.
117
+ The contract / `ignore_imports` edit MUST cite the ADR file path
118
+ in a comment so a future reader finds the authority for the
119
+ exemption.
120
+
121
+ ### Known limitations
122
+
123
+ - **Transitive imports via `plm-shared` are not caught** (CR.2 §9 +
124
+ Edge cases). A control_plane file importing a plm-shared helper
125
+ that itself transitively imports agent_runtime is invisible to
126
+ the contract. Intentional limits blast radius of a single
127
+ PR's contract scope.
128
+ - **Dynamic imports (`importlib`, string-based) are not caught**.
129
+ Static analysis only.
130
+ - **The contracts are scoped to plm-engine-core**. Cross-product-
131
+ line contracts (e.g. `agent_runtime connectors`,
132
+ `agent_runtime workbench`) land with Epic 6 / Epic 8.
133
+
134
+ ## `with_system_identity` allowlist (CR.2 Decision #24)
135
+
136
+ `plm_engine_core.control_plane.identity.with_system_identity` is a
137
+ context manager that binds an `actor_kind="system"` identity for
138
+ in-process callers without an inbound JWT (cron, BackgroundTask,
139
+ GC). It bypasses JWT validation by design and MUST NOT be invoked
140
+ from arbitrary call sites.
141
+
142
+ The path-based BL6 guardrail in
143
+ [`02_App/backend/scripts/architecture_guardrails.py`](../backend/scripts/architecture_guardrails.py)
144
+ restricts the importer set. Initial allowlist:
145
+
146
+ - `plm_engine_core/control_plane/identity/system_identity.py` defining module.
147
+ - `plm_engine_core/control_plane/identity/__init__.py` — re-export site.
148
+ - `plm_engine_core/cli/` — `plm-cli` future subcommands may bind a
149
+ system identity for offline operations.
150
+ - `tests/` — fixtures may import freely.
151
+
152
+ Adding a new module to the allowlist requires an ADR.
153
+
154
+ ## Install (developer)
155
+
156
+ ```bash
157
+ cd 02_App/backend
158
+ pip install -e ../plm-engine-core
159
+ ```
160
+
161
+ The editable install puts `plm_engine_core.*` on the sys.path of the
162
+ backend venv. Like `plm-shared`, **`pip install` MUST run from
163
+ `02_App/backend/`** because pip resolves `-e ../plm-engine-core`
164
+ relative to the invocation CWD.
165
+
166
+ ## Tests
167
+
168
+ ```bash
169
+ cd 02_App/plm-engine-core
170
+ python -m pytest tests/ -v
171
+ ```
172
+
173
+ The smoke test verifies:
174
+ - Both sub-packages import cleanly.
175
+ - `__all__` placeholders match the documented public surface.
176
+ - No `control_plane` module imports from `agent_runtime` (one-way
177
+ contract guard, AC-10).
178
+ - No business logic has snuck in beyond `__init__.py` files (AC-9
179
+ scope-creep guard).
180
+
181
+ ## CI
182
+
183
+ `.github/workflows/test.yml` runs a `plm-engine-core-tests` job
184
+ mirroring `plm-shared-tests` editable-install + pytest on every
185
+ push to `main` / `FTR575-Codebase-Split` and on every PR touching
186
+ `02_App/**`.
187
+
188
+ ## Status
189
+
190
+ - **US-CR.1**: scaffold (Conv E close `822c415`). Ships placeholders only.
191
+ - **US-CR.0** (Wave 1 Conv E + Conv F): `IdentityMiddleware`,
192
+ `Hs256JwtIdentityProvider`, `with_system_identity`, `audit_log`
193
+ migration 0013, and `plm-cli auth issue-token` all land. 16/16 ACs
194
+ covered; story closed Conv F (3/3 PRs).
195
+ - **US-CR.2** (Wave 1 Conv F): two import-linter Forbidden contracts +
196
+ permanent negative-fixture toggling test + BL6 path-based guardrail
197
+ for `with_system_identity` + ADR exemption process.