engineering-process 0.6.0__tar.gz → 0.6.1__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 (188) hide show
  1. {engineering_process-0.6.0/engineering_process.egg-info → engineering_process-0.6.1}/PKG-INFO +9 -1
  2. {engineering_process-0.6.0 → engineering_process-0.6.1}/PRODUCTION_STANDARD.md +6 -0
  3. {engineering_process-0.6.0 → engineering_process-0.6.1}/README.md +8 -0
  4. {engineering_process-0.6.0 → engineering_process-0.6.1}/engineering_process/__init__.py +1 -1
  5. {engineering_process-0.6.0 → engineering_process-0.6.1}/engineering_process/environment.py +34 -5
  6. {engineering_process-0.6.0 → engineering_process-0.6.1/engineering_process.egg-info}/PKG-INFO +9 -1
  7. {engineering_process-0.6.0 → engineering_process-0.6.1}/improvement-catalog.json +2 -2
  8. {engineering_process-0.6.0 → engineering_process-0.6.1}/pyproject.toml +1 -1
  9. engineering_process-0.6.1/release.json +46 -0
  10. {engineering_process-0.6.0 → engineering_process-0.6.1}/tests/test_environment.py +85 -5
  11. {engineering_process-0.6.0 → engineering_process-0.6.1}/tests/test_runner.py +29 -0
  12. engineering_process-0.6.0/release.json +0 -51
  13. {engineering_process-0.6.0 → engineering_process-0.6.1}/LICENSE +0 -0
  14. {engineering_process-0.6.0 → engineering_process-0.6.1}/MANIFEST.in +0 -0
  15. {engineering_process-0.6.0 → engineering_process-0.6.1}/PROCESS_IMPROVEMENT.md +0 -0
  16. {engineering_process-0.6.0 → engineering_process-0.6.1}/VERSIONING.md +0 -0
  17. {engineering_process-0.6.0 → engineering_process-0.6.1}/bundles.json +0 -0
  18. {engineering_process-0.6.0 → engineering_process-0.6.1}/engineering_process/__main__.py +0 -0
  19. {engineering_process-0.6.0 → engineering_process-0.6.1}/engineering_process/_download_worker.py +0 -0
  20. {engineering_process-0.6.0 → engineering_process-0.6.1}/engineering_process/_supervisor_posix.py +0 -0
  21. {engineering_process-0.6.0 → engineering_process-0.6.1}/engineering_process/_supervisor_windows.py +0 -0
  22. {engineering_process-0.6.0 → engineering_process-0.6.1}/engineering_process/_windows_job.py +0 -0
  23. {engineering_process-0.6.0 → engineering_process-0.6.1}/engineering_process/adoption.py +0 -0
  24. {engineering_process-0.6.0 → engineering_process-0.6.1}/engineering_process/artifact_attestation.py +0 -0
  25. {engineering_process-0.6.0 → engineering_process-0.6.1}/engineering_process/bootstrap.py +0 -0
  26. {engineering_process-0.6.0 → engineering_process-0.6.1}/engineering_process/bounded_process.py +0 -0
  27. {engineering_process-0.6.0 → engineering_process-0.6.1}/engineering_process/bundles.py +0 -0
  28. {engineering_process-0.6.0 → engineering_process-0.6.1}/engineering_process/cli.py +0 -0
  29. {engineering_process-0.6.0 → engineering_process-0.6.1}/engineering_process/command_catalog.py +0 -0
  30. {engineering_process-0.6.0 → engineering_process-0.6.1}/engineering_process/contracts.py +0 -0
  31. {engineering_process-0.6.0 → engineering_process-0.6.1}/engineering_process/diagnostics.py +0 -0
  32. {engineering_process-0.6.0 → engineering_process-0.6.1}/engineering_process/distribution.py +0 -0
  33. {engineering_process-0.6.0 → engineering_process-0.6.1}/engineering_process/distribution_verify.py +0 -0
  34. {engineering_process-0.6.0 → engineering_process-0.6.1}/engineering_process/evidence.py +0 -0
  35. {engineering_process-0.6.0 → engineering_process-0.6.1}/engineering_process/evidence_transport.py +0 -0
  36. {engineering_process-0.6.0 → engineering_process-0.6.1}/engineering_process/git.py +0 -0
  37. {engineering_process-0.6.0 → engineering_process-0.6.1}/engineering_process/git_attributes.py +0 -0
  38. {engineering_process-0.6.0 → engineering_process-0.6.1}/engineering_process/helper_launch.py +0 -0
  39. {engineering_process-0.6.0 → engineering_process-0.6.1}/engineering_process/impact.py +0 -0
  40. {engineering_process-0.6.0 → engineering_process-0.6.1}/engineering_process/improvement.py +0 -0
  41. {engineering_process-0.6.0 → engineering_process-0.6.1}/engineering_process/lifecycle.py +0 -0
  42. {engineering_process-0.6.0 → engineering_process-0.6.1}/engineering_process/lifecycle_routes.py +0 -0
  43. {engineering_process-0.6.0 → engineering_process-0.6.1}/engineering_process/managed.py +0 -0
  44. {engineering_process-0.6.0 → engineering_process-0.6.1}/engineering_process/markdown.py +0 -0
  45. {engineering_process-0.6.0 → engineering_process-0.6.1}/engineering_process/process_graph.py +0 -0
  46. {engineering_process-0.6.0 → engineering_process-0.6.1}/engineering_process/publication.py +0 -0
  47. {engineering_process-0.6.0 → engineering_process-0.6.1}/engineering_process/recommendation.py +0 -0
  48. {engineering_process-0.6.0 → engineering_process-0.6.1}/engineering_process/release.py +0 -0
  49. {engineering_process-0.6.0 → engineering_process-0.6.1}/engineering_process/release_candidate.py +0 -0
  50. {engineering_process-0.6.0 → engineering_process-0.6.1}/engineering_process/remote_verification.py +0 -0
  51. {engineering_process-0.6.0 → engineering_process-0.6.1}/engineering_process/requirements-build.txt +0 -0
  52. {engineering_process-0.6.0 → engineering_process-0.6.1}/engineering_process/requirements-dev.txt +0 -0
  53. {engineering_process-0.6.0 → engineering_process-0.6.1}/engineering_process/requirements-release.txt +0 -0
  54. {engineering_process-0.6.0 → engineering_process-0.6.1}/engineering_process/requirements-runtime.txt +0 -0
  55. {engineering_process-0.6.0 → engineering_process-0.6.1}/engineering_process/runner.py +0 -0
  56. {engineering_process-0.6.0 → engineering_process-0.6.1}/engineering_process/runtime.py +0 -0
  57. {engineering_process-0.6.0 → engineering_process-0.6.1}/engineering_process/skills.py +0 -0
  58. {engineering_process-0.6.0 → engineering_process-0.6.1}/engineering_process/supervision.py +0 -0
  59. {engineering_process-0.6.0 → engineering_process-0.6.1}/engineering_process/supplemental.py +0 -0
  60. {engineering_process-0.6.0 → engineering_process-0.6.1}/engineering_process/syncing.py +0 -0
  61. {engineering_process-0.6.0 → engineering_process-0.6.1}/engineering_process/tooling.py +0 -0
  62. {engineering_process-0.6.0 → engineering_process-0.6.1}/engineering_process.egg-info/SOURCES.txt +0 -0
  63. {engineering_process-0.6.0 → engineering_process-0.6.1}/engineering_process.egg-info/dependency_links.txt +0 -0
  64. {engineering_process-0.6.0 → engineering_process-0.6.1}/engineering_process.egg-info/entry_points.txt +0 -0
  65. {engineering_process-0.6.0 → engineering_process-0.6.1}/engineering_process.egg-info/requires.txt +0 -0
  66. {engineering_process-0.6.0 → engineering_process-0.6.1}/engineering_process.egg-info/top_level.txt +0 -0
  67. {engineering_process-0.6.0 → engineering_process-0.6.1}/examples/adoption-migration.json +0 -0
  68. {engineering_process-0.6.0 → engineering_process-0.6.1}/examples/automation-policy.json +0 -0
  69. {engineering_process-0.6.0 → engineering_process-0.6.1}/examples/automation-proposal-policy.json +0 -0
  70. {engineering_process-0.6.0 → engineering_process-0.6.1}/examples/automation-proposal.json +0 -0
  71. {engineering_process-0.6.0 → engineering_process-0.6.1}/examples/change.json +0 -0
  72. {engineering_process-0.6.0 → engineering_process-0.6.1}/examples/improvement-catalog.json +0 -0
  73. {engineering_process-0.6.0 → engineering_process-0.6.1}/examples/improvement-disposition.json +0 -0
  74. {engineering_process-0.6.0 → engineering_process-0.6.1}/examples/improvement-reproduction.json +0 -0
  75. {engineering_process-0.6.0 → engineering_process-0.6.1}/examples/improvement-resolution.json +0 -0
  76. {engineering_process-0.6.0 → engineering_process-0.6.1}/examples/improvement-signal.json +0 -0
  77. {engineering_process-0.6.0 → engineering_process-0.6.1}/examples/plan.json +0 -0
  78. {engineering_process-0.6.0 → engineering_process-0.6.1}/examples/project.json +0 -0
  79. {engineering_process-0.6.0 → engineering_process-0.6.1}/examples/recommendation-resolution.json +0 -0
  80. {engineering_process-0.6.0 → engineering_process-0.6.1}/examples/recommendation-review-assignment.json +0 -0
  81. {engineering_process-0.6.0 → engineering_process-0.6.1}/examples/recommendation-review.json +0 -0
  82. {engineering_process-0.6.0 → engineering_process-0.6.1}/examples/recommendation.json +0 -0
  83. {engineering_process-0.6.0 → engineering_process-0.6.1}/examples/release-change.json +0 -0
  84. {engineering_process-0.6.0 → engineering_process-0.6.1}/examples/release.json +0 -0
  85. {engineering_process-0.6.0 → engineering_process-0.6.1}/examples/remote-verification-evidence.json +0 -0
  86. {engineering_process-0.6.0 → engineering_process-0.6.1}/examples/remote-verification-request.json +0 -0
  87. {engineering_process-0.6.0 → engineering_process-0.6.1}/examples/review.json +0 -0
  88. {engineering_process-0.6.0 → engineering_process-0.6.1}/process-graph.json +0 -0
  89. {engineering_process-0.6.0 → engineering_process-0.6.1}/process_assets/skills/assess-design/SKILL.md +0 -0
  90. {engineering_process-0.6.0 → engineering_process-0.6.1}/process_assets/skills/build-frontend/SKILL.md +0 -0
  91. {engineering_process-0.6.0 → engineering_process-0.6.1}/process_assets/skills/build-frontend-foundation/SKILL.md +0 -0
  92. {engineering_process-0.6.0 → engineering_process-0.6.1}/process_assets/skills/change-api/SKILL.md +0 -0
  93. {engineering_process-0.6.0 → engineering_process-0.6.1}/process_assets/skills/cross-repo-change/SKILL.md +0 -0
  94. {engineering_process-0.6.0 → engineering_process-0.6.1}/process_assets/skills/define-change-contract/SKILL.md +0 -0
  95. {engineering_process-0.6.0 → engineering_process-0.6.1}/process_assets/skills/design-module/SKILL.md +0 -0
  96. {engineering_process-0.6.0 → engineering_process-0.6.1}/process_assets/skills/evolve-process/SKILL.md +0 -0
  97. {engineering_process-0.6.0 → engineering_process-0.6.1}/process_assets/skills/finish-change/SKILL.md +0 -0
  98. {engineering_process-0.6.0 → engineering_process-0.6.1}/process_assets/skills/govern-ui/SKILL.md +0 -0
  99. {engineering_process-0.6.0 → engineering_process-0.6.1}/process_assets/skills/implement-change/SKILL.md +0 -0
  100. {engineering_process-0.6.0 → engineering_process-0.6.1}/process_assets/skills/implement-module/SKILL.md +0 -0
  101. {engineering_process-0.6.0 → engineering_process-0.6.1}/process_assets/skills/implement-use-case/SKILL.md +0 -0
  102. {engineering_process-0.6.0 → engineering_process-0.6.1}/process_assets/skills/integrate-mcp/SKILL.md +0 -0
  103. {engineering_process-0.6.0 → engineering_process-0.6.1}/process_assets/skills/maintain-docs/SKILL.md +0 -0
  104. {engineering_process-0.6.0 → engineering_process-0.6.1}/process_assets/skills/plan-change/SKILL.md +0 -0
  105. {engineering_process-0.6.0 → engineering_process-0.6.1}/process_assets/skills/publish-change/SKILL.md +0 -0
  106. {engineering_process-0.6.0 → engineering_process-0.6.1}/process_assets/skills/review-change/SKILL.md +0 -0
  107. {engineering_process-0.6.0 → engineering_process-0.6.1}/process_assets/skills/run-change/SKILL.md +0 -0
  108. {engineering_process-0.6.0 → engineering_process-0.6.1}/process_assets/skills/run-change/references/execution.md +0 -0
  109. {engineering_process-0.6.0 → engineering_process-0.6.1}/process_assets/skills/run-project-command/SKILL.md +0 -0
  110. {engineering_process-0.6.0 → engineering_process-0.6.1}/process_assets/skills/specify-use-case/SKILL.md +0 -0
  111. {engineering_process-0.6.0 → engineering_process-0.6.1}/process_assets/skills/verify-change/SKILL.md +0 -0
  112. {engineering_process-0.6.0 → engineering_process-0.6.1}/schemas/adoption-migration.schema.json +0 -0
  113. {engineering_process-0.6.0 → engineering_process-0.6.1}/schemas/automation-policy.schema.json +0 -0
  114. {engineering_process-0.6.0 → engineering_process-0.6.1}/schemas/automation-proposal-policy.schema.json +0 -0
  115. {engineering_process-0.6.0 → engineering_process-0.6.1}/schemas/automation-proposal.schema.json +0 -0
  116. {engineering_process-0.6.0 → engineering_process-0.6.1}/schemas/change.schema.json +0 -0
  117. {engineering_process-0.6.0 → engineering_process-0.6.1}/schemas/evidence-receipt.schema.json +0 -0
  118. {engineering_process-0.6.0 → engineering_process-0.6.1}/schemas/improvement-catalog.schema.json +0 -0
  119. {engineering_process-0.6.0 → engineering_process-0.6.1}/schemas/improvement-disposition.schema.json +0 -0
  120. {engineering_process-0.6.0 → engineering_process-0.6.1}/schemas/improvement-reproduction.schema.json +0 -0
  121. {engineering_process-0.6.0 → engineering_process-0.6.1}/schemas/improvement-resolution.schema.json +0 -0
  122. {engineering_process-0.6.0 → engineering_process-0.6.1}/schemas/improvement-signal.schema.json +0 -0
  123. {engineering_process-0.6.0 → engineering_process-0.6.1}/schemas/lifecycle.schema.json +0 -0
  124. {engineering_process-0.6.0 → engineering_process-0.6.1}/schemas/plan.schema.json +0 -0
  125. {engineering_process-0.6.0 → engineering_process-0.6.1}/schemas/process-graph.schema.json +0 -0
  126. {engineering_process-0.6.0 → engineering_process-0.6.1}/schemas/process-lock.schema.json +0 -0
  127. {engineering_process-0.6.0 → engineering_process-0.6.1}/schemas/project.schema.json +0 -0
  128. {engineering_process-0.6.0 → engineering_process-0.6.1}/schemas/recommendation-resolution.schema.json +0 -0
  129. {engineering_process-0.6.0 → engineering_process-0.6.1}/schemas/recommendation-review-assignment.schema.json +0 -0
  130. {engineering_process-0.6.0 → engineering_process-0.6.1}/schemas/recommendation-review.schema.json +0 -0
  131. {engineering_process-0.6.0 → engineering_process-0.6.1}/schemas/recommendation.schema.json +0 -0
  132. {engineering_process-0.6.0 → engineering_process-0.6.1}/schemas/release-change.schema.json +0 -0
  133. {engineering_process-0.6.0 → engineering_process-0.6.1}/schemas/release.schema.json +0 -0
  134. {engineering_process-0.6.0 → engineering_process-0.6.1}/schemas/remote-verification-evidence.schema.json +0 -0
  135. {engineering_process-0.6.0 → engineering_process-0.6.1}/schemas/remote-verification-request.schema.json +0 -0
  136. {engineering_process-0.6.0 → engineering_process-0.6.1}/schemas/review.schema.json +0 -0
  137. {engineering_process-0.6.0 → engineering_process-0.6.1}/schemas/reviewer-attestation.schema.json +0 -0
  138. {engineering_process-0.6.0 → engineering_process-0.6.1}/schemas/supplemental-verification.schema.json +0 -0
  139. {engineering_process-0.6.0 → engineering_process-0.6.1}/schemas/verification.schema.json +0 -0
  140. {engineering_process-0.6.0 → engineering_process-0.6.1}/setup.cfg +0 -0
  141. {engineering_process-0.6.0 → engineering_process-0.6.1}/templates/AGENTS.process.md +0 -0
  142. {engineering_process-0.6.0 → engineering_process-0.6.1}/templates/PULL_REQUEST_TEMPLATE.md +0 -0
  143. {engineering_process-0.6.0 → engineering_process-0.6.1}/templates/adopt-process-windows-job.py +0 -0
  144. {engineering_process-0.6.0 → engineering_process-0.6.1}/templates/adopt-process.py +0 -0
  145. {engineering_process-0.6.0 → engineering_process-0.6.1}/tests/test_adoption.py +0 -0
  146. {engineering_process-0.6.0 → engineering_process-0.6.1}/tests/test_adoption_runner.py +0 -0
  147. {engineering_process-0.6.0 → engineering_process-0.6.1}/tests/test_artifact_attestation.py +0 -0
  148. {engineering_process-0.6.0 → engineering_process-0.6.1}/tests/test_bootstrap.py +0 -0
  149. {engineering_process-0.6.0 → engineering_process-0.6.1}/tests/test_bounded_process.py +0 -0
  150. {engineering_process-0.6.0 → engineering_process-0.6.1}/tests/test_bundles.py +0 -0
  151. {engineering_process-0.6.0 → engineering_process-0.6.1}/tests/test_cli.py +0 -0
  152. {engineering_process-0.6.0 → engineering_process-0.6.1}/tests/test_completed_release_dispatch.py +0 -0
  153. {engineering_process-0.6.0 → engineering_process-0.6.1}/tests/test_completion_evidence_transport.py +0 -0
  154. {engineering_process-0.6.0 → engineering_process-0.6.1}/tests/test_contracts.py +0 -0
  155. {engineering_process-0.6.0 → engineering_process-0.6.1}/tests/test_diagnostics.py +0 -0
  156. {engineering_process-0.6.0 → engineering_process-0.6.1}/tests/test_distribution.py +0 -0
  157. {engineering_process-0.6.0 → engineering_process-0.6.1}/tests/test_distribution_verify.py +0 -0
  158. {engineering_process-0.6.0 → engineering_process-0.6.1}/tests/test_evals.py +0 -0
  159. {engineering_process-0.6.0 → engineering_process-0.6.1}/tests/test_impact.py +0 -0
  160. {engineering_process-0.6.0 → engineering_process-0.6.1}/tests/test_improvement.py +0 -0
  161. {engineering_process-0.6.0 → engineering_process-0.6.1}/tests/test_lifecycle.py +0 -0
  162. {engineering_process-0.6.0 → engineering_process-0.6.1}/tests/test_process_graph.py +0 -0
  163. {engineering_process-0.6.0 → engineering_process-0.6.1}/tests/test_process_install.py +0 -0
  164. {engineering_process-0.6.0 → engineering_process-0.6.1}/tests/test_publication.py +0 -0
  165. {engineering_process-0.6.0 → engineering_process-0.6.1}/tests/test_publish_event.py +0 -0
  166. {engineering_process-0.6.0 → engineering_process-0.6.1}/tests/test_pypi_publication.py +0 -0
  167. {engineering_process-0.6.0 → engineering_process-0.6.1}/tests/test_recommendation.py +0 -0
  168. {engineering_process-0.6.0 → engineering_process-0.6.1}/tests/test_release.py +0 -0
  169. {engineering_process-0.6.0 → engineering_process-0.6.1}/tests/test_release_candidate.py +0 -0
  170. {engineering_process-0.6.0 → engineering_process-0.6.1}/tests/test_release_candidate_boundary.py +0 -0
  171. {engineering_process-0.6.0 → engineering_process-0.6.1}/tests/test_release_completion_identity.py +0 -0
  172. {engineering_process-0.6.0 → engineering_process-0.6.1}/tests/test_release_evidence_restore.py +0 -0
  173. {engineering_process-0.6.0 → engineering_process-0.6.1}/tests/test_release_evidence_selection.py +0 -0
  174. {engineering_process-0.6.0 → engineering_process-0.6.1}/tests/test_release_preparation.py +0 -0
  175. {engineering_process-0.6.0 → engineering_process-0.6.1}/tests/test_release_qualification.py +0 -0
  176. {engineering_process-0.6.0 → engineering_process-0.6.1}/tests/test_remote_verification.py +0 -0
  177. {engineering_process-0.6.0 → engineering_process-0.6.1}/tests/test_remote_verification_adapter.py +0 -0
  178. {engineering_process-0.6.0 → engineering_process-0.6.1}/tests/test_runtime.py +0 -0
  179. {engineering_process-0.6.0 → engineering_process-0.6.1}/tests/test_schemas.py +0 -0
  180. {engineering_process-0.6.0 → engineering_process-0.6.1}/tests/test_self_hosting.py +0 -0
  181. {engineering_process-0.6.0 → engineering_process-0.6.1}/tests/test_skills.py +0 -0
  182. {engineering_process-0.6.0 → engineering_process-0.6.1}/tests/test_source_checkout.py +0 -0
  183. {engineering_process-0.6.0 → engineering_process-0.6.1}/tests/test_supervision.py +0 -0
  184. {engineering_process-0.6.0 → engineering_process-0.6.1}/tests/test_supplemental.py +0 -0
  185. {engineering_process-0.6.0 → engineering_process-0.6.1}/tests/test_syncing.py +0 -0
  186. {engineering_process-0.6.0 → engineering_process-0.6.1}/tests/test_test_suite.py +0 -0
  187. {engineering_process-0.6.0 → engineering_process-0.6.1}/tests/test_tooling.py +0 -0
  188. {engineering_process-0.6.0 → engineering_process-0.6.1}/tests/test_windows_job.py +0 -0
