plm-engine-core 0.1.0a0__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 (83) hide show
  1. plm_engine_core-0.1.0a0/PKG-INFO +179 -0
  2. plm_engine_core-0.1.0a0/README.md +162 -0
  3. plm_engine_core-0.1.0a0/plm_engine_core/__init__.py +24 -0
  4. plm_engine_core-0.1.0a0/plm_engine_core/agent_runtime/__init__.py +31 -0
  5. plm_engine_core-0.1.0a0/plm_engine_core/agent_runtime/dispatcher.py +343 -0
  6. plm_engine_core-0.1.0a0/plm_engine_core/agent_runtime/selector.py +154 -0
  7. plm_engine_core-0.1.0a0/plm_engine_core/cli/__init__.py +64 -0
  8. plm_engine_core-0.1.0a0/plm_engine_core/cli/__main__.py +15 -0
  9. plm_engine_core-0.1.0a0/plm_engine_core/cli/auth.py +125 -0
  10. plm_engine_core-0.1.0a0/plm_engine_core/control_plane/__init__.py +52 -0
  11. plm_engine_core-0.1.0a0/plm_engine_core/control_plane/_lint_fixtures/__init__.py +16 -0
  12. plm_engine_core-0.1.0a0/plm_engine_core/control_plane/_lint_fixtures/violation_demo.py +28 -0
  13. plm_engine_core-0.1.0a0/plm_engine_core/control_plane/capability_registry/__init__.py +45 -0
  14. plm_engine_core-0.1.0a0/plm_engine_core/control_plane/capability_registry/errors.py +71 -0
  15. plm_engine_core-0.1.0a0/plm_engine_core/control_plane/capability_registry/registry.py +403 -0
  16. plm_engine_core-0.1.0a0/plm_engine_core/control_plane/connectors/__init__.py +53 -0
  17. plm_engine_core-0.1.0a0/plm_engine_core/control_plane/connectors/dispatcher.py +148 -0
  18. plm_engine_core-0.1.0a0/plm_engine_core/control_plane/connectors/runtime.py +214 -0
  19. plm_engine_core-0.1.0a0/plm_engine_core/control_plane/dispatch.py +180 -0
  20. plm_engine_core-0.1.0a0/plm_engine_core/control_plane/hitl/__init__.py +45 -0
  21. plm_engine_core-0.1.0a0/plm_engine_core/control_plane/hitl/errors.py +74 -0
  22. plm_engine_core-0.1.0a0/plm_engine_core/control_plane/hitl/gate.py +555 -0
  23. plm_engine_core-0.1.0a0/plm_engine_core/control_plane/hitl/sql_store.py +380 -0
  24. plm_engine_core-0.1.0a0/plm_engine_core/control_plane/identity/__init__.py +46 -0
  25. plm_engine_core-0.1.0a0/plm_engine_core/control_plane/identity/middleware.py +349 -0
  26. plm_engine_core-0.1.0a0/plm_engine_core/control_plane/identity/provider.py +249 -0
  27. plm_engine_core-0.1.0a0/plm_engine_core/control_plane/identity/system_identity.py +92 -0
  28. plm_engine_core-0.1.0a0/plm_engine_core/control_plane/identity/telemetry.py +146 -0
  29. plm_engine_core-0.1.0a0/plm_engine_core/control_plane/knowledge/__init__.py +79 -0
  30. plm_engine_core-0.1.0a0/plm_engine_core/control_plane/knowledge/curation_index.py +119 -0
  31. plm_engine_core-0.1.0a0/plm_engine_core/control_plane/knowledge/envelope.py +358 -0
  32. plm_engine_core-0.1.0a0/plm_engine_core/control_plane/knowledge/runtime.py +205 -0
  33. plm_engine_core-0.1.0a0/plm_engine_core/control_plane/policies/__init__.py +74 -0
  34. plm_engine_core-0.1.0a0/plm_engine_core/control_plane/policies/authorization.py +192 -0
  35. plm_engine_core-0.1.0a0/plm_engine_core/control_plane/policies/autonomy_gating.py +273 -0
  36. plm_engine_core-0.1.0a0/plm_engine_core/control_plane/policies/base.py +174 -0
  37. plm_engine_core-0.1.0a0/plm_engine_core/control_plane/policies/cost_budget.py +490 -0
  38. plm_engine_core-0.1.0a0/plm_engine_core/control_plane/policies/rate_limit.py +369 -0
  39. plm_engine_core-0.1.0a0/plm_engine_core/control_plane/retry_policy.py +288 -0
  40. plm_engine_core-0.1.0a0/plm_engine_core/control_plane/run_task_tracker.py +262 -0
  41. plm_engine_core-0.1.0a0/plm_engine_core/mcp/__init__.py +63 -0
  42. plm_engine_core-0.1.0a0/plm_engine_core/mcp/asgi.py +195 -0
  43. plm_engine_core-0.1.0a0/plm_engine_core/mcp/errors.py +41 -0
  44. plm_engine_core-0.1.0a0/plm_engine_core/mcp/manifest.py +170 -0
  45. plm_engine_core-0.1.0a0/plm_engine_core/mcp/openapi.py +605 -0
  46. plm_engine_core-0.1.0a0/plm_engine_core/mcp/server.py +219 -0
  47. plm_engine_core-0.1.0a0/plm_engine_core/mcp/tools.py +544 -0
  48. plm_engine_core-0.1.0a0/plm_engine_core/studio/__init__.py +11 -0
  49. plm_engine_core-0.1.0a0/plm_engine_core/studio/readers/__init__.py +25 -0
  50. plm_engine_core-0.1.0a0/plm_engine_core/studio/readers/mcrc_v1.py +221 -0
  51. plm_engine_core-0.1.0a0/plm_engine_core.egg-info/PKG-INFO +179 -0
  52. plm_engine_core-0.1.0a0/plm_engine_core.egg-info/SOURCES.txt +81 -0
  53. plm_engine_core-0.1.0a0/plm_engine_core.egg-info/dependency_links.txt +1 -0
  54. plm_engine_core-0.1.0a0/plm_engine_core.egg-info/entry_points.txt +2 -0
  55. plm_engine_core-0.1.0a0/plm_engine_core.egg-info/requires.txt +9 -0
  56. plm_engine_core-0.1.0a0/plm_engine_core.egg-info/top_level.txt +1 -0
  57. plm_engine_core-0.1.0a0/pyproject.toml +118 -0
  58. plm_engine_core-0.1.0a0/setup.cfg +4 -0
  59. plm_engine_core-0.1.0a0/tests/test_authorization_policy.py +352 -0
  60. plm_engine_core-0.1.0a0/tests/test_autonomy_gating_policy.py +491 -0
  61. plm_engine_core-0.1.0a0/tests/test_capability_registry.py +462 -0
  62. plm_engine_core-0.1.0a0/tests/test_cli_auth.py +248 -0
  63. plm_engine_core-0.1.0a0/tests/test_connector_dispatcher.py +374 -0
  64. plm_engine_core-0.1.0a0/tests/test_cost_budget_policy.py +386 -0
  65. plm_engine_core-0.1.0a0/tests/test_error_code_mirror.py +135 -0
  66. plm_engine_core-0.1.0a0/tests/test_hitl_gate.py +517 -0
  67. plm_engine_core-0.1.0a0/tests/test_identity_middleware.py +435 -0
  68. plm_engine_core-0.1.0a0/tests/test_identity_provider.py +286 -0
  69. plm_engine_core-0.1.0a0/tests/test_import_linter.py +216 -0
  70. plm_engine_core-0.1.0a0/tests/test_imports.py +130 -0
  71. plm_engine_core-0.1.0a0/tests/test_knowledge_curation_index.py +73 -0
  72. plm_engine_core-0.1.0a0/tests/test_knowledge_envelope.py +278 -0
  73. plm_engine_core-0.1.0a0/tests/test_knowledge_runtime_adapter.py +198 -0
  74. plm_engine_core-0.1.0a0/tests/test_mcp_asgi.py +181 -0
  75. plm_engine_core-0.1.0a0/tests/test_mcp_server.py +400 -0
  76. plm_engine_core-0.1.0a0/tests/test_mcrc_v1_reader.py +74 -0
  77. plm_engine_core-0.1.0a0/tests/test_openapi.py +238 -0
  78. plm_engine_core-0.1.0a0/tests/test_policy_pipeline_order.py +549 -0
  79. plm_engine_core-0.1.0a0/tests/test_rate_limit_policy.py +430 -0
  80. plm_engine_core-0.1.0a0/tests/test_retry_policy.py +236 -0
  81. plm_engine_core-0.1.0a0/tests/test_run_task_tracker.py +359 -0
  82. plm_engine_core-0.1.0a0/tests/test_skill_selector.py +319 -0
  83. plm_engine_core-0.1.0a0/tests/test_system_identity.py +111 -0
