engineering-process 0.5.1__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 (187) hide show
  1. {engineering_process-0.5.1/engineering_process.egg-info → engineering_process-0.6.1}/PKG-INFO +79 -5
  2. {engineering_process-0.5.1 → engineering_process-0.6.1}/PRODUCTION_STANDARD.md +37 -0
  3. {engineering_process-0.5.1 → engineering_process-0.6.1}/README.md +78 -4
  4. {engineering_process-0.5.1 → engineering_process-0.6.1}/VERSIONING.md +25 -0
  5. {engineering_process-0.5.1 → engineering_process-0.6.1}/engineering_process/__init__.py +1 -1
  6. {engineering_process-0.5.1 → engineering_process-0.6.1}/engineering_process/cli.py +222 -0
  7. {engineering_process-0.5.1 → engineering_process-0.6.1}/engineering_process/command_catalog.py +2 -0
  8. {engineering_process-0.5.1 → engineering_process-0.6.1}/engineering_process/contracts.py +1485 -179
  9. {engineering_process-0.5.1 → engineering_process-0.6.1}/engineering_process/distribution_verify.py +2 -0
  10. {engineering_process-0.5.1 → engineering_process-0.6.1}/engineering_process/environment.py +34 -5
  11. {engineering_process-0.5.1 → engineering_process-0.6.1}/engineering_process/evidence.py +286 -5
  12. {engineering_process-0.5.1 → engineering_process-0.6.1}/engineering_process/lifecycle.py +558 -5
  13. {engineering_process-0.5.1 → engineering_process-0.6.1}/engineering_process/process_graph.py +6 -1
  14. engineering_process-0.6.1/engineering_process/recommendation.py +517 -0
  15. engineering_process-0.6.1/engineering_process/remote_verification.py +498 -0
  16. {engineering_process-0.5.1 → engineering_process-0.6.1/engineering_process.egg-info}/PKG-INFO +79 -5
  17. {engineering_process-0.5.1 → engineering_process-0.6.1}/engineering_process.egg-info/SOURCES.txt +17 -0
  18. {engineering_process-0.5.1 → engineering_process-0.6.1}/examples/change.json +1 -0
  19. {engineering_process-0.5.1 → engineering_process-0.6.1}/examples/project.json +22 -0
  20. engineering_process-0.6.1/examples/recommendation-resolution.json +21 -0
  21. engineering_process-0.6.1/examples/recommendation-review-assignment.json +22 -0
  22. engineering_process-0.6.1/examples/recommendation-review.json +60 -0
  23. engineering_process-0.6.1/examples/recommendation.json +89 -0
  24. engineering_process-0.6.1/examples/remote-verification-evidence.json +26 -0
  25. engineering_process-0.6.1/examples/remote-verification-request.json +40 -0
  26. {engineering_process-0.5.1 → engineering_process-0.6.1}/improvement-catalog.json +5 -4
  27. {engineering_process-0.5.1 → engineering_process-0.6.1}/process-graph.json +1 -1
  28. {engineering_process-0.5.1 → engineering_process-0.6.1}/process_assets/skills/assess-design/SKILL.md +16 -3
  29. {engineering_process-0.5.1 → engineering_process-0.6.1}/process_assets/skills/run-change/references/execution.md +43 -7
  30. {engineering_process-0.5.1 → engineering_process-0.6.1}/process_assets/skills/verify-change/SKILL.md +11 -3
  31. {engineering_process-0.5.1 → engineering_process-0.6.1}/pyproject.toml +13 -1
  32. {engineering_process-0.5.1 → engineering_process-0.6.1}/release.json +12 -12
  33. {engineering_process-0.5.1 → engineering_process-0.6.1}/schemas/change.schema.json +18 -1
  34. {engineering_process-0.5.1 → engineering_process-0.6.1}/schemas/evidence-receipt.schema.json +36 -1
  35. {engineering_process-0.5.1 → engineering_process-0.6.1}/schemas/lifecycle.schema.json +26 -0
  36. {engineering_process-0.5.1 → engineering_process-0.6.1}/schemas/project.schema.json +92 -2
  37. engineering_process-0.6.1/schemas/recommendation-resolution.schema.json +60 -0
  38. engineering_process-0.6.1/schemas/recommendation-review-assignment.schema.json +56 -0
  39. engineering_process-0.6.1/schemas/recommendation-review.schema.json +112 -0
  40. engineering_process-0.6.1/schemas/recommendation.schema.json +178 -0
  41. engineering_process-0.6.1/schemas/remote-verification-evidence.schema.json +61 -0
  42. engineering_process-0.6.1/schemas/remote-verification-request.schema.json +116 -0
  43. {engineering_process-0.5.1 → engineering_process-0.6.1}/tests/test_environment.py +85 -5
  44. engineering_process-0.6.1/tests/test_recommendation.py +578 -0
  45. engineering_process-0.6.1/tests/test_remote_verification.py +833 -0
  46. engineering_process-0.6.1/tests/test_remote_verification_adapter.py +360 -0
  47. {engineering_process-0.5.1 → engineering_process-0.6.1}/tests/test_runner.py +29 -0
  48. {engineering_process-0.5.1 → engineering_process-0.6.1}/tests/test_schemas.py +4 -0
  49. {engineering_process-0.5.1 → engineering_process-0.6.1}/tests/test_self_hosting.py +11 -1
  50. {engineering_process-0.5.1 → engineering_process-0.6.1}/tests/test_skills.py +31 -0
  51. {engineering_process-0.5.1 → engineering_process-0.6.1}/LICENSE +0 -0
  52. {engineering_process-0.5.1 → engineering_process-0.6.1}/MANIFEST.in +0 -0
  53. {engineering_process-0.5.1 → engineering_process-0.6.1}/PROCESS_IMPROVEMENT.md +0 -0
  54. {engineering_process-0.5.1 → engineering_process-0.6.1}/bundles.json +0 -0
  55. {engineering_process-0.5.1 → engineering_process-0.6.1}/engineering_process/__main__.py +0 -0
  56. {engineering_process-0.5.1 → engineering_process-0.6.1}/engineering_process/_download_worker.py +0 -0
  57. {engineering_process-0.5.1 → engineering_process-0.6.1}/engineering_process/_supervisor_posix.py +0 -0
  58. {engineering_process-0.5.1 → engineering_process-0.6.1}/engineering_process/_supervisor_windows.py +0 -0
  59. {engineering_process-0.5.1 → engineering_process-0.6.1}/engineering_process/_windows_job.py +0 -0
  60. {engineering_process-0.5.1 → engineering_process-0.6.1}/engineering_process/adoption.py +0 -0
  61. {engineering_process-0.5.1 → engineering_process-0.6.1}/engineering_process/artifact_attestation.py +0 -0
  62. {engineering_process-0.5.1 → engineering_process-0.6.1}/engineering_process/bootstrap.py +0 -0
  63. {engineering_process-0.5.1 → engineering_process-0.6.1}/engineering_process/bounded_process.py +0 -0
  64. {engineering_process-0.5.1 → engineering_process-0.6.1}/engineering_process/bundles.py +0 -0
  65. {engineering_process-0.5.1 → engineering_process-0.6.1}/engineering_process/diagnostics.py +0 -0
  66. {engineering_process-0.5.1 → engineering_process-0.6.1}/engineering_process/distribution.py +0 -0
  67. {engineering_process-0.5.1 → engineering_process-0.6.1}/engineering_process/evidence_transport.py +0 -0
  68. {engineering_process-0.5.1 → engineering_process-0.6.1}/engineering_process/git.py +0 -0
  69. {engineering_process-0.5.1 → engineering_process-0.6.1}/engineering_process/git_attributes.py +0 -0
  70. {engineering_process-0.5.1 → engineering_process-0.6.1}/engineering_process/helper_launch.py +0 -0
  71. {engineering_process-0.5.1 → engineering_process-0.6.1}/engineering_process/impact.py +0 -0
  72. {engineering_process-0.5.1 → engineering_process-0.6.1}/engineering_process/improvement.py +0 -0
  73. {engineering_process-0.5.1 → engineering_process-0.6.1}/engineering_process/lifecycle_routes.py +0 -0
  74. {engineering_process-0.5.1 → engineering_process-0.6.1}/engineering_process/managed.py +0 -0
  75. {engineering_process-0.5.1 → engineering_process-0.6.1}/engineering_process/markdown.py +0 -0
  76. {engineering_process-0.5.1 → engineering_process-0.6.1}/engineering_process/publication.py +0 -0
  77. {engineering_process-0.5.1 → engineering_process-0.6.1}/engineering_process/release.py +0 -0
  78. {engineering_process-0.5.1 → engineering_process-0.6.1}/engineering_process/release_candidate.py +0 -0
  79. {engineering_process-0.5.1 → engineering_process-0.6.1}/engineering_process/requirements-build.txt +0 -0
  80. {engineering_process-0.5.1 → engineering_process-0.6.1}/engineering_process/requirements-dev.txt +0 -0
  81. {engineering_process-0.5.1 → engineering_process-0.6.1}/engineering_process/requirements-release.txt +0 -0
  82. {engineering_process-0.5.1 → engineering_process-0.6.1}/engineering_process/requirements-runtime.txt +0 -0
  83. {engineering_process-0.5.1 → engineering_process-0.6.1}/engineering_process/runner.py +0 -0
  84. {engineering_process-0.5.1 → engineering_process-0.6.1}/engineering_process/runtime.py +0 -0
  85. {engineering_process-0.5.1 → engineering_process-0.6.1}/engineering_process/skills.py +0 -0
  86. {engineering_process-0.5.1 → engineering_process-0.6.1}/engineering_process/supervision.py +0 -0
  87. {engineering_process-0.5.1 → engineering_process-0.6.1}/engineering_process/supplemental.py +0 -0
  88. {engineering_process-0.5.1 → engineering_process-0.6.1}/engineering_process/syncing.py +0 -0
  89. {engineering_process-0.5.1 → engineering_process-0.6.1}/engineering_process/tooling.py +0 -0
  90. {engineering_process-0.5.1 → engineering_process-0.6.1}/engineering_process.egg-info/dependency_links.txt +0 -0
  91. {engineering_process-0.5.1 → engineering_process-0.6.1}/engineering_process.egg-info/entry_points.txt +0 -0
  92. {engineering_process-0.5.1 → engineering_process-0.6.1}/engineering_process.egg-info/requires.txt +0 -0
  93. {engineering_process-0.5.1 → engineering_process-0.6.1}/engineering_process.egg-info/top_level.txt +0 -0
  94. {engineering_process-0.5.1 → engineering_process-0.6.1}/examples/adoption-migration.json +0 -0
  95. {engineering_process-0.5.1 → engineering_process-0.6.1}/examples/automation-policy.json +0 -0
  96. {engineering_process-0.5.1 → engineering_process-0.6.1}/examples/automation-proposal-policy.json +0 -0
  97. {engineering_process-0.5.1 → engineering_process-0.6.1}/examples/automation-proposal.json +0 -0
  98. {engineering_process-0.5.1 → engineering_process-0.6.1}/examples/improvement-catalog.json +0 -0
  99. {engineering_process-0.5.1 → engineering_process-0.6.1}/examples/improvement-disposition.json +0 -0
  100. {engineering_process-0.5.1 → engineering_process-0.6.1}/examples/improvement-reproduction.json +0 -0
  101. {engineering_process-0.5.1 → engineering_process-0.6.1}/examples/improvement-resolution.json +0 -0
  102. {engineering_process-0.5.1 → engineering_process-0.6.1}/examples/improvement-signal.json +0 -0
  103. {engineering_process-0.5.1 → engineering_process-0.6.1}/examples/plan.json +0 -0
  104. {engineering_process-0.5.1 → engineering_process-0.6.1}/examples/release-change.json +0 -0
  105. {engineering_process-0.5.1 → engineering_process-0.6.1}/examples/release.json +0 -0
  106. {engineering_process-0.5.1 → engineering_process-0.6.1}/examples/review.json +0 -0
  107. {engineering_process-0.5.1 → engineering_process-0.6.1}/process_assets/skills/build-frontend/SKILL.md +0 -0
  108. {engineering_process-0.5.1 → engineering_process-0.6.1}/process_assets/skills/build-frontend-foundation/SKILL.md +0 -0
  109. {engineering_process-0.5.1 → engineering_process-0.6.1}/process_assets/skills/change-api/SKILL.md +0 -0
  110. {engineering_process-0.5.1 → engineering_process-0.6.1}/process_assets/skills/cross-repo-change/SKILL.md +0 -0
  111. {engineering_process-0.5.1 → engineering_process-0.6.1}/process_assets/skills/define-change-contract/SKILL.md +0 -0
  112. {engineering_process-0.5.1 → engineering_process-0.6.1}/process_assets/skills/design-module/SKILL.md +0 -0
  113. {engineering_process-0.5.1 → engineering_process-0.6.1}/process_assets/skills/evolve-process/SKILL.md +0 -0
  114. {engineering_process-0.5.1 → engineering_process-0.6.1}/process_assets/skills/finish-change/SKILL.md +0 -0
  115. {engineering_process-0.5.1 → engineering_process-0.6.1}/process_assets/skills/govern-ui/SKILL.md +0 -0
  116. {engineering_process-0.5.1 → engineering_process-0.6.1}/process_assets/skills/implement-change/SKILL.md +0 -0
  117. {engineering_process-0.5.1 → engineering_process-0.6.1}/process_assets/skills/implement-module/SKILL.md +0 -0
  118. {engineering_process-0.5.1 → engineering_process-0.6.1}/process_assets/skills/implement-use-case/SKILL.md +0 -0
  119. {engineering_process-0.5.1 → engineering_process-0.6.1}/process_assets/skills/integrate-mcp/SKILL.md +0 -0
  120. {engineering_process-0.5.1 → engineering_process-0.6.1}/process_assets/skills/maintain-docs/SKILL.md +0 -0
  121. {engineering_process-0.5.1 → engineering_process-0.6.1}/process_assets/skills/plan-change/SKILL.md +0 -0
  122. {engineering_process-0.5.1 → engineering_process-0.6.1}/process_assets/skills/publish-change/SKILL.md +0 -0
  123. {engineering_process-0.5.1 → engineering_process-0.6.1}/process_assets/skills/review-change/SKILL.md +0 -0
  124. {engineering_process-0.5.1 → engineering_process-0.6.1}/process_assets/skills/run-change/SKILL.md +0 -0
  125. {engineering_process-0.5.1 → engineering_process-0.6.1}/process_assets/skills/run-project-command/SKILL.md +0 -0
  126. {engineering_process-0.5.1 → engineering_process-0.6.1}/process_assets/skills/specify-use-case/SKILL.md +0 -0
  127. {engineering_process-0.5.1 → engineering_process-0.6.1}/schemas/adoption-migration.schema.json +0 -0
  128. {engineering_process-0.5.1 → engineering_process-0.6.1}/schemas/automation-policy.schema.json +0 -0
  129. {engineering_process-0.5.1 → engineering_process-0.6.1}/schemas/automation-proposal-policy.schema.json +0 -0
  130. {engineering_process-0.5.1 → engineering_process-0.6.1}/schemas/automation-proposal.schema.json +0 -0
  131. {engineering_process-0.5.1 → engineering_process-0.6.1}/schemas/improvement-catalog.schema.json +0 -0
  132. {engineering_process-0.5.1 → engineering_process-0.6.1}/schemas/improvement-disposition.schema.json +0 -0
  133. {engineering_process-0.5.1 → engineering_process-0.6.1}/schemas/improvement-reproduction.schema.json +0 -0
  134. {engineering_process-0.5.1 → engineering_process-0.6.1}/schemas/improvement-resolution.schema.json +0 -0
  135. {engineering_process-0.5.1 → engineering_process-0.6.1}/schemas/improvement-signal.schema.json +0 -0
  136. {engineering_process-0.5.1 → engineering_process-0.6.1}/schemas/plan.schema.json +0 -0
  137. {engineering_process-0.5.1 → engineering_process-0.6.1}/schemas/process-graph.schema.json +0 -0
  138. {engineering_process-0.5.1 → engineering_process-0.6.1}/schemas/process-lock.schema.json +0 -0
  139. {engineering_process-0.5.1 → engineering_process-0.6.1}/schemas/release-change.schema.json +0 -0
  140. {engineering_process-0.5.1 → engineering_process-0.6.1}/schemas/release.schema.json +0 -0
  141. {engineering_process-0.5.1 → engineering_process-0.6.1}/schemas/review.schema.json +0 -0
  142. {engineering_process-0.5.1 → engineering_process-0.6.1}/schemas/reviewer-attestation.schema.json +0 -0
  143. {engineering_process-0.5.1 → engineering_process-0.6.1}/schemas/supplemental-verification.schema.json +0 -0
  144. {engineering_process-0.5.1 → engineering_process-0.6.1}/schemas/verification.schema.json +0 -0
  145. {engineering_process-0.5.1 → engineering_process-0.6.1}/setup.cfg +0 -0
  146. {engineering_process-0.5.1 → engineering_process-0.6.1}/templates/AGENTS.process.md +0 -0
  147. {engineering_process-0.5.1 → engineering_process-0.6.1}/templates/PULL_REQUEST_TEMPLATE.md +0 -0
  148. {engineering_process-0.5.1 → engineering_process-0.6.1}/templates/adopt-process-windows-job.py +0 -0
  149. {engineering_process-0.5.1 → engineering_process-0.6.1}/templates/adopt-process.py +0 -0
  150. {engineering_process-0.5.1 → engineering_process-0.6.1}/tests/test_adoption.py +0 -0
  151. {engineering_process-0.5.1 → engineering_process-0.6.1}/tests/test_adoption_runner.py +0 -0
  152. {engineering_process-0.5.1 → engineering_process-0.6.1}/tests/test_artifact_attestation.py +0 -0
  153. {engineering_process-0.5.1 → engineering_process-0.6.1}/tests/test_bootstrap.py +0 -0
  154. {engineering_process-0.5.1 → engineering_process-0.6.1}/tests/test_bounded_process.py +0 -0
  155. {engineering_process-0.5.1 → engineering_process-0.6.1}/tests/test_bundles.py +0 -0
  156. {engineering_process-0.5.1 → engineering_process-0.6.1}/tests/test_cli.py +0 -0
  157. {engineering_process-0.5.1 → engineering_process-0.6.1}/tests/test_completed_release_dispatch.py +0 -0
  158. {engineering_process-0.5.1 → engineering_process-0.6.1}/tests/test_completion_evidence_transport.py +0 -0
  159. {engineering_process-0.5.1 → engineering_process-0.6.1}/tests/test_contracts.py +0 -0
  160. {engineering_process-0.5.1 → engineering_process-0.6.1}/tests/test_diagnostics.py +0 -0
  161. {engineering_process-0.5.1 → engineering_process-0.6.1}/tests/test_distribution.py +0 -0
  162. {engineering_process-0.5.1 → engineering_process-0.6.1}/tests/test_distribution_verify.py +0 -0
  163. {engineering_process-0.5.1 → engineering_process-0.6.1}/tests/test_evals.py +0 -0
  164. {engineering_process-0.5.1 → engineering_process-0.6.1}/tests/test_impact.py +0 -0
  165. {engineering_process-0.5.1 → engineering_process-0.6.1}/tests/test_improvement.py +0 -0
  166. {engineering_process-0.5.1 → engineering_process-0.6.1}/tests/test_lifecycle.py +0 -0
  167. {engineering_process-0.5.1 → engineering_process-0.6.1}/tests/test_process_graph.py +0 -0
  168. {engineering_process-0.5.1 → engineering_process-0.6.1}/tests/test_process_install.py +0 -0
  169. {engineering_process-0.5.1 → engineering_process-0.6.1}/tests/test_publication.py +0 -0
  170. {engineering_process-0.5.1 → engineering_process-0.6.1}/tests/test_publish_event.py +0 -0
  171. {engineering_process-0.5.1 → engineering_process-0.6.1}/tests/test_pypi_publication.py +0 -0
  172. {engineering_process-0.5.1 → engineering_process-0.6.1}/tests/test_release.py +0 -0
  173. {engineering_process-0.5.1 → engineering_process-0.6.1}/tests/test_release_candidate.py +0 -0
  174. {engineering_process-0.5.1 → engineering_process-0.6.1}/tests/test_release_candidate_boundary.py +0 -0
  175. {engineering_process-0.5.1 → engineering_process-0.6.1}/tests/test_release_completion_identity.py +0 -0
  176. {engineering_process-0.5.1 → engineering_process-0.6.1}/tests/test_release_evidence_restore.py +0 -0
  177. {engineering_process-0.5.1 → engineering_process-0.6.1}/tests/test_release_evidence_selection.py +0 -0
  178. {engineering_process-0.5.1 → engineering_process-0.6.1}/tests/test_release_preparation.py +0 -0
  179. {engineering_process-0.5.1 → engineering_process-0.6.1}/tests/test_release_qualification.py +0 -0
  180. {engineering_process-0.5.1 → engineering_process-0.6.1}/tests/test_runtime.py +0 -0
  181. {engineering_process-0.5.1 → engineering_process-0.6.1}/tests/test_source_checkout.py +0 -0
  182. {engineering_process-0.5.1 → engineering_process-0.6.1}/tests/test_supervision.py +0 -0
  183. {engineering_process-0.5.1 → engineering_process-0.6.1}/tests/test_supplemental.py +0 -0
  184. {engineering_process-0.5.1 → engineering_process-0.6.1}/tests/test_syncing.py +0 -0
  185. {engineering_process-0.5.1 → engineering_process-0.6.1}/tests/test_test_suite.py +0 -0
  186. {engineering_process-0.5.1 → engineering_process-0.6.1}/tests/test_tooling.py +0 -0
  187. {engineering_process-0.5.1 → 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.5.1
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
@@ -481,12 +489,77 @@ may authorize installing that policy but never substitutes for a missing policy.
481
489
  When new evidence exposes multiple materially valid directions or would change
482
490
  accepted scope, owner, trust boundary, authority, compatibility, rollout, or
483
491
  lifecycle order, the coordinator stops dependent mutation and asks the project owner.
484
- It presents evidence, the invariant, real options, trade-offs, and a recommendation;
485
- the accepted decision is recorded before work resumes. Bounded implementation details
492
+ Before presenting a material recommendation, it records every hard invariant,
493
+ assumption, and option in a bounded recommendation artifact. `processctl` derives the
494
+ valid, invalid, and unproven sets; cost or minimal-change optimization applies only to
495
+ the complete valid set. A distinct actor and fresh context independently challenge
496
+ assumption evidence, invariant tracing, option classification, and terminal ordering.
497
+ If the exact digest-bound chain is not approved or contains no valid option, the
498
+ result is blocked rather than a recommendation. Bounded implementation details
486
499
  already decided by the contract continue autonomously.
487
500
 
501
+ Validate the recommendation, challenge, and optional owner resolution as one chain:
502
+
503
+ ~~~text
504
+ processctl contract validate --kind recommendation recommendation.json
505
+ processctl recommendation review start --project-root . \
506
+ --recommendation recommendation.json \
507
+ --actor <reviewer> --context <fresh-context> --actor-kind agent \
508
+ --method isolated-context --attested-by <host> \
509
+ --attestation-evidence <bounded-attestation>
510
+ processctl contract validate --kind recommendation-review-assignment \
511
+ .process/runs/recommendations/<decision-id>/review-request-<ids>.json
512
+ processctl contract validate --kind recommendation-review recommendation-review.json
513
+ processctl recommendation validate-chain --project-root . \
514
+ --recommendation recommendation.json \
515
+ --assignment .process/runs/recommendations/<decision-id>/review-request-<ids>.json \
516
+ --review recommendation-review.json
517
+ processctl recommendation resolution --project-root . \
518
+ --recommendation recommendation.json \
519
+ --assignment .process/runs/recommendations/<decision-id>/review-request-<ids>.json \
520
+ --review recommendation-review.json \
521
+ --selected-option <valid-option-id> --owner-id <owner-id> \
522
+ --owner-evidence-sha256 sha256:<digest> \
523
+ --selection-rationale-sha256 sha256:<digest> \
524
+ --output recommendation-resolution.json
525
+ processctl recommendation validate-chain --project-root . \
526
+ --recommendation recommendation.json \
527
+ --assignment .process/runs/recommendations/<decision-id>/review-request-<ids>.json \
528
+ --review recommendation-review.json \
529
+ --resolution recommendation-resolution.json
530
+ ~~~
531
+
532
+ The review-start command reserves the context across lifecycle and recommendation
533
+ reviews before emitting its exact assignment. Resolution creation refuses symlinked,
534
+ existing, or concurrently created output instead of redirecting or replacing it. The
535
+ resolution records a selected valid option but grants no lifecycle completion, merge,
536
+ release, deployment, or adoption authority. Those owning gates remain separate. The
537
+ accepted decision is recorded before dependent work resumes.
538
+
539
+ When a schema-3 change selects a project-owned `requiredEvidence` id, local profiles
540
+ alone do not advance it to review. Create the exact no-authority request, run the
541
+ project adapter, and ingest the complete supplemental set first:
542
+
543
+ ~~~text
544
+ processctl change remote request --project-root . --change-id issue-123 \
545
+ --actor worker --context worker-session --actor-kind agent
546
+ python verification/run_remote_verification.py --project-root . \
547
+ --change-id issue-123 --actor worker --context worker-session \
548
+ --actor-kind agent --repository owner/repository \
549
+ --failure-output /durable/receipts/issue-123-remote-failure.json
550
+ processctl change status --project-root . --change-id issue-123
551
+ ~~~
552
+
553
+ The adapter publishes a uniquely named exact-checkpoint verification tag, never a
554
+ branch or PR, dispatches the protected-base workflow, validates service and bundle
555
+ digests, calls `change remote ingest`, and deletes the tag in every terminal path.
556
+ Downloaded temporary archives are deleted after ingestion; failed evidence is moved
557
+ to the explicit durable failure location before cleanup. Remote artifacts and their
558
+ service ids remain lifecycle evidence, not merge, release, deployment, or adoption
559
+ authority.
560
+
488
561
  The canonical publication order is stricter than a PR-first workflow: implementation
489
- and every required profile pass on a clean checkpoint; a consumer-selected independent
562
+ and every required local and remote profile pass on a clean checkpoint; a consumer-selected independent
490
563
  agent or human semantically reviews that checkpoint; findings repeat implementation,
491
564
  complete verification, and fresh review until approved; `change finish` records
492
565
  completion; only then may automation push and create the PR. Static policy/secret/pin
@@ -718,7 +791,8 @@ fingerprint, source tree, or publication range.
718
791
  exclusively by their hash-locked `requirements/process.txt`. The action invokes the
719
792
  producer-owned installer from its immutable action checkout and never downloads or
720
793
  executes helper source from the consumer branch.
721
- - Versioned JSON schemas define change, plan, verification, review, lifecycle,
794
+ - Versioned JSON schemas define change, plan, verification, review, recommendation,
795
+ independent recommendation assignment and challenge, owner resolution, lifecycle,
722
796
  completion-related artifacts, release-change fragments, and the release
723
797
  classification contract. The generated Release PR gate binds that contract to the
724
798
  exact SemVer increment, package version, latest reachable prior tag, reviewed head,
@@ -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
@@ -71,6 +77,16 @@ are preserved with review evidence. These reports supplement the public N-1
71
77
  lifecycle authority; code under verification never promotes itself to lifecycle
72
78
  authority.
73
79
 
80
+ Projects declare named remote requirements and their exact profile and
81
+ platform/runtime selector sets; change contracts select requirement ids. A lifecycle
82
+ request binds those expanded requirements to one clean checkpoint, comparison base,
83
+ workspace fingerprint, and immutable base-owned workflow checkpoint without granting
84
+ review or delivery authority. Provider adapters remain project-owned and transport
85
+ only the exact request. Core ingests local artifact bytes, verifies service and
86
+ content digests plus one-to-one selector coverage, and keeps the lifecycle
87
+ implementing until every local profile and remote requirement passes. A provider job
88
+ conclusion or later PR check is not lifecycle evidence by itself.
89
+
74
90
  ## Failure to invariant
75
91
 
76
92
  A validated command, gate, release, adoption, or external-integration failure must
@@ -97,6 +113,27 @@ failure. Source, branch, version, credentials, and controls are never changed me
97
113
  to cause another attempt. Independent review treats violation of these ownership and
98
114
  evidence boundaries as completion-blocking.
99
115
 
116
+ ## Recommendation validity
117
+
118
+ A material owner decision derives recommendation eligibility before optimization.
119
+ Every option assesses every governing hard invariant and references only proven or
120
+ explicitly unproven assumptions. Any violated invariant makes the option invalid; any
121
+ unproven invariant or referenced assumption makes it unproven. Only the complete
122
+ derived valid set may enter cost, convenience, minimal-change, rollout, or other
123
+ secondary ranking.
124
+
125
+ High-risk recommendations require a process-created digest-bound review assignment.
126
+ Before review, the reviewer method must match its actor kind, a non-participant host
127
+ must attest independence, and the context is atomically reserved in the same
128
+ project-global registry used by lifecycle review. The assigned independent
129
+ adversarial review covers assumption evidence, invariant tracing, option
130
+ classification, and terminal ordering.
131
+ A missing, stale, incomplete, self-attested, context-reused, changes-requested,
132
+ invalid, or unproven chain cannot produce a recommendation. When no valid option
133
+ exists, the outcome is `decision-required`, not an optimized compromise. Owner
134
+ resolution may select only a valid option and grants no lifecycle completion, merge,
135
+ release, deployment, or adoption authority.
136
+
100
137
  ## Resource and generated-state policy
101
138
 
102
139
  Every operation over repository-controlled or remote input has explicit limits for
@@ -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
@@ -446,12 +454,77 @@ may authorize installing that policy but never substitutes for a missing policy.
446
454
  When new evidence exposes multiple materially valid directions or would change
447
455
  accepted scope, owner, trust boundary, authority, compatibility, rollout, or
448
456
  lifecycle order, the coordinator stops dependent mutation and asks the project owner.
449
- It presents evidence, the invariant, real options, trade-offs, and a recommendation;
450
- the accepted decision is recorded before work resumes. Bounded implementation details
457
+ Before presenting a material recommendation, it records every hard invariant,
458
+ assumption, and option in a bounded recommendation artifact. `processctl` derives the
459
+ valid, invalid, and unproven sets; cost or minimal-change optimization applies only to
460
+ the complete valid set. A distinct actor and fresh context independently challenge
461
+ assumption evidence, invariant tracing, option classification, and terminal ordering.
462
+ If the exact digest-bound chain is not approved or contains no valid option, the
463
+ result is blocked rather than a recommendation. Bounded implementation details
451
464
  already decided by the contract continue autonomously.
452
465
 
466
+ Validate the recommendation, challenge, and optional owner resolution as one chain:
467
+
468
+ ~~~text
469
+ processctl contract validate --kind recommendation recommendation.json
470
+ processctl recommendation review start --project-root . \
471
+ --recommendation recommendation.json \
472
+ --actor <reviewer> --context <fresh-context> --actor-kind agent \
473
+ --method isolated-context --attested-by <host> \
474
+ --attestation-evidence <bounded-attestation>
475
+ processctl contract validate --kind recommendation-review-assignment \
476
+ .process/runs/recommendations/<decision-id>/review-request-<ids>.json
477
+ processctl contract validate --kind recommendation-review recommendation-review.json
478
+ processctl recommendation validate-chain --project-root . \
479
+ --recommendation recommendation.json \
480
+ --assignment .process/runs/recommendations/<decision-id>/review-request-<ids>.json \
481
+ --review recommendation-review.json
482
+ processctl recommendation resolution --project-root . \
483
+ --recommendation recommendation.json \
484
+ --assignment .process/runs/recommendations/<decision-id>/review-request-<ids>.json \
485
+ --review recommendation-review.json \
486
+ --selected-option <valid-option-id> --owner-id <owner-id> \
487
+ --owner-evidence-sha256 sha256:<digest> \
488
+ --selection-rationale-sha256 sha256:<digest> \
489
+ --output recommendation-resolution.json
490
+ processctl recommendation validate-chain --project-root . \
491
+ --recommendation recommendation.json \
492
+ --assignment .process/runs/recommendations/<decision-id>/review-request-<ids>.json \
493
+ --review recommendation-review.json \
494
+ --resolution recommendation-resolution.json
495
+ ~~~
496
+
497
+ The review-start command reserves the context across lifecycle and recommendation
498
+ reviews before emitting its exact assignment. Resolution creation refuses symlinked,
499
+ existing, or concurrently created output instead of redirecting or replacing it. The
500
+ resolution records a selected valid option but grants no lifecycle completion, merge,
501
+ release, deployment, or adoption authority. Those owning gates remain separate. The
502
+ accepted decision is recorded before dependent work resumes.
503
+
504
+ When a schema-3 change selects a project-owned `requiredEvidence` id, local profiles
505
+ alone do not advance it to review. Create the exact no-authority request, run the
506
+ project adapter, and ingest the complete supplemental set first:
507
+
508
+ ~~~text
509
+ processctl change remote request --project-root . --change-id issue-123 \
510
+ --actor worker --context worker-session --actor-kind agent
511
+ python verification/run_remote_verification.py --project-root . \
512
+ --change-id issue-123 --actor worker --context worker-session \
513
+ --actor-kind agent --repository owner/repository \
514
+ --failure-output /durable/receipts/issue-123-remote-failure.json
515
+ processctl change status --project-root . --change-id issue-123
516
+ ~~~
517
+
518
+ The adapter publishes a uniquely named exact-checkpoint verification tag, never a
519
+ branch or PR, dispatches the protected-base workflow, validates service and bundle
520
+ digests, calls `change remote ingest`, and deletes the tag in every terminal path.
521
+ Downloaded temporary archives are deleted after ingestion; failed evidence is moved
522
+ to the explicit durable failure location before cleanup. Remote artifacts and their
523
+ service ids remain lifecycle evidence, not merge, release, deployment, or adoption
524
+ authority.
525
+
453
526
  The canonical publication order is stricter than a PR-first workflow: implementation
454
- and every required profile pass on a clean checkpoint; a consumer-selected independent
527
+ and every required local and remote profile pass on a clean checkpoint; a consumer-selected independent
455
528
  agent or human semantically reviews that checkpoint; findings repeat implementation,
456
529
  complete verification, and fresh review until approved; `change finish` records
457
530
  completion; only then may automation push and create the PR. Static policy/secret/pin
@@ -683,7 +756,8 @@ fingerprint, source tree, or publication range.
683
756
  exclusively by their hash-locked `requirements/process.txt`. The action invokes the
684
757
  producer-owned installer from its immutable action checkout and never downloads or
685
758
  executes helper source from the consumer branch.
686
- - Versioned JSON schemas define change, plan, verification, review, lifecycle,
759
+ - Versioned JSON schemas define change, plan, verification, review, recommendation,
760
+ independent recommendation assignment and challenge, owner resolution, lifecycle,
687
761
  completion-related artifacts, release-change fragments, and the release
688
762
  classification contract. The generated Release PR gate binds that contract to the
689
763
  exact SemVer increment, package version, latest reachable prior tag, reviewed head,
@@ -138,6 +138,31 @@ consumer reproduction after adoption. A read-only pre-release consumer candidate
138
138
  supplemental compatibility evidence only and cannot be committed as an unreleased
139
139
  dependency.
140
140
 
141
+ ## Recommendation-validity capability
142
+
143
+ Recommendation, review-assignment, review, and owner-resolution schema-1 artifacts
144
+ are additive serialized surfaces. Requiring every new material owner decision to use
145
+ their invariant derivation, project-global fresh-context reservation, independent
146
+ challenge, chain validation, and valid resolution changes managed workflow semantics.
147
+ Before 1.0 this is therefore a breaking package change even though `schemaImpact`
148
+ remains additive.
149
+
150
+ After adoption, new material decisions use `recommendation review start` before the
151
+ reviewer acts, validate the exact assignment-bound chain before presenting a
152
+ recommendation, and record the selected valid option before dependent work resumes.
153
+ Completed historical decisions retain their original evidence and require no
154
+ backfill. A recommendation resolution is decision evidence only and never substitutes
155
+ for lifecycle completion or delivery authority.
156
+
157
+ Remote-verification request and evidence-set schema-1 artifacts, optional project
158
+ requirements, optional change selections, lifecycle references, and receipt content
159
+ are additive serialized surfaces. A project does not gain the gate until a separate
160
+ adoption validates the target-version manifest and selects requirement ids. Once
161
+ selected, missing exact remote evidence blocks review and completion; a later PR
162
+ matrix is not a compatibility substitute. Provider transport remains project-owned,
163
+ while request expansion, ingestion, invalidation, and terminal ordering are portable
164
+ process semantics.
165
+
141
166
  ## Release and adoption boundary
142
167
 
143
168
  Release, self-adoption, and consumer adoption are separate changes:
@@ -1,3 +1,3 @@
1
1
  """Agent-neutral engineering process."""
2
2
 
3
- VERSION = "0.5.1"
3
+ VERSION = "0.6.1"
@@ -14,6 +14,7 @@ from .bundles import load_bundles, select_bundles
14
14
  from .bootstrap import initialize_project
15
15
  from .contracts import (
16
16
  ContractError,
17
+ canonical_json_digest,
17
18
  derive_release_version,
18
19
  read_json,
19
20
  validate_adoption_migration,
@@ -29,6 +30,12 @@ from .contracts import (
29
30
  validate_plan,
30
31
  validate_process_lock,
31
32
  validate_project,
33
+ validate_recommendation,
34
+ validate_recommendation_resolution,
35
+ validate_recommendation_review,
36
+ validate_recommendation_review_assignment,
37
+ validate_remote_verification_evidence,
38
+ validate_remote_verification_request,
32
39
  validate_release,
33
40
  validate_release_change,
34
41
  validate_review,
@@ -70,7 +77,9 @@ from .lifecycle import (
70
77
  finish_change,
71
78
  lifecycle_environment_issues,
72
79
  lifecycle_status,
80
+ ingest_remote_verification,
73
81
  register_plan,
82
+ request_remote_verification,
74
83
  start_change,
75
84
  start_review,
76
85
  submit_review,
@@ -89,6 +98,11 @@ from .publication import (
89
98
  validate_evidence_publication,
90
99
  )
91
100
  from .process_graph import load_process_graph, process_root_from_skills
101
+ from .recommendation import (
102
+ create_recommendation_resolution,
103
+ start_recommendation_review,
104
+ validate_recommendation_chain,
105
+ )
92
106
  from .release import validate_release_checkpoint
93
107
  from .release_candidate import prepare_release_candidate, render_release_pull_request
94
108
  from .skills import validate_skills
@@ -281,6 +295,12 @@ def command_contract_validate(args: argparse.Namespace) -> int:
281
295
  "improvement-resolution": validate_improvement_resolution,
282
296
  "improvement-signal": validate_improvement_signal,
283
297
  "plan": validate_plan,
298
+ "recommendation": validate_recommendation,
299
+ "recommendation-resolution": validate_recommendation_resolution,
300
+ "recommendation-review": validate_recommendation_review,
301
+ "recommendation-review-assignment": validate_recommendation_review_assignment,
302
+ "remote-verification-evidence": validate_remote_verification_evidence,
303
+ "remote-verification-request": validate_remote_verification_request,
284
304
  "release": validate_release,
285
305
  "release-change": validate_release_change,
286
306
  "review": validate_review,
@@ -297,6 +317,56 @@ def command_contract_validate(args: argparse.Namespace) -> int:
297
317
  return 0
298
318
 
299
319
 
320
+ def command_recommendation_validate_chain(args: argparse.Namespace) -> int:
321
+ _lifecycle_project(args)
322
+ result = validate_recommendation_chain(
323
+ args.project_root,
324
+ args.recommendation,
325
+ args.assignment,
326
+ args.review,
327
+ args.resolution,
328
+ )
329
+ status = "passed" if result["allowed"] else "blocked"
330
+ _emit(
331
+ args,
332
+ _result("recommendation validate-chain", status=status, **result),
333
+ )
334
+ return 0 if result["allowed"] else 1
335
+
336
+
337
+ def command_recommendation_review_start(args: argparse.Namespace) -> int:
338
+ _lifecycle_project(args)
339
+ result = start_recommendation_review(
340
+ args.project_root,
341
+ args.recommendation,
342
+ actor_id=args.actor,
343
+ context_id=args.context,
344
+ kind=args.actor_kind,
345
+ method=args.method,
346
+ attested_by=args.attested_by,
347
+ evidence=args.attestation_evidence,
348
+ )
349
+ _emit(args, _result("recommendation review start", **result))
350
+ return 0
351
+
352
+
353
+ def command_recommendation_resolution(args: argparse.Namespace) -> int:
354
+ _lifecycle_project(args)
355
+ result = create_recommendation_resolution(
356
+ args.project_root,
357
+ args.recommendation,
358
+ args.assignment,
359
+ args.review,
360
+ selected_option_id=args.selected_option,
361
+ owner_id=args.owner_id,
362
+ owner_evidence_sha256=args.owner_evidence_sha256,
363
+ selection_rationale_sha256=args.selection_rationale_sha256,
364
+ output=args.output,
365
+ )
366
+ _emit(args, _result("recommendation resolution", **result))
367
+ return 0
368
+
369
+
300
370
  def command_improvement_validate_chain(args: argparse.Namespace) -> int:
301
371
  result = validate_improvement_chain(
302
372
  args.signal,
@@ -600,6 +670,53 @@ def command_change_verify(args: argparse.Namespace) -> int:
600
670
  return 0
601
671
 
602
672
 
673
+ def command_change_remote_request(args: argparse.Namespace) -> int:
674
+ project = _lifecycle_project(args)
675
+ state, request = request_remote_verification(
676
+ args.project_root,
677
+ project,
678
+ args.change_id,
679
+ actor_id=args.actor,
680
+ context_id=args.context,
681
+ kind=args.actor_kind,
682
+ )
683
+ _emit(
684
+ args,
685
+ _change_result(
686
+ "change remote request",
687
+ state,
688
+ checkpoint=request["checkpoint"],
689
+ comparisonBase=request["comparisonBase"],
690
+ request=state["remoteVerification"]["request"]["path"],
691
+ requestSha256=canonical_json_digest(request),
692
+ ),
693
+ )
694
+ return 0
695
+
696
+
697
+ def command_change_remote_ingest(args: argparse.Namespace) -> int:
698
+ _lifecycle_project(args)
699
+ state, evidence = ingest_remote_verification(
700
+ args.project_root,
701
+ args.change_id,
702
+ args.evidence,
703
+ actor_id=args.actor,
704
+ context_id=args.context,
705
+ kind=args.actor_kind,
706
+ )
707
+ _emit(
708
+ args,
709
+ _change_result(
710
+ "change remote ingest",
711
+ state,
712
+ checkpoint=evidence["checkpoint"],
713
+ evidence=state["remoteVerification"]["evidence"]["path"],
714
+ artifactCount=len(evidence["artifacts"]),
715
+ ),
716
+ )
717
+ return 0
718
+
719
+
603
720
  def command_change_review_start(args: argparse.Namespace) -> int:
604
721
  _lifecycle_project(args)
605
722
  state, assignment = start_review(
@@ -673,6 +790,7 @@ def command_change_status(args: argparse.Namespace) -> int:
673
790
  plan=state["plan"],
674
791
  implementationActors=state["implementationActors"],
675
792
  verification=state["verification"],
793
+ remoteVerification=state.get("remoteVerification"),
676
794
  pendingFindings=state["pendingFindings"],
677
795
  reviewAssignment=state["reviewAssignment"],
678
796
  review=state["review"],
@@ -1479,6 +1597,12 @@ def build_parser() -> argparse.ArgumentParser:
1479
1597
  "improvement-resolution",
1480
1598
  "improvement-signal",
1481
1599
  "plan",
1600
+ "recommendation",
1601
+ "recommendation-resolution",
1602
+ "recommendation-review",
1603
+ "recommendation-review-assignment",
1604
+ "remote-verification-evidence",
1605
+ "remote-verification-request",
1482
1606
  "release",
1483
1607
  "release-change",
1484
1608
  "review",
@@ -1489,6 +1613,81 @@ def build_parser() -> argparse.ArgumentParser:
1489
1613
  _add_json(contract_validate)
1490
1614
  contract_validate.set_defaults(handler=command_contract_validate)
1491
1615
 
1616
+ recommendation = commands.add_parser(
1617
+ "recommendation",
1618
+ help="Validate evidence-valid recommendations and owner resolutions",
1619
+ )
1620
+ recommendation_commands = recommendation.add_subparsers(
1621
+ dest="recommendation_command", required=True
1622
+ )
1623
+ recommendation_validate = recommendation_commands.add_parser(
1624
+ "validate-chain",
1625
+ help="Validate recommendation validity and its independent challenge",
1626
+ )
1627
+ _add_project_root(recommendation_validate)
1628
+ _add_process_root(recommendation_validate)
1629
+ recommendation_validate.add_argument(
1630
+ "--recommendation", type=Path, required=True
1631
+ )
1632
+ recommendation_validate.add_argument("--assignment", type=Path, required=True)
1633
+ recommendation_validate.add_argument("--review", type=Path, required=True)
1634
+ recommendation_validate.add_argument("--resolution", type=Path)
1635
+ _add_json(recommendation_validate)
1636
+ recommendation_validate.set_defaults(
1637
+ handler=command_recommendation_validate_chain
1638
+ )
1639
+ recommendation_review = recommendation_commands.add_parser(
1640
+ "review", help="Register an independent recommendation reviewer"
1641
+ )
1642
+ recommendation_review_commands = recommendation_review.add_subparsers(
1643
+ dest="recommendation_review_command", required=True
1644
+ )
1645
+ recommendation_review_start = recommendation_review_commands.add_parser(
1646
+ "start",
1647
+ help="Reserve a fresh project-global context and create an assignment",
1648
+ )
1649
+ _add_project_root(recommendation_review_start)
1650
+ _add_process_root(recommendation_review_start)
1651
+ _add_actor(recommendation_review_start)
1652
+ recommendation_review_start.add_argument(
1653
+ "--recommendation", type=Path, required=True
1654
+ )
1655
+ recommendation_review_start.add_argument(
1656
+ "--method", choices=("isolated-context", "separate-person"), required=True
1657
+ )
1658
+ recommendation_review_start.add_argument("--attested-by", required=True)
1659
+ recommendation_review_start.add_argument(
1660
+ "--attestation-evidence", required=True
1661
+ )
1662
+ _add_json(recommendation_review_start)
1663
+ recommendation_review_start.set_defaults(
1664
+ handler=command_recommendation_review_start
1665
+ )
1666
+ recommendation_resolution = recommendation_commands.add_parser(
1667
+ "resolution",
1668
+ help="Create a non-authorizing owner resolution for an approved chain",
1669
+ )
1670
+ _add_project_root(recommendation_resolution)
1671
+ _add_process_root(recommendation_resolution)
1672
+ recommendation_resolution.add_argument(
1673
+ "--recommendation", type=Path, required=True
1674
+ )
1675
+ recommendation_resolution.add_argument("--assignment", type=Path, required=True)
1676
+ recommendation_resolution.add_argument("--review", type=Path, required=True)
1677
+ recommendation_resolution.add_argument("--selected-option", required=True)
1678
+ recommendation_resolution.add_argument("--owner-id", required=True)
1679
+ recommendation_resolution.add_argument(
1680
+ "--owner-evidence-sha256", required=True
1681
+ )
1682
+ recommendation_resolution.add_argument(
1683
+ "--selection-rationale-sha256", required=True
1684
+ )
1685
+ recommendation_resolution.add_argument("--output", type=Path, required=True)
1686
+ _add_json(recommendation_resolution)
1687
+ recommendation_resolution.set_defaults(
1688
+ handler=command_recommendation_resolution
1689
+ )
1690
+
1492
1691
  skills = commands.add_parser("skills", help="Validate portable Agent Skills")
1493
1692
  skills_commands = skills.add_subparsers(dest="skills_command", required=True)
1494
1693
  skills_validate = skills_commands.add_parser("validate")
@@ -2179,6 +2378,29 @@ def build_parser() -> argparse.ArgumentParser:
2179
2378
  change_verify.add_argument("--profile", required=True)
2180
2379
  change_verify.set_defaults(handler=command_change_verify)
2181
2380
 
2381
+ change_remote = change_commands.add_parser(
2382
+ "remote", help="Bind required exact-checkpoint remote verification"
2383
+ )
2384
+ remote_commands = change_remote.add_subparsers(
2385
+ dest="change_remote_command", required=True
2386
+ )
2387
+ remote_request = remote_commands.add_parser(
2388
+ "request", help="Create an exact no-authority remote verification request"
2389
+ )
2390
+ _add_lifecycle_common(remote_request)
2391
+ _add_actor(remote_request)
2392
+ remote_request.add_argument("--change-id", required=True)
2393
+ remote_request.set_defaults(handler=command_change_remote_request)
2394
+
2395
+ remote_ingest = remote_commands.add_parser(
2396
+ "ingest", help="Validate and bind a complete remote evidence set"
2397
+ )
2398
+ _add_lifecycle_common(remote_ingest)
2399
+ _add_actor(remote_ingest)
2400
+ remote_ingest.add_argument("--change-id", required=True)
2401
+ remote_ingest.add_argument("--evidence", type=Path, required=True)
2402
+ remote_ingest.set_defaults(handler=command_change_remote_ingest)
2403
+
2182
2404
  change_review = change_commands.add_parser(
2183
2405
  "review", help="Run the independent-review gate"
2184
2406
  )
@@ -8,6 +8,8 @@ LIFECYCLE_COMMAND_PATHS = frozenset(
8
8
  "change finish",
9
9
  "change implement",
10
10
  "change plan",
11
+ "change remote ingest",
12
+ "change remote request",
11
13
  "change review start",
12
14
  "change review submit",
13
15
  "change start",