@@ -1,6 +1,6 @@
1
1
  Metadata-Version: 2.4
2
2
  Name: engineering-process
3
- Version: 0.6.0
3
+ Version: 0.6.1
4
4
  Summary: Agent-neutral end-to-end engineering lifecycle and deterministic process CLI
5
5
  License-Expression: MIT
6
6
  Project-URL: Homepage, https://github.com/phuongnse/engineering-process
@@ -291,6 +291,14 @@ project-native dependency commands, dependency edges, and remediation. Project s
291
291
  does not carry a generic downloader, archive installer, doctor, or setup lifecycle.
292
292
  Host prerequisites with no safe automated setup action stay blocking.
293
293
 
294
+ The exact logical executable `python` is reserved by the distribution and resolves to
295
+ the absolute interpreter running the selected immutable process authority. This rule
296
+ applies consistently to requirement probes, verification profiles, setup command
297
+ actions, and `processctl exec`; callers do not activate a virtual environment or
298
+ modify `PATH` first. Manifests and reports retain the portable logical token, managed
299
+ tools cannot shadow it, and absolute executables plus non-Python commands keep their
300
+ existing resolution behavior.
301
+
294
302
  Probe `readOnly`, foreground-only execution, and command-action mutation scopes are
295
303
  project-owner attestations, not an operating-system sandbox: `processctl` cannot infer
