engineering-process 0.5.0__tar.gz → 0.6.0__tar.gz

This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
Files changed (188) hide show
  1. {engineering_process-0.5.0/engineering_process.egg-info → engineering_process-0.6.0}/PKG-INFO +75 -8
  2. {engineering_process-0.5.0 → engineering_process-0.6.0}/PRODUCTION_STANDARD.md +31 -0
  3. {engineering_process-0.5.0 → engineering_process-0.6.0}/README.md +74 -7
  4. {engineering_process-0.5.0 → engineering_process-0.6.0}/VERSIONING.md +25 -0
  5. {engineering_process-0.5.0 → engineering_process-0.6.0}/engineering_process/__init__.py +1 -1
  6. {engineering_process-0.5.0 → engineering_process-0.6.0}/engineering_process/_windows_job.py +1 -1
  7. {engineering_process-0.5.0 → engineering_process-0.6.0}/engineering_process/cli.py +222 -0
  8. {engineering_process-0.5.0 → engineering_process-0.6.0}/engineering_process/command_catalog.py +2 -0
  9. {engineering_process-0.5.0 → engineering_process-0.6.0}/engineering_process/contracts.py +1485 -179
  10. {engineering_process-0.5.0 → engineering_process-0.6.0}/engineering_process/distribution_verify.py +2 -0
  11. {engineering_process-0.5.0 → engineering_process-0.6.0}/engineering_process/evidence.py +286 -5
  12. {engineering_process-0.5.0 → engineering_process-0.6.0}/engineering_process/lifecycle.py +558 -5
  13. {engineering_process-0.5.0 → engineering_process-0.6.0}/engineering_process/process_graph.py +6 -1
  14. engineering_process-0.6.0/engineering_process/recommendation.py +517 -0
  15. engineering_process-0.6.0/engineering_process/remote_verification.py +498 -0
  16. {engineering_process-0.5.0 → engineering_process-0.6.0}/engineering_process/supervision.py +1 -0
  17. {engineering_process-0.5.0 → engineering_process-0.6.0/engineering_process.egg-info}/PKG-INFO +75 -8
  18. {engineering_process-0.5.0 → engineering_process-0.6.0}/engineering_process.egg-info/SOURCES.txt +17 -0
  19. {engineering_process-0.5.0 → engineering_process-0.6.0}/examples/change.json +1 -0
  20. {engineering_process-0.5.0 → engineering_process-0.6.0}/examples/project.json +22 -0
  21. engineering_process-0.6.0/examples/recommendation-resolution.json +21 -0
  22. engineering_process-0.6.0/examples/recommendation-review-assignment.json +22 -0
  23. engineering_process-0.6.0/examples/recommendation-review.json +60 -0
  24. engineering_process-0.6.0/examples/recommendation.json +89 -0
  25. engineering_process-0.6.0/examples/remote-verification-evidence.json +26 -0
  26. engineering_process-0.6.0/examples/remote-verification-request.json +40 -0
  27. {engineering_process-0.5.0 → engineering_process-0.6.0}/improvement-catalog.json +5 -4
  28. {engineering_process-0.5.0 → engineering_process-0.6.0}/process-graph.json +1 -1
  29. {engineering_process-0.5.0 → engineering_process-0.6.0}/process_assets/skills/assess-design/SKILL.md +16 -3
  30. {engineering_process-0.5.0 → engineering_process-0.6.0}/process_assets/skills/run-change/references/execution.md +43 -7
  31. {engineering_process-0.5.0 → engineering_process-0.6.0}/process_assets/skills/verify-change/SKILL.md +11 -3
  32. {engineering_process-0.5.0 → engineering_process-0.6.0}/pyproject.toml +13 -1
  33. engineering_process-0.6.0/release.json +51 -0
  34. {engineering_process-0.5.0 → engineering_process-0.6.0}/schemas/change.schema.json +18 -1
  35. {engineering_process-0.5.0 → engineering_process-0.6.0}/schemas/evidence-receipt.schema.json +36 -1
  36. {engineering_process-0.5.0 → engineering_process-0.6.0}/schemas/lifecycle.schema.json +26 -0
  37. {engineering_process-0.5.0 → engineering_process-0.6.0}/schemas/project.schema.json +92 -2
  38. engineering_process-0.6.0/schemas/recommendation-resolution.schema.json +60 -0
  39. engineering_process-0.6.0/schemas/recommendation-review-assignment.schema.json +56 -0
  40. engineering_process-0.6.0/schemas/recommendation-review.schema.json +112 -0
  41. engineering_process-0.6.0/schemas/recommendation.schema.json +178 -0
  42. engineering_process-0.6.0/schemas/remote-verification-evidence.schema.json +61 -0
  43. engineering_process-0.6.0/schemas/remote-verification-request.schema.json +116 -0
  44. {engineering_process-0.5.0 → engineering_process-0.6.0}/templates/adopt-process-windows-job.py +1 -1
  45. engineering_process-0.6.0/tests/test_recommendation.py +578 -0
  46. {engineering_process-0.5.0 → engineering_process-0.6.0}/tests/test_release_candidate.py +22 -12
  47. engineering_process-0.6.0/tests/test_remote_verification.py +833 -0
  48. engineering_process-0.6.0/tests/test_remote_verification_adapter.py +360 -0
  49. {engineering_process-0.5.0 → engineering_process-0.6.0}/tests/test_schemas.py +4 -0
  50. {engineering_process-0.5.0 → engineering_process-0.6.0}/tests/test_self_hosting.py +28 -4
  51. {engineering_process-0.5.0 → engineering_process-0.6.0}/tests/test_skills.py +31 -0
  52. {engineering_process-0.5.0 → engineering_process-0.6.0}/tests/test_windows_job.py +50 -5
  53. engineering_process-0.5.0/release.json +0 -138
  54. {engineering_process-0.5.0 → engineering_process-0.6.0}/LICENSE +0 -0
  55. {engineering_process-0.5.0 → engineering_process-0.6.0}/MANIFEST.in +0 -0
  56. {engineering_process-0.5.0 → engineering_process-0.6.0}/PROCESS_IMPROVEMENT.md +0 -0
  57. {engineering_process-0.5.0 → engineering_process-0.6.0}/bundles.json +0 -0
  58. {engineering_process-0.5.0 → engineering_process-0.6.0}/engineering_process/__main__.py +0 -0
  59. {engineering_process-0.5.0 → engineering_process-0.6.0}/engineering_process/_download_worker.py +0 -0
  60. {engineering_process-0.5.0 → engineering_process-0.6.0}/engineering_process/_supervisor_posix.py +0 -0
  61. {engineering_process-0.5.0 → engineering_process-0.6.0}/engineering_process/_supervisor_windows.py +0 -0
  62. {engineering_process-0.5.0 → engineering_process-0.6.0}/engineering_process/adoption.py +0 -0
  63. {engineering_process-0.5.0 → engineering_process-0.6.0}/engineering_process/artifact_attestation.py +0 -0
  64. {engineering_process-0.5.0 → engineering_process-0.6.0}/engineering_process/bootstrap.py +0 -0
  65. {engineering_process-0.5.0 → engineering_process-0.6.0}/engineering_process/bounded_process.py +0 -0
  66. {engineering_process-0.5.0 → engineering_process-0.6.0}/engineering_process/bundles.py +0 -0
  67. {engineering_process-0.5.0 → engineering_process-0.6.0}/engineering_process/diagnostics.py +0 -0
  68. {engineering_process-0.5.0 → engineering_process-0.6.0}/engineering_process/distribution.py +0 -0
  69. {engineering_process-0.5.0 → engineering_process-0.6.0}/engineering_process/environment.py +0 -0
  70. {engineering_process-0.5.0 → engineering_process-0.6.0}/engineering_process/evidence_transport.py +0 -0
  71. {engineering_process-0.5.0 → engineering_process-0.6.0}/engineering_process/git.py +0 -0
  72. {engineering_process-0.5.0 → engineering_process-0.6.0}/engineering_process/git_attributes.py +0 -0
  73. {engineering_process-0.5.0 → engineering_process-0.6.0}/engineering_process/helper_launch.py +0 -0
  74. {engineering_process-0.5.0 → engineering_process-0.6.0}/engineering_process/impact.py +0 -0
  75. {engineering_process-0.5.0 → engineering_process-0.6.0}/engineering_process/improvement.py +0 -0
  76. {engineering_process-0.5.0 → engineering_process-0.6.0}/engineering_process/lifecycle_routes.py +0 -0
  77. {engineering_process-0.5.0 → engineering_process-0.6.0}/engineering_process/managed.py +0 -0
  78. {engineering_process-0.5.0 → engineering_process-0.6.0}/engineering_process/markdown.py +0 -0
  79. {engineering_process-0.5.0 → engineering_process-0.6.0}/engineering_process/publication.py +0 -0
  80. {engineering_process-0.5.0 → engineering_process-0.6.0}/engineering_process/release.py +0 -0
  81. {engineering_process-0.5.0 → engineering_process-0.6.0}/engineering_process/release_candidate.py +0 -0
  82. {engineering_process-0.5.0 → engineering_process-0.6.0}/engineering_process/requirements-build.txt +0 -0
  83. {engineering_process-0.5.0 → engineering_process-0.6.0}/engineering_process/requirements-dev.txt +0 -0
  84. {engineering_process-0.5.0 → engineering_process-0.6.0}/engineering_process/requirements-release.txt +0 -0
  85. {engineering_process-0.5.0 → engineering_process-0.6.0}/engineering_process/requirements-runtime.txt +0 -0
  86. {engineering_process-0.5.0 → engineering_process-0.6.0}/engineering_process/runner.py +0 -0
  87. {engineering_process-0.5.0 → engineering_process-0.6.0}/engineering_process/runtime.py +0 -0
  88. {engineering_process-0.5.0 → engineering_process-0.6.0}/engineering_process/skills.py +0 -0
  89. {engineering_process-0.5.0 → engineering_process-0.6.0}/engineering_process/supplemental.py +0 -0
  90. {engineering_process-0.5.0 → engineering_process-0.6.0}/engineering_process/syncing.py +0 -0
  91. {engineering_process-0.5.0 → engineering_process-0.6.0}/engineering_process/tooling.py +0 -0
  92. {engineering_process-0.5.0 → engineering_process-0.6.0}/engineering_process.egg-info/dependency_links.txt +0 -0
  93. {engineering_process-0.5.0 → engineering_process-0.6.0}/engineering_process.egg-info/entry_points.txt +0 -0
  94. {engineering_process-0.5.0 → engineering_process-0.6.0}/engineering_process.egg-info/requires.txt +0 -0
  95. {engineering_process-0.5.0 → engineering_process-0.6.0}/engineering_process.egg-info/top_level.txt +0 -0
  96. {engineering_process-0.5.0 → engineering_process-0.6.0}/examples/adoption-migration.json +0 -0
  97. {engineering_process-0.5.0 → engineering_process-0.6.0}/examples/automation-policy.json +0 -0
  98. {engineering_process-0.5.0 → engineering_process-0.6.0}/examples/automation-proposal-policy.json +0 -0
  99. {engineering_process-0.5.0 → engineering_process-0.6.0}/examples/automation-proposal.json +0 -0
  100. {engineering_process-0.5.0 → engineering_process-0.6.0}/examples/improvement-catalog.json +0 -0
  101. {engineering_process-0.5.0 → engineering_process-0.6.0}/examples/improvement-disposition.json +0 -0
  102. {engineering_process-0.5.0 → engineering_process-0.6.0}/examples/improvement-reproduction.json +0 -0
  103. {engineering_process-0.5.0 → engineering_process-0.6.0}/examples/improvement-resolution.json +0 -0
  104. {engineering_process-0.5.0 → engineering_process-0.6.0}/examples/improvement-signal.json +0 -0
  105. {engineering_process-0.5.0 → engineering_process-0.6.0}/examples/plan.json +0 -0
  106. {engineering_process-0.5.0 → engineering_process-0.6.0}/examples/release-change.json +0 -0
  107. {engineering_process-0.5.0 → engineering_process-0.6.0}/examples/release.json +0 -0
  108. {engineering_process-0.5.0 → engineering_process-0.6.0}/examples/review.json +0 -0
  109. {engineering_process-0.5.0 → engineering_process-0.6.0}/process_assets/skills/build-frontend/SKILL.md +0 -0
  110. {engineering_process-0.5.0 → engineering_process-0.6.0}/process_assets/skills/build-frontend-foundation/SKILL.md +0 -0
  111. {engineering_process-0.5.0 → engineering_process-0.6.0}/process_assets/skills/change-api/SKILL.md +0 -0
  112. {engineering_process-0.5.0 → engineering_process-0.6.0}/process_assets/skills/cross-repo-change/SKILL.md +0 -0
  113. {engineering_process-0.5.0 → engineering_process-0.6.0}/process_assets/skills/define-change-contract/SKILL.md +0 -0
  114. {engineering_process-0.5.0 → engineering_process-0.6.0}/process_assets/skills/design-module/SKILL.md +0 -0
  115. {engineering_process-0.5.0 → engineering_process-0.6.0}/process_assets/skills/evolve-process/SKILL.md +0 -0
  116. {engineering_process-0.5.0 → engineering_process-0.6.0}/process_assets/skills/finish-change/SKILL.md +0 -0
  117. {engineering_process-0.5.0 → engineering_process-0.6.0}/process_assets/skills/govern-ui/SKILL.md +0 -0
  118. {engineering_process-0.5.0 → engineering_process-0.6.0}/process_assets/skills/implement-change/SKILL.md +0 -0
  119. {engineering_process-0.5.0 → engineering_process-0.6.0}/process_assets/skills/implement-module/SKILL.md +0 -0
  120. {engineering_process-0.5.0 → engineering_process-0.6.0}/process_assets/skills/implement-use-case/SKILL.md +0 -0
  121. {engineering_process-0.5.0 → engineering_process-0.6.0}/process_assets/skills/integrate-mcp/SKILL.md +0 -0
  122. {engineering_process-0.5.0 → engineering_process-0.6.0}/process_assets/skills/maintain-docs/SKILL.md +0 -0
  123. {engineering_process-0.5.0 → engineering_process-0.6.0}/process_assets/skills/plan-change/SKILL.md +0 -0
  124. {engineering_process-0.5.0 → engineering_process-0.6.0}/process_assets/skills/publish-change/SKILL.md +0 -0
  125. {engineering_process-0.5.0 → engineering_process-0.6.0}/process_assets/skills/review-change/SKILL.md +0 -0
  126. {engineering_process-0.5.0 → engineering_process-0.6.0}/process_assets/skills/run-change/SKILL.md +0 -0
  127. {engineering_process-0.5.0 → engineering_process-0.6.0}/process_assets/skills/run-project-command/SKILL.md +0 -0
  128. {engineering_process-0.5.0 → engineering_process-0.6.0}/process_assets/skills/specify-use-case/SKILL.md +0 -0
  129. {engineering_process-0.5.0 → engineering_process-0.6.0}/schemas/adoption-migration.schema.json +0 -0
  130. {engineering_process-0.5.0 → engineering_process-0.6.0}/schemas/automation-policy.schema.json +0 -0
  131. {engineering_process-0.5.0 → engineering_process-0.6.0}/schemas/automation-proposal-policy.schema.json +0 -0
  132. {engineering_process-0.5.0 → engineering_process-0.6.0}/schemas/automation-proposal.schema.json +0 -0
  133. {engineering_process-0.5.0 → engineering_process-0.6.0}/schemas/improvement-catalog.schema.json +0 -0
  134. {engineering_process-0.5.0 → engineering_process-0.6.0}/schemas/improvement-disposition.schema.json +0 -0
  135. {engineering_process-0.5.0 → engineering_process-0.6.0}/schemas/improvement-reproduction.schema.json +0 -0
  136. {engineering_process-0.5.0 → engineering_process-0.6.0}/schemas/improvement-resolution.schema.json +0 -0
  137. {engineering_process-0.5.0 → engineering_process-0.6.0}/schemas/improvement-signal.schema.json +0 -0
  138. {engineering_process-0.5.0 → engineering_process-0.6.0}/schemas/plan.schema.json +0 -0
  139. {engineering_process-0.5.0 → engineering_process-0.6.0}/schemas/process-graph.schema.json +0 -0
  140. {engineering_process-0.5.0 → engineering_process-0.6.0}/schemas/process-lock.schema.json +0 -0
  141. {engineering_process-0.5.0 → engineering_process-0.6.0}/schemas/release-change.schema.json +0 -0
  142. {engineering_process-0.5.0 → engineering_process-0.6.0}/schemas/release.schema.json +0 -0
  143. {engineering_process-0.5.0 → engineering_process-0.6.0}/schemas/review.schema.json +0 -0
  144. {engineering_process-0.5.0 → engineering_process-0.6.0}/schemas/reviewer-attestation.schema.json +0 -0
  145. {engineering_process-0.5.0 → engineering_process-0.6.0}/schemas/supplemental-verification.schema.json +0 -0
  146. {engineering_process-0.5.0 → engineering_process-0.6.0}/schemas/verification.schema.json +0 -0
  147. {engineering_process-0.5.0 → engineering_process-0.6.0}/setup.cfg +0 -0
  148. {engineering_process-0.5.0 → engineering_process-0.6.0}/templates/AGENTS.process.md +0 -0
  149. {engineering_process-0.5.0 → engineering_process-0.6.0}/templates/PULL_REQUEST_TEMPLATE.md +0 -0
  150. {engineering_process-0.5.0 → engineering_process-0.6.0}/templates/adopt-process.py +0 -0
  151. {engineering_process-0.5.0 → engineering_process-0.6.0}/tests/test_adoption.py +0 -0
  152. {engineering_process-0.5.0 → engineering_process-0.6.0}/tests/test_adoption_runner.py +0 -0
  153. {engineering_process-0.5.0 → engineering_process-0.6.0}/tests/test_artifact_attestation.py +0 -0
  154. {engineering_process-0.5.0 → engineering_process-0.6.0}/tests/test_bootstrap.py +0 -0
  155. {engineering_process-0.5.0 → engineering_process-0.6.0}/tests/test_bounded_process.py +0 -0
  156. {engineering_process-0.5.0 → engineering_process-0.6.0}/tests/test_bundles.py +0 -0
  157. {engineering_process-0.5.0 → engineering_process-0.6.0}/tests/test_cli.py +0 -0
  158. {engineering_process-0.5.0 → engineering_process-0.6.0}/tests/test_completed_release_dispatch.py +0 -0
  159. {engineering_process-0.5.0 → engineering_process-0.6.0}/tests/test_completion_evidence_transport.py +0 -0
  160. {engineering_process-0.5.0 → engineering_process-0.6.0}/tests/test_contracts.py +0 -0
  161. {engineering_process-0.5.0 → engineering_process-0.6.0}/tests/test_diagnostics.py +0 -0
  162. {engineering_process-0.5.0 → engineering_process-0.6.0}/tests/test_distribution.py +0 -0
  163. {engineering_process-0.5.0 → engineering_process-0.6.0}/tests/test_distribution_verify.py +0 -0
  164. {engineering_process-0.5.0 → engineering_process-0.6.0}/tests/test_environment.py +0 -0
  165. {engineering_process-0.5.0 → engineering_process-0.6.0}/tests/test_evals.py +0 -0
  166. {engineering_process-0.5.0 → engineering_process-0.6.0}/tests/test_impact.py +0 -0
  167. {engineering_process-0.5.0 → engineering_process-0.6.0}/tests/test_improvement.py +0 -0
  168. {engineering_process-0.5.0 → engineering_process-0.6.0}/tests/test_lifecycle.py +0 -0
  169. {engineering_process-0.5.0 → engineering_process-0.6.0}/tests/test_process_graph.py +0 -0
  170. {engineering_process-0.5.0 → engineering_process-0.6.0}/tests/test_process_install.py +0 -0
  171. {engineering_process-0.5.0 → engineering_process-0.6.0}/tests/test_publication.py +0 -0
  172. {engineering_process-0.5.0 → engineering_process-0.6.0}/tests/test_publish_event.py +0 -0
  173. {engineering_process-0.5.0 → engineering_process-0.6.0}/tests/test_pypi_publication.py +0 -0
  174. {engineering_process-0.5.0 → engineering_process-0.6.0}/tests/test_release.py +0 -0
  175. {engineering_process-0.5.0 → engineering_process-0.6.0}/tests/test_release_candidate_boundary.py +0 -0
  176. {engineering_process-0.5.0 → engineering_process-0.6.0}/tests/test_release_completion_identity.py +0 -0
  177. {engineering_process-0.5.0 → engineering_process-0.6.0}/tests/test_release_evidence_restore.py +0 -0
  178. {engineering_process-0.5.0 → engineering_process-0.6.0}/tests/test_release_evidence_selection.py +0 -0
  179. {engineering_process-0.5.0 → engineering_process-0.6.0}/tests/test_release_preparation.py +0 -0
  180. {engineering_process-0.5.0 → engineering_process-0.6.0}/tests/test_release_qualification.py +0 -0
  181. {engineering_process-0.5.0 → engineering_process-0.6.0}/tests/test_runner.py +0 -0
  182. {engineering_process-0.5.0 → engineering_process-0.6.0}/tests/test_runtime.py +0 -0
  183. {engineering_process-0.5.0 → engineering_process-0.6.0}/tests/test_source_checkout.py +0 -0
  184. {engineering_process-0.5.0 → engineering_process-0.6.0}/tests/test_supervision.py +0 -0
  185. {engineering_process-0.5.0 → engineering_process-0.6.0}/tests/test_supplemental.py +0 -0
  186. {engineering_process-0.5.0 → engineering_process-0.6.0}/tests/test_syncing.py +0 -0
  187. {engineering_process-0.5.0 → engineering_process-0.6.0}/tests/test_test_suite.py +0 -0
  188. {engineering_process-0.5.0 → engineering_process-0.6.0}/tests/test_tooling.py +0 -0