@@ -0,0 +1,179 @@
1
+ Metadata-Version: 2.4
2
+ Name: plm-engine-core
3
+ Version: 0.1.0a0
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
+ Provides-Extra: test
12
+ Requires-Dist: pytest; extra == "test"
13
+ Requires-Dist: pytest-asyncio; extra == "test"
14
+ Requires-Dist: fastapi; extra == "test"
15
+ Requires-Dist: httpx; extra == "test"
16
+ Requires-Dist: import-linter<3,>=2.0; extra == "test"
17
+
18
+ # plm-engine-core
19
+
20
+ TracePulse PLM Engine Core package. Lives next to `plm-shared` in the
21
+ monorepo; shipped editable for Wave 1 (`pip install -e ../plm-engine-core`),
22
+ internal PyPI publication deferred to Wave 5.
23
+
24
+ US-CR.1 ships this package as **empty scaffolding**. Every other
25
+ US-CR.* story in FTR-607 lands its implementation inside the two
26
+ sub-packages declared here, on top of contracts published by
27
+ `plm-shared` (US-W1.0).
28
+
29
+ ## Internal layout
30
+
31
+ | Sub-package | Owns | Stories landing here |
32
+ |------------------|----------------------------------------------------------------|-----------------------------------------------|
33
+ | `control_plane/` | governance, autonomy, HITL, run lifecycle, trace propagation | CR.0, CR.3, CR.4, CR.5, CR.6, CR.10, CR.13 |
34
+ | `agent_runtime/` | selector, dispatcher, retry, escalation | CR.10, CR.11 |
35
+
36
+ The split implements target architecture invariant **#5** — *execution
37
+ separated from expertise* — and decision **D-LOCKED-13**. The physical
38
+ repo split is deferred to V1.1; Wave 1 delivers the **logical**
39
+ boundary.
40
+
41
+ ## One-way import contract
42
+
43
+ ```
44
+ control_plane ─────► plm_shared.* (frozen contracts)
45
+ agent_runtime ─────► plm_shared.* (frozen contracts)
46
+ agent_runtime ─────► control_plane (asks for verdicts)
47
+ control_plane ──╳──► agent_runtime (FORBIDDEN)
48
+ plm_engine_core ─╳──► plm_accelerators (FORBIDDEN)
49
+ ```
50
+
51
+ `control_plane` decides *what is allowed*; `agent_runtime` asks
52
+ *how do I run this*. Reversing the dependency (control_plane reading
53
+ runtime state) couples policy to execution and breaks the V1.1 repo
54
+ split. **plm-engine-core MUST NOT import from the Workbench /
55
+ Accelerators** package; reversing this absorption would dissolve
56
+ the platform / product-line boundary (anti-pattern #8).
57
+
58
+ **Mechanical enforcement (US-CR.2 / Conv F sub-story 3):** two
59
+ `import-linter` contracts in `pyproject.toml` fail CI on any
60
+ violation:
61
+
62
+ | Contract | Source | Forbidden |
63
+ |-----------------------------------------------------------|------------------------------|---------------------------------|
64
+ | `control_plane-must-not-depend-on-agent_runtime` | `plm_engine_core.control_plane` | `plm_engine_core.agent_runtime` |
65
+ | `plm_engine_core-must-not-depend-on-workbench` | `plm_engine_core` | `plm_accelerators` |
66
+
67
+ `if TYPE_CHECKING:` imports across the boundary are **blocked by
68
+ default** (CR.2 AC-6) — TYPE_CHECKING leakage is the most common
69
+ way the boundary erodes silently. `tests/` lives outside the
70
+ package and is naturally excluded.
71
+
72
+ The CR.1-era by-convention guard in `tests/test_imports.py` STAYS
73
+ alongside the mechanical contract. Both fire if either rule trips
74
+ — belt-and-braces protection if the linter contract has to be
75
+ relaxed for a transient reason.
76
+
77
+ ### Negative-fixture toggling test
78
+
79
+ A permanent sandbox lives at
80
+ `plm_engine_core/control_plane/_lint_fixtures/violation_demo.py`.
81
+ The `tests/test_import_linter.py::test_negative_fixture_trips_*`
82
+ tests (gated by `RUN_LINTER_NEGATIVE=1`) materialise a temporary
83
+ sibling file with an offending import, run `lint-imports`, assert
84
+ the contract trips with the right name + file:line, then delete
85
+ the temp file and verify the clean state passes again. Run with:
86
+
87
+ ```bash
88
+ RUN_LINTER_NEGATIVE=1 pytest tests/test_import_linter.py -v
89
+ ```
90
+
91
+ ### Exemption process
92
+
93
+ Genuine exceptions go through an ADR signed off by the
94
+ architecture team. ADRs live under
95
+ [`02_App/plm-engine-core/docs/adr/`](docs/adr/). Each ADR records
96
+ the contract relaxed, the scope of the relaxation
97
+ (typically a specific `ignore_imports` entry on one contract),
98
+ the rationale, and the cross-link to D-LOCKED-13 + invariant #5.
99
+ The contract / `ignore_imports` edit MUST cite the ADR file path
100
+ in a comment so a future reader finds the authority for the
101
+ exemption.
102
+
103
+ ### Known limitations
104
+
105
+ - **Transitive imports via `plm-shared` are not caught** (CR.2 §9 +
106
+ Edge cases). A control_plane file importing a plm-shared helper
107
+ that itself transitively imports agent_runtime is invisible to
108
+ the contract. Intentional — limits blast radius of a single
109
+ PR's contract scope.
110
+ - **Dynamic imports (`importlib`, string-based) are not caught**.
111
+ Static analysis only.
112
+ - **The contracts are scoped to plm-engine-core**. Cross-product-
113
+ line contracts (e.g. `agent_runtime → connectors`,
114
+ `agent_runtime → workbench`) land with Epic 6 / Epic 8.
115
+
116
+ ## `with_system_identity` allowlist (CR.2 Decision #24)
117
+
118
+ `plm_engine_core.control_plane.identity.with_system_identity` is a
119
+ context manager that binds an `actor_kind="system"` identity for
120
+ in-process callers without an inbound JWT (cron, BackgroundTask,
121
+ GC). It bypasses JWT validation by design and MUST NOT be invoked
122
+ from arbitrary call sites.
123
+
124
+ The path-based BL6 guardrail in
125
+ [`02_App/backend/scripts/architecture_guardrails.py`](../backend/scripts/architecture_guardrails.py)
126
+ restricts the importer set. Initial allowlist:
127
+
128
+ - `plm_engine_core/control_plane/identity/system_identity.py` — defining module.
129
+ - `plm_engine_core/control_plane/identity/__init__.py` — re-export site.
130
+ - `plm_engine_core/cli/` — `plm-cli` future subcommands may bind a
131
+ system identity for offline operations.
132
+ - `tests/` — fixtures may import freely.
133
+
134
+ Adding a new module to the allowlist requires an ADR.
135
+
136
+ ## Install (developer)
137
+
138
+ ```bash
139
+ cd 02_App/backend
140
+ pip install -e ../plm-engine-core
141
+ ```
142
+
143
+ The editable install puts `plm_engine_core.*` on the sys.path of the
144
+ backend venv. Like `plm-shared`, **`pip install` MUST run from
145
+ `02_App/backend/`** because pip resolves `-e ../plm-engine-core`
146
+ relative to the invocation CWD.
147
+
148
+ ## Tests
149
+
150
+ ```bash
151
+ cd 02_App/plm-engine-core
152
+ python -m pytest tests/ -v
153
+ ```
154
+
155
+ The smoke test verifies:
156
+ - Both sub-packages import cleanly.
157
+ - `__all__` placeholders match the documented public surface.
158
+ - No `control_plane` module imports from `agent_runtime` (one-way
159
+ contract guard, AC-10).
160
+ - No business logic has snuck in beyond `__init__.py` files (AC-9
161
+ scope-creep guard).
162
+
163
+ ## CI
164
+
165
+ `.github/workflows/test.yml` runs a `plm-engine-core-tests` job
166
+ mirroring `plm-shared-tests` — editable-install + pytest on every
167
+ push to `main` / `FTR575-Codebase-Split` and on every PR touching
168
+ `02_App/**`.
169
+
170
+ ## Status
171
+
172
+ - **US-CR.1**: scaffold (Conv E close `822c415`). Ships placeholders only.
173
+ - **US-CR.0** (Wave 1 Conv E + Conv F): `IdentityMiddleware`,
174
+ `Hs256JwtIdentityProvider`, `with_system_identity`, `audit_log`
175
+ migration 0013, and `plm-cli auth issue-token` all land. 16/16 ACs
176
+ covered; story closed Conv F (3/3 PRs).
177
+ - **US-CR.2** (Wave 1 Conv F): two import-linter Forbidden contracts +
178
+ permanent negative-fixture toggling test + BL6 path-based guardrail
179
+ for `with_system_identity` + ADR exemption process.
@@ -0,0 +1,162 @@
1
+ # plm-engine-core
2
+
3
+ TracePulse PLM Engine Core package. Lives next to `plm-shared` in the
4
+ monorepo; shipped editable for Wave 1 (`pip install -e ../plm-engine-core`),
5
+ internal PyPI publication deferred to Wave 5.
6
+
7
+ US-CR.1 ships this package as **empty scaffolding**. Every other
8
+ US-CR.* story in FTR-607 lands its implementation inside the two
9
+ sub-packages declared here, on top of contracts published by
10
+ `plm-shared` (US-W1.0).
11
+
12
+ ## Internal layout
13
+
14
+ | Sub-package | Owns | Stories landing here |
15
+ |------------------|----------------------------------------------------------------|-----------------------------------------------|
16
+ | `control_plane/` | governance, autonomy, HITL, run lifecycle, trace propagation | CR.0, CR.3, CR.4, CR.5, CR.6, CR.10, CR.13 |
17
+ | `agent_runtime/` | selector, dispatcher, retry, escalation | CR.10, CR.11 |
18
+
19
+ The split implements target architecture invariant **#5** — *execution
20
+ separated from expertise* — and decision **D-LOCKED-13**. The physical
21
+ repo split is deferred to V1.1; Wave 1 delivers the **logical**
22
+ boundary.
23
+
24
+ ## One-way import contract
25
+
26
+ ```
27
+ control_plane ─────► plm_shared.* (frozen contracts)
28
+ agent_runtime ─────► plm_shared.* (frozen contracts)
29
+ agent_runtime ─────► control_plane (asks for verdicts)
30
+ control_plane ──╳──► agent_runtime (FORBIDDEN)
31
+ plm_engine_core ─╳──► plm_accelerators (FORBIDDEN)
32
+ ```
33
+
34
+ `control_plane` decides *what is allowed*; `agent_runtime` asks
35
+ *how do I run this*. Reversing the dependency (control_plane reading
36
+ runtime state) couples policy to execution and breaks the V1.1 repo
37
+ split. **plm-engine-core MUST NOT import from the Workbench /
38
+ Accelerators** package; reversing this absorption would dissolve
39
+ the platform / product-line boundary (anti-pattern #8).
40
+
41
+ **Mechanical enforcement (US-CR.2 / Conv F sub-story 3):** two
42
+ `import-linter` contracts in `pyproject.toml` fail CI on any
43
+ violation:
44
+
45
+ | Contract | Source | Forbidden |
46
+ |-----------------------------------------------------------|------------------------------|---------------------------------|
47
+ | `control_plane-must-not-depend-on-agent_runtime` | `plm_engine_core.control_plane` | `plm_engine_core.agent_runtime` |
48
+ | `plm_engine_core-must-not-depend-on-workbench` | `plm_engine_core` | `plm_accelerators` |
49
+
50
+ `if TYPE_CHECKING:` imports across the boundary are **blocked by
51
+ default** (CR.2 AC-6) — TYPE_CHECKING leakage is the most common
52
+ way the boundary erodes silently. `tests/` lives outside the
53
+ package and is naturally excluded.
54
+
55
+ The CR.1-era by-convention guard in `tests/test_imports.py` STAYS
56
+ alongside the mechanical contract. Both fire if either rule trips
57
+ — belt-and-braces protection if the linter contract has to be
58
+ relaxed for a transient reason.
59
+
60
+ ### Negative-fixture toggling test
61
+
62
+ A permanent sandbox lives at
63
+ `plm_engine_core/control_plane/_lint_fixtures/violation_demo.py`.
64
+ The `tests/test_import_linter.py::test_negative_fixture_trips_*`
65
+ tests (gated by `RUN_LINTER_NEGATIVE=1`) materialise a temporary
66
+ sibling file with an offending import, run `lint-imports`, assert
67
+ the contract trips with the right name + file:line, then delete
68
+ the temp file and verify the clean state passes again. Run with:
69
+
70
+ ```bash
71
+ RUN_LINTER_NEGATIVE=1 pytest tests/test_import_linter.py -v
72
+ ```
73
+
74
+ ### Exemption process
75
+
76
+ Genuine exceptions go through an ADR signed off by the
77
+ architecture team. ADRs live under
78
+ [`02_App/plm-engine-core/docs/adr/`](docs/adr/). Each ADR records
79
+ the contract relaxed, the scope of the relaxation
80
+ (typically a specific `ignore_imports` entry on one contract),
81
+ the rationale, and the cross-link to D-LOCKED-13 + invariant #5.
82
+ The contract / `ignore_imports` edit MUST cite the ADR file path
83
+ in a comment so a future reader finds the authority for the
84
+ exemption.
85
+
86
+ ### Known limitations
87
+
88
+ - **Transitive imports via `plm-shared` are not caught** (CR.2 §9 +
89
+ Edge cases). A control_plane file importing a plm-shared helper
90
+ that itself transitively imports agent_runtime is invisible to
91
+ the contract. Intentional — limits blast radius of a single
92
+ PR's contract scope.
93
+ - **Dynamic imports (`importlib`, string-based) are not caught**.
94
+ Static analysis only.
95
+ - **The contracts are scoped to plm-engine-core**. Cross-product-
96
+ line contracts (e.g. `agent_runtime → connectors`,
97
+ `agent_runtime → workbench`) land with Epic 6 / Epic 8.
98
+
99
+ ## `with_system_identity` allowlist (CR.2 Decision #24)
100
+
101
+ `plm_engine_core.control_plane.identity.with_system_identity` is a
102
+ context manager that binds an `actor_kind="system"` identity for
103
+ in-process callers without an inbound JWT (cron, BackgroundTask,
104
+ GC). It bypasses JWT validation by design and MUST NOT be invoked
105
+ from arbitrary call sites.
106
+
107
+ The path-based BL6 guardrail in
108
+ [`02_App/backend/scripts/architecture_guardrails.py`](../backend/scripts/architecture_guardrails.py)
109
+ restricts the importer set. Initial allowlist:
110
+
111
+ - `plm_engine_core/control_plane/identity/system_identity.py` — defining module.
112
+ - `plm_engine_core/control_plane/identity/__init__.py` — re-export site.
113
+ - `plm_engine_core/cli/` — `plm-cli` future subcommands may bind a
114
+ system identity for offline operations.
115
+ - `tests/` — fixtures may import freely.
116
+
117
+ Adding a new module to the allowlist requires an ADR.
118
+
119
+ ## Install (developer)
120
+
121
+ ```bash
122
+ cd 02_App/backend
123
+ pip install -e ../plm-engine-core
124
+ ```
125
+
126
+ The editable install puts `plm_engine_core.*` on the sys.path of the
127
+ backend venv. Like `plm-shared`, **`pip install` MUST run from
128
+ `02_App/backend/`** because pip resolves `-e ../plm-engine-core`
129
+ relative to the invocation CWD.
130
+
131
+ ## Tests
132
+
133
+ ```bash
134
+ cd 02_App/plm-engine-core
135
+ python -m pytest tests/ -v
136
+ ```
137
+
138
+ The smoke test verifies:
139
+ - Both sub-packages import cleanly.
140
+ - `__all__` placeholders match the documented public surface.
141
+ - No `control_plane` module imports from `agent_runtime` (one-way
142
+ contract guard, AC-10).
143
+ - No business logic has snuck in beyond `__init__.py` files (AC-9
144
+ scope-creep guard).
145
+
146
+ ## CI
147
+
148
+ `.github/workflows/test.yml` runs a `plm-engine-core-tests` job
149
+ mirroring `plm-shared-tests` — editable-install + pytest on every
150
+ push to `main` / `FTR575-Codebase-Split` and on every PR touching
151
+ `02_App/**`.
152
+
153
+ ## Status
154
+
155
+ - **US-CR.1**: scaffold (Conv E close `822c415`). Ships placeholders only.
156
+ - **US-CR.0** (Wave 1 Conv E + Conv F): `IdentityMiddleware`,
157
+ `Hs256JwtIdentityProvider`, `with_system_identity`, `audit_log`
158
+ migration 0013, and `plm-cli auth issue-token` all land. 16/16 ACs
159
+ covered; story closed Conv F (3/3 PRs).
160
+ - **US-CR.2** (Wave 1 Conv F): two import-linter Forbidden contracts +
161
+ permanent negative-fixture toggling test + BL6 path-based guardrail
162
+ for `with_system_identity` + ADR exemption process.
@@ -0,0 +1,24 @@
1
+ """plm-engine-core — TracePulse PLM Engine Core package (US-CR.1 scaffold).
2
+
3
+ Internally split into two sub-packages aligned with target architecture
4
+ invariant #5 ("execution separated from expertise") and decision
5
+ D-LOCKED-13:
6
+
7
+ * `control_plane/` — governance, autonomy, HITL, run lifecycle,
8
+ trace propagation. Owns *what is allowed*.
9
+ * `agent_runtime/` — selector, dispatcher, retry, escalation.
10
+ Owns *how skills execute*.
11
+
12
+ One-way import contract: `control_plane` MUST NOT import from
13
+ `agent_runtime`. Mechanical enforcement (import-linter rule) lands
14
+ in US-CR.2; until then the rule is documented in README and observed
15
+ by convention.
16
+
17
+ US-CR.1 ships this scaffold deliberately empty — every other US-CR.*
18
+ story (CR.0 identity middleware, CR.2 boundary lint, CR.3-6 policies,
19
+ CR.7 MCP server, CR.8 OpenAPI, CR.9 federated manifest, CR.10 selector,
20
+ CR.11 retry, CR.12 capability registry, CR.13 HITL) lands its
21
+ implementation inside these clear, enforceable internal boundaries
22
+ from day one.
23
+ """
24
+ __version__ = "0.1.0-alpha"
@@ -0,0 +1,31 @@
1
+ """plm_engine_core.agent_runtime — selector + dispatcher + retry +
2
+ escalation (US-CR.1 scaffold).
3
+
4
+ Owns *how skills execute*: skill selection, Kernel dispatch, retry
5
+ orchestration on transient failures, escalation when retries
6
+ exhaust. Downstream stories land here:
7
+
8
+ * US-CR.10 — skill selector → Kernel dispatch loopback (runtime side).
9
+ * US-CR.11 — externalised RetryPolicy module.
10
+
11
+ `agent_runtime` may import from `plm_shared.*` (frozen contracts) and
12
+ from `plm_engine_core.control_plane` is **forbidden** by the one-way
13
+ import rule. Decisions about what is allowed live in `control_plane`;
14
+ the runtime asks control_plane for verdicts but does not depend on
15
+ its internals.
16
+
17
+ The `__all__` placeholders below name the public surface downstream
18
+ stories will populate. Importing any of them today raises
19
+ `ImportError` because the modules don't exist yet — placeholder
20
+ list is the contract, not a runtime shim.
21
+ """
22
+ __all__ = [
23
+ # US-CR.10 — skill selection from a tenant + capability scope.
24
+ "selector",
25
+ # Kernel dispatch loop (runtime side of US-CR.10).
26
+ "dispatcher",
27
+ # US-CR.11 — externalised retry policy (taxonomy-aware).
28
+ "retry",
29
+ # Escalation when retries exhaust or autonomy gate denies.
30
+ "escalation",
31
+ ]