296
304
  arbitrary subprocess side effects. Commands must not daemonize, start a detached
@@ -55,6 +55,12 @@ canonical command, or installing a consumer wrapper. Durable reports record only
55
55
  policy, severity, stream, line number, bounded count, truncation state, and line
56
56
  SHA-256. They never copy the diagnostic line into lifecycle evidence.
57
57
 
58
+ The portable logical command `python` resolves to the exact absolute interpreter of
59
+ the running immutable process authority across doctor, setup, execution, and
60
+ verification. Ambient `PATH` cannot select another Python installation, managed tools
61
+ cannot shadow the reserved binding, and evidence retains the logical command rather
62
+ than a host-specific activation sequence.
63
+
58
64
  Missing, stale, truncated beyond a declared policy, blocked, or unverifiable evidence
59
65
  never becomes a pass. Independent review records each accepted dimension as
60
66
  `verified`, `failed`, or `not-applicable-confirmed`; lifecycle submission compares
@@ -256,6 +256,14 @@ project-native dependency commands, dependency edges, and remediation. Project s
256
256
  does not carry a generic downloader, archive installer, doctor, or setup lifecycle.
257
257
  Host prerequisites with no safe automated setup action stay blocking.
258
258
 
259
+ The exact logical executable `python` is reserved by the distribution and resolves to
260
+ the absolute interpreter running the selected immutable process authority. This rule
261
+ applies consistently to requirement probes, verification profiles, setup command
262
+ actions, and `processctl exec`; callers do not activate a virtual environment or
263
+ modify `PATH` first. Manifests and reports retain the portable logical token, managed
264
+ tools cannot shadow it, and absolute executables plus non-Python commands keep their
265
+ existing resolution behavior.
266
+
259
267
  Probe `readOnly`, foreground-only execution, and command-action mutation scopes are