@@ -1,6 +1,6 @@
1
1
  Metadata-Version: 2.4
2
2
  Name: engineering-process
3
- Version: 0.5.0
3
+ Version: 0.6.0
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
@@ -92,9 +92,10 @@ distribution: the POSIX backend owns a new process session/group and the Windows
92
92
  backend owns a kill-on-close Job Object. Consumer manifests, evidence, and exit codes
93
93
  do not branch by operating system. If an outer Windows Job applies incompatible
94
94
  nesting or UI limits, target creation fails closed instead of running uncontained.
95
- After a command root exits, both backends allow at most 250 milliseconds for child
96
- accounting to drain naturally. A process still present after that bound is terminated
97
- and makes the command fail; commands with no remaining child return immediately.
95
+ After a command root exits, the POSIX backend allows at most 250 milliseconds and the
96
+ Windows Job Object backend allows at most 5 seconds for child accounting to drain
97
+ naturally. A process still present after its platform bound is terminated and makes
98
+ the command fail; commands with no remaining child return immediately.
98
99
 
99
100
  This task boundary intentionally separates finite commands from services and
100
101
  interactive protocols. `processctl exec`, requirement probes, setup command actions,
@@ -480,12 +481,77 @@ may authorize installing that policy but never substitutes for a missing policy.
480
481
  When new evidence exposes multiple materially valid directions or would change
481
482
  accepted scope, owner, trust boundary, authority, compatibility, rollout, or
482
483
  lifecycle order, the coordinator stops dependent mutation and asks the project owner.
483
- It presents evidence, the invariant, real options, trade-offs, and a recommendation;
484
- the accepted decision is recorded before work resumes. Bounded implementation details
484
+ Before presenting a material recommendation, it records every hard invariant,
485
+ assumption, and option in a bounded recommendation artifact. `processctl` derives the
486
+ valid, invalid, and unproven sets; cost or minimal-change optimization applies only to
487
+ the complete valid set. A distinct actor and fresh context independently challenge
488
+ assumption evidence, invariant tracing, option classification, and terminal ordering.
489
+ If the exact digest-bound chain is not approved or contains no valid option, the
490
+ result is blocked rather than a recommendation. Bounded implementation details
485
491
  already decided by the contract continue autonomously.
486
492
 
493
+ Validate the recommendation, challenge, and optional owner resolution as one chain:
494
+
495
+ ~~~text
496
+ processctl contract validate --kind recommendation recommendation.json
497
+ processctl recommendation review start --project-root . \
498
+ --recommendation recommendation.json \
499
+ --actor <reviewer> --context <fresh-context> --actor-kind agent \
500
+ --method isolated-context --attested-by <host> \
501
+ --attestation-evidence <bounded-attestation>
502
+ processctl contract validate --kind recommendation-review-assignment \
503
+ .process/runs/recommendations/<decision-id>/review-request-<ids>.json
504
+ processctl contract validate --kind recommendation-review recommendation-review.json
505
+ processctl recommendation validate-chain --project-root . \
506
+ --recommendation recommendation.json \
507
+ --assignment .process/runs/recommendations/<decision-id>/review-request-<ids>.json \
508
+ --review recommendation-review.json
509
+ processctl recommendation resolution --project-root . \
510
+ --recommendation recommendation.json \
511
+ --assignment .process/runs/recommendations/<decision-id>/review-request-<ids>.json \
512
+ --review recommendation-review.json \
513
+ --selected-option <valid-option-id> --owner-id <owner-id> \
514
+ --owner-evidence-sha256 sha256:<digest> \
515
+ --selection-rationale-sha256 sha256:<digest> \
516
+ --output recommendation-resolution.json
517
+ processctl recommendation validate-chain --project-root . \
518
+ --recommendation recommendation.json \
519
+ --assignment .process/runs/recommendations/<decision-id>/review-request-<ids>.json \
520
+ --review recommendation-review.json \
521
+ --resolution recommendation-resolution.json
522
+ ~~~
523
+
524
+ The review-start command reserves the context across lifecycle and recommendation
525
+ reviews before emitting its exact assignment. Resolution creation refuses symlinked,
526
+ existing, or concurrently created output instead of redirecting or replacing it. The
527
+ resolution records a selected valid option but grants no lifecycle completion, merge,
528
+ release, deployment, or adoption authority. Those owning gates remain separate. The
529
+ accepted decision is recorded before dependent work resumes.
530
+
531
+ When a schema-3 change selects a project-owned `requiredEvidence` id, local profiles
532
+ alone do not advance it to review. Create the exact no-authority request, run the
533
+ project adapter, and ingest the complete supplemental set first:
534
+
535
+ ~~~text
536
+ processctl change remote request --project-root . --change-id issue-123 \
537
+ --actor worker --context worker-session --actor-kind agent
538
+ python verification/run_remote_verification.py --project-root . \
539
+ --change-id issue-123 --actor worker --context worker-session \
540
+ --actor-kind agent --repository owner/repository \
541
+ --failure-output /durable/receipts/issue-123-remote-failure.json
542
+ processctl change status --project-root . --change-id issue-123
543
+ ~~~
544
+
545
+ The adapter publishes a uniquely named exact-checkpoint verification tag, never a
546
+ branch or PR, dispatches the protected-base workflow, validates service and bundle
547
+ digests, calls `change remote ingest`, and deletes the tag in every terminal path.
548
+ Downloaded temporary archives are deleted after ingestion; failed evidence is moved
549
+ to the explicit durable failure location before cleanup. Remote artifacts and their
550
+ service ids remain lifecycle evidence, not merge, release, deployment, or adoption
551
+ authority.
552
+
487
553
  The canonical publication order is stricter than a PR-first workflow: implementation