260
268
  project-owner attestations, not an operating-system sandbox: `processctl` cannot infer
261
269
  arbitrary subprocess side effects. Commands must not daemonize, start a detached
@@ -1,3 +1,3 @@
1
1
  """Agent-neutral engineering process."""
2
2
 
3
- VERSION = "0.6.0"
3
+ VERSION = "0.6.1"
@@ -9,13 +9,14 @@ import threading
9
9
  import time
10
10
  from datetime import UTC, datetime
11
11
  from pathlib import Path
12
- from typing import Any, Mapping
12
+ from typing import Any, Iterable, Mapping
13
13
 
14
14
  import regex as bounded_regex
15
15
 
16
16
  from .contracts import (
17
17
  ContractError,
18
18
  EnvironmentRequirement,
19
+ ManagedTool,
19
20
  MUTATION_SCOPES,
20
21
  Project,
21
22
  ProjectEnvironment,
@@ -479,10 +480,29 @@ def environment_path_entries(
479
480
  return tuple(entries)
480
481
 
481
482
 
483
+ def _authority_command_bindings(
484
+ tools: Iterable[ManagedTool],
485
+ ) -> dict[str, ManagedCommandBinding]:
486
+ bindings = managed_command_bindings(tools)
487
+ if "python" in bindings:
488
+ raise ContractError(
489
+ "managed tools cannot provide the reserved authority command: python"
490
+ )
491
+ authority_python = Path(sys.executable)
492
+ if not authority_python.is_absolute() or not authority_python.is_file():
493
+ raise ContractError(
494
+ "the active process authority does not expose an absolute Python executable"
495
+ )
496
+ return {
497
+ "python": ManagedCommandBinding(application=authority_python),
498
+ **bindings,
499
+ }
500
+
501
+
482
502
  def environment_command_bindings(
483
503
  project: Project, *, profile: str
484
504
  ) -> dict[str, ManagedCommandBinding]:
485
- return managed_command_bindings(
505
+ return _authority_command_bindings(
486
506
  _environment_managed_tools(project, profile=profile)
487
507
  )
488
508
 
@@ -684,7 +704,7 @@ def setup_environment(
684
704
  installed_paths = ()
685
705
  preflight_issues.append(str(error))
686
706
  try:
687
- installed_bindings = managed_command_bindings(
707
+ installed_bindings = _authority_command_bindings(
688
708
  environment.managed_tools[identifier]
689
709
  for identifier in sorted(planned_tool_ids)
690
710
  )
@@ -698,9 +718,18 @@ def setup_environment(
698
718
  tool = environment.managed_tools[action.tool]
699
719
  artifact = selected_artifact(tool)
700
720
  issue = None
721
+ if "python" in artifact.commands:
722
+ issue = (
723
+ f"setup action {action.identifier}: managed tools cannot provide "
724
+ "the reserved authority command: python"
725
+ )
701
726
  install_issue = managed_tool_preflight(tool)
702
727
  if install_issue is not None:
703
- issue = f"setup action {action.identifier}: {install_issue}"
728
+ issue = (
729
+ f"{issue}; {install_issue}"
730
+ if issue is not None
731
+ else f"setup action {action.identifier}: {install_issue}"
732
+ )
704
733
  for command_name in artifact.commands:
705
734
  previous = provided_commands.get(command_name)
706
735
  if previous is not None and previous != action.identifier:
@@ -841,7 +870,7 @@ def setup_environment(
841
870
  environment.managed_tools[identifier]
842
871
  for identifier in sorted(planned_tool_ids)
843
872
  ),
844
- command_bindings=managed_command_bindings(
873
+ command_bindings=_authority_command_bindings(
845
874
  environment.managed_tools[identifier]
846
875
  for identifier in sorted(planned_tool_ids)
847
876
  ),
@@ -1,6 +1,6 @@
1
1
  Metadata-Version: 2.4
2
2
  Name: engineering-process
3
- Version: 0.6.0
3
+ Version: 0.6.1
4
4
  Summary: Agent-neutral end-to-end engineering lifecycle and deterministic process CLI
5
5
  License-Expression: MIT
6
6
  Project-URL: Homepage, https://github.com/phuongnse/engineering-process
@@ -291,6 +291,14 @@ project-native dependency commands, dependency edges, and remediation. Project s
291
291
  does not carry a generic downloader, archive installer, doctor, or setup lifecycle.
292
292
  Host prerequisites with no safe automated setup action stay blocking.
293
293
 
294
+ The exact logical executable `python` is reserved by the distribution and resolves to
295
+ the absolute interpreter running the selected immutable process authority. This rule
296
+ applies consistently to requirement probes, verification profiles, setup command
297
+ actions, and `processctl exec`; callers do not activate a virtual environment or
298
+ modify `PATH` first. Manifests and reports retain the portable logical token, managed
299
+ tools cannot shadow it, and absolute executables plus non-Python commands keep their
300
+ existing resolution behavior.
301
+
294
302
  Probe `readOnly`, foreground-only execution, and command-action mutation scopes are
295
303
  project-owner attestations, not an operating-system sandbox: `processctl` cannot infer
296
304
  arbitrary subprocess side effects. Commands must not daemonize, start a detached
@@ -4,8 +4,8 @@
4
4
  "activeChangeId": null,
5
5
  "id": "deterministic-cross-platform-test-environment",
6
6
  "lastResolution": {
7
- "changeId": "extend-windows-natural-drain",
8
- "version": "0.5.1"
7
+ "changeId": "bind-authority-python-runtime-v2",
8
+ "version": "0.6.1"
9
9
  },
10
10
  "publicSurfaces": [
11
11
  "cross-platform-tests",
@@ -4,7 +4,7 @@ build-backend = "setuptools.build_meta"
4
4
 
5
5
  [project]
6
6
  name = "engineering-process"
7
- version = "0.6.0"
7
+ version = "0.6.1"
8
8
  description = "Agent-neutral end-to-end engineering lifecycle and deterministic process CLI"
9
9
  readme = "README.md"
10
10
  license = "MIT"
@@ -0,0 +1,46 @@
1
+ {
2
+ "schemaVersion": 3,
3
+ "previousVersion": "0.6.0",
4
+ "version": "0.6.1",
5
+ "classification": "patch",
6
+ "compatibility": "backward-compatible",
7
+ "schemaImpact": "unchanged",
8
+ "migration": null,
9
+ "identity": {
10
+ "package": "engineering-process",
11
+ "distribution": "engineering_process",
12
+ "tag": "v0.6.1",
13
+ "releaseName": "v0.6.1",
14
+ "runtimeVersion": {
15
+ "path": "engineering_process/__init__.py",
16
+ "variable": "VERSION"
17
+ },
18
+ "artifacts": [
19
+ "engineering_process-0.6.1-py3-none-any.whl",
20
+ "engineering_process-0.6.1.tar.gz"
21
+ ],
22
+ "receiptAsset": "engineering-process-v0.6.1-evidence.json",
23
+ "authorizationAsset": null
24
+ },
25
+ "provenance": {
26
+ "mode": "governed",
27
+ "statement": "The public N-1 lifecycle receipt and reviewed Release PR authorize this release.",
28
+ "lifecycleReceipt": {
29
+ "asset": "engineering-process-v0.6.1-evidence.json",
30
+ "project": "engineering-process",
31
+ "changeId": "release-0-6-1",
32
+ "cycle": 1
33
+ }
34
+ },
35
+ "changes": [
36
+ {
37
+ "id": "bind-authority-python-runtime-v2",
38
+ "type": "fix",
39
+ "surfaces": [
40
+ "command-execution",
41
+ "environment-resolution"
42
+ ],
43
+ "rationale": "Bind the portable logical command python to the exact interpreter running the immutable process authority across doctor, setup, exec, and verification so ambient shell PATH cannot select an unrelated Python runtime or require consumer activation wrappers."
44
+ }
45
+ ]
46
+ }
@@ -12,6 +12,7 @@ from unittest.mock import patch
12
12
  from engineering_process.contracts import ContractError, validate_project
13
13
  from engineering_process.environment import (
14
14
  doctor_environment,
15
+ environment_command_bindings,
15
16
  execute_command,
16
17
  setup_environment,
17
18
  )
@@ -30,7 +31,7 @@ def project_document(*, setup: bool = True, dependency: bool = False):
30
31
  "id": "prepare-parent",
31
32
  "kind": "command",
32
33
  "run": [
33
- sys.executable,
34
+ "python",
34
35
  "-c",
35
36
  "from pathlib import Path; Path('parent.txt').write_text('ready')",
36
37
  ],
@@ -46,7 +47,7 @@ def project_document(*, setup: bool = True, dependency: bool = False):
46
47
  action = {
47
48
  "id": "prepare-environment",
48
49
  "kind": "command",
49
- "run": [sys.executable, "-c", command],
50
+ "run": ["python", "-c", command],
50
51
  "timeoutSeconds": 30,
51
52
  "mutations": ["project-files"],
52
53
  }
@@ -58,7 +59,7 @@ def project_document(*, setup: bool = True, dependency: bool = False):
58
59
  "id": "project-environment",
59
60
  "description": "Project environment marker",
60
61
  "probe": {
61
- "run": [sys.executable, "-c", ready_probe],
62
+ "run": ["python", "-c", ready_probe],
62
63
  "timeoutSeconds": 30,
63
64
  "readOnly": True,
64
65
  },
@@ -74,14 +75,14 @@ def project_document(*, setup: bool = True, dependency: bool = False):
74
75
  "development": [
75
76
  {
76
77
  "id": "unit",
77
- "run": [sys.executable, "-c", "raise SystemExit(0)"],
78
+ "run": ["python", "-c", "raise SystemExit(0)"],
78
79
  "timeoutSeconds": 30,
79
80
  }
80
81
  ],
81
82
  "review": [
82
83
  {
83
84
  "id": "review",
84
- "run": [sys.executable, "-c", "raise SystemExit(0)"],
85
+ "run": ["python", "-c", "raise SystemExit(0)"],
85
86
  "timeoutSeconds": 30,
86
87
  }
87
88
  ],
@@ -101,6 +102,44 @@ def project_document(*, setup: bool = True, dependency: bool = False):
101
102
 
102
103
 
103
104
  class EnvironmentTests(unittest.TestCase):
105
+ def test_portable_python_uses_authority_without_path_activation(self):
106
+ with tempfile.TemporaryDirectory() as directory:
107
+ root = Path(directory)
108
+ project = validate_project(project_document(setup=False))
109
+ bindings = environment_command_bindings(project, profile="development")
110
+
111
+ with patch.dict(os.environ, {"PATH": str(root)}):
112
+ report = execute_command(
113
+ root,
114
+ identifier="authority-python",
115
+ run=("python", "-c", "import sys; print(sys.executable)"),
116
+ timeout_seconds=30,
117
+ working_directory=".",
118
+ command_bindings=bindings,
119
+ )
120
+
121
+ self.assertEqual("passed", report["status"])
122
+ self.assertEqual(
123
+ ["python", "-c", "import sys; print(sys.executable)"],
124
+ report["command"],
125
+ )
126
+ self.assertEqual(Path(sys.executable), Path(report["stdout"].strip()))
127
+
128
+ def test_managed_tool_cannot_shadow_the_authority_python_binding(self):
129
+ project = validate_project(project_document(setup=False))
130
+ shadow = ManagedCommandBinding(application=Path(sys.executable))
131
+
132
+ with (
133
+ patch(
134
+ "engineering_process.environment.managed_command_bindings",
135
+ return_value={"python": shadow},
136
+ ),
137
+ self.assertRaisesRegex(
138
+ ContractError, "reserved authority command: python"
139
+ ),
140
+ ):
141
+ environment_command_bindings(project, profile="development")
142
+
104
143
  def test_exit_zero_warning_or_error_diagnostic_fails_closed(self):
105
144
  cases = (
106
145
  ("stdout", "WARN: degraded validation"),
@@ -254,6 +293,25 @@ class EnvironmentTests(unittest.TestCase):
254
293
  self.assertEqual("missing", report["requirements"][0]["status"])
255
294
  self.assertFalse((root / "ready.txt").exists())
256
295
 
296
+ def test_doctor_uses_authority_python_when_ambient_path_has_no_python(self):
297
+ with tempfile.TemporaryDirectory() as directory:
298
+ root = Path(directory)
299
+ document = project_document(setup=False)
300
+ document["environment"]["requirements"][0]["probe"] = {
301
+ "run": ["python", "-c", "print('authority ready')"],
302
+ "timeoutSeconds": 30,
303
+ "readOnly": True,
304
+ "outputStream": "stdout",
305
+ "outputRegex": "^authority ready$",
306
+ }
307
+ project = validate_project(document)
308
+
309
+ with patch.dict(os.environ, {"PATH": str(root)}):
310
+ report = doctor_environment(root, project)
311
+
312
+ self.assertEqual("passed", report["status"])
313
+ self.assertEqual("satisfied", report["requirements"][0]["status"])
314
+
257
315
  def test_setup_plan_does_not_mutate_and_lists_required_approval(self):
258
316
  with tempfile.TemporaryDirectory() as directory:
259
317
  root = Path(directory)
@@ -625,6 +683,28 @@ class EnvironmentTests(unittest.TestCase):
625
683
  self.assertIn("not a directory", "\n".join(report["blocked"]))
626
684
  self.assertFalse((root / "mutated").exists())
627
685
 
686
+ def test_setup_rejects_managed_tool_that_provides_reserved_python(self):
687
+ with tempfile.TemporaryDirectory() as directory:
688
+ root = Path(directory)
689
+ document = self.managed_setup_document()
690
+ artifact = document["environment"]["managedTools"][0]["artifacts"][0]
691
+ executable = "python.exe" if os.name == "nt" else "python"
692
+ artifact["commands"] = {"python": executable}
693
+ project = validate_project(document)
694
+
695
+ report = setup_environment(
696
+ root,
697
+ project,
698
+ profile=None,
699
+ apply=False,
700
+ allowed_mutations=set(),
701
+ )
702
+
703
+ self.assertEqual("blocked", report["status"])
704
+ self.assertIn(
705
+ "reserved authority command: python", "\n".join(report["blocked"])
706
+ )
707
+
628
708
  def test_setup_preserves_partial_evidence_for_operational_installer_error(self):
629
709
  with tempfile.TemporaryDirectory() as directory:
630
710
  root = Path(directory)
@@ -84,6 +84,35 @@ class RunnerTests(unittest.TestCase):
84
84
  ]
85
85
  validate_verification(legacy)
86
86
 
87
+ def test_profile_uses_authority_python_from_portable_command(self):
88
+ with tempfile.TemporaryDirectory() as directory:
89
+ root = Path(directory)
90
+ project = Project(
91
+ identifier="sample",
92
+ profiles={
93
+ "development": (
94
+ Check(
95
+ identifier="portable-python",
96
+ run=(
97
+ "python",
98
+ "-c",
99
+ "import sys; print(sys.executable)",
100
+ ),
101
+ timeout_seconds=10,
102
+ working_directory=".",
103
+ ),
104
+ )
105
+ },
106
+ )
107
+
108
+ with patch(
109
+ "engineering_process.environment.sys.stderr", io.StringIO()
110
+ ):
111
+ report = run_profile(root, project, "development")
112
+
113
+ self.assertEqual("passed", report["status"])
114
+ self.assertEqual("python", report["checks"][0]["command"][0])
115
+
87
116
  def test_warning_after_evidence_prefix_and_split_across_writes_fails(self):
88
117
  with tempfile.TemporaryDirectory() as directory:
89
118
  root = Path(directory)
@@ -1,51 +0,0 @@
1
- {
2
- "schemaVersion": 3,
3
- "previousVersion": "0.5.1",
4
- "version": "0.6.0",
5
- "classification": "minor",
6
- "compatibility": "incompatible",
7
- "schemaImpact": "additive",
8
- "migration": "evidence-valid-remote-verification: After immutable release and adoption, route every new material owner decision through recommendation review and resolution. Projects that need remote claims separately add named remoteVerification requirements to the target-version project manifest and select them through requiredEvidence on new change contracts; historical decisions and completed lifecycles require no backfill.",
9
- "identity": {
10
- "package": "engineering-process",
11
- "distribution": "engineering_process",
12
- "tag": "v0.6.0",
13
- "releaseName": "v0.6.0",
14
- "runtimeVersion": {
15
- "path": "engineering_process/__init__.py",
16
- "variable": "VERSION"
17
- },
18
- "artifacts": [
19
- "engineering_process-0.6.0-py3-none-any.whl",
20
- "engineering_process-0.6.0.tar.gz"
21
- ],
22
- "receiptAsset": "engineering-process-v0.6.0-evidence.json",
23
- "authorizationAsset": null
24
- },
25
- "provenance": {
26
- "mode": "governed",
27
- "statement": "The public N-1 lifecycle receipt and reviewed Release PR authorize this release.",
28
- "lifecycleReceipt": {
29
- "asset": "engineering-process-v0.6.0-evidence.json",
30
- "project": "engineering-process",
31
- "changeId": "release-0-6-0",
32
- "cycle": 1
33
- }
34
- },
35
- "changes": [
36
- {
37
- "id": "evidence-valid-remote-verification",
38
- "type": "breaking",
39
- "surfaces": [
40
- "cli",
41
- "governance",
42
- "lifecycle",
43
- "recommendation",
44
- "schema",
45
- "skills",
46
- "verification"
47
- ],
48
- "rationale": "Require evidence-derived valid recommendations with stateful independent challenge, and add project-owned exact-checkpoint remote evidence requests whose complete selector set must be ingested before review or completion."
49
- }
50
- ]
51
- }