488
- and every required profile pass on a clean checkpoint; a consumer-selected independent
554
+ and every required local and remote profile pass on a clean checkpoint; a consumer-selected independent
489
555
  agent or human semantically reviews that checkpoint; findings repeat implementation,
490
556
  complete verification, and fresh review until approved; `change finish` records
491
557
  completion; only then may automation push and create the PR. Static policy/secret/pin
@@ -717,7 +783,8 @@ fingerprint, source tree, or publication range.
717
783
  exclusively by their hash-locked `requirements/process.txt`. The action invokes the
718
784
  producer-owned installer from its immutable action checkout and never downloads or
719
785
  executes helper source from the consumer branch.
720
- - Versioned JSON schemas define change, plan, verification, review, lifecycle,
786
+ - Versioned JSON schemas define change, plan, verification, review, recommendation,
787
+ independent recommendation assignment and challenge, owner resolution, lifecycle,
721
788
  completion-related artifacts, release-change fragments, and the release
722
789
  classification contract. The generated Release PR gate binds that contract to the
723
790
  exact SemVer increment, package version, latest reachable prior tag, reviewed head,
@@ -71,6 +71,16 @@ are preserved with review evidence. These reports supplement the public N-1
71
71
  lifecycle authority; code under verification never promotes itself to lifecycle
72
72
  authority.
73
73
 
74
+ Projects declare named remote requirements and their exact profile and
75
+ platform/runtime selector sets; change contracts select requirement ids. A lifecycle
76
+ request binds those expanded requirements to one clean checkpoint, comparison base,
77
+ workspace fingerprint, and immutable base-owned workflow checkpoint without granting
78
+ review or delivery authority. Provider adapters remain project-owned and transport
79
+ only the exact request. Core ingests local artifact bytes, verifies service and
80
+ content digests plus one-to-one selector coverage, and keeps the lifecycle
81
+ implementing until every local profile and remote requirement passes. A provider job
82
+ conclusion or later PR check is not lifecycle evidence by itself.
83
+
74
84
  ## Failure to invariant
75
85
 
76
86
  A validated command, gate, release, adoption, or external-integration failure must
@@ -97,6 +107,27 @@ failure. Source, branch, version, credentials, and controls are never changed me
97
107
  to cause another attempt. Independent review treats violation of these ownership and
98
108
  evidence boundaries as completion-blocking.
99
109
 
110
+ ## Recommendation validity
111
+
112
+ A material owner decision derives recommendation eligibility before optimization.
113
+ Every option assesses every governing hard invariant and references only proven or
114
+ explicitly unproven assumptions. Any violated invariant makes the option invalid; any
115
+ unproven invariant or referenced assumption makes it unproven. Only the complete
116
+ derived valid set may enter cost, convenience, minimal-change, rollout, or other
117
+ secondary ranking.
118
+
119
+ High-risk recommendations require a process-created digest-bound review assignment.
120
+ Before review, the reviewer method must match its actor kind, a non-participant host
121
+ must attest independence, and the context is atomically reserved in the same
122
+ project-global registry used by lifecycle review. The assigned independent
123
+ adversarial review covers assumption evidence, invariant tracing, option
124
+ classification, and terminal ordering.
125
+ A missing, stale, incomplete, self-attested, context-reused, changes-requested,
126
+ invalid, or unproven chain cannot produce a recommendation. When no valid option
127
+ exists, the outcome is `decision-required`, not an optimized compromise. Owner
128
+ resolution may select only a valid option and grants no lifecycle completion, merge,
129
+ release, deployment, or adoption authority.
130
+
100
131
  ## Resource and generated-state policy
101
132
 
102
133
  Every operation over repository-controlled or remote input has explicit limits for
@@ -57,9 +57,10 @@ distribution: the POSIX backend owns a new process session/group and the Windows
57
57
  backend owns a kill-on-close Job Object. Consumer manifests, evidence, and exit codes
58
58
  do not branch by operating system. If an outer Windows Job applies incompatible
59
59
  nesting or UI limits, target creation fails closed instead of running uncontained.
60
- After a command root exits, both backends allow at most 250 milliseconds for child
61
- accounting to drain naturally. A process still present after that bound is terminated
62
- and makes the command fail; commands with no remaining child return immediately.
60
+ After a command root exits, the POSIX backend allows at most 250 milliseconds and the
61
+ Windows Job Object backend allows at most 5 seconds for child accounting to drain
62
+ naturally. A process still present after its platform bound is terminated and makes
63
+ the command fail; commands with no remaining child return immediately.
63
64
 
64
65
  This task boundary intentionally separates finite commands from services and
65
66
  interactive protocols. `processctl exec`, requirement probes, setup command actions,
@@ -445,12 +446,77 @@ may authorize installing that policy but never substitutes for a missing policy.
445
446
  When new evidence exposes multiple materially valid directions or would change
446
447
  accepted scope, owner, trust boundary, authority, compatibility, rollout, or
447
448
  lifecycle order, the coordinator stops dependent mutation and asks the project owner.
448
- It presents evidence, the invariant, real options, trade-offs, and a recommendation;
449
- the accepted decision is recorded before work resumes. Bounded implementation details
449
+ Before presenting a material recommendation, it records every hard invariant,
450
+ assumption, and option in a bounded recommendation artifact. `processctl` derives the
451
+ valid, invalid, and unproven sets; cost or minimal-change optimization applies only to
452
+ the complete valid set. A distinct actor and fresh context independently challenge
453
+ assumption evidence, invariant tracing, option classification, and terminal ordering.
454
+ If the exact digest-bound chain is not approved or contains no valid option, the
455
+ result is blocked rather than a recommendation. Bounded implementation details
450
456
  already decided by the contract continue autonomously.
451
457
 
458
+ Validate the recommendation, challenge, and optional owner resolution as one chain:
459
+
460
+ ~~~text
461
+ processctl contract validate --kind recommendation recommendation.json
462
+ processctl recommendation review start --project-root . \
463
+ --recommendation recommendation.json \
464
+ --actor <reviewer> --context <fresh-context> --actor-kind agent \
465
+ --method isolated-context --attested-by <host> \
466
+ --attestation-evidence <bounded-attestation>
467
+ processctl contract validate --kind recommendation-review-assignment \
468
+ .process/runs/recommendations/<decision-id>/review-request-<ids>.json
469
+ processctl contract validate --kind recommendation-review recommendation-review.json
470
+ processctl recommendation validate-chain --project-root . \
471
+ --recommendation recommendation.json \
472
+ --assignment .process/runs/recommendations/<decision-id>/review-request-<ids>.json \
473
+ --review recommendation-review.json
474
+ processctl recommendation resolution --project-root . \
475
+ --recommendation recommendation.json \
476
+ --assignment .process/runs/recommendations/<decision-id>/review-request-<ids>.json \
477
+ --review recommendation-review.json \
478
+ --selected-option <valid-option-id> --owner-id <owner-id> \
479
+ --owner-evidence-sha256 sha256:<digest> \
480
+ --selection-rationale-sha256 sha256:<digest> \
481
+ --output recommendation-resolution.json
482
+ processctl recommendation validate-chain --project-root . \
483
+ --recommendation recommendation.json \
484
+ --assignment .process/runs/recommendations/<decision-id>/review-request-<ids>.json \
485
+ --review recommendation-review.json \
486
+ --resolution recommendation-resolution.json
487
+ ~~~
488
+
489
+ The review-start command reserves the context across lifecycle and recommendation
490
+ reviews before emitting its exact assignment. Resolution creation refuses symlinked,
491
+ existing, or concurrently created output instead of redirecting or replacing it. The
492
+ resolution records a selected valid option but grants no lifecycle completion, merge,
493
+ release, deployment, or adoption authority. Those owning gates remain separate. The
494
+ accepted decision is recorded before dependent work resumes.
495
+
496
+ When a schema-3 change selects a project-owned `requiredEvidence` id, local profiles
497
+ alone do not advance it to review. Create the exact no-authority request, run the
498
+ project adapter, and ingest the complete supplemental set first:
499
+
500
+ ~~~text
501
+ processctl change remote request --project-root . --change-id issue-123 \
502
+ --actor worker --context worker-session --actor-kind agent
503
+ python verification/run_remote_verification.py --project-root . \
504
+ --change-id issue-123 --actor worker --context worker-session \
505
+ --actor-kind agent --repository owner/repository \
506
+ --failure-output /durable/receipts/issue-123-remote-failure.json
507
+ processctl change status --project-root . --change-id issue-123
508
+ ~~~
509
+
510
+ The adapter publishes a uniquely named exact-checkpoint verification tag, never a
511
+ branch or PR, dispatches the protected-base workflow, validates service and bundle
512
+ digests, calls `change remote ingest`, and deletes the tag in every terminal path.
513
+ Downloaded temporary archives are deleted after ingestion; failed evidence is moved
514
+ to the explicit durable failure location before cleanup. Remote artifacts and their
515
+ service ids remain lifecycle evidence, not merge, release, deployment, or adoption
516
+ authority.
517
+
452
518
  The canonical publication order is stricter than a PR-first workflow: implementation
453
- and every required profile pass on a clean checkpoint; a consumer-selected independent
519
+ and every required local and remote profile pass on a clean checkpoint; a consumer-selected independent
454
520
  agent or human semantically reviews that checkpoint; findings repeat implementation,
455
521
  complete verification, and fresh review until approved; `change finish` records
456
522
  completion; only then may automation push and create the PR. Static policy/secret/pin
@@ -682,7 +748,8 @@ fingerprint, source tree, or publication range.
682
748
  exclusively by their hash-locked `requirements/process.txt`. The action invokes the
683
749
  producer-owned installer from its immutable action checkout and never downloads or
684
750
  executes helper source from the consumer branch.
685
- - Versioned JSON schemas define change, plan, verification, review, lifecycle,
751
+ - Versioned JSON schemas define change, plan, verification, review, recommendation,
752
+ independent recommendation assignment and challenge, owner resolution, lifecycle,
686
753
  completion-related artifacts, release-change fragments, and the release
687
754
  classification contract. The generated Release PR gate binds that contract to the
688
755
  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.0"
3
+ VERSION = "0.6.0"
@@ -36,7 +36,7 @@ WAIT_FAILED = 0xFFFFFFFF
36
36
  WAIT_OBJECT_0 = 0x00000000
37
37
  WAIT_TIMEOUT = 0x00000102
38
38
  CLEANUP_GRACE_MILLISECONDS = 5_000
39
- NATURAL_DRAIN_GRACE_MILLISECONDS = 250
39
+ NATURAL_DRAIN_GRACE_MILLISECONDS = 5_000
40
40
  MAX_STATUS_BYTES = 4096
41
41
  MAX_STATUS_ERROR_CHARACTERS = 1024
42
42
 
@@ -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",